summaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2001-04-17 12:12:05 +0000
committerru <ru@FreeBSD.org>2001-04-17 12:12:05 +0000
commit78a36d21097dbce47cbcd4818ecd041388952f73 (patch)
tree8c20bfd611f113ea0cc691f0a026ad5ed1b43c72 /contrib
parent3b4ec64f2874f8497458268896220e5c9c859d05 (diff)
parent0e0a0e6429c7113acf15c4c94bd5fe94c45f9e99 (diff)
downloadFreeBSD-src-78a36d21097dbce47cbcd4818ecd041388952f73.zip
FreeBSD-src-78a36d21097dbce47cbcd4818ecd041388952f73.tar.gz
This commit was generated by cvs2svn to compensate for changes in r75584,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib')
-rw-r--r--contrib/groff/ChangeLog1757
-rw-r--r--contrib/groff/INSTALL10
-rw-r--r--contrib/groff/MORE.STUFF69
-rw-r--r--contrib/groff/Makefile.comm6
-rw-r--r--contrib/groff/Makefile.in59
-rw-r--r--contrib/groff/Makefile.sub3
-rw-r--r--contrib/groff/NEWS238
-rw-r--r--contrib/groff/PROBLEMS65
-rw-r--r--contrib/groff/README2
-rw-r--r--contrib/groff/REVISION2
-rw-r--r--contrib/groff/VERSION2
-rw-r--r--contrib/groff/aclocal.m416
-rwxr-xr-xcontrib/groff/configure130
-rw-r--r--contrib/groff/configure.in4
-rw-r--r--contrib/groff/contrib/mm/ChangeLog521
-rw-r--r--contrib/groff/contrib/mm/Makefile.sim66
-rw-r--r--contrib/groff/contrib/mm/Makefile.sub55
-rw-r--r--contrib/groff/contrib/mm/NOTES105
-rw-r--r--contrib/groff/contrib/mm/README37
-rw-r--r--contrib/groff/contrib/mm/examples/APP352
-rw-r--r--contrib/groff/contrib/mm/examples/B1B291
-rw-r--r--contrib/groff/contrib/mm/examples/COVER235
-rw-r--r--contrib/groff/contrib/mm/examples/IND4191
-rw-r--r--contrib/groff/contrib/mm/examples/LT1058
-rw-r--r--contrib/groff/contrib/mm/examples/LT.se1062
-rw-r--r--contrib/groff/contrib/mm/examples/ML169
-rw-r--r--contrib/groff/contrib/mm/examples/MOVE175
-rw-r--r--contrib/groff/contrib/mm/examples/MUL535
-rw-r--r--contrib/groff/contrib/mm/examples/NCOL196
-rw-r--r--contrib/groff/contrib/mm/examples/ND17
-rw-r--r--contrib/groff/contrib/mm/examples/README32
-rw-r--r--contrib/groff/contrib/mm/examples/References975
-rw-r--r--contrib/groff/contrib/mm/examples/SETR109
-rw-r--r--contrib/groff/contrib/mm/groff_mm.man1897
-rw-r--r--contrib/groff/contrib/mm/groff_mmse.man82
-rw-r--r--contrib/groff/contrib/mm/m.tmac3477
-rw-r--r--contrib/groff/contrib/mm/mm/0.MT146
-rw-r--r--contrib/groff/contrib/mm/mm/4.MT81
-rw-r--r--contrib/groff/contrib/mm/mm/5.MT34
-rw-r--r--contrib/groff/contrib/mm/mm/ms.cov84
-rw-r--r--contrib/groff/contrib/mm/mm/se_ms.cov3
-rw-r--r--contrib/groff/contrib/mm/mmroff.man48
-rwxr-xr-xcontrib/groff/contrib/mm/mmroff.pl134
-rw-r--r--contrib/groff/contrib/mm/mse.tmac184
-rw-r--r--contrib/groff/doc/Makefile6
-rw-r--r--contrib/groff/doc/groff.texinfo6416
-rw-r--r--contrib/groff/doc/homepage.ms16
-rw-r--r--contrib/groff/doc/meref.me4
-rw-r--r--contrib/groff/doc/pic.ms33
-rw-r--r--contrib/groff/font/devX100-12/CB308
-rw-r--r--contrib/groff/font/devX100-12/CBI308
-rw-r--r--contrib/groff/font/devX100-12/CI308
-rw-r--r--contrib/groff/font/devX100-12/CR308
-rw-r--r--contrib/groff/font/devX100-12/DESC9
-rw-r--r--contrib/groff/font/devX100-12/HB308
-rw-r--r--contrib/groff/font/devX100-12/HBI308
-rw-r--r--contrib/groff/font/devX100-12/HI308
-rw-r--r--contrib/groff/font/devX100-12/HR308
-rw-r--r--contrib/groff/font/devX100-12/Makefile.sub2
-rw-r--r--contrib/groff/font/devX100-12/NB308
-rw-r--r--contrib/groff/font/devX100-12/NBI308
-rw-r--r--contrib/groff/font/devX100-12/NI308
-rw-r--r--contrib/groff/font/devX100-12/NR308
-rw-r--r--contrib/groff/font/devX100-12/S226
-rw-r--r--contrib/groff/font/devX100-12/TB308
-rw-r--r--contrib/groff/font/devX100-12/TBI308
-rw-r--r--contrib/groff/font/devX100-12/TI308
-rw-r--r--contrib/groff/font/devX100-12/TR308
-rw-r--r--contrib/groff/font/devX100/CB308
-rw-r--r--contrib/groff/font/devX100/CBI308
-rw-r--r--contrib/groff/font/devX100/CI308
-rw-r--r--contrib/groff/font/devX100/CR308
-rw-r--r--contrib/groff/font/devX100/DESC9
-rw-r--r--contrib/groff/font/devX100/HB308
-rw-r--r--contrib/groff/font/devX100/HBI308
-rw-r--r--contrib/groff/font/devX100/HI308
-rw-r--r--contrib/groff/font/devX100/HR308
-rw-r--r--contrib/groff/font/devX100/Makefile.sub2
-rw-r--r--contrib/groff/font/devX100/NB308
-rw-r--r--contrib/groff/font/devX100/NBI308
-rw-r--r--contrib/groff/font/devX100/NI308
-rw-r--r--contrib/groff/font/devX100/NR308
-rw-r--r--contrib/groff/font/devX100/S226
-rw-r--r--contrib/groff/font/devX100/TB308
-rw-r--r--contrib/groff/font/devX100/TBI308
-rw-r--r--contrib/groff/font/devX100/TI308
-rw-r--r--contrib/groff/font/devX100/TR308
-rw-r--r--contrib/groff/font/devX75-12/CB308
-rw-r--r--contrib/groff/font/devX75-12/CBI308
-rw-r--r--contrib/groff/font/devX75-12/CI308
-rw-r--r--contrib/groff/font/devX75-12/CR308
-rw-r--r--contrib/groff/font/devX75-12/DESC9
-rw-r--r--contrib/groff/font/devX75-12/HB308
-rw-r--r--contrib/groff/font/devX75-12/HBI308
-rw-r--r--contrib/groff/font/devX75-12/HI308
-rw-r--r--contrib/groff/font/devX75-12/HR308
-rw-r--r--contrib/groff/font/devX75-12/Makefile.sub2
-rw-r--r--contrib/groff/font/devX75-12/NB308
-rw-r--r--contrib/groff/font/devX75-12/NBI308
-rw-r--r--contrib/groff/font/devX75-12/NI308
-rw-r--r--contrib/groff/font/devX75-12/NR308
-rw-r--r--contrib/groff/font/devX75-12/S226
-rw-r--r--contrib/groff/font/devX75-12/TB308
-rw-r--r--contrib/groff/font/devX75-12/TBI308
-rw-r--r--contrib/groff/font/devX75-12/TI308
-rw-r--r--contrib/groff/font/devX75-12/TR308
-rw-r--r--contrib/groff/font/devX75/CB308
-rw-r--r--contrib/groff/font/devX75/CBI308
-rw-r--r--contrib/groff/font/devX75/CI308
-rw-r--r--contrib/groff/font/devX75/CR308
-rw-r--r--contrib/groff/font/devX75/DESC9
-rw-r--r--contrib/groff/font/devX75/HB308
-rw-r--r--contrib/groff/font/devX75/HBI308
-rw-r--r--contrib/groff/font/devX75/HI308
-rw-r--r--contrib/groff/font/devX75/HR308
-rw-r--r--contrib/groff/font/devX75/Makefile.sub2
-rw-r--r--contrib/groff/font/devX75/NB308
-rw-r--r--contrib/groff/font/devX75/NBI308
-rw-r--r--contrib/groff/font/devX75/NI308
-rw-r--r--contrib/groff/font/devX75/NR308
-rw-r--r--contrib/groff/font/devX75/S226
-rw-r--r--contrib/groff/font/devX75/TB308
-rw-r--r--contrib/groff/font/devX75/TBI308
-rw-r--r--contrib/groff/font/devX75/TI308
-rw-r--r--contrib/groff/font/devX75/TR308
-rw-r--r--contrib/groff/font/devascii/DESC.proto8
-rw-r--r--contrib/groff/font/devascii/Makefile.sub31
-rw-r--r--contrib/groff/font/devascii/R.proto167
-rw-r--r--contrib/groff/font/devcp1047/DESC.proto8
-rw-r--r--contrib/groff/font/devcp1047/Makefile.sub32
-rw-r--r--contrib/groff/font/devcp1047/R.proto356
-rw-r--r--contrib/groff/font/devdvi/B358
-rw-r--r--contrib/groff/font/devdvi/BI365
-rw-r--r--contrib/groff/font/devdvi/CW160
-rw-r--r--contrib/groff/font/devdvi/CWI160
-rw-r--r--contrib/groff/font/devdvi/DESC.in10
-rw-r--r--contrib/groff/font/devdvi/EX144
-rw-r--r--contrib/groff/font/devdvi/H307
-rw-r--r--contrib/groff/font/devdvi/HB307
-rw-r--r--contrib/groff/font/devdvi/HI308
-rw-r--r--contrib/groff/font/devdvi/I366
-rw-r--r--contrib/groff/font/devdvi/MI136
-rw-r--r--contrib/groff/font/devdvi/Makefile.sub11
-rw-r--r--contrib/groff/font/devdvi/R441
-rw-r--r--contrib/groff/font/devdvi/S153
-rw-r--r--contrib/groff/font/devdvi/SA143
-rw-r--r--contrib/groff/font/devdvi/SB132
-rwxr-xr-xcontrib/groff/font/devdvi/generate/CompileFonts15
-rw-r--r--contrib/groff/font/devdvi/generate/Makefile107
-rw-r--r--contrib/groff/font/devdvi/generate/cork.map206
-rw-r--r--contrib/groff/font/devdvi/generate/msam.map127
-rw-r--r--contrib/groff/font/devdvi/generate/msbm.map121
-rw-r--r--contrib/groff/font/devdvi/generate/texb.map127
-rw-r--r--contrib/groff/font/devdvi/generate/texex.map100
-rw-r--r--contrib/groff/font/devdvi/generate/texi.map127
-rw-r--r--contrib/groff/font/devdvi/generate/texmi.map32
-rw-r--r--contrib/groff/font/devdvi/generate/texr.map127
-rw-r--r--contrib/groff/font/devdvi/generate/texsy.map100
-rw-r--r--contrib/groff/font/devdvi/generate/textt.map126
-rw-r--r--contrib/groff/font/devhtml/DESC.proto12
-rw-r--r--contrib/groff/font/devhtml/Makefile.sub34
-rw-r--r--contrib/groff/font/devhtml/R.proto315
-rw-r--r--contrib/groff/font/devlatin1/DESC.proto8
-rw-r--r--contrib/groff/font/devlatin1/Makefile.sub32
-rw-r--r--contrib/groff/font/devlatin1/R.proto357
-rw-r--r--contrib/groff/font/devlbp/CB272
-rw-r--r--contrib/groff/font/devlbp/CI272
-rw-r--r--contrib/groff/font/devlbp/CR272
-rw-r--r--contrib/groff/font/devlbp/DESC.in9
-rw-r--r--contrib/groff/font/devlbp/EB272
-rw-r--r--contrib/groff/font/devlbp/EI272
-rw-r--r--contrib/groff/font/devlbp/ER272
-rw-r--r--contrib/groff/font/devlbp/HB491
-rw-r--r--contrib/groff/font/devlbp/HBI492
-rw-r--r--contrib/groff/font/devlbp/HI492
-rw-r--r--contrib/groff/font/devlbp/HNB491
-rw-r--r--contrib/groff/font/devlbp/HNBI491
-rw-r--r--contrib/groff/font/devlbp/HNI491
-rw-r--r--contrib/groff/font/devlbp/HNR491
-rw-r--r--contrib/groff/font/devlbp/HR491
-rw-r--r--contrib/groff/font/devlbp/Makefile.sub18
-rw-r--r--contrib/groff/font/devlbp/TB513
-rw-r--r--contrib/groff/font/devlbp/TBI493
-rw-r--r--contrib/groff/font/devlbp/TI521
-rw-r--r--contrib/groff/font/devlbp/TR517
-rw-r--r--contrib/groff/font/devlj4/ALBB790
-rw-r--r--contrib/groff/font/devlj4/ALBR805
-rw-r--r--contrib/groff/font/devlj4/AOB748
-rw-r--r--contrib/groff/font/devlj4/AOI813
-rw-r--r--contrib/groff/font/devlj4/AOR735
-rw-r--r--contrib/groff/font/devlj4/CB350
-rw-r--r--contrib/groff/font/devlj4/CBI351
-rw-r--r--contrib/groff/font/devlj4/CI351
-rw-r--r--contrib/groff/font/devlj4/CLARENDON351
-rw-r--r--contrib/groff/font/devlj4/CORONET351
-rw-r--r--contrib/groff/font/devlj4/CR350
-rw-r--r--contrib/groff/font/devlj4/DESC.in9
-rw-r--r--contrib/groff/font/devlj4/GB749
-rw-r--r--contrib/groff/font/devlj4/GBI752
-rw-r--r--contrib/groff/font/devlj4/GI686
-rw-r--r--contrib/groff/font/devlj4/GR872
-rw-r--r--contrib/groff/font/devlj4/LGB350
-rw-r--r--contrib/groff/font/devlj4/LGI351
-rw-r--r--contrib/groff/font/devlj4/LGR350
-rw-r--r--contrib/groff/font/devlj4/MARIGOLD351
-rw-r--r--contrib/groff/font/devlj4/Makefile.sub33
-rw-r--r--contrib/groff/font/devlj4/OB817
-rw-r--r--contrib/groff/font/devlj4/OBI810
-rw-r--r--contrib/groff/font/devlj4/OI923
-rw-r--r--contrib/groff/font/devlj4/OR899
-rw-r--r--contrib/groff/font/devlj4/S195
-rw-r--r--contrib/groff/font/devlj4/TB991
-rw-r--r--contrib/groff/font/devlj4/TBI1045
-rw-r--r--contrib/groff/font/devlj4/TI1131
-rw-r--r--contrib/groff/font/devlj4/TR878
-rw-r--r--contrib/groff/font/devlj4/UB829
-rw-r--r--contrib/groff/font/devlj4/UBI779
-rw-r--r--contrib/groff/font/devlj4/UCB790
-rw-r--r--contrib/groff/font/devlj4/UCBI698
-rw-r--r--contrib/groff/font/devlj4/UCI840
-rw-r--r--contrib/groff/font/devlj4/UCR759
-rw-r--r--contrib/groff/font/devlj4/UI983
-rw-r--r--contrib/groff/font/devlj4/UR880
-rw-r--r--contrib/groff/font/devlj4/generate/Makefile170
-rw-r--r--contrib/groff/font/devlj4/generate/special.map178
-rw-r--r--contrib/groff/font/devlj4/generate/text.map344
-rw-r--r--contrib/groff/font/devps/AB574
-rw-r--r--contrib/groff/font/devps/ABI575
-rw-r--r--contrib/groff/font/devps/AI575
-rw-r--r--contrib/groff/font/devps/AR574
-rw-r--r--contrib/groff/font/devps/BMB441
-rw-r--r--contrib/groff/font/devps/BMBI444
-rw-r--r--contrib/groff/font/devps/BMI437
-rw-r--r--contrib/groff/font/devps/BMR433
-rw-r--r--contrib/groff/font/devps/CB339
-rw-r--r--contrib/groff/font/devps/CBI340
-rw-r--r--contrib/groff/font/devps/CI340
-rw-r--r--contrib/groff/font/devps/CR339
-rw-r--r--contrib/groff/font/devps/DESC.in11
-rw-r--r--contrib/groff/font/devps/HB561
-rw-r--r--contrib/groff/font/devps/HBI562
-rw-r--r--contrib/groff/font/devps/HI630
-rw-r--r--contrib/groff/font/devps/HNB561
-rw-r--r--contrib/groff/font/devps/HNBI562
-rw-r--r--contrib/groff/font/devps/HNI630
-rw-r--r--contrib/groff/font/devps/HNR629
-rw-r--r--contrib/groff/font/devps/HR629
-rw-r--r--contrib/groff/font/devps/Makefile.sub35
-rw-r--r--contrib/groff/font/devps/NB473
-rw-r--r--contrib/groff/font/devps/NBI594
-rw-r--r--contrib/groff/font/devps/NI535
-rw-r--r--contrib/groff/font/devps/NR522
-rw-r--r--contrib/groff/font/devps/PB461
-rw-r--r--contrib/groff/font/devps/PBI463
-rw-r--r--contrib/groff/font/devps/PI465
-rw-r--r--contrib/groff/font/devps/PR466
-rw-r--r--contrib/groff/font/devps/S227
-rw-r--r--contrib/groff/font/devps/SS194
-rw-r--r--contrib/groff/font/devps/TB548
-rw-r--r--contrib/groff/font/devps/TBI531
-rw-r--r--contrib/groff/font/devps/TI544
-rw-r--r--contrib/groff/font/devps/TR536
-rw-r--r--contrib/groff/font/devps/ZCMI494
-rw-r--r--contrib/groff/font/devps/ZD193
-rw-r--r--contrib/groff/font/devps/ZDR193
-rw-r--r--contrib/groff/font/devps/download5
-rw-r--r--contrib/groff/font/devps/generate/Makefile227
-rwxr-xr-xcontrib/groff/font/devps/generate/afmname44
-rw-r--r--contrib/groff/font/devps/generate/dingbats.map2
-rw-r--r--contrib/groff/font/devps/generate/dingbats.rmap1
-rw-r--r--contrib/groff/font/devps/generate/lgreekmap28
-rw-r--r--contrib/groff/font/devps/generate/symbol.sed33
-rw-r--r--contrib/groff/font/devps/generate/symbolchars60
-rw-r--r--contrib/groff/font/devps/generate/symbolsl.afm203
-rw-r--r--contrib/groff/font/devps/generate/textmap453
-rw-r--r--contrib/groff/font/devps/prologue.ps228
-rw-r--r--contrib/groff/font/devps/psstrip.sed7
-rw-r--r--contrib/groff/font/devps/symbol.afm212
-rw-r--r--contrib/groff/font/devps/symbolmap513
-rw-r--r--contrib/groff/font/devps/symbolsl.ps41
-rw-r--r--contrib/groff/font/devps/text.enc231
-rw-r--r--contrib/groff/font/devps/zapfdr.afm222
-rw-r--r--contrib/groff/font/devps/zapfdr.ps225
-rw-r--r--contrib/groff/font/devutf8/DESC.proto8
-rw-r--r--contrib/groff/font/devutf8/Makefile.sub32
-rw-r--r--contrib/groff/font/devutf8/NOTES75
-rw-r--r--contrib/groff/font/devutf8/R.proto473
-rw-r--r--contrib/groff/gendef.sh8
-rw-r--r--contrib/groff/man/groff.man218
-rw-r--r--contrib/groff/man/groff_char.man4
-rw-r--r--contrib/groff/man/groff_font.man26
-rw-r--r--contrib/groff/man/roff.man65
-rw-r--r--contrib/groff/src/devices/grodvi/Makefile.sub6
-rw-r--r--contrib/groff/src/devices/grodvi/dvi.cc912
-rw-r--r--contrib/groff/src/devices/grodvi/grodvi.man174
-rw-r--r--contrib/groff/src/devices/grohtml/Makefile.sub16
-rw-r--r--contrib/groff/src/devices/grohtml/grohtml.man137
-rw-r--r--contrib/groff/src/devices/grohtml/html-chars.h27
-rw-r--r--contrib/groff/src/devices/grohtml/html-text.cc829
-rw-r--r--contrib/groff/src/devices/grohtml/html-text.h109
-rw-r--r--contrib/groff/src/devices/grohtml/html.h96
-rw-r--r--contrib/groff/src/devices/grohtml/output.cc335
-rw-r--r--contrib/groff/src/devices/grohtml/post-html.cc2933
-rw-r--r--contrib/groff/src/devices/grolbp/Makefile.sub6
-rw-r--r--contrib/groff/src/devices/grolbp/charset.h69
-rw-r--r--contrib/groff/src/devices/grolbp/grolbp.man357
-rw-r--r--contrib/groff/src/devices/grolbp/lbp.cc765
-rw-r--r--contrib/groff/src/devices/grolbp/lbp.h511
-rw-r--r--contrib/groff/src/devices/grolj4/Makefile.sub6
-rw-r--r--contrib/groff/src/devices/grolj4/grolj4.man144
-rw-r--r--contrib/groff/src/devices/grolj4/lj4.cc710
-rw-r--r--contrib/groff/src/devices/grops/Makefile.sub12
-rw-r--r--contrib/groff/src/devices/grops/TODO29
-rw-r--r--contrib/groff/src/devices/grops/grops.man861
-rw-r--r--contrib/groff/src/devices/grops/ps.cc1570
-rw-r--r--contrib/groff/src/devices/grops/ps.h122
-rw-r--r--contrib/groff/src/devices/grops/psfig.diff106
-rw-r--r--contrib/groff/src/devices/grops/psrm.cc1118
-rw-r--r--contrib/groff/src/devices/grotty/Makefile.sub6
-rw-r--r--contrib/groff/src/devices/grotty/TODO3
-rw-r--r--contrib/groff/src/devices/grotty/tty.cc509
-rw-r--r--contrib/groff/src/include/Makefile.sub42
-rw-r--r--contrib/groff/src/include/assert.h39
-rw-r--r--contrib/groff/src/include/cmap.h56
-rw-r--r--contrib/groff/src/include/cset.h75
-rw-r--r--contrib/groff/src/include/device.h21
-rw-r--r--contrib/groff/src/include/driver.h35
-rw-r--r--contrib/groff/src/include/errarg.h46
-rw-r--r--contrib/groff/src/include/error.h58
-rw-r--r--contrib/groff/src/include/font.h116
-rw-r--r--contrib/groff/src/include/getopt.h169
-rw-r--r--contrib/groff/src/include/groff-getopt.h68
-rw-r--r--contrib/groff/src/include/html-strings.h31
-rw-r--r--contrib/groff/src/include/htmlindicate.h59
-rw-r--r--contrib/groff/src/include/index.h42
-rw-r--r--contrib/groff/src/include/lib.h133
-rw-r--r--contrib/groff/src/include/macropath.h23
-rw-r--r--contrib/groff/src/include/nonposix.h136
-rw-r--r--contrib/groff/src/include/posix.h51
-rw-r--r--contrib/groff/src/include/printer.h77
-rw-r--r--contrib/groff/src/include/ptable.h168
-rw-r--r--contrib/groff/src/include/refid.h35
-rw-r--r--contrib/groff/src/include/search.h96
-rw-r--r--contrib/groff/src/include/searchpath.h30
-rw-r--r--contrib/groff/src/include/stringclass.h195
-rw-r--r--contrib/groff/src/libs/libbib/Makefile.sub14
-rw-r--r--contrib/groff/src/libs/libbib/common.cc38
-rw-r--r--contrib/groff/src/libs/libbib/index.cc641
-rw-r--r--contrib/groff/src/libs/libbib/linear.cc503
-rw-r--r--contrib/groff/src/libs/libbib/map.c71
-rw-r--r--contrib/groff/src/libs/libbib/search.cc132
-rw-r--r--contrib/groff/src/libs/libdriver/Makefile.sub7
-rw-r--r--contrib/groff/src/libs/libdriver/input.cc504
-rw-r--r--contrib/groff/src/libs/libdriver/printer.cc271
-rw-r--r--contrib/groff/src/libs/libgroff/Makefile.sub84
-rw-r--r--contrib/groff/src/libs/libgroff/assert.cc34
-rw-r--r--contrib/groff/src/libs/libgroff/change_lf.cc37
-rw-r--r--contrib/groff/src/libs/libgroff/device.cc36
-rw-r--r--contrib/groff/src/libs/libgroff/errarg.cc118
-rw-r--r--contrib/groff/src/libs/libgroff/error.cc137
-rw-r--r--contrib/groff/src/libs/libgroff/fatal.cc27
-rw-r--r--contrib/groff/src/libs/libgroff/filename.cc1
-rw-r--r--contrib/groff/src/libs/libgroff/fmod.c28
-rw-r--r--contrib/groff/src/libs/libgroff/font.cc938
-rw-r--r--contrib/groff/src/libs/libgroff/fontfile.cc66
-rw-r--r--contrib/groff/src/libs/libgroff/getcwd.c54
-rw-r--r--contrib/groff/src/libs/libgroff/getopt.c1055
-rw-r--r--contrib/groff/src/libs/libgroff/getopt1.c188
-rw-r--r--contrib/groff/src/libs/libgroff/htmlindicate.cc97
-rw-r--r--contrib/groff/src/libs/libgroff/iftoa.c65
-rw-r--r--contrib/groff/src/libs/libgroff/itoa.c43
-rw-r--r--contrib/groff/src/libs/libgroff/lf.cc62
-rw-r--r--contrib/groff/src/libs/libgroff/lineno.cc1
-rw-r--r--contrib/groff/src/libs/libgroff/macropath.cc30
-rw-r--r--contrib/groff/src/libs/libgroff/matherr.c45
-rw-r--r--contrib/groff/src/libs/libgroff/nametoindex.cc118
-rw-r--r--contrib/groff/src/libs/libgroff/new.cc68
-rw-r--r--contrib/groff/src/libs/libgroff/prime.cc26
-rw-r--r--contrib/groff/src/libs/libgroff/progname.cc1
-rw-r--r--contrib/groff/src/libs/libgroff/ptable.cc52
-rw-r--r--contrib/groff/src/libs/libgroff/putenv.c95
-rw-r--r--contrib/groff/src/libs/libgroff/searchpath.cc132
-rw-r--r--contrib/groff/src/libs/libgroff/strerror.c41
-rw-r--r--contrib/groff/src/libs/libgroff/string.cc311
-rw-r--r--contrib/groff/src/libs/libgroff/strsave.cc31
-rw-r--r--contrib/groff/src/libs/libgroff/strtol.c128
-rw-r--r--contrib/groff/src/libs/libgroff/tmpfile.cc186
-rw-r--r--contrib/groff/src/preproc/eqn/Makefile.sub59
-rw-r--r--contrib/groff/src/preproc/eqn/TODO49
-rw-r--r--contrib/groff/src/preproc/eqn/box.cc611
-rw-r--r--contrib/groff/src/preproc/eqn/box.h277
-rw-r--r--contrib/groff/src/preproc/eqn/delim.cc381
-rw-r--r--contrib/groff/src/preproc/eqn/eqn.cc1277
-rw-r--r--contrib/groff/src/preproc/eqn/eqn.h51
-rw-r--r--contrib/groff/src/preproc/eqn/eqn.man882
-rw-r--r--contrib/groff/src/preproc/eqn/eqn.y331
-rw-r--r--contrib/groff/src/preproc/eqn/eqn_tab.h67
-rw-r--r--contrib/groff/src/preproc/eqn/lex.cc1165
-rw-r--r--contrib/groff/src/preproc/eqn/limit.cc195
-rw-r--r--contrib/groff/src/preproc/eqn/list.cc237
-rw-r--r--contrib/groff/src/preproc/eqn/main.cc419
-rw-r--r--contrib/groff/src/preproc/eqn/mark.cc121
-rw-r--r--contrib/groff/src/preproc/eqn/neqn.man21
-rw-r--r--contrib/groff/src/preproc/eqn/other.cc601
-rw-r--r--contrib/groff/src/preproc/eqn/over.cc196
-rw-r--r--contrib/groff/src/preproc/eqn/pbox.h141
-rw-r--r--contrib/groff/src/preproc/eqn/pile.cc293
-rw-r--r--contrib/groff/src/preproc/eqn/script.cc221
-rw-r--r--contrib/groff/src/preproc/eqn/special.cc115
-rw-r--r--contrib/groff/src/preproc/eqn/sqrt.cc179
-rw-r--r--contrib/groff/src/preproc/eqn/text.cc528
-rw-r--r--contrib/groff/src/preproc/grn/Makefile.sub17
-rw-r--r--contrib/groff/src/preproc/grn/README60
-rw-r--r--contrib/groff/src/preproc/grn/gprint.h84
-rw-r--r--contrib/groff/src/preproc/grn/grn.man636
-rw-r--r--contrib/groff/src/preproc/grn/hdb.cc326
-rw-r--r--contrib/groff/src/preproc/grn/hgraph.cc1043
-rw-r--r--contrib/groff/src/preproc/grn/hpoint.cc49
-rw-r--r--contrib/groff/src/preproc/grn/main.cc905
-rw-r--r--contrib/groff/src/preproc/html/Makefile.sub7
-rw-r--r--contrib/groff/src/preproc/html/pre-html.cc1160
-rw-r--r--contrib/groff/src/preproc/html/pre-html.h37
-rw-r--r--contrib/groff/src/preproc/html/pushbackbuffer.cc337
-rw-r--r--contrib/groff/src/preproc/html/pushbackbuffer.h54
-rw-r--r--contrib/groff/src/preproc/pic/Makefile.sub31
-rw-r--r--contrib/groff/src/preproc/pic/TODO37
-rw-r--r--contrib/groff/src/preproc/pic/common.cc497
-rw-r--r--contrib/groff/src/preproc/pic/common.h70
-rw-r--r--contrib/groff/src/preproc/pic/lex.cc1940
-rw-r--r--contrib/groff/src/preproc/pic/main.cc635
-rw-r--r--contrib/groff/src/preproc/pic/object.cc1833
-rw-r--r--contrib/groff/src/preproc/pic/object.h217
-rw-r--r--contrib/groff/src/preproc/pic/output.h79
-rw-r--r--contrib/groff/src/preproc/pic/pic.cc5216
-rw-r--r--contrib/groff/src/preproc/pic/pic.h104
-rw-r--r--contrib/groff/src/preproc/pic/pic.man883
-rw-r--r--contrib/groff/src/preproc/pic/pic.y1812
-rw-r--r--contrib/groff/src/preproc/pic/pic_tab.h131
-rw-r--r--contrib/groff/src/preproc/pic/position.h47
-rw-r--r--contrib/groff/src/preproc/pic/tex.cc412
-rw-r--r--contrib/groff/src/preproc/pic/text.h28
-rw-r--r--contrib/groff/src/preproc/pic/troff.cc504
-rw-r--r--contrib/groff/src/preproc/refer/Makefile.sub23
-rw-r--r--contrib/groff/src/preproc/refer/TODO124
-rw-r--r--contrib/groff/src/preproc/refer/command.cc807
-rw-r--r--contrib/groff/src/preproc/refer/command.h36
-rw-r--r--contrib/groff/src/preproc/refer/label.cc1602
-rw-r--r--contrib/groff/src/preproc/refer/label.y1177
-rw-r--r--contrib/groff/src/preproc/refer/ref.cc1160
-rw-r--r--contrib/groff/src/preproc/refer/ref.h120
-rw-r--r--contrib/groff/src/preproc/refer/refer.cc1234
-rw-r--r--contrib/groff/src/preproc/refer/refer.h78
-rw-r--r--contrib/groff/src/preproc/refer/refer.man1302
-rw-r--r--contrib/groff/src/preproc/refer/token.cc378
-rw-r--r--contrib/groff/src/preproc/refer/token.h88
-rw-r--r--contrib/groff/src/preproc/soelim/Makefile.sub6
-rw-r--r--contrib/groff/src/preproc/soelim/TODO1
-rw-r--r--contrib/groff/src/preproc/soelim/soelim.cc347
-rw-r--r--contrib/groff/src/preproc/soelim/soelim.man85
-rw-r--r--contrib/groff/src/preproc/tbl/Makefile.sub12
-rw-r--r--contrib/groff/src/preproc/tbl/main.cc1528
-rw-r--r--contrib/groff/src/preproc/tbl/table.cc2778
-rw-r--r--contrib/groff/src/preproc/tbl/table.h152
-rw-r--r--contrib/groff/src/preproc/tbl/tbl.man178
-rw-r--r--contrib/groff/src/roff/groff/Makefile.sub8
-rw-r--r--contrib/groff/src/roff/groff/groff.cc731
-rw-r--r--contrib/groff/src/roff/groff/pipeline.c411
-rw-r--r--contrib/groff/src/roff/groff/pipeline.h30
-rw-r--r--contrib/groff/src/roff/grog/Makefile.sub26
-rw-r--r--contrib/groff/src/roff/grog/grog.man86
-rw-r--r--contrib/groff/src/roff/grog/grog.pl183
-rw-r--r--contrib/groff/src/roff/grog/grog.sh91
-rw-r--r--contrib/groff/src/roff/nroff/Makefile.sub20
-rw-r--r--contrib/groff/src/roff/troff/Makefile.sub48
-rw-r--r--contrib/groff/src/roff/troff/TODO134
-rw-r--r--contrib/groff/src/roff/troff/charinfo.h171
-rw-r--r--contrib/groff/src/roff/troff/column.cc732
-rw-r--r--contrib/groff/src/roff/troff/dictionary.cc212
-rw-r--r--contrib/groff/src/roff/troff/dictionary.h92
-rw-r--r--contrib/groff/src/roff/troff/div.cc1161
-rw-r--r--contrib/groff/src/roff/troff/div.h156
-rw-r--r--contrib/groff/src/roff/troff/env.cc3439
-rw-r--r--contrib/groff/src/roff/troff/env.h350
-rw-r--r--contrib/groff/src/roff/troff/hvunits.h340
-rw-r--r--contrib/groff/src/roff/troff/input.cc6891
-rw-r--r--contrib/groff/src/roff/troff/input.h92
-rw-r--r--contrib/groff/src/roff/troff/node.cc5621
-rw-r--r--contrib/groff/src/roff/troff/node.h584
-rw-r--r--contrib/groff/src/roff/troff/number.cc692
-rw-r--r--contrib/groff/src/roff/troff/reg.cc473
-rw-r--r--contrib/groff/src/roff/troff/reg.h76
-rw-r--r--contrib/groff/src/roff/troff/request.h84
-rw-r--r--contrib/groff/src/roff/troff/symbol.cc150
-rw-r--r--contrib/groff/src/roff/troff/symbol.h73
-rw-r--r--contrib/groff/src/roff/troff/token.h218
-rw-r--r--contrib/groff/src/roff/troff/troff.h88
-rw-r--r--contrib/groff/src/roff/troff/troff.man2462
-rw-r--r--contrib/groff/src/utils/addftinfo/Makefile.sub11
-rw-r--r--contrib/groff/src/utils/addftinfo/addftinfo.cc218
-rw-r--r--contrib/groff/src/utils/addftinfo/addftinfo.man107
-rw-r--r--contrib/groff/src/utils/addftinfo/guess.cc490
-rw-r--r--contrib/groff/src/utils/addftinfo/guess.h44
-rw-r--r--contrib/groff/src/utils/afmtodit/Makefile.sub23
-rw-r--r--contrib/groff/src/utils/afmtodit/afmtodit.man225
-rw-r--r--contrib/groff/src/utils/afmtodit/afmtodit.pl331
-rw-r--r--contrib/groff/src/utils/hpftodit/Makefile.sub6
-rw-r--r--contrib/groff/src/utils/hpftodit/hpftodit.cc827
-rw-r--r--contrib/groff/src/utils/hpftodit/hpftodit.man155
-rw-r--r--contrib/groff/src/utils/indxbib/Makefile.sub31
-rw-r--r--contrib/groff/src/utils/indxbib/dirnamemax.c49
-rw-r--r--contrib/groff/src/utils/indxbib/eign133
-rw-r--r--contrib/groff/src/utils/indxbib/indxbib.cc805
-rw-r--r--contrib/groff/src/utils/indxbib/indxbib.man207
-rw-r--r--contrib/groff/src/utils/indxbib/signal.c63
-rw-r--r--contrib/groff/src/utils/lkbib/Makefile.sub6
-rw-r--r--contrib/groff/src/utils/lkbib/lkbib.cc137
-rw-r--r--contrib/groff/src/utils/lkbib/lkbib.man110
-rw-r--r--contrib/groff/src/utils/lookbib/Makefile.sub7
-rw-r--r--contrib/groff/src/utils/lookbib/lookbib.cc140
-rw-r--r--contrib/groff/src/utils/lookbib/lookbib.man78
-rw-r--r--contrib/groff/src/utils/pfbtops/Makefile.sub6
-rw-r--r--contrib/groff/src/utils/pfbtops/pfbtops.c131
-rw-r--r--contrib/groff/src/utils/pfbtops/pfbtops.man44
-rw-r--r--contrib/groff/src/utils/tfmtodit/Makefile.sub6
-rw-r--r--contrib/groff/src/utils/tfmtodit/tfmtodit.cc874
-rw-r--r--contrib/groff/src/utils/tfmtodit/tfmtodit.man175
-rw-r--r--contrib/groff/src/xditview/ChangeLog413
-rw-r--r--contrib/groff/src/xditview/DESC9
-rw-r--r--contrib/groff/src/xditview/Dvi.c573
-rw-r--r--contrib/groff/src/xditview/Dvi.h46
-rw-r--r--contrib/groff/src/xditview/DviChar.c664
-rw-r--r--contrib/groff/src/xditview/DviChar.h37
-rw-r--r--contrib/groff/src/xditview/DviP.h233
-rw-r--r--contrib/groff/src/xditview/FontMap17
-rw-r--r--contrib/groff/src/xditview/GXditview-ad.h52
-rw-r--r--contrib/groff/src/xditview/GXditview.ad57
-rw-r--r--contrib/groff/src/xditview/INSTALL20
-rw-r--r--contrib/groff/src/xditview/Imakefile.in104
-rw-r--r--contrib/groff/src/xditview/Menu.h46
-rw-r--r--contrib/groff/src/xditview/README14
-rw-r--r--contrib/groff/src/xditview/TODO17
-rw-r--r--contrib/groff/src/xditview/XFontName.c256
-rw-r--r--contrib/groff/src/xditview/XFontName.h45
-rw-r--r--contrib/groff/src/xditview/ad2c62
-rw-r--r--contrib/groff/src/xditview/device.c600
-rw-r--r--contrib/groff/src/xditview/device.h21
-rw-r--r--contrib/groff/src/xditview/draw.c721
-rw-r--r--contrib/groff/src/xditview/font.c471
-rw-r--r--contrib/groff/src/xditview/gray1.bm4
-rw-r--r--contrib/groff/src/xditview/gray2.bm4
-rw-r--r--contrib/groff/src/xditview/gray3.bm4
-rw-r--r--contrib/groff/src/xditview/gray4.bm4
-rw-r--r--contrib/groff/src/xditview/gray5.bm4
-rw-r--r--contrib/groff/src/xditview/gray6.bm4
-rw-r--r--contrib/groff/src/xditview/gray7.bm4
-rw-r--r--contrib/groff/src/xditview/gray8.bm4
-rw-r--r--contrib/groff/src/xditview/gxditview.man246
-rw-r--r--contrib/groff/src/xditview/lex.c103
-rw-r--r--contrib/groff/src/xditview/page.c88
-rw-r--r--contrib/groff/src/xditview/parse.c335
-rw-r--r--contrib/groff/src/xditview/xdit.bm14
-rw-r--r--contrib/groff/src/xditview/xdit_mask.bm14
-rw-r--r--contrib/groff/src/xditview/xditview.c594
-rw-r--r--contrib/groff/src/xditview/xtotroff.c311
-rwxr-xr-xcontrib/groff/test-groff3
-rw-r--r--contrib/groff/tmac/Makefile.sub97
-rw-r--r--contrib/groff/tmac/X.tmac48
-rw-r--r--contrib/groff/tmac/Xps.tmac46
-rw-r--r--contrib/groff/tmac/a4.tmac12
-rw-r--r--contrib/groff/tmac/an-old.tmac478
-rw-r--r--contrib/groff/tmac/an.tmac3
-rw-r--r--contrib/groff/tmac/andoc.tmac14
-rw-r--r--contrib/groff/tmac/doc-old.tmac1858
-rw-r--r--contrib/groff/tmac/doc.tmac6189
-rw-r--r--contrib/groff/tmac/dvi.tmac147
-rw-r--r--contrib/groff/tmac/e.tmac1663
-rw-r--r--contrib/groff/tmac/fixmacros.sed1
-rw-r--r--contrib/groff/tmac/groff_man.man82
-rw-r--r--contrib/groff/tmac/groff_mdoc.man4257
-rw-r--r--contrib/groff/tmac/groff_me.man16
-rw-r--r--contrib/groff/tmac/groff_ms.man17
-rw-r--r--contrib/groff/tmac/groff_mwww.man275
-rw-r--r--contrib/groff/tmac/groff_tmac.man116
-rw-r--r--contrib/groff/tmac/html.tmac47
-rw-r--r--contrib/groff/tmac/hyphen.us4449
-rw-r--r--contrib/groff/tmac/latin1.tmac103
-rw-r--r--contrib/groff/tmac/lbp.tmac15
-rw-r--r--contrib/groff/tmac/lj4.tmac20
-rw-r--r--contrib/groff/tmac/man.local4
-rw-r--r--contrib/groff/tmac/man.tmac3
-rw-r--r--contrib/groff/tmac/mandoc.tmac3
-rw-r--r--contrib/groff/tmac/mdoc.local2
-rw-r--r--contrib/groff/tmac/mdoc.tmac3
-rw-r--r--contrib/groff/tmac/me.tmac3
-rw-r--r--contrib/groff/tmac/ms.tmac3
-rw-r--r--contrib/groff/tmac/mwww.tmac3
-rw-r--r--contrib/groff/tmac/pic.tmac12
-rw-r--r--contrib/groff/tmac/ps.tmac54
-rw-r--r--contrib/groff/tmac/psatk.tmac63
-rw-r--r--contrib/groff/tmac/psfig.tmac89
-rw-r--r--contrib/groff/tmac/psold.tmac61
-rw-r--r--contrib/groff/tmac/pspic.tmac60
-rw-r--r--contrib/groff/tmac/s.tmac1934
-rw-r--r--contrib/groff/tmac/safer.tmac5
-rw-r--r--contrib/groff/tmac/trace.tmac29
-rw-r--r--contrib/groff/tmac/troffrc-end17
-rw-r--r--contrib/groff/tmac/tty-char.tmac204
-rw-r--r--contrib/groff/tmac/tty.tmac50
-rw-r--r--contrib/groff/tmac/www.tmac211
-rw-r--r--contrib/groff/win32-diffs11
610 files changed, 224912 insertions, 3265 deletions
diff --git a/contrib/groff/ChangeLog b/contrib/groff/ChangeLog
index 897767e..e9b435a 100644
--- a/contrib/groff/ChangeLog
+++ b/contrib/groff/ChangeLog
@@ -1,3 +1,1755 @@
+Version 1.17 released
+=====================
+
+2001-04-17 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/Makefile.sub (install-data): mdoc.local-s is in current
+ directory, not in $(srcdir).
+
+2001-04-16 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: More info on conditionals.
+
+2001-04-15 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Added some info about groff internals.
+
+ * src/roff/troff/node.cc (make_glyph_node): Emit warning message
+ about missing special character only if the name is non-null.
+
+2001-04-14 Werner LEMBERG <wl@gnu.org>
+
+ Removing the grohtml-old device driver which is now obsolete.
+
+ * src/devices/grohtml-old/*: Removed.
+ * font/devhtml-old/*: Removed.
+ * src/libgroff/htmlindicate.cc (graphic_start, graphic_end): Remove
+ comments.
+ * Makefile.in (CCPROGDIRS, DEVDIRS): Updated.
+ * test-groff (PATH): Updated.
+ * tmac/Makefile.sub (NORMALFILES): Updated.
+ * tmac/an-old.tmac: Remove special code for html-old device.
+ Replace `html-or-html-old' register with `an-html'.
+ * tmac/eqnrc: Updated.
+ * tmac/html-old.tmac: Removed.
+ * tmac/troffrc, tmac/troffrc-end: Updated.
+ * tmac/www.tmac: Remove special code for html-old device.
+ Replace `html-or-html-old' register with `www-html'.
+
+ * src/libgroff/tmpfile.cc (remove_tmp_files),
+ src/libgroff/htmlindicate.cc (graphic_end), include/htmlindicate.h,
+ src/preproc/grn/*.cc, src/roff/groff/env.{cc,h}: Remove `void'
+ parameter if used as a single argument for consistency with rest of
+ source code.
+
+ * aclocal.m4, tmac/an-old.tmac: Fix copyright.
+
+2001-04-13 Ruslan Ermilov <ru@FreeBSD.org>
+
+ * src/roff/troff/troff.man: Fixing typos.
+
+2001-04-13 Werner LEMBERG <wl@gnu.org>
+
+ * doc/pic.ms: Fixing many font switches.
+ * doc/groff.texinfo: Fixes, additions.
+ * MORE.STUFF: Updated.
+
+2001-04-12 Gaius Mulley <gaius@glam.ac.uk>
+
+ * src/devices/grohtml/grohtml.man: Updated manual page regarding
+ simple anchor.
+ * src/preproc/html/pre-html.cc (createImage): Fixed right hand
+ cropping of images.
+ (removeTempFiles): New function to tidy up temporary files.
+ * src/preproc/html/pre-html.cc (main): Calls `removeTempFiles()'.
+ Many fixes to do with the new inline suppress node and image regions
+ are much tighter.
+ * src/devices/grohtml/post-html.cc: New method `is_auto_img'.
+ (generate_img_src): New function.
+ (html_printer::do_auto_image): Utilizes it.
+ (do_heading, do_title): Include inline images within their contents.
+ (html_printer::begin_page): Tidied up comments that are issued to
+ the html output file.
+ (html_printer::do_fill): Fixed so that `.nf' works with fonts other
+ than courier.
+ (text_glob::is_br): New method used by do_heading.
+ * tmac/s.tmac: If -Thtml then emit $1 in .IP rather than its
+ equivalent diversion.
+ * src/include/html-strings.h: Altered image tags to reflect the
+ inline image node.
+ * src/include/htmlindicate.h (html_end_suppress): Added `is_inline'
+ parameter.
+ * src/preproc/eqn/main.cc: Will suppress generation of image tags if
+ it is already inside a pic image. Only emit tags if the argument
+ `-Tps:html' is present.
+ * src/preproc/tbl/main.cc: Changes to reflect additional
+ `html_end_suppress' parameter.
+ * src/roff/troff/env.cc: Only emit eol tag if a node has been
+ emitted since the last eol tag was written.
+ * src/roff/troff/env.h: New boolean `emitted_node'.
+ * src/roff/troff/input.cc (do_suppress): Handles extra suppress
+ nodes \O3, \O4, \O5. No longer use `output_low_mark_miny'.
+ * src/roff/troff/node.cc (check_charinfo): New method.
+ (troff_output_file::determine_line_limits): Alterations to limit
+ checking.
+ * tmac/www.tmac: Changes to reflect new suppress nodes.
+
+2001-04-12 Bruno Haible <haible@clisp.cons.org>
+
+ * src/devices/grohtml/post-html.cc (html_printer::add_to_sbuf):
+ Escape the html_glyph in the buffer.
+ (str_translate_to_html): Output the unescaped escaped_char.
+ * src/devices/grohtml/html-text.cc (issue_table_begin): Set
+ `frame=void', not `frame=none'. Add `border=0'.
+
+2001-04-12 Ruslan Ermilov <ru@FreeBSD.org>
+
+ * contrib/mm/groff_mm.man: Fixing some typos.
+
+2001-04-12 Werner LEMBERG <wl@gnu.org>
+
+ * PROBLEMS: Add some words on how to avoid wrapper macros.
+
+2001-04-11 Blake McBride <blake@florida-software.com>
+
+ * src/include/nonposix.h (fileno) [_MSC_VER]: Removed.
+
+2001-04-11 Werner LEMBERG <wl@gnu.org>
+
+ * font/devlbp/Makefile.sub (CLEANADD): Set it.
+ * tmac/Makefile.sub (CLEANADD): Add tmac.local-s.
+ * Makefile.in (dist): Don't remove src/xditview/Imakefile, but ...
+ * Makefile.sub (DISTCLEANFILES): Here.
+
+ * libs/libgroff/new.cc: Include `nonposix.h'.
+ * win32-diffs: Updated.
+
+2001-04-10 Ruslan Ermilov <ru@FreeBSD.org>
+
+ Added skeleton macro for defunct macros.
+
+ Updated documentation.
+
+ When inside displays, an empty input line warning should be
+ suppressed. If another macro call is put inside a display,
+ all subsequent empty lines found in that display caused a
+ warning to be emitted.
+
+ * tmac/doc.tmac (doc-defunct-macro): New macro.
+ (Db, Ds, Ex, Or, Sf): Reimplemented using this macro.
+ (doc-restore-global-vars): Fixed typo.
+ (doc-empty-line): Check the `doc-display-depth' register to
+ determine whether we are inside display or not.
+
+ * tmac/doc-common: Removed `Or' and `Sf' registers.
+ Moved obsolete `Ds' macro to doc.tmac.
+
+ * tmac/groff_mdoc.man: Bump document date.
+ Document `.Vt' under ``Variable Types''.
+ Removed documentation for obsolete `.Or' macro.
+
+2001-04-10 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS: Updated.
+ * doc/groff.texinfo: Many fixes, additions, clarifications, etc.
+
+2001-04-10 Bruno Haible <haible@clisp.cons.org>
+
+ * src/devices/grodvi/dvi.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+ * src/devices/grohtml/post-html.cc (main): Accept --help and --version.
+ Write --version output to stdout, not stderr.
+ (usage): Add stream argument. Don't exit.
+ * src/devices/grohtml-old/html.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+ * src/devices/grolbp/lbp.cc (long_options): Use symbolic getopt.h
+ constants.
+ (usage): Add stream argument. Don't exit.
+ (main): Write --help output to stdout, not stderr.
+ * src/devices/grolj4/lj4.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+ * src/devices/grops/ps.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+ * src/devices/grotty/tty.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+ * src/preproc/eqn/main.cc (usage): Add stream argument. Don't exit.
+ (main): Accept --help and --version.
+ * src/preproc/grn/main.cc (usage): Add stream argument. Don't exit.
+ (main): Accept --help and --version.
+ * src/preproc/html/pre-html.cc (usage): Add stream argument.
+ (scanArguments): Accept --help and --version.
+ * src/preproc/pic/main.cc (usage): Add stream argument. Don't exit.
+ (main): Accept --help and --version.
+ * src/preproc/refer/refer.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+ * src/preproc/soelim/soelim.cc (usage): Add stream argument. Don't
+ exit.
+ (main): Accept --help and --version.
+ * src/preproc/tbl/main.cc (usage): Add stream argument. Don't exit.
+ (main): Accept --help and --version.
+ * src/roff/groff/groff.cc (main): Accept --help and --version.
+ (synopsis): Add stream argument.
+ (help): Write --help output to stdout, not stderr.
+ (usage): Add stream argument. Don't exit.
+ * src/roff/grog/grog.pl: Accept --help and --version.
+ (help): New sub.
+ * src/roff/grog/grog.sh: Accept --help and --version.
+ * src/roff/nroff/nroff.sh: Accept --help and --version.
+ * src/roff/troff/input.cc (USAGE_EXIT_CODE): Remove macro.
+ (usage): Add stream argument. Don't exit.
+ (main): Accept --help and --version.
+ * src/utils/addftinfo/addftinfo.cc (main): Accept --help and --version.
+ (usage): New function with stream argument, doesn't exit.
+ * src/utils/hpftodit/hpftodit.cc (main): Accept --help and --version.
+ (usage): New function with stream argument, doesn't exit.
+ * src/utils/indxbib/indxbib.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+ * src/utils/lkbib/lkbib.cc (usage): Add stream argument. Don't exit.
+ (main): Accept --help and --version.
+ * src/utils/lookbib/lookbib.cc (usage): Add stream argument. Don't
+ exit.
+ (main): Accept --help and --version.
+ * src/utils/pfbtops/pfbtops.c (usage): Add stream argument. Don't exit.
+ (main): Accept --help and --version.
+ * src/utils/tfmtodit/tfmtodit.cc (main): Accept --help and --version.
+ (usage): Add stream argument. Don't exit.
+
+2001-04-10 Ruslan Ermilov <ru@freebsd.org>
+
+ Fix indentation in SYNOPSIS.
+
+ Updated to include changes of latest BSD mdoc version (basically,
+ the only change is that `.Fn' and `.Fc' put a final semicolon after
+ a function declaration in the SYNOPSIS section).
+
+ * tmac/doc.tmac (doc-in-synopsis-count): Replaced with ...
+ (doc-in-synopsis-section): New variable. Updated all related
+ functions.
+ (doc-indent-synopsis-active): New register.
+ (Nd, Fn, Fo): Use it.
+ (Cd): It requires manipulation of \n[doc-indent-synopsis] so that
+ `.Cd' with long argument line produces indented wrapped lines.
+ Also, the misplaced `.nop \*[doc-Nm-font]\c'' caused extra
+ undesirable line break to be output.
+ (doc-do-func-decl, Nm, Vt, Fn, Fo): Remove extraneous calls to
+ `.rs'.
+ (Fn, Fc): Add final `;' to output.
+ (doc-save-global-vars, doc-restore-global-vars): Updated.
+ * tmac/doc-common: Remove `Ex' register.
+ Updated.
+ * tmac/doc-ditroff, tmac/doc-nroff, tmac/doc-syms: Updated
+ copyright.
+
+2001-04-06 Ruslan Ermilov <ru@freebsd.org>
+
+ * tmac/doc.tmac (Cd): Simplify code.
+ * tmac/groff_mdoc.man: Document some behaviour of `Cd' request.
+
+2001-04-06 Werner Lemberg <wl@gnu.org>
+
+ Implement continuous underlining for nroff mode. To do that, a new
+ request in the ditroff language has been added: `x u N' (N is 0
+ or 1).
+
+ \X and \Y are now transparent to end-of-sentence recognition.
+
+ * src/include/printer.h (printer): Add `type' parameter to `special'
+ method.
+ * src/libs/libdriver/printer.cc (printer::special): Updated.
+ * src/libs/libdriver/input.cc (do_file): Handle `x u N'.
+
+ * src/devices/dvi/dvi.cc (dvi_printer::special): Handle only
+ specials of type `p'.
+ * src/devices/grohtml/post-html.cc (html_printer::special): Ditto.
+ * src/devices/grohtml-old/html.cc (html_printer::special): Ditto.
+ * src/devices/grops/ps.cc (ps_printer::special): Ditto.
+ * src/devices/grotty/tty.cc: Add new enum CU_MODE.
+ (glyph::order): New method.
+ (tty_printer::add_char): Use it.
+ (tty_printer::special): New method.
+ (tty_printer::end_page): Implement it.
+
+ * src/roff/troff/node.h (special_node): Add `no_init_string' member.
+ * src/roff/troff/node.cc (special_node::special_node): Add parameter
+ to set `no_init_string'.
+ (special_node::tprint_start): Use it.
+ (special_node::same, special_node::copy): Updated.
+ (special_node::ends_sentence): New method.
+ (troff_output_file::start_special): Add parameter to include
+ inititialization of special conditionally.
+
+ * src/roff/troff/env.h (environment): New member `underline_spaces'.
+ * src/roff/troff/env.cc (do_underline_special): New function.
+ (environment::set_font): Use it.
+ (do_underline): Use it. This was `underline()'.
+ (underline): Call `do_underline()'.
+ (continuous_underline): New function which calls `do_underline()'.
+ (environment::newline): Use `do_underline_special()'.
+ (init_env_requests): Updated.
+
+ * NEWS, man/troff_out.man: Updated.
+
+2001-04-06 Bruno Haible <haible@clisp.cons.org>
+
+ * font/devutf8/R.proto: Fix code of 'shc'.
+
+2001-04-06 Ruslan Ermilov <ru@freebsd.org>
+
+ Many fixes. Diag lists can now be nested also; additionally,
+ `-compact' and `-offset' are supported.
+
+ * tmac/doc.tmac (doc-have-indent): Replaced with ...
+ (doc-list-have-indent-stackXXX): A new register stack.
+ (doc-have-diag-list): Removed.
+ (Bl): Use `doc-list-have-indent-stackXXX'.
+ (El): Updated.
+ (doc-diag-list): Use `doc-compact-list-stackXXX'.
+ (doc-tag-list): Use `doc-list-have-indent-stackXXX'.
+ (doc-set-vertical-and-indent): Ditto.
+ (doc-next-list-depth): Removed.
+ (doc-increment-list-stack): Updated.
+ (doc-decrement-list-stack): Use `doc-list-depth' instead of
+ `doc-next-list-depth'.
+ (doc-end-list, doc-end-column-list): Don't use
+ `doc-increment-list-stack'.
+ (doc-set-column-tab): Don't use `doc-list-offset-stackXXX'.
+ (doc-save-global-vars, doc-restore-global-vars): Updated.
+ * tmac/doc-common: Updated.
+ * tmac/groff_mdoc.man: Updated.
+ * NEWS: Fix typo.
+
+2001-04-02 Werner LEMBERG <wl@gnu.org>
+
+ * src/devices/grotty/grotty.man: Fix grammatical error.
+
+2001-03-30 Ruslan Ermilov <ru@freebsd.org>
+
+ Remove .Ld from mdoc package; replace it with special handling of
+ `...'.
+
+ * tmac/doc-common: Remove `Ld' register.
+ Uncomment `doc-volume-ds-*' strings.
+ Remove `doc-operating-system-default'.
+ (Os): Updated.
+ * tmac/doc-syms (Ld): Removed.
+ * tmac/doc.tmac (doc-parse-args, doc-parse-arg-vector): Handle
+ `...' specially.
+ * NEWS: Updated.
+
+ * tmac/groff_mdoc.man: Many fixes and updates.
+
+2001-03-29 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/troffrc-end: Protect data with `.do'. Reported by T. Kurt
+ Bond <tkb@tkb.mpl.com>.
+ * tmac/www.tmac: Save compatibility mode.
+
+2001-03-28 Ruslan Ermilov <ru@freebsd.org>
+
+ * tmac/groff_mdoc.man: Many fixes.
+
+2001-03-28 Werner LEMBERG <wl@gnu.org>
+
+ * src/preproc/soelim/soelim.man: Document that `.<whitespace>so'
+ isn't recognized.
+
+2001-03-27 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/an-old.tmac (TP, an-do-tag): Reduce line length while in
+ diversion. This fixes overlong tags.
+
+2001-03-26 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Fixed and improved documentation of fonts.
+ * tmac/doc-syms: Fix error messages.
+ * tmac/an-old.tmac: Remove incorrect double backslashes.
+
+2001-03-24 Ruslan Ermilov <ru@freebsd.org>
+
+ * tmac/Makefile.sub: Strip mdoc.local also
+ * tmac/strip.sed: Fixed.
+
+2001-03-24 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/doc-nroff, tmac/doc-ditroff: Implement -rSxx switch for
+ selecting the font size.
+ * tmac/groff_mdoc.man, NEWS: Document it.
+
+2001-03-23 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/div.cc (save_vertical_space): Add default argument
+ to `sv' request.
+ * src/roff/troff/env.cc (family_change): Make `.fam' accept no
+ argument to restore previous font family.
+ * src/roff/troff/troff.man, man/groff.man, NEWS: Updated.
+
+ * doc/groff.texinfo: More fixes and additions (mainly for font
+ manipulating commands).
+
+ * tmac/groff_mdoc.reference.man: Small updates and renamed to ...
+ * tmac/groff_mdoc.man: This. The quick reference has been removed.
+ * tmac/Makefile.sub, NEWS: Updated.
+
+2001-03-23 Werner LEMBERG <wl@gnu.org>
+
+ Replaced mdoc implementation. The new version is `state of the
+ art', using almost all new features of groff 1.17 -- it won't run
+ with older versions.
+
+ * tmac/doc.tmac: Completely rewritten.
+ * tmac/doc-common: Ditto.
+ * tmac/doc-nroff: Ditto.
+ * tmac/doc-ditroff: Ditto.
+ * tmac/doc-syms: Ditto.
+ * tmac/mdoc.local: New file.
+ * tmac/groff_mdoc.samples.man: Replaced with ...
+ * tmac/groff_mdoc.reference.man: New file, covering mdoc completely.
+ * tmac/strip.sed: Updated.
+ * tmac/Makefile.sub: Updated.
+ * INSTALL: Updated.
+
+ * tmac/groff_man.man: Add `man.local' to the FILES section.
+
+2001-03-22 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Added many @noindent.
+ Replaced @end_Example -> @endExample.
+ Added info whether registers are r/o.
+ Many other additions and fixes.
+
+2001-03-21 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Added macro @Var (and some hacks due to bugs
+ in makeinfo of texinfo 4.0) to be used in @Def* macros.
+ Improved @Def* macros: Now the exact syntax of request, register,
+ and escapes is shown.
+ Added macros for parentheses and brackets to be used in @Def*.
+ Many fixes and improvements of the documentation.
+
+2001-03-20 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Added new index: `st' (for strings).
+ Added macros @Defstr(x).
+ Added macro @Example (adding @group).
+ Other minor improvements.
+
+2001-03-19 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Added two new indices: `es' (for escapes) and
+ `rq' for requests. `fn' is no longer used.
+ Added macros @Defreq(x), @Defreg(x), and @Defesc(x).
+ Removed @Deffn(x).
+
+ * tmac/an-old.tmac (an-p-footer): If `cR' is set, replace page
+ number with name of man page.
+
+2001-03-19 Larry Kollar <kollar@alltel.net>
+
+ * doc/groff.texinfo: Complete revision. Added many @Deffn to gain
+ consistency.
+
+2001-03-19 Werner LEMBERG <wl@gnu.org>
+
+ * man/groff_font.man: Document `prepro', `postpro', and `print'.
+ * src/roff/groff/groff.man: Improve documentation of `-l' and `-L'.
+ * src/devices/grohtml/grohtml.man: Fixing typos.
+
+2001-03-19 Gaius Mulley <gaius@glam.ac.uk>
+
+ * tmac/s.tmac (@IP): Pass `.ip' html tag.
+ * tmac/groff_mwww.man: Remove .LINE macro
+ * tmac/www.tmac (LINE): Add `.ti'.
+
+ * src/devices/grohtml/post-html.cc (html_printer): New member
+ `indent'.
+ (html_printer::emit_raw): Use it.
+ (html_printer::do_linelength): Ditto.
+ (html_printer::do_pageoffset): Ditto.
+ (html_printer::do_indentation): Ditto.
+ (html_printer::do_tempindent): Ditto.
+ (html_printer::do_break): Ditto.
+ (html_printer::begin_page): Ditto.
+ (html_printer::do_indentedparagraph): New function.
+ (html_printer::troff_tag): Handle `.ip'.
+ * src/devices/grohtml/html-text.cc (html_text::issue_table_begin):
+ Add `<td width=...>' handling.
+ (html_text::do_table): Add parameter.
+ (html_text::do_indent): Updated.
+ * src/devices/groohtml/html-text.h: Updated.
+
+2001-03-16 Gaius Mulley <gaius@glam.ac.uk>
+
+ Introduced simple html tables to implement indentation.
+
+ * src/devices/grohtml/html.h (word, word_list): New structures.
+ (simple_output): Use it.
+ * src/devices/grohtml/post-html.cc: Add `INDENTATION'.
+ (html_printer): Improve indentation handling.
+ (html_printer::emit_raw): Set `in_table' element. Handle
+ indentation if set.
+ (html_printer::write_header): Move conditional downwards.
+ Don't allow whitespace in tags.
+ (html_printer::do_linelength): Handle line length and indentation
+ conditionally.
+ (html_printer::do_pageoffset): Handle indentation conditionally.
+ (html_printer::do_indentation): Ditto.
+ (html_printer::do_tempindent): New function member.
+ (html_printer::do_fill): Take care of indentation.
+ (html_printer::do_flush): Finish table.
+ (html_printer::do_links): Ditto.
+ (html_printer::do_break): New function for handling `.br' and `.ti'.
+ (html_printer::troff_tag): Use it.
+ Handle `.ti'.
+ (html_printer::flush_globs): Fix.
+ (html_printer::flush_page): Finish table.
+ (html_printer::html_printer): Fix error message. Set up
+ `linelength'.
+ (html_printer::add_to_sbuf): Remove special handling of character
+ code 255.
+ (to_unicode): Remove `stop()'.
+ (html_printer::write_title): Cleanup.
+ (html_printer::begin_page): Use `put_string()'. Handle indentation.
+ (html_printer::~html_printer): Flush text and end the line.
+ Use `put_string()'.
+ * src/devices/grohtml/html_text.h: Add more *_TAG enum values.
+ * src/devices/grohtml/html_text.cc (html_text::end_tag): Fix
+ emission of tags.
+ (html_text::start_tag): Disable newlines.
+ (html_text::table_is_void): New function.
+ (html_text::issue_table_begin): Ditto.
+ (html_text::issue_table_end): Ditto.
+ (html_text::push_para): Better table handling.
+ (html_text::do_indent): New function.
+ (html_text::do_table): Ditto.
+ (html_text::done_table): Ditto.
+ (html_text::do_tt): Handle PRE_TAG.
+ (html_text::is_in_table): New function.
+ (html_text::check_emit_text): Handle tables.
+ (html_text::do_emittext): Use `nl()'.
+ (html_text::do_para): Handle table.
+ (html_text::remove_def): New function.
+ * src/devices/grohtml/output.cc (word, word_list): Implement
+ methods.
+ (simple_output::end_line): Flush last word.
+ (simple_output::simple_comment): Ditto.
+ (simple_output::begin_comment): Recoded.
+ (simple_output::end_comment): Ditto.
+ (simple_output::comment_arg): Removed.
+ (simple_output::check_newline): Improve test and flush last word.
+ (simple_output::space_or_newline): Improved.
+ (simple_output::write_newline): Replaced with...
+ (simple_output::nl): This.
+ (simple_output::put_raw_char): Flush last word.
+ (simple_output::check_space): Removed.
+ (simple_output::put_translated_string): Ditto.
+ (simple_output::put_string): Simplified.
+ (simple_output::put_number): Updated.
+ (simple_output::put_float): Ditto.
+ (simple_output::put_symbol): Removed.
+ (simple_output::enable_newlines): Add `check_newline()'.
+ (simple_output::flush_last_word): New function.
+
+ * src/roff/troff/enc.cc (no_fill): Remove call to add_html_tag().
+ * src/roff/troff/div.cc (page_offset): Add call to add_html_tag().
+
+ * tmac/s.tmac (@PP, @IP): Add html conditional code.
+ * tmac/an-old.tmac (TP): Ditto.
+
+2001-03-09 Ruslan Ermilov <ru@freebsd.org>
+
+ * mdate.sh: Make it POSIX compliant.
+
+2001-03-09 Werner LEMBERG <wl@gnu.org>
+
+ Added the `return' request to end a macro immediately. It simply
+ pops iterators from the input stack until a macro iterator is found.
+
+ * src/roff/troff/input.cc (input_iterator::is_macro,
+ macro_iterator::is_macro): New member.
+ (input_return_boundary): New class to signal an immediate return
+ to while_request().
+ (input_stack::add_return_boundary, input_stack::is_return_boundary):
+ New functions.
+ (input_stack::clear): Use it.
+ (input_stack::pop_macro): New function.
+ (while_request): Use `is_return_boundary()'.
+ (return_macro_request): New function.
+ (init_input_requests): Use it.
+
+ * src/roff/troff/TODO: Updated.
+ * NEWS, src/roff/troff/troff.man, man/groff.man: Document it.
+
+2001-03-08 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/input.cc (input_iterator::is_boundary): Minor
+ cleanup.
+
+2001-03-07 Werner LEMBERG <wl@gnu.org>
+
+ Make `\B' more rigid.
+
+ * src/roff/troff/number.cc (parse_expr, parse_term): Add `rigid'
+ parameter.
+ (get_number_rigidly): New function.
+ * src/roff/troff/input.cc (do_expr_test): Use it.
+ * src/roff/troff/token.h: Updated.
+
+ * src/roff/troff/request.h: Fix typo (init_html_request ->
+ init_markup_request).
+
+2001-03-04 Gaius Mulley <gaius@glam.ac.uk>
+
+ Fixed grohtml handling of any named glyph for glyph indexes < 0x80.
+ Cosmetic changes to `.html-begin', `.html-end', `.html-image' which
+ are now `.begin', `.end', `.image'.
+
+ * src/devices/grohtml/post-html.cc: Adding UNICODE_DESC_START.
+ (html_printer::add_to_sbuf): Changing type of `code' parameter.
+ Use add_char_to_sbuf().
+ (to_unicode): New function.
+ (char_translate_to_html): Changing type of `ch' parameter.
+ Use `to_unicode()'.
+ (html_printer::~html_printer): Comment out doctype string.
+ * src/preproc/html/pre-html.cc (write_end_image): Use `.end'
+ instead of `.html-end'.
+ (write_start_image): Use `.begin' and `.image' instead of
+ `.html-begin' and `.html-image'.
+ * src/roff/troff/input.cc: Rename `html_level' to `begin_level'.
+ (html_begin): Renamed to ...
+ (begin): This.
+ (html_end): Renamed to ...
+ (end): This.
+ (html_image): Renamed to ...
+ (image): This.
+ (init_html_requests): Renamed to ...
+ (init_markup_requests): This.
+ * tmac/www.tmac: Updated.
+
+2001-02-28 Bram <bram@avontuur.org>
+
+ * src/libs/libgroff/font.cc (font_widths_cache): Fixing syntax of
+ constructor.
+
+2001-02-26 David Leonard <david.leonard@csee.uq.edu.au>
+
+ * doc/meref.me: Fixing some typos.
+
+2001-02-16 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/node.cc (space_node::get_hyphenation_type): New
+ method. Return `HYPHEN_MIDDLE' if it was `\:'.
+ * src/roff/troff/node.h: Updated.
+
+2001-02-17 Ruslan Ermilov <ru@FreeBSD.org>
+
+ * tmac/groff_tmac.man: Fix typo.
+
+2001-02-16 Werner LEMBERG <wl@gnu.org>
+
+ Fixing a bug which prevented proper end-of-sentence recognition
+ between an `unformatted' box and the following text. As a
+ consequence, vertical line distances are no longer preserved in
+ boxes after a call to `.unformat' -- because boxes aren't
+ line-oriented (contrary to diversions), this doesn't make sense
+ anyway.
+
+ * src/roff/troff/node.cc (*node::set_unformat_flag): Add return
+ value.
+ (vertical_size_node::set_unformat_flag): New method.
+ * src/roff/troff/node.hh: Updated.
+ * src/roff/troff/input.cc (word_space_node::reread,
+ hmotion_node::reread): Reset `unformat' flag after usage.
+ (unformat_macro): Append only if `set_unformat_flag()' returns
+ non-zero.
+ * src/roff/troff/troff.man: Updated.
+
+2001-02-15 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/troff.man, NEWS, man/groff.man: Improved
+ documentation of `asciify' and `unformat' requests.
+
+2001-02-13 Werner LEMBERG <wl@gnu.org>
+
+ Redesigned the `unformat' request. It is no longer connected with
+ `asciify' but rather uses new `reread()' methods if the `unformat'
+ flag is set. Additionally, the handling of space characters after
+ unformatting has been fixed so that they retain their width.
+
+ * src/roff/troff/node.h (width_list): New structure to store
+ original widths of spaces.
+ (node): Added `unformat' member.
+ Replaced `num_spaces' variable with `orig_width' list.
+ * src/roff/troff/node.cc (*node::asciify,
+ asciify_reverse_node_list): Removed `unformat_only' flag and related
+ code.
+ (word_space_node::asciify, word_space_node::word_space_node): Use
+ `orig_width'.
+ (word_space_node::~word_space_node): New destructor.
+ (word_space_node::copy): Updated to handle `orig_width'.
+ (hmotion_node::copy, unbreakable_space_node::copy): Updated.
+ (*node::merge_space): Update `orig_width' list if necessary.
+ (*node::set_unformat_flag): New methods to set the `unformat' flag.
+ * src/roff/troff/enc.cc (environment::space_newline): Use
+ `width_list'.
+ (environment::space): Added method to handle space width and
+ sentence space width as parameters. Use `width_list'.
+ (environment::make_tab_node): Updated.
+ * src/roff/troff/env.h: Updated.
+ * src/roff/troff/input.cc (word_space_node::reread,
+ unbreakable_space_node::reread, hmotion_node::reread): New methods
+ to handle nodes specially if `unformat' flag is set.
+ (do_asciify_macro): Renamed back to ...
+ (asciify_macro): This.
+ (unformat_macro): New implementation to simply set the `unformat'
+ flag.
+
+ * MORE.STUFF: Added more info about deroff.
+
+2001-02-08 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/node.h (unbreakable_space_node, hmotion_node,
+ space_char_hmotion_node, overstrike_node): Add `get_hyphen_list()'
+ and `add_self()' methods to avoid hyphenation. For example, the
+ hyphen list for `foo\0\0bar' was `foobar', causing insertion of a
+ soft hyphen after `foo'. Now the hyphen list is correctly
+ `foo<ignore><ignore>bar'.
+
+2001-02-05 Yoshiteru Kageyama <yt-kage@cb3.so-net.ne.jp>
+
+ * tmac/groff_tmac.man: Fix `BIR' macro.
+
+2001-02-04 Werner LEMBERG <wl@gnu.org>
+
+ A new escape sequence `\:', inserting a zero-width break point.
+
+ * src/roff/troff/input.h: Adding `ESCAPE_COLON'.
+ * src/roff/troff/input.cc (get_copy, token::next, asciify):
+ Implement it.
+ * src/roff/troff/node.h (node): Add `is_escape_colon()' virtual
+ method.
+ (space_node): Add `was_escape_colon' member. Add `is_escape_colon()'
+ and `asciify()' methods.
+ * src/roff/troff/node.cc (space_node::space_node): Updated.
+ (space_node::asciify): Handle `was_escape_colon'.
+ * NEWS, src/roff/troff/troff.man, man/groff.man: Document it.
+
+ Handle `\~' similar to other comparable requests.
+
+ * src/roff/troff/input.cc (process_input_stack): Remove now obsolete
+ label.
+ (token::next): Move creation of an unbreakable_space_node to...
+ (token::add_to_node_list): Here.
+
+ Fix a bug which sometimes prevented hyphenation of words connected
+ with `\~' or `\ ' (and other escape sequences handled as
+ TOKEN_NODE). This also fixes a hyphenation problem with boxes
+ (after a call to the `unformat' request).
+
+ * src/roff/troff/env.h (environment::possibly_break_line,
+ environment::hyphenate_line): Introducing `start_here' parameter.
+ * src/roff/troff/env.cc (environment::space_newline,
+ environment::space): Use it.
+ (environment::possibly_break_line, environment::hyphenate_line):
+ Implement it.
+ * src/roff/troff/input.cc (process_input_stack): Use it.
+ * src/roff/troff/node.h (unbreakable_space_node, hmotion_node,
+ space_char_hmotion_node, overstrike_node): Add
+ `get_hyphenation_type()' method.
+ * src/roff/troff/node.cc (break_char_node::asciify): Don't asciify
+ if `unformat_only' is active.
+
+2001-01-30 Werner LEMBERG <wl@gnu.org>
+
+ Implemented new read-only number register `.linetabs' which
+ returns 1 if in line-tabs mode, 0 otherwise.
+
+ * src/roff/troff/env.h (environment): Add get_line_tabs() member.
+ * src/roff/troff/env.cc (get_line_tabs): New function.
+ (init_env_requests): Use it.
+ * NEWS, src/roff/troff/troff.man, man/groff.man: Document it.
+
+ * VERSION, REVISION: Changing to 1.17.0.
+
+2001-01-28 Werner LEMBERG <wl@gnu.org>
+
+ Fixed a bug which prevented hyphenation of words which are finished
+ with `\)'.
+
+ * src/roff/troff/token.h (token): Add enum type
+ `TOKEN_TRANSPARENT_DUMMY' and method `transparent_dummy()'.
+ * src/roff/troff/input.cc (token::next, token::description,
+ get_line_arg, token::add_to_node_list, token::process): Use it.
+
+2001-01-27 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/div.h (diversion): Add `saved_prev_line_interrupted'.
+ * src/roff/troff/div.cc (do_divert): Use it.
+
+ * src/roff/troff/input.cc (asciify): Add ESCAPE_RIGHT_PARENTHESIS.
+
+2001-01-25 Werner LEMBERG <wl@gnu.org>
+
+ Adding the `linetabs' request. If set, tab distances are not
+ computed relative to the input line but relative to the output line.
+
+ * src/roff/troff/env.h (environment): New member `line_tabs'.
+ * src/roff/troff/env.cc (line_tabs_request): Implement request.
+ (environment::environment, environment::copy): Updated.
+ (environment::distance_to_next_tab): Use `line_tabs'.
+ (init_env_requests): Register request.
+ * src/roff/troff/troff.man, man/groff.man, NEWS: Document it. Other
+ fixes.
+
+2001-01-24 Werner LEMBERG <wl@gnu.org>
+
+ Introducing a new read-only register `.int' which is set to a
+ positive value if the last output line is interrupted (i.e., if it
+ contains `\c').
+
+ * src/roff/troff/env.cc (init_env_requests): Add it.
+ * NEWS, src/roff/troff/troff.man, man/groff.man: Document it.
+
+2001-01-23 Gaius Mulley <gaius@glam.ac.uk>
+
+ * tmac/mwww.tmac: Call `www.tmac', not `arkup.tmac'.
+ * src/preproc/html/pre-html.cc (findPrefix): New function which
+ generates the troff executable name via the system prefix.
+ * src/preproc/eqn/main.cc: Modified warning message.
+
+2001-01-23 Werner LEMBERG <wl@gnu.org>
+
+ troff's `box' and `boxa' requests didn't preserve temporary
+ indentation.
+
+ * src/roff/troff/div.h (diversion): Add `saved_saved_indent' and
+ `saved_target_text_length' members.
+ * src/roff/troff/div.cc (do_divert): Use them.
+
+ Tabs (but not yet leaders and fields) are now handled correctly by
+ `asciify' request.
+
+ * node.h (hmotion_node): Add field `was_tab'.
+ * env.cc (environment::make_tab_node): Set it.
+ * node.cc (hmotion_node::copy, hmotion_node::asciify): Use it.
+
+ Added new request `unformat' which will, contrary to `asciify',
+ preserve font information after unformatting (i.e., only nodes
+ dealing with horizontal space are converted back to input
+ characters).
+
+ * input.cc (asciify_macro): Renamed to ...
+ (do_asciify_macro): this, having a new parameter `unformat_only'.
+ (asciify_macro, unformat_macro): New; using do_asciify_macro.
+ (init_input_requests): Added `unformat'.
+ * node.cc (*_node::asciify), asciify_reverse_node_list: Added
+ parameter to control asciification process.
+ * node.h (*_node::asciify): Ditto.
+ * NEWS, src/roff/troff/troff.man, man/groff.man: Document it.
+
+2001-01-20 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Minor improvement of `.in' documentation.
+
+2001-01-18 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/ps.tmac: Remove call of psold.tmac.
+ * tmac/psold.tmac: Comment updated.
+ * tmac/psnew.tmac: Removed since no longer needed.
+ * tmac/Makefile.sub, NEWS, src/devices/grops/grops.man: Updated.
+
+ * font/devutf8/R.proto: Adding `shc' glyph.
+ * font/devutf8/NOTES: Updated.
+
+ * test-groff: Updated.
+
+2001-01-15 Gaius Mulley <gaius@glam.ac.uk>
+
+ First cut of the new html device driver. Changes to pre-html and
+ the new grohtml are too numerous to be documented here.
+
+ Stuff related to `html' has been renamed to `html-old' and `html2'
+ stuff has been renamed to `html' (including directories). The new
+ html device driver is therefore invoked as `-Thtml'.
+
+ Added new `\O' escape to suppress output (needed by html driver).
+
+ Added functions and code to pass info about input-level commands
+ (`.in', `.fl', etc.) to html driver.
+
+ Three new functions (.html-begin, .html-end, and .html-image) for
+ better html handling: `html-begin' will execute the remaining line
+ if at the outermost nesting level, increasing an internal counter.
+ `html-end' does the same but decreases the internal counter.
+ `html_image' puts its arguments into a special node (suppress_node)
+ to define an image region.
+
+ The `output' request has been removed.
+
+ * tmac/html-tags.tmac: Removed.
+ * tmac/arkup.tmac: Updated and renamed to ...
+ * tmac/www.tmac: New file.
+ * tmac/markup.tmac Updated and renamed to ...
+ * tmac/mwww.tmac: New file.
+ * tmac/Makefile.sub: Updated.
+ * tmac/an-old.tmac: Updated.
+ * tmac/eqnrc: Updated.
+ * tmac/groff_man.man
+ * tmac/groff_markup.man: Updated and renamed to ...
+ * tmac/groff_mwww.man: New file.
+ * tmac/groff_tmac.man: Updated.
+ * tmac/html-old.tmac: Updated and Renamed from html.tmac.
+ * tmac/html.tmac: Updated and renamed from html2.tmac.
+ * tmac/pspic.tmac: Updated html support.
+ * tmac/s.tmac: Added html output support.
+ * tmac/troffrc, tmac/troffrc-end: Updated.
+
+ * Makefile.in, doc/Makefile: Updated.
+ * doc/groff.texinfo: Added info about new `\O' escape.
+ * doc/homepage.ms: Use `MAILTO' macro.
+
+ * font/devhtml/DESC.proto: Add `C' font.
+ * font/devhtml/Makefile.sub: Updated.
+ * font/devhtml/R.proto: Minor fixes.
+ * font/devhtml-old/Makefile.sub: Updated.
+
+ * src/devices/grohtml-old/Makefile.sub: Updated.
+
+ * src/libs/libdriver/printer.cc (printer::get_font_from_index): New
+ method.
+ * src/libs/libgroff/htmlindicate.cc (html_begin_suppress,
+ graphic_start): Add `inline' parameter. Update.
+ (html_end_suppress, graphic_end): Update.
+
+ * src/include/html-strings.h: New file.
+ * src/include/htmlindicate.h: Comments updated.
+ * src/include/printer.h: Updated.
+
+ * src/preproc/eqn/main.cc (do_file, main): Updated.
+ * src/preproc/pic/troff.cc (troff_output::start_picture,
+ troff_output::finish_picture): Updated.
+ * src/preproc/tbl/main.cc (process_input_file): Updated.
+
+ * src/roff/groff/groff.cc (main): Updated.
+ Pass device arguments to predrivers also.
+ Use `ps' device for `eqn' preprocessor if `-Thtml' is given.
+ * src/roff/troff/env.h (environment): Updated.
+ New elements `need_eol' and `ignore_next_eol' (for html output).
+ * src/roff/troff/env.cc (environment::environment): Add initializers
+ for `need_eol' and `ignore_next_eol'.
+ (environment::add_html_tag_eol, environment::add_html_tag_tabs): New
+ functions.
+ (point_size, fill, no_fill, center, right_justify, line_length,
+ indent, temporary_indent, break_request, handle_tab): Use
+ `add_html_tag()'.
+ (set_tabs): Use `add_html_tag_tabs()'.
+ (environment::add_html_tag): Updated.
+ (environment::do_break): Updated.
+ * src/roff/troff/div.cc (space_request, flush_output): Use
+ `environment::add_html_tag()'.
+ * src/roff/troff/input.cc: Updated.
+ New variable `html_level' to indicate nested `html-begin' requests.
+ (file_iterator::fill): Use `environment::add_html_tag_eol()'.
+ (non_interpreted_char_node, token_node, non_interpreted_node): Add
+ `force_tprint()' method.
+ (token::next): Handle `\O'.
+ (do_suppress): Implement it.
+ (html_begin, html_end, html_image): New functions.
+ (init_output_requests): Renamed to ...
+ (init_html_requests): this.
+ (main): Use it.
+ (macro::append_str, macro::append_unsigned, macro::append_int): New
+ methods.
+ New variable `output_low_mark_miny' to limit minimal value of y.
+ (reset_output_registers): Use it.
+ (output_request): Removed.
+ (get_output_registers): New function.
+ * src/roff/troff/node.h (node): Make `force_tprint()' virtual.
+ (*_node): Added `force_tprint()' if necessary.
+ (special_node): New elements `tf' and `get_tfont()'.
+ (suppress_node): New class.
+ * src/roff/troff/node.cc:
+ New global variables `image_no' and `suppress_start_page'.
+ (real_output_file): New method `is_on()'.
+ (troff_output_file): New method `start_special(tfont)'.
+ (troff_output_file::really_print_line): Use `tprint' conditionally.
+ (real_output_file::print_line): Updated.
+ (real_output_file::on): Updated.
+ (*_node): Added `force_tprint()'.
+ (special_node::special_node): Initializer updated.
+ (special_node::same, special_node::copy, special_node::tprint_start):
+ Updated.
+ (get_reg_int, get_reg_str): New functions.
+ (suppress_node::*): New methods.
+ New global variables last_position, last_image_filename;
+ (min): New inline function.
+ * src/roff/troff/reg.h, src/roff/troff/request.h,
+ src/roff/troff/troff.h: Updated.
+
+2001-01-13 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS, src/roff/troff/troff.man, doc/groff.texinfo: Fix
+ documentation of `asciify' request.
+
+2001-01-12 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/input.cc: Move definition of special characters
+ like `ESCAPE_TILDE' to ...
+ * src/roff/troff/input.h: New file.
+ * src/roff/troff/Makefile.sub (HDRS): Add it.
+
+ Extending the .asciify request to `unformat' space characters also.
+
+ * src/roff/troff/node.h (word_space_node): Add `num_spaces' element
+ to count input space characters.
+ Update constructors to take care of it.
+ * src/roff/troff/node.cc (space_char_hmotion_node::asciify): Use
+ `ESCAPE_SPACE' instead of normal space.
+ (word_space_node::asciify): New method.
+ (unbreakable_space_node::asciify): New method.
+ (word_space_node::merge_space): New method.
+ * src/roff/troff/env.cc (environment::space_newline,
+ environment::space): Add code to initialize `num_spaces' (using the
+ constructor of `word_space_node').
+ * NEWS, src/roff/troff/troff.man, man/groff.man, doc/groff.texinfo:
+ Document it.
+
+2001-01-09 Werner LEMBERG <wl@gnu.org>
+
+ * man/groff_char.man: Use table header traps only conditionally.
+
+2001-01-09 Bjarni Ingi Gíslason <bjarniig@hi.is>
+
+ * man/groff_char.man: Add `ý' and `Ý' to the `acute' group.
+
+2001-01-08 Werner LEMBERG <wl@gnu.org>
+
+ Introducing the `box' and `boxa' requests which are similar to
+ `di' resp. `da' but omitting a partially filled line (which is
+ restored after ending the diversion).
+
+ * src/roff/troff/div.h (diversion): Add elements to save partially
+ filled line.
+ * src/roff/troff/div.cc (do_divert): Add parameter `boxing' to save
+ partially filled line.
+ (divert, divert_append): Updated.
+ (box, box_append): New functions.
+ (init_div_requests): Use them.
+ * src/roff/troff/env.h (environment): do_divert() is now a friend.
+ * NEWS, src/roff/troff/troff.man, man/groff.man: Document it.
+
+ * doc/groff.texinfo: Fix documentation of `lf' request.
+
+2000-12-25 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/troff.man, NEWS: Document `writem' request.
+
+2000-12-21 Werner LEMBERG <wl@gnu.org>
+
+ Ignore `ss' request if in compatibility mode.
+
+ * src/roff/troff/input.cc: Make `compatible_flag' non-static.
+ * src/roff/troff/env.h: Added extern `compatible_flag' declaration.
+ * src/roff/troff/env.cc (space_size): Use it.
+
+ * doc/groff.texinfo, src/roff/troff/troff.man: Fix documentation of
+ `ss' request in nroff mode.
+
+ * tmac/an-old.tmac: Fixed some serious bugs introduced with latest
+ changes.
+
+2000-12-15 Ruslan Ermilov <ru@FreeBSD.org>
+
+ * tmac/troffrc, tmac/troffrc-end: Convert tmac.* to *.tmac.
+
+2000-12-13 Werner LEMBERG <wl@gnu.org>
+
+ * src/preproc/eqn/Makefile.sub (MAN1): Added neqn.man.
+ * src/preproc/eqn/neqn.man: Small fixes and additions.
+
+2000-12-13 Ruslan Ermilov <ru@FreeBSD.org>
+
+ * src/utils/addftinfo/addftinfo.man, src/devices/grops/grops.man:
+ Fixing typo.
+
+ * src/preproc/eqn/neqn.man: New file.
+
+ * src/preproc/tbl/table.cc (table::print): Fix `indent cannot be
+ negative' warning.
+
+ * tmac/e.tmac: Add `T&' macro.
+ Fix `indent cannot be negative' warning.
+ * tmac/s.tmac: Fix `indent cannot be negative' warning.
+
+2000-12-07 Werner LEMBERG <wl@gnu.org>
+
+ * src/include/lib.h: Replaced __ALPHA with __alpha symbol.
+
+2000-12-06 Werner LEMBERG <wl@gnu.org>
+
+ * PROBLEMS: Added info about adding -lPW on HP-UX to satisfy the
+ `alloca' symbol .
+
+ * MORE.STUFF: Added info about deroff for djgpp.
+
+ * tmac/an-old.tmac, tmac/groff_man.man, doc/groff.texinfo, NEWS: Fix
+ documentation of -rcR switch.
+
+2000-12-03 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/an-old.tmac: Implementing the -rcR switch (similar to mdoc);
+ if -rcR=1 (which is now the default in nroff mode), a single, very
+ long page is created instead of multiple pages: All `ne' and `wh'
+ requests are put into conditionals; a new macro `an-end' is added to
+ be called with `em'.
+
+ Some other minor cleanups.
+
+ * NEWS, tmac/groff_man.man, doc/groff.texinfo: Updated.
+
+2000-12-02 Werner LEMBERG <wl@gnu.org>
+
+ Fixing a bug which prevented hyphenation in words followed
+ immediately by a TOKEN_NODE (e.g. `\ ', `\~', etc.).
+
+ * src/roff/troff/input.cc (process_input_stack <token::TOKEN_NODE>):
+ Adding possibly_break_line().
+ * src/roff/troff/env.h (environment): Make possibly_break_line()
+ public.
+
+ Make `\~' usable in .tr request.
+
+ * src/roff/troff/token.h (token_type): Add TOKEN_STRETCHABLE_SPACE.
+ (token): Add stretchable_space().
+ * src/roff/troff/input.cc (token::next, token::delimiter,
+ token::description, process_input_stack, do_translate,
+ add_to_node_list, token::process): Use it.
+ * src/roff/troff/node.h (node): Add fourth parameter to add_char()
+ for adjusting the space.
+ * src/roff/troff/node.cc (node::add_char): Implement it. Add code
+ for stretchable space.
+ * src/roff/troff/input.cc (token::add_to_node_list): Use it.
+ (make_node): Add code for stretchable space.
+ * src/roff/troff/env.cc (environment::add_char): Use it.
+ * src/roff/troff/input.cc: Add ESCAPE_TILDE special character.
+ (get_copy, token::next, transparent_translate, asciify): Use it.
+
+ * NEWS, src/roff/troff/troff.man, src/roff/troff/TODO,
+ doc/groff.texinfo: Updated.
+ * man/groff.man: Small reorderings.
+
+2000-11-23 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS: Fixes.
+ * src/preproc/eqn/main.cc (main): Use `config_macro_path' for -M
+ option.
+ * src/roff/troff/input.cc (main): Add `config_macro_path' and
+ `safer_macro_path' to -M option.
+ * src/roff/troff/troff.man: Fixes.
+
+2000-11-22 Werner LEMBERG <wl@gnu.org>
+
+ Use safer path (except for config files) if -U isn't specified. Add
+ a special macro path (without home and current directory) for config
+ files. Add home directory to unsafe path for consistency. Don't
+ include the home directory in the font path.
+
+ * src/lib/libgroff/macropath.cc: Add `config_macro_path', change
+ `macro_path'.
+ * src/include/macropath.h: Add `config_macrp_path'.
+ * src/lib/libgroff/fontfile.cc: Fix font path.
+ * src/roff/troff/input.cc (process_startup_file): Use
+ `config_macro_path'.
+ (main): Select unsafe path if -U is given.
+
+ * src/preproc/eqn/main.cc (main): Fixing search path for
+ configuration file.
+ * src/preproc/eqn/eqn.man: Updated.
+
+ * src/roff/troff/troff.man, man/roff.man, tmac/groff_tmac.man:
+ Updated.
+
+ * src/preproc/grn/grn.man, src/devices/grodvi/grodvi.man,
+ src/devices/grohtml/grohtml.man, src/devices/grolbp/grplbp.man,
+ src/devices/grolj4/grolj4.man, src/devices/grops/grops.man,
+ src/devices/grotty/grotty.man: Updated.
+
+ * Makefile.in: Fix comments.
+
+2000-11-17 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/safer.tmac: Empty file added (again) for compatibility
+ reasons.
+ * tmac/Makefile.sub: Updated.
+
+2000-11-16 Werner LEMBERG <wl@gnu.org>
+
+ * src/devices/grodvi/dvi.cc (main),
+ src/devices/grohtml2/post-html.cc (main),
+ src/devices/grolbp/lbp.cc (main), src/devices/grolj4/lj4.cc
+ (main), src/devices/grops/ps.cc (main), src/devices/grotty/tty.cc
+ (main), src/preproc/eqn/main.cc (main), src/preproc/grn/main.cc
+ (main), src/preproc/html2/pre-html.cc (main),
+ src/preproc/pic/main.cc (main), src/preproc/refer/refer.cc (main),
+ src/preproc/soelim/soelim.cc (main), src/preproc/tbl/main.cc
+ (main), src/roff/groff/groff.cc (main), src/roff/troff/input.cc
+ (main), src/utils/hpftodit/hpftodit.cc (main),
+ src/utils/indxbib/indxbib.cc (main), src/utils/lkbib/lkbib.cc
+ (main), src/utils/lookbib/lookbib.cc (main),
+ src/utils/pfbtops/pfbtops.c (main), src/utils/tfmtodit/tfmtodit.cc
+ (main): Use stdout for -v.
+ * src/roff/groff/groff.cc (run_commands),
+ src/roff/groff/pipeline.c (run_pipeline): New parameter `no_pipe'
+ to make direct printing to stdout possible.
+ * src/roff/groff/pipeline.h: Updated.
+
+ * src/utils/afmtodit/afmtodit.pl: Add -v switch.
+ * src/utils/afmtodit/Makefile.sub (afmtodit): Use @VERSION@.
+ * src/utils/afmtodit/afmtodit.man: Updated.
+
+ * src/utils/addftinfo/addftinfo.cc (main): Add -v switch.
+ (version): New function.
+ (usage): Updated.
+ * src/utils/addftinfo/addftinfo.man: Updated.
+
+ * src/devices/*/*, src/preproc/*/*, src/roff/*/*, src/utils/*/*:
+ Fixing copyright dates.
+
+ * src/preproc/eqn/neqn.sh: Adding GROFF_BIN_PATH to path instead of
+ replacing it.
+
+ * src/devices/grolbp/lbp.cc (main): Use Version_string instead of
+ version_string.
+
+ * src/roff/nroff/Makefile.sub (nroff): Fix use of @VERSION@.
+
+2000-11-15 Werner LEMBERG <wl@gnu.org>
+
+ In all programs, make -v return immediately with exit status 0 to
+ be compliant with the GNU standard.
+
+ * src/devices/grodvi/dvi.cc (main),
+ src/devices/grohtml2/post-html.cc (main),
+ src/devices/grolbp/lbp.cc (main), src/devices/grolj4/lj4.cc
+ (main), src/devices/grops/ps.cc (main), src/devices/grotty/tty.cc
+ (main) src/preproc/eqn/main.cc (main), src/preproc/grn/main.cc
+ (main), src/preproc/html2/pre-html.cc (main),
+ src/preproc/pic/main.cc (main), src/preproc/refer/refer.cc (main),
+ src/preproc/soelim/soelim.cc (main), src/preproc/tbl/main.cc
+ (main), src/roff/groff/groff.cc (main), src/roff/troff/input.cc
+ (main): Implement it.
+ * NEWS: Updated.
+
+ * src/roff/groff/groff.cc (main): Add copyright notice. Add refer
+ and postprocessors to the -v option.
+
+ * src/roff/grog/grog.pl: Implement -v.
+ * src/roff/grog/Makefile.sub (grog): Use @VERSION@.
+ * src/roff/grog/grog.man, doc/groff.texinfo: Updated.
+
+ * src/roff/nroff/nroff.sh: Implement -v.
+ * src/roff/nroff/Makefile.sub (nroff): Use @VERSION@.
+ * src/roff/nroff/nroff.man: Updated.
+
+ * src/preproc/eqn/main.cc (main): Fix comment typo.
+
+ * MORE.STUFF: Added info about djgpp port of grap.
+
+2000-11-14 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/grog/grog.{pl,sh}: Implemented -C switch for compatibility
+ mode (or rather, implemented non-compatibility mode).
+ * NEWS, src/roff/grog/grog.man, doc/groff.texinfo: Updated.
+
+ * src/roff/groff/groff.cc (main): Add BIN_PATH to PATH instead of
+ replacing it -- we don't find gxditview otherwise.
+ * NEWS, src/roff/groff/groff.man, doc/groff.texinfo: Updated.
+
+ * src/preproc/pic/depend: Removed. Unnecessary.
+
+ Implemented dummy keyword `solid' in pic for compatibility with
+ AT&T pic.
+
+ * lex.cc (lookup_keyword): Added `solid'.
+ * pic.y: Added SOLID with dummy rule.
+ * pic.cc, pic_tab.h: Regenerated.
+ * doc/pic.ms: Updated.
+
+2000-11-13 Werner LEMBERG <wl@gnu.org>
+
+ For security reasons, don't use the current directory but the home
+ directory while searching and scanning troffrc and troffrc-end.
+ Similarly, replace the current directory with the home directory
+ in the font path.
+
+ * Makefile.in (fontpath, tmacpath): Remove current directory.
+
+ * src/libs/libgroff/searchpath.cc (search_path::search_path): Add
+ two parameters `add_home' and `add_current'.
+ (search_path::~search_path, search_path::command_line_dir,
+ search_path::open_file): Remove tests for `dirs' being zero.
+ * src/include/searchpath.h: Adjust.
+ * src/libs/libgroff/macropath.cc, src/include/macropath.h: Add
+ `safer_macro_path'.
+ * src/libs/libgroff/fontfile.cc: Adjust `font_path'.
+
+ * src/roff/troff/troff.h: Add `searchpath.h' and `mac_path'.
+ * src/roff/troff/input.cc: Use `mac_path', initialized with
+ `macro_path'.
+ (process_startup_file): Set `mac_path' to `safer_macro_path'.
+ * src/roff/troff/env.cc: Use `mac_path'.
+
+ * src/preproc/eqn/main.cc (main): Use `safer_macro_path'.
+
+ * NEWS, man/roff.man, src/roff/troff/troff.man,
+ src/roff/groff/groff.man, tmac/groff_tmac.man, arch/djgpp/README:
+ Updated.
+
+2000-11-12 Werner LEMBERG <wl@gnu.org>
+
+ * src/include/lib.h: Don't include groff-getopt.h for OSF/1.
+
+ * aclocal.m4 (GROFF_SYS_ERRLIST): Do test in C, not in C++.
+ * configure.in: Fix typo in comment.
+ * configure: Regenerated.
+
+ * src/libgroff/*, src/include/*, src/roff/troff/*: Fixing copyright
+ dates.
+
+2000-11-08 Werner LEMBERG <wl@gnu.org>
+
+ Add system tmac directory (/usr/local/lib/groff/site-tmac).
+
+ * Makefile.in: Add $(libdir), $(libprogramdir), and $(systemtmacdir).
+ (uninstall_dirs): Add $(libdir), $(libprogramdir), and
+ $(systemtmacdir).
+ Use @libdir@.
+ * Makefile.comm (.man.n): Add @SYSTEMMACRODIR@.
+ * tmac/Makefile.sub (install_data): Create
+ $(systemtmacdir) and $(localtmacdir).
+ (uninstall_sub): Use $(systemtmacdir) for wrapper macros.
+ * man/roff.man, src/roff/troff/troff.man, src/roff/groff/groff.man,
+ NEWS, doc/groff.texinfo: Updated and minor fixes.
+
+ * Makefile.comm, Makefile.in: Added tmac_{s,an}_prefix stuff again.
+ * tmac/Makefile.sub: Added `wrap' stuff again, but installing into
+ $(systemtmacdir) since the wrapper files are platform-dependent.
+
+2000-11-01 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Fix typo.
+
+2000-10-26 Werner LEMBERG <wl@gnu.org>
+
+ Convert macros `tmac.XXX' to `XXX.tmac'. Special cases:
+ tmac.doc.old -> doc-old.tmac
+ tmac.an.old -> an-old.tmac
+
+ * tmac/tmac.*: Moved to ...
+ * tmac/*.tmac: this.
+ * tmac/man.local: Fix comment.
+ * tmac/groff_man.man, tmac/groff_markup.man, tmac/groff_mdoc.man,
+ tmac/groff_me.man, tmac/groff_ms.man, tmac/groff_tmac.man: Updated.
+ Added some `FILES' sections. More use of @...@ directives. Other
+ minor updates.
+ * arch/djgpp/README, font/devutf8/NOTES: Updated.
+ * doc/homepage.ms, doc/groff.texinfo: Updated.
+ * man/groff.man, man/roff.man: Updated.
+ * src/devices/grodvi/grodvi.man, src/devices/grolbp/grolbp.man,
+ src/devices/grolj4/grolj4.man, src/devices/grops/grops.man,
+ src/devices/grotty/grotty.man: Updated.
+ * src/preproc/pic/pic.man: Updated.
+ * src/roff/grog/grog.pl, src/roff/grog/grog.sh: Use -mdoc-old
+ instead of -mdoc.old.
+ * src/roff/grog/grog.man: Document -mdoc and -mdoc-old.
+ * src/roff/nroff/nroff.man: Updated.
+ * NEWS: Updated.
+
+ * tmac/fixmacros.sed, tmac/strip.sed: Add explanatory comment.
+
+ * tmac/mm.diff: Removed -- it has no use now since the mm package
+ is part of groff.
+
+ * tmac/*: Removed trailing spaces.
+
+ * arch/djgpp/t-groff.bat: Fix GROFF_TMAC_PATH (hyphen.us is now in
+ the tmac subdirectory also).
+
+ * Makefile.comm, Makefile.in: Remove tmac_{s,an}_prefix stuff.
+ * tmac/Makefile.sub: Adapted to new macro names; removed `wrap'
+ stuff since it is no longer needed.
+
+ * README, PROBLEMS: Updated.
+
+2000-10-25 Werner LEMBERG <wl@gnu.org>
+
+ Invert current behaviour: Search first FOOBAR.tmac, then
+ tmac.FOOBAR.
+
+ * src/roff/troff/input.cc: Introduce MACRO_POSTFIX.
+ (open_mac_file, macro_source): Implement it.
+ * src/roff/troff/troff.man, tmac/groff_tmac.man, man/roff.man,
+ doc/groff.texinfo, NEWS: Document it.
+
+ * src/roff/nroff/nroff.man, src/roff/groff/groff.man, man/groff.man:
+ Small documentation improvements.
+
+ * test-groff: Fix GROFF_TMAC_PATH (hyphen.us is now in the tmac
+ subdirectory also).
+
+ * font/devps/Makefile.sub: Fix rules for dingbats.*map.
+
+2000-10-24 Werner LEMBERG <wl@gnu.org>
+
+ Add local tmac directory (groff/site-tmac).
+
+ * Makefile.in: Add $(localtmacdir).
+ (uninstall_dirs): Add $(localtmacdir).
+ * Makefile.comm (.man.n): Add @LOCALMACRODIR@.
+ * tmac/Makefile.sub (install_data, uninstall_sub): Handle man.local
+ in $(localtmacdir). Create $(localtmacdir).
+ * man/roff.man, src/roff/troff/troff.man, NEWS, doc/groff.texinfo:
+ Updated and minor fixes.
+
+ Rename font/devps/generate/dingbats[r]map to dingbats.[r]map.
+
+ * font/devps/generate/Makefile.sub, arch/djgpp/README: Adjust.
+
+2000-10-23 Werner LEMBERG <wl@gnu.org>
+
+ Move hyphen.us to tmac directory.
+
+ * src/roff/troff/hyphen.us: Removed.
+ * src/tmac/hyphen.us: Added.
+ * src/roff/troff/Makefile.sub, tmac/Makefile.sub: Updated.
+
+ Change installation structure for data files from .../groff/... to
+ .../groff/<version><revision>/... to be conform with other GNU
+ programs.
+
+ * Makefile.in, Makefile.comm, src/utils/indxbib/Makefile.sub,
+ doc/Makefile: Implement it.
+ * aclocal.m4 (GROFF_PAGE): Add test for new directory structure.
+ * configure: Updated.
+ * arch/djgpp/README, font/devutf8/NOTES: Use it.
+ * NEWS: Document it.
+ * man/roff.man, tmac/groff_tmac.man: Use @FONTPATH@, @FONTDIR@, and
+ @MACRODIR@ instead of hard-coded directories.
+
+2000-10-22 Werner LEMBERG <wl@gnu.org>
+
+ Implement $GROFF_BIN_PATH environment variable (which defaults to
+ $bindir) used for child programs of groff and similar wrappers.
+
+ * gendefs.sh: Improve documentation.
+ * Makefile.comm (,man.n), src/include/Makefile.sub (defs.h),
+ src/preproc/eqn/Makefile.sub (neqn),
+ src/roff/nroff/Makefile.sub (nroff): Add $(bindir).
+ * src/preproc/eqn/neqn.sh, src/roff/nroff/nroff.sh: Implement
+ $GROFF_BIN_PATH.
+ * src/roff/groff/groff.cc (main): Implement $GROFF_BIN_PATH and
+ $GROFF_PATH__ (the latter for communication with troff).
+ * src/roff/troff/input.cc (main): Use $GROFF_PATH__ for $PATH if
+ set.
+ * NEWS, src/roff/nroff/nroff.man, src/roff/groff/groff.man,
+ doc/groff.texinfo: Document it.
+
+ * doc/groff.texinfo: Improve documentation of troff's -a option.
+
+2000-10-17 Gaius Mulley <gaius@glam.ac.uk>
+
+ * src/roff/troff/node.cc: Fixed calculation of opminx and fixed
+ non-intrusive eol marker.
+ (troff_output_file::determine_line_limits): New function.
+ (troff_output_file::draw): Use it.
+ * src/roff/troff/env.cc (environment::add_html_tag): Use output() +
+ output_pending_lines() instead of output_line().
+ * src/preproc/eqn/main.cc (do_file): Fix graphic_end().
+ * src/preproc/html2/pre-html.cc (char_buffer::write_file_troff,
+ createImage): Small fixes.
+
+2000-10-14 Werner LEMBERG <wl@gnu.org>
+
+ Replace tmac.safer with a real secure solution.
+
+ * src/roff/troff/input.cc (open_request, opena_request, pipe_source,
+ system_request, pipe_output): Disable requests if in safer mode.
+ * src/roff/groff/groff.cc (main): Remove reference to tmac.safer.
+ * tmac/tmac.safer, tmac/groff_msafer.man: Removed.
+ * tmac/Makefile.sub, NEWS, man/roff.man, tmac/groff_tmac.man,
+ doc/groff.texinfo, src/roff/groff/groff.man,
+ src/roff/troff/troff.man, arch/djgpp/README: Updated.
+
+ * src/devices/grops/ps.cc (main), src/devices/grops/psrm.cc
+ (resource_manager::output_prolog): Replace setenv() with putenv().
+
+2000-10-09 Werner LEMBERG <wl@gnu.org>
+
+ * src/libs/libbib/map.c, src/libs/libgroff/getcwd.c,
+ src/libs/libgroff/strtol.c, src/preproc/html2/image.cc,
+ src/preproc/html2/pre-html.cc, src/preproc/html2/pushbackbuffer.cc,
+ src/roff/groff/pipeline.c: Removing `#ifndef errno' to avoid
+ compilation errors with some compilers. It seems that this code
+ is no longer necessary -- if yes, it is easy to add some #ifdef's
+ for that particular old-fashioned compiler.
+
+ * MORE.STUFF: Added info about Meta-tbl.
+
+ * doc/groff.texinfo: Added more info about `.if "..."..."'.
+
+2000-10-07 Werner LEMBERG <wl@gnu.org>
+
+ Adding a new escape sequence \B'...': If the string between
+ the delimiters is a valid numeric expression, return the character
+ `1', and `0' otherwise. This is an analogon to \A.
+
+ * src/roff/troff/input.cc (do_expr_test): Implement it.
+ (token::next): Use it.
+ * src/roff/troff/troff.man, NEWS, man/groff.man: Document it.
+
+ * tmac/tmac.trace: Made independent from escape character.
+
+2000-10-06 Werner LEMBERG <wl@gnu.org>
+
+ Adding a new request .dei: define indirect. The first and second
+ parameter of .dei are taken from string registers instead directly;
+ this very special request is needed to make tmac.trace independent
+ from the escape character (which might even be disabled).
+
+ * src/roff/troff/input.cc (do_define_macro): Implement it.
+ (define_macro_indirect): New function.
+ (init_input_requests): Use it.
+
+ Adding two requests .ecs and .ecr: Save and restore the escape
+ character. These two requests are needed to make tmac.trace
+ independent from the escape character (which might even be
+ disabled).
+
+ * src/roff/troff/input.cc (save_escape_char, restore_escape_char):
+ Implement it.
+ (init_input_requests): Use it.
+
+ * src/roff/troff/troff.man, NEWS, man/groff.man: Updated.
+
+2000-09-22 Ricardo Soares Guimarães <ricardo@conectiva.com.br>
+
+ Adding a new option -P and new environment variable GROPS_PROLOGUE
+ to grops, selecting a different prologue file (minor modifications
+ by WL).
+
+ * src/devices/grops/psrm.cc (resource_manager::output_prolog),
+ src/devices/grops/ps.cc (main): Implement it.
+ * src/devices/grops/grops.man, NEWS: Document it.
+
+2000-09-22 Werner LEMBERG <wl@gnu.org>
+
+ * INSTALL: Add info about selecting paper format.
+
+2000-09-21 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/input.cc (main): Fixing compiler warning.
+ * src/include/{driver.h, lib.h}: Move inclusion of string.h and
+ strings.h from the former to the latter.
+ * src/devices/grolbp/lpb.cc, src/include/lib.h: Move strncasecmp()
+ stuff from the former to the latter.
+
+2000-09-11 Werner LEMBERG <wl@gnu.org>
+
+ Implementing two new requests .tm1 and .tmc: The former is similar
+ to .tm but can output leading spaces; its syntax is similar to
+ defining a string, i.e., a `"' can be used to mark the beginning of
+ the string to be written to stderr: `.tm1 " test'. The latter is
+ similar to .tm1 but doesn't write out a final newline character.
+
+ * src/roff/troff/input.cc (terminal1, terminal_continue,
+ do_terminal): New functions.
+ (init_input_requests): Use them.
+ * src/roff/troff/troff.man, NEWS, man/groff.man: Updated.
+
+2000-09-09 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/groff_mdoc.samples.man: Small fixes.
+
+2000-09-08 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/groff_mdoc.man: Fixing typo.
+
+2000-09-02 Werner LEMBERG <wl@gnu.org>
+
+ Implementing a .nop request which does nothing.
+
+ * src/roff/troff/input.cc (nop_request): New function.
+ (init_input_requests): Use it.
+ * src/roff/troff/troff.man, NEWS, man/groff.man: Updated.
+
+2000-09-01 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Added some comments.
+
+2000-08-30 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/TODO: Updated.
+
+2000-08-28 Bruno Haible <haible@clisp.cons.org>
+
+ * contrib/mm/Makefile.sub: New target 'all', makes all prerequisites
+ of 'install'.
+
+2000-08-25 Werner LEMBERG <wl@gnu.org>
+
+ * doc/groff.texinfo: Fix comment how to compile the DVI file.
+
+2000-08-25 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * font/devps/generate/Makefile (SHELL): Define explicitly to
+ "/bin/sh", for non-Unix platforms.
+ (extraclean): Use a more portable "" quoting instead of a
+ backslash (which doesn't work on DOS/Windows).
+
+ * font/devlj4/generate/Makefile (extraclean): Ditto.
+
+ * font/devdvi/generate/Makefile (extraclean): Ditto.
+
+2000-08-25 Werner LEMBERG <wl@gnu.org>
+
+ * NEWS, doc/groff.texinfo, tmac/groff_tmac.man, man/roff.man,
+ src/roff/troff/troff.man: Document Eli's latest changes.
+
+2000-08-25 Eli Zaretskii <eliz@is.elta.co.il>
+
+ * src/roff/troff/input.cc (open_mac_file, macro_source): Support
+ macro file names of the form NAME.tmac as well as tmac.NAME.
+
+2000-08-25 Werner LEMBERG <wl@gnu.org>
+
+ * src/include/posix.h: Remove definition of FILENAME_MAX.
+
+ * src/preproc/html2/pre-html.h, pre-html.cc: Add return type to
+ `sys_fatal' and `stop' function().
+
+ * test-groff: Updated.
+
+2000-08-24 Gaius Mulley <gaius@glam.ac.uk>
+
+ Added the new troff command .output <arg> to suppress output (while
+ still obeying motion) and also the opminx, opminy, opmaxx, opmaxy
+ registers (for passing the output dimensions to the output device).
+
+ * src/roff/troff/div.cc (top_level_diversion::output): Use `width'
+ parameter.
+ * src/roff/troff/node.h, src/roff/troff/node.cc
+ (troff_output_file::really_print_line,
+ ascii_output_file::really_print_line,
+ supress_output_file::really_print_line): Use `width' parameter.
+ (troff_output_file::really_on, troff_output_file::really_off,
+ output_file::on, output_file::off, real_output_file::on,
+ real_output_file::off, real_output_file::really_on,
+ real_output_file::really_off): New functions.
+ (real_output_file:public output_file): New variable `output_on'.
+ (real_output_file::begin_page, real_output_file::copy_file,
+ real_output_file::transparent_char, real_output_file::print_line):
+ Use it.
+ (real_output_file::print_line): Use check_output_limits.
+ * src/roff/troff/reg.h, src/roff/troff/request.h,
+ src/roff/troff/input.cc (assign_registers): New function to remove
+ two `goto's.
+ (do_ps_file): Use it.
+ (check_output_limits, reset_output_registers, output_request,
+ init_output_requests): New functions.
+ (init_input_requests): Updated.
+
+ Added new grohtml2 device and html2 preprocessor (coding
+ not yet finished) which will eventually replace grohtml.
+
+ * Makefile.in, tmac/Makefile.sub, tmac/eqnrc, tmac/troffrc-end:
+ Updated.
+ * src/include/htmlindicate.h, src/include/htmlindicate
+ (html_begin_suppress, html_end_suppress): New functions.
+ * src/preproc/tbl/main.cc: Use it.
+ * src/roff/groff/groff.cc: Add support for html2 device (which will
+ automatically invoke the html2 preprocessor).
+ * src/roff/troff/input.cc (is_html2): New variable.
+ * src/roff/troff/troff.h, src/roff/troff/env.h,
+ src/roff/troff/env.cc (environment::add_html_tag): New function
+ (uses `is_html2').
+ (environment::do_break): Use it.
+ * font/devhtml2/*: New files.
+ * src/devices/grohtml2: New device.
+ * src/preproc/html2: New preprocessor.
+ * tmac/tmac.html-tags, tmac/tmac.html2: New files.
+
+2000-08-23 Werner LEMBERG <wl@gnu.org>
+
+ * src/devices/grolbp/lbp.cc: Same workaround for sinix as for AIX.
+
+2000-08-22 Werner LEMBERG <wl@gnu.org>
+
+ * src/include/lib.h: Provide a fix for IRIX to not include
+ groff-getopt.h.
+
+2000-08-18 Werner LEMBERG <wl@gnu.org>
+
+ * configure.in: Don't provide an empty value for SH_SCRIPT_SED_CMD
+ since some non-GNU sed programs can't handle null regexps.
+ * configure, src/preproc/eqn/Makefile.sub,
+ src/roff/grog/Makefile.sub, src/roff/nroff/Makefile.sub: Updated.
+
+ * src/devices/grolbp/lbp.cc: Add an AIX workaround for an autoconf
+ bug (string.h and strings.h are both needed according to latest
+ POSIX standard).
+
+ * MORE.STUFF: Added info about unroff and troffcvt.
+
+2000-08-08 Werner LEMBERG <wl@gnu.org>
+
+ * tmac/tmac.a4: Will now work with ms macros also; -ma4 should be
+ used before -ms.
+
+ * tmac/tmac.man.old: Remove unused number register.
+
+ * tmac.doc: Minor documentation fix.
+
+2000-08-07 Paul Eggert <eggert@twinsun.com>
+
+ * src/roff/groff/pipeline.c (is_system_shell):
+ Fix typo: "monocased_shell" no longer exists.
+
+2000-08-07 Paul Eggert <eggert@twinsun.com>
+
+ Remove FILENAME_MAX limits.
+
+ * src/roff/groff/pipeline.c (is_system_shell): Do not assume
+ that the argument length is less than FILENAME_MAX.
+ * src/libs/libgroff/tmpfile.cc (add_tmp_file): Likewise.
+ Use struct hack to allocate and free file name.
+ (struct xtmpfile_list): fname is now part of the structure,
+ not a pointer to another string.
+
+2000-08-07 Tom Schmidt <tschmidt@micron.com>
+
+ * src/include/posix.h: Add a default value for FILENAME_MAX.
+
+2000-08-06 Paul Eggert <eggert@twinsun.com>
+
+ Add support for new BSD-style man pages (with ".Dd" instead of
+ ".TH"), so that "groff -man" understands both styles, even
+ when running "groff -man" on a host whose system man page
+ macros don't support ".Dd".
+
+ * tmac/Makefile.sub (NORMALFILES): Add tmac.an.old.
+ (stamp-wrap): Source tmac.andoc first when wrapping man macros,
+ in case the system man macros don't define Dd or TH.
+
+ * tmac/tmac.an.old: Renamed from tmac/tmac.an.
+ * tmac/tmac.an: New one-line file.
+ * tmac/tmac.andoc (TH): Adjust to the tmac.an.old file renaming.
+
+2000-08-06 Werner LEMBERG <wl@gnu.org>
+
+ * src/roff/troff/troff.man: Fixing typos.
+
+Version 1.16.1 released
+=======================
+
2000-07-31 Werner LEMBERG <wl@gnu.org>
Preparing release 1.16.1.
@@ -1620,8 +3372,6 @@ Version 1.12 released
* PROJECTS, PROBLEMS, NEWS: Updated.
- * xditview/Makefile: Removed.
-
* VERSION: Updated to 1.12beta.
* BUG-REPORT: Some cosmetic fixes. Corrected email address.
@@ -1806,7 +3556,7 @@ 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).
+ Documentation for pic added (doc/pic.ms).
Sun Nov 26 11:45:13 1995 James Clark <jjc@jclark.com>
@@ -7524,4 +9274,5 @@ Sat Jul 14 11:23:01 1990 James Clark (jjc at yquem)
Local Variables:
version-control: never
+coding: latin-1
End:
diff --git a/contrib/groff/INSTALL b/contrib/groff/INSTALL
index 0465f4e..cdf7eb9 100644
--- a/contrib/groff/INSTALL
+++ b/contrib/groff/INSTALL
@@ -19,6 +19,16 @@ 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.
+If you want A4 or letter paper format and the configure script produces
+an incorrect guess, say
+
+ PAGE=xxx ./configure
+
+where `xxx' should be either `A4' or `letter'. Note that this will only
+affect the paper selection for 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.
+
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
diff --git a/contrib/groff/MORE.STUFF b/contrib/groff/MORE.STUFF
index ef29efc..6f06cef 100644
--- a/contrib/groff/MORE.STUFF
+++ b/contrib/groff/MORE.STUFF
@@ -12,8 +12,7 @@ Here two ports using the gcc compiler and other GNU tools:
Kees Zeelenberg <c.zeelenberg@hccnet.nl>:
- ftp://ftp.franken.de/pub/win32/develop/gnuwin32/
- cygwin/porters/Zeelenberg_Kees/B20/index.html
+ http://gnuwin32.sourceforge.net/
dos
---
@@ -34,6 +33,13 @@ can be found at
http://www.lunabase.org/~faber/Vault/software/grap/
+A djgpp port which runs on MS-DOS and all Win32 systems (Win95, Win98,
+WinNT) done by Kees Zeelenberg <c.zeelenberg@hccnet.nl> is available from
+
+ ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/
+
+It is intended to be used with the djgpp port of groff.
+
plot2dev
--------
@@ -44,6 +50,59 @@ driver). The actual version can be found as
ftp://ftp.ffii.org/pub/groff/plot2dev-x.x.tar.gz
+troffcvt
+--------
+
+From the web page:
+
+ troffcvt is a translator that turns troff input into a form that can be
+ more easily processed. The troffcvt distribution comes with
+ postprocessors that turn troffcvt into various destination formats such
+ as HTML (Hypertext Markup Language), RTF (Rich Text Format) or plain
+ text.
+
+Note that you need a lot of additional packages to compile troffcvt;
+everything is available from
+
+ http://www.primate.wisc.edu/software/troffcvt/
+
+unroff
+______
+
+From the README file:
+
+ Unroff is a Scheme-based, programmable, extensible troff translator with
+ a back-end for the Hypertext Markup Language. Unroff is free software
+ and is distributed both as source and as precompiled binaries.
+
+ http://www.informatik.uni-bremen.de/~net/unroff/unroff.html
+
+You need als Elk, the Scheme based Extension Language Kit, which is
+available from
+
+ http://www.informatik.uni-bremen.de/~net/elk
+
+deroff
+------
+
+Deroff removes roff constructs from documents for the purpose of indexing,
+spell checking etc.
+
+Michael Haardt's <michael@moria.de> implementation is a little smarter than
+traditional implementations, because it knows about certain -man and
+-mm macros. It is able to generate a word list for spell checking tools
+or omit headers for sentence analysis tools. It can further generate
+cpp-style #line lines.
+
+ http://www.moria.de/deroff/
+
+Version 1.6 compiled with DJGPP (for MS-DOS and all Win32 systems, i.e.
+Win95, Win98, WinNT) is available from
+
+ ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/
+
+and its mirrors.
+
miscellaneous
-------------
@@ -80,6 +139,12 @@ miscellaneous
of AT&T, and so should be invoked with the UNIX troff -mm flag; they
should also work with the GNU troff -mm flag.
+. Thomas Baruchel <baruchel@libertysurf.fr> has developed Meta-tbl, a tbl
+ postprocessor to manipulate table cells (like adding gray shades). The
+ latest version can be found at
+
+ http://perso.libertysurf.fr/baruchel/
+
documentation
-------------
diff --git a/contrib/groff/Makefile.comm b/contrib/groff/Makefile.comm
index b6cb4eb..b9c9c85 100644
--- a/contrib/groff/Makefile.comm
+++ b/contrib/groff/Makefile.comm
@@ -119,9 +119,12 @@ 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" \
+ @sed -e "s|@BINDIR@|$(bindir)|g" \
+ -e "s|@FONTDIR@|$(fontdir)|g" \
-e "s|@FONTPATH@|$(fontpath)|g" \
-e "s|@MACRODIR@|$(tmacdir)|g" \
+ -e "s|@SYSTEMMACRODIR@|$(systemtmacdir)|g" \
+ -e "s|@LOCALMACRODIR@|$(localtmacdir)|g" \
-e "s|@MACROPATH@|$(tmacpath)|g" \
-e "s|@DEVICE@|$(DEVICE)|g" \
-e "s|@DEFAULT_INDEX@|$(indexdir)/$(indexname)|g" \
@@ -205,6 +208,7 @@ uninstall_prog:
.PHONY: install_dev
install_dev:
-test -d $(datadir) || $(mkinstalldirs) $(datadir)
+ -test -d $(dataprogramdir) || $(mkinstalldirs) $(dataprogramdir)
-test -d $(datasubdir) || $(mkinstalldirs) $(datasubdir)
-test -d $(fontdir) || $(mkinstalldirs) $(fontdir)
-test -d $(fontsubdir) || $(mkinstalldirs) $(fontsubdir)
diff --git a/contrib/groff/Makefile.in b/contrib/groff/Makefile.in
index 9856aab..63073ec 100644
--- a/contrib/groff/Makefile.in
+++ b/contrib/groff/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 1989-2000 Free Software Foundation, Inc.
+# Copyright (C) 1989-2000, 2001 Free Software Foundation, Inc.
# Written by James Clark (jjc@jclark.com)
#
# This file is part of groff.
@@ -17,6 +17,15 @@
# with groff; see the file COPYING. If not, write to the Free Software
# Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+srcdir=@srcdir@
+top_srcdir=@top_srcdir@
+VPATH=@srcdir@
+top_builddir=@top_builddir@
+
+version=`cat $(top_srcdir)/VERSION`
+# No additional number if revision is zero
+revision=`sed -e 's/^0$$//' -e 's/^[1-9].*$$/.&/' $(top_srcdir)/REVISION`
+
# 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).
@@ -71,27 +80,41 @@ g=@g@
# 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
+bindir=@bindir@
-# datasubdir says where to install data files
+# libdir says where to install platform-dependent data
+libdir=@libdir@
+libprogramdir=$(libdir)/groff
+
+# datasubdir says where to install platform-independent data files
datadir=@datadir@
-datasubdir=$(datadir)/groff
+dataprogramdir=$(datadir)/groff
+datasubdir=$(dataprogramdir)/$(version)$(revision)
# fontdir says where to install dev*/*.
fontdir=$(datasubdir)/font
# fontpath says where to look for dev*/*.
-fontpath=.:$(fontdir):/usr/lib/font
+fontpath=$(fontdir):/usr/lib/font
# tmacdir says where to install macros.
tmacdir=$(datasubdir)/tmac
+# systemtmacdir says where to install platform-dependent macros
+systemtmacdir=$(libprogramdir)/site-tmac
+
+# localtmacdir says where local files will be installed
+localtmacdir=$(dataprogramdir)/site-tmac
+
# tmacpath says where to look for macro files.
-tmacpath=.:$(tmacdir)
+# The current directory will be prepended in unsafe mode only; the home
+# directory will be always added.
+# `troffrc' and `troffrc-end' (and `eqnrc') are searched neither in the
+# current nor in the home directory.
+tmacpath=$(systemtmacdir):$(localtmacdir):$(tmacdir)
# sys_tmac_prefix is prefix (if any) for system macro packages
sys_tmac_prefix=@sys_tmac_prefix@
@@ -225,11 +248,6 @@ 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
@@ -253,13 +271,18 @@ MDEFINES= \
"top_builddir=$(top_builddir)" \
"prefix=$(prefix)" \
"exec_prefix=$(exec_prefix)" \
- "bindir=$(bindir)" \
"g=$(g)" \
"datadir=$(datadir)" \
+ "dataprogramdir=$(dataprogramdir)" \
"datasubdir=$(datasubdir)" \
+ "libdir=$(libdir)" \
+ "libprogramdir=$(libprogramdir)" \
+ "bindir=$(bindir)" \
"fontdir=$(fontdir)" \
"fontpath=$(fontpath)" \
"tmacdir=$(tmacdir)" \
+ "systemtmacdir=$(systemtmacdir)" \
+ "localtmacdir=$(localtmacdir)" \
"tmacpath=$(tmacpath)" \
"indexext=$(indexext)" \
"indexdir=$(indexdir)" \
@@ -318,6 +341,7 @@ CCPROGDIRS=\
src/preproc/grn \
src/preproc/refer \
src/preproc/soelim \
+ src/preproc/html \
src/devices/grops \
src/devices/grotty \
src/devices/grodvi \
@@ -461,15 +485,10 @@ $(INCDIRS) $(OTHERDIRS): FORCE
-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
rm -f groff-$(version)$(revision).tar.gz
- rm -f src/xditview/Imakefile;
mkdir tmp
for d in $(DISTDIRS); do \
$(mkinstalldirs) tmp/$$d; \
@@ -518,7 +537,9 @@ uninstall: uninstall_sub 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)
+ $(tmacdir) $(systemtmacdir) $(localtmacdir) $(fontdir) $(bindir) \
+ $(datasubdir) $(dataprogramdir) $(datadir) \
+ $(libprogramdir) $(libdir)
.PHONY: check
diff --git a/contrib/groff/Makefile.sub b/contrib/groff/Makefile.sub
index ab72a5f..77c701f 100644
--- a/contrib/groff/Makefile.sub
+++ b/contrib/groff/Makefile.sub
@@ -1,4 +1,5 @@
-DISTCLEANFILES=config.status config.log config.cache Makefile
+DISTCLEANFILES=config.status config.log config.cache Makefile \
+ src/xditview/Imakefile
CLEANADD=Makefile.cfg conftest*
distfiles: configure
diff --git a/contrib/groff/NEWS b/contrib/groff/NEWS
index 855a268..4866f4f 100644
--- a/contrib/groff/NEWS
+++ b/contrib/groff/NEWS
@@ -1,6 +1,244 @@
This file describes recent user-visible changes in groff. Bug fixes
are not described. There are more details in the man pages.
+Groff
+-----
+
+o `-mFOO' will now search first for `FOO.tmac' and then for `tmac.FOO'. The
+ old behaviour has been changed to overcome problems with platforms which
+ have an 8+3 file name limit, and platforms which have other versions of
+ troff installed also. Additionally, all macro files have been renamed
+ using the latter scheme to avoid 8+3 name clashes.
+
+o The new environment variable GROFF_BIN_PATH will be checked for programs
+ groff is calling (preprocessors, troff, and output devices) before PATH.
+ If not set, it defaults to the directory where the groff binary is
+ located. Previously, it was PATH only. The nroff script will only use
+ GROFF_BIN_PATH to find the groff binary but passes both the GROFF_BIN_PATH
+ and PATH environment variable to groff.
+
+Troff
+-----
+
+o The mdoc package has been completely rewritten, using the full power of
+ GNU troff to remove limitations of Unix troff (which is no longer
+ supported). Most important changes are:
+
+ . No argument limit.
+ . Almost all macros are parsed and callable (if it makes sense).
+ . `.Lb': prints library names
+ . `.Nm <punctuation>' now works as expected; `.Nm "" <punctuation>' has
+ been withdrawn.
+ . Updated `.St' command
+ . `.Fx': prints FreeBSD
+ . `.Ox': prints OpenBSD
+ . `.Bsx': prints BSD/OS
+ . `.Brq', `.Bro', `.Brc': brace enclosure macros
+ . `.Bd -centered': center lines
+ . `.Bl -xwidth <string>': interpret <string> and use the resulting width
+ . support for double-sided printing (-rD1 command line switch)
+ . support for 11pt and 12pt document sizes (-rS11, -rS12 command line
+ switches)
+
+ `groff_mdoc.man' replaces `groff_mdoc.samples.man'; it now completely
+ documents the mdoc package.
+
+ Great care has been taken to assure backwards compatibility. If you
+ encounter any abnormal results, please report them to bug-groff@gnu.org.
+
+o A new command line option for the `man' macros (similar to the `mdoc'
+ package has been implemented: `-rcR=1' (now the default in nroff mode) will
+ produce one single, very long page instead of multiple pages. `-rcR=0'
+ will deactivate it.
+
+o The `return' request has been added to return immediately from a macro.
+
+o A new request `nop' (no operation) has been added which is similar to
+ `if 1'. For example,
+
+ .if t \{\
+ Hallo!
+ .\}
+
+ can now be written as
+
+ .if t \{\
+ . nop Hallo!
+ .\}
+
+o `box' and `boxa' are two new requests which behave similarly to `di' and
+ `da' but don't include a partially filled line (which is restored after
+ ending the diversion).
+
+o The `asciify' request has been extended to `unformat' space characters
+ and some other escape sequences also.
+
+ `\ ' will no longer be unformatted as a space but remains an unpaddable,
+ unbreakable space character.
+
+o The new `unformat' request is similar to `asciify' but only handles space
+ characters and tabs specially if the diversion is reread, retaining font
+ information. This makes it possible to reformat diversions; for example
+ the following
+
+ .ll 3i
+ .
+ a01 a02 a03 a04 a05 a06 a07 a08 a09 a10.
+ .
+ .box box1
+ .ev 1
+ .nf
+ \f[B]b01 b02 b03 b04 b05 b06 b07 b08 b09 b10.\f[P]
+ .br
+ .ev
+ .box
+ .
+ c01 c02 c03 c04 c05 c06 c07 c08 c09 c10.
+ .
+ .unformat box1
+ .box1
+
+ gives
+
+ a01 a02 a03 a04 a05 a06 a07
+ a08 a09 a10. c01 c02 c03 c04
+ c05 c06 c07 c08 c09 c10. b01
+ b02 b03 b04 b05 b06 b07 b08
+ b09 b10.
+
+ Without the `unformat' request, space characters are converted to word
+ space nodes which are no longer stretchable, and the result would be
+
+ a01 a02 a03 a04 a05 a06 a07
+ a08 a09 a10. c01 c02 c03 c04
+ c05 c06 c07 c08 c09 c10. b01
+ b02 b03 b04 b05 b06 b07 b08
+ b09 b10.
+
+o The new request `linetabs' controls the `line-tabs' mode. In line-tabs
+ mode, tab distances are computed relative to the (current) output line.
+ Otherwise they are taken relative to the input line. For example, the
+ following
+
+ .ds x a\t\c
+ .ds y b\t\c
+ .ds z c
+ .ta 1i 3i
+ \*x
+ \*y
+ \*z
+
+ yields
+
+ a b c
+
+ In line-tabs mode, the same code gives
+
+ a b c
+
+ The new read-only number register `.linetabs' returns 1 if in line-tabs
+ mode, and 0 otherwise.
+
+o Two new requests `tm1' and `tmc' have been added to improve writing
+ messages to the terminal. `tm1' is similar to `tm' but allows leading
+ whitespace. `tmc' is similar to `tm1' but doesn't emit a final newline.
+
+o A new request `dei' (define indirect) has been added. The first and
+ second parameter of `dei' are taken from string registers rather than
+ directly; this very special request is needed to make `trace.tmac'
+ independent from the escape character (which might even be disabled).
+
+o It is now possible to save and restore the escape character with two new
+ requests `ecs' and `ecr'.
+
+o The new escape sequence \B'...' is an analogon to `\A': If the string
+ within the delimiters is a valid numeric expression, return character `1',
+ and `0' otherwise.
+
+o The new escape sequence `\:' inserts a zero-width break point. This is
+ similar to `\%' but without a soft hyphen character.
+
+o The `tr' request can now map characters onto `\~'.
+
+o Calling the `fam' request without an argument switches back to the
+ previous font family.
+
+o The new read-only register `.int' is set to a positive value if the last
+ output line is interrupted (i.e., if it contains `\c').
+
+o The `writem' request is not new, but hasn't been documented before. This
+ is similar to `write' but instead of a string the contents of a given
+ macro or string is written to a stream.
+
+o The read/write number register `hp' to get/set the current horizontal
+ position relative to the input line isn't new but hasn't been documented
+ properly before.
+
+o `\X' and `\Y' are no transparent for end-of-sentence recognition.
+
+o The `cu' request in nroff mode now works as documented (i.e., it does
+ underline spaces also).
+
+Nroff
+-----
+
+Option -v shows the version number.
+
+Grog
+----
+
+o The grog script will now work in non-compatibility mode also (which is the
+ default). As usual, use the `-C' option to activate compatibility mode.
+
+o Option -v shows the version number.
+
+Grops
+-----
+
+A new option `-P' resp. a new environment variable `GROPS_PROLOGUE' has been
+added to select a different prologue file.
+
+The effect of the former `-mpsnew' option to access more Type 1 characters
+is now the default and no longer available. To get the old behaviour (i.e.,
+emulation of some glyphs by composition) use `-mpsold'.
+
+Miscellaneous
+-------------
+
+o For security reasons the following changes have been done:
+
+ . The tmac.safer file has been replaced with a built-in solution; .open,
+ .opena, .pso, .sy, and .pi are completely disabled in safer mode (which
+ is the default); to enable these requests the `-U' command line flag
+ must be used.
+
+ . Files specified with the .mso request or given with the `-m' command
+ line option, and hyphenation patterns loaded with `.hpf' are no longer
+ searched in the current directory by default (besides the usual tmac
+ path). Instead, the home directory is used. To add the current
+ directory, either use the `-U' or `-M' command line option or set the
+ GROFF_TMAC_PATH environment variable to an appropriate value.
+
+ . troffrc, troffrc-end, and eqnrc are neither searched in the current nor
+ in the home directory (even if -U is given). Use -M or GROFF_TMAC_PATH
+ to change that.
+
+ . Similarly, the current directory is no longer part of the font path.
+ Use the `-F' command line option or the GROFF_FONT_PATH environment
+ variable if you really need the current directory.
+
+o groff will now install its data files into
+ /usr/local/share/groff/<version> by default, following the GNU standard.
+ Additionally, a local tmac directory (by default
+ /usr/local/share/groff/site-tmac) will be scanned before the standard tmac
+ directory. Wrapper files for system-specific macro packages (if
+ necessary) are put into /usr/local/lib/groff/site-tmac; this directory
+ will be searched before the local tmac directory.
+
+o All programs now have option `-v' to show the version number; they will
+ exit immediately afterwards, following the GNU standards. Additionally,
+ `--version' and `--help' have been added, doing the obvious actions.
+
VERSION 1.16.1
==============
diff --git a/contrib/groff/PROBLEMS b/contrib/groff/PROBLEMS
index b73db2f..001610e 100644
--- a/contrib/groff/PROBLEMS
+++ b/contrib/groff/PROBLEMS
@@ -118,11 +118,11 @@ on the Software Companion CD and is installed as /opt/sfw/bin/gmake.
* On Ultrix, the make stops with the message
- *** Error code 1
+ *** Error code 1
- Stop.
+ Stop.
-for no apparent reason.
+ for no apparent reason.
Use GNU make.
@@ -172,10 +172,10 @@ No. Real dependency files are created with a `make depend' call.
----------------------------------------------------------------------
-* Groff can't handle my troff document. It works fine with AT&T troff.
+* 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
+option. Alternatively there's the sed script `tmac/fixmacros.sed'
which will attempt to edit a file of macros so that it can be used
with groff without the -C flag.
@@ -186,7 +186,8 @@ with groff without the -C flag.
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.)
+directory may help you to do this. (It will take a *long* time on
+slow computers.)
----------------------------------------------------------------------
@@ -222,7 +223,7 @@ 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.
+ 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
@@ -231,9 +232,22 @@ request.
----------------------------------------------------------------------
+* groff produces wrapper macros for `ms' and friends which call the
+ system's original macros. Then, to get groff's ms macro package I
+ have to use `-mgs' instead `-ms'. Can I avoid this?
+
+Yes. Configure and compile groff as usual, but install it with
+
+ make install tmac_wrap=""
+
+Then no wrapper files are produced, and `-ms' will use groff's `ms'
+macros.
+
+----------------------------------------------------------------------
+
* Groff doesn't use the font names I'm used to.
-Use the `ftr' request. See gtroff(1).
+Use the `ftr' request. See (g)troff(1).
----------------------------------------------------------------------
@@ -326,11 +340,7 @@ 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.
+Use the groff -mm macros.
----------------------------------------------------------------------
@@ -369,7 +379,7 @@ comments, you can do it like this:
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
+modify tmac/an-old.tmac to suit your personal taste. For example, if
you want the center of the page header to say
System Programmer's Manual
@@ -410,10 +420,9 @@ The solution is to fix the manual page:
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):
+groff. Copy /usr/lib/tmac/tmac.an to
+/usr/local/share/groff/site-tmac/an.tmac 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
@@ -436,17 +445,25 @@ Frank Wortner):
.}f
Another possible solution is to install tmac/man.ultrix as
-/usr/local/lib/groff/tmac/man.local.
+/usr/local/share/groff/site-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.
+Copy HP's tmac.an into /usr/local/share/groff/site-tmac/an.tmac, and
+either put `.cp 1' at the beginning or filter it (and any files it .so's)
+through tmac/fixmacros.sed.
+
+----------------------------------------------------------------------
+
+* On HP-UX, the compiler complains about missing symbol `alloca'.
+
+Say
+
+ export LDFLAGS=-lPW
+
+before starting the configure script.
----------------------------------------------------------------------
diff --git a/contrib/groff/README b/contrib/groff/README
index 62ea08d..88f8f87 100644
--- a/contrib/groff/README
+++ b/contrib/groff/README
@@ -20,7 +20,7 @@ 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.
+with the Unix versions of troff, -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.
diff --git a/contrib/groff/REVISION b/contrib/groff/REVISION
index d00491f..573541a 100644
--- a/contrib/groff/REVISION
+++ b/contrib/groff/REVISION
@@ -1 +1 @@
-1
+0
diff --git a/contrib/groff/VERSION b/contrib/groff/VERSION
index e7151969..b48f322 100644
--- a/contrib/groff/VERSION
+++ b/contrib/groff/VERSION
@@ -1 +1 @@
-1.16
+1.17
diff --git a/contrib/groff/aclocal.m4 b/contrib/groff/aclocal.m4
index 1cd92ce..34ee4f1 100644
--- a/contrib/groff/aclocal.m4
+++ b/contrib/groff/aclocal.m4
@@ -1,5 +1,5 @@
dnl Autoconf macros for groff.
-dnl Copyright (C) 1989, 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+dnl Copyright (C) 1989-1995, 2001 Free Software Foundation, Inc.
dnl
dnl This file is part of groff.
dnl
@@ -129,15 +129,12 @@ 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_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
+AC_MSG_RESULT(no))])dnl
dnl
dnl
AC_DEFUN(GROFF_OSFCN_H,
@@ -238,6 +235,13 @@ if test -z "$PAGE"; 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
+ else
+ for f in $prefix/share/groff/*/font/devps/DESC; do
+ if test -r $f; then
+ descfile=$f
+ break
+ fi
+ done
fi
if test -n "$descfile" \
&& grep "^paperlength 841890" $descfile >/dev/null 2>&1; then
diff --git a/contrib/groff/configure b/contrib/groff/configure
index 31d9341..061a658 100755
--- a/contrib/groff/configure
+++ b/contrib/groff/configure
@@ -1389,7 +1389,7 @@ 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=''
+ echo "$ac_t""no" 1>&6; SH_SCRIPT_SED_CMD='1s/a/a/'
fi
rm -f conftest.sh
@@ -1963,18 +1963,10 @@ 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:1976: checking for sys_errlist in <errno.h> or <stdio.h>" >&5
+echo "configure:1968: checking for sys_errlist in <errno.h> or <stdio.h>" >&5
cat > conftest.$ac_ext <<EOF
-#line 1978 "configure"
+#line 1970 "configure"
#include "confdefs.h"
#include <errno.h>
#include <stdio.h>
@@ -1982,7 +1974,7 @@ int main() {
int k; k = (int)sys_errlist[0];
; return 0; }
EOF
-if { (eval echo configure:1986: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1978: \"$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
@@ -1995,13 +1987,6 @@ else
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.
@@ -2011,16 +1996,16 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking C++ <osfcn.h>""... $ac_c" 1>&6
-echo "configure:2015: checking C++ <osfcn.h>" >&5
+echo "configure:2000: checking C++ <osfcn.h>" >&5
cat > conftest.$ac_ext <<EOF
-#line 2017 "configure"
+#line 2002 "configure"
#include "confdefs.h"
#include <osfcn.h>
int main() {
read(0, 0, 0); open(0, 0);
; return 0; }
EOF
-if { (eval echo configure:2024: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2009: \"$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
@@ -2049,16 +2034,16 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking C++ <limits.h>""... $ac_c" 1>&6
-echo "configure:2053: checking C++ <limits.h>" >&5
+echo "configure:2038: checking C++ <limits.h>" >&5
cat > conftest.$ac_ext <<EOF
-#line 2055 "configure"
+#line 2040 "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:2062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2047: \"$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
@@ -2087,16 +2072,16 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking for declaration of time_t""... $ac_c" 1>&6
-echo "configure:2091: checking for declaration of time_t" >&5
+echo "configure:2076: checking for declaration of time_t" >&5
cat > conftest.$ac_ext <<EOF
-#line 2093 "configure"
+#line 2078 "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:2100: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2085: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
echo "$ac_t""yes" 1>&6
else
@@ -2117,12 +2102,12 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:2121: checking return type of signal handlers" >&5
+echo "configure:2106: 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 2126 "configure"
+#line 2111 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -2139,7 +2124,7 @@ int main() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2143: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2128: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
@@ -2158,16 +2143,16 @@ EOF
echo $ac_n "checking struct exception""... $ac_c" 1>&6
-echo "configure:2162: checking struct exception" >&5
+echo "configure:2147: checking struct exception" >&5
cat > conftest.$ac_ext <<EOF
-#line 2164 "configure"
+#line 2149 "configure"
#include "confdefs.h"
#include <math.h>
int main() {
struct exception e;
; return 0; }
EOF
-if { (eval echo configure:2171: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2156: \"$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
@@ -2181,7 +2166,7 @@ else
fi
rm -f conftest*
echo $ac_n "checking for sin in -lm""... $ac_c" 1>&6
-echo "configure:2185: checking for sin in -lm" >&5
+echo "configure:2170: 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
@@ -2189,7 +2174,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lm $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2193 "configure"
+#line 2178 "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
@@ -2200,7 +2185,7 @@ int main() {
sin()
; return 0; }
EOF
-if { (eval echo configure:2204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2189: \"$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
@@ -2225,17 +2210,17 @@ 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:2229: checking for $ac_hdr" >&5
+echo "configure:2214: 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 2234 "configure"
+#line 2219 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2239: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2224: \"$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*
@@ -2264,12 +2249,12 @@ done
for ac_func in getpagesize
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2268: checking for $ac_func" >&5
+echo "configure:2253: 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 2273 "configure"
+#line 2258 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2292,7 +2277,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2281: \"$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
@@ -2317,7 +2302,7 @@ fi
done
echo $ac_n "checking for working mmap""... $ac_c" 1>&6
-echo "configure:2321: checking for working mmap" >&5
+echo "configure:2306: 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
@@ -2325,7 +2310,7 @@ else
ac_cv_func_mmap_fixed_mapped=no
else
cat > conftest.$ac_ext <<EOF
-#line 2329 "configure"
+#line 2314 "configure"
#include "confdefs.h"
/* Thanks to Mike Haertel and Jim Avera for this test.
@@ -2465,7 +2450,7 @@ main()
}
EOF
-if { (eval echo configure:2469: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2454: \"$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
@@ -2492,12 +2477,12 @@ 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:2496: checking for $ac_func" >&5
+echo "configure:2481: 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 2501 "configure"
+#line 2486 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2520,7 +2505,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2524: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2509: \"$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
@@ -2550,12 +2535,12 @@ LIBS="$saved_libs"
for ac_func in rename mkstemp strcasecmp strncasecmp strsep strdup
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2554: checking for $ac_func" >&5
+echo "configure:2539: 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 2559 "configure"
+#line 2544 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2578,7 +2563,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2582: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2567: \"$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
@@ -2603,12 +2588,12 @@ fi
done
echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6
-echo "configure:2607: checking for sys_siglist declaration in signal.h or unistd.h" >&5
+echo "configure:2592: 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 2612 "configure"
+#line 2597 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -2620,7 +2605,7 @@ int main() {
char *msg = *(sys_siglist + 1);
; return 0; }
EOF
-if { (eval echo configure:2624: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2609: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_decl_sys_siglist=yes
else
@@ -2649,16 +2634,16 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking whether ANSI array delete syntax supported""... $ac_c" 1>&6
-echo "configure:2653: checking whether ANSI array delete syntax supported" >&5
+echo "configure:2638: checking whether ANSI array delete syntax supported" >&5
cat > conftest.$ac_ext <<EOF
-#line 2655 "configure"
+#line 2640 "configure"
#include "confdefs.h"
int main() {
char *p = new char[5]; delete [] p;
; return 0; }
EOF
-if { (eval echo configure:2662: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2647: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
echo "$ac_t""yes" 1>&6
else
@@ -2687,16 +2672,16 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking traditional preprocessor""... $ac_c" 1>&6
-echo "configure:2691: checking traditional preprocessor" >&5
+echo "configure:2676: checking traditional preprocessor" >&5
cat > conftest.$ac_ext <<EOF
-#line 2693 "configure"
+#line 2678 "configure"
#include "confdefs.h"
#define name2(a,b) a/**/b
int main() {
int name2(foo,bar);
; return 0; }
EOF
-if { (eval echo configure:2700: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2685: \"$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
@@ -2717,12 +2702,12 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking w_coredump""... $ac_c" 1>&6
-echo "configure:2721: checking w_coredump" >&5
+echo "configure:2706: checking w_coredump" >&5
if test "$cross_compiling" = yes; then
echo "$ac_t""no" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2726 "configure"
+#line 2711 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
@@ -2737,7 +2722,7 @@ main()
#endif
}
EOF
-if { (eval echo configure:2741: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2726: \"$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
@@ -2753,18 +2738,25 @@ rm -fr conftest*
fi
echo $ac_n "checking default value for grops -b option""... $ac_c" 1>&6
-echo "configure:2757: checking default value for grops -b option" >&5
+echo "configure:2742: 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:2762: checking default paper size" >&5
+echo "configure:2747: 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
+ else
+ for f in $prefix/share/groff/*/font/devps/DESC; do
+ if test -r $f; then
+ descfile=$f
+ break
+ fi
+ done
fi
if test -n "$descfile" \
&& grep "^paperlength 841890" $descfile >/dev/null 2>&1; then
@@ -2793,7 +2785,7 @@ 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:2797: checking for existing troff installation" >&5
+echo "configure:2789: 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
@@ -2803,7 +2795,7 @@ else
fi
echo $ac_n "checking for prefix of system macro packages""... $ac_c" 1>&6
-echo "configure:2807: checking for prefix of system macro packages" >&5
+echo "configure:2799: 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
@@ -2823,7 +2815,7 @@ 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:2827: checking which system macro packages should be made available" >&5
+echo "configure:2819: 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;;"`
diff --git a/contrib/groff/configure.in b/contrib/groff/configure.in
index 081df0e..92024e0 100644
--- a/contrib/groff/configure.in
+++ b/contrib/groff/configure.in
@@ -15,7 +15,9 @@ 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='')
+dnl use a dummy substitution if no csh hack is necessary to avoid errors
+dnl with non-GNU sed programs
+GROFF_CSH_HACK(SH_SCRIPT_SED_CMD='1s/.*/:/', SH_SCRIPT_SED_CMD='1s/a/a/')
AC_SUBST(SH_SCRIPT_SED_CMD)
dnl checks for headers
AC_CHECK_HEADERS(stdlib.h unistd.h dirent.h limits.h sys/dir.h \
diff --git a/contrib/groff/contrib/mm/ChangeLog b/contrib/groff/contrib/mm/ChangeLog
new file mode 100644
index 0000000..ab3ed83
--- /dev/null
+++ b/contrib/groff/contrib/mm/ChangeLog
@@ -0,0 +1,521 @@
+Mon Mar 5 09:30:18 2001 Jörgen Hägg (jh@axis.com)
+
+ * S didn't reset to default point size
+ * (dummy line to force cvs update...)
+
+Sat Jan 06 10:30:00 2001 Werner Lemberg (wl@gnu.org)
+
+ * Fixed assignment of page offset given as a command line argument.
+
+Fri Nov 17 05:34:17 2000 Jörgen Hägg (jh@axis.com)
+
+ * Renamed tmac.m and tmac.mse to m.tmac and mse.tmac
+
+Thu Sep 14 05:52:48 2000 Jörgen Hägg (jh@axis.com)
+
+ * New Changelog-format, it will show changes better.
+ Easier for other to use. (Somehow I didn't really
+ understand why the e-mail address was supposed to be
+ 'jh at axis.com' in the Changelog. :-)
+
+Thu Sep 7 06:17:42 2000 Jörgen Hägg (jh at axis.com)
+
+ * version 2.0
+ * Had to do something about my version numbering.
+ The main CVS archive was not in sync with mine.
+ So, now it is 2.0. :-)
+
+Sat Jun 17 23:00:00 2000 Eli Zaretskii (eliz@is.elta.co.il)
+
+ * Makefile.sim (.man.n): Replace `;' with `|', since DOS/Windows
+ path lists use the semicolon as a separator.
+
+Sun Jun 4 21:39:00 2000 Kaneda Hiroshi (vanitas at ma3.seikyou.ne.jp)
+
+ * Fixing a lot of typos in groff_mm.man
+
+Sun Jan 30 22:52:20 2000 Jörgen Hägg (jh at axis.com)
+
+ * version 1.34
+ * Changed the version number in the CVS repository
+ * MC had a bug in column calculation, (thanks to T. Kurt Bond)
+
+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/groff/contrib/mm/Makefile.sim b/contrib/groff/contrib/mm/Makefile.sim
new file mode 100644
index 0000000..e1d4a14
--- /dev/null
+++ b/contrib/groff/contrib/mm/Makefile.sim
@@ -0,0 +1,66 @@
+#
+# $Id: Makefile.sim,v 2.1 2000/11/17 04:26:02 jhaegg Exp $
+#
+# To install mgm separately as gm.tmac:
+# make -f Makefile.sub tmacdir=/usr/local/lib/groff/tmac srcdir=. \
+# INSTALL_DATA='install -m 644' tmac_m=gm install
+#
+# or as m.tmac:
+#
+# 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/groff/contrib/mm/Makefile.sub b/contrib/groff/contrib/mm/Makefile.sub
new file mode 100644
index 0000000..87cf050
--- /dev/null
+++ b/contrib/groff/contrib/mm/Makefile.sub
@@ -0,0 +1,55 @@
+#
+# $Id: Makefile.sub,v 2.1 2000/11/17 04:26:02 jhaegg 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
+
+all: mmroff
+
+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
+ -rm -f $(tmacdir)/$(tmac_m_prefix)m.tmac
+ $(INSTALL_DATA) $(srcdir)/m.tmac $(tmacdir)/$(tmac_m_prefix)m.tmac
+ @sed -e "s;^.mso m.tmac;.mso $(tmac_m_prefix)m.tmac;g" \
+ $(srcdir)/mse.tmac > $(tmacdir)/$(tmac_m_prefix)mse.tmac
+install_mmroff : mmroff
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/mmroff
+ $(INSTALL_SCRIPT) 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_m_prefix)m.tmac
+ -rm -f $(tmacdir)/$(tmac_m_prefix)mse.tmac
+ -rmdir $(tmacdir)/mm
+ -rm -f $(bindir)/mmroff
diff --git a/contrib/groff/contrib/mm/NOTES b/contrib/groff/contrib/mm/NOTES
new file mode 100644
index 0000000..7643c10
--- /dev/null
+++ b/contrib/groff/contrib/mm/NOTES
@@ -0,0 +1,105 @@
+######################################################################
+$Id: NOTES,v 2.0 2000/09/14 03:40:24 jhaegg Exp $
+
+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/groff/contrib/mm/README b/contrib/groff/contrib/mm/README
new file mode 100644
index 0000000..15901dd
--- /dev/null
+++ b/contrib/groff/contrib/mm/README
@@ -0,0 +1,37 @@
+
+$Id: README,v 2.1 2000/11/17 04:27:03 jhaegg Exp $
+
+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.com 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 m.tmac) and the version of groff.
+
+Any new ideas or improvements are welcome.
+
+Newest version is available here or at the groff CVS repository.
+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 Hägg
+
+Thanks to everyone who have sent me bug-reports and fixes.
+
+
+Yes, my version numbering differs from the groff CVS, but I
+like mine better. :-)
+
+More likely, I'm too lazy to change it, but someday I'll
+try to sync them...
+The step to 2.0 is an attempt, let's see if it works.
diff --git a/contrib/groff/contrib/mm/examples/APP b/contrib/groff/contrib/mm/examples/APP
new file mode 100644
index 0000000..82352e5
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/B1B2 b/contrib/groff/contrib/mm/examples/B1B2
new file mode 100644
index 0000000..a2bb3ad
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/COVER b/contrib/groff/contrib/mm/examples/COVER
new file mode 100644
index 0000000..d23597f
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/IND b/contrib/groff/contrib/mm/examples/IND
new file mode 100644
index 0000000..fbf6c43
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/LT b/contrib/groff/contrib/mm/examples/LT
new file mode 100644
index 0000000..cf06389
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/LT.se b/contrib/groff/contrib/mm/examples/LT.se
new file mode 100644
index 0000000..bfbd77f
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/ML b/contrib/groff/contrib/mm/examples/ML
new file mode 100644
index 0000000..bbfca3d
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/MOVE b/contrib/groff/contrib/mm/examples/MOVE
new file mode 100644
index 0000000..0f0399c
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/MUL b/contrib/groff/contrib/mm/examples/MUL
new file mode 100644
index 0000000..ae91fae
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/NCOL b/contrib/groff/contrib/mm/examples/NCOL
new file mode 100644
index 0000000..82c6f8d
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/ND b/contrib/groff/contrib/mm/examples/ND
new file mode 100644
index 0000000..4b3694a
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/README b/contrib/groff/contrib/mm/examples/README
new file mode 100644
index 0000000..cb6980f
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/References b/contrib/groff/contrib/mm/examples/References
new file mode 100644
index 0000000..72f6482
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/examples/SETR b/contrib/groff/contrib/mm/examples/SETR
new file mode 100644
index 0000000..0a92241
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/groff_mm.man b/contrib/groff/contrib/mm/groff_mm.man
new file mode 100644
index 0000000..6af75c6
--- /dev/null
+++ b/contrib/groff/contrib/mm/groff_mm.man
@@ -0,0 +1,1897 @@
+.\"
+.\" $Id: groff_mm.man,v 2.1 2001/04/13 09:03: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
+.br
+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 not appear before \fBTL\fP. The author information
+can contain initials, 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-text [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 which is
+printed at the bottom of each page. Block ends with \fBBE\fP.
+.TP
+.B "BVL text-indent [mark-indent [1]]"
+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 if 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 [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 second argument prevents the empty line between each list item
+to be printed. See \fBLI\fP.
+A third argument will prohibit printing of a blank line before each
+item.
+.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, which
+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 \fIvarname\fP 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 \fIvarname\fP 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.
+.sp
+\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 fontname 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 are 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
+.br
+\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 off 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 \fBLI\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 begin 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's identification are 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 \fBCONFIDENTIAL\fP on the second line
+below the date line. Any argument replaces \fBCONFIDENTIAL\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.
+\fIAddressee\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. \fBMULB\fP starts a diversion and \fBMULE\fP
+ends the diversion and prints the columns.
+The unit for width and space is 'n', but \fBMULB\fP accepts all
+normal unitspecifications like 'c' and 'i'.
+\fBMULB\fP 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. See \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 of
+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@g@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 are 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 reset 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 \fIrefname\fP.
+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 if the second argument is given,
+otherwise at the last.
+No reference data will be printed if the author(s) is specifed
+thru \fB.WA\fP/\fB.WE\fP.
+See \fBINTERNALS\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 contain
+"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 are 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@g@tbl\fP. See separate manual for \fB@g@tbl\fP.
+\fBTS\fP ends with \fBTE\fP.
+Argument \fIH\fP tells \fBm@TMAC_M_PREFIX@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 controls 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 an empty line before the verbose text.
+.T2 4
+Add an 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
+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.
+See 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.
+See also register N.
+.TP
+.B Sectp
+Flag controlling "section-page-numbers". A non-zero value enables this.
+See 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 0 and 5.
+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/groff/contrib/mm/groff_mmse.man b/contrib/groff/contrib/mm/groff_mmse.man
new file mode 100644
index 0000000..1e1f4a0
--- /dev/null
+++ b/contrib/groff/contrib/mm/groff_mmse.man
@@ -0,0 +1,82 @@
+.\"
+.\" $Id: groff_mmse.man,v 2.0 2000/09/14 03:40:24 jhaegg 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/groff/contrib/mm/m.tmac b/contrib/groff/contrib/mm/m.tmac
new file mode 100644
index 0000000..af60f76
--- /dev/null
+++ b/contrib/groff/contrib/mm/m.tmac
@@ -0,0 +1,3477 @@
+.\"
+.de @revision
+.ds RE \\$2
+..
+.\"
+.\" $Id: m.tmac,v 2.3 2001/03/05 09:56:29 jhaegg Exp $
+.@revision $Revision: 2.3 $
+.ig
+
+Copyright (C) 1991-2000 Free Software Foundation, Inc.
+mgm is written by Jörgen Hägg <jh@axis.com>
+
+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]u
+.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[S]
+. 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)
+.\"
+.\" calculate the number of columns/page
+.nr pg*cols-per-page 0
+.nr pg*i \\n[pg*column-size]
+.while \\n[pg*i]<=\\n[.l] \{\
+. nr pg*cols-per-page \\n[pg*cols-per-page]+1
+. nr pg*i \\n[pg*i]+\\n[pg*column-sep]+\\n[pg*column-size]
+.\}
+.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/groff/contrib/mm/mm/0.MT b/contrib/groff/contrib/mm/mm/0.MT
new file mode 100644
index 0000000..61f1a96
--- /dev/null
+++ b/contrib/groff/contrib/mm/mm/0.MT
@@ -0,0 +1,146 @@
+.\"------------
+.\" $Id: 0.MT,v 2.0 2000/09/14 03:40:25 jhaegg 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/groff/contrib/mm/mm/4.MT b/contrib/groff/contrib/mm/mm/4.MT
new file mode 100644
index 0000000..c8b6f37
--- /dev/null
+++ b/contrib/groff/contrib/mm/mm/4.MT
@@ -0,0 +1,81 @@
+.\"------------
+.\" $Id: 4.MT,v 2.0 2000/09/14 03:40:25 jhaegg 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/groff/contrib/mm/mm/5.MT b/contrib/groff/contrib/mm/mm/5.MT
new file mode 100644
index 0000000..a274d23
--- /dev/null
+++ b/contrib/groff/contrib/mm/mm/5.MT
@@ -0,0 +1,34 @@
+.\"------------
+.\" $Id: 5.MT,v 2.0 2000/09/14 03:40:25 jhaegg 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/groff/contrib/mm/mm/ms.cov b/contrib/groff/contrib/mm/mm/ms.cov
new file mode 100644
index 0000000..25d4579
--- /dev/null
+++ b/contrib/groff/contrib/mm/mm/ms.cov
@@ -0,0 +1,84 @@
+.\"------------
+.\" $Id: ms.cov,v 2.0 2000/09/14 03:40:25 jhaegg 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/groff/contrib/mm/mm/se_ms.cov b/contrib/groff/contrib/mm/mm/se_ms.cov
new file mode 100644
index 0000000..2d16d48
--- /dev/null
+++ b/contrib/groff/contrib/mm/mm/se_ms.cov
@@ -0,0 +1,3 @@
+.\" $Id: se_ms.cov,v 2.0 2000/09/14 03:40:25 jhaegg Exp $
+.mso mm/ms.cov
+.nr cur*abstract-ll 11c
diff --git a/contrib/groff/contrib/mm/mmroff.man b/contrib/groff/contrib/mm/mmroff.man
new file mode 100644
index 0000000..efe79b4
--- /dev/null
+++ b/contrib/groff/contrib/mm/mmroff.man
@@ -0,0 +1,48 @@
+.\"
+.\" $Id: mmroff.man,v 2.0 2000/09/14 03:40:24 jhaegg 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/groff/contrib/mm/mmroff.pl b/contrib/groff/contrib/mm/mmroff.pl
new file mode 100755
index 0000000..69b6105
--- /dev/null
+++ b/contrib/groff/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/groff/contrib/mm/mse.tmac b/contrib/groff/contrib/mm/mse.tmac
new file mode 100644
index 0000000..de78cb8
--- /dev/null
+++ b/contrib/groff/contrib/mm/mse.tmac
@@ -0,0 +1,184 @@
+.\" $Id: mse.tmac,v 2.1 2000/11/17 04:26:02 jhaegg Exp $
+.\"
+.\" swedish version of mm
+.\" See m.tmac for version-information.
+.ds @language se
+.mso m.tmac
+.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/contrib/groff/doc/Makefile b/contrib/groff/doc/Makefile
index 042bbe0..408e6e1 100644
--- a/contrib/groff/doc/Makefile
+++ b/contrib/groff/doc/Makefile
@@ -26,7 +26,7 @@ MEMACROS=../tmac/tmac.e
SOELIM=../src/preproc/soelim/soelim
version=`cat ../VERSION`
-# No additional number for the groff archive if revision is zero
+# No additional number if revision is zero
revision=`sed -e 's/^0$$//' -e 's/^[1-9].*$$/.&/' ../REVISION`
all: $(DOCS)
@@ -54,13 +54,13 @@ all: $(DOCS)
GROFF_TMAC_PATH=../tmac; \
export GROFF_TMAC_PATH; \
sed -e "s;@VERSION@;$(version)$(revision);" $< \
- | $(GROFF) -Tascii $(FFLAG) -U -ms -markup >$@
+ | $(GROFF) -Tascii $(FFLAG) -U -ms -mwww >$@
.ms.ps:
GROFF_TMAC_PATH=../tmac; \
export GROFF_TMAC_PATH; \
sed -e "s;@VERSION@;$(version)$(revision);" $< \
- | $(GROFF) -Tps $(FFLAG) -U -ms -markup >$@
+ | $(GROFF) -Tps $(FFLAG) -U -ms -mwww >$@
.texinfo.dvi:
texi2dvi -e $<
diff --git a/contrib/groff/doc/groff.texinfo b/contrib/groff/doc/groff.texinfo
index ca13abb..b537d1a 100644
--- a/contrib/groff/doc/groff.texinfo
+++ b/contrib/groff/doc/groff.texinfo
@@ -1,9 +1,8 @@
\input texinfo @c -*-texinfo-*-
@c
-@c If you use texinfo.tex 1999-09-25.10 or earlier please convert this
-@c manual with `texi2dvi -e groff.texinfo' due to a bug in expanding
-@c user-defined macros.
+@c Please convert this manual with `texi2dvi -e groff.texinfo' due to a bug
+@c in texinfo regarding expansion of user-defined macros.
@c
@c %**start of header (This is for running Texinfo on a region.)
@@ -17,55 +16,182 @@
@c We use the following indices:
@c
@c cindex: concepts
-@c findex: requests, escapes, and functions
+@c rqindex: requests
+@c esindex: escapes
@c vindex: registers
@c kindex: commands in font files
@c pindex: programs and files
@c tindex: environment variables
-@c maindex: macros and strings
+@c maindex: macros
+@c stindex: strings
@c glindex: glyph names
@c opindex: operators
@c
@c tindex and cindex are merged.
+@defcodeindex rq
+@defcodeindex es
@defcodeindex ma
+@defcodeindex st
@defcodeindex gl
@defcodeindex op
@syncodeindex tp cp
-@macro Deffn{category, name, arg}
-@deffn \category\ @t{\name\} \arg\
+@c to avoid uppercasing in @deffn while converting to info, we define
+@c our special @Var{}
+@c
+@c due to a (not officially documented) `feature' in makeinfo 4.0,
+@c macros are not expanded in @deffn (but the macro definition is
+@c properly removed), so we have to define @Var{} directly in TeX also
+
+@macro Var{arg}
+\arg\
+@end macro
+@tex
+\gdef\Var#1{\var{#1}}
+@end tex
+
+
+@c definition of requests
+
+@macro Defreq{name, arg}
+@rqindex \name\
+@deffn Request @t{.\name\} \arg\
+@end macro
+
+@macro Defreqx{name, arg}
+@rqindex \name\
+@deffnx Request @t{.\name\} \arg\
+@end macro
+
+@macro endDefreq
+@end deffn
+@end macro
+
+
+@c definition of escapes
+
+@macro Defesc{name, delimI, arg, delimII}
+@esindex \name\
+@deffn Escape @t{\name\\delimI\}@var{\arg\}@t{\delimII\}
@end macro
-@macro end_Deffn
+@macro Defescx{name, delimI, arg, delimII}
+@esindex \name\
+@deffnx Escape @t{\name\\delimI\}@var{\arg\}@t{\delimII\}
+@end macro
+
+@macro endDefesc
@end deffn
@end macro
-@macro Deffnx{category, name, arg}
-@deffnx \category\ @t{\name\} \arg\
+
+@c definition of registers
+
+@macro Defreg{name}
+@vindex \name\
+@deffn Register @t{\\n[\name\]}
+@end macro
+
+@macro Defregx{name}
+@vindex \name\
+@deffnx Register @t{\\n[\name\]}
@end macro
-@macro end_Deffnx
-@end deffnx
+@macro endDefreg
+@end deffn
@end macro
+
+@c definition of macros
+
@macro Defmac{name, arg}
-@defmac @t{\name\} \arg\
+@maindex \name\
+@defmac @t{.\name\} \arg\
+@end macro
+
+@macro Defmacx{name, arg}
+@maindex \name\
+@defmacx @t{.\name\} \arg\
@end macro
-@macro end_Defmac
+@macro endDefmac
@end defmac
@end macro
-@macro Defmacx{name, arg}
-@defmacx @t{\name\} \arg\
+
+@c definition of strings
+
+@macro Defstr{name, arg}
+@stindex \name\
+@deffn String @t{\name\} \arg\
@end macro
-@macro end_Defmacx
-@end defmacx
+@macro Defstrx{name, arg}
+@stindex \name\
+@deffnx String @t{\name\} \arg\
@end macro
+@macro endDefstr
+@end deffn
+@end macro
+
+
+@c our example macro
+
+@macro Example
+@example
+@group
+@end macro
+
+@macro endExample
+@end group
+@end example
+@end macro
+
+
+@c We need special parentheses and brackets:
+@c
+@c . Real parentheses in @deffn produce an error while compiling with
+@c TeX
+@c . Real brackets use the wrong font in @deffn, overriding @t{}.
+@c
+@c This is true for texinfo 4.0.
+
+@ifnottex
+@macro lparen
+(
+@end macro
+@macro rparen
+)
+@end macro
+@macro lbrack
+[
+@end macro
+@macro rbrack
+]
+@end macro
+@end ifnottex
+
+@iftex
+@macro lparen
+@@lparen
+@end macro
+@macro rparen
+@@rparen
+@end macro
+@macro lbrack
+@@lbrack
+@end macro
+@macro rbrack
+@@rbrack
+@end macro
+@end iftex
+
+
+@c Note: We say `Roman numerals' but `roman font'.
+
@c XXX comment all examples
@@ -186,24 +312,26 @@ contributions are welcome. Send them to bug-groff@@gnu.org.
@end ifinfo
@menu
-* Copying::
-* Introduction::
-* Invoking groff::
-* Tutorial for Macro Users::
-* Macro Packages::
-* Programming Tutorial::
-* Preprocessors::
-* Output Devices::
-* File formats::
-* Installation::
-* Request and Escape Index::
-* Operator Index::
-* Register Index::
-* Macro and String Index::
-* Glyph Name Index::
-* Font File Keyword Index::
-* Program and File Index::
-* Concept Index::
+* Copying::
+* Introduction::
+* Invoking groff::
+* Tutorial for Macro Users::
+* Macro Packages::
+* gtroff Reference::
+* Preprocessors::
+* Output Devices::
+* File formats::
+* Installation::
+* Request Index::
+* Escape Index::
+* Operator Index::
+* Register Index::
+* Macro Index::
+* String Index::
+* Glyph Name Index::
+* Font File Keyword Index::
+* Program and File Index::
+* Concept Index::
@end menu
@@ -617,13 +745,13 @@ use) for about 3@w{ }decades. It is quite widespread and firmly
entrenched in the @acronym{UNIX} community.
@menu
-* What Is groff?::
-* History::
-* groff Capabilities::
-* Macro Package Intro::
-* Preprocessor Intro::
-* Output device intro::
-* Credits::
+* What Is groff?::
+* History::
+* groff Capabilities::
+* Macro Package Intro::
+* Preprocessor Intro::
+* Output device intro::
+* Credits::
@end menu
@@ -644,17 +772,16 @@ 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
+processor}, since that term connotes an integrated system that includes
an editor and a text formatter. Also, many word processors follow the
-@acronym{WYSIWYG} paradigm which was discussed earlier.
+@acronym{WYSIWYG} paradigm discussed earlier.
Although @acronym{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 graphics display to do any operations on a
-document.
+They must be used on a graphics display to work on a document.
@item
Most of the @acronym{WYSIWYG} systems are either non-free or are not
@@ -691,26 +818,26 @@ impossible to accomplish complex actions.'' --Doug Gwyn (22/Jun/91 in
operating system in the mid-sixties. This name came from the common
phrase of the time ``I'll run off a document.'' Bob Morris ported it to
the 635 architecture and called the program @code{roff} (an abbreviation
-of @code{runoff}). It has then been rewritten as @code{rf} for the
-PDP-7 (before having @acronym{UNIX}), and at the same time (1969), Doug
+of @code{runoff}). It was rewritten as @code{rf} for the @w{PDP-7}
+(before having @acronym{UNIX}), and at the same time (1969), Doug
McIllroy rewrote an extended and simplified version of @code{roff} in
the @acronym{BCPL} programming language.
@cindex @code{roff}
-The first version of @acronym{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 McIllroy's @code{roff}, written by
-J.@w{ }F.@w{ }Ossanna.
+The first version of @acronym{UNIX} was developed on a @w{PDP-7} which
+was sitting around Bell Labs. In 1971 the developers wanted to get a
+@w{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 McIllroy's
+@code{roff}, written by J.@w{ }F.@w{ }Ossanna.
@cindex @code{nroff}
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, Ossanna wrote a
-version of @code{nroff} which would drive it. It was dubbed
+version of @code{nroff} that 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 the
use of the Times font family in @code{troff} by default. As such, the
@@ -733,7 +860,7 @@ 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
+Unfortunately, Ossanna's @code{troff} was written in @w{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
@@ -769,8 +896,8 @@ A replacement for @code{ditroff} with many extensions.
The @code{soelim}, @code{pic}, @code{tbl}, and @code{eqn} preprocessors.
@item
-Postprocessors for character devices, @acronym{PostScript}, @TeX{} DVI,
-and X@w{ }windows. GNU @code{troff} also eliminated the need for a
+Postprocessors for character devices, @sc{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
@acronym{ASCII} output.
@@ -792,8 +919,8 @@ version@w{ }1.04 around November@w{ }1991.
Beginning in@w{ }1999, @code{groff} has new maintainers (the package was
an orphan for a few years). As a result, new features and programs like
-@code{grn}, a preprocessor for gremlin images, and @code{grohtml}, an
-output device to produce @acronym{HTML} output, have been added.
+@code{grn}, a preprocessor for gremlin images, and an output device to
+produce @acronym{HTML} output have been added.
@c =====================================================================
@@ -929,11 +1056,11 @@ mathematical pictures (@code{ideal}) and chemical structures
@cindex output devices
@cindex devices for output
-@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 @acronym{PostScript}
-devices, character terminals, X@w{ }Windows (for previewing), @TeX{} DVI
-format, HP LaserJet@w{ }4 and Canon LBP printers (which use
+@code{groff} actually produces device independent code which may be
+fed into a postprocessor to produce output for a particular device.
+Currently, @code{groff} has postprocessors for @sc{PostScript}
+devices, character terminals, X@w{ }Windows (for previewing), @TeX{}
+DVI format, HP LaserJet@w{ }4 and Canon LBP printers (which use
@acronym{CAPSL}), and @acronym{HTML}.
@@ -953,6 +1080,7 @@ GNU/Linux system.
+
@c =====================================================================
@c =====================================================================
@@ -975,9 +1103,9 @@ prefix is omitted since GNU @code{troff} is the only used incarnation of
@code{troff}. Exception: @code{groff} is never replaced by @code{roff}.
@menu
-* Groff Options::
-* Environment::
-* Invocation Examples::
+* Groff Options::
+* Environment::
+* Invocation Examples::
@end menu
@@ -1013,26 +1141,26 @@ grolbp}, and @ref{Invoking gxditview}.
The command line format for @code{groff} is:
-@example
+@Example
groff [ -abeghilpstvzCEGNRSUVXZ ] [ -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} ] [ -I@var{dir} ]
[ @var{files}@dots{} ]
-@end example
+@endExample
The command line format for @code{gtroff} is as follows.
-@example
+@Example
gtroff [ -abivzCERU ] [ -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
+@endExample
@noindent
-Obviously, many of the options to @code{groff} are actually passed
-on to @code{gtroff}.
+Obviously, many of the options to @code{groff} are actually passed on to
+@code{gtroff}.
Options without an argument can be grouped behind a single @option{-}.
A filename of @file{-} denotes the standard input. It is possible to
@@ -1082,15 +1210,14 @@ accessible via @code{groff}. This option prevents the loading of the
Make programs run by @code{groff} print out their version number.
@item -V
-Print the pipeline on stdout instead of executing it.
+Print the pipeline on @code{stdout} instead of executing it.
@item -z
-Suppress output from @code{gtroff}. Only error messages will be
-printed.
+Suppress output from @code{gtroff}. Only error messages are printed.
@item -Z
Do not postprocess the output of @code{gtroff}. Normally @code{groff}
-will automatically run the appropriate postprocessor.
+automatically runs the appropriate postprocessor.
@item -P@var{arg}
Pass @var{arg} to the postprocessor. Each argument should be passed
@@ -1098,13 +1225,17 @@ with a separate @option{-P} option. Note that @code{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.
+Send the output to a spooler for printing. The command used for this is
+specified by the @code{print} command in the device description file
+(see @ref{Font Files}, for more info). If not present, @option{-l} is
+ignored.
@item -L@var{arg}
Pass @var{arg} to the spooler. Each argument should be passed with a
separate @option{-L} option. Note that @code{groff} does not prepend a
-@samp{-} to @var{arg} before passing it to the postprocessor.
+@samp{-} to @var{arg} before passing it to the postprocessor. If the
+@code{print} keyword in the device description file is missing,
+@option{-L} is ignored.
@item -T@var{dev}
Prepare output for device @var{dev}. The default device is @samp{ps},
@@ -1113,7 +1244,7 @@ following are the output devices currently available:
@table @code
@item ps
-For @acronym{PostScript} printers and previewers.
+For @sc{PostScript} printers and previewers.
@item dvi
For @TeX{} DVI format.
@@ -1128,8 +1259,8 @@ For a 100@dmn{dpi} X11 previewer.
For typewriter-like devices.
@item latin1
-For typewriter-like devices that support the @w{Latin-1} (@w{ISO 8859-1})
-character set.
+For typewriter-like devices that support the @w{Latin-1} (@w{ISO
+8859-1}) character set.
@item utf8
For typewriter-like devices which use the Unicode (@w{ISO 10646})
@@ -1149,12 +1280,17 @@ For an HP LaserJet4-compatible (or other PCL5-compatible) printer.
For Canon @acronym{CAPSL} printers (@w{LBP-4} and @w{LBP-8} series laser
printers).
+@pindex pre-grohtml
+@pindex post-grohtml
+@cindex @code{grohtml}
@item html
-To produce @acronym{HTML} output.
+To produce @acronym{HTML} output. Note that the @acronym{HTML} driver
+consists of two parts, a preprocessor (@code{pre-grohtml}) and a
+postprocessor (@code{post-grohtml}).
@end table
@vindex .T
-@maindex \*(.T
+@stindex .T
The predefined @code{gtroff} string register @code{.T} contains the
current output device; the read-only number register @code{.T} is set
to@w{ }1 if this option is used (which is always true if @code{groff} is
@@ -1171,16 +1307,17 @@ This is unlikely to produce good results except with @option{-Tps}.
Note that this is not the same as using @option{-TX75} or
@option{-TX100} to view a document with @code{gxditview}: The former
-will use the metrics of the specified device, whereas the latter will
-use X-specific fonts and metrics.
+uses the metrics of the specified device, whereas the latter uses
+X-specific fonts and metrics.
@item -N
Don't allow newlines with @code{eqn} delimiters. This is the same as
the @option{-N} option in @code{geqn}.
@item -S
-Safer mode. Pass the @option{-S} option to @code{gpic} and use the
-@option{-msafer} macros with @code{gtroff} (enabled by default).
+Safer mode. Pass the @option{-S} option to @code{gpic} and disable the
+@code{open}, @code{opena}, @code{pso}, @code{sy}, and @code{pi}
+requests. For security reasons, this is enabled by default.
@item -U
Unsafe mode. Reverts to the old unsafe behaviour.
@@ -1189,7 +1326,16 @@ Unsafe mode. Reverts to the old unsafe behaviour.
@vindex .A
Generate an @acronym{ASCII} approximation of the typeset output. The
read-only register @code{.A} is then set to@w{ }1. @xref{Built-in
-Registers}.
+Registers}. A typical example is
+
+@Example
+groff -a -man -Tdvi troff.man | less
+@endExample
+
+@noindent
+which shows how lines are broken for the DVI device. Note that this
+option is rather useless today since graphic output devices are
+available virtually everywhere.
@item -b
Print a backtrace with each warning or error message. This backtrace
@@ -1213,20 +1359,25 @@ Inhibit all error messages.
@item -C
Enable compatibility mode. @xref{Implementation Differences}, for the
-list of incompatibilites between @code{groff} and traditional Unix
+list of incompatibilities between @code{groff} and traditional Unix
@code{troff}.
@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 name; @var{name} can be of arbitrary length.
+one-letter name; @var{name} can be of arbitrary length. All string
+assignments happen before loading any macro file (including the start-up
+file).
@item -f@var{fam}
-Use @var{fam} as the default font family.
+Use @var{fam} as the default font family. @xref{Font Families}.
@item -m@var{name}
-Read in the file @file{tmac.@var{name}}. Normally this will be searched
-for in the library directory of @code{groff}.
+Read in the file @file{@var{name}.tmac}. Normally @code{groff} searches
+for this in its macro directories. If it isn't found, it tries
+@file{tmac.@var{name}} (and searches in the same directories).
+
+@c XXX document local and system macro dirs
@item -n@var{num}
Number the first page @var{num}.
@@ -1237,26 +1388,32 @@ Output only pages in @var{list}, which is a comma-separated list of page
ranges; @samp{@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 beginning with @var{n}. @code{gtroff} will exit after printing the
+page beginning with @var{n}. @code{gtroff} exits after printing the
last page in the list. All the ranges are inclusive on both ends.
Within @code{gtroff}, this information can be extracted with the
@samp{.P} register. @xref{Built-in Registers}.
+If your document restarts page numbering at the beginning of each
+chapter, then @code{gtroff} prints the specified page range for each
+chapter.
+
@item -r@var{cn}
@itemx -r@var{name}=@var{n}
Set number register @var{c} or @var{name} to the value @var{n}. @var{c}
must be a one-letter name; @var{name} can be of arbitrary length.
-@var{n} can be any @code{gtroff} numeric expression.
+@var{n} can be any @code{gtroff} numeric expression. All register
+assignments happen before loading any macro file (including the start-up
+file).
@item -F@var{dir}
Search @file{@var{dir}} for subdirectories @file{dev@var{name}}
(@var{name} is the name of the device), for the @file{DESC} file, and
-for font files before looking in the standard directory.
+for font files before looking in the standard directories.
@item -M@var{dir}
Search directory @file{@var{dir}} for macro files before the standard
-directory.
+directories.
@item -I@var{dir}
This option is as described in @ref{gsoelim}. It implies the
@@ -1277,16 +1434,20 @@ not within @code{gtroff}) which can modify the behavior of @code{groff}.
@table @code
@item GROFF_COMMAND_PREFIX
@tindex GROFF_COMMAND_PREFIX, environment variable
-If this is set to @var{X}, then @code{groff} will run
-@code{@var{X}troff} instead of @code{gtroff}. This also applies to
-@code{tbl}, @code{pic}, @code{eqn}, @code{grn}, @code{refer}, and
-@code{soelim}. It does not apply to @code{grops}, @code{grodvi},
-@code{grotty}, @code{grohtml}, @code{grolj4}, and @code{gxditview}.
+If this is set to @var{X}, then @code{groff} runs @code{@var{X}troff}
+instead of @code{gtroff}. This also applies to @code{tbl}, @code{pic},
+@code{eqn}, @code{grn}, @code{refer}, and @code{soelim}. It does not
+apply to @code{grops}, @code{grodvi}, @code{grotty}, @code{pre-grohtml},
+@code{post-grohtml}, @code{grolj4}, and @code{gxditview}.
+
+@c XXX document default values
@item GROFF_TMAC_PATH
@tindex GROFF_TMAC_PATH, environment variable
-A colon-separated list of directories in which to search for macro
-files.
+A colon-separated list of directories in which to search for macro files
+(before the default directories are tried).
+
+@c XXX document local and system macro dirs
@item GROFF_TYPESETTER
@tindex GROFF_TYPESETTER, environment variable
@@ -1295,21 +1456,23 @@ The default output device.
@item GROFF_FONT_PATH
@tindex GROFF_FONT_PATH, environment variable
A colon-separated list of directories in which to search for the
-@code{dev}@var{name} directory.
+@code{dev}@var{name} directory (before the default directories are
+tried).
-@item PATH
-@tindex PATH, environment variable
-The search path for commands executed by @code{groff}.
+@item GROFF_BIN_PATH
+@tindex GROFF_BIN_PATH, environment variable
+This search path, followed by @code{PATH}, is used for commands executed
+by @code{groff}.
@item GROFF_TMPDIR
@tindex GROFF_TMPDIR, environment variable
@tindex TMPDIR, environment variable
-The directory in which temporary files will be created. If this is not
-set and @env{TMPDIR} is set, temporary files will be created in that
-directory. Otherwise temporary files will be created in a
-system-dependent default directory (on Unix and GNU/Linux systems, this
-is usually @file{/tmp}). The @code{grops} and @code{grefer} commands
-can create temporary files in this directory.
+The directory in which @code{groff} creates temporary files. If this is
+not set and @env{TMPDIR} is set, temporary files are created in that
+directory. Otherwise temporary files are created in a system-dependent
+default directory (on Unix and GNU/Linux systems, this is usually
+@file{/tmp}). @code{grops}, @code{grefer}, @code{pre-grohtml}, and
+@code{post-grohtml} can create temporary files in this directory.
@end table
Note that MS-DOS and MS-Windows ports of @code{groff} use semi-colons,
@@ -1324,33 +1487,33 @@ above.
@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.
+This section lists several common uses of @code{groff} and the
+corresponding command lines.
-@example
+@Example
groff file
-@end example
+@endExample
@noindent
This command processes @file{file} without a macro package or a
preprocessor. The output device is the default, @samp{ps}, and the
-output is sent to stdout.
+output is sent to @code{stdout}.
-@example
+@Example
groff -t -mandoc -Tascii file | less
-@end example
+@endExample
@noindent
-This is basically what a call to the @code{man} program does. The
-manual page @file{file} is processed with the @file{mandoc} macros
-(which in turn either calls the @file{man} or the @file{mdoc} macro
-package), using the @code{tbl} preprocessor and the @acronym{ASCII}
-output device. Finally, the result is displayed with the @code{less}
-pager.
-
-@example
+This is basically what a call to the @code{man} program does.
+@code{gtroff} processes the manual page @file{file} with the
+@file{mandoc} macro file (which in turn either calls the @file{man} or
+the @file{mdoc} macro package), using the @code{tbl} preprocessor and
+the @acronym{ASCII} output device. Finally, the @code{less} pager
+displays the result.
+
+@Example
groff -X -m me file
-@end example
+@endExample
@noindent
Preview @file{file} with @code{gxditview}, using the @file{me} macro
@@ -1360,52 +1523,57 @@ device (@samp{ps}). Note that you can either say @w{@samp{-m me}} or
@acronym{UNIX}.@footnote{The same is true for the other main macro
packages that come with @code{groff}: @file{man}, @file{mdoc},
@file{ms}, @file{mm}, and @file{mandoc}. This won't work in general;
-for example, to load @file{tmac.safer}, either @samp{-msafer} or
-@w{@samp{-m safer}} must be used.}
+for example, to load @file{trace.tmac}, either @samp{-mtrace} or
+@w{@samp{-m trace}} must be used.}
-@example
+@Example
groff -man -rD1 -z file
-@end example
+@endExample
@noindent
Check @file{file} with the @file{man} macro package, forcing
double-sided printing -- don't produce any output.
-@c ---------------------------------------------------------------------
-
@menu
-* grog::
+* grog::
@end menu
+@c ---------------------------------------------------------------------
+
@node grog, , Invocation Examples, Invocation Examples
@subsection @code{grog}
@pindex grog
@code{grog} reads files, guesses which of the @code{groff} preprocessors
and/or macro packages are required for formatting them, and prints the
-@code{groff} command including those options on the standard output.
-The options generated are one of @option{-e}, @option{-man},
-@option{-me}, @option{-mm}, @option{-ms}, @option{-p}, @option{-R},
-@option{-g}, @option{-G}, @option{-s}, and @option{-t}.
+@code{groff} command including those options on the standard output. It
+generates one or more of the options @option{-e}, @option{-man},
+@option{-me}, @option{-mm}, @option{-ms}, @option{-mdoc},
+@option{-mdoc-old}, @option{-p}, @option{-R}, @option{-g}, @option{-G},
+@option{-s}, and @option{-t}.
+
+A special file name @file{-} refers to the standard input. Specifying
+no files also means to read the standard input. Any specified options
+are included in the printed command. No space is allowed between
+options and their arguments. The only options recognized are
+@option{-C} (which is also passed on) to enable compatibility mode, and
+@option{-v} (if it is the only parameter) to print the version number.
-A special file name @file{-} 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,
+For example,
-@example
+@Example
grog -Tdvi paper.ms
-@end example
+@endExample
@noindent
-will guess the appropriate command to print @file{paper.ms} and then
-print it to the command line after adding the @option{-Tdvi} option.
-For direct execution, enclose the call to @code{grog} in backquotes at
-the @acronym{UNIX} shell prompt:
+guesses the appropriate command to print @file{paper.ms} and then prints
+it to the command line after adding the @option{-Tdvi} option. For
+direct execution, enclose the call to @code{grog} in backquotes at the
+@acronym{UNIX} shell prompt:
-@example
+@Example
`grog -Tdvi paper.ms` > paper.dvi
-@end example
+@endExample
@noindent
As seen in the example, it is still necessary to redirect the output to
@@ -1430,8 +1598,8 @@ people. This chapter covers the material needed to efficiently use a
macro package.
@menu
-* Basics::
-* Common Features::
+* Basics::
+* Common Features::
@end menu
@@ -1458,39 +1626,39 @@ The word @dfn{argument} is used in this chapter to mean a word or number
which appears on the same line as a request, and which modifies the
meaning of that request. For example, the request
-@example
+@Example
.sp
-@end example
+@endExample
@noindent
spaces one line, but
-@example
+@Example
.sp 4
-@end example
+@endExample
@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}.
+separated from the request and from each other by spaces (@emph{no}
+tabs). More details on this can be found in @ref{Request Arguments}.
The primary function of @code{gtroff} 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
+@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
+@endExample
@noindent
-will be read, packed onto output lines, and justified to produce:
+is 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.
@@ -1502,63 +1670,78 @@ Four score and seven years ago,...
Sometimes a new output line should be started even though the current
line is not yet full; for example, at the end of a paragraph. To do
this it is possible to 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.
+line. Some requests cause a break automatically, as normally 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 (@samp{.}) or an apostrophe (@samp{'}) as the first
-character of the input line.
+Not all input lines are text to be formatted. Some input lines are
+requests which describe how to format the text. Requests always have a
+period (@samp{.}) 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 are a few hints for preparing text for input to @code{gtroff}.
+
+@itemize @bullet
+@item
First, keep the input lines short. Short input lines are easier to
-edit, and @code{gtroff} will pack words onto longer lines 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{gtroff} is smart enough to hyphenate words for the user
-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 a space can occur where not wanted, such
-as ``@w{mother- in}-law''.
-
-@findex ls
+edit, and @code{gtroff} packs words onto longer lines anyhow.
+
+@item
+In keeping with this, it is helpful to begin a new line after every
+comma or phrase, since common corrections are to add or delete sentences
+or phrases.
+
+@item
+End each sentence with two spaces -- or better, start each sentence on a
+new line. @code{gtroff} recognizes characters that usually end a
+sentence, and inserts sentence space accordingly.
+
+@item
+Do not hyphenate words at the end of lines -- @code{gtroff} is smart
+enough to hyphenate words 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 a space
+can occur where not wanted, such as ``@w{mother- in}-law''.
+@end itemize
+
+@rqindex ls
@cindex double spacing
@cindex spacing
-@code{gtroff} will double space output text automatically if you use the
-request @w{@samp{.ls 2}}. Single spaced mode can be reactivated by
-typing @w{@samp{.ls 1}}.
+@code{gtroff} double spaces output text automatically if you use the
+request @w{@samp{.ls 2}}. Reactivate single spaced mode by typing
+@w{@samp{.ls 1}}.
-A number of requests allow to change the way the output 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).
+A number of requests allow to change the way the output 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).
@cindex new page
The @samp{.bp} request starts a new page, causing a line break.
-@cindex blank lines
-@cindex empty lines
-@cindex lines, empty
+@cindex blank line
+@cindex empty line
+@cindex line, empty
The request @w{@samp{.sp @var{N}}} leaves @var{N}@w{ }lines of blank
space. @var{N}@w{ }can be omitted (meaning skip a single line) or can
be of the form @var{N}i (for @var{N}@w{ }inches) or @var{N}c (for
@var{N}@w{ }centimeters). For example, the input:
-@example
+@Example
.sp 1.5i
My thoughts on the subject
.sp
-@end example
+@endExample
@noindent
leaves one and a half inches of space, followed by the line ``My
-thoughts on the subject'', followed by a single blank line.
+thoughts on the subject'', followed by a single blank line (more
+measurement units are available, see @ref{Measurements}).
-@findex ce
+@rqindex ce
@cindex centering lines
@cindex lines, centering
Text lines can be centered by using the @code{ce} request. The line
@@ -1567,17 +1750,17 @@ than one line, use @w{@samp{.ce @var{N}}} (where @var{N} is the number
of lines to center), followed by the @var{N}@w{ }lines. To center many
lines without counting them, type:
-@example
+@Example
.ce 1000
lines to center
.ce 0
-@end example
+@endExample
@noindent
The @w{@samp{.ce 0}} request tells @code{groff} to center zero more
lines, in other words, stop centering.
-@findex br
+@rqindex br
@cindex line break
@cindex break
All of these requests cause a break; that is, they always start a new
@@ -1592,7 +1775,7 @@ line. To start a new line without performing any other action, use
@cindex common features
@cindex features, common
-@code{gtroff} provides very low level operations for formatting a
+@code{gtroff} 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}.
@@ -1600,55 +1783,59 @@ and collected into a @dfn{macro package}.
All macro packages provide certain common capabilities which fall into
the following categories.
-@c ---------------------------------------------------------------------
-
@menu
-* Paragraphs::
-* Sections and Chapters::
-* Headers and Footers::
-* Page Layout Adjustment::
-* Displays::
-* Footnotes and Annotations::
-* Table of Contents::
-* Indices::
-* Paper Formats::
-* Multiple Columns::
-* Font and Size Changes::
-* Predefined Strings::
-* Preprocessor Support::
-* Configuration and Customization::
+* Paragraphs::
+* Sections and Chapters::
+* Headers and Footers::
+* Page Layout Adjustment::
+* Displays::
+* Footnotes and Annotations::
+* Table of Contents::
+* Indices::
+* Paper Formats::
+* Multiple Columns::
+* Font and Size Changes::
+* Predefined Strings::
+* Preprocessor Support::
+* Configuration and Customization::
@end menu
+@c ---------------------------------------------------------------------
+
@node Paragraphs, Sections and Chapters, Common Features, Common Features
@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:
+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
+@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
+@endExample
@noindent
And there are also indented paragraphs which begin with a tag or label
at the margin and the remaining text indented.
@example
+@group
one This is the first paragraph. Notice how the first
line of the resulting paragraph lines up with the
other lines in the paragraph.
+@end group
+@group
longlabel
This paragraph had a long label. The first
- character of text on the first line will not line up
+ character of text on the first line does not line up
with the text on second and subsequent lines,
- although they will line up with each other.
+ although they line up with each other.
+@end group
@end example
A variation of this is a bulleted list.
@@ -1671,10 +1858,9 @@ supply macros for starting chapters and appendices.
@node Headers and Footers, Page Layout Adjustment, Sections and Chapters, Common Features
@subsection Headers and Footers
-Every macro package gives some way to manipulate the headers and
-footers (or @dfn{titles}) on each page. Some packages will allow for
-different ones on the even and odd pages (for material printed in a book
-form).
+Every macro package gives some way to manipulate the headers and footers
+(or @dfn{titles}) on each page. Some packages allow for 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
@@ -1713,17 +1899,16 @@ used in this paper.
@cindex keep
A @dfn{keep} is a display of lines which are kept on a single page if
possible. An example for a keep might be a diagram. Keeps differ from
-lists in that lists may be broken over a page boundary whereas keeps
-will not.
+lists in that lists may be broken over a page boundary whereas keeps are
+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@w{ }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.
+things which are referred to by name, such as ``See figure@w{ }3''. A
+floating keep appears at the bottom of the current page if it fits;
+otherwise, it appears at the top of the next page. Meanwhile, the
+surrounding text `flows' around the keep, thus leaving no blank areas.
@c ---------------------------------------------------------------------
@@ -1755,9 +1940,9 @@ of automatically numbering either type of annotation.
@dfn{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 throughout the paper until printed, usually after
-the paper has ended. Many macro packages will provide the ability to
-have several tables of contents (i.e.@: one standard one, one for
-tables, etc).
+the paper has ended. Many macro packages provide the ability to have
+several tables of contents (e.g.@: a standard table of contents, a list
+of tables, etc).
@c ---------------------------------------------------------------------
@@ -1765,7 +1950,7 @@ tables, etc).
@subsection Indices
@cindex index, in macro package
-While some macro packages will use the term @dfn{index}, none actually
+While some macro packages use the term @dfn{index}, none actually
provide that functionality. The facilities they call indices are
actually more appropriate for tables of contents.
@@ -1810,23 +1995,30 @@ various special characters.
@node Preprocessor Support, Configuration and Customization, Predefined Strings, Common Features
@subsection Preprocessor Support
-All macro packages provide support for the various preprocessors.
+All macro packages provide support for the various preprocessors and may
+extend their functionality.
+
+For example, all macro packages mark tables (which are processed with
+@code{gtbl}) by placing them between @code{.TS} and @code{.TE} macros.
+The @file{ms} macro package has an option, @code{.TS@w{}H}, that prints
+a caption at the top of a new page (when the table is too long to fit on
+a single page).
@c ---------------------------------------------------------------------
@node Configuration and Customization, , Preprocessor Support, Common Features
@subsection Configuration and Customization
-Some macro packages provide means of customizing many of the details of how
-the package behaves. This ranges from setting the default type size to
-changing the appearance of section headers.
+Some macro packages provide means of customizing many of the details of
+how the package behaves. This ranges from setting the default type size
+to changing the appearance of section headers.
@c =====================================================================
@c =====================================================================
-@node Macro Packages, Programming Tutorial, Tutorial for Macro Users, Top
+@node Macro Packages, gtroff Reference, Tutorial for Macro Users, Top
@chapter Macro Packages
@cindex macro packages
@cindex packages, macros
@@ -1835,11 +2027,11 @@ This chapter documents the main macro packages that come with
@code{groff}.
@menu
-* man::
-* mdoc::
-* ms::
-* me::
-* mm::
+* man::
+* mdoc::
+* ms::
+* me::
+* mm::
@end menu
@@ -1849,18 +2041,21 @@ This chapter documents the main macro packages that come with
@section @file{man}
@cindex @file{man}
@cindex manual pages
-@pindex tmac.an
-@pindex tmac.man
+@pindex an.tmac
+@pindex man.tmac
+@pindex man-old.tmac
This is the most popular and probably the most important macro package
of @code{groff}. It is easy to use, and a vast majority of manual pages
are based on it.
@menu
-* Man options::
-* Man usage::
-* Man font macros::
-* Miscellaneous man stuff::
+* Man options::
+* Man usage::
+* Man font macros::
+* Miscellaneous man macros::
+* Predefined man strings::
+* Preprocessors in man pages::
@end menu
@c ---------------------------------------------------------------------
@@ -1871,16 +2066,20 @@ are based on it.
The command line format for using the @file{man} macros with
@code{groff} is:
-@c XXX document @TMAC_AN_PREFIX@
-
-@example
-groff -m man [ -rC1 ] [ -rD1 ] [ -rP@var{nnn} ] [ -rS@var{xx} ]
- [ -rX@var{nnn} ] [ @var{files}@dots{} ]
-@end example
+@Example
+groff -m man [ -rcR=1 ] [ -rC1 ] [ -rD1 ] [ -rP@var{nnn} ]
+ [ -rS@var{xx} ] [ -rX@var{nnn} ] [ @var{files}@dots{} ]
+@endExample
+@noindent
It is possible to use @samp{-man} instead of @w{@samp{-m man}}.
@table @code
+@item -rcR=1
+This option (the default if a tty output device is used) creates a
+single, very long page instead of multiple pages. Use @code{-rcR=0}
+to disable it.
+
@item -rC1
If more than one manual page is given on the command line, number the
pages continuously, rather than starting each at@w{ }1.
@@ -1890,7 +2089,7 @@ Double-sided printing. Footers for even and odd pages are formatted
differently.
@item -rP@var{nnn}
-Enumeration of pages will start with @var{nnn} rather than with@w{ }1.
+Page numbering starts with @var{nnn} rather than with@w{ }1.
@item -rS@var{xx}
Use @var{xx} (which can be 10, 11, or@w{ }12@dmn{pt}) as the base
@@ -1898,7 +2097,7 @@ document font size instead of the default value of@w{ }10@dmn{pt}.
@item -rX@var{nnn}
After page @var{nnn}, number pages as @var{nnn}a, @var{nnn}b,
-@var{nnn}c, etc. For example, the option @option{-rX2} will produce the
+@var{nnn}c, etc. For example, the option @option{-rX2} produces the
following page numbers: 1, 2, 2a, 2b, 2c, etc.
@end table
@@ -1912,22 +2111,22 @@ following page numbers: 1, 2, 2a, 2b, 2c, etc.
@pindex man.local
This section describes the available macros for manual pages. For
further customization, put additional macros and requests into the file
-@file{man.local} which will be loaded immediately after @file{tmac.an}.
+@file{man.local} which is loaded immediately after the @file{man}
+package.
-@maindex TH
-@Defmac{TH, title section [@var{extra1}] [@var{extra2}] [@var{extra3}]}
-Sets the title of the man page to @var{title} and the section to
+@Defmac {TH, title section [@Var{extra1}] [@Var{extra2}] [@Var{extra3}]}
+Set the title of the man page to @var{title} and the section to
@var{section}, which must have a value between 1 and@w{ }8. The value
-of @var{section} may also have a string appended, e.g.@: @samp{.pm}, to
-indicate a specific subsection of the man pages.
+of @var{section} may also have a string appended, e.g.@: @samp{.pm},
+to indicate a specific subsection of the man pages.
Both @var{title} and @var{section} are positioned at the left and right
in the header line (with @var{section} in parentheses immediately
-appended to @var{title}. @var{extra1} will be positioned in the middle
-of the footer line. @var{extra2} will be positioned at the left in the
-footer line (resp.@: at the left on even pages and at the right on odd
-pages if double-sided printing is active). @var{extra3} is centered in
-the header line.
+appended to @var{title}. @var{extra1} is positioned in the middle of
+the footer line. @var{extra2} is positioned at the left in the footer
+line (or at the left on even pages and at the right on odd pages if
+double-sided printing is active). @var{extra3} is centered in the
+header line.
For @acronym{HTML} output, headers and footers are completely suppressed.
@@ -1936,100 +2135,91 @@ again (except if the @option{-rC1} option is given on the command line)
-- this feature is intended only for formatting multiple man pages; a
single man page should contain exactly one @code{TH} macro at the
beginning of the file.
-@end_Defmac
+@endDefmac
-@maindex SH
-@Defmac{SH, [@var{heading}]}
-Sets up an unnumbered section heading sticking out to the left. Prints
-out all the text following @code{SH} up to the end of the line (resp.@:
-the text in the next line if there is no argument to @code{SH}) in bold
+@Defmac {SH, [@Var{heading}]}
+Set up an unnumbered section heading sticking out to the left. Prints
+out all the text following @code{SH} up to the end of the line (or the
+text in the next line if there is no argument to @code{SH}) in bold
face, one size larger than the base document size. Additionally, the
left margin for the following text is reset to its default value.
-@end_Defmac
+@endDefmac
-@maindex SS
-@Defmac{SS, [@var{heading}]}
-Sets up an unnumbered section heading. Prints out all the text
-following @code{SS} up to the end of the line (resp.@: the text in the
-next line if there is no argument to @code{SS}) in bold face, at the
-same size as the base document size. Additionally, the left margin for
-the following text is reset to its default value.
-@end_Defmac
+@Defmac {SS, [@Var{heading}]}
+Set up an unnumbered (sub)section heading. Prints out all the text
+following @code{SS} up to the end of the line (or the text in the next
+line if there is no argument to @code{SS}) in bold face, at the same
+size as the base document size. Additionally, the left margin for the
+following text is reset to its default value.
+@endDefmac
-@maindex TP
-@Defmac{TP, [@var{nnn}]}
-Sets up an indented paragraph with label. The indentation is set to
-@var{nnn} if that argument is supplied (the default unit is @samp{n} if
-omitted), otherwise it is set to the default indentation value.
+@Defmac {TP, [@Var{nnn}]}
+Set up an indented paragraph with label. The indentation is set to
+@var{nnn} if that argument is supplied (the default unit is @samp{n}
+if omitted), otherwise it is set to the default indentation value.
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.
-Note that neither font shape nor font size of the label is set to a
-default value; on the other hand, the rest of the text will have default
-font settings.
-@end_Defmac
-
-@maindex LP
-@maindex PP
-@maindex P
-@Defmac{LP}
-@Defmacx{PP}
-@Defmacx{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
-specified by the @code{PD} macro. The font size and shape are reset to
-the default value (10@dmn{pt} resp.@: Roman). Finally, the current left
-margin is restored.
-@end_Defmac
-
-@maindex IP
-@Defmac{IP, [@var{designator}] [@var{nnn}]}
-Sets up an indented paragraph, using @var{designator} as a tag to mark
-its beginning. The indentation is set to @var{nnn} if that argument is
-supplied (default unit is @samp{n}), otherwise the default indentation
-value is used. Font size and face of the paragraph (but not the
-designator) are reset to their default values. To start an indented
-paragraph with a particular indentation but without a designator, use
-@samp{""} (two double quotes) as the first argument of @code{IP}.
+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. Note that neither font shape nor font size of the label is
+set to a default value; on the other hand, the rest of the text has
+default font settings.
+@endDefmac
+
+@Defmac {LP}
+@Defmacx {PP}
+@Defmacx {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 specified by the @code{PD} macro. The font size and shape are
+reset to the default value (10@dmn{pt} roman). Finally, the current
+left margin is restored.
+@endDefmac
+
+@Defmac {IP, [@Var{designator}] [@Var{nnn}]}
+Set up an indented paragraph, using @var{designator} as a tag to mark
+its beginning. The indentation is set to @var{nnn} if that argument
+is supplied (default unit is @samp{n}), otherwise the default
+indentation value is used. Font size and face of the paragraph (but
+not the designator) are reset to their default values. To start an
+indented paragraph with a particular indentation but without a
+designator, use @samp{""} (two double quotes) as the first argument of
+@code{IP}.
For example, to start a paragraph with bullets as the designator and
4@dmn{en} indentation, write
-@example
+@Example
.IP \(bu 4
-@end example
-@end_Defmac
+@endExample
+@endDefmac
-@maindex HP
@cindex hanging indentation, in manual pages
-@Defmac{HP, [@var{nnn}]}
-Sets up a paragraph with hanging left indentation. The indentation is
+@Defmac {HP, [@Var{nnn}]}
+Set up a paragraph with hanging left indentation. The indentation is
set to @var{nnn} if that argument is supplied (default unit is
@samp{n}), otherwise the default indentation value is used. Font size
and face are reset to their default values.
-@end_Defmac
+@endDefmac
-@maindex RS
@cindex left margin, how to move, in manual pages
-@Defmac{RS, [@var{nnn}]}
-This macro moves the left margin to the right by the value @var{nnn} if
-specified (default unit is @samp{n}); otherwise the default indentation
-value is used. Calls to the @code{RS} macro can be nested.
-@end_Defmac
-
-@maindex RE
-@Defmac{RE, [@var{nnn}]}
-This macro moves the left margin back to level @var{nnn}; if no argument
-is given, it moves one level back. The first level (i.e., no call to
-@code{RS} yet) has number@w{ }1, and each call to @code{RS} increases
-the level by@w{ }1.
-@end_Defmac
+@Defmac {RS, [@Var{nnn}]}
+Move the left margin to the right by the value @var{nnn} if specified
+(default unit is @samp{n}); otherwise the default indentation value is
+used. Calls to the @code{RS} macro can be nested.
+@endDefmac
+
+@Defmac {RE, [@Var{nnn}]}
+Move the left margin back to level @var{nnn}; if no argument is given,
+it moves one level back. The first level (i.e., no call to @code{RS}
+yet) has number@w{ }1, and each call to @code{RS} increases the level
+by@w{ }1.
+@endDefmac
@maindex SH
@maindex SS
@@ -2051,121 +2241,101 @@ vertical space.
@c ---------------------------------------------------------------------
-@node Man font macros, Miscellaneous man stuff, Man usage, man
+@node Man font macros, Miscellaneous man macros, Man usage, man
@subsection Macros to set fonts
@cindex fonts in manual pages
@cindex @code{man}, how to set fonts
-The standard font is Roman; the default text size is 10@w{ }point.
+The standard font is roman; the default text size is 10@w{ }point.
-@maindex SM
-@Defmac{SM, [@var{text}]}
-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.
-@end_Defmac
+@Defmac {SM, [@Var{text}]}
+Set the text on the same line or the text on the next line in a font
+that is one point size smaller than the default font.
+@endDefmac
-@maindex SB
@cindex boldface, in manual pages
-@Defmac{SB, [@var{text}]}
-Causes the text on the same line or the text on the next line to appear
-in boldface font, one point size smaller than the default font.
-@end_Defmac
+@Defmac {SB, [@Var{text}]}
+Set the text on the same line or the text on the next line in boldface
+font, one point size smaller than the default font.
+@endDefmac
-@maindex BI
-@Defmac{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,
+@Defmac {BI, text}
+Set its arguments alternately in bold face and italic. Thus,
-@example
+@Example
.BI this "word and" that
-@end example
+@endExample
@noindent
-would cause ``this'' and ``that'' to appear in bold face, while ``word
-and'' appears in italics.
-@end_Defmac
-
-@maindex IB
-@Defmac{IB, text}
-Causes text to appear alternately in italic and bold face. The text
-must be on the same line as the macro call.
-@end_Defmac
-
-@maindex RI
-@Defmac{RI, text}
-Causes text on the same line to appear alternately in roman and italic.
-The text must be on the same line as the macro call.
-@end_Defmac
-
-@maindex IR
-@Defmac{IR, text}
-Causes text on the same line to appear alternately in italic and roman.
-The text must be on the same line as the macro call.
-@end_Defmac
-
-@maindex BR
-@Defmac{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.
-@end_Defmac
-
-@maindex RB
-@Defmac{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.
-@end_Defmac
-
-@maindex R
-@Defmac{R, [@var{text}]}
-Causes @var{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.
-@end_Defmac
-
-@maindex B
-@Defmac{B, [@var{text}]}
-Causes @var{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.
-@end_Defmac
-
-@maindex I
+would set ``this'' and ``that'' in bold face, and ``word and'' in
+italics.
+@endDefmac
+
+@Defmac {IB, text}
+Set its arguments alternately in italic and bold face.
+@endDefmac
+
+@Defmac {RI, text}
+Set its arguments alternately in roman and italic.
+@endDefmac
+
+@Defmac {IR, text}
+Set its arguments alternately in italic and roman.
+@endDefmac
+
+@Defmac {BR, text}
+Set its arguments alternately in bold face and roman.
+@endDefmac
+
+@Defmac {RB, text}
+Set its arguments alternately in roman and bold face.
+@endDefmac
+
+@Defmac {R, [@Var{text}]}
+Set @var{text} 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.
+@endDefmac
+
+@Defmac {B, [@Var{text}]}
+Set @var{text} 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.
+@endDefmac
+
@cindex italic, in manual pages
-@Defmac{I, [@var{text}]}
-Causes @var{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.
-@end_Defmac
+@Defmac {I, [@Var{text}]}
+Set @var{text} 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.
+@endDefmac
@c ---------------------------------------------------------------------
-@node Miscellaneous man stuff, , Man font macros, man
-@subsection Miscellaneous
+@node Miscellaneous man macros, Predefined man strings, Man font macros, man
+@subsection Miscellaneous macros
@pindex grohtml
@cindex @file{man}, default indentation
@cindex default indentation, @file{man}
The default indentation is 7.2@dmn{n} for all output devices except for
-@code{grohtml} which uses 1.2@dmn{i} instead.
+@code{grohtml} which ignores indentation.
-@maindex DT
@maindex TH
@cindex tab stops, in manual pages
-@Defmac{DT}
-Sets tabs every 0.5@w{ }inches. Since this macro is always called
+@Defmac {DT}
+Set tabs every 0.5@w{ }inches. Since this macro is always called
during a @code{TH} request, it makes sense to call it only if the tab
positions have been changed.
-@end_Defmac
+@endDefmac
-@maindex PD
@cindex empty space before a paragraph, in manual pages
-@Defmac{PD, [@var{nnn}]}
-Adjusts the empty space before a new paragraph (resp.@: section). The
-optional argument gives the amount of space (default units are
+@Defmac {PD, [@Var{nnn}]}
+Adjust the empty space before a new paragraph (or section). The
+optional argument gives the amount of space (default unit is
@samp{v}); without parameter, the value is reset to its default value
(1@w{ }line for tty devices, 0.4@dmn{v}@w{ }otherwise).
-@end_Defmac
+@endDefmac
@maindex SH
@maindex SS
@@ -2175,35 +2345,40 @@ optional argument gives the amount of space (default units are
@maindex P
@maindex IP
@maindex HP
-This affects the macros @code{SH}, @code{SS}, @code{TP}, @code{LP}
-(resp.@: @code{PP} and @code{P}), @code{IP}, and @code{HP}.
+This affects the macros @code{SH}, @code{SS}, @code{TP}, @code{LP} (as
+well as @code{PP} and @code{P}), @code{IP}, and @code{HP}.
+
+@c ---------------------------------------------------------------------
+
+@node Predefined man strings, Preprocessors in man pages, Miscellaneous man macros, man
+@subsection Predefined strings
The following strings are defined:
-@maindex \*S
-@Defmac{\\*S}
+@Defstr {*S}
Switch back to the default font size.
-@end_Defmac
+@endDefstr
-@maindex \*R
-@Defmac{\\*R}
+@Defstr {*R}
The `registered' sign.
-@end_Defmac
+@endDefstr
-@maindex \*(Tm
-@Defmac{\\*(Tm}
+@Defstr {Tm}
The `trademark' sign.
-@end_Defmac
+@endDefstr
-@maindex \*(lq
-@maindex \*(rq
@glindex lq
@glindex rq
-@Defmac{\\*(lq}
-@Defmacx{\\*(rq}
-Left and right quote.
-This is equal to @code{\(lq} and @code{\(rq}, respectively.
-@end_Defmac
+@Defstr {lq}
+@Defstrx {rq}
+Left and right quote. This is equal to @code{\(lq} and @code{\(rq},
+respectively.
+@endDefstr
+
+@c ---------------------------------------------------------------------
+
+@node Preprocessors in man pages, , Predefined man strings, man
+@subsection Preprocessors in @file{man} pages
@cindex preprocessor, calling convention
@cindex calling convention of preprocessors
@@ -2211,14 +2386,15 @@ If a preprocessor like @code{gtbl} or @code{geqn} is needed, it has
become common usage to make the first line of the man page look like
this:
-@example
+@Example
.\" @var{word}
-@end example
+@endExample
@pindex geqn@r{, invocation in manual pages}
@pindex grefer@r{, invocation in manual pages}
@pindex gtbl@r{, invocation in manual pages}
@pindex man@r{, invocation of preprocessors}
+@noindent
Note the single space character after the double quote. @var{word}
consists of letters for the needed preprocessors: @samp{e} for
@code{geqn}, @samp{r} for @code{grefer}, @samp{t} for @code{gtbl}.
@@ -2266,69 +2442,83 @@ and automatically call the right preprocessor(s).
@c =====================================================================
@c =====================================================================
-@node Programming Tutorial, Preprocessors, Macro Packages, Top
-@chapter Programming Tutorial
-@cindex programming tutorial
-@cindex tutorial for programming
+@node gtroff Reference, Preprocessors, Macro Packages, Top
+@chapter @code{gtroff} Reference
+@cindex reference, @code{gtroff}
+@cindex @code{gtroff} reference
This chapter covers @strong{all} of the facilities of @code{gtroff}.
Users of macro packages may skip it if not interested in details.
@menu
-* Text::
-* Input Conventions::
-* Measurements::
-* Expressions::
-* Identifiers::
-* Embedded Commands::
-* Registers::
-* Manipulating Filling and Adjusting::
-* Manipulating Hyphenation::
-* Manipulating Spacing::
-* Tabs and Fields::
-* Character Translations::
-* Troff and Nroff Mode::
-* Line Layout::
-* Page Layout::
-* Page Control::
-* Fonts::
-* Sizes::
-* Strings::
-* Conditionals and Loops::
-* Writing Macros::
-* Page Motions::
-* Drawing Requests::
-* Traps::
-* Diversions::
-* Environments::
-* I/O::
-* Postprocessor Access::
-* Miscellaneous::
-* Debugging::
-* Implementation Differences::
-* Summary::
+* Text::
+* Input Conventions::
+* Measurements::
+* Expressions::
+* Identifiers::
+* Embedded Commands::
+* Registers::
+* Manipulating Filling and Adjusting::
+* Manipulating Hyphenation::
+* Manipulating Spacing::
+* Tabs and Fields::
+* Character Translations::
+* Troff and Nroff Mode::
+* Line Layout::
+* Page Layout::
+* Page Control::
+* Fonts::
+* Sizes::
+* Strings::
+* Conditionals and Loops::
+* Writing Macros::
+* Page Motions::
+* Drawing Requests::
+* Traps::
+* Diversions::
+* Environments::
+* Suppressing output::
+* I/O::
+* Postprocessor Access::
+* Miscellaneous::
+* Gtroff Internals::
+* Debugging::
+* Implementation Differences::
+* Summary::
@end menu
@c =====================================================================
-@node Text, Input Conventions, Programming Tutorial, Programming Tutorial
+@node Text, Input Conventions, gtroff Reference, gtroff Reference
@section Text
@cindex text, @code{gtroff} processing
@code{gtroff} input files contain text with control commands
interspersed throughout. But, even without control codes, @code{gtroff}
-will still do several things with the input text: filling and adjusting,
-adding additional space after sentences, hyphenating and inserting
-implicit line breaks.
+still does several things with the input text:
+
+@itemize @bullet
+@item
+filling and adjusting
+
+@item
+adding additional space after sentences
+
+@item
+hyphenating
+
+@item
+inserting implicit line breaks
+@end itemize
@menu
-* Filling and Adjusting::
-* Hyphenation::
-* Sentences::
-* Tab Stops::
-* Implicit Line Breaks::
+* Filling and Adjusting::
+* Hyphenation::
+* Sentences::
+* Tab Stops::
+* Implicit Line Breaks::
@end menu
@c ---------------------------------------------------------------------
@@ -2338,7 +2528,7 @@ implicit line breaks.
@cindex filling
@cindex adjusting
-When @code{gtroff} reads in text it collects words from input and fits
+When @code{gtroff} reads text, it collects words from the input and fits
as many of them together on one output line as it can. This is known as
@dfn{filling}.
@@ -2346,11 +2536,11 @@ as many of them together on one output line as it can. This is known as
@cindex spaces, leading and trailing
@cindex extra spaces
@cindex trailing spaces
-Once @code{gtroff} has a @dfn{filled} line it will try to @dfn{adjust}
-it. This means it will widen the spacing between words until the text
+Once @code{gtroff} has a @dfn{filled} line, it tries to @dfn{adjust}
+it. This means it widens 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
+Spaces at the front of a line cause a @dfn{break} (breaks are
explained in @ref{Implicit Line Breaks})
@xref{Manipulating Filling and Adjusting}.
@@ -2362,14 +2552,14 @@ explained in @ref{Implicit Line Breaks})
@cindex hyphenation
Since the odds are not great for finding a set of words, for every
-output line, which will fit nicely on a line without inserting excessive
-amounts of space between words, @code{gtroff} will hyphenate words so
-that lines can be justified without there being too much space between
+output line, which fit nicely on a line without inserting excessive
+amounts of space between words, @code{gtroff} hyphenates words so
+that it can justify lines without inserting too much space between
words. It uses an internal hyphenation algorithm (a simplified version
of the algorithm used within @TeX{}) 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
+hyphenated and how to do so. When a word is hyphenated, the first part
+of the word is added to the current filled line being output (with
+an attached hyphen), and the other portion is added to the next
line to be filled.
@xref{Manipulating Hyphenation}.
@@ -2392,11 +2582,11 @@ a comma or a period as part of an abbreviation.
@cindex space between sentences
@cindex french-spacing
@code{gtroff} does this by flagging certain characters (normally
-@samp{!}, @samp{?} and @samp{.}) as @dfn{end of sentence} characters.
+@samp{!}, @samp{?}, and @samp{.}) as @dfn{end of sentence} characters.
When @code{gtroff} encounters one of these characters at the end of a
-line it will append two @dfn{sentence spaces} in the formatted output.
-(This justifies one of the conventions mentioned in @ref{Input
-Conventions}.)
+line, it appends a normal space followed by a @dfn{sentence space} in
+the formatted output. (This justifies one of the conventions mentioned
+in @ref{Input Conventions}.)
@cindex transparent characters
@cindex character, transparent
@@ -2407,13 +2597,13 @@ Conventions}.)
@cindex )
@cindex ]
@cindex *
-In addition, the following characters resp.@: glyphs are treated
+In addition, the following characters or glyphs are treated
transparently while handling end of sentence characters: @samp{"},
@samp{'}, @samp{)}, @samp{]}, @samp{*}, @code{dg}, and @code{rq}.
See the @code{cflags} request in @ref{Using Symbols}, for more details.
-@findex \&
+@esindex \&
To prevent the insertion of extra space after an end of sentence
character (at the end of a line), append @code{\&}.
@@ -2428,15 +2618,15 @@ character (at the end of a line), append @code{\&}.
@cindex @acronym{EBCDIC} encoding
@code{gtroff} translates @dfn{tabulator characters}, also called
-@dfn{tabs} (normally code point @acronym{ASCII} @code{0x09} resp.@:
+@dfn{tabs} (normally code point @acronym{ASCII} @code{0x09} or
@acronym{EBCDIC} @code{0x05}), in the input into movements to the next
tabulator stop. These tab stops are initially located every half inch
-across the page. Using this, simple tables can easily be made.
+across the page. Using this, simple tables can be made easily.
However, it can often be deceptive as the appearance (and width) of the
text on a terminal and the results from @code{gtroff} can vary greatly.
Also, a possible sticking point is that lines beginning with tab
-characters will still be filled, again producing unexpected results.
+characters are still filled, again producing unexpected results.
For example, the following input
@multitable {12345678} {12345678} {12345678} {12345678}
@@ -2447,7 +2637,7 @@ For example, the following input
@end multitable
@noindent
-will produce
+produces
@multitable {12345678} {12345678} {12345678} {12345678} {12345678} {12345678} {12345678}
@item
@@ -2467,33 +2657,38 @@ will produce
@cindex line break
An important concept in @code{gtroff} is the @dfn{break}. When a break
-occurs, @code{gtroff} will output the partially filled line
-(unjustified), and resume collecting and filling text on the next output
+occurs, @code{gtroff} outputs the partially filled line
+(unjustified), and resumes 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 @code{gtroff}. 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.
+@cindex blank line macro
+@rqindex blm
+There are several ways to cause a break in @code{gtroff}. A blank
+line not only causes a break, but it also outputs a one line vertical
+space (effectively a blank line). Note that this behaviour can be
+modified with the blank line macro request @code{blm}.
+
+@c XXX xref for blm
@cindex fill mode
@cindex mode, fill
-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
+A line that begins with a space causes a break and the space is
+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
+The end of file also causes a break -- otherwise the last line of
the document may vanish!
-Certain requests also cause breaks, implicitly or explicitly. This will
-be discussed in @ref{Manipulating Filling and Adjusting}.
+Certain requests also cause breaks, implicitly or explicitly. This is
+discussed in @ref{Manipulating Filling and Adjusting}.
@c =====================================================================
-@node Input Conventions, Measurements, Text, Programming Tutorial
+@node Input Conventions, Measurements, Text, gtroff Reference
@section Input Conventions
@cindex input conventions
@cindex conventions for input
@@ -2505,7 +2700,7 @@ paragraphs. These are some conventions commonly used when typing
@itemize @bullet
@item
-Break lines after punctuation, particularly at the end of a sentence,
+Break lines after punctuation, particularly at the end of a sentence
and in other logical places. Keep separate phrases on lines by
themselves, as entire phrases are often added or deleted when editing.
@@ -2515,13 +2710,13 @@ inserting more text.
@item
Do not try to do any formatting in a @acronym{WYSIWYG} manner (i.e.,
-don't try and use spaces to get proper indentation).
+don't try using spaces to get proper indentation).
@end itemize
@c =====================================================================
-@node Measurements, Expressions, Input Conventions, Programming Tutorial
+@node Measurements, Expressions, Input Conventions, gtroff Reference
@section Measurements
@cindex measurements
@@ -2531,7 +2726,7 @@ don't try and use spaces to get proper indentation).
@cindex measurement units
@cindex @code{u} unit
@cindex unit, @code{u}
-@code{gtroff} (like any other programs) requires numeric parameters to
+@code{gtroff} (like many 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
@dfn{measurement unit} attached. These units are specified as a single
@@ -2540,9 +2735,9 @@ these units are understood, by @code{gtroff}, to be a multiple of its
@dfn{basic unit}. So, whenever a different measurement unit is
specified @code{gtroff} converts this into its @dfn{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. The
-values may be given as fractional numbers; however, fractional basic
-units are always rounded to integers.
+which is quite small, ranging from 1/75@dmn{th} to 1/72000@dmn{th} of an
+inch. The values may be given as fractional numbers; however,
+fractional basic units are always rounded to integers.
Some of the measurement units are completely independent of any of the
current settings (e.g.@: type size) of @code{gtroff}.
@@ -2553,7 +2748,8 @@ current settings (e.g.@: type size) of @code{gtroff}.
@cindex @code{i} unit
@cindex unit, @code{i}
Inches. An antiquated measurement unit still in use in certain
-backwards countries. One inch is equal to@w{ }2.54@dmn{cm}.
+backwards countries with incredibly low-cost computer equipment. One
+inch is equal to@w{ }2.54@dmn{cm}.
@item c
@cindex centimeter
@@ -2584,7 +2780,7 @@ Pica. Another typesetting measurement. 6@w{ }Picas to an inch (and
@xref{Fractional Type Sizes}, for a discussion of these units.
@end table
-The other measurements understood by @code{gtroff} are dependent on
+The other measurements understood by @code{gtroff} depend on
settings currently in effect in @code{gtroff}. These are very useful
for specifying measurements which should look proper with any size of
text.
@@ -2619,7 +2815,7 @@ Vertical space. This is equivalent to the current line spacing.
@end table
@menu
-* Default Units::
+* Default Units::
@end menu
@c ---------------------------------------------------------------------
@@ -2634,34 +2830,35 @@ it can cause strange errors in some expressions. For example, the line
length request expects em units. Here are several attempts to get a
line length of 3.5@w{ }inches and their results:
-@example
+@Example
3.5i @result{} 3.5i
7/2 @result{} 0i
7/2i @result{} 0i
7i/2 @result{} 0.1i
7i/2u @result{} 3.5i
-@end example
+@endExample
@noindent
-Everything will be converted to basic units first. In the above example
-it is assumed that 1@dmn{i} equals@w{ }240@dmn{u}, and 1@dmn{m}
-equals@w{ }10@dmn{p} (thus 1@dmn{m} equals@w{ }33@dmn{u}). The value
-7i/2 will be first handled as 7i/2m, then converted to 1680u/66u which
-is 25@dmn{u}, and this is approximately 0.1@dmn{i}.
+Everything is converted to basic units first. In the above example it
+is assumed that 1@dmn{i} equals@w{ }240@dmn{u}, and 1@dmn{m} equals@w{
+}10@dmn{p} (thus 1@dmn{m} equals@w{ }33@dmn{u}). The value 7@dmn{i}/2
+is first handled as 7@dmn{i}/2@dmn{m}, then converted to
+1680@dmn{u}/66@dmn{u} which is 25@dmn{u}, and this is approximately
+0.1@dmn{i}.
@cindex measurements, specifying safely
-As a conclusion, the safest way to specify measurements is to always
+Thus, the safest way to specify measurements is to always
attach a scaling indicator. If you want to multiply or divide by a
certain scalar value, use @samp{u} as the unit for that value.
@c =====================================================================
-@node Expressions, Identifiers, Measurements, Programming Tutorial
+@node Expressions, Identifiers, Measurements, gtroff Reference
@section Expressions
@cindex expressions
-@code{gtroff} has most of operators common to other languages:
+@code{gtroff} has most arithmetic operators common to other languages:
@c XXX more details; examples
@@ -2707,8 +2904,10 @@ Logical: @samp{&} (logical and), @samp{:} (logical or).
@opindex -
@opindex +
@opindex !
-@findex if@r{, and the @samp{!} operator}
-@findex while@r{, and the @samp{!} operator}
+@rqindex if
+@rqindex while
+@cindex @code{if}, and the @samp{!} operator
+@cindex @code{while}, and the @samp{!} operator
Unary operators: @samp{-} (negating, i.e.@: changing the sign), @samp{+}
(just for completeness; does nothing in expressions), @samp{!} (logical
not; this works only within @code{if} and @code{while} requests). See
@@ -2740,7 +2939,7 @@ indicators in the evaluation of @var{e}.
Parentheses may be used as in any other language. However, in
@code{gtroff} they are necessary to ensure order of evaluation.
@code{gtroff} has no operator precedence; expressions are evaluated left
-to right. This means that @samp{3+5*4} is evaluated as if it were
+to right. This means that @code{gtroff} evaluates @samp{3+5*4} as if it were
parenthesized like @samp{(3+5)*4}, not as @samp{3+(5*4)}, as might be
expected.
@@ -2759,7 +2958,7 @@ input line.
requests and escapes: @code{bp}, @code{in}, @code{ll}, @code{lt},
@code{nm}, @code{nr}, @code{pl}, @code{pn}, @code{po}, @code{ps},
@code{rt}, @code{ti}, @code{\R}, and @code{\s}. Here the plus and minus
-signs indicate increments resp.@: decrements.
+signs indicate increments and decrements.
@c XXX add more xref
@xref{Setting Registers}.
@@ -2774,7 +2973,7 @@ expressions, unless the entire expression is surrounded by parentheses.
@c =====================================================================
-@node Identifiers, Embedded Commands, Expressions, Programming Tutorial
+@node Identifiers, Embedded Commands, Expressions, gtroff Reference
@section Identifiers
@cindex identifiers
@@ -2788,13 +2987,13 @@ characters:
@cindex whitespace characters
@cindex newline character
@cindex character, whitespace
-Whitespace characters (space, tabs, and newlines).
+Whitespace characters (spaces, tabs, and newlines).
@item
@cindex character, backspace
@cindex backspace character
@cindex @acronym{EBCDIC} encoding of backspace
-Backspace (@acronym{ASCII}@w{ }@code{0x08} resp.@: @acronym{EBCDIC}@w{
+Backspace (@acronym{ASCII}@w{ }@code{0x08} or @acronym{EBCDIC}@w{
}@code{0x16}) and character code @code{0x01}.
@item
@@ -2802,7 +3001,7 @@ Backspace (@acronym{ASCII}@w{ }@code{0x08} resp.@: @acronym{EBCDIC}@w{
@cindex input characters, invalid
@cindex characters, invalid input
@cindex unicode
-The following input characters are invalid and will be ignored if
+The following input characters are invalid and are ignored if
@code{groff} runs on a machine based on @acronym{ASCII}, causing a
warning message of type @samp{input} (see @ref{Debugging}, for more
details): @code{0x00}, @code{0x0B}, @code{0x0D}-@code{0x1F},
@@ -2815,46 +3014,46 @@ And here are the invalid input characters if @code{groff} runs on an
Currently, some of these reserved codepoints are used internally, thus
making it non-trivial to extend @code{gtroff} to cover Unicode or other
-character sets resp.@: encodings which use characters of these ranges.
+character sets and encodings which use characters of these ranges.
-Note that invalid characters will be removed before parsing; an
+Note that invalid characters are removed before parsing; an
identifier @code{foo}, followed by an invalid character, followed by
-@code{bar} will be treated as @code{foobar}.
+@code{bar} is treated as @code{foobar}.
@end itemize
For example, any of the following is valid.
-@example
+@Example
br
PP
(l
end-list
@@_
-@end example
+@endExample
-@findex ]
+@rqindex ]
+@noindent
Note that identifiers longer than two characters with a closing bracket
(@samp{]}) in its name can't be accessed with escape sequences which
-expect an identifier as a parameter. For example, @samp{\[foo]]} will
-access the glyph @samp{foo}, followed by @samp{]}, whereas
+expect an identifier as a parameter. For example, @samp{\[foo]]}
+accesses the glyph @samp{foo}, followed by @samp{]}, whereas
@samp{\C'foo]'} really asks for glyph @samp{foo]}.
@c XXX xref
-@Deffn{Escape, \\A, ident}
-Whether an identifier @var{ident} is valid in @code{gtroff} can be
-tested with the @code{\A} escape. It expands to the character@w{ }1
-or@w{ }0 according to whether its argument (usually delimited by quotes)
-is or is not acceptable as the name of a string, macro, diversion,
-number register, environment, or font. It will return@w{ }0 if no
-argument is given. This is useful for looking up user input in some
-sort of associative table.
+@Defesc {\\A, ', ident, '}
+Test whether an identifier @var{ident} is valid in @code{gtroff}. It
+expands to the character@w{ }1 or@w{ }0 according to whether its
+argument (usually delimited by quotes) is or is not acceptable as the
+name of a string, macro, diversion, number register, environment, or
+font. It returns@w{ }0 if no argument is given. This is useful for
+looking up user input in some sort of associative table.
-@example
+@Example
\A'end-list'
@result{} 1
-@end example
-@end_Deffn
+@endExample
+@endDefesc
@xref{Escapes}, for details on parameter delimiting characters.
@@ -2864,9 +3063,9 @@ Identifiers in @code{gtroff} can be any length, but, in some contexts,
@code{gtroff} needs to be told where identifiers end and text begins
(and in different ways depending on their length):
-@findex (
-@findex [
-@findex ]
+@rqindex (
+@rqindex [
+@rqindex ]
@itemize @bullet
@item
Single character.
@@ -2884,15 +3083,29 @@ in brackets.
@cindex indentifiers, undefined
Unlike many other programming languages, undefined identifiers are
silently ignored or expanded to nothing.
+When @code{gtroff} finds an undefined identifier, it emits a
+warning then:
-@c XXX add info about -ww command line option.
+@itemize @bullet
+@item
+If the identifier is a string, macro, or diversion,
+@code{gtroff} defines it as empty.
+
+@item
+If the identifier is a number register, @code{gtroff}
+defines it with a value of@w{ }0.
+@end itemize
+
+@xref{Warnings}.
+
+@c XXX info about common identifier pool for strings and macros.
@xref{Interpolating Registers}, and @ref{Strings}.
@c =====================================================================
-@node Embedded Commands, Registers, Identifiers, Programming Tutorial
+@node Embedded Commands, Registers, Identifiers, gtroff Reference
@section Embedded Commands
@cindex embedded commands
@cindex commands, embedded
@@ -2902,7 +3115,7 @@ implicit line breaking. In order to gain further functionality,
@code{gtroff} allows commands to be embedded into the 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).
+some large-scale operation (e.g.@: break lines, start new pages).
The other is an @dfn{escape} which can be embedded anywhere in the text,
or even as an argument to a request.
@@ -2911,9 +3124,9 @@ Escapes generally do more minor operations like sub- and superscripts,
print a symbol, etc.
@menu
-* Requests::
-* Macros::
-* Escapes::
+* Requests::
+* Macros::
+* Escapes::
@end menu
@c ---------------------------------------------------------------------
@@ -2927,30 +3140,74 @@ print a symbol, etc.
@cindex no-break control character
@cindex character, no-break control
@cindex control character, no-break
-@findex '
-@findex .
+@rqindex '
+@rqindex .
A request line begins with a control character, which is either a single
quote (@samp{'}, the @dfn{no-break control character}) or a period
(@samp{.}, the normal @dfn{control character}). These can be changed;
see @ref{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.
+arguments (@emph{no} tabs here).
+
+@cindex structuring source code of documents or macro packages
+@cindex documents, structuring the source code
+@cindex macro packages, strucuring the source code
+Since a control character followed by whitespace only is ignored, it
+is common practice to use this feature for structuring the source code
+of documents or macro packages.
+
+@Example
+.de foo
+. tm This is foo.
+..
+.
+.
+.de bar
+. tm This is bar.
+..
+@endExample
+
+@cindex blank line
+@cindex blank line macro
+@rqindex blm
+Another possibility is to use the blank line macro request @code{blm}
+by assigning an empty macro to it.
+
+@Example
+.de do-nothing
+..
+.blm do-nothing \" activate blank line macro
+
+.de foo
+. tm This is foo.
+..
+
+
+.de bar
+. tm This is bar.
+..
+
+.blm \" deactivate blank line macro
+@endExample
+
+@c XXX xref to blm
@cindex zero width space character
@cindex character, zero width space
@cindex space character, zero width
-@findex \&@r{, escaping control characters}
+@esindex \&
+@cindex @code{\&}, escaping control characters
To begin a line with a control character without it being interpreted,
precede it with @code{\&}. This represents a zero width space, which
-means it will not affect the output.
+means it does not affect the output.
In most cases the period is used as a control character. Several
-requests will cause a break implicitly; using the single quote control
-character will prevent this.
+requests cause a break implicitly; using the single quote control
+character prevents this.
@menu
-* Request Arguments::
+* Request Arguments::
@end menu
@node Request Arguments, , Requests, Requests
@@ -2959,24 +3216,24 @@ character will prevent this.
@cindex arguments to requests
Arguments 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.
+The line is split into arguments according to spaces. An argument
+which is intended to contain spaces can either be enclosed in double
+quotes, or have the spaces @dfn{escaped} with backslashes.
Here are a few examples:
-@example
+@Example
.uh The Mouse Problem
.uh "The Mouse Problem"
.uh The\ Mouse\ Problem
-@end example
+@endExample
-@findex \~
-@findex \@key{SP}
+@esindex \~
+@esindex \@key{SP}
@noindent
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
+same effect of calling the @code{uh} macro with one argument, @samp{The
Mouse Problem}.@footnote{The last solution, i.e., using escaped spaces,
is ``classical'' in the sense that it can be found in most @code{troff}
documents. Nevertheless, it is not optimal in all situations, since
@@ -2984,8 +3241,22 @@ documents. Nevertheless, it is not optimal in all situations, since
can't stretch. @code{gtroff} provides a different command @code{\~} to
insert a stretchable, non-breaking space.}
-@findex ds
-Note, however, that the @code{ds} request works differently.
+@cindex @code{"}, as a macro argument
+@cindex double quote, as a macro argument
+A double quote which isn't preceded by a space doesn't start a macro
+argument. If not closing a string, it is printed literally.
+
+For example,
+
+@Example
+.xxx a" "b c" "de"fg"
+@endExample
+
+@noindent
+has the arguments @samp{a"}, @w{@samp{b c}}, @samp{de}, and @samp{fg"}.
+
+@rqindex ds
+Duoble quotes in the @code{ds} request are handled differently.
@xref{Strings}, for more details.
@c ---------------------------------------------------------------------
@@ -3011,9 +3282,9 @@ begin with a backslash and are followed by a single character which
indicates the function to be performed. The escape character can be
changed; see @ref{Character Translations}.
-@findex (
-@findex [
-@findex ]
+@rqindex (
+@rqindex [
+@rqindex ]
Escape sequences which require an identifier as a parameter accept three
possible syntax forms.
@@ -3034,13 +3305,13 @@ until a closing bracket as the identifier.
@noindent
Examples:
-@example
+@Example
\fB
\n(XX
\*[TeX]
-@end example
+@endExample
-@findex '
+@rqindex '
@cindex argument delimiting characters
@cindex characters, argument delimiting
@cindex delimiting characters for arguments
@@ -3050,19 +3321,19 @@ In such cases the argument is traditionally enclosed in single quotes
sequences). The enclosed text is then processed according to what that
escape expects. Example:
-@example
+@Example
\l'1.5i\(bu'
-@end example
+@endExample
-@findex \o
-@findex \b
-@findex \X
+@esindex \o
+@esindex \b
+@esindex \X
Note that the quote character can be replaced with any other character
which does not occur in the argument (even a newline or a space
character) in the following escapes: @code{\o}, @code{\b}, and
@code{\X}. This makes e.g.
-@example
+@Example
A caf
\o
e\'
@@ -3070,39 +3341,39 @@ e\'
in Paris
@result{} A caf@'e in Paris
-@end example
+@endExample
@noindent
possible, but it is better not to use this feature to avoid confusion.
-@findex \%
-@findex \@key{SP}
-@findex \|
-@findex \^
-@findex \@{
-@findex \@}
-@findex \'
-@findex \`
-@findex \-
-@findex \_
-@findex \!
-@findex \?
-@findex \@@
-@findex \)
-@findex \/
-@findex \,
-@findex \&
-@findex \~
-@findex \0
-@findex \a
-@findex \c
-@findex \d
-@findex \e
-@findex \E
-@findex \p
-@findex \r
-@findex \t
-@findex \u
+@esindex \%
+@esindex \@key{SP}
+@esindex \|
+@esindex \^
+@esindex \@{
+@esindex \@}
+@esindex \'
+@esindex \`
+@esindex \-
+@esindex \_
+@esindex \!
+@esindex \?
+@esindex \@@
+@esindex \)
+@esindex \/
+@esindex \,
+@esindex \&
+@esindex \~
+@esindex \0
+@esindex \a
+@esindex \c
+@esindex \d
+@esindex \e
+@esindex \E
+@esindex \p
+@esindex \r
+@esindex \t
+@esindex \u
The following escapes sequences (which are handled similarly to
characters since they don't take a parameter) are also allowed as
delimiters: @code{\%}, @w{@samp{\ }}, @code{\|}, @code{\^}, @code{\@{},
@@ -3112,24 +3383,24 @@ delimiters: @code{\%}, @w{@samp{\ }}, @code{\|}, @code{\^}, @code{\@{},
@code{\E}, @code{\p}, @code{\r}, @code{\t}, and @code{\u}. Again, don't
use these if possible.
-@findex \A
-@findex \Z
-@findex \C
-@findex \w
+@esindex \A
+@esindex \Z
+@esindex \C
+@esindex \w
No newline characters as delimiters are allowed in the following
escapes: @code{\A}, @code{\Z}, @code{\C}, and @code{\w}.
-@findex \D
-@findex \h
-@findex \H
-@findex \l
-@findex \L
-@findex \N
-@findex \R
-@findex \s
-@findex \S
-@findex \v
-@findex \x
+@esindex \D
+@esindex \h
+@esindex \H
+@esindex \l
+@esindex \L
+@esindex \N
+@esindex \R
+@esindex \s
+@esindex \S
+@esindex \v
+@esindex \x
Finally, the escapes @code{\D}, @code{\h}, @code{\H}, @code{\l},
@code{\L}, @code{\N}, @code{\R}, @code{\s}, @code{\S}, @code{\v}, and
@code{\x} can't use the following characters as delimiters:
@@ -3167,28 +3438,28 @@ The (single-character) operators @samp{+-/*%<>=&:().}.
The space, tab, and newline characters.
@item
-@findex \%
-@findex \@{
-@findex \@}
-@findex \'
-@findex \`
-@findex \-
-@findex \_
-@findex \!
-@findex \@@
-@findex \/
-@findex \c
-@findex \e
-@findex \p
+@esindex \%
+@esindex \@{
+@esindex \@}
+@esindex \'
+@esindex \`
+@esindex \-
+@esindex \_
+@esindex \!
+@esindex \@@
+@esindex \/
+@esindex \c
+@esindex \e
+@esindex \p
All escape sequences except @code{\%}, @code{\@{}, @code{\@}},
@code{\'}, @code{\`}, @code{\-}, @code{\_}, @code{\!}, @code{\@@},
@code{\/}, @code{\c}, @code{\e}, and @code{\p}.
@end itemize
-@findex \\
-@findex \e
-@findex \E
-To have a backslash (resp.@: the current escape character) appear in the
+@esindex \\
+@esindex \e
+@esindex \E
+To have a backslash (actually, the current escape character) appear in the
output several escapes are defined: @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
@@ -3199,7 +3470,7 @@ more information.
@xref{Identifiers}, and @ref{Character Translations}.
@menu
-* Comments::
+* Comments::
@end menu
@node Comments, , Escapes, Escapes
@@ -3210,17 +3481,18 @@ Probably one of the most@footnote{Unfortunately, this is a lie. But
hopefully future @code{gtroff} hackers will believe it @code{:-)}}
common forms of escapes is the comment.
-@Deffn{Escape, \\"}
+@Defesc {\\", , , }
Start a comment. Everything to the end of the input line is ignored.
This may sound simple, but it can be tricky to keep the comments from
interfering with the appearance of the final output.
-@findex ds
-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 @code{gtroff}. This only affects the @code{.ds} request.
-@c XXX (any others?)
+@rqindex ds
+@rqindex as
+If the escape is to the right of some text or a request, that portion
+of the line is ignored, but the space leading up to it is noticed by
+@code{gtroff}. This only affects the @code{.ds} and @code{.as}
+request.
@cindex tabs before comments
@cindex comments, lining up with tabs
@@ -3230,69 +3502,95 @@ request and macro arguments.
@cindex undefined request
@cindex request, undefined
-A comment on a line by itself will be treated as a blank line, because
+A comment on a line by itself is treated as a blank line, because
after eliminating the comment, that is all that remains:
-@example
+@Example
Test
\" comment
Test
-@end example
+@endExample
@noindent
-will produce
+produces
-@example
+@Example
Test
Test
-@end example
+@endExample
-As a consequence, it is common to start the line with @code{.\"} which
-will cause the line to be treated as an undefined request and thus
-ignored completely.
+To avoid this, it is common to start the line with @code{.\"} which
+causes the line to be treated as an undefined request and thus ignored
+completely.
-@findex '
+@rqindex '
Another commenting scheme seen sometimes is three consecutive single
quotes (@code{'''}) at the beginning of a line. This works, but
-@code{gtroff} will give a warning about an undefined macro (namely
+@code{gtroff} gives a warning about an undefined macro (namely
@code{''}), which is harmless, but irritating.
-@end_Deffn
+@endDefesc
-@Deffn{Escape, \\#}
-To avoid all this, @code{gtroff} has a new comment mechanism using
-the @code{\#} escape. This escape works the same as @code{\"} except
-that the newline is also ignored:
+@Defesc {\\#, , , }
+To avoid all this, @code{gtroff} has a new comment mechanism using the
+@code{\#} escape. This escape works the same as @code{\"} except that
+the newline is also ignored:
-@example
+@Example
Test
\# comment
Test
-@end example
+@endExample
@noindent
-will produce
+produces
-@example
+@Example
Test Test
-@end example
+@endExample
@noindent
as expected.
-@end_Deffn
+@endDefesc
+
+@Defreq {ig, yy}
+Ignore all input until @code{gtroff} encounters the macro named
+@code{.}@var{yy} on a line by itself (or @code{..} if @var{yy} is not
+specified). This is useful for commenting out large blocks of text:
+
+@Example
+text text text...
+.ig
+This is part of a large block
+of text that has been
+temporarily(?) commented out.
+
+We can restore it simply by removing
+the .ig request and the ".." at the
+end of the block.
+..
+More text text text...
+@endExample
+
+@noindent
+produces
-@findex ig
-For commenting away large blocks of text, the @code{ig} request may be
-useful.
+@Example
+text text text@dots{} More text text text@dots{}
+@endExample
-@c XXX definition of .ig
+@noindent
+Note that the commented-out block of text does not
+cause a break.
-@xref{Strings}.
+The input is read in copy-mode; auto-incremented registers @emph{are}
+affected (@pxref{Auto-increment}).
+@endDefreq
@c =====================================================================
-@node Registers, Manipulating Filling and Adjusting, Embedded Commands, Programming Tutorial
+@node Registers, Manipulating Filling and Adjusting, Embedded Commands, gtroff Reference
@section Registers
@cindex registers
@@ -3303,11 +3601,11 @@ details of formatting parameters.
@xref{Identifiers}, for details on register identifiers.
@menu
-* Setting Registers::
-* Interpolating Registers::
-* Auto-increment::
-* Assigning Formats::
-* Built-in Registers::
+* Setting Registers::
+* Interpolating Registers::
+* Auto-increment::
+* Assigning Formats::
+* Built-in Registers::
@end menu
@c ---------------------------------------------------------------------
@@ -3317,46 +3615,46 @@ details of formatting parameters.
@cindex setting registers
@cindex registers, setting
-Registers are defined resp.@: set via the @code{nr} request or the
+Define or set registers using the @code{nr} request or the
@code{\R} escape.
-@Deffn{Request, nr, ident value}
-@Deffnx{Escape, \\R, ident value}
-Set number register @var{ident} to @var{value}. If @var{ident} doesn't
-exist, it will be created.
+@Defreq {nr, ident value}
+@Defescx {\\R, ', ident value, '}
+Set number register @var{ident} to @var{value}. If @var{ident}
+doesn't exist, @code{gtroff} creates it.
-The argument to @code{\R} has to be enclosed in quotes usually.
+The argument to @code{\R} usually has to be enclosed in quotes.
@xref{Escapes}, for details on parameter delimiting characters.
-@end_Deffn
+@endDefreq
For example, the following two lines are equivalent:
-@example
+@Example
.nr a 1
\R'a 1'
-@end example
+@endExample
Both @code{nr} and @code{\R} have two additional special forms to
-increment resp.@: decrement a register.
+increment or decrement a register.
-@Deffn{Request, nr, ident +value}
-@Deffnx{Request, nr, ident -value}
-@Deffnx{Escape, \\R, ident +value}
-@Deffnx{Escape, \\R, ident -value}
+@Defreq {nr, ident @t{+}@Var{value}}
+@Defreqx {nr, ident @t{-}@Var{value}}
+@Defescx {\\R, ', ident @t{+}@Var{value}, '}
+@Defescx {\\R, ', ident @t{-}@Var{value}, '}
Increment (decrement) register @var{ident} by @var{value}.
-@example
+@Example
.nr a 1
.nr a +1
\na
@result{} 2
-@end example
+@endExample
@cindex negating register values
To assign the negated value of a register to another register, some care
must be taken to get the desired result:
-@example
+@Example
.nr a 7
.nr b 3
.nr a -\nb
@@ -3365,14 +3663,14 @@ must be taken to get the desired result:
.nr a (-\nb)
\na
@result{} -3
-@end example
+@endExample
@noindent
The surrounding parentheses prevent the interpretation of the minus sign
as a decrementing operator. An alternative is to start the assignment
with a @samp{0}:
-@example
+@Example
.nr a 7
.nr b -3
.nr a \nb
@@ -3381,26 +3679,25 @@ with a @samp{0}:
.nr a 0\nb
\na
@result{} -3
-@end example
-@end_Deffn
+@endExample
+@endDefreq
-@Deffn{Request, rr, ident}
+@Defreq {rr, ident}
Remove number register @var{ident}. If @var{ident} doesn't exist, the
request is ignored.
-@end_Deffn
+@endDefreq
-@Deffn{Request, rnn, ident1 ident2}
+@Defreq {rnn, ident1 ident2}
Rename number register @var{ident1} to @var{ident2}. If either
@var{ident1} or @var{ident2} doesn't exist, the request is ignored.
-@end_Deffn
+@endDefreq
-@Deffn{Request, aln, ident1 ident2}
-This request creates an alias @var{ident1} for a number register
-@var{ident2}. The new name and the old name will be exactly equivalent.
-If @var{ident1} is undefined, a warning of type @samp{reg} will be
-generated, and the request will be ignored. @xref{Debugging}, for
-information about warnings.
-@end_Deffn
+@Defreq {aln, ident1 ident2}
+Create an alias @var{ident1} for a number register @var{ident2}. The
+new name and the old name are exactly equivalent. If @var{ident1} is
+undefined, a warning of type @samp{reg} is generated, and the request
+is ignored. @xref{Debugging}, for information about warnings.
+@endDefreq
@c ---------------------------------------------------------------------
@@ -3411,19 +3708,37 @@ information about warnings.
Numeric registers can be accessed via the @code{\n} escape.
-@Deffn{Escape, \\n, ident}
-@c XXX is the following correct?
-Interpolate number register @var{ident}. This means that the value of
+@cindex nested assignments
+@cindex assignments, nested
+@cindex indirect assignments
+@cindex assignments, indirect
+@Defesc {\\n, , i, }
+@Defescx {\\n, @lparen{}, id, }
+@Defescx {\\n, @lbrack{}, ident, @rbrack}
+Interpolate number register with name @var{ident} (one-character name
+@var{i}, two-character name @var{id}). This means that the value of
the register is expanded in-place while @code{gtroff} is parsing the
-input line.
+input line. Nested assignments (also called indirect assignments) are
+possible.
-@example
+@Example
.nr a 5
.nr as \na+\na
\n(as
@result{} 10
-@end example
-@end_Deffn
+@endExample
+
+@Example
+.nr a1 5
+.nr ab 6
+.ds str b
+.ds num 1
+\n[a\n[num]]
+ @result{} 5
+\n[a\*[str]]
+ @result{} 6
+@endExample
+@endDefesc
@c ---------------------------------------------------------------------
@@ -3432,31 +3747,40 @@ input line.
@cindex auto-increment
@cindex increment, automatic
-Number registers can also be auto-incremented and auto-decremented. The
-increment resp.@: decrement factor can be specified with a third
+Number registers can also be auto-incremented and auto-decremented.
+The increment or decrement value can be specified with a third
argument to the @code{nr} request or @code{\R} escape.
-@findex \R
-@Deffn{Request, nr, ident value incr}
+@esindex \R
+@Defreq {nr, ident value incr}
Set number register @var{ident} to @var{value}; the increment for
-auto-incrementing is set to @var{incr}. Note that the @code{\R} escape
-doesn't support this notation.
-@end_Deffn
-
-To activate auto-incrementing, the escape @code{\n} has a special syntax
-form.
-
-@Deffn{Escape, \\n, +ident}
-@Deffnx{Escape, \\n, -ident}
-Before interpolating, increment resp.@: decrement @var{ident} by the
+auto-incrementing is set to @var{incr}. Note that the @code{\R}
+escape doesn't support this notation.
+@endDefreq
+
+To activate auto-incrementing, the escape @code{\n} has a special
+syntax form.
+
+@Defesc {\\n, +, i, }
+@Defescx {\\n, -, i, }
+@Defescx {\\n, @lparen{}+, id, }
+@Defescx {\\n, @lparen{}-, id, }
+@Defescx {\\n, +@lparen{}, id, }
+@Defescx {\\n, -@lparen{}, id, }
+@Defescx {\\n, @lbrack{}+, ident, @rbrack{}}
+@Defescx {\\n, @lbrack{}-, ident, @rbrack{}}
+@Defescx {\\n, +@lbrack{}, ident, @rbrack{}}
+@Defescx {\\n, -@lbrack{}, ident, @rbrack{}}
+Before interpolating, increment or decrement @var{ident}
+(one-character name @var{i}, two-character name @var{id}) by the
auto-increment value as specified with the @code{nr} request (or the
-@code{\R} escape). If no auto-increment value has been specified, both
-syntax forms are identical to @code{\n}.
-@end_Deffn
+@code{\R} escape). If no auto-increment value has been specified,
+these syntax forms are identical to @code{\n}.
+@endDefesc
For example,
-@example
+@Example
.nr a 0 1
.nr xx 0 5
.nr foo 0 -2
@@ -3465,24 +3789,24 @@ For example,
\n-(xx, \n-(xx, \n-(xx, \n-(xx, \n-(xx
.br
\n+[foo], \n+[foo], \n+[foo], \n+[foo], \n+[foo]
-@end example
+@endExample
@noindent
produces
-@example
+@Example
1, 2, 3, 4, 5
-5, -10, -15, -20, -25
-2, -4, -6, -8, -10
-@end example
+@endExample
@cindex increment value without changing the register
-To change the increment value without changing the value of a register,
-the following can be used:
+To change the increment value without changing the value of a register
+(@var{a} in the example), the following can be used:
-@example
+@Example
.nr a \na 10
-@end example
+@endExample
@c ---------------------------------------------------------------------
@@ -3491,21 +3815,21 @@ the following can be used:
@cindex assigning formats
@cindex formats, assigning
-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.
+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.
-@Deffn{Request, af, ident format}
+@Defreq {af, ident format}
Change the output format of a number register. The first argument
@var{ident} is the name of the number register to be changed, and the
-second argument @var{format} is the output format. The following output
-formats are available:
+second argument @var{format} is the output format. The following
+output formats are available:
@table @code
@item 1
-Decimal arabic numbers. This is the default format: 1, 2, 3,@w{
+Decimal arabic numbers. This is the default format: 0, 1, 2, 3,@w{
}@enddots{}
@item 0@dots{}0
@@ -3518,7 +3842,7 @@ format @samp{1} could be specified as @samp{0} also (and exactly this is
returned by the @code{\g} escape, see below).
@item I
-@cindex roman numerals
+@cindex Roman numerals
@cindex numerals, Roman
Upper-case Roman numerals: 0, I, II, III, IV,@w{ }@enddots{}
@@ -3526,19 +3850,19 @@ Upper-case Roman numerals: 0, I, II, III, IV,@w{ }@enddots{}
Lower-case Roman numerals: 0, i, ii, iii, iv,@w{ }@enddots{}
@item A
-Upper-case letters: A, B, C, @dots{},@w{ }Z, AA, AB,@w{ }@enddots{}
+Upper-case letters: 0, A, B, C, @dots{},@w{ }Z, AA, AB,@w{ }@enddots{}
@item a
-Lower-case letters: a, b, c, @dots{},@w{ }z, aa, ab,@w{ }@enddots{}
+Lower-case letters: 0, a, b, c, @dots{},@w{ }z, aa, ab,@w{ }@enddots{}
@end table
-Omitting the number register format will cause a warning of type
+Omitting the number register format causes a warning of type
@samp{missing}. @xref{Debugging}, for more details. Specifying a
nonexistent format causes an error.
-The following example will produce @samp{10, X, j, 010}:
+The following example produces @samp{10, X, j, 010}:
-@example
+@Example
.nr a 10
.af a 1 \" the default format
\na,
@@ -3548,35 +3872,38 @@ The following example will produce @samp{10, X, j, 010}:
\na,
.af a 001
\na
-@end example
+@endExample
-@cindex roman numerals, maximum and minimum
+@cindex Roman numerals, maximum and minimum
@cindex maximum values of Roman numerals
@cindex minimum values of Roman numerals
The largest number representable for the @samp{i} and @samp{I} formats
-is 39999 (resp.@: -39999); @acronym{UNIX} @code{troff} uses @samp{z} and
-@samp{w} to represent 10000 and 5000 in Roman numerals, and so does
+is 39999 (or @minus{}39999); @acronym{UNIX} @code{troff} uses @samp{z}
+and @samp{w} to represent 10000 and 5000 in Roman numerals, and so does
@code{gtroff}. Currently, the correct glyphs of Roman numeral five
thousand and Roman numeral ten thousand (Unicode code points
@code{U+2182} and @code{U+2181}, respectively) are not available.
-If @var{ident} doesn't exist, it will be created.
+If @var{ident} doesn't exist, it is created.
@cindex read-only register, changing format
@cindex changing format, read-only register
Changing the output format of a read-only register causes an error. It
is necessary to first copy the register's value to a writeable register,
then apply the @code{af} request to this other register.
-@end_Deffn
+@endDefreq
@cindex format of register
@cindex register, format
-@Deffn{Escape, \\g, ident}
-Return the current format of the specified register @var{ident}. For
-example, @samp{\ga} after the previous example would produce the string
-@samp{000}. If the register hasn't been defined yet, nothing is
-returned.
-@end_Deffn
+@Defesc {\\g, , i, }
+@Defescx {\\g, @lparen{}, id, }
+@Defescx {\\g, @lbrack{}, ident, @rbrack{}}
+Return the current format of the specified register @var{ident}
+(one-character name @var{i}, two-character name @var{id}). For
+example, @samp{\ga} after the previous example would produce the
+string @samp{000}. If the register hasn't been defined yet, nothing
+is returned.
+@endDefesc
@c ---------------------------------------------------------------------
@@ -3635,25 +3962,25 @@ incorrectly claimed that @code{yr} contains the last two digits of the
year. That claim has never been true of either traditional @code{troff}
or GNU @code{troff}. Old @code{troff} input that looks like this:
-@example
+@Example
'\" The following line stopped working after 1999
This document was formatted in 19\n(yr.
-@end example
+@endExample
@noindent
can be corrected as follows:
-@example
+@Example
This document was formatted in \n[year].
-@end example
+@endExample
@noindent
or, to be portable to older @code{troff} versions, as follows:
-@example
+@Example
.nr y4 1900+\n(yr
This document was formatted in \n(y4.
-@end example
+@endExample
@item .c
@vindex .c
@@ -3667,27 +3994,27 @@ affecting both @samp{.c} and @samp{c.}.
@item ln
@vindex ln
-@findex nm
+@rqindex nm
@cindex output line number register
@cindex line number, output, register
The current @emph{output} line number after a call to the @code{nm}
request to activate line numbering.
-@c XXX xref nm request
+@xref{Miscellaneous}, for more information about line numbering.
@item .x
@vindex .x
@cindex major version number register
@cindex version number, major, register
The major version number. For example, if the version number is@w{
-}1.03 then @code{.x} will contain@w{ }@samp{1}.
+}1.03 then @code{.x} contains@w{ }@samp{1}.
@item .y
@vindex .y
@cindex minor version number register
@cindex version number, minor, register
The minor version number. For example, if the version number is@w{
-}1.03 then @code{.y} will contain@w{ }@samp{03}.
+}1.03 then @code{.y} contains@w{ }@samp{03}.
@item .Y
@vindex .Y
@@ -3721,9 +4048,9 @@ If @code{gtroff} is called with the @option{-T} command line option, the
number register @code{.T} is set to@w{ }1, and zero otherwise.
@xref{Groff Options}.
-@maindex \*(.T
+@stindex .T
@cindex output device register
-Additionally, @code{gtroff} predefines a single (read/write) string
+Additionally, @code{gtroff} predefines a single read-write string
register @code{.T} which contains the current output device (for
example, @samp{latin1} or @samp{ps}).
@end table
@@ -3731,7 +4058,7 @@ example, @samp{latin1} or @samp{ps}).
@c =====================================================================
-@node Manipulating Filling and Adjusting, Manipulating Hyphenation, Registers, Programming Tutorial
+@node Manipulating Filling and Adjusting, Manipulating Hyphenation, Registers, gtroff Reference
@section Manipulating Filling and Adjusting
@cindex manipulating filling and adjusting
@cindex filling and adjusting, manipulating
@@ -3741,70 +4068,72 @@ example, @samp{latin1} or @samp{ps}).
@cindex break
@cindex line break
-@findex bp
-@findex ce
-@findex cf
-@findex fi
-@findex fl
-@findex in
-@findex nf
-@findex rj
-@findex sp
-@findex ti
-@findex trf
+@rqindex bp
+@rqindex ce
+@rqindex cf
+@rqindex fi
+@rqindex fl
+@rqindex in
+@rqindex nf
+@rqindex rj
+@rqindex sp
+@rqindex ti
+@rqindex trf
Various 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, but implicitly. These are
+Breaks}. The @code{br} request likewise causes a break. Several
+other requests also cause breaks, but implicitly. These are
@code{bp}, @code{ce}, @code{cf}, @code{fi}, @code{fl}, @code{in},
@code{nf}, @code{rj}, @code{sp}, @code{ti}, and @code{trf}.
-@Deffn{Request, br, }
-Break the current line, i.e., the input collected so far will be emitted
+@Defreq {br, }
+Break the current line, i.e., the input collected so far is emitted
without adjustment.
-If the no-break control character is used, no break will happen:
+If the no-break control character is used, @code{gtroff} suppresses
+the break:
-@example
+@Example
a
'br
b
@result{} a b
-@end example
-@end_Deffn
+@endExample
+@endDefreq
-Initially, @code{gtroff} will fill and adjust text to both margins.
+Initially, @code{gtroff} fills and adjusts text to both margins.
Filling can be disabled via the @code{nf} request and re-enabled with
the @code{fi} request.
@cindex fill mode
@cindex mode, fill
-@vindex .u
-@Deffn{Request, fi, }
+@Defreq {fi, }
+@Defregx {.u}
Activate fill mode (which is the default). This request implicitly
-enables adjusting; it will also cause a break in the text currently
-being filled. The number register @code{.u} is set to@w{ }1.
+enables adjusting; it also inserts a break in the text currently being
+filled. The read-only number register @code{.u} is set to@w{ }1.
The fill mode status is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
@cindex no-fill mode
@cindex mode, no-fill
-@Deffn{Request, nf, }
+@Defreq {nf, }
Activate no-fill mode. Input lines are output as-is, retaining line
-breaks. The current line length will be ignored. This command
-implicitly disables adjusting; it also causes a break. The number
-register @code{.u} will be set to@w{ }0.
+breaks and ignoring the current line length. This command implicitly
+disables adjusting; it also causes a break. The number register
+@code{.u} is set to@w{ }0.
The fill mode status is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
-@Deffn{Request, ad, [@var{mode}]}
+@Defreq {ad, [@Var{mode}]}
+@Defregx {.j}
Set adjusting mode.
-Activation and deactivation of adjusting will be implicitly done with
-calls to the @code{fi} resp.@: @code{nf} requests.
+Activation and deactivation of adjusting is done implicitly with
+calls to the @code{fi} or @code{nf} requests.
@var{mode} can have one of the following values:
@@ -3820,7 +4149,7 @@ Adjust text to the right margin, producing ragged-left text.
@item c
@cindex centered text
-@findex ce
+@rqindex ce
Center filled text. This is different to the @code{ce} request which
only centers text without filling.
@@ -3829,11 +4158,11 @@ only centers text without filling.
Justify to both margins. This is the default used by @code{gtroff}.
@end table
-With no argument, @code{gtroff} will adjust lines in the same way it did
-before adjusting has been deactivated (with a call to @code{na}, for
+With no argument, @code{gtroff} adjusts lines in the same way it did
+before adjusting was deactivated (with a call to @code{na}, for
example).
-@example
+@Example
text
.ad r
text
@@ -3843,48 +4172,49 @@ text
text
.ad \" back to centering
text
-@end example
+@endExample
-@vindex .j
@cindex current adjustment mode register
-The current adjustment mode is available in the number register
-@code{.j}; it can be stored and subsequently used to set adjustment.
+The current adjustment mode is available in the read-only number
+register @code{.j}; it can be stored and subsequently used to set
+adjustment.
The adjustment mode status is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
-@Deffn{Request, na, }
+@Defreq {na, }
Disable adjusting. This request won't change the current adjustment
-mode: A call to @code{ad} afterwards will use the previous adjustment
+mode: A subsequent call to @code{ad} uses the previous adjustment
setting.
The adjustment mode status is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
-@Deffn{Escape, \\p, }
+@Defesc {\\p, , , }
Adjust the current line and cause a break.
-In most cases this will produce very ugly results, since @code{gtroff}
+In most cases this produces very ugly results, since @code{gtroff}
doesn't have a sophisticated paragraph building algorithm (as @TeX{}
-does, for example); instead, @code{gtroff} fills and adjusts a paragraph
+have, for example); instead, @code{gtroff} fills and adjusts a paragraph
line by line:
-@example
+@Example
This is an uninteresting sentence.
This is an uninteresting sentence.\p
This is an uninteresting sentence.
-@end example
+@endExample
+@noindent
is formatted as
-@example
+@Example
This is an uninteresting sentence. This is an
uninteresting sentence.
This is an uninteresting sentence.
-@end example
-@end_Deffn
+@endExample
+@endDefesc
@cindex word space size
@cindex size of word space
@@ -3892,100 +4222,125 @@ is formatted as
@cindex sentence space size
@cindex size of sentence space
@cindex space between sentences
-@Deffn{Request, ss, word_space_size [@var{sentence_space_size}]}
+@Defreq {ss, word_space_size [@Var{sentence_space_size}]}
+@Defregx {.ss}
+@Defregx {.sss}
Change the minimum size of a space between filled words. It takes its
-units as one twelfth of the space width parameter for the current font.
-Initially both the @var{word_space_size} and @var{sentence_space_size}
-are@w{ }12.
+units as one twelfth of the space width parameter for the current
+font. Initially both the @var{word_space_size} and
+@var{sentence_space_size} are@w{ }12.
@cindex fill mode
@cindex mode, fill
-If two arguments are given to the @code{ss} request, the second argument
-sets the sentence space size. If the second argument is not given,
-sentence space size will be set to @var{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 @acronym{UNIX} @code{troff} will be exactly
-that exhibited by GNU @code{troff} if a second argument is never given
-to the @code{ss} request. In GNU @code{troff}, as in @acronym{UNIX}
-@code{troff}, a sentence should always be followed by either a newline
-or two spaces.
-
-@vindex .ss
-@vindex .sss
-The number registers @code{.ss} and @code{.sss} hold the values of the
-parameters set by the first and second arguments of the @code{ss}
-request.
+If two arguments are given to the @code{ss} request, the second
+argument sets the sentence space size. If the second argument is not
+given, sentence space size is set to @var{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 are added; if two spaces follow
+the end of a sentence in the middle of a line, then the second space
+is a sentence space. If a second argument is never given to the
+@code{ss} request, the behaviour of @acronym{UNIX} @code{troff} is the
+same as that exhibited by GNU @code{troff}. In GNU @code{troff}, as
+in @acronym{UNIX} @code{troff}, a sentence should always be followed
+by either a newline or two spaces.
+
+The read-only number registers @code{.ss} and @code{.sss} hold the
+values of the parameters set by the first and second arguments of the
+@code{ss} request.
The word space and sentence space values are associated with the current
environment (@pxref{Environments}).
-This request is ignored in nroff mode; it is also ignored if there is no
-parameter.
-@end_Deffn
+Contrary to traditional Unix @code{troff}, this request is @emph{not}
+ignored if a tty output device is used; the given values are then
+rounded down to a multiple of@w{ }12.
+
+@c XXX xref implementation differences
+
+The request is ignored if there is no parameter.
+@endDefreq
@cindex centering lines
@cindex lines, centering
-@Deffn{Request, ce, [@var{nnn}]}
-Center text. While the @w{@samp{.ad c}} request will also center text,
-it has the side effect of filling the text. @code{ce} will not fill the
+@Defreq {ce, [@Var{nnn}]}
+@Defregx {.ce}
+Center text. While the @w{@samp{.ad c}} request also centers text,
+it fills the text as well. @code{ce} does not fill the
text it affects. This request causes a break.
-With no arguments, @code{ce} will center the next line of text.
-@var{nnn} specifies the number of lines to be centered. If
-the argument is zero or negative, centering is disabled.
+The following example demonstrates the differences.
+Here the input:
+
+@Example
+.ll 4i
+.ce 1000
+This is a small text fragment which shows the differences
+between the `.ce' and the `.ad c' request.
+.ce 0
+
+.ad c
+This is a small text fragment which shows the differences
+between the `.ce' and the `.ad c' request.
+@endExample
+
+@noindent
+And here the result:
+
+@Example
+ This is a small text fragment which
+ shows the differences
+between the `.ce' and the `.ad c' request.
-@findex ll
-@findex in
-@findex ti
+ This is a small text fragment which
+shows the differences between the `.ce'
+ and the `.ad c' request.
+@endExample
+
+With no arguments, @code{ce} centers the next line of text. @var{nnn}
+specifies the number of lines to be centered. If the argument is zero
+or negative, centering is disabled.
+
+@rqindex ll
+@rqindex in
+@rqindex ti
The basic length for centering text is the line length (as set with the
@code{ll} request) minus the indentation (as set with the @code{in}
request). Temporary indentation is ignored.
-A common idiom is to turn on centering for a large number of lines, and
-to turn off centering after text to be centered. 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
+As can be seen in the previous example, it is a common idiom to turn
+on centering for a large number of lines, and to turn off centering
+after text to be centered. This is useful for any request which takes
+a number of lines as an argument.
-@vindex .ce
-The @code{.ce} number register contains the number of lines remaining to
-be centered, as set by the @code{ce} request.
-@end_Deffn
+The @code{.ce} read-only number register contains the number of lines
+remaining to be centered, as set by the @code{ce} request.
+@endDefreq
@cindex justifying text
@cindex text, justifying
@cindex right-justifying
-@vindex .rj
-@Deffn{Request, rj, [@var{nnn}]}
+@Defreq {rj, [@Var{nnn}]}
+@Defregx {.rj}
Justify unfilled text to the right margin. 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. This
-request causes a line break.
-@end_Deffn
+the @code{ce} request. The @code{.rj} read-only number register is
+the number of lines to be right-justified as set by the @code{rj}
+request. This request causes a break.
+@endDefreq
@c =====================================================================
-@node Manipulating Hyphenation, Manipulating Spacing, Manipulating Filling and Adjusting, Programming Tutorial
+@node Manipulating Hyphenation, Manipulating Spacing, Manipulating Filling and Adjusting, gtroff Reference
@section Manipulating Hyphenation
@cindex manipulating hyphenation
@cindex hyphenation, manipulating
-As discussed in @ref{Hyphenation}, @code{gtroff} will hyphenate words.
+As discussed in @ref{Hyphenation}, @code{gtroff} hyphenates words.
There are a number of ways to influence hyphenation.
-@Deffn{Request, hy, [@var{mode}]}
+@Defreq {hy, [@Var{mode}]}
+@Defregx {.hy}
Enable hyphenation. The request has an optional numeric argument,
@var{mode}, to restrict hyphenation if necessary:
@@ -4008,52 +4363,54 @@ Values in the previous table are additive. For example, the value@w{
}12 causes @code{gtroff} to neither hyphenate the last two nor the first
two characters of a word.
-@vindex .hy
@cindex hyphenation restrictions register
-The current hyphenation restrictions can be found in the number register
-@samp{.hy}.
+The current hyphenation restrictions can be found in the read-only
+number register @samp{.hy}.
The hyphenation mode is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
-@Deffn{Request, nh, }
-Disable hyphenation (i.e., set the hyphenation mode to zero). Note that
-the hyphenation mode of the last call to @code{hy} is not remembered.
+@Defreq {nh, }
+Disable hyphenation (i.e., set the hyphenation mode to zero). Note
+that the hyphenation mode of the last call to @code{hy} is not
+remembered.
The hyphenation mode is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
-@vindex .hlc
-@vindex .hlm
-@findex \%
+@esindex \%
@cindex explicit hyphens
@cindex hyphen, explicit
@cindex consecutive hyphenated lines
@cindex lines, consecutive hyphenated
@cindex hyphenated lines, consecutive
-@Deffn{Request, hlm, [@var{nnn}]}
-Set the maximum number of consecutive hyphenated lines to @var{nnn}. If
-this number is negative, there is no maximum. The default value is@w{
-}-1 if @var{nnn} is omitted. This value is associated with the current
-environment (@pxref{Environments}). Only lines output from a given
-environment count towards the maximum associated with that environment.
-Hyphens resulting from @code{\%} are counted; explicit hyphens are not.
+@Defreq {hlm, [@Var{nnn}]}
+@Defregx {.hlm}
+@Defregx {.hlc}
+Set the maximum number of consecutive hyphenated lines to @var{nnn}.
+If this number is negative, there is no maximum. The default value
+is@w{ }@minus{}1 if @var{nnn} is omitted. This value is associated
+with the current environment (@pxref{Environments}). Only lines
+output from a given environment count towards the maximum associated
+with that environment. Hyphens resulting from @code{\%} are counted;
+explicit hyphens are not.
The current setting of @code{hlm} is available in the @code{.hlm}
-register. Also the number of immediately preceding consecutive
-hyphenated lines are available in the number register @samp{.hlc}.
-@end_Deffn
+read-only number register. Also the number of immediately preceding
+consecutive hyphenated lines are available in the read-only number
+register @samp{.hlc}.
+@endDefreq
-@Deffn{Request, hw, word1 word2 @dots{}}
+@Defreq {hw, word1 word2 @dots{}}
Define how @var{word1}, @var{word2}, etc.@: are to be hyphenated. The
words must be given with hyphens at the hyphenation points. For
example:
-@example
+@Example
.hw in-sa-lub-rious
-@end example
+@endExample
@noindent
Besides the space character, any character whose hyphenation code value
@@ -4062,7 +4419,7 @@ documentation for the @code{hcode} request below for more information).
In addition, this request can be used more than once.
Hyphenation exceptions specified with the @code{hw} request are
-associated with the current hyphenation language; it will cause an error
+associated with the current hyphenation language; it causes an error
if there is no current hyphenation language.
This request is ignored if there is no parameter.
@@ -4070,38 +4427,39 @@ This request is ignored if there is no parameter.
In old versions of @code{troff} there was a limited amount of space to
store such information; fortunately, with @code{gtroff}, this is no
longer a restriction.
-@end_Deffn
+@endDefreq
@cindex hyphenation character
@cindex character, hyphenation
@cindex disabling hyphenation
@cindex hyphenation, disabling
-@Deffn{Escape, \\%, }
-To tell @code{gtroff} how to hyphenate words on the fly, the @code{\%}
-escape, also known as the @dfn{hyphenation character}, can be used.
-Preceding a word with this character will prevent it from being
-hyphenated, putting it in a word will indicate to @code{gtroff} that the
-word may be hyphenated at that point. Note that this mechanism will
-only affect that one occurrence of the word; to change the hyphenation
-of a word for the entire document, use the @code{hw} request.
-@end_Deffn
-
-@Deffn{Request, hc, [@var{char}]}
-Change the hyphenation character to @var{char}. This character will
-then work the same as the @code{\%} escape, and thus, no longer appear
-in the output. Without an argument, @code{hc} will reset the
-hyphenation character to be @code{\%} (the default) only.
+@Defesc {\\%, , , }
+To tell @code{gtroff} how to hyphenate words on the fly, use the
+@code{\%} escape, also known as the @dfn{hyphenation character}.
+Preceding a word with this character prevents it from being
+hyphenated; putting it inside a word indicates to @code{gtroff} that
+the word may be hyphenated at that point. Note that this mechanism
+only affects that one occurrence of the word; to change the
+hyphenation of a word for the entire document, use the @code{hw}
+request.
+@endDefesc
+
+@Defreq {hc, [@Var{char}]}
+Change the hyphenation character to @var{char}. This character then
+works the same as the @code{\%} escape, and thus, no longer appears in
+the output. Without an argument, @code{hc} resets the hyphenation
+character to be @code{\%} (the default) only.
The hyphenation character is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
@cindex hyphenation patterns
@cindex patterns for hyphenation
-@Deffn{Request, hpf, pattern_file}
-Read in a file of hyphenation patterns. This file will be searched for
-in the same way as @file{tmac.@var{name}} is searched for if the
-@option{-m@var{name}} option is specified.
+@Defreq {hpf, pattern_file}
+Read in a file of hyphenation patterns. This file is searched for in
+the same way as @file{@var{name}.tmac} (or @file{tmac.@var{name}}) is
+searched for if the @option{-m@var{name}} option is specified.
It should have the same format as the argument to the @code{\patterns}
primitive in @TeX{} (without using @TeX{}'s macro expansion); the
@@ -4112,7 +4470,7 @@ continues to the end of the line.
If no @code{hpf} request is specified (either in the document or in a
macro package), @code{gtroff} won't hyphenate at all.
-@findex hla
+@rqindex hla
@pindex troffrc
@pindex troffrc-end
@pindex hyphen.us
@@ -4122,85 +4480,90 @@ invoked by the @file{troffrc} or @file{troffrc-end} file; by default,
@file{troffrc} loads hyphenation patterns for American English (in file
@file{hyphen.us}).
-@code{hpf} will cause an error if there is no current hyphenation
+Invoking @code{hpf} causes an error if there is no current hyphenation
language.
-@end_Deffn
+@endDefreq
@cindex hyphenation code
@cindex code, hyphenation
-@Deffn{Request, hcode, c1 code1 c2 code2 @dots{}}
-Sets the hyphenation code of character @var{c1} to @var{code1}, that of
-@var{c2} to @var{code2}, etc. 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 (@samp{a}-@samp{z}) has its hyphenation
-set to itself, and each upper-case letter (@samp{A}-@samp{Z}) has a
-hyphenation code which is the lower-case version of itself.
-
-This request will be ignored if it has no parameter.
-@end_Deffn
+@Defreq {hcode, c1 code1 c2 code2 @dots{}}
+Set the hyphenation code of character @var{c1} to @var{code1}, that of
+@var{c2} to @var{code2}, etc. 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 (@samp{a}-@samp{z}) has its
+hyphenation set to itself, and each upper-case letter
+(@samp{A}-@samp{Z}) has a hyphenation code which is the lower-case
+version of itself.
+
+This request is ignored if it has no parameter.
+@endDefreq
@cindex hyphenation margin
@cindex margin for hyphenation
-@findex ad
-@Deffn{Request, hym, [@var{length}]}
+@rqindex ad
+@Defreq {hym, [@Var{length}]}
+@Defregx {.hym}
Set the (right) hyphenation margin to @var{length}. If the current
-adjustment mode is not@w{ }@samp{b}, the line will not be hyphenated if
-it is shorter than @var{length}. Without argument, the hyphenation
-margin will be reset to its default value, which is@w{ }0. The default
-scaling indicator for this request is@w{ }@code{m}. The hyphenation
-margin is associated with the current environment
+adjustment mode is not @samp{b} or@w{ }@samp{n}, the line is not
+hyphenated if it is shorter than @var{length}. Without an argument,
+the hyphenation margin is reset to its default value, which is@w{ }0.
+The default scaling indicator for this request is@w{ }@code{m}. The
+hyphenation margin is associated with the current environment
(@pxref{Environments}).
-A negative argument will reset the hyphenation margin to zero, emitting
+A negative argument resets the hyphenation margin to zero, emitting
a warning of type @samp{range}.
-@vindex .hym
@cindex current hyphenation margin register
-The current hyphenation margin is available in the @code{.hym} register.
-@end_Deffn
+The current hyphenation margin is available in the @code{.hym} read-only
+number register.
+@endDefreq
@cindex hyphenation space
-@findex ad
-@Deffn{Request, hys, [@var{hyphenation_space}]}
+@rqindex ad
+@Defreq {hys, [@Var{hyphenation_space}]}
+@Defregx {.hys}
Set the hyphenation space to @var{hyphenation_space}. If the current
-adjustment mode is@w{ }@samp{b}, don't hyphenate the line if it
-can be justified by adding no more than @var{hyphenation_space} extra
-space to each word space. Without argument, the hyphenation space is
-set to its default value, which is@w{ }0. The default scaling indicator
-for this request is@w{ }@code{m}. The hyphenation space is associated
-with the current environment (@pxref{Environments}).
-
-A negative argument will reset the hyphenation space to zero, emitting a
+adjustment mode is @samp{b} or@w{ }@samp{n}, don't hyphenate the line
+if it can be justified by adding no more than @var{hyphenation_space}
+extra space to each word space. Without argument, the hyphenation
+space is set to its default value, which is@w{ }0. The default
+scaling indicator for this request is@w{ }@code{m}. The hyphenation
+space is associated with the current environment
+(@pxref{Environments}).
+
+A negative argument resets the hyphenation space to zero, emitting a
warning of type @samp{range}.
-@vindex .hys
@cindex current hyphenation space register
-The current hyphenation space is available in the @code{.hys} register.
-@end_Deffn
+The current hyphenation space is available in the @code{.hys} read-only
+number register.
+@endDefreq
@cindex soft hyphen character
@cindex character, soft hyphen
@glindex hy
-@findex char
-@findex tr
-@Deffn{Request, shc, [@var{char}]}
+@rqindex char
+@rqindex tr
+@Defreq {shc, [@Var{char}]}
Set the soft hyphen character to @var{char}. If the argument is
-omitted, the soft hyphen character will be set to the default character
+omitted, the soft hyphen character is set to the default character
@code{\(hy} (this is the start-up value of @code{gtroff} also). 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
+soft hyphen character is the character that is 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 is not 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.
-@end_Deffn
+@endDefreq
-@findex hpf
-@findex hw
+@rqindex hpf
+@rqindex hw
@pindex troffrc
@pindex troffrc-end
-@Deffn{Request, hla, language}
+@Defreq {hla, language}
+@Defregx {.hla}
Set the current hyphenation language to the string @var{language}.
Hyphenation exceptions specified with the @code{hw} request and
hyphenation patterns specified with the @code{hpf} request are both
@@ -4209,111 +4572,120 @@ request is usually invoked by the @file{troffrc} or the
@file{troffrc-end} files; @file{troffrc} sets the default language to
@samp{us}.
-@vindex .hla
@cindex current hyphenation language register
The current hyphenation language is available as a string in the
read-only number register @samp{.hla}.
-@example
+@Example
.ds curr_language \n[.hla]
\*[curr_language]
@result{} us
-@end example
-@end_Deffn
+@endExample
+@endDefreq
@c =====================================================================
-@node Manipulating Spacing, Tabs and Fields, Manipulating Hyphenation, Programming Tutorial
+@node Manipulating Spacing, Tabs and Fields, Manipulating Hyphenation, gtroff Reference
@section Manipulating Spacing
@cindex manipulating spacing
@cindex spacing, manipulating
-@Deffn{Request, sp, [@var{distance}]}
-Space downwards @var{distance}. With no argument it will advance 1@w{
-}line. A negative argument will cause @code{gtroff} to move up the page
+@Defreq {sp, [@Var{distance}]}
+Space downwards @var{distance}. With no argument it advances 1@w{
+}line. A negative argument causes @code{gtroff} to move up the page
the specified distance. If the argument is preceded by a @samp{|}
-@code{gtroff} will move that distance from the top of the page. This
+then @code{gtroff} moves that distance from the top of the page. This
request causes a line break. The default scaling indicator is@w{
}@code{v}.
-@end_Deffn
+@endDefreq
@cindex double-spacing
-@Deffn{Request, ls, [@var{nnn}]}
-Output @w{@var{nnn}-1} blank lines after each line of text. With no
-argument @code{gtroff} will use the previous value before the last
-@code{ls} call.
+@Defreq {ls, [@Var{nnn}]}
+@Defregx {.L}
+Output @w{@var{nnn}@minus{}1} blank lines after each line of text.
+With no argument, @code{gtroff} uses the previous value before the
+last @code{ls} call.
-@example
+@Example
.ls 2 \" This causes double-spaced output
.ls 3 \" This causes triple-spaced output
.ls \" Again double spaced
-@end example
+@endExample
The line spacing is associated with the current environment
(@pxref{Environments}).
-@vindex .L
@cindex current line spacing register
-The number register @code{.L} contains the current line spacing setting.
-@end_Deffn
-
-@Deffn{Escape, \\x, spacing}
-Sometimes, extra vertical spacing is only needed occasionally, e.g.@: to
-allow space for a tall construct (like an equation). The @code{\x}
-escape will do this. The escape is given a numerical argument, usually
+The read-only number register @code{.L} contains the current line
+spacing setting.
+@endDefreq
+
+@c XXX document \n[nl]
+@c XXX document \n[nl] == -1 if vertical position is zero
+
+@Defesc {\\x, ', spacing, '}
+@Defregx {.a}
+Sometimes, extra vertical spacing is only needed occasionally, e.g.@:
+to allow space for a tall construct (like an equation). The @code{\x}
+escape does this. The escape is given a numerical argument, usually
enclosed in quotes (like @samp{\x'3p'}); the default scaling indicator
-is@w{ }@code{v}. 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 of the values is used.
+is@w{ }@code{v}. If this number is positive extra vertical space is
+inserted below the current line. A negative number adds space above.
+If this escape is used multiple times on the same line, the maximum of
+the values is used.
@xref{Escapes}, for details on parameter delimiting characters.
-@vindex .a
@cindex extra vertical line space register
-The @code{.a} number register contains the most recent (nonnegative)
-extra vertical line space.
+The @code{.a} read-only number register contains the most recent
+(nonnegative) extra vertical line space.
@c XXX
@ignore
-@example
+@Example
... example of inline equation ...
-@end example
+@endExample
@end ignore
-@end_Deffn
+@endDefesc
-@findex sp
+@rqindex sp
@cindex no-space mode
@cindex mode, no-space
@cindex blank lines, disabling
@cindex lines, blank, disabling
-@Deffn{Request, ns, }
-Enable @dfn{no-space mode}. In this mode, spacing (either via @code{sp}
-or via blank lines) is disabled. The @code{bp} request to advance to
-the next page is also disabled, except if it is accompanied by a page
-number (see @ref{Page Control}, for more information). This mode will
-end when actual text is output or the @code{rs} request is encountered.
-
+@Defreq {ns, }
+Enable @dfn{no-space mode}. In this mode, spacing (either via
+@code{sp} or via blank lines) is disabled. The @code{bp} request to
+advance to the next page is also disabled, except if it is accompanied
+by a page number (see @ref{Page Control}, for more information). This
+mode ends when actual text is output or the @code{rs} request is
+encountered.
+
+@cindex top-level diversion
+@cindex diversion, top-level
This request is useful for macros which want to avoid that subsequent
macros inadvertently insert some vertical space before the text starts
(for example, to set up the first paragraph after a section header). It
-is associated with the current diversion level.
+has no effect if not called within the top-level diversion
+(@pxref{Diversions}).
@c XXX xref
-@end_Deffn
+@endDefreq
-@Deffn{Request, rs, }
-Disable no-space mode. This request is associated with the current
-diversion level.
+@cindex top-level diversion
+@cindex diversion, top-level
+@Defreq {rs, }
+Disable no-space mode. It has no effect if not called within the
+top-level diversion (@pxref{Diversions}).
@c XXX xref
-@end_Deffn
+@endDefreq
@c =====================================================================
-@node Tabs and Fields, Character Translations, Manipulating Spacing, Programming Tutorial
+@node Tabs and Fields, Character Translations, Manipulating Spacing, gtroff Reference
@section Tabs and Fields
@cindex tabs and fields
@cindex fields and tabs
@@ -4323,33 +4695,34 @@ A tab character (@acronym{ASCII} char@w{ }9, @acronym{EBCDIC} char@w{
}5) causes a horizontal movement to the next tab stop (much
like it did on a typewriter).
-@Deffn{Escape, \\t, }
+@Defesc {\\t, , , }
This escape is a non-interpreted tab character. In copy mode
(@pxref{Copy-in Mode}), @code{\t} is the same as a real tab character.
-@end_Deffn
+@endDefesc
-@Deffn{Request, ta, [@var{n1} @var{n2} @dots{} @var{nn} @t{T} @var{r1} @var{r2} @dots{} @var{rn}]}
+@Defreq {ta, [@Var{n1} @Var{n2} @dots{} @Var{nn} @t{T} @Var{r1} @Var{r2} @dots{} @Var{rn}]}
+@Defregx {.tabs}
Change tab stop positions. This request takes a series of tab
specifiers as arguments (optionally divided into two groups with the
-letter @samp{T}) which indicate where each tab stop is to be (overriding
-any previous settings).
+letter @samp{T}) which indicate where each tab stop is to be
+(overriding any previous settings).
Tab stops can be specified absolutely, i.e., as the distance from the
-left margin. For example, the following will set 6@w{ }tab stops every
+left margin. For example, the following sets 6@w{ }tab stops every
one inch.
-@example
+@Example
.ta 1i 2i 3i 4i 5i 6i
-@end example
+@endExample
-Tab stops can also be specified relatively (using a leading @samp{+})
-which means that the specified tab stop will be set that distance from
+Tab stops can also be specified using a leading @samp{+}
+which means that the specified tab stop is set relative to
the previous tab stop. For example, the following is equivalent to the
previous example.
-@example
+@Example
.ta 1i +1i +1i +1i +1i +1i
-@end example
+@endExample
@code{gtroff} supports an extended syntax to specify repeat values after
the @samp{T} mark (these values are always taken as relative) -- this is
@@ -4357,9 +4730,9 @@ the usual way to specify tabs set at equal intervals. The following is,
yet again, the same as the previous examples. It does even more since
it defines an infinite number of tab stops separated by one inch.
-@example
+@Example
.ta T 1i
-@end example
+@endExample
Now we are ready to interpret the full syntax given at the beginning:
Set tabs at positions @var{n1}, @var{n2}, @dots{}, @var{nn} and then set
@@ -4375,9 +4748,9 @@ may be justified to the right or left or centered in the column. This
is specified by appending @samp{R}, @samp{L}, or @samp{C} to the tab
specifier. The default justification is @samp{L}. Example:
-@example
+@Example
.ta 1i 2iC 2iR
-@end example
+@endExample
Some notes:
@@ -4389,22 +4762,22 @@ The default unit of the @code{ta} request is @samp{m}.
A tab stop is converted into a non-breakable horizontal movement which
can be neither stretched nor squeezed. For example,
-@example
+@Example
.ds foo a\tb\tc
.ta T 5i
\*[foo]
-@end example
+@endExample
@noindent
creates a single line which is a bit longer than 10@w{ }inches (a string
is used to show exactly where the tab characters are). Now consider the
following:
-@example
+@Example
.ds bar a\tb b\tc
.ta T 5i
\*[bar]
-@end example
+@endExample
@noindent
@code{gtroff} first converts the tab stops of the line into unbreakable
@@ -4415,10 +4788,10 @@ the user wants.
@item
Superfluous tabs (i.e., tab characters which do not correspond to a tab
stop) are ignored except the first one which delimits the characters
-belonging to the last tab stop for right-justifying resp.@: centering.
+belonging to the last tab stop for right-justifying or centering.
Consider the following example
-@example
+@Example
.ds Z foo\tbar\tfoo
.ds ZZ foo\tbar\tfoobar
.ds ZZZ foo\tbar\tfoo\tbar
@@ -4429,16 +4802,16 @@ Consider the following example
.br
\*[ZZZ]
.br
-@end example
+@endExample
@noindent
which produces the following output:
-@example
+@Example
foo bar foo
foo bar foobar
foo bar foobar
-@end example
+@endExample
@noindent
The first line right-justifies the second `foo' relative to the tab
@@ -4451,41 +4824,42 @@ Tab stops are associated with the current environment
(@pxref{Environments}).
@item
-Calling @code{ta} without an argument will unset all tab stops.
+Calling @code{ta} without an argument removes all tab stops.
@item
-@cindex tab stops, in nroff mode
-The start-up value of @code{gtroff} is @w{@samp{T 0.5i}}. This value is
-used even in nroff mode (contrary to @acronym{UNIX} @code{nroff} which
-has tab stops preset every 0.8@dmn{i}).
+@cindex tab stops, for tty output devices
+The start-up value of @code{gtroff} is @w{@samp{T 0.5i}}. This value
+is used even for tty output devices (contrary to @acronym{UNIX}
+@code{nroff} which has tab stops preset every 0.8@dmn{i}).
+
+@c XXX xref implementation differences
@end itemize
-@vindex .tabs
@cindex current tab settings register
-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.
+The read-only number register @code{.tabs} contains a string
+representation of the current tab settings suitable for use as an
+argument to the @code{ta} request.
-@example
+@Example
.ds tab-string \n[.tabs]
\*[tab-string]
@result{} T120u
-@end example
-@end_Deffn
-
-@cindex tab repitition character
-@cindex character, tab repitition
-@Deffn{Request, tc, [@var{fill-char}]}
-Normally @code{gtroff} will fill the space to the next tab stop with
-space. This can be changed with the @code{tc} request. With no
-argument @code{gtroff} will revert to using space, which is the default.
-The value of this @dfn{tab repitition} character is associated with the
-current environment (@pxref{Environments}).
-@end_Deffn
+@endExample
+@endDefreq
+
+@cindex tab repetition character
+@cindex character, tab repetition
+@Defreq {tc, [@Var{fill-char}]}
+Normally @code{gtroff} fills the space to the next tab stop with
+whitespace. This can be changed with the @code{tc} request. With no
+argument @code{gtroff} reverts to using whitespace, which is the
+default. The value of this @dfn{tab repetition} character is
+associated with the current environment (@pxref{Environments}).
+@endDefreq
@menu
-* Leaders::
-* Fields::
+* Leaders::
+* Fields::
@end menu
@c ---------------------------------------------------------------------
@@ -4498,7 +4872,7 @@ Sometimes it may may be desirable to use the @code{tc} request to fill a
particular tab stop with a given character (for example dots in a table
of contents), but also normal tab stops on the rest of the line. For
this @code{gtroff} provides an alternate tab mechanism, called
-@dfn{leaders} which will do just that.
+@dfn{leaders} which does just that.
@cindex leader character
A leader character (character code@w{ }1) behaves similarly to a tab
@@ -4506,21 +4880,21 @@ character: It moves to the next tab stop. The only difference is that
for this movement, the fill character defaults to a period character and
not to space.
-@Deffn{Escape, \\a, }
+@Defesc {\\a, , , }
This escape is a non-interpreted leader character. In copy mode
(@pxref{Copy-in Mode}), @code{\a} is the same as a real leader
character.
-@end_Deffn
-
-@cindex leader repitition character
-@cindex character, leader repitition
-@Deffn{Request, lc, [@var{fill-char}]}
-The character that will be repeated can be declared with the @code{lc}
-request. Without an argument, leaders will act the same as tabs (i.e.,
-using space for filling). @code{gtroff}'s start-up value is @samp{.}.
-The value of this @dfn{leader repitition} character is associated with
-the current environment (@pxref{Environments}).
-@end_Deffn
+@endDefesc
+
+@cindex leader repetition character
+@cindex character, leader repetition
+@Defreq {lc, [@Var{fill-char}]}
+Declare the leader character. Without an argument, leaders act the
+same as tabs (i.e., using whitespace for filling). @code{gtroff}'s
+start-up value is @samp{.}. The value of this @dfn{leader repetition}
+character is associated with the current environment
+(@pxref{Environments}).
+@endDefreq
@cindex table of contents
@cindex contents, table of
@@ -4529,19 +4903,19 @@ 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
+@Example
.ds entry 1.1\tFoo\a\t12
.lc .
.ta 1i 5i +.25i
\*[entry]
-@end example
+@endExample
@noindent
This produces
-@example
+@Example
1.1 Foo.......................................... 12
-@end example
+@endExample
@c ---------------------------------------------------------------------
@@ -4566,43 +4940,43 @@ lengths plus the stretchable space equal to the field width. If more
than one padding character is inserted, the available space is evenly
distributed among them.
-@Deffn{Request, fc, [@var{delim-char} [@var{padding-char}]]}
+@Defreq {fc, [@Var{delim-char} [@Var{padding-char}]]}
Define a delimiting and a padding character for fields. If the latter
is missing, the padding character defaults to a space character. If
there is no argument at all, the field mechanism is disabled (which is
-the default). Note that contrary to e.g.@: the tab repitition
+the default). Note that contrary to e.g.@: the tab repetition
character, delimiting and padding characters are not associated to the
current environment (@pxref{Environments}).
Example:
-@example
+@Example
.fc # ^
.ta T 3i
#foo^bar^smurf#
.br
#foo^^bar^smurf#
-@end example
+@endExample
@noindent
and here the result:
-@example
+@Example
foo bar smurf
foo bar smurf
-@end example
-@end_Deffn
+@endExample
+@endDefreq
@c =====================================================================
-@node Character Translations, Troff and Nroff Mode, Tabs and Fields, Programming Tutorial
+@node Character Translations, Troff and Nroff Mode, Tabs and Fields, gtroff Reference
@section Character Translations
@cindex character translations
@cindex translations of characters
-@findex .
-@findex '
+@rqindex .
+@rqindex '
@cindex control character
@cindex character, control
@cindex no-break control character
@@ -4612,29 +4986,30 @@ The control character (@samp{.}) and the no-break control character
(@samp{'}) can be changed with the @code{cc} and @code{c2} requests,
respectively.
-@Deffn{Request, cc, [@var{c}]}
+@Defreq {cc, [@Var{c}]}
Set the control character to @var{c}. With no argument the default
control character @samp{.} is restored. The value of the control
character is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
-@Deffn{Request, c2, [@var{c}]}
+@Defreq {c2, [@Var{c}]}
Set the no-break control character to @var{c}. With no argument the
default control character @samp{'} is restored. The value of the
no-break control character is associated with the current environment
(@pxref{Environments}).
-@end_Deffn
+@endDefreq
-@findex \
-@Deffn{Request, eo, }
-Disable the escape mechanism completely. After executing this request,
-the backslash character @samp{\} no longer starts an escape sequence.
+@esindex \\
+@Defreq {eo, }
+Disable the escape mechanism completely. After executing this
+request, the backslash character @samp{\} no longer starts an escape
+sequence.
This request can be very helpful in writing macros since it is not
necessary then to double the escape character. Here an example:
-@example
+@Example
.\" This is a simplified version of the
.\" .BR request from the man macro package
.eo
@@ -4649,27 +5024,27 @@ necessary then to double the escape character. Here an example:
. ft R
..
.ec
-@end example
-@end_Deffn
+@endExample
+@endDefreq
@cindex escape character
@cindex character, escape
-@Deffn{Request, ec, [@var{c}]}
+@Defreq {ec, [@Var{c}]}
Set the escape character to @var{c}. With no argument the default
-escape character @samp{\} is restored. It can be also used to re-enable
-the escape mechanism after an @code{eo} request.
+escape character @samp{\} is restored. It can be also used to
+re-enable the escape mechanism after an @code{eo} request.
-Note that changing the escape character globally will likely break macro
-packages since @code{gtroff} has no mechanism (like @TeX{}) to `intern'
-macros, i.e., to convert a macro definition into an internal form which
-is independent of its representation. If a macro is called, it will be
-executed literally.
-@end_Deffn
+Note that changing the escape character globally will likely break
+macro packages since @code{gtroff} has no mechanism (like @TeX{}) to
+`intern' macros, i.e., to convert a macro definition into an internal
+form which is independent of its representation. If a macro is
+called, it is executed literally.
+@endDefreq
-@Deffn{Escape, \\e, }
+@Defesc {\\e, , , }
This escape sequence prints the current escape character (which is the
backslash character @samp{\} by default).
-@end_Deffn
+@endDefesc
A @dfn{translation} is a mapping of an input character to an output
character. The default mappings are given in the font definition files
@@ -4678,24 +5053,24 @@ with @code{tr} and in the font definition files) occur at output time,
i.e., the input character gets assigned the metric information of the
mapped output character.
-@Deffn{Request, tr, @var{a}@var{b}@var{c}@var{d}@dots{}}
+@Defreq {tr, @Var{a}@Var{b}@Var{c}@Var{d}@dots{}}
Translate character @var{a} to @var{b}, character @var{c} to @var{d},
-etc. If there is an odd number of arguments, the last one will be
+etc. If there is an odd number of arguments, the last one is
translated to the space character.
Some notes:
@itemize @bullet
@item
-@findex \(
-@findex \[
-@findex \'
-@findex \`
-@findex \-
-@findex \_
-@findex \C
-@findex \N
-@findex char
+@esindex \(
+@esindex \[
+@esindex \'
+@esindex \`
+@esindex \-
+@esindex \_
+@esindex \C
+@esindex \N
+@rqindex char
@cindex special character
@cindex character, special
@cindex numbered character
@@ -4706,13 +5081,14 @@ characters defined with the @code{char} request, and numbered characters
(@code{\N'@var{xxx}'}) can be translated also.
@item
-@findex \e
+@esindex \e
The @code{\e} escape can be translated also.
@item
-@findex \%
-Characters can be mapped onto the @code{\%} escape (but @code{\%} can't
-be mapped onto another character).
+@esindex \%
+@esindex \~
+Characters can be mapped onto the @code{\%} and @code{\~} escapes (but
+@code{\%} and @code{\~} can't be mapped onto another character).
@item
@cindex backspace character
@@ -4723,45 +5099,45 @@ be mapped onto another character).
@cindex character, newline
@cindex tab character
@cindex character, tab
-@findex \a
-@findex \t
+@esindex \a
+@esindex \t
The following characters can't be translated: space (with one exception,
see below), backspace, newline, leader (and @code{\a}), tab (and
@code{\t}).
@item
-@findex shc
+@rqindex shc
Translations are not considered for finding the soft hyphen character
set with the @code{shc} request.
@item
-@findex \&
+@esindex \&
The character pair @samp{@var{c}\&} (this is an arbitrary character@w{
-}@var{c} followed by the zero width space character) will map this
+}@var{c} followed by the zero width space character) maps this
character to nothing.
-@example
+@Example
.tr a\&
foo bar
@result{} foo br
-@end example
+@endExample
@noindent
It is even possible to map the space character to nothing:
-@example
+@Example
.tr aa \&
foo bar
@result{} foobar
-@end example
+@endExample
@noindent
As shown in the example, the space character can't be the first
character pair as an argument of @code{tr}. Additionally, it is not
possible to map the space character to any other character; requests
-like @w{@samp{.tr aa x}} will undo @w{@samp{.tr aa \&}} instead.
+like @w{@samp{.tr aa x}} undo @w{@samp{.tr aa \&}} instead.
-If justification is active, lines will be justified inspite of the
+If justification is active, lines are justified in spite of the
`empty' space character (but there is no minimal distance, i.e.@: the
space character, between words).
@@ -4776,33 +5152,35 @@ string), it is no longer affected by @code{tr}.
@item
Without an argument, the @code{tr} request is ignored.
@end itemize
-@end_Deffn
+@endDefreq
-@findex \!@r{, and @code{trnt}}
-@Deffn{Request, trnt, @var{a}@var{b}@var{c}@var{d}@dots{}}
+@esindex \!
+@cindex @code{\!}, and @code{trnt}
+@Defreq {trnt, @Var{a}@Var{b}@Var{c}@Var{d}@dots{}}
@code{trnt} 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.
+translations do not apply to text that is transparently throughput
+into a diversion with @code{\!}. @xref{Diversions}, for more
+information.
For example,
-@example
+@Example
.tr ab
.di x
\!.tm a
.di
.x
-@end example
+@endExample
@noindent
-will print @samp{b}; if @code{trnt} is used instead of @code{tr} it will
-print @samp{a}.
-@end_Deffn
+prints @samp{b} to the standard error stream; if @code{trnt} is used
+instead of @code{tr} it prints @samp{a}.
+@endDefreq
@c =====================================================================
-@node Troff and Nroff Mode, Line Layout, Character Translations, Programming Tutorial
+@node Troff and Nroff Mode, Line Layout, Character Translations, gtroff Reference
@section Troff and Nroff Mode
@cindex troff mode
@cindex mode, troff
@@ -4811,43 +5189,67 @@ print @samp{a}.
Originally, @code{nroff} and @code{troff} were two separate programs,
the former for tty output, the latter for everything else. With GNU
-@code{troff}, both programs are merged into one executable.
-
-Usually, a macro package can be used with both @code{nroff} and
-@code{troff}. Nevertheless, it is sometimes necessary to make a
-distinction between the two programs (resp.@: modes), and @code{gtroff}
-provides two built-in conditions @samp{n} and @samp{t} for the
-@code{if}, @code{ie}, and @code{while} requests to decide whether
-@code{gtroff} shall behave like @code{nroff} or like @code{troff}.
+@code{troff}, both programs are merged into one executable, sending
+its output to a device driver (@code{grotty} for tty devices,
+@code{grops} for @sc{PostScript}, etc.) which interprets the
+intermediate output of @code{gtroff}. For @acronym{UNIX} @code{troff}
+it makes sense to talk about @dfn{Nroff mode} and @dfn{Troff mode}
+since the differences are hardcoded. For GNU @code{troff}, this
+distinction is not appropriate because @code{gtroff} simply takes the
+information given in the font files for a particular device without
+handling requests specially if a tty output device is used.
+
+Usually, a macro package can be used with all output devices.
+Nevertheless, it is sometimes necessary to make a distinction between
+tty and non-tty devices: @code{gtroff} provides two built-in
+conditions @samp{n} and @samp{t} for the @code{if}, @code{ie}, and
+@code{while} requests to decide whether @code{gtroff} shall behave
+like @code{nroff} or like @code{troff}.
@pindex troffrc
@pindex troffrc-end
-@Deffn{Request, troff, }
+@Defreq {troff, }
Make the @samp{t} built-in condition true (and the @samp{n} built-in
-condition false) for @code{if}, @code{ie}, and @code{while} conditional
-requests. This is the default if @code{gtroff} (@emph{not}
-@code{groff}) is started with the @option{-R} switch to avoid loading of
-the start-up files @file{troffrc} and @file{troffrc-end}. Without
-@option{-R}, @code{gtroff} stays in troff mode if the output device is
-not a tty (e.g.@: `ps').
-@end_Deffn
-
-@pindex tmac.tty
-@Deffn{Request, nroff, }
+condition false) for @code{if}, @code{ie}, and @code{while}
+conditional requests. This is the default if @code{gtroff}
+(@emph{not} @code{groff}) is started with the @option{-R} switch to
+avoid loading of the start-up files @file{troffrc} and
+@file{troffrc-end}. Without @option{-R}, @code{gtroff} stays in troff
+mode if the output device is not a tty (e.g.@: `ps').
+@endDefreq
+
+@pindex tty.tmac
+@Defreq {nroff, }
Make the @samp{n} built-in condition true (and the @samp{t} built-in
-condition false) for @code{if}, @code{ie}, and @code{while} conditional
-requests. This is the default if @code{gtroff} uses a tty output
-device; the code for switching to nroff mode is in the file
-@file{tmac.tty} which will be loaded by the start-up file
-@code{troffrc}.
-@end_Deffn
-
-@xref{Conditionals and Loops}, for more details on built-in conditions.
-
+condition false) for @code{if}, @code{ie}, and @code{while}
+conditional requests. This is the default if @code{gtroff} uses a tty
+output device; the code for switching to nroff mode is in the file
+@file{tty.tmac} which is loaded by the start-up file @code{troffrc}.
+@endDefreq
+
+@xref{Conditionals and Loops}, for more details on built-in
+conditions.
+
+@c XXX move the following to grotty section
+
+@pindex less
+@cindex Teletype
+@cindex ISO 6249 SGR
+@cindex terminal control sequences
+@cindex control sequences, for terminals
+For tty output devices, underlining is done by emitting sequences of
+@samp{_} and @samp{\b} (the backspace character) before the actual
+character. Literally, this is printing an underline character, then
+moving back one character position, and printing the actual character
+at the same position as the underline character (similar to a
+typewriter). Usually, a modern terminal can't interpret this (and the
+original Teletype machines for which this sequence was appropriate are
+no longer in use). You need a pager program like @code{less} which
+translates this into ISO 6429 SGR sequences to control terminals.
@c =====================================================================
-@node Line Layout, Page Layout, Troff and Nroff Mode, Programming Tutorial
+@node Line Layout, Page Layout, Troff and Nroff Mode, gtroff Reference
@section Line Layout
@cindex line layout
@cindex layout, line
@@ -4858,8 +5260,7 @@ The following drawing shows the dimensions which @code{gtroff} uses for
placing a line of output onto the page. They are labeled with the
request which manipulates each dimension.
-@example
-@group
+@Example
-->| in |<--
|<-----------ll------------>|
+----+----+----------------------+----+
@@ -4867,8 +5268,7 @@ request which manipulates each dimension.
+----+----+----------------------+----+
-->| po |<--
|<--------paper width---------------->|
-@end group
-@end example
+@endExample
@noindent
These dimensions are:
@@ -4886,7 +5286,7 @@ output, defining the @dfn{left margin}.
@cindex indentation
@cindex line indentation
@dfn{Indentation} -- this is the distance from the left margin where
-text will be printed.
+text is printed.
@item ll
@cindex line length
@@ -4897,7 +5297,7 @@ margin.
@c XXX improve example
-@example
+@Example
.in +.5i
.ll -.5i
A bunch of really boring text which should
@@ -4905,32 +5305,29 @@ be indented from both margins.
Replace me with a better (and more) example!
.in -.5i
.ll +.5i
-@end example
+@endExample
-@cindex troff mode
-@cindex mode, troff
-@cindex nroff mode
-@cindex mode, nroff
-@Deffn{Request, po, [@var{offset}]}
-@Deffnx{Request, po, +offset}
-@Deffnx{Request, po, -offset}
-Set horizontal page offset to @var{offset} (resp.@: increment or
-decrement the current value by @var{offset}). Note that this request
-does not cause a break, so changing the page offset in the middle of
-text being filled may not yield the expected result. The initial value
-is 1@dmn{i} if in troff mode, and 0 if in nroff mode (@pxref{Troff and
-Nroff Mode}); the default scaling indicator is@w{ }@code{m} (and not@w{
-}@code{v} as incorrectly documented in the original @acronym{UNIX} troff
-manual).
-
-@vindex .o
-The current page offset can be found in the built-in number register
+@pindex troffrc
+@Defreq {po, [@Var{offset}]}
+@Defreqx {po, @t{+}@Var{offset}}
+@Defreqx {po, @t{-}@Var{offset}}
+@Defregx {.o}
+Set horizontal page offset to @var{offset} (or increment or decrement
+the current value by @var{offset}). Note that this request does not
+cause a break, so changing the page offset in the middle of text being
+filled may not yield the expected result. The initial value is
+1@dmn{i}. For tty output devices, it is set to 0 in the startup file
+@file{troffrc}; the default scaling indicator is@w{ }@code{m} (and
+not@w{ }@code{v} as incorrectly documented in the original
+@acronym{UNIX} troff manual).
+
+The current page offset can be found in the read-only number register
@samp{.o}.
If @code{po} is called without an argument, the page offset is reset to
the previous value before the last call to @code{po}.
-@example
+@Example
.po 3i
\n[.o]
@result{} 720
@@ -4940,13 +5337,14 @@ the previous value before the last call to @code{po}.
.po
\n[.o]
@result{} 720
-@end example
-@end_Deffn
-
-@Deffn{Request, in, [@var{indent}]}
-@Deffnx{Request, in, +indent}
-@Deffnx{Request, in, -indent}
-Set indentation to @var{indent} (resp.@: increment or decrement the
+@endExample
+@endDefreq
+
+@Defreq {in, [@Var{indent}]}
+@Defreqx {in, @t{+}@Var{indent}}
+@Defreqx {in, @t{-}@Var{indent}}
+@Defregx {.i}
+Set indentation to @var{indent} (or increment or decrement the
current value by @var{indent}). This request causes a break.
Initially, there is no indentation.
@@ -4961,23 +5359,23 @@ If a negative indentation value is specified (which is not allowed),
indentation to zero.
The effect of @code{in} is delayed until a partially collected line (if
-it exists) is output.
+it exists) is output. A temporary indent value is reset to zero also.
-@vindex .i
The current indentation (as set by @code{in}) can be found in the
-built-in number register @samp{.i}.
-@end_Deffn
+read-only number register @samp{.i}.
+@endDefreq
-@Deffn{Request, ti, offset}
-@Deffnx{Request, ti, +offset}
-@Deffnx{Request, ti, -offset}
+@Defreq {ti, offset}
+@Defreqx {ti, @t{+}@Var{offset}}
+@Defreqx {ti, @t{-}@Var{offset}}
+@Defregx {.in}
Temporarily indent the next output line by @var{offset}. If an
increment or decrement value is specified, adjust the temporary
indentation relative to the value set by the @code{in} request.
This request causes a break; its value is associated with the current
-environment. The default scaling indicator is@w{ }@code{m}. A call of
-@code{ti} without an argument is ignored.
+environment. The default scaling indicator is@w{ }@code{m}. A call
+of @code{ti} without an argument is ignored.
If the total indentation value is negative (which is not allowed),
@code{gtroff} emits a warning of type @samp{range} and sets the
@@ -4988,23 +5386,24 @@ normal indentation, if @var{offset} is given as a relative value.
The effect of @code{ti} is delayed until a partially collected line (if
it exists) is output.
-@vindex .in
-The number register @code{.in} is the indentation that applies to the
-current output line.
+The read-only number register @code{.in} is the indentation that applies
+to the current output line.
The difference between @code{.i} and @code{.in} is that the latter takes
into account whether a partially collected line still uses the old
-indentation value resp.@: a temporary indentation value is active.
-@end_Deffn
-
-@Deffn{Request, ll, [@var{length}]}
-@Deffnx{Request, ll, +length}
-@Deffnx{Request, ll, -length}
-Set the line length to @var{length} (resp.@: increment or decrement the
+indentation value or a temporary indentation value is active.
+@endDefreq
+
+@Defreq {ll, [@Var{length}]}
+@Defreqx {ll, @t{+}@Var{length}}
+@Defreqx {ll, @t{-}@Var{length}}
+@Defregx {.l}
+@Defregx {.ll}
+Set the line length to @var{length} (or increment or decrement the
current value by @var{length}). Initially, the line length is set to
6.5@dmn{i}. The effect of @code{ll} is delayed until a partially
-collected line (if it exists) is output. The default scaling indicator
-is@w{ }@code{m}.
+collected line (if it exists) is output. The default scaling
+indicator is@w{ }@code{m}.
If @code{ll} is called without an argument, the line length is reset to
the previous value before the last call to @code{ll}. If a negative
@@ -5013,22 +5412,20 @@ warning of type @samp{range} and sets the line length to zero.
The line length is associated with the current environment.
-@vindex .l
-@vindex .ll
@cindex current line length register
The current line length (as set by @code{ll}) can be found in the
-built-in number register @code{.l}. The number register @code{.ll} is
-the line length that applies to the current output line.
+read-only number register @samp{.l}. The read-only number register
+@code{.ll} is the line length that applies to the current output line.
Similar to @code{.i} and @code{.in}, the difference between @code{.l}
and @code{.ll} is that the latter takes into account whether a partially
collected line still uses the old line length value.
-@end_Deffn
+@endDefreq
@c =====================================================================
-@node Page Layout, Page Control, Line Layout, Programming Tutorial
+@node Page Layout, Page Control, Line Layout, gtroff Reference
@section Page Layout
@cindex page layout
@cindex layout, page
@@ -5038,16 +5435,16 @@ page layout.
@cindex page length
@cindex length of page
-@Deffn{Request, pl, [@var{length}]}
-@Deffnx{Request, pl, +length}
-@Deffnx{Request, pl, -length}
-Set the @dfn{page length} to @var{length} (resp.@: increment or
-decrement the current value by @var{length}). This is the length of the
+@Defreq {pl, [@Var{length}]}
+@Defreqx {pl, @t{+}@Var{length}}
+@Defreqx {pl, @t{-}@Var{length}}
+@Defregx {.p}
+Set the @dfn{page length} to @var{length} (or increment or decrement
+the current value by @var{length}). This is the length of the
physical output page. The default scaling indicator is@w{ }@code{v}.
-@vindex .p
@cindex current page length register
-The current setting can be found in the built-in number register
+The current setting can be found in the read-only number register
@samp{.p}.
@cindex top margin
@@ -5055,13 +5452,16 @@ The current setting can be found in the built-in number register
@cindex bottom margin
@cindex margin, bottom
Note that this only specifies the size of the page, not the top and
-bottom margins. Those are not set by groff directly. @xref{Traps}, for
-further information on how to do this.
+bottom margins. Those are not set by @code{gtroff} directly.
+@xref{Traps}, for further information on how to do this.
Negative @code{pl} values are possible also, but not very useful: No
trap is sprung, and each line is output on a single page (thus
suppressing all vertical spacing).
-@end_Deffn
+
+If no argument or an invalid argument is given, @code{pl} sets the page
+length to 11@dmn{i}.
+@endDefreq
@cindex headers
@cindex footers
@@ -5071,132 +5471,184 @@ and bottom titles (or headers and footers).
@cindex title line
@cindex three-part title
-@findex tl
-@vindex %
-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. This character can be changed
-with the @code{pc} request (see below).
+@cindex page number character
+@Defreq {tl, @t{'}@Var{left}@t{'}@Var{center}@t{'}@Var{right}@t{'}}
+Print a @dfn{title line}. It consists of three parts: a left
+justified portion, a centered portion, and a right justified portion.
+The argument separator @samp{'} can be replaced with any character not
+occurring in the title line. The @samp{%} character is replaced with
+the current page number. This character can be changed with the
+@code{pc} request (see below).
+
+Without argument, @code{tl} is ignored.
+
+Some notes:
+
+@itemize @bullet
+@item
+A title line is not restricted to the top or bottom of a page.
+
+@item
+@code{tl} prints the title line immediately, ignoring a partially filled
+line (which stays untouched).
+
+@item
+It is not an error to omit closing delimiters. For example,
+@w{@samp{.tl /foo}} is equivalent to @w{@samp{.tl /foo///}}: It prints a
+title line with the left justified word @samp{foo}; the centered and
+right justfied parts are empty.
+
+@item
+Any modifications to the current environment within @code{tl} (e.g.@:
+changing the font or font size) are undone after processing @code{tl}.
+
+@item
+@code{tl} accepts the same parameter delimiting characters as the
+@code{\A} escape; see @ref{Escapes}.
+@end itemize
+@endDefreq
@cindex length of title line
@cindex title line, length
-@findex lt
-@vindex .lt
@cindex current title line length register
-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.
+@Defreq {lt, [@Var{length}]}
+@Defreqx {lt, @t{+}@Var{length}}
+@Defreqx {lt, @t{-}@Var{length}}
+@Defregx {.lt}
+The title line is printed using its own line length, which is
+specified (or incremented or decremented) with the @code{lt} request.
+Initially, the title line length is set to 6.5@dmn{i}. If a negative
+line length is specified (which is not allowed), @code{gtroff} emits a
+warning of type @samp{range} and sets the title line length to zero.
+The default scaling indicator is@w{ }@code{m}. If @code{lt} is called
+without an argument, the title length is reset to the previous value
+before the last call to @code{lt}.
+
+The current setting of this is available in the @code{.lt} read-only
+number register; it is associated with the current environment
+(@pxref{Environments}).
+
+@endDefreq
@cindex page number
@cindex number, page
-@findex pn
-The @code{pn} request will change the page number of the @emph{next}
-page. The only argument is the page number.
+@Defreq {pn, page}
+@Defreqx {pn, @t{+}@Var{page}}
+@Defreqx {pn, @t{-}@Var{page}}
+@Defregx {.pn}
+Change (increase or decrease) the page number of the @emph{next} page.
+The only argument is the page number; the request is ignored without a
+parameter.
+
+The read-only 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@w{ }1.
+@endDefreq
-@vindex %
-@vindex .pn
@cindex current page number register
-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@w{ }1.
+@Defreg {%}
+A read-write register holding the current page number.
+@endDefreg
@cindex changing the page number character
@cindex page number character, changing
-@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.
+@vindex %
+@Defreq {pc, [@Var{char}]}
+Change the page number character (used by the @code{tl} request) to a
+different character. With no argument, this mechanism is disabled.
+Note that this doesn't affect the number register @code{%}.
+@endDefreq
@xref{Traps}.
@c =====================================================================
-@node Page Control, Fonts, Page Layout, Programming Tutorial
+@node Page Control, Fonts, Page Layout, gtroff Reference
@section Page Control
@cindex page control
@cindex control, page
-@findex bp
-@findex pn
+@rqindex pn
@cindex new page
-To stop processing the current page, and move to the next page, invoke
-the @code{bp} request. This request will also cause a break. It 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
+@Defreq {bp, [@Var{page}]}
+@Defreqx {bp, @t{+}@Var{page}}
+@Defreqx {bp, @t{-}@Var{page}}
+Stop processing the current page and move to the next page. This
+request causes a break. It can also take an argument to set
+(increase, decrease) the page number of the next page. 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 \" define macro
+'bp \" begin page
+'sp .5i \" vertical space
+.tl 'left top'center top'right top' \" title
+'sp .3i \" vertical space
+.. \" end macro
+@endExample
+
+@cindex top-level diversion
+@cindex diversion, top-level
+@code{bp} has no effect if not called within the top-level diversion
+(@pxref{Diversions}).
+@endDefreq
+
+@cindex orphan line
+@Defreq {ne, [@Var{space}]}
It is often necessary to force 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 (see @ref{Traps}, for
-further information). The default unit for @code{ne} is @code{v} and
-the default argument is@w{ }1@dmn{v}.
+request ensures that there is a certain distance, specified by the
+first argument, before the next page is triggered (see @ref{Traps},
+for further information). The default unit for @code{ne} is @samp{v};
+the default value of @var{space} is@w{ }1@dmn{v} if no argument is
+given.
For example, to make sure that no fewer than 2@w{ }lines get orphaned,
do the following before each paragraph:
-@example
+@Example
.ne 2
-.ti +5n
-text
-@end example
-
-@findex sv
-@findex os
-@findex ne
-@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@w{ }1@dmn{v}
-and the default unit is @code{v}.
+text text text
+@endExample
+@endDefreq
+
+@rqindex os
+@rqindex ne
+@Defreq {sv, [@Var{space}]}
+@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 is
+output immediately (ignoring a partial filled line which stays
+untouched). If there is not enough space, it is stored for later
+output via the @code{os} request. The default value is@w{ }1@dmn{v}
+if no argument is given; the default unit is @samp{v}.
+@endDefreq
@c =====================================================================
-@node Fonts, Sizes, Page Control, Programming Tutorial
+@node Fonts, Sizes, Page Control, gtroff Reference
@section Fonts
@cindex fonts
-@findex ft
-@findex \f
-@code{gtroff} has the ability to switch fonts at any point in the text.
-There are two ways to do this, via the @code{ft} request and the
-@code{\f} escape.
-
-Fonts are generally specified as upper-case strings, which are usually
-1@w{ }to 4 characters representing an abbreviation or acronym of the font
-name.
+@code{gtroff} can switch fonts at any point in the text.
-The basic set of fonts are @samp{R}, @samp{I}, @samp{B}, and @samp{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). Such symbols fonts cannot be used directly, but should be
-used via an escape.
+The basic set of fonts is @samp{R}, @samp{I}, @samp{B}, and @samp{BI}.
+These are Times Roman, Italic, Bold, and Bold Italic. For non-tty
+devices, there is also at least one symbol font which contains various
+special symbols (Greek, mathematics).
@menu
-* Changing Fonts::
-* Font Families::
-* Font Positions::
-* Using Symbols::
-* Artificial Fonts::
-* Ligatures and Kerning::
+* Changing Fonts::
+* Font Families::
+* Font Positions::
+* Using Symbols::
+* Special Fonts::
+* Artificial Fonts::
+* Ligatures and Kerning::
@end menu
@c ---------------------------------------------------------------------
@@ -5206,93 +5658,67 @@ used via an escape.
@cindex changing fonts
@cindex fonts, changing
-@findex ft
+@rqindex sty
+@rqindex fam
+@kindex styles
+@kindex family
+@pindex DESC
+@Defreq {ft, [@Var{font}]}
+@Defescx {\\f, , f, }
+@Defescx {\\f, @lparen{}, fn, }
+@Defescx {\\f, @lbrack{}, font, @rbrack}
+The @code{ft} request and the @code{\f} escape change the current font
+to @var{font} (one-character name @var{f}, two-character name
+@var{fn}).
+
+If @var{font} is a style name (as set with the @code{sty} request or
+with the @code{styles} command in the @file{DESC} file), use it within
+the current font family (as set with the @code{fam} request or with
+the @code{family} command in the @file{DESC} file).
+
@cindex previous font
@cindex font, previous
-Font changes can be done either with the @code{ft} request or the
-@code{\f} request. With no arguments, it will switch to the previous
-font (also known as @samp{P}).
+With no argument or using @samp{P} as an argument, @code{.ft} switches
+to the previous font. Use @code{\fP} or @code{\f[P]} to do this with
+the escape.
-@example
+Fonts are generally specified as upper-case strings, which are usually
+1@w{ }to 4 characters representing an abbreviation or acronym of the
+font name. This is no limitation, just a convention.
+
+The example below produces two identical lines.
+
+@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
-
-@noindent
-Both of the above examples will produce the same output. Note the usage
-of @samp{P} to indicate the previous font -- using @code{\f} it is not
-possible to omit this parameter.
-
-Sometimes, when putting letters of different fonts, more or less space at
-such boundaries are needed. There are two escapes to help with this.
-
-@findex \/
-@cindex italic correction
-@cindex correction, italic
-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@w{ }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. This small
-amount of space is also called @dfn{italic correction}.
-
-@c XXX example
-@c producing @i{f}), which is ugly. Inserting \/ produces f) and avoids
-@c this problem.
-
-@findex \,
-@cindex left italic correction
-@cindex correction, left italic
-The @code{\,} escape modifies the spacing of the following character so
-that the spacing between that character and the preceding character will
-be 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. In analogy to above, this space could be called @dfn{left italic
-correction}, but this term isn't used widely.
-
-@c XXX example
-@c For example, inserting \, between the parenthesis and the f changes
-@c (f to (f.
-
-@findex ftr
-@findex ft
-@findex ul
-@findex bd
-@findex \f
-@findex cs
-@findex tkf
-@findex special
-@findex fspecial
-@findex fp
-@findex code
-The @code{ftr} request will translate fonts; its syntax is
-
-@example
-.ftr @var{F} @var{G}
-@end example
-
-@noindent
-which translates font@w{ }@var{F} to font@w{ }@var{G}. Whenever a font
-named @var{F} is referred to in a @code{\f} escape sequence, or in the
-@code{ft}, @code{ul}, @code{bd}, @code{cs}, @code{tkf}, @code{special},
-@code{fspecial}, @code{fp}, or @code{code} requests, font@w{ }@var{G}
-will be used. If @var{G} is missing, or equal to @var{F} then font@w{
-}@var{F} will not be translated.
+@endExample
+
+@xref{Font Positions}, for an alternative syntax.
+@endDefreq
+
+@rqindex ft
+@rqindex ul
+@rqindex bd
+@esindex \f
+@rqindex cs
+@rqindex tkf
+@rqindex special
+@rqindex fspecial
+@rqindex fp
+@rqindex code
+@Defreq {ftr, f [@Var{g}]}
+Translate font@w{ }@var{f} to font@w{ }@var{g}. Whenever a font named
+@var{f} is referred to in a @code{\f} escape sequence, or in the
+@code{ft}, @code{ul}, @code{bd}, @code{cs}, @code{tkf},
+@code{special}, @code{fspecial}, @code{fp}, or @code{code} requests,
+font@w{ }@var{g} is used. If @var{g} is missing or equal to @var{f}
+the translation is undone.
+@endDefreq
@c ---------------------------------------------------------------------
@@ -5300,38 +5726,120 @@ will be used. If @var{G} is missing, or equal to @var{F} then font@w{
@subsection Font Families
@cindex font families
@cindex families, font
+@cindex font styles
+@cindex styles, font
Due to the variety of fonts available, @code{gtroff} has added the
-concept of font families. Each of these families has four styles
-(@samp{R}, @samp{I}, @samp{B} and @samp{BI}).
+concept of @dfn{font families} and @dfn{font styles}. The fonts are
+specified as the concatenation of the font family and style. Specifying
+a font without the family part causes @code{gtroff} to use that style of
+the current family.
-The fonts are specified as the concatenation of the font family and
-style. Specifying a font without the family part will cause
-@code{gtroff} to use that style of the current family. By default,
-@code{gtroff} uses the Times family.
+@cindex postscript fonts
+@cindex fonts, postscript
+Currently, only @sc{PostScript} fonts are set up to this mechanism.
+By default, @code{gtroff} uses the Times family with the four styles
+@samp{R}, @samp{I}, @samp{B}, and @samp{BI}.
This way, it is possible to use the basic four fonts and to select a
-different font family on the command line.
+different font family on the command line (@pxref{Groff Options}).
-@findex fam
-@vindex .fam
-Font families can be switched with the @code{fam} request. The current
-font family is available in the number register @code{.fam}. This is a
-string-valued register.
+@Defreq {fam, [@Var{family}]}
+@Defregx {.fam}
+Switch font family to @var{family}. If no argument is given, switch
+back to the previous font family. The current font family is available
+in the read-only number register @samp{.fam} (this is a string-valued
+register); it is associated with the current environment.
-@example
-spam,
-.fam H
-spam,
-.ft B
+@Example
spam,
-.fam T
+.fam H \" helvetica family
+spam, \" used font is family H + style R = HR
+.ft B \" family H + style B = font HB
spam,
-.ft AR
+.fam T \" times family
+spam, \" used font is family T + style B = TB
+.ft AR \" font AR (not a style)
baked beans,
-.ft R
+.ft R \" family T + style R = font TR
and spam.
-@end example
+@endExample
+@endDefreq
+
+@rqindex cs
+@rqindex bd
+@rqindex tkf
+@rqindex uf
+@rqindex fspecial
+@Defreq {sty, n style}
+Associate @var{style} with font position@w{ }@var{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@w{ }1 and font position@w{ }1 is associated with style@w{
+}@samp{R} and the current font family is@w{ }@samp{T}, then font
+@samp{TR} will be used. If the current font is not a style, then the
+current family is ignored. When the requests @code{cs}, @code{bd},
+@code{tkf}, @code{uf}, or @code{fspecial} are applied to a style, then
+they will instead be applied to the member of the current family
+corresponding to that style.
+
+@var{n} must be a non-negative integer value.
+
+@pindex DESC
+@kindex styles
+The default family can be set with the @option{-f} option
+(@pxref{Groff Options}). The @code{styles} command in the @file{DESC}
+file controls which font positions (if any) are initially associated
+with styles rather than fonts. For example, the default setting for
+@sc{PostScript} fonts
+
+@Example
+styles R I B BI
+@endExample
+
+@noindent
+is equivalent to
+
+@Example
+.sty 1 R
+.sty 2 I
+.sty 3 B
+.sty 4 BI
+@endExample
+
+@code{.fam} always checks whether the current font position is valid;
+this can give surprising results if the current font position is
+associated with a style.
+
+In the following example, we want to access the @sc{PostScript} font
+@code{FooBar} from the font family @code{Foo}:
+
+@Example
+.sty \n[.fp] Bar
+.fam Foo
+ @result{} warning: can't find font `FooR'
+@endExample
+
+@noindent
+The default font position at start-up is@w{ }1; for the
+@sc{PostScript} device, this is associated with style @samp{R}, so
+@code{gtroff} tries to open @code{FooR}.
+
+A solution to this problem is to use a dummy font like the following:
+
+@Example
+.fp 0 dummy TR \" set up dummy font at position 0
+.sty \n[.fp] Bar \" register style `Bar'
+.ft 0 \" switch to font at position 0
+.fam Foo \" activate family `Foo'
+.ft Bar \" switch to font `FooBar'
+@endExample
+
+@xref{Font Positions}.
+@endDefreq
@c ---------------------------------------------------------------------
@@ -5340,132 +5848,199 @@ and spam.
@cindex font positions
@cindex positions, font
-For the sake of old phototypesetters and compatability with old versions
+For the sake of old phototypesetters and compatibility with old versions
of @code{troff}, @code{gtroff} 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
-@code{gtroff} 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
+on which various fonts are mounted.
-@noindent
-Note that after these font changes have taken place, the original font
-is restored.
+@Defreq {fp, pos font [@Var{external-name}]}
+@Defregx {.f}
+@Defregx {.fp}
+Mount font @var{font} at position @var{pos} (which must be a
+non-negative integer). This numeric position can then be referred to
+with font changing commands. When @code{gtroff} starts it is using
+font position@w{ }1 (which must exist; position@w{ }0 is unused
+usually at start-up).
-@vindex .f
@cindex current font position register
-The current font in use, as a font position, is available in number
-register @code{.f}. This can be useful to remember the current font,
-for later recall.
+The current font in use, as a font position, is available in the
+read-only number register @samp{.f}. This can be useful to remember the
+current font for later recall. It is associated with the current
+environment (@pxref{Environments}).
-@example
-.nr save-font \n(.f
-... lots 'o text ...
+@Example
+.nr save-font \n[.f]
+.ft B
+... text text text ...
.ft \n[save-font]
-@end example
+@endExample
-@vindex .fp
@cindex next free font position register
-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:
+The number of the next free font position is available in the read-only
+number register @samp{.fp}. This is useful when mounting a new font,
+like so:
-@example
+@Example
.fp \n[.fp] NEATOFONT
-@end example
+@endExample
@pindex DESC@r{, and font mounting}
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 mounted 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 @code{gtroff} 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 next available font position when they are referenced. If a font
+is to be mounted 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 @code{gtroff}
+does not enforce this strictly, it is not allowed to mount a font at a
+position whose number is much greater (approx.@: 1000 positions) than
+that of any currently used position.
-@findex fp
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 @code{gtroff} after it has
-been mounted. If there is no third argument then the internal name will
-be used as the external name. This feature make it possible to use
+been mounted. If there is no third argument then the internal name is
+used as the external name. This feature makes it possible to use
fonts with long names in compatibility mode.
+@endDefreq
+
+Both the @code{ft} request and the @code{\f} escape have alternative
+syntax forms to access font positions.
+
+@rqindex sty
+@rqindex fam
+@kindex styles
+@kindex family
+@pindex DESC
+@Defreq {ft, nnn}
+@Defescx {\\f, , n, }
+@Defescx {\\f, @lparen{}, nn, }
+@Defescx {\\f, @lbrack{}, nnn, @rbrack}
+Change the current font position to @var{nnn} (one-digit position
+@var{n}, two-digit position @var{nn}), which must be a non-negative
+integer.
+
+If @var{nnn} is associated with a style (as set with the @code{sty}
+request or with the @code{styles} command in the @file{DESC} file), use
+it within the current font family (as set with the @code{fam} request or
+with the @code{family} command in the @file{DESC} file).
+
+@Example
+this is font 1
+.ft 2
+this is font 2
+.ft \" switch back to font 1
+.ft 3
+this is font 3
+.ft
+this is font 1 again
+@endExample
+
+@xref{Changing Fonts}, for the standard syntax form.
+@endDefreq
@c ---------------------------------------------------------------------
-@node Using Symbols, Artificial Fonts, Font Positions, Fonts
+@node Using Symbols, Special 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 (usually 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
-characters long, or surrounded by square brackets. So, the symbol for
-the mathematical Greek letter `pi' can be produced either by @code{\(*p}
-or @code{\[*p]}.
+@cindex glyph
+@cindex character
+@cindex ligature
+A @dfn{glyph} is a graphical representation of a @dfn{character}.
+While a character is an abstract entity containing semantic
+information, a glyph is something which can be actually seen on screen
+or paper. It is possible that a character has multiple glyph
+representation forms (for example, the character `A' can be either
+written in a roman or an italic font, yielding two different glyphs);
+sometimes more than one character maps to a single glyph (this is a
+@dfn{ligature} -- the most common is `fi').
-@example
-area = \(*p\fIr\fP\u2\d
-@end example
+@c XXX
-@findex \C
-The escape @code{\C'@var{xxx}'} will typeset the 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 @code{ditroff} and is available in compatibility mode.
-
-@findex \N
-@findex char
-The escape @code{\N'@var{n}'} will typeset the character with code@w{
-}@var{n} in the current font. @var{n} can be any integer. Most devices
-only have characters with codes between 0 and@w{ }255. If the current
-font does not contain a character with that code, special fonts will
-@emph{not} be searched. The @code{\N} escape sequence can be
-conveniently used on conjunction with the @code{char} request:
+Please note that currently the distinction between glyphs and
+characters in this reference is not clearly carried out. This will be
+improved eventually in the next revision.
-@example
-.char \[phone] \f(ZD\N'37'
-@end example
+@cindex symbol
+@cindex special fonts
+@kindex fonts
+@pindex DESC
+@rqindex fspecial
+A @dfn{symbol} is simply a named glyph. Within @code{gtroff}, all
+glyph names of a particular font are defined in its font file. If the
+user requests a glyph not available in this font, @code{gtroff} looks
+up an ordered list of @dfn{special fonts}. By default, the
+@sc{PostScript} output device supports the two special fonts @samp{SS}
+(slanted symbols) and @samp{S} (symbols) (the former is looked up
+before the latter). Other output devices use different names for
+special fonts. Fonts mounted with the @code{fonts} keyword in the
+@file{DESC} file are globally available. To install additional
+special fonts locally (i.e.@: for a particular font), use the
+@code{fspecial} request.
+
+@xref{Font Files}, and @ref{Special Fonts}, for more details.
+
+@Defesc {\\, @lparen{}, nm, }
+@Defescx {\\, @lbrack{}, name, @rbrack}
+Insert a symbol @var{name} (two-character name @var{nm}). There is no
+special syntax for one-character names -- the natural form
+@samp{\@var{n}} would collide with escapes.
+
+If @var{name} is undefined, a warning of type @samp{char} is generated,
+and the escape is ignored. @xref{Debugging}, for information about
+warnings.
+
+The list of available symbols is device dependent; see @ref{Glyph Name
+Index} for some of them discussed in this reference.
+
+@c XXX list of common symbols
+@endDefesc
+
+@Defesc {\\C, ', xxx, '}
+Typeset the 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 newer versions of @code{ditroff} and is available in
+compatibility mode.
+@endDefesc
+
+@rqindex char
+@cindex unicode
+@Defesc {\\N, ', n, '}
+Typeset the character with code@w{ }@var{n} in the current font (this
+is @strong{not} the input character code). @var{n} can be any
+integer. Most devices only have characters with codes between 0
+and@w{ }255; the Unicode output device uses codes in the range
+0--65535. If the current font does not contain a character with that
+code, special fonts are @emph{not} searched. The @code{\N} escape
+sequence can be conveniently used in conjunction with the @code{char}
+request:
+
+@Example
+.char \[phone] \f[ZD]\N'37'
+@endExample
@noindent
@pindex DESC
@cindex unnamed characters
@cindex characters, unnamed
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.
+description file after the @code{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.
+@endDefesc
@c XXX should be `glyph', not `character'
-@findex cflags
@cindex character properties
@cindex properties of characters
+@Defreq {cflags, n c1 c2 @dots{}}
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.
+argument is the the sum of the desired flags and the remaining
+arguments are the characters to have those properties. It is possible
+to omit the spaces between the characters.
@table @code
@item 1
@@ -5511,98 +6086,185 @@ this property)
@glindex dg
@glindex rq
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 @dfn{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).
+this property is treated as the end of a sentence if followed by a
+newline or two spaces; in other words the character is
+@dfn{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
+@endDefreq
-@findex char
@cindex defining characters
@cindex characters, defining
@cindex creating new characters
-New characters can be created with the @code{char} request. It is
-called as
-
-@example
-.char @var{c} @var{string}
-@end example
-
-@findex tr
-@findex lc
-@findex \l
-@findex \L
-@findex hcode
-@noindent
-This defines character@w{ }@var{c} to be @var{string}. Every time
-character@w{ }@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 @samp{\} while @var{string} is being
-processed. Any emboldening, constant spacing or track kerning will be
+@cindex escape character
+@cindex character, escape
+@rqindex tr
+@rqindex cp
+@rqindex rc
+@rqindex lc
+@esindex \l
+@esindex \L
+@esindex \&
+@esindex \e
+@rqindex hcode
+@Defreq {char, c [@Var{string}]}
+Define a new character@w{ }@var{c} to be @var{string} (which can be
+empty). Every time character@w{ }@var{c} needs to be printed,
+@var{string} is processed in a temporary environment and the result is
+wrapped up into a single object. Compatibility mode is turned off and
+the escape character is set to @samp{\} while @var{string} is being
+processed. Any emboldening, constant spacing or track kerning is
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
+@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 is handled
+like normal characters not defined with @code{char}.
+@endDefreq
+
@cindex removing character definition
@cindex character, removing definition
-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.
+@Defreq {rchar, c1 c2 @dots{}}
+Remove the definitions of characters @var{c1}, @var{c2},@w{
+}@enddots{} This undoes the effect of a @code{char} request.
+
+It is possible to omit the whitespace between arguments.
+@endDefreq
@xref{Special Characters}.
@c ---------------------------------------------------------------------
-@node Artificial Fonts, Ligatures and Kerning, Using Symbols, Fonts
+@node Special Fonts, Artificial Fonts, Using Symbols, Fonts
+@subsection Special Fonts
+@cindex special fonts
+@cindex fonts, special
+
+@c XXX
+
+To be written.
+
+@c ---------------------------------------------------------------------
+
+@node Artificial Fonts, Ligatures and Kerning, Special Fonts, Fonts
@subsection Artificial Fonts
@cindex artificial fonts
@cindex fonts, artificial
There are a number of requests for artificially creating fonts. These
-are largely vestigial remains from the days when output devices did not
-have a wide variety of fonts, and when @code{nroff} and @code{troff}
-were separate programs. These are no longer necessary in GNU
-@code{troff}.
+are largely vestiges of the days when output devices did not have a
+wide variety of fonts, and when @code{nroff} and @code{troff} were
+separate programs. These are no longer necessary in GNU
+@code{troff}. Nevertheless, they are supported.
-@findex ul
@cindex underlining
-The @code{ul} request will print subsequent lines in italics on a device
-capable of it, or underline the text on a character output device. The
-single argument is the number of lines to be ``underlined,'' with no
-argument, the next line will be underlined.
+@Defreq {ul, [@Var{lines}]}
+The @code{ul} request normally underlines subsequent lines if a tty
+output device is used. Otherwise, the lines are printed in italics
+(only the term `underlined' is used in the following). The single
+argument is the number of input lines to be underlined; with no
+argument, the next line is underlined. If @var{lines} is zero or
+negative, stop the effects of @code{ul} (if it was active). Requests
+and empty lines do not count for computing the number of underlined
+input lines, even if they produce some output like @code{tl}. Lines
+inserted by macros (e.g.@: invoked by a trap) do count.
+
+At the beginning of @code{ul}, the current font is stored and the
+underline font is activated. Within the span of a @code{ul} request,
+it is possible to change fonts, but after the last line affected by
+@code{ul} the saved font is restored.
+
+@cindex underline font
+@cindex font, for underlining
+@rqindex uf
+This command is associated with the current environment. The
+underline font can be changed with the @code{uf} request.
+
+@c XXX @xref should be changed to grotty
+
+@xref{Troff and Nroff Mode}, for a discussion how underlining is
+implemented in for tty output devices, and which problems can arise.
+
+The @code{ul} request does not underline spaces.
+@endDefreq
-@findex cu
@cindex continuous underlining
@cindex underlining, continuous
-The @code{cu} request is similar to @code{ul} ...
+@Defreq {cu, [@Var{lines}]}
+The @code{cu} request is similar to @code{ul} but underlines spaces as
+well (if a tty output device is used).
+@endDefreq
-@c XXX more info
-
-@findex uf
@cindex underline font
@cindex font for underlining
-The @code{uf} request will set the underline font used by @code{ul} and
-@code{cu}.
+@rqindex ul
+@rqindex cu
+@Defreq {uf, font}
+Set the underline font (globally) used by @code{ul} and @code{cu}. By
+default, this is the font at position@w{ }2. @var{font} can be either
+a non-negative font position or the name of a font.
+@endDefreq
-@findex bd
@cindex imitating bold face
@cindex bold face, imitating
-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.
+@Defreq {bd, font [@Var{offset}]}
+@Defreqx {bd, font1 font2 [@Var{offset}]}
+@Defregx {.b}
+Artificially create a bold font by printing each character twice,
+slightly offset.
+
+Two syntax forms are available.
+
+@itemize @bullet
+@item
+Imitate a bold font unconditionally. The first argument specifies the
+font to embolden, and the second is the number of basic units, minus
+one, by which the two characters is offset. If the second argument is
+missing, emboldening is turned off.
+
+@var{font} can be either a non-negative font position or the name of a
+font.
+
+@var{offset} is available in the @code{.b} read-only register if a
+special font is active; in the @code{bd} request, its default unit is
+@samp{u}.
+
+@rqindex fspecial
+@kindex special
+@cindex embolding of special fonts
+@cindex special fonts, emboldening
+@item
+Imitate a bold form conditionally. Embolden @var{font1} by
+@var{offset} only if font @var{font2} is the current font. This
+command can be issued repeatedly to set up different emboldening
+values for different current fonts. If the second argument is
+missing, emboldening is turned off for this particular current font.
+
+This affects special fonts only (either set up with the @code{special}
+command in font files or with the @code{fspecial} request).
+@end itemize
+@endDefreq
+
+@cindex constant character space mode
+@cindex mode for constant character space
+@cindex character, constant space
+@rqindex ps
+@Defreq {cs, font [@Var{width} [@Var{em-size}]]}
+Switch to and from constant character space mode. If activated, the
+width of every character is @math{@var{width}/36} ems. The em size is
+given absolutely by @var{em-size}; if this argument is missing, the em
+value is taken from the current font size (as set with the @code{ps}
+request) when the font is effectively in use. Without second and
+third argument, constant character space mode is deactivated.
+
+Default unit for @var{em-size} is @samp{z}; @var{width} is an integer.
+@endDefreq
@c ---------------------------------------------------------------------
@@ -5611,68 +6273,192 @@ missing, emboldening will be turned off.
@cindex ligatures and kerning
@cindex kerning and ligatures
-@c XXX What are ligatures?
+Ligatures are groups of characters that are run together. For
+example, the letters `f' and `i' can form a ligature `fi' as in the
+word `file'. This produces a cleaner look (albeit subtle) to the
+printed output. Usually, ligatures are not available in fonts for tty
+output devices.
-@c XXX more info
+Most @sc{PostScript} fonts support the fi and fl ligatures. The C/A/T
+typesetter that was the target of AT&T @code{troff} also supported
+`ff', `ffi', and `ffl' ligatures. Advanced typesetters or `expert'
+fonts may include ligatures for `ft' and `ct', although GNU
+@code{troff} does not support these (yet).
-@findex lg
-@vindex .lg
@cindex ligatures enabled register
+@Defreq {lg, [@Var{flag}]}
+@Defregx {.lg}
The ligature mechanism can be switched on or off with the @code{lg}
-request; if the parameter is non-zero or missing, ligatures are enabled,
-otherwise disabled. Default is on. The current ligature mode can be
-found in the number register @code{.lg} (set to@w{ }1 if ligatures are
-enabled, 0@w{ }otherwise).
-
-@c XXX What is kerning?
+request; if the parameter is non-zero or missing, ligatures are
+enabled, otherwise disabled. Default is on. The current ligature
+mode can be found in the read-only number register @code{.lg} (set to
+1 or@w{ }2 if ligatures are enabled, 0@w{ }otherwise).
+
+Setting the ligature mode to@w{ }2 enables the two-character ligatures
+(fi, fl, and ff) and disables the three-character ligatures (ffi and
+ffl).
+@endDefreq
+
+@dfn{Pairwise kerning} is another subtle typesetting mechanism that
+modifies the distance between a character pair to improve readability.
+In most cases (but not always) the distance is decreased.
+@ifnotinfo
+For example, compare the combination of the letters `V' and `A'. With
+kerning, `VA' is printed. Without kerning it appears as `V@w{}A'.
+@end ifnotinfo
+Typewriter-like fonts and fonts for terminals where all characters
+have the same width don't use kerning.
-@c XXX more info
+@cindex kerning enabled register
+@Defreq {kern, [@Var{flag}]}
+@Defregx {.kern}
+Kerning can be activated with the @code{kern} request. If the
+parameter is non-zero or missing, enable pairwise kerning, otherwise
+disable it. The read-only number register @code{.kern} is set to@w{
+}1 if pairwise kerning is enabled, 0@w{ }otherwise.
@cindex zero width space character
@cindex character, zero width space
@cindex space character, zero width
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 @code{\&} between them.
+characters from that font are kerned. Kerning between two characters
+can be inhibited by placing @code{\&} between them: @samp{V\&A}.
-@findex kern
-@vindex .kern
-@cindex kerning enabled register
-Kerning can be activated with the @code{kern} request. If the parameter
-is non-zero or missing, enable pairwise kerning, otherwise disable it.
-The number register @code{.kern} is set to@w{ }1 if pairwise kerning is
-enabled, 0@w{ }otherwise.
+@xref{Font File Format}.
+@endDefreq
-@findex tkf
@cindex track kerning
@cindex kerning, track
+@dfn{Track kerning} expands or reduces the space between characters.
+This can be handy, for example, if you need to squeeze a long word
+onto a single line or spread some text to fill a narrow column. It
+must be used with great care since it is usually considered bad
+typography if the reader notices the effect.
-@c XXX What is track kerning?
+@Defreq {tkf, f s1 n1 s2 n2}
+Enable track kerning for font@w{ }@var{f}. If the current font is@w{
+}@var{f} the width of every character is increased by an amount
+between @var{n1} and @var{n2} (@var{n1}, @var{n2} can be negative); if
+the current point size is less than or equal to @var{s1} the width is
+increased by @var{n1}; if it is greater than or equal to @var{s2} the
+width is increased by @var{n2}; if the point size is greater than or
+equal to @var{s1} and less than or equal to @var{s2} the increase in
+width is a linear function of the point size.
+
+The default unit is @samp{z} for @var{s1} and @var{s2}, @samp{p} for
+@var{n1} and @var{n2}.
+@endDefreq
+
+Sometimes, when typesetting letters of different fonts, more or less
+space at such boundaries are needed. There are two escapes to help
+with this.
-@c XXX more info
+@cindex italic correction
+@cindex correction, italic
+@cindex correction between italic and roman character
+@cindex roman character, correction after italic character
+@cindex italic character, correction before roman character
+@Defesc {\\/, , , }
+Increase the width of the preceding character so that the spacing
+between that character and the following character is correct if the
+following character is a roman character. For example, if an
+italic@w{ }@code{f} is immediately followed by a roman right
+parenthesis, then in many fonts the top right portion of the @code{f}
+overlaps the top left of the right parenthesis. Use this escape
+sequence whenever an italic character is immediately followed by a
+roman character without any intervening space. This small amount of
+space is also called @dfn{italic correction}.
-Track kerning must be used with great care since it is usually
-considered bad typography if the reader notices the effect. The syntax
-of the @code{tkf} request is like this:
+@iftex
+@example
+@group
+\f[I]f\f[R])
+ @result{} {@it f}@r{)}
+\f[I]f\/\f[R])
+ @result{} @i{f}@r{)}
+@end group
+@end example
+@end iftex
+@endDefesc
+@cindex left italic correction
+@cindex correction, left italic
+@cindex roman character, correction before italic character
+@cindex italic character, correction after roman character
+@Defesc {\\\,, , , }
+Modify the spacing of the following character so that the spacing
+between that character and the preceding character is correct if the
+preceding character is a roman character. Use this escape sequence
+whenever a roman character is immediately followed by an italic
+character without any intervening space. In analogy to above, this
+space could be called @dfn{left italic correction}, but this term
+isn't used widely.
+
+@iftex
@example
-.tkf @var{f} @var{s1} @var{n1} @var{s2} @var{n2}
+@group
+q\f[I]f
+ @result{} @r{q}@i{f}
+q\,\f[I]f
+ @result{} @r{q}@math{@ptexcomma}@i{f}
+@end group
@end example
+@end iftex
+@endDefesc
-@noindent
-Enable track kerning for font@w{ }@var{f}. If the current font is@w{
-}@var{f} the width of every character will be increased by an amount
-between @var{n1} and @var{n2}; if the current point size is less than or
-equal to @var{s1} the width will be increased by @var{n1}; if it is
-greater than or equal to @var{s2} the width will be increased by
-@var{n2}; if the point size is greater than or equal to @var{s1} and
-less than or equal to @var{s2} the increase in width is a linear
-function of the point size.
+@Defesc {\\&, , , }
+Insert a zero-width character, which is invisible. Its intended use
+is to stop interaction of a character with its surrounding.
+
+@itemize @bullet
+@item
+It prevents the insertion of extra space after an end of sentence
+character.
+
+@Example
+Test.
+Test.
+ @result{} Test. Test.
+Test.\&
+Test.
+ @result{} Test. Test.
+@endExample
+
+@item
+It prevents interpretation of a control character at the beginning of
+an input line.
+
+@Example
+.Test
+ @result{} warning: `Test' not defined
+\&.Test
+ @result{} .Test
+@endExample
+
+@item
+It prevents kerning between two characters.
+
+@ifnotinfo
+@example
+@group
+VA
+ @result{} @r{VA}
+V\&A
+ @result{} @r{V@w{}A}
+@end group
+@end example
+@end ifnotinfo
+
+@item
+It is needed to map an arbitrary character to nothing in the @code{tr}
+request (@pxref{Character Translations}).
+@end itemize
+@endDefesc
@c =====================================================================
-@node Sizes, Strings, Fonts, Programming Tutorial
+@node Sizes, Strings, Fonts, gtroff Reference
@section Sizes
@cindex sizes
@@ -5681,23 +6467,29 @@ function of the point size.
@cindex size of type
@cindex vertical spacing
@cindex spacing, vertical
-@code{gtroff} uses two dimensions with each line of text, type size and
-vertical spacing. The @dfn{type size} is the height from the text
-@dfn{baseline} to the top of the tallest character (descenders may drop
-below this baseline). @dfn{Vertical spacing} is the amount of space
-@code{gtroff} allows for a line of text; normally, this is about 20%@w{
-}larger than the current type size. Ratios smaller than this can result
-in hard-to-read text; larger that this, it will spread the text out more
-vertically (useful for term papers). By default, @code{gtroff} uses
-10@w{ }point type on 12@w{ }point spacing.
+@code{gtroff} uses two dimensions with each line of text, type size
+and vertical spacing. The @dfn{type size} is approximately the height
+of the tallest character.@footnote{This is usually the parenthesis.
+Note that in most cases the real dimensions of the glyphs in a font
+are @emph{not} related to its type size! For example, the standard
+@sc{PostScript} font families `Times Roman', `Helvetica', and
+`Courier' can't be used together at 10@dmn{pt}; to get acceptable
+output, the size of `Helvetica' has to be reduced by one point, and
+the size of `Courier' must be increased by one point.} @dfn{Vertical
+spacing} is the amount of space @code{gtroff} allows for a line of
+text; normally, this is about 20%@w{ }larger than the current type
+size. Ratios smaller than this can result in hard-to-read text;
+larger than this, it spreads the text out more vertically (useful for
+term papers). By default, @code{gtroff} uses 10@w{ }point type on
+12@w{ }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::
+* Changing Type Sizes::
+* Fractional Type Sizes::
@end menu
@c ---------------------------------------------------------------------
@@ -5707,32 +6499,34 @@ typesetters, as @dfn{leading}.
@cindex changing type sizes
@cindex type sizes, changing
-@findex ps
-@findex vs
-@findex \s
-@vindex .s
-@vindex .v
-@cindex current type size register
-@cindex current vertical spacing register
-Using the @code{ps} request and the @code{\s} escape the type size can
-be changed. 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.
+@Defreq {ps, [@Var{size}]}
+@Defreqx {ps, @t{+}@Var{size}}
+@Defreqx {ps, @t{-}@Var{size}}
+@Defescx {\\s, , size, }
+@Defregx {.s}
+Use the @code{ps} request or the @code{\s} escape to change (increase,
+decrease) the type size (in points). Specify @var{size} as either an
+absolute point size, or as a relative change from the current size.
+The size@w{ }0, or no argument, goes back to the previous size.
-These requests take parameters in units of points. It is possible to
-specify sizes as an absolute size, or as a relative change from the
-current size. The size@w{ }0 means go back to the previous size. With
-no argument it will also revert to the previous size.
+Default unit of @code{size} is @samp{z}. If @code{size} is zero or
+negative, it is set to 1@dmn{u}.
-@example
+The read-only number register @code{.s} returns the point size in
+points as a decimal fraction. This is a string. To get the point
+size in scaled points, use the @code{.ps} register instead.
+
+@code{.s} is associated with the current environment
+(@pxref{Environments}).
+
+@Example
snap, snap,
.ps +2
grin, grin,
.ps +2
wink, wink, \s+2nudge, nudge,\s+8 say no more!
.ps 10
-@end example
+@endExample
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
@@ -5740,38 +6534,61 @@ and the text begins. Any of the following forms are valid:
@table @code
@item \s@var{n}
-Set the point size to @var{n}@w{ }points. @var{n}@w{ }must be either 0
-or in the range 4 to@w{ }39.
+Set the point size to @var{n}@w{ }points. @var{n}@w{ }must be either
+0 or in the range 4 to@w{ }39.
@item \s+@var{n}
@itemx \s-@var{n}
-Increase resp.@: decrease the point size by @var{n}@w{ }points.
-@var{n}@w{ }must be exactly one digit.
+Increase or decrease the point size by @var{n}@w{ }points. @var{n}@w{
+}must be exactly one digit.
@item \s(@var{nn}
-Set the point size to @var{nn}@w{ }points. @var{nn} must be exactly two
-digits.
+Set the point size to @var{nn}@w{ }points. @var{nn} must be exactly
+two digits.
@item \s+(@var{nn}
@itemx \s-(@var{nn}
@itemx \s(+@var{nn}
@itemx \s(-@var{nn}
-Increase resp.@: decrease the point size by @var{nn}@w{ }points.
-@var{nn} must be exactly two digits.
+Increase or decrease the point size by @var{nn}@w{ }points. @var{nn}
+must be exactly two digits.
@end table
-@xref{Fractional Type Sizes}, for yet another syntactical form of using
-the @code{\s} escape.
+@xref{Fractional Type Sizes}, for yet another syntactical form of
+using the @code{\s} escape.
Some devices may only have certain permissible sizes, in which case
-@code{gtroff} will round to the nearest permissible size.
+@code{gtroff} rounds to the nearest permissible size.
+@endDefreq
+
+@cindex current type size register
+@cindex current vertical spacing register
+@Defreq {vs, [@Var{space}]}
+@Defreqx {vs, @t{+}@Var{space}}
+@Defreqx {vs, @t{-}@Var{space}}
+@Defregx {.v}
+Change (increase, decrease) the vertical spacing by @var{space}. The
+default unit is @samp{p}.
+
+If @code{vs} is called without an argument, the vertical spacing is
+reset to the previous value before the last call to @code{vs}.
+
+@vindex .V
+@code{gtroff} creates a warning of type @samp{range} if @var{space} is
+zero or negative; the vertical spacing is then set to the vertical
+resolution (as given in the @code{.V} register).
+
+The read-only number register @code{.v} contains the current vertical
+spacing; it is associated with the current environment
+(@pxref{Environments}).
+@endDefreq
@c XXX example
@ignore
-@example
+@Example
... .sz macro example?? ...
-@end example
+@endExample
@end ignore
@c ---------------------------------------------------------------------
@@ -5785,32 +6602,33 @@ Some devices may only have certain permissible sizes, in which case
@cindex unit, @code{s}
@cindex @code{z} unit
@cindex unit, @code{z}
-@findex ps
-@findex cs
-@findex tkf
-@findex \H
-@findex \s
-A @dfn{scaled point} is equal to 1/@var{sizescale} points, where
-@var{sizescale} is specified in the @file{DESC} file (1@w{ }by default.)
-There is a new scale indicator @samp{z} which has the effect of
-multiplying by @var{sizescale}. Requests and escape sequences in
-@code{gtroff} interpret arguments that represent a point size 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 (see below).
+@rqindex ps
+@rqindex cs
+@rqindex tkf
+@esindex \H
+@esindex \s
+A @dfn{scaled point} is equal to @math{1/@var{sizescale}} points,
+where @var{sizescale} is specified in the @file{DESC} file (1@w{ }by
+default). There is a new scale indicator @samp{z} which has the
+effect of multiplying by @var{sizescale}. Requests and escape
+sequences in @code{gtroff} interpret arguments that represent a point
+size 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 (see below).
For example, suppose @var{sizescale} is@w{ }1000; then a scaled point
-will be equivalent to a millipoint; the request @w{@samp{.ps 10.25}} is
+is equivalent to a millipoint; the request @w{@samp{.ps 10.25}} is
equivalent to @w{@samp{.ps 10.25z}} and thus sets the point size to
10250@w{ }scaled points, which is equal to 10.25@w{ }points.
-It would make no sense to use the @samp{z} scale indicator in a numeric
+@code{gtroff} disallows the use of the @samp{z} scale indicator in
+instances where it would make no sense, such as a numeric
expression whose default scale indicator was neither @samp{u} nor
-@samp{z}, and so @code{gtroff} disallows this. Similarly it would make
+@samp{z}. Similarly 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
@code{gtroff} disallows this as well.
@@ -5821,18 +6639,36 @@ equal to @samp{1m}. Be sure not to confuse the @samp{s} and @samp{z}
scale indicators.
@vindex .s
-@vindex .ps
-The number register @code{.s} returns the point size in points as decimal
-fraction. There is also a new number register @code{.ps} that returns
-the point size in scaled points.
+@Defreg {.ps}
+A read-only number register returning the point size in scaled points.
+
+@code{.ps} is associated with the current environment
+(@pxref{Environments}).
+@endDefreg
-@vindex .psr
-@vindex .sr
@cindex last-requested point size register
+@cindex point size, last-requested
+@vindex .ps
+@vindex .s
+@Defreg {.psr}
+@Defregx {.sr}
The last-requested point size in scaled points is contained in the
-@code{.psr} number register. The last requested point size in points as
-a decimal fraction can be found in @code{.sr}. This is a string-valued
-register.
+@code{.psr} read-only number register. The last requested point size
+in points as a decimal fraction can be found in @code{.sr}. This is a
+string-valued read-only number register.
+
+Note that the requested point sizes are device-independent, whereas
+the values returned by the @code{.ps} and @code{.s} registers are not.
+For example, if a point size of 11@dmn{pt} is requested for a DVI
+device, 10.95@dmn{pt} are actually used (as specified in the
+@file{DESC} file).
+
+Both registers are associated with the current environment
+(@pxref{Environments}).
+@endDefreg
+
+The @code{\s} escape has the following syntax for working with
+fractional type sizes:
@table @code
@item \s[@var{n}]
@@ -5848,7 +6684,7 @@ expression with a default scale indicator of @samp{z}.
@itemx \s'-@var{n}'
@itemx \s+'@var{n}'
@itemx \s-'@var{n}'
-Increase or resp.@: decrease the point size by @var{n} scaled points;
+Increase or or decrease the point size by @var{n} scaled points;
@var{n} is a numeric expression with a default scale indicator of
@samp{z}.
@end table
@@ -5858,32 +6694,44 @@ Increase or resp.@: decrease the point size by @var{n} scaled points;
@c =====================================================================
-@node Strings, Conditionals and Loops, Sizes, Programming Tutorial
+@node Strings, Conditionals and Loops, Sizes, gtroff Reference
@section Strings
@cindex strings
-@findex ds
@code{gtroff} has string variables, which are entirely for user
-convenience (i.e.@: there are no built-in strings). They are defined
-via the @code{ds} request.
+convenience (i.e.@: there are no built-in strings exept @code{.T}, but
+even this is a read-write string variable).
-@example
-.ds UX \s-1UNIX\s0\u\s-3tm\s0\d
-@end example
-
-@findex \*
@cindex string interpolation
@cindex string expansion
@cindex interpolation of strings
@cindex expansion of strings
-They are interpolated, or expanded in-place, via the @code{\*} escape:
+@Defreq {ds, name [@Var{string}]}
+@Defescx {\\*, , n, }
+@Defescx {\\*, @lparen{}, nm, }
+@Defescx {\\*, @lbrack{}, name, @rbrack{}}
+Define and access a string variable @var{name} (one-character name
+@var{n}, two-character name @var{nm}). If @var{name} already exists,
+@code{ds} overwrites the previous definition.
-@example
+Example:
+
+@Example
+.ds UX \s-1UNIX\s0\u\s-3tm\s0\d
+.
The \*(UX Operating System
-@end example
+@endExample
+
+The @code{\*} escape @dfn{interpolates} (expands in-place) a
+previously-defined string variable. To be more precise, the stored
+string is pushed onto the input stack which is then parsed by
+@code{gtroff}. Similar to number registers, it is possible to nest
+strings, i.e. a string variables can be called within string
+variables.
-If the string named by the @code{\*} does not exist, the escape will be
-replaced by nothing.
+If the string named by the @code{\*} does not exist, it is defined as
+empty, and a warning of type @samp{mac} is emitted (see
+@ref{Debugging}, for more details).
@cindex comments, with @code{ds}
@strong{Caution:} Unlike other requests, the second argument to the
@@ -5891,125 +6739,240 @@ replaced by nothing.
This means that comments on a line with such a request can introduce
unwanted space into a string.
-@example
+@Example
.ds UX \s-1UNIX\s0\u\s-3tm\s0\d \" UNIX trademark
-@end example
+@endExample
@noindent
Instead the comment should be put on another line or have the comment
escape adjacent with the end of the string.
-@example
+@Example
.ds UX \s-1UNIX\s0\u\s-3tm\s0\d\" UNIX trademark
-@end example
+@endExample
@cindex trailing quotes
@cindex quotes, trailing
@cindex leading spaces with @code{ds}
@cindex spaces with @code{ds}
-To produce leading space the string can be started with a double quote.
-No trailing quote is needed; in fact, any trailing quote is included in
-your string.
+To produce leading space the string can be started with a double
+quote. No trailing quote is needed; in fact, any trailing quote is
+included in your string.
-@example
+@Example
.ds sign " Yours in a white wine sauce,
-@end example
-
-@findex as
-@cindex appending to strings
-@cindex strings, appending
-The @code{as} request will append a string to another string. It works
-similar to 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
+@endExample
-@findex \@key{RET}
+@esindex \@key{RET}
@cindex multi-line strings
@cindex strings, multi-line
@cindex newline character in strings, escaping
@cindex escaping newline characters in strings
Strings are not limited to a single 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.
+several lines by escaping the newlines with a backslash. The
+resulting string is stored @emph{without} the newlines.
-@example
+@Example
.ds foo lots and lots \
of text are on these \
next several lines
-@end example
+@endExample
-@findex substring
-@cindex substrings
-Rudimentary string manipulation routines are given with the
-@code{substring} and @code{length} requests. The former has the
-following syntax:
+It is not possible to have real newlines in a string.
-@example
-.substring @var{xx} @var{n1} [@var{n2}]
-@end example
+@cindex name space of macros and strings
+@cindex macros, shared name space with strings
+@cindex strings, shared name space with macros
+Strings, macros, and diversions (and boxes) share the same name space.
+Internally, even the same mechanism is used to store them. This has
+some interesting consequences. For example, it is possible to call a
+macro with string syntax and vice versa.
-@noindent
-It replaces the string in register@w{ }@var{xx} with the substring
-defined by the indices @var{n1} and@w{ }@var{n2}. The first character
-in the string has index one. If @var{n2} is omitted, it is taken to be
-equal to the string's length. If the index value @var{n1} or @var{n2}
-is negative or zero, it will be counted from the end of the string,
-going backwards: The last character has index@w{ }0, the character
-before the last character has index@w{ }-1, etc.
+@Example
+.de xxx
+a funny test.
+..
+This is \*[xxx]
+ @result{} This is a funny test.
-@findex length
-@cindex length of a string
-@cindex string, length of
-Here the syntax of the @code{length} request:
+.ds yyy a funny test
+This is
+.yyy
+ @result{} This is a funny test.
+@endExample
-@example
-.length @var{xx} @var{string}
-@end example
+Diversions and boxes can be also called with string syntax. It is not
+possible to pass arguments to a macro if called with @code{\*}.
-@noindent
-It computes the length of @var{string} and returns it in the number
-register@w{ }@var{xx} (which is not necessarily defined before).
+Another consequence is that you can copy one-line diversions or boxes
+to a string.
-@ignore
-@findex rn
-@code{rn}
+@Example
+.di xxx
+a \fItest\fR
+.br
+.di
+.ds yyy This is \*[xxx]\c
+\*[yyy].
+ @result{} @r{This is a }@i{test}.
+@endExample
-@c XXX
+@noindent
+As the previous example shows, it is possible to store formatted
+output in strings. The @code{\c} escape prevents the insertion of an
+additional blank line in the output.
-@findex rm
-@code{rm}
+Copying diversions longer than a single output line produces
+unexpected results.
-@c XXX
+@Example
+.di xxx
+a funny
+.br
+test
+.br
+.di
+.ds yyy This is \*[xxx]\c
+\*[yyy].
+ @result{} test This is a funny.
+@endExample
+
+Usually, it is not predictable whether a diversion contains one or
+more output lines, so this mechanism should be avoided. With
+@acronym{UNIX} @code{troff}, this was the only solution to strip off a
+final newline from a diversion. Another disadvantage is that the
+spaces in the copied string are already formatted, making them
+unstretchable. This can cause ugly results.
+
+@rqindex chop
+@rqindex unformat
+A clean solution to this problem is available in GNU @code{troff},
+using the requests @code{chop} to remove the final newline of a
+diversion, and @code{unformat} to make the horizontal spaces
+stretchable again.
+
+@Example
+.box xxx
+a funny
+.br
+test
+.br
+.box
+.chop xxx
+.unformat xxx
+This is \*[xxx].
+ @result{} This is a funny test.
+@endExample
-@findex als
-@code{als}
+@xref{Gtroff Internals}, for more information.
+@endDefreq
-@c XXX
+@cindex appending to strings
+@cindex strings, appending
+@Defreq {as, name [@Var{string}]}
+The @code{as} request is similar to @code{ds} but appends @var{string}
+to the string stored as @var{name} instead of redefining it. If
+@var{name} doesn't exist yet, it is created.
-@findex chop
-@code{chop}
+@Example
+.as sign " with shallots, onions and garlic,
+@endExample
+@endDefreq
-@c XXX
-@end ignore
+Rudimentary string manipulation routines are given with the next two
+requests.
+
+@cindex substring
+@Defreq {substring, str n1 [@Var{n2}]}
+Replace the string in register@w{ }@var{str} with the substring
+defined by the indices @var{n1} and@w{ }@var{n2}. The first character
+in the string has index one. If @var{n2} is omitted, it is taken to
+be equal to the string's length. If the index value @var{n1} or
+@var{n2} is negative or zero, it is counted from the end of the
+string, going backwards: The last character has index@w{ }0, the
+character before the last character has index@w{ }@minus{}1, etc.
+
+@Example
+.ds xxx abcdefgh
+.substring xxx 2 -3
+\*[xxx]
+ @result{} bcde
+@endExample
+@endDefreq
+@cindex length of a string
+@cindex string, length of
+@Defreq {length, reg str}
+Compute the length of @var{str} and returns it in the number
+register@w{ }@var{reg}. If @var{reg} doesn't exist, it is created.
+
+@Example
+.ds xxx abcdefgh
+.length yyy xxx
+\n[yyy]
+ @result{} 8
+@endExample
+@endDefreq
+
+@cindex rename request
+@cindex rename macro
+@cindex rename string
+@Defreq {rn, xx yy}
+Rename the request, macro, or string @var{xx} to @var{yy}.
+@endDefreq
+
+@cindex remove request
+@cindex remove macro
+@cindex remove string
+@Defreq {rm, xx}
+Remove the request, macro, or string @var{xx}. @code{gtroff} treats
+subsequent invocations as if the object had never been defined.
+@endDefreq
+
+@cindex alias
+@Defreq {als, new old}
+Create an alias named @var{new} for the request, string, macro, or
+diversion object named @var{old}. The new name and the old name are
+exactly equivalent (it is similar to a hard rather than a soft
+link). If @var{old} is undefined, @code{gtroff} generates a warning of
+type @samp{mac} and ignores the request.
+@endDefreq
+
+@Defreq {chop, xx}
+Remove (chop) the last character from the macro, string, or diversion
+named @var{xx}. This is useful for removing the newline from the end
+of diversions that are to be interpolated as strings. This command
+can be used repeatedly; see @ref{Gtroff Internals}, for details on
+nodes inserted by @code{gtroff} automatically.
+@endDefreq
@xref{Identifiers}, and @ref{Comments}.
@c =====================================================================
-@node Conditionals and Loops, Writing Macros, Strings, Programming Tutorial
+@node Conditionals and Loops, Writing Macros, Strings, gtroff Reference
@section Conditionals and Loops
@cindex conditionals and loops
@cindex loops and conditionals
-@findex if@r{, operators to use with it}
-@findex while@r{, operators to use with it}
-In @code{if} and @code{while} requests, there are several more operators
-available:
+@menu
+* Operators in Conditionals::
+* if-else::
+* while::
+@end menu
+
+@c ---------------------------------------------------------------------
+
+@node Operators in Conditionals, if-else, Conditionals and Loops, Conditionals and Loops
+@subsection Operators in Conditionals
+
+@rqindex if
+@rqindex while
+@cindex @code{if}, operators to use with it
+@cindex @code{while}, operators to use with it
+In @code{if} and @code{while} requests, there are several more
+operators available:
@table @code
@item e
@@ -6017,88 +6980,138 @@ available:
True if the current page is even or odd numbered (respectively).
@item n
-@findex nroff
-True if the document is being processed in nroff mode.
+@rqindex nroff
+True if the document is being processed in nroff mode (i.e., the
+@code{.nroff} command has been issued).
@item t
-@findex troff
-True if the document is being processed in troff mode.
+@rqindex troff
+True if the document is being processed in troff mode (i.e., the
+@code{.troff} command has been issued).
+
+@item v
+Always false.
@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.
-@c XXX (Which?)
-The strings are ``formatted'' before being compared.
-@c XXX (?)
+characters can be used in place of the single quotes; the same set of
+delimiters as for the @code{\D} escape is used (@pxref{Escapes}).
+@code{gtroff} formats the strings before being compared:
+
+@Example
+.ie "|"\fR|\fP" \
+true
+.el \
+false
+ @result{} true
+@endExample
-@item r@var{xxx}
+@noindent
+The resulting motions, character sizes, and fonts have to
+match,@footnote{The created output nodes must be identical.
+@xref{Gtroff Internals}.} and not the individual motion, size, and
+font requests. In the previous example, @samp{|} and @samp{\fR|\fP}
+both result in a roman @samp{|} character with the same point size and
+at the same location on the page, so the strings are equal. If
+@samp{.ft@w{ }I} had been added before the @samp{.ie}, the result
+would be ``false'' because (the first) @samp{|} produces an italic
+@samp{|} rather than a roman one.
+
+@item r @var{xxx}
True if there is a number register named @var{xxx}.
-@item d@var{xxx}
+@item d @var{xxx}
True if there is a string, macro, diversion, or request named @var{xxx}.
-@item c@var{ch}
-@findex char
+@item c @var{ch}
+@rqindex char
True if there is a character @var{ch} available; @var{ch} is either an
@acronym{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.
+@code{\[@var{ch}]}); the condition is also true if @var{ch} has been
+defined by the @code{char} request.
@end table
-@menu
-* if-else::
-* while::
-@end menu
+Note that these operators can't be combined with other operators like
+@samp{:} or @samp{&}; only a leading @samp{!} (without whitespace
+between the exclamation mark and the operator) can be used to negate
+the result.
-@c ---------------------------------------------------------------------
+@Example
+.nr xxx 1
+.ie !r xxx \
+true
+.el \
+false
+ @result{} false
+@endExample
-@node if-else, while, Conditionals and Loops, Conditionals and Loops
-@subsection if-else
-@cindex if-else
+A whitespace after @samp{!} always evaluates to zero (this bizarre
+behaviour is due to compatibility with @acronym{UNIX} @code{troff}).
-@code{gtroff} has if-then-else constructs like other languages, although
-the formatting can be painful.
+@Example
+.nr xxx 1
+.ie ! r xxx \
+true
+.el \
+false
+ @result{} r xxx true
+@endExample
-@findex if
-The @code{if} request has the following syntax:
+It is possible to omit the whitespace before the argument to the
+@samp{r}, @samp{d}, and @samp{c} operators.
-@example
-.if @var{expr} @var{anything}
-@end example
+@xref{Expressions}.
-@noindent
-where @var{expr} is the expression to be evaluated; @var{anything} (the
-remainder of the line) will be executed if @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.
+@c ---------------------------------------------------------------------
-Here are some examples:
+@node if-else, while, Operators in Conditionals, Conditionals and Loops
+@subsection if-else
+@cindex if-else
-@example
-.if t .ls 2 \" double spacing in troff
-.if 0 .ab how'd this happen?
-@end example
+@code{gtroff} has if-then-else constructs like other languages, although
+the formatting can be painful.
-@findex ie
-@findex el
-An if-then-else is written using two requests @code{ie} and @code{el}.
+@Defreq {if, expr anything}
+Evaluate the expression @var{expr}, and executes @var{anything} (the
+remainder of the line) if @var{expr} evaluates to non-zero (true).
+@var{anything} is interpreted as though it was on a line by itself
+(except that leading spaces are swallowed). @xref{Expressions}, for
+more info.
+
+@Example
+.nr xxx 1
+.nr yyy 2
+.if ((\n[xxx] == 1) & (\n[yyy] == 2)) true
+ @result{} true
+@endExample
+@endDefreq
+
+@c XXX .nop request
+
+@Defreq {ie, expr anything}
+@Defreqx {el, anything}
+Use the @code{ie} and @code{el} requests to write an if-then-else.
The first request is the `if' part and the latter is the `else' part.
-@c XXX example
-
-@example
-.ie
-.el
-@end example
-
-@findex \@{
-@findex \@}
-In many cases more than one request is to be executed as a result of any
-of these requests. This can be done using the @code{\@{} and @code{\@}}
+@Example
+.ie n .ls 2 \" double spacing in nroff
+.el .ls 1 \" single spacing in troff
+@endExample
+@endDefreq
+
+@c this is a bug in makeinfo: you can't have `@{' as an argument
+@c to deffn
+
+@esindex \@{
+@esindex \@}
+@c @Defesc {\\@@@{, , , }
+@c @Defescx {\\@@@}, , , }
+In many cases, an if (or if-else) construct needs to execute more than
+one request. This can be done using the @code{\@{} and @code{\@}}
escapes. The following example shows the possible ways to use these
escapes (note the position of the opening and closing braces).
-@example
+@Example
.ie t \@{\
. ds lq ``
. ds rq ''
@@ -6107,8 +7120,8 @@ escapes (note the position of the opening and closing braces).
.\@{\
. ds lq "
. ds rq "\@}
-.ds qq "
-@end example
+@endExample
+@c @endDefesc
@xref{Expressions}.
@@ -6118,94 +7131,179 @@ escapes (note the position of the opening and closing braces).
@subsection while
@cindex while
-@findex while
@code{gtroff} 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
+@Defreq {while, expr anything}
+Evaluate the expression @var{expr}, and repeatedly execute
+@var{anything} (the remainder of the line) until @var{expr} evaluates
+to@w{ }0.
+
+@Example
.nr a 0 1
-.while (\na<9) \&\n+a,
-\&\n+a
-@end example
+.while (\na < 9) \@{\
+\n+a,
+.\@}
+\n+a
+ @result{} 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+@endExample
-@noindent
-The preceding example produces:
+Some remarks.
-@example
-1, 2, 3, 4, 5, 6, 7, 8, 9, 10
-@end example
+@rqindex de
+@itemize @bullet
+@item
+The body of a @code{while} request is treated like the body of a
+@code{de} request: @code{gtroff} temporarily stores it in a macro
+which is deleted after the loop has been exited. It can considerably
+slow down a macro if the body of the @code{while} request (within the
+macro) is large. Each time the macro is executed, the @code{while}
+body is parsed and stored again as a temporary macro.
+
+@Example
+.de xxx
+. nr num 10
+. while (\\n[num] > 0) \@{\
+. \" many lines of code
+. nr num -1
+. \@}
+..
+@endExample
-@cindex zero width space character
-@cindex character, zero width space
-@cindex space character, zero width
-@findex \&
+@cindex recursive macros
+@cindex macros, recursive
@noindent
-Note the usage of the @code{\&} escape to avoid a control character at
-the beginning of a line.
+The traditional and ofter better solution (@acronym{UNIX} @code{troff}
+doesn't have the @code{while} request) is to use a recursive macro
+instead which is parsed only once during its definition.
+
+@Example
+.de yyy
+. if (\\n[num] > 0) \@{\
+. \" many lines of code
+. nr num -1
+. yyy
+. \@}
+..
+.
+.de xxx
+. nr num 10
+. yyy
+..
+@endExample
+
+@noindent
+Note that the number of available recursion levels is set to@w{ }1000
+(this is a compile-time constant value of @code{gtroff}).
+
+@item
+The closing brace of a @code{while} body must end a line.
+
+@Example
+.if 1 \@{\
+. nr a 0 1
+. while (\n[a] < 10) \@{\
+. nop \n+[a]
+.\@}\@}
+ @result{} unbalanced \@{ \@}
+@endExample
+@end itemize
+@endDefreq
+
+@rqindex while
+@cindex @code{break}, in a @code{while} loop
+@cindex @code{continue}, in a @code{while} loop
+@Defreq {break, }
+Break out of a @code{while} loop. Be sure not to confuse this with
+the @code{br} request (causing a line break).
+@endDefreq
-@findex break@r{, in a @code{while} loop}
-@findex continue@r{, in a @code{while} loop}
-The @code{break} request will @dfn{break} out of a while loop. Be sure
-not to confuse this with the @code{br} request (causing a line break).
-The @code{continue} request will finish the current iteration of a while
-loop, immediately restarting the next iteration.
+@Defreq {continue, }
+Finishes the current iteration of a @code{while} loop, immediately
+restarting the next iteration.
+@endDefreq
@xref{Expressions}.
@c =====================================================================
-@node Writing Macros, Page Motions, Conditionals and Loops, Programming Tutorial
+@node Writing Macros, Page Motions, Conditionals and Loops, gtroff Reference
@section Writing Macros
@cindex writing macros
@cindex macros, writing
-@findex de
-A @dfn{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.
+A @dfn{macro} is a collection of text and embedded commands which can
+be invoked multiple times. Use macros to define common operations.
-Here a small example macro called @samp{P} which will cause a break and
-the insertion of some vertical space. It could be used to separate
-paragraphs.
+@Defreq {de, name [@Var{end}]}
+Define a new macro named @var{name}. @code{gtroff} copies subsequent
+lines (starting with the next one) into an internal buffer until it
+encounters the line @samp{..} (two dots). The optional second
+argument to @code{de} changes this to a macro to @samp{.@var{end}}.
-@example
+Note that no leading whitespace is allowed in the line containing the
+ending token (either @samp{..} or the macro @samp{.@var{end}}).
+
+Here a small example macro called @samp{P} which causes a break and
+inserts some vertical space. It could be used to separate paragraphs.
+
+@Example
.de P
-.br
-.sp .8v
+. br
+. sp .8v
..
-@end example
+@endExample
+
+@c XXX add info about macro definitions in macros.
+
+@c XXX give example for end macro.
+
+@c XXX add info about indirect macro calls:
+@c
+@c .de xxx
+@c from yyy\c
+@c ..
+@c
+@c test \*[xxx] test
+@c => test from yyy test
+
+@c XXX info about common identifier pool for strings, macros, and
+@c diversions.
+@endDefreq
-@findex am
@cindex appending, to a macro
-The @code{am} request works similarly to @code{de} except it appends
-onto the macro named by the first argument. So, to make the previously
-defined @samp{P} macro actually do indented instead of block paragraphs,
-is is possible to add the necessary code to the existing macro like
-this:
+@Defreq {am, xx}
+Works similarly to @code{de} except it appends onto the macro named
+@var{xx}. So, to make the previously defined @samp{P} macro actually
+do indented instead of block paragraphs, add the necessary code to the
+existing macro like this:
-@example
+@Example
.am P
.ti +5n
..
-@end example
-
-@findex als
-@cindex aliases, macro
-@cindex macro aliases
-Macros can be aliased with the @code{als} request.
-
-@c XXX example
+@endExample
+@endDefreq
+
+@cindex alias
+@Defreq {als, new old}
+Create an alias named @var{new} for the request, string, macro, or
+diversion object named @var{old}. The new name and the old name are
+exactly equivalent (it is similar to a hard rather than a soft
+link). If @var{old} is undefined, @code{gtroff} generates a warning of
+type @samp{mac} and ignores the request.
+
+The @code{de}, @code{am}, @code{di}, @code{da}, @code{ds},
+and @code{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.
+@endDefreq
@menu
-* Copy-in Mode::
-* Parameters::
+* Copy-in Mode::
+* Parameters::
@end menu
@c ---------------------------------------------------------------------
@@ -6215,14 +7313,19 @@ Macros can be aliased with the @code{als} request.
@cindex copy-in mode
@cindex mode, copy-in
-@findex \n@r{, when reading test for a macro}
-@findex \$@r{, when reading test for a macro}
-@findex \*@r{, when reading test for a macro}
-@findex \\@r{, when reading test for a macro}
-@findex \@key{RET}@r{, when reading test for a macro}
-When @code{gtroff} reads in the text for a macro or diversion it copies
+@esindex \n
+@esindex \$
+@esindex \*
+@esindex \\
+@esindex \@key{RET}
+@cindex @code{\n}, when reading text for a macro
+@cindex @code{\$}, when reading text for a macro
+@cindex @code{\*}, when reading text for a macro
+@cindex @code{\\}, when reading text for a macro
+@cindex \@key{RET}, when reading text for a macro
+When @code{gtroff} reads in the text for a macro or diversion, it copies
the text (including request lines, but excluding escapes) into an
-internal buffer. Escapes will be converted into an internal form,
+internal buffer. Escapes are 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 or
@@ -6233,10 +7336,9 @@ evaluated (either at copy-in time or at the time of use) by insulating
the escapes with an extra backslash. Compare this to the @code{\def}
and @code{\edef} commands in @TeX{}.
-For example, the following will result in the numbers 20 and@c{ }10
-being printed:
+The following example prints the numbers 20 and@w{ }10:
-@example
+@Example
.nr x 20
.de y
.nr x 10
@@ -6244,7 +7346,7 @@ being printed:
\&\\nx
..
.y
-@end example
+@endExample
@c ---------------------------------------------------------------------
@@ -6252,7 +7354,6 @@ being printed:
@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.
@@ -6260,95 +7361,107 @@ Any individual argument can be retrieved with one of the following
escapes:
@cindex copy-in mode, and macro arguments
+@Defesc {\\$, n, , }
+@Defescx {\\$, @lparen{}, nn, }
+@Defescx {\\$, @lbrack{}, nnn, @rbrack{}}
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. As usual, the first form only accepts a single
-number (larger than zero), the second only a two-digit number (larger or
-equal to@w{ }10), and the third any positive integer value (larger than
-zero). Macros can have an unlimited number of arguments. Note that due
-to copy-in mode, two backslashes should be used on these in actual use
-to prevent interpolation until the macro is actually invoked.
-
-@findex shift
-The request @code{shift} will shift the arguments 1@w{ }position, or as
+@code{\$[@var{nnn}]} retrieve the @var{n}@dmn{th}, @var{nn}@dmn{th} or
+@var{nnn}@dmn{th} argument. As usual, the first form only accepts a
+single number (larger than zero), the second a two-digit number (larger
+or equal to@w{ }10), and the third any positive integer value (larger
+than zero). Macros can have an unlimited number of arguments. Note
+that due to copy-in mode, use two backslashes on these in actual use to
+prevent interpolation until the macro is actually invoked.
+@endDefesc
+
+@Defreq {shift, [@Var{n}]}
+Shifts the arguments 1@w{ }position, or as
many positions as specified by its argument. After executing this
-request, argument@w{ }@var{i} will become argument @var{i}-@var{n};
-arguments 1 to@w{ }@var{n} will no longer be available. Shifting by
+request, argument@w{ }@var{i} becomes argument @var{i}-@var{n};
+arguments 1 to@w{ }@var{n} are no longer available. Shifting by
negative amounts is currently undefined.
+@endDefreq
-@findex \$*
-@findex \$@@
+@Defesc {\\$*, , , }
+@Defescx {\\$@@, , , }
In some cases it is convenient to use all of the arguments at once (for
example, to 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
+escape concatenates all the arguments separated by spaces. A
+similar escape is @code{\$@@}, which concatenates all the
arguments with each surrounded by double quotes, and separated by
spaces.
+@endDefesc
-@findex \$0
-@findex als@r{, use with @code{\$0}}
-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.
+@rqindex als
+@cindex @code{als}, use with @code{\$0}
+@Defesc {\\$0, , , }
+The name used to invoke the current macro.
+The @code{als} request can make a macro have more than one name.
-@example
+@Example
.de vl
.ie \\n(.$=1 .ds Vl Pre-Release Version
.el .ds Vl Version \\$3, \\$4.
..
-@end example
+@endExample
+@noindent
This would be called as
-@example
-.vl $Id: groff.texinfo,v 1.40 2000/06/18 10:13:51 wlemb Exp $
-@end example
+@Example
+.vl $Id: groff.texinfo,v 1.74 2001/04/16 14:47:18 wlemb Exp $
+@endExample
+@endDefesc
@xref{Request Arguments}.
@c =====================================================================
-@node Page Motions, Drawing Requests, Writing Macros, Programming Tutorial
+@node Page Motions, Drawing Requests, Writing Macros, gtroff Reference
@section Page Motions
@cindex page motions
@cindex motions, page
-@findex sp@r{, as vertical page motion}
+@cindex @code{sp}, as vertical page motion
+@Defreq {sp, [@Var{len}]}
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.
+@endDefreq
-@findex mk
-@findex rt
+@Defreq {mk, [@Var{reg}]}
+@Defreqx {rt, reg}
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
+which to store the current page location. With no argument it
+stores 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 @emph{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
+request returns @emph{upwards} to the location given in the register
+name given as an argument; with no argument it returns to the
+location marked with the @code{mk} request.
@c XXX example
@ignore
-@example
+@Example
... dual column example ...
-@end example
+@endExample
@end ignore
+@endDefreq
The following escapes give fine control of movements about the page.
-@findex \v
@cindex vertical motion
@cindex motion, vertical
-The @code{\v'@var{e}'} enables arbitrary vertical motion from the
+@Defesc {\\v, ', e, '}
+The @code{\v'@var{e}'} escape enables arbitrary vertical motion from the
current location on the page. The argument@w{ }@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 @code{gtroff} will leave text processing to continue
-wherever the motion ends, so to avoid interference with text processing,
-motions should be balanced.
+default unit for this escape @samp{v}. Beware, however, that
+@code{gtroff} continues text processing at the point where the motion
+ends, so you should always balance motions to avoid interference with
+text processing.
+@endDefesc
There are some special case escapes for vertical motion.
@@ -6363,33 +7476,37 @@ move upwards@w{ }.5@dmn{v}.
move down@w{ }.5@dmn{v}.
@end ftable
-@findex \h
@cindex inserting horizontal space
@cindex horizontal space
@cindex space, horizontal
-Horizontal motions can be done via the @code{\h'@var{e}'} escape. The
+@Defesc {\\h, ', e, '}
+The @code{\h'@var{e}'} escape provides horizontal motions. The
expression@w{ }@var{e} indicates how far to move: positive is rightwards
and negative leftwards.
+@c XXX Is there a default unit for this?
+@endDefesc
There are a number of special case escapes for horizontal motion:
@ftable @code
@item \@key{SP}
-an unbreakable and unpaddable (i.e.@: not expanded during filling)
+An unbreakable and unpaddable (i.e.@: not expanded during filling)
space. (Note: This is a backslash followed by a space.)
@item \~
-an unbreakable space that stretches like a normal inter-word space when
-a line is adjusted.
+An unbreakable space that stretches like a normal inter-word space
+when a line is adjusted.
@item \|
-a 1/6th em space.
+A 1/6@dmn{th} em space. Ignored for tty output devices (rounded to
+zero).
@item \^
-a 1/12th em space.
+A 1/12@dmn{th} em space. Ignored for tty output devices (rounded to
+zero).
@item \0
-a space the size of a digit.
+A space the size of a digit.
@item \&
@cindex zero width space character
@@ -6403,28 +7520,26 @@ Like @code{\&} except that it behaves like a character declared with the
sentence recognition.
@end ftable
-@c XXX example
+The following string sets the @TeX{} logo:
-@ignore
-@example
-... tex logo example ...
-@end example
-@end ignore
+@Example
+.ds TeX T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
+@endExample
-@findex \w
@cindex width escape
@cindex escape, width
-A frequent need is 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.
+@Defesc {\\w, ', text, '}
+Used as @code{\w'@var{text}'},
+returns the width of the specified @var{text} in basic units.
+This allows horizontal movement based on the width of some
+arbitrary text (e.g.@: given as an argument to a macro).
@c XXX example
@ignore
-@example
+@Example
... strlen example ...
-@end example
+@endExample
@end ignore
Font changes may occur in @var{text} which don't affect current
@@ -6448,20 +7563,20 @@ heights and depths of characters.
@item ct
@vindex ct
-is set according to what kinds of characters occur in @var{text}:
+Defines the kinds of characters occurring in @var{text}:
@table @asis
@item 0
only short characters, no descenders or tall characters.
@item 1
-descender.
+at least one descender.
@item 2
-tall character.
+at least one tall character.
@item 3
-both a descender and a tall character.
+at least one each of a descender and a tall character.
@end table
@item ssc
@@ -6472,22 +7587,28 @@ 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
+argument, the center of an accent from a roman font should be placed
over that character.
@end table
+@endDefesc
-@findex \k
-@vindex .k
-@code{\k}
+@Defesc {\\k, ', x, '}
+Stores the current horizontal position in register @var{x}.
+Use this, for example, to return to the beginning of a string
+for highlighting or other decoration.
+@endDefesc
-@code{.k}
+@Defreg {.k}
+A read-only number register containing the current horizontal output
+position.
+@endDefreg
@c XXX documentation
@c =====================================================================
-@node Drawing Requests, Traps, Page Motions, Programming Tutorial
+@node Drawing Requests, Traps, Page Motions, gtroff Reference
@section Drawing Requests
@cindex drawing requests
@cindex requests for drawing
@@ -6502,22 +7623,22 @@ information.
All drawing is done via escapes.
-@findex \l
@cindex drawing horizontal lines
@cindex horizontal line, drawing
@cindex line, horizontal, drawing
-The @code{\l} escape will draw a line rightwards from the current
-location. The full syntax for this escape is like this:
+@Defesc {\\l, ', l c, '}
+Draws a line rightwards from the current
+location. The full syntax for this escape is:
-@example
+@Example
\l'@var{l}@var{c}'
-@end example
+@endExample
@noindent
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 @samp{|}) which will draw back to the beginning
+current location; positive numbers draw to the right, and negative
+numbers draw towards the left. This can also be specified absolutely
+(i.e.@: with a leading @samp{|}) which draws back to the beginning
of the line.
@cindex underscore character
@@ -6525,32 +7646,32 @@ of the line.
@cindex line drawing character
@cindex character for line drawing
The optional second parameter @var{c} is a character to draw the line
-with. If this second argument is not specified, @code{gtroff} will use
+with. If this second argument is not specified, @code{gtroff} uses
the underscore character.
@cindex zero width space character
@cindex character, zero width space
@cindex space character, zero width
-@findex \&
+@esindex \&
To separate the two arguments (to prevent @code{gtroff} from
interpreting a drawing character as a scaling indicator) use @code{\&}.
Here a small useful example:
-@example
+@Example
.de box
\(br\\$*\(br\l'|0\(rn'\l'|0\(ul'
..
-@end example
+@endExample
-@noindent
@opindex |
+@noindent
Note that this works by outputting 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.
+@endDefesc
-@findex \L
@cindex drawing vertical lines
@cindex vertical line drawing
@cindex line, vertical, drawing
@@ -6558,25 +7679,28 @@ the @emph{input} line.
@cindex character for line drawing
@cindex box rule character
@cindex character, box rule
-Vertical lines are drawn using the @code{\L} escape. Its parameters are
-specified similar to the @code{\l} escape. If the length is positive,
-the movement will be downwards, and upwards for negative values. The
+@Defesc {\\L, ', l c, '}
+Draws vertical lines. Its parameters are
+similar to the @code{\l} escape. The
+movement is downwards for positive values,
+and upwards for negative values. The
default character is the box rule character. As with the vertical
-motion escapes, text processing will blindly continue where the line
+motion escapes, text processing blindly continues where the line
ends.
@c XXX example
@ignore
-@example
+@Example
...box macro...
-@end example
+@endExample
@end ignore
+@endDefesc
-@findex \D
-More flexible drawing functions are available via the @code{\D} escape.
-While the previous escapes will work on a character device, these
-escapes will not.
+@Defesc {\\D, ', command arg @dots{}, '}
+The @code{\D} escape provides a variety of drawing functions.
+While the previous escapes work on a character device, these
+escapes do not.
@table @code
@item \D'l @var{dx} @var{dy}'
@@ -6586,9 +7710,9 @@ Draw a line from the current location to the relative point specified by
@c XXX example
@ignore
-@example
+@Example
...revised box macro...
-@end example
+@endExample
@end ignore
@item \D'c @var{d}'
@@ -6630,7 +7754,7 @@ Set the shade of gray to be used for filling solid objects to@w{
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@w{
-}1000 will be used.
+}1000 is used.
@item \D'p @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
@cindex drawing a polygon
@@ -6642,9 +7766,9 @@ are exhausted, a line is drawn back to the starting point.
@c XXX example
@ignore
-@example
+@Example
... box example (yes, again)...
-@end example
+@endExample
@end ignore
@item \D'P @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
@@ -6653,9 +7777,9 @@ Draw a solid polygon with the same parameters as an outlined polygon.
@c XXX example
@ignore
-@example
+@Example
... shaded box example ...
-@end example
+@endExample
@end ignore
@item \D't @var{n}'
@@ -6666,37 +7790,39 @@ zero selects the smallest available line thickness. A negative value
makes the line thickness proportional to the current point size (this is
the default behaviour of @code{ditroff}).
@end table
+@endDefesc
-@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.
+@Defesc {\\b, ', string, '}
+@dfn{Piles} a sequence of characters
+vertically, and centers it vertically on the current line. Use it
+to build large brackets and braces.
-@example
+@Example
\b'\(lt\(bv\(lk\(bv\(lb'
-@end example
+@endExample
+@endDefesc
@xref{Drawing Functions}.
@c =====================================================================
-@node Traps, Diversions, Drawing Requests, Programming Tutorial
+@node Traps, Diversions, Drawing Requests, gtroff Reference
@section Traps
@cindex traps
-@dfn{Traps} are locations, which, when reached, will call a specified
+@dfn{Traps} are locations, which, when reached, 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.
@menu
-* Page Location Traps::
-* Diversion Traps::
-* Input Line Traps::
-* End-of-input Traps::
+* Page Location Traps::
+* Diversion Traps::
+* Input Line Traps::
+* End-of-input Traps::
@end menu
@c ---------------------------------------------------------------------
@@ -6706,16 +7832,49 @@ lines or at the end of input.
@cindex page location traps
@cindex traps, page location
-@c XXX definition of wh request
+@dfn{Page location traps} perform an action when @code{gtroff}
+reaches a certain vertical location on the page. Page location
+traps have a variety of purposes, including:
+
+@itemize
+@item
+setting headers and footers
+
+@item
+setting body text in multiple columns
+
+@item
+setting footnotes
+@end itemize
+
+@cindex vertical position trap enable register
+@Defreq {vpt, flag}
+@Defregx {.vpt}
+Enables vertical position traps if @var{flag} is non-zero, or disables
+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
+@code{.vpt} read-only number register.
+@endDefreq
+
+@Defreq {wh, dist macro}
+Sets a page location trap. Positive values for @var{dist} set
+the trap relative to the top of the page; negative values set
+the trap relative to the bottom of the page.
+
+@var{macro} is the name of the macro to execute when the
+trap is sprung.
@cindex page headers
@cindex page footers
@cindex headers
@cindex footers
-Page location traps are frequently used for page headers and footers.
-The following is a simple example of this.
+The following is a simple example of how many macro packages
+set headers and footers.
-@example
+@Example
.de hd \" Page header
'sp .5i
.tl 'Title''date'
@@ -6728,57 +7887,52 @@ The following is a simple example of this.
..
.wh 0 hd \" trap at top of the page
.wh -1i fo \" trap one inch from bottom
-@end example
+@endExample
+@endDefreq
-@vindex .t
@cindex distance to next trap
@cindex trap, distance
-The number register @code{.t} is the distance to the next trap.
+@Defreg {.t}
+A read-only number register holding the distance to the next trap.
+@endDefreg
-@findex ch
@cindex changing trap location
@cindex trap, changing location
-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.
+@Defreq {ch, dist macro}
+Changes the location of a trap.
+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
+(note that the parameters are specified the opposite of the @code{.wh} request).
This is useful for building up footnotes in a diversion to allow more
space at the bottom of the page for them.
@c XXX
@ignore
-@example
+@Example
... (simplified) footnote example ...
-@end example
+@endExample
@end ignore
-
-@findex vpt
-@findex wh
-@vindex .vpt
-@cindex vertical position trap enable register
-The @code{vpt} request will enable vertical position traps if the
-argument 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@r{, and the @code{.trunc} register}
-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.
+@endDefreq
+
+@Defreg {.ne}
+The read-only 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.
+@endDefreg
+
+@rqindex ne
+@cindex @code{ne}, and the @code{.trunc} register
+@Defreg {.trunc}
+A read-only register containing the amount of vertical space truncated
+by the most recently sprung vertical position trap, or, if the trap was
+sprung by an @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.
+@endDefreg
@c ---------------------------------------------------------------------
@@ -6787,13 +7941,16 @@ Control}, for more information.
@cindex diversion traps
@cindex traps, diversion
-@findex dt
-@vindex .t@r{, and diversions}
-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.
+@vindex .t
+@cindex @code{.t}, and diversions
+@Defreq {dt, dist macro}
+Sets a trap @emph{within} a diversion.
+@var{dist} is the first argument is the location of the trap
+(identical to the @code{.wh} request)
+and @var{macro} is the name of the macro to be invoked. The
+number register @code{.t} still works within diversions.
@xref{Diversions}, for more information.
+@endDefreq
@c ---------------------------------------------------------------------
@@ -6802,31 +7959,25 @@ number register @code{.t} will still work within diversions.
@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
-
-@example
-.it @var{n} @var{name}
-@end example
-
-@noindent
-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.
+@Defreq {it, n macro}
+Sets an input line trap.
+@var{n} is the number of lines of input which may be read before
+@dfn{springing} the trap, @var{macro} 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
+For example, one possible use is to have a macro which prints the
next @var{n}@w{ }lines in a bold font.
-@example
+@Example
.de B
-.it B-end \\$1
+.it \\$1 B-end
.ft B
..
.de B-end
.ft R
..
-@end example
+@endExample
+@endDefreq
@c ---------------------------------------------------------------------
@@ -6835,16 +7986,16 @@ next @var{n}@w{ }lines in a bold font.
@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 argument will be executed after the last line of the
+@Defreq {em, macro}
+Sets a trap at the end of input. The @var{macro}
+specified is executed after the last line of the
input file has been processed.
For example, if the document had to have a section at the bottom of the
last page for someone to approve it, the @code{em} request could be
used.
-@example
+@Example
.de approval
.ne 5v
.sp |(\\n(.t-6v)
@@ -6856,12 +8007,13 @@ Approved:\t\a
Date:\t\t\a
..
.em approval
-@end example
+@endExample
+@endDefreq
@c =====================================================================
-@node Diversions, Environments, Traps, Programming Tutorial
+@node Diversions, Environments, Traps, gtroff Reference
@section Diversions
@cindex diversions
@@ -6871,49 +8023,62 @@ 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 indices.
-@findex di
-@findex da
-A diversion is initiated by the @code{di} request. Like the @code{de}
+@c XXX describe top-level diversion
+@c XXX index entry for top-level diversion
+
+@Defreq {di, macro}
+@Defreqx {da, macro}
+Begins a diversion. Like the @code{de}
request, it takes an argument of a macro name to divert subsequent text
-into. The @code{da} macro will append to an existing diversion.
+into. The @code{da} macro appends to an existing diversion.
-@code{di} (resp.@: @code{da}) without an argument ends the diversion.
+@code{di} or @code{da} without an argument ends the diversion.
@c XXX example
@ignore
-@example
+@Example
... end-note example ...
-@end example
+@endExample
@end ignore
+@endDefreq
-@vindex .z
-@vindex .d
@vindex nl
@vindex .h
@cindex nested diversions
@cindex diversion, nested
-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}.
+@Defreg {.z}
+@Defregx {.d}
+Diversions may be nested. The read-only number register @code{.z}
+contains the name of the current diversion (this is a string-valued
+register). The read-only 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}.
+@endDefreg
@c XXX more info
-@code{.h}
+@Defreg {.h}
+The @dfn{high-water mark} on the current page. It corresponds to the
+text baseline of the lowest line on the page. This is a read-only
+register.
+@endDefreg
-@vindex dn
-@vindex dl
-After completing a diversion, the built-in number registers @code{dn}
+@Defreg {dn}
+@Defregx {dl}
+After completing a diversion, the read-write number registers @code{dn}
and @code{dl} contain the vertical and horizontal size of the diversion.
@example
+@group
.\" Center text both horizontally & vertically
.de (c
.br
.nf
.di @@c
..
+@end group
+@group
.de )c
.br
.di
@@ -6929,36 +8094,39 @@ and @code{dl} contain the vertical and horizontal size of the diversion.
.fi
.rr @@s
..
+@end group
@end example
+@endDefreg
-@findex \!
@cindex transparent output
@cindex output, transparent
-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
+@Defesc {\\!, , , }
+@Defescx {\\?, , @Var{anything}, \\?}
+Prevents requests, macros and escapes from being
+interpreted when read into a diversion. This takes the given text
+and @dfn{transparently} embeds it into the diversion. This is useful for
macros which shouldn't be invoked until the diverted text is actually
output.
@c XXX anything is read in copy mode. (what about \! ??)
-@findex \?
-The other way is to surround the text by the @code{\?} escape, i.e.
+The @code{\!} escape transparently embeds text up to
+and including the end of the line.
+The @code{\?} escape transparently embeds text until the next
+occurrence of the @code{\?} escape. For example:
-@example
+@Example
\?@var{anything}\?
-@end example
+@endExample
@noindent
@var{anything} may not contain newlines; use @code{\!} to embed
newlines in a diversion. The escape sequence @code{\?} is also
recognized in copy mode and turned into a single internal code; it is
-this code that terminates anything. Thus the following example will
-print@w{ }4.
+this code that terminates anything. Thus the following example
+prints@w{ }4.
-@example
+@Example
.nr x 1
.nf
.di d
@@ -6974,42 +8142,43 @@ print@w{ }4.
.di
.nr x 4
.f
-@end example
+@endExample
+@endDefesc
-@findex asciify
@cindex unformatting diversions
@cindex diversion, unformatting
-The @code{asciify} request only exists in order to make certain gross
-hacks work with GNU @code{troff}. It @dfn{unformats} the diversion
-specified as an argument in such a way that @acronym{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@w{ }1.
-
-@example
+@Defreq {asciify, div}
+@dfn{Unformats} the diversion specified by @var{div}
+in such a way that @acronym{ASCII} and space characters that
+were formatted and diverted are treated like ordinary input
+characters when the diversion is reread. It can be also used for gross
+hacks; for example, the following sets register @code{n} to@w{ }1.
+
+@Example
.tr @@.
.di x
-@@nr\ n\ 1
+@@nr n 1
.br
.di
.tr @@@@
.asciify x
.x
-@end example
+@endExample
@xref{Copy-in Mode}.
+@endDefreq
@c =====================================================================
-@node Environments, I/O, Diversions, Programming Tutorial
+@node Environments, Suppressing output, Diversions, gtroff Reference
@section Environments
@cindex environments
It happens frequently that some text should be printed 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
-@code{gtroff} has @dfn{environments} in which text is processed. An
+@code{gtroff} processes text in @dfn{environments}. An
environment contains most of the parameters that control text
processing. It is possible to switch amongst these environments; by
default @code{gtroff} processes text in environment@w{ }0. The
@@ -7039,121 +8208,177 @@ These environments may be given arbitrary names (see @ref{Identifiers},
for more info). Old versions of @code{troff} only had environments
named @samp{0}, @samp{1} and@w{ }@samp{2}.
-@findex ev
-@vindex .ev
@cindex switch environments
@cindex current environment number/name register
-The @code{ev} request will switch to another environment. The single
-argument is the name of the environment to switch to. With no argument
-@code{gtroff} will switch back to the previous environment. There is no
-limit on the number of named environments; they will be created the
-first time that they are referenced. The @code{.ev} register contains
-the name or number of the current environment. This is a string-valued
-register.
-
-Note that a call to @code{ev} (with argument) will push the previously
+@Defreq {ev, env}
+@Defregx {.ev}
+Switches to another environment. The argument @var{env} is the name of
+the environment to switch to. With no argument, @code{gtroff} switches
+back to the previous environment. There is no limit on the number of
+named environments; they are created the first time that they are
+referenced. The @code{.ev} read-only register contains the name or
+number of the current environment. This is a string-valued register.
+
+Note that a call to @code{ev} (with argument) pushes the previously
active environment onto a stack. If, say, environments @samp{foo},
@samp{bar}, and @samp{zap} are called (in that order), the first
-@code{ev} request without parameter will switch back to environment
-@samp{bar} (which will be popped off the stack), and a second call will
-switch back to environment @samp{foo}.
+@code{ev} request without parameter switches back to environment
+@samp{bar} (which is popped off the stack), and a second call
+switches back to environment @samp{foo}.
@c XXX example
@ignore
-@example
+@Example
... page break macro, revised ...
-@end example
+@endExample
@end ignore
-Here is another example:
+Here is an example:
-@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
+@endExample
+@endDefreq
-@findex evc
@cindex copy environment
-To copy an environment into the current one, use the @code{evc} request,
-which takes the name of the environment to copy from as an argument.
+@Defreq {evc, env}
+Copies the environment @var{env} into the current environment.
+@endDefreq
+
+
+@c =====================================================================
+
+@node Suppressing output, I/O, Environments, gtroff Reference
+@section Suppressing output
+@cindex suppressing output
+
+@Defesc {\\O, , num, }
+Disables or enables output depending on the value of @var{num}:
+
+@table @samp
+@item \O0
+Disable any ditroff glyphs from being emitted to the device driver.
+
+@item \O1
+Enable output of glyphs.
+@end table
+
+@vindex opminx
+@vindex opminy
+@vindex opmaxx
+@vindex opmaxy
+@code{\O0} and @code{\O1} also reset the four registers @samp{opminx},
+@samp{opminy}, @samp{opmaxx}, and @samp{opmaxy} to @minus{}1.
+@xref{Register Index}. These four registers mark the top left and
+bottom right hand corners of a box which encompasses all written glyphs.
+
+The following two forms of @code{\O} are specific to @code{grohtml}.
+
+@table @samp
+@item \O2
+Disable any ditroff glyphs from being emitted to the device driver. Also
+write out to @code{stderr} the page number and four registers encompassing
+the glyphs previously written since the last call to @code{\O}.
+
+@item \O3
+Enable output of glyphs (the default). Also write out to @code{stderr}
+the page number and four registers encompassing the glyphs previously
+written since the last call to @code{\O}.
+@end table
+@endDefesc
@c =====================================================================
-@node I/O, Postprocessor Access, Environments, Programming Tutorial
+@node I/O, Postprocessor Access, Suppressing output, gtroff Reference
@section I/O
@cindex i/o
@cindex input and output requests
@cindex requests for input and output
@cindex output and input requests
-@findex so
+@code{gtroff} has several requests for including files:
+
@cindex including a file
@cindex file inclusion
-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.
+@Defreq {so, file}
+Reads in the specified @var{file} and
+includes it in place of the @code{so} request. This is quite useful for
+large documents, e.g.@: keeping each chapter in a separate file.
@xref{gsoelim}, for more information.
+@endDefreq
-@findex mso
-The @code{mso} request is the same as the @code{so} request except that
-the file is searched for in the same directories as
-@file{tmac.@var{name}} is searched for when the @option{-m@var{name}}
-option is specified.
+@Defreq {mso, file}
+Identical to the @code{so} request except that @code{gtroff}
+searches for the specified
+@var{file} in the same directories as macro files for the
+the @option{-m} command line option. If the file name to be included
+has the form @file{@var{name}.tmac} and it isn't found, @code{mso} tries
+to include @file{tmac.@var{name}} and vice versa.
+@endDefreq
-@findex cf
@cindex transparent output
@cindex output, transparent
-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
+@Defreq {cf, file}
+@Defreqx {trf, file}
+Transparently outputs the contents of @var{file}. Each line is output
as it were 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, to define a macro@w{ }@code{x}
+a newline is added. For example, to define a macro@w{ }@code{x}
containing the contents of file@w{ }@file{f}, use
-@example
+@Example
.di x
.trf f
.di
-@end example
+@endExample
The request @w{@code{.cf @var{filename}}}, when used in a diversion,
-will embed in the diversion an object which, when reread, will cause the
+embeds an object in the diversion which, when reread, causes the
contents of @var{filename} to be transparently copied through to the
-output. In @acronym{UNIX} @code{troff}, the contents of @var{filename}
+output.
+
+In @acronym{UNIX} @code{troff}, the contents of @var{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. This request causes a line break.
-@findex trf
+@rqindex trf
With @code{trf}, unlike @code{cf}, the file cannot contain characters
such as NUL that are not valid @code{gtroff} input characters
(@pxref{Identifiers}). This request causes a line break.
+@endDefreq
-@findex nx
-The @code{nx} request will force @code{gtroff} to continue processing of
+@Defreq {nx, }
+Forces @code{gtroff} to continue processing of
the file specified as an argument.
+@endDefreq
-@findex rd
-The @code{rd} request will read from standard input, and include what is
+@Defreq {rd, }
+The @code{rd} request reads from standard input, and includes what is
read as though it were part of the input file. Text is read until a
blank line is encountered.
+@endDefreq
@cindex form letters
@cindex letters, form
-Using these two requests it is easy to set up form letters. The form
+Using the @code{nx} and @code{rd} requests,
+it is easy to set up form letters. The form
letter template is constructed like this:
-@example
+@Example
.ce
\*(td
.sp 2
@@ -7165,9 +8390,9 @@ letter template is constructed like this:
Body of letter.
.bp
.nx repeat.let
-@end example
+@endExample
-@findex ex
+@rqindex ex
@noindent
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
@@ -7175,7 +8400,7 @@ 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.
-@example
+@Example
Trent A. Fisher
708 NW 19th Av., #202
Portland, OR 97209
@@ -7189,100 +8414,106 @@ San Diego, CA 92103
Dear Mr. Adollar,
.ex
-@end example
+@endExample
-@findex pi
-@code{pi}
+@Defreq {pi, pipe}
+Pipes the output of @code{gtroff} to the shell command(s)
+specified by @var{pipe}. This request must occur before
+@code{gtroff} has a chance to print anything.
+@endDefreq
-@c XXX documentation
-
-@findex sy
-The @code{sy} request will allow arbitrary system commands to be
-executed from within a @code{gtroff} document. The output is not saved
-anyplace, so it is up to the user to do so.
+@Defreq {sy, cmds}
+@Defregx {systat}
+In @dfn{unsafe} mode, executes the shell command(s) specified by
+@var{cmds}. The output is not saved anyplace, so it is up to the user
+to do so.
@c XXX add info about safer and unsafe mode
-For example, the following example will introduce the current time
+For example, the following example introduces the current time
into a document:
@cindex time, current
@cindex current time
@pindex perl
-@example
+@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
+@endExample
@noindent
Note that this works by having the @code{perl} script (run by @code{sy})
-print out the @code{nr} requests which will set the number registers
+print out the @code{nr} requests which set the number registers
@samp{H}, @samp{M} and @samp{S}, and then reads those commands in with
the @code{so} request.
-@vindex systat
@cindex @code{system()} return value register
-The @code{systat} number register contains the return value of the
-@code{system()} function executed by the last @code{sy} request.
+The @code{systat} read-write number register contains the return value
+of the @code{system()} function executed by the last @code{sy} request.
+@endDefreq
-@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.
+@Defreq {open, stream file}
+@Defreqx {opena, stream file}
+Opens the specified @var{file} for writing and
+associates the specified @var{stream} with it.
-@findex opena
The @code{opena} is like @code{open}, but if the file exists, append to
it instead of truncating it.
+@endDefreq
-@findex write
@cindex copy-in mode, and @code{write} requests
@cindex mode, copy-in, and @code{write} requests
-The @code{write} request will write to the file associated with the
-stream specified by the first argument. The stream must previously have
+@Defreq {write, stream data}
+Writes to the file associated with the specified @var{stream}.
+The stream must previously have
been the subject of an open request. The remainder of the line is
interpreted as the @code{ds} request reads its second argument: A
-leading @samp{"} will be stripped, and it will be read in copy-in mode.
+leading @samp{"} is stripped, and it is read in copy-in mode.
+@endDefreq
-@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
+@Defreq {close, stream}
+Closes the specified @var{stream};
+the stream is no longer an acceptable argument to the
@code{write} request.
@c XXX example
@ignore
-@example
+@Example
... example of open write &c...
-@end example
+@endExample
@end ignore
+@endDefreq
-@findex \V
-The @code{\V} escape will interpolate the contents of the specified
-environment variable, as returned by the function @code{getenv}. The
-argument to @code{\V} is specified as an identifier, i.e.@:
+@Defesc {\\V, ', xxx, '}
+Interpolates the contents of the specified
+environment variable, as returned by the function @code{getenv}.
+Specify the argument to @code{\V} 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.
+@endDefesc
@c =====================================================================
-@node Postprocessor Access, Miscellaneous, I/O, Programming Tutorial
+@node Postprocessor Access, Miscellaneous, I/O, gtroff Reference
@section Postprocessor Access
@cindex postprocessor access
@cindex access of postprocessor
-There are two escapes which will allow information to be directly given
-to the postprocessor. This is particularly useful for embedding
+There are two escapes which give information directly to the
+postprocessor. This is particularly useful for embedding
@sc{PostScript} into the final document.
-@findex \X
-The @code{\X} escape will embed its argument into the @code{gtroff}
+@Defesc {\\X, ', xxx, '}
+Embeds its argument into the @code{gtroff}
output preceded with @w{@samp{x X}}.
+@endDefesc
-@findex \Y
+@Defesc {\\Y, ', xxx, '}
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
@@ -7290,38 +8521,40 @@ 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 extension to
-the @acronym{UNIX} @code{troff} output format, and will confuse drivers
+the @acronym{UNIX} @code{troff} output format, and confuses drivers
that do not know about this extension.
+@endDefesc
@xref{Output Devices}.
@c =====================================================================
-@node Miscellaneous, Debugging, Postprocessor Access, Programming Tutorial
+@node Miscellaneous, Gtroff Internals, Postprocessor Access, gtroff Reference
@section Miscellaneous
@cindex miscellaneous
This section documents parts of @code{gtroff} which cannot (yet) be
categorized elsewhere in this manual.
-@findex nm
@cindex line numbers
@cindex numbers, line
-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@w{ }1. The second argument indicates on
-which lines numbers will be printed, i.e.@: 5 means put line numbers on
-every 5@w{ }lines; this defaults to@w{ }1. The third argument is the
+@Defreq {nm, start inc space indent}
+Prints line numbers in the left margin.
+@var{start} is the line number of the @emph{next}
+output line; this defaults to@w{ }1. @var{inc} indicates on
+which lines numbers are printed, i.e.@: 5 means put line numbers on
+every 5@w{ }lines; this defaults to@w{ }1. @var{space} is the
space to be left between the number and the text; this defaults to@w{
}1. The fourth argument is the indentation of the line numbers.
Without arguments, line numbers are turned off.
+@endDefreq
@c XXX xref ln register
-@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
+@Defreq {nn, [@Var{skip}]}
+Temporarily turns off line numbering. The
+argument is the number of lines not to be numbered; this defaults
to@w{ }1.
@c XXX (does this disable incrementing or display?)
@@ -7329,19 +8562,20 @@ to@w{ }1.
@c XXX example
@ignore
-@example
+@Example
... line numbering example ...
-@end example
+@endExample
@end ignore
+@endDefreq
-@findex mc
@cindex margin characters
@cindex characters for margins
-Margin characters can be automatically printed to the right of the text
-with the @code{mc} request. The first argument is the character to be
+@Defreq {mc, char dist}
+Prints margin characters to the right of the text.
+The first argument is the character to be
printed, and the second argument is the distance away from the main body
text. With no arguments the margin characters are turned off. If this
-occurs before a break, no margin character will be printed.
+occurs before a break, no margin character is printed.
@pindex nrchbar
@pindex changebar
@@ -7353,146 +8587,218 @@ there are programs available for doing this (they are called
@c XXX example
@ignore
-@example
+@Example
... margin char example ...
-@end example
+@endExample
@end ignore
+@endDefreq
-@findex lf
@pindex soelim
@cindex multi-file documents
@cindex documents, multi-file
-The primary reason for the existence of @code{lf} 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
+@Defreq {lf, line filename}
+A debugging aid for
+documents which are split into many files, then put together
+with @code{soelim} and other preprocessors. The second argument is the
+name of the file and the first argument is the input line number in
that file. This way @code{gtroff} can produce error messages which are
intelligible to the user.
@c XXX example
@ignore
-@example
+@Example
... example of soelim'ed doc ...
-@end example
+@endExample
@end ignore
+@endDefreq
+
+
+@c =====================================================================
+
+@node Gtroff Internals, Debugging, Miscellaneous, gtroff Reference
+@section @code{gtroff} Internals
+
+@cindex input token
+@cindex token, input
+@cindex output node
+@cindex node, output
+@code{gtroff} processes input in three steps. One or more input
+characters are converted to an @dfn{input token}. Then, one or more
+input tokens are converted to an @dfn{output node}. Finally, output
+nodes are converted to the intermediate output language understood by
+all output devices.
+
+For example, the input string @samp{fi\[:u]} is converted in a
+character token @samp{f}, a character token @samp{i}, and a special
+token @samp{:u} (representing u@w{ }umlaut). Later on, the character
+tokens @samp{f} and @samp{i} are merged to a single output node
+representing the ligature glyph @samp{fi}; the same happens with
+@samp{:u}. All output glyph nodes are `processed' which means that
+they are invariably associated with a given font, font size, advance
+width, etc. During the formatting process, @code{gtroff} itself adds
+various nodes to control the data flow.
+
+Macros, diversions, and strings collect elements in two chained lists:
+a list of input tokens which have been passed unprocessed, and a list
+of output nodes. Consider the following the diversion.
+
+@Example
+.di xxx
+a
+\!b
+c
+.br
+.di
+@endExample
+
+@noindent
+It contains these elements.
+
+@multitable {@i{vertical size node}} {token list} {element number}
+@item node list @tab token list @tab element number
+
+@item @i{line start node} @tab --- @tab 1
+@item @i{glyph node @code{a}} @tab --- @tab 2
+@item @i{word space node} @tab --- @tab 3
+@item --- @tab @code{b} @tab 4
+@item --- @tab @code{\n} @tab 5
+@item @i{glyph node @code{c}} @tab --- @tab 6
+@item @i{vertical size node} @tab --- @tab 7
+@item @i{vertical size node} @tab --- @tab 8
+@item --- @tab @code{\n} @tab 9
+@end multitable
+
+@esindex \v
+@rqindex unformat
+@noindent
+Elements 1, 7, and@w{ }8 are inserted by @code{gtroff}; the latter two
+(which are always present) specify the vertical extent of the last
+line, possibly modified by @code{\v}. The @code{br} request finishes
+the current partial line, inserting a newline input token which is
+subsequently converted to a space when the diversion is reread. Note
+that the word space node has a fixed width which isn't stretchable
+anymore. To convert horizontal space nodes back to input tokens, use
+the @code{unformat} request.
+
+Macros only contain elements in the token list (and the node list is
+empty); diversions and strings can contain elements in both lists.
@c =====================================================================
-@node Debugging, Implementation Differences, Miscellaneous, Programming Tutorial
+@node Debugging, Implementation Differences, Gtroff Internals, gtroff Reference
@section Debugging
@cindex debugging
@code{gtroff} 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 the standard error stream;
-this is very useful for printing debugging output.
+@Defreq {tm, string}
+Sends the @var{string} to the standard error stream;
+this is very useful for printing debugging output among other things.
+@endDefreq
+
+@cindex aborting
+@Defreq {ab, [@Var{string}]}
+Similar to the @code{tm} request, except that
+it causes @code{gtroff} to stop processing. With no argument it
+prints @samp{User Abort}.
+@endDefreq
+
+@cindex @code{ex}, use in debugging
+@cindex exiting
+@Defreq {ex, }
+The @code{ex} request also causes @code{gtroff} to stop processing
+if encountered at the topmost level; see also @ref{I/O}.
+@endDefreq
-@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
+@Example
.if \n(DB .tm debugging output
-@end example
+@endExample
@noindent
To activate these statements say
-@example
+@Example
groff -rDB=1 file
-@end example
-
-@item
-@findex ab
-@cindex aborting
-The @code{ab} request is similar to the @code{tm} request, except that
-it will cause @code{gtroff} to stop processing. With no argument it
-will print @samp{User Abort}.
+@endExample
-@item
-@findex ex@r{, use in debugging}
-@cindex exiting
-The @code{ex} request will also cause @code{gtroff} to stop processing
-if encountered at the topmost level; see also @ref{I/O}.
+@c XXX .tm1, .tmc requests
-@item
If it is known in advance that there will be many errors and no useful
output, @code{gtroff} can be forced to suppress formatted output with
the @option{-z} flag.
-@item
-@findex pm
@cindex dumping symbol table
@cindex symbol table, dumping
-The @code{pm} request will dump out the entire symbol table.
+@Defreq {pm, }
+The @code{pm} request prints out the entire symbol table on @code{stderr}.
+@endDefreq
-@item
-@findex pnr
@cindex dumping number registers
@cindex number registers, dumping
-The @code{pnr} request will print the names and contents of all
-currently defined number registers on stderr.
+@Defreq {pnr, }
+Prints the names and contents of all
+currently defined number registers on @code{stderr}.
+@endDefreq
-@item
-@findex ptr
@cindex dumping traps
@cindex traps, dumping
-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.
+@Defreq {ptr, }
+Prints the names and positions of all traps
+(not including input line traps and diversion traps) on @code{stderr}.
+Empty slots in the page trap list are printed as well, because they can
+affect the priority of subsequently planted traps.
+@endDefreq
-@item
-@findex fl
@cindex flush output
@cindex output, flush
@cindex interactive use of @code{gtroff}
@cindex @code{gtroff}, interactive use
-The @code{fl} request instructs @code{gtroff} to flush its output
-immediately. The intention is that this be used when using
-@code{gtroff} interactively. There is little other use for it. This
+@Defreq {fl, }
+Instructs @code{gtroff} to flush its output
+immediately. The intent is for interactive use.
+@code{gtroff}; there is little other use for it. This
request causes a line break.
+@endDefreq
-@item
-@findex backtrace
@cindex backtrace of input stack
@cindex input stack, backtrace
-The @code{backtrace} request will print a backtrace of the input stack
+@Defreq {backtrace, }
+The @code{backtrace} request prints a backtrace of the input stack
to the standard error stream.
+@endDefreq
-@item
@cindex warnings
@code{gtroff} has command line options for printing out more warnings
(@option{-w}) and for printing backtraces (@option{-b}) when a warning
or an error occurs. The most verbose level of warnings is @option{-ww}.
-@item
-@findex warn
-@vindex .warn
@cindex level of warnings
@cindex warnings, level
-The @code{warn} request controls the level of warnings checked for. The
-only 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,
-@w{@code{.warn 0}} will disable all warnings, and @w{@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
-
-@c ---------------------------------------------------------------------
+@Defreq {warn, [@Var{flags}]}
+@Defregx {.warn}
+Controls the level of warnings checked for. The @var{flags} are the sum
+of the numbers associated with each warning that is to be enabled; all
+other warnings are disabled. The number associated with each warning is
+listed below. For example, @w{@code{.warn 0}} disables all warnings,
+and @w{@code{.warn 1}} disables all warnings except that about missing
+characters. If an argument is not given, all warnings are enabled.
+
+The read-only number register @code{.warn} contains the current warning
+level.
+@endDefreq
@menu
-* Warnings::
+* Warnings::
@end menu
+@c ---------------------------------------------------------------------
+
@node Warnings, , Debugging, Debugging
@subsection Warnings
@cindex warnings
@@ -7525,8 +8831,8 @@ Missing or mismatched closing delimiters.
@item el
@itemx 16
-@findex ie
-@findex el
+@rqindex ie
+@rqindex el
Use of the @code{el} request with no matching @code{ie} request.
@xref{if-else}.
@@ -7544,28 +8850,30 @@ Dubious syntax in numeric expressions.
@item di
@itemx 256
-@findex di@r{, debugging}
-@findex da@r{, debugging}
+@rqindex di
+@rqindex da
+@cindex @code{di}, debugging
+@cindex @code{da}, debugging
Use of @code{di} or @code{da} without an argument when there is no
current diversion.
@item mac
@itemx 512
-@findex de
-@c XXX more findex entries
+@rqindex de
+@c XXX more index entries
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
+as empty. So, in most cases, at most one warning is given for each
name.
@item reg
@itemx 1024
-@findex nr
-@c XXX more findex entries
+@rqindex nr
+@c XXX more index entries
Use of undefined number registers. When an undefined number register is
used, that register is automatically defined to have a value of@w{ }0.
A definition is automatically made with a value of@w{ }0. So, in most
-cases, at most one warning will be given for use of a particular name.
+cases, at most one warning is given for use of a particular name.
@item tab
@itemx 2048
@@ -7573,7 +8881,8 @@ Use of a tab character where a number was expected.
@item right-brace
@itemx 4096
-@findex \@}@r{, debugging}
+@esindex \@}
+@cindex @code{\@}}, debugging
Use of @code{\@}} where a number was expected.
@item missing
@@ -7593,11 +8902,11 @@ encountered, the escape character is ignored.
@itemx 65536
@cindex compatibility mode
Missing space between a request or macro and its argument. This warning
-will be given when an undefined name longer than two characters is
+is 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
+name. The request or macro is not invoked. When this warning is
given, no macro is automatically defined. This is enabled by default.
-This warning will never occur in compatibility mode.
+This warning never occurs in compatibility mode.
@item font
@itemx 131072
@@ -7615,7 +8924,7 @@ All warnings.
@c =====================================================================
-@node Implementation Differences, Summary, Debugging, Programming Tutorial
+@node Implementation Differences, Summary, Debugging, gtroff Reference
@section Implementation Differences
@cindex implementation differences
@cindex differences in implementation
@@ -7629,46 +8938,48 @@ with documents written with old versions of @code{troff}.
@cindex long names
@cindex names, long
Long names cause some incompatibilities. @acronym{UNIX} @code{troff}
-will interpret
+interprets
-@example
+@Example
.dsabcd
-@end example
+@endExample
-@findex \*@r{, incompatibilities with Unix @code{troff}}
-@findex \n@r{, incompatibilities with Unix @code{troff}}
-@findex cp
+@esindex \*
+@esindex \n
+@cindex @code{\*}, incompatibilities with Unix @code{troff}
+@cindex @code{\n}, incompatibilities with Unix @code{troff}
+@rqindex cp
@vindex .C
@noindent
as defining a string @samp{ab} with contents @samp{cd}. Normally, GNU
-@code{troff} will interpret this as a call of a macro named
-@code{dsabcd}. Also @acronym{UNIX} @code{troff} will interpret
+@code{troff} interprets this as a call of a macro named
+@code{dsabcd}. Also @acronym{UNIX} @code{troff} interprets
@code{\*[} or @code{\n[} as references to a string or number register
-called @samp{[}. In GNU @code{troff}, however, this will normally be
+called @samp{[}. In GNU @code{troff}, however, this is normally
interpreted as the start of a long name. In compatibility mode GNU
-@code{troff} will interpret these things in the traditional way. In
-compatibility mode, however, long names are not recognized.
+@code{troff} interprets long names in the traditional way
+(which means that they are not recognized as names).
Compatibility mode can be turned on with the @option{-C} command line
option, and turned on or off with the @code{cp} request. The number
register @code{.C} is@w{ }1 if compatibility mode is on, 0@w{
}otherwise.
-@findex \A
-@findex \|
-@findex \^
-@findex \&
-@findex \@}
-@findex \@{
-@findex \@key{SP}
-@findex \'
-@findex \`
-@findex \-
-@findex \_
-@findex \!
-@findex \%
-@findex \c
+@esindex \A
+@esindex \|
+@esindex \^
+@esindex \&
+@esindex \@{
+@esindex \@}
+@esindex \@key{SP}
+@esindex \'
+@esindex \`
+@esindex \-
+@esindex \_
+@esindex \!
+@esindex \%
+@esindex \c
GNU @code{troff} does not allow the use of the escape sequences
-@code{\|}, @code{\^}, @code{\&}, @code{\@}}, @code{\@{},
+@code{\|}, @code{\^}, @code{\&}, @code{\@{}, @code{\@}},
@code{\@key{SP}}, @code{\'}, @code{\`}, @code{\-}, @code{\_}, @code{\!},
@code{\%}, and @code{\c} in names of strings, macros, diversions, number
registers, fonts or environments; @acronym{UNIX} @code{troff} does. The
@@ -7677,31 +8988,37 @@ avoiding use of these escape sequences in names.
@cindex fractional point sizes
@cindex point sizes, fractional
-@findex ps@r{, incompatibilities with Unix @code{troff}}
+@rqindex ps
+@cindex @code{ps}, incompatibilities with Unix @code{troff}
Fractional point sizes cause one noteworthy incompatibility. In
@acronym{UNIX} @code{troff} the @code{ps} request ignores scale
indicators and thus
-@example
+@Example
.ps 10u
-@end example
+@endExample
@noindent
-will set the point size to 10@w{ }points, whereas in GNU @code{troff} it
-will set the point size to 10@w{ }scaled points. @xref{Fractional Type
+sets the point size to 10@w{ }points, whereas in GNU @code{troff} it
+sets the point size to 10@w{ }scaled points. @xref{Fractional Type
Sizes}, for more information.
-@findex bd@r{, incompatibilities with Unix @code{troff}}
-@findex cs@r{, incompatibilities with Unix @code{troff}}
-@findex tkf@r{, incompatibilities with Unix @code{troff}}
-@findex tr@r{, incompatibilities with Unix @code{troff}}
-@findex fp@r{, incompatibilities with Unix @code{troff}}
+@rqindex bd
+@rqindex cs
+@rqindex tkf
+@rqindex tr
+@rqindex fp
+@cindex @code{bd}, incompatibilities with Unix @code{troff}
+@cindex @code{cs}, incompatibilities with Unix @code{troff}
+@cindex @code{tkf}, incompatibilities with Unix @code{troff}
+@cindex @code{tr}, incompatibilities with Unix @code{troff}
+@cindex @code{fp}, incompatibilities with Unix @code{troff}
@cindex input and output characters, compatibility with Unix
@cindex output characters, compatibility with Unix
@cindex characters, input and output, compatibility with Unix
In GNU @code{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
+Everything that affects how an output character is 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.
@@ -7714,40 +9031,46 @@ 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
+@Example
.di x
\\\\
.br
.di
.x
-@end example
-
-@findex \e@r{, incompatibilities with Unix @code{troff}}
-@findex \!@r{, incompatibilities with Unix @code{troff}}
-@findex \?@r{, incompatibilities with Unix @code{troff}}
+@endExample
+
+@esindex \e
+@esindex \!
+@esindex \?
+@cindex @code{\e}, incompatibilities with Unix @code{troff}
+@cindex @code{\!}, incompatibilities with Unix @code{troff}
+@cindex @code{\?}, incompatibilities with Unix @code{troff}
@cindex transparent output, incompatibilities with Unix @code{troff}
@cindex output, transparent, incompatibilities with Unix @code{troff}
@noindent
-will print @samp{\\} in GNU @code{troff}; each pair of input backslashes
+prints @samp{\\} in GNU @code{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.
@acronym{UNIX} @code{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 sequence: This always prints 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 @code{troff} and @acronym{UNIX}
+diversion; it also works in both GNU @code{troff} and @acronym{UNIX}
@code{troff}. To store, for some reason, an escape sequence in a
diversion that will be interpreted when the diversion is reread, either
use the traditional @code{\!} transparent output facility, or, if this
is unsuitable, the new @code{\?} escape sequence.
+@c XXX .tl compatibility mode -> input stack level
+@c XXX .if compatibility mode -> input stack level
+
@xref{Diversions}, for more information.
@c =====================================================================
-@node Summary, , Implementation Differences, Programming Tutorial
+@node Summary, , Implementation Differences, gtroff Reference
@section Summary
@cindex summary
@@ -7758,7 +9081,7 @@ is unsuitable, the new @code{\?} escape sequence.
@c =====================================================================
@c =====================================================================
-@node Preprocessors, Output Devices, Programming Tutorial, Top
+@node Preprocessors, Output Devices, gtroff Reference, Top
@chapter Preprocessors
@cindex preprocessors
@@ -7766,13 +9089,13 @@ This chapter describes all preprocessors that come with @code{groff} or
which are freely available.
@menu
-* geqn::
-* gtbl::
-* gpic::
-* ggrn::
-* grap::
-* grefer::
-* gsoelim::
+* geqn::
+* gtbl::
+* gpic::
+* ggrn::
+* grap::
+* grefer::
+* gsoelim::
@end menu
@@ -7786,7 +9109,7 @@ which are freely available.
@c XXX
@menu
-* Invoking geqn::
+* Invoking geqn::
@end menu
@c ---------------------------------------------------------------------
@@ -7809,7 +9132,7 @@ which are freely available.
@c XXX
@menu
-* Invoking gtbl::
+* Invoking gtbl::
@end menu
@c ---------------------------------------------------------------------
@@ -7832,7 +9155,7 @@ which are freely available.
@c XXX
@menu
-* Invoking gpic::
+* Invoking gpic::
@end menu
@c ---------------------------------------------------------------------
@@ -7855,7 +9178,7 @@ which are freely available.
@c XXX
@menu
-* Invoking ggrn::
+* Invoking ggrn::
@end menu
@c ---------------------------------------------------------------------
@@ -7892,7 +9215,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking grefer::
+* Invoking grefer::
@end menu
@c ---------------------------------------------------------------------
@@ -7915,7 +9238,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking gsoelim::
+* Invoking gsoelim::
@end menu
@c ---------------------------------------------------------------------
@@ -7940,14 +9263,14 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Special Characters::
-* grotty::
-* grops::
-* grodvi::
-* grolj4::
-* grolbp::
-* grohtml::
-* gxditview::
+* Special Characters::
+* grotty::
+* grops::
+* grodvi::
+* grolj4::
+* grolbp::
+* grohtml::
+* gxditview::
@end menu
@@ -7972,7 +9295,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking grotty::
+* Invoking grotty::
@end menu
@c ---------------------------------------------------------------------
@@ -7994,8 +9317,8 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking grops::
-* Embedding PostScript::
+* Invoking grops::
+* Embedding PostScript::
@end menu
@c ---------------------------------------------------------------------
@@ -8026,7 +9349,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking grodvi::
+* Invoking grodvi::
@end menu
@c ---------------------------------------------------------------------
@@ -8048,7 +9371,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking grolj4::
+* Invoking grolj4::
@end menu
@c ---------------------------------------------------------------------
@@ -8070,7 +9393,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking grolbp::
+* Invoking grolbp::
@end menu
@c ---------------------------------------------------------------------
@@ -8092,7 +9415,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking grohtml::
+* Invoking grohtml::
@end menu
@c ---------------------------------------------------------------------
@@ -8114,7 +9437,7 @@ is available as an extra package from the following address:
@c XXX
@menu
-* Invoking gxditview::
+* Invoking gxditview::
@end menu
@c ---------------------------------------------------------------------
@@ -8140,8 +9463,8 @@ is available as an extra package from the following address:
@c XXX
@menu
-* gtroff Output::
-* Font Files::
+* gtroff Output::
+* Font Files::
@end menu
@@ -8153,14 +9476,15 @@ is available as an extra package from the following address:
@cindex output, @code{gtroff}
This section describes the format output of GNU @code{troff}. The
-output format used by GNU @code{troff} is very similar to that used by
+output format used by GNU @code{troff} is very similar -- but
+not identical -- to that used by
@acronym{UNIX} device-independent @code{troff} (@code{ditroff}).
@menu
-* Output Format::
-* Device Control::
-* Drawing Functions::
-* Line Continuation::
+* Output Format::
+* Device Control::
+* Drawing Functions::
+* Line Continuation::
@end menu
@c ---------------------------------------------------------------------
@@ -8182,10 +9506,10 @@ parameters which are separated from subsequent text by whitespace or a
newline.
The names of characters and fonts can be of arbitrary length; drivers
-should not assume that they will be only two characters long (as
+should not assume that they are only two characters long (as
@code{ditroff} does).
-When a character is to be printed, that character will always be in the
+When a character is to be printed, that character is always in the
current font. Unlike @code{ditroff}, it is not necessary for drivers to
search special fonts to find a character.
@@ -8286,28 +9610,28 @@ points.
The first three output commands are guaranteed to be:
-@example
+@Example
x T device
x res n h v
x init
-@end example
+@endExample
@noindent
For example, the input
-@example
+@Example
crunchy \fH\s+2frog\s0\fP!?
-@end example
+@endExample
@noindent
-will produce
+produces
@c XXX example
@ignore
-@example
+@Example
... sample output here ...
-@end example
+@endExample
@end ignore
@c ---------------------------------------------------------------------
@@ -8318,8 +9642,8 @@ will produce
@cindex functions for drawing
@pindex gpic
-The @samp{D} drawing command has been extended. These extensions will
-only be used by GNU @code{pic} if the @option{-x} option is given.
+The @samp{D} drawing command has been extended. These extensions are
+used by GNU @code{pic} only if the @option{-x} option is given.
@xref{Drawing Requests}.
@@ -8331,11 +9655,11 @@ Set the shade of gray to be used for filling solid objects to@w{
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@w{
-}1000 will be used. Whatever color a solid object has, it should
+}1000 is used. Whatever color a solid object has, it should
completely obscure everything beneath it. A value greater than@w{ }1000
or less than@w{ }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.
+is black, but some drivers may provide a way of changing this.
@item DC @var{d}
Draw a solid circle with a diameter of@w{ }@var{d} with the leftmost
@@ -8347,11 +9671,12 @@ vertical diameter of@w{ }@var{dy} with the leftmost point at the current
position.
@item Dp @var{dx1} @var{dy1} @var{dx2} @var{dy2} @dots{} @var{dxn} @var{dyn}
-Draw a polygon with. The first vertex is at the current position, the
-second vertex at an offset (@var{dx1},@var{dy1}) from the current
-position, the second vertex at an offset (@var{dx2},@var{dy2}) from the
-first vertex, and so on up to the @var{n}-th vertex. At the moment, GNU
-@code{pic} only uses this command to generate triangles and rectangles.
+Draw a polygon with automatic closure. The first vertex is at the
+current position, the second vertex at an offset (@var{dx1},@var{dy1})
+from the current position, the second vertex at an offset
+(@var{dx2},@var{dy2}) from the first vertex, and so on up to the
+@var{n}@dmn{th} vertex. At the moment, GNU @code{pic} only uses this
+command to generate triangles and rectangles.
@item DP @var{dx1} @var{dy1} @var{dx2} @var{dy2} @dots{} @var{dxn} @var{dyn}
Like @code{Dp} but draw a solid rather than outlined polygon.
@@ -8367,24 +9692,24 @@ has been given with a negative value of@w{ }@var{n}. A zero value of@w{
}@var{n} selects the smallest available line thickness.
@end table
-@findex \D
+@esindex \D
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 @code{pic} does not depend on this. Given a
drawing command of the form
-@example
+@Example
\D'@var{c} @var{x1} @var{y1} @var{x2} @var{y2} @dots{} @var{xn} @var{yn}'
-@end example
+@endExample
-@findex \w
+@esindex \w
@vindex st
-@findex sb
+@vindex sb
@noindent
where @var{c} is not one of @samp{c}, @samp{e}, @samp{l}, @samp{a} or
-@samp{~}, @acronym{UNIX} @code{troff} will treat each of the x@w{ }value
-as a horizontal quantity, and each of the y@w{ }values as a vertical
-quantity and will assume that the width of the drawn object is sum if
+@samp{~}, @acronym{UNIX} @code{troff} treats each x@w{ }value
+as a horizontal quantity, and each y@w{ }value as a vertical
+quantity; it assumes that the width of the drawn object is the sum of
all x@w{ }values, and that the height is the sum of all y@w{ }values.
(The assumption about the height can be seen by examining the @code{st}
and @code{sb} registers after using such a @code{D}@w{ }command in a
@@ -8395,9 +9720,9 @@ produces an ugly result in the case of the @code{Df}, @code{Dt}, and, to
a lesser extent, @code{DE}@w{ }commands. Thus after executing a
@code{D}@w{ }command of the form
-@example
+@Example
D@var{c} @var{x1} @var{y1} @var{x2} @var{y2} @dots{} @var{xn} @var{yn}
-@end example
+@endExample
@noindent
the current position should be increased horizontally by the sum of all
@@ -8412,8 +9737,8 @@ x@w{ }values and vertically by the sum of all y@w{ }values.
There is a continuation convention which permits the argument to the
@w{@samp{x X}} command to contain newlines: When outputting the argument
-to the @w{@samp{x X}} command, GNU @code{troff} will follow each newline
-in the argument with a @samp{+} character (as usual, it will terminate
+to the @w{@samp{x X}} command, GNU @code{troff} follows each newline
+in the argument with a @samp{+} character (as usual, it terminates
the entire argument with a newline); thus if the line after the line
containing the @w{@samp{x X}} command starts with @samp{+}, then the
newline ending the line containing the @w{@samp{x X}} command should be
@@ -8439,14 +9764,14 @@ file called @file{DESC} and for each font@w{ }@var{f} a font file
called@w{ }@file{@var{f}}.
@menu
-* DESC file format::
-* Font file format::
+* DESC File Format::
+* Font File Format::
@end menu
@c ---------------------------------------------------------------------
-@node DESC file format, Font file format, Font Files, Font Files
-@subsection @file{DESC} file format
+@node DESC File Format, Font File Format, Font Files, Font Files
+@subsection @file{DESC} File Format
@cindex @file{DESC} file format
@cindex font description file format
@cindex format of font description file
@@ -8493,16 +9818,15 @@ list can extend over more than one line.
@item styles @var{S1} @var{S2} @dots{} @var{Sm}
@kindex styles
-The first @var{m}@w{ }font positions will be associated with styles
+The first @var{m}@w{ }font positions are associated with styles
@var{S1} @dots{} @var{Sm}.
@item fonts @var{n} @var{F1} @var{F2} @var{F3} @dots{} @var{Fn}
@kindex fonts
-Fonts @var{F1} @dots{} @var{Fn} will be mounted in the font positions
+Fonts @var{F1} @dots{} @var{Fn} are 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@var{ }0 will cause no font to be mounted on the corresponding font
-position.
+of@var{ }0 means no font is mounted on the corresponding font position.
@item family @var{fam}
@kindex family
@@ -8524,8 +9848,8 @@ in the @file{DESC} file.
@c ---------------------------------------------------------------------
-@node Font file format, , DESC file format, Font Files
-@subsection Font file format
+@node Font File Format, , DESC File Format, Font Files
+@subsection Font File Format
@cindex font file format
@cindex format of font files
@@ -8558,7 +9882,7 @@ than one line.
@item special
@kindex 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
+is not present in the current font, it is searched for in any
special fonts that are mounted.
@end table
@@ -8585,13 +9909,13 @@ separated by blanks or tabs. The format is
@c XXX fix it for new HTML additions
-@example
+@Example
@var{name} @var{metrics} @var{type} @var{code} @var{comment}
-@end example
+@endExample
@cindex 8-bit input
@cindex input, 8-bit
-@findex \N
+@esindex \N
@kindex ---
@noindent
@var{name} identifies the character: If @var{name} is a single
@@ -8628,18 +9952,18 @@ the character has both an ascender and a descender, for example, `('.
The @var{code} field gives the code which the postprocessor uses to
print the character. The character can also be input to @code{gtroff}
using this code by means of the @code{\N} escape sequence. The code can
-be any integer. If it starts with @samp{0} it will be interpreted as
-octal; if it starts with @samp{0x} or @samp{0X} it will be interpreted as
+be any integer. If it starts with @samp{0} it is interpreted as
+octal; if it starts with @samp{0x} or @samp{0X} it is interpreted as
hexadecimal.
-Anything on the line after the @var{code} field will be ignored.
+Anything on the line after the @var{code} field is ignored.
The @var{metrics} field has the form:
-@example
+@Example
@var{width}[,@var{height}[,@var{depth}[,@var{italic_correction}
[,@var{left_italic_correction}[,@var{subscript_correction}]]]]]
-@end example
+@endExample
@noindent
There must not be any spaces between these subfields (it has been split
@@ -8657,19 +9981,19 @@ the lowest point below the baseline to which the character extends
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
+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
+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
+@Example
@var{name} "
-@end example
+@endExample
@noindent
This indicates that @var{name} is just another name for the character
@@ -8679,13 +10003,14 @@ mentioned in the preceding line.
The word @code{kernpairs} starts the kernpairs section. This contains a
sequence of lines of the form:
-@example
+@Example
@var{c1} @var{c2} @var{n}
-@end example
+@endExample
+@noindent
This means that when character @var{c1} appears next to character
@var{c2} the space between them should be increased by@w{ }@var{n}.
-Most entries in kernpairs section will have a negative value for@w{
+Most entries in the kernpairs section have a negative value for@w{
}@var{n}.
@@ -8693,7 +10018,7 @@ Most entries in kernpairs section will have a negative value for@w{
@c =====================================================================
@c =====================================================================
-@node Installation, Request and Escape Index, File formats, Top
+@node Installation, Request Index, File formats, Top
@chapter Installation
@cindex installation
@@ -8704,21 +10029,30 @@ Most entries in kernpairs section will have a negative value for@w{
@c =====================================================================
@c =====================================================================
-@node Request and Escape Index, Operator Index, Installation, Top
-@chapter Request and Escape Index
+@node Request Index, Escape Index, Installation, Top
+@chapter Request Index
-In this index, escapes are listed with a leading backslash (@samp{\}) to
-distinguish them from requests which appear without the leading control
-character (normally either @samp{.} or @samp{'}).
+Requests appear without the leading control character (normally either
+@samp{.} or @samp{'}).
-@printindex fn
+@printindex rq
@c =====================================================================
@c =====================================================================
-@node Operator Index, Register Index, Request and Escape Index, Top
+@node Escape Index, Operator Index, Request Index, Top
+@chapter Escape Index
+
+@printindex es
+
+
+
+@c =====================================================================
+@c =====================================================================
+
+@node Operator Index, Register Index, Escape Index, Top
@chapter Operator Index
@printindex op
@@ -8728,7 +10062,7 @@ character (normally either @samp{.} or @samp{'}).
@c =====================================================================
@c =====================================================================
-@node Register Index, Macro and String Index, Operator Index, Top
+@node Register Index, Macro Index, Operator Index, Top
@chapter Register Index
@printindex vr
@@ -8738,12 +10072,8 @@ character (normally either @samp{.} or @samp{'}).
@c =====================================================================
@c =====================================================================
-@node Macro and String Index, Glyph Name Index, Register Index, Top
-@chapter Macro and String Index
-
-In this index, strings are listed with the calling escape sequence
-(@samp{\*}) to distinguish them from macros which appear without the
-leading control character (normally either @samp{.} or @samp{'}).
+@node Macro Index, String Index, Register Index, Top
+@chapter Macro Index
@printindex ma
@@ -8752,7 +10082,17 @@ leading control character (normally either @samp{.} or @samp{'}).
@c =====================================================================
@c =====================================================================
-@node Glyph Name Index, Font File Keyword Index, Macro and String Index, Top
+@node String Index, Glyph Name Index, Macro Index, Top
+@chapter String Index
+
+@printindex st
+
+
+
+@c =====================================================================
+@c =====================================================================
+
+@node Glyph Name Index, Font File Keyword Index, String Index, Top
@chapter Glyph Name Index
A glyph name @code{xx} consisting of exactly two characters can be
diff --git a/contrib/groff/doc/homepage.ms b/contrib/groff/doc/homepage.ms
index b542d73..00da216 100644
--- a/contrib/groff/doc/homepage.ms
+++ b/contrib/groff/doc/homepage.ms
@@ -2,9 +2,9 @@
.\" with groff.
.\"
.\"
-.\" To make it work with other output devices also, we include tmac.arkup
+.\" To make it work with other output devices also, we include arkup.tmac
.\" directly.
-.mso tmac.arkup
+.mso arkup.tmac
.\"
.LP
.\"
@@ -139,16 +139,18 @@ 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
+\fP
.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.
+Note that groff@gnu.org is an alias for
+.MAILTO groff@ffii.org 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
+.MAILTO groff-request@ffii.org 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
@@ -157,6 +159,6 @@ It is now maintained by
.MAILTO Ted.Harding@nessie.mcc.ac.uk "Ted Harding"
and
.MAILTO wl@gnu.org "Werner Lemberg" .
-.LINE
+.br
.
.\" EOF
diff --git a/contrib/groff/doc/meref.me b/contrib/groff/doc/meref.me
index 445fcd7..e99bfd0 100644
--- a/contrib/groff/doc/meref.me
+++ b/contrib/groff/doc/meref.me
@@ -1271,7 +1271,7 @@ is spread or broken (including hyphenated).
In other words,
it is safe in nofill mode only.
.TL
-.b sm
+.b .sm
.i W
.i X
.DE
@@ -2021,7 +2021,7 @@ NAME TYPE DESCRIPTION
\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 umlaut
\e*< S begin subscript
\e*> S end subscript
\&.EN M end equation
diff --git a/contrib/groff/doc/pic.ms b/contrib/groff/doc/pic.ms
index 8553953..a38d58f 100644
--- a/contrib/groff/doc/pic.ms
+++ b/contrib/groff/doc/pic.ms
@@ -10,7 +10,7 @@
.\" 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.1.1 2000/02/06 09:39:20 wlemb Exp $
+.\" $Id: pic.ms,v 1.3 2001/04/13 17:11:32 wlemb Exp $
.\"
.\" Set a proper TeX
.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
@@ -806,7 +806,7 @@ 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.
+In places where \fIn\fBth\fR is allowed, \fB`\fIexpr\fB'th\fR is also allowed.
Note that
.B 'th
is a single token: no space is allowed between the
@@ -947,7 +947,7 @@ 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
+form marked by \fBof\fP; thus, \fBcenter of last circle\fP 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
@@ -1004,7 +1004,7 @@ 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.
+\fB1/3 <here, last ellipse>\fP.
.KS
.PS
arrow up right;
@@ -1048,9 +1048,9 @@ 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 .ne); "\fB(B,A)\fP 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 .sw); "\fB(A,B)\fP 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"
@@ -1368,16 +1368,17 @@ 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
+Various built-in functions are supported: \fBsin(\fIx\fB)\fR,
+\fBcos(\fIx\fB)\fR, \fBlog(\fIx\fB)\fR, \fBexp(\fIx\fB)\fR,
+\fBsqrt(\fIx\fB)\fR, \fBmax(\fIx\fB,\fIy\fB)\fR,
+\fBatan2(\fIx\fB,\fIy\fB)\fR, \fBmin(\fIx\fB,\fIy\fB)\fR,
+\fBint(\fIx\fB)\fR, 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
+\fBrand(\fIx\fB)\fR, which returns a random number between 1 and
\fIx\fP, but this is deprecated and may be removed in a future
version.
.PP
@@ -1966,7 +1967,7 @@ multiple-part pattern:
\&
\& line down from 1st box .s lineht;
\& A: line down;
-\& line down from 2nd box .s; filter "\\fBhtml2ms";
+\& line down from 2nd box .s; filter "\\fBhtml2ms\\fP";
\& B: line down;
\& line down from 3rd box .s; filter "\\fBformat\\fP";
\& C: line down;
@@ -2032,7 +2033,7 @@ Top: [
line down from 1st box .s lineht;
A: line down;
- line down from 2nd box .s; filter "\fBhtml2ms";
+ line down from 2nd box .s; filter "\fBhtml2ms\fP";
B: line down;
line down from 3rd box .s; filter "\fBformat\fP";
C: line down;
@@ -2238,8 +2239,6 @@ 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
@@ -2295,7 +2294,7 @@ 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
+expression, as opposed to a numeric literal) is not documented in DWB
\fBpic\fR(1).
.PP
The following style variables control output:
diff --git a/contrib/groff/font/devX100-12/CB b/contrib/groff/font/devX100-12/CB
new file mode 100644
index 0000000..d151ee3
--- /dev/null
+++ b/contrib/groff/font/devX100-12/CB
@@ -0,0 +1,308 @@
+name CB
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+dq "
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/CBI b/contrib/groff/font/devX100-12/CBI
new file mode 100644
index 0000000..f298973
--- /dev/null
+++ b/contrib/groff/font/devX100-12/CBI
@@ -0,0 +1,308 @@
+name CBI
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+dq "
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/CI b/contrib/groff/font/devX100-12/CI
new file mode 100644
index 0000000..3f1437f
--- /dev/null
+++ b/contrib/groff/font/devX100-12/CI
@@ -0,0 +1,308 @@
+name CI
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+dq "
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/CR b/contrib/groff/font/devX100-12/CR
new file mode 100644
index 0000000..895c5dd
--- /dev/null
+++ b/contrib/groff/font/devX100-12/CR
@@ -0,0 +1,308 @@
+name CR
+spacewidth 10
+charset
+--- 10,1 0 040
+! 10,11 0 041
+" 10,11 0 042
+dq "
+# 10,11,1 0 043
+sh "
+$ 10,12,1 0 044
+Do "
+% 10,11 0 045
+& 10,9 0 046
+' 10,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/DESC b/contrib/groff/font/devX100-12/DESC
new file mode 100644
index 0000000..ead70b9
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX100-12/HB b/contrib/groff/font/devX100-12/HB
new file mode 100644
index 0000000..9e91e0b
--- /dev/null
+++ b/contrib/groff/font/devX100-12/HB
@@ -0,0 +1,308 @@
+name HB
+spacewidth 5
+charset
+--- 5,1 0 040
+! 6,12 0 041
+" 8,12 0 042
+dq "
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 12,12 0 046
+' 5,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/HBI b/contrib/groff/font/devX100-12/HBI
new file mode 100644
index 0000000..12011ca
--- /dev/null
+++ b/contrib/groff/font/devX100-12/HBI
@@ -0,0 +1,308 @@
+name HBI
+spacewidth 5
+charset
+--- 5,1 0 040
+! 6,12 0 041
+" 8,12 0 042
+dq "
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 12,12 0 046
+' 5,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/HI b/contrib/groff/font/devX100-12/HI
new file mode 100644
index 0000000..c5be9f9
--- /dev/null
+++ b/contrib/groff/font/devX100-12/HI
@@ -0,0 +1,308 @@
+name HI
+spacewidth 5
+charset
+--- 5,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+dq "
+# 9,12 0 043
+sh "
+$ 9,13,1 0 044
+Do "
+% 14,12 0 045
+& 11,12 0 046
+' 4,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/HR b/contrib/groff/font/devX100-12/HR
new file mode 100644
index 0000000..55d6bf5
--- /dev/null
+++ b/contrib/groff/font/devX100-12/HR
@@ -0,0 +1,308 @@
+name HR
+spacewidth 5
+charset
+--- 5,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+dq "
+# 9,11 0 043
+sh "
+$ 9,13,2 0 044
+Do "
+% 14,12 0 045
+& 11,12 0 046
+' 4,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/Makefile.sub b/contrib/groff/font/devX100-12/Makefile.sub
new file mode 100644
index 0000000..d074757
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX100-12/NB b/contrib/groff/font/devX100-12/NB
new file mode 100644
index 0000000..975de35
--- /dev/null
+++ b/contrib/groff/font/devX100-12/NB
@@ -0,0 +1,308 @@
+name NB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+dq "
+# 10,12 0 043
+sh "
+$ 10,14,1 0 044
+Do "
+% 14,12 0 045
+& 14,12 0 046
+' 4,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/NBI b/contrib/groff/font/devX100-12/NBI
new file mode 100644
index 0000000..d67e0e4
--- /dev/null
+++ b/contrib/groff/font/devX100-12/NBI
@@ -0,0 +1,308 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,12 0 041
+" 7,12 0 042
+dq "
+# 10,12 0 043
+sh "
+$ 9,14,1 0 044
+Do "
+% 15,12 0 045
+& 15,12 0 046
+' 4,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/NI b/contrib/groff/font/devX100-12/NI
new file mode 100644
index 0000000..be54ca3
--- /dev/null
+++ b/contrib/groff/font/devX100-12/NI
@@ -0,0 +1,308 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,12 0 041
+" 7,12 0 042
+dq "
+# 9,12 0 043
+sh "
+$ 9,14,1 0 044
+Do "
+% 14,12 0 045
+& 14,12 0 046
+' 3,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/NR b/contrib/groff/font/devX100-12/NR
new file mode 100644
index 0000000..f4f922e
--- /dev/null
+++ b/contrib/groff/font/devX100-12/NR
@@ -0,0 +1,308 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,12 0 041
+" 6,12 0 042
+dq "
+# 9,12 0 043
+sh "
+$ 9,13,2 0 044
+Do "
+% 14,12 0 045
+& 13,12 0 046
+' 3,12 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/S b/contrib/groff/font/devX100-12/S
new file mode 100644
index 0000000..453c295
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX100-12/TB b/contrib/groff/font/devX100-12/TB
new file mode 100644
index 0000000..b81e017
--- /dev/null
+++ b/contrib/groff/font/devX100-12/TB
@@ -0,0 +1,308 @@
+name TB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 9,11 0 042
+dq "
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 16,12 0 045
+& 14,11 0 046
+' 6,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/TBI b/contrib/groff/font/devX100-12/TBI
new file mode 100644
index 0000000..712f7d2
--- /dev/null
+++ b/contrib/groff/font/devX100-12/TBI
@@ -0,0 +1,308 @@
+name TBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 9,11 0 042
+dq "
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 6,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/TI b/contrib/groff/font/devX100-12/TI
new file mode 100644
index 0000000..72ed683
--- /dev/null
+++ b/contrib/groff/font/devX100-12/TI
@@ -0,0 +1,308 @@
+name TI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 6,11 0 041
+" 7,10 0 042
+dq "
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 6,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100-12/TR b/contrib/groff/font/devX100-12/TR
new file mode 100644
index 0000000..989dd56
--- /dev/null
+++ b/contrib/groff/font/devX100-12/TR
@@ -0,0 +1,308 @@
+name TR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 7,11 0 042
+dq "
+# 8,11 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 14,11 0 045
+& 13,11 0 046
+' 5,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/CB b/contrib/groff/font/devX100/CB
new file mode 100644
index 0000000..7353611
--- /dev/null
+++ b/contrib/groff/font/devX100/CB
@@ -0,0 +1,308 @@
+name CB
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+dq "
+# 9,10,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/CBI b/contrib/groff/font/devX100/CBI
new file mode 100644
index 0000000..d590a19
--- /dev/null
+++ b/contrib/groff/font/devX100/CBI
@@ -0,0 +1,308 @@
+name CBI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,10 0 041
+" 9,9 0 042
+dq "
+# 9,11,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/CI b/contrib/groff/font/devX100/CI
new file mode 100644
index 0000000..484eeca
--- /dev/null
+++ b/contrib/groff/font/devX100/CI
@@ -0,0 +1,308 @@
+name CI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+dq "
+# 9,10,1 0 043
+sh "
+$ 9,10,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/CR b/contrib/groff/font/devX100/CR
new file mode 100644
index 0000000..b8b35d1
--- /dev/null
+++ b/contrib/groff/font/devX100/CR
@@ -0,0 +1,308 @@
+name CR
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+dq "
+# 9,9,1 0 043
+sh "
+$ 9,11,2 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/DESC b/contrib/groff/font/devX100/DESC
new file mode 100644
index 0000000..7f63535
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX100/HB b/contrib/groff/font/devX100/HB
new file mode 100644
index 0000000..1a1d963
--- /dev/null
+++ b/contrib/groff/font/devX100/HB
@@ -0,0 +1,308 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 7,11 0 042
+dq "
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/HBI b/contrib/groff/font/devX100/HBI
new file mode 100644
index 0000000..bcfbfae
--- /dev/null
+++ b/contrib/groff/font/devX100/HBI
@@ -0,0 +1,308 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 7,11 0 042
+dq "
+# 10,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/HI b/contrib/groff/font/devX100/HI
new file mode 100644
index 0000000..4be615c
--- /dev/null
+++ b/contrib/groff/font/devX100/HI
@@ -0,0 +1,308 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+dq "
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/HR b/contrib/groff/font/devX100/HR
new file mode 100644
index 0000000..f462a24
--- /dev/null
+++ b/contrib/groff/font/devX100/HR
@@ -0,0 +1,308 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+dq "
+# 8,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/Makefile.sub b/contrib/groff/font/devX100/Makefile.sub
new file mode 100644
index 0000000..4d40f0f
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX100/NB b/contrib/groff/font/devX100/NB
new file mode 100644
index 0000000..f99169e
--- /dev/null
+++ b/contrib/groff/font/devX100/NB
@@ -0,0 +1,308 @@
+name NB
+spacewidth 11
+charset
+--- 11,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+dq "
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/NBI b/contrib/groff/font/devX100/NBI
new file mode 100644
index 0000000..dd940af
--- /dev/null
+++ b/contrib/groff/font/devX100/NBI
@@ -0,0 +1,308 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+dq "
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11,1 0 045
+& 13,11 0 046
+' 4,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/NI b/contrib/groff/font/devX100/NI
new file mode 100644
index 0000000..bb31b53
--- /dev/null
+++ b/contrib/groff/font/devX100/NI
@@ -0,0 +1,308 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+dq "
+# 11,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 12,11,1 0 045
+& 11,11 0 046
+' 4,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/NR b/contrib/groff/font/devX100/NR
new file mode 100644
index 0000000..729f76e
--- /dev/null
+++ b/contrib/groff/font/devX100/NR
@@ -0,0 +1,308 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,11 0 041
+" 5,11 0 042
+dq "
+# 8,11 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/S b/contrib/groff/font/devX100/S
new file mode 100644
index 0000000..59af889
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX100/TB b/contrib/groff/font/devX100/TB
new file mode 100644
index 0000000..f9f191c
--- /dev/null
+++ b/contrib/groff/font/devX100/TB
@@ -0,0 +1,308 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,10 0 041
+" 7,10 0 042
+dq "
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 12,10 0 046
+' 4,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/TBI b/contrib/groff/font/devX100/TBI
new file mode 100644
index 0000000..76e9828
--- /dev/null
+++ b/contrib/groff/font/devX100/TBI
@@ -0,0 +1,308 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 7,10 0 041
+" 7,10 0 042
+dq "
+# 8,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 10,10 0 046
+' 5,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/TI b/contrib/groff/font/devX100/TI
new file mode 100644
index 0000000..53401e5
--- /dev/null
+++ b/contrib/groff/font/devX100/TI
@@ -0,0 +1,308 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+dq "
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 5,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX100/TR b/contrib/groff/font/devX100/TR
new file mode 100644
index 0000000..39d106a
--- /dev/null
+++ b/contrib/groff/font/devX100/TR
@@ -0,0 +1,308 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+dq "
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 4,10 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/CB b/contrib/groff/font/devX75-12/CB
new file mode 100644
index 0000000..8b3766c
--- /dev/null
+++ b/contrib/groff/font/devX75-12/CB
@@ -0,0 +1,308 @@
+name CB
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+dq "
+# 7,8 0 043
+sh "
+$ 7,10,2 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/CBI b/contrib/groff/font/devX75-12/CBI
new file mode 100644
index 0000000..23df8ea
--- /dev/null
+++ b/contrib/groff/font/devX75-12/CBI
@@ -0,0 +1,308 @@
+name CBI
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+dq "
+# 7,9 0 043
+sh "
+$ 7,10,2 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/CI b/contrib/groff/font/devX75-12/CI
new file mode 100644
index 0000000..04f4c46
--- /dev/null
+++ b/contrib/groff/font/devX75-12/CI
@@ -0,0 +1,308 @@
+name CI
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,8 0 041
+" 7,8 0 042
+dq "
+# 7,8 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/CR b/contrib/groff/font/devX75-12/CR
new file mode 100644
index 0000000..957ce6a
--- /dev/null
+++ b/contrib/groff/font/devX75-12/CR
@@ -0,0 +1,308 @@
+name CR
+spacewidth 7
+charset
+--- 7,1 0 040
+! 7,9 0 041
+" 7,8 0 042
+dq "
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 7,8 0 045
+& 7,8 0 046
+' 7,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/DESC b/contrib/groff/font/devX75-12/DESC
new file mode 100644
index 0000000..4793e59
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX75-12/HB b/contrib/groff/font/devX75-12/HB
new file mode 100644
index 0000000..f9ccd5f
--- /dev/null
+++ b/contrib/groff/font/devX75-12/HB
@@ -0,0 +1,308 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+dq "
+# 8,8 0 043
+sh "
+$ 7,9,2 0 044
+Do "
+% 12,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/HBI b/contrib/groff/font/devX75-12/HBI
new file mode 100644
index 0000000..21d4355
--- /dev/null
+++ b/contrib/groff/font/devX75-12/HBI
@@ -0,0 +1,308 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+dq "
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 13,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/HI b/contrib/groff/font/devX75-12/HI
new file mode 100644
index 0000000..6051dc7
--- /dev/null
+++ b/contrib/groff/font/devX75-12/HI
@@ -0,0 +1,308 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+dq "
+# 7,8 0 043
+sh "
+$ 7,9,1 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 3,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/HR b/contrib/groff/font/devX75-12/HR
new file mode 100644
index 0000000..f78bed5
--- /dev/null
+++ b/contrib/groff/font/devX75-12/HR
@@ -0,0 +1,308 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+dq "
+# 7,8 0 043
+sh "
+$ 6,9,2 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 3,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/Makefile.sub b/contrib/groff/font/devX75-12/Makefile.sub
new file mode 100644
index 0000000..37f4b7c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX75-12/NB b/contrib/groff/font/devX75-12/NB
new file mode 100644
index 0000000..b5f4a08
--- /dev/null
+++ b/contrib/groff/font/devX75-12/NB
@@ -0,0 +1,308 @@
+name NB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+dq "
+# 8,9 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 13,9 0 045
+& 11,9 0 046
+' 3,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/NBI b/contrib/groff/font/devX75-12/NBI
new file mode 100644
index 0000000..01539d5
--- /dev/null
+++ b/contrib/groff/font/devX75-12/NBI
@@ -0,0 +1,308 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,9 0 041
+" 6,9 0 042
+dq "
+# 8,8 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 12,9 0 045
+& 12,9 0 046
+' 3,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/NI b/contrib/groff/font/devX75-12/NI
new file mode 100644
index 0000000..3ffc940
--- /dev/null
+++ b/contrib/groff/font/devX75-12/NI
@@ -0,0 +1,308 @@
+name NI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+dq "
+# 8,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 10,9 0 045
+& 10,9 0 046
+' 3,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/NR b/contrib/groff/font/devX75-12/NR
new file mode 100644
index 0000000..1d91f11
--- /dev/null
+++ b/contrib/groff/font/devX75-12/NR
@@ -0,0 +1,308 @@
+name NR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 6,9 0 042
+dq "
+# 8,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 11,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/S b/contrib/groff/font/devX75-12/S
new file mode 100644
index 0000000..2e66ad0
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX75-12/TB b/contrib/groff/font/devX75-12/TB
new file mode 100644
index 0000000..1ac16ec
--- /dev/null
+++ b/contrib/groff/font/devX75-12/TB
@@ -0,0 +1,308 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+dq "
+# 6,9 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 12,9 0 045
+& 10,9 0 046
+' 4,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/TBI b/contrib/groff/font/devX75-12/TBI
new file mode 100644
index 0000000..68d97ed
--- /dev/null
+++ b/contrib/groff/font/devX75-12/TBI
@@ -0,0 +1,308 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,9 0 041
+" 7,9 0 042
+dq "
+# 7,9 0 043
+sh "
+$ 7,10,1 0 044
+Do "
+% 12,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/TI b/contrib/groff/font/devX75-12/TI
new file mode 100644
index 0000000..037cec3
--- /dev/null
+++ b/contrib/groff/font/devX75-12/TI
@@ -0,0 +1,308 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,9 0 041
+" 5,9 0 042
+dq "
+# 6,9 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 10,9 0 045
+& 9,9 0 046
+' 4,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75-12/TR b/contrib/groff/font/devX75-12/TR
new file mode 100644
index 0000000..16de8a9
--- /dev/null
+++ b/contrib/groff/font/devX75-12/TR
@@ -0,0 +1,308 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,9 0 041
+" 5,9 0 042
+dq "
+# 6,8 0 043
+sh "
+$ 6,10,1 0 044
+Do "
+% 9,9 0 045
+& 10,9 0 046
+' 4,9 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/CB b/contrib/groff/font/devX75/CB
new file mode 100644
index 0000000..58e0d8b
--- /dev/null
+++ b/contrib/groff/font/devX75/CB
@@ -0,0 +1,308 @@
+name CB
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,6 0 042
+dq "
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,6 0 045
+& 6,6 0 046
+' 6,7 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/CBI b/contrib/groff/font/devX75/CBI
new file mode 100644
index 0000000..db6f6ba
--- /dev/null
+++ b/contrib/groff/font/devX75/CBI
@@ -0,0 +1,308 @@
+name CBI
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+dq "
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,7 0 045
+& 6,6 0 046
+' 6,7 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/CI b/contrib/groff/font/devX75/CI
new file mode 100644
index 0000000..43d383a
--- /dev/null
+++ b/contrib/groff/font/devX75/CI
@@ -0,0 +1,308 @@
+name CI
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+dq "
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,7 0 045
+& 6,6 0 046
+' 6,7 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/CR b/contrib/groff/font/devX75/CR
new file mode 100644
index 0000000..900a4a0
--- /dev/null
+++ b/contrib/groff/font/devX75/CR
@@ -0,0 +1,308 @@
+name CR
+spacewidth 6
+charset
+--- 6,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+dq "
+# 6,7 0 043
+sh "
+$ 6,7,1 0 044
+Do "
+% 6,6 0 045
+& 6,6 0 046
+' 6,7 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/DESC b/contrib/groff/font/devX75/DESC
new file mode 100644
index 0000000..172170c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX75/HB b/contrib/groff/font/devX75/HB
new file mode 100644
index 0000000..ab6f979
--- /dev/null
+++ b/contrib/groff/font/devX75/HB
@@ -0,0 +1,308 @@
+name HB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 5,8 0 042
+dq "
+# 6,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 8,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/HBI b/contrib/groff/font/devX75/HBI
new file mode 100644
index 0000000..ec132d3
--- /dev/null
+++ b/contrib/groff/font/devX75/HBI
@@ -0,0 +1,308 @@
+name HBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+dq "
+# 7,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/HI b/contrib/groff/font/devX75/HI
new file mode 100644
index 0000000..324e4b7
--- /dev/null
+++ b/contrib/groff/font/devX75/HI
@@ -0,0 +1,308 @@
+name HI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,8 0 041
+" 4,8 0 042
+dq "
+# 7,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/HR b/contrib/groff/font/devX75/HR
new file mode 100644
index 0000000..fc0143d
--- /dev/null
+++ b/contrib/groff/font/devX75/HR
@@ -0,0 +1,308 @@
+name HR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 3,8 0 041
+" 4,8 0 042
+dq "
+# 6,7 0 043
+sh "
+$ 6,8,1 0 044
+Do "
+% 9,8 0 045
+& 8,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/Makefile.sub b/contrib/groff/font/devX75/Makefile.sub
new file mode 100644
index 0000000..2a90fca
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX75/NB b/contrib/groff/font/devX75/NB
new file mode 100644
index 0000000..9ea6576
--- /dev/null
+++ b/contrib/groff/font/devX75/NB
@@ -0,0 +1,308 @@
+name NB
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,8 0 041
+" 6,8 0 042
+dq "
+# 8,8 0 043
+sh "
+$ 6,9,1 0 044
+Do "
+% 11,8 0 045
+& 9,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/NBI b/contrib/groff/font/devX75/NBI
new file mode 100644
index 0000000..9346faf
--- /dev/null
+++ b/contrib/groff/font/devX75/NBI
@@ -0,0 +1,308 @@
+name NBI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 5,8 0 041
+" 6,8 0 042
+dq "
+# 8,7 0 043
+sh "
+$ 6,9,1 0 044
+Do "
+% 11,8 0 045
+& 10,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/NI b/contrib/groff/font/devX75/NI
new file mode 100644
index 0000000..d14f9ca
--- /dev/null
+++ b/contrib/groff/font/devX75/NI
@@ -0,0 +1,308 @@
+name NI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+dq "
+# 8,7 0 043
+sh "
+$ 5,9,1 0 044
+Do "
+% 9,8 0 045
+& 9,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/NR b/contrib/groff/font/devX75/NR
new file mode 100644
index 0000000..8a04d77
--- /dev/null
+++ b/contrib/groff/font/devX75/NR
@@ -0,0 +1,308 @@
+name NR
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,8 0 041
+" 6,8 0 042
+dq "
+# 8,8 0 043
+sh "
+$ 5,9,1 0 044
+Do "
+% 9,8 0 045
+& 10,8 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/S b/contrib/groff/font/devX75/S
new file mode 100644
index 0000000..b1cfbbf
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devX75/TB b/contrib/groff/font/devX75/TB
new file mode 100644
index 0000000..29fa10a
--- /dev/null
+++ b/contrib/groff/font/devX75/TB
@@ -0,0 +1,308 @@
+name TB
+spacewidth 2
+charset
+--- 2,1 0 040
+! 4,7 0 041
+" 5,7 0 042
+dq "
+# 6,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 9,7 0 045
+& 9,7 0 046
+' 4,7 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/TBI b/contrib/groff/font/devX75/TBI
new file mode 100644
index 0000000..064d31d
--- /dev/null
+++ b/contrib/groff/font/devX75/TBI
@@ -0,0 +1,308 @@
+name TBI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 6,7 0 041
+" 6,7 0 042
+dq "
+# 8,7 0 043
+sh "
+$ 5,7 0 044
+Do "
+% 11,7 0 045
+& 8,7 0 046
+' 4,7 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/TI b/contrib/groff/font/devX75/TI
new file mode 100644
index 0000000..6e091e2
--- /dev/null
+++ b/contrib/groff/font/devX75/TI
@@ -0,0 +1,308 @@
+name TI
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,7 0 041
+" 4,8 0 042
+dq "
+# 5,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 9,7 0 045
+& 8,7 0 046
+' 3,8 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devX75/TR b/contrib/groff/font/devX75/TR
new file mode 100644
index 0000000..819dff4
--- /dev/null
+++ b/contrib/groff/font/devX75/TR
@@ -0,0 +1,308 @@
+name TR
+spacewidth 2
+charset
+--- 2,1 0 040
+! 3,7 0 041
+" 4,7 0 042
+dq "
+# 5,7 0 043
+sh "
+$ 5,8,1 0 044
+Do "
+% 8,7 0 045
+& 8,7 0 046
+' 3,7 0 047
+cq "
+( 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
+¶ "
+pc 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/contrib/groff/font/devascii/DESC.proto b/contrib/groff/font/devascii/DESC.proto
new file mode 100644
index 0000000..88399ab
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devascii/Makefile.sub b/contrib/groff/font/devascii/Makefile.sub
new file mode 100644
index 0000000..238f7b7
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devascii/R.proto b/contrib/groff/font/devascii/R.proto
new file mode 100644
index 0000000..b4d0907
--- /dev/null
+++ b/contrib/groff/font/devascii/R.proto
@@ -0,0 +1,167 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0041
+" 24 0 0042
+dq "
+lq "
+rq "
+# 24 0 0043
+sh "
+$ 24 0 0044
+Do "
+% 24 0 0045
+& 24 0 0046
+' 24 0 0047
+aa "
+fm "
+aq "
+cq "
+( 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/contrib/groff/font/devcp1047/DESC.proto b/contrib/groff/font/devcp1047/DESC.proto
new file mode 100644
index 0000000..88399ab
--- /dev/null
+++ b/contrib/groff/font/devcp1047/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/contrib/groff/font/devcp1047/Makefile.sub b/contrib/groff/font/devcp1047/Makefile.sub
new file mode 100644
index 0000000..42721cb
--- /dev/null
+++ b/contrib/groff/font/devcp1047/Makefile.sub
@@ -0,0 +1,32 @@
+DEV=cp1047
+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/contrib/groff/font/devcp1047/R.proto b/contrib/groff/font/devcp1047/R.proto
new file mode 100644
index 0000000..6a624c3
--- /dev/null
+++ b/contrib/groff/font/devcp1047/R.proto
@@ -0,0 +1,356 @@
+name R
+internalname 0
+spacewidth 24
+charset
+^a 24 0 0102
+char66 "
+:a 24 0 0103
+char67 "
+`a 24 0 0104
+char68 "
+'a 24 0 0105
+char69 "
+~a 24 0 0106
+char70 "
+oa 24 0 0107
+char71 "
+,c 24 0 0110
+char72 "
+~n 24 0 0111
+char73 "
+ct 24 0 0112
+char74 "
+. 24 0 0113
+< 24 0 0114
+fo "
+la "
+( 24 0 0115
++ 24 0 0116
+pl "
+| 24 0 0117
+ba "
+br "
+bv "
+lb "
+lc "
+lf "
+lk "
+lt "
+or "
+rb "
+rc "
+rf "
+rk "
+rt "
+& 24 0 0120
+'e 24 0 0121
+char81 "
+^e 24 0 0122
+char82 "
+:e 24 0 0123
+char83 "
+`e 24 0 0124
+char84 "
+'i 24 0 0125
+char85 "
+^i 24 0 0126
+char86 "
+:i 24 0 0127
+char87 "
+`i 24 0 0130
+char88 "
+ss 24 0 0131
+char89 "
+! 24 0 0132
+$ 24 0 0133
+Do "
+* 24 0 0134
+** "
+) 24 0 0135
+; 24 0 0136
+^ 24 0 0137
+a^ "
+ha "
+\- 24 0 0140
+- "
+en "
+hy "
+mi "
+/ 24 0 0141
+f/ "
+sl "
+^A 24 0 0142
+char98 "
+:A 24 0 0143
+char99 "
+`A 24 0 0144
+char100 "
+'A 24 0 0145
+char101 "
+~A 24 0 0146
+char102 "
+oA 24 0 0147
+char103 "
+,C 24 0 0150
+char104 "
+~N 24 0 0151
+char105 "
+bb 24 0 0152
+char106 "
+, 24 0 0153
+% 24 0 0154
+_ 24 0 0155
+ru "
+ul "
+> 24 0 0156
+fc "
+ra "
+? 24 0 0157
+/o 24 0 0160
+char112 "
+'E 24 0 0161
+char113 "
+^E 24 0 0162
+char114 "
+:E 24 0 0163
+char115 "
+`E 24 0 0164
+char116 "
+'I 24 0 0165
+char117 "
+^I 24 0 0166
+char118 "
+:I 24 0 0167
+char119 "
+`I 24 0 0170
+char120 "
+` 24 0 0171
+ga "
+oq "
+: 24 0 0172
+# 24 0 0173
+sh "
+@ 24 0 0174
+at "
+' 24 0 0175
+aq "
+fm "
+cq "
+= 24 0 0176
+eq "
+" 24 0 0177
+dq "
+lq "
+rq "
+/O 24 0 0200
+char128 "
+a 24 0 0201
+b 24 0 0202
+c 24 0 0203
+d 24 0 0204
+e 24 0 0205
+f 24 0 0206
+g 24 0 0207
+h 24 0 0210
+i 24 0 0211
+.i "
+Fo 24 0 0212
+char138 "
+Fc 24 0 0213
+char139 "
+Sd 24 0 0214
+char140 "
+'y 24 0 0215
+char141 "
+Tp 24 0 0216
+char142 "
++- 24 0 0217
+char143 "
+de 24 0 0220
+char144 "
+j 24 0 0221
+k 24 0 0222
+l 24 0 0223
+m 24 0 0224
+n 24 0 0225
+o 24 0 0226
+*o "
+p 24 0 0227
+q 24 0 0230
+r 24 0 0231
+Of 24 0 0232
+char154 "
+Om 24 0 0233
+char155 "
+ae 24 0 0234
+char156 "
+ac 24 0 0235
+char157 "
+AE 24 0 0236
+char158 "
+Cs 24 0 0237
+char159 "
+*m 24 0 0240
+char160 "
+~ 24 0 0241
+a~ "
+ap "
+ti "
+s 24 0 0242
+t 24 0 0243
+u 24 0 0244
+v 24 0 0245
+w 24 0 0246
+x 24 0 0247
+y 24 0 0250
+z 24 0 0251
+r! 24 0 0252
+char170 "
+r? 24 0 0253
+char171 "
+-D 24 0 0254
+char172 "
+[ 24 0 0255
+lB "
+TP 24 0 0256
+char174 "
+rg 24 0 0257
+char175 "
+no 24 0 0260
+char176 "
+Po 24 0 0261
+char177 "
+Ye 24 0 0262
+char178 "
+md 24 0 0263
+pc "
+char179 "
+co 24 0 0264
+char180 "
+sc 24 0 0265
+char181 "
+ps 24 0 0266
+char182 "
+14 24 0 0267
+char183 "
+12 24 0 0270
+char184 "
+34 24 0 0271
+char185 "
+'Y 24 0 0272
+char186 "
+ad 24 0 0273
+char187 "
+a- 24 0 0274
+char188 "
+] 24 0 0275
+rB "
+aa 24 0 0276
+char190 "
+mu 24 0 0277
+char191 "
+{ 24 0 0300
+lC "
+A 24 0 0301
+*A "
+B 24 0 0302
+*B "
+C 24 0 0303
+D 24 0 0304
+E 24 0 0305
+*E "
+F 24 0 0306
+G 24 0 0307
+H 24 0 0310
+*Y "
+I 24 0 0311
+*I "
+shc 24 0 0312
+char202 "
+^o 24 0 0313
+char203 "
+:o 24 0 0314
+char204 "
+`o 24 0 0315
+char205 "
+'o 24 0 0316
+char206 "
+~o 24 0 0317
+char207 "
+} 24 0 0320
+rC "
+J 24 0 0321
+K 24 0 0322
+*K "
+L 24 0 0323
+M 24 0 0324
+*M "
+N 24 0 0325
+*N "
+O 24 0 0326
+*O "
+ci "
+P 24 0 0327
+*R "
+Q 24 0 0330
+R 24 0 0331
+S1 24 0 0332
+char218 "
+^u 24 0 0333
+char219 "
+:u 24 0 0334
+char220 "
+`u 24 0 0335
+char221 "
+'u 24 0 0336
+char222 "
+:y 24 0 0337
+char223 "
+\ 24 0 0340
+rs "
+di 24 0 0341
+char225 "
+S 24 0 0342
+T 24 0 0343
+*T "
+U 24 0 0344
+V 24 0 0345
+W 24 0 0346
+X 24 0 0347
+*X "
+Y 24 0 0350
+*U "
+Z 24 0 0351
+*Z "
+S2 24 0 0352
+char234 "
+^O 24 0 0353
+char235 "
+:O 24 0 0354
+char236 "
+`O 24 0 0355
+char237 "
+'O 24 0 0356
+char238 "
+~O 24 0 0357
+char239 "
+0 24 0 0360
+1 24 0 0361
+2 24 0 0362
+3 24 0 0363
+4 24 0 0364
+5 24 0 0365
+6 24 0 0366
+7 24 0 0367
+8 24 0 0370
+9 24 0 0371
+S3 24 0 0372
+char250 "
+^U 24 0 0373
+char251 "
+:U 24 0 0374
+char252 "
+`U 24 0 0375
+char253 "
+'U 24 0 0376
+char254 "
diff --git a/contrib/groff/font/devdvi/B b/contrib/groff/font/devdvi/B
new file mode 100644
index 0000000..53a2b9c
--- /dev/null
+++ b/contrib/groff/font/devdvi/B
@@ -0,0 +1,358 @@
+#
+# manually added kernings for `` and ''
+#
+name B
+internalname cmbx10
+spacewidth 401952
+ligatures ff fi fl ffi ffl 0
+checksum 452076118
+designsize 10485760
+kernpairs
+ff ' 114323
+ff cq 114323
+ff ? 114323
+ff ! 114323
+ff ) 114323
+ff rB 114323
+ff ] 114323
+' ' -100488
+' cq -100488
+cq ' -100488
+cq cq -100488
+' ? 133984
+cq ? 133984
+' ! 133984
+cq ! 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 cq 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
+cq 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/contrib/groff/font/devdvi/BI b/contrib/groff/font/devdvi/BI
new file mode 100644
index 0000000..35e2824
--- /dev/null
+++ b/contrib/groff/font/devdvi/BI
@@ -0,0 +1,365 @@
+#
+# manually added kernings for `` and ''
+#
+name BI
+internalname cmbxti10
+spacewidth 434573
+slant 14.036243
+ligatures ff fi fl ffi ffl 0
+checksum 1175274390
+designsize 10485760
+kernpairs
+ff cq 111848
+ff ' 111848
+ff ? 111848
+ff ! 111848
+ff ) 111848
+ff rB 111848
+ff ] 111848
+' ' -92624
+cq ' -92624
+' cq -92624
+cq cq -92624
+' ? 123498
+cq ? 123498
+' ! 123498
+cq ! 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 cq 111848
+Fn ' 111848
+f cq 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
+n cq -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
+cq 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/contrib/groff/font/devdvi/CW b/contrib/groff/font/devdvi/CW
new file mode 100644
index 0000000..2039d23
--- /dev/null
+++ b/contrib/groff/font/devdvi/CW
@@ -0,0 +1,160 @@
+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
+dq 550498,640797 2 0042
+" "
+sh 550498,640797 2 0043
+# "
+Do 550498,728178,87381 3 0044
+$ "
+% 550498,728178,87381 3 0045
+& 550498,640797 2 0046
+cq 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/contrib/groff/font/devdvi/CWI b/contrib/groff/font/devdvi/CWI
new file mode 100644
index 0000000..7e7b540
--- /dev/null
+++ b/contrib/groff/font/devdvi/CWI
@@ -0,0 +1,160 @@
+name CWI
+internalname cmitt10
+spacewidth 550498
+slant 14.036243
+checksum -538297224
+designsize 10485760
+charset
+*G 550498,640797,0,182045 2 0000
+*D 550498,640797,0,182045 2 0001
+*H 550498,640797,0,182045 2 0002
+*L 550498,640797,0,182045 2 0003
+*C 550498,640797,0,182045 2 0004
+*P 550498,640797,0,182045 2 0005
+*S 550498,640797,0,182045 2 0006
+*U 550498,640797,0,182045 2 0007
+*F 550498,640797,0,182045 2 0010
+*Q 550498,640797,0,182045 2 0011
+*W 550498,640797,0,182045 2 0012
+ff 550498,640797,0,182045 2 0013
+fi 550498,640797,0,182045 2 0014
+fl 550498,640797,0,182045 2 0015
+Fi 550498,407779,233018,182045 1 0016
+Fl 550498,407779,233018,182045 1 0017
+.i 550498,451470,0,182045 0 0020
+.j 550498,451470,233018,182045 1 0021
+ga 550498,640797,0,182045 2 0022
+char180 550498,640797,0,182045 2 0023
+aa "
+ah 550498,593466,0,182045 2 0024
+ab 550498,640797,0,182045 2 0025
+char175 550498,593027,0,182045 2 0026
+a- "
+ao 550498,640797,0,182045 2 0027
+char184 550498,0,203891,182045 1 0030
+ac "
+char223 550498,640797,233018,182045 3 0031
+ss "
+char230 550498,451470,0,182045 0 0032
+ae "
+oe 550498,451470,0,182045 0 0033
+char248 550498,567979,116509,182045 3 0034
+/o "
+char198 550498,640797,0,182045 2 0035
+AE "
+OE 550498,640797,0,182045 2 0036
+char216 550498,699051,58254,182045 3 0037
+/O "
+--- 550498,230104,116509,182045 1 0040
+! 550498,640797,0,182045 2 0041
+dq 550498,640797,0,182045 2 0042
+" "
+sh 550498,640797,0,182045 2 0043
+# "
+Do 550498,640797,0,182045 2 0044
+$ "
+% 550498,728178,87381,182045 3 0045
+& 550498,640797,0,182045 2 0046
+cq 550498,640797,0,182045 2 0047
+' "
+( 550498,728178,87379,182045 3 0050
+) 550498,728178,87379,182045 3 0051
+* 550498,546134,0,182045 2 0052
++ 550498,556326,-84470,182045 2 0053
+, 550498,131072,145635,182045 1 0054
+\- 550498,556326,-84470,182045 2 0055
+- "
+. 550498,131072,0,182045 0 0056
+sl 550498,728178,87379,182045 3 0057
+/ "
+0 550498,640797,0,182045 2 0060
+1 550498,640797,0,182045 2 0061
+2 550498,640797,0,182045 2 0062
+3 550498,640797,0,182045 2 0063
+4 550498,640797,233018,182045 3 0064
+5 550498,640797,0,182045 2 0065
+6 550498,640797,0,182045 2 0066
+7 550498,640797,233018,182045 3 0067
+8 550498,640797,0,182045 2 0070
+9 550498,640797,0,182045 2 0071
+: 550498,451470,0,182045 0 0072
+; 550498,451470,145635,182045 1 0073
+< 550498,582542,-58254,182045 2 0074
+= 550498,435813,-204984,182045 0 0075
+> 550498,582542,-58254,182045 2 0076
+? 550498,640797,0,182045 2 0077
+at 550498,640797,0,182045 2 0100
+@ "
+A 550498,640797,0,182045 2 0101
+B 550498,640797,0,182045 2 0102
+C 550498,640797,0,182045 2 0103
+D 550498,640797,0,182045 2 0104
+E 550498,640797,0,182045 2 0105
+F 550498,640797,0,182045 2 0106
+G 550498,640797,0,182045 2 0107
+H 550498,640797,0,182045 2 0110
+I 550498,640797,0,182045 2 0111
+J 550498,640797,0,182045 2 0112
+K 550498,640797,0,182045 2 0113
+L 550498,640797,0,182045 2 0114
+M 550498,640797,0,182045 2 0115
+N 550498,640797,0,182045 2 0116
+O 550498,640797,0,182045 2 0117
+P 550498,640797,0,182045 2 0120
+Q 550498,640797,145635,182045 3 0121
+R 550498,640797,0,182045 2 0122
+S 550498,640797,0,182045 2 0123
+T 550498,640797,0,182045 2 0124
+U 550498,640797,0,182045 2 0125
+V 550498,640797,0,182045 2 0126
+W 550498,640797,0,182045 2 0127
+X 550498,640797,0,182045 2 0130
+Y 550498,640797,0,182045 2 0131
+Z 550498,640797,0,182045 2 0132
+lB 550498,728178,87379,182045 3 0133
+[ "
+rs 550498,728178,87379,182045 3 0134
+\ "
+rB 550498,728178,87379,182045 3 0135
+] "
+ha 550498,640797,0,182045 2 0136
+^ "
+a^ "
+_ 550498,0,99757,182045 1 0137
+oq 550498,640797,0,182045 2 0140
+` "
+a 550498,451470,0,182045 0 0141
+b 550498,640797,0,182045 2 0142
+c 550498,451470,0,182045 0 0143
+d 550498,640797,0,182045 2 0144
+e 550498,451470,0,182045 0 0145
+f 550498,640797,233018,182045 3 0146
+g 550498,451470,233018,182045 1 0147
+h 550498,640797,0,182045 2 0150
+i 550498,640797,0,182045 2 0151
+j 550498,640797,233018,182045 3 0152
+k 550498,640797,0,182045 2 0153
+l 550498,640797,0,182045 2 0154
+m 550498,451470,0,182045 0 0155
+n 550498,451470,0,182045 0 0156
+o 550498,451470,0,182045 0 0157
+p 550498,451470,233018,182045 1 0160
+q 550498,451470,233018,182045 1 0161
+r 550498,451470,0,182045 0 0162
+s 550498,451470,0,182045 0 0163
+t 550498,640797,0,182045 2 0164
+u 550498,451470,0,182045 0 0165
+v 550498,451470,0,182045 0 0166
+w 550498,451470,0,182045 0 0167
+x 550498,451470,0,182045 0 0170
+y 550498,451470,233018,182045 1 0171
+z 550498,451470,0,182045 0 0172
+{ 550498,728178,87379,182045 3 0173
+lC "
+| 550498,728178,87379,182045 3 0174
+ba "
+} 550498,728178,87379,182045 3 0175
+rC "
+~ 550498,640797,0,182045 2 0176
+a~ "
+--- 550498,640797,0,182045 2 0177
diff --git a/contrib/groff/font/devdvi/DESC.in b/contrib/groff/font/devdvi/DESC.in
new file mode 100644
index 0000000..54c1302b
--- /dev/null
+++ b/contrib/groff/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 1095 1200 1400 1440 1600 1728 1800
+2000 2074 2200 2400 2488 2800 3600 0
+fonts 14 R I B BI 0 0 0 0 0 MI S EX CW CWI
+tcommand
+postpro grodvi
diff --git a/contrib/groff/font/devdvi/EX b/contrib/groff/font/devdvi/EX
new file mode 100644
index 0000000..6e83d02
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devdvi/H b/contrib/groff/font/devdvi/H
new file mode 100644
index 0000000..f563c18
--- /dev/null
+++ b/contrib/groff/font/devdvi/H
@@ -0,0 +1,307 @@
+name H
+internalname cmss10
+spacewidth 349526
+ligatures ff fi fl ffi ffl 0
+checksum 1831058770
+designsize 10485760
+kernpairs
+ff cq 72818
+ff ' 72818
+ff ? 72818
+ff ! 72818
+ff ) 72818
+ff rB 72818
+ff ] 72818
+cq ? 116509
+' ? 116509
+cq ! 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 cq 72818
+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
+cq 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/contrib/groff/font/devdvi/HB b/contrib/groff/font/devdvi/HB
new file mode 100644
index 0000000..c0cc6e2
--- /dev/null
+++ b/contrib/groff/font/devdvi/HB
@@ -0,0 +1,307 @@
+name HB
+internalname cmssbx10
+spacewidth 384480
+ligatures ff fi fl ffi ffl 0
+checksum -244629176
+designsize 10485760
+kernpairs
+ff cq 80101
+ff ' 80101
+ff ? 80101
+ff ! 80101
+ff ) 80101
+ff rB 80101
+ff ] 80101
+cq ? 128160
+' ? 128160
+cq ! 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 cq 80101
+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
+cq 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/contrib/groff/font/devdvi/HI b/contrib/groff/font/devdvi/HI
new file mode 100644
index 0000000..4f96bdb
--- /dev/null
+++ b/contrib/groff/font/devdvi/HI
@@ -0,0 +1,308 @@
+name HI
+internalname cmssi10
+spacewidth 349526
+slant 11.999911
+ligatures ff fi fl ffi ffl 0
+checksum -984248855
+designsize 10485760
+kernpairs
+ff cq 72818
+ff ' 72818
+ff ? 72818
+ff ! 72818
+ff ) 72818
+ff rB 72818
+ff ] 72818
+cq ? 116509
+' ? 116509
+cq ! 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 cq 72818
+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
+cq 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/contrib/groff/font/devdvi/I b/contrib/groff/font/devdvi/I
new file mode 100644
index 0000000..2323eed
--- /dev/null
+++ b/contrib/groff/font/devdvi/I
@@ -0,0 +1,366 @@
+#
+# manually added kernings for `` and ''
+#
+name I
+special
+internalname cmti10
+spacewidth 375155
+slant 14.036243
+ligatures ff fi fl ffi ffl 0
+checksum -50321606
+designsize 10485760
+kernpairs
+ff cq 109373
+ff ' 109373
+ff ? 109373
+ff ! 109373
+ff ) 109373
+ff rB 109373
+ff ] 109373
+' ' -80390
+cq ' -80390
+' cq -80390
+cq cq -80390
+cq ? 107187
+' ? 107187
+cq ! 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 cq 109373
+Fn ' 109373
+f cq 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 cq -107187
+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
+cq 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/contrib/groff/font/devdvi/MI b/contrib/groff/font/devdvi/MI
new file mode 100644
index 0000000..2b2e349
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devdvi/Makefile.sub b/contrib/groff/font/devdvi/Makefile.sub
new file mode 100644
index 0000000..5f30be2
--- /dev/null
+++ b/contrib/groff/font/devdvi/Makefile.sub
@@ -0,0 +1,11 @@
+DEV=dvi
+DEVFILES=DESC R I B BI CW CWI 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/contrib/groff/font/devdvi/R b/contrib/groff/font/devdvi/R
new file mode 100644
index 0000000..2c7fe30
--- /dev/null
+++ b/contrib/groff/font/devdvi/R
@@ -0,0 +1,441 @@
+#
+# manually added kernings for `` and ''
+#
+name R
+special
+internalname cmr10
+spacewidth 349526
+ligatures ff fi fl ffi ffl 0
+checksum 1274110073
+designsize 10485760
+kernpairs
+ff cq 81557
+ff ' 81557
+ff ? 81557
+ff ! 81557
+ff ) 81557
+ff rB 81557
+ff ] 81557
+' ' -87382
+cq ' -87382
+' cq -87382
+cq cq -87382
+' ? 116509
+cq ? 116509
+' ! 116509
+cq ! 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 cq 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
+cq 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/contrib/groff/font/devdvi/S b/contrib/groff/font/devdvi/S
new file mode 100644
index 0000000..75abc6c
--- /dev/null
+++ b/contrib/groff/font/devdvi/S
@@ -0,0 +1,153 @@
+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
+pc "
+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/contrib/groff/font/devdvi/SA b/contrib/groff/font/devdvi/SA
new file mode 100644
index 0000000..91879fc
--- /dev/null
+++ b/contrib/groff/font/devdvi/SA
@@ -0,0 +1,143 @@
+name SA
+special
+internalname msam10
+checksum -1749815603
+designsize 10485760
+charset
+boxdot 815562,707789 2 0000
+boxplus 815562,707789 2 0001
+boxtimes 815562,707789 2 0002
+square 815562,707789 2 0003
+blacksquare 815562,707789 2 0004
+centerdot 291272,576570 2 0005
+lz 699053,725867,116509 3 0006
+lozenge "
+blacklozenge 699053,725867,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,707789 2 0014
+Vdash 757307,725867 2 0015
+Vvdash 932070,725867 2 0016
+vDash 640798,725867 2 0017
+twoheadrightarrow 1048579,547770,14197 3 0020
+twoheadleftarrow 1048579,547770,14197 3 0021
+leftleftarrows 1048579,707789,189584 3 0022
+rightrightarrows 1048579,707789,189584 3 0023
+upuparrows 873816,725867,203888 3 0024
+downdownarrows 873816,725867,203888 3 0025
+upharpoonright 436909,725867,203888 3 0026
+downharpoonright 436909,725867,203888 3 0027
+upharpoonleft 436909,725867,203888 3 0030
+downharpoonleft 436909,725867,203888 3 0031
+rightarrowtail 1165088,547770,14197 3 0032
+leftarrowtail 1165088,547770,14197 3 0033
+leftrightarrows 1048579,707789,189584 3 0034
+rightleftarrows 1048579,707789,189584 3 0035
+Lsh 524290,725867 2 0036
+Rsh 524290,725867 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,725867 2 0051
+tf "
+therefore "
+because 699053,725867 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,707789,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,707789,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,725867,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,725867 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,707789,0,26214 2 0125
+Ye "
+yen "
+Rrightarrow 1048579,667592,143304 3 0126
+Lleftarrow 1048579,667592,143304 3 0127
+OK 873816,725867 2 0130
+checkmark "
+veebar 640798,725867,203888 3 0131
+barwedge 640798,725867,203888 3 0132
+doublebarwedge 640798,792549,203888 3 0133
+/_ 757307,725867 2 0134
+angle "
+measuredangle 757307,725867 2 0135
+sphericalangle 757307,547770,36882 3 0136
+varpropto 815562,725867 2 0137
+smallsmile 815562,725867,203888 3 0140
+smallfrown 815562,725867,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,725867 2 0150
+rightthreetimes 815562,725867 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,725867 2 0160
+urcorner 524290,725867 2 0161
+rg 992648,725867,163146 3 0162
+char174 "
+circledR "
+circledS 946045,725867,163146 3 0163
+pitchfork 699053,725867 2 0164
+dotplus 815562,725867,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,725867 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/contrib/groff/font/devdvi/SB b/contrib/groff/font/devdvi/SB
new file mode 100644
index 0000000..811b351
--- /dev/null
+++ b/contrib/groff/font/devdvi/SB
@@ -0,0 +1,132 @@
+name SB
+special
+internalname msbm10
+spacewidth 314576
+slant 14.036243
+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/contrib/groff/font/devdvi/generate/CompileFonts b/contrib/groff/font/devdvi/generate/CompileFonts
new file mode 100755
index 0000000..8859f8e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devdvi/generate/Makefile b/contrib/groff/font/devdvi/generate/Makefile
new file mode 100644
index 0000000..8e3d144
--- /dev/null
+++ b/contrib/groff/font/devdvi/generate/Makefile
@@ -0,0 +1,107 @@
+# 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.
+
+# This is set up so you can do:
+# make -f generate/Makefile
+# in the parent directory of the directory containing this file.
+
+# Note that the following font files have manually added kerning values for
+# `` and '': B, BI, I, R.
+
+srcdir=.
+tfmdir=/usr/local/lib/groff-tfm
+gfdir=/usr/local/lib/groff-gf
+
+TFMTODIT=tfmtodit
+FONTS=R I B BI CW CWI 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 $@
+
+CWI: $(srcdir)/textt.map
+ $(TFMTODIT) \
+ $(tfmdir)/cmitt10.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)/texb.map
+ $(TFMTODIT) -g $(gfdir)/cmss10.300gf \
+ $(tfmdir)/cmss10.tfm $(srcdir)/texb.map $@
+
+HB: $(srcdir)/texb.map
+ $(TFMTODIT) -g $(gfdir)/cmssbx10.300gf \
+ $(tfmdir)/cmssbx10.tfm $(srcdir)/texb.map $@
+
+HI: $(srcdir)/texb.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/contrib/groff/font/devdvi/generate/cork.map b/contrib/groff/font/devdvi/generate/cork.map
new file mode 100644
index 0000000..4e4a35a
--- /dev/null
+++ b/contrib/groff/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 " dq
+35 # sh
+36 $ Do
+37 %
+38 &
+39 ' aq cq
+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/contrib/groff/font/devdvi/generate/msam.map b/contrib/groff/font/devdvi/generate/msam.map
new file mode 100644
index 0000000..90006c9
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devdvi/generate/msbm.map b/contrib/groff/font/devdvi/generate/msbm.map
new file mode 100644
index 0000000..07ee095
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devdvi/generate/texb.map b/contrib/groff/font/devdvi/generate/texb.map
new file mode 100644
index 0000000..b2bcd15
--- /dev/null
+++ b/contrib/groff/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 ' cq
+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/contrib/groff/font/devdvi/generate/texex.map b/contrib/groff/font/devdvi/generate/texex.map
new file mode 100644
index 0000000..a5b2690
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devdvi/generate/texi.map b/contrib/groff/font/devdvi/generate/texi.map
new file mode 100644
index 0000000..4ca802a
--- /dev/null
+++ b/contrib/groff/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 ' cq
+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/contrib/groff/font/devdvi/generate/texmi.map b/contrib/groff/font/devdvi/generate/texmi.map
new file mode 100644
index 0000000..6d01dc4
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devdvi/generate/texr.map b/contrib/groff/font/devdvi/generate/texr.map
new file mode 100644
index 0000000..7db0e5f
--- /dev/null
+++ b/contrib/groff/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 ' cq
+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/contrib/groff/font/devdvi/generate/texsy.map b/contrib/groff/font/devdvi/generate/texsy.map
new file mode 100644
index 0000000..fe98eb2
--- /dev/null
+++ b/contrib/groff/font/devdvi/generate/texsy.map
@@ -0,0 +1,100 @@
+0 \- mi
+1 md pc
+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/contrib/groff/font/devdvi/generate/textt.map b/contrib/groff/font/devdvi/generate/textt.map
new file mode 100644
index 0000000..80e8911
--- /dev/null
+++ b/contrib/groff/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 " dq
+35 # sh
+36 $ Do
+37 %
+38 &
+39 ' cq
+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/contrib/groff/font/devhtml/DESC.proto b/contrib/groff/font/devhtml/DESC.proto
new file mode 100644
index 0000000..e245441
--- /dev/null
+++ b/contrib/groff/font/devhtml/DESC.proto
@@ -0,0 +1,12 @@
+res 240
+hor 24
+vert 40
+unitwidth 10
+sizes 6 8 10 12 14 16 18 0
+fonts 6 R I B BI C S
+tcommand
+html
+postpro post-grohtml
+prepro pre-grohtml
+use_charnames_in_special
+pass_filenames
diff --git a/contrib/groff/font/devhtml/Makefile.sub b/contrib/groff/font/devhtml/Makefile.sub
new file mode 100644
index 0000000..df56914
--- /dev/null
+++ b/contrib/groff/font/devhtml/Makefile.sub
@@ -0,0 +1,34 @@
+DEV=html
+PROTOFONTS=R I B BI CR
+FONTS=$(PROTOFONTS) S
+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/CR/4/" \
+ -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/contrib/groff/font/devhtml/R.proto b/contrib/groff/font/devhtml/R.proto
new file mode 100644
index 0000000..f2c9d24
--- /dev/null
+++ b/contrib/groff/font/devhtml/R.proto
@@ -0,0 +1,315 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0x0021
+" 24 0 0x0022 &quot;
+dq "
+# 24 0 0x0023
+sh "
+$ 24 0 0x0024
+Do "
+% 24 0 0x0025
+& 24 0 0x0026 &amp;
+aq 24 0 0x0027
+' "
+( 24 0 0x0028
+) 24 0 0x0029
+* 24 0 0x002A
++ 24 0 0x002B
+pl "
+, 24 0 0x002C
+\- 24 0 0x002D
+hy "
+- "
+mi "
+en "
+. 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 &lt;
+la "
+= 24 0 0x003D
+eq "
+> 24 0 0x003E &gt;
+ra "
+? 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 "
+^ 24 0 0x005E
+a^ "
+ha "
+_ 24 0 0x005F
+ru "
+ul "
+` 24 0 0x0060
+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 &iexcl;
+char161 "
+ct 24 0 0x00A2 &cent;
+char162 "
+Po 24 0 0x00A3 &pound;
+char163 "
+Cs 24 0 0x00A4 &curren;
+char164 "
+Ye 24 0 0x00A5 &yen;
+char165 "
+bb 24 0 0x00A6 &brvbar;
+char166 "
+sc 24 0 0x00A7 &sect;
+char167 "
+ad 24 0 0x00A8 &uml;
+char168 "
+co 24 0 0x00A9 &copy;
+char169 "
+Of 24 0 0x00AA &ordf;
+char170 "
+Fo 24 0 0x00AB &laquo;
+char171 "
+no 24 0 0x00AC &not;
+char172 "
+rg 24 0 0x00AE &reg;
+char174 "
+a- 24 0 0x00AF &macr;
+char175 "
+de 24 0 0x00B0 &deg;
+char176 "
++- 24 0 0x00B1 &plusmn;
+char177 "
+S2 24 0 0x00B2 &sup2;
+char178 "
+S3 24 0 0x00B3 &sup3;
+char179 "
+aa 24 0 0x00B4 &acute;
+\' "
+char180 "
+char181 24 0 0x00B5 &micro;
+ps 24 0 0x00B6 &para;
+char182 "
+pc 24 0 0x00B7 &middot;
+char183 "
+ac 24 0 0x00B8 &cedil;
+char184 "
+S1 24 0 0x00B9 &sup1;
+char185 "
+Om 24 0 0x00BA &ordm;
+char186 "
+Fc 24 0 0x00BB &raquo;
+char187 "
+14 24 0 0x00BC &frac14;
+char188 "
+12 24 0 0x00BD &frac12;
+char189 "
+34 24 0 0x00BE &frac34;
+char190 "
+r? 24 0 0x00BF &iquest;
+char191 "
+`A 24 0 0x00C0 &Agrave;
+char192 "
+'A 24 0 0x00C1 &Aacute;
+char193 "
+^A 24 0 0x00C2 &Acirc;
+char194 "
+~A 24 0 0x00C3 &Atilde;
+char195 "
+:A 24 0 0x00C4 &Auml;
+char196 "
+oA 24 0 0x00C5 &Aring;
+char197 "
+AE 24 0 0x00C6 &AElig;
+char198 "
+,C 24 0 0x00C7 &Ccedil;
+char199 "
+`E 24 0 0x00C8 &Egrave;
+char200 "
+'E 24 0 0x00C9 &Eacute;
+char201 "
+^E 24 0 0x00CA &Ecirc;
+char202 "
+:E 24 0 0x00CB &Euml;
+char203 "
+`I 24 0 0x00CC &Igrave;
+char204 "
+'I 24 0 0x00CD &Iacute;
+char205 "
+^I 24 0 0x00CE &Icirc;
+char206 "
+:I 24 0 0x00CF &Iuml;
+char207 "
+-D 24 0 0x00D0 &ETH;
+char208 "
+~N 24 0 0x00D1 &Ntilde;
+char209 "
+`O 24 0 0x00D2 &Ograve;
+char210 "
+'O 24 0 0x00D3 &Oacute;
+char211 "
+^O 24 0 0x00D4 &Ocirc;
+char212 "
+~O 24 0 0x00D5 &Otilde;
+char213 "
+:O 24 0 0x00D6 &Ouml;
+char214 "
+mu 24 0 0x00D7 &times;
+char215 "
+/O 24 0 0x00D8 &Oslash;
+char216 "
+`U 24 0 0x00D9 &Ugrave;
+char217 "
+'U 24 0 0x00DA &Uacute;
+char218 "
+^U 24 0 0x00DB &Ucirc;
+char219 "
+:U 24 0 0x00DC &Uuml;
+char220 "
+'Y 24 0 0x00DD &Yacute;
+char221 "
+TP 24 0 0x00DE &THORN;
+char222 "
+ss 24 0 0x00DF &szlig;
+char223 "
+`a 24 0 0x00E0 &agrave;
+char224 "
+'a 24 0 0x00E1 &aacute;
+char225 "
+^a 24 0 0x00E2 &acirc;
+char226 "
+~a 24 0 0x00E3 &atilde;
+char227 "
+:a 24 0 0x00E4 &auml;
+char228 "
+oa 24 0 0x00E5 &aring;
+char229 "
+ae 24 0 0x00E6 &aelig;
+char230 "
+,c 24 0 0x00E7 &ccedil;
+char231 "
+`e 24 0 0x00E8 &egrave;
+char232 "
+'e 24 0 0x00E9 &eacute;
+char233 "
+^e 24 0 0x00EA &ecirc;
+char234 "
+:e 24 0 0x00EB &euml;
+char235 "
+`i 24 0 0x00EC &igrave;
+char236 "
+'i 24 0 0x00ED &iacute;
+char237 "
+^i 24 0 0x00EE &icirc;
+char238 "
+:i 24 0 0x00EF &iuml;
+char239 "
+Sd 24 0 0x00F0 &eth;
+char240 "
+~n 24 0 0x00F1 &ntilde;
+char241 "
+`o 24 0 0x00F2 &ograve;
+char242 "
+'o 24 0 0x00F3 &oacute;
+char243 "
+^o 24 0 0x00F4 &ocirc;
+char244 "
+~o 24 0 0x00F5 &otilde;
+char245 "
+:o 24 0 0x00F6 &ouml;
+char246 "
+di 24 0 0x00F7 &divide;
+char247 "
+/o 24 0 0x00F8 &oslash;
+char248 "
+`u 24 0 0x00F9 &ugrave;
+char249 "
+'u 24 0 0x00FA &uacute;
+char250 "
+^u 24 0 0x00FB &ucirc;
+char251 "
+:u 24 0 0x00FC &uuml;
+char252 "
+'y 24 0 0x00FD &yacute;
+char253 "
+Tp 24 0 0x00FE &thorn;
+char254 "
+:y 24 0 0x00FF &yuml;
+char255 "
+\` 24 0 0x2018 &grave;
+ga "
diff --git a/contrib/groff/font/devlatin1/DESC.proto b/contrib/groff/font/devlatin1/DESC.proto
new file mode 100644
index 0000000..88399ab
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devlatin1/Makefile.sub b/contrib/groff/font/devlatin1/Makefile.sub
new file mode 100644
index 0000000..25de3f7
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devlatin1/R.proto b/contrib/groff/font/devlatin1/R.proto
new file mode 100644
index 0000000..a527a9f
--- /dev/null
+++ b/contrib/groff/font/devlatin1/R.proto
@@ -0,0 +1,357 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0041
+" 24 0 0042
+dq "
+lq "
+rq "
+# 24 0 0043
+sh "
+$ 24 0 0044
+Do "
+% 24 0 0045
+& 24 0 0046
+' 24 0 0047
+fm "
+aq "
+cq "
+( 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 "
+shc 24 0 0255
+char173 "
+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 "
+pc 24 0 0267
+md "
+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/contrib/groff/font/devlbp/CB b/contrib/groff/font/devlbp/CB
new file mode 100644
index 0000000..5c34658
--- /dev/null
+++ b/contrib/groff/font/devlbp/CB
@@ -0,0 +1,272 @@
+
+name CB
+lbpname NcourierB
+spacewidth 2200
+slant 0
+charset
+aq 2200 0 0x27 -- 0,39 # quotesingle
+space 2200 0 0x20 -- 0,32
+! 2200 0 0x21 -- 0,33 # exclam
+" 2200 0 0x22 -- 0,34 # quotedbl
+dq 2200 0 0x22 -- 0,34 # quotedbl
+# 2200 0 0x23 -- 0,35 # numbersign
+sh 2200 0 0x23 -- 0,35 # "
+$ 2200 0 0x24 -- 0,36 # dollar
+Do 2200 0 0x24 -- 0,36 # "
+% 2200 0 0x25 -- 0,37 # percent
+& 2200 0 0x26 -- 0,38 # ampersand
+' 2200 0 0x27 -- 0,39 # quoteright
+cq 2200 0 0x27 -- 0,39 # quoteright
+( 2200 0 0x28 -- 0,40 # parenleft
+) 2200 0 0x29 -- 0,41 # parenright
+* 2200 0 0x2a -- 0,42 # asterisk
++ 2200 0 0x2b -- 0,43 # plus
+, 2200 0 0x2c -- 0,44 # comma
+- 2200 0 0x2d -- 0,45 # hyphen
+\- 2200 0 0x2d -- 0,45 # hyphen
+hy 2200 0 0x2d -- 0,45 # "
+char173 2200 0 0x2d -- 0,45 # "
+. 2200 0 0x2e -- 0,46 # period
+/ 2200 0 0x2f -- 0,47 # slash
+sl 2200 0 0x2f -- 0,47 # "
+0 2200 0 0x30 -- 0,48 # zero
+1 2200 0 0x31 -- 0,49 # one
+2 2200 0 0x32 -- 0,50 # two
+3 2200 0 0x33 -- 0,51 # three
+4 2200 0 0x34 -- 0,52 # four
+5 2200 0 0x35 -- 0,53 # five
+6 2200 0 0x36 -- 0,54 # six
+7 2200 0 0x37 -- 0,55 # seven
+8 2200 0 0x38 -- 0,56 # eight
+9 2200 0 0x39 -- 0,57 # nine
+: 2200 0 0x3a -- 0,58 # colon
+; 2200 0 0x3b -- 0,59 # semicolon
+< 2200 0 0x3c -- 0,60 # less
+= 2200 0 0x3d -- 0,61 # equal
+> 2200 0 0x3e -- 0,62 # greater
+? 2200 0 0x3f -- 0,63 # question
+@ 2200 0 0x40 -- 0,64 # at
+at 2200 0 0x40 -- 0,64 # "
+A 2200 0 0x41 -- 0,65 # A
+B 2200 0 0x42 -- 0,66 # B
+C 2200 0 0x43 -- 0,67 # C
+D 2200 0 0x44 -- 0,68 # D
+E 2200 0 0x45 -- 0,69 # E
+F 2200 0 0x46 -- 0,70 # F
+G 2200 0 0x47 -- 0,71 # G
+H 2200 0 0x48 -- 0,72 # H
+I 2200 0 0x49 -- 0,73 # I
+J 2200 0 0x4a -- 0,74 # J
+K 2200 0 0x4b -- 0,75 # K
+L 2200 0 0x4c -- 0,76 # L
+M 2200 0 0x4d -- 0,77 # M
+N 2200 0 0x4e -- 0,78 # N
+O 2200 0 0x4f -- 0,79 # O
+P 2200 0 0x50 -- 0,80 # P
+Q 2200 0 0x51 -- 0,81 # Q
+R 2200 0 0x52 -- 0,82 # R
+S 2200 0 0x53 -- 0,83 # S
+T 2200 0 0x54 -- 0,84 # T
+U 2200 0 0x55 -- 0,85 # U
+V 2200 0 0x56 -- 0,86 # V
+W 2200 0 0x57 -- 0,87 # W
+X 2200 0 0x58 -- 0,88 # X
+Y 2200 0 0x59 -- 0,89 # Y
+Z 2200 0 0x5a -- 0,90 # Z
+[ 2200 0 0x5b -- 0,91 # bracketleft
+lB 2200 0 0x5b -- 0,91 # "
+\ 2200 0 0x5c -- 0,92 # backslash
+rs 2200 0 0x5c -- 0,92 # "
+] 2200 0 0x5d -- 0,93 # bracketright
+rB 2200 0 0x5d -- 0,93 # "
+a^ 2200 0 0x5e -- 0,94 # circumflex
+^ 2200 0 0x5e -- 0,94 # "
+_ 2200 0 0x5f -- 0,95 # underscore
+` 2200 0 0x60 -- 0,96 # quoteleft
+oq 2200 0 0x60 -- 0,96 # "
+a 2200 0 0x61 -- 0,97 # a
+b 2200 0 0x62 -- 0,98 # b
+c 2200 0 0x63 -- 0,99 # c
+d 2200 0 0x64 -- 0,100 # d
+e 2200 0 0x65 -- 0,101 # e
+f 2200 0 0x66 -- 0,102 # f
+g 2200 0 0x67 -- 0,103 # g
+h 2200 0 0x68 -- 0,104 # h
+i 2200 0 0x69 -- 0,105 # i
+j 2200 0 0x6a -- 0,106 # j
+k 2200 0 0x6b -- 0,107 # k
+l 2200 0 0x6c -- 0,108 # l
+m 2200 0 0x6d -- 0,109 # m
+n 2200 0 0x6e -- 0,110 # n
+o 2200 0 0x6f -- 0,111 # o
+p 2200 0 0x70 -- 0,112 # p
+q 2200 0 0x71 -- 0,113 # q
+r 2200 0 0x72 -- 0,114 # r
+s 2200 0 0x73 -- 0,115 # s
+t 2200 0 0x74 -- 0,116 # t
+u 2200 0 0x75 -- 0,117 # u
+v 2200 0 0x76 -- 0,118 # v
+w 2200 0 0x77 -- 0,119 # w
+x 2200 0 0x78 -- 0,120 # x
+y 2200 0 0x79 -- 0,121 # y
+z 2200 0 0x7a -- 0,122 # z
+lC 2200 0 0x7b -- 0,123 # braceleft
+{ 2200 0 0x7b -- 0,123 # "
+| 2200 0 0x7c -- 0,124 # "
+rC 2200 0 0x7d -- 0,125 # braceright
+} 2200 0 0x7d -- 0,125 # "
+a~ 2200 0 0x7e -- 0,126 # tilde
+~ 2200 0 0x7e -- 0,126 # "
+char161 2200 0 0xad -- 4,7 # exclamdown
+char162 2200 0 0x9b -- 4,19 # cent
+char163 2200 0 0x9c -- 4,11 # sterling
+char165 2200 0 0x9d -- 4,12 # yen
+char166 2200 0 0x7c -- 0,124 # brokenbar
+char167 2200 0 0x15 -- 4,6 # section
+char170 2200 0 0xa6 -- 4,15 # ordfeminine
+char171 2200 0 0xae -- 4,9 # guillemotleft
+char172 2200 0 0xaa -- 6,20 # logicalnot
+char175 2200 0 0x2d -- 6,0 # macron
+char176 2200 0 0xf8 -- 6,36 # degree
+char177 2200 0 0xf1 -- 6,1 # plusminus
+char178 2200 0 0xfd -- 4,20 # twosuperior
+char181 2200 0 0xe6 -- 8,25 # mu
+char182 2200 0 0x14 -- 4,5 # paragraph
+char183 2200 0 0xfa -- 6,32 # periodcentered
+char186 2200 0 0xa7 -- 4,16 # ordmasculine
+char187 2200 0 0xaf -- 4,10 # guillemotright
+char188 2200 0 0xac -- 4,18 # onequarter
+char189 2200 0 0xab -- 4,17 # onehalf
+char191 2200 0 0xa8 -- 4,8 # questiondown
+char195 2200 0 0x28e -- 1,76 # Atilde
+char196 2200 0 0x8e -- 1,30 # Adieresis
+char197 2200 0 0x8f -- 1,34 # Aring
+char198 2200 0 0x92 -- 1,36 # AE
+char199 2200 0 0x80 -- 1,38 # Ccedilla
+char201 2200 0 0x90 -- 1,40 # Eacute
+char209 2200 0 0xa5 -- 1,56 # Ntilde
+char214 2200 0 0x99 -- 1,62 # Odieresis
+char220 2200 0 0x9a -- 1,70 # Udieresis
+char224 2200 0 0x85 -- 1,33 # agrave
+char225 2200 0 0xa0 -- 1,27 # aacute
+char226 2200 0 0x83 -- 1,29 # acircumflex
+char227 2200 0 0x284 -- 1,93 # atilde
+char228 2200 0 0x84 -- 1,31 # adieresis
+char229 2200 0 0x86 -- 1,35 # aring
+char230 2200 0 0x91 -- 1,37 # ae
+char231 2200 0 0x87 -- 1,39 # ccedilla
+char232 2200 0 0x8a -- 1,47 # egrave
+char233 2200 0 0x82 -- 1,41 # eacute
+char234 2200 0 0x88 -- 1,43 # ecircumflex
+char235 2200 0 0x89 -- 1,45 # edieresis
+char236 2200 0 0x8d -- 1,55 # igrave
+char237 2200 0 0xa1 -- 1,49 # iacute
+char238 2200 0 0x8c -- 1,51 # icircumflex
+char239 2200 0 0x8b -- 1,53 # idieresis
+char241 2200 0 0xa4 -- 1,57 # ntilde
+char242 2200 0 0x95 -- 1,65 # ograve
+char243 2200 0 0xa2 -- 1,59 # oacute
+char244 2200 0 0x93 -- 1,61 # ocircumflex
+char246 2200 0 0x94 -- 1,63 # odieresis
+char247 2200 0 0xf6 -- 6,8 # divide
+char249 2200 0 0x97 -- 1,73 # ugrave
+char250 2200 0 0xa3 -- 1,67 # uacute
+char251 2200 0 0x96 -- 1,69 # ucircumflex
+char252 2200 0 0x81 -- 1,71 # udieresis
+char255 2200 0 0x98 -- 1,75 # ydieresis
+AE 2200 0 0x92 -- 1,36 # AE
+ae 2200 0 0x91 -- 1,37 # ae
+'E 2200 0 0x90 -- 1,40 # Eacute
+'a 2200 0 0xa0 -- 1,27 # aacute
+'e 2200 0 0x82 -- 1,41 # eacute
+'i 2200 0 0xa1 -- 1,49 # iacute
+'o 2200 0 0xa2 -- 1,59 # oacute
+'u 2200 0 0x95 -- 1,65 # uacute
+:A 2200 0 0x8e -- 1,30 # Adieresis
+:O 2200 0 0x99 -- 1,62 # Odieresis
+:U 2200 0 0x9a -- 1,70 # Udieresis
+:a 2200 0 0x84 -- 1,31 # adieresis
+:e 2200 0 0x89 -- 1,45 # edieresis
+:i 2200 0 0x8b -- 1,53 # idieresis
+:o 2200 0 0x94 -- 1,63 # odieresis
+:u 2200 0 0x81 -- 1,71 # udieresis
+:y 2200 0 0x98 -- 1,75 # ydieresis
+^a 2200 0 0x83 -- 1,29 # acircumflex
+^e 2200 0 0x88 -- 1,43 # ecircumflex
+^i 2200 0 0x8c -- 1,51 # icircumflex
+^o 2200 0 0x93 -- 1,61 # ocircumflex
+^u 2200 0 0x96 -- 1,69 # ucircumflex
+`a 2200 0 0x85 -- 1,33 # agrave
+`e 2200 0 0x8a -- 1,47 # egrave
+`i 2200 0 0x8d -- 1,55 # igrave
+`o 2200 0 0x95 -- 1,65 # ograve
+`u 2200 0 0x97 -- 1,73 # ugrave
+~A 2200 0 0x28e -- 1,26 # Atilde
+~N 2200 0 0xa5 -- 1,56 # Ntilde
+~a 2200 0 0x284 -- --- # atilde
+~n 2200 0 0xa4 -- 1,57 # ntilde
+,C 2200 0 0x80 -- 1,38 # Ccedilla
+,c 2200 0 0x87 -- 1,39 # ccedilla
+oA 2200 0 0x8f -- 1,34 # Aring
+oa 2200 0 0x86 -- 1,35 # aring
+a^ 2200 0 0x5e -- 1,3 # circumflex "circumflex accent"
+a~ 2200 0 0x7e -- 1,2 # tilde "tilde accent"
+Do 2200 0 0x24 -- 0,36 # dollar
+Po 2200 0 0x9c -- 4,11 # sterling
+Ye 2200 0 0x9d -- 4,12 # yen
+Fn 2200 0 0x9f -- 4,14 # florin
+ct 2200 0 0x9b -- 4,19 # cent
+Fo 2200 0 0xae -- 4,9 # guillemotleft
+r! 2200 0 0xad -- 4,7 # exclamdown
+r? 2200 0 0xa8 -- 4,8 # questiondown
+Of 2200 0 0xa6 -- 4,15 # ordfeminine
+Om 2200 0 0xa7 -- 4,16 # ordmasculine
+S2 2200 0 0xfd -- 4,20 # twosuperior
+<- 2200 0 0x1b -- 6,22 # arrowleft
+-> 2200 0 0x1a -- 6,21 # arrowright
+<> 2200 0 0x1d -- 6,25 # arrowboth "horizontal double-headed arrow"
+da 2200 0 0x19 -- 6,24 # arrowdown
+ua 2200 0 0x18 -- 6,23 # arrowup
+va 2200 0 0x12 -- 6,26 # \& "vertical double-headed arrow"
+ba 2200 0 0xb3 -- 3,9 # bar
+bb 2200 0 0x7c -- 0,124 # brokenbar
+ul 2200 0 0x5f -- 0,95 # ul "underline with traditional troff metrics"
+ci 2200 0 0x9 -- 4,1 # circle
+bu 2200 0 0x7 -- 4,0 # bullet
+ps 2200 0 0x14 -- 4,5 # paragraph
+sc 2200 0 0x15 -- 4,6 # section
+de 2200 0 0xf8 -- 6,36 # degree
+12 2200 0 0xab -- 4,17 # onehalf
+14 2200 0 0xac -- 4,18 # onequarter
+hy 2200 0 0x2d -- 6,0 # hyphen
+lB 2200 0 0x5b -- 0,91 # bracketleft
+rB 2200 0 0x5d -- 0,93 # bracketright
+lC 2200 0 0x7b -- 0,123 # braceleft
+rC 2200 0 0x7d -- 0,125 # braceright
+aq 2200 0 0x27 -- 0,39 # quotesingle "apostrophe quote"
+at 2200 0 0x40 -- 0,64 # at
+.C1 2200 0 0x2d -- 0,45 # - minus "minus sign from current font"
+sh 2200 0 0x23 -- 0,35 # numbersign
+sl 2200 0 0x2f -- 0,47 # slash
+rs 2200 0 0x5c -- 0,92 # backslash
+*a 2200 0 0xe0 -- 8,1 # alpha
+*b 2200 0 0xe1 -- 8,3 # beta
+*d 2200 0 0xeb -- 8,9 # delta
+*h 2200 0 0xe9 -- 8,17 # theta
+*m 2200 0 0xe6 -- 8,25 # mu
+*p 2200 0 0xe3 -- 8,33 # pi
+*s 2200 0 0xe5 -- 8,37 # sigma
+*t 2200 0 0xe7 -- 8,41 # tau
+~~ 2200 0 0xf7 -- 6,13 # approxequal
+~= 2200 0 0xf7 -- 6,13 # approxequal
++- 2200 0 0xf1 -- 6,1 # plusminus
+<= 2200 0 0xf3 -- 6,2 # lessequal
+ca 2200 0 0xef -- 6,16 # intersection "intersection, cap"
+-h 2200 0 0xc4 -- 3,8 # hbar
+CL 2200 0 0x5 -- 5,168 # club "club suit"
+SP 2200 0 0x6 -- 5,171 # spade "spade suit"
+HE 2200 0 0x3 -- 5,170 # heart "heart suit"
+DI 2200 0 0x4 -- 5,169 # diamond "diamond suit"
+<< 2200 0 0xae -- 6,77 # "" "much less"
+>> 2200 0 0xaf -- 6,78 # "" "much greater"
+pc 2200 0 0xfa -- 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/CI b/contrib/groff/font/devlbp/CI
new file mode 100644
index 0000000..84b0ac4
--- /dev/null
+++ b/contrib/groff/font/devlbp/CI
@@ -0,0 +1,272 @@
+
+name CI
+lbpname NcourierI
+spacewidth 2200
+slant 0
+charset
+aq 2200 0 0x27 -- 0,39 # quotesingle
+space 2200 0 0x20 -- 0,32
+! 2200 0 0x21 -- 0,33 # exclam
+" 2200 0 0x22 -- 0,34 # quotedbl
+dq 2200 0 0x22 -- 0,34 # quotedbl
+# 2200 0 0x23 -- 0,35 # numbersign
+sh 2200 0 0x23 -- 0,35 # "
+$ 2200 0 0x24 -- 0,36 # dollar
+Do 2200 0 0x24 -- 0,36 # "
+% 2200 0 0x25 -- 0,37 # percent
+& 2200 0 0x26 -- 0,38 # ampersand
+' 2200 0 0x27 -- 0,39 # quoteright
+cq 2200 0 0x27 -- 0,39 # quoteright
+( 2200 0 0x28 -- 0,40 # parenleft
+) 2200 0 0x29 -- 0,41 # parenright
+* 2200 0 0x2a -- 0,42 # asterisk
++ 2200 0 0x2b -- 0,43 # plus
+, 2200 0 0x2c -- 0,44 # comma
+- 2200 0 0x2d -- 0,45 # hyphen
+\- 2200 0 0x2d -- 0,45 # hyphen
+hy 2200 0 0x2d -- 0,45 # "
+char173 2200 0 0x2d -- 0,45 # "
+. 2200 0 0x2e -- 0,46 # period
+/ 2200 0 0x2f -- 0,47 # slash
+sl 2200 0 0x2f -- 0,47 # "
+0 2200 0 0x30 -- 0,48 # zero
+1 2200 0 0x31 -- 0,49 # one
+2 2200 0 0x32 -- 0,50 # two
+3 2200 0 0x33 -- 0,51 # three
+4 2200 0 0x34 -- 0,52 # four
+5 2200 0 0x35 -- 0,53 # five
+6 2200 0 0x36 -- 0,54 # six
+7 2200 0 0x37 -- 0,55 # seven
+8 2200 0 0x38 -- 0,56 # eight
+9 2200 0 0x39 -- 0,57 # nine
+: 2200 0 0x3a -- 0,58 # colon
+; 2200 0 0x3b -- 0,59 # semicolon
+< 2200 0 0x3c -- 0,60 # less
+= 2200 0 0x3d -- 0,61 # equal
+> 2200 0 0x3e -- 0,62 # greater
+? 2200 0 0x3f -- 0,63 # question
+@ 2200 0 0x40 -- 0,64 # at
+at 2200 0 0x40 -- 0,64 # "
+A 2200 0 0x41 -- 0,65 # A
+B 2200 0 0x42 -- 0,66 # B
+C 2200 0 0x43 -- 0,67 # C
+D 2200 0 0x44 -- 0,68 # D
+E 2200 0 0x45 -- 0,69 # E
+F 2200 0 0x46 -- 0,70 # F
+G 2200 0 0x47 -- 0,71 # G
+H 2200 0 0x48 -- 0,72 # H
+I 2200 0 0x49 -- 0,73 # I
+J 2200 0 0x4a -- 0,74 # J
+K 2200 0 0x4b -- 0,75 # K
+L 2200 0 0x4c -- 0,76 # L
+M 2200 0 0x4d -- 0,77 # M
+N 2200 0 0x4e -- 0,78 # N
+O 2200 0 0x4f -- 0,79 # O
+P 2200 0 0x50 -- 0,80 # P
+Q 2200 0 0x51 -- 0,81 # Q
+R 2200 0 0x52 -- 0,82 # R
+S 2200 0 0x53 -- 0,83 # S
+T 2200 0 0x54 -- 0,84 # T
+U 2200 0 0x55 -- 0,85 # U
+V 2200 0 0x56 -- 0,86 # V
+W 2200 0 0x57 -- 0,87 # W
+X 2200 0 0x58 -- 0,88 # X
+Y 2200 0 0x59 -- 0,89 # Y
+Z 2200 0 0x5a -- 0,90 # Z
+[ 2200 0 0x5b -- 0,91 # bracketleft
+lB 2200 0 0x5b -- 0,91 # "
+\ 2200 0 0x5c -- 0,92 # backslash
+rs 2200 0 0x5c -- 0,92 # "
+] 2200 0 0x5d -- 0,93 # bracketright
+rB 2200 0 0x5d -- 0,93 # "
+a^ 2200 0 0x5e -- 0,94 # circumflex
+^ 2200 0 0x5e -- 0,94 # "
+_ 2200 0 0x5f -- 0,95 # underscore
+` 2200 0 0x60 -- 0,96 # quoteleft
+oq 2200 0 0x60 -- 0,96 # "
+a 2200 0 0x61 -- 0,97 # a
+b 2200 0 0x62 -- 0,98 # b
+c 2200 0 0x63 -- 0,99 # c
+d 2200 0 0x64 -- 0,100 # d
+e 2200 0 0x65 -- 0,101 # e
+f 2200 0 0x66 -- 0,102 # f
+g 2200 0 0x67 -- 0,103 # g
+h 2200 0 0x68 -- 0,104 # h
+i 2200 0 0x69 -- 0,105 # i
+j 2200 0 0x6a -- 0,106 # j
+k 2200 0 0x6b -- 0,107 # k
+l 2200 0 0x6c -- 0,108 # l
+m 2200 0 0x6d -- 0,109 # m
+n 2200 0 0x6e -- 0,110 # n
+o 2200 0 0x6f -- 0,111 # o
+p 2200 0 0x70 -- 0,112 # p
+q 2200 0 0x71 -- 0,113 # q
+r 2200 0 0x72 -- 0,114 # r
+s 2200 0 0x73 -- 0,115 # s
+t 2200 0 0x74 -- 0,116 # t
+u 2200 0 0x75 -- 0,117 # u
+v 2200 0 0x76 -- 0,118 # v
+w 2200 0 0x77 -- 0,119 # w
+x 2200 0 0x78 -- 0,120 # x
+y 2200 0 0x79 -- 0,121 # y
+z 2200 0 0x7a -- 0,122 # z
+lC 2200 0 0x7b -- 0,123 # braceleft
+{ 2200 0 0x7b -- 0,123 # "
+| 2200 0 0x7c -- 0,124 # "
+rC 2200 0 0x7d -- 0,125 # braceright
+} 2200 0 0x7d -- 0,125 # "
+a~ 2200 0 0x7e -- 0,126 # tilde
+~ 2200 0 0x7e -- 0,126 # "
+char161 2200 0 0xad -- 4,7 # exclamdown
+char162 2200 0 0x9b -- 4,19 # cent
+char163 2200 0 0x9c -- 4,11 # sterling
+char165 2200 0 0x9d -- 4,12 # yen
+char166 2200 0 0x7c -- 0,124 # brokenbar
+char167 2200 0 0x15 -- 4,6 # section
+char170 2200 0 0xa6 -- 4,15 # ordfeminine
+char171 2200 0 0xae -- 4,9 # guillemotleft
+char172 2200 0 0xaa -- 6,20 # logicalnot
+char175 2200 0 0x2d -- 6,0 # macron
+char176 2200 0 0xf8 -- 6,36 # degree
+char177 2200 0 0xf1 -- 6,1 # plusminus
+char178 2200 0 0xfd -- 4,20 # twosuperior
+char181 2200 0 0xe6 -- 8,25 # mu
+char182 2200 0 0x14 -- 4,5 # paragraph
+char183 2200 0 0xfa -- 6,32 # periodcentered
+char186 2200 0 0xa7 -- 4,16 # ordmasculine
+char187 2200 0 0xaf -- 4,10 # guillemotright
+char188 2200 0 0xac -- 4,18 # onequarter
+char189 2200 0 0xab -- 4,17 # onehalf
+char191 2200 0 0xa8 -- 4,8 # questiondown
+char195 2200 0 0x28e -- 1,76 # Atilde
+char196 2200 0 0x8e -- 1,30 # Adieresis
+char197 2200 0 0x8f -- 1,34 # Aring
+char198 2200 0 0x92 -- 1,36 # AE
+char199 2200 0 0x80 -- 1,38 # Ccedilla
+char201 2200 0 0x90 -- 1,40 # Eacute
+char209 2200 0 0xa5 -- 1,56 # Ntilde
+char214 2200 0 0x99 -- 1,62 # Odieresis
+char220 2200 0 0x9a -- 1,70 # Udieresis
+char224 2200 0 0x85 -- 1,33 # agrave
+char225 2200 0 0xa0 -- 1,27 # aacute
+char226 2200 0 0x83 -- 1,29 # acircumflex
+char227 2200 0 0x284 -- 1,93 # atilde
+char228 2200 0 0x84 -- 1,31 # adieresis
+char229 2200 0 0x86 -- 1,35 # aring
+char230 2200 0 0x91 -- 1,37 # ae
+char231 2200 0 0x87 -- 1,39 # ccedilla
+char232 2200 0 0x8a -- 1,47 # egrave
+char233 2200 0 0x82 -- 1,41 # eacute
+char234 2200 0 0x88 -- 1,43 # ecircumflex
+char235 2200 0 0x89 -- 1,45 # edieresis
+char236 2200 0 0x8d -- 1,55 # igrave
+char237 2200 0 0xa1 -- 1,49 # iacute
+char238 2200 0 0x8c -- 1,51 # icircumflex
+char239 2200 0 0x8b -- 1,53 # idieresis
+char241 2200 0 0xa4 -- 1,57 # ntilde
+char242 2200 0 0x95 -- 1,65 # ograve
+char243 2200 0 0xa2 -- 1,59 # oacute
+char244 2200 0 0x93 -- 1,61 # ocircumflex
+char246 2200 0 0x94 -- 1,63 # odieresis
+char247 2200 0 0xf6 -- 6,8 # divide
+char249 2200 0 0x97 -- 1,73 # ugrave
+char250 2200 0 0xa3 -- 1,67 # uacute
+char251 2200 0 0x96 -- 1,69 # ucircumflex
+char252 2200 0 0x81 -- 1,71 # udieresis
+char255 2200 0 0x98 -- 1,75 # ydieresis
+AE 2200 0 0x92 -- 1,36 # AE
+ae 2200 0 0x91 -- 1,37 # ae
+'E 2200 0 0x90 -- 1,40 # Eacute
+'a 2200 0 0xa0 -- 1,27 # aacute
+'e 2200 0 0x82 -- 1,41 # eacute
+'i 2200 0 0xa1 -- 1,49 # iacute
+'o 2200 0 0xa2 -- 1,59 # oacute
+'u 2200 0 0x95 -- 1,65 # uacute
+:A 2200 0 0x8e -- 1,30 # Adieresis
+:O 2200 0 0x99 -- 1,62 # Odieresis
+:U 2200 0 0x9a -- 1,70 # Udieresis
+:a 2200 0 0x84 -- 1,31 # adieresis
+:e 2200 0 0x89 -- 1,45 # edieresis
+:i 2200 0 0x8b -- 1,53 # idieresis
+:o 2200 0 0x94 -- 1,63 # odieresis
+:u 2200 0 0x81 -- 1,71 # udieresis
+:y 2200 0 0x98 -- 1,75 # ydieresis
+^a 2200 0 0x83 -- 1,29 # acircumflex
+^e 2200 0 0x88 -- 1,43 # ecircumflex
+^i 2200 0 0x8c -- 1,51 # icircumflex
+^o 2200 0 0x93 -- 1,61 # ocircumflex
+^u 2200 0 0x96 -- 1,69 # ucircumflex
+`a 2200 0 0x85 -- 1,33 # agrave
+`e 2200 0 0x8a -- 1,47 # egrave
+`i 2200 0 0x8d -- 1,55 # igrave
+`o 2200 0 0x95 -- 1,65 # ograve
+`u 2200 0 0x97 -- 1,73 # ugrave
+~A 2200 0 0x28e -- 1,26 # Atilde
+~N 2200 0 0xa5 -- 1,56 # Ntilde
+~a 2200 0 0x284 -- --- # atilde
+~n 2200 0 0xa4 -- 1,57 # ntilde
+,C 2200 0 0x80 -- 1,38 # Ccedilla
+,c 2200 0 0x87 -- 1,39 # ccedilla
+oA 2200 0 0x8f -- 1,34 # Aring
+oa 2200 0 0x86 -- 1,35 # aring
+a^ 2200 0 0x5e -- 1,3 # circumflex "circumflex accent"
+a~ 2200 0 0x7e -- 1,2 # tilde "tilde accent"
+Do 2200 0 0x24 -- 0,36 # dollar
+Po 2200 0 0x9c -- 4,11 # sterling
+Ye 2200 0 0x9d -- 4,12 # yen
+Fn 2200 0 0x9f -- 4,14 # florin
+ct 2200 0 0x9b -- 4,19 # cent
+Fo 2200 0 0xae -- 4,9 # guillemotleft
+r! 2200 0 0xad -- 4,7 # exclamdown
+r? 2200 0 0xa8 -- 4,8 # questiondown
+Of 2200 0 0xa6 -- 4,15 # ordfeminine
+Om 2200 0 0xa7 -- 4,16 # ordmasculine
+S2 2200 0 0xfd -- 4,20 # twosuperior
+<- 2200 0 0x1b -- 6,22 # arrowleft
+-> 2200 0 0x1a -- 6,21 # arrowright
+<> 2200 0 0x1d -- 6,25 # arrowboth "horizontal double-headed arrow"
+da 2200 0 0x19 -- 6,24 # arrowdown
+ua 2200 0 0x18 -- 6,23 # arrowup
+va 2200 0 0x12 -- 6,26 # \& "vertical double-headed arrow"
+ba 2200 0 0xb3 -- 3,9 # bar
+bb 2200 0 0x7c -- 0,124 # brokenbar
+ul 2200 0 0x5f -- 0,95 # ul "underline with traditional troff metrics"
+ci 2200 0 0x9 -- 4,1 # circle
+bu 2200 0 0x7 -- 4,0 # bullet
+ps 2200 0 0x14 -- 4,5 # paragraph
+sc 2200 0 0x15 -- 4,6 # section
+de 2200 0 0xf8 -- 6,36 # degree
+12 2200 0 0xab -- 4,17 # onehalf
+14 2200 0 0xac -- 4,18 # onequarter
+hy 2200 0 0x2d -- 6,0 # hyphen
+lB 2200 0 0x5b -- 0,91 # bracketleft
+rB 2200 0 0x5d -- 0,93 # bracketright
+lC 2200 0 0x7b -- 0,123 # braceleft
+rC 2200 0 0x7d -- 0,125 # braceright
+aq 2200 0 0x27 -- 0,39 # quotesingle "apostrophe quote"
+at 2200 0 0x40 -- 0,64 # at
+.C1 2200 0 0x2d -- 0,45 # - minus "minus sign from current font"
+sh 2200 0 0x23 -- 0,35 # numbersign
+sl 2200 0 0x2f -- 0,47 # slash
+rs 2200 0 0x5c -- 0,92 # backslash
+*a 2200 0 0xe0 -- 8,1 # alpha
+*b 2200 0 0xe1 -- 8,3 # beta
+*d 2200 0 0xeb -- 8,9 # delta
+*h 2200 0 0xe9 -- 8,17 # theta
+*m 2200 0 0xe6 -- 8,25 # mu
+*p 2200 0 0xe3 -- 8,33 # pi
+*s 2200 0 0xe5 -- 8,37 # sigma
+*t 2200 0 0xe7 -- 8,41 # tau
+~~ 2200 0 0xf7 -- 6,13 # approxequal
+~= 2200 0 0xf7 -- 6,13 # approxequal
++- 2200 0 0xf1 -- 6,1 # plusminus
+<= 2200 0 0xf3 -- 6,2 # lessequal
+ca 2200 0 0xef -- 6,16 # intersection "intersection, cap"
+-h 2200 0 0xc4 -- 3,8 # hbar
+CL 2200 0 0x5 -- 5,168 # club "club suit"
+SP 2200 0 0x6 -- 5,171 # spade "spade suit"
+HE 2200 0 0x3 -- 5,170 # heart "heart suit"
+DI 2200 0 0x4 -- 5,169 # diamond "diamond suit"
+<< 2200 0 0xae -- 6,77 # "" "much less"
+>> 2200 0 0xaf -- 6,78 # "" "much greater"
+pc 2200 0 0xfa -- 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/CR b/contrib/groff/font/devlbp/CR
new file mode 100644
index 0000000..ef4a56b
--- /dev/null
+++ b/contrib/groff/font/devlbp/CR
@@ -0,0 +1,272 @@
+
+name CR
+lbpname NcourierR
+spacewidth 2200
+slant 0
+charset
+aq 2200 0 0x27 -- 0,39 # quotesingle
+space 2200 0 0x20 -- 0,32
+! 2200 0 0x21 -- 0,33 # exclam
+" 2200 0 0x22 -- 0,34 # quotedbl
+dq 2200 0 0x22 -- 0,34 # quotedbl
+# 2200 0 0x23 -- 0,35 # numbersign
+sh 2200 0 0x23 -- 0,35 # "
+$ 2200 0 0x24 -- 0,36 # dollar
+Do 2200 0 0x24 -- 0,36 # "
+% 2200 0 0x25 -- 0,37 # percent
+& 2200 0 0x26 -- 0,38 # ampersand
+' 2200 0 0x27 -- 0,39 # quoteright
+cq 2200 0 0x27 -- 0,39 # quoteright
+( 2200 0 0x28 -- 0,40 # parenleft
+) 2200 0 0x29 -- 0,41 # parenright
+* 2200 0 0x2a -- 0,42 # asterisk
++ 2200 0 0x2b -- 0,43 # plus
+, 2200 0 0x2c -- 0,44 # comma
+- 2200 0 0x2d -- 0,45 # hyphen
+\- 2200 0 0x2d -- 0,45 # hyphen
+hy 2200 0 0x2d -- 0,45 # "
+char173 2200 0 0x2d -- 0,45 # "
+. 2200 0 0x2e -- 0,46 # period
+/ 2200 0 0x2f -- 0,47 # slash
+sl 2200 0 0x2f -- 0,47 # "
+0 2200 0 0x30 -- 0,48 # zero
+1 2200 0 0x31 -- 0,49 # one
+2 2200 0 0x32 -- 0,50 # two
+3 2200 0 0x33 -- 0,51 # three
+4 2200 0 0x34 -- 0,52 # four
+5 2200 0 0x35 -- 0,53 # five
+6 2200 0 0x36 -- 0,54 # six
+7 2200 0 0x37 -- 0,55 # seven
+8 2200 0 0x38 -- 0,56 # eight
+9 2200 0 0x39 -- 0,57 # nine
+: 2200 0 0x3a -- 0,58 # colon
+; 2200 0 0x3b -- 0,59 # semicolon
+< 2200 0 0x3c -- 0,60 # less
+= 2200 0 0x3d -- 0,61 # equal
+> 2200 0 0x3e -- 0,62 # greater
+? 2200 0 0x3f -- 0,63 # question
+@ 2200 0 0x40 -- 0,64 # at
+at 2200 0 0x40 -- 0,64 # "
+A 2200 0 0x41 -- 0,65 # A
+B 2200 0 0x42 -- 0,66 # B
+C 2200 0 0x43 -- 0,67 # C
+D 2200 0 0x44 -- 0,68 # D
+E 2200 0 0x45 -- 0,69 # E
+F 2200 0 0x46 -- 0,70 # F
+G 2200 0 0x47 -- 0,71 # G
+H 2200 0 0x48 -- 0,72 # H
+I 2200 0 0x49 -- 0,73 # I
+J 2200 0 0x4a -- 0,74 # J
+K 2200 0 0x4b -- 0,75 # K
+L 2200 0 0x4c -- 0,76 # L
+M 2200 0 0x4d -- 0,77 # M
+N 2200 0 0x4e -- 0,78 # N
+O 2200 0 0x4f -- 0,79 # O
+P 2200 0 0x50 -- 0,80 # P
+Q 2200 0 0x51 -- 0,81 # Q
+R 2200 0 0x52 -- 0,82 # R
+S 2200 0 0x53 -- 0,83 # S
+T 2200 0 0x54 -- 0,84 # T
+U 2200 0 0x55 -- 0,85 # U
+V 2200 0 0x56 -- 0,86 # V
+W 2200 0 0x57 -- 0,87 # W
+X 2200 0 0x58 -- 0,88 # X
+Y 2200 0 0x59 -- 0,89 # Y
+Z 2200 0 0x5a -- 0,90 # Z
+[ 2200 0 0x5b -- 0,91 # bracketleft
+lB 2200 0 0x5b -- 0,91 # "
+\ 2200 0 0x5c -- 0,92 # backslash
+rs 2200 0 0x5c -- 0,92 # "
+] 2200 0 0x5d -- 0,93 # bracketright
+rB 2200 0 0x5d -- 0,93 # "
+a^ 2200 0 0x5e -- 0,94 # circumflex
+^ 2200 0 0x5e -- 0,94 # "
+_ 2200 0 0x5f -- 0,95 # underscore
+` 2200 0 0x60 -- 0,96 # quoteleft
+oq 2200 0 0x60 -- 0,96 # "
+a 2200 0 0x61 -- 0,97 # a
+b 2200 0 0x62 -- 0,98 # b
+c 2200 0 0x63 -- 0,99 # c
+d 2200 0 0x64 -- 0,100 # d
+e 2200 0 0x65 -- 0,101 # e
+f 2200 0 0x66 -- 0,102 # f
+g 2200 0 0x67 -- 0,103 # g
+h 2200 0 0x68 -- 0,104 # h
+i 2200 0 0x69 -- 0,105 # i
+j 2200 0 0x6a -- 0,106 # j
+k 2200 0 0x6b -- 0,107 # k
+l 2200 0 0x6c -- 0,108 # l
+m 2200 0 0x6d -- 0,109 # m
+n 2200 0 0x6e -- 0,110 # n
+o 2200 0 0x6f -- 0,111 # o
+p 2200 0 0x70 -- 0,112 # p
+q 2200 0 0x71 -- 0,113 # q
+r 2200 0 0x72 -- 0,114 # r
+s 2200 0 0x73 -- 0,115 # s
+t 2200 0 0x74 -- 0,116 # t
+u 2200 0 0x75 -- 0,117 # u
+v 2200 0 0x76 -- 0,118 # v
+w 2200 0 0x77 -- 0,119 # w
+x 2200 0 0x78 -- 0,120 # x
+y 2200 0 0x79 -- 0,121 # y
+z 2200 0 0x7a -- 0,122 # z
+lC 2200 0 0x7b -- 0,123 # braceleft
+{ 2200 0 0x7b -- 0,123 # "
+| 2200 0 0x7c -- 0,124 # "
+rC 2200 0 0x7d -- 0,125 # braceright
+} 2200 0 0x7d -- 0,125 # "
+a~ 2200 0 0x7e -- 0,126 # tilde
+~ 2200 0 0x7e -- 0,126 # "
+char161 2200 0 0xad -- 4,7 # exclamdown
+char162 2200 0 0x9b -- 4,19 # cent
+char163 2200 0 0x9c -- 4,11 # sterling
+char165 2200 0 0x9d -- 4,12 # yen
+char166 2200 0 0x7c -- 0,124 # brokenbar
+char167 2200 0 0x15 -- 4,6 # section
+char170 2200 0 0xa6 -- 4,15 # ordfeminine
+char171 2200 0 0xae -- 4,9 # guillemotleft
+char172 2200 0 0xaa -- 6,20 # logicalnot
+char175 2200 0 0x2d -- 6,0 # macron
+char176 2200 0 0xf8 -- 6,36 # degree
+char177 2200 0 0xf1 -- 6,1 # plusminus
+char178 2200 0 0xfd -- 4,20 # twosuperior
+char181 2200 0 0xe6 -- 8,25 # mu
+char182 2200 0 0x14 -- 4,5 # paragraph
+char183 2200 0 0xfa -- 6,32 # periodcentered
+char186 2200 0 0xa7 -- 4,16 # ordmasculine
+char187 2200 0 0xaf -- 4,10 # guillemotright
+char188 2200 0 0xac -- 4,18 # onequarter
+char189 2200 0 0xab -- 4,17 # onehalf
+char191 2200 0 0xa8 -- 4,8 # questiondown
+char195 2200 0 0x28e -- 1,76 # Atilde
+char196 2200 0 0x8e -- 1,30 # Adieresis
+char197 2200 0 0x8f -- 1,34 # Aring
+char198 2200 0 0x92 -- 1,36 # AE
+char199 2200 0 0x80 -- 1,38 # Ccedilla
+char201 2200 0 0x90 -- 1,40 # Eacute
+char209 2200 0 0xa5 -- 1,56 # Ntilde
+char214 2200 0 0x99 -- 1,62 # Odieresis
+char220 2200 0 0x9a -- 1,70 # Udieresis
+char224 2200 0 0x85 -- 1,33 # agrave
+char225 2200 0 0xa0 -- 1,27 # aacute
+char226 2200 0 0x83 -- 1,29 # acircumflex
+char227 2200 0 0x284 -- 1,93 # atilde
+char228 2200 0 0x84 -- 1,31 # adieresis
+char229 2200 0 0x86 -- 1,35 # aring
+char230 2200 0 0x91 -- 1,37 # ae
+char231 2200 0 0x87 -- 1,39 # ccedilla
+char232 2200 0 0x8a -- 1,47 # egrave
+char233 2200 0 0x82 -- 1,41 # eacute
+char234 2200 0 0x88 -- 1,43 # ecircumflex
+char235 2200 0 0x89 -- 1,45 # edieresis
+char236 2200 0 0x8d -- 1,55 # igrave
+char237 2200 0 0xa1 -- 1,49 # iacute
+char238 2200 0 0x8c -- 1,51 # icircumflex
+char239 2200 0 0x8b -- 1,53 # idieresis
+char241 2200 0 0xa4 -- 1,57 # ntilde
+char242 2200 0 0x95 -- 1,65 # ograve
+char243 2200 0 0xa2 -- 1,59 # oacute
+char244 2200 0 0x93 -- 1,61 # ocircumflex
+char246 2200 0 0x94 -- 1,63 # odieresis
+char247 2200 0 0xf6 -- 6,8 # divide
+char249 2200 0 0x97 -- 1,73 # ugrave
+char250 2200 0 0xa3 -- 1,67 # uacute
+char251 2200 0 0x96 -- 1,69 # ucircumflex
+char252 2200 0 0x81 -- 1,71 # udieresis
+char255 2200 0 0x98 -- 1,75 # ydieresis
+AE 2200 0 0x92 -- 1,36 # AE
+ae 2200 0 0x91 -- 1,37 # ae
+'E 2200 0 0x90 -- 1,40 # Eacute
+'a 2200 0 0xa0 -- 1,27 # aacute
+'e 2200 0 0x82 -- 1,41 # eacute
+'i 2200 0 0xa1 -- 1,49 # iacute
+'o 2200 0 0xa2 -- 1,59 # oacute
+'u 2200 0 0x95 -- 1,65 # uacute
+:A 2200 0 0x8e -- 1,30 # Adieresis
+:O 2200 0 0x99 -- 1,62 # Odieresis
+:U 2200 0 0x9a -- 1,70 # Udieresis
+:a 2200 0 0x84 -- 1,31 # adieresis
+:e 2200 0 0x89 -- 1,45 # edieresis
+:i 2200 0 0x8b -- 1,53 # idieresis
+:o 2200 0 0x94 -- 1,63 # odieresis
+:u 2200 0 0x81 -- 1,71 # udieresis
+:y 2200 0 0x98 -- 1,75 # ydieresis
+^a 2200 0 0x83 -- 1,29 # acircumflex
+^e 2200 0 0x88 -- 1,43 # ecircumflex
+^i 2200 0 0x8c -- 1,51 # icircumflex
+^o 2200 0 0x93 -- 1,61 # ocircumflex
+^u 2200 0 0x96 -- 1,69 # ucircumflex
+`a 2200 0 0x85 -- 1,33 # agrave
+`e 2200 0 0x8a -- 1,47 # egrave
+`i 2200 0 0x8d -- 1,55 # igrave
+`o 2200 0 0x95 -- 1,65 # ograve
+`u 2200 0 0x97 -- 1,73 # ugrave
+~A 2200 0 0x28e -- 1,26 # Atilde
+~N 2200 0 0xa5 -- 1,56 # Ntilde
+~a 2200 0 0x284 -- --- # atilde
+~n 2200 0 0xa4 -- 1,57 # ntilde
+,C 2200 0 0x80 -- 1,38 # Ccedilla
+,c 2200 0 0x87 -- 1,39 # ccedilla
+oA 2200 0 0x8f -- 1,34 # Aring
+oa 2200 0 0x86 -- 1,35 # aring
+a^ 2200 0 0x5e -- 1,3 # circumflex "circumflex accent"
+a~ 2200 0 0x7e -- 1,2 # tilde "tilde accent"
+Do 2200 0 0x24 -- 0,36 # dollar
+Po 2200 0 0x9c -- 4,11 # sterling
+Ye 2200 0 0x9d -- 4,12 # yen
+Fn 2200 0 0x9f -- 4,14 # florin
+ct 2200 0 0x9b -- 4,19 # cent
+Fo 2200 0 0xae -- 4,9 # guillemotleft
+r! 2200 0 0xad -- 4,7 # exclamdown
+r? 2200 0 0xa8 -- 4,8 # questiondown
+Of 2200 0 0xa6 -- 4,15 # ordfeminine
+Om 2200 0 0xa7 -- 4,16 # ordmasculine
+S2 2200 0 0xfd -- 4,20 # twosuperior
+<- 2200 0 0x1b -- 6,22 # arrowleft
+-> 2200 0 0x1a -- 6,21 # arrowright
+<> 2200 0 0x1d -- 6,25 # arrowboth "horizontal double-headed arrow"
+da 2200 0 0x19 -- 6,24 # arrowdown
+ua 2200 0 0x18 -- 6,23 # arrowup
+va 2200 0 0x12 -- 6,26 # \& "vertical double-headed arrow"
+ba 2200 0 0xb3 -- 3,9 # bar
+bb 2200 0 0x7c -- 0,124 # brokenbar
+ul 2200 0 0x5f -- 0,95 # ul "underline with traditional troff metrics"
+ci 2200 0 0x9 -- 4,1 # circle
+bu 2200 0 0x7 -- 4,0 # bullet
+ps 2200 0 0x14 -- 4,5 # paragraph
+sc 2200 0 0x15 -- 4,6 # section
+de 2200 0 0xf8 -- 6,36 # degree
+12 2200 0 0xab -- 4,17 # onehalf
+14 2200 0 0xac -- 4,18 # onequarter
+hy 2200 0 0x2d -- 6,0 # hyphen
+lB 2200 0 0x5b -- 0,91 # bracketleft
+rB 2200 0 0x5d -- 0,93 # bracketright
+lC 2200 0 0x7b -- 0,123 # braceleft
+rC 2200 0 0x7d -- 0,125 # braceright
+aq 2200 0 0x27 -- 0,39 # quotesingle "apostrophe quote"
+at 2200 0 0x40 -- 0,64 # at
+.C1 2200 0 0x2d -- 0,45 # - minus "minus sign from current font"
+sh 2200 0 0x23 -- 0,35 # numbersign
+sl 2200 0 0x2f -- 0,47 # slash
+rs 2200 0 0x5c -- 0,92 # backslash
+*a 2200 0 0xe0 -- 8,1 # alpha
+*b 2200 0 0xe1 -- 8,3 # beta
+*d 2200 0 0xeb -- 8,9 # delta
+*h 2200 0 0xe9 -- 8,17 # theta
+*m 2200 0 0xe6 -- 8,25 # mu
+*p 2200 0 0xe3 -- 8,33 # pi
+*s 2200 0 0xe5 -- 8,37 # sigma
+*t 2200 0 0xe7 -- 8,41 # tau
+~~ 2200 0 0xf7 -- 6,13 # approxequal
+~= 2200 0 0xf7 -- 6,13 # approxequal
++- 2200 0 0xf1 -- 6,1 # plusminus
+<= 2200 0 0xf3 -- 6,2 # lessequal
+ca 2200 0 0xef -- 6,16 # intersection "intersection, cap"
+-h 2200 0 0xc4 -- 3,8 # hbar
+CL 2200 0 0x5 -- 5,168 # club "club suit"
+SP 2200 0 0x6 -- 5,171 # spade "spade suit"
+HE 2200 0 0x3 -- 5,170 # heart "heart suit"
+DI 2200 0 0x4 -- 5,169 # diamond "diamond suit"
+<< 2200 0 0xae -- 6,77 # "" "much less"
+>> 2200 0 0xaf -- 6,78 # "" "much greater"
+pc 2200 0 0xfa -- 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/DESC.in b/contrib/groff/font/devlbp/DESC.in
new file mode 100644
index 0000000..eb5d6f2
--- /dev/null
+++ b/contrib/groff/font/devlbp/DESC.in
@@ -0,0 +1,9 @@
+res 300
+unitwidth 800
+family T
+styles R I B BI
+sizes 1-1000 0
+fonts 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+tcommand
+orientation portrait
+postpro grolbp
diff --git a/contrib/groff/font/devlbp/EB b/contrib/groff/font/devlbp/EB
new file mode 100644
index 0000000..50c6f71
--- /dev/null
+++ b/contrib/groff/font/devlbp/EB
@@ -0,0 +1,272 @@
+
+name EB
+lbpname NeliteB
+spacewidth 1900
+slant 0
+charset
+aq 1900 0 0x27 -- 0,39 # quotesingle
+space 1900 0 0x20 -- 0,32
+! 1900 0 0x21 -- 0,33 # exclam
+" 1900 0 0x22 -- 0,34 # quotedbl
+dq 1900 0 0x22 -- 0,34 # quotedbl
+# 1900 0 0x23 -- 0,35 # numbersign
+sh 1900 0 0x23 -- 0,35 # "
+$ 1900 0 0x24 -- 0,36 # dollar
+Do 1900 0 0x24 -- 0,36 # "
+% 1900 0 0x25 -- 0,37 # percent
+& 1900 0 0x26 -- 0,38 # ampersand
+' 1900 0 0x27 -- 0,39 # quoteright
+cq 1900 0 0x27 -- 0,39 # quoteright
+( 1900 0 0x28 -- 0,40 # parenleft
+) 1900 0 0x29 -- 0,41 # parenright
+* 1900 0 0x2a -- 0,42 # asterisk
++ 1900 0 0x2b -- 0,43 # plus
+, 1900 0 0x2c -- 0,44 # comma
+- 1900 0 0x2d -- 0,45 # hyphen
+\- 1900 0 0x2d -- 0,45 # hyphen
+hy 1900 0 0x2d -- 0,45 # "
+char173 1900 0 0x2d -- 0,45 # "
+. 1900 0 0x2e -- 0,46 # period
+/ 1900 0 0x2f -- 0,47 # slash
+sl 1900 0 0x2f -- 0,47 # "
+0 1900 0 0x30 -- 0,48 # zero
+1 1900 0 0x31 -- 0,49 # one
+2 1900 0 0x32 -- 0,50 # two
+3 1900 0 0x33 -- 0,51 # three
+4 1900 0 0x34 -- 0,52 # four
+5 1900 0 0x35 -- 0,53 # five
+6 1900 0 0x36 -- 0,54 # six
+7 1900 0 0x37 -- 0,55 # seven
+8 1900 0 0x38 -- 0,56 # eight
+9 1900 0 0x39 -- 0,57 # nine
+: 1900 0 0x3a -- 0,58 # colon
+; 1900 0 0x3b -- 0,59 # semicolon
+< 1900 0 0x3c -- 0,60 # less
+= 1900 0 0x3d -- 0,61 # equal
+> 1900 0 0x3e -- 0,62 # greater
+? 1900 0 0x3f -- 0,63 # question
+@ 1900 0 0x40 -- 0,64 # at
+at 1900 0 0x40 -- 0,64 # "
+A 1900 0 0x41 -- 0,65 # A
+B 1900 0 0x42 -- 0,66 # B
+C 1900 0 0x43 -- 0,67 # C
+D 1900 0 0x44 -- 0,68 # D
+E 1900 0 0x45 -- 0,69 # E
+F 1900 0 0x46 -- 0,70 # F
+G 1900 0 0x47 -- 0,71 # G
+H 1900 0 0x48 -- 0,72 # H
+I 1900 0 0x49 -- 0,73 # I
+J 1900 0 0x4a -- 0,74 # J
+K 1900 0 0x4b -- 0,75 # K
+L 1900 0 0x4c -- 0,76 # L
+M 1900 0 0x4d -- 0,77 # M
+N 1900 0 0x4e -- 0,78 # N
+O 1900 0 0x4f -- 0,79 # O
+P 1900 0 0x50 -- 0,80 # P
+Q 1900 0 0x51 -- 0,81 # Q
+R 1900 0 0x52 -- 0,82 # R
+S 1900 0 0x53 -- 0,83 # S
+T 1900 0 0x54 -- 0,84 # T
+U 1900 0 0x55 -- 0,85 # U
+V 1900 0 0x56 -- 0,86 # V
+W 1900 0 0x57 -- 0,87 # W
+X 1900 0 0x58 -- 0,88 # X
+Y 1900 0 0x59 -- 0,89 # Y
+Z 1900 0 0x5a -- 0,90 # Z
+[ 1900 0 0x5b -- 0,91 # bracketleft
+lB 1900 0 0x5b -- 0,91 # "
+\ 1900 0 0x5c -- 0,92 # backslash
+rs 1900 0 0x5c -- 0,92 # "
+] 1900 0 0x5d -- 0,93 # bracketright
+rB 1900 0 0x5d -- 0,93 # "
+a^ 1900 0 0x5e -- 0,94 # circumflex
+^ 1900 0 0x5e -- 0,94 # "
+_ 1900 0 0x5f -- 0,95 # underscore
+` 1900 0 0x60 -- 0,96 # quoteleft
+oq 1900 0 0x60 -- 0,96 # "
+a 1900 0 0x61 -- 0,97 # a
+b 1900 0 0x62 -- 0,98 # b
+c 1900 0 0x63 -- 0,99 # c
+d 1900 0 0x64 -- 0,100 # d
+e 1900 0 0x65 -- 0,101 # e
+f 1900 0 0x66 -- 0,102 # f
+g 1900 0 0x67 -- 0,103 # g
+h 1900 0 0x68 -- 0,104 # h
+i 1900 0 0x69 -- 0,105 # i
+j 1900 0 0x6a -- 0,106 # j
+k 1900 0 0x6b -- 0,107 # k
+l 1900 0 0x6c -- 0,108 # l
+m 1900 0 0x6d -- 0,109 # m
+n 1900 0 0x6e -- 0,110 # n
+o 1900 0 0x6f -- 0,111 # o
+p 1900 0 0x70 -- 0,112 # p
+q 1900 0 0x71 -- 0,113 # q
+r 1900 0 0x72 -- 0,114 # r
+s 1900 0 0x73 -- 0,115 # s
+t 1900 0 0x74 -- 0,116 # t
+u 1900 0 0x75 -- 0,117 # u
+v 1900 0 0x76 -- 0,118 # v
+w 1900 0 0x77 -- 0,119 # w
+x 1900 0 0x78 -- 0,120 # x
+y 1900 0 0x79 -- 0,121 # y
+z 1900 0 0x7a -- 0,122 # z
+lC 1900 0 0x7b -- 0,123 # braceleft
+{ 1900 0 0x7b -- 0,123 # "
+| 1900 0 0x7c -- 0,124 # "
+rC 1900 0 0x7d -- 0,125 # braceright
+} 1900 0 0x7d -- 0,125 # "
+a~ 1900 0 0x7e -- 0,126 # tilde
+~ 1900 0 0x7e -- 0,126 # "
+char161 1900 0 0xad -- 4,7 # exclamdown
+char162 1900 0 0x9b -- 4,19 # cent
+char163 1900 0 0x9c -- 4,11 # sterling
+char165 1900 0 0x9d -- 4,12 # yen
+char166 1900 0 0x7c -- 0,124 # brokenbar
+char167 1900 0 0x15 -- 4,6 # section
+char170 1900 0 0xa6 -- 4,15 # ordfeminine
+char171 1900 0 0xae -- 4,9 # guillemotleft
+char172 1900 0 0xaa -- 6,20 # logicalnot
+char175 1900 0 0x2d -- 6,0 # macron
+char176 1900 0 0xf8 -- 6,36 # degree
+char177 1900 0 0xf1 -- 6,1 # plusminus
+char178 1900 0 0xfd -- 4,20 # twosuperior
+char181 1900 0 0xe6 -- 8,25 # mu
+char182 1900 0 0x14 -- 4,5 # paragraph
+char183 1900 0 0xfa -- 6,32 # periodcentered
+char186 1900 0 0xa7 -- 4,16 # ordmasculine
+char187 1900 0 0xaf -- 4,10 # guillemotright
+char188 1900 0 0xac -- 4,18 # onequarter
+char189 1900 0 0xab -- 4,17 # onehalf
+char191 1900 0 0xa8 -- 4,8 # questiondown
+char195 1900 0 0x28e -- 1,76 # Atilde
+char196 1900 0 0x8e -- 1,30 # Adieresis
+char197 1900 0 0x8f -- 1,34 # Aring
+char198 1900 0 0x92 -- 1,36 # AE
+char199 1900 0 0x80 -- 1,38 # Ccedilla
+char201 1900 0 0x90 -- 1,40 # Eacute
+char209 1900 0 0xa5 -- 1,56 # Ntilde
+char214 1900 0 0x99 -- 1,62 # Odieresis
+char220 1900 0 0x9a -- 1,70 # Udieresis
+char224 1900 0 0x85 -- 1,33 # agrave
+char225 1900 0 0xa0 -- 1,27 # aacute
+char226 1900 0 0x83 -- 1,29 # acircumflex
+char227 1900 0 0x284 -- 1,93 # atilde
+char228 1900 0 0x84 -- 1,31 # adieresis
+char229 1900 0 0x86 -- 1,35 # aring
+char230 1900 0 0x91 -- 1,37 # ae
+char231 1900 0 0x87 -- 1,39 # ccedilla
+char232 1900 0 0x8a -- 1,47 # egrave
+char233 1900 0 0x82 -- 1,41 # eacute
+char234 1900 0 0x88 -- 1,43 # ecircumflex
+char235 1900 0 0x89 -- 1,45 # edieresis
+char236 1900 0 0x8d -- 1,55 # igrave
+char237 1900 0 0xa1 -- 1,49 # iacute
+char238 1900 0 0x8c -- 1,51 # icircumflex
+char239 1900 0 0x8b -- 1,53 # idieresis
+char241 1900 0 0xa4 -- 1,57 # ntilde
+char242 1900 0 0x95 -- 1,65 # ograve
+char243 1900 0 0xa2 -- 1,59 # oacute
+char244 1900 0 0x93 -- 1,61 # ocircumflex
+char246 1900 0 0x94 -- 1,63 # odieresis
+char247 1900 0 0xf6 -- 6,8 # divide
+char249 1900 0 0x97 -- 1,73 # ugrave
+char250 1900 0 0xa3 -- 1,67 # uacute
+char251 1900 0 0x96 -- 1,69 # ucircumflex
+char252 1900 0 0x81 -- 1,71 # udieresis
+char255 1900 0 0x98 -- 1,75 # ydieresis
+AE 1900 0 0x92 -- 1,36 # AE
+ae 1900 0 0x91 -- 1,37 # ae
+'E 1900 0 0x90 -- 1,40 # Eacute
+'a 1900 0 0xa0 -- 1,27 # aacute
+'e 1900 0 0x82 -- 1,41 # eacute
+'i 1900 0 0xa1 -- 1,49 # iacute
+'o 1900 0 0xa2 -- 1,59 # oacute
+'u 1900 0 0x95 -- 1,65 # uacute
+:A 1900 0 0x8e -- 1,30 # Adieresis
+:O 1900 0 0x99 -- 1,62 # Odieresis
+:U 1900 0 0x9a -- 1,70 # Udieresis
+:a 1900 0 0x84 -- 1,31 # adieresis
+:e 1900 0 0x89 -- 1,45 # edieresis
+:i 1900 0 0x8b -- 1,53 # idieresis
+:o 1900 0 0x94 -- 1,63 # odieresis
+:u 1900 0 0x81 -- 1,71 # udieresis
+:y 1900 0 0x98 -- 1,75 # ydieresis
+^a 1900 0 0x83 -- 1,29 # acircumflex
+^e 1900 0 0x88 -- 1,43 # ecircumflex
+^i 1900 0 0x8c -- 1,51 # icircumflex
+^o 1900 0 0x93 -- 1,61 # ocircumflex
+^u 1900 0 0x96 -- 1,69 # ucircumflex
+`a 1900 0 0x85 -- 1,33 # agrave
+`e 1900 0 0x8a -- 1,47 # egrave
+`i 1900 0 0x8d -- 1,55 # igrave
+`o 1900 0 0x95 -- 1,65 # ograve
+`u 1900 0 0x97 -- 1,73 # ugrave
+~A 1900 0 0x28e -- 1,26 # Atilde
+~N 1900 0 0xa5 -- 1,56 # Ntilde
+~a 1900 0 0x284 -- --- # atilde
+~n 1900 0 0xa4 -- 1,57 # ntilde
+,C 1900 0 0x80 -- 1,38 # Ccedilla
+,c 1900 0 0x87 -- 1,39 # ccedilla
+oA 1900 0 0x8f -- 1,34 # Aring
+oa 1900 0 0x86 -- 1,35 # aring
+a^ 1900 0 0x5e -- 1,3 # circumflex "circumflex accent"
+a~ 1900 0 0x7e -- 1,2 # tilde "tilde accent"
+Do 1900 0 0x24 -- 0,36 # dollar
+Po 1900 0 0x9c -- 4,11 # sterling
+Ye 1900 0 0x9d -- 4,12 # yen
+Fn 1900 0 0x9f -- 4,14 # florin
+ct 1900 0 0x9b -- 4,19 # cent
+Fo 1900 0 0xae -- 4,9 # guillemotleft
+r! 1900 0 0xad -- 4,7 # exclamdown
+r? 1900 0 0xa8 -- 4,8 # questiondown
+Of 1900 0 0xa6 -- 4,15 # ordfeminine
+Om 1900 0 0xa7 -- 4,16 # ordmasculine
+S2 1900 0 0xfd -- 4,20 # twosuperior
+<- 1900 0 0x1b -- 6,22 # arrowleft
+-> 1900 0 0x1a -- 6,21 # arrowright
+<> 1900 0 0x1d -- 6,25 # arrowboth "horizontal double-headed arrow"
+da 1900 0 0x19 -- 6,24 # arrowdown
+ua 1900 0 0x18 -- 6,23 # arrowup
+va 1900 0 0x12 -- 6,26 # \& "vertical double-headed arrow"
+ba 1900 0 0xb3 -- 3,9 # bar
+bb 1900 0 0x7c -- 0,124 # brokenbar
+ul 1900 0 0x5f -- 0,95 # ul "underline with traditional troff metrics"
+ci 1900 0 0x9 -- 4,1 # circle
+bu 1900 0 0x7 -- 4,0 # bullet
+ps 1900 0 0x14 -- 4,5 # paragraph
+sc 1900 0 0x15 -- 4,6 # section
+de 1900 0 0xf8 -- 6,36 # degree
+12 1900 0 0xab -- 4,17 # onehalf
+14 1900 0 0xac -- 4,18 # onequarter
+hy 1900 0 0x2d -- 6,0 # hyphen
+lB 1900 0 0x5b -- 0,91 # bracketleft
+rB 1900 0 0x5d -- 0,93 # bracketright
+lC 1900 0 0x7b -- 0,123 # braceleft
+rC 1900 0 0x7d -- 0,125 # braceright
+aq 1900 0 0x27 -- 0,39 # quotesingle "apostrophe quote"
+at 1900 0 0x40 -- 0,64 # at
+.C1 1900 0 0x2d -- 0,45 # - minus "minus sign from current font"
+sh 1900 0 0x23 -- 0,35 # numbersign
+sl 1900 0 0x2f -- 0,47 # slash
+rs 1900 0 0x5c -- 0,92 # backslash
+*a 1900 0 0xe0 -- 8,1 # alpha
+*b 1900 0 0xe1 -- 8,3 # beta
+*d 1900 0 0xeb -- 8,9 # delta
+*h 1900 0 0xe9 -- 8,17 # theta
+*m 1900 0 0xe6 -- 8,25 # mu
+*p 1900 0 0xe3 -- 8,33 # pi
+*s 1900 0 0xe5 -- 8,37 # sigma
+*t 1900 0 0xe7 -- 8,41 # tau
+~~ 1900 0 0xf7 -- 6,13 # approxequal
+~= 1900 0 0xf7 -- 6,13 # approxequal
++- 1900 0 0xf1 -- 6,1 # plusminus
+<= 1900 0 0xf3 -- 6,2 # lessequal
+ca 1900 0 0xef -- 6,16 # intersection "intersection, cap"
+-h 1900 0 0xc4 -- 3,8 # hbar
+CL 1900 0 0x5 -- 5,168 # club "club suit"
+SP 1900 0 0x6 -- 5,171 # spade "spade suit"
+HE 1900 0 0x3 -- 5,170 # heart "heart suit"
+DI 1900 0 0x4 -- 5,169 # diamond "diamond suit"
+<< 1900 0 0xae -- 6,77 # "" "much less"
+>> 1900 0 0xaf -- 6,78 # "" "much greater"
+pc 1900 0 0xfa -- 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/EI b/contrib/groff/font/devlbp/EI
new file mode 100644
index 0000000..364cea6
--- /dev/null
+++ b/contrib/groff/font/devlbp/EI
@@ -0,0 +1,272 @@
+
+name EI
+lbpname NeliteI
+spacewidth 1900
+slant 0
+charset
+aq 1900 0 0x27 -- 0,39 # quotesingle
+space 1900 0 0x20 -- 0,32
+! 1900 0 0x21 -- 0,33 # exclam
+" 1900 0 0x22 -- 0,34 # quotedbl
+dq 1900 0 0x22 -- 0,34 # quotedbl
+# 1900 0 0x23 -- 0,35 # numbersign
+sh 1900 0 0x23 -- 0,35 # "
+$ 1900 0 0x24 -- 0,36 # dollar
+Do 1900 0 0x24 -- 0,36 # "
+% 1900 0 0x25 -- 0,37 # percent
+& 1900 0 0x26 -- 0,38 # ampersand
+' 1900 0 0x27 -- 0,39 # quoteright
+cq 1900 0 0x27 -- 0,39 # quoteright
+( 1900 0 0x28 -- 0,40 # parenleft
+) 1900 0 0x29 -- 0,41 # parenright
+* 1900 0 0x2a -- 0,42 # asterisk
++ 1900 0 0x2b -- 0,43 # plus
+, 1900 0 0x2c -- 0,44 # comma
+- 1900 0 0x2d -- 0,45 # hyphen
+\- 1900 0 0x2d -- 0,45 # hyphen
+hy 1900 0 0x2d -- 0,45 # "
+char173 1900 0 0x2d -- 0,45 # "
+. 1900 0 0x2e -- 0,46 # period
+/ 1900 0 0x2f -- 0,47 # slash
+sl 1900 0 0x2f -- 0,47 # "
+0 1900 0 0x30 -- 0,48 # zero
+1 1900 0 0x31 -- 0,49 # one
+2 1900 0 0x32 -- 0,50 # two
+3 1900 0 0x33 -- 0,51 # three
+4 1900 0 0x34 -- 0,52 # four
+5 1900 0 0x35 -- 0,53 # five
+6 1900 0 0x36 -- 0,54 # six
+7 1900 0 0x37 -- 0,55 # seven
+8 1900 0 0x38 -- 0,56 # eight
+9 1900 0 0x39 -- 0,57 # nine
+: 1900 0 0x3a -- 0,58 # colon
+; 1900 0 0x3b -- 0,59 # semicolon
+< 1900 0 0x3c -- 0,60 # less
+= 1900 0 0x3d -- 0,61 # equal
+> 1900 0 0x3e -- 0,62 # greater
+? 1900 0 0x3f -- 0,63 # question
+@ 1900 0 0x40 -- 0,64 # at
+at 1900 0 0x40 -- 0,64 # "
+A 1900 0 0x41 -- 0,65 # A
+B 1900 0 0x42 -- 0,66 # B
+C 1900 0 0x43 -- 0,67 # C
+D 1900 0 0x44 -- 0,68 # D
+E 1900 0 0x45 -- 0,69 # E
+F 1900 0 0x46 -- 0,70 # F
+G 1900 0 0x47 -- 0,71 # G
+H 1900 0 0x48 -- 0,72 # H
+I 1900 0 0x49 -- 0,73 # I
+J 1900 0 0x4a -- 0,74 # J
+K 1900 0 0x4b -- 0,75 # K
+L 1900 0 0x4c -- 0,76 # L
+M 1900 0 0x4d -- 0,77 # M
+N 1900 0 0x4e -- 0,78 # N
+O 1900 0 0x4f -- 0,79 # O
+P 1900 0 0x50 -- 0,80 # P
+Q 1900 0 0x51 -- 0,81 # Q
+R 1900 0 0x52 -- 0,82 # R
+S 1900 0 0x53 -- 0,83 # S
+T 1900 0 0x54 -- 0,84 # T
+U 1900 0 0x55 -- 0,85 # U
+V 1900 0 0x56 -- 0,86 # V
+W 1900 0 0x57 -- 0,87 # W
+X 1900 0 0x58 -- 0,88 # X
+Y 1900 0 0x59 -- 0,89 # Y
+Z 1900 0 0x5a -- 0,90 # Z
+[ 1900 0 0x5b -- 0,91 # bracketleft
+lB 1900 0 0x5b -- 0,91 # "
+\ 1900 0 0x5c -- 0,92 # backslash
+rs 1900 0 0x5c -- 0,92 # "
+] 1900 0 0x5d -- 0,93 # bracketright
+rB 1900 0 0x5d -- 0,93 # "
+a^ 1900 0 0x5e -- 0,94 # circumflex
+^ 1900 0 0x5e -- 0,94 # "
+_ 1900 0 0x5f -- 0,95 # underscore
+` 1900 0 0x60 -- 0,96 # quoteleft
+oq 1900 0 0x60 -- 0,96 # "
+a 1900 0 0x61 -- 0,97 # a
+b 1900 0 0x62 -- 0,98 # b
+c 1900 0 0x63 -- 0,99 # c
+d 1900 0 0x64 -- 0,100 # d
+e 1900 0 0x65 -- 0,101 # e
+f 1900 0 0x66 -- 0,102 # f
+g 1900 0 0x67 -- 0,103 # g
+h 1900 0 0x68 -- 0,104 # h
+i 1900 0 0x69 -- 0,105 # i
+j 1900 0 0x6a -- 0,106 # j
+k 1900 0 0x6b -- 0,107 # k
+l 1900 0 0x6c -- 0,108 # l
+m 1900 0 0x6d -- 0,109 # m
+n 1900 0 0x6e -- 0,110 # n
+o 1900 0 0x6f -- 0,111 # o
+p 1900 0 0x70 -- 0,112 # p
+q 1900 0 0x71 -- 0,113 # q
+r 1900 0 0x72 -- 0,114 # r
+s 1900 0 0x73 -- 0,115 # s
+t 1900 0 0x74 -- 0,116 # t
+u 1900 0 0x75 -- 0,117 # u
+v 1900 0 0x76 -- 0,118 # v
+w 1900 0 0x77 -- 0,119 # w
+x 1900 0 0x78 -- 0,120 # x
+y 1900 0 0x79 -- 0,121 # y
+z 1900 0 0x7a -- 0,122 # z
+lC 1900 0 0x7b -- 0,123 # braceleft
+{ 1900 0 0x7b -- 0,123 # "
+| 1900 0 0x7c -- 0,124 # "
+rC 1900 0 0x7d -- 0,125 # braceright
+} 1900 0 0x7d -- 0,125 # "
+a~ 1900 0 0x7e -- 0,126 # tilde
+~ 1900 0 0x7e -- 0,126 # "
+char161 1900 0 0xad -- 4,7 # exclamdown
+char162 1900 0 0x9b -- 4,19 # cent
+char163 1900 0 0x9c -- 4,11 # sterling
+char165 1900 0 0x9d -- 4,12 # yen
+char166 1900 0 0x7c -- 0,124 # brokenbar
+char167 1900 0 0x15 -- 4,6 # section
+char170 1900 0 0xa6 -- 4,15 # ordfeminine
+char171 1900 0 0xae -- 4,9 # guillemotleft
+char172 1900 0 0xaa -- 6,20 # logicalnot
+char175 1900 0 0x2d -- 6,0 # macron
+char176 1900 0 0xf8 -- 6,36 # degree
+char177 1900 0 0xf1 -- 6,1 # plusminus
+char178 1900 0 0xfd -- 4,20 # twosuperior
+char181 1900 0 0xe6 -- 8,25 # mu
+char182 1900 0 0x14 -- 4,5 # paragraph
+char183 1900 0 0xfa -- 6,32 # periodcentered
+char186 1900 0 0xa7 -- 4,16 # ordmasculine
+char187 1900 0 0xaf -- 4,10 # guillemotright
+char188 1900 0 0xac -- 4,18 # onequarter
+char189 1900 0 0xab -- 4,17 # onehalf
+char191 1900 0 0xa8 -- 4,8 # questiondown
+char195 1900 0 0x28e -- 1,76 # Atilde
+char196 1900 0 0x8e -- 1,30 # Adieresis
+char197 1900 0 0x8f -- 1,34 # Aring
+char198 1900 0 0x92 -- 1,36 # AE
+char199 1900 0 0x80 -- 1,38 # Ccedilla
+char201 1900 0 0x90 -- 1,40 # Eacute
+char209 1900 0 0xa5 -- 1,56 # Ntilde
+char214 1900 0 0x99 -- 1,62 # Odieresis
+char220 1900 0 0x9a -- 1,70 # Udieresis
+char224 1900 0 0x85 -- 1,33 # agrave
+char225 1900 0 0xa0 -- 1,27 # aacute
+char226 1900 0 0x83 -- 1,29 # acircumflex
+char227 1900 0 0x284 -- 1,93 # atilde
+char228 1900 0 0x84 -- 1,31 # adieresis
+char229 1900 0 0x86 -- 1,35 # aring
+char230 1900 0 0x91 -- 1,37 # ae
+char231 1900 0 0x87 -- 1,39 # ccedilla
+char232 1900 0 0x8a -- 1,47 # egrave
+char233 1900 0 0x82 -- 1,41 # eacute
+char234 1900 0 0x88 -- 1,43 # ecircumflex
+char235 1900 0 0x89 -- 1,45 # edieresis
+char236 1900 0 0x8d -- 1,55 # igrave
+char237 1900 0 0xa1 -- 1,49 # iacute
+char238 1900 0 0x8c -- 1,51 # icircumflex
+char239 1900 0 0x8b -- 1,53 # idieresis
+char241 1900 0 0xa4 -- 1,57 # ntilde
+char242 1900 0 0x95 -- 1,65 # ograve
+char243 1900 0 0xa2 -- 1,59 # oacute
+char244 1900 0 0x93 -- 1,61 # ocircumflex
+char246 1900 0 0x94 -- 1,63 # odieresis
+char247 1900 0 0xf6 -- 6,8 # divide
+char249 1900 0 0x97 -- 1,73 # ugrave
+char250 1900 0 0xa3 -- 1,67 # uacute
+char251 1900 0 0x96 -- 1,69 # ucircumflex
+char252 1900 0 0x81 -- 1,71 # udieresis
+char255 1900 0 0x98 -- 1,75 # ydieresis
+AE 1900 0 0x92 -- 1,36 # AE
+ae 1900 0 0x91 -- 1,37 # ae
+'E 1900 0 0x90 -- 1,40 # Eacute
+'a 1900 0 0xa0 -- 1,27 # aacute
+'e 1900 0 0x82 -- 1,41 # eacute
+'i 1900 0 0xa1 -- 1,49 # iacute
+'o 1900 0 0xa2 -- 1,59 # oacute
+'u 1900 0 0x95 -- 1,65 # uacute
+:A 1900 0 0x8e -- 1,30 # Adieresis
+:O 1900 0 0x99 -- 1,62 # Odieresis
+:U 1900 0 0x9a -- 1,70 # Udieresis
+:a 1900 0 0x84 -- 1,31 # adieresis
+:e 1900 0 0x89 -- 1,45 # edieresis
+:i 1900 0 0x8b -- 1,53 # idieresis
+:o 1900 0 0x94 -- 1,63 # odieresis
+:u 1900 0 0x81 -- 1,71 # udieresis
+:y 1900 0 0x98 -- 1,75 # ydieresis
+^a 1900 0 0x83 -- 1,29 # acircumflex
+^e 1900 0 0x88 -- 1,43 # ecircumflex
+^i 1900 0 0x8c -- 1,51 # icircumflex
+^o 1900 0 0x93 -- 1,61 # ocircumflex
+^u 1900 0 0x96 -- 1,69 # ucircumflex
+`a 1900 0 0x85 -- 1,33 # agrave
+`e 1900 0 0x8a -- 1,47 # egrave
+`i 1900 0 0x8d -- 1,55 # igrave
+`o 1900 0 0x95 -- 1,65 # ograve
+`u 1900 0 0x97 -- 1,73 # ugrave
+~A 1900 0 0x28e -- 1,26 # Atilde
+~N 1900 0 0xa5 -- 1,56 # Ntilde
+~a 1900 0 0x284 -- --- # atilde
+~n 1900 0 0xa4 -- 1,57 # ntilde
+,C 1900 0 0x80 -- 1,38 # Ccedilla
+,c 1900 0 0x87 -- 1,39 # ccedilla
+oA 1900 0 0x8f -- 1,34 # Aring
+oa 1900 0 0x86 -- 1,35 # aring
+a^ 1900 0 0x5e -- 1,3 # circumflex "circumflex accent"
+a~ 1900 0 0x7e -- 1,2 # tilde "tilde accent"
+Do 1900 0 0x24 -- 0,36 # dollar
+Po 1900 0 0x9c -- 4,11 # sterling
+Ye 1900 0 0x9d -- 4,12 # yen
+Fn 1900 0 0x9f -- 4,14 # florin
+ct 1900 0 0x9b -- 4,19 # cent
+Fo 1900 0 0xae -- 4,9 # guillemotleft
+r! 1900 0 0xad -- 4,7 # exclamdown
+r? 1900 0 0xa8 -- 4,8 # questiondown
+Of 1900 0 0xa6 -- 4,15 # ordfeminine
+Om 1900 0 0xa7 -- 4,16 # ordmasculine
+S2 1900 0 0xfd -- 4,20 # twosuperior
+<- 1900 0 0x1b -- 6,22 # arrowleft
+-> 1900 0 0x1a -- 6,21 # arrowright
+<> 1900 0 0x1d -- 6,25 # arrowboth "horizontal double-headed arrow"
+da 1900 0 0x19 -- 6,24 # arrowdown
+ua 1900 0 0x18 -- 6,23 # arrowup
+va 1900 0 0x12 -- 6,26 # \& "vertical double-headed arrow"
+ba 1900 0 0xb3 -- 3,9 # bar
+bb 1900 0 0x7c -- 0,124 # brokenbar
+ul 1900 0 0x5f -- 0,95 # ul "underline with traditional troff metrics"
+ci 1900 0 0x9 -- 4,1 # circle
+bu 1900 0 0x7 -- 4,0 # bullet
+ps 1900 0 0x14 -- 4,5 # paragraph
+sc 1900 0 0x15 -- 4,6 # section
+de 1900 0 0xf8 -- 6,36 # degree
+12 1900 0 0xab -- 4,17 # onehalf
+14 1900 0 0xac -- 4,18 # onequarter
+hy 1900 0 0x2d -- 6,0 # hyphen
+lB 1900 0 0x5b -- 0,91 # bracketleft
+rB 1900 0 0x5d -- 0,93 # bracketright
+lC 1900 0 0x7b -- 0,123 # braceleft
+rC 1900 0 0x7d -- 0,125 # braceright
+aq 1900 0 0x27 -- 0,39 # quotesingle "apostrophe quote"
+at 1900 0 0x40 -- 0,64 # at
+.C1 1900 0 0x2d -- 0,45 # - minus "minus sign from current font"
+sh 1900 0 0x23 -- 0,35 # numbersign
+sl 1900 0 0x2f -- 0,47 # slash
+rs 1900 0 0x5c -- 0,92 # backslash
+*a 1900 0 0xe0 -- 8,1 # alpha
+*b 1900 0 0xe1 -- 8,3 # beta
+*d 1900 0 0xeb -- 8,9 # delta
+*h 1900 0 0xe9 -- 8,17 # theta
+*m 1900 0 0xe6 -- 8,25 # mu
+*p 1900 0 0xe3 -- 8,33 # pi
+*s 1900 0 0xe5 -- 8,37 # sigma
+*t 1900 0 0xe7 -- 8,41 # tau
+~~ 1900 0 0xf7 -- 6,13 # approxequal
+~= 1900 0 0xf7 -- 6,13 # approxequal
++- 1900 0 0xf1 -- 6,1 # plusminus
+<= 1900 0 0xf3 -- 6,2 # lessequal
+ca 1900 0 0xef -- 6,16 # intersection "intersection, cap"
+-h 1900 0 0xc4 -- 3,8 # hbar
+CL 1900 0 0x5 -- 5,168 # club "club suit"
+SP 1900 0 0x6 -- 5,171 # spade "spade suit"
+HE 1900 0 0x3 -- 5,170 # heart "heart suit"
+DI 1900 0 0x4 -- 5,169 # diamond "diamond suit"
+<< 1900 0 0xae -- 6,77 # "" "much less"
+>> 1900 0 0xaf -- 6,78 # "" "much greater"
+pc 1900 0 0xfa -- 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/ER b/contrib/groff/font/devlbp/ER
new file mode 100644
index 0000000..f2734cc
--- /dev/null
+++ b/contrib/groff/font/devlbp/ER
@@ -0,0 +1,272 @@
+
+name ER
+lbpname NeliteR
+spacewidth 1900
+slant 0
+charset
+aq 1900 0 0x27 -- 0,39 # quotesingle
+space 1900 0 0x20 -- 0,32
+! 1900 0 0x21 -- 0,33 # exclam
+" 1900 0 0x22 -- 0,34 # quotedbl
+dq 1900 0 0x22 -- 0,34 # quotedbl
+# 1900 0 0x23 -- 0,35 # numbersign
+sh 1900 0 0x23 -- 0,35 # "
+$ 1900 0 0x24 -- 0,36 # dollar
+Do 1900 0 0x24 -- 0,36 # "
+% 1900 0 0x25 -- 0,37 # percent
+& 1900 0 0x26 -- 0,38 # ampersand
+' 1900 0 0x27 -- 0,39 # quoteright
+cq 1900 0 0x27 -- 0,39 # quoteright
+( 1900 0 0x28 -- 0,40 # parenleft
+) 1900 0 0x29 -- 0,41 # parenright
+* 1900 0 0x2a -- 0,42 # asterisk
++ 1900 0 0x2b -- 0,43 # plus
+, 1900 0 0x2c -- 0,44 # comma
+- 1900 0 0x2d -- 0,45 # hyphen
+\- 1900 0 0x2d -- 0,45 # hyphen
+hy 1900 0 0x2d -- 0,45 # "
+char173 1900 0 0x2d -- 0,45 # "
+. 1900 0 0x2e -- 0,46 # period
+/ 1900 0 0x2f -- 0,47 # slash
+sl 1900 0 0x2f -- 0,47 # "
+0 1900 0 0x30 -- 0,48 # zero
+1 1900 0 0x31 -- 0,49 # one
+2 1900 0 0x32 -- 0,50 # two
+3 1900 0 0x33 -- 0,51 # three
+4 1900 0 0x34 -- 0,52 # four
+5 1900 0 0x35 -- 0,53 # five
+6 1900 0 0x36 -- 0,54 # six
+7 1900 0 0x37 -- 0,55 # seven
+8 1900 0 0x38 -- 0,56 # eight
+9 1900 0 0x39 -- 0,57 # nine
+: 1900 0 0x3a -- 0,58 # colon
+; 1900 0 0x3b -- 0,59 # semicolon
+< 1900 0 0x3c -- 0,60 # less
+= 1900 0 0x3d -- 0,61 # equal
+> 1900 0 0x3e -- 0,62 # greater
+? 1900 0 0x3f -- 0,63 # question
+@ 1900 0 0x40 -- 0,64 # at
+at 1900 0 0x40 -- 0,64 # "
+A 1900 0 0x41 -- 0,65 # A
+B 1900 0 0x42 -- 0,66 # B
+C 1900 0 0x43 -- 0,67 # C
+D 1900 0 0x44 -- 0,68 # D
+E 1900 0 0x45 -- 0,69 # E
+F 1900 0 0x46 -- 0,70 # F
+G 1900 0 0x47 -- 0,71 # G
+H 1900 0 0x48 -- 0,72 # H
+I 1900 0 0x49 -- 0,73 # I
+J 1900 0 0x4a -- 0,74 # J
+K 1900 0 0x4b -- 0,75 # K
+L 1900 0 0x4c -- 0,76 # L
+M 1900 0 0x4d -- 0,77 # M
+N 1900 0 0x4e -- 0,78 # N
+O 1900 0 0x4f -- 0,79 # O
+P 1900 0 0x50 -- 0,80 # P
+Q 1900 0 0x51 -- 0,81 # Q
+R 1900 0 0x52 -- 0,82 # R
+S 1900 0 0x53 -- 0,83 # S
+T 1900 0 0x54 -- 0,84 # T
+U 1900 0 0x55 -- 0,85 # U
+V 1900 0 0x56 -- 0,86 # V
+W 1900 0 0x57 -- 0,87 # W
+X 1900 0 0x58 -- 0,88 # X
+Y 1900 0 0x59 -- 0,89 # Y
+Z 1900 0 0x5a -- 0,90 # Z
+[ 1900 0 0x5b -- 0,91 # bracketleft
+lB 1900 0 0x5b -- 0,91 # "
+\ 1900 0 0x5c -- 0,92 # backslash
+rs 1900 0 0x5c -- 0,92 # "
+] 1900 0 0x5d -- 0,93 # bracketright
+rB 1900 0 0x5d -- 0,93 # "
+a^ 1900 0 0x5e -- 0,94 # circumflex
+^ 1900 0 0x5e -- 0,94 # "
+_ 1900 0 0x5f -- 0,95 # underscore
+` 1900 0 0x60 -- 0,96 # quoteleft
+oq 1900 0 0x60 -- 0,96 # "
+a 1900 0 0x61 -- 0,97 # a
+b 1900 0 0x62 -- 0,98 # b
+c 1900 0 0x63 -- 0,99 # c
+d 1900 0 0x64 -- 0,100 # d
+e 1900 0 0x65 -- 0,101 # e
+f 1900 0 0x66 -- 0,102 # f
+g 1900 0 0x67 -- 0,103 # g
+h 1900 0 0x68 -- 0,104 # h
+i 1900 0 0x69 -- 0,105 # i
+j 1900 0 0x6a -- 0,106 # j
+k 1900 0 0x6b -- 0,107 # k
+l 1900 0 0x6c -- 0,108 # l
+m 1900 0 0x6d -- 0,109 # m
+n 1900 0 0x6e -- 0,110 # n
+o 1900 0 0x6f -- 0,111 # o
+p 1900 0 0x70 -- 0,112 # p
+q 1900 0 0x71 -- 0,113 # q
+r 1900 0 0x72 -- 0,114 # r
+s 1900 0 0x73 -- 0,115 # s
+t 1900 0 0x74 -- 0,116 # t
+u 1900 0 0x75 -- 0,117 # u
+v 1900 0 0x76 -- 0,118 # v
+w 1900 0 0x77 -- 0,119 # w
+x 1900 0 0x78 -- 0,120 # x
+y 1900 0 0x79 -- 0,121 # y
+z 1900 0 0x7a -- 0,122 # z
+lC 1900 0 0x7b -- 0,123 # braceleft
+{ 1900 0 0x7b -- 0,123 # "
+| 1900 0 0x7c -- 0,124 # "
+rC 1900 0 0x7d -- 0,125 # braceright
+} 1900 0 0x7d -- 0,125 # "
+a~ 1900 0 0x7e -- 0,126 # tilde
+~ 1900 0 0x7e -- 0,126 # "
+char161 1900 0 0xad -- 4,7 # exclamdown
+char162 1900 0 0x9b -- 4,19 # cent
+char163 1900 0 0x9c -- 4,11 # sterling
+char165 1900 0 0x9d -- 4,12 # yen
+char166 1900 0 0x7c -- 0,124 # brokenbar
+char167 1900 0 0x15 -- 4,6 # section
+char170 1900 0 0xa6 -- 4,15 # ordfeminine
+char171 1900 0 0xae -- 4,9 # guillemotleft
+char172 1900 0 0xaa -- 6,20 # logicalnot
+char175 1900 0 0x2d -- 6,0 # macron
+char176 1900 0 0xf8 -- 6,36 # degree
+char177 1900 0 0xf1 -- 6,1 # plusminus
+char178 1900 0 0xfd -- 4,20 # twosuperior
+char181 1900 0 0xe6 -- 8,25 # mu
+char182 1900 0 0x14 -- 4,5 # paragraph
+char183 1900 0 0xfa -- 6,32 # periodcentered
+char186 1900 0 0xa7 -- 4,16 # ordmasculine
+char187 1900 0 0xaf -- 4,10 # guillemotright
+char188 1900 0 0xac -- 4,18 # onequarter
+char189 1900 0 0xab -- 4,17 # onehalf
+char191 1900 0 0xa8 -- 4,8 # questiondown
+char195 1900 0 0x28e -- 1,76 # Atilde
+char196 1900 0 0x8e -- 1,30 # Adieresis
+char197 1900 0 0x8f -- 1,34 # Aring
+char198 1900 0 0x92 -- 1,36 # AE
+char199 1900 0 0x80 -- 1,38 # Ccedilla
+char201 1900 0 0x90 -- 1,40 # Eacute
+char209 1900 0 0xa5 -- 1,56 # Ntilde
+char214 1900 0 0x99 -- 1,62 # Odieresis
+char220 1900 0 0x9a -- 1,70 # Udieresis
+char224 1900 0 0x85 -- 1,33 # agrave
+char225 1900 0 0xa0 -- 1,27 # aacute
+char226 1900 0 0x83 -- 1,29 # acircumflex
+char227 1900 0 0x284 -- 1,93 # atilde
+char228 1900 0 0x84 -- 1,31 # adieresis
+char229 1900 0 0x86 -- 1,35 # aring
+char230 1900 0 0x91 -- 1,37 # ae
+char231 1900 0 0x87 -- 1,39 # ccedilla
+char232 1900 0 0x8a -- 1,47 # egrave
+char233 1900 0 0x82 -- 1,41 # eacute
+char234 1900 0 0x88 -- 1,43 # ecircumflex
+char235 1900 0 0x89 -- 1,45 # edieresis
+char236 1900 0 0x8d -- 1,55 # igrave
+char237 1900 0 0xa1 -- 1,49 # iacute
+char238 1900 0 0x8c -- 1,51 # icircumflex
+char239 1900 0 0x8b -- 1,53 # idieresis
+char241 1900 0 0xa4 -- 1,57 # ntilde
+char242 1900 0 0x95 -- 1,65 # ograve
+char243 1900 0 0xa2 -- 1,59 # oacute
+char244 1900 0 0x93 -- 1,61 # ocircumflex
+char246 1900 0 0x94 -- 1,63 # odieresis
+char247 1900 0 0xf6 -- 6,8 # divide
+char249 1900 0 0x97 -- 1,73 # ugrave
+char250 1900 0 0xa3 -- 1,67 # uacute
+char251 1900 0 0x96 -- 1,69 # ucircumflex
+char252 1900 0 0x81 -- 1,71 # udieresis
+char255 1900 0 0x98 -- 1,75 # ydieresis
+AE 1900 0 0x92 -- 1,36 # AE
+ae 1900 0 0x91 -- 1,37 # ae
+'E 1900 0 0x90 -- 1,40 # Eacute
+'a 1900 0 0xa0 -- 1,27 # aacute
+'e 1900 0 0x82 -- 1,41 # eacute
+'i 1900 0 0xa1 -- 1,49 # iacute
+'o 1900 0 0xa2 -- 1,59 # oacute
+'u 1900 0 0x95 -- 1,65 # uacute
+:A 1900 0 0x8e -- 1,30 # Adieresis
+:O 1900 0 0x99 -- 1,62 # Odieresis
+:U 1900 0 0x9a -- 1,70 # Udieresis
+:a 1900 0 0x84 -- 1,31 # adieresis
+:e 1900 0 0x89 -- 1,45 # edieresis
+:i 1900 0 0x8b -- 1,53 # idieresis
+:o 1900 0 0x94 -- 1,63 # odieresis
+:u 1900 0 0x81 -- 1,71 # udieresis
+:y 1900 0 0x98 -- 1,75 # ydieresis
+^a 1900 0 0x83 -- 1,29 # acircumflex
+^e 1900 0 0x88 -- 1,43 # ecircumflex
+^i 1900 0 0x8c -- 1,51 # icircumflex
+^o 1900 0 0x93 -- 1,61 # ocircumflex
+^u 1900 0 0x96 -- 1,69 # ucircumflex
+`a 1900 0 0x85 -- 1,33 # agrave
+`e 1900 0 0x8a -- 1,47 # egrave
+`i 1900 0 0x8d -- 1,55 # igrave
+`o 1900 0 0x95 -- 1,65 # ograve
+`u 1900 0 0x97 -- 1,73 # ugrave
+~A 1900 0 0x28e -- 1,26 # Atilde
+~N 1900 0 0xa5 -- 1,56 # Ntilde
+~a 1900 0 0x284 -- --- # atilde
+~n 1900 0 0xa4 -- 1,57 # ntilde
+,C 1900 0 0x80 -- 1,38 # Ccedilla
+,c 1900 0 0x87 -- 1,39 # ccedilla
+oA 1900 0 0x8f -- 1,34 # Aring
+oa 1900 0 0x86 -- 1,35 # aring
+a^ 1900 0 0x5e -- 1,3 # circumflex "circumflex accent"
+a~ 1900 0 0x7e -- 1,2 # tilde "tilde accent"
+Do 1900 0 0x24 -- 0,36 # dollar
+Po 1900 0 0x9c -- 4,11 # sterling
+Ye 1900 0 0x9d -- 4,12 # yen
+Fn 1900 0 0x9f -- 4,14 # florin
+ct 1900 0 0x9b -- 4,19 # cent
+Fo 1900 0 0xae -- 4,9 # guillemotleft
+r! 1900 0 0xad -- 4,7 # exclamdown
+r? 1900 0 0xa8 -- 4,8 # questiondown
+Of 1900 0 0xa6 -- 4,15 # ordfeminine
+Om 1900 0 0xa7 -- 4,16 # ordmasculine
+S2 1900 0 0xfd -- 4,20 # twosuperior
+<- 1900 0 0x1b -- 6,22 # arrowleft
+-> 1900 0 0x1a -- 6,21 # arrowright
+<> 1900 0 0x1d -- 6,25 # arrowboth "horizontal double-headed arrow"
+da 1900 0 0x19 -- 6,24 # arrowdown
+ua 1900 0 0x18 -- 6,23 # arrowup
+va 1900 0 0x12 -- 6,26 # \& "vertical double-headed arrow"
+ba 1900 0 0xb3 -- 3,9 # bar
+bb 1900 0 0x7c -- 0,124 # brokenbar
+ul 1900 0 0x5f -- 0,95 # ul "underline with traditional troff metrics"
+ci 1900 0 0x9 -- 4,1 # circle
+bu 1900 0 0x7 -- 4,0 # bullet
+ps 1900 0 0x14 -- 4,5 # paragraph
+sc 1900 0 0x15 -- 4,6 # section
+de 1900 0 0xf8 -- 6,36 # degree
+12 1900 0 0xab -- 4,17 # onehalf
+14 1900 0 0xac -- 4,18 # onequarter
+hy 1900 0 0x2d -- 6,0 # hyphen
+lB 1900 0 0x5b -- 0,91 # bracketleft
+rB 1900 0 0x5d -- 0,93 # bracketright
+lC 1900 0 0x7b -- 0,123 # braceleft
+rC 1900 0 0x7d -- 0,125 # braceright
+aq 1900 0 0x27 -- 0,39 # quotesingle "apostrophe quote"
+at 1900 0 0x40 -- 0,64 # at
+.C1 1900 0 0x2d -- 0,45 # - minus "minus sign from current font"
+sh 1900 0 0x23 -- 0,35 # numbersign
+sl 1900 0 0x2f -- 0,47 # slash
+rs 1900 0 0x5c -- 0,92 # backslash
+*a 1900 0 0xe0 -- 8,1 # alpha
+*b 1900 0 0xe1 -- 8,3 # beta
+*d 1900 0 0xeb -- 8,9 # delta
+*h 1900 0 0xe9 -- 8,17 # theta
+*m 1900 0 0xe6 -- 8,25 # mu
+*p 1900 0 0xe3 -- 8,33 # pi
+*s 1900 0 0xe5 -- 8,37 # sigma
+*t 1900 0 0xe7 -- 8,41 # tau
+~~ 1900 0 0xf7 -- 6,13 # approxequal
+~= 1900 0 0xf7 -- 6,13 # approxequal
++- 1900 0 0xf1 -- 6,1 # plusminus
+<= 1900 0 0xf3 -- 6,2 # lessequal
+ca 1900 0 0xef -- 6,16 # intersection "intersection, cap"
+-h 1900 0 0xc4 -- 3,8 # hbar
+CL 1900 0 0x5 -- 5,168 # club "club suit"
+SP 1900 0 0x6 -- 5,171 # spade "spade suit"
+HE 1900 0 0x3 -- 5,170 # heart "heart suit"
+DI 1900 0 0x4 -- 5,169 # diamond "diamond suit"
+<< 1900 0 0xae -- 6,77 # "" "much less"
+>> 1900 0 0xaf -- 6,78 # "" "much greater"
+pc 1900 0 0xfa -- 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HB b/contrib/groff/font/devlbp/HB
new file mode 100644
index 0000000..1ad7b4e
--- /dev/null
+++ b/contrib/groff/font/devlbp/HB
@@ -0,0 +1,491 @@
+name HB
+lbpname Swiss-Bold
+special
+spacewidth 927
+slant 0
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 2223 2 0x169 1,176 # Scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vs 1853 2 0x173 1,177 # scaron
+vz 1667 2 0x174 1,207 # zcaron
+:Y 2223 2 0x16d 1,74 # Ydieresis
+tm 3333 2 0x170 4,41 # trademark
+aq 793 2 0x27 0,39 # quotesingle
+space 927 0 0x20 0,32
+! 1110 2 0x21 0,33 # exclam
+" 1580 2 0x22 0,34 # quotedbl
+dq 1580 2 0x22 0,34 # quotedbl
+# 1853 2 0x23 0,35 # numbersign
+sh 1853 2 0x23 0,35 # "
+$ 1853 2 0x24 0,36 # dollar
+Do 1853 2 0x24 0,36 # "
+% 2963 2 0x25 0,37 # percent
+& 2407 2 0x26 0,38 # ampersand
+' 793 2 0x27 0,39 # quoteright
+cq 793 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1297 2 0x2a 0,42 # asterisk
++ 1947 0 0x2b 0,43 # plus
+, 927 0 0x2c 0,44 # comma
+- 1947 0 0x2d 0,45 # hyphen
+hy 1947 0 0x2d 0,45 # "
+char173 1947 0 0x2d 0,45 # "
+. 927 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1853 2 0x30 0,48 # zero
+1 1853 2 0x31 0,49 # one
+2 1853 2 0x32 0,50 # two
+3 1853 2 0x33 0,51 # three
+4 1853 2 0x34 0,52 # four
+5 1853 2 0x35 0,53 # five
+6 1853 2 0x36 0,54 # six
+7 1853 2 0x37 0,55 # seven
+8 1853 2 0x38 0,56 # eight
+9 1853 2 0x39 0,57 # nine
+: 1110 0 0x3a 0,58 # colon
+; 1110 0 0x3b 0,59 # semicolon
+< 1947 0 0x3c 0,60 # less
+= 1947 0 0x3d 0,61 # equal
+> 1947 0 0x3e 0,62 # greater
+? 2037 2 0x3f 0,63 # question
+@ 3250 2 0x40 0,64 # at
+at 3250 2 0x40 0,64 # "
+A 2407 2 0x41 0,65 # A
+B 2407 2 0x42 0,66 # B
+C 2407 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2223 2 0x45 0,69 # E
+F 2037 2 0x46 0,70 # F
+G 2593 2 0x47 0,71 # G
+H 2407 2 0x48 0,72 # H
+I 927 2 0x49 0,73 # I
+J 1853 2 0x4a 0,74 # J
+K 2407 2 0x4b 0,75 # K
+L 2037 2 0x4c 0,76 # L
+M 2777 2 0x4d 0,77 # M
+N 2407 2 0x4e 0,78 # N
+O 2593 2 0x4f 0,79 # O
+P 2223 2 0x50 0,80 # P
+Q 2593 2 0x51 0,81 # Q
+R 2407 2 0x52 0,82 # R
+S 2223 2 0x53 0,83 # S
+T 2037 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2223 2 0x56 0,86 # V
+W 3147 2 0x57 0,87 # W
+X 2223 2 0x58 0,88 # X
+Y 2223 2 0x59 0,89 # Y
+Z 2037 2 0x5a 0,90 # Z
+[ 1110 2 0x5b 0,91 # bracketleft
+lB 1110 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 1110 2 0x5d 0,93 # bracketright
+rB 1110 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1853 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1853 0 0x61 0,97 # a
+b 2037 2 0x62 0,98 # b
+c 1853 0 0x63 0,99 # c
+d 2037 2 0x64 0,100 # d
+e 1853 0 0x65 0,101 # e
+f 1110 2 0x66 0,102 # f
+g 2037 1 0x67 0,103 # g
+h 2037 2 0x68 0,104 # h
+i 927 2 0x69 0,105 # i
+j 927 2 0x6a 0,106 # j
+k 1853 2 0x6b 0,107 # k
+l 927 2 0x6c 0,108 # l
+m 2963 0 0x6d 0,109 # m
+n 2037 0 0x6e 0,110 # n
+o 2037 0 0x6f 0,111 # o
+p 2037 1 0x70 0,112 # p
+q 2037 1 0x71 0,113 # q
+r 1297 0 0x72 0,114 # r
+s 1853 0 0x73 0,115 # s
+t 1110 2 0x74 0,116 # t
+u 2037 0 0x75 0,117 # u
+v 1853 0 0x76 0,118 # v
+w 2593 0 0x77 0,119 # w
+x 1853 0 0x78 0,120 # x
+y 1853 1 0x79 0,121 # y
+z 1667 0 0x7a 0,122 # z
+lC 1297 2 0x7b 0,123 # braceleft
+{ 1297 2 0x7b 0,123 # "
+| 933 2 0x7c 0,124 # "
+rC 1297 2 0x7d 0,125 # braceright
+} 1297 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1110 1 0xad 4,7 # exclamdown
+char162 1853 2 0x9b 4,19 # cent
+char163 1853 2 0x9c 4,11 # sterling
+char164 1853 2 0x12f 4,24 # currency
+char165 1853 2 0x9d 4,12 # yen
+char166 933 2 0x7c 0,124 # brokenbar
+char167 1853 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2457 2 0x154 4,23 # copyright
+char170 1233 2 0xa6 4,15 # ordfeminine
+char171 1853 0 0xae 4,9 # guillemotleft
+char172 1947 0 0xaa 6,20 # logicalnot
+char173 1853 0 0x132 4,33 # hyphen
+char174 2457 2 0x155 4,22 # registered
+char175 1947 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 1947 0 0xf1 6,1 # plusminus
+char178 1110 2 0xfd 4,20 # twosuperior
+char179 1110 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 2037 1 0xe6 8,25 # mu
+char182 1853 2 0x14 4,5 # paragraph
+char183 927 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1110 2 0x156 4,78 # onesuperior
+char186 1217 2 0xa7 4,16 # ordmasculine
+char187 1853 0 0xaf 4,10 # guillemotright
+char188 2780 2 0xac 4,18 # onequarter
+char189 2780 2 0xab 4,17 # onehalf
+char190 2780 2 0x12e 4,25 # threequarters
+char191 2037 1 0xa8 4,8 # questiondown
+char192 2407 2 0x15c 1,32 # Agrave
+char193 2407 2 0x15a 1,26 # Aacute
+char194 2407 2 0x15b 1,28 # Acircumflex
+char195 2407 2 0x28e 1,76 # Atilde
+char196 2407 2 0x8e 1,30 # Adieresis
+char197 2407 2 0x8f 1,34 # Aring
+char198 3333 2 0x92 1,36 # AE
+char199 2407 2 0x80 1,38 # Ccedilla
+char200 2223 2 0x160 1,46 # Egrave
+char201 2223 2 0x90 1,40 # Eacute
+char202 2223 2 0x15e 1,42 # Ecircumflex
+char203 2223 2 0x15f 1,44 # Edieresis
+char204 927 2 0x164 1,54 # Igrave
+char205 927 2 0x161 1,48 # Iacute
+char206 927 2 0x162 1,50 # Icircumflex
+char207 927 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2407 2 0xa5 1,56 # Ntilde
+char210 2593 2 0x167 1,64 # Ograve
+char211 2593 2 0x165 1,58 # Oacute
+char212 2593 2 0x166 1,60 # Ocircumflex
+char213 2593 2 0x168 1,82 # Otilde
+char214 2593 2 0x99 1,62 # Odieresis
+char215 1947 0 0x157 6,39 # multiply
+char216 2593 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 2223 2 0x16f 1,84 # Yacute
+char222 2223 2 0x13e 1,88 # Thorn
+char223 2037 2 0x147 1,23 # germandbls
+char224 1853 2 0x85 1,33 # agrave
+char225 1853 2 0xa0 1,27 # aacute
+char226 1853 2 0x83 1,29 # acircumflex
+char227 1853 2 0x284 1,93 # atilde
+char228 1853 2 0x84 1,31 # adieresis
+char229 1853 2 0x86 1,35 # aring
+char230 2963 0 0x91 1,37 # ae
+char231 1853 0 0x87 1,39 # ccedilla
+char232 1853 2 0x8a 1,47 # egrave
+char233 1853 2 0x82 1,41 # eacute
+char234 1853 2 0x88 1,43 # ecircumflex
+char235 1853 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 2037 2 0x148 1,87 # eth
+char241 2037 2 0xa4 1,57 # ntilde
+char242 2037 2 0x95 1,65 # ograve
+char243 2037 2 0xa2 1,59 # oacute
+char244 2037 2 0x93 1,61 # ocircumflex
+char245 2037 2 0x172 1,83 # otilde
+char246 2037 2 0x94 1,63 # odieresis
+char247 1947 0 0xf6 6,8 # divide
+char248 2037 0 0x145 1,81 # oslash
+char249 2037 2 0x97 1,73 # ugrave
+char250 2037 2 0xa3 1,67 # uacute
+char251 2037 2 0x96 1,69 # ucircumflex
+char252 2037 2 0x81 1,71 # udieresis
+char253 1853 3 0x175 1,85 # yacute
+char254 2037 3 0x143 1,89 # thorn
+char255 1853 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 2037 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 2223 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 2037 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 3333 2 0x92 1,36 # AE
+ae 2963 0 0x91 1,37 # ae
+OE 3333 2 0x141 1,166 # OE
+oe 3147 0 0x146 1,167 # oe
+ij 1830 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 2037 2 0x147 1,23 # germandbls
+'A 2407 2 0x15a 1,26 # Aacute
+'E 2223 2 0x90 1,40 # Eacute
+'I 927 2 0x161 1,48 # Iacute
+'O 2593 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1853 2 0xa0 1,27 # aacute
+'e 1853 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 2037 2 0xa2 1,59 # oacute
+'u 2037 2 0x95 1,65 # uacute
+:A 2407 2 0x8e 1,30 # Adieresis
+:E 2223 2 0x15f 1,44 # Edieresis
+:I 927 2 0x163 1,52 # Idieresis
+:O 2593 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 2223 2 0x16d 1,74 # Ydieresis
+:a 1853 2 0x84 1,31 # adieresis
+:e 1853 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 2037 2 0x94 1,63 # odieresis
+:u 2037 2 0x81 1,71 # udieresis
+:y 1853 3 0x98 1,75 # ydieresis
+^A 2407 2 0x15b 1,28 # Acircumflex
+^E 2223 2 0x15e 1,42 # Ecircumflex
+^I 927 2 0x162 1,50 # Icircumflex
+^O 2593 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1853 2 0x83 1,29 # acircumflex
+^e 1853 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 2037 2 0x93 1,61 # ocircumflex
+^u 2037 2 0x96 1,69 # ucircumflex
+`A 2407 2 0x15c 1,32 # Agrave
+`E 2223 2 0x160 1,46 # Egrave
+`I 927 2 0x164 1,54 # Igrave
+`O 2593 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1853 2 0x85 1,33 # agrave
+~a 1853 2 0x284 --- # atilde
+`e 1853 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 2037 2 0x95 1,65 # ograve
+`u 2037 2 0x97 1,73 # ugrave
+~A 2407 2 0x28e 1,26 # Atilde
+~N 2407 2 0xa5 1,56 # Ntilde
+~O 2593 2 0x168 1,82 # Otilde
+~n 2037 2 0xa4 1,57 # ntilde
+~o 2037 2 0x172 1,83 # otilde
+vS 2223 2 0x169 1,176 # Scaron
+vs 1853 2 0x173 1,177 # scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vz 1667 2 0x174 1,207 # zcaron
+,C 2407 2 0x80 1,38 # Ccedilla
+,c 1853 0 0x87 1,39 # ccedilla
+/L 2037 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 927 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2593 2 0x140 1,80 # Oslash
+/o 2037 0 0x145 1,81 # oslash
+oA 2407 2 0x8f 1,34 # Aring
+oa 1853 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1853 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1853 2 0x24 0,36 # dollar
+Po 1853 2 0x9c 4,11 # sterling
+Ye 1853 2 0x9d 4,12 # yen
+Fn 1853 2 0x9f 4,14 # florin
+ct 1853 2 0x9b 4,19 # cent
+Fo 1853 0 0xae 4,9 # guillemotleft
+Fc 1110 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1110 1 0xad 4,7 # exclamdown
+r? 2037 1 0xa8 4,8 # questiondown
+fi 2037 2 0x130 4,54 # fi "fi ligature"
+fl 2037 2 0x131 4,55 # fl "fl ligature"
+OK 2037 0 0x3d6 --- # \& "check mark, tick"
+Of 1233 2 0xa6 4,15 # ordfeminine
+Om 1217 2 0xa7 4,16 # ordmasculine
+S1 1110 2 0x156 4,78 # onesuperior
+S2 1110 2 0xfd 4,20 # twosuperior
+S3 1110 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 933 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 3333 0 0x123 4,34 # ru "baseline rule"
+ul 1853 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0x3f4 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2457 2 0x154 4,23 # copyright
+rg 2457 2 0x155 4,22 # registered
+tm 3333 2 0x170 4,41 # trademark
+dd 1853 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1853 2 0x12a 4,39 # dagger
+ps 1853 2 0x14 4,5 # paragraph
+sc 1853 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 3333 0 0x123 4,34 # emdash "em dash"
+en 1853 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2780 2 0xab 4,17 # onehalf
+14 2780 2 0xac 4,18 # onequarter
+34 2780 2 0x12e 4,25 # threequarters
+f/ 927 2 0x158 6,6 # fraction "bar for fractions"
+fm 927 0 0x3a2 6,45 # minute "footmark, prime"
+sd 927 0 0x3b2 6,46 # second
+ha 927 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 927 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 1947 0 0x2d 6,0 # hyphen
+lB 1110 2 0x5b 0,91 # bracketleft
+rB 1110 2 0x5d 0,93 # bracketright
+lC 1297 2 0x7b 0,123 # braceleft
+rC 1297 2 0x7d 0,125 # braceright
+la 1297 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1297 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1667 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1667 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1667 2 0x125 4,32 # quotedblleft
+rq 1667 2 0x4ba 6,31 # quotedblright
+oq 927 2 0x176 4,29 # quoteleft "single open quote"
+aq 793 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 933 0 0x3f4 0,124 # bar
+at 3250 2 0x40 0,64 # at
+.C1 1947 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1853 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2477 0 0x346 8,44 # Phi
+*G 1953 0 0x347 8,6 # Gamma
+*H 1953 0 0x351 8,16 # Theta
+*I 1953 0 0x349 8,18 # Iota
+*K 1953 0 0x34b 8,20 # Kappa
+*L 1953 0 0x34c 8,22 # Lambda
+*M 1953 0 0x34d 8,24 # Mu
+*N 1953 0 0x34e 8,26 # Nu
+*O 1953 0 0x34f 8,30 # Omicron
+*P 1953 0 0x350 8,32 # Pi
+*Q 1953 0 0x359 8,48 # Psi
+*R 1953 0 0x352 8,34 # Rho
+*S 1953 0 0x353 8,36 # Sigma
+*T 1953 0 0x354 8,40 # Tau
+*U 1953 0 0x3a1 8,76 # Upsilon
+*W 2560 0 0x357 8,50 # Omega
+*X 1953 0 0x343 8,36 # Chi
+*Y 1953 0 0x348 8,14 # Eta
+*Z 1953 0 0x35a 8,12 # Zeta
+*a 2027 0 0xe0 8,1 # alpha
+*b 2027 0 0xe1 8,3 # beta
+*c 2027 0 0x378 8,29 # xi
+*d 1980 0 0xeb 8,9 # delta
+*e 1980 0 0x36e 8,70 # epsilon
+*f 1980 0 0x366 8,45 # phi
++f 1980 0 0x36a 8,77 # phi1 "variant phi"
+*g 1980 0 0x367 8,7 # gamma
+*h 1977 0 0xe9 8,17 # theta
++h 1977 0 0x375 8,71 # theta1 "variant theta"
+*i 1977 0 0x369 8,19 # iota
+*k 1977 0 0x36b 8,21 # kappa
+*l 1977 0 0x36c 8,23 # lambda
+*m 2037 0 0xe6 8,25 # mu
+*n 2037 0 0x36e 8,27 # nu
+*o 2037 0 0x36f 8,31 # omicron
+*p 2143 0 0xe3 8,33 # pi
++p 2143 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 2143 0 0x379 8,49 # psi
+*r 2143 0 0x372 8,35 # rho
+*s 2157 0 0xe5 8,37 # sigma
+*t 1503 0 0xe7 8,41 # tau
+*u 1503 0 0x375 8,27 # upsilon
+*w 1503 0 0x377 8,51 # omega
+*x 1503 0 0x363 8,47 # chi
+*y 1503 0 0x368 8,15 # eta
+*z 1503 0 0x37a 8,13 # zeta
+ts 1503 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 927 0 0x32a 0,32 # asteriskmath
++- 1947 0 0xf1 6,1 # plusminus
+<= 2407 0 0xf3 6,2 # lessequal
+== 2407 0 0x3ba 8,14 # equivalence
+=~ 2407 0 0x340 8,116 # congruent
+>= 2027 0 0x3b3 8,3 # greaterequal
+AN 2027 0 0x3d9 8,85 # logicaland
+OR 2027 0 0x3da 8,86 # logicalor
+no 2027 0 0x3d8 8,20 # logicalnot
+te 2027 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 2027 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 2027 0 0x3c0 9,0 # aleph
+Im 2027 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 2027 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 2027 0 0x3a5 8,19 # infinity
+md 2027 0 0x3b7 8,32 # dotmath
+mo 2027 0 0x3ce 8,15 # element
+mu 2027 0 0x3b4 8,39 # multiply
+nc 2027 0 0x3cb 8,197 # notpropersuperset
+nm 2027 0 0x3cf 8,209 # notelement
+pl 1110 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 1947 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 1947 0 0x3b5 6,4 # proportional
+pp 1947 0 0x35e 8,89 # perpendicular
+sb 1947 0 0x3cc 6,67 # propersubset
+sp 1947 0 0x3c9 6,68 # propersuperset
+ib 1947 0 0x3cd 6,69 # reflexsubset
+ip 1947 0 0x3ca 6,70 # reflexsuperset
+ap 1947 0 0x37e 6,12 # similar
+pd 1947 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 1947 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 1947 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 1947 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2593 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1853 0 0xae 6,77 # "" "much less"
+>> 1853 0 0xaf 6,78 # "" "much greater"
+wp 1853 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1853 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 927 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HBI b/contrib/groff/font/devlbp/HBI
new file mode 100644
index 0000000..30fa995
--- /dev/null
+++ b/contrib/groff/font/devlbp/HBI
@@ -0,0 +1,492 @@
+slant 18.49
+name HBI
+lbpname Swiss-BoldOblique
+special
+spacewidth 927
+slant 0
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 2223 2 0x169 1,176 # Scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vs 1853 2 0x173 1,177 # scaron
+vz 1667 2 0x174 1,207 # zcaron
+:Y 2223 2 0x16d 1,74 # Ydieresis
+tm 3333 2 0x170 4,41 # trademark
+aq 793 2 0x27 0,39 # quotesingle
+space 927 0 0x20 0,32
+! 1110 2 0x21 0,33 # exclam
+" 1580 2 0x22 0,34 # quotedbl
+dq 1580 2 0x22 0,34 # quotedbl
+# 1853 2 0x23 0,35 # numbersign
+sh 1853 2 0x23 0,35 # "
+$ 1853 2 0x24 0,36 # dollar
+Do 1853 2 0x24 0,36 # "
+% 2963 2 0x25 0,37 # percent
+& 2407 2 0x26 0,38 # ampersand
+' 793 2 0x27 0,39 # quoteright
+cq 793 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1297 2 0x2a 0,42 # asterisk
++ 1947 0 0x2b 0,43 # plus
+, 927 0 0x2c 0,44 # comma
+- 1947 0 0x2d 0,45 # hyphen
+hy 1947 0 0x2d 0,45 # "
+char173 1947 0 0x2d 0,45 # "
+. 927 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1853 2 0x30 0,48 # zero
+1 1853 2 0x31 0,49 # one
+2 1853 2 0x32 0,50 # two
+3 1853 2 0x33 0,51 # three
+4 1853 2 0x34 0,52 # four
+5 1853 2 0x35 0,53 # five
+6 1853 2 0x36 0,54 # six
+7 1853 2 0x37 0,55 # seven
+8 1853 2 0x38 0,56 # eight
+9 1853 2 0x39 0,57 # nine
+: 1110 0 0x3a 0,58 # colon
+; 1110 0 0x3b 0,59 # semicolon
+< 1947 0 0x3c 0,60 # less
+= 1947 0 0x3d 0,61 # equal
+> 1947 0 0x3e 0,62 # greater
+? 2037 2 0x3f 0,63 # question
+@ 3250 2 0x40 0,64 # at
+at 3250 2 0x40 0,64 # "
+A 2407 2 0x41 0,65 # A
+B 2407 2 0x42 0,66 # B
+C 2407 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2223 2 0x45 0,69 # E
+F 2037 2 0x46 0,70 # F
+G 2593 2 0x47 0,71 # G
+H 2407 2 0x48 0,72 # H
+I 927 2 0x49 0,73 # I
+J 1853 2 0x4a 0,74 # J
+K 2407 2 0x4b 0,75 # K
+L 2037 2 0x4c 0,76 # L
+M 2777 2 0x4d 0,77 # M
+N 2407 2 0x4e 0,78 # N
+O 2593 2 0x4f 0,79 # O
+P 2223 2 0x50 0,80 # P
+Q 2593 2 0x51 0,81 # Q
+R 2407 2 0x52 0,82 # R
+S 2223 2 0x53 0,83 # S
+T 2037 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2223 2 0x56 0,86 # V
+W 3147 2 0x57 0,87 # W
+X 2223 2 0x58 0,88 # X
+Y 2223 2 0x59 0,89 # Y
+Z 2037 2 0x5a 0,90 # Z
+[ 1110 2 0x5b 0,91 # bracketleft
+lB 1110 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 1110 2 0x5d 0,93 # bracketright
+rB 1110 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1853 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1853 0 0x61 0,97 # a
+b 2037 2 0x62 0,98 # b
+c 1853 0 0x63 0,99 # c
+d 2037 2 0x64 0,100 # d
+e 1853 0 0x65 0,101 # e
+f 1110 2 0x66 0,102 # f
+g 2037 1 0x67 0,103 # g
+h 2037 2 0x68 0,104 # h
+i 927 2 0x69 0,105 # i
+j 927 2 0x6a 0,106 # j
+k 1853 2 0x6b 0,107 # k
+l 927 2 0x6c 0,108 # l
+m 2963 0 0x6d 0,109 # m
+n 2037 0 0x6e 0,110 # n
+o 2037 0 0x6f 0,111 # o
+p 2037 1 0x70 0,112 # p
+q 2037 1 0x71 0,113 # q
+r 1297 0 0x72 0,114 # r
+s 1853 0 0x73 0,115 # s
+t 1110 2 0x74 0,116 # t
+u 2037 0 0x75 0,117 # u
+v 1853 0 0x76 0,118 # v
+w 2593 0 0x77 0,119 # w
+x 1853 0 0x78 0,120 # x
+y 1853 1 0x79 0,121 # y
+z 1667 0 0x7a 0,122 # z
+lC 1297 2 0x7b 0,123 # braceleft
+{ 1297 2 0x7b 0,123 # "
+| 933 2 0x7c 0,124 # "
+rC 1297 2 0x7d 0,125 # braceright
+} 1297 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1110 1 0xad 4,7 # exclamdown
+char162 1853 2 0x9b 4,19 # cent
+char163 1853 2 0x9c 4,11 # sterling
+char164 1853 2 0x12f 4,24 # currency
+char165 1853 2 0x9d 4,12 # yen
+char166 933 2 0x7c 0,124 # brokenbar
+char167 1853 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2457 2 0x154 4,23 # copyright
+char170 1233 2 0xa6 4,15 # ordfeminine
+char171 1853 0 0xae 4,9 # guillemotleft
+char172 1947 0 0xaa 6,20 # logicalnot
+char173 1853 0 0x132 4,33 # hyphen
+char174 2457 2 0x155 4,22 # registered
+char175 1947 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 1947 0 0xf1 6,1 # plusminus
+char178 1110 2 0xfd 4,20 # twosuperior
+char179 1110 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 2037 1 0xe6 8,25 # mu
+char182 1853 2 0x14 4,5 # paragraph
+char183 927 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1110 2 0x156 4,78 # onesuperior
+char186 1217 2 0xa7 4,16 # ordmasculine
+char187 1853 0 0xaf 4,10 # guillemotright
+char188 2780 2 0xac 4,18 # onequarter
+char189 2780 2 0xab 4,17 # onehalf
+char190 2780 2 0x12e 4,25 # threequarters
+char191 2037 1 0xa8 4,8 # questiondown
+char192 2407 2 0x15c 1,32 # Agrave
+char193 2407 2 0x15a 1,26 # Aacute
+char194 2407 2 0x15b 1,28 # Acircumflex
+char195 2407 2 0x28e 1,76 # Atilde
+char196 2407 2 0x8e 1,30 # Adieresis
+char197 2407 2 0x8f 1,34 # Aring
+char198 3333 2 0x92 1,36 # AE
+char199 2407 2 0x80 1,38 # Ccedilla
+char200 2223 2 0x160 1,46 # Egrave
+char201 2223 2 0x90 1,40 # Eacute
+char202 2223 2 0x15e 1,42 # Ecircumflex
+char203 2223 2 0x15f 1,44 # Edieresis
+char204 927 2 0x164 1,54 # Igrave
+char205 927 2 0x161 1,48 # Iacute
+char206 927 2 0x162 1,50 # Icircumflex
+char207 927 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2407 2 0xa5 1,56 # Ntilde
+char210 2593 2 0x167 1,64 # Ograve
+char211 2593 2 0x165 1,58 # Oacute
+char212 2593 2 0x166 1,60 # Ocircumflex
+char213 2593 2 0x168 1,82 # Otilde
+char214 2593 2 0x99 1,62 # Odieresis
+char215 1947 0 0x157 6,39 # multiply
+char216 2593 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 2223 2 0x16f 1,84 # Yacute
+char222 2223 2 0x13e 1,88 # Thorn
+char223 2037 2 0x147 1,23 # germandbls
+char224 1853 2 0x85 1,33 # agrave
+char225 1853 2 0xa0 1,27 # aacute
+char226 1853 2 0x83 1,29 # acircumflex
+char227 1853 2 0x284 1,93 # atilde
+char228 1853 2 0x84 1,31 # adieresis
+char229 1853 2 0x86 1,35 # aring
+char230 2963 0 0x91 1,37 # ae
+char231 1853 0 0x87 1,39 # ccedilla
+char232 1853 2 0x8a 1,47 # egrave
+char233 1853 2 0x82 1,41 # eacute
+char234 1853 2 0x88 1,43 # ecircumflex
+char235 1853 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 2037 2 0x148 1,87 # eth
+char241 2037 2 0xa4 1,57 # ntilde
+char242 2037 2 0x95 1,65 # ograve
+char243 2037 2 0xa2 1,59 # oacute
+char244 2037 2 0x93 1,61 # ocircumflex
+char245 2037 2 0x172 1,83 # otilde
+char246 2037 2 0x94 1,63 # odieresis
+char247 1947 0 0xf6 6,8 # divide
+char248 2037 0 0x145 1,81 # oslash
+char249 2037 2 0x97 1,73 # ugrave
+char250 2037 2 0xa3 1,67 # uacute
+char251 2037 2 0x96 1,69 # ucircumflex
+char252 2037 2 0x81 1,71 # udieresis
+char253 1853 3 0x175 1,85 # yacute
+char254 2037 3 0x143 1,89 # thorn
+char255 1853 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 2037 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 2223 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 2037 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 3333 2 0x92 1,36 # AE
+ae 2963 0 0x91 1,37 # ae
+OE 3333 2 0x141 1,166 # OE
+oe 3147 0 0x146 1,167 # oe
+ij 1830 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 2037 2 0x147 1,23 # germandbls
+'A 2407 2 0x15a 1,26 # Aacute
+'E 2223 2 0x90 1,40 # Eacute
+'I 927 2 0x161 1,48 # Iacute
+'O 2593 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1853 2 0xa0 1,27 # aacute
+'e 1853 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 2037 2 0xa2 1,59 # oacute
+'u 2037 2 0x95 1,65 # uacute
+:A 2407 2 0x8e 1,30 # Adieresis
+:E 2223 2 0x15f 1,44 # Edieresis
+:I 927 2 0x163 1,52 # Idieresis
+:O 2593 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 2223 2 0x16d 1,74 # Ydieresis
+:a 1853 2 0x84 1,31 # adieresis
+:e 1853 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 2037 2 0x94 1,63 # odieresis
+:u 2037 2 0x81 1,71 # udieresis
+:y 1853 3 0x98 1,75 # ydieresis
+^A 2407 2 0x15b 1,28 # Acircumflex
+^E 2223 2 0x15e 1,42 # Ecircumflex
+^I 927 2 0x162 1,50 # Icircumflex
+^O 2593 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1853 2 0x83 1,29 # acircumflex
+^e 1853 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 2037 2 0x93 1,61 # ocircumflex
+^u 2037 2 0x96 1,69 # ucircumflex
+`A 2407 2 0x15c 1,32 # Agrave
+`E 2223 2 0x160 1,46 # Egrave
+`I 927 2 0x164 1,54 # Igrave
+`O 2593 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1853 2 0x85 1,33 # agrave
+~a 1853 2 0x284 --- # atilde
+`e 1853 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 2037 2 0x95 1,65 # ograve
+`u 2037 2 0x97 1,73 # ugrave
+~A 2407 2 0x28e 1,26 # Atilde
+~N 2407 2 0xa5 1,56 # Ntilde
+~O 2593 2 0x168 1,82 # Otilde
+~n 2037 2 0xa4 1,57 # ntilde
+~o 2037 2 0x172 1,83 # otilde
+vS 2223 2 0x169 1,176 # Scaron
+vs 1853 2 0x173 1,177 # scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vz 1667 2 0x174 1,207 # zcaron
+,C 2407 2 0x80 1,38 # Ccedilla
+,c 1853 0 0x87 1,39 # ccedilla
+/L 2037 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 927 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2593 2 0x140 1,80 # Oslash
+/o 2037 0 0x145 1,81 # oslash
+oA 2407 2 0x8f 1,34 # Aring
+oa 1853 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1853 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1853 2 0x24 0,36 # dollar
+Po 1853 2 0x9c 4,11 # sterling
+Ye 1853 2 0x9d 4,12 # yen
+Fn 1853 2 0x9f 4,14 # florin
+ct 1853 2 0x9b 4,19 # cent
+Fo 1853 0 0xae 4,9 # guillemotleft
+Fc 1110 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1110 1 0xad 4,7 # exclamdown
+r? 2037 1 0xa8 4,8 # questiondown
+fi 2037 2 0x130 4,54 # fi "fi ligature"
+fl 2037 2 0x131 4,55 # fl "fl ligature"
+OK 2037 0 0x3d6 --- # \& "check mark, tick"
+Of 1233 2 0xa6 4,15 # ordfeminine
+Om 1217 2 0xa7 4,16 # ordmasculine
+S1 1110 2 0x156 4,78 # onesuperior
+S2 1110 2 0xfd 4,20 # twosuperior
+S3 1110 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 933 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 3333 0 0x123 4,34 # ru "baseline rule"
+ul 1853 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0x3f4 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2457 2 0x154 4,23 # copyright
+rg 2457 2 0x155 4,22 # registered
+tm 3333 2 0x170 4,41 # trademark
+dd 1853 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1853 2 0x12a 4,39 # dagger
+ps 1853 2 0x14 4,5 # paragraph
+sc 1853 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 3333 0 0x123 4,34 # emdash "em dash"
+en 1853 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2780 2 0xab 4,17 # onehalf
+14 2780 2 0xac 4,18 # onequarter
+34 2780 2 0x12e 4,25 # threequarters
+f/ 557 2 0x158 6,6 # fraction "bar for fractions"
+fm 557 0 0x3a2 6,45 # minute "footmark, prime"
+sd 557 0 0x3b2 6,46 # second
+ha 557 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 557 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 1947 0 0x2d 6,0 # hyphen
+lB 1110 2 0x5b 0,91 # bracketleft
+rB 1110 2 0x5d 0,93 # bracketright
+lC 1297 2 0x7b 0,123 # braceleft
+rC 1297 2 0x7d 0,125 # braceright
+la 1297 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1297 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1667 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1667 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1667 2 0x125 4,32 # quotedblleft
+rq 1667 2 0x4ba 6,31 # quotedblright
+oq 927 2 0x176 4,29 # quoteleft "single open quote"
+aq 793 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 933 0 0x3f4 0,124 # bar
+at 3250 2 0x40 0,64 # at
+.C1 1947 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1853 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2477 0 0x346 8,44 # Phi
+*G 1953 0 0x347 8,6 # Gamma
+*H 1953 0 0x351 8,16 # Theta
+*I 1953 0 0x349 8,18 # Iota
+*K 1953 0 0x34b 8,20 # Kappa
+*L 1953 0 0x34c 8,22 # Lambda
+*M 1953 0 0x34d 8,24 # Mu
+*N 1953 0 0x34e 8,26 # Nu
+*O 1953 0 0x34f 8,30 # Omicron
+*P 1953 0 0x350 8,32 # Pi
+*Q 1953 0 0x359 8,48 # Psi
+*R 1953 0 0x352 8,34 # Rho
+*S 1953 0 0x353 8,36 # Sigma
+*T 1953 0 0x354 8,40 # Tau
+*U 1953 0 0x3a1 8,76 # Upsilon
+*W 2560 0 0x357 8,50 # Omega
+*X 1953 0 0x343 8,36 # Chi
+*Y 1953 0 0x348 8,14 # Eta
+*Z 1953 0 0x35a 8,12 # Zeta
+*a 2027 0 0xe0 8,1 # alpha
+*b 2027 0 0xe1 8,3 # beta
+*c 2027 0 0x378 8,29 # xi
+*d 1980 0 0xeb 8,9 # delta
+*e 1980 0 0x36e 8,70 # epsilon
+*f 1980 0 0x366 8,45 # phi
++f 1980 0 0x36a 8,77 # phi1 "variant phi"
+*g 1980 0 0x367 8,7 # gamma
+*h 1977 0 0xe9 8,17 # theta
++h 1977 0 0x375 8,71 # theta1 "variant theta"
+*i 1977 0 0x369 8,19 # iota
+*k 1977 0 0x36b 8,21 # kappa
+*l 1977 0 0x36c 8,23 # lambda
+*m 2037 0 0xe6 8,25 # mu
+*n 2037 0 0x36e 8,27 # nu
+*o 2037 0 0x36f 8,31 # omicron
+*p 2143 0 0xe3 8,33 # pi
++p 2143 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 2143 0 0x379 8,49 # psi
+*r 2143 0 0x372 8,35 # rho
+*s 2157 0 0xe5 8,37 # sigma
+*t 1503 0 0xe7 8,41 # tau
+*u 1503 0 0x375 8,27 # upsilon
+*w 1503 0 0x377 8,51 # omega
+*x 1503 0 0x363 8,47 # chi
+*y 1503 0 0x368 8,15 # eta
+*z 1503 0 0x37a 8,13 # zeta
+ts 1503 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 927 0 0x32a 0,32 # asteriskmath
++- 1947 0 0xf1 6,1 # plusminus
+<= 2407 0 0xf3 6,2 # lessequal
+== 2407 0 0x3ba 8,14 # equivalence
+=~ 2407 0 0x340 8,116 # congruent
+>= 2027 0 0x3b3 8,3 # greaterequal
+AN 2027 0 0x3d9 8,85 # logicaland
+OR 2027 0 0x3da 8,86 # logicalor
+no 2027 0 0x3d8 8,20 # logicalnot
+te 2027 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 2027 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 2027 0 0x3c0 9,0 # aleph
+Im 2027 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 2027 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 2027 0 0x3a5 8,19 # infinity
+md 2027 0 0x3b7 8,32 # dotmath
+mo 2027 0 0x3ce 8,15 # element
+mu 2027 0 0x3b4 8,39 # multiply
+nc 2027 0 0x3cb 8,197 # notpropersuperset
+nm 2027 0 0x3cf 8,209 # notelement
+pl 1110 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 1947 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 1947 0 0x3b5 6,4 # proportional
+pp 1947 0 0x35e 8,89 # perpendicular
+sb 1947 0 0x3cc 6,67 # propersubset
+sp 1947 0 0x3c9 6,68 # propersuperset
+ib 1947 0 0x3cd 6,69 # reflexsubset
+ip 1947 0 0x3ca 6,70 # reflexsuperset
+ap 1947 0 0x37e 6,12 # similar
+pd 1947 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 1947 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 1947 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 1947 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2593 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1853 0 0xae 6,77 # "" "much less"
+>> 1853 0 0xaf 6,78 # "" "much greater"
+wp 1853 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1853 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 927 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HI b/contrib/groff/font/devlbp/HI
new file mode 100644
index 0000000..59201e2
--- /dev/null
+++ b/contrib/groff/font/devlbp/HI
@@ -0,0 +1,492 @@
+slant 18.49
+name HI
+lbpname Swiss-Oblique
+special
+spacewidth 927
+slant 0
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 2223 2 0x169 1,176 # Scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vs 1667 2 0x173 1,177 # scaron
+vz 1667 2 0x174 1,207 # zcaron
+:Y 2223 2 0x16d 1,74 # Ydieresis
+tm 3333 2 0x170 4,41 # trademark
+aq 637 2 0x27 0,39 # quotesingle
+space 927 0 0x20 0,32
+! 927 2 0x21 0,33 # exclam
+" 1183 2 0x22 0,34 # quotedbl
+dq 1183 2 0x22 0,34 # quotedbl
+# 1853 2 0x23 0,35 # numbersign
+sh 1853 2 0x23 0,35 # "
+$ 1853 2 0x24 0,36 # dollar
+Do 1853 2 0x24 0,36 # "
+% 2963 2 0x25 0,37 # percent
+& 2223 2 0x26 0,38 # ampersand
+' 637 2 0x27 0,39 # quoteright
+cq 637 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1297 2 0x2a 0,42 # asterisk
++ 1947 0 0x2b 0,43 # plus
+, 927 0 0x2c 0,44 # comma
+- 1947 0 0x2d 0,45 # hyphen
+hy 1947 0 0x2d 0,45 # "
+char173 1947 0 0x2d 0,45 # "
+. 927 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1853 2 0x30 0,48 # zero
+1 1853 2 0x31 0,49 # one
+2 1853 2 0x32 0,50 # two
+3 1853 2 0x33 0,51 # three
+4 1853 2 0x34 0,52 # four
+5 1853 2 0x35 0,53 # five
+6 1853 2 0x36 0,54 # six
+7 1853 2 0x37 0,55 # seven
+8 1853 2 0x38 0,56 # eight
+9 1853 2 0x39 0,57 # nine
+: 927 0 0x3a 0,58 # colon
+; 927 0 0x3b 0,59 # semicolon
+< 1947 0 0x3c 0,60 # less
+= 1947 0 0x3d 0,61 # equal
+> 1947 0 0x3e 0,62 # greater
+? 1853 2 0x3f 0,63 # question
+@ 3383 2 0x40 0,64 # at
+at 3383 2 0x40 0,64 # "
+A 2223 2 0x41 0,65 # A
+B 2223 2 0x42 0,66 # B
+C 2407 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2223 2 0x45 0,69 # E
+F 2037 2 0x46 0,70 # F
+G 2593 2 0x47 0,71 # G
+H 2407 2 0x48 0,72 # H
+I 927 2 0x49 0,73 # I
+J 1667 2 0x4a 0,74 # J
+K 2223 2 0x4b 0,75 # K
+L 1853 2 0x4c 0,76 # L
+M 2777 2 0x4d 0,77 # M
+N 2407 2 0x4e 0,78 # N
+O 2593 2 0x4f 0,79 # O
+P 2223 2 0x50 0,80 # P
+Q 2593 2 0x51 0,81 # Q
+R 2407 2 0x52 0,82 # R
+S 2223 2 0x53 0,83 # S
+T 2037 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2223 2 0x56 0,86 # V
+W 3147 2 0x57 0,87 # W
+X 2223 2 0x58 0,88 # X
+Y 2223 2 0x59 0,89 # Y
+Z 2037 2 0x5a 0,90 # Z
+[ 927 2 0x5b 0,91 # bracketleft
+lB 927 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 927 2 0x5d 0,93 # bracketright
+rB 927 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1853 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1853 0 0x61 0,97 # a
+b 1853 2 0x62 0,98 # b
+c 1667 0 0x63 0,99 # c
+d 1853 2 0x64 0,100 # d
+e 1853 0 0x65 0,101 # e
+f 927 2 0x66 0,102 # f
+g 1853 1 0x67 0,103 # g
+h 1853 2 0x68 0,104 # h
+i 740 2 0x69 0,105 # i
+j 740 2 0x6a 0,106 # j
+k 1667 2 0x6b 0,107 # k
+l 740 2 0x6c 0,108 # l
+m 2777 0 0x6d 0,109 # m
+n 1853 0 0x6e 0,110 # n
+o 1853 0 0x6f 0,111 # o
+p 1853 1 0x70 0,112 # p
+q 1853 1 0x71 0,113 # q
+r 1110 0 0x72 0,114 # r
+s 1667 0 0x73 0,115 # s
+t 927 2 0x74 0,116 # t
+u 1853 0 0x75 0,117 # u
+v 1667 0 0x76 0,118 # v
+w 2407 0 0x77 0,119 # w
+x 1667 0 0x78 0,120 # x
+y 1667 1 0x79 0,121 # y
+z 1667 0 0x7a 0,122 # z
+lC 1113 2 0x7b 0,123 # braceleft
+{ 1113 2 0x7b 0,123 # "
+| 867 2 0x7c 0,124 # "
+rC 1113 2 0x7d 0,125 # braceright
+} 1113 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1110 1 0xad 4,7 # exclamdown
+char162 1853 2 0x9b 4,19 # cent
+char163 1853 2 0x9c 4,11 # sterling
+char164 1853 2 0x12f 4,24 # currency
+char165 1853 2 0x9d 4,12 # yen
+char166 867 2 0x7c 0,124 # brokenbar
+char167 1853 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2457 2 0x154 4,23 # copyright
+char170 1233 2 0xa6 4,15 # ordfeminine
+char171 1853 0 0xae 4,9 # guillemotleft
+char172 1947 0 0xaa 6,20 # logicalnot
+char173 1853 0 0x132 4,33 # hyphen
+char174 2457 2 0x155 4,22 # registered
+char175 1947 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 1947 0 0xf1 6,1 # plusminus
+char178 1110 2 0xfd 4,20 # twosuperior
+char179 1110 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 1853 1 0xe6 8,25 # mu
+char182 1790 2 0x14 4,5 # paragraph
+char183 927 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1110 2 0x156 4,78 # onesuperior
+char186 1217 2 0xa7 4,16 # ordmasculine
+char187 1853 0 0xaf 4,10 # guillemotright
+char188 2780 2 0xac 4,18 # onequarter
+char189 2780 2 0xab 4,17 # onehalf
+char190 2780 2 0x12e 4,25 # threequarters
+char191 2037 1 0xa8 4,8 # questiondown
+char192 2223 2 0x15c 1,32 # Agrave
+char193 2223 2 0x15a 1,26 # Aacute
+char194 2223 2 0x15b 1,28 # Acircumflex
+char195 2223 2 0x28e 1,76 # Atilde
+char196 2223 2 0x8e 1,30 # Adieresis
+char197 2223 2 0x8f 1,34 # Aring
+char198 3333 2 0x92 1,36 # AE
+char199 2407 2 0x80 1,38 # Ccedilla
+char200 2223 2 0x160 1,46 # Egrave
+char201 2223 2 0x90 1,40 # Eacute
+char202 2223 2 0x15e 1,42 # Ecircumflex
+char203 2223 2 0x15f 1,44 # Edieresis
+char204 927 2 0x164 1,54 # Igrave
+char205 927 2 0x161 1,48 # Iacute
+char206 927 2 0x162 1,50 # Icircumflex
+char207 927 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2407 2 0xa5 1,56 # Ntilde
+char210 2593 2 0x167 1,64 # Ograve
+char211 2593 2 0x165 1,58 # Oacute
+char212 2593 2 0x166 1,60 # Ocircumflex
+char213 2593 2 0x168 1,82 # Otilde
+char214 2593 2 0x99 1,62 # Odieresis
+char215 1947 0 0x157 6,39 # multiply
+char216 2593 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 2223 2 0x16f 1,84 # Yacute
+char222 2223 2 0x13e 1,88 # Thorn
+char223 2037 2 0x147 1,23 # germandbls
+char224 1853 2 0x85 1,33 # agrave
+char225 1853 2 0xa0 1,27 # aacute
+char226 1853 2 0x83 1,29 # acircumflex
+char227 1853 2 0x284 1,93 # atilde
+char228 1853 2 0x84 1,31 # adieresis
+char229 1853 2 0x86 1,35 # aring
+char230 2963 0 0x91 1,37 # ae
+char231 1667 0 0x87 1,39 # ccedilla
+char232 1853 2 0x8a 1,47 # egrave
+char233 1853 2 0x82 1,41 # eacute
+char234 1853 2 0x88 1,43 # ecircumflex
+char235 1853 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 1853 2 0x148 1,87 # eth
+char241 1853 2 0xa4 1,57 # ntilde
+char242 1853 2 0x95 1,65 # ograve
+char243 1853 2 0xa2 1,59 # oacute
+char244 1853 2 0x93 1,61 # ocircumflex
+char245 1853 2 0x172 1,83 # otilde
+char246 1853 2 0x94 1,63 # odieresis
+char247 1947 0 0xf6 6,8 # divide
+char248 2037 0 0x145 1,81 # oslash
+char249 1853 2 0x97 1,73 # ugrave
+char250 1853 2 0xa3 1,67 # uacute
+char251 1853 2 0x96 1,69 # ucircumflex
+char252 1853 2 0x81 1,71 # udieresis
+char253 1667 3 0x175 1,85 # yacute
+char254 1853 3 0x143 1,89 # thorn
+char255 1667 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 1853 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 2223 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 1853 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 3333 2 0x92 1,36 # AE
+ae 2963 0 0x91 1,37 # ae
+OE 3333 2 0x141 1,166 # OE
+oe 3147 0 0x146 1,167 # oe
+ij 1437 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 2037 2 0x147 1,23 # germandbls
+'A 2223 2 0x15a 1,26 # Aacute
+'E 2223 2 0x90 1,40 # Eacute
+'I 927 2 0x161 1,48 # Iacute
+'O 2593 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1853 2 0xa0 1,27 # aacute
+'e 1853 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 1853 2 0xa2 1,59 # oacute
+'u 1853 2 0x95 1,65 # uacute
+:A 2223 2 0x8e 1,30 # Adieresis
+:E 2223 2 0x15f 1,44 # Edieresis
+:I 927 2 0x163 1,52 # Idieresis
+:O 2593 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 2223 2 0x16d 1,74 # Ydieresis
+:a 1853 2 0x84 1,31 # adieresis
+:e 1853 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 1853 2 0x94 1,63 # odieresis
+:u 1853 2 0x81 1,71 # udieresis
+:y 1667 3 0x98 1,75 # ydieresis
+^A 2223 2 0x15b 1,28 # Acircumflex
+^E 2223 2 0x15e 1,42 # Ecircumflex
+^I 927 2 0x162 1,50 # Icircumflex
+^O 2593 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1853 2 0x83 1,29 # acircumflex
+^e 1853 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 1853 2 0x93 1,61 # ocircumflex
+^u 1853 2 0x96 1,69 # ucircumflex
+`A 2223 2 0x15c 1,32 # Agrave
+`E 2223 2 0x160 1,46 # Egrave
+`I 927 2 0x164 1,54 # Igrave
+`O 2593 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1853 2 0x85 1,33 # agrave
+~a 1853 2 0x284 --- # atilde
+`e 1853 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 1853 2 0x95 1,65 # ograve
+`u 1853 2 0x97 1,73 # ugrave
+~A 2223 2 0x28e 1,26 # Atilde
+~N 2407 2 0xa5 1,56 # Ntilde
+~O 2593 2 0x168 1,82 # Otilde
+~n 1853 2 0xa4 1,57 # ntilde
+~o 1853 2 0x172 1,83 # otilde
+vS 2223 2 0x169 1,176 # Scaron
+vs 1667 2 0x173 1,177 # scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vz 1667 2 0x174 1,207 # zcaron
+,C 2407 2 0x80 1,38 # Ccedilla
+,c 1667 0 0x87 1,39 # ccedilla
+/L 1853 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 740 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2593 2 0x140 1,80 # Oslash
+/o 2037 0 0x145 1,81 # oslash
+oA 2223 2 0x8f 1,34 # Aring
+oa 1853 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1853 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1853 2 0x24 0,36 # dollar
+Po 1853 2 0x9c 4,11 # sterling
+Ye 1853 2 0x9d 4,12 # yen
+Fn 1853 2 0x9f 4,14 # florin
+ct 1853 2 0x9b 4,19 # cent
+Fo 1853 0 0xae 4,9 # guillemotleft
+Fc 1110 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1110 1 0xad 4,7 # exclamdown
+r? 2037 1 0xa8 4,8 # questiondown
+fi 1667 2 0x130 4,54 # fi "fi ligature"
+fl 1667 2 0x131 4,55 # fl "fl ligature"
+OK 1667 0 0x3d6 --- # \& "check mark, tick"
+Of 1233 2 0xa6 4,15 # ordfeminine
+Om 1217 2 0xa7 4,16 # ordmasculine
+S1 1110 2 0x156 4,78 # onesuperior
+S2 1110 2 0xfd 4,20 # twosuperior
+S3 1110 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 867 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 3333 0 0x123 4,34 # ru "baseline rule"
+ul 1853 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0x3f4 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2457 2 0x154 4,23 # copyright
+rg 2457 2 0x155 4,22 # registered
+tm 3333 2 0x170 4,41 # trademark
+dd 1853 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1853 2 0x12a 4,39 # dagger
+ps 1790 2 0x14 4,5 # paragraph
+sc 1853 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 3333 0 0x123 4,34 # emdash "em dash"
+en 1853 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2780 2 0xab 4,17 # onehalf
+14 2780 2 0xac 4,18 # onequarter
+34 2780 2 0x12e 4,25 # threequarters
+f/ 557 2 0x158 6,6 # fraction "bar for fractions"
+fm 557 0 0x3a2 6,45 # minute "footmark, prime"
+sd 557 0 0x3b2 6,46 # second
+ha 557 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 557 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 1947 0 0x2d 6,0 # hyphen
+lB 927 2 0x5b 0,91 # bracketleft
+rB 927 2 0x5d 0,93 # bracketright
+lC 1113 2 0x7b 0,123 # braceleft
+rC 1113 2 0x7d 0,125 # braceright
+la 1113 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1113 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1110 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1110 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1110 2 0x125 4,32 # quotedblleft
+rq 1110 2 0x4ba 6,31 # quotedblright
+oq 740 2 0x176 4,29 # quoteleft "single open quote"
+aq 637 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 867 0 0x3f4 0,124 # bar
+at 3383 2 0x40 0,64 # at
+.C1 1947 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1853 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2377 0 0x346 8,44 # Phi
+*G 1907 0 0x347 8,6 # Gamma
+*H 1907 0 0x351 8,16 # Theta
+*I 1907 0 0x349 8,18 # Iota
+*K 1907 0 0x34b 8,20 # Kappa
+*L 1907 0 0x34c 8,22 # Lambda
+*M 1907 0 0x34d 8,24 # Mu
+*N 1907 0 0x34e 8,26 # Nu
+*O 1907 0 0x34f 8,30 # Omicron
+*P 1907 0 0x350 8,32 # Pi
+*Q 1907 0 0x359 8,48 # Psi
+*R 1907 0 0x352 8,34 # Rho
+*S 1973 0 0x353 8,36 # Sigma
+*T 1973 0 0x354 8,40 # Tau
+*U 1973 0 0x3a1 8,76 # Upsilon
+*W 2547 0 0x357 8,50 # Omega
+*X 1973 0 0x343 8,36 # Chi
+*Y 1973 0 0x348 8,14 # Eta
+*Z 1973 0 0x35a 8,12 # Zeta
+*a 2023 0 0xe0 8,1 # alpha
+*b 1893 0 0xe1 8,3 # beta
+*c 1893 0 0x378 8,29 # xi
+*d 1890 0 0xeb 8,9 # delta
+*e 1890 0 0x36e 8,70 # epsilon
+*f 1890 0 0x366 8,45 # phi
++f 1890 0 0x36a 8,77 # phi1 "variant phi"
+*g 1890 0 0x367 8,7 # gamma
+*h 1853 0 0xe9 8,17 # theta
++h 1853 0 0x375 8,71 # theta1 "variant theta"
+*i 1853 0 0x369 8,19 # iota
+*k 1853 0 0x36b 8,21 # kappa
+*l 1853 0 0x36c 8,23 # lambda
+*m 1853 0 0xe6 8,25 # mu
+*n 1853 0 0x36e 8,27 # nu
+*o 1853 0 0x36f 8,31 # omicron
+*p 1963 0 0xe3 8,33 # pi
++p 1963 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 1963 0 0x379 8,49 # psi
+*r 1963 0 0x372 8,35 # rho
+*s 2037 0 0xe5 8,37 # sigma
+*t 1463 0 0xe7 8,41 # tau
+*u 1463 0 0x375 8,27 # upsilon
+*w 1463 0 0x377 8,51 # omega
+*x 1463 0 0x363 8,47 # chi
+*y 1463 0 0x368 8,15 # eta
+*z 1463 0 0x37a 8,13 # zeta
+ts 1463 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 927 0 0x32a 0,32 # asteriskmath
++- 1947 0 0xf1 6,1 # plusminus
+<= 2413 0 0xf3 6,2 # lessequal
+== 2413 0 0x3ba 8,14 # equivalence
+=~ 2413 0 0x340 8,116 # congruent
+>= 1893 0 0x3b3 8,3 # greaterequal
+AN 1893 0 0x3d9 8,85 # logicaland
+OR 1893 0 0x3da 8,86 # logicalor
+no 1893 0 0x3d8 8,20 # logicalnot
+te 1893 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 1893 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 1893 0 0x3c0 9,0 # aleph
+Im 1893 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 1893 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 1893 0 0x3a5 8,19 # infinity
+md 1893 0 0x3b7 8,32 # dotmath
+mo 1893 0 0x3ce 8,15 # element
+mu 1893 0 0x3b4 8,39 # multiply
+nc 1893 0 0x3cb 8,197 # notpropersuperset
+nm 1893 0 0x3cf 8,209 # notelement
+pl 927 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 1947 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 1947 0 0x3b5 6,4 # proportional
+pp 1947 0 0x35e 8,89 # perpendicular
+sb 1947 0 0x3cc 6,67 # propersubset
+sp 1947 0 0x3c9 6,68 # propersuperset
+ib 1947 0 0x3cd 6,69 # reflexsubset
+ip 1947 0 0x3ca 6,70 # reflexsuperset
+ap 1947 0 0x37e 6,12 # similar
+pd 1947 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 1947 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 1947 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 1947 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2593 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1853 0 0xae 6,77 # "" "much less"
+>> 1853 0 0xaf 6,78 # "" "much greater"
+wp 1853 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1853 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 927 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HNB b/contrib/groff/font/devlbp/HNB
new file mode 100644
index 0000000..c5d8d33
--- /dev/null
+++ b/contrib/groff/font/devlbp/HNB
@@ -0,0 +1,491 @@
+name HNB
+lbpname Swiss-Narrow-Bold
+special
+spacewidth 228
+slant 0
+ligatures fi fl 0
+charset
+ha 280 2 0x4c3 0,94 # asciicircum
+ti 280 0 0x4c4 0,126 # asciitilde
+vS 280 2 0x169 1,176 # Scaron
+vZ 280 2 0x16e 1,206 # Zcaron
+vs 280 2 0x173 1,177 # scaron
+vz 280 2 0x174 1,207 # zcaron
+:Y 280 2 0x16d 1,74 # Ydieresis
+tm 280 2 0x170 4,41 # trademark
+aq 195 2 0x27 0,39 # quotesingle
+space 228 0 0x20 0,32
+! 273 2 0x21 0,33 # exclam
+" 389 2 0x22 0,34 # quotedbl
+dq 389 2 0x22 0,34 # quotedbl
+# 456 2 0x23 0,35 # numbersign
+sh 456 2 0x23 0,35 # "
+$ 456 2 0x24 0,36 # dollar
+Do 456 2 0x24 0,36 # "
+% 720 2 0x25 0,37 # percent
+& 592 2 0x26 0,38 # ampersand
+' 195 2 0x27 0,39 # quoteright
+cq 195 2 0x27 0,39 # quoteright
+( 273 2 0x28 0,40 # parenleft
+) 273 2 0x29 0,41 # parenright
+* 319 2 0x2a 0,42 # asterisk
++ 479 0 0x2b 0,43 # plus
+, 228 0 0x2c 0,44 # comma
+- 479 0 0x2d 0,45 # hyphen
+hy 479 0 0x2d 0,45 # "
+char173 479 0 0x2d 0,45 # "
+. 228 0 0x2e 0,46 # period
+/ 228 2 0x2f 0,47 # slash
+sl 228 2 0x2f 0,47 # "
+0 456 2 0x30 0,48 # zero
+1 456 2 0x31 0,49 # one
+2 456 2 0x32 0,50 # two
+3 456 2 0x33 0,51 # three
+4 456 2 0x34 0,52 # four
+5 456 2 0x35 0,53 # five
+6 456 2 0x36 0,54 # six
+7 456 2 0x37 0,55 # seven
+8 456 2 0x38 0,56 # eight
+9 456 2 0x39 0,57 # nine
+: 273 0 0x3a 0,58 # colon
+; 273 0 0x3b 0,59 # semicolon
+< 479 0 0x3c 0,60 # less
+= 479 0 0x3d 0,61 # equal
+> 479 0 0x3e 0,62 # greater
+? 501 2 0x3f 0,63 # question
+@ 800 2 0x40 0,64 # at
+at 800 2 0x40 0,64 # "
+A 592 2 0x41 0,65 # A
+B 592 2 0x42 0,66 # B
+C 592 2 0x43 0,67 # C
+D 592 2 0x44 0,68 # D
+E 547 2 0x45 0,69 # E
+F 501 2 0x46 0,70 # F
+G 638 2 0x47 0,71 # G
+H 592 2 0x48 0,72 # H
+I 228 2 0x49 0,73 # I
+J 456 2 0x4a 0,74 # J
+K 592 2 0x4b 0,75 # K
+L 501 2 0x4c 0,76 # L
+M 683 2 0x4d 0,77 # M
+N 592 2 0x4e 0,78 # N
+O 638 2 0x4f 0,79 # O
+P 547 2 0x50 0,80 # P
+Q 638 2 0x51 0,81 # Q
+R 592 2 0x52 0,82 # R
+S 547 2 0x53 0,83 # S
+T 501 2 0x54 0,84 # T
+U 592 2 0x55 0,85 # U
+V 547 2 0x56 0,86 # V
+W 774 2 0x57 0,87 # W
+X 547 2 0x58 0,88 # X
+Y 547 2 0x59 0,89 # Y
+Z 501 2 0x5a 0,90 # Z
+[ 273 2 0x5b 0,91 # bracketleft
+lB 273 2 0x5b 0,91 # "
+\ 228 2 0x5c 0,92 # backslash
+rs 228 2 0x5c 0,92 # "
+] 273 2 0x5d 0,93 # bracketright
+rB 273 2 0x5d 0,93 # "
+a^ 280 2 0x5e 0,94 # circumflex
+^ 280 2 0x5e 0,94 # "
+_ 456 0 0x5f 0,95 # underscore
+` 280 2 0x60 0,96 # quoteleft
+oq 280 2 0x60 0,96 # "
+a 456 0 0x61 0,97 # a
+b 501 2 0x62 0,98 # b
+c 456 0 0x63 0,99 # c
+d 501 2 0x64 0,100 # d
+e 456 0 0x65 0,101 # e
+f 273 2 0x66 0,102 # f
+g 501 1 0x67 0,103 # g
+h 501 2 0x68 0,104 # h
+i 228 2 0x69 0,105 # i
+j 228 2 0x6a 0,106 # j
+k 456 2 0x6b 0,107 # k
+l 228 2 0x6c 0,108 # l
+m 729 0 0x6d 0,109 # m
+n 501 0 0x6e 0,110 # n
+o 501 0 0x6f 0,111 # o
+p 501 1 0x70 0,112 # p
+q 501 1 0x71 0,113 # q
+r 319 0 0x72 0,114 # r
+s 456 0 0x73 0,115 # s
+t 273 2 0x74 0,116 # t
+u 501 0 0x75 0,117 # u
+v 456 0 0x76 0,118 # v
+w 638 0 0x77 0,119 # w
+x 456 0 0x78 0,120 # x
+y 456 1 0x79 0,121 # y
+z 410 0 0x7a 0,122 # z
+lC 319 2 0x7b 0,123 # braceleft
+{ 319 2 0x7b 0,123 # "
+| 230 2 0x7c 0,124 # "
+rC 319 2 0x7d 0,125 # braceright
+} 319 2 0x7d 0,125 # "
+a~ 280 2 0x7e 0,126 # tilde
+~ 280 2 0x7e 0,126 # "
+char161 273 1 0xad 4,7 # exclamdown
+char162 456 2 0x9b 4,19 # cent
+char163 456 2 0x9c 4,11 # sterling
+char164 456 2 0x12f 4,24 # currency
+char165 456 2 0x9d 4,12 # yen
+char166 230 2 0x7c 0,124 # brokenbar
+char167 456 2 0x15 4,6 # section
+char168 273 2 0x122 1,7 # dieresis
+char169 604 2 0x154 4,23 # copyright
+char170 303 2 0xa6 4,15 # ordfeminine
+char171 456 0 0xae 4,9 # guillemotleft
+char172 479 0 0xaa 6,20 # logicalnot
+char173 456 0 0x132 4,33 # hyphen
+char174 604 2 0x155 4,22 # registered
+char175 500 2 0x2d 6,0 # macron
+char176 328 2 0xf8 6,36 # degree
+char177 479 0 0xf1 6,1 # plusminus
+char178 273 2 0xfd 4,20 # twosuperior
+char179 273 2 0x14d 4,26 # threesuperior
+char180 273 2 0x120 1,6 # acute "acute accent"
+char181 501 1 0xe6 8,25 # mu
+char182 456 2 0x14 4,5 # paragraph
+char183 240 0 0xfa 6,32 # periodcentered
+char184 273 0 0x139 1,17 # cedilla
+char185 273 2 0x156 4,78 # onesuperior
+char186 299 2 0xa7 4,16 # ordmasculine
+char187 456 0 0xaf 4,10 # guillemotright
+char188 684 2 0xac 4,18 # onequarter
+char189 684 2 0xab 4,17 # onehalf
+char190 684 2 0x12e 4,25 # threequarters
+char191 501 1 0xa8 4,8 # questiondown
+char192 501 2 0x15c 1,32 # Agrave
+char193 501 2 0x15a 1,26 # Aacute
+char194 501 2 0x15b 1,28 # Acircumflex
+char195 501 2 0x28e 1,76 # Atilde
+char196 592 2 0x8e 1,30 # Adieresis
+char197 592 2 0x8f 1,34 # Aring
+char198 820 2 0x92 1,36 # AE
+char199 592 2 0x80 1,38 # Ccedilla
+char200 592 2 0x160 1,46 # Egrave
+char201 547 2 0x90 1,40 # Eacute
+char202 547 2 0x15e 1,42 # Ecircumflex
+char203 547 2 0x15f 1,44 # Edieresis
+char204 547 2 0x164 1,54 # Igrave
+char205 547 2 0x161 1,48 # Iacute
+char206 547 2 0x162 1,50 # Icircumflex
+char207 547 2 0x163 1,52 # Idieresis
+char208 592 2 0x13d 1,78 # Eth
+char209 592 2 0xa5 1,56 # Ntilde
+char210 592 2 0x167 1,64 # Ograve
+char211 592 2 0x165 1,58 # Oacute
+char212 592 2 0x166 1,60 # Ocircumflex
+char213 592 2 0x168 1,82 # Otilde
+char214 638 2 0x99 1,62 # Odieresis
+char215 479 0 0x157 6,39 # multiply
+char216 638 2 0x140 1,80 # Oslash
+char217 638 2 0x16c 1,72 # Ugrave
+char218 638 2 0x16a 1,66 # Uacute
+char219 638 2 0x16b 1,68 # Ucircumflex
+char220 592 2 0x9a 1,70 # Udieresis
+char221 592 2 0x16f 1,84 # Yacute
+char222 547 2 0x13e 1,88 # Thorn
+char223 501 2 0x147 1,23 # germandbls
+char224 456 2 0x85 1,33 # agrave
+char225 456 2 0xa0 1,27 # aacute
+char226 456 2 0x83 1,29 # acircumflex
+char227 456 2 0x284 1,93 # atilde
+char228 456 2 0x84 1,31 # adieresis
+char229 456 2 0x86 1,35 # aring
+char230 729 0 0x91 1,37 # ae
+char231 456 0 0x87 1,39 # ccedilla
+char232 456 2 0x8a 1,47 # egrave
+char233 456 2 0x82 1,41 # eacute
+char234 456 2 0x88 1,43 # ecircumflex
+char235 456 2 0x89 1,45 # edieresis
+char236 228 2 0x8d 1,55 # igrave
+char237 228 2 0xa1 1,49 # iacute
+char238 228 2 0x8c 1,51 # icircumflex
+char239 228 2 0x8b 1,53 # idieresis
+char240 501 2 0x148 1,87 # eth
+char241 501 2 0xa4 1,57 # ntilde
+char242 501 2 0x95 1,65 # ograve
+char243 501 2 0xa2 1,59 # oacute
+char244 501 2 0x93 1,61 # ocircumflex
+char245 501 2 0x172 1,83 # otilde
+char246 501 2 0x94 1,63 # odieresis
+char247 479 0 0xf6 6,8 # divide
+char248 501 0 0x145 1,81 # oslash
+char249 501 2 0x97 1,73 # ugrave
+char250 501 2 0xa3 1,67 # uacute
+char251 501 2 0x96 1,69 # ucircumflex
+char252 501 2 0x81 1,71 # udieresis
+char253 501 3 0x175 1,85 # yacute
+char254 501 3 0x143 1,89 # thorn
+char255 456 3 0x98 1,75 # ydieresis
+-D 592 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 501 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 547 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 501 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 820 2 0x92 1,36 # AE
+ae 729 0 0x91 1,37 # ae
+OE 820 2 0x141 1,166 # OE
+oe 774 0 0x146 1,167 # oe
+ij 450 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 501 2 0x147 1,23 # germandbls
+'A 501 2 0x15a 1,26 # Aacute
+'E 547 2 0x90 1,40 # Eacute
+'I 547 2 0x161 1,48 # Iacute
+'O 547 2 0x165 1,58 # Oacute
+'U 547 2 0x16a 1,66 # Uacute
+'a 456 2 0xa0 1,27 # aacute
+'e 456 2 0x82 1,41 # eacute
+'i 228 2 0xa1 1,49 # iacute
+'o 501 2 0xa2 1,59 # oacute
+'u 501 2 0x95 1,65 # uacute
+:A 592 2 0x8e 1,30 # Adieresis
+:E 592 2 0x15f 1,44 # Edieresis
+:I 592 2 0x163 1,52 # Idieresis
+:O 638 2 0x99 1,62 # Odieresis
+:U 592 2 0x9a 1,70 # Udieresis
+:Y 592 2 0x16d 1,74 # Ydieresis
+:a 456 2 0x84 1,31 # adieresis
+:e 456 2 0x89 1,45 # edieresis
+:i 228 2 0x8b 1,53 # idieresis
+:o 501 2 0x94 1,63 # odieresis
+:u 501 2 0x81 1,71 # udieresis
+:y 456 3 0x98 1,75 # ydieresis
+^A 456 2 0x15b 1,28 # Acircumflex
+^E 456 2 0x15e 1,42 # Ecircumflex
+^I 456 2 0x162 1,50 # Icircumflex
+^O 456 2 0x166 1,60 # Ocircumflex
+^U 456 2 0x16b 1,68 # Ucircumflex
+^a 456 2 0x83 1,29 # acircumflex
+^e 456 2 0x88 1,43 # ecircumflex
+^i 228 2 0x8c 1,51 # icircumflex
+^o 501 2 0x93 1,61 # ocircumflex
+^u 501 2 0x96 1,69 # ucircumflex
+`A 501 2 0x15c 1,32 # Agrave
+`E 501 2 0x160 1,46 # Egrave
+`I 501 2 0x164 1,54 # Igrave
+`O 501 2 0x167 1,64 # Ograve
+`U 501 2 0x16c 1,72 # Ugrave
+`a 456 2 0x85 1,33 # agrave
+~a 456 2 0x284 --- # atilde
+`e 456 2 0x8a 1,47 # egrave
+`i 228 2 0x8d 1,55 # igrave
+`o 501 2 0x95 1,65 # ograve
+`u 501 2 0x97 1,73 # ugrave
+~A 501 2 0x28e 1,26 # Atilde
+~N 592 2 0xa5 1,56 # Ntilde
+~O 592 2 0x168 1,82 # Otilde
+~n 501 2 0xa4 1,57 # ntilde
+~o 501 2 0x172 1,83 # otilde
+vS 501 2 0x169 1,176 # Scaron
+vs 501 2 0x173 1,177 # scaron
+vZ 501 2 0x16e 1,206 # Zcaron
+vz 501 2 0x174 1,207 # zcaron
+,C 592 2 0x80 1,38 # Ccedilla
+,c 456 0 0x87 1,39 # ccedilla
+/L 501 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 228 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 638 2 0x140 1,80 # Oslash
+/o 501 0 0x145 1,81 # oslash
+oA 592 2 0x8f 1,34 # Aring
+oa 456 2 0x86 1,35 # aring
+a" 273 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 273 2 0x135 1,8 # macron "macron or bar accent"
+a. 273 2 0x137 1,15 # dotaccent "dot accent"
+a^ 273 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 273 2 0x120 1,6 # acute "acute accent"
+ga 273 2 0x121 1,0 # grave "grave accent"
+ab 273 2 0x136 1,22 # breve "breve accent"
+ac 273 0 0x139 1,17 # cedilla "cedilla accent"
+ad 273 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 273 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 273 2 0x138 1,14 # ring "ring or circle accent"
+a~ 273 2 0x7e 1,2 # tilde "tilde accent"
+ho 273 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 228 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 456 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 456 2 0x24 0,36 # dollar
+Po 456 2 0x9c 4,11 # sterling
+Ye 456 2 0x9d 4,12 # yen
+Fn 456 2 0x9f 4,14 # florin
+ct 456 2 0x9b 4,19 # cent
+Fo 456 0 0xae 4,9 # guillemotleft
+Fc 273 0 0x4bb 4,20 # guillemotright
+fo 273 0 0x127 4,35 # guilsinglleft
+fc 273 0 0x128 4,36 # guilsinglright
+r! 273 1 0xad 4,7 # exclamdown
+r? 501 1 0xa8 4,8 # questiondown
+fi 501 2 0x130 4,54 # fi "fi ligature"
+fl 501 2 0x131 4,55 # fl "fl ligature"
+OK 501 0 0x3d6 --- # \& "check mark, tick"
+Of 303 2 0xa6 4,15 # ordfeminine
+Om 299 2 0xa7 4,16 # ordmasculine
+S1 273 2 0x156 4,78 # onesuperior
+S2 273 2 0xfd 4,20 # twosuperior
+S3 273 2 0x14d 4,26 # threesuperior
+<- 809 0 0x1b 6,22 # arrowleft
+-> 809 0 0x1a 6,21 # arrowright
+<> 854 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 494 0 0x19 6,24 # arrowdown
+ua 494 0 0x18 6,23 # arrowup
+va 494 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 494 0 0x3dc 6,57 # arrowdblleft
+rA 494 0 0x3de 6,56 # arrowdblright
+hA 494 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 494 0 0x3df 6,59 # arrowdbldown
+uA 494 0 0x3dd 6,58 # arrowdblup
+ba 820 2 0xb3 3,9 # bar
+bb 230 2 0x7c 0,124 # brokenbar
+br 820 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 820 0 0x123 4,34 # ru "baseline rule"
+ul 456 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 820 0 0x3f4 3,9 # bv "bold vertical"
+ci 699 0 0x9 4,1 # circle
+bu 522 0 0x7 4,0 # bullet
+co 604 2 0x154 4,23 # copyright
+rg 604 2 0x155 4,22 # registered
+tm 604 2 0x170 4,41 # trademark
+dd 456 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 456 2 0x12a 4,39 # dagger
+ps 456 2 0x14 4,5 # paragraph
+sc 456 2 0x15 4,6 # section
+de 328 2 0xf8 6,36 # degree
+em 820 0 0x123 4,34 # emdash "em dash"
+en 456 0 0x132 4,33 # endash "en dash"
+%0 820 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 684 2 0xab 4,17 # onehalf
+14 684 2 0xac 4,18 # onequarter
+34 684 2 0x12e 4,25 # threequarters
+f/ 137 2 0x158 6,6 # fraction "bar for fractions"
+fm 137 0 0x3a2 6,45 # minute "footmark, prime"
+sd 137 0 0x3b2 6,46 # second
+ha 137 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 137 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 500 0 0x2d 6,0 # hyphen
+lB 273 2 0x5b 0,91 # bracketleft
+rB 273 2 0x5d 0,93 # bracketright
+lC 319 2 0x7b 0,123 # braceleft
+rC 319 2 0x7d 0,125 # braceright
+la 319 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 319 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 410 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 410 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 410 2 0x125 4,32 # quotedblleft
+rq 410 2 0x4ba 6,31 # quotedblright
+oq 228 2 0x176 4,29 # quoteleft "single open quote"
+aq 195 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 230 0 0x3f4 0,124 # bar
+at 800 2 0x40 0,64 # at
+.C1 479 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 456 2 0x23 0,35 # numbersign
+sl 228 2 0x2f 0,47 # slash
+rs 228 2 0x5c 0,92 # backslash
+3d 228 0 0x35c 6,102 # therefore
+tf 228 0 0x35c 6,102 # therefore
+*A 228 0 0x341 8,0 # Alpha
+*B 228 0 0x342 8,2 # Beta
+*C 228 0 0x358 8,28 # Xi
+*D 228 0 0x344 8,8 # Delta
+*E 228 0 0x345 8,10 # Epsilon
+*F 609 0 0x346 8,44 # Phi
+*G 481 0 0x347 8,6 # Gamma
+*H 481 0 0x351 8,16 # Theta
+*I 481 0 0x349 8,18 # Iota
+*K 481 0 0x34b 8,20 # Kappa
+*L 481 0 0x34c 8,22 # Lambda
+*M 481 0 0x34d 8,24 # Mu
+*N 481 0 0x34e 8,26 # Nu
+*O 481 0 0x34f 8,30 # Omicron
+*P 481 0 0x350 8,32 # Pi
+*Q 481 0 0x359 8,48 # Psi
+*R 481 0 0x352 8,34 # Rho
+*S 481 0 0x353 8,36 # Sigma
+*T 481 0 0x354 8,40 # Tau
+*U 481 0 0x3a1 8,76 # Upsilon
+*W 630 0 0x357 8,50 # Omega
+*X 481 0 0x343 8,36 # Chi
+*Y 481 0 0x348 8,14 # Eta
+*Z 481 0 0x35a 8,12 # Zeta
+*a 499 0 0xe0 8,1 # alpha
+*b 499 0 0xe1 8,3 # beta
+*c 499 0 0x378 8,29 # xi
+*d 487 0 0xeb 8,9 # delta
+*e 487 0 0x36e 8,70 # epsilon
+*f 487 0 0x366 8,45 # phi
++f 487 0 0x36a 8,77 # phi1 "variant phi"
+*g 487 0 0x367 8,7 # gamma
+*h 486 0 0xe9 8,17 # theta
++h 486 0 0x375 8,71 # theta1 "variant theta"
+*i 486 0 0x369 8,19 # iota
+*k 486 0 0x36b 8,21 # kappa
+*l 486 0 0x36c 8,23 # lambda
+*m 501 0 0xe6 8,25 # mu
+*n 501 0 0x36e 8,27 # nu
+*o 501 0 0x36f 8,31 # omicron
+*p 527 0 0xe3 8,33 # pi
++p 527 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 527 0 0x379 8,49 # psi
+*r 527 0 0x372 8,35 # rho
+*s 531 0 0xe5 8,37 # sigma
+*t 375 0 0xe7 8,41 # tau
+*u 375 0 0x375 8,27 # upsilon
+*w 375 0 0x377 8,51 # omega
+*x 375 0 0x363 8,47 # chi
+*y 375 0 0x368 8,15 # eta
+*z 375 0 0x37a 8,13 # zeta
+ts 375 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 655 0 0xf7 6,13 # approxequal
+~= 655 0 0xf7 6,13 # approxequal
+!= 655 0 0x3b9 6,99 # notequal
+** 228 0 0x32a 0,32 # asteriskmath
++- 479 0 0xf1 6,1 # plusminus
+<= 592 0 0xf3 6,2 # lessequal
+== 592 0 0x3ba 8,14 # equivalence
+=~ 592 0 0x340 8,116 # congruent
+>= 499 0 0x3b3 8,3 # greaterequal
+AN 499 0 0x3d9 8,85 # logicaland
+OR 499 0 0x3da 8,86 # logicalor
+no 499 0 0x3d8 8,20 # logicalnot
+te 499 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 499 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 499 0 0x3c0 9,0 # aleph
+Im 499 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 499 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 499 0 0x3a5 8,19 # infinity
+md 499 0 0x3b7 8,32 # dotmath
+mo 499 0 0x3ce 8,15 # element
+mu 499 0 0x3b4 8,39 # multiply
+nc 499 0 0x3cb 8,197 # notpropersuperset
+nm 499 0 0x3cf 8,209 # notelement
+pl 273 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 479 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 479 0 0x3b5 6,4 # proportional
+pp 479 0 0x35e 8,89 # perpendicular
+sb 479 0 0x3cc 6,67 # propersubset
+sp 479 0 0x3c9 6,68 # propersuperset
+ib 479 0 0x3cd 6,69 # reflexsubset
+ip 479 0 0x3ca 6,70 # reflexsuperset
+ap 479 0 0x37e 6,12 # similar
+pd 479 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 479 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 479 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 645 0 0xef 6,16 # intersection "intersection, cap"
+cu 645 0 0x3c8 6,66 # union "union, cup"
+di 479 0 0x3b8 6,8 # divide "division sign"
+-h 820 0 0xc4 3,8 # hbar
+gr 820 0 0x3d1 6,33 # gradient
+es 638 0 0x3c6 0,79 # emptyset
+CL 617 0 0x5 5,168 # club "club suit"
+SP 617 0 0x6 5,171 # spade "spade suit"
+HE 617 0 0x3 5,170 # heart "heart suit"
+DI 617 0 0x4 5,169 # diamond "diamond suit"
+CR 617 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 617 0 0x327 6,71 # suchthat
+/_ 617 0 0x3d0 6,79 # angle
+<< 456 0 0xae 6,77 # "" "much less"
+>> 456 0 0xaf 6,78 # "" "much greater"
+wp 456 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 456 0 0x3e0 6,95 # lozenge
+an 820 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 240 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HNBI b/contrib/groff/font/devlbp/HNBI
new file mode 100644
index 0000000..14bd4e3
--- /dev/null
+++ b/contrib/groff/font/devlbp/HNBI
@@ -0,0 +1,491 @@
+name HNBI
+lbpname Swiss-Narrow-BoldOblique
+special
+spacewidth 228
+slant 0
+ligatures fi fl 0
+charset
+ha 280 2 0x4c3 0,94 # asciicircum
+ti 280 0 0x4c4 0,126 # asciitilde
+vS 280 2 0x169 1,176 # Scaron
+vZ 280 2 0x16e 1,206 # Zcaron
+vs 280 2 0x173 1,177 # scaron
+vz 280 2 0x174 1,207 # zcaron
+:Y 280 2 0x16d 1,74 # Ydieresis
+tm 280 2 0x170 4,41 # trademark
+aq 195 2 0x27 0,39 # quotesingle
+space 228 0 0x20 0,32
+! 273 2 0x21 0,33 # exclam
+" 389 2 0x22 0,34 # quotedbl
+dq 389 2 0x22 0,34 # quotedbl
+# 456 2 0x23 0,35 # numbersign
+sh 456 2 0x23 0,35 # "
+$ 456 2 0x24 0,36 # dollar
+Do 456 2 0x24 0,36 # "
+% 720 2 0x25 0,37 # percent
+& 592 2 0x26 0,38 # ampersand
+' 195 2 0x27 0,39 # quoteright
+cq 195 2 0x27 0,39 # quoteright
+( 273 2 0x28 0,40 # parenleft
+) 273 2 0x29 0,41 # parenright
+* 319 2 0x2a 0,42 # asterisk
++ 479 0 0x2b 0,43 # plus
+, 228 0 0x2c 0,44 # comma
+- 479 0 0x2d 0,45 # hyphen
+hy 479 0 0x2d 0,45 # "
+char173 479 0 0x2d 0,45 # "
+. 228 0 0x2e 0,46 # period
+/ 228 2 0x2f 0,47 # slash
+sl 228 2 0x2f 0,47 # "
+0 456 2 0x30 0,48 # zero
+1 456 2 0x31 0,49 # one
+2 456 2 0x32 0,50 # two
+3 456 2 0x33 0,51 # three
+4 456 2 0x34 0,52 # four
+5 456 2 0x35 0,53 # five
+6 456 2 0x36 0,54 # six
+7 456 2 0x37 0,55 # seven
+8 456 2 0x38 0,56 # eight
+9 456 2 0x39 0,57 # nine
+: 273 0 0x3a 0,58 # colon
+; 273 0 0x3b 0,59 # semicolon
+< 479 0 0x3c 0,60 # less
+= 479 0 0x3d 0,61 # equal
+> 479 0 0x3e 0,62 # greater
+? 501 2 0x3f 0,63 # question
+@ 800 2 0x40 0,64 # at
+at 800 2 0x40 0,64 # "
+A 592 2 0x41 0,65 # A
+B 592 2 0x42 0,66 # B
+C 592 2 0x43 0,67 # C
+D 592 2 0x44 0,68 # D
+E 547 2 0x45 0,69 # E
+F 501 2 0x46 0,70 # F
+G 638 2 0x47 0,71 # G
+H 592 2 0x48 0,72 # H
+I 228 2 0x49 0,73 # I
+J 456 2 0x4a 0,74 # J
+K 592 2 0x4b 0,75 # K
+L 501 2 0x4c 0,76 # L
+M 683 2 0x4d 0,77 # M
+N 592 2 0x4e 0,78 # N
+O 638 2 0x4f 0,79 # O
+P 547 2 0x50 0,80 # P
+Q 638 2 0x51 0,81 # Q
+R 592 2 0x52 0,82 # R
+S 547 2 0x53 0,83 # S
+T 501 2 0x54 0,84 # T
+U 592 2 0x55 0,85 # U
+V 547 2 0x56 0,86 # V
+W 774 2 0x57 0,87 # W
+X 547 2 0x58 0,88 # X
+Y 547 2 0x59 0,89 # Y
+Z 501 2 0x5a 0,90 # Z
+[ 273 2 0x5b 0,91 # bracketleft
+lB 273 2 0x5b 0,91 # "
+\ 228 2 0x5c 0,92 # backslash
+rs 228 2 0x5c 0,92 # "
+] 273 2 0x5d 0,93 # bracketright
+rB 273 2 0x5d 0,93 # "
+a^ 280 2 0x5e 0,94 # circumflex
+^ 280 2 0x5e 0,94 # "
+_ 456 0 0x5f 0,95 # underscore
+` 280 2 0x60 0,96 # quoteleft
+oq 280 2 0x60 0,96 # "
+a 456 0 0x61 0,97 # a
+b 501 2 0x62 0,98 # b
+c 456 0 0x63 0,99 # c
+d 501 2 0x64 0,100 # d
+e 456 0 0x65 0,101 # e
+f 273 2 0x66 0,102 # f
+g 501 1 0x67 0,103 # g
+h 501 2 0x68 0,104 # h
+i 228 2 0x69 0,105 # i
+j 228 2 0x6a 0,106 # j
+k 456 2 0x6b 0,107 # k
+l 228 2 0x6c 0,108 # l
+m 729 0 0x6d 0,109 # m
+n 501 0 0x6e 0,110 # n
+o 501 0 0x6f 0,111 # o
+p 501 1 0x70 0,112 # p
+q 501 1 0x71 0,113 # q
+r 319 0 0x72 0,114 # r
+s 456 0 0x73 0,115 # s
+t 273 2 0x74 0,116 # t
+u 501 0 0x75 0,117 # u
+v 456 0 0x76 0,118 # v
+w 638 0 0x77 0,119 # w
+x 456 0 0x78 0,120 # x
+y 456 1 0x79 0,121 # y
+z 410 0 0x7a 0,122 # z
+lC 319 2 0x7b 0,123 # braceleft
+{ 319 2 0x7b 0,123 # "
+| 230 2 0x7c 0,124 # "
+rC 319 2 0x7d 0,125 # braceright
+} 319 2 0x7d 0,125 # "
+a~ 280 2 0x7e 0,126 # tilde
+~ 280 2 0x7e 0,126 # "
+char161 273 1 0xad 4,7 # exclamdown
+char162 456 2 0x9b 4,19 # cent
+char163 456 2 0x9c 4,11 # sterling
+char164 456 2 0x12f 4,24 # currency
+char165 456 2 0x9d 4,12 # yen
+char166 230 2 0x7c 0,124 # brokenbar
+char167 456 2 0x15 4,6 # section
+char168 273 2 0x122 1,7 # dieresis
+char169 604 2 0x154 4,23 # copyright
+char170 303 2 0xa6 4,15 # ordfeminine
+char171 456 0 0xae 4,9 # guillemotleft
+char172 479 0 0xaa 6,20 # logicalnot
+char173 456 0 0x132 4,33 # hyphen
+char174 604 2 0x155 4,22 # registered
+char175 500 2 0x2d 6,0 # macron
+char176 328 2 0xf8 6,36 # degree
+char177 479 0 0xf1 6,1 # plusminus
+char178 273 2 0xfd 4,20 # twosuperior
+char179 273 2 0x14d 4,26 # threesuperior
+char180 273 2 0x120 1,6 # acute "acute accent"
+char181 501 1 0xe6 8,25 # mu
+char182 456 2 0x14 4,5 # paragraph
+char183 240 0 0xfa 6,32 # periodcentered
+char184 273 0 0x139 1,17 # cedilla
+char185 273 2 0x156 4,78 # onesuperior
+char186 299 2 0xa7 4,16 # ordmasculine
+char187 456 0 0xaf 4,10 # guillemotright
+char188 684 2 0xac 4,18 # onequarter
+char189 684 2 0xab 4,17 # onehalf
+char190 684 2 0x12e 4,25 # threequarters
+char191 501 1 0xa8 4,8 # questiondown
+char192 501 2 0x15c 1,32 # Agrave
+char193 501 2 0x15a 1,26 # Aacute
+char194 501 2 0x15b 1,28 # Acircumflex
+char195 501 2 0x28e 1,76 # Atilde
+char196 592 2 0x8e 1,30 # Adieresis
+char197 592 2 0x8f 1,34 # Aring
+char198 820 2 0x92 1,36 # AE
+char199 592 2 0x80 1,38 # Ccedilla
+char200 592 2 0x160 1,46 # Egrave
+char201 547 2 0x90 1,40 # Eacute
+char202 547 2 0x15e 1,42 # Ecircumflex
+char203 547 2 0x15f 1,44 # Edieresis
+char204 547 2 0x164 1,54 # Igrave
+char205 547 2 0x161 1,48 # Iacute
+char206 547 2 0x162 1,50 # Icircumflex
+char207 547 2 0x163 1,52 # Idieresis
+char208 592 2 0x13d 1,78 # Eth
+char209 592 2 0xa5 1,56 # Ntilde
+char210 592 2 0x167 1,64 # Ograve
+char211 592 2 0x165 1,58 # Oacute
+char212 592 2 0x166 1,60 # Ocircumflex
+char213 592 2 0x168 1,82 # Otilde
+char214 638 2 0x99 1,62 # Odieresis
+char215 479 0 0x157 6,39 # multiply
+char216 638 2 0x140 1,80 # Oslash
+char217 638 2 0x16c 1,72 # Ugrave
+char218 638 2 0x16a 1,66 # Uacute
+char219 638 2 0x16b 1,68 # Ucircumflex
+char220 592 2 0x9a 1,70 # Udieresis
+char221 592 2 0x16f 1,84 # Yacute
+char222 547 2 0x13e 1,88 # Thorn
+char223 501 2 0x147 1,23 # germandbls
+char224 456 2 0x85 1,33 # agrave
+char225 456 2 0xa0 1,27 # aacute
+char226 456 2 0x83 1,29 # acircumflex
+char227 456 2 0x284 1,93 # atilde
+char228 456 2 0x84 1,31 # adieresis
+char229 456 2 0x86 1,35 # aring
+char230 729 0 0x91 1,37 # ae
+char231 456 0 0x87 1,39 # ccedilla
+char232 456 2 0x8a 1,47 # egrave
+char233 456 2 0x82 1,41 # eacute
+char234 456 2 0x88 1,43 # ecircumflex
+char235 456 2 0x89 1,45 # edieresis
+char236 228 2 0x8d 1,55 # igrave
+char237 228 2 0xa1 1,49 # iacute
+char238 228 2 0x8c 1,51 # icircumflex
+char239 228 2 0x8b 1,53 # idieresis
+char240 501 2 0x148 1,87 # eth
+char241 501 2 0xa4 1,57 # ntilde
+char242 501 2 0x95 1,65 # ograve
+char243 501 2 0xa2 1,59 # oacute
+char244 501 2 0x93 1,61 # ocircumflex
+char245 501 2 0x172 1,83 # otilde
+char246 501 2 0x94 1,63 # odieresis
+char247 479 0 0xf6 6,8 # divide
+char248 501 0 0x145 1,81 # oslash
+char249 501 2 0x97 1,73 # ugrave
+char250 501 2 0xa3 1,67 # uacute
+char251 501 2 0x96 1,69 # ucircumflex
+char252 501 2 0x81 1,71 # udieresis
+char253 501 3 0x175 1,85 # yacute
+char254 501 3 0x143 1,89 # thorn
+char255 456 3 0x98 1,75 # ydieresis
+-D 592 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 501 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 547 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 501 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 820 2 0x92 1,36 # AE
+ae 729 0 0x91 1,37 # ae
+OE 820 2 0x141 1,166 # OE
+oe 774 0 0x146 1,167 # oe
+ij 450 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 501 2 0x147 1,23 # germandbls
+'A 501 2 0x15a 1,26 # Aacute
+'E 547 2 0x90 1,40 # Eacute
+'I 547 2 0x161 1,48 # Iacute
+'O 547 2 0x165 1,58 # Oacute
+'U 547 2 0x16a 1,66 # Uacute
+'a 456 2 0xa0 1,27 # aacute
+'e 456 2 0x82 1,41 # eacute
+'i 228 2 0xa1 1,49 # iacute
+'o 501 2 0xa2 1,59 # oacute
+'u 501 2 0x95 1,65 # uacute
+:A 592 2 0x8e 1,30 # Adieresis
+:E 592 2 0x15f 1,44 # Edieresis
+:I 592 2 0x163 1,52 # Idieresis
+:O 638 2 0x99 1,62 # Odieresis
+:U 592 2 0x9a 1,70 # Udieresis
+:Y 592 2 0x16d 1,74 # Ydieresis
+:a 456 2 0x84 1,31 # adieresis
+:e 456 2 0x89 1,45 # edieresis
+:i 228 2 0x8b 1,53 # idieresis
+:o 501 2 0x94 1,63 # odieresis
+:u 501 2 0x81 1,71 # udieresis
+:y 456 3 0x98 1,75 # ydieresis
+^A 456 2 0x15b 1,28 # Acircumflex
+^E 456 2 0x15e 1,42 # Ecircumflex
+^I 456 2 0x162 1,50 # Icircumflex
+^O 456 2 0x166 1,60 # Ocircumflex
+^U 456 2 0x16b 1,68 # Ucircumflex
+^a 456 2 0x83 1,29 # acircumflex
+^e 456 2 0x88 1,43 # ecircumflex
+^i 228 2 0x8c 1,51 # icircumflex
+^o 501 2 0x93 1,61 # ocircumflex
+^u 501 2 0x96 1,69 # ucircumflex
+`A 501 2 0x15c 1,32 # Agrave
+`E 501 2 0x160 1,46 # Egrave
+`I 501 2 0x164 1,54 # Igrave
+`O 501 2 0x167 1,64 # Ograve
+`U 501 2 0x16c 1,72 # Ugrave
+`a 456 2 0x85 1,33 # agrave
+~a 456 2 0x284 --- # atilde
+`e 456 2 0x8a 1,47 # egrave
+`i 228 2 0x8d 1,55 # igrave
+`o 501 2 0x95 1,65 # ograve
+`u 501 2 0x97 1,73 # ugrave
+~A 501 2 0x28e 1,26 # Atilde
+~N 592 2 0xa5 1,56 # Ntilde
+~O 592 2 0x168 1,82 # Otilde
+~n 501 2 0xa4 1,57 # ntilde
+~o 501 2 0x172 1,83 # otilde
+vS 501 2 0x169 1,176 # Scaron
+vs 501 2 0x173 1,177 # scaron
+vZ 501 2 0x16e 1,206 # Zcaron
+vz 501 2 0x174 1,207 # zcaron
+,C 592 2 0x80 1,38 # Ccedilla
+,c 456 0 0x87 1,39 # ccedilla
+/L 501 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 228 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 638 2 0x140 1,80 # Oslash
+/o 501 0 0x145 1,81 # oslash
+oA 592 2 0x8f 1,34 # Aring
+oa 456 2 0x86 1,35 # aring
+a" 273 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 273 2 0x135 1,8 # macron "macron or bar accent"
+a. 273 2 0x137 1,15 # dotaccent "dot accent"
+a^ 273 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 273 2 0x120 1,6 # acute "acute accent"
+ga 273 2 0x121 1,0 # grave "grave accent"
+ab 273 2 0x136 1,22 # breve "breve accent"
+ac 273 0 0x139 1,17 # cedilla "cedilla accent"
+ad 273 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 273 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 273 2 0x138 1,14 # ring "ring or circle accent"
+a~ 273 2 0x7e 1,2 # tilde "tilde accent"
+ho 273 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 228 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 456 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 456 2 0x24 0,36 # dollar
+Po 456 2 0x9c 4,11 # sterling
+Ye 456 2 0x9d 4,12 # yen
+Fn 456 2 0x9f 4,14 # florin
+ct 456 2 0x9b 4,19 # cent
+Fo 456 0 0xae 4,9 # guillemotleft
+Fc 273 0 0x4bb 4,20 # guillemotright
+fo 273 0 0x127 4,35 # guilsinglleft
+fc 273 0 0x128 4,36 # guilsinglright
+r! 273 1 0xad 4,7 # exclamdown
+r? 501 1 0xa8 4,8 # questiondown
+fi 501 2 0x130 4,54 # fi "fi ligature"
+fl 501 2 0x131 4,55 # fl "fl ligature"
+OK 501 0 0x3d6 --- # \& "check mark, tick"
+Of 303 2 0xa6 4,15 # ordfeminine
+Om 299 2 0xa7 4,16 # ordmasculine
+S1 273 2 0x156 4,78 # onesuperior
+S2 273 2 0xfd 4,20 # twosuperior
+S3 273 2 0x14d 4,26 # threesuperior
+<- 809 0 0x1b 6,22 # arrowleft
+-> 809 0 0x1a 6,21 # arrowright
+<> 854 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 494 0 0x19 6,24 # arrowdown
+ua 494 0 0x18 6,23 # arrowup
+va 494 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 494 0 0x3dc 6,57 # arrowdblleft
+rA 494 0 0x3de 6,56 # arrowdblright
+hA 494 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 494 0 0x3df 6,59 # arrowdbldown
+uA 494 0 0x3dd 6,58 # arrowdblup
+ba 820 2 0xb3 3,9 # bar
+bb 230 2 0x7c 0,124 # brokenbar
+br 820 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 820 0 0x123 4,34 # ru "baseline rule"
+ul 456 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 820 0 0x3f4 3,9 # bv "bold vertical"
+ci 699 0 0x9 4,1 # circle
+bu 522 0 0x7 4,0 # bullet
+co 604 2 0x154 4,23 # copyright
+rg 604 2 0x155 4,22 # registered
+tm 604 2 0x170 4,41 # trademark
+dd 456 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 456 2 0x12a 4,39 # dagger
+ps 456 2 0x14 4,5 # paragraph
+sc 456 2 0x15 4,6 # section
+de 328 2 0xf8 6,36 # degree
+em 820 0 0x123 4,34 # emdash "em dash"
+en 456 0 0x132 4,33 # endash "en dash"
+%0 820 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 684 2 0xab 4,17 # onehalf
+14 684 2 0xac 4,18 # onequarter
+34 684 2 0x12e 4,25 # threequarters
+f/ 137 2 0x158 6,6 # fraction "bar for fractions"
+fm 137 0 0x3a2 6,45 # minute "footmark, prime"
+sd 137 0 0x3b2 6,46 # second
+ha 137 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 137 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 500 0 0x2d 6,0 # hyphen
+lB 273 2 0x5b 0,91 # bracketleft
+rB 273 2 0x5d 0,93 # bracketright
+lC 319 2 0x7b 0,123 # braceleft
+rC 319 2 0x7d 0,125 # braceright
+la 319 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 319 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 410 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 410 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 410 2 0x125 4,32 # quotedblleft
+rq 410 2 0x4ba 6,31 # quotedblright
+oq 228 2 0x176 4,29 # quoteleft "single open quote"
+aq 195 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 230 0 0x3f4 0,124 # bar
+at 800 2 0x40 0,64 # at
+.C1 479 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 456 2 0x23 0,35 # numbersign
+sl 228 2 0x2f 0,47 # slash
+rs 228 2 0x5c 0,92 # backslash
+3d 228 0 0x35c 6,102 # therefore
+tf 228 0 0x35c 6,102 # therefore
+*A 228 0 0x341 8,0 # Alpha
+*B 228 0 0x342 8,2 # Beta
+*C 228 0 0x358 8,28 # Xi
+*D 228 0 0x344 8,8 # Delta
+*E 228 0 0x345 8,10 # Epsilon
+*F 609 0 0x346 8,44 # Phi
+*G 481 0 0x347 8,6 # Gamma
+*H 481 0 0x351 8,16 # Theta
+*I 481 0 0x349 8,18 # Iota
+*K 481 0 0x34b 8,20 # Kappa
+*L 481 0 0x34c 8,22 # Lambda
+*M 481 0 0x34d 8,24 # Mu
+*N 481 0 0x34e 8,26 # Nu
+*O 481 0 0x34f 8,30 # Omicron
+*P 481 0 0x350 8,32 # Pi
+*Q 481 0 0x359 8,48 # Psi
+*R 481 0 0x352 8,34 # Rho
+*S 481 0 0x353 8,36 # Sigma
+*T 481 0 0x354 8,40 # Tau
+*U 481 0 0x3a1 8,76 # Upsilon
+*W 630 0 0x357 8,50 # Omega
+*X 481 0 0x343 8,36 # Chi
+*Y 481 0 0x348 8,14 # Eta
+*Z 481 0 0x35a 8,12 # Zeta
+*a 499 0 0xe0 8,1 # alpha
+*b 499 0 0xe1 8,3 # beta
+*c 499 0 0x378 8,29 # xi
+*d 487 0 0xeb 8,9 # delta
+*e 487 0 0x36e 8,70 # epsilon
+*f 487 0 0x366 8,45 # phi
++f 487 0 0x36a 8,77 # phi1 "variant phi"
+*g 487 0 0x367 8,7 # gamma
+*h 486 0 0xe9 8,17 # theta
++h 486 0 0x375 8,71 # theta1 "variant theta"
+*i 486 0 0x369 8,19 # iota
+*k 486 0 0x36b 8,21 # kappa
+*l 486 0 0x36c 8,23 # lambda
+*m 501 0 0xe6 8,25 # mu
+*n 501 0 0x36e 8,27 # nu
+*o 501 0 0x36f 8,31 # omicron
+*p 527 0 0xe3 8,33 # pi
++p 527 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 527 0 0x379 8,49 # psi
+*r 527 0 0x372 8,35 # rho
+*s 531 0 0xe5 8,37 # sigma
+*t 375 0 0xe7 8,41 # tau
+*u 375 0 0x375 8,27 # upsilon
+*w 375 0 0x377 8,51 # omega
+*x 375 0 0x363 8,47 # chi
+*y 375 0 0x368 8,15 # eta
+*z 375 0 0x37a 8,13 # zeta
+ts 375 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 655 0 0xf7 6,13 # approxequal
+~= 655 0 0xf7 6,13 # approxequal
+!= 655 0 0x3b9 6,99 # notequal
+** 228 0 0x32a 0,32 # asteriskmath
++- 479 0 0xf1 6,1 # plusminus
+<= 592 0 0xf3 6,2 # lessequal
+== 592 0 0x3ba 8,14 # equivalence
+=~ 592 0 0x340 8,116 # congruent
+>= 499 0 0x3b3 8,3 # greaterequal
+AN 499 0 0x3d9 8,85 # logicaland
+OR 499 0 0x3da 8,86 # logicalor
+no 499 0 0x3d8 8,20 # logicalnot
+te 499 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 499 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 499 0 0x3c0 9,0 # aleph
+Im 499 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 499 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 499 0 0x3a5 8,19 # infinity
+md 499 0 0x3b7 8,32 # dotmath
+mo 499 0 0x3ce 8,15 # element
+mu 499 0 0x3b4 8,39 # multiply
+nc 499 0 0x3cb 8,197 # notpropersuperset
+nm 499 0 0x3cf 8,209 # notelement
+pl 273 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 479 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 479 0 0x3b5 6,4 # proportional
+pp 479 0 0x35e 8,89 # perpendicular
+sb 479 0 0x3cc 6,67 # propersubset
+sp 479 0 0x3c9 6,68 # propersuperset
+ib 479 0 0x3cd 6,69 # reflexsubset
+ip 479 0 0x3ca 6,70 # reflexsuperset
+ap 479 0 0x37e 6,12 # similar
+pd 479 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 479 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 479 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 645 0 0xef 6,16 # intersection "intersection, cap"
+cu 645 0 0x3c8 6,66 # union "union, cup"
+di 479 0 0x3b8 6,8 # divide "division sign"
+-h 820 0 0xc4 3,8 # hbar
+gr 820 0 0x3d1 6,33 # gradient
+es 638 0 0x3c6 0,79 # emptyset
+CL 617 0 0x5 5,168 # club "club suit"
+SP 617 0 0x6 5,171 # spade "spade suit"
+HE 617 0 0x3 5,170 # heart "heart suit"
+DI 617 0 0x4 5,169 # diamond "diamond suit"
+CR 617 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 617 0 0x327 6,71 # suchthat
+/_ 617 0 0x3d0 6,79 # angle
+<< 456 0 0xae 6,77 # "" "much less"
+>> 456 0 0xaf 6,78 # "" "much greater"
+wp 456 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 456 0 0x3e0 6,95 # lozenge
+an 820 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 240 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HNI b/contrib/groff/font/devlbp/HNI
new file mode 100644
index 0000000..578faf7
--- /dev/null
+++ b/contrib/groff/font/devlbp/HNI
@@ -0,0 +1,491 @@
+name HNI
+lbpname Swiss-Narrow-Oblique
+special
+spacewidth 228
+slant 0
+ligatures fi fl 0
+charset
+ha 280 2 0x4c3 0,94 # asciicircum
+ti 280 0 0x4c4 0,126 # asciitilde
+vS 280 2 0x169 1,176 # Scaron
+vZ 280 2 0x16e 1,206 # Zcaron
+vs 280 2 0x173 1,177 # scaron
+vz 280 2 0x174 1,207 # zcaron
+:Y 280 2 0x16d 1,74 # Ydieresis
+tm 280 2 0x170 4,41 # trademark
+aq 157 2 0x27 0,39 # quotesingle
+space 228 0 0x20 0,32
+! 228 2 0x21 0,33 # exclam
+" 291 2 0x22 0,34 # quotedbl
+dq 291 2 0x22 0,34 # quotedbl
+# 456 2 0x23 0,35 # numbersign
+sh 456 2 0x23 0,35 # "
+$ 456 2 0x24 0,36 # dollar
+Do 456 2 0x24 0,36 # "
+% 720 2 0x25 0,37 # percent
+& 547 2 0x26 0,38 # ampersand
+' 157 2 0x27 0,39 # quoteright
+cq 157 2 0x27 0,39 # quoteright
+( 273 2 0x28 0,40 # parenleft
+) 273 2 0x29 0,41 # parenright
+* 319 2 0x2a 0,42 # asterisk
++ 479 0 0x2b 0,43 # plus
+, 228 0 0x2c 0,44 # comma
+- 479 0 0x2d 0,45 # hyphen
+hy 479 0 0x2d 0,45 # "
+char173 479 0 0x2d 0,45 # "
+. 228 0 0x2e 0,46 # period
+/ 228 2 0x2f 0,47 # slash
+sl 228 2 0x2f 0,47 # "
+0 456 2 0x30 0,48 # zero
+1 456 2 0x31 0,49 # one
+2 456 2 0x32 0,50 # two
+3 456 2 0x33 0,51 # three
+4 456 2 0x34 0,52 # four
+5 456 2 0x35 0,53 # five
+6 456 2 0x36 0,54 # six
+7 456 2 0x37 0,55 # seven
+8 456 2 0x38 0,56 # eight
+9 456 2 0x39 0,57 # nine
+: 228 0 0x3a 0,58 # colon
+; 228 0 0x3b 0,59 # semicolon
+< 479 0 0x3c 0,60 # less
+= 479 0 0x3d 0,61 # equal
+> 479 0 0x3e 0,62 # greater
+? 456 2 0x3f 0,63 # question
+@ 832 2 0x40 0,64 # at
+at 832 2 0x40 0,64 # "
+A 547 2 0x41 0,65 # A
+B 547 2 0x42 0,66 # B
+C 592 2 0x43 0,67 # C
+D 592 2 0x44 0,68 # D
+E 547 2 0x45 0,69 # E
+F 501 2 0x46 0,70 # F
+G 638 2 0x47 0,71 # G
+H 592 2 0x48 0,72 # H
+I 228 2 0x49 0,73 # I
+J 410 2 0x4a 0,74 # J
+K 547 2 0x4b 0,75 # K
+L 456 2 0x4c 0,76 # L
+M 683 2 0x4d 0,77 # M
+N 592 2 0x4e 0,78 # N
+O 638 2 0x4f 0,79 # O
+P 547 2 0x50 0,80 # P
+Q 638 2 0x51 0,81 # Q
+R 592 2 0x52 0,82 # R
+S 547 2 0x53 0,83 # S
+T 501 2 0x54 0,84 # T
+U 592 2 0x55 0,85 # U
+V 547 2 0x56 0,86 # V
+W 774 2 0x57 0,87 # W
+X 547 2 0x58 0,88 # X
+Y 547 2 0x59 0,89 # Y
+Z 501 2 0x5a 0,90 # Z
+[ 228 2 0x5b 0,91 # bracketleft
+lB 228 2 0x5b 0,91 # "
+\ 228 2 0x5c 0,92 # backslash
+rs 228 2 0x5c 0,92 # "
+] 228 2 0x5d 0,93 # bracketright
+rB 228 2 0x5d 0,93 # "
+a^ 280 2 0x5e 0,94 # circumflex
+^ 280 2 0x5e 0,94 # "
+_ 456 0 0x5f 0,95 # underscore
+` 280 2 0x60 0,96 # quoteleft
+oq 280 2 0x60 0,96 # "
+a 456 0 0x61 0,97 # a
+b 456 2 0x62 0,98 # b
+c 410 0 0x63 0,99 # c
+d 456 2 0x64 0,100 # d
+e 456 0 0x65 0,101 # e
+f 228 2 0x66 0,102 # f
+g 456 1 0x67 0,103 # g
+h 456 2 0x68 0,104 # h
+i 182 2 0x69 0,105 # i
+j 182 2 0x6a 0,106 # j
+k 410 2 0x6b 0,107 # k
+l 182 2 0x6c 0,108 # l
+m 683 0 0x6d 0,109 # m
+n 456 0 0x6e 0,110 # n
+o 456 0 0x6f 0,111 # o
+p 456 1 0x70 0,112 # p
+q 456 1 0x71 0,113 # q
+r 273 0 0x72 0,114 # r
+s 410 0 0x73 0,115 # s
+t 228 2 0x74 0,116 # t
+u 456 0 0x75 0,117 # u
+v 410 0 0x76 0,118 # v
+w 592 0 0x77 0,119 # w
+x 410 0 0x78 0,120 # x
+y 410 1 0x79 0,121 # y
+z 410 0 0x7a 0,122 # z
+lC 274 2 0x7b 0,123 # braceleft
+{ 274 2 0x7b 0,123 # "
+| 213 2 0x7c 0,124 # "
+rC 274 2 0x7d 0,125 # braceright
+} 274 2 0x7d 0,125 # "
+a~ 280 2 0x7e 0,126 # tilde
+~ 280 2 0x7e 0,126 # "
+char161 273 1 0xad 4,7 # exclamdown
+char162 456 2 0x9b 4,19 # cent
+char163 456 2 0x9c 4,11 # sterling
+char164 456 2 0x12f 4,24 # currency
+char165 456 2 0x9d 4,12 # yen
+char166 213 2 0x7c 0,124 # brokenbar
+char167 456 2 0x15 4,6 # section
+char168 273 2 0x122 1,7 # dieresis
+char169 604 2 0x154 4,23 # copyright
+char170 303 2 0xa6 4,15 # ordfeminine
+char171 456 0 0xae 4,9 # guillemotleft
+char172 479 0 0xaa 6,20 # logicalnot
+char173 456 0 0x132 4,33 # hyphen
+char174 604 2 0x155 4,22 # registered
+char175 500 2 0x2d 6,0 # macron
+char176 328 2 0xf8 6,36 # degree
+char177 479 0 0xf1 6,1 # plusminus
+char178 273 2 0xfd 4,20 # twosuperior
+char179 273 2 0x14d 4,26 # threesuperior
+char180 273 2 0x120 1,6 # acute "acute accent"
+char181 456 1 0xe6 8,25 # mu
+char182 440 2 0x14 4,5 # paragraph
+char183 240 0 0xfa 6,32 # periodcentered
+char184 273 0 0x139 1,17 # cedilla
+char185 273 2 0x156 4,78 # onesuperior
+char186 299 2 0xa7 4,16 # ordmasculine
+char187 456 0 0xaf 4,10 # guillemotright
+char188 684 2 0xac 4,18 # onequarter
+char189 684 2 0xab 4,17 # onehalf
+char190 684 2 0x12e 4,25 # threequarters
+char191 501 1 0xa8 4,8 # questiondown
+char192 501 2 0x15c 1,32 # Agrave
+char193 501 2 0x15a 1,26 # Aacute
+char194 501 2 0x15b 1,28 # Acircumflex
+char195 501 2 0x28e 1,76 # Atilde
+char196 547 2 0x8e 1,30 # Adieresis
+char197 547 2 0x8f 1,34 # Aring
+char198 820 2 0x92 1,36 # AE
+char199 592 2 0x80 1,38 # Ccedilla
+char200 592 2 0x160 1,46 # Egrave
+char201 547 2 0x90 1,40 # Eacute
+char202 547 2 0x15e 1,42 # Ecircumflex
+char203 547 2 0x15f 1,44 # Edieresis
+char204 547 2 0x164 1,54 # Igrave
+char205 547 2 0x161 1,48 # Iacute
+char206 547 2 0x162 1,50 # Icircumflex
+char207 547 2 0x163 1,52 # Idieresis
+char208 592 2 0x13d 1,78 # Eth
+char209 592 2 0xa5 1,56 # Ntilde
+char210 592 2 0x167 1,64 # Ograve
+char211 592 2 0x165 1,58 # Oacute
+char212 592 2 0x166 1,60 # Ocircumflex
+char213 592 2 0x168 1,82 # Otilde
+char214 638 2 0x99 1,62 # Odieresis
+char215 479 0 0x157 6,39 # multiply
+char216 638 2 0x140 1,80 # Oslash
+char217 638 2 0x16c 1,72 # Ugrave
+char218 638 2 0x16a 1,66 # Uacute
+char219 638 2 0x16b 1,68 # Ucircumflex
+char220 592 2 0x9a 1,70 # Udieresis
+char221 592 2 0x16f 1,84 # Yacute
+char222 547 2 0x13e 1,88 # Thorn
+char223 501 2 0x147 1,23 # germandbls
+char224 456 2 0x85 1,33 # agrave
+char225 456 2 0xa0 1,27 # aacute
+char226 456 2 0x83 1,29 # acircumflex
+char227 456 2 0x284 1,93 # atilde
+char228 456 2 0x84 1,31 # adieresis
+char229 456 2 0x86 1,35 # aring
+char230 729 0 0x91 1,37 # ae
+char231 410 0 0x87 1,39 # ccedilla
+char232 456 2 0x8a 1,47 # egrave
+char233 456 2 0x82 1,41 # eacute
+char234 456 2 0x88 1,43 # ecircumflex
+char235 456 2 0x89 1,45 # edieresis
+char236 228 2 0x8d 1,55 # igrave
+char237 228 2 0xa1 1,49 # iacute
+char238 228 2 0x8c 1,51 # icircumflex
+char239 228 2 0x8b 1,53 # idieresis
+char240 456 2 0x148 1,87 # eth
+char241 456 2 0xa4 1,57 # ntilde
+char242 456 2 0x95 1,65 # ograve
+char243 456 2 0xa2 1,59 # oacute
+char244 456 2 0x93 1,61 # ocircumflex
+char245 456 2 0x172 1,83 # otilde
+char246 456 2 0x94 1,63 # odieresis
+char247 479 0 0xf6 6,8 # divide
+char248 501 0 0x145 1,81 # oslash
+char249 456 2 0x97 1,73 # ugrave
+char250 456 2 0xa3 1,67 # uacute
+char251 456 2 0x96 1,69 # ucircumflex
+char252 456 2 0x81 1,71 # udieresis
+char253 456 3 0x175 1,85 # yacute
+char254 456 3 0x143 1,89 # thorn
+char255 410 3 0x98 1,75 # ydieresis
+-D 592 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 456 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 547 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 456 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 820 2 0x92 1,36 # AE
+ae 729 0 0x91 1,37 # ae
+OE 820 2 0x141 1,166 # OE
+oe 774 0 0x146 1,167 # oe
+ij 353 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 501 2 0x147 1,23 # germandbls
+'A 501 2 0x15a 1,26 # Aacute
+'E 547 2 0x90 1,40 # Eacute
+'I 547 2 0x161 1,48 # Iacute
+'O 547 2 0x165 1,58 # Oacute
+'U 547 2 0x16a 1,66 # Uacute
+'a 456 2 0xa0 1,27 # aacute
+'e 456 2 0x82 1,41 # eacute
+'i 228 2 0xa1 1,49 # iacute
+'o 456 2 0xa2 1,59 # oacute
+'u 456 2 0x95 1,65 # uacute
+:A 547 2 0x8e 1,30 # Adieresis
+:E 547 2 0x15f 1,44 # Edieresis
+:I 547 2 0x163 1,52 # Idieresis
+:O 638 2 0x99 1,62 # Odieresis
+:U 592 2 0x9a 1,70 # Udieresis
+:Y 592 2 0x16d 1,74 # Ydieresis
+:a 456 2 0x84 1,31 # adieresis
+:e 456 2 0x89 1,45 # edieresis
+:i 228 2 0x8b 1,53 # idieresis
+:o 456 2 0x94 1,63 # odieresis
+:u 456 2 0x81 1,71 # udieresis
+:y 410 3 0x98 1,75 # ydieresis
+^A 410 2 0x15b 1,28 # Acircumflex
+^E 410 2 0x15e 1,42 # Ecircumflex
+^I 410 2 0x162 1,50 # Icircumflex
+^O 410 2 0x166 1,60 # Ocircumflex
+^U 410 2 0x16b 1,68 # Ucircumflex
+^a 456 2 0x83 1,29 # acircumflex
+^e 456 2 0x88 1,43 # ecircumflex
+^i 228 2 0x8c 1,51 # icircumflex
+^o 456 2 0x93 1,61 # ocircumflex
+^u 456 2 0x96 1,69 # ucircumflex
+`A 456 2 0x15c 1,32 # Agrave
+`E 456 2 0x160 1,46 # Egrave
+`I 456 2 0x164 1,54 # Igrave
+`O 456 2 0x167 1,64 # Ograve
+`U 456 2 0x16c 1,72 # Ugrave
+`a 456 2 0x85 1,33 # agrave
+~a 456 2 0x284 --- # atilde
+`e 456 2 0x8a 1,47 # egrave
+`i 228 2 0x8d 1,55 # igrave
+`o 456 2 0x95 1,65 # ograve
+`u 456 2 0x97 1,73 # ugrave
+~A 456 2 0x28e 1,26 # Atilde
+~N 592 2 0xa5 1,56 # Ntilde
+~O 592 2 0x168 1,82 # Otilde
+~n 456 2 0xa4 1,57 # ntilde
+~o 456 2 0x172 1,83 # otilde
+vS 456 2 0x169 1,176 # Scaron
+vs 456 2 0x173 1,177 # scaron
+vZ 456 2 0x16e 1,206 # Zcaron
+vz 456 2 0x174 1,207 # zcaron
+,C 592 2 0x80 1,38 # Ccedilla
+,c 410 0 0x87 1,39 # ccedilla
+/L 456 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 182 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 638 2 0x140 1,80 # Oslash
+/o 501 0 0x145 1,81 # oslash
+oA 547 2 0x8f 1,34 # Aring
+oa 456 2 0x86 1,35 # aring
+a" 273 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 273 2 0x135 1,8 # macron "macron or bar accent"
+a. 273 2 0x137 1,15 # dotaccent "dot accent"
+a^ 273 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 273 2 0x120 1,6 # acute "acute accent"
+ga 273 2 0x121 1,0 # grave "grave accent"
+ab 273 2 0x136 1,22 # breve "breve accent"
+ac 273 0 0x139 1,17 # cedilla "cedilla accent"
+ad 273 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 273 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 273 2 0x138 1,14 # ring "ring or circle accent"
+a~ 273 2 0x7e 1,2 # tilde "tilde accent"
+ho 273 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 228 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 456 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 456 2 0x24 0,36 # dollar
+Po 456 2 0x9c 4,11 # sterling
+Ye 456 2 0x9d 4,12 # yen
+Fn 456 2 0x9f 4,14 # florin
+ct 456 2 0x9b 4,19 # cent
+Fo 456 0 0xae 4,9 # guillemotleft
+Fc 273 0 0x4bb 4,20 # guillemotright
+fo 273 0 0x127 4,35 # guilsinglleft
+fc 273 0 0x128 4,36 # guilsinglright
+r! 273 1 0xad 4,7 # exclamdown
+r? 501 1 0xa8 4,8 # questiondown
+fi 410 2 0x130 4,54 # fi "fi ligature"
+fl 410 2 0x131 4,55 # fl "fl ligature"
+OK 410 0 0x3d6 --- # \& "check mark, tick"
+Of 303 2 0xa6 4,15 # ordfeminine
+Om 299 2 0xa7 4,16 # ordmasculine
+S1 273 2 0x156 4,78 # onesuperior
+S2 273 2 0xfd 4,20 # twosuperior
+S3 273 2 0x14d 4,26 # threesuperior
+<- 809 0 0x1b 6,22 # arrowleft
+-> 809 0 0x1a 6,21 # arrowright
+<> 854 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 494 0 0x19 6,24 # arrowdown
+ua 494 0 0x18 6,23 # arrowup
+va 494 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 494 0 0x3dc 6,57 # arrowdblleft
+rA 494 0 0x3de 6,56 # arrowdblright
+hA 494 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 494 0 0x3df 6,59 # arrowdbldown
+uA 494 0 0x3dd 6,58 # arrowdblup
+ba 820 2 0xb3 3,9 # bar
+bb 213 2 0x7c 0,124 # brokenbar
+br 820 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 820 0 0x123 4,34 # ru "baseline rule"
+ul 456 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 820 0 0x3f4 3,9 # bv "bold vertical"
+ci 699 0 0x9 4,1 # circle
+bu 522 0 0x7 4,0 # bullet
+co 604 2 0x154 4,23 # copyright
+rg 604 2 0x155 4,22 # registered
+tm 604 2 0x170 4,41 # trademark
+dd 456 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 456 2 0x12a 4,39 # dagger
+ps 440 2 0x14 4,5 # paragraph
+sc 456 2 0x15 4,6 # section
+de 328 2 0xf8 6,36 # degree
+em 820 0 0x123 4,34 # emdash "em dash"
+en 456 0 0x132 4,33 # endash "en dash"
+%0 820 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 684 2 0xab 4,17 # onehalf
+14 684 2 0xac 4,18 # onequarter
+34 684 2 0x12e 4,25 # threequarters
+f/ 137 2 0x158 6,6 # fraction "bar for fractions"
+fm 137 0 0x3a2 6,45 # minute "footmark, prime"
+sd 137 0 0x3b2 6,46 # second
+ha 137 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 137 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 500 0 0x2d 6,0 # hyphen
+lB 228 2 0x5b 0,91 # bracketleft
+rB 228 2 0x5d 0,93 # bracketright
+lC 274 2 0x7b 0,123 # braceleft
+rC 274 2 0x7d 0,125 # braceright
+la 274 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 274 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 273 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 273 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 273 2 0x125 4,32 # quotedblleft
+rq 273 2 0x4ba 6,31 # quotedblright
+oq 182 2 0x176 4,29 # quoteleft "single open quote"
+aq 157 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 213 0 0x3f4 0,124 # bar
+at 832 2 0x40 0,64 # at
+.C1 479 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 456 2 0x23 0,35 # numbersign
+sl 228 2 0x2f 0,47 # slash
+rs 228 2 0x5c 0,92 # backslash
+3d 228 0 0x35c 6,102 # therefore
+tf 228 0 0x35c 6,102 # therefore
+*A 228 0 0x341 8,0 # Alpha
+*B 228 0 0x342 8,2 # Beta
+*C 228 0 0x358 8,28 # Xi
+*D 228 0 0x344 8,8 # Delta
+*E 228 0 0x345 8,10 # Epsilon
+*F 585 0 0x346 8,44 # Phi
+*G 469 0 0x347 8,6 # Gamma
+*H 469 0 0x351 8,16 # Theta
+*I 469 0 0x349 8,18 # Iota
+*K 469 0 0x34b 8,20 # Kappa
+*L 469 0 0x34c 8,22 # Lambda
+*M 469 0 0x34d 8,24 # Mu
+*N 469 0 0x34e 8,26 # Nu
+*O 469 0 0x34f 8,30 # Omicron
+*P 469 0 0x350 8,32 # Pi
+*Q 469 0 0x359 8,48 # Psi
+*R 469 0 0x352 8,34 # Rho
+*S 485 0 0x353 8,36 # Sigma
+*T 485 0 0x354 8,40 # Tau
+*U 485 0 0x3a1 8,76 # Upsilon
+*W 626 0 0x357 8,50 # Omega
+*X 485 0 0x343 8,36 # Chi
+*Y 485 0 0x348 8,14 # Eta
+*Z 485 0 0x35a 8,12 # Zeta
+*a 498 0 0xe0 8,1 # alpha
+*b 466 0 0xe1 8,3 # beta
+*c 466 0 0x378 8,29 # xi
+*d 465 0 0xeb 8,9 # delta
+*e 465 0 0x36e 8,70 # epsilon
+*f 465 0 0x366 8,45 # phi
++f 465 0 0x36a 8,77 # phi1 "variant phi"
+*g 465 0 0x367 8,7 # gamma
+*h 456 0 0xe9 8,17 # theta
++h 456 0 0x375 8,71 # theta1 "variant theta"
+*i 456 0 0x369 8,19 # iota
+*k 456 0 0x36b 8,21 # kappa
+*l 456 0 0x36c 8,23 # lambda
+*m 456 0 0xe6 8,25 # mu
+*n 456 0 0x36e 8,27 # nu
+*o 456 0 0x36f 8,31 # omicron
+*p 483 0 0xe3 8,33 # pi
++p 483 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 483 0 0x379 8,49 # psi
+*r 483 0 0x372 8,35 # rho
+*s 501 0 0xe5 8,37 # sigma
+*t 375 0 0xe7 8,41 # tau
+*u 375 0 0x375 8,27 # upsilon
+*w 375 0 0x377 8,51 # omega
+*x 375 0 0x363 8,47 # chi
+*y 375 0 0x368 8,15 # eta
+*z 375 0 0x37a 8,13 # zeta
+ts 375 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 655 0 0xf7 6,13 # approxequal
+~= 655 0 0xf7 6,13 # approxequal
+!= 655 0 0x3b9 6,99 # notequal
+** 228 0 0x32a 0,32 # asteriskmath
++- 479 0 0xf1 6,1 # plusminus
+<= 594 0 0xf3 6,2 # lessequal
+== 594 0 0x3ba 8,14 # equivalence
+=~ 594 0 0x340 8,116 # congruent
+>= 466 0 0x3b3 8,3 # greaterequal
+AN 466 0 0x3d9 8,85 # logicaland
+OR 466 0 0x3da 8,86 # logicalor
+no 466 0 0x3d8 8,20 # logicalnot
+te 466 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 466 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 466 0 0x3c0 9,0 # aleph
+Im 466 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 466 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 466 0 0x3a5 8,19 # infinity
+md 466 0 0x3b7 8,32 # dotmath
+mo 466 0 0x3ce 8,15 # element
+mu 466 0 0x3b4 8,39 # multiply
+nc 466 0 0x3cb 8,197 # notpropersuperset
+nm 466 0 0x3cf 8,209 # notelement
+pl 228 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 479 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 479 0 0x3b5 6,4 # proportional
+pp 479 0 0x35e 8,89 # perpendicular
+sb 479 0 0x3cc 6,67 # propersubset
+sp 479 0 0x3c9 6,68 # propersuperset
+ib 479 0 0x3cd 6,69 # reflexsubset
+ip 479 0 0x3ca 6,70 # reflexsuperset
+ap 479 0 0x37e 6,12 # similar
+pd 479 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 479 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 479 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 645 0 0xef 6,16 # intersection "intersection, cap"
+cu 645 0 0x3c8 6,66 # union "union, cup"
+di 479 0 0x3b8 6,8 # divide "division sign"
+-h 820 0 0xc4 3,8 # hbar
+gr 820 0 0x3d1 6,33 # gradient
+es 638 0 0x3c6 0,79 # emptyset
+CL 617 0 0x5 5,168 # club "club suit"
+SP 617 0 0x6 5,171 # spade "spade suit"
+HE 617 0 0x3 5,170 # heart "heart suit"
+DI 617 0 0x4 5,169 # diamond "diamond suit"
+CR 617 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 617 0 0x327 6,71 # suchthat
+/_ 617 0 0x3d0 6,79 # angle
+<< 456 0 0xae 6,77 # "" "much less"
+>> 456 0 0xaf 6,78 # "" "much greater"
+wp 456 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 456 0 0x3e0 6,95 # lozenge
+an 820 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 240 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HNR b/contrib/groff/font/devlbp/HNR
new file mode 100644
index 0000000..d0e78af
--- /dev/null
+++ b/contrib/groff/font/devlbp/HNR
@@ -0,0 +1,491 @@
+name HNR
+lbpname Swiss-Narrow
+special
+spacewidth 228
+slant 0
+ligatures fi fl 0
+charset
+ha 290 2 0x4c3 0,94 # asciicircum
+ti 280 0 0x4c4 0,126 # asciitilde
+vS 280 2 0x169 1,176 # Scaron
+vZ 280 2 0x16e 1,206 # Zcaron
+vs 280 2 0x173 1,177 # scaron
+vz 280 2 0x174 1,207 # zcaron
+:Y 280 2 0x16d 1,74 # Ydieresis
+tm 280 2 0x170 4,41 # trademark
+aq 157 2 0x27 0,39 # quotesingle
+space 228 0 0x20 0,32
+! 228 2 0x21 0,33 # exclam
+" 291 2 0x22 0,34 # quotedbl
+dq 291 2 0x22 0,34 # quotedbl
+# 456 2 0x23 0,35 # numbersign
+sh 456 2 0x23 0,35 # "
+$ 456 2 0x24 0,36 # dollar
+Do 456 2 0x24 0,36 # "
+% 720 2 0x25 0,37 # percent
+& 547 2 0x26 0,38 # ampersand
+' 157 2 0x27 0,39 # quoteright
+cq 157 2 0x27 0,39 # quoteright
+( 273 2 0x28 0,40 # parenleft
+) 273 2 0x29 0,41 # parenright
+* 319 2 0x2a 0,42 # asterisk
++ 479 0 0x2b 0,43 # plus
+, 228 0 0x2c 0,44 # comma
+- 479 0 0x2d 0,45 # hyphen
+hy 479 0 0x2d 0,45 # "
+char173 479 0 0x2d 0,45 # "
+. 228 0 0x2e 0,46 # period
+/ 228 2 0x2f 0,47 # slash
+sl 228 2 0x2f 0,47 # "
+0 456 2 0x30 0,48 # zero
+1 456 2 0x31 0,49 # one
+2 456 2 0x32 0,50 # two
+3 456 2 0x33 0,51 # three
+4 456 2 0x34 0,52 # four
+5 456 2 0x35 0,53 # five
+6 456 2 0x36 0,54 # six
+7 456 2 0x37 0,55 # seven
+8 456 2 0x38 0,56 # eight
+9 456 2 0x39 0,57 # nine
+: 228 0 0x3a 0,58 # colon
+; 228 0 0x3b 0,59 # semicolon
+< 479 0 0x3c 0,60 # less
+= 479 0 0x3d 0,61 # equal
+> 479 0 0x3e 0,62 # greater
+? 456 2 0x3f 0,63 # question
+@ 832 2 0x40 0,64 # at
+at 832 2 0x40 0,64 # "
+A 547 2 0x41 0,65 # A
+B 547 2 0x42 0,66 # B
+C 592 2 0x43 0,67 # C
+D 592 2 0x44 0,68 # D
+E 547 2 0x45 0,69 # E
+F 501 2 0x46 0,70 # F
+G 638 2 0x47 0,71 # G
+H 592 2 0x48 0,72 # H
+I 228 2 0x49 0,73 # I
+J 410 2 0x4a 0,74 # J
+K 547 2 0x4b 0,75 # K
+L 456 2 0x4c 0,76 # L
+M 683 2 0x4d 0,77 # M
+N 592 2 0x4e 0,78 # N
+O 638 2 0x4f 0,79 # O
+P 547 2 0x50 0,80 # P
+Q 638 2 0x51 0,81 # Q
+R 592 2 0x52 0,82 # R
+S 547 2 0x53 0,83 # S
+T 501 2 0x54 0,84 # T
+U 592 2 0x55 0,85 # U
+V 547 2 0x56 0,86 # V
+W 774 2 0x57 0,87 # W
+X 547 2 0x58 0,88 # X
+Y 547 2 0x59 0,89 # Y
+Z 501 2 0x5a 0,90 # Z
+[ 228 2 0x5b 0,91 # bracketleft
+lB 228 2 0x5b 0,91 # "
+\ 228 2 0x5c 0,92 # backslash
+rs 228 2 0x5c 0,92 # "
+] 228 2 0x5d 0,93 # bracketright
+rB 228 2 0x5d 0,93 # "
+a^ 290 2 0x5e 0,94 # circumflex
+^ 290 2 0x5e 0,94 # "
+_ 456 0 0x5f 0,95 # underscore
+` 290 2 0x60 0,96 # quoteleft
+oq 290 2 0x60 0,96 # "
+a 456 0 0x61 0,97 # a
+b 456 2 0x62 0,98 # b
+c 410 0 0x63 0,99 # c
+d 456 2 0x64 0,100 # d
+e 456 0 0x65 0,101 # e
+f 228 2 0x66 0,102 # f
+g 456 1 0x67 0,103 # g
+h 456 2 0x68 0,104 # h
+i 182 2 0x69 0,105 # i
+j 182 2 0x6a 0,106 # j
+k 410 2 0x6b 0,107 # k
+l 182 2 0x6c 0,108 # l
+m 683 0 0x6d 0,109 # m
+n 456 0 0x6e 0,110 # n
+o 456 0 0x6f 0,111 # o
+p 456 1 0x70 0,112 # p
+q 456 1 0x71 0,113 # q
+r 273 0 0x72 0,114 # r
+s 410 0 0x73 0,115 # s
+t 228 2 0x74 0,116 # t
+u 456 0 0x75 0,117 # u
+v 410 0 0x76 0,118 # v
+w 592 0 0x77 0,119 # w
+x 410 0 0x78 0,120 # x
+y 410 1 0x79 0,121 # y
+z 410 0 0x7a 0,122 # z
+lC 274 2 0x7b 0,123 # braceleft
+{ 274 2 0x7b 0,123 # "
+| 213 2 0x7c 0,124 # "
+rC 274 2 0x7d 0,125 # braceright
+} 274 2 0x7d 0,125 # "
+a~ 280 2 0x7e 0,126 # tilde
+~ 280 2 0x7e 0,126 # "
+char161 273 1 0xad 4,7 # exclamdown
+char162 456 2 0x9b 4,19 # cent
+char163 456 2 0x9c 4,11 # sterling
+char164 456 2 0x12f 4,24 # currency
+char165 456 2 0x9d 4,12 # yen
+char166 213 2 0x7c 0,124 # brokenbar
+char167 456 2 0x15 4,6 # section
+char168 273 2 0x122 1,7 # dieresis
+char169 604 2 0x154 4,23 # copyright
+char170 303 2 0xa6 4,15 # ordfeminine
+char171 456 0 0xae 4,9 # guillemotleft
+char172 479 0 0xaa 6,20 # logicalnot
+char173 456 0 0x132 4,33 # hyphen
+char174 604 2 0x155 4,22 # registered
+char175 500 2 0x2d 6,0 # macron
+char176 328 2 0xf8 6,36 # degree
+char177 479 0 0xf1 6,1 # plusminus
+char178 273 2 0xfd 4,20 # twosuperior
+char179 273 2 0x14d 4,26 # threesuperior
+char180 273 2 0x120 1,6 # acute "acute accent"
+char181 456 1 0xe6 8,25 # mu
+char182 440 2 0x14 4,5 # paragraph
+char183 240 0 0xfa 6,32 # periodcentered
+char184 273 0 0x139 1,17 # cedilla
+char185 273 2 0x156 4,78 # onesuperior
+char186 299 2 0xa7 4,16 # ordmasculine
+char187 456 0 0xaf 4,10 # guillemotright
+char188 684 2 0xac 4,18 # onequarter
+char189 684 2 0xab 4,17 # onehalf
+char190 684 2 0x12e 4,25 # threequarters
+char191 501 1 0xa8 4,8 # questiondown
+char192 501 2 0x15c 1,32 # Agrave
+char193 501 2 0x15a 1,26 # Aacute
+char194 501 2 0x15b 1,28 # Acircumflex
+char195 501 2 0x28e 1,76 # Atilde
+char196 547 2 0x8e 1,30 # Adieresis
+char197 547 2 0x8f 1,34 # Aring
+char198 820 2 0x92 1,36 # AE
+char199 592 2 0x80 1,38 # Ccedilla
+char200 592 2 0x160 1,46 # Egrave
+char201 547 2 0x90 1,40 # Eacute
+char202 547 2 0x15e 1,42 # Ecircumflex
+char203 547 2 0x15f 1,44 # Edieresis
+char204 547 2 0x164 1,54 # Igrave
+char205 547 2 0x161 1,48 # Iacute
+char206 547 2 0x162 1,50 # Icircumflex
+char207 547 2 0x163 1,52 # Idieresis
+char208 592 2 0x13d 1,78 # Eth
+char209 592 2 0xa5 1,56 # Ntilde
+char210 592 2 0x167 1,64 # Ograve
+char211 592 2 0x165 1,58 # Oacute
+char212 592 2 0x166 1,60 # Ocircumflex
+char213 592 2 0x168 1,82 # Otilde
+char214 638 2 0x99 1,62 # Odieresis
+char215 479 0 0x157 6,39 # multiply
+char216 638 2 0x140 1,80 # Oslash
+char217 638 2 0x16c 1,72 # Ugrave
+char218 638 2 0x16a 1,66 # Uacute
+char219 638 2 0x16b 1,68 # Ucircumflex
+char220 592 2 0x9a 1,70 # Udieresis
+char221 592 2 0x16f 1,84 # Yacute
+char222 547 2 0x13e 1,88 # Thorn
+char223 501 2 0x147 1,23 # germandbls
+char224 456 2 0x85 1,33 # agrave
+char225 456 2 0xa0 1,27 # aacute
+char226 456 2 0x83 1,29 # acircumflex
+char227 456 2 0x284 1,93 # atilde
+char228 456 2 0x84 1,31 # adieresis
+char229 456 2 0x86 1,35 # aring
+char230 729 0 0x91 1,37 # ae
+char231 410 0 0x87 1,39 # ccedilla
+char232 456 2 0x8a 1,47 # egrave
+char233 456 2 0x82 1,41 # eacute
+char234 456 2 0x88 1,43 # ecircumflex
+char235 456 2 0x89 1,45 # edieresis
+char236 228 2 0x8d 1,55 # igrave
+char237 228 2 0xa1 1,49 # iacute
+char238 228 2 0x8c 1,51 # icircumflex
+char239 228 2 0x8b 1,53 # idieresis
+char240 456 2 0x148 1,87 # eth
+char241 456 2 0xa4 1,57 # ntilde
+char242 456 2 0x95 1,65 # ograve
+char243 456 2 0xa2 1,59 # oacute
+char244 456 2 0x93 1,61 # ocircumflex
+char245 456 2 0x172 1,83 # otilde
+char246 456 2 0x94 1,63 # odieresis
+char247 479 0 0xf6 6,8 # divide
+char248 501 0 0x145 1,81 # oslash
+char249 456 2 0x97 1,73 # ugrave
+char250 456 2 0xa3 1,67 # uacute
+char251 456 2 0x96 1,69 # ucircumflex
+char252 456 2 0x81 1,71 # udieresis
+char253 456 3 0x175 1,85 # yacute
+char254 456 3 0x143 1,89 # thorn
+char255 410 3 0x98 1,75 # ydieresis
+-D 592 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 456 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 547 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 456 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 820 2 0x92 1,36 # AE
+ae 729 0 0x91 1,37 # ae
+OE 820 2 0x141 1,166 # OE
+oe 774 0 0x146 1,167 # oe
+ij 353 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 501 2 0x147 1,23 # germandbls
+'A 501 2 0x15a 1,26 # Aacute
+'E 547 2 0x90 1,40 # Eacute
+'I 547 2 0x161 1,48 # Iacute
+'O 547 2 0x165 1,58 # Oacute
+'U 547 2 0x16a 1,66 # Uacute
+'a 456 2 0xa0 1,27 # aacute
+'e 456 2 0x82 1,41 # eacute
+'i 228 2 0xa1 1,49 # iacute
+'o 456 2 0xa2 1,59 # oacute
+'u 456 2 0x95 1,65 # uacute
+:A 547 2 0x8e 1,30 # Adieresis
+:E 547 2 0x15f 1,44 # Edieresis
+:I 547 2 0x163 1,52 # Idieresis
+:O 638 2 0x99 1,62 # Odieresis
+:U 592 2 0x9a 1,70 # Udieresis
+:Y 592 2 0x16d 1,74 # Ydieresis
+:a 456 2 0x84 1,31 # adieresis
+:e 456 2 0x89 1,45 # edieresis
+:i 228 2 0x8b 1,53 # idieresis
+:o 456 2 0x94 1,63 # odieresis
+:u 456 2 0x81 1,71 # udieresis
+:y 410 3 0x98 1,75 # ydieresis
+^A 410 2 0x15b 1,28 # Acircumflex
+^E 410 2 0x15e 1,42 # Ecircumflex
+^I 410 2 0x162 1,50 # Icircumflex
+^O 410 2 0x166 1,60 # Ocircumflex
+^U 410 2 0x16b 1,68 # Ucircumflex
+^a 456 2 0x83 1,29 # acircumflex
+^e 456 2 0x88 1,43 # ecircumflex
+^i 228 2 0x8c 1,51 # icircumflex
+^o 456 2 0x93 1,61 # ocircumflex
+^u 456 2 0x96 1,69 # ucircumflex
+`A 456 2 0x15c 1,32 # Agrave
+`E 456 2 0x160 1,46 # Egrave
+`I 456 2 0x164 1,54 # Igrave
+`O 456 2 0x167 1,64 # Ograve
+`U 456 2 0x16c 1,72 # Ugrave
+`a 456 2 0x85 1,33 # agrave
+~a 456 2 0x284 --- # atilde
+`e 456 2 0x8a 1,47 # egrave
+`i 228 2 0x8d 1,55 # igrave
+`o 456 2 0x95 1,65 # ograve
+`u 456 2 0x97 1,73 # ugrave
+~A 456 2 0x28e 1,26 # Atilde
+~N 592 2 0xa5 1,56 # Ntilde
+~O 592 2 0x168 1,82 # Otilde
+~n 456 2 0xa4 1,57 # ntilde
+~o 456 2 0x172 1,83 # otilde
+vS 456 2 0x169 1,176 # Scaron
+vs 456 2 0x173 1,177 # scaron
+vZ 456 2 0x16e 1,206 # Zcaron
+vz 456 2 0x174 1,207 # zcaron
+,C 592 2 0x80 1,38 # Ccedilla
+,c 410 0 0x87 1,39 # ccedilla
+/L 456 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 182 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 638 2 0x140 1,80 # Oslash
+/o 501 0 0x145 1,81 # oslash
+oA 547 2 0x8f 1,34 # Aring
+oa 456 2 0x86 1,35 # aring
+a" 273 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 273 2 0x135 1,8 # macron "macron or bar accent"
+a. 273 2 0x137 1,15 # dotaccent "dot accent"
+a^ 273 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 273 2 0x120 1,6 # acute "acute accent"
+ga 273 2 0x121 1,0 # grave "grave accent"
+ab 273 2 0x136 1,22 # breve "breve accent"
+ac 273 0 0x139 1,17 # cedilla "cedilla accent"
+ad 273 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 273 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 273 2 0x138 1,14 # ring "ring or circle accent"
+a~ 273 2 0x7e 1,2 # tilde "tilde accent"
+ho 273 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 228 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 456 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 456 2 0x24 0,36 # dollar
+Po 456 2 0x9c 4,11 # sterling
+Ye 456 2 0x9d 4,12 # yen
+Fn 456 2 0x9f 4,14 # florin
+ct 456 2 0x9b 4,19 # cent
+Fo 456 0 0xae 4,9 # guillemotleft
+Fc 273 0 0x4bb 4,20 # guillemotright
+fo 273 0 0x127 4,35 # guilsinglleft
+fc 273 0 0x128 4,36 # guilsinglright
+r! 273 1 0xad 4,7 # exclamdown
+r? 501 1 0xa8 4,8 # questiondown
+fi 410 2 0x130 4,54 # fi "fi ligature"
+fl 410 2 0x131 4,55 # fl "fl ligature"
+OK 410 0 0x3d6 --- # \& "check mark, tick"
+Of 303 2 0xa6 4,15 # ordfeminine
+Om 299 2 0xa7 4,16 # ordmasculine
+S1 273 2 0x156 4,78 # onesuperior
+S2 273 2 0xfd 4,20 # twosuperior
+S3 273 2 0x14d 4,26 # threesuperior
+<- 809 0 0x1b 6,22 # arrowleft
+-> 809 0 0x1a 6,21 # arrowright
+<> 854 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 494 0 0x19 6,24 # arrowdown
+ua 494 0 0x18 6,23 # arrowup
+va 494 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 494 0 0x3dc 6,57 # arrowdblleft
+rA 494 0 0x3de 6,56 # arrowdblright
+hA 494 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 494 0 0x3df 6,59 # arrowdbldown
+uA 494 0 0x3dd 6,58 # arrowdblup
+ba 820 2 0xb3 3,9 # bar
+bb 213 2 0x7c 0,124 # brokenbar
+br 820 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 820 0 0x123 4,34 # ru "baseline rule"
+ul 456 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 820 0 0x3f4 3,9 # bv "bold vertical"
+ci 699 0 0x9 4,1 # circle
+bu 522 0 0x7 4,0 # bullet
+co 604 2 0x154 4,23 # copyright
+rg 604 2 0x155 4,22 # registered
+tm 604 2 0x170 4,41 # trademark
+dd 456 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 456 2 0x12a 4,39 # dagger
+ps 440 2 0x14 4,5 # paragraph
+sc 456 2 0x15 4,6 # section
+de 328 2 0xf8 6,36 # degree
+em 820 0 0x123 4,34 # emdash "em dash"
+en 456 0 0x132 4,33 # endash "en dash"
+%0 820 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 684 2 0xab 4,17 # onehalf
+14 684 2 0xac 4,18 # onequarter
+34 684 2 0x12e 4,25 # threequarters
+f/ 137 2 0x158 6,6 # fraction "bar for fractions"
+fm 137 0 0x3a2 6,45 # minute "footmark, prime"
+sd 137 0 0x3b2 6,46 # second
+ha 137 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 137 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 500 0 0x2d 6,0 # hyphen
+lB 228 2 0x5b 0,91 # bracketleft
+rB 228 2 0x5d 0,93 # bracketright
+lC 274 2 0x7b 0,123 # braceleft
+rC 274 2 0x7d 0,125 # braceright
+la 274 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 274 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 273 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 273 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 273 2 0x125 4,32 # quotedblleft
+rq 273 2 0x4ba 6,31 # quotedblright
+oq 182 2 0x176 4,29 # quoteleft "single open quote"
+aq 157 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 213 0 0x3f4 0,124 # bar
+at 832 2 0x40 0,64 # at
+.C1 479 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 456 2 0x23 0,35 # numbersign
+sl 228 2 0x2f 0,47 # slash
+rs 228 2 0x5c 0,92 # backslash
+3d 228 0 0x35c 6,102 # therefore
+tf 228 0 0x35c 6,102 # therefore
+*A 228 0 0x341 8,0 # Alpha
+*B 228 0 0x342 8,2 # Beta
+*C 228 0 0x358 8,28 # Xi
+*D 228 0 0x344 8,8 # Delta
+*E 228 0 0x345 8,10 # Epsilon
+*F 585 0 0x346 8,44 # Phi
+*G 469 0 0x347 8,6 # Gamma
+*H 469 0 0x351 8,16 # Theta
+*I 469 0 0x349 8,18 # Iota
+*K 469 0 0x34b 8,20 # Kappa
+*L 469 0 0x34c 8,22 # Lambda
+*M 469 0 0x34d 8,24 # Mu
+*N 469 0 0x34e 8,26 # Nu
+*O 469 0 0x34f 8,30 # Omicron
+*P 469 0 0x350 8,32 # Pi
+*Q 469 0 0x359 8,48 # Psi
+*R 469 0 0x352 8,34 # Rho
+*S 485 0 0x353 8,36 # Sigma
+*T 485 0 0x354 8,40 # Tau
+*U 485 0 0x3a1 8,76 # Upsilon
+*W 626 0 0x357 8,50 # Omega
+*X 485 0 0x343 8,36 # Chi
+*Y 485 0 0x348 8,14 # Eta
+*Z 485 0 0x35a 8,12 # Zeta
+*a 498 0 0xe0 8,1 # alpha
+*b 466 0 0xe1 8,3 # beta
+*c 466 0 0x378 8,29 # xi
+*d 465 0 0xeb 8,9 # delta
+*e 465 0 0x36e 8,70 # epsilon
+*f 465 0 0x366 8,45 # phi
++f 465 0 0x36a 8,77 # phi1 "variant phi"
+*g 465 0 0x367 8,7 # gamma
+*h 456 0 0xe9 8,17 # theta
++h 456 0 0x375 8,71 # theta1 "variant theta"
+*i 456 0 0x369 8,19 # iota
+*k 456 0 0x36b 8,21 # kappa
+*l 456 0 0x36c 8,23 # lambda
+*m 456 0 0xe6 8,25 # mu
+*n 456 0 0x36e 8,27 # nu
+*o 456 0 0x36f 8,31 # omicron
+*p 483 0 0xe3 8,33 # pi
++p 483 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 483 0 0x379 8,49 # psi
+*r 483 0 0x372 8,35 # rho
+*s 501 0 0xe5 8,37 # sigma
+*t 375 0 0xe7 8,41 # tau
+*u 375 0 0x375 8,27 # upsilon
+*w 375 0 0x377 8,51 # omega
+*x 375 0 0x363 8,47 # chi
+*y 375 0 0x368 8,15 # eta
+*z 375 0 0x37a 8,13 # zeta
+ts 375 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 655 0 0xf7 6,13 # approxequal
+~= 655 0 0xf7 6,13 # approxequal
+!= 655 0 0x3b9 6,99 # notequal
+** 228 0 0x32a 0,32 # asteriskmath
++- 479 0 0xf1 6,1 # plusminus
+<= 594 0 0xf3 6,2 # lessequal
+== 594 0 0x3ba 8,14 # equivalence
+=~ 594 0 0x340 8,116 # congruent
+>= 466 0 0x3b3 8,3 # greaterequal
+AN 466 0 0x3d9 8,85 # logicaland
+OR 466 0 0x3da 8,86 # logicalor
+no 466 0 0x3d8 8,20 # logicalnot
+te 466 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 466 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 466 0 0x3c0 9,0 # aleph
+Im 466 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 466 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 466 0 0x3a5 8,19 # infinity
+md 466 0 0x3b7 8,32 # dotmath
+mo 466 0 0x3ce 8,15 # element
+mu 466 0 0x3b4 8,39 # multiply
+nc 466 0 0x3cb 8,197 # notpropersuperset
+nm 466 0 0x3cf 8,209 # notelement
+pl 228 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 479 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 479 0 0x3b5 6,4 # proportional
+pp 479 0 0x35e 8,89 # perpendicular
+sb 479 0 0x3cc 6,67 # propersubset
+sp 479 0 0x3c9 6,68 # propersuperset
+ib 479 0 0x3cd 6,69 # reflexsubset
+ip 479 0 0x3ca 6,70 # reflexsuperset
+ap 479 0 0x37e 6,12 # similar
+pd 479 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 479 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 479 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 645 0 0xef 6,16 # intersection "intersection, cap"
+cu 645 0 0x3c8 6,66 # union "union, cup"
+di 479 0 0x3b8 6,8 # divide "division sign"
+-h 820 0 0xc4 3,8 # hbar
+gr 820 0 0x3d1 6,33 # gradient
+es 638 0 0x3c6 0,79 # emptyset
+CL 617 0 0x5 5,168 # club "club suit"
+SP 617 0 0x6 5,171 # spade "spade suit"
+HE 617 0 0x3 5,170 # heart "heart suit"
+DI 617 0 0x4 5,169 # diamond "diamond suit"
+CR 617 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 617 0 0x327 6,71 # suchthat
+/_ 617 0 0x3d0 6,79 # angle
+<< 456 0 0xae 6,77 # "" "much less"
+>> 456 0 0xaf 6,78 # "" "much greater"
+wp 456 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 456 0 0x3e0 6,95 # lozenge
+an 820 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 240 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/HR b/contrib/groff/font/devlbp/HR
new file mode 100644
index 0000000..81cfa96
--- /dev/null
+++ b/contrib/groff/font/devlbp/HR
@@ -0,0 +1,491 @@
+name HR
+lbpname Swiss
+special
+spacewidth 927
+slant 0
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 2223 2 0x169 1,176 # Scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vs 1667 2 0x173 1,177 # scaron
+vz 1667 2 0x174 1,207 # zcaron
+:Y 2223 2 0x16d 1,74 # Ydieresis
+tm 3333 2 0x170 4,41 # trademark
+aq 637 2 0x27 0,39 # quotesingle
+space 927 0 0x20 0,32
+! 927 2 0x21 0,33 # exclam
+" 1183 2 0x22 0,34 # quotedbl
+dq 1183 2 0x22 0,34 # quotedbl
+# 1853 2 0x23 0,35 # numbersign
+sh 1853 2 0x23 0,35 # "
+$ 1853 2 0x24 0,36 # dollar
+Do 1853 2 0x24 0,36 # "
+% 2963 2 0x25 0,37 # percent
+& 2223 2 0x26 0,38 # ampersand
+' 637 2 0x27 0,39 # quoteright
+cq 637 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1297 2 0x2a 0,42 # asterisk
++ 1947 0 0x2b 0,43 # plus
+, 927 0 0x2c 0,44 # comma
+- 1947 0 0x2d 0,45 # hyphen
+hy 1947 0 0x2d 0,45 # "
+char173 1947 0 0x2d 0,45 # "
+. 927 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1853 2 0x30 0,48 # zero
+1 1853 2 0x31 0,49 # one
+2 1853 2 0x32 0,50 # two
+3 1853 2 0x33 0,51 # three
+4 1853 2 0x34 0,52 # four
+5 1853 2 0x35 0,53 # five
+6 1853 2 0x36 0,54 # six
+7 1853 2 0x37 0,55 # seven
+8 1853 2 0x38 0,56 # eight
+9 1853 2 0x39 0,57 # nine
+: 927 0 0x3a 0,58 # colon
+; 927 0 0x3b 0,59 # semicolon
+< 1947 0 0x3c 0,60 # less
+= 1947 0 0x3d 0,61 # equal
+> 1947 0 0x3e 0,62 # greater
+? 1853 2 0x3f 0,63 # question
+@ 3383 2 0x40 0,64 # at
+at 3383 2 0x40 0,64 # "
+A 2223 2 0x41 0,65 # A
+B 2223 2 0x42 0,66 # B
+C 2407 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2223 2 0x45 0,69 # E
+F 2037 2 0x46 0,70 # F
+G 2593 2 0x47 0,71 # G
+H 2407 2 0x48 0,72 # H
+I 927 2 0x49 0,73 # I
+J 1667 2 0x4a 0,74 # J
+K 2223 2 0x4b 0,75 # K
+L 1853 2 0x4c 0,76 # L
+M 2777 2 0x4d 0,77 # M
+N 2407 2 0x4e 0,78 # N
+O 2593 2 0x4f 0,79 # O
+P 2223 2 0x50 0,80 # P
+Q 2593 2 0x51 0,81 # Q
+R 2407 2 0x52 0,82 # R
+S 2223 2 0x53 0,83 # S
+T 2037 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2223 2 0x56 0,86 # V
+W 3147 2 0x57 0,87 # W
+X 2223 2 0x58 0,88 # X
+Y 2223 2 0x59 0,89 # Y
+Z 2037 2 0x5a 0,90 # Z
+[ 927 2 0x5b 0,91 # bracketleft
+lB 927 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 927 2 0x5d 0,93 # bracketright
+rB 927 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1853 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1853 0 0x61 0,97 # a
+b 1853 2 0x62 0,98 # b
+c 1667 0 0x63 0,99 # c
+d 1853 2 0x64 0,100 # d
+e 1853 0 0x65 0,101 # e
+f 927 2 0x66 0,102 # f
+g 1853 1 0x67 0,103 # g
+h 1853 2 0x68 0,104 # h
+i 740 2 0x69 0,105 # i
+j 740 2 0x6a 0,106 # j
+k 1667 2 0x6b 0,107 # k
+l 740 2 0x6c 0,108 # l
+m 2777 0 0x6d 0,109 # m
+n 1853 0 0x6e 0,110 # n
+o 1853 0 0x6f 0,111 # o
+p 1853 1 0x70 0,112 # p
+q 1853 1 0x71 0,113 # q
+r 1110 0 0x72 0,114 # r
+s 1667 0 0x73 0,115 # s
+t 927 2 0x74 0,116 # t
+u 1853 0 0x75 0,117 # u
+v 1667 0 0x76 0,118 # v
+w 2407 0 0x77 0,119 # w
+x 1667 0 0x78 0,120 # x
+y 1667 1 0x79 0,121 # y
+z 1667 0 0x7a 0,122 # z
+lC 1113 2 0x7b 0,123 # braceleft
+{ 1113 2 0x7b 0,123 # "
+| 867 2 0x7c 0,124 # "
+rC 1113 2 0x7d 0,125 # braceright
+} 1113 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1110 1 0xad 4,7 # exclamdown
+char162 1853 2 0x9b 4,19 # cent
+char163 1853 2 0x9c 4,11 # sterling
+char164 1853 2 0x12f 4,24 # currency
+char165 1853 2 0x9d 4,12 # yen
+char166 867 2 0x7c 0,124 # brokenbar
+char167 1853 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2457 2 0x154 4,23 # copyright
+char170 1233 2 0xa6 4,15 # ordfeminine
+char171 1853 0 0xae 4,9 # guillemotleft
+char172 1947 0 0xaa 6,20 # logicalnot
+char173 1853 0 0x132 4,33 # hyphen
+char174 2457 2 0x155 4,22 # registered
+char175 1947 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 1947 0 0xf1 6,1 # plusminus
+char178 1110 2 0xfd 4,20 # twosuperior
+char179 1110 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 1853 1 0xe6 8,25 # mu
+char182 1790 2 0x14 4,5 # paragraph
+char183 927 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1110 2 0x156 4,78 # onesuperior
+char186 1217 2 0xa7 4,16 # ordmasculine
+char187 1853 0 0xaf 4,10 # guillemotright
+char188 2780 2 0xac 4,18 # onequarter
+char189 2780 2 0xab 4,17 # onehalf
+char190 2780 2 0x12e 4,25 # threequarters
+char191 2037 1 0xa8 4,8 # questiondown
+char192 2223 2 0x15c 1,32 # Agrave
+char193 2223 2 0x15a 1,26 # Aacute
+char194 2223 2 0x15b 1,28 # Acircumflex
+char195 2223 2 0x28e 1,76 # Atilde
+char196 2223 2 0x8e 1,30 # Adieresis
+char197 2223 2 0x8f 1,34 # Aring
+char198 3333 2 0x92 1,36 # AE
+char199 2407 2 0x80 1,38 # Ccedilla
+char200 2223 2 0x160 1,46 # Egrave
+char201 2223 2 0x90 1,40 # Eacute
+char202 2223 2 0x15e 1,42 # Ecircumflex
+char203 2223 2 0x15f 1,44 # Edieresis
+char204 927 2 0x164 1,54 # Igrave
+char205 927 2 0x161 1,48 # Iacute
+char206 927 2 0x162 1,50 # Icircumflex
+char207 927 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2407 2 0xa5 1,56 # Ntilde
+char210 2593 2 0x167 1,64 # Ograve
+char211 2593 2 0x165 1,58 # Oacute
+char212 2593 2 0x166 1,60 # Ocircumflex
+char213 2593 2 0x168 1,82 # Otilde
+char214 2593 2 0x99 1,62 # Odieresis
+char215 1947 0 0x157 6,39 # multiply
+char216 2593 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 2223 2 0x16f 1,84 # Yacute
+char222 2223 2 0x13e 1,88 # Thorn
+char223 2037 2 0x147 1,23 # germandbls
+char224 1853 2 0x85 1,33 # agrave
+char225 1853 2 0xa0 1,27 # aacute
+char226 1853 2 0x83 1,29 # acircumflex
+char227 1853 2 0x284 1,93 # atilde
+char228 1853 2 0x84 1,31 # adieresis
+char229 1853 2 0x86 1,35 # aring
+char230 2963 0 0x91 1,37 # ae
+char231 1667 0 0x87 1,39 # ccedilla
+char232 1853 2 0x8a 1,47 # egrave
+char233 1853 2 0x82 1,41 # eacute
+char234 1853 2 0x88 1,43 # ecircumflex
+char235 1853 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 1853 2 0x148 1,87 # eth
+char241 1853 2 0xa4 1,57 # ntilde
+char242 1853 2 0x95 1,65 # ograve
+char243 1853 2 0xa2 1,59 # oacute
+char244 1853 2 0x93 1,61 # ocircumflex
+char245 1853 2 0x172 1,83 # otilde
+char246 1853 2 0x94 1,63 # odieresis
+char247 1947 0 0xf6 6,8 # divide
+char248 2037 0 0x145 1,81 # oslash
+char249 1853 2 0x97 1,73 # ugrave
+char250 1853 2 0xa3 1,67 # uacute
+char251 1853 2 0x96 1,69 # ucircumflex
+char252 1853 2 0x81 1,71 # udieresis
+char253 1667 3 0x175 1,85 # yacute
+char254 1853 3 0x143 1,89 # thorn
+char255 1667 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 1853 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 2223 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 1853 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 3333 2 0x92 1,36 # AE
+ae 2963 0 0x91 1,37 # ae
+OE 3333 2 0x141 1,166 # OE
+oe 3147 0 0x146 1,167 # oe
+ij 1437 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 2037 2 0x147 1,23 # germandbls
+'A 2223 2 0x15a 1,26 # Aacute
+'E 2223 2 0x90 1,40 # Eacute
+'I 927 2 0x161 1,48 # Iacute
+'O 2593 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1853 2 0xa0 1,27 # aacute
+'e 1853 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 1853 2 0xa2 1,59 # oacute
+'u 1853 2 0x95 1,65 # uacute
+:A 2223 2 0x8e 1,30 # Adieresis
+:E 2223 2 0x15f 1,44 # Edieresis
+:I 927 2 0x163 1,52 # Idieresis
+:O 2593 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 2223 2 0x16d 1,74 # Ydieresis
+:a 1853 2 0x84 1,31 # adieresis
+:e 1853 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 1853 2 0x94 1,63 # odieresis
+:u 1853 2 0x81 1,71 # udieresis
+:y 1667 3 0x98 1,75 # ydieresis
+^A 2223 2 0x15b 1,28 # Acircumflex
+^E 2223 2 0x15e 1,42 # Ecircumflex
+^I 927 2 0x162 1,50 # Icircumflex
+^O 2593 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1853 2 0x83 1,29 # acircumflex
+^e 1853 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 1853 2 0x93 1,61 # ocircumflex
+^u 1853 2 0x96 1,69 # ucircumflex
+`A 2223 2 0x15c 1,32 # Agrave
+`E 2223 2 0x160 1,46 # Egrave
+`I 927 2 0x164 1,54 # Igrave
+`O 2593 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1853 2 0x85 1,33 # agrave
+~a 1853 2 0x284 --- # atilde
+`e 1853 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 1853 2 0x95 1,65 # ograve
+`u 1853 2 0x97 1,73 # ugrave
+~A 2223 2 0x28e 1,26 # Atilde
+~N 2407 2 0xa5 1,56 # Ntilde
+~O 2593 2 0x168 1,82 # Otilde
+~n 1853 2 0xa4 1,57 # ntilde
+~o 1853 2 0x172 1,83 # otilde
+vS 2223 2 0x169 1,176 # Scaron
+vs 1667 2 0x173 1,177 # scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vz 1667 2 0x174 1,207 # zcaron
+,C 2407 2 0x80 1,38 # Ccedilla
+,c 1667 0 0x87 1,39 # ccedilla
+/L 1853 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 740 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2593 2 0x140 1,80 # Oslash
+/o 2037 0 0x145 1,81 # oslash
+oA 2223 2 0x8f 1,34 # Aring
+oa 1853 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1853 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1853 2 0x24 0,36 # dollar
+Po 1853 2 0x9c 4,11 # sterling
+Ye 1853 2 0x9d 4,12 # yen
+Fn 1853 2 0x9f 4,14 # florin
+ct 1853 2 0x9b 4,19 # cent
+Fo 1853 0 0xae 4,9 # guillemotleft
+Fc 1110 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1110 1 0xad 4,7 # exclamdown
+r? 2037 1 0xa8 4,8 # questiondown
+fi 1667 2 0x130 4,54 # fi "fi ligature"
+fl 1667 2 0x131 4,55 # fl "fl ligature"
+OK 1667 0 0x3d6 --- # \& "check mark, tick"
+Of 1233 2 0xa6 4,15 # ordfeminine
+Om 1217 2 0xa7 4,16 # ordmasculine
+S1 1110 2 0x156 4,78 # onesuperior
+S2 1110 2 0xfd 4,20 # twosuperior
+S3 1110 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 867 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 3333 0 0x123 4,34 # ru "baseline rule"
+ul 1853 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0x3f4 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2457 2 0x154 4,23 # copyright
+rg 2457 2 0x155 4,22 # registered
+tm 3333 2 0x170 4,41 # trademark
+dd 1853 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1853 2 0x12a 4,39 # dagger
+ps 1790 2 0x14 4,5 # paragraph
+sc 1853 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 3333 0 0x123 4,34 # emdash "em dash"
+en 1853 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2780 2 0xab 4,17 # onehalf
+14 2780 2 0xac 4,18 # onequarter
+34 2780 2 0x12e 4,25 # threequarters
+f/ 556 2 0x158 6,6 # fraction "bar for fractions"
+fm 556 0 0x3a2 6,45 # minute "footmark, prime"
+sd 556 0 0x3b2 6,46 # second
+ha 556 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 556 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 1947 0 0x2d 6,0 # hyphen
+lB 927 2 0x5b 0,91 # bracketleft
+rB 927 2 0x5d 0,93 # bracketright
+lC 1113 2 0x7b 0,123 # braceleft
+rC 1113 2 0x7d 0,125 # braceright
+la 1113 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1113 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1110 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1110 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1110 2 0x125 4,32 # quotedblleft
+rq 1110 2 0x4ba 6,31 # quotedblright
+oq 740 2 0x176 4,29 # quoteleft "single open quote"
+aq 637 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 867 0 0x3f4 0,124 # bar
+at 3383 2 0x40 0,64 # at
+.C1 1947 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1853 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2377 0 0x346 8,44 # Phi
+*G 1907 0 0x347 8,6 # Gamma
+*H 1907 0 0x351 8,16 # Theta
+*I 1907 0 0x349 8,18 # Iota
+*K 1907 0 0x34b 8,20 # Kappa
+*L 1907 0 0x34c 8,22 # Lambda
+*M 1907 0 0x34d 8,24 # Mu
+*N 1907 0 0x34e 8,26 # Nu
+*O 1907 0 0x34f 8,30 # Omicron
+*P 1907 0 0x350 8,32 # Pi
+*Q 1907 0 0x359 8,48 # Psi
+*R 1907 0 0x352 8,34 # Rho
+*S 1973 0 0x353 8,36 # Sigma
+*T 1973 0 0x354 8,40 # Tau
+*U 1973 0 0x3a1 8,76 # Upsilon
+*W 2547 0 0x357 8,50 # Omega
+*X 1973 0 0x343 8,36 # Chi
+*Y 1973 0 0x348 8,14 # Eta
+*Z 1973 0 0x35a 8,12 # Zeta
+*a 2023 0 0xe0 8,1 # alpha
+*b 1893 0 0xe1 8,3 # beta
+*c 1893 0 0x378 8,29 # xi
+*d 1890 0 0xeb 8,9 # delta
+*e 1890 0 0x36e 8,70 # epsilon
+*f 1890 0 0x366 8,45 # phi
++f 1890 0 0x36a 8,77 # phi1 "variant phi"
+*g 1890 0 0x367 8,7 # gamma
+*h 1853 0 0xe9 8,17 # theta
++h 1853 0 0x375 8,71 # theta1 "variant theta"
+*i 1853 0 0x369 8,19 # iota
+*k 1853 0 0x36b 8,21 # kappa
+*l 1853 0 0x36c 8,23 # lambda
+*m 1853 0 0xe6 8,25 # mu
+*n 1853 0 0x36e 8,27 # nu
+*o 1853 0 0x36f 8,31 # omicron
+*p 1963 0 0xe3 8,33 # pi
++p 1963 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 1963 0 0x379 8,49 # psi
+*r 1963 0 0x372 8,35 # rho
+*s 2037 0 0xe5 8,37 # sigma
+*t 1463 0 0xe7 8,41 # tau
+*u 1463 0 0x375 8,27 # upsilon
+*w 1463 0 0x377 8,51 # omega
+*x 1463 0 0x363 8,47 # chi
+*y 1463 0 0x368 8,15 # eta
+*z 1463 0 0x37a 8,13 # zeta
+ts 1463 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 927 0 0x32a 0,32 # asteriskmath
++- 1947 0 0xf1 6,1 # plusminus
+<= 2413 0 0xf3 6,2 # lessequal
+== 2413 0 0x3ba 8,14 # equivalence
+=~ 2413 0 0x340 8,116 # congruent
+>= 1893 0 0x3b3 8,3 # greaterequal
+AN 1893 0 0x3d9 8,85 # logicaland
+OR 1893 0 0x3da 8,86 # logicalor
+no 1893 0 0x3d8 8,20 # logicalnot
+te 1893 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 1893 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 1893 0 0x3c0 9,0 # aleph
+Im 1893 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 1893 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 1893 0 0x3a5 8,19 # infinity
+md 1893 0 0x3b7 8,32 # dotmath
+mo 1893 0 0x3ce 8,15 # element
+mu 1893 0 0x3b4 8,39 # multiply
+nc 1893 0 0x3cb 8,197 # notpropersuperset
+nm 1893 0 0x3cf 8,209 # notelement
+pl 927 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 1947 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 1947 0 0x3b5 6,4 # proportional
+pp 1947 0 0x35e 8,89 # perpendicular
+sb 1947 0 0x3cc 6,67 # propersubset
+sp 1947 0 0x3c9 6,68 # propersuperset
+ib 1947 0 0x3cd 6,69 # reflexsubset
+ip 1947 0 0x3ca 6,70 # reflexsuperset
+ap 1947 0 0x37e 6,12 # similar
+pd 1947 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 1947 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 1947 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 1947 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2593 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1853 0 0xae 6,77 # "" "much less"
+>> 1853 0 0xaf 6,78 # "" "much greater"
+wp 1853 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1853 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 927 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/Makefile.sub b/contrib/groff/font/devlbp/Makefile.sub
new file mode 100644
index 0000000..6959b25
--- /dev/null
+++ b/contrib/groff/font/devlbp/Makefile.sub
@@ -0,0 +1,18 @@
+DEV=lbp
+LBPPRINT=$(PSPRINT)
+DEVFILES=DESC \
+ HB HBI HI HR \
+ TB TBI TI TR
+
+CLEANADD=DESC
+
+DESC: DESC.in
+ -rm -f DESC
+ cat $(srcdir)/DESC.in >>DESC
+ if test "$(PAGE)" = A4; then \
+ echo "papersize a4" >>DESC; \
+ else \
+ echo "papersize letter" >>DESC; \
+ fi
+ test -z '$(LBPPRINT)' || echo print '$(LBPPRINT)' >>DESC
+
diff --git a/contrib/groff/font/devlbp/TB b/contrib/groff/font/devlbp/TB
new file mode 100644
index 0000000..70a09f2
--- /dev/null
+++ b/contrib/groff/font/devlbp/TB
@@ -0,0 +1,513 @@
+name TB
+lbpname Dutch-Bold
+special
+spacewidth 833
+slant 0
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 1853 2 0x169 1,176 # Scaron
+vZ 2223 2 0x16e 1,206 # Zcaron
+vs 1297 2 0x173 1,177 # scaron
+vz 1480 2 0x174 1,207 # zcaron
+:Y 2407 2 0x16d 1,74 # Ydieresis
+tm 3333 2 0x170 4,41 # trademark
+aq 927 2 0x27 0,39 # quotesingle
+space 833 0 0x20 0,32
+! 1110 2 0x21 0,33 # exclam
+" 1850 2 0x22 0,34 # quotedbl
+dq 1850 2 0x22 0,34 # quotedbl
+# 1667 2 0x23 0,35 # numbersign
+sh 1667 2 0x23 0,35 # "
+$ 1667 2 0x24 0,36 # dollar
+Do 1667 2 0x24 0,36 # "
+% 3333 2 0x25 0,37 # percent
+& 2777 2 0x26 0,38 # ampersand
+' 927 2 0x27 0,39 # quoteright
+cq 927 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1667 2 0x2a 0,42 # asterisk
++ 1900 0 0x2b 0,43 # plus
+, 833 0 0x2c 0,44 # comma
+- 1900 0 0x2d 0,45 # hyphen
+\- 1900 0 0x2d 0,45 # hyphen
+hy 1900 0 0x2d 0,45 # "
+char173 1900 0 0x2d 0,45 # "
+. 833 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1667 2 0x30 0,48 # zero
+1 1667 2 0x31 0,49 # one
+2 1667 2 0x32 0,50 # two
+3 1667 2 0x33 0,51 # three
+4 1667 2 0x34 0,52 # four
+5 1667 2 0x35 0,53 # five
+6 1667 2 0x36 0,54 # six
+7 1667 2 0x37 0,55 # seven
+8 1667 2 0x38 0,56 # eight
+9 1667 2 0x39 0,57 # nine
+: 0 0 0x3a 0,58 # colon
+; 1110 0 0x3b 0,59 # semicolon
+< 1900 0 0x3c 0,60 # less
+= 1900 0 0x3d 0,61 # equal
+> 1900 0 0x3e 0,62 # greater
+? 1667 2 0x3f 0,63 # question
+@ 3100 2 0x40 0,64 # at
+at 3100 2 0x40 0,64 # "
+A 2407 2 0x41 0,65 # A
+B 2223 2 0x42 0,66 # B
+C 2407 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2223 2 0x45 0,69 # E
+F 2037 2 0x46 0,70 # F
+G 2593 2 0x47 0,71 # G
+H 2593 2 0x48 0,72 # H
+I 1297 2 0x49 0,73 # I
+J 1667 2 0x4a 0,74 # J
+K 2593 2 0x4b 0,75 # K
+L 2223 2 0x4c 0,76 # L
+M 3147 2 0x4d 0,77 # M
+N 2407 2 0x4e 0,78 # N
+O 2593 2 0x4f 0,79 # O
+P 2037 2 0x50 0,80 # P
+Q 2593 2 0x51 0,81 # Q
+R 2407 2 0x52 0,82 # R
+S 1853 2 0x53 0,83 # S
+T 2223 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2407 2 0x56 0,86 # V
+W 3333 2 0x57 0,87 # W
+X 2407 2 0x58 0,88 # X
+Y 2407 2 0x59 0,89 # Y
+Z 2223 2 0x5a 0,90 # Z
+[ 1110 2 0x5b 0,91 # bracketleft
+lB 1110 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 1110 2 0x5d 0,93 # bracketright
+rB 1110 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1667 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1667 0 0x61 0,97 # a
+b 1853 2 0x62 0,98 # b
+c 1480 0 0x63 0,99 # c
+d 1853 2 0x64 0,100 # d
+e 1480 0 0x65 0,101 # e
+f 1110 2 0x66 0,102 # f
+g 1667 1 0x67 0,103 # g
+h 1853 2 0x68 0,104 # h
+i 927 2 0x69 0,105 # i
+j 1110 2 0x6a 0,106 # j
+k 1853 2 0x6b 0,107 # k
+l 927 2 0x6c 0,108 # l
+m 2777 0 0x6d 0,109 # m
+n 1853 0 0x6e 0,110 # n
+o 1667 0 0x6f 0,111 # o
+p 1853 1 0x70 0,112 # p
+q 1853 1 0x71 0,113 # q
+r 1480 0 0x72 0,114 # r
+s 1297 0 0x73 0,115 # s
+t 1110 2 0x74 0,116 # t
+u 1853 0 0x75 0,117 # u
+v 1667 0 0x76 0,118 # v
+w 2407 0 0x77 0,119 # w
+x 1667 0 0x78 0,120 # x
+y 1667 1 0x79 0,121 # y
+z 1480 0 0x7a 0,122 # z
+lC 1313 2 0x7b 0,123 # braceleft
+{ 1313 2 0x7b 0,123 # "
+ba 733 2 0x7c 0,124 # bar
+| 733 2 0x7c 0,124 # "
+rC 1313 2 0x7d 0,125 # braceright
+} 1313 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1110 1 0xad 4,7 # exclamdown
+char162 1667 2 0x9b 4,19 # cent
+char163 1667 2 0x9c 4,11 # sterling
+char164 1667 2 0x12f 4,24 # currency
+char165 1667 2 0x9d 4,12 # yen
+char166 733 2 0x7c 0,124 # brokenbar
+char167 1667 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2490 2 0x154 4,23 # copyright
+char170 1000 2 0xa6 4,15 # ordfeminine
+char171 1667 0 0xae 4,9 # guillemotleft
+char172 1900 0 0xaa 6,20 # logicalnot
+char173 1667 0 0x132 4,33 # hyphen
+char174 2490 2 0x155 4,22 # registered
+char175 1900 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 1900 0 0xf1 6,1 # plusminus
+char178 1000 2 0xfd 4,20 # twosuperior
+char179 1000 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 1853 1 0xe6 8,25 # mu
+char182 1800 2 0x14 4,5 # paragraph
+char183 833 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1000 2 0x156 4,78 # onesuperior
+char186 1100 2 0xa7 4,16 # ordmasculine
+char187 1667 0 0xaf 4,10 # guillemotright
+char188 2500 2 0xac 4,18 # onequarter
+char189 2500 2 0xab 4,17 # onehalf
+char190 2500 2 0x12e 4,25 # threequarters
+char191 1667 1 0xa8 4,8 # questiondown
+char192 2407 2 0x15c 1,32 # Agrave
+char193 2407 2 0x15a 1,26 # Aacute
+char194 2407 2 0x15b 1,28 # Acircumflex
+char195 2407 2 0x28e 1,76 # Atilde
+char196 2407 2 0x8e 1,30 # Adieresis
+char197 2407 2 0x8f 1,34 # Aring
+char198 3333 2 0x92 1,36 # AE
+char199 2407 2 0x80 1,38 # Ccedilla
+char200 2223 2 0x160 1,46 # Egrave
+char201 2223 2 0x90 1,40 # Eacute
+char202 2223 2 0x15e 1,42 # Ecircumflex
+char203 2223 2 0x15f 1,44 # Edieresis
+char204 1297 2 0x164 1,54 # Igrave
+char205 1297 2 0x161 1,48 # Iacute
+char206 1297 2 0x162 1,50 # Icircumflex
+char207 1297 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2407 2 0xa5 1,56 # Ntilde
+char210 2593 2 0x167 1,64 # Ograve
+char211 2593 2 0x165 1,58 # Oacute
+char212 2593 2 0x166 1,60 # Ocircumflex
+char213 2593 2 0x168 1,82 # Otilde
+char214 2593 2 0x99 1,62 # Odieresis
+char215 1900 0 0x157 6,39 # multiply
+char216 2593 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 2407 2 0x16f 1,84 # Yacute
+char222 2037 2 0x13e 1,88 # Thorn
+char223 1853 2 0x147 1,23 # germandbls
+char224 1667 2 0x85 1,33 # agrave
+char225 1667 2 0xa0 1,27 # aacute
+char226 1667 2 0x83 1,29 # acircumflex
+char227 1667 2 0x284 1,93 # atilde
+char228 1667 2 0x84 1,31 # adieresis
+char229 1667 2 0x86 1,35 # aring
+char230 2407 0 0x91 1,37 # ae
+char231 1480 0 0x87 1,39 # ccedilla
+char232 1480 2 0x8a 1,47 # egrave
+char233 1480 2 0x82 1,41 # eacute
+char234 1480 2 0x88 1,43 # ecircumflex
+char235 1480 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 1667 2 0x148 1,87 # eth
+char241 1853 2 0xa4 1,57 # ntilde
+char242 1667 2 0x95 1,65 # ograve
+char243 1667 2 0xa2 1,59 # oacute
+char244 1667 2 0x93 1,61 # ocircumflex
+char245 1667 2 0x172 1,83 # otilde
+char246 1667 2 0x94 1,63 # odieresis
+char247 1900 0 0xf6 6,8 # divide
+char248 1667 0 0x145 1,81 # oslash
+char249 1853 2 0x97 1,73 # ugrave
+char250 1853 2 0xa3 1,67 # uacute
+char251 1853 2 0x96 1,69 # ucircumflex
+char252 1853 2 0x81 1,71 # udieresis
+char253 1667 3 0x175 1,85 # yacute
+char254 1853 3 0x143 1,89 # thorn
+char255 1667 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 1667 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 2037 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 1853 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 3333 2 0x92 1,36 # AE
+ae 2407 0 0x91 1,37 # ae
+OE 3333 2 0x141 1,166 # OE
+oe 2407 0 0x146 1,167 # oe
+ij 1990 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 1853 2 0x147 1,23 # germandbls
+'A 2407 2 0x15a 1,26 # Aacute
+'E 2223 2 0x90 1,40 # Eacute
+'I 1297 2 0x161 1,48 # Iacute
+'O 2593 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1667 2 0xa0 1,27 # aacute
+'e 1480 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 1667 2 0xa2 1,59 # oacute
+'u 1667 2 0x95 1,65 # uacute
+:A 2407 2 0x8e 1,30 # Adieresis
+:E 2223 2 0x15f 1,44 # Edieresis
+:I 1297 2 0x163 1,52 # Idieresis
+:O 2593 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 2407 2 0x16d 1,74 # Ydieresis
+:a 1667 2 0x84 1,31 # adieresis
+:e 1480 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 1667 2 0x94 1,63 # odieresis
+:u 1853 2 0x81 1,71 # udieresis
+:y 1667 3 0x98 1,75 # ydieresis
+^A 2407 2 0x15b 1,28 # Acircumflex
+^E 2223 2 0x15e 1,42 # Ecircumflex
+^I 1297 2 0x162 1,50 # Icircumflex
+^O 2593 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1667 2 0x83 1,29 # acircumflex
+^e 1480 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 1667 2 0x93 1,61 # ocircumflex
+^u 1853 2 0x96 1,69 # ucircumflex
+`A 2407 2 0x15c 1,32 # Agrave
+`E 2223 2 0x160 1,46 # Egrave
+`I 1297 2 0x164 1,54 # Igrave
+`O 2593 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1667 2 0x85 1,33 # agrave
+`e 1480 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 1667 2 0x95 1,65 # ograve
+`u 1853 2 0x97 1,73 # ugrave
+~A 2407 2 0x28e 1,26 # Atilde
+~N 2407 2 0xa5 1,56 # Ntilde
+~O 2593 2 0x168 1,82 # Otilde
+~a 1667 2 0x284 --- # atilde
+~n 1853 2 0xa4 1,57 # ntilde
+~o 1667 2 0x172 1,83 # otilde
+vS 1853 2 0x169 1,176 # Scaron
+vs 1297 2 0x173 1,177 # scaron
+vZ 2223 2 0x16e 1,206 # Zcaron
+vz 1480 2 0x174 1,207 # zcaron
+,C 2407 2 0x80 1,38 # Ccedilla
+,c 1480 0 0x87 1,39 # ccedilla
+/L 2223 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 927 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2593 2 0x140 1,80 # Oslash
+/o 1667 0 0x145 1,81 # oslash
+oA 2407 2 0x8f 1,34 # Aring
+oa 1667 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1667 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1667 2 0x24 0,36 # dollar
+Po 1667 2 0x9c 4,11 # sterling
+Ye 1667 2 0x9d 4,12 # yen
+Fn 1667 2 0x9f 4,14 # florin
+ct 1667 2 0x9b 4,19 # cent
+Fo 1667 0 0xae 4,9 # guillemotleft
+Fc 1000 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1110 1 0xad 4,7 # exclamdown
+r? 1667 1 0xa8 4,8 # questiondown
+fi 1853 2 0x130 4,54 # fi "fi ligature"
+fl 1853 2 0x131 4,55 # fl "fl ligature"
+OK 1853 0 0x3d6 --- # \& "check mark, tick"
+Of 1000 2 0xa6 4,15 # ordfeminine
+Om 1100 2 0xa7 4,16 # ordmasculine
+S1 1000 2 0x156 4,78 # onesuperior
+S2 1000 2 0xfd 4,20 # twosuperior
+S3 1000 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 733 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 3333 0 0x123 4,34 # ru "baseline rule"
+ul 1667 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0xb3 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2490 2 0x154 4,23 # copyright
+rg 2490 2 0x155 4,22 # registered
+tm 3333 2 0x170 4,41 # trademark
+dd 1667 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1667 2 0x12a 4,39 # dagger
+ps 1800 2 0x14 4,5 # paragraph
+sc 1667 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 3333 0 0x123 4,34 # emdash "em dash"
+en 1667 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2500 2 0xab 4,17 # onehalf
+14 2500 2 0xac 4,18 # onequarter
+34 2500 2 0x12e 4,25 # threequarters
+f/ 927 2 0x158 6,6 # fraction "bar for fractions"
+fm 927 0 0x3a2 6,45 # minute "footmark, prime"
+sd 927 0 0x3b2 6,46 # second
+ha 927 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 927 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 1900 0 0x2d 6,0 # hyphen
+lB 1110 2 0x5b 0,91 # bracketleft
+rB 1110 2 0x5d 0,93 # bracketright
+lC 1313 2 0x7b 0,123 # braceleft
+rC 1313 2 0x7d 0,125 # braceright
+la 1313 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1313 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1667 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1667 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1667 2 0x125 4,32 # quotedblleft
+rq 1667 2 0x4ba 6,31 # quotedblright
+oq 1110 2 0x176 4,29 # quoteleft "single open quote"
+aq 927 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 733 0 0x3f4 0,124 # bar
+at 3100 2 0x40 0,64 # at
+.C1 1900 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1667 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2560 0 0x346 8,44 # Phi
+*G 2003 0 0x347 8,6 # Gamma
+*H 2003 0 0x351 8,16 # Theta
+*I 2003 0 0x349 8,18 # Iota
+*K 2003 0 0x34b 8,20 # Kappa
+*L 2003 0 0x34c 8,22 # Lambda
+*M 2003 0 0x34d 8,24 # Mu
+*N 2003 0 0x34e 8,26 # Nu
+*O 2003 0 0x34f 8,30 # Omicron
+*P 2003 0 0x350 8,32 # Pi
+*Q 2003 0 0x359 8,48 # Psi
+*R 2003 0 0x352 8,34 # Rho
+*S 2203 0 0x353 8,36 # Sigma
+*T 2203 0 0x354 8,40 # Tau
+*U 2203 0 0x3a1 8,76 # Upsilon
+*W 2510 0 0x357 8,50 # Omega
+*X 2203 0 0x343 8,36 # Chi
+*Y 2203 0 0x348 8,14 # Eta
+*Z 2203 0 0x35a 8,12 # Zeta
+*a 1787 0 0xe0 8,1 # alpha
+*b 1633 0 0xe1 8,3 # beta
+*c 1633 0 0x378 8,29 # xi
+*d 1610 0 0xeb 8,9 # delta
+*e 1610 0 0x36e 8,70 # epsilon
+*f 1610 0 0x366 8,45 # phi
++f 1610 0 0x36a 8,77 # phi1 "variant phi"
+*g 1610 0 0x367 8,7 # gamma
+*h 1587 0 0xe9 8,17 # theta
++h 1587 0 0x375 8,71 # theta1 "variant theta"
+*i 1587 0 0x369 8,19 # iota
+*k 1587 0 0x36b 8,21 # kappa
+*l 1587 0 0x36c 8,23 # lambda
+*m 1853 0 0xe6 8,25 # mu
+*n 1853 0 0x36e 8,27 # nu
+*o 1853 0 0x36f 8,31 # omicron
+*p 1920 0 0xe3 8,33 # pi
++p 1920 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 1920 0 0x379 8,49 # psi
+*r 1920 0 0x372 8,35 # rho
+*s 1747 0 0xe5 8,37 # sigma
+*t 1473 0 0xe7 8,41 # tau
+*u 1473 0 0x375 8,27 # upsilon
+*w 1473 0 0x377 8,51 # omega
+*x 1473 0 0x363 8,47 # chi
+*y 1473 0 0x368 8,15 # eta
+*z 1473 0 0x37a 8,13 # zeta
+ts 1473 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 833 0 0x32a 0,32 # asteriskmath
++- 1900 0 0xf1 6,1 # plusminus
+<= 2407 0 0xf3 6,2 # lessequal
+== 2407 0 0x3ba 8,14 # equivalence
+=~ 2407 0 0x340 8,116 # congruent
+>= 1633 0 0x3b3 8,3 # greaterequal
+AN 1633 0 0x3d9 8,85 # logicaland
+OR 1633 0 0x3da 8,86 # logicalor
+no 1633 0 0x3d8 8,20 # logicalnot
+te 1633 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 1633 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 1633 0 0x3c0 9,0 # aleph
+Im 1633 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 1633 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 1633 0 0x3a5 8,19 # infinity
+md 1633 0 0x3b7 8,32 # dotmath
+mo 1633 0 0x3ce 8,15 # element
+mu 1633 0 0x3b4 8,39 # multiply
+nc 1633 0 0x3cb 8,197 # notpropersuperset
+nm 1633 0 0x3cf 8,209 # notelement
+pl 1110 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 1900 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 1900 0 0x3b5 6,4 # proportional
+pp 1900 0 0x35e 8,89 # perpendicular
+sb 1900 0 0x3cc 6,67 # propersubset
+sp 1900 0 0x3c9 6,68 # propersuperset
+ib 1900 0 0x3cd 6,69 # reflexsubset
+ip 1900 0 0x3ca 6,70 # reflexsuperset
+ap 1900 0 0x37e 6,12 # similar
+pd 1900 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 1900 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 1900 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 1900 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2593 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1667 0 0xae 6,77 # "" "much less"
+>> 1667 0 0xaf 6,78 # "" "much greater"
+wp 1667 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1667 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 833 0 0xfa 6,32 # periodcentered
+kernpairs
+V A -120
+W A -96
+Y A -72
+Y C -48
+A V -120
+A W -120
+A Y -120
+V a -24
+Y a -48
+V c -48
+Y c -48
+P e -48
+V e -48
+Y e -72
+V o -48
+W o -48
+Y o -96
+A v -48
+A w -48
diff --git a/contrib/groff/font/devlbp/TBI b/contrib/groff/font/devlbp/TBI
new file mode 100644
index 0000000..1c2f8fe
--- /dev/null
+++ b/contrib/groff/font/devlbp/TBI
@@ -0,0 +1,493 @@
+name TBI
+lbpname Dutch-BoldItalic
+special
+spacewidth 833
+slant 18.49
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 1853 2 0x169 1,176 # Scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vs 1297 2 0x173 1,177 # scaron
+vz 1297 2 0x174 1,207 # zcaron
+:Y 2037 2 0x16d 1,74 # Ydieresis
+tm 3333 2 0x170 4,41 # trademark
+aq 927 2 0x27 0,39 # quotesingle
+space 833 0 0x20 0,32
+! 1297 2 0x21 0,33 # exclam
+" 1850 2 0x22 0,34 # quotedbl
+dq 1850 2 0x22 0,34 # quotedbl
+# 1667 2 0x23 0,35 # numbersign
+sh 1667 2 0x23 0,35 # "
+$ 1667 2 0x24 0,36 # dollar
+Do 1667 2 0x24 0,36 # "
+% 2777 2 0x25 0,37 # percent
+& 2593 2 0x26 0,38 # ampersand
+' 927 2 0x27 0,39 # quoteright
+cq 927 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1667 2 0x2a 0,42 # asterisk
++ 1900 0 0x2b 0,43 # plus
+, 833 0 0x2c 0,44 # comma
+- 2020 0 0x2d 0,45 # hyphen
+\- 2020 0 0x2d 0,45 # hyphen
+hy 2020 0 0x2d 0,45 # "
+char173 2020 0 0x2d 0,45 # "
+. 833 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1667 2 0x30 0,48 # zero
+1 1667 2 0x31 0,49 # one
+2 1667 2 0x32 0,50 # two
+3 1667 2 0x33 0,51 # three
+4 1667 2 0x34 0,52 # four
+5 1667 2 0x35 0,53 # five
+6 1667 2 0x36 0,54 # six
+7 1667 2 0x37 0,55 # seven
+8 1667 2 0x38 0,56 # eight
+9 1667 2 0x39 0,57 # nine
+: 1110 0 0x3a 0,58 # colon
+; 1110 0 0x3b 0,59 # semicolon
+< 1900 0 0x3c 0,60 # less
+= 1900 0 0x3d 0,61 # equal
+> 1900 0 0x3e 0,62 # greater
+? 1667 2 0x3f 0,63 # question
+@ 2773 2 0x40 0,64 # at
+at 2773 2 0x40 0,64 # "
+A 2223 2 0x41 0,65 # A
+B 2223 2 0x42 0,66 # B
+C 2223 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2223 2 0x45 0,69 # E
+F 2223 2 0x46 0,70 # F
+G 2407 2 0x47 0,71 # G
+H 2593 2 0x48 0,72 # H
+I 1297 2 0x49 0,73 # I
+J 1667 2 0x4a 0,74 # J
+K 2223 2 0x4b 0,75 # K
+L 2037 2 0x4c 0,76 # L
+M 2963 2 0x4d 0,77 # M
+N 2407 2 0x4e 0,78 # N
+O 2407 2 0x4f 0,79 # O
+P 2037 2 0x50 0,80 # P
+Q 2407 2 0x51 0,81 # Q
+R 2223 2 0x52 0,82 # R
+S 1853 2 0x53 0,83 # S
+T 2037 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2223 2 0x56 0,86 # V
+W 2963 2 0x57 0,87 # W
+X 2223 2 0x58 0,88 # X
+Y 2037 2 0x59 0,89 # Y
+Z 2037 2 0x5a 0,90 # Z
+[ 1110 2 0x5b 0,91 # bracketleft
+lB 1110 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 1110 2 0x5d 0,93 # bracketright
+rB 1110 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1667 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1667 0 0x61 0,97 # a
+b 1667 2 0x62 0,98 # b
+c 1480 0 0x63 0,99 # c
+d 1667 2 0x64 0,100 # d
+e 1480 0 0x65 0,101 # e
+f 1110 2 0x66 0,102 # f
+g 1667 1 0x67 0,103 # g
+h 1853 2 0x68 0,104 # h
+i 927 2 0x69 0,105 # i
+j 927 2 0x6a 0,106 # j
+k 1667 2 0x6b 0,107 # k
+l 927 2 0x6c 0,108 # l
+m 2593 0 0x6d 0,109 # m
+n 1853 0 0x6e 0,110 # n
+o 1667 0 0x6f 0,111 # o
+p 1667 1 0x70 0,112 # p
+q 1667 1 0x71 0,113 # q
+r 1297 0 0x72 0,114 # r
+s 1297 0 0x73 0,115 # s
+t 927 2 0x74 0,116 # t
+u 1853 0 0x75 0,117 # u
+v 1480 0 0x76 0,118 # v
+w 2223 0 0x77 0,119 # w
+x 1667 0 0x78 0,120 # x
+y 1480 1 0x79 0,121 # y
+z 1297 0 0x7a 0,122 # z
+lC 1160 2 0x7b 0,123 # braceleft
+{ 1160 2 0x7b 0,123 # "
+ba 733 2 0x7c 0,124 # bar
+| 733 2 0x7c 0,124 # "
+rC 1160 2 0x7d 0,125 # braceright
+} 1160 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1297 1 0xad 4,7 # exclamdown
+char162 1667 2 0x9b 4,19 # cent
+char163 1667 2 0x9c 4,11 # sterling
+char164 1667 2 0x12f 4,24 # currency
+char165 1667 2 0x9d 4,12 # yen
+char166 733 2 0x7c 0,124 # brokenbar
+char167 1667 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2490 2 0x154 4,23 # copyright
+char170 887 2 0xa6 4,15 # ordfeminine
+char171 1667 0 0xae 4,9 # guillemotleft
+char172 2020 0 0xaa 6,20 # logicalnot
+char173 1667 0 0x132 4,33 # hyphen
+char174 2490 2 0x155 4,22 # registered
+char175 2020 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 1900 0 0xf1 6,1 # plusminus
+char178 1000 2 0xfd 4,20 # twosuperior
+char179 1000 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 1920 1 0xe6 8,25 # mu
+char182 1667 2 0x14 4,5 # paragraph
+char183 833 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1000 2 0x156 4,78 # onesuperior
+char186 1000 2 0xa7 4,16 # ordmasculine
+char187 1667 0 0xaf 4,10 # guillemotright
+char188 2500 2 0xac 4,18 # onequarter
+char189 2500 2 0xab 4,17 # onehalf
+char190 2500 2 0x12e 4,25 # threequarters
+char191 1667 1 0xa8 4,8 # questiondown
+char192 2223 2 0x15c 1,32 # Agrave
+char193 2223 2 0x15a 1,26 # Aacute
+char194 2223 2 0x15b 1,28 # Acircumflex
+char195 2223 2 0x28e 1,76 # Atilde
+char196 2223 2 0x8e 1,30 # Adieresis
+char197 2223 2 0x8f 1,34 # Aring
+char198 3147 2 0x92 1,36 # AE
+char199 2223 2 0x80 1,38 # Ccedilla
+char200 2223 2 0x160 1,46 # Egrave
+char201 2223 2 0x90 1,40 # Eacute
+char202 2223 2 0x15e 1,42 # Ecircumflex
+char203 2223 2 0x15f 1,44 # Edieresis
+char204 1297 2 0x164 1,54 # Igrave
+char205 1297 2 0x161 1,48 # Iacute
+char206 1297 2 0x162 1,50 # Icircumflex
+char207 1297 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2407 2 0xa5 1,56 # Ntilde
+char210 2407 2 0x167 1,64 # Ograve
+char211 2407 2 0x165 1,58 # Oacute
+char212 2407 2 0x166 1,60 # Ocircumflex
+char213 2407 2 0x168 1,82 # Otilde
+char214 2407 2 0x99 1,62 # Odieresis
+char215 1900 0 0x157 6,39 # multiply
+char216 2407 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 2037 2 0x16f 1,84 # Yacute
+char222 2037 2 0x13e 1,88 # Thorn
+char223 1667 2 0x147 1,23 # germandbls
+char224 1667 2 0x85 1,33 # agrave
+char225 1667 2 0xa0 1,27 # aacute
+char226 1667 2 0x83 1,29 # acircumflex
+char227 1667 2 0x284 1,93 # atilde
+char228 1667 2 0x84 1,31 # adieresis
+char229 1667 2 0x86 1,35 # aring
+char230 2407 0 0x91 1,37 # ae
+char231 1480 0 0x87 1,39 # ccedilla
+char232 1480 2 0x8a 1,47 # egrave
+char233 1480 2 0x82 1,41 # eacute
+char234 1480 2 0x88 1,43 # ecircumflex
+char235 1480 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 1667 2 0x148 1,87 # eth
+char241 1853 2 0xa4 1,57 # ntilde
+char242 1667 2 0x95 1,65 # ograve
+char243 1667 2 0xa2 1,59 # oacute
+char244 1667 2 0x93 1,61 # ocircumflex
+char245 1667 2 0x172 1,83 # otilde
+char246 1667 2 0x94 1,63 # odieresis
+char247 1900 0 0xf6 6,8 # divide
+char248 1667 0 0x145 1,81 # oslash
+char249 1853 2 0x97 1,73 # ugrave
+char250 1853 2 0xa3 1,67 # uacute
+char251 1853 2 0x96 1,69 # ucircumflex
+char252 1853 2 0x81 1,71 # udieresis
+char253 1480 3 0x175 1,85 # yacute
+char254 1667 3 0x143 1,89 # thorn
+char255 1480 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 1667 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 2037 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 1667 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 3147 2 0x92 1,36 # AE
+ae 2407 0 0x91 1,37 # ae
+OE 3147 2 0x141 1,166 # OE
+oe 2407 0 0x146 1,167 # oe
+ij 1807 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 1667 2 0x147 1,23 # germandbls
+'A 2223 2 0x15a 1,26 # Aacute
+'E 2223 2 0x90 1,40 # Eacute
+'I 1297 2 0x161 1,48 # Iacute
+'O 2407 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1667 2 0xa0 1,27 # aacute
+'e 1480 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 1667 2 0xa2 1,59 # oacute
+'u 1667 2 0x95 1,65 # uacute
+:A 2223 2 0x8e 1,30 # Adieresis
+:E 2223 2 0x15f 1,44 # Edieresis
+:I 1297 2 0x163 1,52 # Idieresis
+:O 2407 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 2037 2 0x16d 1,74 # Ydieresis
+:a 1667 2 0x84 1,31 # adieresis
+:e 1480 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 1667 2 0x94 1,63 # odieresis
+:u 1853 2 0x81 1,71 # udieresis
+:y 1480 3 0x98 1,75 # ydieresis
+^A 2223 2 0x15b 1,28 # Acircumflex
+^E 2223 2 0x15e 1,42 # Ecircumflex
+^I 1297 2 0x162 1,50 # Icircumflex
+^O 2407 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1667 2 0x83 1,29 # acircumflex
+^e 1480 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 1667 2 0x93 1,61 # ocircumflex
+^u 1853 2 0x96 1,69 # ucircumflex
+`A 2223 2 0x15c 1,32 # Agrave
+`E 2223 2 0x160 1,46 # Egrave
+`I 1297 2 0x164 1,54 # Igrave
+`O 2407 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1667 2 0x85 1,33 # agrave
+`e 1480 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 1667 2 0x95 1,65 # ograve
+`u 1853 2 0x97 1,73 # ugrave
+~A 2223 2 0x28e 1,26 # Atilde
+~N 2407 2 0xa5 1,56 # Ntilde
+~O 2407 2 0x168 1,82 # Otilde
+~a 1667 2 0x284 --- # atilde
+~n 1853 2 0xa4 1,57 # ntilde
+~o 1667 2 0x172 1,83 # otilde
+vS 1853 2 0x169 1,176 # Scaron
+vs 1297 2 0x173 1,177 # scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vz 1297 2 0x174 1,207 # zcaron
+,C 2223 2 0x80 1,38 # Ccedilla
+,c 1480 0 0x87 1,39 # ccedilla
+/L 2037 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 927 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2407 2 0x140 1,80 # Oslash
+/o 1667 0 0x145 1,81 # oslash
+oA 2223 2 0x8f 1,34 # Aring
+oa 1667 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1667 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1667 2 0x24 0,36 # dollar
+Po 1667 2 0x9c 4,11 # sterling
+Ye 1667 2 0x9d 4,12 # yen
+Fn 1667 2 0x9f 4,14 # florin
+ct 1667 2 0x9b 4,19 # cent
+Fo 1667 0 0xae 4,9 # guillemotleft
+Fc 1000 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1297 1 0xad 4,7 # exclamdown
+r? 1667 1 0xa8 4,8 # questiondown
+fi 1853 2 0x130 4,54 # fi "fi ligature"
+fl 1853 2 0x131 4,55 # fl "fl ligature"
+OK 1853 0 0x3d6 --- # \& "check mark, tick"
+Of 887 2 0xa6 4,15 # ordfeminine
+Om 1000 2 0xa7 4,16 # ordmasculine
+S1 1000 2 0x156 4,78 # onesuperior
+S2 1000 2 0xfd 4,20 # twosuperior
+S3 1000 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 733 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 3333 0 0x123 4,34 # ru "baseline rule"
+ul 1667 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0xb3 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2490 2 0x154 4,23 # copyright
+rg 2490 2 0x155 4,22 # registered
+tm 3333 2 0x170 4,41 # trademark
+dd 1667 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1667 2 0x12a 4,39 # dagger
+ps 1667 2 0x14 4,5 # paragraph
+sc 1667 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 3333 0 0x123 4,34 # emdash "em dash"
+en 1667 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2500 2 0xab 4,17 # onehalf
+14 2500 2 0xac 4,18 # onequarter
+34 2500 2 0x12e 4,25 # threequarters
+f/ 927 2 0x158 6,6 # fraction "bar for fractions"
+fm 927 0 0x3a2 6,45 # minute "footmark, prime"
+sd 927 0 0x3b2 6,46 # second
+ha 927 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 927 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 2020 0 0x2d 6,0 # hyphen
+lB 1110 2 0x5b 0,91 # bracketleft
+rB 1110 2 0x5d 0,93 # bracketright
+lC 1160 2 0x7b 0,123 # braceleft
+rC 1160 2 0x7d 0,125 # braceright
+la 1160 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1160 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1667 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1667 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1667 2 0x125 4,32 # quotedblleft
+rq 1667 2 0x4ba 6,31 # quotedblright
+oq 1110 2 0x176 4,29 # quoteleft "single open quote"
+aq 927 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 733 0 0x3f4 0,124 # bar
+at 2773 2 0x40 0,64 # at
+.C1 2020 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1667 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2560 0 0x346 8,44 # Phi
+*G 2003 0 0x347 8,6 # Gamma
+*H 2003 0 0x351 8,16 # Theta
+*I 2003 0 0x349 8,18 # Iota
+*K 2003 0 0x34b 8,20 # Kappa
+*L 2003 0 0x34c 8,22 # Lambda
+*M 2003 0 0x34d 8,24 # Mu
+*N 2003 0 0x34e 8,26 # Nu
+*O 2003 0 0x34f 8,30 # Omicron
+*P 2003 0 0x350 8,32 # Pi
+*Q 2003 0 0x359 8,48 # Psi
+*R 2003 0 0x352 8,34 # Rho
+*S 2203 0 0x353 8,36 # Sigma
+*T 2203 0 0x354 8,40 # Tau
+*U 2203 0 0x3a1 8,76 # Upsilon
+*W 2510 0 0x357 8,50 # Omega
+*X 2203 0 0x343 8,36 # Chi
+*Y 2203 0 0x348 8,14 # Eta
+*Z 2203 0 0x35a 8,12 # Zeta
+*a 1787 0 0xe0 8,1 # alpha
+*b 1633 0 0xe1 8,3 # beta
+*c 1633 0 0x378 8,29 # xi
+*d 1610 0 0xeb 8,9 # delta
+*e 1610 0 0x36e 8,70 # epsilon
+*f 1610 0 0x366 8,45 # phi
++f 1610 0 0x36a 8,77 # phi1 "variant phi"
+*g 1610 0 0x367 8,7 # gamma
+*h 1587 0 0xe9 8,17 # theta
++h 1587 0 0x375 8,71 # theta1 "variant theta"
+*i 1587 0 0x369 8,19 # iota
+*k 1587 0 0x36b 8,21 # kappa
+*l 1587 0 0x36c 8,23 # lambda
+*m 1920 0 0xe6 8,25 # mu
+*n 1920 0 0x36e 8,27 # nu
+*o 1920 0 0x36f 8,31 # omicron
+*p 1920 0 0xe3 8,33 # pi
++p 1920 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 1920 0 0x379 8,49 # psi
+*r 1920 0 0x372 8,35 # rho
+*s 1747 0 0xe5 8,37 # sigma
+*t 1473 0 0xe7 8,41 # tau
+*u 1473 0 0x375 8,27 # upsilon
+*w 1473 0 0x377 8,51 # omega
+*x 1473 0 0x363 8,47 # chi
+*y 1473 0 0x368 8,15 # eta
+*z 1473 0 0x37a 8,13 # zeta
+ts 1473 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 833 0 0x32a 0,32 # asteriskmath
++- 1900 0 0xf1 6,1 # plusminus
+<= 2407 0 0xf3 6,2 # lessequal
+== 2407 0 0x3ba 8,14 # equivalence
+=~ 2407 0 0x340 8,116 # congruent
+>= 1633 0 0x3b3 8,3 # greaterequal
+AN 1633 0 0x3d9 8,85 # logicaland
+OR 1633 0 0x3da 8,86 # logicalor
+no 1633 0 0x3d8 8,20 # logicalnot
+te 1633 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 1633 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 1633 0 0x3c0 9,0 # aleph
+Im 1633 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 1633 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 1633 0 0x3a5 8,19 # infinity
+md 1633 0 0x3b7 8,32 # dotmath
+mo 1633 0 0x3ce 8,15 # element
+mu 1633 0 0x3b4 8,39 # multiply
+nc 1633 0 0x3cb 8,197 # notpropersuperset
+nm 1633 0 0x3cf 8,209 # notelement
+pl 1110 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 1900 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 1900 0 0x3b5 6,4 # proportional
+pp 1900 0 0x35e 8,89 # perpendicular
+sb 1900 0 0x3cc 6,67 # propersubset
+sp 1900 0 0x3c9 6,68 # propersuperset
+ib 1900 0 0x3cd 6,69 # reflexsubset
+ip 1900 0 0x3ca 6,70 # reflexsuperset
+ap 1900 0 0x37e 6,12 # similar
+pd 1900 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 1900 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 1900 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 1900 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2407 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1667 0 0xae 6,77 # "" "much less"
+>> 1667 0 0xaf 6,78 # "" "much greater"
+wp 1667 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1667 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 833 0 0xfa 6,32 # periodcentered
diff --git a/contrib/groff/font/devlbp/TI b/contrib/groff/font/devlbp/TI
new file mode 100644
index 0000000..7de08bc
--- /dev/null
+++ b/contrib/groff/font/devlbp/TI
@@ -0,0 +1,521 @@
+name TI
+lbpname Dutch-Italic
+special
+spacewidth 833
+slant 18.49
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 1667 2 0x169 1,176 # Scaron
+vZ 1853 2 0x16e 1,206 # Zcaron
+vs 1297 2 0x173 1,177 # scaron
+vz 1297 2 0x174 1,207 # zcaron
+:Y 1853 2 0x16d 1,74 # Ydieresis
+tm 3266 2 0x170 4,41 # trademark
+aq 713 2 0x27 0,39 # quotesingle
+space 833 0 0x20 0,32
+! 1110 2 0x21 0,33 # exclam
+" 1400 2 0x22 0,34 # quotedbl
+dq 1400 2 0x22 0,34 # quotedbl
+# 1667 2 0x23 0,35 # numbersign
+sh 1667 2 0x23 0,35 # "
+$ 1667 2 0x24 0,36 # dollar
+Do 1667 2 0x24 0,36 # "
+% 2777 2 0x25 0,37 # percent
+& 2593 2 0x26 0,38 # ampersand
+' 713 2 0x27 0,39 # quoteright
+cq 713 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1667 2 0x2a 0,42 # asterisk
++ 2250 0 0x2b 0,43 # plus
+, 833 0 0x2c 0,44 # comma
+- 2250 0 0x2d 0,45 # hyphen
+\- 2250 0 0x2d 0,45 # hyphen
+hy 2250 0 0x2d 0,45 # "
+char173 2250 0 0x2d 0,45 # "
+. 833 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1667 2 0x30 0,48 # zero
+1 1667 2 0x31 0,49 # one
+2 1667 2 0x32 0,50 # two
+3 1667 2 0x33 0,51 # three
+4 1667 2 0x34 0,52 # four
+5 1667 2 0x35 0,53 # five
+6 1667 2 0x36 0,54 # six
+7 1667 2 0x37 0,55 # seven
+8 1667 2 0x38 0,56 # eight
+9 1667 2 0x39 0,57 # nine
+: 0 0 0x3a 0,58 # colon
+; 1110 0 0x3b 0,59 # semicolon
+< 2250 0 0x3c 0,60 # less
+= 2250 0 0x3d 0,61 # equal
+> 2250 0 0x3e 0,62 # greater
+? 1667 2 0x3f 0,63 # question
+@ 3067 2 0x40 0,64 # at
+at 3067 2 0x40 0,64 # "
+A 2037 2 0x41 0,65 # A
+B 2037 2 0x42 0,66 # B
+C 2223 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2037 2 0x45 0,69 # E
+F 2037 2 0x46 0,70 # F
+G 2407 2 0x47 0,71 # G
+H 2407 2 0x48 0,72 # H
+I 1110 2 0x49 0,73 # I
+J 1480 2 0x4a 0,74 # J
+K 2223 2 0x4b 0,75 # K
+L 1853 2 0x4c 0,76 # L
+M 2777 2 0x4d 0,77 # M
+N 2223 2 0x4e 0,78 # N
+O 2407 2 0x4f 0,79 # O
+P 2037 2 0x50 0,80 # P
+Q 2407 2 0x51 0,81 # Q
+R 2037 2 0x52 0,82 # R
+S 1667 2 0x53 0,83 # S
+T 1853 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2037 2 0x56 0,86 # V
+W 2777 2 0x57 0,87 # W
+X 2037 2 0x58 0,88 # X
+Y 1853 2 0x59 0,89 # Y
+Z 1853 2 0x5a 0,90 # Z
+[ 1297 2 0x5b 0,91 # bracketleft
+lB 1297 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 1297 2 0x5d 0,93 # bracketright
+rB 1297 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1667 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1667 0 0x61 0,97 # a
+b 1667 2 0x62 0,98 # b
+c 1480 0 0x63 0,99 # c
+d 1667 2 0x64 0,100 # d
+e 1480 0 0x65 0,101 # e
+f 927 2 0x66 0,102 # f
+g 1667 1 0x67 0,103 # g
+h 1667 2 0x68 0,104 # h
+i 927 2 0x69 0,105 # i
+j 927 2 0x6a 0,106 # j
+k 1480 2 0x6b 0,107 # k
+l 927 2 0x6c 0,108 # l
+m 2407 0 0x6d 0,109 # m
+n 1667 0 0x6e 0,110 # n
+o 1667 0 0x6f 0,111 # o
+p 1667 1 0x70 0,112 # p
+q 1667 1 0x71 0,113 # q
+r 1297 0 0x72 0,114 # r
+s 1297 0 0x73 0,115 # s
+t 927 2 0x74 0,116 # t
+u 1667 0 0x75 0,117 # u
+v 1480 0 0x76 0,118 # v
+w 2223 0 0x77 0,119 # w
+x 1480 0 0x78 0,120 # x
+y 1480 1 0x79 0,121 # y
+z 1297 0 0x7a 0,122 # z
+lC 1333 2 0x7b 0,123 # braceleft
+{ 1333 2 0x7b 0,123 # "
+ba 917 2 0x7c 0,124 # bar
+| 917 2 0x7c 0,124 # "
+rC 1333 2 0x7d 0,125 # braceright
+} 1333 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1297 1 0xad 4,7 # exclamdown
+char162 1667 2 0x9b 4,19 # cent
+char163 1667 2 0x9c 4,11 # sterling
+char164 1667 2 0x12f 4,24 # currency
+char165 1667 2 0x9d 4,12 # yen
+char166 917 2 0x7c 0,124 # brokenbar
+char167 1667 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2533 2 0x154 4,23 # copyright
+char170 920 2 0xa6 4,15 # ordfeminine
+char171 1667 0 0xae 4,9 # guillemotleft
+char172 2250 0 0xaa 6,20 # logicalnot
+char173 1667 0 0x132 4,33 # hyphen
+char174 2533 2 0x155 4,22 # registered
+char175 2250 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 2250 0 0xf1 6,1 # plusminus
+char178 1000 2 0xfd 4,20 # twosuperior
+char179 1000 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 1667 1 0xe6 8,25 # mu
+char182 1743 2 0x14 4,5 # paragraph
+char183 833 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1000 2 0x156 4,78 # onesuperior
+char186 1033 2 0xa7 4,16 # ordmasculine
+char187 1667 0 0xaf 4,10 # guillemotright
+char188 2500 2 0xac 4,18 # onequarter
+char189 2500 2 0xab 4,17 # onehalf
+char190 2500 2 0x12e 4,25 # threequarters
+char191 1667 1 0xa8 4,8 # questiondown
+char192 2037 2 0x15c 1,32 # Agrave
+char193 2037 2 0x15a 1,26 # Aacute
+char194 2037 2 0x15b 1,28 # Acircumflex
+char195 2037 2 0x28e 1,76 # Atilde
+char196 2037 2 0x8e 1,30 # Adieresis
+char197 2037 2 0x8f 1,34 # Aring
+char198 2963 2 0x92 1,36 # AE
+char199 2223 2 0x80 1,38 # Ccedilla
+char200 2037 2 0x160 1,46 # Egrave
+char201 2037 2 0x90 1,40 # Eacute
+char202 2037 2 0x15e 1,42 # Ecircumflex
+char203 2037 2 0x15f 1,44 # Edieresis
+char204 1110 2 0x164 1,54 # Igrave
+char205 1110 2 0x161 1,48 # Iacute
+char206 1110 2 0x162 1,50 # Icircumflex
+char207 1110 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2223 2 0xa5 1,56 # Ntilde
+char210 2407 2 0x167 1,64 # Ograve
+char211 2407 2 0x165 1,58 # Oacute
+char212 2407 2 0x166 1,60 # Ocircumflex
+char213 2407 2 0x168 1,82 # Otilde
+char214 2407 2 0x99 1,62 # Odieresis
+char215 2250 0 0x157 6,39 # multiply
+char216 2407 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 1853 2 0x16f 1,84 # Yacute
+char222 2037 2 0x13e 1,88 # Thorn
+char223 1667 2 0x147 1,23 # germandbls
+char224 1667 2 0x85 1,33 # agrave
+char225 1667 2 0xa0 1,27 # aacute
+char226 1667 2 0x83 1,29 # acircumflex
+char227 1667 2 0x284 1,93 # atilde
+char228 1667 2 0x84 1,31 # adieresis
+char229 1667 2 0x86 1,35 # aring
+char230 2223 0 0x91 1,37 # ae
+char231 1480 0 0x87 1,39 # ccedilla
+char232 1480 2 0x8a 1,47 # egrave
+char233 1480 2 0x82 1,41 # eacute
+char234 1480 2 0x88 1,43 # ecircumflex
+char235 1480 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 1667 2 0x148 1,87 # eth
+char241 1667 2 0xa4 1,57 # ntilde
+char242 1667 2 0x95 1,65 # ograve
+char243 1667 2 0xa2 1,59 # oacute
+char244 1667 2 0x93 1,61 # ocircumflex
+char245 1667 2 0x172 1,83 # otilde
+char246 1667 2 0x94 1,63 # odieresis
+char247 2250 0 0xf6 6,8 # divide
+char248 1667 0 0x145 1,81 # oslash
+char249 1667 2 0x97 1,73 # ugrave
+char250 1667 2 0xa3 1,67 # uacute
+char251 1667 2 0x96 1,69 # ucircumflex
+char252 1667 2 0x81 1,71 # udieresis
+char253 1480 3 0x175 1,85 # yacute
+char254 1667 3 0x143 1,89 # thorn
+char255 1480 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 1667 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 2037 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 1667 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 2963 2 0x92 1,36 # AE
+ae 2223 0 0x91 1,37 # ae
+OE 3147 2 0x141 1,166 # OE
+oe 2223 0 0x146 1,167 # oe
+ij 1807 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 1667 2 0x147 1,23 # germandbls
+'A 2037 2 0x15a 1,26 # Aacute
+'E 2037 2 0x90 1,40 # Eacute
+'I 1110 2 0x161 1,48 # Iacute
+'O 2407 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1667 2 0xa0 1,27 # aacute
+'e 1480 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 1667 2 0xa2 1,59 # oacute
+'u 1667 2 0x95 1,65 # uacute
+:A 2037 2 0x8e 1,30 # Adieresis
+:E 2037 2 0x15f 1,44 # Edieresis
+:I 1110 2 0x163 1,52 # Idieresis
+:O 2407 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 1853 2 0x16d 1,74 # Ydieresis
+:a 1667 2 0x84 1,31 # adieresis
+:e 1480 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 1667 2 0x94 1,63 # odieresis
+:u 1667 2 0x81 1,71 # udieresis
+:y 1480 3 0x98 1,75 # ydieresis
+^A 2037 2 0x15b 1,28 # Acircumflex
+^E 2037 2 0x15e 1,42 # Ecircumflex
+^I 1110 2 0x162 1,50 # Icircumflex
+^O 2407 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1667 2 0x83 1,29 # acircumflex
+^e 1480 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 1667 2 0x93 1,61 # ocircumflex
+^u 1667 2 0x96 1,69 # ucircumflex
+`A 2037 2 0x15c 1,32 # Agrave
+`E 2037 2 0x160 1,46 # Egrave
+`I 1110 2 0x164 1,54 # Igrave
+`O 2407 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1667 2 0x85 1,33 # agrave
+`e 1480 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 1667 2 0x95 1,65 # ograve
+`u 1667 2 0x97 1,73 # ugrave
+~A 2037 2 0x28e 1,26 # Atilde
+~N 2223 2 0xa5 1,56 # Ntilde
+~O 2407 2 0x168 1,82 # Otilde
+~a 1667 2 0x284 --- # atilde
+~n 1667 2 0xa4 1,57 # ntilde
+~o 1667 2 0x172 1,83 # otilde
+vS 1667 2 0x169 1,176 # Scaron
+vs 1297 2 0x173 1,177 # scaron
+vZ 1853 2 0x16e 1,206 # Zcaron
+vz 1297 2 0x174 1,207 # zcaron
+,C 2223 2 0x80 1,38 # Ccedilla
+,c 1480 0 0x87 1,39 # ccedilla
+/L 1853 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 927 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2407 2 0x140 1,80 # Oslash
+/o 1667 0 0x145 1,81 # oslash
+oA 2037 2 0x8f 1,34 # Aring
+oa 1667 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1667 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1667 2 0x24 0,36 # dollar
+Po 1667 2 0x9c 4,11 # sterling
+Ye 1667 2 0x9d 4,12 # yen
+Fn 1667 2 0x9f 4,14 # florin
+ct 1667 2 0x9b 4,19 # cent
+Fo 1667 0 0xae 4,9 # guillemotleft
+Fc 1000 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1297 1 0xad 4,7 # exclamdown
+r? 1667 1 0xa8 4,8 # questiondown
+fi 1667 2 0x130 4,54 # fi "fi ligature"
+fl 1667 2 0x131 4,55 # fl "fl ligature"
+OK 1667 0 0x3d6 --- # \& "check mark, tick"
+Of 920 2 0xa6 4,15 # ordfeminine
+Om 1033 2 0xa7 4,16 # ordmasculine
+S1 1000 2 0x156 4,78 # onesuperior
+S2 1000 2 0xfd 4,20 # twosuperior
+S3 1000 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 917 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 2963 0 0x123 4,34 # ru "baseline rule"
+ul 1667 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0xb3 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2533 2 0x154 4,23 # copyright
+rg 2533 2 0x155 4,22 # registered
+tm 3266 2 0x170 4,41 # trademark
+dd 1667 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1667 2 0x12a 4,39 # dagger
+ps 1743 2 0x14 4,5 # paragraph
+sc 1667 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 2963 0 0x123 4,34 # emdash "em dash"
+en 1667 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2500 2 0xab 4,17 # onehalf
+14 2500 2 0xac 4,18 # onequarter
+34 2500 2 0x12e 4,25 # threequarters
+f/ 927 2 0x158 6,6 # fraction "bar for fractions"
+fm 927 0 0x3a2 6,45 # minute "footmark, prime"
+sd 927 0 0x3b2 6,46 # second
+ha 927 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 927 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 2250 0 0x2d 6,0 # hyphen
+lB 1297 2 0x5b 0,91 # bracketleft
+rB 1297 2 0x5d 0,93 # bracketright
+lC 1333 2 0x7b 0,123 # braceleft
+rC 1333 2 0x7d 0,125 # braceright
+la 1333 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1333 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1853 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1853 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1853 2 0x125 4,32 # quotedblleft
+rq 1853 2 0x4ba 6,31 # quotedblright
+oq 1110 2 0x176 4,29 # quoteleft "single open quote"
+aq 713 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 917 0 0x3f4 0,124 # bar
+at 3067 2 0x40 0,64 # at
+.C1 2250 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1667 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2627 0 0x346 8,44 # Phi
+*G 1977 0 0x347 8,6 # Gamma
+*H 1977 0 0x351 8,16 # Theta
+*I 1977 0 0x349 8,18 # Iota
+*K 1977 0 0x34b 8,20 # Kappa
+*L 1977 0 0x34c 8,22 # Lambda
+*M 1977 0 0x34d 8,24 # Mu
+*N 1977 0 0x34e 8,26 # Nu
+*O 1977 0 0x34f 8,30 # Omicron
+*P 1977 0 0x350 8,32 # Pi
+*Q 1977 0 0x359 8,48 # Psi
+*R 1977 0 0x352 8,34 # Rho
+*S 2140 0 0x353 8,36 # Sigma
+*T 2140 0 0x354 8,40 # Tau
+*U 2140 0 0x3a1 8,76 # Upsilon
+*W 2653 0 0x357 8,50 # Omega
+*X 2140 0 0x343 8,36 # Chi
+*Y 2140 0 0x348 8,14 # Eta
+*Z 2140 0 0x35a 8,12 # Zeta
+*a 1987 0 0xe0 8,1 # alpha
+*b 1723 0 0xe1 8,3 # beta
+*c 1723 0 0x378 8,29 # xi
+*d 1760 0 0xeb 8,9 # delta
+*e 1760 0 0x36e 8,70 # epsilon
+*f 1760 0 0x366 8,45 # phi
++f 1760 0 0x36a 8,77 # phi1 "variant phi"
+*g 1760 0 0x367 8,7 # gamma
+*h 1643 0 0xe9 8,17 # theta
++h 1643 0 0x375 8,71 # theta1 "variant theta"
+*i 1643 0 0x369 8,19 # iota
+*k 1643 0 0x36b 8,21 # kappa
+*l 1643 0 0x36c 8,23 # lambda
+*m 1667 0 0xe6 8,25 # mu
+*n 1667 0 0x36e 8,27 # nu
+*o 1667 0 0x36f 8,31 # omicron
+*p 2037 0 0xe3 8,33 # pi
++p 2037 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 2037 0 0x379 8,49 # psi
+*r 2037 0 0x372 8,35 # rho
+*s 1753 0 0xe5 8,37 # sigma
+*t 1413 0 0xe7 8,41 # tau
+*u 1413 0 0x375 8,27 # upsilon
+*w 1413 0 0x377 8,51 # omega
+*x 1413 0 0x363 8,47 # chi
+*y 1413 0 0x368 8,15 # eta
+*z 1413 0 0x37a 8,13 # zeta
+ts 1413 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 833 0 0x32a 0,32 # asteriskmath
++- 2250 0 0xf1 6,1 # plusminus
+<= 2413 0 0xf3 6,2 # lessequal
+== 2413 0 0x3ba 8,14 # equivalence
+=~ 2413 0 0x340 8,116 # congruent
+>= 1723 0 0x3b3 8,3 # greaterequal
+AN 1723 0 0x3d9 8,85 # logicaland
+OR 1723 0 0x3da 8,86 # logicalor
+no 1723 0 0x3d8 8,20 # logicalnot
+te 1723 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 1723 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 1723 0 0x3c0 9,0 # aleph
+Im 1723 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 1723 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 1723 0 0x3a5 8,19 # infinity
+md 1723 0 0x3b7 8,32 # dotmath
+mo 1723 0 0x3ce 8,15 # element
+mu 1723 0 0x3b4 8,39 # multiply
+nc 1723 0 0x3cb 8,197 # notpropersuperset
+nm 1723 0 0x3cf 8,209 # notelement
+pl 1297 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 2250 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 2250 0 0x3b5 6,4 # proportional
+pp 2250 0 0x35e 8,89 # perpendicular
+sb 2250 0 0x3cc 6,67 # propersubset
+sp 2250 0 0x3c9 6,68 # propersuperset
+ib 2250 0 0x3cd 6,69 # reflexsubset
+ip 2250 0 0x3ca 6,70 # reflexsuperset
+ap 2250 0 0x37e 6,12 # similar
+pd 2250 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 2250 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 2250 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 2250 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2407 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1667 0 0xae 6,77 # "" "much less"
+>> 1667 0 0xaf 6,78 # "" "much greater"
+wp 1667 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1667 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 833 0 0xfa 6,32 # periodcentered
+kernpairs
+V A -168
+W A -96
+Y A -72
+A V -72
+A W -72
+A Y -48
+T a -48
+V a -48
+W a -48
+Y a -48
+v a -48
+T c -48
+V c -48
+Y c -48
+P e -48
+T e -48
+V e -48
+Y e 48
+f e -24
+F o -48
+P o -48
+T o -48
+V o -72
+W o -48
+Y o -120
+A v -48
+A w -24
diff --git a/contrib/groff/font/devlbp/TR b/contrib/groff/font/devlbp/TR
new file mode 100644
index 0000000..9a641df
--- /dev/null
+++ b/contrib/groff/font/devlbp/TR
@@ -0,0 +1,517 @@
+name TR
+lbpname Dutch-Roman
+special
+spacewidth 833
+slant 0
+ligatures fi fl 0
+charset
+ha 1110 2 0x4c3 0,94 # asciicircum
+ti 1110 0 0x4c4 0,126 # asciitilde
+vS 1853 2 0x169 1,176 # Scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vs 1297 2 0x173 1,177 # scaron
+vz 1480 2 0x174 1,207 # zcaron
+:Y 2407 2 0x16d 1,74 # Ydieresis
+tm 3226 2 0x170 4,41 # trademark
+aq 600 2 0x27 0,39 # quotesingle
+space 833 0 0x20 0,32
+! 1110 2 0x21 0,33 # exclam
+" 1360 2 0x22 0,34 # quotedbl
+dq 1360 2 0x22 0,34 # quotedbl
+# 1667 2 0x23 0,35 # numbersign
+sh 1667 2 0x23 0,35 # "
+$ 1667 2 0x24 0,36 # dollar
+Do 1667 2 0x24 0,36 # "
+% 2777 2 0x25 0,37 # percent
+& 2593 2 0x26 0,38 # ampersand
+' 600 2 0x27 0,39 # quoteright
+cq 600 2 0x27 0,39 # quoteright
+( 1110 2 0x28 0,40 # parenleft
+) 1110 2 0x29 0,41 # parenright
+* 1667 2 0x2a 0,42 # asterisk
++ 1880 0 0x2b 0,43 # plus
+, 833 0 0x2c 0,44 # comma
+- 1110 0 0x2d 0,45 # hyphen
+\- 1110 0 0x2d 0,45 # hyphen
+hy 1110 0 0x2d 0,45 # "
+char173 1110 0 0x2d 0,45 # "
+. 833 0 0x2e 0,46 # period
+/ 927 2 0x2f 0,47 # slash
+sl 927 2 0x2f 0,47 # "
+0 1667 2 0x30 0,48 # zero
+1 1667 2 0x31 0,49 # one
+2 1667 2 0x32 0,50 # two
+3 1667 2 0x33 0,51 # three
+4 1667 2 0x34 0,52 # four
+5 1667 2 0x35 0,53 # five
+6 1667 2 0x36 0,54 # six
+7 1667 2 0x37 0,55 # seven
+8 1667 2 0x38 0,56 # eight
+9 1667 2 0x39 0,57 # nine
+: 927 0 0x3a 0,58 # colon
+; 927 0 0x3b 0,59 # semicolon
+< 1880 0 0x3c 0,60 # less
+= 1880 0 0x3d 0,61 # equal
+> 1880 0 0x3e 0,62 # greater
+? 1480 2 0x3f 0,63 # question
+@ 3070 2 0x40 0,64 # at
+at 3070 2 0x40 0,64 # "
+A 2407 2 0x41 0,65 # A
+B 2223 2 0x42 0,66 # B
+C 2223 2 0x43 0,67 # C
+D 2407 2 0x44 0,68 # D
+E 2037 2 0x45 0,69 # E
+F 1853 2 0x46 0,70 # F
+G 2407 2 0x47 0,71 # G
+H 2407 2 0x48 0,72 # H
+I 1110 2 0x49 0,73 # I
+J 1297 2 0x4a 0,74 # J
+K 2407 2 0x4b 0,75 # K
+L 2037 2 0x4c 0,76 # L
+M 2963 2 0x4d 0,77 # M
+N 2407 2 0x4e 0,78 # N
+O 2407 2 0x4f 0,79 # O
+P 1853 2 0x50 0,80 # P
+Q 2407 2 0x51 0,81 # Q
+R 2223 2 0x52 0,82 # R
+S 1853 2 0x53 0,83 # S
+T 2037 2 0x54 0,84 # T
+U 2407 2 0x55 0,85 # U
+V 2407 2 0x56 0,86 # V
+W 3147 2 0x57 0,87 # W
+X 2407 2 0x58 0,88 # X
+Y 2407 2 0x59 0,89 # Y
+Z 2037 2 0x5a 0,90 # Z
+[ 1110 2 0x5b 0,91 # bracketleft
+lB 1110 2 0x5b 0,91 # "
+\ 927 2 0x5c 0,92 # backslash
+rs 927 2 0x5c 0,92 # "
+] 1110 2 0x5d 0,93 # bracketright
+rB 1110 2 0x5d 0,93 # "
+a^ 1110 2 0x5e 0,94 # circumflex
+^ 1110 2 0x5e 0,94 # "
+_ 1667 0 0x5f 0,95 # underscore
+` 1110 2 0x60 0,96 # quoteleft
+oq 1110 2 0x60 0,96 # "
+a 1480 0 0x61 0,97 # a
+b 1667 2 0x62 0,98 # b
+c 1480 0 0x63 0,99 # c
+d 1667 2 0x64 0,100 # d
+e 1480 0 0x65 0,101 # e
+f 1110 2 0x66 0,102 # f
+g 1667 1 0x67 0,103 # g
+h 1667 2 0x68 0,104 # h
+i 927 2 0x69 0,105 # i
+j 927 2 0x6a 0,106 # j
+k 1667 2 0x6b 0,107 # k
+l 927 2 0x6c 0,108 # l
+m 2593 0 0x6d 0,109 # m
+n 1667 0 0x6e 0,110 # n
+o 1667 0 0x6f 0,111 # o
+p 1667 1 0x70 0,112 # p
+q 1667 1 0x71 0,113 # q
+r 1110 0 0x72 0,114 # r
+s 1297 0 0x73 0,115 # s
+t 927 2 0x74 0,116 # t
+u 1667 0 0x75 0,117 # u
+v 1667 0 0x76 0,118 # v
+w 2407 0 0x77 0,119 # w
+x 1667 0 0x78 0,120 # x
+y 1667 1 0x79 0,121 # y
+z 1480 0 0x7a 0,122 # z
+lC 1600 2 0x7b 0,123 # braceleft
+{ 1600 2 0x7b 0,123 # "
+| 667 2 0x7c 0,124 # "
+rC 1600 2 0x7d 0,125 # braceright
+} 1600 2 0x7d 0,125 # "
+a~ 1110 2 0x7e 0,126 # tilde
+~ 1110 2 0x7e 0,126 # "
+char161 1110 1 0xad 4,7 # exclamdown
+char162 1667 2 0x9b 4,19 # cent
+char163 1667 2 0x9c 4,11 # sterling
+char164 1667 2 0x12f 4,24 # currency
+char165 1667 2 0x9d 4,12 # yen
+char166 667 2 0x7c 0,124 # brokenbar
+char167 1667 2 0x15 4,6 # section
+char168 1110 2 0x122 1,7 # dieresis
+char169 2533 2 0x154 4,23 # copyright
+char170 920 2 0xa6 4,15 # ordfeminine
+char171 1667 0 0xae 4,9 # guillemotleft
+char172 1880 0 0xaa 6,20 # logicalnot
+char173 1667 0 0x132 4,33 # hyphen
+char174 2533 2 0x155 4,22 # registered
+char175 1880 2 0x2d 6,0 # macron
+char176 1333 2 0xf8 6,36 # degree
+char177 1880 0 0xf1 6,1 # plusminus
+char178 1000 2 0xfd 4,20 # twosuperior
+char179 1000 2 0x14d 4,26 # threesuperior
+char180 1110 2 0x120 1,6 # acute "acute accent"
+char181 1667 1 0xe6 8,25 # mu
+char182 1510 2 0x14 4,5 # paragraph
+char183 833 0 0xfa 6,32 # periodcentered
+char184 1110 0 0x139 1,17 # cedilla
+char185 1000 2 0x156 4,78 # onesuperior
+char186 1033 2 0xa7 4,16 # ordmasculine
+char187 1667 0 0xaf 4,10 # guillemotright
+char188 2500 2 0xac 4,18 # onequarter
+char189 2500 2 0xab 4,17 # onehalf
+char190 2500 2 0x12e 4,25 # threequarters
+char191 1480 1 0xa8 4,8 # questiondown
+char192 2407 2 0x15c 1,32 # Agrave
+char193 2407 2 0x15a 1,26 # Aacute
+char194 2407 2 0x15b 1,28 # Acircumflex
+char195 2407 2 0x28e 1,76 # Atilde
+char196 2407 2 0x8e 1,30 # Adieresis
+char197 2407 2 0x8f 1,34 # Aring
+char198 2963 2 0x92 1,36 # AE
+char199 2223 2 0x80 1,38 # Ccedilla
+char200 2037 2 0x160 1,46 # Egrave
+char201 2037 2 0x90 1,40 # Eacute
+char202 2037 2 0x15e 1,42 # Ecircumflex
+char203 2037 2 0x15f 1,44 # Edieresis
+char204 1110 2 0x164 1,54 # Igrave
+char205 1110 2 0x161 1,48 # Iacute
+char206 1110 2 0x162 1,50 # Icircumflex
+char207 1110 2 0x163 1,52 # Idieresis
+char208 2407 2 0x13d 1,78 # Eth
+char209 2407 2 0xa5 1,56 # Ntilde
+char210 2407 2 0x167 1,64 # Ograve
+char211 2407 2 0x165 1,58 # Oacute
+char212 2407 2 0x166 1,60 # Ocircumflex
+char213 2407 2 0x168 1,82 # Otilde
+char214 2407 2 0x99 1,62 # Odieresis
+char215 1880 0 0x157 6,39 # multiply
+char216 2407 2 0x140 1,80 # Oslash
+char217 2407 2 0x16c 1,72 # Ugrave
+char218 2407 2 0x16a 1,66 # Uacute
+char219 2407 2 0x16b 1,68 # Ucircumflex
+char220 2407 2 0x9a 1,70 # Udieresis
+char221 2407 2 0x16f 1,84 # Yacute
+char222 1853 2 0x13e 1,88 # Thorn
+char223 1667 2 0x147 1,23 # germandbls
+char224 1480 2 0x85 1,33 # agrave
+char225 1480 2 0xa0 1,27 # aacute
+char226 1480 2 0x83 1,29 # acircumflex
+char227 1480 2 0x284 1,93 # atilde
+char228 1480 2 0x84 1,31 # adieresis
+char229 1480 2 0x86 1,35 # aring
+char230 2223 0 0x91 1,37 # ae
+char231 1480 0 0x87 1,39 # ccedilla
+char232 1480 2 0x8a 1,47 # egrave
+char233 1480 2 0x82 1,41 # eacute
+char234 1480 2 0x88 1,43 # ecircumflex
+char235 1480 2 0x89 1,45 # edieresis
+char236 927 2 0x8d 1,55 # igrave
+char237 927 2 0xa1 1,49 # iacute
+char238 927 2 0x8c 1,51 # icircumflex
+char239 927 2 0x8b 1,53 # idieresis
+char240 1667 2 0x148 1,87 # eth
+char241 1667 2 0xa4 1,57 # ntilde
+char242 1667 2 0x95 1,65 # ograve
+char243 1667 2 0xa2 1,59 # oacute
+char244 1667 2 0x93 1,61 # ocircumflex
+char245 1667 2 0x172 1,83 # otilde
+char246 1667 2 0x94 1,63 # odieresis
+char247 1880 0 0xf6 6,8 # divide
+char248 1667 0 0x145 1,81 # oslash
+char249 1667 2 0x97 1,73 # ugrave
+char250 1667 2 0xa3 1,67 # uacute
+char251 1667 2 0x96 1,69 # ucircumflex
+char252 1667 2 0x81 1,71 # udieresis
+char253 1667 3 0x175 1,85 # yacute
+char254 1667 3 0x143 1,89 # thorn
+char255 1667 3 0x98 1,75 # ydieresis
+-D 2407 2 0x13d 1,78 # Eth "Icelandic uppercase eth"
+Sd 1667 2 0x148 1,87 # eth "Icelandic lowercase eth"
+TP 1853 2 0x13e 1,88 # Thorn "Icelandic uppercase thorn"
+Tp 1667 3 0x143 1,89 # thorn "Icelandic lowercase thorn"
+AE 2963 2 0x92 1,36 # AE
+ae 2223 0 0x91 1,37 # ae
+OE 2963 2 0x141 1,166 # OE
+oe 2407 0 0x146 1,167 # oe
+ij 1783 0 0x150 1,139 # ij "Dutch ij ligature"
+ss 1667 2 0x147 1,23 # germandbls
+'A 2407 2 0x15a 1,26 # Aacute
+'E 2037 2 0x90 1,40 # Eacute
+'I 1110 2 0x161 1,48 # Iacute
+'O 2407 2 0x165 1,58 # Oacute
+'U 2407 2 0x16a 1,66 # Uacute
+'a 1480 2 0xa0 1,27 # aacute
+'e 1480 2 0x82 1,41 # eacute
+'i 927 2 0xa1 1,49 # iacute
+'o 1667 2 0xa2 1,59 # oacute
+'u 1667 2 0x95 1,65 # uacute
+:A 2407 2 0x8e 1,30 # Adieresis
+:E 2037 2 0x15f 1,44 # Edieresis
+:I 1110 2 0x163 1,52 # Idieresis
+:O 2407 2 0x99 1,62 # Odieresis
+:U 2407 2 0x9a 1,70 # Udieresis
+:Y 2407 2 0x16d 1,74 # Ydieresis
+:a 1480 2 0x84 1,31 # adieresis
+:e 1480 2 0x89 1,45 # edieresis
+:i 927 2 0x8b 1,53 # idieresis
+:o 1667 2 0x94 1,63 # odieresis
+:u 1667 2 0x81 1,71 # udieresis
+:y 1667 3 0x98 1,75 # ydieresis
+^A 2407 2 0x15b 1,28 # Acircumflex
+^E 2037 2 0x15e 1,42 # Ecircumflex
+^I 1110 2 0x162 1,50 # Icircumflex
+^O 2407 2 0x166 1,60 # Ocircumflex
+^U 2407 2 0x16b 1,68 # Ucircumflex
+^a 1480 2 0x83 1,29 # acircumflex
+^e 1480 2 0x88 1,43 # ecircumflex
+^i 927 2 0x8c 1,51 # icircumflex
+^o 1667 2 0x93 1,61 # ocircumflex
+^u 1667 2 0x96 1,69 # ucircumflex
+`A 2407 2 0x15c 1,32 # Agrave
+`E 2037 2 0x160 1,46 # Egrave
+`I 1110 2 0x164 1,54 # Igrave
+`O 2407 2 0x167 1,64 # Ograve
+`U 2407 2 0x16c 1,72 # Ugrave
+`a 1480 2 0x85 1,33 # agrave
+`e 1480 2 0x8a 1,47 # egrave
+`i 927 2 0x8d 1,55 # igrave
+`o 1667 2 0x95 1,65 # ograve
+`u 1667 2 0x97 1,73 # ugrave
+~A 2407 2 0x28e 1,26 # Atilde
+~N 2407 2 0xa5 1,56 # Ntilde
+~O 2407 2 0x168 1,82 # Otilde
+~a 1480 2 0x284 --- # atilde
+~n 1667 2 0xa4 1,57 # ntilde
+~o 1667 2 0x172 1,83 # otilde
+vS 1853 2 0x169 1,176 # Scaron
+vs 1297 2 0x173 1,177 # scaron
+vZ 2037 2 0x16e 1,206 # Zcaron
+vz 1480 2 0x174 1,207 # zcaron
+,C 2223 2 0x80 1,38 # Ccedilla
+,c 1480 0 0x87 1,39 # ccedilla
+/L 2037 2 0x13f 1,152 # Lslash "Polish L with a slash"
+/l 927 2 0x144 1,153 # lslash "Polish l with a slash"
+/O 2407 2 0x140 1,80 # Oslash
+/o 1667 0 0x145 1,81 # oslash
+oA 2407 2 0x8f 1,34 # Aring
+oa 1480 2 0x86 1,35 # aring
+a" 1110 2 0x13a 1,16 # hungarumlaut "Hungarian umlaut"
+a- 1110 2 0x135 1,8 # macron "macron or bar accent"
+a. 1110 2 0x137 1,15 # dotaccent "dot accent"
+a^ 1110 2 0x5e 1,3 # circumflex "circumflex accent"
+aa 1110 2 0x120 1,6 # acute "acute accent"
+ga 1110 2 0x121 1,0 # grave "grave accent"
+ab 1110 2 0x136 1,22 # breve "breve accent"
+ac 1110 0 0x139 1,17 # cedilla "cedilla accent"
+ad 1110 2 0x122 1,7 # dieresis "umlaut or dieresis"
+ah 1110 2 0x13c 1,19 # caron "h\('a\(vcek accent"
+ao 1110 2 0x138 1,14 # ring "ring or circle accent"
+a~ 1110 2 0x7e 1,2 # tilde "tilde accent"
+ho 1110 0 0x13b 1,18 # ogonek "hook or ogonek accent"
+.i 927 0 0x142 1,239 # dotlessi "i without a dot"
+Cs 1667 2 0x12f 4,24 # currency "Scandinavian currency sign"
+Do 1667 2 0x24 0,36 # dollar
+Po 1667 2 0x9c 4,11 # sterling
+Ye 1667 2 0x9d 4,12 # yen
+Fn 1667 2 0x9f 4,14 # florin
+ct 1667 2 0x9b 4,19 # cent
+Fo 1667 0 0xae 4,9 # guillemotleft
+Fc 1000 0 0x4bb 4,20 # guillemotright
+fo 1110 0 0x127 4,35 # guilsinglleft
+fc 1110 0 0x128 4,36 # guilsinglright
+r! 1110 1 0xad 4,7 # exclamdown
+r? 1480 1 0xa8 4,8 # questiondown
+fi 1853 2 0x130 4,54 # fi "fi ligature"
+fl 1853 2 0x131 4,55 # fl "fl ligature"
+OK 1853 0 0x3d6 --- # \& "check mark, tick"
+Of 920 2 0xa6 4,15 # ordfeminine
+Om 1033 2 0xa7 4,16 # ordmasculine
+S1 1000 2 0x156 4,78 # onesuperior
+S2 1000 2 0xfd 4,20 # twosuperior
+S3 1000 2 0x14d 4,26 # threesuperior
+<- 3290 0 0x1b 6,22 # arrowleft
+-> 3290 0 0x1a 6,21 # arrowright
+<> 3473 0 0x1d 6,25 # arrowboth "horizontal double-headed arrow"
+da 2010 0 0x19 6,24 # arrowdown
+ua 2010 0 0x18 6,23 # arrowup
+va 2010 0 0x12 6,26 # \& "vertical double-headed arrow"
+lA 2010 0 0x3dc 6,57 # arrowdblleft
+rA 2010 0 0x3de 6,56 # arrowdblright
+hA 2010 0 0x3db 6,60 # arrowdblboth "horizontal double-headed double arrow"
+dA 2010 0 0x3df 6,59 # arrowdbldown
+uA 2010 0 0x3dd 6,58 # arrowdblup
+ba 3333 2 0xb3 3,9 # bar
+bb 667 2 0x7c 0,124 # brokenbar
+br 3333 0 0x1db 3,9 # br "box rule with traditional troff metrics"
+ru 3333 0 0x123 4,34 # ru "baseline rule"
+ul 1667 0 0x5f 0,95 # ul "underline with traditional troff metrics"
+bv 3333 0 0x3f4 3,9 # bv "bold vertical"
+ci 2843 0 0x9 4,1 # circle
+bu 2120 0 0x7 4,0 # bullet
+co 2533 2 0x154 4,23 # copyright
+rg 2533 2 0x155 4,22 # registered
+tm 3226 2 0x170 4,41 # trademark
+dd 1667 2 0x12b 4,40 # daggerdbl "double dagger sign"
+dg 1667 2 0x12a 4,39 # dagger
+ps 1510 2 0x14 4,5 # paragraph
+sc 1667 2 0x15 4,6 # section
+de 1333 2 0xf8 6,36 # degree
+em 3333 0 0x123 4,34 # emdash "em dash"
+en 1667 0 0x132 4,33 # endash "en dash"
+%0 3333 2 0x129 4,75 # perthousand "per thousand, per mille sign"
+12 2500 2 0xab 4,17 # onehalf
+14 2500 2 0xac 4,18 # onequarter
+34 2500 2 0x12e 4,25 # threequarters
+f/ 550 2 0x158 6,6 # fraction "bar for fractions"
+fm 550 0 0x3a2 6,45 # minute "footmark, prime"
+sd 550 0 0x3b2 6,46 # second
+ha 550 2 0x4c3 6,85 # asciicircum "\s-2ASCII\s+2 circumflex, hat, caret"
+ti 550 0 0x4c4 6,12 # asciitilde "\s-2ASCII\s0 tilde, large tilde"
+hy 1880 0 0x2d 6,0 # hyphen
+lB 1110 2 0x5b 0,91 # bracketleft
+rB 1110 2 0x5d 0,93 # bracketright
+lC 1600 2 0x7b 0,123 # braceleft
+rC 1600 2 0x7d 0,125 # braceright
+la 1600 0 0x3e1 6,10 # angleleft "left angle bracket"
+ra 1600 0 0x3f1 6,11 # angleright "right angle bracket"
+Bq 1480 0 0x4b9 4,63 # quotedblbase "low double comma quote"
+bq 1480 0 0x4b8 6,62 # quotesinglbase "low single comma quote"
+lq 1480 2 0x125 4,32 # quotedblleft
+rq 1480 2 0x4ba 6,31 # quotedblright
+oq 1110 2 0x176 4,29 # quoteleft "single open quote"
+aq 600 2 0x27 0,39 # quotesingle "apostrophe quote"
+or 667 0 0x3f4 0,124 # bar
+at 3070 2 0x40 0,64 # at
+.C1 1110 0 0x2d 0,45 # - minus "minus sign from current font"
+sh 1667 2 0x23 0,35 # numbersign
+sl 927 2 0x2f 0,47 # slash
+rs 927 2 0x5c 0,92 # backslash
+3d 927 0 0x35c 6,102 # therefore
+tf 927 0 0x35c 6,102 # therefore
+*A 927 0 0x341 8,0 # Alpha
+*B 927 0 0x342 8,2 # Beta
+*C 927 0 0x358 8,28 # Xi
+*D 927 0 0x344 8,8 # Delta
+*E 927 0 0x345 8,10 # Epsilon
+*F 2627 0 0x346 8,44 # Phi
+*G 1977 0 0x347 8,6 # Gamma
+*H 1977 0 0x351 8,16 # Theta
+*I 1977 0 0x349 8,18 # Iota
+*K 1977 0 0x34b 8,20 # Kappa
+*L 1977 0 0x34c 8,22 # Lambda
+*M 1977 0 0x34d 8,24 # Mu
+*N 1977 0 0x34e 8,26 # Nu
+*O 1977 0 0x34f 8,30 # Omicron
+*P 1977 0 0x350 8,32 # Pi
+*Q 1977 0 0x359 8,48 # Psi
+*R 1977 0 0x352 8,34 # Rho
+*S 2140 0 0x353 8,36 # Sigma
+*T 2140 0 0x354 8,40 # Tau
+*U 2140 0 0x3a1 8,76 # Upsilon
+*W 2653 0 0x357 8,50 # Omega
+*X 2140 0 0x343 8,36 # Chi
+*Y 2140 0 0x348 8,14 # Eta
+*Z 2140 0 0x35a 8,12 # Zeta
+*a 1987 0 0xe0 8,1 # alpha
+*b 1723 0 0xe1 8,3 # beta
+*c 1723 0 0x378 8,29 # xi
+*d 1760 0 0xeb 8,9 # delta
+*e 1760 0 0x36e 8,70 # epsilon
+*f 1760 0 0x366 8,45 # phi
++f 1760 0 0x36a 8,77 # phi1 "variant phi"
+*g 1760 0 0x367 8,7 # gamma
+*h 1643 0 0xe9 8,17 # theta
++h 1643 0 0x375 8,71 # theta1 "variant theta"
+*i 1643 0 0x369 8,19 # iota
+*k 1643 0 0x36b 8,21 # kappa
+*l 1643 0 0x36c 8,23 # lambda
+*m 1667 0 0xe6 8,25 # mu
+*n 1667 0 0x36e 8,27 # nu
+*o 1667 0 0x36f 8,31 # omicron
+*p 2037 0 0xe3 8,33 # pi
++p 2037 0 0x376 8,78 # omega1 "variant pi, looking like omega"
+*q 2037 0 0x379 8,49 # psi
+*r 2037 0 0x372 8,35 # rho
+*s 1753 0 0xe5 8,37 # sigma
+*t 1413 0 0xe7 8,41 # tau
+*u 1413 0 0x375 8,27 # upsilon
+*w 1413 0 0x377 8,51 # omega
+*x 1413 0 0x363 8,47 # chi
+*y 1413 0 0x368 8,15 # eta
+*z 1413 0 0x37a 8,13 # zeta
+ts 1413 0 0x356 8,39 # sigma1 "terminal sigma"
+~~ 2663 0 0xf7 6,13 # approxequal
+~= 2663 0 0xf7 6,13 # approxequal
+!= 2663 0 0x3b9 6,99 # notequal
+** 833 0 0x32a 0,32 # asteriskmath
++- 1880 0 0xf1 6,1 # plusminus
+<= 2413 0 0xf3 6,2 # lessequal
+== 2413 0 0x3ba 8,14 # equivalence
+=~ 2413 0 0x340 8,116 # congruent
+>= 1723 0 0x3b3 8,3 # greaterequal
+AN 1723 0 0x3d9 8,85 # logicaland
+OR 1723 0 0x3da 8,86 # logicalor
+no 1723 0 0x3d8 8,20 # logicalnot
+te 1723 0 0x324 8,121 # existential "there exists, existential quantifier"
+fa 1723 0 0x322 8,122 # universal "for all, universal quantifier"
+Ah 1723 0 0x3c0 9,0 # aleph
+Im 1723 0 0x3c1 8,21 # Ifraktur "Fraktur I, imaginary"
+Re 1723 0 0x3c2 8,22 # Rfraktur "Fraktur R, real"
+if 1723 0 0x3a5 8,19 # infinity
+md 1723 0 0x3b7 8,32 # dotmath
+mo 1723 0 0x3ce 8,15 # element
+mu 1723 0 0x3b4 8,39 # multiply
+nc 1723 0 0x3cb 8,197 # notpropersuperset
+nm 1723 0 0x3cf 8,209 # notelement
+pl 1110 0 0x32b 0,93 # plusmath "plus sign in special font"
+eq 1880 0 0x33d 0,61 # equalmath "equals sign in special font"
+pt 1880 0 0x3b5 6,4 # proportional
+pp 1880 0 0x35e 8,89 # perpendicular
+sb 1880 0 0x3cc 6,67 # propersubset
+sp 1880 0 0x3c9 6,68 # propersuperset
+ib 1880 0 0x3cd 6,69 # reflexsubset
+ip 1880 0 0x3ca 6,70 # reflexsuperset
+ap 1880 0 0x37e 6,12 # similar
+pd 1880 0 0x3b6 6,34 # partialdiff "partial differentiation sign"
+c* 1880 0 0x3c4 6,80 # circlemultiply "multiply sign in a circle"
+c+ 1880 0 0x3c5 6,81 # circleplus "plus sign in a circle"
+ca 2620 0 0xef 6,16 # intersection "intersection, cap"
+cu 2620 0 0x3c8 6,66 # union "union, cup"
+di 1880 0 0x3b8 6,8 # divide "division sign"
+-h 3333 0 0xc4 3,8 # hbar
+gr 3333 0 0x3d1 6,33 # gradient
+es 2407 0 0x3c6 0,79 # emptyset
+CL 2510 0 0x5 5,168 # club "club suit"
+SP 2510 0 0x6 5,171 # spade "spade suit"
+HE 2510 0 0x3 5,170 # heart "heart suit"
+DI 2510 0 0x4 5,169 # diamond "diamond suit"
+CR 2510 0 0x3bf 5,20 # carriagereturn "carriage return symbol"
+st 2510 0 0x327 6,71 # suchthat
+/_ 2510 0 0x3d0 6,79 # angle
+<< 1667 0 0xae 6,77 # "" "much less"
+>> 1667 0 0xaf 6,78 # "" "much greater"
+wp 1667 0 0x3c3 6,53 # weierstrass "Weierstrass p"
+lz 1667 0 0x3e0 6,95 # lozenge
+an 3333 0 0x3be 3,8 # arrowhorizex "horizontal arrow extension"
+pc 833 0 0xfa 6,32 # periodcentered
+kernpairs
+F A -48
+P A -48
+V A -72
+W A -72
+Y A -72
+A V -96
+A W -72
+A Y -72
+P a -48
+V a -48
+W a -48
+Y a -24
+V c -48
+W c -48
+Y c -24
+P e -48
+V e -48
+W e -48
+Y e -48
+V o -48
+W o -24
+Y o -48
+A v -48
+A w -48
diff --git a/contrib/groff/font/devlj4/ALBB b/contrib/groff/font/devlj4/ALBB
new file mode 100644
index 0000000..9c0c71f
--- /dev/null
+++ b/contrib/groff/font/devlj4/ALBB
@@ -0,0 +1,790 @@
+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 cq -975
+L ' -975
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A cq -1461
+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 cq -486
+p ' -486
+e cq -486
+e ' -486
+b cq -486
+b ' -486
+a cq -486
+a ' -486
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -486
+h ' -486
+m cq -486
+m ' -486
+R cq -975
+R ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+cq d -1950
+' 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
+cq s -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 cq -486
+K ' -486
+k cq -486
+k ' -486
+O cq -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/ALBR b/contrib/groff/font/devlj4/ALBR
new file mode 100644
index 0000000..684f29f
--- /dev/null
+++ b/contrib/groff/font/devlj4/ALBR
@@ -0,0 +1,805 @@
+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 cq -2925
+L ' -2925
+T char173 -3903
+T hy -3903
+T - -3903
+T en -3903
+T em -3903
+A cq -2925
+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 cq -1950
+p ' -1950
+e cq -975
+e ' -975
+b cq -1950
+b ' -1950
+a cq -1461
+a ' -1461
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h cq -1950
+h ' -1950
+n cq -1950
+n ' -1950
+m cq -1950
+m ' -1950
+R cq -975
+R ' -975
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+cq d -1950
+' 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 cq -486
+K ' -486
+b f -486
+k cq -486
+k ' -486
+O cq -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/AOB b/contrib/groff/font/devlj4/AOB
new file mode 100644
index 0000000..913ca39
--- /dev/null
+++ b/contrib/groff/font/devlj4/AOB
@@ -0,0 +1,748 @@
+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 cq -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/AOI b/contrib/groff/font/devlj4/AOI
new file mode 100644
index 0000000..f43a1af
--- /dev/null
+++ b/contrib/groff/font/devlj4/AOI
@@ -0,0 +1,813 @@
+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 cq -3414
+L ' -3414
+T char173 -1461
+T hy -1461
+T - -1461
+T en -1461
+T em -1461
+A cq -1950
+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 cq -1950
+p ' -1950
+c cq -975
+c ' -975
+e cq -1950
+e ' -1950
+b cq -1950
+b ' -1950
+a cq -1950
+a ' -1950
+V char173 -975
+V hy -975
+V - -975
+V en -975
+V em -975
+h cq -1950
+h ' -1950
+n cq -1950
+n ' -1950
+m cq -1950
+m ' -1950
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+cq d -1950
+' d -1950
+s cq -975
+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
+cq s -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/AOR b/contrib/groff/font/devlj4/AOR
new file mode 100644
index 0000000..b9a0485
--- /dev/null
+++ b/contrib/groff/font/devlj4/AOR
@@ -0,0 +1,735 @@
+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 cq -3903
+L ' -3903
+T char173 -975
+T hy -975
+T - -975
+T en -975
+T em -975
+A cq -2439
+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 cq -1950
+p ' -1950
+c cq -975
+c ' -975
+e cq -1950
+e ' -1950
+b cq -1950
+b ' -1950
+a cq -1461
+a ' -1461
+h cq -1950
+h ' -1950
+n cq -1461
+n ' -1461
+m cq -1461
+m ' -1461
+cq d -1950
+' 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
+cq s -975
+' s -975
+char173 A -1461
+hy A -1461
+- A -1461
+en A -1461
+b f -975
+charset
+! 8295,20160,405 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/CB b/contrib/groff/font/devlj4/CB
new file mode 100644
index 0000000..0da67ed
--- /dev/null
+++ b/contrib/groff/font/devlj4/CB
@@ -0,0 +1,350 @@
+name CB
+spacewidth 15873
+pcltypeface 4099
+pclproportional 0
+pclweight 3
+pclstyle 0
+charset
+! 15873,15060,330 0 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/CBI b/contrib/groff/font/devlj4/CBI
new file mode 100644
index 0000000..10f468d
--- /dev/null
+++ b/contrib/groff/font/devlj4/CBI
@@ -0,0 +1,351 @@
+name CBI
+spacewidth 15873
+slant 11.300000
+pcltypeface 4099
+pclproportional 0
+pclweight 3
+pclstyle 1
+charset
+! 15873,15060,330,0,-3018 0 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/CI b/contrib/groff/font/devlj4/CI
new file mode 100644
index 0000000..8a98a36
--- /dev/null
+++ b/contrib/groff/font/devlj4/CI
@@ -0,0 +1,351 @@
+name CI
+spacewidth 15873
+slant 11.300000
+pcltypeface 4099
+pclproportional 0
+pclweight 0
+pclstyle 1
+charset
+! 15873,15060,330,0,-5232 0 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/CLARENDON b/contrib/groff/font/devlj4/CLARENDON
new file mode 100644
index 0000000..86f6c00
--- /dev/null
+++ b/contrib/groff/font/devlj4/CLARENDON
@@ -0,0 +1,351 @@
+name CLARENDON
+spacewidth 5856
+pcltypeface 4140
+pclproportional 1
+pclweight 3
+pclstyle 4
+ligatures fi fl ff ffi ffl 0
+charset
+! 6342,18300 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/CORONET b/contrib/groff/font/devlj4/CORONET
new file mode 100644
index 0000000..9dcecce
--- /dev/null
+++ b/contrib/groff/font/devlj4/CORONET
@@ -0,0 +1,351 @@
+name CORONET
+spacewidth 13227
+slant 12.000000
+pcltypeface 4102
+pclproportional 0
+pclweight 0
+pclstyle 1
+charset
+! 13227,18990,330 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/CR b/contrib/groff/font/devlj4/CR
new file mode 100644
index 0000000..c6da8a6
--- /dev/null
+++ b/contrib/groff/font/devlj4/CR
@@ -0,0 +1,350 @@
+name CR
+spacewidth 15873
+pcltypeface 4099
+pclproportional 0
+pclweight 0
+pclstyle 0
+charset
+! 15873,15060,330 0 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/DESC.in b/contrib/groff/font/devlj4/DESC.in
new file mode 100644
index 0000000..b726647
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devlj4/GB b/contrib/groff/font/devlj4/GB
new file mode 100644
index 0000000..5433de6
--- /dev/null
+++ b/contrib/groff/font/devlj4/GB
@@ -0,0 +1,749 @@
+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 cq -2925
+L ' -2925
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A cq -2925
+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 cq -1461
+p ' -1461
+e cq -486
+e ' -486
+b cq -975
+b ' -975
+a cq -975
+a ' -975
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+R cq -1461
+R ' -1461
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+cq d -1461
+' 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
+cq s -486
+' 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 cq -486
+G ' -486
+B cq -486
+B ' -486
+charset
+! 7317,18948,390 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/GBI b/contrib/groff/font/devlj4/GBI
new file mode 100644
index 0000000..806237c
--- /dev/null
+++ b/contrib/groff/font/devlj4/GBI
@@ -0,0 +1,752 @@
+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 cq -4878
+L ' -4878
+T char173 -3903
+T hy -3903
+T - -3903
+T en -3903
+T em -3903
+A cq -2439
+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 cq -486
+p ' -486
+b cq -975
+b ' -975
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h cq -486
+h ' -486
+n cq -486
+n ' -486
+m cq -486
+m ' -486
+R cq -975
+R ' -975
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+cq d -975
+' 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 cq -486
+v ' -486
+w cq -486
+w ' -486
+E cq -486
+E ' -486
+Z char173 -1461
+Z hy -1461
+Z - -1461
+Z en -1461
+Z em -1461
+B cq -486
+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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/GI b/contrib/groff/font/devlj4/GI
new file mode 100644
index 0000000..6ca1893
--- /dev/null
+++ b/contrib/groff/font/devlj4/GI
@@ -0,0 +1,686 @@
+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 cq -4878
+L ' -4878
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A cq -2439
+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 cq -486
+p ' -486
+b cq -975
+b ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -486
+h ' -486
+n cq -486
+n ' -486
+m cq -486
+m ' -486
+R cq -1950
+R ' -1950
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+cq d -975
+' 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 cq -486
+v ' -486
+w cq -486
+w ' -486
+E cq -486
+E ' -486
+Z cq -975
+Z ' -975
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+B cq -486
+B ' -486
+charset
+! 6342,18648,390,2823,786,910 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/GR b/contrib/groff/font/devlj4/GR
new file mode 100644
index 0000000..169cbd1
--- /dev/null
+++ b/contrib/groff/font/devlj4/GR
@@ -0,0 +1,872 @@
+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 cq -3414
+L ' -3414
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A cq -2925
+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 cq -975
+p ' -975
+e cq -486
+e ' -486
+b cq -1461
+b ' -1461
+a cq -486
+a ' -486
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+R cq -1950
+R ' -1950
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+cq d -1461
+' 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
+cq s -486
+' 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 cq -486
+K ' -486
+G cq -486
+G ' -486
+E cq -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 cq -486
+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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/LGB b/contrib/groff/font/devlj4/LGB
new file mode 100644
index 0000000..681116e
--- /dev/null
+++ b/contrib/groff/font/devlj4/LGB
@@ -0,0 +1,350 @@
+name LGB
+spacewidth 13227
+pcltypeface 4102
+pclproportional 0
+pclweight 3
+pclstyle 0
+charset
+! 13227,18990,330 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/LGI b/contrib/groff/font/devlj4/LGI
new file mode 100644
index 0000000..ef8fae2
--- /dev/null
+++ b/contrib/groff/font/devlj4/LGI
@@ -0,0 +1,351 @@
+name LGI
+spacewidth 13227
+slant 12.000000
+pcltypeface 4102
+pclproportional 0
+pclweight 0
+pclstyle 1
+charset
+! 13227,18990,330,0,-2748 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/LGR b/contrib/groff/font/devlj4/LGR
new file mode 100644
index 0000000..6e9c476
--- /dev/null
+++ b/contrib/groff/font/devlj4/LGR
@@ -0,0 +1,350 @@
+name LGR
+spacewidth 13227
+pcltypeface 4102
+pclproportional 0
+pclweight 0
+pclstyle 0
+charset
+! 13227,18990,330 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/MARIGOLD b/contrib/groff/font/devlj4/MARIGOLD
new file mode 100644
index 0000000..cc0921b
--- /dev/null
+++ b/contrib/groff/font/devlj4/MARIGOLD
@@ -0,0 +1,351 @@
+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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/Makefile.sub b/contrib/groff/font/devlj4/Makefile.sub
new file mode 100644
index 0000000..dd49b63
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devlj4/OB b/contrib/groff/font/devlj4/OB
new file mode 100644
index 0000000..8ea8f29
--- /dev/null
+++ b/contrib/groff/font/devlj4/OB
@@ -0,0 +1,817 @@
+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 cq -2925
+L ' -2925
+T char173 -2925
+T hy -2925
+T - -2925
+T en -2925
+T em -2925
+A cq -3414
+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 cq -1461
+p ' -1461
+c cq -486
+c ' -486
+e cq -975
+e ' -975
+b cq -1461
+b ' -1461
+a cq -975
+a ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+cq d -1461
+' d -1461
+s cq -486
+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
+cq s -975
+' 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 cq -486
+K ' -486
+t g -486
+b f -486
+k cq -486
+k ' -486
+M cq -486
+M ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+cq M -486
+' M -486
+k char173 -486
+k hy -486
+k - -486
+k en -486
+k em -486
+charset
+! 7317,18000,375 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/OBI b/contrib/groff/font/devlj4/OBI
new file mode 100644
index 0000000..e17fe3f
--- /dev/null
+++ b/contrib/groff/font/devlj4/OBI
@@ -0,0 +1,810 @@
+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 cq -2439
+L ' -2439
+T char173 -2439
+T hy -2439
+T - -2439
+T en -2439
+T em -2439
+A cq -3414
+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 cq -486
+p ' -486
+c cq -486
+c ' -486
+e cq -1461
+e ' -1461
+b cq -1950
+b ' -1950
+a cq -975
+a ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -1461
+h ' -1461
+n cq -1461
+n ' -1461
+R cq -486
+R ' -486
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+cq d -1461
+' 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
+cq s -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 -486
+R hy -486
+R - -486
+R en -486
+R em -486
+K cq -486
+K ' -486
+b f -486
+k cq -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/OI b/contrib/groff/font/devlj4/OI
new file mode 100644
index 0000000..bbe9b44
--- /dev/null
+++ b/contrib/groff/font/devlj4/OI
@@ -0,0 +1,923 @@
+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 cq -2439
+L ' -2439
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A cq -3903
+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 cq -1950
+p ' -1950
+c cq -486
+c ' -486
+e cq -975
+e ' -975
+b cq -1461
+b ' -1461
+a cq -1950
+a ' -1950
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -1461
+h ' -1461
+n cq -1461
+n ' -1461
+R cq -975
+R ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+cq d -1461
+' 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
+cq s -975
+' 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 cq -486
+K ' -486
+t g -486
+b f -486
+k cq -486
+k ' -486
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+U cq -486
+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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/OR b/contrib/groff/font/devlj4/OR
new file mode 100644
index 0000000..edea52a
--- /dev/null
+++ b/contrib/groff/font/devlj4/OR
@@ -0,0 +1,899 @@
+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 cq -3414
+L ' -3414
+T char173 -3903
+T hy -3903
+T - -3903
+T en -3903
+T em -3903
+A cq -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 cq -1461
+p ' -1461
+c cq -486
+c ' -486
+e cq -975
+e ' -975
+b cq -1461
+b ' -1461
+a cq -1461
+a ' -1461
+V char173 -2439
+V hy -2439
+V - -2439
+V en -2439
+V em -2439
+h cq -1461
+h ' -1461
+n cq -1461
+n ' -1461
+m cq -1461
+m ' -1461
+R cq -975
+R ' -975
+W char173 -1461
+W hy -1461
+W - -1461
+W en -1461
+W em -1461
+cq d -1461
+' d -1461
+s cq -486
+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
+cq s -975
+' 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 cq -486
+k ' -486
+M cq -486
+M ' -486
+G cq -486
+G ' -486
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+B cq -486
+B ' -486
+U cq -486
+U ' -486
+cq M -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/S b/contrib/groff/font/devlj4/S
new file mode 100644
index 0000000..599867f
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devlj4/TB b/contrib/groff/font/devlj4/TB
new file mode 100644
index 0000000..644425a
--- /dev/null
+++ b/contrib/groff/font/devlj4/TB
@@ -0,0 +1,991 @@
+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 cq -3414
+L ' -3414
+T char173 -1461
+T hy -1461
+T - -1461
+T en -1461
+T em -1461
+A cq -3414
+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 cq -975
+c ' -975
+e cq -975
+e ' -975
+b cq -486
+b ' -486
+a cq -1461
+a ' -1461
+V char173 -2439
+V hy -2439
+V - -2439
+V en -2439
+V em -2439
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+R cq -975
+R ' -975
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+cq d -1461
+' d -1461
+s cq -486
+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
+cq s -975
+' 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 cq -486
+K ' -486
+t g -486
+b f -486
+k cq -486
+k ' -486
+C cq -486
+C ' -486
+E cq -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/TBI b/contrib/groff/font/devlj4/TBI
new file mode 100644
index 0000000..e1a30a8
--- /dev/null
+++ b/contrib/groff/font/devlj4/TBI
@@ -0,0 +1,1045 @@
+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 cq -2925
+L ' -2925
+T char173 -975
+T hy -975
+T - -975
+T en -975
+T em -975
+A cq -3414
+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 cq -1950
+p ' -1950
+c cq -1461
+c ' -1461
+e cq -1950
+e ' -1950
+b cq -1950
+b ' -1950
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+R cq -486
+R ' -486
+W char173 -1950
+W hy -1950
+W - -1950
+W en -1950
+W em -1950
+cq d -975
+' 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
+cq s -486
+' 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 cq -486
+K ' -486
+t g -486
+v cq -486
+v ' -486
+b f -975
+y cq -486
+y ' -486
+w cq -486
+w ' -486
+C cq -486
+C ' -486
+E cq -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 cq -975
+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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/TI b/contrib/groff/font/devlj4/TI
new file mode 100644
index 0000000..6b4a3ec
--- /dev/null
+++ b/contrib/groff/font/devlj4/TI
@@ -0,0 +1,1131 @@
+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 cq -1950
+L ' -1950
+T char173 -486
+T hy -486
+T - -486
+T en -486
+T em -486
+A cq -2439
+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 cq -1950
+p ' -1950
+c cq -1461
+c ' -1461
+e cq -1950
+e ' -1950
+b cq -1950
+b ' -1950
+V char173 -1950
+V hy -1950
+V - -1950
+V en -1950
+V em -1950
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+R cq -1461
+R ' -1461
+W char173 -2439
+W hy -2439
+W - -2439
+W en -2439
+W em -2439
+cq d -1461
+' 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
+cq s -486
+' 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 cq -486
+K ' -486
+t g -975
+v cq -486
+v ' -486
+b f -486
+y cq -486
+y ' -486
+w cq -486
+w ' -486
+k cq -975
+k ' -975
+P cq -486
+P ' -486
+P char173 -975
+P hy -975
+P - -975
+P en -975
+P em -975
+E cq -486
+E ' -486
+E char173 -975
+E hy -975
+E - -975
+E en -975
+E em -975
+B cq -486
+B ' -486
+J cq -486
+J ' -486
+J char173 -486
+J hy -486
+J - -486
+J en -486
+J em -486
+U cq -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/TR b/contrib/groff/font/devlj4/TR
new file mode 100644
index 0000000..64a1243
--- /dev/null
+++ b/contrib/groff/font/devlj4/TR
@@ -0,0 +1,878 @@
+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 cq -3903
+L ' -3903
+T char173 -1950
+T hy -1950
+T - -1950
+T en -1950
+T em -1950
+A cq -3903
+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 cq -975
+p ' -975
+c cq -1461
+c ' -1461
+e cq -975
+e ' -975
+b cq -1461
+b ' -1461
+a cq -1461
+a ' -1461
+V char173 -2925
+V hy -2925
+V - -2925
+V en -2925
+V em -2925
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+R cq -1461
+R ' -1461
+W char173 -2439
+W hy -2439
+W - -2439
+W en -2439
+W em -2439
+cq d -1461
+' d -1461
+s cq -975
+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
+cq s -975
+' 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 cq -486
+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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UB b/contrib/groff/font/devlj4/UB
new file mode 100644
index 0000000..5c1717f
--- /dev/null
+++ b/contrib/groff/font/devlj4/UB
@@ -0,0 +1,829 @@
+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 cq -6342
+L ' -6342
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A cq -2439
+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 cq -1461
+p ' -1461
+c cq -975
+c ' -975
+e cq -1461
+e ' -1461
+b cq -1461
+b ' -1461
+a cq -975
+a ' -975
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+cq d -2439
+' d -2439
+s cq -486
+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
+cq s -1950
+' 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
+cq n -1461
+' n -1461
+cq m -1461
+' m -1461
+cq r -1461
+' r -1461
+cq v -1461
+' v -1461
+charset
+! 8781,18165 2 3617
+dq 13662,18135 2 3618
+" "
+sh 16587,18105 2 3619
+# "
+Do 16587,18750,645 2 3620
+$ "
+% 26346,18720,840 2 3621
+& 20004,18495 2 3622
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UBI b/contrib/groff/font/devlj4/UBI
new file mode 100644
index 0000000..00ffcfc
--- /dev/null
+++ b/contrib/groff/font/devlj4/UBI
@@ -0,0 +1,779 @@
+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 cq -6342
+L ' -6342
+T char173 -2925
+T hy -2925
+T - -2925
+T en -2925
+T em -2925
+A cq -2439
+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 cq -975
+p ' -975
+c cq -1461
+c ' -1461
+e cq -1461
+e ' -1461
+b cq -1461
+b ' -1461
+a cq -1461
+a ' -1461
+V char173 -975
+V hy -975
+V - -975
+V en -975
+V em -975
+h cq -1461
+h ' -1461
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+cq d -2439
+' d -2439
+s cq -486
+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
+cq s -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
+cq n -1461
+' n -1461
+cq m -1461
+' m -1461
+cq r -1461
+' r -1461
+cq v -1950
+' v -1950
+charset
+! 8781,18165,0,2643,33,1012 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UCB b/contrib/groff/font/devlj4/UCB
new file mode 100644
index 0000000..2864278
--- /dev/null
+++ b/contrib/groff/font/devlj4/UCB
@@ -0,0 +1,790 @@
+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 cq -4389
+L ' -4389
+T char173 -2925
+T hy -2925
+T - -2925
+T en -2925
+T em -2925
+A cq -1461
+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 cq -1461
+p ' -1461
+c cq -975
+c ' -975
+e cq -1461
+e ' -1461
+b cq -1461
+b ' -1461
+a cq -975
+a ' -975
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h cq -975
+h ' -975
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+cq d -975
+' d -975
+s cq -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
+cq s -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
+b f -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+charset
+! 7806,18135 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UCBI b/contrib/groff/font/devlj4/UCBI
new file mode 100644
index 0000000..d1876c1
--- /dev/null
+++ b/contrib/groff/font/devlj4/UCBI
@@ -0,0 +1,698 @@
+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 cq -3903
+L ' -3903
+T char173 -1950
+T hy -1950
+T - -1950
+T en -1950
+T em -1950
+A cq -1461
+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 cq -975
+p ' -975
+c cq -975
+c ' -975
+e cq -1461
+e ' -1461
+b cq -1461
+b ' -1461
+a cq -975
+a ' -975
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h cq -1461
+h ' -1461
+n cq -975
+n ' -975
+m cq -975
+m ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+cq d -975
+' d -975
+s cq -486
+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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UCI b/contrib/groff/font/devlj4/UCI
new file mode 100644
index 0000000..4214f49
--- /dev/null
+++ b/contrib/groff/font/devlj4/UCI
@@ -0,0 +1,840 @@
+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 cq -3414
+L ' -3414
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A cq -1461
+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 cq -1950
+p ' -1950
+c cq -1950
+c ' -1950
+e cq -1950
+e ' -1950
+b cq -1950
+b ' -1950
+a cq -1950
+a ' -1950
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h cq -1461
+h ' -1461
+n cq -1461
+n ' -1461
+m cq -1461
+m ' -1461
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+cq d -486
+' d -486
+s cq -975
+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
+cq s -486
+' 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 cq -486
+v ' -486
+C cq -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UCR b/contrib/groff/font/devlj4/UCR
new file mode 100644
index 0000000..3b50399
--- /dev/null
+++ b/contrib/groff/font/devlj4/UCR
@@ -0,0 +1,759 @@
+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 cq -5364
+L ' -5364
+T char173 -3414
+T hy -3414
+T - -3414
+T en -3414
+T em -3414
+A cq -1461
+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 cq -975
+p ' -975
+c cq -975
+c ' -975
+e cq -975
+e ' -975
+b cq -975
+b ' -975
+a cq -1461
+a ' -1461
+V char173 -486
+V hy -486
+V - -486
+V en -486
+V em -486
+h cq -1461
+h ' -1461
+n cq -1461
+n ' -1461
+m cq -1461
+m ' -1461
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+cq d -1950
+' d -1950
+s cq -486
+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
+cq s -486
+' 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 cq -486
+K ' -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+charset
+! 7806,18135 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UI b/contrib/groff/font/devlj4/UI
new file mode 100644
index 0000000..12bcc26
--- /dev/null
+++ b/contrib/groff/font/devlj4/UI
@@ -0,0 +1,983 @@
+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 cq -7317
+L ' -7317
+T char173 -4389
+T hy -4389
+T - -4389
+T en -4389
+T em -4389
+A cq -3903
+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 cq -2925
+p ' -2925
+c cq -2925
+c ' -2925
+e cq -2925
+e ' -2925
+b cq -2925
+b ' -2925
+a cq -2925
+a ' -2925
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -2439
+h ' -2439
+n cq -2439
+n ' -2439
+m cq -2439
+m ' -2439
+R cq -975
+R ' -975
+W char173 -486
+W hy -486
+W - -486
+W en -486
+W em -486
+cq d -2925
+' d -2925
+s cq -1950
+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
+cq s -1950
+' 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 cq -1461
+x ' -1461
+X cq -1461
+X ' -1461
+K cq -1461
+K ' -1461
+t g -486
+t cq -975
+t ' -975
+l cq -975
+l ' -975
+r cq -975
+r ' -975
+g cq -975
+g ' -975
+i cq -975
+i ' -975
+v cq -975
+v ' -975
+z cq -975
+z ' -975
+d cq -975
+d ' -975
+y cq -975
+y ' -975
+f cq -975
+f ' -975
+w cq -975
+w ' -975
+j cq -975
+j ' -975
+u cq -975
+u ' -975
+k cq -975
+k ' -975
+T cq -975
+T ' -975
+O cq -975
+O ' -975
+H cq -975
+H ' -975
+N cq -975
+N ' -975
+M cq -975
+M ' -975
+G cq -975
+G ' -975
+I cq -975
+I ' -975
+P cq -975
+P ' -975
+C cq -975
+C ' -975
+V cq -975
+V ' -975
+E cq -975
+E ' -975
+Z cq -975
+Z ' -975
+Z char173 -975
+Z hy -975
+Z - -975
+Z en -975
+Z em -975
+D cq -975
+D ' -975
+B cq -975
+B ' -975
+S cq -975
+S ' -975
+Y cq -975
+Y ' -975
+F cq -975
+F ' -975
+W cq -975
+W ' -975
+J cq -975
+J ' -975
+U cq -975
+U ' -975
+cq t -1461
+' t -1461
+cq n -1461
+' n -1461
+cq m -1461
+' m -1461
+cq l -975
+' l -975
+cq r -1461
+' r -1461
+cq v -1461
+' v -1461
+cq T -975
+' T -975
+cq N -975
+' N -975
+cq M -975
+' M -975
+cq L -975
+' L -975
+cq R -975
+' R -975
+cq D -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
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/UR b/contrib/groff/font/devlj4/UR
new file mode 100644
index 0000000..b7eba7c
--- /dev/null
+++ b/contrib/groff/font/devlj4/UR
@@ -0,0 +1,880 @@
+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 cq -6342
+L ' -6342
+T char173 -4878
+T hy -4878
+T - -4878
+T en -4878
+T em -4878
+A cq -2925
+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 cq -1950
+p ' -1950
+c cq -1461
+c ' -1461
+e cq -1950
+e ' -1950
+b cq -1950
+b ' -1950
+a cq -1461
+a ' -1461
+V char173 -1461
+V hy -1461
+V - -1461
+V en -1461
+V em -1461
+h cq -1461
+h ' -1461
+n cq -1461
+n ' -1461
+m cq -1461
+m ' -1461
+W char173 -975
+W hy -975
+W - -975
+W en -975
+W em -975
+cq d -3414
+' d -3414
+s cq -486
+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
+cq s -1950
+' 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 cq -486
+K ' -486
+t g -486
+b f -486
+Z char173 -486
+Z hy -486
+Z - -486
+Z en -486
+Z em -486
+cq t -975
+' t -975
+cq n -1461
+' n -1461
+cq m -1461
+' m -1461
+cq r -1461
+' r -1461
+cq v -1461
+' v -1461
+charset
+! 8781,18165 2 3617
+dq 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
+cq 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
+pc "
+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/contrib/groff/font/devlj4/generate/Makefile b/contrib/groff/font/devlj4/generate/Makefile
new file mode 100644
index 0000000..c11dbee
--- /dev/null
+++ b/contrib/groff/font/devlj4/generate/Makefile
@@ -0,0 +1,170 @@
+# 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://ftp.hp.com/pub/faxes/software/tfmlj4.exe
+#
+# This is a self-extracting MS-DOS archive (in ZIP format).
+
+# This is set up so you can do
+# make -f generate/Makefile
+# in the parent directory of this directory.
+
+AUTOFONT=/usr/local/lib/groff-lj4
+HPFTODIT=hpftodit
+# .05 em
+IFLAG=-i 439
+SFLAG=-s
+srcdir=generate
+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/contrib/groff/font/devlj4/generate/special.map b/contrib/groff/font/devlj4/generate/special.map
new file mode 100644
index 0000000..ea23337
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devlj4/generate/text.map b/contrib/groff/font/devlj4/generate/text.map
new file mode 100644
index 0000000..0175cbe
--- /dev/null
+++ b/contrib/groff/font/devlj4/generate/text.map
@@ -0,0 +1,344 @@
+# Map MSL numbers to troff names for a text font.
+1 !
+2 "
+2 dq
+3 #
+3 sh
+4 $
+4 Do
+5 %
+6 &
+8 '
+8 cq
+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 pc
+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/contrib/groff/font/devps/AB b/contrib/groff/font/devps/AB
new file mode 100644
index 0000000..f00cf9a
--- /dev/null
+++ b/contrib/groff/font/devps/AB
@@ -0,0 +1,574 @@
+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 cq -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 cq -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
+, cq -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
+. cq -70
+. rq -70
+lq A -50
+` ` -80
+` oq -80
+oq ` -80
+oq oq -80
+` A -50
+oq A -50
+' v -10
+cq v -10
+' t 10
+cq t 10
+' s -15
+cq s -15
+' r -20
+cq r -20
+' ' -80
+' cq -80
+cq ' -80
+cq cq -80
+' d -50
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 280,320 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/ABI b/contrib/groff/font/devps/ABI
new file mode 100644
index 0000000..d236b63
--- /dev/null
+++ b/contrib/groff/font/devps/ABI
@@ -0,0 +1,575 @@
+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 cq -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 cq -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
+, cq -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
+. cq -70
+. rq -70
+lq A -50
+` ` -80
+` oq -80
+oq ` -80
+oq oq -80
+` A -50
+oq A -50
+' v -10
+cq v -10
+' t 10
+cq t 10
+' s -15
+cq s -15
+' r -20
+cq r -20
+' ' -80
+' cq -80
+cq ' -80
+cq cq -80
+' d -50
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 280,320,0,35,-58,35 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/AI b/contrib/groff/font/devps/AI
new file mode 100644
index 0000000..be0e099
--- /dev/null
+++ b/contrib/groff/font/devps/AI
@@ -0,0 +1,575 @@
+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 cq -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 cq -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
+, cq -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
+. cq -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
+cq v -30
+' t 10
+cq t 10
+' s -15
+cq s -15
+' r -20
+cq r -20
+' ' -203
+' cq -203
+cq ' -203
+cq cq -203
+' rq -35
+cq rq -35
+' d -110
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 277,316,0,8,-87,8 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/AR b/contrib/groff/font/devps/AR
new file mode 100644
index 0000000..9dff2dc
--- /dev/null
+++ b/contrib/groff/font/devps/AR
@@ -0,0 +1,574 @@
+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 cq -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 cq -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
+, cq -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
+. cq -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
+cq v -30
+' t 10
+cq t 10
+' s -15
+cq s -15
+' r -20
+cq r -20
+' ' -203
+' cq -203
+cq ' -203
+cq cq -203
+' rq -35
+cq rq -35
+' d -110
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 277,316 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/BMB b/contrib/groff/font/devps/BMB
new file mode 100644
index 0000000..186ec7b
--- /dev/null
+++ b/contrib/groff/font/devps/BMB
@@ -0,0 +1,441 @@
+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
+dq "
+# 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
+cq "
+( 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,125 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,750,250 3 0174 -- bar
+| "
+rC 320,725,140 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,675,175 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 2 0266 -- paragraph
+char182 "
+pc 340,355 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/BMBI b/contrib/groff/font/devps/BMBI
new file mode 100644
index 0000000..43d2bdd
--- /dev/null
+++ b/contrib/groff/font/devps/BMBI
@@ -0,0 +1,444 @@
+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
+dq "
+# 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
+cq "
+( 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,125,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,163,1,73 2 0173 -- braceleft
+{ "
+ba 620,750,250,0,-253 3 0174 -- bar
+| "
+rC 300,751,114,106,58,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,675,175,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,-68,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,0,85,-87,73 2 0266 -- paragraph
+char182 "
+pc 340,358,0,26,-76,26 0 0267 -- periodcentered
+char183 "
+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,65,-77,65 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/contrib/groff/font/devps/BMI b/contrib/groff/font/devps/BMI
new file mode 100644
index 0000000..9b90a65
--- /dev/null
+++ b/contrib/groff/font/devps/BMI
@@ -0,0 +1,437 @@
+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,861,17,78,-11,70 2 0002 -- Scaron
+vZ 580,861,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,865,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
+dq "
+# 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
+cq "
+( 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,125,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,132,-72,70 2 0173 -- braceleft
+{ "
+ba 600,750,250,0,-244 3 0174 -- bar
+| "
+rC 380,717,191,3,37,3 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,675,175,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,-80,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 "
+pc 300,364,0,22,-87,22 0 0267 -- periodcentered
+char183 "
+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,-89,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,883,0,70,75,70 2 0300 -- Agrave
+char192 "
+'A 700,883,0,70,75,70 2 0301 -- Aacute
+char193 "
+^A 700,862,0,70,75,70 2 0302 -- Acircumflex
+char194 "
+~A 700,848,0,70,75,70 2 0303 -- Atilde
+char195 "
+:A 700,865,0,70,75,70 2 0304 -- Adieresis
+char196 "
+oA 700,883,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,883,0,106,29,70 2 0310 -- Egrave
+char200 "
+'E 680,883,0,106,29,70 2 0311 -- Eacute
+char201 "
+^E 680,862,0,106,29,70 2 0312 -- Ecircumflex
+char202 "
+:E 680,865,0,106,29,70 2 0313 -- Edieresis
+char203 "
+`I 320,883,0,142,29,70 2 0314 -- Igrave
+char204 "
+'I 320,883,0,142,29,70 2 0315 -- Iacute
+char205 "
+^I 320,862,0,179,29,70 2 0316 -- Icircumflex
+char206 "
+:I 320,865,0,177,29,70 2 0317 -- Idieresis
+char207 "
+-D 740,681,0,92,29,70 2 0320 -- Eth
+char208 "
+~N 720,848,0,153,32,70 2 0321 -- Ntilde
+char209 "
+`O 760,883,17,89,-38,70 2 0322 -- Ograve
+char210 "
+'O 760,883,17,89,-38,70 2 0323 -- Oacute
+char211 "
+^O 760,862,17,89,-38,70 2 0324 -- Ocircumflex
+char212 "
+~O 760,848,17,89,-38,70 2 0325 -- Otilde
+char213 "
+:O 760,865,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,883,17,172,-68,70 2 0331 -- Ugrave
+char217 "
+'U 720,883,17,172,-68,70 2 0332 -- Uacute
+char218 "
+^U 720,862,17,172,-68,70 2 0333 -- Ucircumflex
+char219 "
+:U 720,865,17,172,-68,70 2 0334 -- Udieresis
+char220 "
+'Y 660,883,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/contrib/groff/font/devps/BMR b/contrib/groff/font/devps/BMR
new file mode 100644
index 0000000..615b7cc
--- /dev/null
+++ b/contrib/groff/font/devps/BMR
@@ -0,0 +1,433 @@
+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,849,17 2 0002 -- Scaron
+vZ 640,849 2 0003 -- Zcaron
+vs 520,672,8 2 0004 -- scaron
+vz 480,672 2 0005 -- zcaron
+:Y 640,851 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
+dq "
+# 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
+cq "
+( 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,125 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,750,250 3 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,698 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,675,175 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 "
+pc 320,327 0 0267 -- periodcentered
+char183 "
+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,866 2 0300 -- Agrave
+char192 "
+'A 680,866 2 0301 -- Aacute
+char193 "
+^A 680,862 2 0302 -- Acircumflex
+char194 "
+~A 680,838 2 0303 -- Atilde
+char195 "
+:A 680,851 2 0304 -- Adieresis
+char196 "
+oA 680,908 2 0305 -- Aring
+char197 "
+AE 1260,681 2 0306 -- AE
+char198 "
+,C 740,698,200 2 0307 -- Ccedilla
+char199 "
+`E 720,866 2 0310 -- Egrave
+char200 "
+'E 720,866 2 0311 -- Eacute
+char201 "
+^E 720,862 2 0312 -- Ecircumflex
+char202 "
+:E 720,851 2 0313 -- Edieresis
+char203 "
+`I 340,866 2 0314 -- Igrave
+char204 "
+'I 340,866 2 0315 -- Iacute
+char205 "
+^I 340,862 2 0316 -- Icircumflex
+char206 "
+:I 340,851 2 0317 -- Idieresis
+char207 "
+-D 800,681 2 0320 -- Eth
+char208 "
+~N 740,838 2 0321 -- Ntilde
+char209 "
+`O 800,866,17 2 0322 -- Ograve
+char210 "
+'O 800,866,17 2 0323 -- Oacute
+char211 "
+^O 800,862,17 2 0324 -- Ocircumflex
+char212 "
+~O 800,838,17 2 0325 -- Otilde
+char213 "
+:O 800,851,17 2 0326 -- Odieresis
+char214 "
+char215 600,513 0 0327 -- multiply
+/O 800,733,53 2 0330 -- Oslash
+char216 "
+`U 780,866,17 2 0331 -- Ugrave
+char217 "
+'U 780,866,17 2 0332 -- Uacute
+char218 "
+^U 780,862,17 2 0333 -- Ucircumflex
+char219 "
+:U 780,851,17 2 0334 -- Udieresis
+char220 "
+'Y 640,866 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/contrib/groff/font/devps/CB b/contrib/groff/font/devps/CB
new file mode 100644
index 0000000..6c01b8d
--- /dev/null
+++ b/contrib/groff/font/devps/CB
@@ -0,0 +1,339 @@
+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
+dq "
+# 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
+cq "
+( 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 "
+pc 600,351 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/CBI b/contrib/groff/font/devps/CBI
new file mode 100644
index 0000000..72b5561
--- /dev/null
+++ b/contrib/groff/font/devps/CBI
@@ -0,0 +1,340 @@
+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
+dq "
+# 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
+cq "
+( 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 "
+pc 600,351,0,0,-199 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/CI b/contrib/groff/font/devps/CI
new file mode 100644
index 0000000..63ea748
--- /dev/null
+++ b/contrib/groff/font/devps/CI
@@ -0,0 +1,340 @@
+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
+dq "
+# 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
+cq "
+( 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 "
+pc 600,327,0,0,-225 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/CR b/contrib/groff/font/devps/CR
new file mode 100644
index 0000000..fc3c91e
--- /dev/null
+++ b/contrib/groff/font/devps/CR
@@ -0,0 +1,339 @@
+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
+dq "
+# 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
+cq "
+( 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 "
+pc 600,327 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/DESC.in b/contrib/groff/font/devps/DESC.in
new file mode 100644
index 0000000..e9d26c8
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/HB b/contrib/groff/font/devps/HB
new file mode 100644
index 0000000..96e022e
--- /dev/null
+++ b/contrib/groff/font/devps/HB
@@ -0,0 +1,561 @@
+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 cq -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
+, cq -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 cq 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
+. cq -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+cq v -20
+' s -60
+cq s -60
+' r -40
+cq r -40
+' ' -46
+' cq -46
+cq ' -46
+cq cq -46
+' l -20
+cq l -20
+' d -80
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 278,334 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/HBI b/contrib/groff/font/devps/HBI
new file mode 100644
index 0000000..a12e389
--- /dev/null
+++ b/contrib/groff/font/devps/HBI
@@ -0,0 +1,562 @@
+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 cq -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
+, cq -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 cq 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
+. cq -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+cq v -20
+' s -60
+cq s -60
+' r -40
+cq r -40
+' ' -46
+' cq -46
+cq ' -46
+cq cq -46
+' l -20
+cq l -20
+' d -80
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 278,334,0,48,-60,48 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/HI b/contrib/groff/font/devps/HI
new file mode 100644
index 0000000..1846122
--- /dev/null
+++ b/contrib/groff/font/devps/HI
@@ -0,0 +1,630 @@
+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 cq -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
+, cq -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f cq 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
+. cq -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+cq s -50
+' r -50
+cq r -50
+' ' -57
+' cq -57
+cq ' -57
+cq cq -57
+' d -50
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 278,315,0,29,-79,29 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/HNB b/contrib/groff/font/devps/HNB
new file mode 100644
index 0000000..ded4815
--- /dev/null
+++ b/contrib/groff/font/devps/HNB
@@ -0,0 +1,561 @@
+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 cq -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
+, cq -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 cq 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
+. cq -97
+. rq -97
+` ` -37
+` oq -37
+oq ` -37
+oq oq -37
+' v -15
+cq v -15
+' s -48
+cq s -48
+' r -32
+cq r -32
+' ' -37
+' cq -37
+cq ' -37
+cq cq -37
+' l -15
+cq l -15
+' d -65
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 228,334 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/HNBI b/contrib/groff/font/devps/HNBI
new file mode 100644
index 0000000..a5809e1
--- /dev/null
+++ b/contrib/groff/font/devps/HNBI
@@ -0,0 +1,562 @@
+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 cq -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
+, cq -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 cq 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
+. cq -120
+. rq -120
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' v -20
+cq v -20
+' s -60
+cq s -60
+' r -40
+cq r -40
+' ' -46
+' cq -46
+cq ' -46
+cq cq -46
+' l -20
+cq l -20
+' d -80
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 228,334,0,48,-40,48 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/HNI b/contrib/groff/font/devps/HNI
new file mode 100644
index 0000000..c9ab4ec
--- /dev/null
+++ b/contrib/groff/font/devps/HNI
@@ -0,0 +1,630 @@
+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 cq -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
+, cq -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f cq 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
+. cq -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+cq s -50
+' r -50
+cq r -50
+' ' -57
+' cq -57
+cq ' -57
+cq cq -57
+' d -50
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 228,315,0,33,-56,33 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/HNR b/contrib/groff/font/devps/HNR
new file mode 100644
index 0000000..e4f30ee
--- /dev/null
+++ b/contrib/groff/font/devps/HNR
@@ -0,0 +1,629 @@
+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 cq -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
+, cq -81
+, rq -81
+e y -15
+e x -24
+e w -15
+e v -24
+e . -11
+e , -11
+f ' 41
+f cq 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
+. cq -81
+. rq -81
+` ` -46
+` oq -46
+oq ` -46
+oq oq -46
+' s -40
+cq s -40
+' r -40
+cq r -40
+' ' -46
+' cq -46
+cq ' -46
+cq cq -46
+' d -40
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 228,315 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/HR b/contrib/groff/font/devps/HR
new file mode 100644
index 0000000..3f89e25
--- /dev/null
+++ b/contrib/groff/font/devps/HR
@@ -0,0 +1,629 @@
+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 cq -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
+, cq -100
+, rq -100
+e y -20
+e x -30
+e w -20
+e v -30
+e . -15
+e , -15
+f ' 50
+f cq 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
+. cq -100
+. rq -100
+` ` -57
+` oq -57
+oq ` -57
+oq oq -57
+' s -50
+cq s -50
+' r -50
+cq r -50
+' ' -57
+' cq -57
+cq ' -57
+cq cq -57
+' d -50
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 278,315 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/Makefile.sub b/contrib/groff/font/devps/Makefile.sub
new file mode 100644
index 0000000..08b61e2
--- /dev/null
+++ b/contrib/groff/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/dingbats.map \
+ generate/dingbats.rmap 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/contrib/groff/font/devps/NB b/contrib/groff/font/devps/NB
new file mode 100644
index 0000000..1a926cb
--- /dev/null
+++ b/contrib/groff/font/devps/NB
@@ -0,0 +1,473 @@
+name NB
+internalname NewCenturySchlbk-Bold
+spacewidth 287
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -18
+A w -18
+A v -18
+A ' -74
+A cq -74
+A rq -74
+A Y -91
+A W -74
+A V -74
+A U -18
+A T -55
+C . -18
+C , -18
+D . -25
+D , -25
+F r -18
+F . -125
+F o -55
+F i -18
+F e -55
+F , -125
+F a -74
+J u -18
+J . -55
+J o -18
+J e -18
+J , -55
+J a -18
+J A -18
+K y -25
+K u -18
+L y -25
+L ' -100
+L cq -100
+L rq -100
+L Y -74
+L W -74
+L V -100
+L T -100
+N . -18
+N , -18
+O . -25
+O , -25
+O T 10
+P . -150
+P o -55
+P e -55
+P , -150
+P a -55
+P A -74
+S . -18
+S , -18
+T u -18
+T r -18
+T . -100
+T o -74
+T i -18
+T - -125
+T hy -125
+T char173 -125
+T e -74
+T , -100
+T a -74
+T O 10
+T A -55
+U . -25
+U , -25
+U A -18
+V u -55
+V ; -37
+V . -125
+V o -74
+V i -18
+V - -100
+V hy -100
+V char173 -100
+V e -74
+V , -125
+V : -37
+V a -74
+V A -74
+W y -25
+W u -37
+W ; -55
+W . -100
+W o -74
+W i -18
+W - -100
+W hy -100
+W char173 -100
+W e -74
+W , -100
+W : -55
+W a -74
+W A -74
+Y u -55
+Y ; -25
+Y . -100
+Y o -100
+Y i -18
+Y - -125
+Y hy -125
+Y char173 -125
+Y e -100
+Y , -100
+Y : -25
+Y a -100
+Y A -91
+, ' -18
+, cq -18
+, rq -18
+f ' 75
+f cq 75
+f rq 75
+. ' -18
+. cq -18
+. rq -18
+lq A -74
+` A -74
+oq A -74
+' s -25
+cq s -25
+' d -25
+cq d -25
+r . -74
+r , -74
+v . -100
+v , -100
+w . -100
+w , -100
+y . -100
+y , -100
+charset
+ha 606,690 2 0000 -- asciicircum
+ti 606,346 0 0001 -- asciitilde
+vS 667,952,15 2 0002 -- Scaron
+vZ 667,952 2 0003 -- Zcaron
+vs 500,725,15 2 0004 -- scaron
+vz 537,725 2 0005 -- zcaron
+:Y 722,921 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
+dq "
+# 574,690 2 0043 -- numbersign
+sh "
+$ 574,810,141 2 0044 -- dollar
+Do "
+% 833,705,15 2 0045 -- percent
+& 852,737,15 2 0046 -- ampersand
+' 241,737 2 0047 -- quoteright
+cq "
+( 389,745,117 2 0050 -- parenleft
+) 389,745,117 2 0051 -- parenright
+* 500,737 2 0052 -- asterisk
++ 606,506 0 0053 -- plus
+, 278,175,184 0 0054 -- comma
+- 333,302 0 0055 -- hyphen
+hy "
+char173 "
+. 278,175,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 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,184 0 0073 -- semicolon
+< 606,515,9 0 0074 -- less
+= 606,403 0 0075 -- equal
+> 606,515,9 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,10 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,10 2 0126 -- V
+W 981,722,10 2 0127 -- W
+X 722,722 2 0130 -- X
+Y 722,722 2 0131 -- Y
+Z 667,722 2 0132 -- Z
+[ 389,737,109 2 0133 -- bracketleft
+lB "
+\ 606,737,15 2 0134 -- backslash
+rs "
+] 389,737,109 2 0135 -- bracketright
+rB "
+a^ 333,725 2 0136 -- circumflex
+^ "
+_ 500,0,125 0 0137 -- underscore
+` 241,737 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,535,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,10 0 0166 -- v
+w 889,475,10 0 0167 -- w
+x 611,475 0 0170 -- x
+y 611,475,205 1 0171 -- y
+z 537,475 0 0172 -- z
+lC 389,737,109 2 0173 -- braceleft
+{ "
+ba 606,750,250 3 0174 -- bar
+| "
+rC 389,737,109 2 0175 -- braceright
+} "
+a~ 333,705 2 0176 -- tilde
+~ "
+bq 241,175,184 0 0200 -- quotesinglbase
+Fo 500,397 0 0201 -- guillemotleft
+char171 "
+Fc 500,397 0 0202 -- guillemotright
+char187 "
+bu 606,542 0 0203 -- bullet
+Fn 574,737,205 3 0204 -- florin
+f/ 167,705,15 2 0205 -- fraction
+%0 1000,705,15 2 0206 -- perthousand
+dg 500,737,101 2 0207 -- dagger
+dd 500,737,89 2 0210 -- daggerdbl
+en 500,292 0 0211 -- endash
+em 1000,292 0 0212 -- emdash
+fi 685,737 2 0214 -- fi
+fl 685,737 2 0215 -- fl
+.i 370,475 0 0220 -- dotlessi
+ga 333,737 2 0222 -- grave
+a" 333,737 2 0223 -- hungarumlaut
+a. 333,694 2 0224 -- dotaccent
+ab 333,714 2 0225 -- breve
+ah 333,725 2 0226 -- caron
+ao 333,761 2 0227 -- ring
+ho 333,3,163 0 0230 -- ogonek
+lq 481,737 2 0231 -- quotedblleft
+rq 481,737 2 0232 -- quotedblright
+oe 907,485,15 0 0233 -- oe
+/l 352,737 2 0234 -- lslash
+Bq 481,175,184 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,572,102 0 0242 -- cent
+char162 "
+Po 574,705,15 2 0243 -- sterling
+char163 "
+Cs 574,605 0 0244 -- currency
+char164 "
+Ye 574,690 2 0245 -- yen
+char165 "
+bb 606,675,175 2 0246 -- brokenbar
+char166 "
+sc 500,737,86 2 0247 -- section
+char167 "
+ad 333,694 2 0250 -- dieresis
+char168 "
+co 747,737,15 2 0251 -- copyright
+char169 "
+Of 367,705 2 0252 -- ordfeminine
+char170 "
+fo 333,397 0 0253 -- guilsinglleft
+no 606,403 0 0254 -- logicalnot
+char172 "
+\- 606,307 0 0255 -- minus
+rg 747,737,15 2 0256 -- registered
+char174 "
+a- 333,664 0 0257 -- macron
+char175 "
+de 400,705 2 0260 -- degree
+char176 "
+char177 606,506 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,71 2 0266 -- paragraph
+char182 "
+pc 278,372 0 0267 -- periodcentered
+char183 "
+ac 333,0,224 1 0270 -- cedilla
+char184 "
+S1 344,705 2 0271 -- onesuperior
+char185 "
+Om 367,705 2 0272 -- ordmasculine
+char186 "
+fc 333,397 0 0273 -- guilsinglright
+14 861,705,15 2 0274 -- onequarter
+char188 "
+12 861,705,15 2 0275 -- onehalf
+char189 "
+34 861,705,15 2 0276 -- threequarters
+char190 "
+r? 500,547,205 1 0277 -- questiondown
+char191 "
+`A 759,964 2 0300 -- Agrave
+char192 "
+'A 759,964 2 0301 -- Aacute
+char193 "
+^A 759,952 2 0302 -- Acircumflex
+char194 "
+~A 759,932 2 0303 -- Atilde
+char195 "
+:A 759,921 2 0304 -- Adieresis
+char196 "
+oA 759,988 2 0305 -- Aring
+char197 "
+AE 981,722 2 0306 -- AE
+char198 "
+,C 778,737,224 3 0307 -- Ccedilla
+char199 "
+`E 759,964 2 0310 -- Egrave
+char200 "
+'E 759,964 2 0311 -- Eacute
+char201 "
+^E 759,952 2 0312 -- Ecircumflex
+char202 "
+:E 759,921 2 0313 -- Edieresis
+char203 "
+`I 444,964 2 0314 -- Igrave
+char204 "
+'I 444,964 2 0315 -- Iacute
+char205 "
+^I 444,952 2 0316 -- Icircumflex
+char206 "
+:I 444,921 2 0317 -- Idieresis
+char207 "
+-D 833,722 2 0320 -- Eth
+char208 "
+~N 833,932,10 2 0321 -- Ntilde
+char209 "
+`O 833,964,15 2 0322 -- Ograve
+char210 "
+'O 833,964,15 2 0323 -- Oacute
+char211 "
+^O 833,952,15 2 0324 -- Ocircumflex
+char212 "
+~O 833,932,15 2 0325 -- Otilde
+char213 "
+:O 833,921,15 2 0326 -- Odieresis
+char214 "
+char215 606,491 0 0327 -- multiply
+/O 833,775,53 2 0330 -- Oslash
+char216 "
+`U 833,964,15 2 0331 -- Ugrave
+char217 "
+'U 833,964,15 2 0332 -- Uacute
+char218 "
+^U 833,952,15 2 0333 -- Ucircumflex
+char219 "
+:U 833,921,15 2 0334 -- Udieresis
+char220 "
+'Y 722,964 2 0335 -- Yacute
+char221 "
+TP 759,722 2 0336 -- Thorn
+char222 "
+ss 611,737,15 2 0337 -- germandbls
+char223 "
+`a 611,737,15 2 0340 -- agrave
+char224 "
+'a 611,737,15 2 0341 -- aacute
+char225 "
+^a 611,725,15 2 0342 -- acircumflex
+char226 "
+~a 611,705,15 2 0343 -- atilde
+char227 "
+:a 611,694,15 2 0344 -- adieresis
+char228 "
+oa 611,761,15 2 0345 -- aring
+char229 "
+ae 870,485,15 0 0346 -- ae
+char230 "
+,c 556,485,224 1 0347 -- ccedilla
+char231 "
+`e 574,737,15 2 0350 -- egrave
+char232 "
+'e 574,737,15 2 0351 -- eacute
+char233 "
+^e 574,725,15 2 0352 -- ecircumflex
+char234 "
+:e 574,694,15 2 0353 -- edieresis
+char235 "
+`i 370,737 2 0354 -- igrave
+char236 "
+'i 370,737 2 0355 -- iacute
+char237 "
+^i 370,725 2 0356 -- icircumflex
+char238 "
+:i 370,694 2 0357 -- idieresis
+char239 "
+Sd 611,737,15 2 0360 -- eth
+char240 "
+~n 685,705 2 0361 -- ntilde
+char241 "
+`o 611,737,15 2 0362 -- ograve
+char242 "
+'o 611,737,15 2 0363 -- oacute
+char243 "
+^o 611,725,15 2 0364 -- ocircumflex
+char244 "
+~o 611,705,15 2 0365 -- otilde
+char245 "
+:o 611,694,15 2 0366 -- odieresis
+char246 "
+char247 606,546,40 0 0367 -- divide
+/o 611,573,103 0 0370 -- oslash
+char248 "
+`u 685,737,15 2 0371 -- ugrave
+char249 "
+'u 685,737,15 2 0372 -- uacute
+char250 "
+^u 685,725,15 2 0373 -- ucircumflex
+char251 "
+:u 685,694,15 2 0374 -- udieresis
+char252 "
+'y 611,737,205 3 0375 -- yacute
+char253 "
+Tp 667,737,205 3 0376 -- thorn
+char254 "
+:y 611,694,205 3 0377 -- ydieresis
+char255 "
diff --git a/contrib/groff/font/devps/NBI b/contrib/groff/font/devps/NBI
new file mode 100644
index 0000000..97e4f46
--- /dev/null
+++ b/contrib/groff/font/devps/NBI
@@ -0,0 +1,594 @@
+name NBI
+internalname NewCenturySchlbk-BoldItalic
+slant 16
+spacewidth 287
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -33
+A w -25
+A v -10
+A u -15
+A ' -95
+A cq -95
+A rq -95
+A Y -70
+A W -84
+A V -100
+A U -32
+A T 5
+A Q 5
+A O 5
+A G 5
+A C 5
+B . 15
+B , 15
+B U 15
+B A -11
+C A -5
+D . -11
+D , -11
+D Y 6
+D W -11
+D V -18
+F r -27
+F . -91
+F o -47
+F i -41
+F e -41
+F , -91
+F a -47
+F A -79
+J u -39
+J . -74
+J o -40
+J e -33
+J , -74
+J a -40
+J A -30
+K y -48
+K u -4
+K o -4
+K e 18
+L y -30
+L ' -100
+L cq -100
+L rq -100
+L Y -55
+L W -69
+L V -97
+L T -75
+N . -49
+N , -49
+O . -18
+O , -18
+O X -18
+O W -15
+O V -24
+O A -5
+P . -100
+P o -40
+P e -33
+P , -100
+P a -40
+P A -80
+R W -14
+R V -24
+S . -18
+S , -18
+T y -30
+T w -30
+T u -22
+T r -9
+T . -55
+T o -40
+T i -22
+T - -75
+T hy -75
+T char173 -75
+T h -9
+T e -33
+T , -55
+T a -40
+T O 11
+T A -60
+U . -25
+U , -25
+U A -42
+V u -70
+V ; 6
+V . -94
+V o -71
+V i -35
+V - -94
+V hy -94
+V char173 -94
+V e -66
+V , -94
+V : -49
+V a -55
+V O -19
+V G -12
+V A -100
+W y -41
+W u -25
+W ; -22
+W . -86
+W o -33
+W i -27
+W - -61
+W hy -61
+W char173 -61
+W h 5
+W e -39
+W , -86
+W : -22
+W a -33
+W O -11
+W A -66
+Y u -58
+Y ; -55
+Y . -91
+Y o -77
+Y i -22
+Y - -91
+Y hy -91
+Y char173 -91
+Y e -71
+Y , -91
+Y : -55
+Y a -77
+Y A -79
+a y -8
+a w -8
+a v 6
+b y -6
+b v 8
+b . 6
+b , 6
+c y -20
+c . -8
+c l -13
+c k -8
+c h -18
+c , -8
+, ' -18
+, cq -18
+, rq -18
+d y -15
+d w -15
+e y -15
+e x -5
+e w -15
+e p -11
+e g -4
+e b -8
+f ' 105
+f cq 105
+f rq 105
+f . -28
+f o 7
+f l 7
+f i 7
+f e 14
+f .i 7
+f , -28
+f a 8
+g y -11
+g r 11
+g . -5
+g , -5
+h y -20
+i v 7
+k y -15
+k o -22
+k e -16
+l y -7
+l w -7
+m y -20
+m u -11
+n y -20
+n v -7
+n u -11
+o y -11
+o w -8
+o v 6
+p y -4
+p . 8
+p , 8
+. ' -18
+. cq -18
+. rq -18
+lq ` 20
+lq oq 20
+lq A -60
+` A -80
+oq A -80
+' v -16
+cq v -16
+' t -22
+cq t -22
+' s -46
+cq s -46
+' r -9
+cq r -9
+' l -22
+cq l -22
+' d -41
+cq d -41
+r y -20
+r v -7
+r u -11
+r t -11
+r ; 9
+r s -20
+r ' 9
+r cq 9
+r . -90
+r p -17
+r o -11
+r l -14
+r k 9
+r i -14
+r - -16
+r hy -16
+r char173 -16
+r g -11
+r e -7
+r d -7
+r , -90
+r : 9
+r a -11
+s . 11
+s , 11
+v . -11
+v o -6
+v , -11
+v a -6
+w . -17
+w o -14
+w e -8
+w , -17
+w a -14
+x e 5
+y . -25
+y o 8
+y e 15
+y , -25
+y a 8
+z e 4
+charset
+ha 606,690,0,0,-16 2 0000 -- asciicircum
+ti 606,346,0,0,-22 0 0001 -- asciitilde
+vS 685,930,15,31,49,31 2 0002 -- Scaron
+vZ 704,930,0,57,83,57 2 0003 -- Zcaron
+vs 481,705,15,46,50,46 2 0004 -- scaron
+vz 519,695,15,4,69,4 2 0005 -- zcaron
+:Y 704,915,0,121,37,109 2 0006 -- Ydieresis
+tm 950,722,0,117,8,109 2 0007 -- trademark
+aq 287,737,0,13,-62,13 2 0010 -- quotesingle
+space 287 0 0040
+! 333,737,15,50,50,50 2 0041 -- exclam
+" 400,737,0,78,-16,78 2 0042 -- quotedbl
+dq "
+# 574,690,0,20,20,20 2 0043 -- numbersign
+sh "
+$ 574,810,120,41,41,41 2 0044 -- dollar
+Do "
+% 889,727,28,0,-4 2 0045 -- percent
+& 889,737,15,0,18 2 0046 -- ampersand
+' 259,737,0,66,2,66 2 0047 -- quoteright
+cq "
+( 407,745,117,97,-22,97 2 0050 -- parenleft
+) 407,745,117,0,120 2 0051 -- parenright
+* 500,737,0,48,-8,48 2 0052 -- asterisk
++ 606,506 0 0053 -- plus
+, 287,157,192,0,107 0 0054 -- comma
+- 333,299,0,0,48 0 0055 -- hyphen
+hy "
+char173 "
+. 287,157,15,0,70 0 0056 -- period
+/ 278,737,15,92,91,92 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,3,14,88,14 2 0062 -- two
+3 574,705,15,12,57,12 2 0063 -- three
+4 574,705,0,20,63,20 2 0064 -- four
+5 574,705,15,50,50,50 2 0065 -- five
+6 574,705,15,50,19,50 2 0066 -- six
+7 574,705,15,69,-14,69 2 0067 -- seven
+8 574,705,15,28,50,28 2 0070 -- eight
+9 574,705,15,19,50,19 2 0071 -- nine
+: 287,477,15,0,70 0 0072 -- colon
+; 287,477,192,0,107 0 0073 -- semicolon
+< 606,515,9 0 0074 -- less
+= 606,403 0 0075 -- equal
+> 606,514,8 0 0076 -- greater
+? 481,737,15,20,-29,20 2 0077 -- question
+@ 747,737,15,54,54,54 2 0100 -- at
+at "
+A 741,737,0,25,125,25 2 0101 -- A
+B 759,722,0,12,100,12 2 0102 -- B
+C 759,737,15,50,13,50 2 0103 -- C
+D 833,722,0,13,97,13 2 0104 -- D
+E 741,722,0,39,91,39 2 0105 -- E
+F 704,722,0,76,91,76 2 0106 -- F
+G 815,737,15,40,13,40 2 0107 -- G
+H 870,722,0,91,91,91 2 0110 -- H
+I 444,722,0,91,91,91 2 0111 -- I
+J 667,722,15,91,70,91 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,94,94 2 0115 -- M
+N 852,722,10,111,111,109 2 0116 -- N
+O 833,737,15,13,13,13 2 0117 -- O
+P 741,722,0,39,91,39 2 0120 -- P
+Q 833,737,189,13,13,13 2 0121 -- Q
+R 796,722,15,3,91,3 2 0122 -- R
+S 685,737,15,31,49,31 2 0123 -- S
+T 722,722,0,87,9,87 2 0124 -- T
+U 833,722,15,117,-38,109 2 0125 -- U
+V 741,722,10,111,18,109 2 0126 -- V
+W 944,722,10,106,10,106 2 0127 -- W
+X 741,722,0,110,132,109 2 0130 -- X
+Y 704,722,0,121,37,109 2 0131 -- Y
+Z 704,722,0,57,83,57 2 0132 -- Z
+[ 407,737,109,107,49,107 2 0133 -- bracketleft
+lB "
+\ 606,737,15,0,-111 2 0134 -- backslash
+rs "
+] 407,737,109,5,151,5 2 0135 -- bracketright
+rB "
+a^ 333,705,0,82,27,82 2 0136 -- circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 -- underscore
+` 259,737,0,65,3,65 2 0140 -- quoteleft
+oq "
+a 667,477,15,19,44,19 0 0141 -- a
+b 611,737,15,0,21 2 0142 -- b
+c 537,477,15,0,50 0 0143 -- c
+d 667,737,15,43,50,43 2 0144 -- d
+e 519,477,15,10,50,10 0 0145 -- e
+f 389,737,205,211,98,109 3 0146 -- f
+g 611,528,205,43,113,43 1 0147 -- g
+h 685,737,15,4,50,4 2 0150 -- h
+i 389,737,15,6,18,6 2 0151 -- i
+j 370,737,205,27,255,27 3 0152 -- j
+k 648,737,15,0,61 2 0153 -- k
+l 389,737,15,36,18,36 2 0154 -- l
+m 944,477,15,15,50,15 0 0155 -- m
+n 685,477,15,4,50,4 0 0156 -- n
+o 574,477,15,6,50,6 0 0157 -- o
+p 648,477,205,0,169 1 0160 -- p
+q 630,477,205,7,50,7 1 0161 -- q
+r 519,486,0,58,50,58 0 0162 -- r
+s 481,477,15,4,50,4 0 0163 -- s
+t 407,650,15,46,26,46 2 0164 -- t
+u 685,477,15,0,20 0 0165 -- u
+v 556,477,15,0,20 0 0166 -- v
+w 833,477,15,0,20 0 0167 -- w
+x 574,477,15,50,96,50 0 0170 -- x
+y 519,477,205,24,116,24 1 0171 -- y
+z 519,477,15,4,69,4 0 0172 -- z
+lC 407,737,109,51,-2,51 2 0173 -- braceleft
+{ "
+ba 606,750,250,0,-199 3 0174 -- bar
+| "
+rC 407,737,109,0,75 2 0175 -- braceright
+} "
+a~ 333,690,0,115,22,109 2 0176 -- tilde
+~ "
+bq 259,157,192,0,107 0 0200 -- quotesinglbase
+Fo 481,407,0,18,85,18 0 0201 -- guillemotleft
+char171 "
+Fc 481,407,0,22,81,22 0 0202 -- guillemotright
+char187 "
+bu 606,542,0,0,-72 0 0203 -- bullet
+Fn 574,737,205,51,93,51 3 0204 -- florin
+f/ 167,705,15,216,216,109 2 0205 -- fraction
+%0 1167,727,28,30,30,30 2 0206 -- perthousand
+dg 500,737,146,58,2,58 2 0207 -- dagger
+dd 500,737,150,58,110,58 2 0210 -- daggerdbl
+en 500,287,0,29,97,29 0 0211 -- endash
+em 1000,287,0,29,97,29 0 0212 -- emdash
+fi 685,737,205,6,120,6 3 0214 -- fi
+fl 685,737,205,36,120,36 3 0215 -- fl
+.i 389,477,15,6,18,6 0 0220 -- dotlessi
+ga 333,722,0,11,-24,11 2 0222 -- grave
+a" 333,722,0,197,35,109 2 0223 -- hungarumlaut
+a. 333,690,0,6,-95,6 2 0224 -- dotaccent
+ab 333,698,0,107,-17,107 2 0225 -- breve
+ah 333,705,0,120,-10,109 2 0226 -- caron
+ao 333,746,0,52,-61,52 2 0227 -- ring
+ho 333,0,155,0,-18 0 0230 -- ogonek
+lq 481,737,0,90,-4,90 2 0231 -- quotedblleft
+rq 481,737,0,79,7,79 2 0232 -- quotedblright
+oe 852,477,15,10,56,10 0 0233 -- oe
+/l 389,737,15,51,45,51 2 0234 -- lslash
+Bq 481,157,192,0,107 0 0235 -- quotedblbase
+OE 963,722,0,76,21,76 2 0236 -- OE
+/L 704,722,0,16,91,16 2 0237 -- Lslash
+r! 333,547,205,6,94,6 1 0241 -- exclamdown
+char161 "
+ct 574,578,144,0,20 0 0242 -- cent
+char162 "
+Po 574,705,15,42,68,42 2 0243 -- sterling
+char163 "
+Cs 574,605,0,23,23,23 0 0244 -- currency
+char164 "
+Ye 574,690,0,105,33,105 2 0245 -- yen
+char165 "
+bb 606,675,175,0,-199 2 0246 -- brokenbar
+char166 "
+sc 500,737,146,65,80,65 2 0247 -- section
+char167 "
+ad 333,690,0,110,17,109 2 0250 -- dieresis
+char168 "
+co 747,737,15,53,52,53 2 0251 -- copyright
+char169 "
+Of 412,705,0,98,3,98 2 0252 -- ordfeminine
+char170 "
+fo 278,407,0,16,75,16 0 0253 -- guilsinglleft
+no 606,403 0 0254 -- logicalnot
+char172 "
+\- 606,307 0 0255 -- minus
+rg 747,737,15,53,52,53 2 0256 -- registered
+char174 "
+a- 333,649,0,121,3,109 2 0257 -- macron
+char175 "
+de 400,705,0,22,-36,22 2 0260 -- degree
+char176 "
+char177 606,506 0 0261 -- plusminus
+S2 344,705,0,68,67,68 2 0262 -- twosuperior
+char178 "
+S3 344,705,0,67,47,67 2 0263 -- threesuperior
+char179 "
+aa 333,722,0,89,-73,89 2 0264 -- acute
+char180 "
+char181 685,477,205,0,139 1 0265 -- mu
+ps 650,722,131,81,25,81 2 0266 -- paragraph
+char182 "
+pc 287,372,0,0,-7 0 0267 -- periodcentered
+char183 "
+ac 333,3,220,0,71 1 0270 -- cedilla
+char184 "
+S1 344,705,0,32,31,32 2 0271 -- onesuperior
+char185 "
+Om 356,705,0,88,8,88 2 0272 -- ordmasculine
+char186 "
+fc 278,407,0,15,76,15 0 0273 -- guilsinglright
+14 861,705,15,0,33 2 0274 -- onequarter
+char188 "
+12 861,705,15,0,33 2 0275 -- onehalf
+char189 "
+34 861,705,15,0,15 2 0276 -- threequarters
+char190 "
+r? 481,547,205,0,50 1 0277 -- questiondown
+char191 "
+`A 741,947,0,25,125,25 2 0300 -- Agrave
+char192 "
+'A 741,947,0,25,125,25 2 0301 -- Aacute
+char193 "
+^A 741,930,0,25,125,25 2 0302 -- Acircumflex
+char194 "
+~A 741,915,0,25,125,25 2 0303 -- Atilde
+char195 "
+:A 741,915,0,25,125,25 2 0304 -- Adieresis
+char196 "
+oA 741,991,0,25,125,25 2 0305 -- Aring
+char197 "
+AE 889,722,0,76,136,76 2 0306 -- AE
+char198 "
+,C 759,737,220,50,13,50 3 0307 -- Ccedilla
+char199 "
+`E 741,947,0,39,91,39 2 0310 -- Egrave
+char200 "
+'E 741,947,0,39,91,39 2 0311 -- Eacute
+char201 "
+^E 741,930,0,39,91,39 2 0312 -- Ecircumflex
+char202 "
+:E 741,915,0,39,91,39 2 0313 -- Edieresis
+char203 "
+`I 444,947,0,91,91,91 2 0314 -- Igrave
+char204 "
+'I 444,947,0,94,91,94 2 0315 -- Iacute
+char205 "
+^I 444,930,0,91,91,91 2 0316 -- Icircumflex
+char206 "
+:I 444,915,0,115,91,109 2 0317 -- Idieresis
+char207 "
+-D 833,722,0,13,97,13 2 0320 -- Eth
+char208 "
+~N 852,915,10,111,111,109 2 0321 -- Ntilde
+char209 "
+`O 833,947,15,13,13,13 2 0322 -- Ograve
+char210 "
+'O 833,947,15,13,13,13 2 0323 -- Oacute
+char211 "
+^O 833,930,15,13,13,13 2 0324 -- Ocircumflex
+char212 "
+~O 833,915,15,13,13,13 2 0325 -- Otilde
+char213 "
+:O 833,915,15,13,13,13 2 0326 -- Odieresis
+char214 "
+char215 606,491,0,0,-15 0 0327 -- multiply
+/O 833,790,68,15,15,15 2 0330 -- Oslash
+char216 "
+`U 833,947,15,117,-38,109 2 0331 -- Ugrave
+char217 "
+'U 833,947,15,117,-38,109 2 0332 -- Uacute
+char218 "
+^U 833,930,15,117,-38,109 2 0333 -- Ucircumflex
+char219 "
+:U 833,915,15,117,-38,109 2 0334 -- Udieresis
+char220 "
+'Y 704,947,0,121,37,109 2 0335 -- Yacute
+char221 "
+TP 741,722,0,0,91 2 0336 -- Thorn
+char222 "
+ss 574,737,205,16,141,16 3 0337 -- germandbls
+char223 "
+`a 667,722,15,19,44,19 2 0340 -- agrave
+char224 "
+'a 667,722,15,19,44,19 2 0341 -- aacute
+char225 "
+^a 667,705,15,19,44,19 2 0342 -- acircumflex
+char226 "
+~a 667,690,15,19,44,19 2 0343 -- atilde
+char227 "
+:a 667,690,15,19,44,19 2 0344 -- adieresis
+char228 "
+oa 667,746,15,19,44,19 2 0345 -- aring
+char229 "
+ae 815,477,15,10,68,10 0 0346 -- ae
+char230 "
+,c 537,477,220,0,50 1 0347 -- ccedilla
+char231 "
+`e 519,722,15,10,50,10 2 0350 -- egrave
+char232 "
+'e 519,722,15,10,50,10 2 0351 -- eacute
+char233 "
+^e 519,705,15,10,50,10 2 0352 -- ecircumflex
+char234 "
+:e 519,690,15,17,50,17 2 0353 -- edieresis
+char235 "
+`i 389,715,15,6,18,6 2 0354 -- igrave
+char236 "
+'i 389,715,15,31,18,31 2 0355 -- iacute
+char237 "
+^i 389,698,15,24,29,24 2 0356 -- icircumflex
+char238 "
+:i 389,683,15,52,19,52 2 0357 -- idieresis
+char239 "
+Sd 574,752,15,6,50,6 2 0360 -- eth
+char240 "
+~n 685,690,15,4,50,4 2 0361 -- ntilde
+char241 "
+`o 574,722,15,6,50,6 2 0362 -- ograve
+char242 "
+'o 574,722,15,6,50,6 2 0363 -- oacute
+char243 "
+^o 574,705,15,6,50,6 2 0364 -- ocircumflex
+char244 "
+~o 574,690,15,6,50,6 2 0365 -- otilde
+char245 "
+:o 574,690,15,6,50,6 2 0366 -- odieresis
+char246 "
+char247 606,546,40 0 0367 -- divide
+/o 574,583,121,6,50,6 0 0370 -- oslash
+char248 "
+`u 685,722,15,0,20 2 0371 -- ugrave
+char249 "
+'u 685,722,15,0,20 2 0372 -- uacute
+char250 "
+^u 685,705,15,0,20 2 0373 -- ucircumflex
+char251 "
+:u 685,690,15,0,20 2 0374 -- udieresis
+char252 "
+'y 519,722,205,24,116,24 3 0375 -- yacute
+char253 "
+Tp 648,737,205,0,169 3 0376 -- thorn
+char254 "
+:y 519,690,205,24,116,24 3 0377 -- ydieresis
+char255 "
diff --git a/contrib/groff/font/devps/NI b/contrib/groff/font/devps/NI
new file mode 100644
index 0000000..af7c79f
--- /dev/null
+++ b/contrib/groff/font/devps/NI
@@ -0,0 +1,535 @@
+name NI
+internalname NewCenturySchlbk-Italic
+slant 16
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -55
+A w -18
+A v -18
+A u -18
+A ' -125
+A cq -125
+A rq -125
+A Y -55
+A W -74
+A V -74
+A U -37
+A T -30
+A Q -18
+A O -18
+A G -18
+A C -18
+B . -50
+B , -50
+C . -50
+C , -50
+D . -50
+D , -50
+D Y -18
+D W -18
+D V -18
+F r -55
+F . -125
+F o -55
+F i -10
+F e -55
+F , -125
+F a -55
+F A -35
+G . -50
+G , -50
+J u -18
+J . -100
+J o -37
+J e -37
+J , -100
+J a -37
+J A -18
+L y -50
+L ' -125
+L cq -125
+L rq -125
+L Y -100
+L W -100
+L V -100
+L T -100
+N . -60
+N , -60
+O . -50
+O , -50
+O Y -18
+O X -18
+O V -18
+O T 18
+P . -125
+P o -55
+P e -55
+P , -125
+P a -55
+P A -50
+Q . -20
+Q , -20
+R Y -18
+R W -18
+R V -18
+R U -18
+S . -50
+S , -50
+T y -50
+T w -50
+T u -50
+T ; -50
+T r -50
+T . -100
+T o -74
+T i -18
+T - -100
+T hy -100
+T char173 -100
+T h -25
+T e -74
+T , -100
+T : -50
+T a -74
+T O 18
+U . -100
+U , -100
+U A -18
+V u -75
+V ; -75
+V . -100
+V o -75
+V i -50
+V - -100
+V hy -100
+V char173 -100
+V e -75
+V , -100
+V : -75
+V a -75
+V A -37
+W y -55
+W u -55
+W ; -75
+W . -100
+W o -55
+W i -20
+W - -75
+W hy -75
+W char173 -75
+W h -20
+W e -55
+W , -100
+W : -75
+W a -55
+W A -55
+Y u -100
+Y ; -75
+Y . -100
+Y o -100
+Y i -25
+Y - -100
+Y hy -100
+Y char173 -100
+Y e -100
+Y , -100
+Y : -75
+Y a -100
+Y A -55
+b . -50
+b , -50
+b b -10
+c . -50
+c k -18
+c h -18
+c , -50
+, ' -37
+, cq -37
+, rq -37
+e . -37
+e , -37
+f ' 75
+f cq 75
+f rq 75
+f . -75
+f o -10
+f , -75
+g . -50
+g , -50
+l y -10
+o . -50
+o , -50
+p . -50
+p , -50
+. ' -37
+. cq -37
+. rq -37
+lq A -75
+` ` -37
+` oq -37
+oq ` -37
+oq oq -37
+` A -75
+oq A -75
+' s -25
+cq s -25
+' ' -37
+' cq -37
+cq ' -37
+cq cq -37
+' d -37
+cq d -37
+r ; -25
+r s -10
+r . -125
+r k -18
+r - -75
+r hy -75
+r char173 -75
+r , -125
+r : -25
+s . -50
+s , -50
+v . -75
+v , -75
+w . -75
+w , -75
+y . -75
+y , -75
+charset
+ha 606,690,0,0,-39 2 0000 -- asciicircum
+ti 606,322,0,0,-22 0 0001 -- asciitilde
+vS 667,946,15,21,56,21 2 0002 -- Scaron
+vZ 667,946,0,50,75,50 2 0003 -- Zcaron
+vs 444,690,15,40,48,40 2 0004 -- scaron
+vz 463,690,15,30,83,30 2 0005 -- zcaron
+:Y 685,902,0,125,19,107 2 0006 -- Ydieresis
+tm 950,722,0,68,18,68 2 0007 -- trademark
+aq 278,737,0,9,-101,9 2 0010 -- quotesingle
+space 278 0 0040
+! 333,737,15,20,33,20 2 0041 -- exclam
+" 400,737,0,13,-77,13 2 0042 -- quotedbl
+dq "
+# 556,690,0,22,22,22 2 0043 -- numbersign
+sh "
+$ 556,808,142,30,46,30 2 0044 -- dollar
+Do "
+% 833,705,15,7,7,7 2 0045 -- percent
+& 852,737,15,0,26 2 0046 -- ampersand
+' 204,737,0,75,11,75 2 0047 -- quoteright
+cq "
+( 333,745,117,128,-3,107 2 0050 -- parenleft
+) 333,745,117,0,143 2 0051 -- parenright
+* 500,737,0,50,-30,50 2 0052 -- asterisk
++ 606,506 0 0053 -- plus
+, 278,109,165,0,89 0 0054 -- comma
+- 333,274,0,0,18 0 0055 -- hyphen
+hy "
+char173 "
+. 278,109,15,0,33 0 0056 -- period
+/ 606,737,15,0,-82 2 0057 -- slash
+sl "
+0 556,705,15,20,20,20 2 0060 -- zero
+1 556,705 2 0061 -- one
+2 556,705,0,0,87 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,42,14,42 2 0066 -- six
+7 556,705,15,55,-19,55 2 0067 -- seven
+8 556,705,15,20,44,20 2 0070 -- eight
+9 556,705,15,14,42,14 2 0071 -- nine
+: 278,466,15,1,33,1 0 0072 -- colon
+; 278,466,165,1,89,1 0 0073 -- semicolon
+< 606,514,8,0,14 0 0074 -- less
+= 606,389 0 0075 -- equal
+> 606,514,8,14,-14,14 0 0076 -- greater
+? 444,737,15,23,-52,23 2 0077 -- question
+@ 747,737,15,53,52,53 2 0100 -- at
+at "
+A 704,737,0,14,137,14 2 0101 -- A
+B 722,722,0,0,83 2 0102 -- B
+C 722,737,15,40,10,40 2 0103 -- C
+D 778,722,0,10,83,10 2 0104 -- D
+E 722,722,0,28,83,28 2 0105 -- E
+F 667,722,0,83,83,83 2 0106 -- F
+G 778,737,15,35,10,35 2 0107 -- G
+H 833,722,0,83,83,83 2 0110 -- H
+I 407,722,0,78,83,78 2 0111 -- I
+J 611,722,15,90,64,90 2 0112 -- J
+K 741,722,0,125,83,107 2 0113 -- K
+L 667,722,0,10,83,10 2 0114 -- L
+M 944,722,0,83,83,83 2 0115 -- M
+N 815,722,15,101,101,101 2 0116 -- N
+O 778,737,15,10,10,10 2 0117 -- O
+P 667,722,0,50,83,50 2 0120 -- P
+Q 778,737,190,10,10,10 2 0121 -- Q
+R 741,722,15,1,95,1 2 0122 -- R
+S 667,737,15,21,56,21 2 0123 -- S
+T 685,722,0,90,10,90 2 0124 -- T
+U 815,722,15,102,-43,102 2 0125 -- U
+V 704,722,10,125,14,107 2 0126 -- V
+W 926,722,10,102,-3,102 2 0127 -- W
+X 704,722,0,125,125,107 2 0130 -- X
+Y 685,722,0,125,19,107 2 0131 -- Y
+Z 667,722,0,50,75,50 2 0132 -- Z
+[ 333,737,109,105,105,105 2 0133 -- bracketleft
+lB "
+\ 606,737,15,0,-82 2 0134 -- backslash
+rs "
+] 333,737,109,83,127,83 2 0135 -- bracketright
+rB "
+a^ 333,690,0,48,13,48 2 0136 -- circumflex
+^ "
+_ 500,0,125,50,50,50 0 0137 -- underscore
+` 204,737,0,75,11,75 2 0140 -- quoteleft
+oq "
+a 574,466,15,0,48 0 0141 -- a
+b 556,737,15,0,18 2 0142 -- b
+c 444,466,15,0,48 0 0143 -- c
+d 611,737,15,24,48,24 2 0144 -- d
+e 444,466,15,0,56 0 0145 -- e
+f 333,737,205,187,118,107 3 0146 -- f
+g 537,497,205,36,129,36 1 0147 -- g
+h 611,737,15,1,36,1 2 0150 -- h
+i 333,715,15,0,21 2 0151 -- i
+j 315,715,205,53,216,53 3 0152 -- j
+k 556,737,15,0,50 2 0153 -- k
+l 333,737,15,9,36,9 2 0154 -- l
+m 889,466,15,1,36,1 0 0155 -- m
+n 611,466,15,1,36,1 0 0156 -- n
+o 500,466,15,0,48 0 0157 -- o
+p 574,466,205,0,151 1 0160 -- p
+q 556,466,205,0,48 1 0161 -- q
+r 444,466,0,40,40,40 0 0162 -- r
+s 444,466,15,0,48 0 0163 -- s
+t 352,619,15,26,26,26 2 0164 -- t
+u 611,466,15,0,6 0 0165 -- u
+v 519,466,15,0,19 0 0166 -- v
+w 778,466,15,0,19 0 0167 -- w
+x 500,466,15,21,83,21 0 0170 -- x
+y 500,466,205,0,133 1 0171 -- y
+z 463,466,15,3,83,3 0 0172 -- z
+lC 333,737,109,111,12,107 2 0173 -- braceleft
+{ "
+ba 606,750,250,0,-217 3 0174 -- bar
+| "
+rC 333,737,109,0,137 2 0175 -- braceright
+} "
+a~ 333,649,0,100,-2,100 2 0176 -- tilde
+~ "
+bq 204,109,165,0,128 0 0200 -- quotesinglbase
+Fo 426,402,0,26,65,26 0 0201 -- guillemotleft
+char171 "
+Fc 426,402,0,26,65,26 0 0202 -- guillemotright
+char187 "
+bu 606,542,0,0,-72 0 0203 -- bullet
+Fn 556,737,205,63,108,63 3 0204 -- florin
+f/ 167,705,15,184,184,107 2 0205 -- fraction
+%0 1000,705,15,44,44,44 2 0206 -- perthousand
+dg 500,737,147,56,-1,56 2 0207 -- dagger
+dd 500,737,147,56,104,56 2 0210 -- daggerdbl
+en 500,268,0,37,77,37 0 0211 -- endash
+em 1000,268,0,37,77,37 0 0212 -- emdash
+fi 611,737,205,0,118 3 0214 -- fi
+fl 611,737,205,26,118,26 3 0215 -- fl
+.i 333,466,15,0,21 0 0220 -- dotlessi
+ga 333,690,0,0,-21 2 0222 -- grave
+a" 333,690,0,172,18,107 2 0223 -- hungarumlaut
+a. 333,646,0,0,-96 2 0224 -- dotaccent
+ab 333,677,0,87,-19,87 2 0225 -- breve
+ah 333,690,0,95,-23,95 2 0226 -- caron
+ao 333,712,0,31,-64,31 2 0227 -- ring
+ho 333,0,215,0,-18 1 0230 -- ogonek
+lq 389,737,0,67,11,67 2 0231 -- quotedblleft
+rq 389,737,0,67,11,67 2 0232 -- quotedblright
+oe 778,466,15,0,48 0 0233 -- oe
+/l 333,737,15,57,75,57 2 0234 -- lslash
+Bq 389,109,165,0,128 0 0235 -- quotedblbase
+OE 981,722,0,44,10,44 2 0236 -- OE
+/L 667,722,0,10,83,10 2 0237 -- Lslash
+r! 333,547,205,0,72 1 0241 -- exclamdown
+char161 "
+ct 556,580,144,0,-12 0 0242 -- cent
+char162 "
+Po 556,705,15,38,63,38 2 0243 -- sterling
+char163 "
+Cs 556,597,0,24,24,24 0 0244 -- currency
+char164 "
+Ye 556,690,0,118,10,107 2 0245 -- yen
+char165 "
+bb 606,675,175,0,-217 2 0246 -- brokenbar
+char166 "
+sc 500,737,147,30,60,30 2 0247 -- section
+char167 "
+ad 333,646,0,76,-9,76 2 0250 -- dieresis
+char168 "
+co 747,737,15,53,52,53 2 0251 -- copyright
+char169 "
+Of 422,705,0,48,-22,48 2 0252 -- ordfeminine
+char170 "
+fo 333,402,0,0,10 0 0253 -- guilsinglleft
+no 606,389 0 0254 -- logicalnot
+char172 "
+\- 606,289 0 0255 -- minus
+rg 747,737,15,53,52,53 2 0256 -- registered
+char174 "
+a- 333,610,0,80,-2,80 0 0257 -- macron
+char175 "
+de 400,705,0,22,-36,22 2 0260 -- degree
+char176 "
+char177 606,506 0 0261 -- plusminus
+S2 333,705,0,76,50,76 2 0262 -- twosuperior
+char178 "
+S3 333,705,0,76,28,76 2 0263 -- threesuperior
+char179 "
+aa 333,690,0,72,-82,72 2 0264 -- acute
+char180 "
+char181 611,466,205,0,110 1 0265 -- mu
+ps 650,722,132,65,2,65 2 0266 -- paragraph
+char182 "
+pc 278,374,0,0,-21 0 0267 -- periodcentered
+char183 "
+ac 333,0,215,0,47 1 0270 -- cedilla
+char184 "
+S1 333,705,0,28,16,28 2 0271 -- onesuperior
+char185 "
+Om 372,705,0,48,-16,48 2 0272 -- ordmasculine
+char186 "
+fc 333,402,0,0,10 0 0273 -- guilsinglright
+14 834,705,15,0,16 2 0274 -- onequarter
+char188 "
+12 834,705,15,0,16 2 0275 -- onehalf
+char189 "
+34 834,705,15,0,28 2 0276 -- threequarters
+char190 "
+r? 444,547,205,0,53 1 0277 -- questiondown
+char191 "
+`A 704,946,0,14,137,14 2 0300 -- Agrave
+char192 "
+'A 704,946,0,14,137,14 2 0301 -- Aacute
+char193 "
+^A 704,946,0,14,137,14 2 0302 -- Acircumflex
+char194 "
+~A 704,905,0,14,137,14 2 0303 -- Atilde
+char195 "
+:A 704,902,0,14,137,14 2 0304 -- Adieresis
+char196 "
+oA 704,958,0,14,137,14 2 0305 -- Aring
+char197 "
+AE 870,722,0,68,137,68 2 0306 -- AE
+char198 "
+,C 722,737,215,40,10,40 3 0307 -- Ccedilla
+char199 "
+`E 722,946,0,28,83,28 2 0310 -- Egrave
+char200 "
+'E 722,946,0,28,83,28 2 0311 -- Eacute
+char201 "
+^E 722,946,0,28,83,28 2 0312 -- Ecircumflex
+char202 "
+:E 722,902,0,28,83,28 2 0313 -- Edieresis
+char203 "
+`I 407,946,0,78,83,78 2 0314 -- Igrave
+char204 "
+'I 407,946,0,95,83,95 2 0315 -- Iacute
+char205 "
+^I 407,946,0,78,83,78 2 0316 -- Icircumflex
+char206 "
+:I 407,902,0,99,83,99 2 0317 -- Idieresis
+char207 "
+-D 778,722,0,10,83,10 2 0320 -- Eth
+char208 "
+~N 815,905,15,101,101,101 2 0321 -- Ntilde
+char209 "
+`O 778,946,15,10,10,10 2 0322 -- Ograve
+char210 "
+'O 778,946,15,10,10,10 2 0323 -- Oacute
+char211 "
+^O 778,946,15,10,10,10 2 0324 -- Ocircumflex
+char212 "
+~O 778,905,15,10,10,10 2 0325 -- Otilde
+char213 "
+:O 778,902,15,10,10,10 2 0326 -- Odieresis
+char214 "
+char215 606,482,0,0,-24 0 0327 -- multiply
+/O 778,780,68,20,34,20 2 0330 -- Oslash
+char216 "
+`U 815,946,15,102,-43,102 2 0331 -- Ugrave
+char217 "
+'U 815,946,15,102,-43,102 2 0332 -- Uacute
+char218 "
+^U 815,946,15,102,-43,102 2 0333 -- Ucircumflex
+char219 "
+:U 815,902,15,102,-43,102 2 0334 -- Udieresis
+char220 "
+'Y 685,946,0,125,19,107 2 0335 -- Yacute
+char221 "
+TP 667,722,0,10,83,10 2 0336 -- Thorn
+char222 "
+ss 556,737,205,19,126,19 3 0337 -- germandbls
+char223 "
+`a 574,690,15,0,48 2 0340 -- agrave
+char224 "
+'a 574,690,15,0,48 2 0341 -- aacute
+char225 "
+^a 574,690,15,0,48 2 0342 -- acircumflex
+char226 "
+~a 574,649,15,0,48 2 0343 -- atilde
+char227 "
+:a 574,646,15,0,48 2 0344 -- adieresis
+char228 "
+oa 574,712,15,0,48 2 0345 -- aring
+char229 "
+ae 722,466,15,0,68 0 0346 -- ae
+char230 "
+,c 444,466,215,0,48 1 0347 -- ccedilla
+char231 "
+`e 444,690,15,0,56 2 0350 -- egrave
+char232 "
+'e 444,690,15,17,56,17 2 0351 -- eacute
+char233 "
+^e 444,690,15,0,56 2 0352 -- ecircumflex
+char234 "
+:e 444,646,15,21,56,21 2 0353 -- edieresis
+char235 "
+`i 333,690,15,0,21 2 0354 -- igrave
+char236 "
+'i 333,690,15,72,21,72 2 0355 -- iacute
+char237 "
+^i 333,690,15,48,21,48 2 0356 -- icircumflex
+char238 "
+:i 333,646,15,76,21,76 2 0357 -- idieresis
+char239 "
+Sd 500,737,15,0,48 2 0360 -- eth
+char240 "
+~n 611,649,15,1,36,1 2 0361 -- ntilde
+char241 "
+`o 500,690,15,0,48 2 0362 -- ograve
+char242 "
+'o 500,690,15,0,48 2 0363 -- oacute
+char243 "
+^o 500,690,15,0,48 2 0364 -- ocircumflex
+char244 "
+~o 500,649,15,17,48,17 2 0365 -- otilde
+char245 "
+:o 500,646,15,0,48 2 0366 -- odieresis
+char246 "
+char247 606,528,22 0 0367 -- divide
+/o 500,549,121,0,48 0 0370 -- oslash
+char248 "
+`u 611,690,15,0,6 2 0371 -- ugrave
+char249 "
+'u 611,690,15,0,6 2 0372 -- uacute
+char250 "
+^u 611,690,15,0,6 2 0373 -- ucircumflex
+char251 "
+:u 611,646,15,0,6 2 0374 -- udieresis
+char252 "
+'y 500,690,205,0,133 3 0375 -- yacute
+char253 "
+Tp 574,737,205,0,151 3 0376 -- thorn
+char254 "
+:y 500,646,205,0,133 3 0377 -- ydieresis
+char255 "
diff --git a/contrib/groff/font/devps/NR b/contrib/groff/font/devps/NR
new file mode 100644
index 0000000..b111f5d
--- /dev/null
+++ b/contrib/groff/font/devps/NR
@@ -0,0 +1,522 @@
+name NR
+internalname NewCenturySchlbk-Roman
+spacewidth 278
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A y -37
+A w -25
+A v -37
+A ' -74
+A cq -74
+A rq -74
+A Y -75
+A W -50
+A V -75
+A U -30
+A T -18
+B . -37
+B , -37
+B A -18
+C . -37
+C , -37
+C A -18
+D . -37
+D , -37
+D Y -18
+D V -18
+F r -10
+F . -125
+F o -55
+F i -10
+F e -55
+F , -125
+F a -65
+F A -50
+G . -37
+G , -37
+J u -25
+J . -74
+J o -25
+J e -25
+J , -74
+J a -25
+J A -18
+K y -25
+K o 10
+K e 10
+L y -25
+L ' -100
+L cq -100
+L rq -100
+L Y -74
+L W -74
+L V -91
+L T -75
+N . -55
+N , -55
+O . -37
+O , -37
+O Y -18
+O V -18
+O T 10
+P . -125
+P o -37
+P e -37
+P , -125
+P a -37
+P A -55
+Q . -25
+Q , -25
+S . -37
+S , -37
+T ; -37
+T . -125
+T o -55
+T - -100
+T hy -100
+T char173 -100
+T e -55
+T , -125
+T : -37
+T a -55
+T O 10
+T A -18
+U . -100
+U , -100
+U A -30
+V u -75
+V ; -75
+V . -125
+V o -75
+V i -18
+V - -100
+V hy -100
+V char173 -100
+V e -75
+V , -125
+V : -75
+V a -85
+V O -18
+V A -74
+W y -55
+W u -55
+W ; -100
+W . -125
+W o -60
+W i -18
+W - -100
+W hy -100
+W char173 -100
+W e -60
+W , -125
+W : -100
+W a -75
+W A -50
+Y u -91
+Y ; -75
+Y . -100
+Y o -100
+Y i -18
+Y - -125
+Y hy -125
+Y char173 -125
+Y e -100
+Y , -100
+Y : -75
+Y a -100
+Y O -18
+Y A -75
+a y -10
+a w -10
+a v -10
+b . -18
+b , -18
+c . -18
+c l -7
+c k -7
+c h -7
+c , -18
+, ' -37
+, cq -37
+, rq -37
+e . -18
+e , -18
+f ' 100
+f cq 100
+f rq 100
+f . -37
+f , -37
+g . -25
+g , -25
+o . -18
+o , -18
+p . -18
+p , -18
+. ' -37
+. cq -37
+. rq -37
+lq A -74
+` ` -25
+` oq -25
+oq ` -25
+oq oq -25
+` A -74
+oq A -74
+' s -25
+cq s -25
+' ' -25
+' cq -25
+cq ' -25
+cq cq -25
+' d -37
+cq d -37
+r . -100
+r - -37
+r hy -37
+r char173 -37
+r , -100
+s . -25
+s , -25
+v . -125
+v , -125
+w . -125
+w , -125
+w a -18
+y . -125
+y , -125
+charset
+ha 606,690 2 0000 -- asciicircum
+ti 606,322 0 0001 -- asciitilde
+vS 630,933,15 2 0002 -- Scaron
+vZ 611,933 2 0003 -- Zcaron
+vs 463,695,15 2 0004 -- scaron
+vz 481,695 2 0005 -- zcaron
+:Y 704,883 2 0006 -- Ydieresis
+tm 1000,722 2 0007 -- trademark
+aq 204,737 2 0010 -- quotesingle
+space 278 0 0040
+! 296,737,15 2 0041 -- exclam
+" 389,737 2 0042 -- quotedbl
+dq "
+# 556,690 2 0043 -- numbersign
+sh "
+$ 556,813,138 2 0044 -- dollar
+Do "
+% 833,705,15 2 0045 -- percent
+& 815,737,15 2 0046 -- ampersand
+' 204,737 2 0047 -- quoteright
+cq "
+( 333,745,117 2 0050 -- parenleft
+) 333,745,117 2 0051 -- parenright
+* 500,737 2 0052 -- asterisk
++ 606,506 0 0053 -- plus
+, 278,109,185 0 0054 -- comma
+- 333,277 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 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,474,15 0 0072 -- colon
+; 278,474,185 0 0073 -- semicolon
+< 606,514,8 0 0074 -- less
+= 606,389 0 0075 -- equal
+> 606,514,8 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,190 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,10 2 0126 -- V
+W 981,722,10 2 0127 -- W
+X 704,722 2 0130 -- X
+Y 704,722 2 0131 -- Y
+Z 611,722 2 0132 -- Z
+[ 333,737,109 2 0133 -- bracketleft
+lB "
+\ 606,737,15 2 0134 -- backslash
+rs "
+] 333,737,109 2 0135 -- bracketright
+rB "
+a^ 333,695 2 0136 -- circumflex
+^ "
+_ 500,0,125 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,722 2 0151 -- i
+j 296,722,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,10 0 0166 -- v
+w 778,464,10 0 0167 -- w
+x 537,464 0 0170 -- x
+y 537,464,205 1 0171 -- y
+z 481,464 0 0172 -- z
+lC 333,737,109 2 0173 -- braceleft
+{ "
+ba 606,750,250 3 0174 -- bar
+| "
+rC 333,737,109 2 0175 -- braceright
+} "
+a~ 333,655 0 0176 -- tilde
+~ "
+bq 204,109,185 0 0200 -- quotesinglbase
+Fo 426,398 0 0201 -- guillemotleft
+char171 "
+Fc 426,398 0 0202 -- guillemotright
+char187 "
+bu 606,542 0 0203 -- bullet
+Fn 556,737,205 3 0204 -- florin
+f/ 167,705,15 2 0205 -- fraction
+%0 1000,705,15 2 0206 -- perthousand
+dg 500,737,147 2 0207 -- dagger
+dd 500,737,149 2 0210 -- daggerdbl
+en 556,268 0 0211 -- endash
+em 1000,268 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,699 2 0223 -- hungarumlaut
+a. 333,645 0 0224 -- dotaccent
+ab 333,685 2 0225 -- breve
+ah 333,695 2 0226 -- caron
+ao 333,722 2 0227 -- ring
+ho 333,0,215 1 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,109,185 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,597 0 0244 -- currency
+char164 "
+Ye 556,690 2 0245 -- yen
+char165 "
+bb 606,675,175 2 0246 -- brokenbar
+char166 "
+sc 500,737,147 2 0247 -- section
+char167 "
+ad 333,645 0 0250 -- dieresis
+char168 "
+co 737,737,15 2 0251 -- copyright
+char169 "
+Of 334,705 2 0252 -- ordfeminine
+char170 "
+fo 259,398 0 0253 -- guilsinglleft
+no 606,389 0 0254 -- logicalnot
+char172 "
+\- 606,289 0 0255 -- minus
+rg 737,737,15 2 0256 -- registered
+char174 "
+a- 333,623 0 0257 -- macron
+char175 "
+de 400,705 2 0260 -- degree
+char176 "
+char177 606,506 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,132 2 0266 -- paragraph
+char182 "
+pc 278,374 0 0267 -- periodcentered
+char183 "
+ac 333,0,215 1 0270 -- cedilla
+char184 "
+S1 333,705 2 0271 -- onesuperior
+char185 "
+Om 300,705 2 0272 -- ordmasculine
+char186 "
+fc 259,398 0 0273 -- guilsinglright
+14 834,705,15 2 0274 -- onequarter
+char188 "
+12 834,705,15 2 0275 -- onehalf
+char189 "
+34 834,705,15 2 0276 -- threequarters
+char190 "
+r? 444,547,205 1 0277 -- questiondown
+char191 "
+`A 722,937 2 0300 -- Agrave
+char192 "
+'A 722,937 2 0301 -- Aacute
+char193 "
+^A 722,933 2 0302 -- Acircumflex
+char194 "
+~A 722,893 2 0303 -- Atilde
+char195 "
+:A 722,883 2 0304 -- Adieresis
+char196 "
+oA 722,965 2 0305 -- Aring
+char197 "
+AE 1000,722 2 0306 -- AE
+char198 "
+,C 722,737,215 3 0307 -- Ccedilla
+char199 "
+`E 722,937 2 0310 -- Egrave
+char200 "
+'E 722,937 2 0311 -- Eacute
+char201 "
+^E 722,933 2 0312 -- Ecircumflex
+char202 "
+:E 722,883 2 0313 -- Edieresis
+char203 "
+`I 407,937 2 0314 -- Igrave
+char204 "
+'I 407,937 2 0315 -- Iacute
+char205 "
+^I 407,933 2 0316 -- Icircumflex
+char206 "
+:I 407,883 2 0317 -- Idieresis
+char207 "
+-D 778,722 2 0320 -- Eth
+char208 "
+~N 815,893,15 2 0321 -- Ntilde
+char209 "
+`O 778,937,15 2 0322 -- Ograve
+char210 "
+'O 778,937,15 2 0323 -- Oacute
+char211 "
+^O 778,933,15 2 0324 -- Ocircumflex
+char212 "
+~O 778,893,15 2 0325 -- Otilde
+char213 "
+:O 778,883,15 2 0326 -- Odieresis
+char214 "
+char215 606,482 0 0327 -- multiply
+/O 778,778,56 2 0330 -- Oslash
+char216 "
+`U 815,937,15 2 0331 -- Ugrave
+char217 "
+'U 815,937,15 2 0332 -- Uacute
+char218 "
+^U 815,933,15 2 0333 -- Ucircumflex
+char219 "
+:U 815,883,15 2 0334 -- Udieresis
+char220 "
+'Y 704,937 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,695,15 2 0342 -- acircumflex
+char226 "
+~a 556,655,15 0 0343 -- atilde
+char227 "
+:a 556,645,15 0 0344 -- adieresis
+char228 "
+oa 556,732,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,695,15 2 0352 -- ecircumflex
+char234 "
+:e 500,645,15 0 0353 -- edieresis
+char235 "
+`i 315,699 2 0354 -- igrave
+char236 "
+'i 315,699 2 0355 -- iacute
+char237 "
+^i 315,695 2 0356 -- icircumflex
+char238 "
+:i 315,645 0 0357 -- idieresis
+char239 "
+Sd 500,752,15 2 0360 -- eth
+char240 "
+~n 611,655 0 0361 -- ntilde
+char241 "
+`o 500,699,15 2 0362 -- ograve
+char242 "
+'o 500,699,15 2 0363 -- oacute
+char243 "
+^o 500,695,15 2 0364 -- ocircumflex
+char244 "
+~o 500,655,15 0 0365 -- otilde
+char245 "
+:o 500,645,15 0 0366 -- odieresis
+char246 "
+char247 606,528,22 0 0367 -- divide
+/o 500,561,97 0 0370 -- oslash
+char248 "
+`u 611,699,15 2 0371 -- ugrave
+char249 "
+'u 611,699,15 2 0372 -- uacute
+char250 "
+^u 611,695,15 2 0373 -- ucircumflex
+char251 "
+:u 611,645,15 0 0374 -- udieresis
+char252 "
+'y 537,699,205 3 0375 -- yacute
+char253 "
+Tp 574,737,205 3 0376 -- thorn
+char254 "
+:y 537,645,205 1 0377 -- ydieresis
+char255 "
diff --git a/contrib/groff/font/devps/PB b/contrib/groff/font/devps/PB
new file mode 100644
index 0000000..0f327d3
--- /dev/null
+++ b/contrib/groff/font/devps/PB
@@ -0,0 +1,461 @@
+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 cq -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 cq -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 cq 37
+f f -18
+1 1 -37
+` ` -55
+` oq -55
+oq ` -55
+oq oq -55
+' t -18
+cq t -18
+' s -55
+cq s -55
+' ' -55
+' cq -55
+cq ' -55
+cq cq -55
+r ' 55
+r cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,335 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/PBI b/contrib/groff/font/devps/PBI
new file mode 100644
index 0000000..7ec5ff3
--- /dev/null
+++ b/contrib/groff/font/devps/PBI
@@ -0,0 +1,463 @@
+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 cq -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 cq -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 cq 37
+f f -37
+1 1 -55
+` ` -55
+` oq -55
+oq ` -55
+oq oq -55
+' t -18
+cq t -18
+' s -37
+cq s -37
+' ' -55
+' cq -55
+cq ' -55
+cq cq -55
+r ' 55
+r cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,324,0,6,-17,6 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/PI b/contrib/groff/font/devps/PI
new file mode 100644
index 0000000..d35c7f8
--- /dev/null
+++ b/contrib/groff/font/devps/PI
@@ -0,0 +1,465 @@
+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 cq -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 cq -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
+f cq 55
+1 1 -55
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+' t -37
+cq t -37
+' s -55
+cq s -55
+' ' -74
+' cq -74
+cq ' -74
+cq cq -74
+r ' 37
+r cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,312,0,0,-3 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/PR b/contrib/groff/font/devps/PR
new file mode 100644
index 0000000..2eccf3c
--- /dev/null
+++ b/contrib/groff/font/devps/PR
@@ -0,0 +1,466 @@
+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 cq -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 cq -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 cq 55
+f f -18
+1 1 -55
+` ` -37
+` oq -37
+oq ` -37
+oq oq -37
+' ' -37
+' cq -37
+cq ' -37
+cq cq -37
+r u -8
+r ' 74
+r cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,319 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/S b/contrib/groff/font/devps/S
new file mode 100644
index 0000000..3cf77d9
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/SS b/contrib/groff/font/devps/SS
new file mode 100644
index 0000000..933eb1c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/TB b/contrib/groff/font/devps/TB
new file mode 100644
index 0000000..4d1fc8c
--- /dev/null
+++ b/contrib/groff/font/devps/TB
@@ -0,0 +1,548 @@
+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 cq -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 cq -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
+, cq -55
+, rq -45
+d w -15
+e v -15
+f ' 55
+f cq 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
+. cq -55
+. rq -55
+lq A -10
+` ` -63
+` oq -63
+oq ` -63
+oq oq -63
+` A -10
+oq A -10
+' v -20
+cq v -20
+' s -37
+cq s -37
+' r -20
+cq r -20
+' ' -63
+' cq -63
+cq ' -63
+cq cq -63
+' d -20
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,417 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/TBI b/contrib/groff/font/devps/TBI
new file mode 100644
index 0000000..a79efb7
--- /dev/null
+++ b/contrib/groff/font/devps/TBI
@@ -0,0 +1,531 @@
+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 cq -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 cq -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
+, cq -95
+, rq -95
+e b -10
+f ' 55
+f cq 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
+. cq -95
+. rq -95
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+' v -15
+cq v -15
+' t -37
+cq t -37
+' s -74
+cq s -74
+' r -15
+cq r -15
+' ' -74
+' cq -74
+cq ' -74
+cq cq -74
+' d -15
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,405,0,0,-1 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/TI b/contrib/groff/font/devps/TI
new file mode 100644
index 0000000..992089d
--- /dev/null
+++ b/contrib/groff/font/devps/TI
@@ -0,0 +1,544 @@
+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 cq -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 cq -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
+, cq -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 cq 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
+. cq -140
+. rq -140
+` ` -111
+` oq -111
+oq ` -111
+oq oq -111
+' v -10
+cq v -10
+' t -30
+cq t -30
+' s -40
+cq s -40
+' r -25
+cq r -25
+' ' -111
+' cq -111
+cq ' -111
+cq cq -111
+' d -25
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,310,0,0,-20 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/TR b/contrib/groff/font/devps/TR
new file mode 100644
index 0000000..6b98075
--- /dev/null
+++ b/contrib/groff/font/devps/TR
@@ -0,0 +1,536 @@
+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 cq -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 cq -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
+, cq -70
+, rq -70
+e y -15
+e x -15
+e w -25
+e v -25
+e g -15
+f ' 55
+f cq 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
+. cq -70
+. rq -70
+lq A -80
+` ` -74
+` oq -74
+oq ` -74
+oq oq -74
+` A -80
+oq A -80
+' v -50
+cq v -50
+' t -18
+cq t -18
+' s -55
+cq s -55
+' r -50
+cq r -50
+' ' -74
+' cq -74
+cq ' -74
+cq cq -74
+' l -10
+cq l -10
+' d -50
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 250,310 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/ZCMI b/contrib/groff/font/devps/ZCMI
new file mode 100644
index 0000000..e25c2a6
--- /dev/null
+++ b/contrib/groff/font/devps/ZCMI
@@ -0,0 +1,494 @@
+name ZCMI
+internalname ZapfChancery-MediumItalic
+slant 14
+spacewidth 220
+encoding text.enc
+ligatures fi fl 0
+kernpairs
+A ' -40
+A cq -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 cq -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
+, cq -70
+, rq -70
+d w -20
+d v -10
+d d -40
+e y 10
+f ' 30
+f cq 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
+. cq -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
+cq v 30
+' t 20
+cq t 20
+' s -25
+cq s -25
+' r 30
+cq r 30
+' ' -115
+' cq -115
+cq ' -115
+cq cq -115
+' rq 20
+cq rq 20
+' l 20
+cq 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
+dq "
+# 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
+cq "
+( 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 "
+pc 220,310,0,71,-89,71 0 0267 -- periodcentered
+char183 "
+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/contrib/groff/font/devps/ZD b/contrib/groff/font/devps/ZD
new file mode 100644
index 0000000..3066c39
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/ZDR b/contrib/groff/font/devps/ZDR
new file mode 100644
index 0000000..ab5b54f
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/download b/contrib/groff/font/devps/download
new file mode 100644
index 0000000..b98885c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/generate/Makefile b/contrib/groff/font/devps/generate/Makefile
new file mode 100644
index 0000000..897385f
--- /dev/null
+++ b/contrib/groff/font/devps/generate/Makefile
@@ -0,0 +1,227 @@
+# 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.
+
+# This is set up so you can do
+# make -f generate/Makefile
+# in the parent directory of this directory.
+
+# The following line is required for DOS/Windows systems, since
+# this Makefile needs a Unixy shell to run.
+SHELL = /bin/sh
+
+# 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/lib/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
+AFMNAME=$(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)/dingbats.map $@
+
+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)/dingbats.rmap $@
+
+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)/dingbats.map
+ZDR: $(srcdir)/dingbats.rmap
+$(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/contrib/groff/font/devps/generate/afmname b/contrib/groff/font/devps/generate/afmname
new file mode 100755
index 0000000..3e837df
--- /dev/null
+++ b/contrib/groff/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 '
+/^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/contrib/groff/font/devps/generate/dingbats.map b/contrib/groff/font/devps/generate/dingbats.map
new file mode 100644
index 0000000..3a97fa9
--- /dev/null
+++ b/contrib/groff/font/devps/generate/dingbats.map
@@ -0,0 +1,2 @@
+a19 OK
+a12 rh
diff --git a/contrib/groff/font/devps/generate/dingbats.rmap b/contrib/groff/font/devps/generate/dingbats.rmap
new file mode 100644
index 0000000..ccc14cb
--- /dev/null
+++ b/contrib/groff/font/devps/generate/dingbats.rmap
@@ -0,0 +1 @@
+a12 lh
diff --git a/contrib/groff/font/devps/generate/lgreekmap b/contrib/groff/font/devps/generate/lgreekmap
new file mode 100644
index 0000000..0b0c197
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/generate/symbol.sed b/contrib/groff/font/devps/generate/symbol.sed
new file mode 100644
index 0000000..b4b02ab
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/generate/symbolchars b/contrib/groff/font/devps/generate/symbolchars
new file mode 100644
index 0000000..41ec3e4
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/generate/symbolsl.afm b/contrib/groff/font/devps/generate/symbolsl.afm
new file mode 100644
index 0000000..90939ad
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/generate/textmap b/contrib/groff/font/devps/generate/textmap
new file mode 100644
index 0000000..5b5e0ea
--- /dev/null
+++ b/contrib/groff/font/devps/generate/textmap
@@ -0,0 +1,453 @@
+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 .
+periodcentered pc
+perthousand %0
+perpendicular pp
+plus +
+plusmath pl
+propersubset sb
+propersuperset sp
+proportional pt
+question ?
+questiondown r?
+quotedbl "
+quotedbl dq
+quotedblbase Bq
+quotedblleft lq
+quotedblright rq
+quoteleft `
+quoteleft oq
+quoteright '
+quoteright cq
+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/contrib/groff/font/devps/prologue.ps b/contrib/groff/font/devps/prologue.ps
new file mode 100644
index 0000000..b7bad1c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/psstrip.sed b/contrib/groff/font/devps/psstrip.sed
new file mode 100644
index 0000000..3e61775
--- /dev/null
+++ b/contrib/groff/font/devps/psstrip.sed
@@ -0,0 +1,7 @@
+/^%[%!]/b
+s/%.*//
+s/^[ ][ ]*//
+s/[ ][ ]*$//
+/^$/d
+s|[ ]*\([][}{/]\)|\1|g
+s|\([][}{/]\)[ ]*|\1|g
diff --git a/contrib/groff/font/devps/symbol.afm b/contrib/groff/font/devps/symbol.afm
new file mode 100644
index 0000000..33cba6a
--- /dev/null
+++ b/contrib/groff/font/devps/symbol.afm
@@ -0,0 +1,212 @@
+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/contrib/groff/font/devps/symbolmap b/contrib/groff/font/devps/symbolmap
new file mode 100644
index 0000000..03d6e70
--- /dev/null
+++ b/contrib/groff/font/devps/symbolmap
@@ -0,0 +1,513 @@
+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 .
+periodcentered pc
+perthousand %0
+perpendicular pp
+plus +
+plusmath pl
+propersubset sb
+propersuperset sp
+proportional pt
+question ?
+questiondown r?
+quotedbl "
+quotedbl dq
+quotedblbase Bq
+quotedblleft lq
+quotedblright rq
+quoteleft `
+quoteleft oq
+quoteright '
+quoteright cq
+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/contrib/groff/font/devps/symbolsl.ps b/contrib/groff/font/devps/symbolsl.ps
new file mode 100644
index 0000000..d384203
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/text.enc b/contrib/groff/font/devps/text.enc
new file mode 100644
index 0000000..dde5bb7
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/zapfdr.afm b/contrib/groff/font/devps/zapfdr.afm
new file mode 100644
index 0000000..ce216de
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devps/zapfdr.ps b/contrib/groff/font/devps/zapfdr.ps
new file mode 100644
index 0000000..8283be2
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devutf8/DESC.proto b/contrib/groff/font/devutf8/DESC.proto
new file mode 100644
index 0000000..88399ab
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devutf8/Makefile.sub b/contrib/groff/font/devutf8/Makefile.sub
new file mode 100644
index 0000000..f6ce659
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/font/devutf8/NOTES b/contrib/groff/font/devutf8/NOTES
new file mode 100644
index 0000000..ba597af
--- /dev/null
+++ b/contrib/groff/font/devutf8/NOTES
@@ -0,0 +1,75 @@
+The following from the original troff manual (by Ossanna and Kernighan) is
+unmapped:
+
+ \(bs shaded solid ball (Bell System logo, AT&T logo)
+
+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, 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
+
+\(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
+
+The following lines could be added, to define names which are known to e.g.
+"devdvi" but are not known to "devps".
+<< 24 0 0x226A
+>> 24 0 0x226B
+
+"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.
+
+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/<version>/font/devutf8/.
+
+- In your source file, use the notation \N'8364' where 8364 is the decimal
+ representation of 0x20AC.
diff --git a/contrib/groff/font/devutf8/R.proto b/contrib/groff/font/devutf8/R.proto
new file mode 100644
index 0000000..7715ed4
--- /dev/null
+++ b/contrib/groff/font/devutf8/R.proto
@@ -0,0 +1,473 @@
+name R
+internalname 0
+spacewidth 24
+charset
+! 24 0 0x0021
+" 24 0 0x0022
+dq "
+# 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 "
+shc 24 0 0x00AD
+char173 "
+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 "
+pc 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
+cq "
+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
+pc 24 0 0x22C5
+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/contrib/groff/gendef.sh b/contrib/groff/gendef.sh
index de32279..4853eef 100644
--- a/contrib/groff/gendef.sh
+++ b/contrib/groff/gendef.sh
@@ -1,4 +1,8 @@
-# gendef filename var=val var=val
+#
+# gendef filename var=val var=val ...
+#
+# This script is used to generate src/include/defs.h
+#
file=$1
shift
@@ -26,3 +30,5 @@ test -r $file && cmp -s $t $file || cp $t $file
rm -f $t
exit 0
+
+# eof
diff --git a/contrib/groff/man/groff.man b/contrib/groff/man/groff.man
index 73c9188..d69330d 100644
--- a/contrib/groff/man/groff.man
+++ b/contrib/groff/man/groff.man
@@ -24,7 +24,7 @@ FDL in the main directory of the groff source package.
.\" --------------------------------------------------------------------
.
.if n \{\
-. mso tmac.tty-char
+. mso tty-char.tmac
. ftr CR R
. ftr CI I
. ftr CB B
@@ -542,7 +542,14 @@ Groff provides a printable representation with the
escape sequence.
.TP
.character \(dq
-The double quote is used to enclose arguments in requests and macros.
+The double quote is used to enclose arguments in requests and macros. In
+the
+.request .ds
+and
+.request .as
+requests, a leading double quote in the argument will be stripped off,
+making everything else afterwards the string to be defined (enabling leading
+whitespace).
The escaped double quote
.esc \(dq
introduces a comment.
@@ -866,7 +873,7 @@ to
.argument stringvar .
.
.REQ .asciify diversion
-Unformat special ASCII characters in
+Unformat ASCII characters, spaces, and some escape sequences in
.argument diversion .
.
.REQ .backtrace
@@ -885,6 +892,21 @@ Embolden Special Font
when current font is
.argument font .
.
+.REQ .box
+End current diversion.
+.
+.REQ .box macro
+Divert to
+.argument macro ,
+omitting a partially filled line.
+.
+.REQ .boxa
+End current diversion.
+.
+.REQ .boxa macro
+Divert and append to
+.argument macro ,
+omitting a partially filled line.
.REQ .bp
Eject current page and begin new page.
.
@@ -985,6 +1007,9 @@ Continuous underline in nroff, like
.request .ul
in troff.
.
+.REQ .da
+End current diversion.
+.
.REQ .da macro
Divert and append to
.argument macro .
@@ -1003,6 +1028,21 @@ until
.request .end
is called.
.
+.REQ .dei macro
+Define or redefine a macro whose name is contained in the string register
+.argument macro
+until
+.request ..
+is called.
+.
+.REQ .dei macro end
+Define or redefine a macro indirectly.
+.argument macro
+and
+.argument end
+are string registers whose contents are interpolated for the macro name
+and the end macro, respectively.
+.
.REQ .di
End current diversion.
.
@@ -1035,6 +1075,13 @@ Reset escape character to
Set escape character to
.argument c .
.
+.REQ .ecr
+Restore escape character saved with
+.request .ecs .
+.
+.REQ .ecs
+Save current escape character.
+.
.REQ .el anything
Else part for if-else (\c
.argument .ie )
@@ -1065,6 +1112,9 @@ No pushing or popping.
.REQ .ex
Exit from roff processing.
.
+.REQ .fam
+Return to previous font family.
+.
.REQ .fam name
Set the current font family to
.argument name .
@@ -1235,6 +1285,15 @@ Write the length of the string
in
.argument register .
.
+.REQ .linetabs
+Enable line-tabs mode (i.e., calculate tab positions relative to output
+line).
+.
+.REQ .linetabs n
+If
+.argument n
+is zero, disable line-tabs mode, otherwise enable it.
+.
.REQ .lf N file
Set input line number to
.argument N
@@ -1293,7 +1352,7 @@ Mark current vertical position in
.REQ .mso file
The same as the .so request except that
.I file
-is also searched in the tmac directories.
+is searched in the tmac directories.
.
.REQ .na
No output-line adjusting.
@@ -1327,6 +1386,10 @@ Do not number next
.argument N
lines.
.
+.REQ .nop anything
+Always execute
+.argument anything .
+.
.REQ .nr register \(+-N M
Define or modify
.argument register
@@ -1440,6 +1503,9 @@ Remove the definitions of characters
.REQ .rd prompt
Read insertion.
.
+.REQ .return
+Return from a macro.
+.
.REQ .rj n
Right justify the next
.argument n
@@ -1595,15 +1661,25 @@ Enable track kerning for
.REQ .tl \f(CB\(cq\fPleft\f(CB\(cq\fPcenter\f(CB\(cq\fPright\f(CB\(cq\fP
Three-part title.
.
-.REQ .trf filename
-Transparently output the contents of file
-.argument filename .
-.
.REQ .tm anything
Print
.argument anything
on terminal (UNIX standard message output).
.
+.REQ .tm1 anything
+Print
+.argument anything
+on terminal (UNIX standard message output), allowing leading whitespace if
+.argument anything
+starts with
+.character \(dq
+(which will be stripped off).
+.
+.REQ .tmc anything
+Similar to
+.request .tm1
+without emitting a final newline.
+.
.REQ .tr abcd....
Translate
.argument a
@@ -1614,6 +1690,10 @@ to
.argument d ,
etc. on output.
.
+.REQ .trf filename
+Transparently output the contents of file
+.argument filename .
+.
.REQ .trnt abcd....
This is the same as the
.request .tr
@@ -1639,6 +1719,9 @@ Underline (italicize in troff)
.argument N
input lines.
.
+.REQ .unformat diversion
+Unformat space characters and tabs, preserving font information in
+.argument diversion .
.REQ .vpt n
Enable vertical position traps if
.argument n
@@ -1891,6 +1974,11 @@ preceding character is a roman character.
Unbreakable space that stretches like a normal inter-word space when a
line is adjusted.
.
+.ESC :
+Inserts a zero-width break point (similar to
+.esc %
+but without a soft hyphen character).
+.
.ESC \& newline
Ignored newline, for continuation lines.
.
@@ -1922,15 +2010,25 @@ Non-interpreted leader character.
.ESCq A anything
If
.argument anything
-acceptable as name of a string, macro, diversion, register,
-environment or font it is
-.number 1
-otherwise
-.number 0 .
+is acceptable as a name of a string, macro, diversion, register,
+environment or font it expands to
+.number 1 ,
+and
+.number 0
+otherwise.
.
.ESCq b abc...
Bracket building function.
.
+.ESCq B anything
+If
+.argument anything
+is acceptable as a valid numeric expression it expands to
+.number 1 ,
+and
+.number 0
+otherwise.
+.
.ESC c
Interrupt text processing.
.
@@ -2220,6 +2318,9 @@ from request calls.
.LP
.PD 0
.REG .$ Number of arguments in the current macro.
+.REG .a
+Post-line extra line-space most recently utilized using
+.escarg x 'N' .
.REG .A
Set to
.number 1
@@ -2231,19 +2332,8 @@ is used; always
.number 1
in
.BR nroff .
-.REG .H Available horizontal resolution in basic units.
-.REG .T
-Set to
-.number 1
-if option
-.B \-T
-is used.
-.REG .V Available vertical resolution in basic units.
-.REG .a
-Post-line extra line-space most recently utilized using
-.escarg x 'N' .
-.REG .C 1 if compatibility mode is in effect, 0 otherwise.
.REG .c Current input line number.
+.REG .C 1 if compatibility mode is in effect, 0 otherwise.
.REG .cdp
The depth of the last character added to the current environment.
It is positive if the character extends below the baseline.
@@ -2269,6 +2359,7 @@ Current vertical place in current diversion; equal to register
Always 1 in GNU troff.
Macros should use it to test if running under groff.
.REG .h Text base-line high-water mark on current page or diversion.
+.REG .H Available horizontal resolution in basic units.
.REG .hla
The current hyphenation language as set by the
.B .hla
@@ -2294,6 +2385,9 @@ The current hyphenation space (as set by the
request).
.REG .i Current ident.
.REG .in The indent that applies to the current output line.
+.REG .int
+Positive if last output line contains
+.esc c .
.REG .kern
.number 1
if pairwise kerning is enabled,
@@ -2304,6 +2398,10 @@ otherwise.
The current ligature mode (as set by the
.request .lg
request).
+.REG .linetabs
+The current line-tabs mode (as set by the
+.request .linetabs
+request).
.REG .ll The line length that applies to the current output line.
.REG .lt
The title length (as set by the
@@ -2331,6 +2429,12 @@ The number of lines to be right-justified as set by the rj request.
The last requested pointsize in points as a decimal fraction
(string-valued).
.REG .t Distance to the next trap.
+.REG .T
+Set to
+.number 1
+if option
+.B \-T
+is used.
.REG .tabs
A string representation of the current tab settings suitable for use as
an argument to the
@@ -2359,6 +2463,7 @@ The value of the parameters set by the second argument of the
request.
.REG .u Equal to 1 bin fill mode and 0 in nofill mode.
.REG .v Current vertical line spacing.
+.REG .V Available vertical resolution in basic units.
.REG .vpt
.number 1
if vertical position traps are enabled,
@@ -2371,6 +2476,25 @@ The sum of the number codes of the currently enabled warnings.
.REG .y The minor version number.
.REG .Y The revision number of groff.
.REG .z Name of current diversion.
+.PD
+.
+.\" --------------------------------------------------------------------
+.SS "WRITABLE REGISTERS"
+.\" --------------------------------------------------------------------
+The following registers can be read and written by the user.
+They have predefined default values, but these can be modified for
+customizing a document.
+.LP
+.PD 0
+.REG % Current page number.
+.REG c. Current input line number.
+.REG ct Character type (set by width function
+.esc w ).
+.REG dl Maximal width of last completed diversion.
+.REG dn Height of last completed diversion.
+.REG dw Current day of week (1-7).
+.REG dy Current day of month (1-31).
+.REG hp Current horizontal position at input line.
.REG llx
Lower left x-coordinate (in PostScript units) of a given PostScript
image (set by
@@ -2379,6 +2503,9 @@ image (set by
Lower left y-coordinate (in PostScript units) of a given PostScript
image (set by
.request .psbb ).
+.REG ln Output line number.
+.REG mo Current month (1-12).
+.REG nl Vertical position of last printed text base-line.
.REG rsb Like
.register sb ,
but takes account of the heights and depths of characters.
@@ -2393,6 +2520,10 @@ Depth of string below base line (generated by width function
Right skip width from the center of the last character in the
.esc w
argument.
+.REG slimit
+If greater than 0, the maximum number of objects on the input stack.
+If \(<=0 there is no limit, i.e., recursion can continue until virtual
+memory is exhausted.
.REG ssc
The amount of horizontal space (possibly negative) that should be added
to the last character before a subscript (generated by width function
@@ -2400,6 +2531,12 @@ to the last character before a subscript (generated by width function
.REG st
Height of string above base line (generated by width function
.esc w ).
+.REG systat
+The return value of the
+.I system()
+function executed by the last
+.request .sy
+request.
.REG urx
Upper right x-coordinate (in PostScript units) of a given PostScript
image (set by
@@ -2408,37 +2545,6 @@ image (set by
Upper right y-coordinate (in PostScript units) of a given PostScript
image (set by
.request .psbb ).
-.PD
-.
-.\" --------------------------------------------------------------------
-.SS "WRITABLE REGISTERS"
-.\" --------------------------------------------------------------------
-The following registers can be read and written by the user.
-They have predefined default values, but these can be modified for
-customizing a document.
-.LP
-.PD 0
-.REG % Current page number.
-.REG c. Current input line number.
-.REG ct Character type (set by width function
-.esc w ).
-.REG dl Maximal width of last completed diversion.
-.REG dw Current day of week (1-7).
-.REG dy Current day of month (1-31).
-.REG hp Current horizontal position at input line.
-.REG ln Output line number.
-.REG mo Current month (1-12).
-.REG nl Vertical position of last printed text base-line.
-.REG slimit
-If greater than 0, the maximum number of objects on the input stack.
-If \(<=0 there is no limit, i.e., recursion can continue until virtual
-memory is exhausted.
-.REG systat
-The return value of the
-.I system()
-function executed by the last
-.request .sy
-request.
.REG year The current year (year 2000 compliant).
.REG yr
Current year minus 1900. For Y2K compliance use register
diff --git a/contrib/groff/man/groff_char.man b/contrib/groff/man/groff_char.man
index fd9f4ce..1a2de90 100644
--- a/contrib/groff/man/groff_char.man
+++ b/contrib/groff/man/groff_char.man
@@ -132,7 +132,7 @@ a larger glyph can be obtained with
\&\\$3\t\\*(CH\t\\$2\t\\$4\t\\$5
.\}
..
-.wh \n(nlu+\n(.tu-\n(.Vu Fo
+.if !\n[cR] .wh \n(nlu+\n(.tu-\n(.Vu Fo
.de Fo
'bp
.He
@@ -290,12 +290,14 @@ Output Input Input PostScript Notes
.C2 'I Iacute
.C2 'O Oacute
.C2 'U Uacute
+.C2 'Y Yacute
.C2 'a aacute
.C2 'c cacute
.C2 'e eacute
.C2 'i iacute
.C2 'o oacute
.C2 'u uacute
+.C2 'y yacute
.C2 :A Adieresis
.C2 :E Edieresis
.C2 :I Idieresis
diff --git a/contrib/groff/man/groff_font.man b/contrib/groff/man/groff_font.man
index 8b9e3b4..9700e6a 100644
--- a/contrib/groff/man/groff_font.man
+++ b/contrib/groff/man/groff_font.man
@@ -1,5 +1,5 @@
.ig \"-*- nroff -*-
-Copyright (C) 1989-1995 Free Software Foundation, Inc.
+Copyright (C) 1989-1995, 2001 Free Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -87,6 +87,16 @@ for fonts whose point size is
.I n
scaled points.
.TP
+.BI prepro\ program
+Call
+.I program
+as a preprocessor.
+.TP
+.BI postpro\ program
+Use
+.I program
+as the postprocessor.
+.TP
.B tcommand
This means that the postprocessor can handle the
.B t
@@ -143,6 +153,18 @@ This is achieved by another tcommand:
.B charset
This line and everything following in the file are ignored.
It is allowed for the sake of backwards compatibility.
+.TP
+.BI print\ program
+Use
+.I program
+as the spooler program for printing.
+If omitted, the
+.B \-l
+and
+.B \-L
+options of
+.B groff
+are ignored.
.LP
The res, unitwidth, fonts and sizes lines are compulsory.
Other commands are ignored by
@@ -250,7 +272,7 @@ otherwise it corresponds to the groff input character
(if it is exactly two characters
.I xx
it can be entered as
-.BI \e( xx\fR.)
+.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
diff --git a/contrib/groff/man/roff.man b/contrib/groff/man/roff.man
index 793ce61..0ed8a37 100644
--- a/contrib/groff/man/roff.man
+++ b/contrib/groff/man/roff.man
@@ -1,4 +1,4 @@
-.\" -*- nroff -*-
+.\" t -*- nroff -*-
.ig
roff.7
@@ -24,7 +24,7 @@ FDL in the main directory of the groff source package.
.\" --------------------------------------------------------------------
.
.if n \{\
-. mso tmac.tty-char
+. mso tty-char.tmac
. ftr CR R
. ftr CI I
. ftr CB B
@@ -70,6 +70,12 @@ FDL in the main directory of the groff source package.
. rm @tmp@
..
.
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.
.\" --------------------------------------------------------------------
.\" Title
.\" --------------------------------------------------------------------
@@ -276,8 +282,10 @@ Macro packages are collections of macros that are suitable to format a
special kind of documents in a convenient way.
This greatly eases the usage of roff.
The macro definitions of a package are kept in a file called
-.BI tmac. name
-where
+.IB name .tmac
+(or
+.BI tmac. name\c
+) where
.I name
is the internal roff name for this package.
All tmac files are stored in a single or few directories at standard
@@ -294,7 +302,7 @@ or
.argname name .
General details on the naming of macro packages and their placement is
found in
-.BR tmac (@MAN5EXT@).
+.BR groff_tmac (@MAN5EXT@).
.LP
Famous classical macro packages are
.IR man ,
@@ -371,7 +379,7 @@ in all flavors of the Emacs editor.
.B GROFF_TMAC_PATH
A colon separated list of directories in which to search for
macro files, see
-.BR tmac (@MAN5EXT@).
+.BR groff_tmac (@MAN5EXT@).
.TP
.SM
.B GROFF_TYPESETTER
@@ -383,38 +391,52 @@ 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
+will first search in directories given with the
.option \-F
-option before these, and in standard directories
-.RB ( .:/usr/local/share/groff/font:/usr/lib/font )
-after these.
+command line option, then in
+.BR GROFF_FONT_PATH ,
+and finally in the standard directories
+.RB ( @FONTPATH@ ).
.\" --------------------------------------------------------------------
.SH FILES
.\" --------------------------------------------------------------------
By default,
.I groff
-installs all of its library files in a directory tree under
-.IR /usr/local/share/groff .
-This location might vary for different systems.
-In the following, this directory is referred to as
-.IR <groff_dir> .
-.LP
+installs all of its data files in subdirectories of
+.I @FONTDIR@
+and in
+.I @MACRODIR@
+(except wrapper files for system-specific macro packages which will be
+in
+.IR @SYSTEMMACRODIR@ ).
+These locations might vary for different systems.
+In the following, the former is referred to as
+.IR <groff_font_dir> ,
+the latter as
+.IR <groff_macro_dir> .
.TP
-.IB <groff_dir> /tmac/troffrc
+.IB <groff_macro_dir> /troffrc
Initialization file for troff.
.TP
-.IB <groff_dir> /tmac/tmac. name
+.IB <groff_macro_dir> / name .tmac
+.TQ
+.IB <groff_macro_dir> /tmac. name
Macro files.
.TP
-.IB <groff_dir> /font/dev name /DESC
+.IB <groff_font_dir> /dev name /DESC
Device description file for device
.IR name .
.TP
-.IB <groff_dir> /font/dev name / F
+.IB <groff_font_dir> /dev name / F
Font file for font
.I F
of device
.IR name .
+.LP
+Finally, a local macro directory
+.I @LOCALMACRODIR@
+is provided for site-specific macros and packages; by default, it will be
+searched before the main macro directory.
.\" --------------------------------------------------------------------
.SH BUGS
.\" --------------------------------------------------------------------
@@ -482,9 +504,8 @@ The man pages for macro packages include
.BR groff_me (@MAN7EXT@),
.BR groff_mm (@MAN7EXT@),
.BR groff_mmroff (@MAN7EXT@),
-.BR groff_ms (@MAN7EXT@),
and
-.BR groff_msafer (@MAN7EXT@).
+.BR groff_ms (@MAN7EXT@).
.LP
The following utilities are available:
.BR addftinfo (@MAN1EXT@),
diff --git a/contrib/groff/src/devices/grodvi/Makefile.sub b/contrib/groff/src/devices/grodvi/Makefile.sub
new file mode 100644
index 0000000..0e5d32c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grodvi/dvi.cc b/contrib/groff/src/devices/grodvi/dvi.cc
new file mode 100644
index 0000000..74422f8
--- /dev/null
+++ b/contrib/groff/src/devices/grodvi/dvi.cc
@@ -0,0 +1,912 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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 "nonposix.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, char type);
+ 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, char type)
+{
+ if (type != 'p')
+ return;
+ 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(FILE *stream);
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((c = getopt_long(argc, argv, "F:vw:d", long_options, NULL)) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU grodvi (groff) version %s\n", Version_string);
+ exit(0);
+ 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 CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ default:
+ assert(0);
+ }
+#ifdef SET_BINARY
+ SET_BINARY(fileno(stdout));
+#endif
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-dv] [-F dir] [-w n] [files ...]\n",
+ program_name);
+}
diff --git a/contrib/groff/src/devices/grodvi/grodvi.man b/contrib/groff/src/devices/grodvi/grodvi.man
new file mode 100644
index 0000000..7aa4431
--- /dev/null
+++ b/contrib/groff/src/devices/grodvi/grodvi.man
@@ -0,0 +1,174 @@
+.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 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 \|.\|.\|.
+]
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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@/dvi.tmac ;
+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
+Prepend directory
+.IB dir /devdvi
+to the search path for font and device description files.
+.SH FILES
+.TP
+.B @FONTDIR@/devdvi/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devdvi/ F
+Font description file for font
+.IR F .
+.TP
+.B @MACRODIR@/dvi.tmac
+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
+.BR 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 groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/contrib/groff/src/devices/grohtml/Makefile.sub b/contrib/groff/src/devices/grohtml/Makefile.sub
new file mode 100644
index 0000000..2c3a55a
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/Makefile.sub
@@ -0,0 +1,16 @@
+PROG=post-grohtml
+MAN1=grohtml.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=\
+ post-html.o \
+ html-text.o \
+ output.o
+CCSRCS=\
+ $(srcdir)/post-html.cc \
+ $(srcdir)/html-text.cc \
+ $(srcdir)/output.cc
+HDRS=\
+ $(srcdir)/html.h \
+ $(srcdir)/html-chars.h \
+ $(srcdir)/html-text.h
diff --git a/contrib/groff/src/devices/grohtml/grohtml.man b/contrib/groff/src/devices/grohtml/grohtml.man
new file mode 100644
index 0000000..8796d8f
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/grohtml.man
@@ -0,0 +1,137 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1999-2000, 2001 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
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBgrohtml 'u
+.ti \niu
+.B grohtml
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-v?lrn
+.OP \-F dir
+.OP \-i resolution
+.OP \-o image vertical offset
+.RI "[\ " files\|.\|.\|. "\ ]"
+.br
+.ad \na
+.SH DESCRIPTION
+.B grohtml
+translates the output of GNU
+.B troff
+to html.
+Users should always invoke
+.B grohtml
+via 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
+.BR groff 's
+.B \-P
+option.
+.SH OPTIONS
+.TP
+.B \-v
+Displays the version.
+.TP
+.B \-?
+Emits a usage synopsis.
+.TP
+.B -l
+Turns off the production of automatic section links at the top of the document.
+.TP
+.B -r
+Turns off the automatic header and footer line (html rule).
+.TP
+.B -n
+Generate simple heading anchors whenever a section/number heading is found.
+Without the option the anchor value is the textual heading. This can cause problems
+when a heading contains a `?' on some brousers (netscape).
+This flag is automatically turned on if a heading contains an image.
+.TP
+.BI \-F dir
+Prepend directory
+.IB dir /dev name
+to the search path for font and device description files;
+.I name
+is the name of the device, usually
+.BR html .
+.TP
+.BI \-i resolution
+select the resolution for all images.
+By default this is 80 pixels per inch.
+Example: -i100 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.
+.SH DEPENDENCIES
+.B grohtml
+is dependent upon the png utilities and gs.
+Images are generated whenever a table, picture, equation or line is
+encountered.
+.SH BUGS
+.B Grohtml
+has been completely redesigned and rewritten.
+It is still alpha code.
+.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/contrib/groff/src/devices/grohtml/html-chars.h b/contrib/groff/src/devices/grohtml/html-chars.h
new file mode 100644
index 0000000..f58f8dc
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/html-chars.h
@@ -0,0 +1,27 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 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/contrib/groff/src/devices/grohtml/html-text.cc b/contrib/groff/src/devices/grohtml/html-text.cc
new file mode 100644
index 0000000..0b63aa0
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/html-text.cc
@@ -0,0 +1,829 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cc
+ *
+ * html-text.cc
+ *
+ * provide a troff like state machine interface which
+ * generates html text.
+ */
+
+/*
+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"
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+
+#include "html-text.h"
+
+
+html_text::html_text (simple_output *op) :
+ stackptr(NULL), lastptr(NULL), out(op), space_emitted(TRUE),
+ current_indentation(-1), pageoffset(-1), linelength(-1)
+{
+}
+
+html_text::~html_text ()
+{
+ flush_text();
+}
+
+/*
+ * end_tag - shuts down the tag.
+ */
+
+void html_text::end_tag (tag_definition *t)
+{
+ switch (t->type) {
+
+ case I_TAG: out->put_string("</i>"); break;
+ case B_TAG: out->put_string("</b>"); break;
+ case P_TAG: out->put_string("</p>").nl().enable_newlines(FALSE); break;
+ case SUB_TAG: out->put_string("</sub>"); break;
+ case SUP_TAG: out->put_string("</sup>"); break;
+ case TT_TAG: out->put_string("</tt>"); break;
+ case PRE_TAG: out->put_string("</pre>");
+ if (! is_present(TABLE_TAG)) {
+ out->nl();
+ out->enable_newlines(TRUE);
+ }
+ break;
+ case SMALL_TAG: out->put_string("</small>"); break;
+ case BIG_TAG: out->put_string("</big>"); break;
+ case TABLE_TAG: issue_table_end(); break;
+
+ default:
+ error("unrecognised tag");
+ }
+}
+
+/*
+ * issue_tag - writes out an html tag with argument.
+ */
+
+void html_text::issue_tag (char *tagname, char *arg)
+{
+ if ((arg == 0) || (strlen(arg) == 0)) {
+ out->put_string(tagname);
+ out->put_string(">");
+ } else {
+ out->put_string(tagname);
+ out->put_string(" ");
+ out->put_string(arg);
+ out->put_string(">");
+ }
+}
+
+/*
+ * start_tag - starts a tag.
+ */
+
+void html_text::start_tag (tag_definition *t)
+{
+ switch (t->type) {
+
+ case I_TAG: issue_tag("<i", t->arg1); break;
+ case B_TAG: issue_tag("<b", t->arg1); break;
+ case P_TAG: issue_tag("\n<p", t->arg1);
+ out->enable_newlines(TRUE); break;
+ case SUB_TAG: issue_tag("<sub", t->arg1); break;
+ case SUP_TAG: issue_tag("<sup", t->arg1); break;
+ case TT_TAG: issue_tag("<tt", t->arg1); break;
+ case PRE_TAG: out->nl(); issue_tag("<pre", t->arg1);
+ out->enable_newlines(FALSE); break;
+ case SMALL_TAG: issue_tag("<small", t->arg1); break;
+ case BIG_TAG: issue_tag("<big", t->arg1); break;
+ case TABLE_TAG: issue_table_begin(t); break;
+ case BREAK_TAG: break;
+
+ default:
+ error("unrecognised tag");
+ }
+}
+
+int html_text::table_is_void (tag_definition *t)
+{
+ if (linelength > 0) {
+ return( current_indentation*100/linelength <= 0 );
+ } else {
+ return( FALSE );
+ }
+}
+
+void html_text::issue_table_begin (tag_definition *t)
+{
+ if (linelength > 0) {
+ int width=current_indentation*100/linelength;
+
+ if (width > 0) {
+ out->put_string("<table width=\"100%\" border=0 rules=\"none\" frame=\"void\"\n cols=\"2\" cellspacing=\"0\" cellpadding=\"0\">").nl();
+ out->put_string("<tr valign=\"top\" align=\"left\">").nl();
+ if ((t->arg1 == 0) || (strcmp(t->arg1, "") == 0))
+ out->put_string("<td width=\"").put_number(width).put_string("%\"></td>");
+ else {
+ out->put_string("<td width=\"").put_number(width).put_string("%\">").nl();
+ out->put_string(t->arg1).put_string("</td>");
+ t->arg1[0] = (char)0;
+ }
+ out->put_string("<td width=\"").put_number(100-width).put_string("%\">").nl();
+ }
+ }
+}
+
+void html_text::issue_table_end (void)
+{
+ out->put_string("</td></table>").nl();
+ out->enable_newlines(TRUE);
+}
+
+/*
+ * flush_text - flushes html tags which are outstanding on the html stack.
+ */
+
+void html_text::flush_text (void)
+{
+ int notext=TRUE;
+ tag_definition *p=stackptr;
+
+ while (stackptr != 0) {
+ notext = (notext && (! stackptr->text_emitted));
+ if (! notext) {
+ end_tag(stackptr);
+ }
+ p = stackptr;
+ stackptr = stackptr->next;
+ free(p);
+ }
+ lastptr = NULL;
+}
+
+/*
+ * is_present - returns TRUE if tag is already present on the stack.
+ */
+
+int html_text::is_present (HTML_TAG t)
+{
+ tag_definition *p=stackptr;
+
+ while (p != NULL) {
+ if (t == p->type) {
+ return( TRUE );
+ }
+ p = p->next;
+ }
+ return( FALSE );
+}
+
+/*
+ * push_para - adds a new entry onto the html paragraph stack.
+ */
+
+void html_text::push_para (HTML_TAG t, char *arg)
+{
+ tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
+
+ p->type = t;
+ p->arg1 = arg;
+ p->text_emitted = FALSE;
+
+ /*
+ * if t is a P_TAG or TABLE_TAG or PRE_TAG make sure it goes on the end of the stack.
+ * But we insist that a TABLE_TAG is always after a PRE_TAG
+ * and that a P_TAG is always after a TABLE_TAG
+ */
+
+ if (((t == P_TAG) || (t == PRE_TAG) || (t == TABLE_TAG)) &&
+ (lastptr != NULL)) {
+ if (((lastptr->type == TABLE_TAG) && (t == PRE_TAG)) ||
+ ((lastptr->type == P_TAG) && (t == TABLE_TAG))) {
+ /*
+ * insert p before the lastptr
+ */
+ if (stackptr == lastptr) {
+ /*
+ * only on element of the stack
+ */
+ p->next = stackptr;
+ stackptr = p;
+ } else {
+ /*
+ * more than one element is on the stack
+ */
+ tag_definition *q = stackptr;
+
+ while (q->next != lastptr) {
+ q = q->next;
+ }
+ q->next = p;
+ p->next = lastptr;
+ }
+ } else {
+ /*
+ * store, p, at the end
+ */
+ lastptr->next = p;
+ lastptr = p;
+ p->next = NULL;
+ }
+ } else {
+ p->next = stackptr;
+ if (stackptr == NULL)
+ lastptr = p;
+ stackptr = p;
+ }
+}
+
+/*
+ * do_indent - remember the indent parameters and if
+ * indent is > pageoff and indent has changed
+ * then we start a html table to implement the indentation.
+ */
+
+void html_text::do_indent (char *arg, int indent, int pageoff, int linelen)
+{
+ if ((current_indentation != -1) &&
+ (pageoffset+current_indentation != indent+pageoff)) {
+ /*
+ * actual indentation of text has changed, we need to put
+ * a table tag onto the stack.
+ */
+ do_table(arg);
+ }
+ current_indentation = indent;
+ pageoffset = pageoff;
+ linelength = linelen;
+}
+
+void html_text::do_table (char *arg)
+{
+ int in_pre = is_in_pre();
+ // char *para_type = done_para();
+ done_pre();
+ shutdown(TABLE_TAG); // shutdown a previous table, if present
+ remove_break();
+ if (in_pre) {
+ do_pre();
+ }
+ // do_para(para_type);
+ push_para(TABLE_TAG, arg);
+}
+
+/*
+ * done_table - terminates a possibly existing table.
+ */
+
+void html_text::done_table (void)
+{
+ shutdown(TABLE_TAG);
+ space_emitted = TRUE;
+}
+
+/*
+ * do_italic - changes to italic
+ */
+
+void html_text::do_italic (void)
+{
+ done_bold();
+ done_tt();
+ if (! is_present(I_TAG)) {
+ push_para(I_TAG, "");
+ }
+}
+
+/*
+ * do_bold - changes to bold.
+ */
+
+void html_text::do_bold (void)
+{
+ done_italic();
+ done_tt();
+ if (! is_present(B_TAG)) {
+ push_para(B_TAG, "");
+ }
+}
+
+/*
+ * do_tt - changes to teletype.
+ */
+
+void html_text::do_tt (void)
+{
+ done_bold();
+ done_italic();
+ if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG))) {
+ push_para(TT_TAG, "");
+ }
+}
+
+/*
+ * do_pre - changes to preformated text.
+ */
+
+void html_text::do_pre (void)
+{
+ done_bold();
+ done_italic();
+ done_tt();
+ char *type = done_para();
+ if (! is_present(PRE_TAG)) {
+ push_para(PRE_TAG, "");
+ }
+}
+
+/*
+ * is_in_pre - returns TRUE if we are currently within a preformatted
+ * <pre> block.
+ */
+
+int html_text::is_in_pre (void)
+{
+ return( is_present(PRE_TAG) );
+}
+
+/*
+ * is_in_table - returns TRUE if we are currently within a table.
+ */
+
+int html_text::is_in_table (void)
+{
+ return( is_present(TABLE_TAG) );
+}
+
+/*
+ * shutdown - shuts down an html tag.
+ */
+
+char *html_text::shutdown (HTML_TAG t)
+{
+ char *arg=NULL;
+
+ if (is_present(t)) {
+ tag_definition *p =stackptr;
+ tag_definition *temp =NULL;
+ int notext =TRUE;
+
+ while ((stackptr != NULL) && (stackptr->type != t)) {
+ notext = (notext && (! stackptr->text_emitted));
+ if (! notext) {
+ end_tag(stackptr);
+ }
+
+ /*
+ * pop tag
+ */
+ p = stackptr;
+ stackptr = stackptr->next;
+ if (stackptr == NULL)
+ lastptr = NULL;
+
+ /*
+ * push tag onto temp stack
+ */
+ p->next = temp;
+ temp = p;
+ }
+
+ /*
+ * and examine stackptr
+ */
+ if ((stackptr != NULL) && (stackptr->type == t)) {
+ if (stackptr->text_emitted) {
+ end_tag(stackptr);
+ }
+ if (t == P_TAG) {
+ arg = stackptr->arg1;
+ }
+ p = stackptr;
+ stackptr = stackptr->next;
+ if (stackptr == NULL)
+ lastptr = NULL;
+ free(p);
+ }
+
+ /*
+ * and restore unaffected tags
+ */
+ while (temp != NULL) {
+ push_para(temp->type, temp->arg1);
+ p = temp;
+ temp = temp->next;
+ free(p);
+ }
+ }
+ return( arg );
+}
+
+/*
+ * done_bold - shuts downs a bold tag.
+ */
+
+void html_text::done_bold (void)
+{
+ shutdown(B_TAG);
+}
+
+/*
+ * done_italic - shuts downs an italic tag.
+ */
+
+void html_text::done_italic (void)
+{
+ shutdown(I_TAG);
+}
+
+/*
+ * done_sup - shuts downs a sup tag.
+ */
+
+void html_text::done_sup (void)
+{
+ shutdown(SUP_TAG);
+}
+
+/*
+ * done_sub - shuts downs a sub tag.
+ */
+
+void html_text::done_sub (void)
+{
+ shutdown(SUB_TAG);
+}
+
+/*
+ * done_tt - shuts downs a tt tag.
+ */
+
+void html_text::done_tt (void)
+{
+ shutdown(TT_TAG);
+}
+
+/*
+ * done_pre - shuts downs a pre tag.
+ */
+
+void html_text::done_pre (void)
+{
+ shutdown(PRE_TAG);
+}
+
+/*
+ * done_small - shuts downs a small tag.
+ */
+
+void html_text::done_small (void)
+{
+ shutdown(SMALL_TAG);
+}
+
+/*
+ * done_big - shuts downs a big tag.
+ */
+
+void html_text::done_big (void)
+{
+ shutdown(BIG_TAG);
+}
+
+/*
+ * check_emit_text - ensures that all previous tags have been emitted (in order)
+ * before the text is written.
+ */
+
+void html_text::check_emit_text (tag_definition *t)
+{
+ if ((t != NULL) && (! t->text_emitted)) {
+ /*
+ * we peep and see whether there is a <p> before the <table>
+ * in which case we skip the <p>
+ */
+ if (t->type == TABLE_TAG) {
+ if (table_is_void(t)) {
+ tag_definition *n = t->next;
+ remove_def(t);
+ check_emit_text(n);
+ } else {
+ /*
+ * a table which will be emitted, is there a <p> succeeding it?
+ */
+ if ((t->next != NULL) &&
+ (t->next->type == P_TAG) &&
+ ((t->next->arg1 == 0) || strcmp(t->next->arg1, "") == 0)) {
+ /*
+ * yes skip the <p>
+ */
+ check_emit_text(t->next->next);
+ } else {
+ check_emit_text(t->next);
+ }
+ t->text_emitted = TRUE;
+ start_tag(t);
+ }
+ } else {
+ check_emit_text(t->next);
+ t->text_emitted = TRUE;
+ start_tag(t);
+ }
+ }
+}
+
+/*
+ * do_emittext - tells the class that text was written during the current tag.
+ */
+
+void html_text::do_emittext (char *s, int length)
+{
+ if ((! is_present(P_TAG)) && (! is_present(PRE_TAG)))
+ do_para("");
+
+ if (is_present(BREAK_TAG)) {
+ int text = remove_break();
+ check_emit_text(stackptr);
+ if (text) {
+ if (is_present(PRE_TAG)) {
+ out->nl();
+ } else {
+ out->put_string("<br>").nl();
+ }
+ }
+ } else {
+ check_emit_text(stackptr);
+ }
+ out->put_string(s, length);
+ space_emitted = FALSE;
+}
+
+/*
+ * do_para- starts a new paragraph
+ */
+
+void html_text::do_para (char *arg)
+{
+ done_pre();
+ if (! is_present(P_TAG)) {
+ remove_sub_sup();
+ if ((arg != 0) && (strcmp(arg, "") != 0)) {
+ remove_tag(TABLE_TAG);
+ }
+ push_para(P_TAG, arg);
+ space_emitted = TRUE;
+ }
+}
+
+/*
+ * done_para - shuts down a paragraph tag.
+ */
+
+char *html_text::done_para (void)
+{
+ space_emitted = TRUE;
+ return( shutdown(P_TAG) );
+}
+
+/*
+ * do_space - issues an end of paragraph
+ */
+
+void html_text::do_space (void)
+{
+ if (is_in_pre()) {
+ do_emittext("", 0);
+ } else {
+ do_para(done_para());
+ }
+ space_emitted = TRUE;
+}
+
+/*
+ * do_break - issue a break tag.
+ */
+
+void html_text::do_break (void)
+{
+ if (! is_present(PRE_TAG)) {
+ if (emitted_text()) {
+ if (! is_present(BREAK_TAG)) {
+ push_para(BREAK_TAG, "");
+ }
+ }
+ }
+ space_emitted = TRUE;
+}
+
+/*
+ * do_newline - issue a newline providing that we are inside a <pre> tag.
+ */
+
+void html_text::do_newline (void)
+{
+ if (is_present(PRE_TAG)) {
+ do_emittext("\n", 1);
+ space_emitted = TRUE;
+ }
+}
+
+/*
+ * emitted_text - returns FALSE if white space has just been written.
+ */
+
+int html_text::emitted_text (void)
+{
+ return( ! space_emitted);
+}
+
+/*
+ * emit_space - writes a space providing that text was written beforehand.
+ */
+
+int html_text::emit_space (void)
+{
+ if (space_emitted) {
+ if (is_present(PRE_TAG)) {
+ do_emittext(" ", 1);
+ }
+ } else {
+ out->space_or_newline();
+ space_emitted = TRUE;
+ }
+}
+
+/*
+ * remove_def - removes a definition, t, from the stack.
+ */
+
+void html_text::remove_def (tag_definition *t)
+{
+ tag_definition *p = stackptr;
+ tag_definition *l = 0;
+ tag_definition *q = 0;
+
+ while ((p != 0) && (p != t)) {
+ l = p;
+ p = p->next;
+ }
+ if ((p != 0) && (p == t)) {
+ if (p == stackptr) {
+ stackptr = stackptr->next;
+ if (stackptr == NULL)
+ lastptr = NULL;
+ q = stackptr;
+ } else if (l == 0) {
+ error("stack list pointers are wrong");
+ } else {
+ l->next = p->next;
+ q = p->next;
+ if (l->next == NULL)
+ lastptr = l;
+ }
+ free(p);
+ }
+}
+
+/*
+ * remove_tag - removes a tag from the stack.
+ */
+
+void html_text::remove_tag (HTML_TAG tag)
+{
+ tag_definition *p = stackptr;
+
+ while ((p != 0) && (p->type != tag)) {
+ p = p->next;
+ }
+ if ((p != 0) && (p->type == tag))
+ remove_def(p);
+}
+
+/*
+ * remove_sub_sup - removes a sub or sup tag, should either exist on the stack.
+ */
+
+void html_text::remove_sub_sup (void)
+{
+ if (is_present(SUB_TAG)) {
+ remove_tag(SUB_TAG);
+ }
+ if (is_present(SUP_TAG)) {
+ remove_tag(SUP_TAG);
+ }
+ if (is_present(PRE_TAG)) {
+ remove_tag(PRE_TAG);
+ }
+}
+
+/*
+ * remove_break - break tags are not balanced thus remove it once it has been emitted.
+ * It returns TRUE if text was emitted before the <br> was issued.
+ */
+
+int html_text::remove_break (void)
+{
+ tag_definition *p = stackptr;
+ tag_definition *l = 0;
+ tag_definition *q = 0;
+
+ while ((p != 0) && (p->type != BREAK_TAG)) {
+ l = p;
+ p = p->next;
+ }
+ if ((p != 0) && (p->type == BREAK_TAG)) {
+ if (p == stackptr) {
+ stackptr = stackptr->next;
+ if (stackptr == NULL)
+ lastptr = NULL;
+ q = stackptr;
+ } else if (l == 0) {
+ error("stack list pointers are wrong");
+ } else {
+ l->next = p->next;
+ q = p->next;
+ if (l->next == NULL)
+ lastptr = l;
+ }
+ free(p);
+ }
+ /*
+ * now determine whether text was issued before <br>
+ */
+ while (q != 0) {
+ if (q->text_emitted) {
+ return( TRUE );
+ } else {
+ q = q->next;
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * do_small - potentially inserts a <small> tag into the html stream.
+ * However we check for a <big> tag, if present then we terminate it.
+ * Otherwise a <small> tag is inserted.
+ */
+
+void html_text::do_small (void)
+{
+ if (is_present(BIG_TAG)) {
+ done_big();
+ } else {
+ push_para(SMALL_TAG, "");
+ }
+}
+
+/*
+ * do_big - is the mirror image of do_small.
+ */
+
+void html_text::do_big (void)
+{
+ if (is_present(SMALL_TAG)) {
+ done_small();
+ } else {
+ push_para(BIG_TAG, "");
+ }
+}
+
+/*
+ * do_sup - save a superscript tag on the stack of tags.
+ */
+
+void html_text::do_sup (void)
+{
+ push_para(SUP_TAG, "");
+}
+
+/*
+ * do_sub - save a subscript tag on the stack of tags.
+ */
+
+void html_text::do_sub (void)
+{
+ push_para(SUB_TAG, "");
+}
+
diff --git a/contrib/groff/src/devices/grohtml/html-text.h b/contrib/groff/src/devices/grohtml/html-text.h
new file mode 100644
index 0000000..c8ab2ac
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/html-text.h
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote html-text.cc
+ *
+ * html-text.h
+ *
+ * provides a state machine interface which generates html text.
+ */
+
+/*
+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 "html.h"
+
+/*
+ * html tags
+ */
+
+typedef enum {I_TAG, B_TAG, P_TAG, SUB_TAG, SUP_TAG, TT_TAG,
+ PRE_TAG, SMALL_TAG, BIG_TAG, BREAK_TAG, TABLE_TAG} HTML_TAG;
+
+typedef struct tag_definition {
+ HTML_TAG type;
+ char *arg1;
+ int text_emitted;
+ tag_definition *next;
+} tag_definition ;
+
+/*
+ * the state of the current paragraph.
+ * It allows post-html.cc to request font changes, paragraph start/end
+ * and emits balanced tags with a small amount of peephole optimization.
+ */
+
+class html_text {
+public:
+ html_text (simple_output *op);
+ ~html_text (void);
+ void flush_text (void);
+ void do_emittext (char *s, int length);
+ void do_italic (void);
+ void do_bold (void);
+ void do_roman (void);
+ void do_tt (void);
+ void do_pre (void);
+ void do_small (void);
+ void do_big (void);
+ void do_para (char *arg1);
+ void do_sup (void);
+ void do_sub (void);
+ void do_space (void);
+ void do_break (void);
+ void do_newline (void);
+ void do_table (char *arg);
+ void done_bold (void);
+ void done_italic (void);
+ char *done_para (void);
+ void done_sup (void);
+ void done_sub (void);
+ void done_tt (void);
+ void done_pre (void);
+ void done_small (void);
+ void done_big (void);
+ void do_indent (char *arg, int indent, int pageoff, int linelen);
+ int emitted_text (void);
+ int emit_space (void);
+ int is_in_pre (void);
+ void remove_tag (HTML_TAG tag);
+ void remove_sub_sup (void);
+ void done_table (void);
+ int is_in_table (void);
+
+private:
+ tag_definition *stackptr; /* the current paragraph state */
+ tag_definition *lastptr; /* the end of the stack */
+ simple_output *out;
+ int space_emitted;
+ int current_indentation; /* current .in value */
+ int pageoffset; /* .po value */
+ int linelength; /* current line length */
+
+ int is_present (HTML_TAG t);
+ void end_tag (tag_definition *t);
+ void start_tag (tag_definition *t);
+ void push_para (HTML_TAG t, char *arg);
+ char *shutdown (HTML_TAG t);
+ void check_emit_text (tag_definition *t);
+ int remove_break (void);
+ void issue_tag (char *tagname, char *arg);
+ void issue_table_begin (tag_definition *t);
+ void issue_table_end (void);
+ int table_is_void (tag_definition *t);
+ void remove_def (tag_definition *t);
+};
diff --git a/contrib/groff/src/devices/grohtml/html.h b/contrib/groff/src/devices/grohtml/html.h
new file mode 100644
index 0000000..69b6e35
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/html.h
@@ -0,0 +1,96 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 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 !defined(HTML_H)
+# define HTML_H
+# undef DEBUGGING
+// # define DEBUGGING
+
+/*
+ * class and structure needed to buffer words
+ */
+
+struct word {
+ char *s;
+ word *next;
+
+ word (const char *w, int n);
+ ~word ();
+};
+
+class word_list {
+public:
+ word_list ();
+ int flush (FILE *f);
+ void add_word (const char *s, int n);
+ int get_length (void);
+
+private:
+ int length;
+ word *head;
+ word *tail;
+};
+
+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 &enable_newlines(int);
+ simple_output &check_newline(int n);
+ simple_output &nl(void);
+ simple_output &space_or_newline (void);
+ simple_output &begin_tag (void);
+ FILE *get_file();
+private:
+ FILE *fp;
+ int max_line_length; // not including newline
+ int col;
+ int fixed_point;
+ int newlines; // can we issue newlines automatically?
+ word_list last_word;
+
+ void flush_last_word (void);
+ int check_space (const char *s, int n);
+};
+
+inline FILE *simple_output::get_file()
+{
+ return fp;
+}
+
+#endif
diff --git a/contrib/groff/src/devices/grohtml/output.cc b/contrib/groff/src/devices/grohtml/output.cc
new file mode 100644
index 0000000..4c72bba
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/output.cc
@@ -0,0 +1,335 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 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
+
+/*
+ * word - initialise a word and set next to NULL
+ */
+
+word::word (const char *w, int n)
+ : next(0)
+{
+ s = (char *)malloc(n+1);
+ strncpy(s, w, n);
+ s[n] = (char)0;
+}
+
+/*
+ * destroy word and the string copy.
+ */
+
+word::~word ()
+{
+ free(s);
+}
+
+/*
+ * word_list - create an empty word list.
+ */
+
+word_list::word_list ()
+ : head(0), tail(0), length(0)
+{
+}
+
+/*
+ * flush - flush a word list to a FILE, f, and return the
+ * length of the buffered string.
+ */
+
+int word_list::flush (FILE *f)
+{
+ word *t;
+ int len=length;
+
+ while (head != 0) {
+ t = head;
+ head = head->next;
+ fputs(t->s, f);
+ delete t;
+ }
+ head = 0;
+ tail = 0;
+ length = 0;
+#if defined(DEBUGGING)
+ fflush(f); // just for testing
+#endif
+ return( len );
+}
+
+/*
+ * add_word - adds a word to the outstanding word list.
+ */
+
+void word_list::add_word (const char *s, int n)
+{
+ if (head == 0) {
+ head = new word(s, n);
+ tail = head;
+ } else {
+ tail->next = new word(s, n);
+ tail = tail->next;
+ }
+ length += n;
+}
+
+/*
+ * get_length - returns the number of characters buffered
+ */
+
+int word_list::get_length (void)
+{
+ return( length );
+}
+
+/*
+ * the classes and methods for simple_output manipulation
+ */
+
+simple_output::simple_output(FILE *f, int n)
+: fp(f), max_line_length(n), col(0), fixed_point(0), newlines(0)
+{
+}
+
+simple_output &simple_output::set_file(FILE *f)
+{
+ if (fp)
+ fflush(fp);
+ fp = f;
+ 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()
+{
+ flush_last_word();
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ }
+ return *this;
+}
+
+simple_output &simple_output::special(const char *s)
+{
+ return *this;
+}
+
+simple_output &simple_output::simple_comment(const char *s)
+{
+ flush_last_word();
+ if (col != 0)
+ putc('\n', fp);
+ fputs("<!-- ", fp);
+ fputs(s, fp);
+ fputs(" -->\n", fp);
+ col = 0;
+ return *this;
+}
+
+simple_output &simple_output::begin_comment(const char *s)
+{
+ flush_last_word();
+ if (col != 0)
+ putc('\n', fp);
+ col = 0;
+ put_string("<!--");
+ space_or_newline();
+ last_word.add_word(s, strlen(s));
+ return *this;
+}
+
+simple_output &simple_output::end_comment()
+{
+ flush_last_word();
+ space_or_newline();
+ put_string("-->").nl();
+ return *this;
+}
+
+/*
+ * check_newline - checks to see whether we are able to issue
+ * a newline and that one is needed.
+ */
+
+simple_output &simple_output::check_newline(int n)
+{
+ if ((col + n + last_word.get_length() + 1 > max_line_length) && (newlines)) {
+ fputc('\n', fp);
+ col = last_word.flush(fp);
+ }
+}
+
+/*
+ * space_or_newline - will emit a newline or a space later on
+ * depending upon the current column.
+ */
+
+simple_output &simple_output::space_or_newline (void)
+{
+#if defined(DEBUGGING)
+ fflush(fp); // just for testing
+#endif
+ if ((col + last_word.get_length() + 1 > max_line_length) && (newlines)) {
+ fputc('\n', fp);
+ if (last_word.get_length() > 0) {
+ col = last_word.flush(fp);
+ } else {
+ col = 0;
+ }
+ } else {
+ if (last_word.get_length() != 0) {
+ if (col > 0) {
+ fputc(' ', fp);
+ col++;
+ }
+ col += last_word.flush(fp);
+ }
+ }
+}
+
+/*
+ * nl - writes a newline providing that we
+ * are not in the first column.
+ */
+
+simple_output &simple_output::nl (void)
+{
+ space_or_newline();
+ col += last_word.flush(fp);
+ if (col != 0) {
+ fputc('\n', fp);
+ col = 0;
+ }
+ 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)
+{
+ col += last_word.flush(fp);
+ putc(c, fp);
+ col++;
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s, int n)
+{
+ last_word.add_word(s, n);
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s)
+{
+ last_word.add_word(s, strlen(s));
+ return *this;
+}
+
+simple_output &simple_output::put_number(int n)
+{
+ char buf[1 + INT_DIGITS + 1];
+ sprintf(buf, "%d", n);
+ put_string(buf);
+ return *this;
+}
+
+simple_output &simple_output::put_float(double d)
+{
+ char buf[128];
+
+ sprintf(buf, "%.4f", d);
+ put_string(buf);
+ return *this;
+}
+
+simple_output &simple_output::enable_newlines (int auto_newlines)
+{
+ check_newline(0);
+ newlines = auto_newlines;
+ check_newline(0);
+}
+
+/*
+ * flush_last_word - flushes the last word and adjusts the
+ * col position. It will insert a newline
+ * before the last word if allowed and if
+ * necessary.
+ */
+
+void simple_output::flush_last_word (void)
+{
+ int len=last_word.get_length();
+
+ if (len > 0) {
+ if (newlines) {
+ if (col + len + 1 > max_line_length) {
+ fputs("\n", fp);
+ col = 0;
+ } else {
+ fputs(" ", fp);
+ col++;
+ }
+ len += last_word.flush(fp);
+ } else {
+ fputs(" ", fp);
+ col++;
+ col += last_word.flush(fp);
+ }
+ }
+}
diff --git a/contrib/groff/src/devices/grohtml/post-html.cc b/contrib/groff/src/devices/grohtml/post-html.cc
new file mode 100644
index 0000000..0237bfc
--- /dev/null
+++ b/contrib/groff/src/devices/grohtml/post-html.cc
@@ -0,0 +1,2933 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote post-html.cc
+ * 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 "html-text.h"
+
+#include <time.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+#define MAX_STRING_LENGTH 4096
+#define MAX_LINE_LENGTH 60 /* maximum characters we want in a line */
+#define SIZE_INCREMENT 2 /* font size increment <big> = +2 */
+#define BASE_POINT_SIZE 10 /* 10 points is the base size ie html size 3 */
+#define CENTER_TOLERANCE 2 /* how many pixels off center will we still */
+#define ANCHOR_TEMPLATE "heading%d" /* if simple anchor is set we use this */
+#define UNICODE_DESC_START 0x80 /* all character entities above this are */
+ /* either encoded by their glyph names or if */
+ /* there is no name then we use &#nnn; */
+#define INDENTATION /* #undef INDENTATION to remove .in handling */
+
+typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT;
+
+/*
+ * prototypes
+ */
+
+void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single);
+char *get_html_translation (font *f, const char *name);
+
+
+static int auto_links = TRUE; /* by default we enable automatic links at */
+ /* top of the document. */
+static int auto_rule = TRUE; /* by default we enable an automatic rule */
+ /* at the top and bottom of the document */
+static int simple_anchors = FALSE; /* default to anchors with heading text */
+
+
+/*
+ * start with a few favorites
+ */
+
+void stop () {}
+
+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') );
+}
+
+/*
+ * the classes and methods for maintaining a list of files.
+ */
+
+struct file {
+ FILE *fp;
+ file *next;
+
+ file (FILE *f);
+};
+
+/*
+ * file - initialize all fields to NULL
+ */
+
+file::file (FILE *f)
+ : fp(f), next(0)
+{
+}
+
+class files {
+public:
+ files ();
+ FILE *get_file (void);
+ void start_of_list (void);
+ void move_next (void);
+ void add_new_file (FILE *f);
+private:
+ file *head;
+ file *tail;
+ file *ptr;
+};
+
+/*
+ * files - create an empty list of files.
+ */
+
+files::files ()
+ : head(0), tail(0), ptr(0)
+{
+}
+
+/*
+ * get_file - returns the FILE associated with ptr.
+ */
+
+FILE *files::get_file (void)
+{
+ if (ptr) {
+ return( ptr->fp );
+ } else {
+ return( 0 );
+ }
+}
+
+/*
+ * start_of_list - reset the ptr to the start of the list.
+ */
+
+void files::start_of_list (void)
+{
+ ptr = head;
+}
+
+/*
+ * move_next - moves the ptr to the next element on the list.
+ */
+
+void files::move_next (void)
+{
+ if (ptr != 0)
+ ptr = ptr->next;
+}
+
+/*
+ * add_new_file - adds a new file, f, to the list.
+ */
+
+void files::add_new_file (FILE *f)
+{
+ if (head == 0) {
+ head = new file(f);
+ tail = head;
+ } else {
+ tail->next = new file(f);
+ tail = tail->next;
+ }
+ ptr = tail;
+}
+
+/*
+ * 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 glyph positions.
+ */
+
+class text_glob {
+public:
+ text_glob (style *s, char *string, unsigned int length,
+ int min_vertical , int min_horizontal,
+ int max_vertical , int max_horizontal,
+ int is_html , int is_troff_command,
+ int is_auto_image,
+ int is_a_line , int thickness);
+ text_glob (void);
+ ~text_glob (void);
+ int is_a_line (void);
+ int is_a_tag (void);
+ int is_raw (void);
+ int is_eol (void);
+ int is_auto_img (void);
+ int is_br (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_tag; // is this a .br, .sp, .tl etc
+ int is_line; // is the command a <line>?
+ int is_img_auto; // image created by eqn delim
+ int thickness; // the thickness of a line
+};
+
+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_html, int is_troff_command,
+ int is_auto_image,
+ int is_a_line, int line_thickness)
+ : text_style(*s), text_string(string), text_length(length),
+ minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal),
+ is_raw_command(is_html), is_tag(is_troff_command), is_img_auto(is_auto_image),
+ is_line(is_a_line), thickness(line_thickness)
+{
+}
+
+text_glob::text_glob ()
+ : text_string(0), text_length(0), minv(-1), maxv(-1), minh(-1), maxh(-1),
+ is_raw_command(FALSE), is_tag(FALSE), is_line(FALSE), thickness(0)
+{
+}
+
+text_glob::~text_glob ()
+{
+}
+
+/*
+ * is_a_line - returns TRUE if glob should be converted into an <hr>
+ */
+
+int text_glob::is_a_line (void)
+{
+ return( is_line );
+}
+
+/*
+ * is_a_tag - returns TRUE if glob contains a troff directive.
+ */
+
+int text_glob::is_a_tag (void)
+{
+ return( is_tag );
+}
+
+/*
+ * is_eol - returns TRUE if glob contains the tag eol
+ */
+
+int text_glob::is_eol (void)
+{
+ return( is_tag && (strcmp(text_string, "html-tag:eol") == 0) );
+}
+
+/*
+ * is_raw - returns TRUE if glob contains raw html.
+ */
+
+int text_glob::is_raw (void)
+{
+ return( is_raw_command );
+}
+
+/*
+ * is_auto_img - returns TRUE if the glob contains an automatically
+ * generated image.
+ */
+
+int text_glob::is_auto_img (void)
+{
+ return( is_img_auto );
+}
+
+/*
+ * is_br - returns TRUE if the glob is a tag containing a .br
+ */
+
+int text_glob::is_br (void)
+{
+ return( is_a_tag() && (strcmp("html-tag:.br", text_string) == 0) );
+}
+
+/*
+ * the class and methods used to construct ordered double linked lists.
+ * In a previous implementation we used templates via #include "ordered-list.h",
+ * but this does assume that all C++ compilers can handle this feature. Pragmatically
+ * it is safer to assume this is not the case.
+ */
+
+struct element_list {
+ element_list *right;
+ element_list *left;
+ text_glob *datum;
+ int lineno;
+ int minv, maxv, minh, maxh;
+
+ element_list (text_glob *d,
+ int line_number,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ element_list ();
+};
+
+element_list::element_list ()
+ : right(0), left(0), datum(0), lineno(0), minv(-1), maxv(-1), minh(-1), maxh(-1)
+{
+}
+
+/*
+ * element_list - create a list element assigning the datum and region parameters.
+ */
+
+element_list::element_list (text_glob *in,
+ int line_number,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
+ : right(0), left(0), datum(in), lineno(line_number),
+ minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal)
+{
+}
+
+class list {
+public:
+ list ();
+ ~list ();
+ int is_less (element_list *a, element_list *b);
+ void add (text_glob *in,
+ int line_number,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ 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);
+ text_glob *move_right_get_data (void);
+ text_glob *move_left_get_data (void);
+ text_glob *get_data (void);
+private:
+ element_list *head;
+ element_list *tail;
+ element_list *ptr;
+};
+
+/*
+ * list - construct an empty list.
+ */
+
+list::list ()
+ : head(0), tail(0), ptr(0)
+{
+}
+
+/*
+ * ~list - destroy a complete list.
+ */
+
+list::~list()
+{
+ element_list *temp=head;
+
+ do {
+ temp = head;
+ if (temp != 0) {
+ head = head->right;
+ delete temp;
+ }
+ } while ((head != 0) && (head != tail));
+}
+
+/*
+ * is_less - returns TRUE if a is left of b if on the same line or
+ * if a is higher up the page than b.
+ */
+
+int list::is_less (element_list *a, element_list *b)
+{
+ // was if (is_intersection(a->minv+1, a->maxv-1, b->minv+1, b->maxv-1)) {
+ if (a->lineno < b->lineno) {
+ return( TRUE );
+ } else if (a->lineno > b->lineno) {
+ return( FALSE );
+ } else if (is_intersection(a->minv, a->maxv, b->minv, b->maxv)) {
+ return( a->minh < b->minh );
+ } else {
+ return( a->maxv < b->maxv );
+ }
+}
+
+/*
+ * add - adds a datum to the list in the order specified by the region position.
+ */
+
+void list::add (text_glob *in, int line_number, int min_vertical, int min_horizontal, int max_vertical, int max_horizontal)
+{
+ // create a new list element with datum and position fields initialized
+ element_list *t = new element_list(in, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
+ element_list *last;
+
+ if (head == 0) {
+ head = t;
+ tail = t;
+ t->left = t;
+ t->right = t;
+ } else {
+ last = tail;
+
+ while ((last != head) && (is_less(t, last))) {
+ last = last->left;
+ }
+
+ if (is_less(t, last)) {
+ 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 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;
+ }
+ }
+ }
+}
+
+/*
+ * sub_move_right - removes the element which is currently pointed to by ptr
+ * from the list and moves ptr to the right.
+ */
+
+void list::sub_move_right (void)
+{
+ element_list *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;
+ }
+}
+
+/*
+ * start_from_head - assigns ptr to the head.
+ */
+
+void list::start_from_head (void)
+{
+ ptr = head;
+}
+
+/*
+ * start_from_tail - assigns ptr to the tail.
+ */
+
+void list::start_from_tail (void)
+{
+ ptr = tail;
+}
+
+/*
+ * is_empty - returns TRUE if the list has no elements.
+ */
+
+int list::is_empty (void)
+{
+ return( head == 0 );
+}
+
+/*
+ * is_equal_to_tail - returns TRUE if the ptr equals the tail.
+ */
+
+int list::is_equal_to_tail (void)
+{
+ return( ptr == tail );
+}
+
+/*
+ * is_equal_to_head - returns TRUE if the ptr equals the head.
+ */
+
+int list::is_equal_to_head (void)
+{
+ return( ptr == head );
+}
+
+/*
+ * move_left - moves the ptr left.
+ */
+
+void list::move_left (void)
+{
+ ptr = ptr->left;
+}
+
+/*
+ * move_right - moves the ptr right.
+ */
+
+void list::move_right (void)
+{
+ ptr = ptr->right;
+}
+
+/*
+ * get_datum - returns the datum referenced via ptr.
+ */
+
+text_glob* list::get_data (void)
+{
+ return( ptr->datum );
+}
+
+/*
+ * move_right_get_data - returns the datum referenced via ptr and moves
+ * ptr right.
+ */
+
+text_glob* list::move_right_get_data (void)
+{
+ ptr = ptr->right;
+ if (ptr == head) {
+ return( 0 );
+ } else {
+ return( ptr->datum );
+ }
+}
+
+/*
+ * move_left_get_data - returns the datum referenced via ptr and moves
+ * ptr right.
+ */
+
+text_glob* list::move_left_get_data (void)
+{
+ ptr = ptr->left;
+ if (ptr == tail) {
+ return( 0 );
+ } else {
+ return( ptr->datum );
+ }
+}
+
+/*
+ * page class and methods
+ */
+
+class page {
+public:
+ page (void);
+ void add (style *s, char *string, unsigned int length,
+ int line_number,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_html (style *s, char *string, unsigned int length,
+ int line_number,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_tag (style *s, char *string, unsigned int length,
+ int line_number,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_line (style *s,
+ int line_number,
+ int x1, int y1, int x2, int y2,
+ int thickness);
+ void dump_page (void); // debugging method
+
+ // and the data
+
+ list glyphs; // position of glyphs and specials on page
+ char_buffer buffer; // all characters for this page
+};
+
+page::page()
+{
+}
+
+void page::add (style *s, char *string, unsigned int length,
+ int line_number,
+ 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, FALSE, FALSE, 0);
+ glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
+ }
+}
+
+/*
+ * add_html - add a raw html command, for example mailto, line, background, image etc.
+ */
+
+void page::add_html (style *s, char *string, unsigned int length,
+ int line_number,
+ 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,
+ TRUE, FALSE, FALSE, FALSE, 0);
+ glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
+ }
+}
+
+/*
+ * add_tag - adds a troff tag, for example: .tl .sp .br
+ */
+
+void page::add_tag (style *s, char *string, unsigned int length,
+ int line_number,
+ 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, TRUE,
+ (strncmp(string, "html-tag:.auto-image", 20) == 0),
+ FALSE, 0);
+ glyphs.add(g, line_number, min_vertical, min_horizontal, max_vertical, max_horizontal);
+ }
+}
+
+/*
+ * add_line - adds the <line> primitive providing that y1==y2
+ */
+
+void page::add_line (style *s,
+ int line_number,
+ int x1, int y1, int x2, int y2,
+ int thickness)
+{
+ if (y1 == y2) {
+ text_glob *g = new text_glob(s, "", 0,
+ min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2),
+ FALSE, TRUE, FALSE, FALSE, thickness);
+ glyphs.add(g, line_number, min(y1, y2), min(x1, y2), max(y1, y2), max(x1, x2));
+ }
+}
+
+/*
+ * dump_page - dump the page contents for debugging purposes.
+ */
+
+void page::dump_page(void)
+{
+ text_glob *g;
+
+ printf("\n\ndebugging start\n");
+ glyphs.start_from_head();
+ do {
+ g = glyphs.get_data();
+ printf("%s ", g->text_string);
+ glyphs.move_right();
+ } while (! glyphs.is_equal_to_head());
+ printf("\ndebugging end\n\n");
+}
+
+/*
+ * font classes and methods
+ */
+
+class html_font : public font {
+ html_font(const char *);
+public:
+ int encoding_index;
+ char *encoding;
+ char *reencoded_name;
+ ~html_font();
+ 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()
+{
+}
+
+/*
+ * 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
+ list headers; // list of headers built from .NH and .SH
+ 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, int force);
+};
+
+header_desc::header_desc ()
+ : no_of_headings(0), header_level(2), written_header(0)
+{
+}
+
+header_desc::~header_desc ()
+{
+}
+
+/*
+ * write_headings - emits a list of links for the headings in this document
+ */
+
+void header_desc::write_headings (FILE *f, int force)
+{
+ text_glob *g;
+
+ if (auto_links || force) {
+ if (! headers.is_empty()) {
+ int h=1;
+
+ headers.start_from_head();
+ do {
+ g = headers.get_data();
+ fputs("<a href=\"#", f);
+ if (simple_anchors)
+ fprintf(f, ANCHOR_TEMPLATE, h);
+ else
+ fputs(g->text_string, f);
+ h++;
+ fputs("\">", f);
+ fputs(g->text_string, f);
+ fputs("</a><br>\n", f);
+ headers.move_right();
+ } while (! headers.is_equal_to_head());
+ fputs("\n", f);
+ }
+ }
+}
+
+class html_printer : public printer {
+ files file_list;
+ simple_output html;
+ int 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;
+ style output_style;
+ int output_hpos;
+ int output_vpos;
+ int output_vpos_max;
+ int output_draw_point_size;
+ int line_thickness;
+ int output_line_thickness;
+ unsigned char output_space_code;
+ string defs;
+ char *inside_font_style;
+ int page_number;
+ title_desc title;
+ title_desc indent; // use title class to remember $1 of .ip
+ header_desc header;
+ int header_indent;
+ int supress_sub_sup;
+ int cutoff_heading;
+ page *page_contents;
+ html_text *current_paragraph;
+ int end_center;
+ int end_tempindent;
+ TAG_ALIGNMENT next_tag;
+ int fill_on;
+ int linelength;
+ int pageoffset;
+ int indentation;
+ int prev_indent;
+ int pointsize;
+ int vertical_spacing;
+ int line_number;
+
+ 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 terminate_current_font (void);
+ void flush_font (void);
+ void add_char_to_sbuf (unsigned char code);
+ void add_to_sbuf (unsigned char code, const char *name);
+ void write_title (int in_head);
+ 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 ();
+ int seen_backwards_escape (char *s, int l);
+ void flush_page (void);
+ void troff_tag (text_glob *g);
+ void flush_globs (void);
+ void emit_line (text_glob *g);
+ void emit_raw (text_glob *g);
+ void translate_to_html (text_glob *g);
+ void determine_space (text_glob *g);
+ void start_font (const char *name);
+ void end_font (const char *name);
+ int is_font_courier (font *f);
+ int is_courier_until_eol (void);
+ void start_size (int from, int to);
+ void do_font (text_glob *g);
+ void do_center (char *arg);
+ void do_break (void);
+ void do_eol (void);
+ void do_title (void);
+ void do_fill (int on);
+ void do_heading (char *arg);
+ void write_header (void);
+ void determine_header_level (int level);
+ void do_linelength (char *arg);
+ void do_pageoffset (char *arg);
+ void do_indentation (char *arg);
+ void do_tempindent (char *arg);
+ void do_indentedparagraph (void);
+ void do_verticalspacing (char *arg);
+ void do_pointsize (char *arg);
+ void do_centered_image (void);
+ void do_left_image (void);
+ void do_right_image (void);
+ void do_auto_image (text_glob *g, const char *filename);
+ void do_links (void);
+ void do_flush (void);
+ int is_in_middle (int left, int right);
+ void do_sup_or_sub (text_glob *g);
+ int start_subscript (text_glob *g);
+ int end_subscript (text_glob *g);
+ int start_superscript (text_glob *g);
+ int end_superscript (text_glob *g);
+
+ // 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, char type);
+ font *make_font (const char *);
+ void end_of_line ();
+};
+
+printer *make_printer()
+{
+ return new html_printer;
+}
+
+static void usage(FILE *stream);
+
+void html_printer::set_style(const style &sty)
+{
+ const char *fontname = sty.f->get_name();
+ if (fontname == 0)
+ fatal("no internalname specified for font");
+
+#if 0
+ change_font(fontname, (font::res/(72*font::sizescale))*sty.point_size);
+#endif
+}
+
+void html_printer::end_of_line()
+{
+ flush_sbuf();
+ line_number++;
+}
+
+/*
+ * emit_line - writes out a horizontal rule.
+ */
+
+void html_printer::emit_line (text_glob *g)
+{
+ // --fixme-- needs to know the length in percentage
+ html.put_string("<hr>");
+}
+
+/*
+ * emit_raw - writes the raw html information directly to the device.
+ */
+
+void html_printer::emit_raw (text_glob *g)
+{
+ do_font(g);
+ if (next_tag == INLINE) {
+ determine_space(g);
+ current_paragraph->do_emittext(g->text_string, g->text_length);
+ } else {
+ int in_table=current_paragraph->is_in_table();
+
+ current_paragraph->done_para();
+ switch (next_tag) {
+
+ case CENTERED:
+ current_paragraph->do_para("align=center");
+ break;
+ case LEFT:
+ current_paragraph->do_para("align=left");
+ break;
+ case RIGHT:
+ current_paragraph->do_para("align=right");
+ break;
+ default:
+ fatal("unknown enumeration");
+ }
+ current_paragraph->do_emittext(g->text_string, g->text_length);
+ current_paragraph->done_para();
+ next_tag = INLINE;
+ supress_sub_sup = TRUE;
+#if defined(INDENTATION)
+ if (in_table) {
+ stop();
+ current_paragraph->do_indent(NULL, 0, pageoffset, linelength);
+ current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ }
+#endif
+ }
+}
+
+/*
+ * do_center - handle the .ce commands from troff.
+ */
+
+void html_printer::do_center (char *arg)
+{
+ int n = atoi(arg);
+
+ current_paragraph->do_break();
+ current_paragraph->done_para();
+ supress_sub_sup = TRUE;
+
+ if (n > 0) {
+ current_paragraph->do_para("align=center");
+ end_center += n;
+ } else {
+ end_center = 0;
+ }
+}
+
+/*
+ * do_centered_image - set a flag such that the next html-tag is
+ * placed inside a centered paragraph.
+ */
+
+void html_printer::do_centered_image (void)
+{
+ next_tag = CENTERED;
+}
+
+/*
+ * do_right_image - set a flag such that the next html-tag is
+ * placed inside a right aligned paragraph.
+ */
+
+void html_printer::do_right_image (void)
+{
+ next_tag = RIGHT;
+}
+
+/*
+ * do_left_image - set a flag such that the next html-tag is
+ * placed inside a left aligned paragraph.
+ */
+
+void html_printer::do_left_image (void)
+{
+ next_tag = LEFT;
+}
+
+/*
+ * exists - returns TRUE if filename exists.
+ */
+
+static int exists (const char *filename)
+{
+ FILE *fp = fopen(filename, "r");
+
+ if (fp == 0) {
+ return( FALSE );
+ } else {
+ fclose(fp);
+ return( TRUE );
+ }
+}
+
+/*
+ * generate_img_src - returns a html image tag for the filename
+ * providing that the image exists.
+ */
+
+static char *generate_img_src (const char *filename)
+{
+ static char buffer[MAX_STRING_LENGTH];
+
+ while (filename && (filename[0] == ' ')) {
+ filename++;
+ }
+ if (exists(filename)) {
+ strcpy(buffer, "<img src=\"");
+ strncat(buffer, filename, MAX_STRING_LENGTH-strlen("<img src=\"")-1);
+ if (strlen(buffer) < MAX_STRING_LENGTH-3) {
+ strncat(buffer, "\">", 3);
+ }
+ return( (char *)&buffer );
+ } else {
+ return( 0 );
+ }
+}
+
+/*
+ * do_auto_image - tests whether the image, indicated by filename,
+ * is present, if so then it emits an html image tag.
+ * An image tag may be passed through from pic, eqn
+ * but the corresponding image might not be created.
+ * Consider .EQ delim $$ .EN or an empty .PS .PE.
+ */
+
+void html_printer::do_auto_image (text_glob *g, const char *filename)
+{
+ char *buffer = generate_img_src(filename);
+
+ if (buffer) {
+ /*
+ * utilize emit_raw by creating a new text_glob.
+ */
+ text_glob h = *g;
+
+ h.text_string = buffer;
+ h.text_length = strlen(buffer);
+ emit_raw(&h);
+ } else {
+ next_tag = INLINE;
+ }
+}
+
+/*
+ * do_title - handle the .tl commands from troff.
+ */
+
+void html_printer::do_title (void)
+{
+ text_glob *t;
+ int removed_from_head;
+ char buf[MAX_STRING_LENGTH];
+
+ if (page_number == 1) {
+ int found_title_start = FALSE;
+ if (! page_contents->glyphs.is_empty()) {
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ do {
+ t = page_contents->glyphs.get_data();
+ removed_from_head = FALSE;
+ if (t->is_auto_img()) {
+ char *img=generate_img_src((char *)(t->text_string + 20));
+
+ if (img) {
+ if (found_title_start) {
+ strcat(title.text, " ");
+ }
+ found_title_start = TRUE;
+ title.has_been_found = TRUE;
+ strcat(title.text, img);
+ }
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ removed_from_head = ((!page_contents->glyphs.is_empty()) &&
+ (page_contents->glyphs.is_equal_to_head()));
+ } else if (t->is_raw_command) {
+ /* skip raw commands
+ */
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ } else if (t->is_eol()) {
+ /* end of title found
+ */
+ title.has_been_found = TRUE;
+ return;
+ } else if (t->is_a_tag()) {
+ /* end of title found, but move back so that we read this tag and process it
+ */
+ page_contents->glyphs.move_left(); /* move backwards to last word */
+ title.has_been_found = TRUE;
+ return;
+ } else if (found_title_start) {
+ 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->glyphs.sub_move_right(); /* move onto next word */
+ removed_from_head = ((!page_contents->glyphs.is_empty()) &&
+ (page_contents->glyphs.is_equal_to_head()));
+ } else {
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ strcpy((char *)title.text, buf);
+ found_title_start = TRUE;
+ title.has_been_found = TRUE;
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ removed_from_head = ((!page_contents->glyphs.is_empty()) &&
+ (page_contents->glyphs.is_equal_to_head()));
+ }
+ } while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head));
+ }
+ // page_contents->glyphs.move_left(); /* move backwards to last word */
+ }
+}
+
+void html_printer::write_header (void)
+{
+ if (strlen(header.header_buffer) > 0) {
+ if (header.header_level > 7) {
+ header.header_level = 7;
+ }
+
+ // firstly we must terminate any font and type faces
+ current_paragraph->done_para();
+ current_paragraph->done_table();
+ supress_sub_sup = TRUE;
+
+ if (cutoff_heading+2 > header.header_level) {
+ // now we save the header so we can issue a list of links
+ header.no_of_headings++;
+ style st;
+
+ 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, FALSE, FALSE, FALSE);
+ header.headers.add(h,
+ header.no_of_headings,
+ header.no_of_headings, header.no_of_headings,
+ header.no_of_headings, header.no_of_headings); // and add this header to the header list
+
+ // lastly we generate a tag
+
+ html.nl().put_string("<a name=\"");
+ if (simple_anchors) {
+ char buffer[MAX_LINE_LENGTH];
+
+ sprintf(buffer, ANCHOR_TEMPLATE, header.no_of_headings);
+ html.put_string(buffer);
+ } else {
+ html.put_string(header.header_buffer);
+ }
+ html.put_string("\"></a>").nl();
+ }
+
+ // 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(">").nl();
+
+ current_paragraph->do_para("");
+ }
+}
+
+void html_printer::determine_header_level (int level)
+{
+ if (level == 0) {
+ int i;
+ int l=strlen(header.header_buffer);
+
+ for (i=0; ((i<l) && ((header.header_buffer[i] == '.') || is_digit(header.header_buffer[i]))) ; i++) {
+ if (header.header_buffer[i] == '.') {
+ level++;
+ }
+ }
+ }
+ header.header_level = level+1;
+}
+
+/*
+ * do_heading - handle the .SH and .NH and equivalent commands from troff.
+ */
+
+void html_printer::do_heading (char *arg)
+{
+ text_glob *g;
+ text_glob *l = 0;
+ char buf[MAX_STRING_LENGTH];
+ int level=atoi(arg);
+
+ strcpy(header.header_buffer, "");
+ page_contents->glyphs.move_right();
+ if (! page_contents->glyphs.is_equal_to_head()) {
+ g = page_contents->glyphs.get_data();
+ do {
+ if (g->is_auto_img()) {
+ char *img=generate_img_src((char *)(g->text_string + 20));
+
+ if (img) {
+ simple_anchors = TRUE; // we cannot use full heading anchors with images
+ if (l != 0) {
+ strcat(header.header_buffer, " ");
+ }
+ l = g;
+ strcat(header.header_buffer, img);
+ }
+ } else if (! (g->is_a_line() || g->is_a_tag() || g->is_raw())) {
+ /*
+ * we ignore raw commands when constructing a heading
+ */
+ if (l != 0) {
+ strcat(header.header_buffer, " ");
+ }
+ l = g;
+ 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->glyphs.move_right();
+ g = page_contents->glyphs.get_data();
+ } while ((! page_contents->glyphs.is_equal_to_head()) &&
+ (! g->is_br()));
+ }
+
+ determine_header_level(level);
+ write_header();
+
+ // finally set the output to neutral for after the header
+ g = page_contents->glyphs.get_data();
+ page_contents->glyphs.move_left(); // so that next time we use old g
+}
+
+/*
+ * is_courier_until_eol - returns TRUE if we can see a whole line which is courier
+ */
+
+int html_printer::is_courier_until_eol (void)
+{
+ text_glob *orig = page_contents->glyphs.get_data();
+ int result = TRUE;
+ text_glob *g;
+
+ if (! page_contents->glyphs.is_equal_to_tail()) {
+ page_contents->glyphs.move_right();
+ do {
+ g = page_contents->glyphs.get_data();
+ if (! is_font_courier(g->text_style.f)) {
+ result = FALSE;
+ }
+ page_contents->glyphs.move_right();
+ } while ((result) &&
+ (! page_contents->glyphs.is_equal_to_head()) &&
+ (! g->is_eol()));
+
+ /*
+ * now restore our previous position.
+ */
+ while (page_contents->glyphs.get_data() != orig) {
+ page_contents->glyphs.move_left();
+ }
+ }
+ return( result );
+}
+
+/*
+ * do_linelength - handle the .ll command from troff.
+ */
+
+void html_printer::do_linelength (char *arg)
+{
+#if defined(INDENTATION)
+ if (fill_on) {
+ linelength = atoi(arg);
+ current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ }
+#endif
+}
+
+/*
+ * do_pageoffset - handle the .po command from troff.
+ */
+
+void html_printer::do_pageoffset (char *arg)
+{
+#if defined(INDENTATION)
+ pageoffset = atoi(arg);
+ if (fill_on) {
+ current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ }
+#endif
+}
+
+/*
+ * do_indentation - handle the .in command from troff.
+ */
+
+void html_printer::do_indentation (char *arg)
+{
+#if defined(INDENTATION)
+ if (fill_on) {
+ indentation = atoi(arg);
+ current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ }
+#endif
+}
+
+/*
+ * do_tempindent - handle the .ti command from troff.
+ */
+
+void html_printer::do_tempindent (char *arg)
+{
+#if defined(INDENTATION)
+ if (fill_on) {
+ end_tempindent = 1;
+ prev_indent = indentation;
+ indentation = atoi(arg);
+ current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ }
+#endif
+}
+
+/*
+ * do_indentedparagraph - handle the .ip tag, this buffers the next line
+ * and passes this to text-text as the left hand
+ * column table entry.
+ */
+
+void html_printer::do_indentedparagraph (void)
+{
+#if defined(INDENTATION)
+ text_glob *t;
+ int removed_from_head;
+ char buf[MAX_STRING_LENGTH];
+ int found_indent_start = FALSE;
+
+ indent.has_been_found = FALSE;
+ indent.text[0] = (char)0;
+
+ if (! page_contents->glyphs.is_empty()) {
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ do {
+ t = page_contents->glyphs.get_data();
+ removed_from_head = FALSE;
+ if (t->is_auto_img()) {
+ char *img=generate_img_src((char *)(t->text_string + 20));
+
+ if (img) {
+ if (found_indent_start) {
+ strcat(indent.text, " ");
+ }
+ found_indent_start = TRUE;
+ strcat(indent.text, img);
+ }
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ } else if (t->is_raw_command) {
+ /* skip raw commands
+ */
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ } else if (t->is_a_tag() && (strncmp(t->text_string, "html-tag:.br", 12) == 0)) {
+ /* end of indented para found, but move back so that we read this tag and process it
+ */
+ page_contents->glyphs.move_left(); /* move backwards to last word */
+ indent.has_been_found = TRUE;
+ return;
+ } else if (t->is_a_tag()) {
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ } else if (found_indent_start) {
+ strcat(indent.text, " ");
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ strcat(indent.text, buf);
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ removed_from_head = ((!page_contents->glyphs.is_empty()) &&
+ (page_contents->glyphs.is_equal_to_head()));
+ } else {
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ strcpy((char *)indent.text, buf);
+ found_indent_start = TRUE;
+ indent.has_been_found = TRUE;
+ page_contents->glyphs.sub_move_right(); /* move onto next word */
+ removed_from_head = ((!page_contents->glyphs.is_empty()) &&
+ (page_contents->glyphs.is_equal_to_head()));
+ }
+ } while ((! page_contents->glyphs.is_equal_to_head()) || (removed_from_head));
+ }
+ // page_contents->glyphs.move_left(); /* move backwards to last word */
+#endif
+}
+
+/*
+ * do_verticalspacing - handle the .vs command from troff.
+ */
+
+void html_printer::do_verticalspacing (char *arg)
+{
+ vertical_spacing = atoi(arg);
+}
+
+/*
+ * do_pointsize - handle the .ps command from troff.
+ */
+
+void html_printer::do_pointsize (char *arg)
+{
+ pointsize = atoi(arg);
+}
+
+/*
+ * do_fill - records whether troff has requested that text be filled.
+ */
+
+void html_printer::do_fill (int on)
+{
+ current_paragraph->do_break();
+ output_hpos = indentation+pageoffset;
+ supress_sub_sup = TRUE;
+
+ if (fill_on != on) {
+ if (on) {
+ current_paragraph->done_pre();
+ } else {
+ current_paragraph->do_pre();
+ }
+ }
+ fill_on = on;
+}
+
+/*
+ * do_eol - handle the end of line
+ */
+
+void html_printer::do_eol (void)
+{
+ if (! fill_on) {
+ current_paragraph->do_newline();
+ current_paragraph->do_break();
+ }
+ output_hpos = indentation+pageoffset;
+ if (end_center > 0) {
+ if (end_center > 1) {
+ current_paragraph->do_break();
+ }
+ end_center--;
+ if (end_center == 0) {
+ current_paragraph->done_para();
+ supress_sub_sup = TRUE;
+ }
+ }
+}
+
+/*
+ * do_flush - flushes all output and tags.
+ */
+
+void html_printer::do_flush (void)
+{
+ current_paragraph->done_para();
+ current_paragraph->done_table();
+}
+
+/*
+ * do_links - moves onto a new temporary file and sets auto_links to FALSE.
+ */
+
+void html_printer::do_links (void)
+{
+ current_paragraph->done_para();
+ current_paragraph->done_table();
+ auto_links = FALSE; /* from now on only emit under user request */
+#if !defined(DEBUGGING)
+ file_list.add_new_file(xtmpfile());
+ html.set_file(file_list.get_file());
+#endif
+}
+
+/*
+ * do_break - handles the ".br" request and also
+ * undoes an outstanding ".ti" command.
+ */
+
+void html_printer::do_break (void)
+{
+ current_paragraph->do_break();
+#if defined(INDENTATION)
+ if (end_tempindent > 0) {
+ end_tempindent--;
+ if (end_tempindent == 0) {
+ indentation = prev_indent;
+ current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+ }
+ }
+#endif
+ output_hpos = indentation+pageoffset;
+ supress_sub_sup = TRUE;
+}
+
+/*
+ * troff_tag - processes the troff tag and manipulates the troff state machine.
+ */
+
+void html_printer::troff_tag (text_glob *g)
+{
+ /*
+ * firstly skip over html-tag:
+ */
+ char *t=(char *)g->text_string+9;
+
+ if (g->is_eol()) {
+ do_eol();
+ } else if (strncmp(t, ".sp", 3) == 0) {
+ current_paragraph->do_space();
+ supress_sub_sup = TRUE;
+ } else if (strncmp(t, ".br", 3) == 0) {
+ do_break();
+ } else if (strcmp(t, ".centered-image") == 0) {
+ do_centered_image();
+ } else if (strcmp(t, ".right-image") == 0) {
+ do_right_image();
+ } else if (strcmp(t, ".left-image") == 0) {
+ do_left_image();
+ } else if (strncmp(t, ".auto-image", 11) == 0) {
+ char *a = (char *)t+11;
+ do_auto_image(g, a);
+ } else if (strncmp(t, ".ce", 3) == 0) {
+ char *a = (char *)t+3;
+ supress_sub_sup = TRUE;
+ do_center(a);
+ } else if (strncmp(t, ".tl", 3) == 0) {
+ supress_sub_sup = TRUE;
+ do_title();
+ } else if (strncmp(t, ".fi", 3) == 0) {
+ do_fill(TRUE);
+ } else if (strncmp(t, ".nf", 3) == 0) {
+ do_fill(FALSE);
+ } else if ((strncmp(t, ".SH", 3) == 0) || (strncmp(t, ".NH", 3) == 0)) {
+ char *a = (char *)t+3;
+ do_heading(a);
+ } else if (strncmp(t, ".ll", 3) == 0) {
+ char *a = (char *)t+3;
+ do_linelength(a);
+ } else if (strncmp(t, ".po", 3) == 0) {
+ char *a = (char *)t+3;
+ do_pageoffset(a);
+ } else if (strncmp(t, ".in", 3) == 0) {
+ char *a = (char *)t+3;
+ do_indentation(a);
+ } else if (strncmp(t, ".ti", 3) == 0) {
+ char *a = (char *)t+3;
+ do_tempindent(a);
+ } else if (strncmp(t, ".vs", 3) == 0) {
+ char *a = (char *)t+3;
+ do_verticalspacing(a);
+ } else if (strncmp(t, ".ip", 3) == 0) {
+ do_indentedparagraph();
+ } else if (strcmp(t, ".links") == 0) {
+ do_links();
+ }
+}
+
+/*
+ * is_in_middle - returns TRUE if the positions left..right are in the center of the page.
+ */
+
+int html_printer::is_in_middle (int left, int right)
+{
+ return( abs(abs(left-pageoffset) - abs(pageoffset+linelength-right)) <= CENTER_TOLERANCE );
+}
+
+/*
+ * flush_globs - runs through the text glob list and emits html.
+ */
+
+void html_printer::flush_globs (void)
+{
+ text_glob *g;
+
+ if (! page_contents->glyphs.is_empty()) {
+ page_contents->glyphs.start_from_head();
+ do {
+ g = page_contents->glyphs.get_data();
+
+ if (strcmp(g->text_string, "XXXXXXX") == 0) {
+ stop();
+ }
+
+ if (g->is_raw()) {
+ emit_raw(g);
+ } else if (g->is_a_tag()) {
+ troff_tag(g);
+ } else if (g->is_a_line()) {
+ emit_line(g);
+ } else {
+ translate_to_html(g);
+ }
+ /*
+ * after processing the title (and removing it) the glyph list might be empty
+ */
+ if (! page_contents->glyphs.is_empty()) {
+ page_contents->glyphs.move_right();
+ }
+ } while (! page_contents->glyphs.is_equal_to_head());
+ }
+}
+
+void html_printer::flush_page (void)
+{
+ supress_sub_sup = TRUE;
+ flush_sbuf();
+ // page_contents->dump_page();
+ flush_globs();
+ current_paragraph->done_para();
+ current_paragraph->done_table();
+
+ // move onto a new page
+ delete page_contents;
+ page_contents = new page;
+}
+
+/*
+ * determine_space - works out whether we need to write a space.
+ * If last glyth is ajoining then no space emitted.
+ */
+
+void html_printer::determine_space (text_glob *g)
+{
+ if (current_paragraph->is_in_pre()) {
+ int space_width = sbuf_style.f->get_space_width(sbuf_style.point_size);
+ /*
+ * .nf has been specified
+ */
+ while (output_hpos < g->minh) {
+ output_hpos += space_width;
+ current_paragraph->emit_space();
+ }
+ } else {
+ if ((output_vpos != g->minv) || (output_hpos < g->minh)) {
+ current_paragraph->emit_space();
+ }
+ }
+}
+
+/*
+ * is_font_courier - returns TRUE if the font, f, is courier.
+ */
+
+int html_printer::is_font_courier (font *f)
+{
+ if (f != 0) {
+ const char *fontname = f->get_name();
+
+ return( (fontname != 0) && (fontname[0] == 'C') );
+ }
+ return( FALSE );
+}
+
+/*
+ * end_font - shuts down the font corresponding to fontname.
+ */
+
+void html_printer::end_font (const char *fontname)
+{
+ if (strcmp(fontname, "B") == 0) {
+ current_paragraph->done_bold();
+ } else if (strcmp(fontname, "I") == 0) {
+ current_paragraph->done_italic();
+ } else if (strcmp(fontname, "BI") == 0) {
+ current_paragraph->done_bold();
+ current_paragraph->done_italic();
+ } else if (strcmp(fontname, "CR") == 0) {
+ current_paragraph->done_tt();
+ current_paragraph->done_pre();
+ }
+}
+
+/*
+ * start_font - starts the font corresponding to name.
+ */
+
+void html_printer::start_font (const char *fontname)
+{
+ if (strcmp(fontname, "R") == 0) {
+ current_paragraph->done_bold();
+ current_paragraph->done_italic();
+ current_paragraph->done_tt();
+ } else if (strcmp(fontname, "B") == 0) {
+ current_paragraph->do_bold();
+ } else if (strcmp(fontname, "I") == 0) {
+ current_paragraph->do_italic();
+ } else if (strcmp(fontname, "BI") == 0) {
+ current_paragraph->do_bold();
+ current_paragraph->do_italic();
+ } else if (strcmp(fontname, "CR") == 0) {
+ if ((! fill_on) && (is_courier_until_eol())) {
+ current_paragraph->do_pre();
+ }
+ current_paragraph->do_tt();
+ }
+}
+
+/*
+ * start_size - from is old font size, to is the new font size.
+ * The html increase <big> and <small> decrease alters the
+ * font size by 20%. We try and map these onto glyph sizes.
+ */
+
+void html_printer::start_size (int from, int to)
+{
+ if (from < to) {
+ while (from < to) {
+ current_paragraph->do_big();
+ from += SIZE_INCREMENT;
+ }
+ } else if (from > to) {
+ while (from > to) {
+ current_paragraph->do_small();
+ from -= SIZE_INCREMENT;
+ }
+ }
+}
+
+/*
+ * do_font - checks to see whether we need to alter the html font.
+ */
+
+void html_printer::do_font (text_glob *g)
+{
+ /*
+ * check if the output_style.point_size has not been set yet
+ * this allow users to place .ps at the top of their troff files
+ * and grohtml can then treat the .ps value as the base font size (3)
+ */
+ if (output_style.point_size == -1) {
+ output_style.point_size = pointsize;
+ }
+
+ if (g->text_style.f != output_style.f) {
+ if (output_style.f != 0) {
+ end_font(output_style.f->get_name());
+ }
+ output_style.f = g->text_style.f;
+ if (output_style.f != 0) {
+ start_font(output_style.f->get_name());
+ }
+ }
+ if (output_style.point_size != g->text_style.point_size) {
+ do_sup_or_sub(g);
+ if ((output_style.point_size > 0) &&
+ (g->text_style.point_size > 0)) {
+ start_size(output_style.point_size, g->text_style.point_size);
+ }
+ if (g->text_style.point_size > 0) {
+ output_style.point_size = g->text_style.point_size;
+ }
+ }
+}
+
+/*
+ * start_subscript - returns TRUE if, g, looks like a subscript start.
+ */
+
+int html_printer::start_subscript (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ return( (output_style.point_size != 0) &&
+ (output_vpos < g->minv) &&
+ (output_vpos-height > g->maxv) &&
+ (output_style.point_size > g->text_style.point_size) );
+}
+
+/*
+ * start_superscript - returns TRUE if, g, looks like a superscript start.
+ */
+
+int html_printer::start_superscript (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ return( (output_style.point_size != 0) &&
+ (output_vpos > g->minv) &&
+ (output_vpos-height < g->maxv) &&
+ (output_style.point_size > g->text_style.point_size) );
+}
+
+/*
+ * end_subscript - returns TRUE if, g, looks like the end of a subscript.
+ */
+
+int html_printer::end_subscript (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ return( (output_style.point_size != 0) &&
+ (g->minv < output_vpos) &&
+ (output_vpos-height > g->maxv) &&
+ (output_style.point_size < g->text_style.point_size) );
+}
+
+/*
+ * end_superscript - returns TRUE if, g, looks like the end of a superscript.
+ */
+
+int html_printer::end_superscript (text_glob *g)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ return( (output_style.point_size != 0) &&
+ (g->minv > output_vpos) &&
+ (output_vpos-height < g->maxv) &&
+ (output_style.point_size < g->text_style.point_size) );
+}
+
+/*
+ * do_sup_or_sub - checks to see whether the next glyph is a subscript/superscript
+ * start/end and it calls the services of html-text to issue the
+ * appropriate tags.
+ */
+
+void html_printer::do_sup_or_sub (text_glob *g)
+{
+ if (! supress_sub_sup) {
+ if (start_subscript(g)) {
+ current_paragraph->do_sub();
+ } else if (start_superscript(g)) {
+ current_paragraph->do_sup();
+ } else if (end_subscript(g)) {
+ current_paragraph->done_sub();
+ } else if (end_superscript(g)) {
+ current_paragraph->done_sup();
+ }
+ }
+}
+
+/*
+ * translate_to_html - translates a textual string into html text
+ */
+
+void html_printer::translate_to_html (text_glob *g)
+{
+ char buf[MAX_STRING_LENGTH];
+
+ do_font(g);
+ determine_space(g);
+ str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH,
+ g->text_string, g->text_length, TRUE);
+ current_paragraph->do_emittext(buf, strlen(buf));
+ output_vpos = g->minv;
+ output_hpos = g->maxh;
+ output_vpos_max = g->maxv;
+ supress_sub_sup = FALSE;
+}
+
+/*
+ * 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,
+ line_number,
+ 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;
+ }
+}
+
+void html_printer::set_line_thickness(const environment *env)
+{
+ line_thickness = env->size;
+}
+
+void html_printer::draw(int code, int *p, int np, const environment *env)
+{
+ switch (code) {
+
+ case 'l':
+ if (np == 2) {
+ page_contents->add_line(&sbuf_style,
+ line_number,
+ env->hpos, env->vpos, env->hpos+p[0], env->vpos+p[1], line_thickness);
+ } 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 0
+ 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);
+#endif
+ }
+ break;
+ case 'E':
+ // fall through
+ case 'e':
+#if 0
+ 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);
+#endif
+ break;
+ case 'C':
+ // fill circle
+
+ case 'c':
+ {
+#if 0
+ // 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);
+#endif
+ }
+ break;
+ case 'a':
+ {
+#if 0
+ 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");
+ }
+#endif
+ }
+ break;
+ case '~':
+ {
+#if 0
+ 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);
+#endif
+ }
+ break;
+ case 'f':
+ {
+#if 0
+ 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;
+ }
+#endif
+ break;
+ }
+
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+}
+
+html_printer::html_printer()
+: html(0, MAX_LINE_LENGTH),
+ no_of_printed_pages(0),
+ sbuf_len(0),
+ output_hpos(-1),
+ output_vpos(-1),
+ output_vpos_max(-1),
+ line_thickness(-1),
+ inside_font_style(0),
+ page_number(0),
+ header_indent(-1),
+ supress_sub_sup(TRUE),
+ cutoff_heading(100),
+ end_center(0),
+ end_tempindent(0),
+ next_tag(INLINE),
+ fill_on(TRUE),
+ pageoffset(0),
+ indentation(0),
+ prev_indent(0),
+ linelength(0),
+ line_number(0)
+{
+#if defined(DEBUGGING)
+ file_list.add_new_file(stdout);
+#else
+ file_list.add_new_file(xtmpfile());
+#endif
+ html.set_file(file_list.get_file());
+ if (font::hor != 24)
+ fatal("horizontal resolution must be 24");
+ if (font::vert != 40)
+ fatal("vertical resolution must be 40");
+#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;
+ linelength = font::res*13/2;
+ if (paper_length == 0)
+ paper_length = 11*font::res;
+
+ page_contents = new page();
+}
+
+/*
+ * 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.
+ */
+
+void html_printer::add_to_sbuf (unsigned char code, const char *name)
+{
+ if (name == 0) {
+ add_char_to_sbuf(code);
+ } else {
+ if (sbuf_style.f != NULL) {
+ char *html_glyph = get_html_translation(sbuf_style.f, name);
+
+ if (html_glyph == NULL) {
+ add_char_to_sbuf(code);
+ } else {
+ int l = strlen(html_glyph);
+ int i;
+
+ // Escape the name, so that "&" doesn't get expanded to "&amp;"
+ // later during translate_to_html.
+ add_char_to_sbuf('\\'); add_char_to_sbuf('(');
+
+ for (i=0; i<l; i++) {
+ add_char_to_sbuf(html_glyph[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) {
+ add_to_sbuf(code, name);
+ 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/2) {
+ add_to_sbuf(code, name);
+ 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 );
+ }
+}
+
+/*
+ * 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, const char *name)
+{
+ int index;
+
+ if ((f == 0) || (name == 0) || (strcmp(name, "") == 0)) {
+ return( NULL );
+ } else {
+ index = f->name_to_index((char *)name);
+ if (index == 0) {
+ error("character `%s' not found", name);
+ return( NULL );
+ } else {
+ if (f->contains(index)) {
+ return( (char *)f->get_special_device_encoding(index) );
+ } else {
+ return( NULL );
+ }
+ }
+ }
+}
+
+/*
+ * to_unicode - returns a unicode translation of char, ch.
+ */
+
+static char *to_unicode (unsigned char ch)
+{
+ static char buf[20];
+
+ sprintf(buf, "&#%u;", (unsigned int)ch);
+ return( buf );
+}
+
+/*
+ * char_translate_to_html - convert a single non escaped character
+ * into the appropriate html character.
+ */
+
+int char_translate_to_html (font *f, char *buf, int buflen, unsigned char ch, int b, int and_single)
+{
+ if (and_single) {
+ int t, l;
+ char *translation;
+ char name[2];
+
+ name[0] = ch;
+ name[1] = (char)0;
+ translation = get_html_translation(f, name);
+ if ((translation == NULL) && (ch >= UNICODE_DESC_START)) {
+ translation = to_unicode(ch);
+ }
+ 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] = ch;
+ b++;
+ }
+ }
+ } else {
+ /*
+ * do not attempt to encode single characters
+ */
+ if (b<buflen) {
+ buf[b] = ch;
+ b++;
+ }
+ }
+ return( b );
+}
+
+/*
+ * 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)
+{
+ char *translation;
+ int e;
+ char escaped_char[MAX_STRING_LENGTH];
+ int l;
+ 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 (f->contains(index) && (index != 0)) {
+ buf[b] = f->get_code(index);
+ b++;
+ }
+ }
+ }
+ } else {
+ b = char_translate_to_html(f, buf, buflen, str[i], b, and_single);
+ i++;
+ }
+ } else {
+ b = char_translate_to_html(f, buf, buflen, str[i], b, and_single);
+ i++;
+ }
+ }
+ buf[min(b, buflen)] = (char)0;
+}
+
+/*
+ * 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 ((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);
+ sbuf_end_hpos = env->hpos + w;
+ sbuf_start_hpos = env->hpos;
+ sbuf_vpos = env->vpos;
+ sbuf_style = sty;
+ sbuf_kern = 0;
+ }
+}
+
+/*
+ * 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>").nl().nl();
+ } else {
+ title.has_been_written = TRUE;
+ html.put_string("<h1 align=center>");
+ html.put_string(title.text);
+ html.put_string("</h1>").nl().nl();
+ }
+ } else if (in_head) {
+ // place empty title tags to help conform to `tidy'
+ html.put_string("<title></title>").nl();
+ }
+}
+
+/*
+ * write_rule - emits a html rule tag, if the auto_rule boolean is true.
+ */
+
+static void write_rule (void)
+{
+ if (auto_rule)
+ fputs("<hr>\n", stdout);
+}
+
+void html_printer::begin_page(int n)
+{
+ page_number = n;
+#if defined(DEBUGGING)
+ html.begin_comment("Page: ").put_string(i_to_a(page_number)).end_comment();;
+#endif
+ no_of_printed_pages++;
+
+ output_style.f = 0;
+ output_style.point_size= -1;
+ output_space_code = 32;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ output_hpos = -1;
+ output_vpos = -1;
+ output_vpos_max = -1;
+ current_paragraph = new html_text(&html);
+#if defined(INDENTATION)
+ current_paragraph->do_indent(indent.text, indentation, pageoffset, linelength);
+#endif
+ current_paragraph->do_para("");
+}
+
+void html_printer::end_page(int)
+{
+ flush_sbuf();
+ flush_page();
+}
+
+font *html_printer::make_font(const char *nm)
+{
+ return html_font::load_html_font(nm);
+}
+
+html_printer::~html_printer()
+{
+ current_paragraph->flush_text();
+ html.end_line();
+ html.set_file(stdout);
+ /*
+ * 'HTML: The definitive guide', O'Reilly, p47. advises against specifying
+ * the dtd, so for the moment I'll leave this commented out.
+ * If requested we could always emit it if a command line switch
+ * was present.
+ *
+ * fputs("<!doctype html public \"-//IETF//DTD HTML 4.0//EN\">\n", stdout);
+ */
+ fputs("<html>\n", stdout);
+ fputs("<head>\n", stdout);
+ fputs("<meta name=\"generator\" content=\"groff -Thtml, see www.gnu.org\">\n", stdout);
+ fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
+ write_title(TRUE);
+ fputs("</head>\n", stdout);
+ fputs("<body>\n\n", stdout);
+ write_title(FALSE);
+ header.write_headings(stdout, FALSE);
+ write_rule();
+ {
+ extern const char *Version_string;
+ html.begin_comment("Creator : ")
+ .put_string("groff ")
+ .put_string("version ")
+ .put_string(Version_string)
+ .end_comment();
+ }
+ {
+#ifdef LONG_FOR_TIME_T
+ long
+#else
+ time_t
+#endif
+ t = time(0);
+ html.begin_comment("CreationDate: ")
+ .put_string(ctime(&t), strlen(ctime(&t))-1)
+ .end_comment();
+ }
+#if defined(DEBUGGING)
+ html.begin_comment("Total number of pages: ").put_string(i_to_a(no_of_printed_pages)).end_comment();
+#endif
+ html.end_line();
+ html.end_line();
+ /*
+ * now run through the file list copying each temporary file in turn and emitting the links.
+ */
+ file_list.start_of_list();
+ while (file_list.get_file() != 0) {
+ if (fseek(file_list.get_file(), 0L, 0) < 0)
+ fatal("fseek on temporary file failed");
+ html.copy_file(file_list.get_file());
+ fclose(file_list.get_file());
+ file_list.move_next();
+ if (file_list.get_file() != 0)
+ header.write_headings(stdout, TRUE);
+ }
+ write_rule();
+ fputs("</body>\n", stdout);
+ fputs("</html>\n", stdout);
+}
+
+/*
+ * special - handle all x X requests from troff. For post-html they allow users
+ * to pass raw html commands, turn auto linked headings off/on and
+ * also allow troff to emit tags to indicate when a: .br, .sp etc occurs.
+ */
+
+void html_printer::special(char *s, const environment *env, char type)
+{
+ if (type != 'p')
+ return;
+ if (s != 0) {
+ flush_sbuf();
+ if (env->fontno >= 0) {
+ style sty(get_font_from_index(env->fontno), env->size, env->height, env->slant, env->fontno);
+ sbuf_style = sty;
+ }
+
+ 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);
+
+ /*
+ * need to pass rest of string through to html output during flush
+ */
+ page_contents->add_html(&sbuf_style, buf, strlen(buf),
+ line_number,
+ env->vpos-env->size*r/72, env->hpos,
+ env->vpos , env->hpos);
+
+ /*
+ * assume that the html command has no width, if it does then hopefully troff
+ * will have fudged this in a macro by requesting that the formatting move right by
+ * the appropriate width.
+ */
+ } else if (strncmp(s, "index:", 6) == 0) {
+ cutoff_heading = atoi(&s[6]);
+ } else if (strncmp(s, "html-tag:", 9) == 0) {
+ int r=font::res; /* resolution of the device */
+
+ page_contents->add_tag(&sbuf_style, s, strlen(s),
+ line_number,
+ env->vpos-env->size*r/72, env->hpos,
+ env->vpos , env->hpos);
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((c = getopt_long(argc, argv, "o:i:F:vd?lrn", long_options, NULL))
+ != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU post-grohtml (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'l':
+ auto_links = FALSE;
+ break;
+ case 'r':
+ auto_rule = FALSE;
+ break;
+ case 'o':
+ /* handled by pre-html */
+ break;
+ case 'i':
+ /* handled by pre-html */
+ break;
+ case 'n':
+ simple_anchors = TRUE;
+ break;
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-vld?n] [-F dir] [files ...]\n",
+ program_name);
+}
diff --git a/contrib/groff/src/devices/grolbp/Makefile.sub b/contrib/groff/src/devices/grolbp/Makefile.sub
new file mode 100644
index 0000000..d60008b
--- /dev/null
+++ b/contrib/groff/src/devices/grolbp/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=grolbp
+MAN1=grolbp.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=lbp.o
+CCSRCS=$(srcdir)/lbp.cc
diff --git a/contrib/groff/src/devices/grolbp/charset.h b/contrib/groff/src/devices/grolbp/charset.h
new file mode 100644
index 0000000..adc76f4
--- /dev/null
+++ b/contrib/groff/src/devices/grolbp/charset.h
@@ -0,0 +1,69 @@
+// Definition of the WP54 character set
+
+char symset[] = {
+0x57,0x50,0x35,0x34,0x00,0x41,0x76,0x61,0x6e,0x74,0x47,0x61,
+0x72,0x64,0x65,0x2d,0x42,0x6f,0x6f,0x6b,0x00,0x41,0x76,
+0x61,0x6e,0x74,0x47,0x61,0x72,0x64,0x65,0x2d,0x44,0x65,
+0x6d,0x69,0x00,0x41,0x76,0x61,0x6e,0x74,0x47,0x61,0x72,
+0x64,0x65,0x2d,0x42,0x6f,0x6f,0x6b,0x4f,0x62,0x6c,0x69,
+0x71,0x75,0x65,0x00,0x41,0x76,0x61,0x6e,0x74,0x47,0x61,
+0x72,0x64,0x65,0x2d,0x44,0x65,0x6d,0x69,0x4f,0x62,0x6c,
+0x69,0x71,0x75,0x65,0x00,0x42,0x6f,0x6f,0x6b,0x6d,0x61,
+0x6e,0x2d,0x4c,0x69,0x67,0x68,0x74,0x00,0x42,0x6f,0x6f,
+0x6b,0x6d,0x61,0x6e,0x2d,0x44,0x65,0x6d,0x69,0x00,0x42,
+0x6f,0x6f,0x6b,0x6d,0x61,0x6e,0x2d,0x4c,0x69,0x67,0x68,
+0x74,0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x42,0x6f,0x6f,
+0x6b,0x6d,0x61,0x6e,0x2d,0x44,0x65,0x6d,0x69,0x49,0x74,
+0x61,0x6c,0x69,0x63,0x00,0x43,0x65,0x6e,0x74,0x75,0x72,
+0x79,0x53,0x63,0x68,0x6c,0x62,0x6b,0x2d,0x52,0x6f,0x6d,
+0x61,0x6e,0x00,0x43,0x65,0x6e,0x74,0x75,0x72,0x79,0x53,
+0x63,0x68,0x6c,0x62,0x6b,0x2d,0x42,0x6f,0x6c,0x64,0x00,
+0x43,0x65,0x6e,0x74,0x75,0x72,0x79,0x53,0x63,0x68,0x6c,
+0x62,0x6b,0x2d,0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x43,
+0x65,0x6e,0x74,0x75,0x72,0x79,0x53,0x63,0x68,0x6c,0x62,
+0x6b,0x2d,0x42,0x6f,0x6c,0x64,0x49,0x74,0x61,0x6c,0x69,
+0x63,0x00,0x44,0x75,0x74,0x63,0x68,0x2d,0x52,0x6f,0x6d,
+0x61,0x6e,0x00,0x44,0x75,0x74,0x63,0x68,0x2d,0x42,0x6f,
+0x6c,0x64,0x00,0x44,0x75,0x74,0x63,0x68,0x2d,0x49,0x74,
+0x61,0x6c,0x69,0x63,0x00,0x44,0x75,0x74,0x63,0x68,0x2d,
+0x42,0x6f,0x6c,0x64,0x49,0x74,0x61,0x6c,0x69,0x63,0x00,
+0x53,0x77,0x69,0x73,0x73,0x00,0x53,0x77,0x69,0x73,0x73,
+0x2d,0x42,0x6f,0x6c,0x64,0x00,0x53,0x77,0x69,0x73,0x73,
+0x2d,0x4f,0x62,0x6c,0x69,0x71,0x75,0x65,0x00,0x53,0x77,
+0x69,0x73,0x73,0x2d,0x42,0x6f,0x6c,0x64,0x4f,0x62,0x6c,
+0x69,0x71,0x75,0x65,0x00,0x53,0x77,0x69,0x73,0x73,0x2d,
+0x4e,0x61,0x72,0x72,0x6f,0x77,0x00,0x53,0x77,0x69,0x73,
+0x73,0x2d,0x4e,0x61,0x72,0x72,0x6f,0x77,0x2d,0x42,0x6f,
+0x6c,0x64,0x00,0x53,0x77,0x69,0x73,0x73,0x2d,0x4e,0x61,
+0x72,0x72,0x6f,0x77,0x2d,0x4f,0x62,0x6c,0x69,0x71,0x75,
+0x65,0x00,0x53,0x77,0x69,0x73,0x73,0x2d,0x4e,0x61,0x72,
+0x72,0x6f,0x77,0x2d,0x42,0x6f,0x6c,0x64,0x4f,0x62,0x6c,
+0x69,0x71,0x75,0x65,0x00,0x5a,0x61,0x70,0x66,0x43,0x61,
+0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x2d,
+0x52,0x6f,0x6d,0x61,0x6e,0x00,0x5a,0x61,0x70,0x66,0x43,
+0x61,0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68,0x69,0x63,
+0x2d,0x42,0x6f,0x6c,0x64,0x00,0x5a,0x61,0x70,0x66,0x43,
+0x61,0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68,0x69,0x63,
+0x2d,0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x5a,0x61,0x70,
+0x66,0x43,0x61,0x6c,0x6c,0x69,0x67,0x72,0x61,0x70,0x68,
+0x69,0x63,0x2d,0x42,0x6f,0x6c,0x64,0x49,0x74,0x61,0x6c,
+0x69,0x63,0x00,0x5a,0x61,0x70,0x66,0x43,0x68,0x61,0x6e,
+0x63,0x65,0x72,0x79,0x2d,0x4d,0x65,0x64,0x69,0x75,0x6d,
+0x49,0x74,0x61,0x6c,0x69,0x63,0x00,0x00,0x09,0x00,0x0A,
+0x00,0x0B,0x00,0x0E,0x00,0x14,0x00,0x17,0x00,0x18,0x00,
+0x1F,0x00,0x20,0x00,0x36,0x00,0x37,0x00,0x38,0x00,0x45,0x00,
+0x47,0x00,0x48,0x00,0x80,0x00,0x82,0x00,0x83,0x00,0x84,
+0x00,0x85,0x00,0x87,0x00,0x8B,0x00,0x8C,0x00,0x8D,0x00,0x8E,
+0x00,0x8F,0x00,0x90,0x00,0x91,0x00,0x92,0x00,0x95,0x00,0x96,
+0x00,0x97,0x00,0x98,0x00,0x99,0x00,0x9C,0x00,0x9E,0x00,
+0x9F,0x00,0xA0,0x00,0xA1,0x00,0xA2,0x00,0xA3,0x00,0xCB,0x00,
+0xCC,0x00,0xCD,0x00,0xCE,0x00,0xD1,0x00,0xD3,0x00,0xD4,
+0x00,0xD5,0x00,0xD6,0x00,0xFA,0x00,0xFB,0x00,0xFC,0x00,0xFD,
+0x00,0xCF,0x00,0x26,0x00,0x7E,0x03,0x05,0x00,0xA5,0x00,
+0xA6,0x00,0xA8,0x00,0xAA,0x00,0xAD,0x00,0xAE,0x00,0xAF,0x00,
+0xB0,0x00,0xB1,0x00,0xB2,0x00,0xB3,0x00,0xB5,0x00,0xB6,0x00,
+0xB8,0x00,0xB9,0x00,0xBA,0x00,0xBB,0x00,0xBC,0x00,0xBE,
+0x00,0xBF,0x00,0xC0,0x00,0xC1,0x00,0xC6,0x00,0xDC,0x00,0xEB,
+0x00,0xEC,0x00,0xF2,0x00,0xF3,0x00,0x15,0x00,0x16,0x00,
+0x86
+};
diff --git a/contrib/groff/src/devices/grolbp/grolbp.man b/contrib/groff/src/devices/grolbp/grolbp.man
new file mode 100644
index 0000000..d567c1a
--- /dev/null
+++ b/contrib/groff/src/devices/grolbp/grolbp.man
@@ -0,0 +1,357 @@
+'\" t
+.\" The above line should force the use of tbl as a preprocessor
+.\" vim: set syntax=nroff :
+.\" The above line should set vim into nroff mode
+.ig
+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.
+
+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.
+
+Modified by Francisco Andrés Verdú <pandres@dragonet.es> for the grolbp
+program.
+..
+.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 GROLBP @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grolbp \- groff driver for Canon CAPSL printers (LBP-4 and LBP-8 series laser printers).
+.SH SYNOPSIS
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBgrolbp 'u
+.ti \niu
+.B grolpb
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-l
+.OP \-\-landscape
+.OP \-v
+.OP \-\-version
+.OP \-c n
+.OP \-\-copies= numcopies
+.OP \-p paper_size
+.OP \-\-papersize= paper_size
+.OP \-o orientation
+.OP \-\-orientation= orientation
+.OP \-F dir
+.OP \-\-fontdir= dir
+.OP \-h
+.OP \-\-help
+.RI "[\ " files\|.\|.\|. "\ ]"
+.br
+.ad \na
+.SH DESCRIPTION
+.B grolbp
+is a driver for
+.B groff
+that produces output in CAPSL and VDM format suitable for Canon LBP\-4 and
+LBP\-8 printers.
+.LP
+For compatibility with grolj4 there is an additional drawing command
+available:
+.TP
+.BI \eD'R\ dh\ dv '
+Draw a rule (i.e.\ a solid black rectangle), with one corner at the current
+position, and the diagonally opposite corner at the current position
+.RI +( dh , dv ).
+.SH OPTIONS
+Note that there can be whitespace between a one-letter option and its
+argument; on the other hand, there must be whitespace and/or an equal sign
+(`=') between a long-name option and its argument.
+.TP
+.BI \-c numcopies
+.TQ
+.BI \-\-copies= numcopies
+Print
+.I numcopies
+copies of each page.
+.TP
+.B \-l
+.TQ
+.B \-\-landscape
+Print the document with a landscape orientation.
+.TP
+.BI \-p paper_size
+.TQ
+.BI \-\-papersize= paper_size
+Set the paper size to
+.IR paper_size ,
+which must be a valid paper size description as indicated in the section
+.BR "PAPER SIZES" .
+.TP
+.BI \-o orientation
+.TQ
+.BI \-\-orientation= orientation
+Print the document with
+.I orientation
+orientation, which must be `portrait' or `landscape'.
+.TP
+.B \-v
+.TQ
+.B \-\-version
+Print the version number.
+.TP
+.BI \-F dir
+.TQ
+.BI \-\-fontdir= dir
+Prepend directory
+.IB dir /devlbp
+to the search path for font and device description files.
+.TP
+.B \-h
+.TQ
+.B \-\-help
+Print a short help text.
+.SH TYPEFACES
+The driver supports the Dutch, Swiss and Swiss-Narrow scalable typefaces,
+each one in the Regular, Bold, Italic and Bold-Italic styles.
+Additionally, the Courier and Elite monospaced typefaces at the sizes 8 and
+12 points (for Courier) resp. 8 and 10 points (for Elite) are supported,
+each one in the Regular, Bold and Italic styles.
+.PP
+The following chart summarizes the font names you can use to access these
+fonts:
+.PP
+.TS
+tab(|) allbox center;
+c c c c c
+ab c c c c
+.
+Typeface | Regular | Bold | Italic | Bold-Italic
+Dutch | TR | TB | TI | TBI
+Swiss | HR | HB | HI | HBI
+Swiss Narrow | HNR | HNB | HNI | HNBI
+Courier | CR | CB | CI |
+Elite | ER | EB | EI |
+.TE
+.PP
+.SH PAPER SIZES
+The paper size can be set in the
+.B DESC
+file or with command line options to
+.BR grolbp .
+If the paper size is specified both ways, the command line options take
+precedence over the contents of the
+.B DESC
+file (this applies to the page orientation too).
+.PP
+To set the paper size in the
+.B DESC
+file, insert in that file a line containing
+.B papersize
+.IR desired_papersize ,
+where
+.I desired_papersize
+is:
+.IP \(bu 4
+One of the recognized paper sizes: `a4', `letter', `legal' or `executive'.
+.IP \(bu 4
+A custom defined paper size, as described in the
+.B CUSTOM PAPER SIZES
+subsection below.
+.IP \(bu 4
+The name of a file (e.g.
+.IR /etc/papersize )
+whose first line must be the desired paper size in one of the above formats.
+.PP
+If there are various papersize lines in the
+.B DESC
+file, only the first valid one is used.
+.PP
+To set the paper size in the command line, add
+.sp 1
+.in +2m
+.BI \-p \ desired_papersize
+.in -2m
+.sp 1
+or
+.sp 1
+.in +2m
+.BI \-\-papersize= desired_papersize
+.in -2m
+.sp 1
+to the other
+.B grolbp
+options, where
+.B desired_papersize
+is in the same format as in the
+.B DESC
+file.
+.PP
+Paper sizes are case insensitive (i.e., `A4' is the same as `a4').
+.PP
+If no paper size is specified in the
+.B DESC
+file or the command line, a default size of A4 is used.
+.TP
+.SH CUSTOM PAPER SIZES
+Custom defined paper sizes are in the form
+.BI cust length x width
+where
+.I length
+and
+.I width
+are the dimensions of the paper you want to to use, specified in printer
+units (1/300 of an inch).
+For instance, to print in a postcard sized paper which is two inches long
+and four inches wide you can insert a line containing
+.sp 1
+.in +2m
+.B papersize cust600x1200
+.in -2m
+.sp 1
+at the beginning of the
+.B DESC
+file.
+.SH PAGE ORIENTATION
+As with the page size, the orientation of the printed page
+.RB ( portrait
+or
+.BR landscape )
+can be set in the
+.B DESC
+file or with command line options.
+It is also case insensitive.
+.PP
+To set the orientation in the
+.B DESC
+file, insert a line with the following content:
+.sp 1
+.in +2m
+.B orientation
+.RB [ portrait | landscape ]
+.in -2m
+.sp 1
+As with paper sizes, only the first valid orientation command in the
+.B DESC
+file is used.
+.PP
+To set the page orientation with command line options you can use the
+.B \-o
+or
+.B \-\-orientation
+option with the same parameters
+.RB ( portrait
+or
+.BR landscape )
+as in the
+.B DESC
+file.
+Or you can use the
+.B \-l
+option to force the pages to be printed in landscape.
+.SH FONT FILE FORMAT
+In addition to the usual commands described in
+.BR groff_font (@MAN5EXT@),
+.B grolbp
+provides the command
+.I lbpname
+which sets the font name sent to the printer when requesting this font.
+The syntax of this command is:
+.sp 1
+.in +2m
+.B lbpname
+.I printer_font_name
+.in -2m
+.IP \(bu
+For bitmapped fonts,
+.I printer_font_name
+has the form
+.sp 1
+.in +2m
+.RI N\(la base_fontname \(ra\(la font_style \(ra
+.in -2m
+.sp 1
+.I base_fontname
+is the font name as it appears in the printers font listings without the
+first letter, up to (but not including) the font size.
+.I font_style
+can be one of the letters
+.BR R ,
+.BR I ,
+or
+.BR B ,
+indicating the font styles Roman, Italic and Bold respectively.
+.IP
+For instance, if the printer's
+.I font listing A
+shows font `Nelite12I.ISO_USA', the corresponding entry in the font
+description file is
+.sp 1
+.in +2m
+.B lbpname NeliteI
+.in -2m
+.IP
+Note that you may need to modify
+.B grolbp
+to add support for new bitmapped fonts, since the available font names and
+font sizes of bitmapped fonts (as documented above) are hard-coded into the
+program.
+.IP \(bu
+For scalable fonts,
+.I printer_font_name
+is identical to the font name as it appears in the printer's
+.IR "font listing A" .
+.IP
+For instance, to select the `Swiss' font in bold style, which appears in
+the printer's
+.I font listing A
+as `Swiss-Bold', the required
+.B lbpname
+command line is
+.sp 1
+.in +2m
+.B lbpname Swiss-Bold
+.in -2m
+.sp 1
+.PP
+The argument of
+.B lbpname
+is case sensitive.
+.SH FILES
+.TP
+.B @FONTDIR@/devlbp/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devlbp/ F
+Font description file for font
+.IR F .
+.TP
+.B @MACRODIR@/lbp.tmac
+Macros for use with
+.BR grolbp .
+.SH SEE ALSO
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
+.\"
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
diff --git a/contrib/groff/src/devices/grolbp/lbp.cc b/contrib/groff/src/devices/grolbp/lbp.cc
new file mode 100644
index 0000000..69196af
--- /dev/null
+++ b/contrib/groff/src/devices/grolbp/lbp.cc
@@ -0,0 +1,765 @@
+// -*- C++ -*-
+/* Copyright (C) 1994, 2000, 2001 Free Software Foundation, Inc.
+ Written by Francisco Andrés Verdú <pandres@dragonet.es> with many ideas
+ taken from the other groff drivers.
+
+
+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
+
+ - Add X command to include bitmaps
+*/
+#define _GNU_SOURCE
+
+#include "driver.h"
+#include "lbp.h"
+#include "charset.h"
+
+#include "nonposix.h"
+
+static short int papersize = -1, // papersize
+ orientation = -1 , // orientation
+ paperlength = 0, // Custom Paper size
+ paperwidth = 0,
+ ncopies = 1; // Number of copies
+
+class lbp_font : public font {
+public:
+ ~lbp_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static lbp_font *load_lbp_font(const char *);
+ char *lbpname;
+ char is_scalable;
+private:
+ lbp_font(const char *);
+};
+
+class lbp_printer : public printer {
+public:
+ lbp_printer();
+ ~lbp_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 vdmstart();
+ void vdmflush(); // the name vdmend was already used in lbp.h
+ void setfillmode(int mode);
+ void polygon( int hpos,int vpos,int np,int *p);
+ char *font_name(const lbp_font *f, const int siz);
+
+ int fill_pattern;
+ int fill_mode;
+ int cur_hpos;
+ int cur_vpos;
+ lbp_font *cur_font;
+ int cur_size;
+ unsigned short cur_symbol_set;
+ int line_thickness;
+};
+
+// Compatibility section.
+//
+// Here we define some functions not present in some of the targets
+// platforms
+#ifndef HAVE_STRSEP
+// Solaris 8 doesn't have the strsep function
+static char *strsep(char **pcadena, const char *delim)
+{
+ char *p;
+
+ p = strtok(*pcadena,delim);
+ *pcadena = strtok(NULL,delim);
+ return p;
+
+};
+#endif
+
+#ifndef HAVE_STRDUP
+// Ditto with OS/390 and strdup
+static char *strdup(const char *s)
+{
+ char *result;
+
+ result = (char *)malloc(strlen(s)+1);
+ if (result != NULL) strcpy(result,s);
+ return result;
+
+}; // strdup
+
+#endif
+lbp_font::lbp_font(const char *nm)
+: font(nm)
+{
+}
+
+lbp_font::~lbp_font()
+{
+}
+
+lbp_font *lbp_font::load_lbp_font(const char *s)
+{
+ lbp_font *f = new lbp_font(s);
+ f->lbpname = NULL;
+ f->is_scalable = 1; // Default is that fonts are scalable
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+
+void lbp_font::handle_unknown_font_command(const char *command,
+ const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "lbpname") == 0) {
+ if (arg == 0)
+ fatal_with_file_and_line(filename, lineno,
+ "`%1' command requires an argument",
+ command);
+ this->lbpname = new char[strlen(arg)+1];
+ strcpy(this->lbpname,arg);
+ // We Recongnize bitmaped fonts by the first character of it's name
+ if (arg[0] == 'N') this->is_scalable = 0;
+ // fprintf(stderr,"Loading font \"%s\" \n",arg);
+ }; // if (strcmp(command, "lbpname")
+ // fprintf(stderr,"Loading font %s \"%s\" in %s at %d\n",command,arg,filename,lineno);
+};
+
+static void wp54charset()
+{
+ int i;
+
+ lbpputs("\033[714;100;29;0;32;120.}");
+ for (i = 0; i < sizeof(symset) ; i++) lbpputc(symset[i]);
+ lbpputs("\033[100;0 D");
+ return ;
+};
+
+lbp_printer::lbp_printer()
+: fill_pattern(1),
+ fill_mode(0),
+ cur_hpos(-1),
+ cur_font(0),
+ cur_size(0),
+ cur_symbol_set(0),
+ line_thickness(-1)
+{
+#ifdef SET_BINARY
+ SET_BINARY(fileno(stdout));
+#endif
+ lbpinit(stdout);
+ lbpputs("\033c\033;\033[2&z\033[7 I\033[?32h\033[?33h\033[11h");
+ wp54charset(); // Define the new symbol set
+ lbpputs("\033[7 I\033[?32h\033[?33h\033[11h");
+ // Paper size handling
+ if (orientation < 0) orientation = 0;// Default orientation is portrait
+ if (papersize < 0) papersize = 14; // Default paper size is A4
+ if (papersize < 80) // standard paper
+ lbpprintf("\033[%dp",(papersize | orientation));
+ else // Custom paper
+ lbpprintf("\033[%d;%d;%dp",(papersize | orientation),\
+ paperlength,paperwidth);
+
+ // Number of copies
+ lbpprintf("\033[%dv\n",ncopies);
+
+ lbpputs("\033[0u\033[1u\033P1y Grolbp\033\\");
+ lbpmoveabs(0,0);
+ lbpputs("\033[0t\033[2t");
+ lbpputs("\033('$2\033)' 1"); // Primary symbol set IBML
+ // Secondary symbol set IBMR1
+ cur_symbol_set = 0;
+};
+
+lbp_printer::~lbp_printer()
+{
+ lbpputs("\033P1y\033\\");
+ lbpputs("\033c\033<");
+}
+
+void lbp_printer::begin_page(int)
+{
+}
+
+void lbp_printer::end_page(int)
+{
+ if (vdminited()) vdmflush();
+ lbpputc('\f');
+ cur_hpos = -1;
+}
+
+void lbp_printer::end_of_line()
+{
+ cur_hpos = -1; // force absolute motion
+}
+
+char *lbp_printer::font_name(const lbp_font *f, const int siz)
+{
+ static char bfont_name[255] ; // The resulting font name
+ char type, // Italic, Roman, Bold
+ ori, // Normal or Rotated
+ *nam; // The font name without other data.
+// nam[strlen(f->lbpname)-2]; // The font name without other data.
+ int cpi; // The font size in characters per inch
+ // (Bitmaped fonts are monospaced).
+
+
+ /* Bitmap font selection is ugly in this printer, so don't expect
+ this function to be elegant. */
+
+ bfont_name[0] = 0x00;
+ if (orientation) // Landscape
+ ori = 'R';
+ else // Portrait
+ ori = 'N';
+ type = f->lbpname[strlen(f->lbpname)-1];
+ nam = new char[strlen(f->lbpname)-2];
+ strncpy(nam,&(f->lbpname[1]),strlen(f->lbpname)-2);
+ nam[strlen(f->lbpname)-2] = 0x00;
+ // fprintf(stderr,"Bitmap font '%s' %d %c %c \n",nam,siz,type,ori);
+ /* Since these fonts are avaiable only at certain sizes,
+ 10 and 17 cpi for courier, 12 and 17 cpi for elite,
+ we adjust the resulting size. */
+ cpi = 17;
+ // Fortunately there were only two bitmaped fonts shiped with the printer.
+ if (!strcasecmp(nam,"courier"))
+ { // Courier font
+ if (siz >= 12) cpi = 10;
+ else cpi = 17;
+ };
+ if (!strcasecmp(nam,"elite"))
+ { // Elite font
+ if (siz >= 10) cpi = 12;
+ else cpi = 17;
+ };
+
+ // Now that we have all the data, let's generate the font name.
+ if ((type != 'B') && (type != 'I')) // Roman font
+ sprintf(bfont_name,"%c%s%d",ori,nam,cpi);
+ else
+ sprintf(bfont_name,"%c%s%d%c",ori,nam,cpi,type);
+
+ return bfont_name;
+
+}; // lbp_printer::font_name
+
+void lbp_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 (f != cur_font) {
+ lbp_font *psf = (lbp_font *)f;
+ // fprintf(stderr,"Loading font %s \"%d\" \n",psf->lbpname,env->size);
+ if (psf->is_scalable)
+ { // Scalable font selection is different from bitmaped
+ lbpprintf("\033Pz%s.IBML\033\\\033[%d C",psf->lbpname,\
+ (int)((env->size*300)/72));
+ } else
+ { // Bitmaped font
+ lbpprintf("\033Pz%s.IBML\033\\\n",font_name(psf,env->size));
+ };
+ lbpputs("\033)' 1"); // Select IBML and IBMR1 symbol set
+ cur_size = env->size;
+ cur_font = psf;
+ cur_symbol_set = 0;
+ }
+ if (symbol_set != cur_symbol_set) {
+ if ( cur_symbol_set == 3 ) {
+ // if current symbol set is Symbol we must restore the font
+ lbpprintf("\033Pz%s.IBML\033\\\033[%d C",cur_font->lbpname,\
+ (int)((env->size*300)/72));
+ }; // if ( cur_symbol_set == 3 )
+ switch (symbol_set) {
+ case 0: lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets
+ break;
+ case 1: lbpputs("\033(d\033)' 1"); // Select wp54 symbol set
+ break;
+ case 2: lbpputs("\033('$2\033)'!0"); // Select IBMP symbol set
+ break;
+ case 3: lbpprintf("\033PzSymbol.SYML\033\\\033[%d C",\
+ (int)((env->size*300)/72));
+ lbpputs("\033(\"!!0\033)\"!!1"); // Select symbol font
+ break;
+ case 4: lbpputs("\033)\"! 1\033(\"!$2"); // Select PS symbol set
+ break;
+ }; // switch (symbol_set)
+
+// if (symbol_set == 1) lbpputs("\033(d"); // Select wp54 symbol set
+// else lbpputs("\033('$2\033)' 1"); // Select IBML and IBMR1 symbol sets
+ cur_symbol_set = symbol_set;
+ }
+ if (env->size != cur_size) {
+
+ if (!cur_font->is_scalable)
+ lbpprintf("\033Pz%s.IBML\033\\\n",font_name(cur_font,env->size));
+ else
+ lbpprintf("\033[%d C",(int)((env->size*300)/72));
+ cur_size = env->size;
+ }
+ if ((env->hpos != cur_hpos) || (env->vpos != cur_vpos))
+ {
+ // lbpmoveabs(env->hpos - ((5*300)/16),env->vpos );
+ lbpmoveabs(env->hpos - 64,env->vpos - 64 );
+ cur_vpos = env->vpos;
+ cur_hpos = env->hpos;
+ };
+ if ((ch & 0x7F) < 32) lbpputs("\033[1.v");
+ lbpputc(ch);
+ cur_hpos += w;
+};
+
+void
+lbp_printer::vdmstart()
+{
+ FILE *f;
+ static int changed_origin = 0;
+
+ errno = 0;
+ f = tmpfile();
+ // f = fopen("/tmp/gtmp","w+");
+ if (f == NULL) perror("Openinig temp file");
+ vdminit(f);
+ if (!changed_origin) { // we should change the origin only one time
+ changed_origin = 1;
+ vdmorigin(-63,0);
+ };
+ vdmlinewidth(line_thickness);
+
+};
+
+void
+lbp_printer::vdmflush()
+{
+ char buffer[1024];
+ int bytes_read = 1;
+
+ vdmend();
+ fflush(lbpoutput);
+ /* lets copy the vdm code to the output */
+ rewind(vdmoutput);
+ do
+ {
+ bytes_read = fread(buffer,1,sizeof(buffer),vdmoutput);
+ bytes_read = fwrite(buffer,1,bytes_read,lbpoutput);
+ } while ( bytes_read == sizeof(buffer));
+
+ fclose(vdmoutput); // This will also delete the file,
+ // since it is created by tmpfile()
+ vdmoutput = NULL;
+
+}; // lbp_printer::vdmflush
+
+inline void
+lbp_printer::setfillmode(int mode)
+{
+ if (mode != fill_mode) {
+ if (mode != 1) vdmsetfillmode(mode,1,0);
+ else vdmsetfillmode(mode,1,1); // To get black we must use white
+ // inverted
+ fill_mode = mode;
+ };
+}; // setfillmode
+
+inline void
+lbp_printer::polygon( int hpos,int vpos,int np,int *p)
+{
+ //int points[np+2],i;
+ int *points,i;
+
+ points = new int[np+2];
+ points[0] = hpos;
+ points[1] = vpos;
+/* fprintf(stderr,"Poligon (%d,%d) ", points[0],points[1]);*/
+ for (i = 0; i < np; i++) points[i+2] = p[i];
+/* for (i = 0; i < np; i++) fprintf(stderr," %d ",p[i]);
+ fprintf(stderr,"\n"); */
+ vdmpolygon((np /2) + 1,points);
+};
+
+void lbp_printer::draw(int code, int *p, int np, const environment *env)
+{
+ switch (code) {
+ 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;
+ } // if (np != ...
+ if (p[0] == 0) line_thickness = 1;
+ if (p[0] < 0) // Default = 1 point
+ line_thickness = (int)(env->size*30/72);
+ line_thickness = (int)((abs(p[0])*env->size)/10);
+ if ((line_thickness > 16 ) && (!vdminited()))
+ { /* for greater thickness we must use VDM */
+ vdmstart();
+ /* vdmlinewidth(line_thickness); already done in
+ * vdmstart() */
+ };
+ if (vdminited()) vdmlinewidth(line_thickness);
+ // fprintf(stderr,"\nthickness: %d == %d, size %d\n",
+ // p[0],line_thickness,env->size );
+ } // else
+ break;
+
+ case 'l': // Line
+ if (np != 2) {
+ error("2 arguments required for line");
+ break;
+ };
+ if (!vdminited()) vdmstart();
+ vdmline(env->hpos,env->vpos,p[0],p[1]);
+ /*fprintf(stderr,"\nline: %d,%d - %d,%d thickness %d == %d\n",\
+ env->hpos - 64,env->vpos -64, env->hpos - 64 + p[0],\
+ env->vpos -64 + p[1],env->size, line_thickness);*/
+ break;
+ case 'R': // Rule
+ if (np != 2) {
+ error("2 arguments required for Rule");
+ break;
+ }
+ if (vdminited()) {
+ setfillmode(fill_pattern); // Solid Rule
+ vdmrectangle(env->hpos,env->vpos,p[0],p[1]);
+ }
+ else {
+ lbpruleabs(env->hpos - 64,env->vpos -64 , p[0], p[1]);
+ cur_vpos = p[1];
+ cur_hpos = p[0];
+ };
+ fprintf(stderr,"\nrule: thickness %d == %d\n", env->size, line_thickness);
+ break;
+ case 'P': // Filled Polygon
+ if (!vdminited()) vdmstart();
+ setfillmode(fill_pattern);
+ polygon(env->hpos,env->vpos,np,p);
+ break;
+ case 'p': // Empty Polygon
+ if (!vdminited()) vdmstart();
+ setfillmode(0);
+ polygon(env->hpos,env->vpos,np,p);
+ break;
+ case 'C': // Filled Circle
+ if (!vdminited()) vdmstart();
+ // fprintf(stderr,"Circle (%d,%d) Fill %d\n",env->hpos,env->vpos,fill_pattern);
+ setfillmode(fill_pattern);
+ vdmcircle(env->hpos + (p[0]/2),env->vpos,p[0]/2);
+ break;
+ case 'c': // Empty Circle
+ if (!vdminited()) vdmstart();
+ setfillmode(0);
+ vdmcircle(env->hpos + (p[0]/2),env->vpos,p[0]/2);
+ break;
+ case 'E': // Filled Ellipse
+ if (!vdminited()) vdmstart();
+ setfillmode(fill_pattern);
+ vdmellipse(env->hpos + (p[0]/2),env->vpos,p[0]/2,p[1]/2,0);
+ break;
+ case 'e': // Empty Ellipse
+ if (!vdminited()) vdmstart();
+ setfillmode(0);
+ vdmellipse(env->hpos + (p[0]/2),env->vpos,p[0]/2,p[1]/2,0);
+ break;
+ case 'a': // Arc
+ if (!vdminited()) vdmstart();
+ setfillmode(0);
+ // VDM draws arcs clockwise and pic counterclockwise
+ // We must compensate for that, exchanging the starting and
+ // ending points
+ vdmvarc(env->hpos + p[0],env->vpos+p[1],\
+ int(sqrt( double((p[0]*p[0])+(p[1]*p[1])))),\
+ p[2],p[3],\
+ (-p[0]),(-p[1]),1,2);
+ break;
+ case '~': // Spline
+ if (!vdminited()) vdmstart();
+ setfillmode(0);
+ vdmspline(np/2,env->hpos,env->vpos,p);
+ break;
+ case 'f':
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ };
+ // fprintf(stderr,"Fill %d\n",p[0]);
+ if ((p[0] == 1) || (p[0] >= 1000)) { // Black
+ fill_pattern = 1;
+ break;
+ }; // if (p[0] == 1)
+ if (p[0] == 0) { // White
+ fill_pattern = 0;
+ break;
+ };
+ if ((p[0] > 1) && (p[0] < 1000))
+ {
+ if (p[0] >= 990) fill_pattern = -23;
+ else if (p[0] >= 700) fill_pattern = -28;
+ else if (p[0] >= 500) fill_pattern = -27;
+ else if (p[0] >= 400) fill_pattern = -26;
+ else if (p[0] >= 300) fill_pattern = -25;
+ else if (p[0] >= 200) fill_pattern = -22;
+ else if (p[0] >= 100) fill_pattern = -24;
+ else fill_pattern = -21;
+ }; // if (p[0] >= 0 && p[0] <= 1000)
+ break;
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }; // switch (code)
+ return ;
+};
+
+font *lbp_printer::make_font(const char *nm)
+{
+ return lbp_font::load_lbp_font(nm);
+}
+
+
+
+printer *make_printer()
+{
+ return new lbp_printer;
+}
+
+static struct
+{
+ const char *name;
+ int code;
+} papersizes[] =
+{{ "A4", 14 },
+{ "letter", 30 },
+{ "legal", 32 },
+{ "executive", 40 },
+};
+
+
+static int set_papersize(const char *papersize)
+{
+ int i;
+
+ // First test for a standard (i.e. supported directly by the printer)
+ // papersize
+ for (i = 0 ; i < sizeof(papersizes)/sizeof(papersizes[0]); i++)
+ {
+ if (strcasecmp(papersizes[i].name,papersize) == 0)
+ return papersizes[i].code;
+ };
+
+ // Now test for a custom papersize
+ if (strncasecmp("cust",papersize,4) == 0)
+ {
+ char *p ,
+ *p1,
+ *papsize;
+
+ p = papsize = strdup(&papersize[4]);
+ if (papsize == NULL) return -1;
+ p1 = strsep(&p,"x");
+ if (p == NULL)
+ { // let's test for an uppercase x
+ p = papsize ;
+ p1 = strsep(&p,"X");
+ if (p == NULL) { free(papsize); return -1;};
+ }; // if (p1 == NULL)
+ paperlength = atoi(p1);
+ if (paperlength == 0) { free(papsize); return -1;};
+ paperwidth = atoi(p);
+ if (paperwidth == 0) { free(papsize); return -1;};
+ free(papsize);
+ return 82;
+ }; // if (strcnasecmp("cust",papersize,4) == 0)
+
+ return -1;
+};
+
+static int handle_papersize_command(const char *arg)
+{
+ int n = set_papersize(arg);
+
+ if (n < 0)
+ { // If is not a standard nor custom paper size
+ // let's see if it's a file (i.e /etc/papersize )
+ FILE *f = fopen(arg,"r");
+ if (f != NULL)
+ { // the file exists and is readable
+ char psize[255],*p;
+ fgets(psize,254,f);
+ fclose(f);
+ // set_papersize doesn't like the trailing \n
+ p = psize; while (*p) p++;
+ if (*(--p) == '\n') *p = 0x00;
+
+ n = set_papersize(psize);
+ }; // if (f != NULL)
+ }; // if (n < 0)
+
+ return n;
+}; // handle_papersize_command
+
+
+static void handle_unknown_desc_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ // papersize command
+ if (strcasecmp(command, "papersize") == 0) {
+ // We give priority to command line options
+ if (papersize > 0) return;
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`papersize' command requires an argument");
+ else
+ {
+ int n = handle_papersize_command(arg);
+ if (n < 0)
+ error_with_file_and_line(filename, lineno,
+ "unknown paper size `%1'", arg);
+ else
+ papersize = n;
+
+ }; // if (arg == 0) ... else ...
+ }; // if (strcasecmp(command, "papersize")
+
+ // orientation command
+ if (strcasecmp(command, "orientation") == 0) {
+ // We give priority to command line options
+ if (orientation > 0) return;
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`papersize' command requires an argument");
+ else {
+ if (strcasecmp(arg,"portrait") == 0) orientation = 0;
+ else { if (strcasecmp(arg,"landscape") == 0) orientation = 1;
+ else error_with_file_and_line(filename, lineno,
+ "`orientation' command requires an argument");
+ };
+ }; // if (arg == 0) ... else ...
+ }; // if (strcasecmp(command, "orientation") == 0)
+};
+
+static struct option long_options[] = {
+ { "orientation", required_argument, NULL, 'o' },
+ { "version", no_argument, NULL, 'v' },
+ { "copies", required_argument, NULL, 'c' },
+ { "landscape", no_argument, NULL, 'l' },
+ { "papersize", required_argument, NULL, 'p' },
+ { "fontdir", required_argument, NULL, 'F' },
+ { "help", no_argument, NULL, 'h' },
+ { NULL, 0, 0, 0 }
+ };
+
+static void usage(FILE *stream)
+{
+ fprintf(stream,
+ "usage: %s [-lvh] [-c n] [-p paper_size] [-F dir] [-o or] "\
+ " [files ...]\n"\
+ " -o --orientation=[portrait|landscape]\n"\
+ " -v --version\n"\
+ " -c --copies=numcopies\n"\
+ " -l --landscape\n"\
+ " -p --papersize=paper_size\n"\
+ " -F --fontdir=dir\n"\
+ " -h --help\n",
+ program_name);
+}; // usage
+
+int main(int argc, char **argv)
+{
+ if (program_name == NULL) program_name = strdup(argv[0]);
+
+ font::set_unknown_desc_command_handler(handle_unknown_desc_command);
+ // command line parsing
+ int c = 0;
+ int option_index = 0;
+
+ while (c >= 0 )
+ {
+ c = getopt_long (argc, argv, "F:p:lvo:c:h",\
+ long_options, &option_index);
+ switch (c) {
+ case 'F' : font::command_line_font_dir(optarg);
+ break;
+ case 'p' : {
+ int n = handle_papersize_command(optarg);
+ if (n < 0)
+ error("unknown paper size `%1'", optarg);
+ else
+ papersize = n;
+ break;
+ };
+ case 'l' : orientation = 1;
+ break;
+ case 'v' : {
+ extern const char *Version_string;
+ printf("GNU grolbp (groff) version %s\n",
+ Version_string);
+ exit(0);
+ break;
+ };
+ case 'o' : {
+ if (strcasecmp(optarg,"portrait") == 0)
+ orientation = 0;
+ else {
+ if (strcasecmp(optarg,"landscape") == 0)
+ orientation = 1;
+ else
+ error("unknown orientation '%1'", 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 'h' : usage(stdout);
+ exit(0);
+ break;
+ case '?' : usage(stderr);
+ exit(1);
+ break;
+
+ }; // switch (c)
+ }; // while (c > 0 )
+
+ if (optind >= argc)
+ do_file("-");
+
+ while (optind < argc) {
+ do_file(argv[optind++]);
+ };
+
+ lbpputs("\033c\033<");
+ return 0;
+};
diff --git a/contrib/groff/src/devices/grolbp/lbp.h b/contrib/groff/src/devices/grolbp/lbp.h
new file mode 100644
index 0000000..6a11b19
--- /dev/null
+++ b/contrib/groff/src/devices/grolbp/lbp.h
@@ -0,0 +1,511 @@
+// -*- C -*-
+/* Copyright (C) 1994, 2000 Free Software Foundation, Inc.
+ Written by Francisco Andrés Verdú <pandres@dragonet.es>
+
+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 file contains a set of utility functions to use canon CAPSL printers
+ * (lbp-4 and lbp-8 series printers) */
+
+#ifndef LBP_H
+#define LBP_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+static FILE *lbpoutput = NULL;
+static FILE *vdmoutput = NULL;
+
+static inline void
+lbpinit(FILE *outfile)
+{
+ lbpoutput = outfile;
+};
+
+
+static inline void
+lbpprintf(char *format, ... )
+{ /* Taken from cjet */
+ va_list stuff;
+
+ va_start(stuff, format);
+ vfprintf(lbpoutput, format, stuff);
+ va_end(stuff);
+};
+
+static inline void
+lbpputs(char *data)
+{
+ fputs(data,lbpoutput);
+};
+
+static inline void
+lbpputc(char c)
+{
+ fputc(c,lbpoutput);
+};
+
+
+static inline void
+lbpsavestatus(int index )
+{
+ fprintf(lbpoutput,"\033[%d%%y",index);
+};
+
+static inline void
+lbprestorestatus(int index )
+{
+ fprintf(lbpoutput,"\033[%d%cz",index ,'%');
+};
+
+static inline void
+lbpsavepos(int index)
+{
+ fprintf(lbpoutput,"\033[1;%d;0x",index);
+};
+
+static inline void
+lbprestorepos(int index)
+{
+ fprintf(lbpoutput,"\033[0;%d;0x",index);
+};
+
+static inline void
+lbprestoreposx(int index)
+{
+ fprintf(lbpoutput,"\033[0;%d;1x",index);
+};
+
+static inline void
+lbpmoverel(int despl, char direction)
+{
+ fprintf(lbpoutput,"\033[%d%c",despl,direction);
+};
+
+static inline void
+lbplinerel(int width,int despl,char direction )
+{
+ fprintf(lbpoutput,"\033[%d;0;9{\033[%d%c\033[9}",width,despl,direction);
+};
+
+static inline void
+lbpmoveabs(int x, int y)
+{
+ fprintf(lbpoutput,"\033[%d;%df",y,x);
+};
+
+static inline void
+lbplineto(int x,int y, int width )
+{
+ fprintf(lbpoutput,"\033[%d;0;9{",width);
+ lbpmoveabs(x,y);
+ fprintf(lbpoutput,"\033[9}\n");
+};
+
+static inline void
+lbpruleabs(int x, int y, int hsize, int vsize)
+{
+ lbpmoveabs(x,y);
+ fprintf(lbpoutput,"\033[0;9;000s");
+ lbpmoveabs(x+hsize,y+vsize);
+ fprintf(lbpoutput,"\033[9r");
+};
+
+static inline void vdmprintf(char *format, ... );
+
+static inline char *
+vdmnum(int num,char *result)
+{
+ char b1,b2,b3;
+ char *p = result;
+ int nm;
+
+ nm = abs(num);
+ /* First byte 1024 - 32768 */
+ b1 = ((nm >> 10) & 0x3F);
+ if (b1) *p++ = b1 | 0x40;
+
+ /* Second Byte 16 - 1024 */
+ b2 = ((nm >> 4) & 0x3F);
+ if ( b1 || b2) *p++= b2 | 0x40;
+
+ /* Third byte 0 - 15 */
+ b3 = ((nm & 0x0F) | 32);
+ if (num >= 0) b3 |= 16;
+ *p++ = b3;
+ *p = 0x00; /* End of the resulting string */
+ return result;
+};
+
+static inline void
+vdmorigin(int newx, int newy)
+{
+ char nx[4],ny[4];
+
+ vdmprintf("}\"%s%s\x1e",vdmnum(newx,nx),vdmnum(newy,ny));
+}; /* vdmorigin */
+
+
+static inline FILE *
+vdminit(FILE *vdmfile)
+{
+ char scale[4],size[4],lineend[4];
+
+/* vdmoutput = tmpfile();*/
+ vdmoutput = vdmfile;
+ /* Initialize the VDM mode */
+ vdmprintf("\033[0&}#GROLBP\x1e!0%s%s\x1e$\x1e}F%s\x1e",\
+ vdmnum(-3,scale),vdmnum(1,size),vdmnum(1,lineend));
+ return vdmoutput;
+
+};
+
+static inline void
+vdmend()
+{
+ vdmprintf("}p\x1e");
+};
+
+static inline void
+vdmprintf(char *format, ... )
+{ /* Taken from cjet */
+ va_list stuff;
+
+ if (vdmoutput == NULL) vdminit(tmpfile());
+ va_start(stuff, format);
+ vfprintf(vdmoutput, format, stuff);
+ va_end(stuff);
+};
+
+static inline void
+vdmsetfillmode(int pattern,int perimeter, int inverted)
+{
+ char patt[4],perim[4],
+ rot[4], /* rotation */
+ espejo[4], /* espejo */
+ inv[4]; /* Inverted */
+
+ vdmprintf("I%s%s%s%s%s\x1e",vdmnum(pattern,patt),\
+ vdmnum(perimeter,perim),vdmnum(0,rot),
+ vdmnum(0,espejo),vdmnum(inverted,inv));
+};
+
+static inline void
+vdmcircle(int centerx, int centery, int radius)
+{
+ char x[4],y[4],rad[4];
+
+ vdmprintf("5%s%s%s\x1e",vdmnum(centerx,x),vdmnum(centery,y),\
+ vdmnum(radius,rad));
+};
+
+static inline void
+vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style,int arcopen)
+{
+ char x[4],y[4],rad[4],stx[4],sty[4],styl[4],op[4];
+
+ vdmprintf("}6%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\
+ vdmnum(centerx,x),vdmnum(centery,y),\
+ vdmnum(radius,rad),vdmnum(startangle,stx),vdmnum(angle,sty),\
+ vdmnum(style,styl));
+};
+
+static inline void
+vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, int endy,\
+ int style,int arcopen)
+{
+ char x[4],y[4],rad[4],stx[4],sty[4],enx[4],eny[4],styl[4],op[4];
+
+ vdmprintf("}6%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\
+ vdmnum(centerx,x),vdmnum(centery,y),\
+ vdmnum(radius,rad),vdmnum(startx,stx),vdmnum(starty,sty),\
+ vdmnum(endx,enx),vdmnum(endy,eny),vdmnum(style,styl));
+};
+
+static inline void
+vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation)
+{
+ char x[4],y[4],radx[4],rady[4],rotat[4];
+
+ vdmprintf("}7%s%s%s%s%s\x1e\n",vdmnum(centerx,x),vdmnum(centery,y),\
+ vdmnum(radiusx,radx),vdmnum(radiusy,rady),\
+ vdmnum(rotation,rotat));
+};
+
+static inline void
+vdmsetlinetype(int lintype)
+{
+ char ltyp[4], expfact[4];
+
+ vdmprintf("E1%s%s\x1e",vdmnum(lintype,ltyp),vdmnum(1,expfact));
+
+};
+
+static inline void
+vdmsetlinestyle(int lintype, int pattern,int unionstyle)
+{
+ char patt[4],ltip[4],
+ rot[4], /* rotation */
+ espejo[4], /* espejo */
+ in[4]; /* Inverted */
+
+ vdmprintf("}G%s%s%s%s%s\x1e",vdmnum(lintype,ltip),\
+ vdmnum(pattern,patt),vdmnum(0,rot),
+ vdmnum(0,espejo),vdmnum(0,in));
+ vdmprintf("}F%s",vdmnum(unionstyle,rot));
+};
+
+static inline void
+vdmlinewidth(int width)
+{
+ char wh[4];
+
+ vdmprintf("F1%s\x1e",vdmnum(width,wh));
+};
+
+static inline void
+vdmrectangle(int origx, int origy,int dstx, int dsty)
+{
+ char xcoord[4],ycoord[4],sdstx[4],sdsty[4];
+
+ vdmprintf("}:%s%s%s%s\x1e\n",vdmnum(origx,xcoord),vdmnum(dstx,sdstx),\
+ vdmnum(origy,ycoord),vdmnum(dsty,sdsty));
+}; /* polyline */
+
+static inline void
+vdmpolyline(int numpoints, int *points)
+{
+ int i,*p = points;
+ char xcoord[4],ycoord[4];
+
+ if (numpoints < 2) return;
+ vdmprintf("1%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
+ p += 2;
+ for (i = 1; i < numpoints ; i++) {
+ vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
+ p += 2;
+ }; /* for */
+ vdmprintf("\x1e\n");
+}; /* polyline */
+
+static inline void
+vdmpolygon(int numpoints, int *points)
+{
+ int i,*p = points;
+ char xcoord[4],ycoord[4];
+
+ if (numpoints < 2) return;
+ vdmprintf("2%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
+ p += 2;
+ for (i = 1; i < numpoints ; i++) {
+ vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
+ p += 2;
+ }; /* for */
+ vdmprintf("\x1e\n");
+
+}; /* vdmpolygon */
+
+
+/************************************************************************
+ * Highter level auxiliary functions *
+ ************************************************************************/
+static inline int
+vdminited()
+{
+ return (vdmoutput != NULL);
+}; /* vdminited */
+
+
+static inline void
+vdmline(int startx, int starty, int sizex, int sizey)
+{
+ int points[4];
+
+ points[0] = startx;
+ points[1] = starty;
+ points[2] = sizex;
+ points[3] = sizey;
+
+ vdmpolyline(2,points);
+
+};
+
+/*#define THRESHOLD .05 */ /* inch */
+#define THRESHOLD 1 /* points (1/300 inch) */
+static inline void
+splinerel(double px,double py,int flush)
+{
+ static int lx = 0 ,ly = 0;
+ static float pend = 0.0;
+ static int dy = 0, despx = 0, despy = 0, sigpend = 0;
+ int dxnew ,dynew, sg;
+ char xcoord[4],ycoord[4];
+ float npend ;
+
+ if (flush == -1) {lx = (int)px; ly = (int)py; return;};
+
+ if (flush == 0) {
+ dxnew = (int)px -lx;
+ dynew = (int)py -ly;
+ if ((dxnew == 0) && (dynew == 0)) return;
+ sg = (dxnew < 0)? -1 : 0;
+/* fprintf(stderr,"s (%d,%d) (%d,%d)\n",dxnew,dynew,despx,despy);*/
+ if (dynew == 0) {
+ despx = dxnew;
+ if ((sg == sigpend) && (dy == 0)){
+ return;
+ };
+ dy = 0;
+ }
+ else {
+ dy = 1;
+ npend = (1.0*dxnew)/dynew;
+ if (( npend == pend) && (sigpend == sg))
+ { despy = dynew; despx = dxnew; return; }
+ else
+ { sigpend = sg;
+ pend = npend;
+ }; /* else (( npend == pend) && ... */
+ }; /* else (if (dynew == 0)) */
+ }; /* if (!flush ) */
+
+ /* if we've changed direction we must draw the line */
+/* fprintf(stderr," (%d) %.2f,%.2f\n",flush,(float)px,(float)py);*/
+ if ((despx != 0) || (despy != 0)) vdmprintf("%s%s",vdmnum(despx,xcoord),\
+ vdmnum(despy,ycoord));
+ /*if ((despx != 0) || (despy != 0)) fprintf(stderr,"2
+ *%d,%d\n",despx,despy);*/
+ if (flush) {
+ dxnew = dy = despx = despy = 0;
+ return;
+ }; /* if (flush) */
+ dxnew -= despx;
+ dynew -= despy;
+ if ((dxnew != 0) || (dynew != 0)) vdmprintf("%s%s",vdmnum(dxnew,xcoord),\
+ vdmnum(dynew,ycoord));
+
+/* if ((dxnew != 0) || (dynew != 0)) fprintf(stderr,"3
+ * %d,%d\n",dxnew,dynew);*/
+ lx = (int)px; ly = (int)py;
+ dxnew = dy = despx = despy = 0;
+
+}; /* splinerel */
+
+/**********************************************************************
+ * The following code to draw splines is adapted from the transfig package
+ */
+static void
+quadratic_spline(double a1,double b1, double a2, double b2, \
+ double a3, double b3, double a4, double b4)
+{
+ double x1, y1, x4, y4;
+ double xmid, ymid;
+
+ x1 = a1; y1 = b1;
+ x4 = a4; y4 = b4;
+ xmid = (a2 + a3)/2.0;
+ ymid = (b2 + b3)/2.0;
+ if ((fabs(x1 - xmid) < THRESHOLD) && (fabs(y1 - ymid) < THRESHOLD)) {
+ splinerel(xmid,ymid,0);
+/* fprintf(tfp, "PA%.4f,%.4f;\n", xmid, ymid);*/
+ }
+ else {
+ quadratic_spline(x1, y1, ((x1+a2)/2.0), ((y1+b2)/2.0),
+ ((3.0*a2+a3)/4.0), ((3.0*b2+b3)/4.0), xmid, ymid);
+ }
+
+ if ((fabs(xmid - x4) < THRESHOLD) && (fabs(ymid - y4) < THRESHOLD)) {
+ splinerel(x4,y4,0);
+/* fprintf(tfp, "PA%.4f,%.4f;\n", x4, y4);*/
+ }
+ else {
+ quadratic_spline(xmid, ymid, ((a2+3.0*a3)/4.0), ((b2+3.0*b3)/4.0),
+ ((a3+x4)/2.0), ((b3+y4)/2.0), x4, y4);
+ };
+}; /* quadratic_spline */
+
+#define XCOORD(i) numbers[(2*i)]
+#define YCOORD(i) numbers[(2*i)+1]
+static void
+vdmspline(int numpoints, int ox,int oy, int *numbers)
+{
+ double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
+ double x1, y1, x2, y2;
+ char xcoord[4],ycoord[4];
+ int i;
+
+ /*p = s->points;
+ x1 = p->x/ppi;*/
+ x1 = ox;
+ y1 = oy;
+/* p = p->next;
+ x2 = p->x/ppi;
+ y2 = p->y/ppi;*/
+ x2 = ox + XCOORD(0);
+ y2 = oy + YCOORD(0);
+ cx1 = (x1 + x2)/2.0;
+ cy1 = (y1 + y2)/2.0;
+ cx2 = (x1 + 3.0*x2)/4.0;
+ cy2 = (y1 + 3.0*y2)/4.0;
+
+/* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x1,(int)y1);*/
+ vdmprintf("1%s%s",vdmnum((int)x1,xcoord),vdmnum((int)y1,ycoord));
+ splinerel(x1,y1,-1);
+ splinerel(cx1,cy1,0);
+/* fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f;\n",
+ x1, y1, cx1, cy1);*/
+
+ /*for (p = p->next; p != NULL; p = p->next) {*/
+ for (i = 1; i < (numpoints); i++) {
+ x1 = x2;
+ y1 = y2;
+/* x2 = p->x/ppi;
+ y2 = p->y/ppi;*/
+ x2 = x1 + XCOORD(i);
+ y2 = y1 + YCOORD(i);
+ cx3 = (3.0*x1 + x2)/4.0;
+ cy3 = (3.0*y1 + y2)/4.0;
+ cx4 = (x1 + x2)/2.0;
+ cy4 = (y1 + y2)/2.0;
+ /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x1,(int)(y1),(int)x2,(int)y2);*/
+ quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
+ cx1 = cx4;
+ cy1 = cy4;
+ cx2 = (x1 + 3.0*x2)/4.0;
+ cy2 = (y1 + 3.0*y2)/4.0;
+ }
+ x1 = x2;
+ y1 = y2;
+/* p = s->points->next;
+ x2 = p->x/ppi;
+ y2 = p->y/ppi;*/
+ x2 = ox + XCOORD(0);
+ y2 = oy + YCOORD(0);
+ cx3 = (3.0*x1 + x2)/4.0;
+ cy3 = (3.0*y1 + y2)/4.0;
+ cx4 = (x1 + x2)/2.0;
+ cy4 = (y1 + y2)/2.0;
+ splinerel(x1,y1,0);
+ splinerel(x1,y1,1);
+ /*vdmprintf("%s%s",vdmnum((int)(x1-lx),xcoord),\
+ vdmnum((int)(y1-ly),ycoord));*/
+ vdmprintf("\x1e\n");
+/* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x1, y1);*/
+
+
+}; /* vdmspline */
+
+
+#endif
diff --git a/contrib/groff/src/devices/grolj4/Makefile.sub b/contrib/groff/src/devices/grolj4/Makefile.sub
new file mode 100644
index 0000000..bbb0cff
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grolj4/grolj4.man b/contrib/groff/src/devices/grolj4/grolj4.man
new file mode 100644
index 0000000..891d7dc
--- /dev/null
+++ b/contrib/groff/src/devices/grolj4/grolj4.man
@@ -0,0 +1,144 @@
+.ig \"-*- nroff -*-
+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.
+
+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
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBgrolj4 'u
+.ti \niu
+.B grolj4
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-lv
+.OP \-d \fR[\fPn\fR]\fP
+.OP \-c n
+.OP \-p paper_size
+.OP \-w n
+.OP \-F dir
+.RI "[\ " files\|.\|.\|. "\ ]"
+.br
+.ad \na
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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
+Prepend directory
+.IB dir /devlj4
+to the search path for font and device description files.
+.LP
+The following four commands are available additionally in the
+.B DESC
+file:
+.TP
+.BI pclweight \ N
+The integer value
+.I N
+must be in the range -7 to +7; default is 0.
+.TP
+.BI pclstyle \ N
+The integer value
+.I N
+must be in the range 0 to 32767; default is 0.
+.TP
+.BI pclproportional \ N
+A boolean flag which can be either 0 or 1; default is 0.
+.TP
+.BI pcltypeface \ N
+The integer value
+.I N
+must be in the range 0 to 65535; default is 0.
+.SH FILES
+.TP
+.B @FONTDIR@/devlj4/DESC
+Device description file.
+.TP
+.BI @FONTDIR@/devlj4/ F
+Font description file for font
+.IR F .
+.TP
+.B @MACRODIR@/lj4.tmac
+Macros for use with
+.BR grolj4 .
+.SH BUGS
+Small dots.
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/contrib/groff/src/devices/grolj4/lj4.cc b/contrib/groff/src/devices/grolj4/lj4.cc
new file mode 100644
index 0000000..9fbc6af
--- /dev/null
+++ b/contrib/groff/src/devices/grolj4/lj4.cc
@@ -0,0 +1,710 @@
+// -*- C++ -*-
+/* Copyright (C) 1994, 2000, 2001 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"
+#include "nonposix.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(FILE *stream);
+
+extern "C" int optopt, optind;
+
+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;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((c = getopt_long(argc, argv, ":F:p:d:lvw:c:", long_options, NULL))
+ != 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;
+ printf("GNU grolj4 (groff) version %s\n", Version_string);
+ exit(0);
+ 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 CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ default:
+ assert(0);
+ }
+#ifdef SET_BINARY
+ SET_BINARY(fileno(stdout));
+#endif
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage(FILE *stream)
+{
+ fprintf(stream,
+ "usage: %s [-lv] [-d [n]] [-c n] [-p paper_size]\n"
+ " [-w n] [-F dir] [files ...]\n",
+ program_name);
+}
diff --git a/contrib/groff/src/devices/grops/Makefile.sub b/contrib/groff/src/devices/grops/Makefile.sub
new file mode 100644
index 0000000..4182527
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grops/TODO b/contrib/groff/src/devices/grops/TODO
new file mode 100644
index 0000000..da67973
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grops/grops.man b/contrib/groff/src/devices/grops/grops.man
new file mode 100644
index 0000000..1dac725
--- /dev/null
+++ b/contrib/groff/src/devices/grops/grops.man
@@ -0,0 +1,861 @@
+.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.
+..
+.\" 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
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBgrops 'u
+.ti \niu
+.B grops
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-glmv
+.OP \-b n
+.OP \-c n
+.OP \-w n
+.OP \-F dir
+.OP \-P prologue
+.RI "[\ " files\|.\|.\|. "\ ]"
+.br
+.ad \na
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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
+Prepend directory
+.IB dir /dev name
+to the search path for prologue, font, and device description files;
+.I name
+is the name of the device, usually
+.BR ps .
+.TP
+.BI \-P prologue-file
+Use the file
+.I prologue-file
+(in the font path) as the prologue instead of the default prologue file
+.BR prologue .
+This option overrides the environment variable
+.SM GROPS_PROLOGUE.
+.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 (@MAN5EXT@).
+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 ENVIRONMENT
+.TP
+.SM
+.B GROPS_PROLOGUE
+If this is set to
+.IR foo ,
+then
+.B grops
+will use the file
+.I foo
+(in the font path) instead of the default prologue file
+.BR prologue .
+The option
+.B \-P
+overrides this environment variable.
+.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@/ps.tmac
+Macros for use with
+.BR grops ;
+automatically loaded by
+.BR troffrc
+.TP
+.B @MACRODIR@/pspic.tmac
+Definition of
+.B PSPIC
+macro,
+automatically loaded by
+.BR ps.tmac .
+.TP
+.B @MACRODIR@/psold.tmac
+Macros to disable use of characters not present in older
+PostScript printers (e.g. `eth' or `thorn').
+.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/contrib/groff/src/devices/grops/ps.cc b/contrib/groff/src/devices/grops/ps.cc
new file mode 100644
index 0000000..98b1a91
--- /dev/null
+++ b/contrib/groff/src/devices/grops/ps.cc
@@ -0,0 +1,1570 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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 "nonposix.h"
+
+#include "ps.h"
+#include <time.h>
+
+#ifdef NEED_DECLARATION_PUTENV
+extern "C" {
+ int putenv(const char *);
+}
+#endif /* NEED_DECLARATION_PUTENV */
+
+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 = if_to_a(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, char type);
+ 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 command_array[] = {'A', 'B', 'C', 'D',
+ 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T'};
+ char sym[2];
+ sym[0] = command_array[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(i_to_a(n));
+ out.comment_arg(i_to_a(++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(i_to_a(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, char type)
+{
+ if (type != 'p')
+ return;
+ 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(FILE *stream);
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ string env;
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((c = getopt_long(argc, argv, "F:P:glmc:w:vb:", long_options, NULL))
+ != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU grops (groff) version %s\n", Version_string);
+ exit(0);
+ 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 'P':
+ env = "GROPS_PROLOGUE";
+ env += '=';
+ env += optarg;
+ env += '\0';
+ if (putenv(strsave(env.contents())))
+ fatal("putenv failed");
+ 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 CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ default:
+ assert(0);
+ }
+ font::set_unknown_desc_command_handler(handle_unknown_desc_command);
+#ifdef SET_BINARY
+ SET_BINARY(fileno(stdout));
+#endif
+ if (optind >= argc)
+ do_file("-");
+ else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage(FILE *stream)
+{
+ fprintf(stream,
+ "usage: %s [-glmv] [-b n] [-c n] [-w n] [-P prologue] [-F dir] [files ...]\n",
+ program_name);
+}
diff --git a/contrib/groff/src/devices/grops/ps.h b/contrib/groff/src/devices/grops/ps.h
new file mode 100644
index 0000000..6e78597
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grops/psfig.diff b/contrib/groff/src/devices/grops/psfig.diff
new file mode 100644
index 0000000..5be080d
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grops/psrm.cc b/contrib/groff/src/devices/grops/psrm.cc
new file mode 100644
index 0000000..b816c6b
--- /dev/null
+++ b/contrib/groff/src/devices/grops/psrm.cc
@@ -0,0 +1,1118 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 "stringclass.h"
+#include "cset.h"
+
+#include "ps.h"
+
+#ifdef NEED_DECLARATION_PUTENV
+extern "C" {
+ int putenv(const char *);
+}
+#endif /* NEED_DECLARATION_PUTENV */
+
+#define GROPS_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;
+ if (!getenv("GROPS_PROLOGUE")) {
+ string e = "GROPS_PROLOGUE";
+ e += '=';
+ e += GROPS_PROLOGUE;
+ e += '\0';
+ if (putenv(strsave(e.contents())))
+ fatal("putenv failed");
+ }
+ char *prologue = getenv("GROPS_PROLOGUE");
+ 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/contrib/groff/src/devices/grotty/Makefile.sub b/contrib/groff/src/devices/grotty/Makefile.sub
new file mode 100644
index 0000000..91d3908
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grotty/TODO b/contrib/groff/src/devices/grotty/TODO
new file mode 100644
index 0000000..3f23dc3
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/devices/grotty/tty.cc b/contrib/groff/src/devices/grotty/tty.cc
new file mode 100644
index 0000000..a8ee065
--- /dev/null
+++ b/contrib/groff/src/devices/grotty/tty.cc
@@ -0,0 +1,509 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-2000, 2001 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 = 0x01,
+ BOLD_MODE = 0x02,
+ VDRAW_MODE = 0x04,
+ HDRAW_MODE = 0x08,
+ CU_MODE = 0x10
+};
+
+// 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); }
+ inline int order() { return mode & (VDRAW_MODE|HDRAW_MODE|CU_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 special(char *arg, const environment *env, char type);
+ 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 CU specials before 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)->order() >= g->order()))
+ break;
+ g->next = *pp;
+ *pp = g;
+}
+
+void tty_printer::special(char *arg, const environment *env, char type)
+{
+ if (type == 'u')
+ add_char(*arg - '0', env->hpos, env->vpos, CU_MODE);
+}
+
+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);
+ }
+}
+
+int cu_flag = 0;
+
+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 (p->mode & CU_MODE) {
+ cu_flag = p->code;
+ continue;
+ }
+ 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;
+ if (cu_flag) {
+ putchar('_');
+ putchar('\b');
+ }
+ putchar('\t');
+ hpos = next_tab_pos;
+ }
+ }
+ for (; hpos < p->hpos; hpos++) {
+ if (cu_flag) {
+ putchar('_');
+ putchar('\b');
+ }
+ 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(FILE *stream);
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((c = getopt_long(argc, argv, "F:vhfbuoBUd", long_options, NULL))
+ != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU grotty (groff) version %s\n", Version_string);
+ exit(0);
+ 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 CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-hfvbuodBU] [-F dir] [files ...]\n",
+ program_name);
+}
diff --git a/contrib/groff/src/include/Makefile.sub b/contrib/groff/src/include/Makefile.sub
new file mode 100644
index 0000000..cee00d3
--- /dev/null
+++ b/contrib/groff/src/include/Makefile.sub
@@ -0,0 +1,42 @@
+HDRS=\
+ assert.h \
+ cmap.h \
+ cset.h \
+ device.h \
+ driver.h \
+ errarg.h \
+ error.h \
+ font.h \
+ getopt.h \
+ groff-getopt.h \
+ htmlindicate.h \
+ index.h \
+ lib.h \
+ macropath.h \
+ nonposix.h \
+ posix.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)\"" \
+ "BINPATH=\"$(bindir)\"" \
+ "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/contrib/groff/src/include/assert.h b/contrib/groff/src/include/assert.h
new file mode 100644
index 0000000..18d9c26
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/cmap.h b/contrib/groff/src/include/cmap.h
new file mode 100644
index 0000000..1537d46
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/cset.h b/contrib/groff/src/include/cset.h
new file mode 100644
index 0000000..b3a1a97
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/device.h b/contrib/groff/src/include/device.h
new file mode 100644
index 0000000..341af8d
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/driver.h b/contrib/groff/src/include/driver.h
new file mode 100644
index 0000000..97eb891
--- /dev/null
+++ b/contrib/groff/src/include/driver.h
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <stdio.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/contrib/groff/src/include/errarg.h b/contrib/groff/src/include/errarg.h
new file mode 100644
index 0000000..0c7957c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/error.h b/contrib/groff/src/include/error.h
new file mode 100644
index 0000000..d26e2c7
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/font.h b/contrib/groff/src/include/font.h
new file mode 100644
index 0000000..099f97b
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/getopt.h b/contrib/groff/src/include/getopt.h
new file mode 100644
index 0000000..b0147e9
--- /dev/null
+++ b/contrib/groff/src/include/getopt.h
@@ -0,0 +1,169 @@
+/* Declarations for getopt.
+ Copyright (C) 1989,90,91,92,93,94,96,97,98 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+# if defined __STDC__ && __STDC__
+ const char *name;
+# else
+ char *name;
+# endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+#endif /* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `getopt' that there are no more
+ options.
+
+ If OPTS begins with `--', then non-option arguments are treated as
+ arguments to the option '\0'. This behavior is specific to the GNU
+ `getopt'. */
+
+#if defined __STDC__ && __STDC__
+# ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int __argc, char *const *__argv, const char *__shortopts);
+# else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+# endif /* __GNU_LIBRARY__ */
+
+# ifndef __need_getopt
+extern int getopt_long (int __argc, char *const *__argv, const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+extern int getopt_long_only (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int __argc, char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts, int *__longind,
+ int __long_only);
+# endif
+#else /* not __STDC__ */
+extern int getopt ();
+# ifndef __need_getopt
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+# endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations. */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/contrib/groff/src/include/groff-getopt.h b/contrib/groff/src/include/groff-getopt.h
new file mode 100644
index 0000000..1807fc7
--- /dev/null
+++ b/contrib/groff/src/include/groff-getopt.h
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ Written by Werner Lemberg (wl@gnu.org)
+
+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 file has to be included from within lib.h instead of getopt.h
+ to avoid problems with picky C++ compilers.
+*/
+
+#ifndef _GROFF_GETOPT_H
+#define _GROFF_GETOPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+struct option
+{
+ const char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+extern int getopt(int __argc,
+ char *const *__argv,
+ const char *__shortopts);
+extern int getopt_long(int __argc,
+ char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind);
+extern int getopt_long_only(int __argc,
+ char *const *__argv,
+ const char *__shortopts,
+ const struct option *__longopts,
+ int *__longind);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GROFF_GETOPT_H */
diff --git a/contrib/groff/src/include/html-strings.h b/contrib/groff/src/include/html-strings.h
new file mode 100644
index 0000000..710e8d7
--- /dev/null
+++ b/contrib/groff/src/include/html-strings.h
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+/* Copyright (C) 2001 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. */
+
+/*
+ * defines the image tags issued by the pre-processors (tbl, pic, eqn)
+ * and later detected by pre-html.cc
+ */
+
+#define HTML_IMAGE_INLINE_BEGIN "\\O[HTML-IMAGE-INLINE-BEGIN]"
+#define HTML_IMAGE_INLINE_END "\\O[HTML-IMAGE-INLINE-END]"
+#define HTML_IMAGE_CENTERED ".HTML-IMAGE"
+#define HTML_IMAGE_RIGHT ".HTML-IMAGE-RIGHT"
+#define HTML_IMAGE_LEFT ".HTML-IMAGE-LEFT"
+#define HTML_IMAGE_END ".HTML-IMAGE-END"
diff --git a/contrib/groff/src/include/htmlindicate.h b/contrib/groff/src/include/htmlindicate.h
new file mode 100644
index 0000000..4915ba8
--- /dev/null
+++ b/contrib/groff/src/include/htmlindicate.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 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. */
+
+#ifndef HTMLINDICATE_H
+#define HTMLINDICATE_H
+
+/*
+ * graphic_start - emit a html graphic start indicator, but only
+ * if one has not already been issued.
+ *
+ * The boolean, is_inline, should be:
+ *
+ * FALSE if this is called via EQ, TS, PS, and
+ * TRUE if issued via delim $$ $ x over y $ etc.
+ */
+extern void graphic_start(int is_inline);
+
+/*
+ * graphic_end - emit a html graphic end indicator, but only
+ * if a corresponding matching graphic-start has
+ * been issued.
+ *
+ */
+extern void graphic_end();
+
+/*
+ * html_begin_suppress - suppresses output for the html device
+ * and resets the min/max registers for -Tps
+ *
+ * The boolean, is_inline, should be:
+ *
+ * FALSE if this is called via EQ, TS, PS, and
+ * TRUE if issued via delim $$ $ x over y $ etc.
+ */
+extern void html_begin_suppress(int is_inline);
+
+/*
+ * html_end_suppress - end the suppression of output.
+ */
+extern void html_end_suppress(int is_inline);
+
+#endif
diff --git a/contrib/groff/src/include/index.h b/contrib/groff/src/include/index.h
new file mode 100644
index 0000000..7e60813
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/lib.h b/contrib/groff/src/include/lib.h
new file mode 100644
index 0000000..ad416e0
--- /dev/null
+++ b/contrib/groff/src/include/lib.h
@@ -0,0 +1,133 @@
+// -*- 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. */
+
+extern "C" {
+#ifndef strerror
+ char *strerror(int);
+#endif
+ const char *i_to_a(int);
+ const char *if_to_a(int, int);
+}
+
+/* stdio.h on IRIX and OSF/1 include getopt.h */
+
+#if !(defined(__sgi) || (defined(__osf__) && defined(__alpha)))
+#include <groff-getopt.h>
+#endif
+
+char *strsave(const char *s);
+int is_prime(unsigned);
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+FILE *xtmpfile(char **namep=0, char *postfix=0, int do_unlink=1);
+char *xtmptemplate(char *extension=0);
+
+#ifdef NEED_DECLARATION_POPEN
+
+extern "C" { FILE *popen(const char *, const char *); }
+
+#endif /* NEED_DECLARATION_POPEN */
+
+#ifdef NEED_DECLARATION_PCLOSE
+
+extern "C" { int pclose (FILE *); }
+
+#endif /* NEED_DECLARATION_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];
+}
+
+#if !defined(_AIX) && !defined(sinix) && !defined(__sinix__)
+#ifdef HAVE_STRNCASECMP
+#ifdef NEED_DECLARATION_STRNCASECMP
+extern "C" {
+ // SunOS's string.h fails to declare this.
+ int strncasecmp(const char *, const char *, int);
+}
+#endif /* NEED_DECLARATION_STRNCASECMP */
+#endif /* HAVE_STRNCASECMP */
+#endif /* !_AIX && !sinix && !__sinix__ */
+
+#ifndef HAVE_STRCASECMP
+#define strcasecmp(a,b) strcmp((a),(b))
+#endif
+
+#ifndef HAVE_STRNCASECMP
+#define strncasecmp(a,b,c) strncmp((a),(b),(c))
+#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/contrib/groff/src/include/macropath.h b/contrib/groff/src/include/macropath.h
new file mode 100644
index 0000000..b4a2bd0
--- /dev/null
+++ b/contrib/groff/src/include/macropath.h
@@ -0,0 +1,23 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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. */
+
+extern search_path macro_path;
+extern search_path safer_macro_path;
+extern search_path config_macro_path;
diff --git a/contrib/groff/src/include/nonposix.h b/contrib/groff/src/include/nonposix.h
new file mode 100644
index 0000000..5144983
--- /dev/null
+++ b/contrib/groff/src/include/nonposix.h
@@ -0,0 +1,136 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+ Written by Eli Zaretskii (eliz@is.elta.co.il)
+
+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 header file compartmentalize all idiosyncrasies of non-Posix
+ systems, such as MS-DOS, MS-Windows, etc. */
+
+#if defined _MSC_VER
+# ifndef _WIN32
+# define _WIN32
+# endif
+# define setmode(f,m) _setmode(f,m)
+#endif
+
+#if defined(__MSDOS__) || (defined(_WIN32) && !defined(__CYGWIN32__))
+
+/* Binary I/O nuisances. Note: "setmode" is right for DJGPP and
+ Borland; Windows compilers might need _setmode or some such. */
+# include <fcntl.h>
+# include <io.h>
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+# define SET_BINARY(f) do {if (!isatty(f)) setmode(f,O_BINARY);} while(0)
+# define FOPEN_RB "rb"
+# define FOPEN_WB "wb"
+# define FOPEN_RWB "wb+"
+# ifdef _MSC_VER
+# define POPEN_RT "rt"
+# define POPEN_WT "wt"
+# define popen(c,m) _popen(c,m)
+# define pclose(p) _pclose(p)
+# define getpid() (1)
+# endif
+# ifndef O_BINARY
+# ifdef _O_BINARY
+# define O_BINARY (_O_BINARY)
+# endif
+# endif
+
+/* The system shell. Groff assumes a Unixy shell, but non-Posix
+ systems don't have standard places where it lives, and might not
+ have it installed to begin with. We want to give them some leeway. */
+# define BSHELL (system_shell_name())
+# define BSHELL_DASH_C (system_shell_dash_c())
+# define IS_BSHELL(s) (is_system_shell(s))
+
+/* The separator for directories in PATH and other environment
+ variables. */
+# define PATH_SEP ";"
+
+/* Characters that separate directories in a path name. */
+# define DIR_SEPS "/\\:"
+
+/* How to tell if the argument is an absolute file name. */
+# define IS_ABSOLUTE(f) \
+ ((f)[0] == '/' || (f)[0] == '\\' || (f)[0] && (f)[1] == ':')
+
+/* The executable extension. */
+# define EXE_EXT ".exe"
+
+/* The system null device. */
+# define NULL_DEV "NUL"
+
+/* Prototypes. */
+# ifdef __cplusplus
+ extern "C" {
+# endif
+ const char * system_shell_name(void);
+ const char * system_shell_dash_c(void);
+ int is_system_shell(const char *);
+# ifdef __cplusplus
+ }
+# endif
+
+#endif
+
+/* Defaults, for Posix systems. */
+
+#ifndef FOPEN_RB
+# define FOPEN_RB "r"
+#endif
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef FOPEN_RWB
+# define FOPEN_RWB "w+"
+#endif
+#ifndef POPEN_RT
+# define POPEN_RT "r"
+#endif
+#ifndef POPEN_WT
+# define POPEN_WT "w"
+#endif
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+#ifndef BSHELL
+# define BSHELL "/bin/sh"
+#endif
+#ifndef BSHELL_DASH_C
+# define BSHELL_DASH_C "-c"
+#endif
+#ifndef IS_BSHELL
+# define IS_BSHELL(s) ((s) && strcmp(s,BSHELL) == 0)
+#endif
+#ifndef PATH_SEP
+# define PATH_SEP ":"
+#endif
+#ifndef DIR_SEPS
+# define DIR_SEPS "/"
+#endif
+#ifndef IS_ABSOLUTE
+# define IS_ABSOLUTE(f) ((f)[0] == '/')
+#endif
+#ifndef EXE_EXT
+# define EXE_EXT ""
+#endif
+#ifndef NULL_DEV
+# define NULL_DEV "/dev/null"
+#endif
diff --git a/contrib/groff/src/include/posix.h b/contrib/groff/src/include/posix.h
new file mode 100644
index 0000000..1b7d5cd
--- /dev/null
+++ b/contrib/groff/src/include/posix.h
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+/* Copyright (C) 1992, 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 <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_CC_OSFCN_H
+#include <osfcn.h>
+#else
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#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/contrib/groff/src/include/printer.h b/contrib/groff/src/include/printer.h
new file mode 100644
index 0000000..beae4d9
--- /dev/null
+++ b/contrib/groff/src/include/printer.h
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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);
+ font *get_font_from_index(int fontno);
+ 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, char type = 'p');
+ 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/contrib/groff/src/include/ptable.h b/contrib/groff/src/include/ptable.h
new file mode 100644
index 0000000..dc56add
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/refid.h b/contrib/groff/src/include/refid.h
new file mode 100644
index 0000000..605427e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/search.h b/contrib/groff/src/include/search.h
new file mode 100644
index 0000000..260410e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/include/searchpath.h b/contrib/groff/src/include/searchpath.h
new file mode 100644
index 0000000..4d89a8d
--- /dev/null
+++ b/contrib/groff/src/include/searchpath.h
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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. */
+
+class search_path {
+ char *dirs;
+ unsigned init_len;
+public:
+ search_path(const char *envvar, const char *standard,
+ int add_home, int add_current);
+ ~search_path();
+ void command_line_dir(const char *);
+ FILE *open_file(const char *, char **);
+};
diff --git a/contrib/groff/src/include/stringclass.h b/contrib/groff/src/include/stringclass.h
new file mode 100644
index 0000000..be3a044
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libbib/Makefile.sub b/contrib/groff/src/libs/libbib/Makefile.sub
new file mode 100644
index 0000000..482f01a
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libbib/common.cc b/contrib/groff/src/libs/libbib/common.cc
new file mode 100644
index 0000000..4b2bcca
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libbib/index.cc b/contrib/groff/src/libs/libbib/index.cc
new file mode 100644
index 0000000..5573771
--- /dev/null
+++ b/contrib/groff/src/libs/libbib/index.cc
@@ -0,0 +1,641 @@
+// -*- 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"
+
+#include "nonposix.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 | O_BINARY);
+ 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 | O_BINARY);
+ 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, FOPEN_RB);
+ 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';
+ // Remove the CR characters from CRLF pairs.
+ int sidx = 1, didx = 1;
+ for ( ; sidx < length + 1; sidx++, didx++)
+ {
+ if (buf[sidx] == '\r')
+ {
+ if (buf[++sidx] != '\n')
+ buf[didx++] = '\r';
+ else
+ length--;
+ }
+ if (sidx != didx)
+ buf[didx] = buf[sidx];
+ }
+ 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 (IS_ABSOLUTE(filename))
+ return filename;
+ const char *cwd = pool;
+ int need_slash = (cwd[0] != 0
+ && strchr(DIR_SEPS, strchr(cwd, '\0')[-1]) == 0);
+ 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 | O_BINARY);
+ 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/contrib/groff/src/libs/libbib/linear.cc b/contrib/groff/src/libs/libbib/linear.cc
new file mode 100644
index 0000000..a8c2a55
--- /dev/null
+++ b/contrib/groff/src/libs/libbib/linear.cc
@@ -0,0 +1,503 @@
+// -*- 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 "nonposix.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';
+ int sidx = 4, didx = 4;
+ for ( ; sidx < size + 4; sidx++, didx++)
+ {
+ if (buffer[sidx] == '\r')
+ {
+ if (buffer[++sidx] != '\n')
+ buffer[didx++] = '\r';
+ else
+ size--;
+ }
+ if (sidx != didx)
+ buffer[didx] = buffer[sidx];
+ }
+ 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/contrib/groff/src/libs/libbib/map.c b/contrib/groff/src/libs/libbib/map.c
new file mode 100644
index 0000000..ee5d008
--- /dev/null
+++ b/contrib/groff/src/libs/libbib/map.c
@@ -0,0 +1,71 @@
+/* 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>
+
+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/contrib/groff/src/libs/libbib/search.cc b/contrib/groff/src/libs/libbib/search.cc
new file mode 100644
index 0000000..1e027c6
--- /dev/null
+++ b/contrib/groff/src/libs/libbib/search.cc
@@ -0,0 +1,132 @@
+// -*- 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 "nonposix.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 | O_BINARY);
+ 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/contrib/groff/src/libs/libdriver/Makefile.sub b/contrib/groff/src/libs/libdriver/Makefile.sub
new file mode 100644
index 0000000..d50f060
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libdriver/input.cc b/contrib/groff/src/libs/libdriver/input.cc
new file mode 100644
index 0000000..e19841c
--- /dev/null
+++ b/contrib/groff/src/libs/libdriver/input.cc
@@ -0,0 +1,504 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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;
+ case 'u':
+ // .cu
+ pr->special(get_string(), &env, 'u');
+ 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/contrib/groff/src/libs/libdriver/printer.cc b/contrib/groff/src/libs/libdriver/printer.cc
new file mode 100644
index 0000000..4d66f7b
--- /dev/null
+++ b/contrib/groff/src/libs/libdriver/printer.cc
@@ -0,0 +1,271 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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 *, char)
+{
+}
+
+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);
+}
+
+font *printer::get_font_from_index(int fontno)
+{
+ if ((fontno >= 0) && (fontno < nfonts))
+ return(font_table[fontno]);
+ else
+ return(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/contrib/groff/src/libs/libgroff/Makefile.sub b/contrib/groff/src/libs/libgroff/Makefile.sub
new file mode 100644
index 0000000..5ce0691
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/Makefile.sub
@@ -0,0 +1,84 @@
+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 \
+ getopt.o \
+ getopt1.o \
+ htmlindicate.o \
+ illegal.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 \
+ $(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)/htmlindicate.cc \
+ $(srcdir)/illegal.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
+CSRCS=\
+ $(srcdir)/fmod.c \
+ $(srcdir)/getcwd.c \
+ $(srcdir)/getopt.c \
+ $(srcdir)/getopt1.c \
+ $(srcdir)/iftoa.c \
+ $(srcdir)/itoa.c \
+ $(srcdir)/matherr.c \
+ $(srcdir)/putenv.c \
+ $(srcdir)/strerror.c \
+ $(srcdir)/strtol.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/contrib/groff/src/libs/libgroff/assert.cc b/contrib/groff/src/libs/libgroff/assert.cc
new file mode 100644
index 0000000..89742e3
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/change_lf.cc b/contrib/groff/src/libs/libgroff/change_lf.cc
new file mode 100644
index 0000000..2e44af1
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/device.cc b/contrib/groff/src/libs/libgroff/device.cc
new file mode 100644
index 0000000..7efbfef
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/errarg.cc b/contrib/groff/src/libs/libgroff/errarg.cc
new file mode 100644
index 0000000..f8075ea
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/errarg.cc
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <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 *i_to_a(int);
+}
+
+void errarg::print() const
+{
+ switch (type) {
+ case INTEGER:
+ fputs(i_to_a(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/contrib/groff/src/libs/libgroff/error.cc b/contrib/groff/src/libs/libgroff/error.cc
new file mode 100644
index 0000000..53fd629
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/fatal.cc b/contrib/groff/src/libs/libgroff/fatal.cc
new file mode 100644
index 0000000..42560dc
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/filename.cc b/contrib/groff/src/libs/libgroff/filename.cc
new file mode 100644
index 0000000..1cbaa93
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/filename.cc
@@ -0,0 +1 @@
+const char *current_filename = 0;
diff --git a/contrib/groff/src/libs/libgroff/fmod.c b/contrib/groff/src/libs/libgroff/fmod.c
new file mode 100644
index 0000000..818f946
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/font.cc b/contrib/groff/src/libs/libgroff/font.cc
new file mode 100644
index 0000000..6cdd647
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/font.cc
@@ -0,0 +1,938 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <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 * = 0);
+ ~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)
+: 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 non-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/contrib/groff/src/libs/libgroff/fontfile.cc b/contrib/groff/src/libs/libgroff/fontfile.cc
new file mode 100644
index 0000000..cc1ad2c
--- /dev/null
+++ b/contrib/groff/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, 0, 0);
+
+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/contrib/groff/src/libs/libgroff/getcwd.c b/contrib/groff/src/libs/libgroff/getcwd.c
new file mode 100644
index 0000000..7a769ff
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/getcwd.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 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. */
+
+/* Partial emulation of getcwd in terms of getwd. */
+
+#include <sys/param.h>
+#include <string.h>
+#include <errno.h>
+
+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/contrib/groff/src/libs/libgroff/getopt.c b/contrib/groff/src/libs/libgroff/getopt.c
new file mode 100644
index 0000000..4744e43
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/getopt.c
@@ -0,0 +1,1055 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to drepper@gnu.org
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+ Free Software Foundation, Inc.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+# ifndef const
+# define const
+# endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+# include <gnu-versions.h>
+# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+# define ELIDE_CODE
+# endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+# include <stdlib.h>
+# include <unistd.h>
+#endif /* GNU C library. */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+# include <string.h>
+# endif
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+ When compiling libc, the _ macro is predefined. */
+# ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(msgid) gettext (msgid)
+# else
+# define _(msgid) (msgid)
+# endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+# include <string.h>
+# define my_index strchr
+#else
+
+# if HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# define SWAP_FLAGS(ch1, ch2) \
+ if (nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#ifdef _LIBC
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ if (nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len = strlen (orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', nonoption_flags_max_len - len);
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int print_errors = opterr;
+ if (optstring[0] == ':')
+ print_errors = 0;
+
+ optarg = NULL;
+
+ if (optind == 0 || !__getopt_initialized)
+ {
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring);
+ __getopt_initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+
+ nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (print_errors)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (print_errors)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/groff/src/libs/libgroff/getopt1.c b/contrib/groff/src/libs/libgroff/getopt1.c
new file mode 100644
index 0000000..3d264f2
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/getopt1.c
@@ -0,0 +1,188 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* Not ELIDE_CODE. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/groff/src/libs/libgroff/htmlindicate.cc b/contrib/groff/src/libs/libgroff/htmlindicate.cc
new file mode 100644
index 0000000..2e6a5d7
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/htmlindicate.cc
@@ -0,0 +1,97 @@
+/* Copyright (C) 2000, 2001 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. */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nonposix.h"
+#include "stringclass.h"
+#include "html-strings.h"
+
+/*
+ * This file contains a very simple set of routines shared by
+ * tbl, pic, eqn which help the html device driver to make
+ * sensible formatting choices. Currently it simply indicates
+ * to pre-html when an image is about to be created this is then
+ * passes to pre-html.
+ * Pre-html runs troff twice, once with -Thtml and once with -Tps.
+ * troff -Thtml device driver emits a <src='image'.png> tag
+ * and the postscript device driver works out the min/max limits
+ * of the graphic region. These region limits are read by pre-html
+ * and an image is generated via troff -Tps -> gs -> png
+ */
+
+static int is_in_graphic_start = 0;
+static int is_inline_image = 0;
+
+/*
+ * html_begin_suppress - emit a start of image tag which will be seen
+ * by pre-html.
+ */
+void html_begin_suppress(int is_inline)
+{
+ if (is_inline)
+ put_string(HTML_IMAGE_INLINE_BEGIN, stdout);
+ else {
+ put_string(HTML_IMAGE_CENTERED, stdout);
+ put_string("\n", stdout);
+ }
+}
+
+/*
+ * html_end_suppress - emit an end of image tag which will be seen
+ * by pre-html.
+ */
+void html_end_suppress(int is_inline)
+{
+ if (is_inline)
+ put_string(HTML_IMAGE_INLINE_END, stdout);
+ else {
+ put_string(HTML_IMAGE_END, stdout);
+ put_string("\n", stdout);
+ }
+}
+
+/*
+ * graphic_start - The boolean, is_inline, should be:
+ *
+ * FALSE if this is called via EQ, TS, PS, and
+ * TRUE if issued via delim $$ $ x over y $ etc.
+ */
+void graphic_start(int is_inline)
+{
+ if (!is_in_graphic_start) {
+ html_begin_suppress(is_inline);
+ is_inline_image = is_inline;
+ is_in_graphic_start = 1;
+ }
+}
+
+/*
+ * graphic_end - tell troff that the image region is ending.
+ */
+
+void graphic_end()
+{
+ if (is_in_graphic_start) {
+ html_end_suppress(is_inline_image);
+ is_in_graphic_start = 0;
+ }
+}
diff --git a/contrib/groff/src/libs/libgroff/iftoa.c b/contrib/groff/src/libs/libgroff/iftoa.c
new file mode 100644
index 0000000..29a3d89
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/iftoa.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 INT_DIGITS 19 /* enough for 64-bit integer */
+
+char *if_to_a(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/contrib/groff/src/libs/libgroff/itoa.c b/contrib/groff/src/libs/libgroff/itoa.c
new file mode 100644
index 0000000..72826b7
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/itoa.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 INT_DIGITS 19 /* enough for 64 bit integer */
+
+char *i_to_a(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/contrib/groff/src/libs/libgroff/lf.cc b/contrib/groff/src/libs/libgroff/lf.cc
new file mode 100644
index 0000000..34272c7
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/lineno.cc b/contrib/groff/src/libs/libgroff/lineno.cc
new file mode 100644
index 0000000..f7138db
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/lineno.cc
@@ -0,0 +1 @@
+int current_lineno = 0;
diff --git a/contrib/groff/src/libs/libgroff/macropath.cc b/contrib/groff/src/libs/libgroff/macropath.cc
new file mode 100644
index 0000000..03c04cb
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/macropath.cc
@@ -0,0 +1,30 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 "lib.h"
+#include "searchpath.h"
+#include "macropath.h"
+#include "defs.h"
+
+#define MACROPATH_ENVVAR "GROFF_TMAC_PATH"
+
+search_path macro_path(MACROPATH_ENVVAR, MACROPATH, 1, 1);
+search_path safer_macro_path(MACROPATH_ENVVAR, MACROPATH, 1, 0);
+search_path config_macro_path(MACROPATH_ENVVAR, MACROPATH, 0, 0);
diff --git a/contrib/groff/src/libs/libgroff/matherr.c b/contrib/groff/src/libs/libgroff/matherr.c
new file mode 100644
index 0000000..b0097b8
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/nametoindex.cc b/contrib/groff/src/libs/libgroff/nametoindex.cc
new file mode 100644
index 0000000..578ff34
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/nametoindex.cc
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <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, i_to_a(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/contrib/groff/src/libs/libgroff/new.cc b/contrib/groff/src/libs/libgroff/new.cc
new file mode 100644
index 0000000..8d98591
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/new.cc
@@ -0,0 +1,68 @@
+/* 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"
+#include "nonposix.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/contrib/groff/src/libs/libgroff/prime.cc b/contrib/groff/src/libs/libgroff/prime.cc
new file mode 100644
index 0000000..f0b1ead
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/progname.cc b/contrib/groff/src/libs/libgroff/progname.cc
new file mode 100644
index 0000000..a70e341
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/progname.cc
@@ -0,0 +1 @@
+const char *program_name = 0;
diff --git a/contrib/groff/src/libs/libgroff/ptable.cc b/contrib/groff/src/libs/libgroff/ptable.cc
new file mode 100644
index 0000000..76735c2
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/putenv.c b/contrib/groff/src/libs/libgroff/putenv.c
new file mode 100644
index 0000000..c1ca671
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/searchpath.cc b/contrib/groff/src/libs/libgroff/searchpath.cc
new file mode 100644
index 0000000..f4e2b90
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/searchpath.cc
@@ -0,0 +1,132 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "lib.h"
+#include "searchpath.h"
+#include "nonposix.h"
+
+search_path::search_path(const char *envvar, const char *standard,
+ int add_home, int add_current)
+{
+ char *home = 0;
+ if (add_home)
+ home = getenv("HOME");
+ char *e = 0;
+ if (envvar)
+ e = getenv(envvar);
+ dirs = new char[((e && *e) ? strlen(e) + 1 : 0)
+ + (add_current ? 1 + 1 : 0)
+ + ((home && *home) ? strlen(home) + 1 : 0)
+ + ((standard && *standard) ? strlen(standard) : 0)
+ + 1];
+ *dirs = '\0';
+ if (e && *e) {
+ strcat(dirs, e);
+ strcat(dirs, PATH_SEP);
+ }
+ if (add_current) {
+ strcat(dirs, ".");
+ strcat(dirs, PATH_SEP);
+ }
+ if (home && *home) {
+ strcat(dirs, home);
+ strcat(dirs, PATH_SEP);
+ }
+ if (standard && *standard)
+ strcat(dirs, standard);
+ init_len = strlen(dirs);
+}
+
+search_path::~search_path()
+{
+ // dirs is always allocated
+ a_delete dirs;
+}
+
+void search_path::command_line_dir(const char *s)
+{
+ 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++ = PATH_SEP[0];
+ memcpy(p, s, slen);
+ p += slen;
+ if (init_len > 0) {
+ *p++ = PATH_SEP[0];
+ 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 (IS_ABSOLUTE(name) || *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, PATH_SEP[0]);
+ if (!end)
+ end = strchr(p, '\0');
+ int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0;
+ 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/contrib/groff/src/libs/libgroff/strerror.c b/contrib/groff/src/libs/libgroff/strerror.c
new file mode 100644
index 0000000..69089f1
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/string.cc b/contrib/groff/src/libs/libgroff/string.cc
new file mode 100644
index 0000000..4bcd4cc
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/strsave.cc b/contrib/groff/src/libs/libgroff/strsave.cc
new file mode 100644
index 0000000..dfd2b6f
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/libs/libgroff/strtol.c b/contrib/groff/src/libs/libgroff/strtol.c
new file mode 100644
index 0000000..61ce70e
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/strtol.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#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/contrib/groff/src/libs/libgroff/tmpfile.cc b/contrib/groff/src/libs/libgroff/tmpfile.cc
new file mode 100644
index 0000000..a6c2010
--- /dev/null
+++ b/contrib/groff/src/libs/libgroff/tmpfile.cc
@@ -0,0 +1,186 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "posix.h"
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "nonposix.h"
+
+extern "C" {
+ // Solaris 2.5.1 has these functions,
+ // but its stdlib.h fails to declare them.
+ 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 if P_tmpdir is defined, create temporary files there
+#ifdef P_tmpdir
+# define DEFAULT_TMPDIR P_tmpdir
+#else
+// otherwise create temporary files here.
+# define DEFAULT_TMPDIR "/tmp"
+#endif
+// Use this as the prefix for temporary filenames.
+#define TMPFILE_PREFIX "groff"
+
+/*
+ * Generate a temporary name template with a postfix
+ * immediately after the TMPFILE_PREFIX.
+ * It uses the groff preferences for a temporary directory.
+ * Note that no file name is either created or opened,
+ * only the *template* is returned.
+ */
+
+char *xtmptemplate(char *postfix)
+{
+ const char *dir = getenv(GROFF_TMPDIR_ENVVAR);
+ int postlen = 0;
+
+ if (postfix)
+ postlen = strlen(postfix);
+
+ if (!dir) {
+ dir = getenv(TMPDIR_ENVVAR);
+ if (!dir)
+ dir = DEFAULT_TMPDIR;
+ }
+
+ size_t dir_len = strlen(dir);
+ const char *dir_end = dir + dir_len - 1;
+ int needs_slash = strchr(DIR_SEPS, *dir_end) == NULL;
+ char *templ = new char[strlen(dir) + needs_slash
+ + sizeof(TMPFILE_PREFIX) - 1 + 6 + 1 + postlen];
+ strcpy(templ, dir);
+ if (needs_slash)
+ strcat(templ, "/");
+ strcat(templ, TMPFILE_PREFIX);
+ if (postlen > 0)
+ strcat(templ, postfix);
+ strcat(templ, "XXXXXX");
+
+ return( templ );
+}
+
+// The trick with unlinking the temporary file while it is still in
+// use is not portable, it will fail on MS-DOS and most MS-Windows
+// filesystems. So it cannot be used on non-Posix systems.
+// Instead, we maintain a list of files to be deleted on exit, and
+// register an atexit function that will remove them all in one go.
+// This should be portable to all platforms.
+
+static struct xtmpfile_list {
+ struct xtmpfile_list *next;
+ char fname[1];
+} *xtmpfiles_to_delete;
+
+static void remove_tmp_files()
+{
+ struct xtmpfile_list *p = xtmpfiles_to_delete;
+
+ while (p)
+ {
+ if (unlink(p->fname) < 0)
+ error("cannot unlink `%1': %2", p->fname, strerror(errno));
+ struct xtmpfile_list *old = p;
+ p = p->next;
+ free(old);
+ }
+}
+
+static void add_tmp_file(const char *name)
+{
+ if (xtmpfiles_to_delete == NULL)
+ atexit(remove_tmp_files);
+
+ struct xtmpfile_list *p
+ = (struct xtmpfile_list *)malloc(sizeof(struct xtmpfile_list)
+ + strlen (name));
+ if (p == NULL)
+ {
+ error("cannot unlink `%1': %2", name, strerror(errno));
+ return;
+ }
+ p->next = xtmpfiles_to_delete;
+ strcpy(p->fname, name);
+ xtmpfiles_to_delete = p;
+}
+
+// Open a temporary file and with fatal error on failure.
+
+#ifndef _MSC_VER
+
+FILE *xtmpfile(char **namep, char *postfix, int do_unlink)
+{
+ char *templ = xtmptemplate(postfix);
+
+#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, FOPEN_RWB); // many callers of xtmpfile use binary I/O
+ 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, FOPEN_RWB);
+ if (!fp)
+ fatal("cannot open `%1': %2", templ, strerror(errno));
+#endif /* not HAVE_MKSTEMP */
+ if (do_unlink)
+ add_tmp_file(templ);
+ if ((namep != 0) && ((*namep) != 0)) {
+ *namep = templ;
+ } else {
+ a_delete templ;
+ }
+ return fp;
+}
+
+#else
+
+// FIXME: does MSVC have mktemp or mkstemp? If so, it should now
+// use the version above, as it no longer removes an open file.
+// The version below will NOT work with grohtml, since grohtml
+// wants to know the name of the file opened by xtmpfile!!
+
+// If you're not running Unix, the following will do:
+FILE *xtmpfile(char **namep, char *postfix, int do_unlink)
+{
+ FILE *fp = tmpfile();
+ if (!fp)
+ fatal("couldn't create temporary file");
+ return fp;
+}
+
+#endif /* _MSC_VER */
diff --git a/contrib/groff/src/preproc/eqn/Makefile.sub b/contrib/groff/src/preproc/eqn/Makefile.sub
new file mode 100644
index 0000000..20421e1c
--- /dev/null
+++ b/contrib/groff/src/preproc/eqn/Makefile.sub
@@ -0,0 +1,59 @@
+PROG=eqn
+MAN1=eqn.n neqn.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 $@
+ sed -e 's/@g@/$(g)/g' \
+ -e 's|@BINDIR@|$(bindir)|g' \
+ -e $(SH_SCRIPT_SED_CMD) $(srcdir)/neqn.sh >$@
+ chmod +x $@
+
+install_data: neqn
+ -rm -f $(bindir)/$(NAMEPREFIX)neqn
+ $(INSTALL_SCRIPT) neqn $(bindir)/$(NAMEPREFIX)neqn
+
+uninstall_sub:
+ -rm -f $(bindir)/$(NAMEPREFIX)neqn
diff --git a/contrib/groff/src/preproc/eqn/TODO b/contrib/groff/src/preproc/eqn/TODO
new file mode 100644
index 0000000..210d0ab
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/box.cc b/contrib/groff/src/preproc/eqn/box.cc
new file mode 100644
index 0000000..4e61b5d
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/box.h b/contrib/groff/src/preproc/eqn/box.h
new file mode 100644
index 0000000..01bfe96
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/delim.cc b/contrib/groff/src/preproc/eqn/delim.cc
new file mode 100644
index 0000000..29deded
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/eqn.cc b/contrib/groff/src/preproc/eqn/eqn.cc
new file mode 100644
index 0000000..1fdda61
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/eqn.h b/contrib/groff/src/preproc/eqn/eqn.h
new file mode 100644
index 0000000..70b1927
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/eqn.man b/contrib/groff/src/preproc/eqn/eqn.man
new file mode 100644
index 0000000..381d97d
--- /dev/null
+++ b/contrib/groff/src/preproc/eqn/eqn.man
@@ -0,0 +1,882 @@
+.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
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fB@g@eqn 'u
+.ti \niu
+.B @g@eqn
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-rvCNR
+.OP \-d cc
+.OP \-T name
+.OP \-M dir
+.OP \-f F
+.OP \-s n
+.OP \-p n
+.OP \-m n
+.RI "[\ " files\|.\|.\|. "\ ]"
+.br
+.ad \na
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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
+in the directories given with the
+.B \-M
+option first, then in
+.BR @SYSTEMMACRODIR@ ,
+.BR @LOCALMACRODIR@ ,
+and finally in the standard macro directory
+.BR @MACRODIR@ .
+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 ,
+.BR latin1 ,
+.BR utf8 ,
+and
+.B cp1047
+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/contrib/groff/src/preproc/eqn/eqn.y b/contrib/groff/src/preproc/eqn/eqn.y
new file mode 100644
index 0000000..833a0f0
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/eqn_tab.h b/contrib/groff/src/preproc/eqn/eqn_tab.h
new file mode 100644
index 0000000..9a8b3cb
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/lex.cc b/contrib/groff/src/preproc/eqn/lex.cc
new file mode 100644
index 0000000..25faec2
--- /dev/null
+++ b/contrib/groff/src/preproc/eqn/lex.cc
@@ -0,0 +1,1165 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 "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/contrib/groff/src/preproc/eqn/limit.cc b/contrib/groff/src/preproc/eqn/limit.cc
new file mode 100644
index 0000000..046885d
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/list.cc b/contrib/groff/src/preproc/eqn/list.cc
new file mode 100644
index 0000000..1118fa1
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/main.cc b/contrib/groff/src/preproc/eqn/main.cc
new file mode 100644
index 0000000..6dc03f0
--- /dev/null
+++ b/contrib/groff/src/preproc/eqn/main.cc
@@ -0,0 +1,419 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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"
+#include "htmlindicate.h"
+#include "pbox.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 html = 0;
+// if we encounter a region marked as an image then we
+// do not mark up inline equations.
+int suppress_html = 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() >= 12
+ && linebuf[0] == '.' && linebuf[1] == 'H' && linebuf[2] == 'T'
+ && linebuf[3] == 'M' && linebuf[4] == 'L' && linebuf[5] == '-'
+ && linebuf[6] == 'I' && linebuf[7] == 'M' && linebuf[8] == 'A'
+ && linebuf[9] == 'G' && linebuf[10] == 'E'
+ && linebuf[11] == '\n') {
+ put_string(linebuf, stdout);
+ suppress_html++;
+ }
+ else if (linebuf.length() >= 16
+ && linebuf[0] == '.' && linebuf[1] == 'H' && linebuf[2] == 'T'
+ && linebuf[3] == 'M' && linebuf[4] == 'L' && linebuf[5] == '-'
+ && linebuf[6] == 'I' && linebuf[7] == 'M' && linebuf[8] == 'A'
+ && linebuf[9] == 'G' && linebuf[10] == 'E' && linebuf[11] == '-'
+ && linebuf[12] == 'E' && linebuf[13] == 'N' && linebuf[14] == 'D'
+ && linebuf[15] == '\n') {
+ put_string(linebuf, stdout);
+ suppress_html--;
+ }
+ else if (linebuf.length() >= 4
+ && linebuf[0] == '.'
+ && linebuf[1] == 'E'
+ && linebuf[2] == 'Q'
+ && (linebuf[3] == ' ' || linebuf[3] == '\n'
+ || compatible_flag)) {
+ if (html && (suppress_html == 0))
+ graphic_start(0);
+ put_string(linebuf, 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(linebuf, stdout);
+ if (html && (suppress_html == 0))
+ graphic_end();
+ }
+ 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,
+// 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';
+ if (html && (suppress_html == 0)) {
+ printf(".as %s ", LINE_STRING);
+ graphic_start(1);
+ printf("\n");
+ }
+ init_lex(str.contents(), current_filename, start_lineno);
+ yyparse();
+ if (html && (suppress_html == 0)) {
+ printf(".as %s ", LINE_STRING);
+ graphic_end();
+ printf("\n");
+ }
+ 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();
+ 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(FILE *stream)
+{
+ fprintf(stream,
+ "usage: %s [ -rvDCNR ] -dxx -fn -sn -pn -mn -Mdir -Ts [ files ... ]\n",
+ program_name);
+}
+
+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;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "DCRvd:f:p:s:m:T:M:rN", long_options,
+ NULL))
+ != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'R': // don't load eqnrc
+ load_startup_file = 0;
+ break;
+ case 'M':
+ config_macro_path.command_line_dir(optarg);
+ break;
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU eqn (groff) version %s\n", Version_string);
+ exit(0);
+ 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;
+ if (strcmp(device, "ps:html") == 0) {
+ device = "ps";
+ html = 1;
+ }
+ 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 CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ default:
+ assert(0);
+ }
+ init_table(device);
+ init_char_table();
+ printf(".if !'\\*(.T'%s' "
+ ".if !'\\*(.T'html' " // the html device uses `-Tps' to render
+ // equations as images
+ ".tm warning: %s should have been given a `-T\\*(.T' option\n",
+ device, program_name);
+ printf(".if '\\*(.T'html' "
+ ".if !'%s'ps' "
+ ".tm warning: %s should have been given a `-Tps' option\n",
+ device, program_name);
+ printf(".if '\\*(.T'html' "
+ ".if !'%s'ps' "
+ ".tm warning: (it is advisable to invoke groff via: groff -Thtml -e)\n",
+ device);
+ if (load_startup_file) {
+ char *path;
+ FILE *fp = config_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/contrib/groff/src/preproc/eqn/mark.cc b/contrib/groff/src/preproc/eqn/mark.cc
new file mode 100644
index 0000000..99d1b75
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/neqn.man b/contrib/groff/src/preproc/eqn/neqn.man
new file mode 100644
index 0000000..bca7dc2
--- /dev/null
+++ b/contrib/groff/src/preproc/eqn/neqn.man
@@ -0,0 +1,21 @@
+.TH @G@NEQN @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@neqn \- format equations for ascii output
+.SH SYNOPSIS
+.B @g@neqn
+[@g@eqn options]
+.SH DESCRIPTION
+The
+.B @g@neqn
+program is actually just a shell script which invokes the
+.BR @g@eqn (@MAN1EXT@)
+command with the
+.B ascii
+output device.
+.LP
+Note that
+.B @g@eqn
+does not support low-resolution, typewriter-like devices (although it may
+work adequately for very simple input).
+.SH "SEE ALSO"
+.BR @g@eqn (@MAN1EXT@)
diff --git a/contrib/groff/src/preproc/eqn/other.cc b/contrib/groff/src/preproc/eqn/other.cc
new file mode 100644
index 0000000..eb9e50a
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/over.cc b/contrib/groff/src/preproc/eqn/over.cc
new file mode 100644
index 0000000..06b0321
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/pbox.h b/contrib/groff/src/preproc/eqn/pbox.h
new file mode 100644
index 0000000..d1f16ac
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/pile.cc b/contrib/groff/src/preproc/eqn/pile.cc
new file mode 100644
index 0000000..0df5241
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/script.cc b/contrib/groff/src/preproc/eqn/script.cc
new file mode 100644
index 0000000..7c2e6c2
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/special.cc b/contrib/groff/src/preproc/eqn/special.cc
new file mode 100644
index 0000000..310261a
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/sqrt.cc b/contrib/groff/src/preproc/eqn/sqrt.cc
new file mode 100644
index 0000000..6109ffe
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/eqn/text.cc b/contrib/groff/src/preproc/eqn/text.cc
new file mode 100644
index 0000000..b0f1700
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/grn/Makefile.sub b/contrib/groff/src/preproc/grn/Makefile.sub
new file mode 100644
index 0000000..ffa0ad2
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/Makefile.sub
@@ -0,0 +1,17 @@
+PROG=grn
+MAN1=grn.n
+MLIB=$(LIBM)
+XLIBS=$(LIBGROFF)
+OBJS=\
+ hdb.o \
+ hpoint.o \
+ hgraph.o \
+ main.o
+CCSRCS=\
+ $(srcdir)/hdb.cc \
+ $(srcdir)/hpoint.cc \
+ $(srcdir)/hgraph.cc \
+ $(srcdir)/main.cc
+HDRS=\
+ $(srcdir)/gprint.h
+NAMEPREFIX=$(g)
diff --git a/contrib/groff/src/preproc/grn/README b/contrib/groff/src/preproc/grn/README
new file mode 100644
index 0000000..b5b9fc9
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/README
@@ -0,0 +1,60 @@
+This is grn from the Berkeley ditroff distribution. It has no
+AT&T code and is therefore freely distributable.
+
+Tim Theisen <tim@cs.wisc.edu>
+
+=====================================================================
+
+This is the modified code for the groff. It uses the different
+devxxx format that is ascii rather than binary as in the
+Berkeley distribution. Since groff does not have the \Ds option
+for line drawing (dotted, dashed, etc.), this version includes
+the routines for drawing curves and arcs, so it does not use the
+\D~, \Da nor \Dc. Although also included in here is a routine
+for drawing the optional gremlin style curves, it is not used
+because the gremlin editor uses the conventional spline
+algorithm. The Berkeley grn has the choice of different
+stipples. Here, only different shades of gray will be painted
+depending on the gremlin file. It is possible to upgrade this at
+a later time. (Daniel Senderowicz <daniel@synchrods.com> 12/28/99)
+
+=====================================================================
+
+It has been further modified by Werner Lemberg <wl@gnu.org> to fit
+better into the groff package.
+
+ . Replaced Makefile with Makefile.sub.
+
+ . Removed dev.h since it is unused.
+
+ . Renamed grn.1 to grn.man; this man page has been extensively
+ revised.
+
+ . Used error() and fatal() from libgroff for all source files.
+
+ . Renamed *.c to *.cc; updates as needed for C++ (prototypes, proper
+ casts, standard header files etc). Heavy formatting.
+
+ . main.cc:
+
+ Using groff's default values instead of DEVDIR, DEFAULTDEV, PRINTER,
+ TYPESETTER, and GREMLIB.
+
+ `res' is now an integer.
+
+ Added `-C' command flag (for compatibility mode) as with other
+ preprocessors.
+
+ Added `-F' and `-v' option (similar to troff).
+
+ Renamed `-L' option to `-M' for consistence.
+
+ Removed `-P' option.
+
+ Using font::load_desc() for scanning DESC files.
+
+ Removed SYSV-specific code.
+
+ Using macro_path.open_file() for getting gremlin graphic files.
+
+ Added usage().
diff --git a/contrib/groff/src/preproc/grn/gprint.h b/contrib/groff/src/preproc/grn/gprint.h
new file mode 100644
index 0000000..b25305b
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/gprint.h
@@ -0,0 +1,84 @@
+/* Last non-groff version: gprint.h 1.1 84/10/08
+ *
+ * This file contains standard definitions used by the gprint program.
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+
+#define xorn(x,y) (x)
+ /* was 512 */
+#define yorn(x,y) (511 - (y)) /* switch direction for */
+ /* y-coordinates */
+
+#define STYLES 6
+#define SIZES 4
+#define FONTS 4
+#define SOLID -1
+#define DOTTED 004 /* 014 */
+#define DASHED 020 /* 034 */
+#define DOTDASHED 024 /* 054 */
+#define LONGDASHED 074
+
+#define DEFTHICK -1 /* default thicknes */
+#define DEFSTYLE SOLID /* default line style */
+
+#define TRUE 1
+#define FALSE 0
+
+#define nullelt -1
+#define nullpt -1
+#define nullun NULL
+
+#define BOTLEFT 0
+#define BOTRIGHT 1
+#define CENTCENT 2
+#define VECTOR 3
+#define ARC 4
+#define CURVE 5
+#define POLYGON 6
+#define TOPLEFT 10
+#define TOPCENT 11
+#define TOPRIGHT 12
+#define CENTLEFT 13
+#define CENTRIGHT 14
+#define BOTCENT 15
+#define TEXT(t) ( (t <= CENTCENT) || (t >= TOPLEFT) )
+
+/* WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING
+ * The above (TEXT) test is dependent on the relative values of the
+ * constants and will have to change if these values change or if new
+ * commands are added with value greater than BOTCENT
+ */
+
+#define NUSER 4
+#define NFONTS 4
+#define NBRUSHES 6
+#define NSIZES 4
+#define NJUSTS 9
+#define NSTIPPLES 16
+
+#define ADD 1
+#define DELETE 2
+#define MOD 3
+
+typedef struct point {
+ float x, y;
+ struct point *nextpt;
+} POINT;
+
+typedef struct elmt {
+ int type, brushf, size, textlength;
+ char *textpt;
+ POINT *ptlist;
+ struct elmt *nextelt, *setnext;
+} ELT;
+
+#define DBNextElt(elt) (elt->nextelt)
+#define DBNextofSet(elt) (elt->setnext)
+#define DBNullelt(elt) (elt == NULL)
+#define Nullpoint(pt) ((pt) == (POINT *) NULL)
+#define PTNextPoint(pt) (pt->nextpt)
+
+/* EOF */
diff --git a/contrib/groff/src/preproc/grn/grn.man b/contrib/groff/src/preproc/grn/grn.man
new file mode 100644
index 0000000..f2613da
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/grn.man
@@ -0,0 +1,636 @@
+.ig \"-*- nroff -*-
+Copyright (C) 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 @G@GRN @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+@g@grn \- groff preprocessor for gremlin files
+.SH SYNOPSIS
+.BR @g@grn
+[
+.B \-Cv
+]
+[
+.BI \-T dev
+]
+[
+.BI \-M dir
+]
+[
+.BI \-F dir
+]
+[
+.IR file\.\.\.
+]
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.SH DESCRIPTION
+.I @g@grn
+is a preprocessor for including
+.I gremlin
+pictures in
+.I groff
+input.
+.I @g@grn
+writes to standard output, processing only input lines between two that
+start with
+.B .GS
+and
+.BR .GE.
+Those lines must contain
+.I @g@grn
+commands (see below).
+These commands request a
+.I gremlin
+file, and the picture in that file is
+converted and placed in the
+.I @g@troff
+input stream.
+The
+.B .GS
+request may be followed by a C, L, or R to center, left, or right
+justify the whole
+.I gremlin
+picture (default justification is center).
+If no
+.I file
+is mentioned, the standard input is read.
+At the end of the picture, the position on the page is the bottom of the
+.I gremlin
+picture.
+If the
+.I @g@grn
+entry is ended with
+.B .GF
+instead of
+.BR .GE ,
+the position is left at the top of the picture.
+.PP
+Please note that currently only the \-me macro package has support for
+.BR .GS ,
+.BR .GE ,
+and
+.BR .GF .
+.PP
+The following command-line options are understood:
+.TP
+.BI \-T dev
+Prepare output for printer
+.IR dev .
+The default device is
+.BR @DEVICE@ .
+See
+.BR groff (@MAN1EXT@)
+for acceptable devices.
+.TP
+.BI \-M dir
+Prepend
+.I dir
+to the default search path for
+.I gremlin
+files.
+The default path is (in that order) the current directory, the home
+directory,
+.BR @SYSTEMMACRODIR@ ,
+.BR @LOCALMACRODIR@ ,
+and
+.BR @MACRODIR@ .
+.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 before the normal
+.BR @FONTDIR@ .
+.TP
+.B \-C
+Recognize
+.B .GS
+and
+.B .GE
+(resp.
+.BR .GF )
+even when followed by a character other than space or newline.
+.\".TP
+.\".B \-s
+.\"This switch causes the picture to be traversed twice:
+.\"The first time, only the interiors of filled polygons (as borderless
+.\"polygons) are printed.
+.\"The second time, the outline is printed as a series of line segments.
+.\"This way, postprocessors that overwrite rather than merge picture elements
+.\"(such as Postscript) can still have text and graphics on a shaded
+.\"background.
+.TP
+.B \-v
+Print the version number.
+.SH GRN COMMANDS
+Each input line between
+.B .GS
+and
+.B .GE
+may have one
+.I @g@grn
+command.
+Commands consist of one or two strings separated by white space, the first
+string being the command and the second its operand.
+Commands may be upper or lower case and abbreviated down to one character.
+.PP
+Commands that affect a picture's environment (those listed before
+.BR default ,
+see below) are only in effect for the current picture:
+The environment is reinitialized to the defaults at the start of the next
+picture.
+The commands are as follows:
+.TP
+.BI 1\ N
+.TQ
+.BI 2\ N
+.TQ
+.BI 3\ N
+.TQ
+.BI 4\ N
+Set
+.IR gremlin 's
+text size number 1 (2, 3, or 4) to
+.I N
+points.
+The default is 12 (resp. 16, 24, and 36).
+.TP
+.BI roman\ f
+.TQ
+.BI italics\ f
+.TQ
+.BI bold\ f
+.TQ
+.BI special\ f
+Set the roman (italics, bold, or special) font to
+.IR @g@troff 's
+font
+.I f
+(either a name or number).
+The default is R (resp. I, B, and S).
+.TP
+.BI l\ f
+.TQ
+.BI stipple\ f
+Set the stipple font to
+.IR @g@troff 's
+stipple font
+.I f
+(name or number).
+The command
+.B stipple
+may be abbreviated down as far as `st' (to avoid
+confusion with
+.BR special ).
+There is
+.I no
+default for stipples (unless one is set by the default command), and it is
+illegal to include a
+.I gremlin
+picture with polygons without specifying a
+stipple font.
+.TP
+.BI x\ N
+.TQ
+.BI scale\ N
+Magnify the picture (in addition to any default magnification) by
+.IR N ,
+a floating point number larger than zero.
+The command
+.B scale
+may be abbreviated down to `sc'.
+.TP
+.BI narrow\ N
+.TQ
+.BI medium\ N
+.TQ
+.BI thick\ N
+Set the thickness of
+.IR gremlin 's
+narrow (resp. medium and thick) lines to
+.I N
+times 0.15pt (this value can be changed at compile time).
+The default is 1.0 (resp. 3.0 and 5.0), which corresponds to 0.15pt
+(resp. 0.45pt and 0.75pt).
+A thickness value of zero selects the smallest available line thickness.
+Negative values cause the line thickness to be proportional to the current
+point size.
+.TP
+.BI pointscale\ <off/on>
+Scale text to match the picture.
+Gremlin text is usually printed in the point size specified with the
+commands
+.BR 1 ,\ 2 ,\ 3 ,\ or\ 4
+regardless of any scaling factors in the picture.
+Setting
+.B pointscale
+will cause the point sizes to scale with the picture (within
+.IR @g@troff 's
+limitations, of course).
+An operand of anything but
+.I off
+will turn text scaling on.
+.TP
+.B default
+Reset the picture environment defaults to the settings in the current
+picture.
+This is meant to be used as a global parameter setting mechanism at the
+beginning of the
+.I @g@troff
+input file, but can be used at any time to reset the
+default settings.
+.TP
+.BI width\ N
+Forces the picture to be
+.I N
+inches wide.
+This overrides any scaling factors present in the same picture.
+.RB ` width
+.IR 0 '
+is ignored.
+.TP
+.BI height\ N
+Forces picture to be
+.I N
+inches high, overriding other scaling factors.
+If both `width' and `height' are specified the tighter constraint will
+determine the scale of the picture.
+.B Height
+and
+.B width
+commands are not saved with a
+.B default
+command.
+They will, however, affect point size scaling if that option is set.
+.TP
+.BI file\ name
+Get picture from
+.I gremlin
+file
+.I name
+located the current directory (or in the library directory; see the
+.B \-M
+option above).
+If two
+.B file
+commands are given, the second one overrides the first.
+If
+.I name
+doesn't exist, an error message is reported and processing continues from
+the
+.B .GE
+line.
+.SH NOTES ABOUT GROFF
+Since
+.I @g@grn
+is a preprocessor, it doesn't know about current indents, point sizes,
+margins, number registers, etc.
+Consequently, no
+.I @g@troff
+input can be placed between the
+.B .GS
+and
+.B .GE
+requests.
+However,
+.I gremlin
+text is now processed by
+.IR @g@troff ,
+so anything legal in a single line of
+.I @g@troff
+input is legal in a line of
+.I gremlin
+text (barring `.' directives at the beginning of a line).
+Thus, it is possible to have equations within a
+.I gremlin
+figure by including in the
+.I gremlin
+file
+.I eqn
+expressions enclosed by previously defined delimiters (e.g.
+.IR $$ ).
+.PP
+When using
+.I @g@grn
+along with other preprocessors, it is best to run
+.I tbl
+before
+.IR @g@grn ,
+.IR pic ,
+and/or
+.I ideal
+to avoid overworking
+.IR tbl .
+.I Eqn
+should always be run last.
+.PP
+A picture is considered an entity, but that doesn't stop
+.I @g@troff
+from trying to break it up if it falls off the end of a page.
+Placing the picture between `keeps' in \-me macros will ensure proper
+placement.
+.PP
+.I @g@grn
+uses
+.IR @g@troff 's
+number registers
+.B g1
+through
+.B g9
+and sets registers
+.B g1
+and
+.B g2
+to the width and height of the
+.I gremlin
+figure (in device units) before entering the
+.B .GS
+request (this is for those who want to rewrite these macros).
+.SH GREMLIN FILE FORMAT
+There exist two distinct
+.I gremlin
+file formats, the original format from the
+.I AED
+graphic terminal version, and the
+.I SUN
+or
+.I X11
+version.
+An extension to the
+.IR SUN / X11
+version allowing reference points with negative coordinates is
+.B not
+compatible with the
+.I AED
+version.
+As long as a
+.I gremlin
+file does not contain negative coordinates, either format will be read
+correctly by either version of
+.I gremlin
+or
+.IR @g@grn .
+The other difference to the
+.IR SUN / X11
+format is the use of names for picture objects (e.g., POLYGON, CURVE)
+instead of numbers.
+Files representing the same picture are shown in Table 1 in each format.
+.sp
+.DS
+.TS
+center, tab(@);
+l lw(0.1i) l.
+sungremlinfile@@gremlinfile
+0 240.00 128.00@@0 240.00 128.00
+CENTCENT@@2
+240.00 128.00@@240.00 128.00
+185.00 120.00@@185.00 120.00
+240.00 120.00@@240.00 120.00
+296.00 120.00@@296.00 120.00
+*@@-1.00 -1.00
+2 3@@2 3
+10 A Triangle@@10 A Triangle
+POLYGON@@6
+224.00 416.00@@224.00 416.00
+96.00 160.00@@96.00 160.00
+384.00 160.00@@384.00 160.00
+*@@-1.00 -1.00
+5 1@@5 1
+0@@0
+-1@@-1
+.T&
+css.
+.sp
+Table 1. File examples
+.TE
+.DE
+.sp
+.IP \(bu
+The first line of each
+.I gremlin
+file contains either the string
+.B gremlinfile
+.RI ( AED
+version) or
+.B sungremlinfile
+.RI ( SUN / X11 )
+.IP \(bu
+The second line of the file contains an orientation, and
+.B x
+and
+.B y
+values for a positioning point, separated by spaces.
+The orientation, either
+.B 0
+or
+.BR 1 ,
+is ignored by the
+.IR SUN / X11
+version.
+.B 0
+means that
+.I gremlin
+will display things in horizontal format (drawing area wider than it is
+tall, with menu across top).
+.B 1
+means that
+.I gremlin
+will display things in vertical format (drawing area taller than it is wide,
+with menu on left side).
+.B x
+and
+.B y
+are floating point values giving a positioning point to be used when this
+file is read into another file.
+The stuff on this line really isn't all that important; a value of ``1 0.00
+0.00'' is suggested.
+.IP \(bu
+The rest of the file consists of zero or more element specifications.
+After the last element specification is a line containing the string ``-1''.
+.SH ELEMENT SPECIFICATIONS
+.IP \(bu
+The first line of each element contains a single decimal number giving the
+type of the element
+.RI ( AED
+version) or its ASCII name
+.RI ( SUN / X11
+version).
+See Table 2.
+.sp
+.DS
+.TS
+center, tab(@);
+css
+ccc
+nll.
+\fIgremlin\fP File Format \(mi Object Type Specification
+.sp
+\fIAED\fP Number@\fISUN\fP/\fIX11\fP Name@Description
+0@BOTLEFT@bottom-left-justified text
+1@BOTRIGHT@bottom-right-justified text
+2@CENTCENT@center-justified text
+3@VECTOR@vector
+4@ARC@arc
+5@CURVE@curve
+6@POLYGON@polygon
+10@TOPLEFT@top-left-justified text
+11@TOPCENT@top-center-justified text
+12@TOPRIGHT@top-right-justified text
+13@CENTLEFT@left-center-justified text
+14@CENTRIGHT@right-center-justified text
+15@BOTCENT@bottom-center-justified text
+.T&
+css.
+.sp
+Table 2.
+Type Specifications in \fIgremlin\fP Files
+.TE
+.DE
+.sp
+.IP \(bu
+After the object type comes a variable number of lines, each specifying a
+point used to display the element.
+Each line contains an x-coordinate and a y-coordinate in floating point
+format, separated by spaces.
+The list of points is terminated by a line containing the string ``-1.0
+-1.0''
+.RI ( AED
+version) or a single asterisk, ``*''
+.RI ( SUN / X11
+version).
+.IP \(bu
+After the points comes a line containing two decimal values, giving the
+brush and size for the element.
+The brush determines the style in which things are drawn.
+For vectors, arcs, and curves there are six legal brush values:
+.sp
+.DS
+.TS
+center, tab(@);
+ncw(0.1i)l.
+1 \(mi@@thin dotted lines
+2 \(mi@@thin dot-dashed lines
+3 \(mi@@thick solid lines
+4 \(mi@@thin dashed lines
+5 \(mi@@thin solid lines
+6 \(mi@@medium solid lines
+.TE
+.DE
+.sp
+For polygons, one more value, 0, is legal.
+It specifies a polygon with an invisible border.
+For text, the brush selects a font as follows:
+.sp
+.DS
+.TS
+center, tab(@);
+ncw(0.1i)l.
+1 \(mi@@roman (R font in groff)
+2 \(mi@@italics (I font in groff)
+3 \(mi@@bold (B font in groff)
+4 \(mi@@special (S font in groff)
+.TE
+.DE
+.sp
+If you're using
+.I @g@grn
+to run your pictures through
+.IR groff ,
+the font is really just a starting font:
+The text string can contain formatting sequences like
+``\\fI''
+or
+``\\d''
+which may change the font (as well as do many other things).
+For text, the size field is a decimal value between 1 and 4.
+It selects the size of the font in which the text will be drawn.
+For polygons, this size field is interpreted as a stipple number to fill the
+polygon with.
+The number is used to index into a stipple font at print time.
+.IP \(bu
+The last line of each element contains a decimal number and a string of
+characters, separated by a single space.
+The number is a count of the number of characters in the string.
+This information is only used for text elements, and contains the text
+string.
+There can be spaces inside the text.
+For arcs, curves, and vectors, this line of the element contains the string
+``0''.
+.SH NOTES ON COORDINATES
+.I gremlin
+was designed for
+.IR AED s,
+and its coordinates reflect the
+.I AED
+coordinate space.
+For vertical pictures, x-values range 116 to 511, and y-values from 0 to
+483.
+For horizontal pictures, x-values range from 0 to 511 and y-values range
+from 0 to 367.
+Although you needn't absolutely stick to this range, you'll get best results
+if you at least stay in this vicinity.
+Also, point lists are terminated by a point of (-1, -1), so you shouldn't
+ever use negative coordinates.
+.I gremlin
+writes out coordinates using format ``%f1.2''; it's probably a good idea to
+use the same format if you want to modify the
+.I @g@grn
+code.
+.SH NOTES ON SUN/X11 COORDINATES
+There is no longer a restriction on the range of coordinates used to create
+objects in the
+.IR SUN / X11
+version of
+.IR gremlin .
+However, files with negative coordinates
+.B will
+cause problems if displayed on the
+.IR AED .
+.SH FILES
+.Tp \w'@FONTDIR@/devname/DESC'u+3n
+.BI @FONTDIR@/dev name /DESC
+Device description file for device
+.IR name .
+.SH SEE ALSO
+.BR gremlin (1),
+.BR groff (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR ideal (1)
+.SH HISTORY
+.PP
+David Slattengren and Barry Roitblat wrote the original Berkeley
+.IR @g@grn .
+.PP
+Daniel Senderowicz and Werner Lemberg modified it for
+.IR groff .
diff --git a/contrib/groff/src/preproc/grn/hdb.cc b/contrib/groff/src/preproc/grn/hdb.cc
new file mode 100644
index 0000000..fd5bb48
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/hdb.cc
@@ -0,0 +1,326 @@
+/* Last non-groff version: hdb.c 1.8 (Berkeley) 84/10/20
+ *
+ * Copyright -C- 1982 Barry S. Roitblat
+ *
+ * This file contains database routines for the hard copy programs of the
+ * gremlin picture editor.
+ */
+
+#include "gprint.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "errarg.h"
+#include "error.h"
+
+#define MAXSTRING 128
+
+/* imports from main.cc */
+
+extern int linenum; /* current line number in input file */
+extern char gremlinfile[]; /* name of file currently reading */
+extern int SUNFILE; /* TRUE if SUN gremlin file */
+extern void savebounds(float x, float y);
+
+/* imports from hpoint.cc */
+
+extern POINT *PTInit();
+extern POINT *PTMakePoint(float x, float y, POINT ** pplist);
+
+
+int DBGetType(register char *s);
+
+
+/*
+ * This routine returns a pointer to an initialized database element which
+ * would be the only element in an empty list.
+ */
+ELT *
+DBInit()
+{
+ return ((ELT *) NULL);
+} /* end DBInit */
+
+
+/*
+ * This routine creates a new element with the specified attributes and
+ * links it into database.
+ */
+ELT *
+DBCreateElt(int type,
+ POINT * pointlist,
+ int brush,
+ int size,
+ char *text,
+ ELT **db)
+{
+ register ELT *temp;
+
+ temp = (ELT *) malloc(sizeof(ELT));
+ temp->nextelt = *db;
+ temp->type = type;
+ temp->ptlist = pointlist;
+ temp->brushf = brush;
+ temp->size = size;
+ temp->textpt = text;
+ *db = temp;
+ return (temp);
+} /* end CreateElt */
+
+
+/*
+ * This routine reads the specified file into a database and returns a
+ * pointer to that database.
+ */
+ELT *
+DBRead(register FILE *file)
+{
+ register int i;
+ register int done; /* flag for input exhausted */
+ register float nx; /* x holder so x is not set before orienting */
+ int type; /* element type */
+ ELT *elist; /* pointer to the file's elements */
+ POINT *plist; /* pointer for reading in points */
+ char string[MAXSTRING], *txt;
+ float x, y; /* x and y are read in point coords */
+ int len, brush, size;
+ int lastpoint;
+
+ SUNFILE = FALSE;
+ elist = DBInit();
+ (void) fscanf(file, "%s\n", string);
+ if (strcmp(string, "gremlinfile")) {
+ if (strcmp(string, "sungremlinfile")) {
+ error("`%1' is not a gremlin file", gremlinfile);
+ return (elist);
+ }
+ SUNFILE = TRUE;
+ }
+
+ (void) fscanf(file, "%d%f%f\n", &size, &x, &y);
+ /* ignore orientation and file positioning point */
+
+ done = FALSE;
+ while (!done) {
+ /* if (fscanf(file,"%s\n", string) == EOF) */
+ /* I changed the scanf format because the element */
+ /* can have two words (e.g. CURVE SPLINE) */
+ if (fscanf(file, "\n%[^\n]\n", string) == EOF) {
+ error("`%1', error in file format", gremlinfile);
+ return (elist);
+ }
+
+ type = DBGetType(string); /* interpret element type */
+ if (type < 0) { /* no more data */
+ done = TRUE;
+ (void) fclose(file);
+ } else {
+#ifdef UW_FASTSCAN
+ (void) xscanf(file, &x, &y); /* always one point */
+#else
+ (void) fscanf(file, "%f%f\n", &x, &y); /* always one point */
+#endif /* UW_FASTSCAN */
+ plist = PTInit(); /* NULL point list */
+
+ /*
+ * Files created on the SUN have point lists terminated by a line
+ * containing only an asterik ('*'). Files created on the AED have
+ * point lists terminated by the coordinate pair (-1.00 -1.00).
+ */
+ if (TEXT(type)) { /* read only first point for TEXT elements */
+ nx = xorn(x, y);
+ y = yorn(x, y);
+ (void) PTMakePoint(nx, y, &plist);
+ savebounds(nx, y);
+
+#ifdef UW_FASTSCAN
+ while (xscanf(file, &x, &y));
+#else
+ lastpoint = FALSE;
+ do {
+ fgets(string, MAXSTRING, file);
+ if (string[0] == '*') { /* SUN gremlin file */
+ lastpoint = TRUE;
+ } else {
+ (void) sscanf(string, "%f%f", &x, &y);
+ if ((x == -1.00 && y == -1.00) && (!SUNFILE))
+ lastpoint = TRUE;
+ }
+ } while (!lastpoint);
+#endif /* UW_FASTSCAN */
+ } else { /* not TEXT element */
+#ifdef UW_FASTSCAN
+ do {
+ nx = xorn(x, y);
+ y = yorn(x, y);
+ (void) PTMakePoint(nx, y, &plist);
+ savebounds(nx, y);
+ } while (xscanf(file, &x, &y));
+#else
+ lastpoint = FALSE;
+ while (!lastpoint) {
+ nx = xorn(x, y);
+ y = yorn(x, y);
+ (void) PTMakePoint(nx, y, &plist);
+ savebounds(nx, y);
+
+ fgets(string, MAXSTRING, file);
+ if (string[0] == '*') { /* SUN gremlin file */
+ lastpoint = TRUE;
+ } else {
+ (void) sscanf(string, "%f%f", &x, &y);
+ if ((x == -1.00 && y == -1.00) && (!SUNFILE))
+ lastpoint = TRUE;
+ }
+ }
+#endif /* UW_FASTSCAN */
+ }
+ (void) fscanf(file, "%d%d\n", &brush, &size);
+ (void) fscanf(file, "%d", &len); /* text length */
+ (void) getc(file); /* eat blank */
+ txt = (char *) malloc((unsigned) len + 1);
+ for (i = 0; i < len; ++i) { /* read text */
+ txt[i] = getc(file);
+ }
+ txt[len] = '\0';
+ (void) DBCreateElt(type, plist, brush, size, txt, &elist);
+ } /* end else */
+ } /* end while not done */ ;
+ return (elist);
+} /* end DBRead */
+
+
+/*
+ * Interpret element type in string s.
+ * Old file format consisted of integer element types.
+ * New file format has literal names for element types.
+ */
+int
+DBGetType(register char *s)
+{
+ if (isdigit(s[0]) || (s[0] == '-')) /* old element format or EOF */
+ return (atoi(s));
+
+ switch (s[0]) {
+ case 'P':
+ return (POLYGON);
+ case 'V':
+ return (VECTOR);
+ case 'A':
+ return (ARC);
+ case 'C':
+ if (s[1] == 'U')
+ return (CURVE);
+ switch (s[4]) {
+ case 'L':
+ return (CENTLEFT);
+ case 'C':
+ return (CENTCENT);
+ case 'R':
+ return (CENTRIGHT);
+ default:
+ fatal("unknown element type");
+ }
+ case 'B':
+ switch (s[3]) {
+ case 'L':
+ return (BOTLEFT);
+ case 'C':
+ return (BOTCENT);
+ case 'R':
+ return (BOTRIGHT);
+ default:
+ fatal("unknown element type");
+ }
+ case 'T':
+ switch (s[3]) {
+ case 'L':
+ return (TOPLEFT);
+ case 'C':
+ return (TOPCENT);
+ case 'R':
+ return (TOPRIGHT);
+ default:
+ fatal("unknown element type");
+ }
+ default:
+ fatal("unknown element type");
+ }
+
+ return 0; /* never reached */
+}
+
+#ifdef UW_FASTSCAN
+/*
+ * Optimization hack added by solomon@crys.wisc.edu, 12/2/86.
+ * A huge fraction of the time was spent reading floating point numbers from
+ * the input file, but the numbers always have the format 'ddd.dd'. Thus
+ * the following special-purpose version of fscanf.
+ *
+ * xscanf(f,xp,yp) does roughly what fscanf(f,"%f%f",xp,yp) does except:
+ * -the next piece of input must be of the form
+ * <space>* <digit>*'.'<digit>* <space>* <digit>*'.'<digit>*
+ * -xscanf eats the character following the second number
+ * -xscanf returns 0 for "end-of-data" indication, 1 otherwise, where
+ * end-of-data is signalled by a '*' [in which case the rest of the
+ * line is gobbled], or by '-1.00 -1.00' [but only if !SUNFILE].
+ */
+int
+xscanf(FILE *f,
+ float *xp,
+ float *yp)
+{
+ register int c, i, j, m, frac;
+ int iscale = 1, jscale = 1; /* x = i/scale, y=j/jscale */
+
+ while ((c = getc(f)) == ' ');
+ if (c == '*') {
+ while ((c = getc(f)) != '\n');
+ return 0;
+ }
+ i = m = frac = 0;
+ while (isdigit(c) || c == '.' || c == '-') {
+ if (c == '-') {
+ m++;
+ c = getc(f);
+ continue;
+ }
+ if (c == '.')
+ frac = 1;
+ else {
+ if (frac)
+ iscale *= 10;
+ i = 10 * i + c - '0';
+ }
+ c = getc(f);
+ }
+ if (m)
+ i = -i;
+ *xp = (double) i / (double) iscale;
+
+ while ((c = getc(f)) == ' ');
+ j = m = frac = 0;
+ while (isdigit(c) || c == '.' || c == '-') {
+ if (c == '-') {
+ m++;
+ c = getc(f);
+ continue;
+ }
+ if (c == '.')
+ frac = 1;
+ else {
+ if (frac)
+ jscale *= 10;
+ j = 10 * j + c - '0';
+ }
+ c = getc(f);
+ }
+ if (m)
+ j = -j;
+ *yp = (double) j / (double) jscale;
+ return (SUNFILE || i != -iscale || j != -jscale);
+}
+#endif /* UW_FASTSCAN */
+
+/* EOF */
diff --git a/contrib/groff/src/preproc/grn/hgraph.cc b/contrib/groff/src/preproc/grn/hgraph.cc
new file mode 100644
index 0000000..7963720
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/hgraph.cc
@@ -0,0 +1,1043 @@
+/* Last non-groff version: hgraph.c 1.14 (Berkeley) 84/11/27
+ *
+ * This file contains the graphics routines for converting gremlin pictures
+ * to troff input.
+ */
+
+#include "gprint.h"
+
+#ifdef NEED_DECLARATION_HYPOT
+extern "C" {
+ double hypot(double, double);
+}
+#endif /* NEED_DECLARATION_HYPOT */
+
+#define MAXVECT 40
+#define MAXPOINTS 200
+#define LINELENGTH 1
+#define PointsPerInterval 64
+#define pi 3.14159265358979324
+#define twopi (2.0 * pi)
+#define len(a, b) hypot((double)(b.x-a.x), (double)(b.y-a.y))
+
+
+extern int dotshifter; /* for the length of dotted curves */
+
+extern int style[]; /* line and character styles */
+extern double thick[];
+extern char *tfont[];
+extern int tsize[];
+extern int stipple_index[]; /* stipple font index for stipples 0 - 16 */
+extern char *stipple; /* stipple type (cf or ug) */
+
+
+extern double troffscale; /* imports from main.c */
+extern double linethickness;
+extern int linmod;
+extern int lastx;
+extern int lasty;
+extern int lastyline;
+extern int ytop;
+extern int ybottom;
+extern int xleft;
+extern int xright;
+extern enum {
+ OUTLINE, FILL, BOTH
+} polyfill;
+
+extern double adj1;
+extern double adj2;
+extern double adj3;
+extern double adj4;
+extern int res;
+
+void HGSetFont(int font, int size);
+void HGPutText(int justify, POINT pnt, register char *string);
+void HGSetBrush(int mode);
+void tmove2(int px, int py);
+void doarc(POINT cp, POINT sp, int angle);
+void tmove(POINT * ptr);
+void cr();
+void drawwig(POINT * ptr);
+void HGtline(int x1, int y1);
+void dx(double x);
+void dy(double y);
+void HGArc(register int cx, register int cy, int px, int py, int angle);
+void picurve(register int *x, register int *y, int npts);
+void Paramaterize(int x[], int y[], float h[], int n);
+void PeriodicSpline(float h[], int z[],
+ float dz[], float d2z[], float d3z[],
+ int npoints);
+void NaturalEndSpline(float h[], int z[],
+ float dz[], float d2z[], float d3z[],
+ int npoints);
+
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: HGPrintElt (element_pointer, baseline)
+ |
+ | Results: Examines a picture element and calls the appropriate
+ | routine(s) to print them according to their type. After the
+ | picture is drawn, current position is (lastx, lasty).
+ *----------------------------------------------------------------------------*/
+
+void
+HGPrintElt(ELT *element,
+ int baseline)
+{
+ register POINT *p1;
+ register POINT *p2;
+ register int length;
+ register int graylevel;
+
+ if (!DBNullelt(element) && !Nullpoint((p1 = element->ptlist))) {
+ /* p1 always has first point */
+ if (TEXT(element->type)) {
+ HGSetFont(element->brushf, element->size);
+ switch (element->size) {
+ case 1:
+ p1->y += adj1;
+ break;
+ case 2:
+ p1->y += adj2;
+ break;
+ case 3:
+ p1->y += adj3;
+ break;
+ case 4:
+ p1->y += adj4;
+ break;
+ default:
+ break;
+ }
+ HGPutText(element->type, *p1, element->textpt);
+ } else {
+ if (element->brushf) /* if there is a brush, the */
+ HGSetBrush(element->brushf); /* graphics need it set */
+
+ switch (element->type) {
+
+ case ARC:
+ p2 = PTNextPoint(p1);
+ tmove(p2);
+ doarc(*p1, *p2, element->size);
+ cr();
+ break;
+
+ case CURVE:
+ length = 0; /* keep track of line length */
+ drawwig(p1);
+ cr();
+ break;
+
+ case VECTOR:
+ length = 0; /* keep track of line length so */
+ tmove(p1); /* single lines don't get long */
+ while (!Nullpoint((p1 = PTNextPoint(p1)))) {
+ HGtline((int) (p1->x * troffscale),
+ (int) (p1->y * troffscale));
+ if (length++ > LINELENGTH) {
+ length = 0;
+ printf("\\\n");
+ }
+ } /* end while */
+ cr();
+ break;
+
+ case POLYGON:
+ {
+ /* brushf = style of outline; size = color of fill:
+ * on first pass (polyfill=FILL), do the interior using 'P'
+ * unless size=0
+ * on second pass (polyfill=OUTLINE), do the outline using a series
+ * of vectors. It might make more sense to use \D'p ...',
+ * but there is no uniform way to specify a 'fill character'
+ * that prints as 'no fill' on all output devices (and
+ * stipple fonts).
+ * If polyfill=BOTH, just use the \D'p ...' command.
+ */
+ float firstx = p1->x;
+ float firsty = p1->y;
+
+ length = 0; /* keep track of line length so */
+ /* single lines don't get long */
+
+ if (polyfill == FILL || polyfill == BOTH) {
+ /* do the interior */
+ char command = (polyfill == BOTH && element->brushf) ? 'p' : 'P';
+
+ /* include outline, if there is one and */
+ /* the -p flag was set */
+
+ /* switch based on what gremlin gives */
+ switch (element->size) {
+ case 1:
+ graylevel = 1;
+ break;
+ case 3:
+ graylevel = 2;
+ break;
+ case 12:
+ graylevel = 3;
+ break;
+ case 14:
+ graylevel = 4;
+ break;
+ case 16:
+ graylevel = 5;
+ break;
+ case 19:
+ graylevel = 6;
+ break;
+ case 21:
+ graylevel = 7;
+ break;
+ case 23:
+ graylevel = 8;
+ break;
+ default: /* who's giving something else? */
+ graylevel = NSTIPPLES;
+ break;
+ }
+ /* int graylevel = element->size; */
+
+ if (graylevel < 0)
+ break;
+ if (graylevel > NSTIPPLES)
+ graylevel = NSTIPPLES;
+ printf("\\h'-%du'\\D'f %du'",
+ stipple_index[graylevel],
+ stipple_index[graylevel]);
+ cr();
+ tmove(p1);
+ printf("\\D'%c", command);
+
+ while (!Nullpoint((PTNextPoint(p1)))) {
+ p1 = PTNextPoint(p1);
+ dx((double) p1->x);
+ dy((double) p1->y);
+ if (length++ > LINELENGTH) {
+ length = 0;
+ printf("\\\n");
+ }
+ } /* end while */
+
+ /* close polygon if not done so by user */
+ if ((firstx != p1->x) || (firsty != p1->y)) {
+ dx((double) firstx);
+ dy((double) firsty);
+ }
+ putchar('\'');
+ cr();
+ break;
+ }
+ /* else polyfill == OUTLINE; only draw the outline */
+ if (!(element->brushf))
+ break;
+ length = 0; /* keep track of line length */
+ tmove(p1);
+
+ while (!Nullpoint((PTNextPoint(p1)))) {
+ p1 = PTNextPoint(p1);
+ HGtline((int) (p1->x * troffscale),
+ (int) (p1->y * troffscale));
+ if (length++ > LINELENGTH) {
+ length = 0;
+ printf("\\\n");
+ }
+ } /* end while */
+
+ /* close polygon if not done so by user */
+ if ((firstx != p1->x) || (firsty != p1->y)) {
+ HGtline((int) (firstx * troffscale),
+ (int) (firsty * troffscale));
+ }
+ cr();
+ break;
+ } /* end case POLYGON */
+ } /* end switch */
+ } /* end else Text */
+ } /* end if */
+} /* end PrintElt */
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: HGPutText (justification, position_point, string)
+ |
+ | Results: Given the justification, a point to position with, and a
+ | string to put, HGPutText first sends the string into a
+ | diversion, moves to the positioning point, then outputs
+ | local vertical and horizontal motions as needed to justify
+ | the text. After all motions are done, the diversion is
+ | printed out.
+ *----------------------------------------------------------------------------*/
+
+void
+HGPutText(int justify,
+ POINT pnt,
+ register char *string)
+{
+ int savelasty = lasty; /* vertical motion for text is to be */
+ /* ignored. Save current y here */
+
+ printf(".nr g8 \\n(.d\n"); /* save current vertical position. */
+ printf(".ds g9 \""); /* define string containing the text. */
+ while (*string) { /* put out the string */
+ if (*string == '\\' &&
+ *(string + 1) == '\\') { /* one character at a */
+ printf("\\\\\\"); /* time replacing // */
+ string++; /* by //// to prevent */
+ } /* interpretation at */
+ printf("%c", *(string++)); /* printout time */
+ }
+ printf("\n");
+
+ tmove(&pnt); /* move to positioning point */
+
+ switch (justify) {
+ /* local vertical motions */
+ /* (the numbers here are used to be somewhat compatible with gprint) */
+ case CENTLEFT:
+ case CENTCENT:
+ case CENTRIGHT:
+ printf("\\v'0.85n'"); /* down half */
+ break;
+
+ case TOPLEFT:
+ case TOPCENT:
+ case TOPRIGHT:
+ printf("\\v'1.7n'"); /* down whole */
+ }
+
+ switch (justify) {
+ /* local horizontal motions */
+ case BOTCENT:
+ case CENTCENT:
+ case TOPCENT:
+ printf("\\h'-\\w'\\*(g9'u/2u'"); /* back half */
+ break;
+
+ case BOTRIGHT:
+ case CENTRIGHT:
+ case TOPRIGHT:
+ printf("\\h'-\\w'\\*(g9'u'"); /* back whole */
+ }
+
+ printf("\\&\\*(g9\n"); /* now print the text. */
+ printf(".sp |\\n(g8u\n"); /* restore vertical position */
+ lasty = savelasty; /* vertical position restored to where it */
+ lastx = xleft; /* was before text, also horizontal is at */
+ /* left */
+} /* end HGPutText */
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: doarc (center_point, start_point, angle)
+ |
+ | Results: Produces either drawarc command or a drawcircle command
+ | depending on the angle needed to draw through.
+ *----------------------------------------------------------------------------*/
+
+void
+doarc(POINT cp,
+ POINT sp,
+ int angle)
+{
+ if (angle) /* arc with angle */
+ HGArc((int) (cp.x * troffscale), (int) (cp.y * troffscale),
+ (int) (sp.x * troffscale), (int) (sp.y * troffscale), angle);
+ else /* a full circle (angle == 0) */
+ HGArc((int) (cp.x * troffscale), (int) (cp.y * troffscale),
+ (int) (sp.x * troffscale), (int) (sp.y * troffscale), 0);
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: HGSetFont (font_number, Point_size)
+ |
+ | Results: ALWAYS outputs a .ft and .ps directive to troff. This is
+ | done because someone may change stuff inside a text string.
+ | Changes thickness back to default thickness. Default
+ | thickness depends on font and pointsize.
+ *----------------------------------------------------------------------------*/
+
+void
+HGSetFont(int font,
+ int size)
+{
+ printf(".ft %s\n"
+ ".ps %d\n", tfont[font - 1], tsize[size - 1]);
+ linethickness = DEFTHICK;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: HGSetBrush (line_mode)
+ |
+ | Results: Generates the troff commands to set up the line width and
+ | style of subsequent lines. Does nothing if no change is
+ | needed.
+ |
+ | Side Efct: Sets `linmode' and `linethicknes'.
+ *----------------------------------------------------------------------------*/
+
+void
+HGSetBrush(int mode)
+{
+ register int printed = 0;
+
+ if (linmod != style[--mode]) {
+ /* Groff doesn't understand \Ds, so we take it out */
+ /* printf ("\\D's %du'", linmod = style[mode]); */
+ linmod = style[mode];
+ printed = 1;
+ }
+ if (linethickness != thick[mode]) {
+ linethickness = thick[mode];
+ printf("\\h'-%.2fp'\\D't %.2fp'", linethickness, linethickness);
+ printed = 1;
+ }
+ if (printed)
+ cr();
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: dx (x_destination)
+ |
+ | Results: Scales and outputs a number for delta x (with a leading
+ | space) given `lastx' and x_destination.
+ |
+ | Side Efct: Resets `lastx' to x_destination.
+ *----------------------------------------------------------------------------*/
+
+void
+dx(double x)
+{
+ register int ix = (int) (x * troffscale);
+
+ printf(" %du", ix - lastx);
+ lastx = ix;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: dy (y_destination)
+ |
+ | Results: Scales and outputs a number for delta y (with a leading
+ | space) given `lastyline' and y_destination.
+ |
+ | Side Efct: Resets `lastyline' to y_destination. Since `line' vertical
+ | motions don't affect `page' ones, `lasty' isn't updated.
+ *----------------------------------------------------------------------------*/
+
+void
+dy(double y)
+{
+ register int iy = (int) (y * troffscale);
+
+ printf(" %du", iy - lastyline);
+ lastyline = iy;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: tmove2 (px, py)
+ |
+ | Results: Produces horizontal and vertical moves for troff given the
+ | pair of points to move to and knowing the current position.
+ | Also puts out a horizontal move to start the line. This is
+ | a variation without the .sp command.
+ *----------------------------------------------------------------------------*/
+
+void
+tmove2(int px,
+ int py)
+{
+ register int dx;
+ register int dy;
+
+ if ((dy = py - lasty)) {
+ printf("\\v'%du'", dy);
+ }
+ lastyline = lasty = py; /* lasty is always set to current */
+ if ((dx = px - lastx)) {
+ printf("\\h'%du'", dx);
+ lastx = px;
+ }
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: tmove (point_pointer)
+ |
+ | Results: Produces horizontal and vertical moves for troff given the
+ | pointer of a point to move to and knowing the current
+ | position. Also puts out a horizontal move to start the
+ | line.
+ *----------------------------------------------------------------------------*/
+
+void
+tmove(POINT * ptr)
+{
+ register int ix = (int) (ptr->x * troffscale);
+ register int iy = (int) (ptr->y * troffscale);
+ register int dx;
+ register int dy;
+
+ if ((dy = iy - lasty)) {
+ printf(".sp %du\n", dy);
+ }
+ lastyline = lasty = iy; /* lasty is always set to current */
+ if ((dx = ix - lastx)) {
+ printf("\\h'%du'", dx);
+ lastx = ix;
+ }
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: cr ( )
+ |
+ | Results: Ends off an input line. `.sp -1' is also added to counteract
+ | the vertical move done at the end of text lines.
+ |
+ | Side Efct: Sets `lastx' to `xleft' for troff's return to left margin.
+ *----------------------------------------------------------------------------*/
+
+void
+cr()
+{
+ printf("\n.sp -1\n");
+ lastx = xleft;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: line ( )
+ |
+ | Results: Draws a single solid line to (x,y).
+ *----------------------------------------------------------------------------*/
+
+void
+line(int px,
+ int py)
+{
+ printf("\\D'l");
+ printf(" %du", px - lastx);
+ printf(" %du'", py - lastyline);
+ lastx = px;
+ lastyline = lasty = py;
+}
+
+
+/*----------------------------------------------------------------------------
+ | Routine: drawwig (ptr)
+ |
+ | Results: The point sequence found in the structure pointed by ptr is
+ | placed in integer arrays for further manipulation by the
+ | existing routing. With the proper parameters, HGCurve is
+ | called.
+ *----------------------------------------------------------------------------*/
+
+void
+drawwig(POINT * ptr)
+{
+ register int npts; /* point list index */
+ int x[MAXPOINTS], y[MAXPOINTS]; /* point list */
+
+ for (npts = 1; !Nullpoint(ptr); ptr = PTNextPoint(ptr), npts++) {
+ x[npts] = (int) (ptr->x * troffscale);
+ y[npts] = (int) (ptr->y * troffscale);
+ }
+ if (--npts) {
+ /* HGCurve(&x[0], &y[0], npts); */ /*Gremlin looks different, so... */
+ picurve(&x[0], &y[0], npts);
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ | Routine: HGArc (xcenter, ycenter, xstart, ystart, angle)
+ |
+ | Results: This routine plots an arc centered about (cx, cy) counter
+ | clockwise starting from the point (px, py) through `angle'
+ | degrees. If angle is 0, a full circle is drawn. It does so
+ | by creating a draw-path around the arc whose density of
+ | points depends on the size of the arc.
+ *----------------------------------------------------------------------------*/
+
+void
+HGArc(register int cx,
+ register int cy,
+ int px,
+ int py,
+ int angle)
+{
+ double xs, ys, resolution, fullcircle;
+ int m;
+ register int mask;
+ register int extent;
+ register int nx;
+ register int ny;
+ register int length;
+ register double epsilon;
+
+ xs = px - cx;
+ ys = py - cy;
+
+ length = 0;
+
+ resolution = (1.0 + hypot(xs, ys) / res) * PointsPerInterval;
+ /* mask = (1 << (int) log10(resolution + 1.0)) - 1; */
+ (void) frexp(resolution, &m); /* A bit more elegant than log10 */
+ for (mask = 1; mask < m; mask = mask << 1);
+ mask -= 1;
+
+ epsilon = 1.0 / resolution;
+ fullcircle = (2.0 * pi) * resolution;
+ if (angle == 0)
+ extent = (int) fullcircle;
+ else
+ extent = (int) (angle * fullcircle / 360.0);
+
+ HGtline(px, py);
+ while (--extent >= 0) {
+ xs += epsilon * ys;
+ nx = cx + (int) (xs + 0.5);
+ ys -= epsilon * xs;
+ ny = cy + (int) (ys + 0.5);
+ if (!(extent & mask)) {
+ HGtline(nx, ny); /* put out a point on circle */
+ if (length++ > LINELENGTH) {
+ length = 0;
+ printf("\\\n");
+ }
+ }
+ } /* end for */
+} /* end HGArc */
+
+
+/*----------------------------------------------------------------------------
+ | Routine: picurve (xpoints, ypoints, num_of_points)
+ |
+ | Results: Draws a curve delimited by (not through) the line segments
+ | traced by (xpoints, ypoints) point list. This is the `Pic'
+ | style curve.
+ *----------------------------------------------------------------------------*/
+
+void
+picurve(register int *x,
+ register int *y,
+ int npts)
+{
+ register int nseg; /* effective resolution for each curve */
+ register int xp; /* current point (and temporary) */
+ register int yp;
+ int pxp, pyp; /* previous point (to make lines from) */
+ int i; /* inner curve segment traverser */
+ int length = 0;
+ double w; /* position factor */
+ double t1, t2, t3; /* calculation temps */
+
+ if (x[1] == x[npts] && y[1] == y[npts]) {
+ x[0] = x[npts - 1]; /* if the lines' ends meet, make */
+ y[0] = y[npts - 1]; /* sure the curve meets */
+ x[npts + 1] = x[2];
+ y[npts + 1] = y[2];
+ } else { /* otherwise, make the ends of the */
+ x[0] = x[1]; /* curve touch the ending points of */
+ y[0] = y[1]; /* the line segments */
+ x[npts + 1] = x[npts];
+ y[npts + 1] = y[npts];
+ }
+
+ pxp = (x[0] + x[1]) / 2; /* make the last point pointers */
+ pyp = (y[0] + y[1]) / 2; /* point to the start of the 1st line */
+ tmove2(pxp, pyp);
+
+ for (; npts--; x++, y++) { /* traverse the line segments */
+ xp = x[0] - x[1];
+ yp = y[0] - y[1];
+ nseg = (int) hypot((double) xp, (double) yp);
+ xp = x[1] - x[2];
+ yp = y[1] - y[2];
+ /* `nseg' is the number of line */
+ /* segments that will be drawn for */
+ /* each curve segment. */
+ nseg = (int) ((double) (nseg + (int) hypot((double) xp, (double) yp)) /
+ res * PointsPerInterval);
+
+ for (i = 1; i < nseg; i++) {
+ w = (double) i / (double) nseg;
+ t1 = w * w;
+ t3 = t1 + 1.0 - (w + w);
+ t2 = 2.0 - (t3 + t1);
+ xp = (((int) (t1 * x[2] + t2 * x[1] + t3 * x[0])) + 1) / 2;
+ yp = (((int) (t1 * y[2] + t2 * y[1] + t3 * y[0])) + 1) / 2;
+
+ HGtline(xp, yp);
+ if (length++ > LINELENGTH) {
+ length = 0;
+ printf("\\\n");
+ }
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ | Routine: HGCurve(xpoints, ypoints, num_points)
+ |
+ | Results: This routine generates a smooth curve through a set of
+ | points. The method used is the parametric spline curve on
+ | unit knot mesh described in `Spline Curve Techniques' by
+ | Patrick Baudelaire, Robert Flegal, and Robert Sproull --
+ | Xerox Parc.
+ *----------------------------------------------------------------------------*/
+
+void
+HGCurve(int *x,
+ int *y,
+ int numpoints)
+{
+ float h[MAXPOINTS], dx[MAXPOINTS], dy[MAXPOINTS];
+ float d2x[MAXPOINTS], d2y[MAXPOINTS], d3x[MAXPOINTS], d3y[MAXPOINTS];
+ float t, t2, t3;
+ register int j;
+ register int k;
+ register int nx;
+ register int ny;
+ int lx, ly;
+ int length = 0;
+
+ lx = x[1];
+ ly = y[1];
+ tmove2(lx, ly);
+
+ /*
+ * Solve for derivatives of the curve at each point separately for x and y
+ * (parametric).
+ */
+ Paramaterize(x, y, h, numpoints);
+
+ /* closed curve */
+ if ((x[1] == x[numpoints]) && (y[1] == y[numpoints])) {
+ PeriodicSpline(h, x, dx, d2x, d3x, numpoints);
+ PeriodicSpline(h, y, dy, d2y, d3y, numpoints);
+ } else {
+ NaturalEndSpline(h, x, dx, d2x, d3x, numpoints);
+ NaturalEndSpline(h, y, dy, d2y, d3y, numpoints);
+ }
+
+ /*
+ * generate the curve using the above information and PointsPerInterval
+ * vectors between each specified knot.
+ */
+
+ for (j = 1; j < numpoints; ++j) {
+ if ((x[j] == x[j + 1]) && (y[j] == y[j + 1]))
+ continue;
+ for (k = 0; k <= PointsPerInterval; ++k) {
+ t = (float) k *h[j] / (float) PointsPerInterval;
+ t2 = t * t;
+ t3 = t * t * t;
+ nx = x[j] + (int) (t * dx[j] + t2 * d2x[j] / 2 + t3 * d3x[j] / 6);
+ ny = y[j] + (int) (t * dy[j] + t2 * d2y[j] / 2 + t3 * d3y[j] / 6);
+ HGtline(nx, ny);
+ if (length++ > LINELENGTH) {
+ length = 0;
+ printf("\\\n");
+ }
+ } /* end for k */
+ } /* end for j */
+} /* end HGCurve */
+
+
+/*----------------------------------------------------------------------------
+ | Routine: Paramaterize (xpoints, ypoints, hparams, num_points)
+ |
+ | Results: This routine calculates parameteric values for use in
+ | calculating curves. The parametric values are returned
+ | in the array h. The values are an approximation of
+ | cumulative arc lengths of the curve (uses cord length).
+ | For additional information, see paper cited below.
+ *----------------------------------------------------------------------------*/
+
+void
+Paramaterize(int x[],
+ int y[],
+ float h[],
+ int n)
+{
+ register int dx;
+ register int dy;
+ register int i;
+ register int j;
+ float u[MAXPOINTS];
+
+ for (i = 1; i <= n; ++i) {
+ u[i] = 0;
+ for (j = 1; j < i; j++) {
+ dx = x[j + 1] - x[j];
+ dy = y[j + 1] - y[j];
+ /* Here was overflowing, so I changed it. */
+ /* u[i] += sqrt ((double) (dx * dx + dy * dy)); */
+ u[i] += hypot((double) dx, (double) dy);
+ }
+ }
+ for (i = 1; i < n; ++i)
+ h[i] = u[i + 1] - u[i];
+} /* end Paramaterize */
+
+
+/*----------------------------------------------------------------------------
+ | Routine: PeriodicSpline (h, z, dz, d2z, d3z, npoints)
+ |
+ | Results: This routine solves for the cubic polynomial to fit a spline
+ | curve to the the points specified by the list of values.
+ | The Curve generated is periodic. The algorithms for this
+ | curve are from the `Spline Curve Techniques' paper cited
+ | above.
+ *----------------------------------------------------------------------------*/
+
+void
+PeriodicSpline(float h[], /* paramaterization */
+ int z[], /* point list */
+ float dz[], /* to return the 1st derivative */
+ float d2z[], /* 2nd derivative */
+ float d3z[], /* 3rd derivative */
+ int npoints) /* number of valid points */
+{
+ float d[MAXPOINTS];
+ float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
+ float c[MAXPOINTS], r[MAXPOINTS], s[MAXPOINTS];
+ int i;
+
+ /* step 1 */
+ for (i = 1; i < npoints; ++i) {
+ deltaz[i] = h[i] ? ((double) (z[i + 1] - z[i])) / h[i] : 0;
+ }
+ h[0] = h[npoints - 1];
+ deltaz[0] = deltaz[npoints - 1];
+
+ /* step 2 */
+ for (i = 1; i < npoints - 1; ++i) {
+ d[i] = deltaz[i + 1] - deltaz[i];
+ }
+ d[0] = deltaz[1] - deltaz[0];
+
+ /* step 3a */
+ a[1] = 2 * (h[0] + h[1]);
+ b[1] = d[0];
+ c[1] = h[0];
+ for (i = 2; i < npoints - 1; ++i) {
+ a[i] = 2 * (h[i - 1] + h[i]) -
+ pow((double) h[i - 1], (double) 2.0) / a[i - 1];
+ b[i] = d[i - 1] - h[i - 1] * b[i - 1] / a[i - 1];
+ c[i] = -h[i - 1] * c[i - 1] / a[i - 1];
+ }
+
+ /* step 3b */
+ r[npoints - 1] = 1;
+ s[npoints - 1] = 0;
+ for (i = npoints - 2; i > 0; --i) {
+ r[i] = -(h[i] * r[i + 1] + c[i]) / a[i];
+ s[i] = (6 * b[i] - h[i] * s[i + 1]) / a[i];
+ }
+
+ /* step 4 */
+ d2z[npoints - 1] = (6 * d[npoints - 2] - h[0] * s[1]
+ - h[npoints - 1] * s[npoints - 2])
+ / (h[0] * r[1] + h[npoints - 1] * r[npoints - 2]
+ + 2 * (h[npoints - 2] + h[0]));
+ for (i = 1; i < npoints - 1; ++i) {
+ d2z[i] = r[i] * d2z[npoints - 1] + s[i];
+ }
+ d2z[npoints] = d2z[1];
+
+ /* step 5 */
+ for (i = 1; i < npoints; ++i) {
+ dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6;
+ d3z[i] = h[i] ? (d2z[i + 1] - d2z[i]) / h[i] : 0;
+ }
+} /* end PeriodicSpline */
+
+
+/*----------------------------------------------------------------------------
+ | Routine: NaturalEndSpline (h, z, dz, d2z, d3z, npoints)
+ |
+ | Results: This routine solves for the cubic polynomial to fit a spline
+ | curve the the points specified by the list of values. The
+ | alogrithms for this curve are from the `Spline Curve
+ | Techniques' paper cited above.
+ *----------------------------------------------------------------------------*/
+
+void
+NaturalEndSpline(float h[], /* parameterization */
+ int z[], /* Point list */
+ float dz[], /* to return the 1st derivative */
+ float d2z[], /* 2nd derivative */
+ float d3z[], /* 3rd derivative */
+ int npoints) /* number of valid points */
+{
+ float d[MAXPOINTS];
+ float deltaz[MAXPOINTS], a[MAXPOINTS], b[MAXPOINTS];
+ int i;
+
+ /* step 1 */
+ for (i = 1; i < npoints; ++i) {
+ deltaz[i] = h[i] ? ((double) (z[i + 1] - z[i])) / h[i] : 0;
+ }
+ deltaz[0] = deltaz[npoints - 1];
+
+ /* step 2 */
+ for (i = 1; i < npoints - 1; ++i) {
+ d[i] = deltaz[i + 1] - deltaz[i];
+ }
+ d[0] = deltaz[1] - deltaz[0];
+
+ /* step 3 */
+ a[0] = 2 * (h[2] + h[1]);
+ b[0] = d[1];
+ for (i = 1; i < npoints - 2; ++i) {
+ a[i] = 2 * (h[i + 1] + h[i + 2]) -
+ pow((double) h[i + 1], (double) 2.0) / a[i - 1];
+ b[i] = d[i + 1] - h[i + 1] * b[i - 1] / a[i - 1];
+ }
+
+ /* step 4 */
+ d2z[npoints] = d2z[1] = 0;
+ for (i = npoints - 1; i > 1; --i) {
+ d2z[i] = (6 * b[i - 2] - h[i] * d2z[i + 1]) / a[i - 2];
+ }
+
+ /* step 5 */
+ for (i = 1; i < npoints; ++i) {
+ dz[i] = deltaz[i] - h[i] * (2 * d2z[i] + d2z[i + 1]) / 6;
+ d3z[i] = h[i] ? (d2z[i + 1] - d2z[i]) / h[i] : 0;
+ }
+} /* end NaturalEndSpline */
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: change (x_position, y_position, visible_flag)
+ |
+ | Results: As HGtline passes from the invisible to visible (or vice
+ | versa) portion of a line, change is called to either draw
+ | the line, or initialize the beginning of the next one.
+ | Change calls line to draw segments if visible_flag is set
+ | (which means we're leaving a visible area).
+ *----------------------------------------------------------------------------*/
+
+void
+change(register int x,
+ register int y,
+ register int vis)
+{
+ static int length = 0;
+
+ if (vis) { /* leaving a visible area, draw it. */
+ line(x, y);
+ if (length++ > LINELENGTH) {
+ length = 0;
+ printf("\\\n");
+ }
+ } else { /* otherwise, we're entering one, remember */
+ /* beginning */
+ tmove2(x, y);
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ | Routine: HGtline (xstart, ystart, xend, yend)
+ |
+ | Results: Draws a line from current position to (x1,y1) using line(x1,
+ | y1) to place individual segments of dotted or dashed lines.
+ *----------------------------------------------------------------------------*/
+
+void
+HGtline(int x1,
+ int y1)
+{
+ register int x0 = lastx;
+ register int y0 = lasty;
+ register int dx;
+ register int dy;
+ register int oldcoord;
+ register int res1;
+ register int visible;
+ register int res2;
+ register int xinc;
+ register int yinc;
+ register int dotcounter;
+
+ if (linmod == SOLID) {
+ line(x1, y1);
+ return;
+ }
+
+ /* for handling different resolutions */
+ dotcounter = linmod << dotshifter;
+
+ xinc = 1;
+ yinc = 1;
+ if ((dx = x1 - x0) < 0) {
+ xinc = -xinc;
+ dx = -dx;
+ }
+ if ((dy = y1 - y0) < 0) {
+ yinc = -yinc;
+ dy = -dy;
+ }
+ res1 = 0;
+ res2 = 0;
+ visible = 0;
+ if (dx >= dy) {
+ oldcoord = y0;
+ while (x0 != x1) {
+ if ((x0 & dotcounter) && !visible) {
+ change(x0, y0, 0);
+ visible = 1;
+ } else if (visible && !(x0 & dotcounter)) {
+ change(x0 - xinc, oldcoord, 1);
+ visible = 0;
+ }
+ if (res1 > res2) {
+ oldcoord = y0;
+ res2 += dx - res1;
+ res1 = 0;
+ y0 += yinc;
+ }
+ res1 += dy;
+ x0 += xinc;
+ }
+ } else {
+ oldcoord = x0;
+ while (y0 != y1) {
+ if ((y0 & dotcounter) && !visible) {
+ change(x0, y0, 0);
+ visible = 1;
+ } else if (visible && !(y0 & dotcounter)) {
+ change(oldcoord, y0 - yinc, 1);
+ visible = 0;
+ }
+ if (res1 > res2) {
+ oldcoord = x0;
+ res2 += dy - res1;
+ res1 = 0;
+ x0 += xinc;
+ }
+ res1 += dx;
+ y0 += yinc;
+ }
+ }
+ if (visible)
+ change(x1, y1, 1);
+ else
+ change(x1, y1, 0);
+}
+
+/* EOF */
diff --git a/contrib/groff/src/preproc/grn/hpoint.cc b/contrib/groff/src/preproc/grn/hpoint.cc
new file mode 100644
index 0000000..f4e1ca8
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/hpoint.cc
@@ -0,0 +1,49 @@
+/* Last non-groff version: hpoint.c 1.1 84/10/08 */
+
+/*
+ * This file contains routines for manipulating the point data structures
+ * for the gremlin picture editor.
+ */
+
+#include <stdlib.h>
+#include "gprint.h"
+
+
+/*
+ * Return pointer to empty point list.
+ */
+POINT *
+PTInit()
+{
+ return ((POINT *) NULL);
+}
+
+
+/*
+ * This routine creates a new point with coordinates x and y and links it
+ * into the pointlist.
+ */
+POINT *
+PTMakePoint(float x,
+ float y,
+ POINT **pplist)
+{
+ register POINT *point;
+
+ if (Nullpoint(point = *pplist)) { /* empty list */
+ *pplist = (POINT *) malloc(sizeof(POINT));
+ point = *pplist;
+ } else {
+ while (!Nullpoint(point->nextpt))
+ point = point->nextpt;
+ point->nextpt = (POINT *) malloc(sizeof(POINT));
+ point = point->nextpt;
+ }
+
+ point->x = x;
+ point->y = y;
+ point->nextpt = PTInit();
+ return (point);
+} /* end PTMakePoint */
+
+/* EOF */
diff --git a/contrib/groff/src/preproc/grn/main.cc b/contrib/groff/src/preproc/grn/main.cc
new file mode 100644
index 0000000..92e64c6
--- /dev/null
+++ b/contrib/groff/src/preproc/grn/main.cc
@@ -0,0 +1,905 @@
+/* Last non-groff version: main.cc 1.23 (Berkeley) 85/08/05
+ *
+ * Adapted to GNU troff by Daniel Senderowicz 99/12/29.
+ *
+ * Further refinements by Werner Lemberg 00/02/20.
+ *
+ *
+ * This file contains the main and file system dependent routines for
+ * processing gremlin files into troff input. The program watches input go
+ * by to standard output, only interpreting things between .GS and .GE
+ * lines. Default values (font, size, scale, thickness) may be overridden
+ * with a `default' command and are further overridden by commands in the
+ * input.
+ *
+ * Inside the GS and GE, commands are accepted to reconfigure the picture.
+ * At most one command may reside on each line, and each command is followed
+ * by a parameter separated by white space. The commands are as follows,
+ * and may be abbreviated down to one character (with exception of `scale'
+ * and `stipple' down to "sc" and "st") and may be upper or lower case.
+ *
+ * default - Make all settings in the current
+ * .GS/.GE the global defaults. Height,
+ * width and file are NOT saved.
+ * 1, 2, 3, 4 - Set size 1, 2, 3, or 4 (followed by an
+ * integer point size).
+ * roman, italics, bold, special - Set gremlin's fonts to any other troff
+ * font (one or two characters).
+ * stipple, l - Use a stipple font for polygons. Arg
+ * is troff font name. No Default. Can
+ * use only one stipple font per picture.
+ * (See below for stipple font index.)
+ * scale, x - Scale is IN ADDITION to the global
+ * scale factor from the default.
+ * pointscale - Turn on scaling point sizes to match
+ * `scale' commands. (Optional operand
+ * `off' to turn it off.)
+ * narrow, medium, thick - Set widths of lines.
+ * file - Set the file name to read the gremlin
+ * picture from. If the file isn't in
+ * the current directory, the gremlin
+ * library is tried.
+ * width, height - These two commands override any
+ * scaling factor that is in effect, and
+ * forces the picture to fit into either
+ * the height or width specified,
+ * whichever makes the picture smaller.
+ * The operand for these two commands is
+ * a floating-point number in units of
+ * inches.
+ * l<nn> (integer <nn>) - Set association between stipple <nn>
+ * and a stipple `character'. <nn> must
+ * be in the range 0 to NSTIPPLES (16)
+ * inclusive. The integer operand is an
+ * index in the stipple font selected.
+ * Valid cf (cifplot) indices are 1-32
+ * (although 24 is not defined), valid ug
+ * (unigrafix) indices are 1-14, and
+ * valid gs (gray scale) indices are
+ * 0-16. Nonetheless, any number between
+ * 0 and 255 is accepted since new
+ * stipple fonts may be added. An
+ * integer operand is required.
+ *
+ * Troff number registers used: g1 through g9. g1 is the width of the
+ * picture, and g2 is the height. g3, and g4, save information, g8 and g9
+ * are used for text processing and g5-g7 are reserved.
+ */
+
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "gprint.h"
+
+#include "device.h"
+#include "font.h"
+#include "searchpath.h"
+#include "macropath.h"
+
+#include "lib.h"
+#include "errarg.h"
+#include "error.h"
+#include "defs.h"
+
+/* database imports */
+
+extern void HGPrintElt(ELT *element, int baseline);
+extern ELT *DBInit();
+extern ELT *DBRead(register FILE *file);
+extern POINT *PTInit();
+extern POINT *PTMakePoint(float x, float y, POINT **pplist);
+
+
+#define SUN_SCALEFACTOR 0.70
+
+/* #define DEFSTIPPLE "gs" */
+#define DEFSTIPPLE "cf"
+
+#define MAXINLINE 100 /* input line length */
+
+#define SCREENtoINCH 0.02 /* scaling factor, screen to inches */
+
+#define BIG 999999999999.0 /* unweildly large floating number */
+
+
+static char sccsid[] = "@(#) (Berkeley) 8/5/85, 12/28/99";
+
+int res; /* the printer's resolution goes here */
+
+int dotshifter; /* for the length of dotted curves */
+
+double linethickness; /* brush styles */
+int linmod;
+int lastx; /* point registers for printing elements */
+int lasty;
+int lastyline; /* A line's vertical position is NOT the */
+ /* same after that line is over, so for a */
+ /* line of drawing commands, vertical */
+ /* spacing is kept in lastyline */
+
+/* These are the default fonts, sizes, line styles, */
+/* and thicknesses. They can be modified from a */
+/* `default' command and are reset each time the */
+/* start of a picture (.GS) is found. */
+
+char *deffont[] =
+{"R", "I", "B", "S"};
+int defsize[] =
+{10, 16, 24, 36};
+/* #define BASE_THICKNESS 1.0 */
+#define BASE_THICKNESS 0.15
+double defthick[STYLES] =
+{1 * BASE_THICKNESS,
+ 1 * BASE_THICKNESS,
+ 5 * BASE_THICKNESS,
+ 1 * BASE_THICKNESS,
+ 1 * BASE_THICKNESS,
+ 3 * BASE_THICKNESS};
+
+/* int cf_stipple_index[NSTIPPLES + 1] = */
+/* {0, 1, 3, 12, 14, 16, 19, 21, 23}; */
+/* a logarithmic scale looks better than a linear one for the gray shades */
+/* */
+/* int other_stipple_index[NSTIPPLES + 1] = */
+/* {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; */
+
+int cf_stipple_index[NSTIPPLES + 1] =
+{0, 18, 32, 56, 100, 178, 316, 562, 1000}; /* only 1-8 used */
+int other_stipple_index[NSTIPPLES + 1] =
+{0, 62, 125, 187, 250, 312, 375, 437, 500,
+ 562, 625, 687, 750, 812, 875, 937, 1000};
+
+/* int *defstipple_index = other_stipple_index; */
+int *defstipple_index = cf_stipple_index;
+
+int style[STYLES] =
+{DOTTED, DOTDASHED, SOLID, DASHED, SOLID, SOLID};
+double scale = 1.0; /* no scaling, default */
+int defpoint = 0; /* flag for pointsize scaling */
+char *defstipple = (char *) 0;
+enum {
+ OUTLINE, FILL, BOTH
+} polyfill;
+
+/* flag to controll filling of polygons */
+
+double adj1 = 0.0;
+double adj2 = 0.0;
+double adj3 = 0.0;
+double adj4 = 0.0;
+
+double thick[STYLES]; /* thicknesses set by defaults, then by */
+ /* commands */
+char *tfont[FONTS]; /* fonts originally set to deffont values, */
+ /* then */
+int tsize[SIZES]; /* optionally changed by commands inside */
+ /* grn */
+int stipple_index[NSTIPPLES + 1]; /* stipple font file indices */
+char *stipple;
+
+double xscale; /* scaling factor from individual pictures */
+double troffscale; /* scaling factor at output time */
+
+double width; /* user-request maximum width for picture */
+ /* (in inches) */
+double height; /* user-request height */
+int pointscale; /* flag for pointsize scaling */
+int setdefault; /* flag for a .GS/.GE to remember all */
+ /* settings */
+int sflag; /* -s flag: sort order (do polyfill first) */
+
+double toppoint; /* remember the picture */
+double bottompoint; /* bounds in these variables */
+double leftpoint;
+double rightpoint;
+
+int ytop; /* these are integer versions of the above */
+int ybottom; /* so not to convert each time they're used */
+int xleft;
+int xright;
+
+int linenum = 0; /* line number of input file */
+char inputline[MAXINLINE]; /* spot to filter through the file */
+char *c1 = inputline; /* c1, c2, and c3 will be used to */
+char *c2 = inputline + 1; /* hunt for lines that begin with */
+char *c3 = inputline + 2; /* ".GS" by looking individually */
+char *c4 = inputline + 3; /* needed for compatibility mode */
+char GScommand[MAXINLINE]; /* put user's ".GS" command line here */
+char gremlinfile[MAXINLINE]; /* filename to use for a picture */
+int SUNFILE = FALSE; /* TRUE if SUN gremlin file */
+int compatibility_flag = FALSE; /* TRUE if in compatibility mode */
+
+
+void getres();
+char *doinput(FILE *fp);
+void conv(register FILE *fp, int baseline);
+void savestate();
+int has_polygon(register ELT *elist);
+void interpret(char *line);
+
+
+void
+usage(FILE *stream)
+{
+ fprintf(stream,
+ "usage: %s [ -vCs ] [ -M dir ] [ -F dir ] [ -T dev ] [ file ]\n",
+ program_name);
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: main (argument_count, argument_pointer)
+ |
+ | Results: Parses the command line, accumulating input file names, then
+ | reads the inputs, passing it directly to output until a `.GS'
+ | line is read. Main then passes control to `conv' to do the
+ | gremlin file conversions.
+ *----------------------------------------------------------------------------*/
+
+int
+main(int argc,
+ char **argv)
+{
+ program_name = argv[0];
+ register FILE *fp;
+ register int k;
+ register char c;
+ register int gfil = 0;
+ char *file[50];
+ char *operand(int *argcp, char ***argvp);
+
+ while (--argc) {
+ if (**++argv != '-')
+ file[gfil++] = *argv;
+ else
+ switch (c = (*argv)[1]) {
+
+ case 0:
+ file[gfil++] = NULL;
+ break;
+
+ case 'C': /* compatibility mode */
+ compatibility_flag = TRUE;
+ break;
+
+ case 'F': /* font path to find DESC */
+ font::command_line_font_dir(operand(&argc, &argv));
+ break;
+
+ case 'T': /* final output typesetter name */
+ device = operand(&argc, &argv);
+ break;
+
+ case 'M': /* set library directory */
+ macro_path.command_line_dir(operand(&argc, &argv));
+ break;
+
+ case 's': /* preserve order of elements */
+ sflag = 1;
+ break;
+
+ case '-':
+ if (strcmp(*argv,"--version")==0) {
+ case 'v':
+ extern const char *Version_string;
+ printf("GNU grn (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ if (strcmp(*argv,"--help")==0) {
+ case '?':
+ usage(stdout);
+ exit(0);
+ break;
+ }
+ // fallthrough
+ default:
+ error("unknown switch: %1", c);
+ usage(stderr);
+ exit(1);
+ }
+ }
+
+ getres(); /* set the resolution for an output device */
+
+ if (gfil == 0) { /* no filename, use standard input */
+ file[0] = NULL;
+ gfil++;
+ }
+
+ for (k = 0; k < gfil; k++) {
+ if (file[k] != NULL) {
+ if ((fp = fopen(file[k], "r")) == NULL)
+ fatal("can't open %1", file[k]);
+ } else
+ fp = stdin;
+
+ while (doinput(fp) != NULL) {
+ if (*c1 == '.' && *c2 == 'G' && *c3 == 'S') {
+ if (compatibility_flag ||
+ *c4 == '\n' || *c4 == ' ' || *c4 == '\0')
+ conv(fp, linenum);
+ else
+ fputs(inputline, stdout);
+ } else
+ fputs(inputline, stdout);
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: char * operand (& argc, & argv)
+ |
+ | Results: Returns address of the operand given with a command-line
+ | option. It uses either `-Xoperand' or `-X operand', whichever
+ | is present. The program is terminated if no option is
+ | present.
+ |
+ | Side Efct: argc and argv are updated as necessary.
+ *----------------------------------------------------------------------------*/
+
+char *
+operand(int *argcp,
+ char ***argvp)
+{
+ if ((**argvp)[2])
+ return (**argvp + 2); /* operand immediately follows */
+ if ((--*argcp) <= 0) { /* no operand */
+ error("command-line option operand missing.");
+ exit(8);
+ }
+ return (*(++(*argvp))); /* operand is next word */
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: getres ()
+ |
+ | Results: Sets `res' to the resolution of the output device.
+ *----------------------------------------------------------------------------*/
+
+void
+getres()
+{
+ int linepiece;
+
+ if (!font::load_desc())
+ fatal("sorry, I can't continue");
+
+ res = font::res;
+
+ /* Correct the brush thicknesses based on res */
+ /* if (res >= 256) {
+ defthick[0] = res >> 8;
+ defthick[1] = res >> 8;
+ defthick[2] = res >> 4;
+ defthick[3] = res >> 8;
+ defthick[4] = res >> 8;
+ defthick[5] = res >> 6;
+ } */
+
+ linepiece = res >> 9;
+ for (dotshifter = 0; linepiece; dotshifter++)
+ linepiece = linepiece >> 1;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: char * doinput (file_pointer)
+ |
+ | Results: A line of input is read into `inputline'.
+ |
+ | Side Efct: "linenum" is incremented.
+ |
+ | Bugs: Lines longer than MAXINLINE are NOT checked, except for
+ | updating `linenum'.
+ *----------------------------------------------------------------------------*/
+
+char *
+doinput(FILE *fp)
+{
+ char *k;
+
+ if ((k = fgets(inputline, MAXINLINE, fp)) == NULL)
+ return k;
+ if (strchr(inputline, '\n')) /* ++ only if it's a complete line */
+ linenum++;
+ return (char *) !NULL;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: initpic ( )
+ |
+ | Results: Sets all parameters to the normal defaults, possibly
+ | overridden by a setdefault command. Initialize the picture
+ | variables, and output the startup commands to troff to begin
+ | the picture.
+ *----------------------------------------------------------------------------*/
+
+void
+initpic()
+{
+ register int i;
+
+ for (i = 0; i < STYLES; i++) { /* line thickness defaults */
+ thick[i] = defthick[i];
+ }
+ for (i = 0; i < FONTS; i++) { /* font name defaults */
+ tfont[i] = deffont[i];
+ }
+ for (i = 0; i < SIZES; i++) { /* font size defaults */
+ tsize[i] = defsize[i];
+ }
+ for (i = 0; i <= NSTIPPLES; i++) { /* stipple font file default indices */
+ stipple_index[i] = defstipple_index[i];
+ }
+ stipple = defstipple;
+
+ gremlinfile[0] = 0; /* filename is `null' */
+ setdefault = 0; /* this is not the default settings (yet) */
+
+ toppoint = BIG; /* set the picture bounds out */
+ bottompoint = -BIG; /* of range so they'll be set */
+ leftpoint = BIG; /* by `savebounds' on input */
+ rightpoint = -BIG;
+
+ pointscale = defpoint; /* flag for scaling point sizes default */
+ xscale = scale; /* default scale of individual pictures */
+ width = 0.0; /* size specifications input by user */
+ height = 0.0;
+
+ linethickness = DEFTHICK; /* brush styles */
+ linmod = DEFSTYLE;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: conv (file_pointer, starting_line)
+ |
+ | Results: At this point, we just passed a `.GS' line in the input
+ | file. conv reads the input and calls `interpret' to process
+ | commands, gathering up information until a `.GE' line is
+ | found. It then calls `HGPrint' to do the translation of the
+ | gremlin file to troff commands.
+ *----------------------------------------------------------------------------*/
+
+void
+conv(register FILE *fp,
+ int baseline)
+{
+ register FILE *gfp = NULL; /* input file pointer */
+ register int done = 0; /* flag to remember if finished */
+ register ELT *e; /* current element pointer */
+ ELT *PICTURE; /* whole picture data base pointer */
+ double temp; /* temporary calculating area */
+ /* POINT ptr; */ /* coordinates of a point to pass to `mov' */
+ /* routine */
+ int flyback; /* flag `want to end up at the top of the */
+ /* picture?' */
+ int compat; /* test character after .GE or .GF */
+
+
+ initpic(); /* set defaults, ranges, etc. */
+ strcpy(GScommand, inputline); /* save `.GS' line for later */
+
+ do {
+ done = (doinput(fp) == NULL); /* test for EOF */
+ flyback = (*c3 == 'F'); /* and .GE or .GF */
+ compat = (compatibility_flag ||
+ *c4 == '\n' || *c4 == ' ' || *c4 == '\0');
+ done |= (*c1 == '.' && *c2 == 'G' && (*c3 == 'E' || flyback) &&
+ compat);
+
+ if (done) {
+ if (setdefault)
+ savestate();
+
+ if (!gremlinfile[0]) {
+ if (!setdefault)
+ error("at line %1: no picture filename.\n", baseline);
+ return;
+ }
+ char *path;
+ gfp = macro_path.open_file(gremlinfile, &path);
+ if (!gfp)
+ return;
+ PICTURE = DBRead(gfp); /* read picture file */
+ fclose(gfp);
+ a_delete path;
+ if (DBNullelt(PICTURE))
+ return; /* If a request is made to make the */
+ /* picture fit into a specific area, */
+ /* set the scale to do that. */
+
+ if (stipple == (char *) NULL) /* if user forgot stipple */
+ if (has_polygon(PICTURE)) /* and picture has a polygon */
+ stipple = DEFSTIPPLE; /* then set the default */
+
+ if ((temp = bottompoint - toppoint) < 0.1)
+ temp = 0.1;
+ temp = (height != 0.0) ? height / (temp * SCREENtoINCH) : BIG;
+ if ((troffscale = rightpoint - leftpoint) < 0.1)
+ troffscale = 0.1;
+ troffscale = (width != 0.0) ?
+ width / (troffscale * SCREENtoINCH) : BIG;
+ if (temp == BIG && troffscale == BIG)
+ troffscale = xscale;
+ else {
+ if (temp < troffscale)
+ troffscale = temp;
+ } /* here, troffscale is the */
+ /* picture's scaling factor */
+ if (pointscale) {
+ register int i; /* do pointscaling here, when */
+ /* scale is known, before output */
+ for (i = 0; i < SIZES; i++)
+ tsize[i] = (int) (troffscale * (double) tsize[i] + 0.5);
+ }
+
+ /* change to device units */
+ troffscale *= SCREENtoINCH * res; /* from screen units */
+
+ ytop = (int) (toppoint * troffscale); /* calculate integer */
+ ybottom = (int) (bottompoint * troffscale); /* versions of the */
+ xleft = (int) (leftpoint * troffscale); /* picture limits */
+ xright = (int) (rightpoint * troffscale);
+
+ /* save stuff in number registers, */
+ /* register g1 = picture width and */
+ /* register g2 = picture height, */
+ /* set vertical spacing, no fill, */
+ /* and break (to make sure picture */
+ /* starts on left), and put out the */
+ /* user's `.GS' line. */
+ printf(".br\n"
+ ".nr g1 %du\n"
+ ".nr g2 %du\n"
+ "%s"
+ ".nr g3 \\n(.f\n"
+ ".nr g4 \\n(.s\n"
+ "\\0\n"
+ ".sp -1\n",
+ xright - xleft, ybottom - ytop, GScommand);
+
+ if (stipple) /* stipple requested for this picture */
+ printf(".st %s\n", stipple);
+ lastx = xleft; /* note where we are (upper left */
+ lastyline = lasty = ytop; /* corner of the picture) */
+
+ /* Just dump everything in the order it appears.
+ *
+ * If -s command-line option, traverse picture twice: First time,
+ * print only the interiors of filled polygons (as borderless
+ * polygons). Second time, print the outline as series of line
+ * segments. This way, postprocessors that overwrite rather than
+ * merge picture elements (such as Postscript) can still have text and
+ * graphics on a shaded background.
+ */
+ /* if (sflag) */
+ if (!sflag) { /* changing the default for filled polygons */
+ e = PICTURE;
+ polyfill = FILL;
+ while (!DBNullelt(e)) {
+ printf(".mk\n");
+ if (e->type == POLYGON)
+ HGPrintElt(e, baseline);
+ printf(".rt\n");
+ lastx = xleft;
+ lastyline = lasty = ytop;
+ e = DBNextElt(e);
+ }
+ }
+ e = PICTURE;
+
+ /* polyfill = !sflag ? BOTH : OUTLINE; */
+ polyfill = sflag ? BOTH : OUTLINE; /* changing the default */
+ while (!DBNullelt(e)) {
+ printf(".mk\n");
+ HGPrintElt(e, baseline);
+ printf(".rt\n");
+ lastx = xleft;
+ lastyline = lasty = ytop;
+ e = DBNextElt(e);
+ }
+
+ /* decide where to end picture */
+
+ /* I changed everything here. I always use the combination .mk and */
+ /* .rt so once finished I just space down the heigth of the picture */
+ /* that is \n(g2u */
+ if (flyback) { /* end picture at upper left */
+ /* ptr.x = leftpoint;
+ ptr.y = toppoint; */
+ } else { /* end picture at lower left */
+ /* ptr.x = leftpoint;
+ ptr.y = bottompoint; */
+ printf(".sp \\n(g2u\n");
+ }
+
+ /* tmove(&ptr); */ /* restore default line parameters */
+
+ /* restore everything to the way it was before the .GS, then put */
+ /* out the `.GE' line from user */
+
+ /* printf("\\D't %du'\\D's %du'\n", DEFTHICK, DEFSTYLE); */
+ /* groff doesn't understand the \Ds command */
+
+ printf("\\D't %du'\n", DEFTHICK);
+ if (flyback) /* make sure we end up at top of */
+ printf(".sp -1\n"); /* picture if `flying back' */
+ if (stipple) /* restore stipple to previous */
+ printf(".st\n");
+ printf(".br\n"
+ ".ft \\n(g3\n"
+ ".ps \\n(g4\n"
+ "%s", inputline);
+ } else
+ interpret(inputline); /* take commands from the input file */
+ } while (!done);
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: savestate ( )
+ |
+ | Results: all the current scaling / font size / font name / thickness
+ | / pointscale settings are saved to be the defaults. Scaled
+ | point sizes are NOT saved. The scaling is done each time a
+ | new picture is started.
+ |
+ | Side Efct: scale, and def* are modified.
+ *----------------------------------------------------------------------------*/
+
+void
+savestate()
+{
+ register int i;
+
+ for (i = 0; i < STYLES; i++) /* line thickness defaults */
+ defthick[i] = thick[i];
+ for (i = 0; i < FONTS; i++) /* font name defaults */
+ deffont[i] = tfont[i];
+ for (i = 0; i < SIZES; i++) /* font size defaults */
+ defsize[i] = tsize[i];
+ for (i = 0; i <= NSTIPPLES; i++) /* stipple font file default indices */
+ defstipple_index[i] = stipple_index[i];
+
+ defstipple = stipple; /* if stipple has been set, it's remembered */
+ scale *= xscale; /* default scale of individual pictures */
+ defpoint = pointscale; /* flag for scaling pointsizes from x factors */
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: savebounds (x_coordinate, y_coordinate)
+ |
+ | Results: Keeps track of the maximum and minimum extent of a picture
+ | in the global variables: left-, right-, top- and
+ | bottompoint. `savebounds' assumes that the points have been
+ | oriented to the correct direction. No scaling has taken
+ | place, though.
+ *----------------------------------------------------------------------------*/
+
+void
+savebounds(float x,
+ float y)
+{
+ if (x < leftpoint)
+ leftpoint = x;
+ if (x > rightpoint)
+ rightpoint = x;
+ if (y < toppoint)
+ toppoint = y;
+ if (y > bottompoint)
+ bottompoint = y;
+}
+
+
+/*----------------------------------------------------------------------------*
+ | Routine: interpret (character_string)
+ |
+ | Results: Commands are taken from the input string and performed.
+ | Commands are separated by the endofline, and are of the
+ | format:
+ | string1 string2
+ |
+ | where string1 is the command and string2 is the argument.
+ |
+ | Side Efct: Font and size strings, plus the gremlin file name and the
+ | width and height variables are set by this routine.
+ *----------------------------------------------------------------------------*/
+
+void
+interpret(char *line)
+{
+ char str1[MAXINLINE];
+ char str2[MAXINLINE];
+ register char *chr;
+ register int i;
+ double par;
+
+ str2[0] = '\0';
+ sscanf(line, "%80s%80s", &str1[0], &str2[0]);
+ for (chr = &str1[0]; *chr; chr++) /* convert command to */
+ if (isupper(*chr))
+ *chr = tolower(*chr); /* lower case */
+
+ switch (str1[0]) {
+
+ case '1':
+ case '2': /* font sizes */
+ case '3':
+ case '4':
+ i = atoi(str2);
+ if (i > 0 && i < 1000)
+ tsize[str1[0] - '1'] = i;
+ else
+ error("bad font size value at line %1", linenum);
+ break;
+
+ case 'r': /* roman */
+ if (str2[0] < '0')
+ goto nofont;
+ tfont[0] = (char *) malloc(strlen(str2) + 1);
+ strcpy(tfont[0], str2);
+ break;
+
+ case 'i': /* italics */
+ if (str2[0] < '0')
+ goto nofont;
+ tfont[1] = (char *) malloc(strlen(str2) + 1);
+ strcpy(tfont[1], str2);
+ break;
+
+ case 'b': /* bold */
+ if (str2[0] < '0')
+ goto nofont;
+ tfont[2] = (char *) malloc(strlen(str2) + 1);
+ strcpy(tfont[2], str2);
+ break;
+
+ case 's': /* special */
+ if (str1[1] == 'c')
+ goto scalecommand; /* or scale */
+
+ if (str2[0] < '0') {
+ nofont:
+ error("no fontname specified in line %1", linenum);
+ break;
+ }
+ if (str1[1] == 't')
+ goto stipplecommand; /* or stipple */
+
+ tfont[3] = (char *) malloc(strlen(str2) + 1);
+ strcpy(tfont[3], str2);
+ break;
+
+ case 'l': /* l */
+ if (isdigit(str1[1])) { /* set stipple index */
+ int index = atoi(str1 + 1), val;
+
+ if (index < 0 || index > NSTIPPLES) {
+ error("bad stipple number %1 at line %2", index, linenum);
+ break;
+ }
+ if (!defstipple_index)
+ defstipple_index = other_stipple_index;
+ val = atoi(str2);
+ if (val >= 0 && val < 256)
+ stipple_index[index] = val;
+ else
+ error("bad stipple index value at line %1", linenum);
+ break;
+ }
+
+ stipplecommand: /* set stipple name */
+ stipple = (char *) malloc(strlen(str2) + 1);
+ strcpy(stipple, str2);
+ /* if its a `known' font (currently only `cf'), set indicies */
+ if (strcmp(stipple, "cf") == 0)
+ defstipple_index = cf_stipple_index;
+ else
+ defstipple_index = other_stipple_index;
+ for (i = 0; i <= NSTIPPLES; i++)
+ stipple_index[i] = defstipple_index[i];
+ break;
+
+ case 'a': /* text adjust */
+ par = atof(str2);
+ switch (str1[1]) {
+ case '1':
+ adj1 = par;
+ break;
+ case '2':
+ adj2 = par;
+ break;
+ case '3':
+ adj3 = par;
+ break;
+ case '4':
+ adj4 = par;
+ break;
+ default:
+ error("bad adjust command at line %1", linenum);
+ break;
+ }
+ break;
+
+ case 't': /* thick */
+ thick[2] = defthick[0] * atof(str2);
+ break;
+
+ case 'm': /* medium */
+ thick[5] = defthick[0] * atof(str2);
+ break;
+
+ case 'n': /* narrow */
+ thick[0] = thick[1] = thick[3] = thick[4] =
+ defthick[0] * atof(str2);
+ break;
+
+ case 'x': /* x */
+ scalecommand: /* scale */
+ par = atof(str2);
+ if (par > 0.0)
+ xscale *= par;
+ else
+ error("illegal scale value on line %1", linenum);
+ break;
+
+ case 'f': /* file */
+ strcpy(gremlinfile, str2);
+ break;
+
+ case 'w': /* width */
+ width = atof(str2);
+ if (width < 0.0)
+ width = -width;
+ break;
+
+ case 'h': /* height */
+ height = atof(str2);
+ if (height < 0.0)
+ height = -height;
+ break;
+
+ case 'd': /* defaults */
+ setdefault = 1;
+ break;
+
+ case 'p': /* pointscale */
+ if (strcmp("off", str2))
+ pointscale = 1;
+ else
+ pointscale = 0;
+ break;
+
+ default:
+ error("unknown command `%1' on line %2", str1, linenum);
+ exit(8);
+ break;
+ };
+}
+
+
+/*
+ * return TRUE if picture contains a polygon
+ * otherwise FALSE
+ */
+
+int
+has_polygon(register ELT *elist)
+{
+ while (!DBNullelt(elist)) {
+ if (elist->type == POLYGON)
+ return (1);
+ elist = DBNextElt(elist);
+ }
+
+ return (0);
+}
+
+/* EOF */
diff --git a/contrib/groff/src/preproc/html/Makefile.sub b/contrib/groff/src/preproc/html/Makefile.sub
new file mode 100644
index 0000000..9d5045a
--- /dev/null
+++ b/contrib/groff/src/preproc/html/Makefile.sub
@@ -0,0 +1,7 @@
+PROG=pre-grohtml
+# MAN1=pre-grohtml.n
+MAN1=
+XLIBS=$(LIBGROFF)
+OBJS=pre-html.o pushbackbuffer.o
+CCSRCS=$(srcdir)/pre-html.cc $(srcdir)/pushbackbuffer.cc
+NAMEPREFIX=$(g)
diff --git a/contrib/groff/src/preproc/html/pre-html.cc b/contrib/groff/src/preproc/html/pre-html.cc
new file mode 100644
index 0000000..8357dd6
--- /dev/null
+++ b/contrib/groff/src/preproc/html/pre-html.cc
@@ -0,0 +1,1160 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 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. */
+
+#define PREHTMLC
+
+#include <stdio.h>
+#include <signal.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 "posix.h"
+#include "defs.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _POSIX_VERSION
+#include <sys/wait.h>
+#define PID_T pid_t
+#else /* not _POSIX_VERSION */
+#define PID_T int
+#endif /* not _POSIX_VERSION */
+
+extern char *strerror();
+
+#include "pre-html.h"
+#include "pushbackbuffer.h"
+#include "html-strings.h"
+
+#define POSTSCRIPTRES 72000 // maybe there is a better way to find this? --fixme--
+#define DEFAULT_IMAGE_RES 80 // 80 pixels per inch resolution
+#define DEFAULT_VERTICAL_OFFSET 45 // DEFAULT_VERTICAL_OFFSET/72 of an inch
+#define IMAGE_BOARDER_PIXELS 0
+#define MAX_WIDTH 8 // inches
+#define INLINE_LEADER_CHAR '\\'
+
+#define TRANSPARENT "-background \"#FFF\" -transparent \"#FFF\""
+
+#if 0
+# define DEBUGGING
+# define DEBUG_HTML
+#endif
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+void stop() {}
+
+typedef enum {CENTERED, LEFT, RIGHT, INLINE} IMAGE_ALIGNMENT;
+
+static int stdoutfd = 1; // output file descriptor - normally 1 but might move
+ // -1 means closed
+static int copyofstdoutfd =-1; // a copy of stdout, so we can restore stdout when
+ // writing to post-html
+static char *psFileName = 0; // name of postscript file
+static char *regionFileName = 0; // name of file containing all image regions
+static char *imagePageStem = 0; // stem of all files containing page images
+static char *image_device = "pnmraw";
+static int image_res = DEFAULT_IMAGE_RES;
+static int vertical_offset= DEFAULT_VERTICAL_OFFSET;
+static char *image_template = 0; // image template filename
+static int troff_arg = 0; // troff arg index
+static char *command_prefix = 0; // optional prefix for some installations.
+static char *troff_command = 0;
+#if defined(DEBUGGING)
+static int debug = FALSE;
+static char *troffFileName = 0; // output of pre-html output which is sent to troff -Tps
+static char *htmlFileName = 0; // output of pre-html output which is sent to troff -Thtml
+#endif
+
+
+/*
+ * Images are generated via postscript, gs and the pnm utilities.
+ */
+
+#define IMAGE_DEVICE "-Tps"
+
+/*
+ * prototypes
+ */
+static int do_file(const char *filename);
+
+/*
+ * sys_fatal - writes a fatal error message. Taken from src/roff/groff/pipeline.c
+ */
+
+void sys_fatal (const char *s)
+{
+ fprintf(stderr, "%s: %s: %s", program_name, s, strerror(errno));
+}
+
+/*
+ * 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 - constructor, sets the, used, and, next, fields to zero.
+ */
+
+char_block::char_block()
+: used(0), next(0)
+{
+}
+
+class char_buffer {
+public:
+ char_buffer();
+ ~char_buffer();
+ int read_file(FILE *fp);
+ int do_html(int argc, char *argv[]);
+ int do_image(int argc, char *argv[]);
+ void write_file_html(void);
+ void write_file_troff(void);
+ void write_upto_newline (char_block **t, int *i, int is_html);
+ int can_see(char_block **t, int *i, char *string);
+ int skip_spaces(char_block **t, int *i);
+ void skip_to_newline(char_block **t, int *i);
+private:
+ char_block *head;
+ char_block *tail;
+};
+
+/*
+ * char_buffer - constructor
+ */
+
+char_buffer::char_buffer()
+: head(0), tail(0)
+{
+}
+
+/*
+ * char_buffer - deconstructor, throws aways the whole buffer list.
+ */
+
+char_buffer::~char_buffer()
+{
+ while (head != 0) {
+ char_block *temp = head;
+ head = head->next;
+ delete temp;
+ }
+}
+
+/*
+ * read_file - read in a complete file, fp, placing the contents inside char_blocks.
+ */
+
+int char_buffer::read_file (FILE *fp)
+{
+ int i=0;
+ unsigned int old_used;
+ int n;
+
+ while (! feof(fp)) {
+ if (tail == 0) {
+ tail = new char_block;
+ head = tail;
+ } else {
+ if (tail->used == char_block::SIZE) {
+ tail->next = new char_block;
+ tail = tail->next;
+ }
+ }
+ // at this point we have a tail which is ready for the next SIZE bytes of the file
+
+ n = fread(tail->buffer, sizeof(char), char_block::SIZE-tail->used, fp);
+ if (n <= 0) {
+ // error
+ return( 0 );
+ } else {
+ tail->used += n*sizeof(char);
+ }
+ }
+ return( 1 );
+}
+
+/*
+ * writeNbytes - writes n bytes to stdout.
+ */
+
+static void writeNbytes (char *s, int l)
+{
+ int n=0;
+ int r;
+
+ while (n<l) {
+ r = write(stdoutfd, s, l-n);
+ if (r<0) {
+ sys_fatal("write");
+ }
+ n += r;
+ s += r;
+ }
+}
+
+/*
+ * writeString - writes a string to stdout.
+ */
+
+static void writeString (char *s)
+{
+ writeNbytes(s, strlen(s));
+}
+
+/*
+ * makeFileName - creates the image filename template.
+ */
+
+void makeFileName ()
+{
+ char buffer[8192];
+
+ sprintf(buffer, "grohtml-%d", (int)getpid());
+ strcat(buffer, "-%d");
+ image_template = (char *)malloc(strlen(buffer)+1);
+ strcpy(image_template, buffer);
+}
+
+/*
+ * write_end_image - ends the image. It writes out the image extents if we are using -Tps.
+ */
+
+static void write_end_image (int is_html)
+{
+ if (is_html) {
+ /*
+ * emit image name and enable output
+ */
+ writeString("\\O2\\O1\\O4\n");
+ } else {
+ /*
+ * postscript, therefore emit image boundaries
+ */
+ writeString("\\O2\\O4\n");
+ }
+}
+
+/*
+ * write_start_image - writes the troff which will:
+ *
+ * (i) disable html output for the following image
+ * (ii) reset the max/min x/y registers during postscript
+ * rendering.
+ */
+
+static void write_start_image (IMAGE_ALIGNMENT pos, int is_html)
+{
+ if (pos == INLINE) {
+ writeString("\\O3\\O5'");
+ writeString(image_template); writeString(".png'");
+ } else {
+ writeString(".begin \\{\\\n");
+ switch (pos) {
+
+ case LEFT:
+ writeString(". image l ");
+ break;
+ case RIGHT:
+ writeString(". image r ");
+ break;
+ case CENTERED:
+ default:
+ writeString(". image c ");
+ }
+ writeString(image_template); writeString(".png\n");
+ if (! is_html) {
+ writeString(".bp\n");
+ writeString(".tl ''''\n");
+ }
+ writeString("\\}\n");
+ }
+ if (is_html) {
+ writeString("\\O0\n");
+ } else {
+ // reset min/max registers
+ writeString("\\O0\\O1\n");
+ }
+}
+
+/*
+ * write_upto_newline - writes the contents of the buffer until a newline is seen.
+ * It checks for HTML_IMAGE_INLINE_BEGIN and HTML_IMAGE_INLINE_END
+ * and if they are present it processes them.
+ */
+
+void char_buffer::write_upto_newline (char_block **t, int *i, int is_html)
+{
+ int j=*i;
+
+ if (*t) {
+ while ((j < (*t)->used) && ((*t)->buffer[j] != '\n') &&
+ ((*t)->buffer[j] != INLINE_LEADER_CHAR)) {
+ j++;
+ }
+ if ((j < (*t)->used) && ((*t)->buffer[j] == '\n')) {
+ j++;
+ }
+ writeNbytes((*t)->buffer+(*i), j-(*i));
+ if ((*t)->buffer[j] == INLINE_LEADER_CHAR) {
+ if (can_see(t, &j, HTML_IMAGE_INLINE_BEGIN))
+ write_start_image(INLINE, is_html);
+ else if (can_see(t, &j, HTML_IMAGE_INLINE_END))
+ write_end_image(is_html);
+ else {
+ if (j < (*t)->used) {
+ *i = j;
+ j++;
+ writeNbytes((*t)->buffer+(*i), j-(*i));
+ }
+ }
+ }
+ if (j == (*t)->used) {
+ *i = 0;
+ if ((*t)->buffer[j-1] == '\n') {
+ *t = (*t)->next;
+ } else {
+ *t = (*t)->next;
+ write_upto_newline(t, i, is_html);
+ }
+ } else {
+ // newline was seen
+ *i = j;
+ }
+ }
+}
+
+/*
+ * can_see - returns TRUE if we can see string in t->buffer[i] onwards
+ */
+
+int char_buffer::can_see (char_block **t, int *i, char *string)
+{
+ int j = 0;
+ int l = strlen(string);
+ int k = *i;
+ char_block *s = *t;
+
+ while (s) {
+ while ((k<s->used) && (j<l) && (s->buffer[k] == string[j])) {
+ j++;
+ k++;
+ }
+ if (j == l) {
+ *i = k;
+ *t = s;
+ return( TRUE );
+ } else if ((k<s->used) && (s->buffer[k] != string[j])) {
+ return( FALSE );
+ }
+ s = s->next;
+ k = 0;
+ }
+ return( FALSE );
+}
+
+/*
+ * skip_spaces - returns TRUE if we have not run out of data.
+ * It also consumes spaces.
+ */
+
+int char_buffer::skip_spaces(char_block **t, int *i)
+{
+ char_block *s = *t;
+ int k = *i;
+
+ while (s) {
+ while ((k<s->used) && (isspace(s->buffer[k]))) {
+ k++;
+ }
+ if (k == s->used) {
+ k = 0;
+ s = s->next;
+ } else {
+ *i = k;
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * skip_to_newline - skips all characters until a newline is seen.
+ * The newline is also consumed.
+ */
+
+void char_buffer::skip_to_newline (char_block **t, int *i)
+{
+ int j=*i;
+
+ if (*t) {
+ while ((j < (*t)->used) && ((*t)->buffer[j] != '\n')) {
+ j++;
+ }
+ if ((j < (*t)->used) && ((*t)->buffer[j] == '\n')) {
+ j++;
+ }
+ if (j == (*t)->used) {
+ *i = 0;
+ if ((*t)->buffer[j-1] == '\n') {
+ *t = (*t)->next;
+ } else {
+ *t = (*t)->next;
+ skip_to_newline(t, i);
+ }
+ } else {
+ // newline was seen
+ *i = j;
+ }
+ }
+}
+
+/*
+ * write_file_troff - writes the buffer to stdout (troff).
+ */
+
+void char_buffer::write_file_troff (void)
+{
+ char_block *t=head;
+ int r;
+ int i=0;
+
+ if (t != 0) {
+ do {
+ /*
+ * remember to check the shortest string last
+ */
+ if (can_see(&t, &i, HTML_IMAGE_END)) {
+ write_end_image(FALSE);
+ skip_to_newline(&t, &i);
+ } else if (can_see(&t, &i, HTML_IMAGE_LEFT)) {
+ write_start_image(LEFT, FALSE);
+ skip_to_newline(&t, &i);
+ } else if (can_see(&t, &i, HTML_IMAGE_RIGHT)) {
+ write_start_image(RIGHT, FALSE);
+ skip_to_newline(&t, &i);
+ } else if (can_see(&t, &i, HTML_IMAGE_CENTERED)) {
+ write_start_image(CENTERED, FALSE);
+ skip_to_newline(&t, &i);
+ } else {
+ write_upto_newline(&t, &i, FALSE);
+ }
+ } while (t != 0);
+ }
+ if (close(stdoutfd) < 0)
+ sys_fatal("close");
+
+ // now we grab fd=1 so that the next pipe cannot use fd=1
+ if (stdoutfd == 1) {
+ if (dup(2) != stdoutfd) {
+ sys_fatal("dup failed to use fd=1");
+ }
+ }
+}
+
+/*
+ * the image class remembers the position of all images in the postscript file
+ * and assigns names for each image.
+ */
+
+struct imageItem {
+ imageItem *next;
+ int X1;
+ int Y1;
+ int X2;
+ int Y2;
+ char *imageName;
+ int resolution;
+ int maxx;
+ int pageNo;
+
+ imageItem (int x1, int y1, int x2, int y2, int page, int res, int max_width, char *name);
+ ~imageItem ();
+};
+
+/*
+ * imageItem - constructor
+ */
+
+imageItem::imageItem (int x1, int y1, int x2, int y2, int page, int res, int max_width, char *name)
+{
+ X1 = x1;
+ Y1 = y1;
+ X2 = x2;
+ Y2 = y2;
+ pageNo = page;
+ resolution = res;
+ maxx = max_width;
+ imageName = name;
+ next = 0;
+}
+
+/*
+ * imageItem - deconstructor
+ */
+
+imageItem::~imageItem ()
+{
+}
+
+/*
+ * imageList - class containing a list of imageItems.
+ */
+
+class imageList {
+private:
+ imageItem *head;
+ imageItem *tail;
+ int count;
+public:
+ imageList();
+ ~imageList();
+ void add(int x1, int y1, int x2, int y2, int page, int res, int maxx, char *name);
+};
+
+/*
+ * imageList - constructor.
+ */
+
+imageList::imageList ()
+ : head(0), tail(0), count(0)
+{
+}
+
+/*
+ * imageList - deconstructor.
+ */
+
+imageList::~imageList ()
+{
+ while (head != 0) {
+ imageItem *i = head;
+ head = head->next;
+ delete i;
+ }
+}
+
+/*
+ * createAllPages - creates a set of images, one per page.
+ */
+
+static void createAllPages (void)
+{
+ char buffer[4096];
+
+ sprintf(buffer,
+ "echo showpage | gs -q -dSAFER -sDEVICE=%s -r%d -sOutputFile=%s%%d %s - > /dev/null 2>&1 \n",
+ image_device,
+ image_res,
+ imagePageStem,
+ psFileName);
+#if defined(DEBUGGING)
+ fwrite(buffer, sizeof(char), strlen(buffer), stderr);
+ fflush(stderr);
+#endif
+ system(buffer);
+}
+
+/*
+ * removeAllPages - removes all page images.
+ */
+
+static void removeAllPages (void)
+{
+#if !defined(DEBUGGING)
+ char buffer[4096];
+ int i=1;
+
+ do {
+ sprintf(buffer, "%s%d", imagePageStem, i);
+ i++;
+ } while (remove(buffer) == 0);
+#endif
+}
+
+/*
+ * abs - returns the absolute value.
+ */
+
+int abs (int x)
+{
+ if (x < 0) {
+ return( -x );
+ } else {
+ return( x );
+ }
+}
+
+/*
+ * min - returns the minimum of two numbers.
+ */
+
+int min (int x, int y)
+{
+ if (x < y) {
+ return( x );
+ } else {
+ return( y );
+ }
+}
+
+/*
+ * max - returns the maximum of two numbers.
+ */
+
+int max (int x, int y)
+{
+ if (x > y) {
+ return( x );
+ } else {
+ return( y );
+ }
+}
+
+/*
+ * createImage - generates a minimal png file from the set of page images.
+ */
+
+static void createImage (imageItem *i)
+{
+ if (i->X1 != -1) {
+ char buffer[4096];
+ int x1 = max(min(i->X1, i->X2)*image_res/POSTSCRIPTRES-1*IMAGE_BOARDER_PIXELS, 0);
+ int y1 = max((image_res*vertical_offset/72)+min(i->Y1, i->Y2)*image_res/POSTSCRIPTRES-IMAGE_BOARDER_PIXELS, 0);
+ int x2 = max(i->X1, i->X2)*image_res/POSTSCRIPTRES+1*IMAGE_BOARDER_PIXELS;
+ int y2 = (image_res*vertical_offset/72)+max(i->Y1, i->Y2)*image_res/POSTSCRIPTRES+1*IMAGE_BOARDER_PIXELS;
+
+ sprintf(buffer,
+ "pnmcut %d %d %d %d < %s%d | pnmtopng %s > %s \n",
+ x1, y1, x2-x1+1, y2-y1+1,
+ imagePageStem,
+ i->pageNo,
+ TRANSPARENT,
+ i->imageName);
+#if defined(DEBUGGING)
+ fprintf(stderr, buffer);
+#endif
+ system(buffer);
+#if defined(DEBUGGING)
+ } else {
+ fprintf(stderr, "ignoring image as x1 coord is -1\n");
+ fflush(stderr);
+#endif
+ }
+}
+
+/*
+ * add - an image description to the imageList.
+ */
+
+void imageList::add (int x1, int y1, int x2, int y2, int page, int res, int maxx, char *name)
+{
+ imageItem *i = new imageItem(x1, y1, x2, y2, page, res, maxx, name);
+
+ if (head == 0) {
+ head = i;
+ tail = i;
+ } else {
+ tail->next = i;
+ tail = i;
+ }
+ createImage(i);
+}
+
+static imageList listOfImages; // list of images defined by the region file.
+
+/*
+ * write_file_html - writes the buffer to stdout (troff).
+ * It writes out the file replacing template image names with
+ * actual image names.
+ */
+
+void char_buffer::write_file_html (void)
+{
+ char_block *t =head;
+ char *name;
+ int i=0;
+
+ if (t != 0) {
+ stop();
+ do {
+ /*
+ * remember to check the shortest string last
+ */
+ if (can_see(&t, &i, HTML_IMAGE_END)) {
+ write_end_image(TRUE);
+ skip_to_newline(&t, &i);
+ } else if (can_see(&t, &i, HTML_IMAGE_LEFT)) {
+ write_start_image(LEFT, TRUE);
+ skip_to_newline(&t, &i);
+ } else if (can_see(&t, &i, HTML_IMAGE_RIGHT)) {
+ write_start_image(RIGHT, TRUE);
+ skip_to_newline(&t, &i);
+ } else if (can_see(&t, &i, HTML_IMAGE_CENTERED)) {
+ stop();
+ write_start_image(CENTERED, TRUE);
+ skip_to_newline(&t, &i);
+ } else {
+ write_upto_newline(&t, &i, TRUE);
+ }
+ } while (t != 0);
+ }
+ if (close(stdoutfd) < 0)
+ sys_fatal("close");
+
+ // now we grab fd=1 so that the next pipe cannot use fd=1
+ if (stdoutfd == 1) {
+ if (dup(2) != stdoutfd) {
+ sys_fatal("dup failed to use fd=1");
+ }
+ }
+}
+
+/*
+ * generateImages - parses the region file and generates images
+ * from the postscript file. The region file
+ * contains the x1,y1 x2,y2 extents of each
+ * image.
+ */
+
+static void generateImages (char *regionFileName)
+{
+ pushBackBuffer *f=new pushBackBuffer(regionFileName);
+ char ch;
+
+ while (f->putPB(f->getPB()) != eof) {
+ if (f->isString("grohtml-info:page")) {
+ int page = f->readInt();
+ int x1 = f->readInt();
+ int y1 = f->readInt();
+ int x2 = f->readInt();
+ int y2 = f->readInt();
+ int maxx = max(f->readInt(), MAX_WIDTH*image_res);
+ char *name = f->readString();
+ int res = POSTSCRIPTRES; // --fixme-- prefer (f->readInt()) providing that troff can discover the value
+ listOfImages.add(x1, y1, x2, y2, page, res, maxx, name);
+ while ((f->putPB(f->getPB()) != '\n') &&
+ (f->putPB(f->getPB()) != eof)) {
+ ch = f->getPB();
+ }
+ if (f->putPB(f->getPB()) == '\n') {
+ ch = f->getPB();
+ }
+ } else {
+ /*
+ * write any error messages out to the user
+ */
+ fputc(f->getPB(), stderr);
+ }
+ }
+}
+
+/*
+ * replaceFd - replace a file descriptor, was, with, willbe.
+ */
+
+static void replaceFd (int was, int willbe)
+{
+ int dupres;
+
+ if (was != willbe) {
+ if (close(was)<0) {
+ sys_fatal("close");
+ }
+ dupres = dup(willbe);
+ if (dupres != was) {
+ sys_fatal("dup");
+ fprintf(stderr, "trying to replace fd=%d with %d dup used %d\n", was, willbe, dupres);
+ if (willbe == 1) {
+ fprintf(stderr, "likely that stdout should be opened before %d\n", was);
+ }
+ exit(1);
+ }
+ if (close(willbe) < 0) {
+ sys_fatal("close");
+ }
+ }
+}
+
+/*
+ * waitForChild - waits for child, pid, to exit.
+ */
+
+static void waitForChild (PID_T pid)
+{
+ PID_T waitpd;
+ int status;
+
+ waitpd = wait(&status);
+ if (waitpd != pid)
+ sys_fatal("wait");
+}
+
+/*
+ * alterDeviceTo - if toImage is set then the arg list is altered to include
+ * IMAGE_DEVICE and we invoke groff rather than troff.
+ * else
+ * set -Thtml and troff
+ */
+
+static void alterDeviceTo (int argc, char *argv[], int toImage)
+{
+ int i=0;
+
+ if (toImage) {
+ while (i < argc) {
+ if (strcmp(argv[i], "-Thtml") == 0) {
+ argv[i] = IMAGE_DEVICE;
+ }
+ i++;
+ }
+ argv[troff_arg] = "groff"; /* rather than troff */
+ } else {
+ while (i < argc) {
+ if (strcmp(argv[i], IMAGE_DEVICE) == 0) {
+ argv[i] = "-Thtml";
+ }
+ i++;
+ }
+ argv[troff_arg] = troff_command; /* use troff */
+ }
+}
+
+/*
+ * do_html - sets the troff number htmlflip and
+ * writes out the buffer to troff -Thtml
+ */
+
+int char_buffer::do_html(int argc, char *argv[])
+{
+ int pdes[2];
+ PID_T pid;
+
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+
+ alterDeviceTo(argc, argv, 0);
+ argv += troff_arg; // skip all arguments up to troff/groff
+ argc -= troff_arg;
+
+#if defined(DEBUG_HTML)
+ write_file_html();
+ writeString("--------------- troff --------------------------\n");
+ write_file_troff();
+#else
+ pid = fork();
+ if (pid < 0)
+ sys_fatal("fork");
+
+ if (pid == 0) {
+ // child
+ replaceFd(0, pdes[0]);
+ // close end we are not using
+ if (close(pdes[1])<0)
+ sys_fatal("close");
+ replaceFd(1, copyofstdoutfd); // and restore stdout
+
+ execvp(argv[0], argv);
+ error("couldn't exec %1: %2", argv[0], strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ exit(1);
+ } else {
+ // parent
+
+#if defined(DEBUGGING)
+ /*
+ * slight security risk so only enabled if compiled with defined(DEBUGGING)
+ */
+ if (debug) {
+ replaceFd(1, creat(htmlFileName, S_IWUSR|S_IRUSR));
+ write_file_html();
+ }
+#endif
+ replaceFd(1, pdes[1]);
+ // close end we are not using
+ if (close(pdes[0])<0)
+ sys_fatal("close");
+
+ write_file_html();
+ waitForChild(pid);
+ }
+#endif
+ return( 0 );
+}
+
+/*
+ * addps4html - appends -rps4html=1 onto the command list for troff.
+ */
+
+char **addps4html (int argc, char *argv[])
+{
+ char **new_argv = (char **)malloc((argc+2)*sizeof(char *));
+ int i=0;
+
+ while (i<argc) {
+ new_argv[i] = argv[i];
+ i++;
+ }
+ new_argv[argc] = "-rps4html=1";
+ argc++;
+ new_argv[argc] = NULL;
+ return( new_argv );
+}
+
+/*
+ * do_image - writes out the buffer to troff -Tps
+ */
+
+int char_buffer::do_image(int argc, char *argv[])
+{
+ PID_T pid;
+ int pdes[2];
+
+ if (pipe(pdes) < 0)
+ sys_fatal("pipe");
+
+ alterDeviceTo(argc, argv, 1);
+ argv += troff_arg; // skip all arguments up to troff/groff
+ argc -= troff_arg;
+ argv = addps4html(argc, argv);
+ argc++;
+
+ pid = fork();
+ if (pid == 0) {
+ // child
+
+ int psFd = creat(psFileName, S_IWUSR|S_IRUSR);
+ int regionFd = creat(regionFileName, S_IWUSR|S_IRUSR);
+
+ replaceFd(1, psFd);
+ replaceFd(0, pdes[0]);
+ replaceFd(2, regionFd);
+
+ // close end we are not using
+ if (close(pdes[1])<0)
+ sys_fatal("close");
+
+ execvp(argv[0], argv);
+ error("couldn't exec %1: %2", argv[0], strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ exit(1);
+ } else {
+ // parent
+
+#if defined(DEBUGGING)
+ /*
+ * slight security risk so only enabled if compiled with defined(DEBUGGING)
+ */
+ if (debug) {
+ replaceFd(1, creat(troffFileName, S_IWUSR|S_IRUSR));
+ write_file_troff();
+ }
+#endif
+ replaceFd(1, pdes[1]);
+ write_file_troff();
+ waitForChild(pid);
+ }
+ return( 0 );
+}
+
+static char_buffer inputFile;
+
+
+/*
+ * usage - emit usage arguments.
+ */
+
+void usage(FILE *stream)
+{
+ fprintf(stream, "usage: %s troffname [-P-o vertical_image_offset] [-P-i image_resolution] [troff flags] [files]\n", program_name);
+ fprintf(stream, " vertical_image_offset (default %d/72 of an inch)\n", vertical_offset);
+ fprintf(stream, " image_resolution (default %d) pixels per inch\n", image_res);
+}
+
+/*
+ * scanArguments - scans for -P-i and -P-o arguments.
+ */
+
+int scanArguments (int argc, char **argv)
+{
+ int i=1;
+
+ while (i<argc) {
+ if (strncmp(argv[i], "-i", 2) == 0) {
+ image_res = atoi((char *)(argv[i]+2));
+ } else if (strncmp(argv[i], "-o", 2) == 0) {
+ vertical_offset = atoi((char *)(argv[i]+2));
+ } else if ((strcmp(argv[i], "-v") == 0)
+ || (strcmp(argv[i], "--version") == 0)) {
+ extern const char *Version_string;
+ printf("GNU pre-grohtml (groff) version %s\n", Version_string);
+ exit(0);
+ } else if ((strcmp(argv[i], "-h") == 0)
+ || (strcmp(argv[i], "--help") == 0)
+ || (strcmp(argv[i], "-?") == 0)) {
+ usage(stdout);
+ exit(0);
+ } else if (strcmp(argv[i], "troff") == 0) {
+ /* remember troff argument number */
+ troff_arg = i;
+#if defined(DEBUGGING)
+ } else if (strcmp(argv[i], "-d") == 0) {
+ debug = TRUE;
+#endif
+ } else if (argv[i][0] != '-') {
+ return( i );
+ }
+ i++;
+ }
+ return( argc );
+}
+
+/*
+ * makeTempFiles - name the temporary files
+ */
+
+static void makeTempFiles (void)
+{
+#if defined(DEBUGGING)
+ psFileName = "/tmp/prehtml-ps";
+ regionFileName = "/tmp/prehtml-region";
+ imagePageStem = "/tmp/prehtml-page";
+ troffFileName = "/tmp/prehtml-troff";
+ htmlFileName = "/tmp/prehtml-html";
+#else
+ psFileName = mktemp(xtmptemplate("-ps-"));
+ regionFileName = mktemp(xtmptemplate("-regions-"));
+ imagePageStem = mktemp(xtmptemplate("-page-"));
+#endif
+}
+
+/*
+ * removeTempFiles - remove the temporary files
+ */
+
+static void removeTempFiles (void)
+{
+#if !defined(DEBUGGING)
+ remove(psFileName);
+ remove(regionFileName);
+#endif
+}
+
+/*
+ * findPrefix - finds the optional prefix to the groff utilities.
+ * It also builds the 'troff' executable name.
+ */
+
+static void findPrefix (void)
+{
+ command_prefix = getenv("GROFF_COMMAND_PREFIX");
+ if (!command_prefix)
+ command_prefix = PROG_PREFIX;
+ troff_command = (char *)malloc(strlen("troff")+strlen(command_prefix)+1);
+ strcpy(troff_command, command_prefix);
+ strcat(troff_command, "troff");
+}
+
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int i;
+ int found=0;
+ int ok=1;
+
+ findPrefix();
+ makeFileName();
+ i = scanArguments(argc, argv);
+ while (i < argc) {
+ if (argv[i][0] != '-') {
+ /* found source file */
+ ok = do_file(argv[i]);
+ if (! ok) {
+ return( 0 );
+ }
+ found = 1;
+ }
+ i++;
+ }
+
+ copyofstdoutfd=dup(stdoutfd);
+
+ if (! found) {
+ do_file("-");
+ }
+ makeTempFiles();
+ ok = inputFile.do_image(argc, argv);
+ if (ok == 0) {
+ createAllPages();
+ generateImages(regionFileName);
+ ok = inputFile.do_html(argc, argv);
+ removeAllPages();
+ }
+ removeTempFiles();
+ return ok;
+}
+
+static int do_file(const char *filename)
+{
+ FILE *fp;
+
+ current_filename = filename;
+ if (strcmp(filename, "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(filename, "r");
+ if (fp == 0) {
+ error("can't open `%1': %2", filename, strerror(errno));
+ return 0;
+ }
+ }
+
+ if (inputFile.read_file(fp)) {
+ }
+
+ if (fp != stdin)
+ fclose(fp);
+ current_filename = 0;
+ return 1;
+}
diff --git a/contrib/groff/src/preproc/html/pre-html.h b/contrib/groff/src/preproc/html/pre-html.h
new file mode 100644
index 0000000..f9a590c
--- /dev/null
+++ b/contrib/groff/src/preproc/html/pre-html.h
@@ -0,0 +1,37 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 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. */
+
+/*
+ * defines functions implemented within pre-html.c
+ */
+
+#if !defined(PREHTMLH)
+# define PREHTMLH
+# if defined(PREHTMLC)
+# define EXTERN
+# else
+# define EXTERN extern
+# endif
+
+
+extern void sys_fatal (const char *s);
+
+#undef EXTERN
+#endif
diff --git a/contrib/groff/src/preproc/html/pushbackbuffer.cc b/contrib/groff/src/preproc/html/pushbackbuffer.cc
new file mode 100644
index 0000000..1d380f4
--- /dev/null
+++ b/contrib/groff/src/preproc/html/pushbackbuffer.cc
@@ -0,0 +1,337 @@
+// -*- C++ -*-
+/* Copyright (C) 2000, 2001 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. */
+
+#include <stdio.h>
+#include <signal.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 "posix.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "pushbackbuffer.h"
+#include "pre-html.h"
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+# define ERROR(X) (fprintf(stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) && \
+ (fflush(stderr)) && localexit(1))
+
+
+#define MAXPUSHBACKSTACK 4096 /* maximum number of character that can be pushed back */
+
+
+/*
+ * constructor for pushBackBuffer
+ */
+
+pushBackBuffer::pushBackBuffer (char *filename)
+{
+ charStack = (char *)malloc(MAXPUSHBACKSTACK);
+ if (charStack == 0) {
+ sys_fatal("malloc");
+ }
+ stackPtr = 0; /* index to push back stack */
+ debug = 0;
+ verbose = 0;
+ eofFound = FALSE;
+ lineNo = 1;
+ if (strcmp(filename, "") != 0) {
+ stdIn = dup(0);
+ close(0);
+ if (open(filename, O_RDONLY) != 0) {
+ sys_fatal("when trying to open file");
+ } else {
+ fileName = filename;
+ }
+ }
+}
+
+pushBackBuffer::~pushBackBuffer ()
+{
+ int old;
+
+ if (charStack != 0) {
+ free(charStack);
+ }
+ close(0);
+ /* restore stdin in file descriptor 0 */
+ old = dup(stdIn);
+ close(stdIn);
+}
+
+/*
+ * localexit - wraps exit with a return code to aid the ERROR macro.
+ */
+
+int localexit (int i)
+{
+ exit(i);
+ return( 1 );
+}
+
+/*
+ * getPB - returns a character, possibly a pushed back character.
+ */
+
+char pushBackBuffer::getPB (void)
+{
+ if (stackPtr>0) {
+ stackPtr--;
+ return( charStack[stackPtr] );
+ } else {
+ char ch;
+
+ if (read(0, &ch, 1) == 1) {
+ if (verbose) {
+ printf("%c", ch);
+ }
+ if (ch == '\n') {
+ lineNo++;
+ }
+ return( ch );
+ } else {
+ eofFound = TRUE;
+ return( eof );
+ }
+ }
+}
+
+/*
+ * putPB - pushes a character onto the push back stack.
+ * The same character is returned.
+ */
+
+char pushBackBuffer::putPB (char ch)
+{
+ if (stackPtr<MAXPUSHBACKSTACK) {
+ charStack[stackPtr] = ch ;
+ stackPtr++;
+ } else {
+ ERROR("max push back stack exceeded, increase MAXPUSHBACKSTACK constant");
+ }
+ return( ch );
+}
+
+/*
+ * isWhite - returns TRUE if a white character is found. This character is NOT consumed.
+ */
+
+static int isWhite (char ch)
+{
+ return( (ch==' ') || (ch == '\t') || (ch == '\n') );
+}
+
+/*
+ * skipToNewline - skips characters until a newline is seen.
+ */
+
+void pushBackBuffer::skipToNewline (void)
+{
+ char ch;
+
+ while ((putPB(getPB()) != '\n') && (! eofFound)) {
+ ch = getPB();
+ }
+}
+
+/*
+ * skipUntilToken - skips until a token is seen
+ */
+
+void pushBackBuffer::skipUntilToken (void)
+{
+ char ch;
+
+ while ((isWhite(putPB(getPB())) || (putPB(getPB()) == '#')) && (! eofFound)) {
+ ch = getPB();
+ if (ch == '#') {
+ skipToNewline();
+ }
+ }
+}
+
+/*
+ * isString - returns TRUE if the string, s, matches the pushed back string.
+ * if TRUE is returned then this string is consumed, otherwise it is
+ * left alone.
+ */
+
+int pushBackBuffer::isString (char *s)
+{
+ int length=strlen(s);
+ int i=0;
+ int j;
+
+ while ((i<length) && (putPB(getPB())==s[i])) {
+ if (getPB() != s[i]) {
+ ERROR("assert failed");
+ }
+ i++;
+ }
+ if (i==length) {
+ return( TRUE );
+ } else {
+ i--;
+ while (i>=0) {
+ if (putPB(s[i]) != s[i]) {
+ ERROR("assert failed");
+ }
+ i--;
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * isDigit - returns TRUE if the character, ch, is a digit.
+ */
+
+static int isDigit (char ch)
+{
+ return( ((ch>='0') && (ch<='9')) );
+}
+
+/*
+ * isHexDigit - returns TRUE if the character, ch, is a hex digit.
+ */
+
+static int isHexDigit (char ch)
+{
+ return( (isDigit(ch)) || ((ch>='a') && (ch<='f')) );
+}
+
+/*
+ * readInt - returns an integer from the input stream.
+ */
+
+int pushBackBuffer::readInt (void)
+{
+ int c =0;
+ int i =0;
+ int s =1;
+ char ch=getPB();
+
+ while (isWhite(ch)) {
+ ch=getPB();
+ }
+ // now read integer
+
+ if (ch == '-') {
+ s = -1;
+ ch = getPB();
+ }
+ while (isDigit(ch)) {
+ i *= 10;
+ if ((ch>='0') && (ch<='9')) {
+ i += (int)(ch-'0');
+ }
+ ch = getPB();
+ c++;
+ }
+ if (ch != putPB(ch)) {
+ ERROR("assert failed");
+ }
+ return( i*s );
+}
+
+/*
+ * convertToFloat - converts integers, a and b into a.b
+ */
+
+static float convertToFloat (int a, int b)
+{
+ int c=10;
+ float f;
+
+ while (b>c) {
+ c *= 10;
+ }
+ f = ((float)a) + (((float)b)/((float)c));
+ return( f );
+}
+
+/*
+ * readNumber - returns a float representing the word just read.
+ */
+
+float pushBackBuffer::readNumber (void)
+{
+ int integer;
+ int fraction;
+ char ch;
+ float f;
+
+ integer = readInt();
+ if (putPB(getPB()) == '.') {
+ ch = getPB();
+ fraction = readInt();
+ f = convertToFloat(integer, fraction);
+ return( f );
+ } else {
+ return( (float)integer );
+ }
+}
+
+/*
+ * readString - reads a string terminated by white space
+ * and returns a malloced area of memory containing
+ * a copy of the characters.
+ */
+
+char *pushBackBuffer::readString (void)
+{
+ char buffer[MAXPUSHBACKSTACK];
+ char *string = 0;
+ int i=0;
+ char ch=getPB();
+
+ while (isWhite(ch)) {
+ ch=getPB();
+ }
+ while ((i < MAXPUSHBACKSTACK) && (! isWhite(ch)) && (! eofFound)) {
+ buffer[i] = ch;
+ i++;
+ ch = getPB();
+ }
+ if (i < MAXPUSHBACKSTACK) {
+ buffer[i] = (char)0;
+ string = (char *)malloc(strlen(buffer)+1);
+ strcpy(string, buffer);
+ }
+ return( string );
+}
diff --git a/contrib/groff/src/preproc/html/pushbackbuffer.h b/contrib/groff/src/preproc/html/pushbackbuffer.h
new file mode 100644
index 0000000..93cb3f1
--- /dev/null
+++ b/contrib/groff/src/preproc/html/pushbackbuffer.h
@@ -0,0 +1,54 @@
+// -*- C -*-
+/* Copyright (C) 2000, 2001 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. */
+
+
+#define eof (char)-1
+
+
+/*
+ * defines the class and methods implemented within pushbackbuffer.cc
+ */
+
+class pushBackBuffer
+{
+ private:
+ char *charStack;
+ int stackPtr; /* index to push back stack */
+ int debug;
+ int verbose;
+ int eofFound;
+ char *fileName;
+ int lineNo;
+ int stdIn;
+
+ public:
+ pushBackBuffer (char *);
+ ~ pushBackBuffer ();
+ char getPB (void);
+ char putPB (char ch);
+ void skipUntilToken (void);
+ void skipToNewline (void);
+ float readNumber (void);
+ int readInt (void);
+ char *readString (void);
+ int isString (char *string);
+};
+
+
diff --git a/contrib/groff/src/preproc/pic/Makefile.sub b/contrib/groff/src/preproc/pic/Makefile.sub
new file mode 100644
index 0000000..f1e2927
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/TODO b/contrib/groff/src/preproc/pic/TODO
new file mode 100644
index 0000000..2346b57
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/common.cc b/contrib/groff/src/preproc/pic/common.cc
new file mode 100644
index 0000000..e83ef31
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/common.h b/contrib/groff/src/preproc/pic/common.h
new file mode 100644
index 0000000..25a6e10
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/lex.cc b/contrib/groff/src/preproc/pic/lex.cc
new file mode 100644
index 0000000..5b6d439
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/lex.cc
@@ -0,0 +1,1940 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 "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 },
+ { "solid", SOLID },
+ { "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/contrib/groff/src/preproc/pic/main.cc b/contrib/groff/src/preproc/pic/main.cc
new file mode 100644
index 0000000..87d2b93
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/main.cc
@@ -0,0 +1,635 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [ -nvC ] [ filename ... ]\n", program_name);
+#ifdef TEX_SUPPORT
+ fprintf(stream, " %s -t [ -cvzC ] [ filename ... ]\n", program_name);
+#endif
+#ifdef FIG_SUPPORT
+ fprintf(stream, " %s -f [ -v ] [ filename ]\n", program_name);
+#endif
+}
+
+#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
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "T:CDSUtcvnxzpf", long_options, NULL))
+ != 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;
+ printf("GNU pic (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case 'z':
+ // zero length lines will be printed as dots
+ zero_length_line_flag++;
+ break;
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ 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(stderr);
+ exit(1);
+ } 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/contrib/groff/src/preproc/pic/object.cc b/contrib/groff/src/preproc/pic/object.cc
new file mode 100644
index 0000000..6b34633
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/object.h b/contrib/groff/src/preproc/pic/object.h
new file mode 100644
index 0000000..2748e81
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/output.h b/contrib/groff/src/preproc/pic/output.h
new file mode 100644
index 0000000..ac490db
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/pic.cc b/contrib/groff/src/preproc/pic/pic.cc
new file mode 100644
index 0000000..f6d97bb
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/pic.cc
@@ -0,0 +1,5216 @@
+#ifndef lint
+/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/
+static char yyrcsid[] = "$Id: pic.cc,v 1.3 2000/11/14 20:40:28 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/src/preproc/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();
+#ifdef RET_TYPE_SRAND_IS_VOID
+ void srand(unsigned int);
+#else
+ int srand(unsigned int);
+#endif
+}
+
+/* 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 82 "/home/cjk/groff/src/preproc/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 92 "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 SOLID 291
+#define DOTTED 292
+#define DASHED 293
+#define CHOP 294
+#define SAME 295
+#define INVISIBLE 296
+#define LJUST 297
+#define RJUST 298
+#define ABOVE 299
+#define BELOW 300
+#define OF 301
+#define THE 302
+#define WAY 303
+#define BETWEEN 304
+#define AND 305
+#define HERE 306
+#define DOT_N 307
+#define DOT_E 308
+#define DOT_W 309
+#define DOT_S 310
+#define DOT_NE 311
+#define DOT_SE 312
+#define DOT_NW 313
+#define DOT_SW 314
+#define DOT_C 315
+#define DOT_START 316
+#define DOT_END 317
+#define DOT_X 318
+#define DOT_Y 319
+#define DOT_HT 320
+#define DOT_WID 321
+#define DOT_RAD 322
+#define SIN 323
+#define COS 324
+#define ATAN2 325
+#define LOG 326
+#define EXP 327
+#define SQRT 328
+#define K_MAX 329
+#define K_MIN 330
+#define INT 331
+#define RAND 332
+#define SRAND 333
+#define COPY 334
+#define THRU 335
+#define TOP 336
+#define BOTTOM 337
+#define UPPER 338
+#define LOWER 339
+#define SH 340
+#define PRINT 341
+#define CW 342
+#define CCW 343
+#define FOR 344
+#define DO 345
+#define IF 346
+#define ELSE 347
+#define ANDAND 348
+#define OROR 349
+#define NOTEQUAL 350
+#define EQUALEQUAL 351
+#define LESSEQUAL 352
+#define GREATEREQUAL 353
+#define LEFT_CORNER 354
+#define RIGHT_CORNER 355
+#define CENTER 356
+#define END 357
+#define START 358
+#define RESET 359
+#define UNTIL 360
+#define PLOT 361
+#define THICKNESS 362
+#define FILL 363
+#define ALIGNED 364
+#define SPRINTF 365
+#define COMMAND 366
+#define DEFINE 367
+#define UNDEF 368
+#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, 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, 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, 126, 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, 147, 204, 205, 150,
+ 152, 189, 190, 146, 176, 177, 178, 179, 180, 181,
+ 182, 183, 184, 185, 186, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 187, 188, 0, 0,
+ 195, 196, 201, 203, 202, 0, 0, 0, 0, 0,
+ 132, 130, 148, 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, 114,
+ 115, 116, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 102, 103, 0, 0, 0,
+ 112, 113, 120, 121, 122, 123, 117, 118, 0, 0,
+ 125, 0, 119, 36, 0, 0, 10, 0, 22, 0,
+ 20, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 191, 193, 197, 199, 192, 194, 198, 200,
+ 0, 0, 0, 0, 0, 0, 0, 0, 138, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 206, 207, 208,
+ 209, 210, 0, 143, 0, 0, 164, 156, 157, 158,
+ 159, 160, 161, 162, 0, 155, 153, 154, 39, 0,
+ 0, 57, 0, 0, 0, 43, 0, 0, 0, 0,
+ 81, 128, 0, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 167, 100, 0, 170, 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, 229, 0, 0,
+ 218, 141, 0, 151, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 149, 133, 134, 163, 0, 0, 53,
+ 0, 0, 0, 0, 0, 51, 0, 0, 50, 49,
+ 0, 66, 83, 32, 175, 0, 0, 0, 0, 165,
+ 0, 169, 0, 0, 23, 0, 219, 220, 0, 222,
+ 223, 224, 0, 0, 227, 228, 230, 0, 0, 0,
+ 0, 0, 44, 0, 127, 0, 0, 174, 173, 0,
+ 166, 0, 0, 27, 0, 0, 0, 135, 139, 0,
+ 0, 0, 0, 70, 67, 172, 0, 24, 46, 221,
+ 225, 226, 137, 0, 0, 171, 0, 0, 28, 0,
+ 0, 29,
+};
+short yydgoto[] = { 2,
+ 106, 182, 108, 405, 91, 92, 33, 93, 94, 266,
+ 267, 268, 109, 96, 34, 3, 35, 36, 97, 226,
+ 98, 99, 384, 341, 110, 101, 102, 244, 5, 38,
+ 46, 287, 382, 160, 356, 411, 246, 39, 334, 115,
+ 395, 376, 116, 205,
+};
+short yysindex[] = { 25,
+ 0, 0, 0,11784, 59, -47, -5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, -250, 0,10817, -218,10934, -197,11387, 90,10817,
+ 0, 0, -214, 0, 25,10516, 0, 0, -36, 0,
+ 25,10934, 75, -192, 0, -124, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 106, 107, 110, 111, 113,
+ 120, 122, 124, 143, 146, 153, 0, 0, -213, -41,
+ 0, 0, 0, 0, 0,11061,10934,11387,11387, 635,
+ 0, 0, 0, -61, -64, 2542, 44, 834, 356, 0,
+10817, 0, 133,10934,10934, 1378, -91, -294, -64, -279,
+ 0, -28, -52,10817, 25, 25, 0, 0,11406, 0,
+ 0, 0,11694,11694,11694,11694,11387,11387,11387,11387,
+11505,11505,11505, 3348,11609, 0, 0,11694,11694,11694,
+ 0, 0, 0, 0, 0, 0, 0, 0,11387,11694,
+ 0, 1491, 0, 0, -33,10189, 0,10934, 0, -46,
+ 0,10934,10934,10934,10934,10934,10934,10934,10934,10934,
+10633,10934, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1524, 194, 195, -23, -26, 150, 150, -56, 0,11387,
+11387,11387,11387,11387,11387,11387,11505,11387,11387,11387,
+11387,11387,11387,11387,11505, -29, 213, 0, 0, 0,
+ 0, 0, -7, 0,11609,11609, 0, 0, 0, 0,
+ 0, 0, 0, 0, 167, 0, 0, 0, 0,11387,
+ 150, 0,10934,10934,11387, 0,10934,10934, -230, -230,
+ 0, 0, 139,11784, 177, 11, 0, 1491, 1491, 1491,
+ 1491, 1491, 1491, 1491, 1491, 635, 44, 44, 44, 2101,
+ 432, 834, 2101, 17, 0, 0, 2435, 0,11178, 623,
+ 0, 1491, 1491, 1491, 1491, 1491, 0, -47, -5, 0,
+ 0, 0, -64, 0, 44, 0, 18, 0, 240, 246,
+ 244, 248, 249, 250, 252, 253, 257, 0, 260, 262,
+ 0, 0,11505, 0, 1, 1953, 1821, 158, 158, 4,
+ 4, 1491, -19, 48, 4, 200, 200, 150, 150, 150,
+ 150, -42, 213, 0, 0, 0, 0, 1044, 1953, 0,
+ 1924, -43, 4, 46, 1953, 0, 1924, -43, 0, 0,
+ 19, 0, 0, 0, 0, 834, 2101, 2101, 266, 0,
+ 49, 0, 1079, 195, 0, -49, 0, 0,10934, 0,
+ 0, 0,10934,10934, 0, 0, 0, 33, 8,11505,
+11505,11387, 0,11387, 0,11784, 2101, 0, 0, 2101,
+ 0, -49, 55, 0, 275, 277, 290, 0, 0, 7,
+ 44, 1484, 1491, 0, 0, 0, 293, 0, 0, 0,
+ 0, 0, 0,11283, -10, 0,11387, 1491, 0, 1491,
+ 74, 0,
+};
+short yyrindex[] = { 204,
+ 0, 0, 0, 338, 94, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 36, 0, 0, 0,
+ 0, 0, 399, 0, 27, 412, 0, 0, 443, 0,
+10384, 0, 0, 454, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 8824,
+ 0, 0, 0, 0, 4444, 8610, 9125, 0, 0, 0,
+ 467, 0, 0, 0, 0, 954, 0, 970, 0, 0,
+ 0,10077, 0, 487,11820,11820, 0, 0, 31, 0,
+ 0, 0, 9459, 9500, 9245, 9351, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 9612, 9720, 9761,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9868,
+ 0, 4996, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 299, 0, 114, 0, 0, 456, 566, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3115, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 224, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 5297, 5406, 5707,
+ 5816, 6117, 6226, 6527, 6636, 0, 6937, 7046, 7347, 0,
+ 0, 0, 0, 0, 0, 0, 8697, 0, 0, 0,
+ 0, 7456, 7757, 7866, 8167, 8276, 0, 9870, 1967, 3642,
+ 4085, 184, 233, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4001, 4110, 3224, 3558, 2229,
+ 2338, 4887, 9004, 0, 2672, 1786, 1895, 900, 1009, 1343,
+ 1452, 0, 3667, 0, 0, 0, 0, 0, 29, 0,
+ 38, 182, 2781, 0, 96, 0, 468, 578, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 299, 0, 0, 495, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 530, 0, 0, 0, 0,
+ 0, 495, 0, 0, 0, 0, 0, 0, 0, 0,
+ 4553, -4, 39, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, -2, 0, -1,
+ 0, 0,
+};
+short yygindex[] = { 0,
+ -24, 480, -89, 0, -18, 189, 0, 0, -48, 0,
+ 0, 354, 3172, -87, -114, -3, 0, 0, 1313, -74,
+ 0, 0, -21, 0, 9, 326, -57, 2, 324, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+#define YYTABLESIZE 12186
+short yytable[] = { 90,
+ 215, 4, 216, 112, 247, 90, 207, 155, 203, 44,
+ 41, 152, 37, 201, 199, 232, 200, 203, 202, 215,
+ 303, 216, 201, 199, 228, 200, 6, 202, 237, 8,
+ 7, 235, 100, 198, 87, 34, 118, 238, 100, 103,
+ 203, 284, 156, 229, 153, 201, 199, 214, 200, 215,
+ 202, 216, 43, 237, 238, 42, 229, 173, 174, 375,
+ 111, 181, 374, 186, 187, 204, 87, 183, 403, 237,
+ 239, 240, 237, 388, 204, 215, 90, 216, 238, 129,
+ 231, 238, 129, 1, 45, 265, 215, 237, 216, 90,
+ 215, 370, 216, 7, 34, 52, 238, 204, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 256, 256, 100,
+ 270, 243, 245, 272, 273, 274, 271, 40, 323, 6,
+ 241, 237, 100, 7, 275, 276, 7, 37, 34, 113,
+ 238, 256, 117, 7, 29, 158, 52, 161, 7, 52,
+ 175, 176, 159, 330, 332, 162, 163, 336, 338, 164,
+ 165, 6, 166, 237, 52, 7, 132, 132, 132, 167,
+ 34, 168, 238, 169, 37, 306, 307, 308, 309, 310,
+ 311, 312, 313, 315, 316, 317, 318, 319, 320, 321,
+ 256, 56, 170, 63, 7, 171, 347, 348, 52, 7,
+ 270, 270, 172, 230, 203, 47, 325, 326, 236, 201,
+ 199, 50, 200, 6, 202, 328, 51, 242, 329, 331,
+ 333, 265, 335, 337, 265, 288, 7, 235, 352, 198,
+ 52, 154, 56, 239, 277, 56, 130, 47, 130, 177,
+ 178, 8, 64, 50, 301, 302, 203, 304, 51, 206,
+ 56, 201, 63, 204, 353, 305, 202, 339, 340, 324,
+ 354, 204, 37, 208, 209, 210, 211, 212, 213, 327,
+ 239, 394, 371, 342, 239, 239, 239, 239, 239, 343,
+ 239, 377, 344, 350, 56, 131, 63, 131, 256, 355,
+ 357, 188, 239, 239, 189, 239, 358, 359, 360, 361,
+ 362, 64, 237, 204, 6, 363, 364, 365, 265, 265,
+ 366, 238, 367, 369, 237, 381, 56, 373, 63, 380,
+ 383, 389, 179, 180, 399, 400, 239, 401, 237, 190,
+ 191, 192, 193, 194, 195, 64, 6, 238, 265, 237,
+ 402, 265, 237, 406, 409, 412, 29, 1, 238, 47,
+ 58, 238, 59, 60, 282, 256, 256, 392, 239, 393,
+ 7, 7, 7, 7, 7, 114, 7, 64, 119, 52,
+ 398, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 0, 0, 237, 237, 0, 408,
+ 0, 0, 410, 0, 37, 52, 238, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 30, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 61, 0, 0, 0, 0, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 0, 7,
+ 7, 7, 7, 7, 7, 0, 0, 7, 0, 7,
+ 0, 0, 33, 52, 52, 56, 225, 7, 7, 7,
+ 7, 7, 7, 21, 7, 217, 0, 30, 7, 7,
+ 6, 6, 0, 6, 6, 0, 18, 55, 0, 0,
+ 61, 56, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 0, 0, 17, 239, 217, 0,
+ 0, 30, 217, 0, 45, 217, 217, 217, 217, 217,
+ 217, 33, 217, 0, 61, 107, 0, 0, 55, 194,
+ 195, 55, 21, 239, 217, 217, 0, 217, 0, 0,
+ 0, 157, 225, 30, 239, 18, 55, 239, 0, 69,
+ 56, 0, 0, 0, 0, 33, 61, 6, 0, 0,
+ 0, 0, 0, 6, 6, 17, 21, 6, 217, 6,
+ 0, 217, 0, 45, 0, 0, 0, 0, 0, 18,
+ 55, 0, 6, 0, 6, 239, 185, 33, 6, 6,
+ 0, 239, 239, 239, 239, 239, 239, 54, 21, 17,
+ 217, 0, 0, 0, 0, 0, 0, 45, 69, 0,
+ 0, 18, 55, 0, 0, 0, 0, 0, 239, 0,
+ 0, 0, 239, 0, 0, 239, 239, 239, 239, 239,
+ 239, 17, 239, 345, 0, 217, 349, 0, 54, 45,
+ 0, 54, 69, 227, 239, 239, 0, 239, 218, 219,
+ 220, 221, 222, 223, 0, 224, 54, 286, 0, 0,
+ 0, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 299, 300, 0, 0, 69, 0, 0, 0, 239, 203,
+ 0, 239, 0, 0, 201, 199, 196, 200, 0, 202,
+ 54, 203, 0, 0, 0, 0, 201, 199, 196, 200,
+ 0, 202, 235, 0, 198, 0, 0, 0, 0, 0,
+ 239, 217, 0, 0, 197, 0, 198, 0, 0, 346,
+ 378, 379, 54, 0, 218, 219, 220, 221, 222, 223,
+ 0, 224, 217, 217, 217, 217, 204, 0, 217, 217,
+ 217, 217, 217, 217, 217, 217, 217, 217, 204, 0,
+ 396, 55, 0, 397, 0, 0, 217, 217, 217, 217,
+ 217, 217, 217, 217, 217, 217, 217, 217, 217, 217,
+ 217, 217, 217, 217, 217, 217, 217, 55, 0, 217,
+ 217, 217, 217, 217, 217, 217, 217, 217, 217, 217,
+ 217, 217, 217, 0, 0, 0, 0, 0, 217, 217,
+ 217, 217, 217, 217, 217, 217, 217, 217, 217, 0,
+ 0, 217, 217, 217, 217, 0, 0, 217, 217, 0,
+ 217, 0, 0, 217, 217, 217, 217, 217, 217, 217,
+ 217, 217, 217, 217, 0, 0, 55, 217, 217, 217,
+ 217, 0, 239, 239, 239, 239, 0, 0, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239, 385, 0,
+ 0, 54, 386, 387, 0, 0, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 54, 0, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 0, 0, 0, 0, 0, 239, 239,
+ 239, 239, 239, 239, 239, 239, 239, 239, 239, 213,
+ 0, 239, 239, 239, 239, 0, 0, 239, 239, 0,
+ 239, 0, 0, 239, 239, 239, 239, 239, 239, 239,
+ 239, 239, 239, 239, 225, 0, 54, 239, 239, 239,
+ 239, 0, 213, 0, 0, 188, 213, 0, 189, 213,
+ 213, 213, 213, 213, 213, 0, 213, 0, 0, 0,
+ 0, 0, 0, 47, 0, 0, 0, 0, 213, 213,
+ 0, 213, 0, 0, 0, 0, 0, 0, 0, 48,
+ 190, 191, 192, 193, 194, 195, 0, 0, 0, 0,
+ 0, 0, 190, 191, 192, 193, 194, 195, 0, 0,
+ 0, 0, 213, 0, 47, 213, 0, 47, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 214, 0,
+ 48, 0, 47, 48, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 213, 0, 0, 0, 48, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 214, 0, 0, 0, 214, 47, 0, 214, 214,
+ 214, 214, 214, 214, 0, 214, 0, 0, 0, 0,
+ 0, 0, 48, 0, 0, 0, 0, 214, 214, 0,
+ 214, 0, 0, 0, 0, 0, 0, 0, 47, 0,
+ 203, 0, 0, 0, 0, 201, 199, 0, 200, 0,
+ 202, 0, 0, 217, 48, 0, 0, 0, 0, 0,
+ 0, 214, 0, 235, 214, 198, 218, 219, 220, 221,
+ 222, 223, 0, 224, 0, 203, 0, 0, 0, 0,
+ 201, 199, 196, 200, 0, 202, 0, 0, 0, 0,
+ 0, 0, 0, 214, 0, 0, 0, 204, 235, 0,
+ 198, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 213, 213, 213, 213,
+ 0, 0, 213, 213, 213, 213, 213, 213, 213, 213,
+ 213, 213, 204, 0, 0, 0, 0, 0, 0, 0,
+ 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
+ 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
+ 213, 0, 0, 213, 213, 213, 213, 213, 213, 213,
+ 213, 213, 213, 213, 213, 213, 213, 47, 0, 0,
+ 0, 0, 213, 213, 213, 213, 213, 213, 213, 213,
+ 213, 213, 213, 48, 0, 213, 213, 213, 213, 0,
+ 0, 213, 213, 47, 213, 0, 0, 213, 213, 213,
+ 213, 213, 213, 213, 213, 213, 213, 213, 0, 48,
+ 0, 213, 213, 213, 213, 214, 214, 214, 214, 0,
+ 0, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 0, 0, 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, 214,
+ 0, 0, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 0, 0, 0, 372,
+ 0, 214, 214, 214, 214, 214, 214, 214, 214, 214,
+ 214, 214, 215, 0, 214, 214, 214, 214, 0, 0,
+ 214, 214, 0, 214, 0, 0, 214, 214, 214, 214,
+ 214, 214, 214, 214, 214, 214, 214, 0, 0, 0,
+ 214, 214, 214, 214, 0, 215, 0, 0, 0, 215,
+ 0, 0, 215, 215, 215, 215, 215, 215, 0, 215,
+ 0, 190, 191, 192, 193, 194, 195, 0, 184, 0,
+ 0, 215, 215, 0, 215, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 203, 0, 0, 0, 0, 201,
+ 199, 0, 200, 0, 202, 0, 233, 234, 192, 193,
+ 194, 195, 0, 0, 0, 215, 0, 235, 215, 198,
+ 0, 0, 0, 257, 258, 259, 0, 0, 0, 0,
+ 0, 216, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 215, 285, 0,
+ 0, 204, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 216, 0, 0, 0, 216, 0,
+ 0, 216, 216, 216, 216, 216, 216, 0, 216, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 314,
+ 216, 216, 0, 216, 0, 0, 0, 322, 0, 0,
+ 203, 0, 0, 0, 0, 201, 199, 203, 200, 0,
+ 202, 0, 201, 199, 0, 200, 0, 202, 0, 0,
+ 0, 0, 0, 235, 216, 198, 0, 216, 0, 0,
+ 235, 0, 198, 0, 0, 0, 0, 0, 0, 0,
+ 203, 0, 0, 0, 0, 201, 199, 196, 200, 0,
+ 202, 0, 0, 0, 0, 0, 216, 204, 0, 0,
+ 0, 0, 0, 197, 204, 198, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 215,
+ 215, 215, 215, 0, 0, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 368, 0, 204, 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, 215, 0, 0, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 0, 0, 0, 0, 0, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 215, 215, 0, 0, 215, 215,
+ 215, 215, 390, 391, 215, 215, 0, 215, 0, 0,
+ 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+ 215, 0, 0, 0, 215, 215, 215, 215, 216, 216,
+ 216, 216, 0, 0, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 0, 233, 234, 192, 193, 194,
+ 195, 0, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 0, 0, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 216, 216, 216, 216, 0,
+ 0, 0, 404, 0, 216, 216, 216, 216, 216, 216,
+ 216, 216, 216, 216, 216, 211, 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, 0, 0, 216, 216, 216, 216, 0, 211, 0,
+ 0, 0, 0, 0, 188, 211, 211, 189, 211, 211,
+ 211, 190, 191, 192, 193, 194, 195, 0, 190, 191,
+ 192, 193, 194, 195, 211, 211, 0, 211, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 203, 0, 0,
+ 0, 0, 201, 199, 0, 200, 0, 202, 0, 0,
+ 0, 233, 234, 192, 193, 194, 195, 0, 211, 0,
+ 235, 211, 198, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 212, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 211, 0, 0, 0, 204, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 212, 0, 0,
+ 0, 0, 0, 0, 212, 212, 0, 212, 212, 212,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 212, 212, 0, 212, 0, 0, 0,
+ 203, 0, 0, 0, 0, 201, 199, 0, 200, 0,
+ 202, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 235, 0, 198, 0, 212, 0, 203,
+ 212, 0, 0, 0, 201, 199, 0, 200, 0, 202,
+ 0, 0, 0, 204, 0, 0, 0, 0, 204, 204,
+ 204, 204, 235, 204, 198, 0, 0, 204, 0, 212,
+ 0, 0, 0, 0, 0, 0, 204, 0, 204, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 211, 211, 211, 211, 204, 0, 211, 211,
+ 211, 211, 211, 211, 211, 211, 211, 211, 0, 0,
+ 204, 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, 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, 0,
+ 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, 264, 211, 211, 211,
+ 211, 212, 212, 212, 212, 0, 0, 212, 212, 212,
+ 212, 212, 212, 212, 212, 212, 212, 0, 190, 0,
+ 192, 193, 194, 195, 0, 212, 212, 212, 212, 212,
+ 212, 212, 212, 212, 212, 212, 212, 212, 212, 212,
+ 212, 212, 212, 212, 212, 212, 0, 0, 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, 232, 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, 0, 212, 212, 212, 212,
+ 0, 232, 0, 0, 0, 0, 0, 204, 232, 232,
+ 204, 233, 232, 192, 193, 194, 195, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 232, 232, 0,
+ 232, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 192, 193, 194, 195, 0, 0, 0, 0,
+ 0, 0, 0, 0, 204, 204, 204, 204, 204, 204,
+ 0, 232, 0, 0, 232, 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, 232, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 234, 52, 53, 0, 0, 0, 0, 234, 234, 0,
+ 0, 234, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 234, 234, 0, 234,
+ 0, 0, 0, 0, 0, 0, 0, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 234, 0, 0, 234, 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, 234, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 351, 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, 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, 213, 0, 0,
+ 232, 232, 232, 232, 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, 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, 233, 0, 234, 234, 234, 234, 0, 0, 234,
+ 234, 0, 234, 0, 0, 234, 234, 234, 234, 234,
+ 234, 234, 234, 234, 234, 234, 0, 0, 0, 234,
+ 234, 234, 234, 0, 233, 52, 53, 0, 0, 0,
+ 0, 233, 233, 0, 0, 233, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 233, 233, 0, 233, 0, 0, 0, 0, 0, 0,
+ 0, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 233, 0, 0, 233, 0, 0,
+ 77, 78, 79, 80, 0, 0, 0, 0, 0, 0,
+ 231, 0, 0, 0, 0, 0, 0, 0, 81, 82,
+ 83, 84, 85, 0, 0, 0, 233, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 231, 0, 0, 0, 0, 0, 0,
+ 231, 231, 0, 0, 231, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 231, 0, 0, 231, 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, 231, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 233, 233,
+ 233, 233, 0, 0, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 0, 0, 0, 0, 0, 0,
+ 0, 0, 233, 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,
+ 0, 0, 0, 0, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 233, 0, 0, 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, 231, 231, 231,
+ 231, 0, 0, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 231, 0, 0, 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, 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, 144, 0, 231, 231, 231, 231,
+ 0, 0, 231, 231, 0, 231, 0, 0, 231, 231,
+ 231, 231, 231, 231, 231, 231, 231, 231, 231, 0,
+ 0, 0, 231, 231, 231, 231, 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, 95, 0, 0, 0, 0,
+ 0, 95, 0, 0, 0, 0, 0, 144, 0, 0,
+ 144, 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, 144,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 236, 95, 0, 0,
+ 0, 0, 0, 236, 236, 0, 0, 236, 0, 0,
+ 0, 0, 95, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 236, 0, 0, 95, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 95, 95, 95, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 236, 0, 0, 236,
+ 0, 0, 0, 0, 0, 0, 0, 283, 0, 0,
+ 0, 0, 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, 0, 0, 0, 0, 95, 0,
+ 0, 144, 144, 144, 144, 0, 95, 144, 0, 144,
+ 144, 144, 144, 144, 144, 144, 144, 263, 0, 0,
+ 0, 0, 0, 264, 0, 144, 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, 0, 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, 95, 0, 144, 144, 144, 144,
+ 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, 236, 0, 0, 236, 236, 236,
+ 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
+ 236, 95, 95, 0, 0, 0, 236, 236, 236, 236,
+ 236, 236, 236, 236, 236, 236, 236, 235, 0, 236,
+ 236, 236, 236, 0, 0, 236, 236, 0, 236, 0,
+ 0, 236, 236, 236, 236, 0, 0, 236, 236, 236,
+ 236, 236, 0, 0, 0, 236, 236, 236, 236, 0,
+ 235, 0, 0, 0, 0, 0, 0, 235, 235, 0,
+ 0, 235, 0, 0, 260, 0, 0, 0, 0, 0,
+ 261, 0, 0, 0, 0, 262, 235, 0, 52, 53,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 14, 0, 0, 0, 0, 0, 0, 0, 0,
+ 235, 0, 0, 235, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 0, 145, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 235, 77, 78, 79, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 145,
+ 14, 81, 82, 83, 84, 85, 145, 145, 0, 145,
+ 145, 145, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 145, 0, 0, 145, 0,
+ 0, 0, 0, 0, 14, 0, 0, 189, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 145,
+ 0, 0, 145, 0, 0, 0, 14, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 145, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 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, 0, 0, 235, 235, 235, 235, 0, 189, 235,
+ 235, 0, 235, 0, 189, 235, 235, 235, 235, 189,
+ 0, 235, 235, 235, 235, 235, 0, 0, 0, 235,
+ 235, 235, 235, 145, 145, 145, 145, 0, 0, 145,
+ 0, 145, 145, 145, 145, 145, 145, 145, 145, 0,
+ 0, 0, 189, 0, 0, 0, 0, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 0, 0, 0,
+ 0, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
+ 237, 0, 145, 145, 145, 145, 0, 0, 145, 145,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 145, 145, 145, 145, 145, 0, 0, 0, 145, 145,
+ 145, 145, 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, 15, 0, 0, 0, 0, 0,
+ 0, 0, 0, 237, 0, 0, 237, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 238,
+ 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, 238, 15, 0, 0, 0, 0, 0, 238,
+ 238, 0, 0, 238, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 238, 0,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0,
+ 190, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 238, 0, 0, 238, 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, 238, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 237, 237, 237, 237,
+ 0, 190, 237, 237, 0, 237, 0, 190, 237, 237,
+ 0, 0, 190, 0, 237, 237, 237, 237, 237, 0,
+ 0, 0, 237, 237, 237, 237, 238, 238, 238, 238,
+ 0, 0, 238, 238, 238, 238, 238, 238, 238, 238,
+ 238, 238, 0, 0, 0, 190, 0, 0, 0, 0,
+ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+ 238, 0, 0, 238, 238, 238, 238, 238, 238, 238,
+ 238, 238, 238, 238, 238, 238, 238, 0, 0, 0,
+ 0, 0, 238, 238, 238, 238, 238, 238, 238, 238,
+ 238, 238, 238, 131, 0, 238, 238, 238, 238, 0,
+ 0, 238, 238, 0, 238, 0, 0, 0, 238, 0,
+ 0, 0, 0, 238, 238, 238, 238, 238, 0, 0,
+ 0, 238, 238, 238, 238, 0, 131, 0, 0, 0,
+ 0, 0, 0, 131, 131, 0, 131, 131, 131, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 131, 0, 0, 131, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 131, 0, 0, 131,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 136, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 131, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 136, 0, 0, 0, 0,
+ 0, 0, 136, 136, 0, 0, 136, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 136, 0, 0, 136, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 136, 0, 0, 136, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 136, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 131, 131, 131, 131, 0, 0, 131, 0, 131, 131,
+ 131, 131, 131, 131, 131, 131, 0, 0, 0, 0,
+ 0, 0, 0, 0, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 131, 131, 131, 0, 0, 0, 0, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 131, 131, 131,
+ 131, 0, 0, 0, 0, 0, 131, 131, 131, 131,
+ 131, 131, 131, 131, 131, 131, 131, 0, 0, 131,
+ 131, 131, 131, 0, 0, 131, 131, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 131, 131, 131,
+ 131, 131, 0, 0, 0, 131, 131, 131, 131, 136,
+ 136, 136, 136, 0, 0, 136, 0, 136, 136, 136,
+ 136, 136, 136, 136, 136, 0, 0, 0, 0, 0,
+ 0, 0, 0, 136, 136, 136, 136, 136, 136, 136,
+ 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
+ 136, 136, 136, 0, 0, 0, 0, 136, 136, 136,
+ 136, 136, 136, 136, 136, 136, 136, 136, 136, 136,
+ 0, 0, 0, 0, 0, 136, 136, 136, 136, 136,
+ 136, 136, 136, 136, 136, 136, 140, 0, 136, 136,
+ 136, 136, 0, 0, 136, 136, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 136, 136, 136, 136,
+ 136, 0, 0, 0, 136, 136, 136, 136, 0, 140,
+ 0, 0, 0, 0, 0, 0, 140, 140, 0, 0,
+ 140, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 140, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 140,
+ 0, 0, 140, 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, 140, 0, 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, 140, 140, 140, 140, 0, 0, 140,
+ 0, 140, 140, 140, 140, 140, 140, 140, 140, 0,
+ 0, 0, 0, 0, 0, 0, 0, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 140, 0, 0, 0,
+ 0, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 0, 0, 0, 0, 0, 140,
+ 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
+ 0, 0, 140, 140, 140, 140, 0, 0, 140, 140,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 140, 140, 140, 140, 140, 0, 0, 0, 140, 140,
+ 140, 140, 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, 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, 0, 92, 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, 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, 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, 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, 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, 0, 94, 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, 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, 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, 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, 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, 0, 85, 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, 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, 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, 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, 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, 0, 87, 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, 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, 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, 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, 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, 0, 98, 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, 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, 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, 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, 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, 0, 105, 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, 0, 105, 0,
+ 0, 0, 0, 0, 0, 105, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 105, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 105, 0,
+ 0, 105, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 105, 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, 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, 105, 105, 105, 105, 0, 0, 105, 0,
+ 105, 105, 105, 105, 105, 105, 105, 105, 0, 0,
+ 0, 0, 0, 0, 0, 0, 105, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 107, 0, 0, 0,
+ 0, 105, 105, 105, 105, 105, 105, 105, 105, 105,
+ 105, 105, 105, 0, 0, 0, 0, 0, 105, 105,
+ 105, 105, 105, 105, 105, 105, 105, 105, 105, 107,
+ 0, 105, 105, 105, 105, 0, 107, 105, 105, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 105,
+ 105, 105, 105, 105, 0, 107, 0, 105, 105, 105,
+ 105, 0, 0, 0, 0, 0, 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, 107, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 111, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 107, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 111, 0,
+ 0, 0, 0, 0, 0, 111, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 111, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 111, 0,
+ 0, 111, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 111, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 107, 107, 107, 107, 0, 0, 107,
+ 0, 107, 107, 107, 107, 107, 107, 107, 107, 0,
+ 0, 0, 0, 0, 0, 0, 0, 107, 107, 107,
+ 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
+ 107, 107, 107, 107, 107, 107, 107, 0, 0, 0,
+ 0, 0, 107, 107, 107, 107, 107, 107, 107, 107,
+ 107, 107, 107, 107, 0, 0, 0, 0, 0, 107,
+ 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
+ 0, 0, 107, 107, 107, 107, 0, 0, 107, 107,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 107, 107, 107, 107, 107, 0, 0, 0, 107, 107,
+ 107, 107, 111, 111, 111, 111, 0, 0, 111, 0,
+ 111, 111, 111, 111, 111, 111, 111, 111, 0, 0,
+ 0, 0, 0, 0, 0, 0, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 111, 111, 111, 124, 0, 0, 0,
+ 0, 111, 111, 111, 111, 111, 111, 111, 111, 111,
+ 111, 111, 111, 0, 0, 0, 0, 0, 111, 111,
+ 111, 111, 111, 111, 111, 111, 111, 111, 111, 124,
+ 0, 111, 111, 111, 111, 0, 124, 111, 111, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 111,
+ 111, 111, 111, 111, 0, 124, 0, 111, 111, 111,
+ 111, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 124,
+ 0, 0, 124, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 109, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 124, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 109, 0,
+ 0, 0, 0, 0, 0, 109, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 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, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 109, 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, 0, 0, 0, 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, 124, 124, 124, 124, 0, 0, 124,
+ 0, 124, 124, 124, 124, 124, 124, 124, 124, 0,
+ 0, 0, 0, 0, 0, 0, 0, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 124, 124, 124, 0, 0, 0,
+ 0, 0, 124, 124, 124, 124, 124, 124, 124, 124,
+ 124, 124, 124, 124, 0, 0, 0, 0, 0, 124,
+ 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
+ 0, 0, 124, 124, 124, 124, 0, 0, 124, 124,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 124, 124, 124, 124, 124, 0, 0, 0, 124, 124,
+ 124, 124, 109, 109, 109, 109, 0, 0, 109, 0,
+ 109, 109, 109, 109, 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, 109, 0, 0, 0, 0,
+ 0, 109, 109, 109, 109, 109, 109, 109, 109, 109,
+ 109, 109, 109, 0, 0, 0, 0, 0, 109, 109,
+ 109, 109, 109, 109, 109, 109, 109, 109, 109, 142,
+ 0, 109, 109, 109, 109, 0, 0, 109, 109, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 109,
+ 109, 109, 109, 109, 0, 0, 0, 109, 109, 109,
+ 109, 0, 142, 0, 0, 0, 0, 0, 0, 142,
+ 142, 0, 142, 142, 142, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 142, 0,
+ 0, 142, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 168, 0, 0, 0,
+ 0, 0, 142, 0, 0, 142, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 168,
+ 0, 0, 0, 0, 142, 0, 168, 168, 0, 0,
+ 168, 168, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 168, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 168,
+ 0, 0, 168, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 168, 0, 40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 40, 0, 0, 0,
+ 0, 0, 0, 40, 0, 0, 142, 142, 142, 142,
+ 0, 0, 142, 0, 142, 142, 142, 142, 142, 142,
+ 142, 142, 40, 0, 0, 0, 0, 0, 0, 0,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 0, 0, 0, 0, 142, 142, 40, 0, 0, 40,
+ 0, 0, 0, 0, 0, 0, 0, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 0, 0, 0, 0, 0, 40, 0,
+ 0, 142, 142, 168, 168, 168, 168, 0, 0, 168,
+ 0, 168, 168, 168, 168, 168, 168, 0, 0, 0,
+ 0, 142, 142, 142, 142, 0, 0, 168, 168, 168,
+ 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+ 168, 168, 168, 168, 168, 168, 168, 0, 0, 0,
+ 0, 0, 168, 231, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 168,
+ 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+ 0, 0, 0, 0, 0, 0, 231, 0, 168, 168,
+ 0, 0, 0, 231, 231, 0, 0, 231, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 168, 168,
+ 168, 168, 231, 231, 0, 231, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 40, 40, 40, 40, 0, 0, 40, 0, 0, 0,
+ 0, 40, 0, 0, 40, 40, 231, 0, 0, 231,
+ 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, 0, 231, 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, 42, 0, 40,
+ 40, 40, 40, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 40, 40, 40,
+ 40, 40, 0, 42, 0, 0, 0, 0, 40, 0,
+ 0, 0, 0, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 95, 0, 0, 0, 0, 42,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 231, 231, 231, 231, 0, 0, 231, 0, 0, 0,
+ 0, 231, 0, 0, 231, 231, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 95, 0, 0, 0, 0, 0, 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, 95, 0, 231,
+ 231, 231, 231, 0, 0, 0, 0, 0, 0, 0,
+ 93, 231, 231, 231, 231, 231, 231, 231, 231, 231,
+ 231, 231, 0, 0, 0, 0, 0, 0, 231, 95,
+ 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, 0, 0, 0, 0, 0, 0, 0, 0, 93,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 0, 93, 0, 0, 0, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 89, 0,
+ 42, 42, 42, 42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 93, 0, 0, 42, 42,
+ 42, 42, 42, 0, 0, 0, 0, 0, 0, 42,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 91,
+ 0, 0, 0, 0, 95, 0, 0, 0, 0, 95,
+ 95, 95, 0, 95, 95, 95, 95, 89, 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, 95, 189, 0, 0, 0, 0,
+ 0, 89, 0, 0, 0, 0, 0, 0, 91, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 89, 0, 0, 95, 95, 0, 0,
+ 0, 0, 91, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 95, 95, 95, 95,
+ 93, 104, 0, 0, 0, 93, 93, 93, 0, 93,
+ 93, 93, 93, 0, 91, 0, 0, 0, 0, 0,
+ 0, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 190, 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, 93, 93, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 104, 0, 0, 0, 0, 0,
+ 0, 0, 93, 93, 93, 93, 0, 0, 89, 106,
+ 0, 0, 0, 89, 89, 89, 0, 89, 89, 89,
+ 89, 0, 0, 0, 0, 0, 104, 0, 0, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89, 89, 91,
+ 110, 0, 0, 0, 91, 91, 91, 0, 91, 91,
+ 91, 91, 0, 0, 0, 0, 0, 0, 106, 0,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 89, 89, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 106, 0, 0, 0, 0, 0, 0, 110,
+ 89, 89, 89, 89, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 91, 91, 0, 106, 0, 0, 0, 0, 0,
+ 0, 0, 0, 110, 0, 0, 0, 0, 0, 0,
+ 0, 91, 91, 91, 91, 0, 0, 108, 0, 147,
+ 0, 104, 0, 0, 0, 0, 104, 104, 104, 0,
+ 104, 104, 104, 104, 0, 110, 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, 104, 147, 0, 147, 147, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 108, 0, 147, 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, 104, 0, 0, 0, 0, 0,
+ 108, 0, 147, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 104, 104, 104, 104, 0, 0, 106,
+ 0, 0, 0, 0, 106, 106, 106, 0, 106, 106,
+ 106, 106, 108, 0, 147, 0, 0, 0, 0, 0,
+ 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
+ 106, 106, 106, 106, 106, 106, 106, 106, 106, 106,
+ 110, 0, 0, 0, 0, 110, 110, 110, 0, 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,
+ 110, 106, 106, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 80, 0, 0, 0,
+ 0, 106, 106, 106, 106, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 110, 110, 0, 0, 0, 0, 0, 80,
+ 0, 0, 0, 0, 0, 0, 80, 0, 0, 0,
+ 0, 0, 110, 110, 110, 110, 0, 108, 0, 0,
+ 0, 0, 108, 108, 108, 80, 108, 108, 108, 108,
+ 147, 147, 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, 108, 0, 80,
+ 0, 0, 80, 0, 0, 0, 147, 147, 147, 147,
+ 147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
+ 147, 147, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 80, 0, 0, 0, 147, 147, 147, 147, 108,
+ 108, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 89, 0, 147, 147, 147, 147, 147, 86, 108,
+ 108, 108, 108, 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, 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, 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, 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, 6, 0, 80, 80,
+ 0, 0, 0, 6, 0, 0, 0, 0, 6, 0,
+ 80, 80, 80, 80, 80, 0, 0, 0, 80, 80,
+ 80, 0, 0, 0, 0, 278, 279, 49, 8, 9,
+ 0, 50, 0, 0, 0, 0, 51, 10, 11, 280,
+ 281, 14, 15, 16, 17, 18, 19, 20, 21, 0,
+ 0, 0, 0, 0, 6, 0, 0, 0, 0, 6,
+ 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, 6, 0, 0, 0,
+ 0, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 22, 0, 77, 78, 79, 80, 23, 24,
+ 0, 0, 25, 0, 26, 0, 0, 0, 0, 0,
+ 0, 0, 81, 82, 83, 84, 85, 27, 89, 28,
+ 0, 0, 0, 29, 30, 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,
+ 6, 6, 6, 6, 6, 0, 6, 0, 0, 0,
+ 0, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 0, 105, 0, 0, 0, 0,
+ 0, 0, 104, 298, 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,
+ 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,
+ 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, 146, 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, 89,
+ 0, 77, 78, 79, 80, 0, 86, 147, 148, 0,
+ 0, 88, 0, 0, 0, 0, 0, 0, 0, 81,
+ 82, 83, 84, 85, 0, 0, 0, 149, 150, 151,
+ 29, 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, 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, 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, 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, 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,
+ 47, 48, 49, 8, 0, 0, 50, 0, 0, 0,
+ 0, 51, 0, 0, 52, 53, 0, 0, 0, 0,
+ 105, 0, 0, 0, 0, 0, 0, 269, 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, 89, 0, 47, 48, 49,
+ 8, 0, 104, 50, 407, 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, 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, 89,
+ 0, 0, 0, 0, 0, 29, 104, 0, 0, 0,
+ 0, 88, 0, 0, 47, 48, 49, 8, 0, 0,
+ 50, 0, 0, 0, 0, 51, 0, 0, 52, 53,
+ 0, 0, 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, 87, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 0, 32, 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, 31, 0,
+ 0, 81, 82, 83, 84, 85, 0, 89, 0, 47,
+ 48, 49, 29, 0, 86, 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, 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, 89, 0, 47, 48, 49, 0, 0, 269, 50,
+ 0, 0, 0, 88, 51, 0, 0, 52, 53, 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, 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, 89, 0, 0, 0,
+ 0, 0, 0, 104, 0, 0, 0, 0, 88, 22,
+ 81, 82, 83, 84, 85, 23, 24, 0, 0, 25,
+ 0, 26, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 47, 48, 49, 27, 0, 28, 50, 0, 0,
+ 29, 30, 51, 0, 0, 52, 53, 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,
+ 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,
+ 0, 0, 0, 0, 0, 0, 0, 0, 81, 82,
+ 83, 84, 85, 0, 0, 47, 48, 49, 0, 0,
+ 0, 50, 0, 0, 32, 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, 31, 0, 0, 0,
+ 6, 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, 6, 0, 77, 78, 79, 80, 0, 0,
+ 47, 48, 49, 0, 0, 0, 50, 0, 0, 0,
+ 0, 51, 81, 82, 83, 84, 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, 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, 0,
+ 6, 7, 0, 8, 9, 0, 0, 81, 82, 83,
+ 84, 85, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 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, 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, 0, 0, 0, 29, 30,
+ 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, 0, 45, 28, 119, 30, 94, 44, 37, 260,
+ 58, 36, 4, 42, 43, 105, 45, 37, 47, 43,
+ 44, 45, 42, 43, 99, 45, 0, 47, 0, 260,
+ 0, 60, 24, 62, 96, 0, 35, 0, 30, 258,
+ 37, 156, 41, 101, 36, 42, 43, 96, 45, 43,
+ 47, 45, 58, 348, 349, 61, 114, 271, 272, 41,
+ 258, 86, 44, 88, 89, 94, 96, 86, 62, 41,
+ 350, 351, 44, 41, 94, 43, 101, 45, 41, 41,
+ 105, 44, 44, 59, 335, 134, 43, 59, 45, 114,
+ 43, 44, 45, 0, 59, 0, 59, 94, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 101,
+ 135, 115, 116, 138, 139, 140, 135, 59, 206, 93,
+ 112, 93, 114, 93, 149, 150, 33, 119, 93, 40,
+ 93, 156, 347, 40, 365, 61, 41, 262, 45, 44,
+ 354, 355, 335, 233, 234, 40, 40, 237, 238, 40,
+ 40, 125, 40, 125, 59, 125, 43, 44, 45, 40,
+ 125, 40, 125, 40, 156, 190, 191, 192, 193, 194,
+ 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 205, 0, 40, 0, 91, 40, 261, 262, 93, 96,
+ 215, 216, 40, 61, 37, 257, 215, 216, 290, 42,
+ 43, 263, 45, 0, 47, 230, 268, 260, 233, 234,
+ 235, 260, 237, 238, 263, 262, 123, 60, 267, 62,
+ 125, 258, 41, 0, 258, 44, 43, 257, 45, 271,
+ 272, 260, 0, 263, 41, 41, 37, 264, 268, 301,
+ 59, 42, 59, 94, 269, 302, 47, 239, 240, 257,
+ 269, 94, 244, 318, 319, 320, 321, 322, 46, 93,
+ 37, 376, 305, 125, 41, 42, 43, 44, 45, 93,
+ 47, 346, 262, 257, 93, 43, 93, 45, 303, 262,
+ 41, 301, 59, 60, 304, 62, 41, 44, 41, 41,
+ 41, 59, 264, 94, 91, 44, 44, 41, 347, 348,
+ 41, 264, 41, 303, 348, 257, 125, 262, 125, 44,
+ 360, 304, 354, 355, 260, 41, 93, 41, 290, 348,
+ 349, 350, 351, 352, 353, 93, 123, 290, 377, 301,
+ 41, 380, 304, 41, 345, 262, 365, 0, 301, 41,
+ 345, 304, 345, 345, 156, 370, 371, 372, 125, 374,
+ 257, 258, 259, 260, 261, 30, 263, 125, 35, 264,
+ 382, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, -1, -1, 348, 349, -1, 404,
+ -1, -1, 407, -1, 376, 290, 349, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 0, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, 0, -1, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 334, -1, 336,
+ 337, 338, 339, 340, 341, -1, -1, 344, -1, 346,
+ -1, -1, 0, 348, 349, 264, 91, 354, 355, 356,
+ 357, 358, 359, 0, 361, 0, -1, 59, 365, 366,
+ 257, 258, -1, 260, 261, -1, 0, 0, -1, -1,
+ 59, 290, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, -1, -1, 0, 264, 33, -1,
+ -1, 93, 37, -1, 0, 40, 41, 42, 43, 44,
+ 45, 59, 47, -1, 93, 26, -1, -1, 41, 352,
+ 353, 44, 59, 290, 59, 60, -1, 62, -1, -1,
+ -1, 42, 91, 125, 301, 59, 59, 304, -1, 0,
+ 349, -1, -1, -1, -1, 93, 125, 334, -1, -1,
+ -1, -1, -1, 340, 341, 59, 93, 344, 93, 346,
+ -1, 96, -1, 59, -1, -1, -1, -1, -1, 93,
+ 93, -1, 359, -1, 361, 0, 87, 125, 365, 366,
+ -1, 348, 349, 350, 351, 352, 353, 0, 125, 93,
+ 125, -1, -1, -1, -1, -1, -1, 93, 59, -1,
+ -1, 125, 125, -1, -1, -1, -1, -1, 33, -1,
+ -1, -1, 37, -1, -1, 40, 41, 42, 43, 44,
+ 45, 125, 47, 260, -1, 260, 263, -1, 41, 125,
+ -1, 44, 93, 268, 59, 60, -1, 62, 273, 274,
+ 275, 276, 277, 278, -1, 280, 59, 158, -1, -1,
+ -1, 162, 163, 164, 165, 166, 167, 168, 169, 170,
+ 171, 172, -1, -1, 125, -1, -1, -1, 93, 37,
+ -1, 96, -1, -1, 42, 43, 44, 45, -1, 47,
+ 93, 37, -1, -1, -1, -1, 42, 43, 44, 45,
+ -1, 47, 60, -1, 62, -1, -1, -1, -1, -1,
+ 125, 260, -1, -1, 60, -1, 62, -1, -1, 268,
+ 347, 348, 125, -1, 273, 274, 275, 276, 277, 278,
+ -1, 280, 257, 258, 259, 260, 94, -1, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 94, -1,
+ 377, 264, -1, 380, -1, -1, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 290, -1, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, -1,
+ -1, 336, 337, 338, 339, -1, -1, 342, 343, -1,
+ 345, -1, -1, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, -1, -1, 349, 362, 363, 364,
+ 365, -1, 257, 258, 259, 260, -1, -1, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 359, -1,
+ -1, 264, 363, 364, -1, -1, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 290, -1, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 0,
+ -1, 336, 337, 338, 339, -1, -1, 342, 343, -1,
+ 345, -1, -1, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, 91, -1, 349, 362, 363, 364,
+ 365, -1, 33, -1, -1, 301, 37, -1, 304, 40,
+ 41, 42, 43, 44, 45, -1, 47, -1, -1, -1,
+ -1, -1, -1, 0, -1, -1, -1, -1, 59, 60,
+ -1, 62, -1, -1, -1, -1, -1, -1, -1, 0,
+ 348, 349, 350, 351, 352, 353, -1, -1, -1, -1,
+ -1, -1, 348, 349, 350, 351, 352, 353, -1, -1,
+ -1, -1, 93, -1, 41, 96, -1, 44, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 0, -1,
+ 41, -1, 59, 44, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 125, -1, -1, -1, 59, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 33, -1, -1, -1, 37, 93, -1, 40, 41,
+ 42, 43, 44, 45, -1, 47, -1, -1, -1, -1,
+ -1, -1, 93, -1, -1, -1, -1, 59, 60, -1,
+ 62, -1, -1, -1, -1, -1, -1, -1, 125, -1,
+ 37, -1, -1, -1, -1, 42, 43, -1, 45, -1,
+ 47, -1, -1, 260, 125, -1, -1, -1, -1, -1,
+ -1, 93, -1, 60, 96, 62, 273, 274, 275, 276,
+ 277, 278, -1, 280, -1, 37, -1, -1, -1, -1,
+ 42, 43, 44, 45, -1, 47, -1, -1, -1, -1,
+ -1, -1, -1, 125, -1, -1, -1, 94, 60, -1,
+ 62, -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, 94, -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,
+ 301, -1, -1, 304, 305, 306, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, 317, 264, -1, -1,
+ -1, -1, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 333, 264, -1, 336, 337, 338, 339, -1,
+ -1, 342, 343, 290, 345, -1, -1, 348, 349, 350,
+ 351, 352, 353, 354, 355, 356, 357, 358, -1, 290,
+ -1, 362, 363, 364, 365, 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, 301,
+ -1, -1, 304, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, -1, -1, -1, 286,
+ -1, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, 0, -1, 336, 337, 338, 339, -1, -1,
+ 342, 343, -1, 345, -1, -1, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, -1, -1, -1,
+ 362, 363, 364, 365, -1, 33, -1, -1, -1, 37,
+ -1, -1, 40, 41, 42, 43, 44, 45, -1, 47,
+ -1, 348, 349, 350, 351, 352, 353, -1, 86, -1,
+ -1, 59, 60, -1, 62, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 37, -1, -1, -1, -1, 42,
+ 43, -1, 45, -1, 47, -1, 348, 349, 350, 351,
+ 352, 353, -1, -1, -1, 93, -1, 60, 96, 62,
+ -1, -1, -1, 131, 132, 133, -1, -1, -1, -1,
+ -1, 0, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 125, 156, -1,
+ -1, 94, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 33, -1, -1, -1, 37, -1,
+ -1, 40, 41, 42, 43, 44, 45, -1, 47, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 197,
+ 59, 60, -1, 62, -1, -1, -1, 205, -1, -1,
+ 37, -1, -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, -1, -1,
+ 60, -1, 62, -1, -1, -1, -1, -1, -1, -1,
+ 37, -1, -1, -1, -1, 42, 43, 44, 45, -1,
+ 47, -1, -1, -1, -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, 257,
+ 258, 259, 260, -1, -1, 263, 264, 265, 266, 267,
+ 268, 269, 270, 271, 272, 303, -1, 94, -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, 301, -1, -1, 304, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, 317,
+ -1, -1, -1, -1, -1, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 333, -1, -1, 336, 337,
+ 338, 339, 370, 371, 342, 343, -1, 345, -1, -1,
+ 348, 349, 350, 351, 352, 353, 354, 355, 356, 357,
+ 358, -1, -1, -1, 362, 363, 364, 365, 257, 258,
+ 259, 260, -1, -1, 263, 264, 265, 266, 267, 268,
+ 269, 270, 271, 272, -1, 348, 349, 350, 351, 352,
+ 353, -1, 281, 282, 283, 284, 285, 286, 287, 288,
+ 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+ 299, 300, 301, -1, -1, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, 317, -1,
+ -1, -1, 289, -1, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, 333, 0, -1, 336, 337, 338,
+ 339, -1, -1, 342, 343, -1, 345, -1, -1, 348,
+ 349, 350, 351, 352, 353, 354, 355, 356, 357, 358,
+ -1, -1, -1, 362, 363, 364, 365, -1, 33, -1,
+ -1, -1, -1, -1, 301, 40, 41, 304, 43, 44,
+ 45, 348, 349, 350, 351, 352, 353, -1, 348, 349,
+ 350, 351, 352, 353, 59, 60, -1, 62, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 37, -1, -1,
+ -1, -1, 42, 43, -1, 45, -1, 47, -1, -1,
+ -1, 348, 349, 350, 351, 352, 353, -1, 93, -1,
+ 60, 96, 62, -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,
+ 125, -1, -1, -1, 94, -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, 60, -1, 62, -1, -1, -1,
+ 37, -1, -1, -1, -1, 42, 43, -1, 45, -1,
+ 47, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 60, -1, 62, -1, 93, -1, 37,
+ 96, -1, -1, -1, 42, 43, -1, 45, -1, 47,
+ -1, -1, -1, 37, -1, -1, -1, -1, 42, 43,
+ 44, 45, 60, 47, 62, -1, -1, 94, -1, 125,
+ -1, -1, -1, -1, -1, -1, 60, -1, 62, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 257, 258, 259, 260, 94, -1, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, -1, -1,
+ 94, -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, 301, -1, -1, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, -1,
+ -1, 336, 337, 338, 339, -1, -1, 342, 343, -1,
+ 345, -1, -1, 348, 349, 350, 351, 352, 353, 354,
+ 355, 356, 357, 358, -1, -1, 46, 362, 363, 364,
+ 365, 257, 258, 259, 260, -1, -1, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, -1, 348, -1,
+ 350, 351, 352, 353, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, 300, 301, -1, -1, 304, 305,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, 317, -1, -1, -1, -1, -1, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, 333, 0, -1,
+ 336, 337, 338, 339, -1, -1, 342, 343, -1, 345,
+ -1, -1, 348, 349, 350, 351, 352, 353, 354, 355,
+ 356, 357, 358, -1, -1, -1, 362, 363, 364, 365,
+ -1, 33, -1, -1, -1, -1, -1, 301, 40, 41,
+ 304, 348, 44, 350, 351, 352, 353, -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, 350, 351, 352, 353, -1, -1, -1, -1,
+ -1, -1, -1, -1, 348, 349, 350, 351, 352, 353,
+ -1, 93, -1, -1, 96, -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, -1, -1, 125, -1, -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,
+ -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, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, 317, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 93, -1, -1, 96, -1, -1, 336, 337, 338, 339,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 354, 355, 356, 357, 358, -1,
+ -1, -1, 125, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 46, -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, 301,
+ -1, -1, 304, 305, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, -1, -1, -1, -1,
+ -1, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, -1, -1, 336, 337, 338, 339, -1, -1,
+ 342, 343, -1, 345, -1, -1, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, 46, -1, -1,
+ 362, 363, 364, 365, 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, 301, -1,
+ -1, 304, 305, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 317, -1, -1, -1, -1, -1,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ 333, 0, -1, 336, 337, 338, 339, -1, -1, 342,
+ 343, -1, 345, -1, -1, 348, 349, 350, 351, 352,
+ 353, 354, 355, 356, 357, 358, -1, -1, -1, 362,
+ 363, 364, 365, -1, 33, 271, 272, -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, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, 317, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 93, -1, -1, 96, -1, -1,
+ 336, 337, 338, 339, -1, -1, -1, -1, -1, -1,
+ 0, -1, -1, -1, -1, -1, -1, -1, 354, 355,
+ 356, 357, 358, -1, -1, -1, 125, -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,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 59,
+ 60, -1, 62, -1, -1, -1, -1, -1, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, 317, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 93, -1, -1, 96, 336, 337, 338,
+ 339, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 354, 355, 356, 357, 358,
+ -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, 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, 301, -1, -1, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, 317, -1,
+ -1, -1, -1, -1, 323, 324, 325, 326, 327, 328,
+ 329, 330, 331, 332, 333, -1, -1, 336, 337, 338,
+ 339, -1, -1, 342, 343, -1, 345, -1, -1, 348,
+ 349, 350, 351, 352, 353, 354, 355, 356, 357, 358,
+ -1, -1, -1, 362, 363, 364, 365, 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, 301, -1, -1, 304, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, 317, -1, -1,
+ -1, -1, -1, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 333, 0, -1, 336, 337, 338, 339,
+ -1, -1, 342, 343, -1, 345, -1, -1, 348, 349,
+ 350, 351, 352, 353, 354, 355, 356, 357, 358, -1,
+ -1, -1, 362, 363, 364, 365, -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, 24, -1, -1, -1, -1,
+ -1, 30, -1, -1, -1, -1, -1, 93, -1, -1,
+ 96, -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, -1, -1, 125,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 33, 86, -1, -1,
+ -1, -1, -1, 40, 41, -1, -1, 44, -1, -1,
+ -1, -1, 101, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 59, -1, -1, 114, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 131, 132, 133, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 93, -1, -1, 96,
+ -1, -1, -1, -1, -1, -1, -1, 156, -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, 197, -1,
+ -1, 257, 258, 259, 260, -1, 205, 263, -1, 265,
+ 266, 267, 268, 269, 270, 271, 272, 40, -1, -1,
+ -1, -1, -1, 46, -1, 281, 282, 283, 284, 285,
+ 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
+ 296, 297, 298, 299, 300, -1, -1, -1, -1, 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, 333, -1, -1,
+ 336, 337, 338, 339, -1, -1, 342, 343, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 354, 355,
+ 356, 357, 358, -1, 303, -1, 362, 363, 364, 365,
+ 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, 301, -1, -1, 304, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, 370, 371, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 0, -1, 336,
+ 337, 338, 339, -1, -1, 342, 343, -1, 345, -1,
+ -1, 348, 349, 350, 351, -1, -1, 354, 355, 356,
+ 357, 358, -1, -1, -1, 362, 363, 364, 365, -1,
+ 33, -1, -1, -1, -1, -1, -1, 40, 41, -1,
+ -1, 44, -1, -1, 257, -1, -1, -1, -1, -1,
+ 263, -1, -1, -1, -1, 268, 59, -1, 271, 272,
+ -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, -1,
+ 93, -1, -1, 96, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 317, -1, 0, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 125, 336, 337, 338, 339, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 33,
+ 59, 354, 355, 356, 357, 358, 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, 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, 93,
+ -1, -1, 96, -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, 125, -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, 301, -1,
+ -1, 304, 305, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 317, -1, -1, -1, -1, -1,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ 333, -1, -1, 336, 337, 338, 339, -1, 257, 342,
+ 343, -1, 345, -1, 263, 348, 349, 350, 351, 268,
+ -1, 354, 355, 356, 357, 358, -1, -1, -1, 362,
+ 363, 364, 365, 257, 258, 259, 260, -1, -1, 263,
+ -1, 265, 266, 267, 268, 269, 270, 271, 272, -1,
+ -1, -1, 301, -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, -1,
+ -1, 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, 333,
+ 0, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 364, 365, -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, 0, -1, -1, -1, -1, -1,
+ -1, -1, -1, 93, -1, -1, 96, -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, -1, -1, 125, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 33, 59, -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, 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, 93, -1, -1, 96, -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, 125, -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, 301, -1, -1, 304, 305, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, 317, -1, -1,
+ -1, -1, -1, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 333, -1, -1, 336, 337, 338, 339,
+ -1, 257, 342, 343, -1, 345, -1, 263, 348, 349,
+ -1, -1, 268, -1, 354, 355, 356, 357, 358, -1,
+ -1, -1, 362, 363, 364, 365, 257, 258, 259, 260,
+ -1, -1, 263, 264, 265, 266, 267, 268, 269, 270,
+ 271, 272, -1, -1, -1, 301, -1, -1, -1, -1,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, 300,
+ 301, -1, -1, 304, 305, 306, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, 317, -1, -1, -1,
+ -1, -1, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 333, 0, -1, 336, 337, 338, 339, -1,
+ -1, 342, 343, -1, 345, -1, -1, -1, 349, -1,
+ -1, -1, -1, 354, 355, 356, 357, 358, -1, -1,
+ -1, 362, 363, 364, 365, -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, 0, -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, 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,
+ 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, 300, -1, -1, -1, -1, 305, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, -1, -1, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, -1, -1, 336,
+ 337, 338, 339, -1, -1, 342, 343, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 354, 355, 356,
+ 357, 358, -1, -1, -1, 362, 363, 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, 300, -1, -1, -1, -1, 305, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, 317,
+ -1, -1, -1, -1, -1, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 333, 0, -1, 336, 337,
+ 338, 339, -1, -1, 342, 343, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 354, 355, 356, 357,
+ 358, -1, -1, -1, 362, 363, 364, 365, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, 0, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, 59, -1, 362, 363, 364,
+ 365, -1, -1, -1, -1, -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, 0, -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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, -1, -1, 342, 343,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 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, 300, -1, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 0,
+ -1, 336, 337, 338, 339, -1, -1, 342, 343, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, -1, -1, 362, 363, 364,
+ 365, -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, 0, -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, 33,
+ -1, -1, -1, -1, 125, -1, 40, 41, -1, -1,
+ 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, -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, 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, -1, -1, 257, 258, 259, 260,
+ -1, -1, 263, -1, 265, 266, 267, 268, 269, 270,
+ 271, 272, 59, -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, -1, -1, 305, 306, 93, -1, -1, 96,
+ -1, -1, -1, -1, -1, -1, -1, 318, 319, 320,
+ 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+ 331, 332, 333, -1, -1, -1, -1, -1, 125, -1,
+ -1, 342, 343, 257, 258, 259, 260, -1, -1, 263,
+ -1, 265, 266, 267, 268, 269, 270, -1, -1, -1,
+ -1, 362, 363, 364, 365, -1, -1, 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, 306, 0, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, -1, -1, -1, -1, 33, -1, 342, 343,
+ -1, -1, -1, 40, 41, -1, -1, 44, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 362, 363,
+ 364, 365, 59, 60, -1, 62, -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, 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, 0, -1, -1, -1, 125, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, -1, -1, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 33, -1, 336,
+ 337, 338, 339, -1, 40, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 354, 355, 356,
+ 357, 358, -1, 59, -1, -1, -1, -1, 365, -1,
+ -1, -1, -1, -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, 0, -1, -1, -1, -1, 125,
+ -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,
+ -1, -1, -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, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, -1, -1, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 93, -1, 336,
+ 337, 338, 339, -1, -1, -1, -1, -1, -1, -1,
+ 0, 348, 349, 350, 351, 352, 353, 354, 355, 356,
+ 357, 358, -1, -1, -1, -1, -1, -1, 365, 125,
+ -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, -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,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, 317, -1, 93, -1, -1, -1, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, 333, 0, -1,
+ 336, 337, 338, 339, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 125, -1, -1, 354, 355,
+ 356, 357, 358, -1, -1, -1, -1, -1, -1, 365,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
+ -1, -1, -1, -1, 260, -1, -1, -1, -1, 265,
+ 266, 267, -1, 269, 270, 271, 272, 59, -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, 301, -1, -1, -1, -1,
+ -1, 93, -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, 125, -1, -1, 342, 343, -1, -1,
+ -1, -1, 93, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 362, 363, 364, 365,
+ 260, 0, -1, -1, -1, 265, 266, 267, -1, 269,
+ 270, 271, 272, -1, 125, -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, 301, -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, 342, 343, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 93, -1, -1, -1, -1, -1,
+ -1, -1, 362, 363, 364, 365, -1, -1, 260, 0,
+ -1, -1, -1, 265, 266, 267, -1, 269, 270, 271,
+ 272, -1, -1, -1, -1, -1, 125, -1, -1, 281,
+ 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+ 292, 293, 294, 295, 296, 297, 298, 299, 300, 260,
+ 0, -1, -1, -1, 265, 266, 267, -1, 269, 270,
+ 271, 272, -1, -1, -1, -1, -1, -1, 59, -1,
+ 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+ 291, 292, 293, 294, 295, 296, 297, 298, 299, 300,
+ 342, 343, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 93, -1, -1, -1, -1, -1, -1, 59,
+ 362, 363, 364, 365, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 342, 343, -1, 125, -1, -1, -1, -1, -1,
+ -1, -1, -1, 93, -1, -1, -1, -1, -1, -1,
+ -1, 362, 363, 364, 365, -1, -1, 0, -1, 0,
+ -1, 260, -1, -1, -1, -1, 265, 266, 267, -1,
+ 269, 270, 271, 272, -1, 125, -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, 43, -1, 45, 46, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 59, -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, 342, 343, -1, -1, -1, -1, -1,
+ 93, -1, 93, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 362, 363, 364, 365, -1, -1, 260,
+ -1, -1, -1, -1, 265, 266, 267, -1, 269, 270,
+ 271, 272, 125, -1, 125, -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, -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, 342, 343, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 0, -1, -1, -1,
+ -1, 362, 363, 364, 365, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 342, 343, -1, -1, -1, -1, -1, 33,
+ -1, -1, -1, -1, -1, -1, 40, -1, -1, -1,
+ -1, -1, 362, 363, 364, 365, -1, 260, -1, -1,
+ -1, -1, 265, 266, 267, 59, 269, 270, 271, 272,
+ 271, 272, -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, 93,
+ -1, -1, 96, -1, -1, -1, 307, 308, 309, 310,
+ 311, 312, 313, 314, 315, 316, 317, 318, 319, 320,
+ 321, 322, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 125, -1, -1, -1, 336, 337, 338, 339, 342,
+ 343, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 33, -1, 354, 355, 356, 357, 358, 40, 362,
+ 363, 364, 365, 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, 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, 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, 300, -1, -1, -1,
+ -1, -1, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, 33, -1, 342, 343,
+ -1, -1, -1, 40, -1, -1, -1, -1, 45, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, 362, 363,
+ 364, -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, -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, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, 123, -1, -1, -1,
+ -1, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, 334, -1, 336, 337, 338, 339, 340, 341,
+ -1, -1, 344, -1, 346, -1, -1, -1, -1, -1,
+ -1, -1, 354, 355, 356, 357, 358, 359, 33, 361,
+ -1, -1, -1, 365, 366, 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,
+ 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, 33, -1, -1, -1, -1,
+ -1, -1, 40, 41, -1, -1, -1, 45, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, -1, -1, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, 334, -1, 336,
+ 337, 338, 339, 340, 341, -1, -1, 344, 96, 346,
+ -1, -1, -1, -1, -1, -1, -1, 354, 355, 356,
+ 357, 358, 359, -1, 361, -1, -1, -1, 365, 366,
+ -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, 300, -1, -1, -1, -1,
+ -1, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, -1, -1, -1, -1, -1, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 33,
+ -1, 336, 337, 338, 339, -1, 40, 342, 343, -1,
+ -1, 45, -1, -1, -1, -1, -1, -1, -1, 354,
+ 355, 356, 357, 358, -1, -1, -1, 362, 363, 364,
+ 365, -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, -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, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, 317,
+ -1, -1, -1, -1, -1, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 333, 33, -1, 336, 337,
+ 338, 339, -1, 40, -1, -1, -1, -1, 45, -1,
+ -1, -1, -1, -1, -1, -1, 354, 355, 356, 357,
+ 358, -1, -1, -1, -1, -1, -1, 365, -1, -1,
+ -1, -1, -1, -1, -1, -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, 257, 258, 259, 260, -1, -1, 263,
+ -1, -1, -1, -1, 268, -1, -1, 271, 272, -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, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, -1, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, 96, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 354, 355, 356, 357, 358, -1, -1, -1, -1, -1,
+ -1, 365, -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,
+ 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, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, -1, -1, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, -1, -1, 336,
+ 337, 338, 339, 96, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 354, 355, 356,
+ 357, 358, -1, -1, -1, -1, -1, -1, 365, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -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, -1, 306, 307, 308, 309,
+ 310, 311, 312, 313, 314, 315, 316, 317, 96, -1,
+ -1, -1, -1, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 333, -1, -1, 336, 337, 338, 339,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 354, 355, 356, 357, 358, 33,
+ -1, -1, -1, -1, -1, 365, 40, -1, -1, -1,
+ -1, 45, -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, -1, -1,
+ -1, -1, -1, -1, 59, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 96, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 317, -1, 91, -1, -1, -1,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ 333, -1, -1, 336, 337, 338, 339, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 123, -1,
+ -1, 354, 355, 356, 357, 358, -1, 33, -1, 257,
+ 258, 259, 365, -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, -1, 306, 307,
+ 308, 309, 310, 311, 312, 313, 314, 315, 316, 317,
+ 96, -1, -1, -1, -1, 323, 324, 325, 326, 327,
+ 328, 329, 330, 331, 332, 333, -1, -1, 336, 337,
+ 338, 339, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 354, 355, 356, 357,
+ 358, 33, -1, 257, 258, 259, -1, -1, 40, 263,
+ -1, -1, -1, 45, 268, -1, -1, 271, 272, -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, 306, 307, 308, 309, 310, 311, 312, 313,
+ 314, 315, 316, 317, 96, -1, -1, -1, -1, 323,
+ 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+ -1, -1, 336, 337, 338, 339, 33, -1, -1, -1,
+ -1, -1, -1, 40, -1, -1, -1, -1, 45, 334,
+ 354, 355, 356, 357, 358, 340, 341, -1, -1, 344,
+ -1, 346, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 257, 258, 259, 359, -1, 361, 263, -1, -1,
+ 365, 366, 268, -1, -1, 271, 272, -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,
+ 306, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+ 316, 317, -1, -1, -1, -1, -1, 323, 324, 325,
+ 326, 327, 328, 329, 330, 331, 332, 333, -1, -1,
+ 336, 337, 338, 339, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 354, 355,
+ 356, 357, 358, -1, -1, 257, 258, 259, -1, -1,
+ -1, 263, -1, -1, 91, -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, 123, -1, -1, -1,
+ 91, -1, -1, -1, 306, 307, 308, 309, 310, 311,
+ 312, 313, 314, 315, 316, 317, -1, -1, -1, -1,
+ -1, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+ 332, 333, 123, -1, 336, 337, 338, 339, -1, -1,
+ 257, 258, 259, -1, -1, -1, 263, -1, -1, -1,
+ -1, 268, 354, 355, 356, 357, 358, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 306,
+ 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+ 317, -1, -1, -1, -1, -1, 323, 324, 325, 326,
+ 327, 328, 329, 330, 331, 332, 333, -1, -1, 336,
+ 337, 338, 339, -1, -1, -1, -1, -1, -1, -1,
+ 257, 258, -1, 260, 261, -1, -1, 354, 355, 356,
+ 357, 358, 269, 270, 271, 272, 273, 274, 275, 276,
+ 277, 278, 279, 280, -1, -1, -1, -1, -1, -1,
+ -1, -1, -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, 334, -1, -1,
+ -1, -1, -1, 340, 341, -1, -1, 344, -1, 346,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 359, -1, 361, -1, -1, -1, 365, 366,
+ -1, -1, -1, 334, -1, -1, -1, -1, -1, 340,
+ 341, -1, -1, 344, -1, 346, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 359, -1,
+ 361, -1, -1, -1, 365, 366,
+};
+#define YYFINAL 2
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 368
+#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","SOLID","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 SOLID",
+"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 1546 "/home/cjk/groff/src/preproc/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 3409 "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 283 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ if (olist.head)
+ print_picture(olist.head);
+ }
+break;
+case 3:
+#line 292 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pl = yyvsp[-1].pl; }
+break;
+case 4:
+#line 297 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pl = yyvsp[0].pl; }
+break;
+case 5:
+#line 299 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pl = yyvsp[-2].pl; }
+break;
+case 10:
+#line 314 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ define_variable(yyvsp[-2].str, yyvsp[0].x);
+ a_delete yyvsp[-2].str;
+ }
+break;
+case 11:
+#line 319 "/home/cjk/groff/src/preproc/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 331 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ current_direction = UP_DIRECTION; }
+break;
+case 13:
+#line 333 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ current_direction = DOWN_DIRECTION; }
+break;
+case 14:
+#line 335 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ current_direction = LEFT_DIRECTION; }
+break;
+case 15:
+#line 337 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ current_direction = RIGHT_DIRECTION; }
+break;
+case 16:
+#line 339 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ olist.append(make_command_object(yyvsp[0].lstr.str, yyvsp[0].lstr.filename,
+ yyvsp[0].lstr.lineno));
+ }
+break;
+case 17:
+#line 344 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ olist.append(make_command_object(yyvsp[0].lstr.str, yyvsp[0].lstr.filename,
+ yyvsp[0].lstr.lineno));
+ }
+break;
+case 18:
+#line 349 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ fprintf(stderr, "%s\n", yyvsp[0].lstr.str);
+ a_delete yyvsp[0].lstr.str;
+ fflush(stderr);
+ }
+break;
+case 19:
+#line 355 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 20:
+#line 357 "/home/cjk/groff/src/preproc/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 366 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ if (yychar < 0)
+ do_lookahead();
+ do_copy(yyvsp[0].lstr.str);
+ /* do not delete the filename*/
+ }
+break;
+case 22:
+#line 373 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 2; }
+break;
+case 23:
+#line 375 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 0; }
+break;
+case 24:
+#line 377 "/home/cjk/groff/src/preproc/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 386 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 2; }
+break;
+case 26:
+#line 388 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 0; }
+break;
+case 27:
+#line 390 "/home/cjk/groff/src/preproc/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 398 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 29:
+#line 400 "/home/cjk/groff/src/preproc/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 407 "/home/cjk/groff/src/preproc/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 415 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 32:
+#line 417 "/home/cjk/groff/src/preproc/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 430 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ define_variable("scale", 1.0); }
+break;
+case 35:
+#line 435 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ reset(yyvsp[0].str); a_delete yyvsp[0].str; }
+break;
+case 36:
+#line 437 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ reset(yyvsp[0].str); a_delete yyvsp[0].str; }
+break;
+case 37:
+#line 439 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ reset(yyvsp[0].str); a_delete yyvsp[0].str; }
+break;
+case 38:
+#line 444 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.lstr = yyvsp[0].lstr; }
+break;
+case 39:
+#line 446 "/home/cjk/groff/src/preproc/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 465 "/home/cjk/groff/src/preproc/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 472 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.lstr = yyvsp[0].lstr; }
+break;
+case 42:
+#line 474 "/home/cjk/groff/src/preproc/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 483 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 1; }
+break;
+case 44:
+#line 485 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ delim_flag = 0; yyval.if_data.x = yyvsp[-3].x; yyval.if_data.body = yyvsp[0].str; }
+break;
+case 45:
+#line 490 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.str = 0; }
+break;
+case 46:
+#line 492 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.str = yyvsp[0].lstr.str; }
+break;
+case 47:
+#line 497 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[0].x; }
+break;
+case 48:
+#line 499 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[0].x; }
+break;
+case 49:
+#line 504 "/home/cjk/groff/src/preproc/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 510 "/home/cjk/groff/src/preproc/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 516 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 52:
+#line 518 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 53:
+#line 520 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 54:
+#line 522 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 55:
+#line 524 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 56:
+#line 526 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 57:
+#line 528 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[0].x == 0.0); }
+break;
+case 58:
+#line 534 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.by.val = 1.0; yyval.by.is_multiplicative = 0; }
+break;
+case 59:
+#line 536 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.by.val = yyvsp[0].x; yyval.by.is_multiplicative = 0; }
+break;
+case 60:
+#line 538 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.by.val = yyvsp[0].x; yyval.by.is_multiplicative = 1; }
+break;
+case 61:
+#line 543 "/home/cjk/groff/src/preproc/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 557 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pl = yyvsp[0].pl; define_label(yyvsp[-3].str, & yyval.pl); a_delete yyvsp[-3].str; }
+break;
+case 63:
+#line 559 "/home/cjk/groff/src/preproc/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 567 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pl = yyvsp[0].pl;
+ define_label(yyvsp[-3].str, & yyval.pl);
+ a_delete yyvsp[-3].str;
+ }
+break;
+case 65:
+#line 573 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.state.x = current_position.x;
+ yyval.state.y = current_position.y;
+ yyval.state.dir = current_direction;
+ }
+break;
+case 66:
+#line 579 "/home/cjk/groff/src/preproc/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 585 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pl = yyvsp[-3].pl;
+ }
+break;
+case 68:
+#line 589 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pl.obj = 0;
+ yyval.pl.x = current_position.x;
+ yyval.pl.y = current_position.y;
+ }
+break;
+case 69:
+#line 598 "/home/cjk/groff/src/preproc/pic/pic.y"
+{}
+break;
+case 70:
+#line 600 "/home/cjk/groff/src/preproc/pic/pic.y"
+{}
+break;
+case 71:
+#line 605 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = new object_spec(BOX_OBJECT);
+ }
+break;
+case 72:
+#line 609 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = new object_spec(CIRCLE_OBJECT);
+ }
+break;
+case 73:
+#line 613 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = new object_spec(ELLIPSE_OBJECT);
+ }
+break;
+case 74:
+#line 617 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = new object_spec(ARC_OBJECT);
+ yyval.spec->dir = current_direction;
+ }
+break;
+case 75:
+#line 622 "/home/cjk/groff/src/preproc/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 629 "/home/cjk/groff/src/preproc/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 636 "/home/cjk/groff/src/preproc/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 643 "/home/cjk/groff/src/preproc/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 650 "/home/cjk/groff/src/preproc/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 655 "/home/cjk/groff/src/preproc/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 660 "/home/cjk/groff/src/preproc/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 667 "/home/cjk/groff/src/preproc/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 682 "/home/cjk/groff/src/preproc/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 694 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->height = yyvsp[0].x;
+ yyval.spec->flags |= HAS_HEIGHT;
+ }
+break;
+case 85:
+#line 700 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->radius = yyvsp[0].x;
+ yyval.spec->flags |= HAS_RADIUS;
+ }
+break;
+case 86:
+#line 706 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->width = yyvsp[0].x;
+ yyval.spec->flags |= HAS_WIDTH;
+ }
+break;
+case 87:
+#line 712 "/home/cjk/groff/src/preproc/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 718 "/home/cjk/groff/src/preproc/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 737 "/home/cjk/groff/src/preproc/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 744 "/home/cjk/groff/src/preproc/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 751 "/home/cjk/groff/src/preproc/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 758 "/home/cjk/groff/src/preproc/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 765 "/home/cjk/groff/src/preproc/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 772 "/home/cjk/groff/src/preproc/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 779 "/home/cjk/groff/src/preproc/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 786 "/home/cjk/groff/src/preproc/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 793 "/home/cjk/groff/src/preproc/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 800 "/home/cjk/groff/src/preproc/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 815 "/home/cjk/groff/src/preproc/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 827 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= HAS_WITH;
+ yyval.spec->with = yyvsp[0].pth;
+ }
+break;
+case 101:
+#line 833 "/home/cjk/groff/src/preproc/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 840 "/home/cjk/groff/src/preproc/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 852 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec; /* nothing*/
+ }
+break;
+case 104:
+#line 856 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_DOTTED;
+ lookup_variable("dashwid", & yyval.spec->dash_width);
+ }
+break;
+case 105:
+#line 862 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= IS_DOTTED;
+ yyval.spec->dash_width = yyvsp[0].x;
+ }
+break;
+case 106:
+#line 868 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_DASHED;
+ lookup_variable("dashwid", & yyval.spec->dash_width);
+ }
+break;
+case 107:
+#line 874 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= IS_DASHED;
+ yyval.spec->dash_width = yyvsp[0].x;
+ }
+break;
+case 108:
+#line 880 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_DEFAULT_FILLED;
+ }
+break;
+case 109:
+#line 885 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= IS_FILLED;
+ yyval.spec->fill = yyvsp[0].x;
+ }
+break;
+case 110:
+#line 891 "/home/cjk/groff/src/preproc/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 111:
+#line 907 "/home/cjk/groff/src/preproc/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 112:
+#line 924 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_SAME;
+ }
+break;
+case 113:
+#line 929 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_INVISIBLE;
+ }
+break;
+case 114:
+#line 934 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= HAS_LEFT_ARROW_HEAD;
+ }
+break;
+case 115:
+#line 939 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= HAS_RIGHT_ARROW_HEAD;
+ }
+break;
+case 116:
+#line 944 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD);
+ }
+break;
+case 117:
+#line 949 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_CLOCKWISE;
+ }
+break;
+case 118:
+#line 954 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags &= ~IS_CLOCKWISE;
+ }
+break;
+case 119:
+#line 959 "/home/cjk/groff/src/preproc/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 120:
+#line 967 "/home/cjk/groff/src/preproc/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 121:
+#line 977 "/home/cjk/groff/src/preproc/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 122:
+#line 987 "/home/cjk/groff/src/preproc/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 123:
+#line 997 "/home/cjk/groff/src/preproc/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 124:
+#line 1007 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-2].spec;
+ yyval.spec->flags |= HAS_THICKNESS;
+ yyval.spec->thickness = yyvsp[0].x;
+ }
+break;
+case 125:
+#line 1013 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.spec = yyvsp[-1].spec;
+ yyval.spec->flags |= IS_ALIGNED;
+ }
+break;
+case 126:
+#line 1021 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.lstr = yyvsp[0].lstr;
+ }
+break;
+case 127:
+#line 1025 "/home/cjk/groff/src/preproc/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 128:
+#line 1036 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.dv.v = 0;
+ yyval.dv.nv = 0;
+ yyval.dv.maxv = 0;
+ }
+break;
+case 129:
+#line 1042 "/home/cjk/groff/src/preproc/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 130:
+#line 1064 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pair = yyvsp[0].pair; }
+break;
+case 131:
+#line 1066 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ position pos = yyvsp[0].pl;
+ yyval.pair.x = pos.x;
+ yyval.pair.y = pos.y;
+ }
+break;
+case 132:
+#line 1075 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pair = yyvsp[0].pair; }
+break;
+case 133:
+#line 1077 "/home/cjk/groff/src/preproc/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 1082 "/home/cjk/groff/src/preproc/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 135:
+#line 1087 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pair.x = yyvsp[-3].pair.x;
+ yyval.pair.y = yyvsp[-1].pair.y;
+ }
+break;
+case 136:
+#line 1092 "/home/cjk/groff/src/preproc/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 137:
+#line 1097 "/home/cjk/groff/src/preproc/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 140:
+#line 1110 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pair.x = yyvsp[-2].x; yyval.pair.y = yyvsp[0].x; }
+break;
+case 141:
+#line 1112 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pair = yyvsp[-1].pair; }
+break;
+case 142:
+#line 1117 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.pl = yyvsp[0].pl; }
+break;
+case 143:
+#line 1119 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ path pth(yyvsp[0].crn);
+ if (!pth.follow(yyvsp[-1].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 144:
+#line 1125 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ path pth(yyvsp[-1].crn);
+ if (!pth.follow(yyvsp[0].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 145:
+#line 1131 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ path pth(yyvsp[-2].crn);
+ if (!pth.follow(yyvsp[0].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 146:
+#line 1137 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pl.x = current_position.x;
+ yyval.pl.y = current_position.y;
+ yyval.pl.obj = 0;
+ }
+break;
+case 147:
+#line 1146 "/home/cjk/groff/src/preproc/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 148:
+#line 1156 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pl.obj = yyvsp[0].obj;
+ }
+break;
+case 149:
+#line 1160 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ path pth(yyvsp[0].str);
+ if (!pth.follow(yyvsp[-2].pl, & yyval.pl))
+ YYABORT;
+ }
+break;
+case 150:
+#line 1169 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.n = yyvsp[0].n; }
+break;
+case 151:
+#line 1171 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ /* XXX Check for overflow (and non-integers?).*/
+ yyval.n = (int)yyvsp[-1].x;
+ }
+break;
+case 152:
+#line 1179 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.n = 1; }
+break;
+case 153:
+#line 1181 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.n = yyvsp[-1].n; }
+break;
+case 154:
+#line 1186 "/home/cjk/groff/src/preproc/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 155:
+#line 1201 "/home/cjk/groff/src/preproc/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 156:
+#line 1219 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = BOX_OBJECT; }
+break;
+case 157:
+#line 1221 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = CIRCLE_OBJECT; }
+break;
+case 158:
+#line 1223 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = ELLIPSE_OBJECT; }
+break;
+case 159:
+#line 1225 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = ARC_OBJECT; }
+break;
+case 160:
+#line 1227 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = LINE_OBJECT; }
+break;
+case 161:
+#line 1229 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = ARROW_OBJECT; }
+break;
+case 162:
+#line 1231 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = SPLINE_OBJECT; }
+break;
+case 163:
+#line 1233 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = BLOCK_OBJECT; }
+break;
+case 164:
+#line 1235 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.obtype = TEXT_OBJECT; }
+break;
+case 165:
+#line 1240 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pth = new path(yyvsp[0].str);
+ }
+break;
+case 166:
+#line 1244 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pth = yyvsp[-2].pth;
+ yyval.pth->append(yyvsp[0].str);
+ }
+break;
+case 167:
+#line 1252 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pth = new path(yyvsp[0].crn);
+ }
+break;
+case 168:
+#line 1259 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 169:
+#line 1263 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pth = yyvsp[-1].pth;
+ yyval.pth->append(yyvsp[0].crn);
+ }
+break;
+case 170:
+#line 1271 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 171:
+#line 1275 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ yyval.pth = yyvsp[-3].pth;
+ yyval.pth->set_ypath(yyvsp[-1].pth);
+ }
+break;
+case 172:
+#line 1281 "/home/cjk/groff/src/preproc/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 173:
+#line 1287 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ lex_warning("`last %1' in `with' argument ignored",
+ object_type_name(yyvsp[-1].obtype));
+ yyval.pth = yyvsp[0].pth;
+ }
+break;
+case 174:
+#line 1293 "/home/cjk/groff/src/preproc/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 175:
+#line 1299 "/home/cjk/groff/src/preproc/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 176:
+#line 1308 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north; }
+break;
+case 177:
+#line 1310 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::east; }
+break;
+case 178:
+#line 1312 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::west; }
+break;
+case 179:
+#line 1314 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::south; }
+break;
+case 180:
+#line 1316 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north_east; }
+break;
+case 181:
+#line 1318 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object:: south_east; }
+break;
+case 182:
+#line 1320 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north_west; }
+break;
+case 183:
+#line 1322 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::south_west; }
+break;
+case 184:
+#line 1324 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::center; }
+break;
+case 185:
+#line 1326 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::start; }
+break;
+case 186:
+#line 1328 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::end; }
+break;
+case 187:
+#line 1330 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north; }
+break;
+case 188:
+#line 1332 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::south; }
+break;
+case 189:
+#line 1334 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::west; }
+break;
+case 190:
+#line 1336 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::east; }
+break;
+case 191:
+#line 1338 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north_west; }
+break;
+case 192:
+#line 1340 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::south_west; }
+break;
+case 193:
+#line 1342 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north_east; }
+break;
+case 194:
+#line 1344 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::south_east; }
+break;
+case 195:
+#line 1346 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::west; }
+break;
+case 196:
+#line 1348 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::east; }
+break;
+case 197:
+#line 1350 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north_west; }
+break;
+case 198:
+#line 1352 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::south_west; }
+break;
+case 199:
+#line 1354 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::north_east; }
+break;
+case 200:
+#line 1356 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::south_east; }
+break;
+case 201:
+#line 1358 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::center; }
+break;
+case 202:
+#line 1360 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::start; }
+break;
+case 203:
+#line 1362 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.crn = &object::end; }
+break;
+case 204:
+#line 1367 "/home/cjk/groff/src/preproc/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 205:
+#line 1375 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[0].x; }
+break;
+case 206:
+#line 1377 "/home/cjk/groff/src/preproc/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 207:
+#line 1384 "/home/cjk/groff/src/preproc/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 208:
+#line 1391 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->height();
+ else
+ yyval.x = 0.0;
+ }
+break;
+case 209:
+#line 1398 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->width();
+ else
+ yyval.x = 0.0;
+ }
+break;
+case 210:
+#line 1405 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ if (yyvsp[-1].pl.obj != 0)
+ yyval.x = yyvsp[-1].pl.obj->radius();
+ else
+ yyval.x = 0.0;
+ }
+break;
+case 211:
+#line 1412 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[-2].x + yyvsp[0].x; }
+break;
+case 212:
+#line 1414 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[-2].x - yyvsp[0].x; }
+break;
+case 213:
+#line 1416 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[-2].x * yyvsp[0].x; }
+break;
+case 214:
+#line 1418 "/home/cjk/groff/src/preproc/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 215:
+#line 1426 "/home/cjk/groff/src/preproc/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 216:
+#line 1434 "/home/cjk/groff/src/preproc/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 217:
+#line 1447 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = -yyvsp[0].x; }
+break;
+case 218:
+#line 1449 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[-1].x; }
+break;
+case 219:
+#line 1451 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = sin(yyvsp[-1].x);
+ if (errno == ERANGE) {
+ lex_error("sin result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 220:
+#line 1460 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = cos(yyvsp[-1].x);
+ if (errno == ERANGE) {
+ lex_error("cos result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 221:
+#line 1469 "/home/cjk/groff/src/preproc/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 222:
+#line 1482 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = log10(yyvsp[-1].x);
+ if (errno == ERANGE) {
+ lex_error("log result out of range");
+ YYABORT;
+ }
+ }
+break;
+case 223:
+#line 1491 "/home/cjk/groff/src/preproc/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 224:
+#line 1500 "/home/cjk/groff/src/preproc/pic/pic.y"
+{
+ errno = 0;
+ yyval.x = sqrt(yyvsp[-1].x);
+ if (errno == EDOM) {
+ lex_error("sqrt argument out of domain");
+ YYABORT;
+ }
+ }
+break;
+case 225:
+#line 1509 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[-3].x > yyvsp[-1].x ? yyvsp[-3].x : yyvsp[-1].x; }
+break;
+case 226:
+#line 1511 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = yyvsp[-3].x < yyvsp[-1].x ? yyvsp[-3].x : yyvsp[-1].x; }
+break;
+case 227:
+#line 1513 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = floor(yyvsp[-1].x); }
+break;
+case 228:
+#line 1515 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*yyvsp[-1].x); }
+break;
+case 229:
+#line 1517 "/home/cjk/groff/src/preproc/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 230:
+#line 1523 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = 0; srand((unsigned int)yyvsp[-1].x); }
+break;
+case 231:
+#line 1525 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x < yyvsp[0].x); }
+break;
+case 232:
+#line 1527 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x <= yyvsp[0].x); }
+break;
+case 233:
+#line 1529 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x > yyvsp[0].x); }
+break;
+case 234:
+#line 1531 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x >= yyvsp[0].x); }
+break;
+case 235:
+#line 1533 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x == yyvsp[0].x); }
+break;
+case 236:
+#line 1535 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != yyvsp[0].x); }
+break;
+case 237:
+#line 1537 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); }
+break;
+case 238:
+#line 1539 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); }
+break;
+case 239:
+#line 1541 "/home/cjk/groff/src/preproc/pic/pic.y"
+{ yyval.x = (yyvsp[0].x == 0.0); }
+break;
+#line 5161 "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/contrib/groff/src/preproc/pic/pic.h b/contrib/groff/src/preproc/pic/pic.h
new file mode 100644
index 0000000..36c36d1
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/pic.h
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef NEED_DECLARATION_HYPOT
+extern "C" {
+ double hypot(double, double);
+}
+#endif /* NEED_DECLARATION_HYPOT */
+
+#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/contrib/groff/src/preproc/pic/pic.man b/contrib/groff/src/preproc/pic/pic.man
new file mode 100644
index 0000000..e187021
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/pic.man
@@ -0,0 +1,883 @@
+.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.
+..
+.\" 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
+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
+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
+.B 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
+.B pic
+and the original version of
+.BR pic .
+Many of these differences also apply to newer versions of Unix
+.BR pic .
+.SS \*(tx mode
+.LP
+\*(tx mode is enabled by the
+.B \-t
+option.
+In \*(tx mode,
+.B 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;
+.B 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
+.B pic
+will always scale a picture by the same amount vertically as horizontally.
+This is different from the
+.SM DWB
+2.0
+.B 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
+.B 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 CONVERSION
+To obtain a stand-alone picture from a
+.B pic
+file, enclose your
+.B pic
+code with
+.B .PS
+and
+.B .PE
+requests;
+.B roff
+configuration commands may be added at the beginning of the file, but no
+.B roff
+text.
+.LP
+It is necessary to feed this file into
+.B groff
+without adding any page information, so you must check which
+.B .PS
+and
+.B .PE
+requests are actually called.
+For example, the mm macro package adds a page number, which is very
+annoying.
+At the moment, calling standard
+.B groff
+without any macro package works.
+Alternatively, you can define your own requests, e.g. to do nothing:
+.LP
+.RS
+.nf
+.ft B
+\&.de PS
+\&..
+\&.de PE
+\&..
+.ft
+.fi
+.RE
+.LP
+.B groff
+itself does not provide direct conversion into other graphics file
+formats.
+But there are lots of possibilities if you first transform your picture
+into PostScript\*R format using the
+.B groff
+option
+.BR -Tps .
+Since this
+.IR ps -file
+lacks BoundingBox information it is not very useful by itself, but it
+may be fed into other conversion programs, usually named
+.BI ps2 other
+or
+.BI psto other
+or the like.
+Moreover, the PostScript interpreter
+.B ghostscript
+.RB ( gs )
+has built-in graphics conversion devices that are called with the option
+.LP
+.RS
+.BI "gs -sDEVICE=" <devname>
+.RE
+.LP
+Call
+.RS
+.B gs --help
+.RE
+.LP
+for a list of the available devices.
+.LP
+As the Encapsulated PostScript File Format
+.B EPS
+is getting more and more important, and the conversion wasn't regarded
+trivial in the past you might be interested to know that there is a
+conversion tool named
+.B ps2eps
+which does the right job.
+It is much better than the tool
+.B ps2epsi
+packaged with
+.BR gs .
+.LP
+For bitmapped graphic formats, you should use
+.BR pstopnm ;
+the resulting (intermediate)
+.B PNM
+file can be then converted to virtually any graphics format using the tools
+of the
+.B netpbm
+package .
+.SH FILES
+.Tp \w'\fB@MACRODIR@/pic.tmac'u+3n
+.B
+@MACRODIR@/pic.tmac
+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 gs (1),
+.BR ps2eps (1),
+.BR pstopnm (1),
+.BR ps2epsi (1),
+.BR pnm (5)
+.LP
+Tpic: Pic for \*(tx
+.LP
+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).
+.LP
+.B ps2eps
+is available from CTAN mirrors, e.g.
+.br
+<ftp://ftp.dante.de/tex-archive/support/ps2eps/>
+.LP
+W. Richard Stevens - Turning PIC Into HTML
+.br
+<http://www.kohala.com/start/troff/pic2html.html>
+.LP
+W. Richard Stevens - Examples of picMacros
+.br
+<http://www.kohala.com/start/troff/pic.examples.ps>
+.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.
+.LP
+PostScript\*R is a registered trademark of Adobe Systems Incorporation.
diff --git a/contrib/groff/src/preproc/pic/pic.y b/contrib/groff/src/preproc/pic/pic.y
new file mode 100644
index 0000000..38b960a
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/pic.y
@@ -0,0 +1,1812 @@
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 "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();
+#ifdef RET_TYPE_SRAND_IS_VOID
+ void srand(unsigned int);
+#else
+ int srand(unsigned int);
+#endif
+}
+
+/* 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 SOLID
+%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 SOLID 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 SOLID
+ {
+ $$ = $1; // nothing
+ }
+ | 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/contrib/groff/src/preproc/pic/pic_tab.h b/contrib/groff/src/preproc/pic/pic_tab.h
new file mode 100644
index 0000000..1765882
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/pic_tab.h
@@ -0,0 +1,131 @@
+#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 SOLID 291
+#define DOTTED 292
+#define DASHED 293
+#define CHOP 294
+#define SAME 295
+#define INVISIBLE 296
+#define LJUST 297
+#define RJUST 298
+#define ABOVE 299
+#define BELOW 300
+#define OF 301
+#define THE 302
+#define WAY 303
+#define BETWEEN 304
+#define AND 305
+#define HERE 306
+#define DOT_N 307
+#define DOT_E 308
+#define DOT_W 309
+#define DOT_S 310
+#define DOT_NE 311
+#define DOT_SE 312
+#define DOT_NW 313
+#define DOT_SW 314
+#define DOT_C 315
+#define DOT_START 316
+#define DOT_END 317
+#define DOT_X 318
+#define DOT_Y 319
+#define DOT_HT 320
+#define DOT_WID 321
+#define DOT_RAD 322
+#define SIN 323
+#define COS 324
+#define ATAN2 325
+#define LOG 326
+#define EXP 327
+#define SQRT 328
+#define K_MAX 329
+#define K_MIN 330
+#define INT 331
+#define RAND 332
+#define SRAND 333
+#define COPY 334
+#define THRU 335
+#define TOP 336
+#define BOTTOM 337
+#define UPPER 338
+#define LOWER 339
+#define SH 340
+#define PRINT 341
+#define CW 342
+#define CCW 343
+#define FOR 344
+#define DO 345
+#define IF 346
+#define ELSE 347
+#define ANDAND 348
+#define OROR 349
+#define NOTEQUAL 350
+#define EQUALEQUAL 351
+#define LESSEQUAL 352
+#define GREATEREQUAL 353
+#define LEFT_CORNER 354
+#define RIGHT_CORNER 355
+#define CENTER 356
+#define END 357
+#define START 358
+#define RESET 359
+#define UNTIL 360
+#define PLOT 361
+#define THICKNESS 362
+#define FILL 363
+#define ALIGNED 364
+#define SPRINTF 365
+#define COMMAND 366
+#define DEFINE 367
+#define UNDEF 368
+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/contrib/groff/src/preproc/pic/position.h b/contrib/groff/src/preproc/pic/position.h
new file mode 100644
index 0000000..ab7d546
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/tex.cc b/contrib/groff/src/preproc/pic/tex.cc
new file mode 100644
index 0000000..2a91b62
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/text.h b/contrib/groff/src/preproc/pic/text.h
new file mode 100644
index 0000000..f9d3487
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/pic/troff.cc b/contrib/groff/src/preproc/pic/troff.cc
new file mode 100644
index 0000000..62fe540
--- /dev/null
+++ b/contrib/groff/src/preproc/pic/troff.cc
@@ -0,0 +1,504 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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"
+#include "htmlindicate.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;
+ graphic_start(0);
+ printf(".PS %.3fi %.3fi", height, width);
+ if (args)
+ printf(" %s\n", args);
+ else
+ putchar('\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");
+ // this is a little gross
+ set_location(current_filename, current_lineno);
+ fputs(flyback_flag ? ".PF\n" : ".PE\n", stdout);
+ graphic_end();
+}
+
+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/contrib/groff/src/preproc/refer/Makefile.sub b/contrib/groff/src/preproc/refer/Makefile.sub
new file mode 100644
index 0000000..1631b5e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/TODO b/contrib/groff/src/preproc/refer/TODO
new file mode 100644
index 0000000..5bbd9bf
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/command.cc b/contrib/groff/src/preproc/refer/command.cc
new file mode 100644
index 0000000..004189e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/command.h b/contrib/groff/src/preproc/refer/command.h
new file mode 100644
index 0000000..c7085db
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/label.cc b/contrib/groff/src/preproc/refer/label.cc
new file mode 100644
index 0000000..c6dc07c
--- /dev/null
+++ b/contrib/groff/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.2 2000/02/28 11:02:12 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 = i_to_a(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 i_to_a(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/contrib/groff/src/preproc/refer/label.y b/contrib/groff/src/preproc/refer/label.y
new file mode 100644
index 0000000..2648b98
--- /dev/null
+++ b/contrib/groff/src/preproc/refer/label.y
@@ -0,0 +1,1177 @@
+/* -*- C++ -*-
+ Copyright (C) 1989, 1990, 1991, 1992, 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 "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 = i_to_a(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 i_to_a(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/contrib/groff/src/preproc/refer/ref.cc b/contrib/groff/src/preproc/refer/ref.cc
new file mode 100644
index 0000000..c3517b1
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/ref.h b/contrib/groff/src/preproc/refer/ref.h
new file mode 100644
index 0000000..13a984a
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/refer.cc b/contrib/groff/src/preproc/refer/refer.cc
new file mode 100644
index 0000000..b6cefc5
--- /dev/null
+++ b/contrib/groff/src/preproc/refer/refer.cc
@@ -0,0 +1,1234 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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(FILE *stream);
+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(stderr);
+ exit(1);
+ }
+ }
+ 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(stderr);
+ exit(1);
+ }
+ }
+ 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 '-':
+ if (opt[1] == '\0') {
+ finished_options = 1;
+ opt++;
+ break;
+ }
+ if (strcmp(opt,"-version")==0) {
+ case 'v':
+ extern const char *Version_string;
+ printf("GNU refer (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ if (strcmp(opt,"-help")==0) {
+ usage(stdout);
+ exit(0);
+ break;
+ }
+ // fall through
+ default:
+ error("unrecognized option `%1'", *opt);
+ usage(stderr);
+ exit(1);
+ 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(FILE *stream)
+{
+ fprintf(stream,
+"usage: %s [-benvCPRS] [-aN] [-cXYZ] [-fN] [-iXYZ] [-kX] [-lM,N] [-p file]\n"
+" [-sXYZ] [-tN] [-BL.M] [files ...]\n",
+ program_name);
+}
+
+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 + (int)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" {
+
+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/contrib/groff/src/preproc/refer/refer.h b/contrib/groff/src/preproc/refer/refer.h
new file mode 100644
index 0000000..f0ab3cd
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/refer.man b/contrib/groff/src/preproc/refer/refer.man
new file mode 100644
index 0000000..13708cf
--- /dev/null
+++ b/contrib/groff/src/preproc/refer/refer.man
@@ -0,0 +1,1302 @@
+.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.
+..
+.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
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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/contrib/groff/src/preproc/refer/token.cc b/contrib/groff/src/preproc/refer/token.cc
new file mode 100644
index 0000000..1cf6890
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/refer/token.h b/contrib/groff/src/preproc/refer/token.h
new file mode 100644
index 0000000..6da430d
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/soelim/Makefile.sub b/contrib/groff/src/preproc/soelim/Makefile.sub
new file mode 100644
index 0000000..77007e2
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/soelim/TODO b/contrib/groff/src/preproc/soelim/TODO
new file mode 100644
index 0000000..f2a3924
--- /dev/null
+++ b/contrib/groff/src/preproc/soelim/TODO
@@ -0,0 +1 @@
+Understand .pso.
diff --git a/contrib/groff/src/preproc/soelim/soelim.cc b/contrib/groff/src/preproc/soelim/soelim.cc
new file mode 100644
index 0000000..e05f240
--- /dev/null
+++ b/contrib/groff/src/preproc/soelim/soelim.cc
@@ -0,0 +1,347 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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 "nonposix.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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [ -vC ] [ -I file ] [ files ]\n", program_name);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ include_path_append(".");
+ int opt;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "CI:v", long_options, NULL)) != EOF)
+ switch (opt) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU soelim (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'I':
+ include_path_append(optarg);
+ break;
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ 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 (IS_ABSOLUTE(filename)) {
+ 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/contrib/groff/src/preproc/soelim/soelim.man b/contrib/groff/src/preproc/soelim/soelim.man
new file mode 100644
index 0000000..b97ea61
--- /dev/null
+++ b/contrib/groff/src/preproc/soelim/soelim.man
@@ -0,0 +1,85 @@
+.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@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 \|.\|.\|.\|
+]
+.PP
+It is possible to have whitespace between the
+.B \-I
+command line option and its parameter.
+.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 .
+.PP
+Note that there must be no whitespace between the leading dot and
+the two characters `s' and `o'. Otherwise, only
+.B groff
+interprets the
+.B .so
+request (and
+.B soelim
+ignores it).
+.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/contrib/groff/src/preproc/tbl/Makefile.sub b/contrib/groff/src/preproc/tbl/Makefile.sub
new file mode 100644
index 0000000..224baff
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/tbl/main.cc b/contrib/groff/src/preproc/tbl/main.cc
new file mode 100644
index 0000000..a08ea0b
--- /dev/null
+++ b/contrib/groff/src/preproc/tbl/main.cc
@@ -0,0 +1,1528 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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"
+#include "htmlindicate.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) {
+ printf(".if '\\*(.T'html' \\X(table-start(\n");
+ html_begin_suppress(0);
+ 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');
+ current_lineno++;
+ {
+ table_input input(fp);
+ process_table(input);
+ set_troff_location(current_filename, current_lineno);
+ if (input.ended()) {
+ fputs(".TE", stdout);
+ while ((c = getc(fp)) != '\n') {
+ if (c == EOF) {
+ printf(".if '\\*(.T'html' \\X(table-end(\n");
+ html_end_suppress(0);
+ putchar('\n');
+ return;
+ }
+ putchar(c);
+ }
+ putchar('\n');
+ printf(".if '\\*(.T'html' \\X(table-end(\n");
+ html_end_suppress(0);
+ 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [ -vC ] [ files... ]\n", program_name);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "vCT:", long_options, NULL)) != EOF)
+ switch (opt) {
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU tbl (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case 'T':
+ // I'm sick of getting bug reports from IRIX users
+ break;
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ 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/contrib/groff/src/preproc/tbl/table.cc b/contrib/groff/src/preproc/tbl/table.cc
new file mode 100644
index 0000000..c7f96cd
--- /dev/null
+++ b/contrib/groff/src/preproc/tbl/table.cc
@@ -0,0 +1,2778 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 "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[.i])\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/contrib/groff/src/preproc/tbl/table.h b/contrib/groff/src/preproc/tbl/table.h
new file mode 100644
index 0000000..ca55b80
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/preproc/tbl/tbl.man b/contrib/groff/src/preproc/tbl/tbl.man
new file mode 100644
index 0000000..6016ddf
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/groff/Makefile.sub b/contrib/groff/src/roff/groff/Makefile.sub
new file mode 100644
index 0000000..42ae221
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/groff/groff.cc b/contrib/groff/src/roff/groff/groff.cc
new file mode 100644
index 0000000..aaca4e1
--- /dev/null
+++ b/contrib/groff/src/roff/groff/groff.cc
@@ -0,0 +1,731 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-2000, 2001 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 "nonposix.h"
+#include "defs.h"
+
+#define GXDITVIEW "gxditview"
+
+// troff will be passed an argument of -rXREG=1 if the -X option is
+// specified
+#define XREG ".X"
+
+#ifdef NEED_DECLARATION_PUTENV
+extern "C" {
+ int putenv(const char *);
+}
+#endif /* NEED_DECLARATION_PUTENV */
+
+const int SOELIM_INDEX = 0;
+const int REFER_INDEX = SOELIM_INDEX + 1;
+const int GRAP_INDEX = REFER_INDEX + 1;
+const int PIC_INDEX = GRAP_INDEX + 1;
+const int TBL_INDEX = PIC_INDEX + 1;
+const int GRN_INDEX = TBL_INDEX + 1;
+const int EQN_INDEX = GRN_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 *postdriver = 0;
+char *predriver = 0;
+
+possible_command commands[NCOMMANDS];
+
+int run_commands(int no_pipe);
+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(FILE *stream);
+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 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");
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, 'h' },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv,
+ "abCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
+ long_options, NULL))
+ != 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 'g':
+ commands[GRN_INDEX].set_name(command_prefix, "grn");
+ break;
+ case 'G':
+ commands[GRAP_INDEX].set_name(command_prefix, "grap");
+ 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':
+ vflag = 1;
+ {
+ extern const char *Version_string;
+ printf("GNU groff version %s\n", Version_string);
+ printf("Copyright (C) 1989-2001 Free Software Foundation, Inc.\n"
+ "GNU groff comes with ABSOLUTELY NO WARRANTY.\n"
+ "You may redistribute copies of groff and its subprograms\n"
+ "under the terms of the GNU General Public License.\n"
+ "For more information about these matters, see the file named COPYING.\n");
+ printf("\ncalled subprograms:\n\n");
+ fflush(stdout);
+ }
+ commands[POST_INDEX].append_arg(buf);
+ // fall through
+ case 'C':
+ commands[SOELIM_INDEX].append_arg(buf);
+ commands[REFER_INDEX].append_arg(buf);
+ commands[PIC_INDEX].append_arg(buf);
+ commands[GRAP_INDEX].append_arg(buf);
+ commands[TBL_INDEX].append_arg(buf);
+ commands[GRN_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, "html") == 0) {
+ // force soelim to aid the html preprocessor
+ commands[SOELIM_INDEX].set_name(command_prefix, "soelim");
+ }
+ 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 += PATH_SEP[0];
+ 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[GRAP_INDEX].append_arg(buf, optarg);
+ commands[GRN_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(stderr);
+ exit(1);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ if (safer_flag)
+ commands[PIC_INDEX].append_arg("-S");
+ 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 (!postdriver)
+ fatal("no `postpro' command in DESC file for device `%1'", device);
+
+ if (predriver) {
+ commands[TROFF_INDEX].insert_arg(commands[TROFF_INDEX].get_name());
+ const char *p = Pargs.contents();
+ const char *end = p + Pargs.length();
+ while (p < end) {
+ // pass the device arguments to the predrivers as well
+ commands[TROFF_INDEX].insert_arg(p);
+ p = strchr(p, '\0') + 1;
+ }
+ commands[TROFF_INDEX].set_name(predriver);
+ }
+
+ const char *real_driver = 0;
+ if (Xflag) {
+ real_driver = postdriver;
+ postdriver = GXDITVIEW;
+ commands[TROFF_INDEX].append_arg("-r" XREG "=", "1");
+ }
+ if (postdriver)
+ commands[POST_INDEX].set_name(postdriver);
+ int gxditview_flag = postdriver && strcmp(xbasename(postdriver), 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(BSHELL_DASH_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);
+ // html renders equations as images via ps
+ if (strcmp(device, "html") == 0)
+ commands[EQN_INDEX].append_arg("-Tps:html");
+ else
+ commands[EQN_INDEX].append_arg("-T", device);
+
+ commands[GRN_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 += PATH_SEP[0];
+ e += fontpath;
+ }
+ e += '\0';
+ if (putenv(strsave(e.contents())))
+ fatal("putenv failed");
+ }
+ {
+ // we save the original path in GROFF_PATH__ and put it into the
+ // environment -- troff will pick it up later.
+ char *path = getenv("PATH");
+ string e = "GROFF_PATH__";
+ e += '=';
+ if (path && *path)
+ e += path;
+ e += '\0';
+ if (putenv(strsave(e.contents())))
+ fatal("putenv failed");
+ char *binpath = getenv("GROFF_BIN_PATH");
+ string f = "PATH";
+ f += '=';
+ if (binpath && *binpath)
+ f += binpath;
+ else
+ f += BINPATH;
+ if (path && *path) {
+ f += PATH_SEP[0];
+ f += path;
+ }
+ f += '\0';
+ if (putenv(strsave(f.contents())))
+ fatal("putenv failed");
+ }
+ if (Vflag) {
+ print_commands();
+ exit(0);
+ }
+ return run_commands(vflag);
+}
+
+const char *xbasename(const char *s)
+{
+ if (!s)
+ return 0;
+ // DIR_SEPS[] are possible directory separator characters, see nonposix.h
+ // We want the rightmost separator of all possible ones.
+ // Example: d:/foo\\bar.
+ const char *p = strrchr(s, DIR_SEPS[0]), *p1;
+ const char *sep = &DIR_SEPS[1];
+
+ while (*sep)
+ {
+ p1 = strrchr(s, *sep);
+ if (p1 && (!p || p1 > p))
+ p = p1;
+ sep++;
+ }
+ 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, "prepro") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`prepro' command requires an argument");
+ else {
+ for (const char *p = arg; *p; p++)
+ if (csspace(*p)) {
+ error_with_file_and_line(filename, lineno,
+ "invalid `prepro' argument `%1'"
+ ": program name required", arg);
+ return;
+ }
+ predriver = 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;
+ }
+ postdriver = 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(int no_pipe)
+{
+ 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, no_pipe);
+}
+
+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 (IS_BSHELL(argv[0])
+ && argv[1] != 0 && strcmp(argv[1], BSHELL_DASH_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(FILE *stream)
+{
+ fprintf(stream,
+"usage: %s [-abeghilpstvzCENRSUVXZ] [-Fdir] [-mname] [-Tdev] [-ffam]\n"
+" [-wname] [-Wname] [-Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg]\n"
+" [-Larg] [-Idir] [files...]\n",
+ program_name);
+}
+
+void help()
+{
+ synopsis(stdout);
+ fputs("\n"
+"-h\tprint this message\n"
+"-t\tpreprocess with tbl\n"
+"-p\tpreprocess with pic\n"
+"-e\tpreprocess with eqn\n"
+"-g\tpreprocess with grn\n"
+"-G\tpreprocess with grap\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 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"
+"-Idir\tsearch dir for soelim. Implies -s\n"
+"\n",
+ stdout);
+ exit(0);
+}
+
+void usage(FILE *stream)
+{
+ synopsis(stream);
+ fprintf(stream, "%s -h gives more help\n", program_name);
+}
+
+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/contrib/groff/src/roff/groff/pipeline.c b/contrib/groff/src/roff/groff/pipeline.c
new file mode 100644
index 0000000..a4573ba
--- /dev/null
+++ b/contrib/groff/src/roff/groff/pipeline.c
@@ -0,0 +1,411 @@
+/* Copyright (C) 1989, 1990, 1991, 1992, 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. */
+
+/*
+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
+
+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 *i_to_a P((int));
+
+/* MSVC can support asynchronous processes, but it's unlikely to have
+ fork(). So, until someone writes an emulation, let them at least
+ have a workable groff by using the good-ole DOS pipe simulation
+ via temporary files... */
+
+#if defined(__MSDOS__) || (defined(_WIN32) && !defined(__CYGWIN32__))
+
+#include <process.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "nonposix.h"
+
+/* A signal handler that just records that a signal has happened. */
+static int child_interrupted;
+
+static RETSIGTYPE signal_catcher (int signo)
+{
+ child_interrupted++;
+}
+
+static const char *sh = "sh";
+static const char *command = "command";
+
+const char *
+system_shell_name (void)
+{
+ static const char *shell_name;
+
+ /* We want them to be able to use a Unixy shell if they have it
+ installed. Let spawnlp try to find it, but if it fails, default
+ to COMMAND.COM. */
+ if (shell_name == NULL)
+ {
+ int sh_found = spawnlp (P_WAIT, sh, sh, "-c", ":", NULL) == 0;
+
+ if (sh_found)
+ shell_name = sh;
+ else
+ shell_name = command;
+ }
+ return shell_name;
+}
+
+const char *
+system_shell_dash_c (void)
+{
+ if (strcmp (system_shell_name(), sh) == 0)
+ return "-c";
+ else
+ return "/c";
+}
+
+int
+is_system_shell (const char *shell)
+{
+ size_t shlen;
+ size_t ibase = 0, idot, i;
+
+ if (!shell) /* paranoia */
+ return 0;
+ idot = shlen = strlen(shell);
+
+ for (i = 0; i < shlen; i++)
+ {
+ if (shell[i] == '.')
+ idot = i;
+ else if (shell[i] == '/' || shell[i] == '\\' || shell[i] == ':')
+ {
+ ibase = i + 1;
+ idot = shlen;
+ }
+ }
+
+ /* "sh" and "sh.exe" should compare equal. */
+ return
+ (strncasecmp (shell + ibase, system_shell_name (), idot - ibase) == 0
+ && (idot == shlen
+ || strcasecmp (shell + idot, ".exe") == 0
+ || strcasecmp (shell + idot, ".com") == 0));
+}
+
+/* MSDOS doesn't have `fork', so we need to simulate the pipe by
+ running the programs in sequence with redirected standard streams. */
+
+int run_pipeline (ncommands, commands, no_pipe)
+ int ncommands;
+ char ***commands;
+ int no_pipe;
+{
+ int save_stdin = dup(0);
+ int save_stdout = dup(1);
+ char *tmpfiles[2];
+ char tem1[L_tmpnam], tem2[L_tmpnam];
+ int infile = 0;
+ int outfile = 1;
+ int i, f, ret = 0;
+
+ tmpfiles[0] = tmpnam(tem1);
+ tmpfiles[1] = tmpnam(tem2);
+
+ for (i = 0; i < ncommands; i++)
+ {
+ int exit_status;
+ RETSIGTYPE (*prev_handler)(int);
+
+ if (i)
+ {
+ /* redirect stdin from temp file */
+ f = open(tmpfiles[infile], O_RDONLY|O_BINARY, 0666);
+ if (f < 0)
+ sys_fatal("open stdin");
+ if (dup2(f, 0) < 0)
+ sys_fatal("dup2 stdin");
+ if (close(f) < 0)
+ sys_fatal("close stdin");
+ }
+ if ((i < ncommands - 1) && !no_pipe)
+ {
+ /* redirect stdout to temp file */
+ f = open(tmpfiles[outfile], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
+ if (f < 0)
+ sys_fatal("open stdout");
+ if (dup2(f, 1) < 0)
+ sys_fatal("dup2 stdout");
+ if (close(f) < 0)
+ sys_fatal("close stdout");
+ }
+ else if (dup2(save_stdout, 1) < 0)
+ sys_fatal("restore stdout");
+
+ /* run the program */
+ child_interrupted = 0;
+ prev_handler = signal(SIGINT, signal_catcher);
+ exit_status = spawnvp(P_WAIT, commands[i][0], commands[i]);
+ signal(SIGINT, prev_handler);
+ if (child_interrupted)
+ {
+ error("%1: Interrupted", commands[i][0], (char *)0, (char *)0);
+ ret |= 2;
+ }
+ else if (exit_status < 0)
+ {
+ error("couldn't exec %1: %2", commands[i][0],
+ strerror(errno), (char *)0);
+ fflush(stderr); /* just in case error() doesn't */
+ ret |= 4;
+ }
+ if (exit_status != 0)
+ ret |= 1;
+
+ /* There's no sense to continue with the pipe if one of the
+ programs has ended abnormally, is there? */
+ if (ret != 0)
+ break;
+
+ /* swap temp files: make output of this program be input for the next */
+ infile = 1 - infile;
+ outfile = 1 - outfile;
+ }
+
+ if (dup2(save_stdin, 0) < 0)
+ sys_fatal("restore stdin");
+
+ unlink(tmpfiles[0]);
+ unlink(tmpfiles[1]);
+
+ return ret;
+}
+
+#else /* not __MSDOS__, not _WIN32 */
+
+int run_pipeline(ncommands, commands, no_pipe)
+ int ncommands;
+ char ***commands;
+ int no_pipe;
+{
+ 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) && !no_pipe) {
+ 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) && !no_pipe) {
+ 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) && !no_pipe) {
+ 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",
+ i_to_a(status), (char *)0, (char *)0);
+ break;
+ }
+ }
+ return ret;
+}
+
+#endif /* not __MSDOS__, not _WIN32 */
+
+static void sys_fatal(s)
+ const char *s;
+{
+ c_fatal("%1: %2", s, strerror(errno), (char *)0);
+}
+
+static char *i_to_a(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/contrib/groff/src/roff/groff/pipeline.h b/contrib/groff/src/roff/groff/pipeline.h
new file mode 100644
index 0000000..abb4b0c
--- /dev/null
+++ b/contrib/groff/src/roff/groff/pipeline.h
@@ -0,0 +1,30 @@
+/* Copyright (C) 1989, 1990, 1991, 1992, 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. */
+
+#ifdef __cplusplus
+extern "C" {
+ int run_pipeline(int, char ***, int);
+}
+#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/contrib/groff/src/roff/grog/Makefile.sub b/contrib/groff/src/roff/grog/Makefile.sub
new file mode 100644
index 0000000..054d06e
--- /dev/null
+++ b/contrib/groff/src/roff/grog/Makefile.sub
@@ -0,0 +1,26 @@
+MAN1=grog.n
+CLEANADD=grog
+NAMEPREFIX=$(g)
+
+all: grog
+
+grog: grog.pl grog.sh
+ if test -n "$(PERLPATH)" && test -f "$(PERLPATH)"; then \
+ rm -f $@; \
+ sed -e "s|/usr/bin/perl|$(PERLPATH)|" \
+ -e "s|@VERSION@|$(version)$(revision)|" $(srcdir)/grog.pl >$@; \
+ else \
+ rm -f $@; \
+ sed -e "s|@g@|$(g)|g" \
+ -e "s|@VERSION@|$(version)$(revision)|" \
+ -e $(SH_SCRIPT_SED_CMD) $(srcdir)/grog.sh >$@; \
+ fi
+ chmod +x $@
+
+install_data: grog
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/grog
+ $(INSTALL_SCRIPT) grog $(bindir)/grog
+
+uninstall_sub:
+ -rm -f $(bindir)/grog
diff --git a/contrib/groff/src/roff/grog/grog.man b/contrib/groff/src/roff/grog/grog.man
new file mode 100644
index 0000000..4a2d311
--- /dev/null
+++ b/contrib/groff/src/roff/grog/grog.man
@@ -0,0 +1,86 @@
+.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 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 \-mdoc,
+.BR \-mdoc-old,
+.BR \-p ,
+.BR \-R ,
+.BR \-g ,
+.BR \-G ,
+.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.
+The only options recognized are
+.B \-C
+(which is also passed on) to enable compatibility mode, and
+.B \-v
+to print the version number.
+.LP
+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@refer (@MAN1EXT@),
+.BR @g@grn (@MAN1EXT@),
+.BR grap (1),
+.BR @g@soelim (@MAN1EXT@)
diff --git a/contrib/groff/src/roff/grog/grog.pl b/contrib/groff/src/roff/grog/grog.pl
new file mode 100644
index 0000000..57cd159
--- /dev/null
+++ b/contrib/groff/src/roff/grog/grog.pl
@@ -0,0 +1,183 @@
+#!/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@.*/@@;
+
+$sp = "[\\s\\n]";
+
+push(@command, "groff");
+
+while ($ARGV[0] =~ /^-./) {
+ $arg = shift(@ARGV);
+ $sp = "" if $arg eq "-C";
+ &usage(0) if $arg eq "-v" || $arg eq "--version";
+ &help() if $arg eq "--help";
+ 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$sp/) {
+ $_ = <FILE>;
+ if (!/^\./) {
+ $tbl++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.EQ$sp/) {
+ $_ = <FILE>;
+ if (!/^\./ || /^\.[0-9]/) {
+ $eqn++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.GS$sp/) {
+ $_ = <FILE>;
+ if (!/^\./) {
+ $grn++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.G1$sp/) {
+ $_ = <FILE>;
+ if (!/^\./) {
+ $grap++;
+ $pic++;
+ $soelim++ if $level;
+ }
+ }
+ elsif (/^\.PS$sp([ 0-9.<].*)?$/) {
+ if (/^\.PS\s*<\s*(\S+)/) {
+ $pic++;
+ $soelim++ if $level;
+ &process($1, $level);
+ }
+ else {
+ $_ = <FILE>;
+ if (!/^\./ || /^\.ps/) {
+ $pic++;
+ $soelim++ if $level;
+ }
+ }
+ }
+ elsif (/^\.R1$sp/ || /^\.\[$sp/) {
+ $refer++;
+ $soelim++ if $level;
+ }
+ elsif (/^\.[PLI]P$sp/) {
+ $PP++;
+ }
+ elsif (/^\.P$/) {
+ $P++;
+ }
+ elsif (/^\.(PH|SA)$sp/) {
+ $mm++;
+ }
+ elsif (/^\.TH$sp/) {
+ $TH++;
+ }
+ elsif (/^\.SH$sp/) {
+ $SH++;
+ }
+ elsif (/^\.([pnil]p|sh)$sp/) {
+ $me++;
+ }
+ elsif (/^\.Dd$sp/) {
+ $mdoc++;
+ }
+ elsif (/^\.(Tp|Dp|De|Cx|Cl)$sp/) {
+ $mdoc_old = 1;
+ }
+ # In the old version of -mdoc `Oo' is a toggle, in the new it's
+ # closed by `Oc'.
+ elsif (/^\.Oo$sp/) {
+ $Oo++;
+ }
+ elsif (/^\.Oc$sp/) {
+ $Oo--;
+ }
+ if (/^\.so$sp/) {
+ chop;
+ s/^.so *//;
+ s/\\\".*//;
+ s/ .*$//;
+ &process($_, $level + 1) unless /\\/ || $_ eq "";
+ }
+ }
+ close(FILE);
+}
+
+sub usage {
+ local($exit_status) = $_;
+ print "GNU grog (groff) version @VERSION@\n";
+ exit $exit_status;
+}
+
+sub help {
+ print "usage: grog [ option ...] [files...]\n";
+ exit 0;
+}
+
+if ($pic || $tbl || $eqn || $grn || $grap || $refer) {
+ $s = "-";
+ $s .= "s" if $soelim;
+ $s .= "R" if $refer;
+ # grap must be run before pic
+ $s .= "G" if $grap;
+ $s .= "p" if $pic;
+ $s .= "g" if $grn;
+ $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/contrib/groff/src/roff/grog/grog.sh b/contrib/groff/src/roff/grog/grog.sh
new file mode 100644
index 0000000..7919dbf
--- /dev/null
+++ b/contrib/groff/src/roff/grog/grog.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+# grog -- guess options for groff command
+# Like doctype in Kernighan & Pike, Unix Programming Environment, pp 306-8.
+
+soelim=@g@soelim
+
+opts=
+sp="([ ]|$)"
+
+for arg
+do
+ case "$arg" in
+ --)
+ shift; break;;
+ -)
+ break;;
+ -C)
+ sp=; opts="$opts -C"; shift; break;;
+ -v | --version)
+ echo "GNU grog (groff) version @VERSION@"
+ exit 0;;
+ --help)
+ echo "usage: grog [ option ...] [files...]"
+ exit 0;;
+ -*)
+ opts="$opts $arg"; shift;;
+ *)
+ break;;
+ esac
+done
+
+egrep -h "^\.(P|PS|[PLI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|Oc|TS|EQ|TH|SH|so|\[|R1|GS|G1|PH|SA)$sp" $* \
+| sed -e '/^\.so/s/^.*$/.SO_START\
+&\
+.SO_END/' \
+| $soelim \
+| egrep '^\.(P|PS|[PLI]P|[pnil]p|sh|Dd|Tp|Dp|De|Cx|Cl|Oo|Oc|TS|EQ|TH|SH|\[|R1|GS|G1|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++ }
+/^\.GS/ { grn++; if (so > 0) soelim++ }
+/^\.G1/ { grap++; pic++; 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 || grn > 0 || grap > 0 || eqn > 0 || refer > 0) {
+ printf " -"
+ if (soelim > 0) printf "s"
+ if (refer > 0) printf "R"
+ if (grn > 0) printf "g"
+ if (grap > 0) printf "G"
+ 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/contrib/groff/src/roff/nroff/Makefile.sub b/contrib/groff/src/roff/nroff/Makefile.sub
new file mode 100644
index 0000000..b9cb482
--- /dev/null
+++ b/contrib/groff/src/roff/nroff/Makefile.sub
@@ -0,0 +1,20 @@
+MAN1=nroff.n
+NAMEPREFIX=$(g)
+CLEANADD=nroff
+
+all: nroff
+
+nroff: nroff.sh
+ rm -f $@
+ sed -e "s|@BINDIR@|$(bindir)|g" \
+ -e $(SH_SCRIPT_SED_CMD) \
+ -e "s|@VERSION@|$(version)$(revision)|" $(srcdir)/nroff.sh >$@
+ chmod +x $@
+
+install_data: nroff
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/$(NAMEPREFIX)nroff
+ $(INSTALL_SCRIPT) nroff $(bindir)/$(NAMEPREFIX)nroff
+
+uninstall_sub:
+ -rm -f $(bindir)/$(NAMEPREFIX)nroff
diff --git a/contrib/groff/src/roff/troff/Makefile.sub b/contrib/groff/src/roff/troff/Makefile.sub
new file mode 100644
index 0000000..e883959
--- /dev/null
+++ b/contrib/groff/src/roff/troff/Makefile.sub
@@ -0,0 +1,48 @@
+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)/input.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`\"\; >>$@
diff --git a/contrib/groff/src/roff/troff/TODO b/contrib/groff/src/roff/troff/TODO
new file mode 100644
index 0000000..6660597
--- /dev/null
+++ b/contrib/groff/src/roff/troff/TODO
@@ -0,0 +1,134 @@
+A line prefix request to make e.g. French quotation possible:
+
+ He said: >> blablablabla
+ >> blablabla blabla bla
+ >> blabla blabla bla bla
+ >> bla bla bla blablabla
+ >> blabla. <<
+
+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. \='...'...'...' 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.
+
+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).
+
+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.
+
+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 (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.
+
+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.
diff --git a/contrib/groff/src/roff/troff/charinfo.h b/contrib/groff/src/roff/troff/charinfo.h
new file mode 100644
index 0000000..a4ecd57
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/troff/column.cc b/contrib/groff/src/roff/troff/column.cc
new file mode 100644
index 0000000..8d6a6eb
--- /dev/null
+++ b/contrib/groff/src/roff/troff/column.cc
@@ -0,0 +1,732 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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. */
+
+#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 i_to_a(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 i_to_a(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/contrib/groff/src/roff/troff/dictionary.cc b/contrib/groff/src/roff/troff/dictionary.cc
new file mode 100644
index 0000000..169536c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/troff/dictionary.h b/contrib/groff/src/roff/troff/dictionary.h
new file mode 100644
index 0000000..4f319be
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/troff/div.cc b/contrib/groff/src/roff/troff/div.cc
new file mode 100644
index 0000000..281c1af
--- /dev/null
+++ b/contrib/groff/src/roff/troff/div.cc
@@ -0,0 +1,1161 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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, int boxing)
+{
+ tok.skip();
+ symbol nm = get_name();
+ if (nm.is_null()) {
+ if (curdiv->prev) {
+ if (boxing) {
+ curenv->line = curdiv->saved_line;
+ curenv->width_total = curdiv->saved_width_total;
+ curenv->space_total = curdiv->saved_space_total;
+ curenv->saved_indent = curdiv->saved_saved_indent;
+ curenv->target_text_length = curdiv->saved_target_text_length;
+ curenv->prev_line_interrupted = curdiv->saved_prev_line_interrupted;
+ }
+ 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;
+ if (boxing) {
+ curdiv->saved_line = curenv->line;
+ curdiv->saved_width_total = curenv->width_total;
+ curdiv->saved_space_total = curenv->space_total;
+ curdiv->saved_saved_indent = curenv->saved_indent;
+ curdiv->saved_target_text_length = curenv->target_text_length;
+ curdiv->saved_prev_line_interrupted = curenv->prev_line_interrupted;
+ curenv->line = 0;
+ curenv->start_line();
+ }
+ }
+ skip_line();
+}
+
+void divert()
+{
+ do_divert(0, 0);
+}
+
+void divert_append()
+{
+ do_divert(1, 0);
+}
+
+void box()
+{
+ do_divert(0, 1);
+}
+
+void box_append()
+{
+ do_divert(1, 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);
+ }
+ }
+ 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);
+ 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, width);
+ 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;
+ curenv->add_html_tag(".po", n.to_units());
+ 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;
+ curenv->add_html_tag(".sp", n.to_units());
+ 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 (!has_arg() || !get_vunits(&x, 'v'))
+ x = curenv->get_vertical_spacing();
+ 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();
+ curenv->add_html_tag(".fl");
+ 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 i_to_a(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 i_to_a(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 i_to_a(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 i_to_a(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 i_to_a(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 i_to_a(topdiv->get_next_page_number());
+}
+
+class page_ejecting_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *page_ejecting_reg::get_string()
+{
+ return i_to_a(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 i_to_a(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("box", box);
+ init_request("boxa", box_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/contrib/groff/src/roff/troff/div.h b/contrib/groff/src/roff/troff/div.h
new file mode 100644
index 0000000..83f9e33
--- /dev/null
+++ b/contrib/groff/src/roff/troff/div.h
@@ -0,0 +1,156 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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, int boxing);
+ friend void end_diversions();
+ diversion *prev;
+ node *saved_line;
+ hunits saved_width_total;
+ int saved_space_total;
+ hunits saved_saved_indent;
+ hunits saved_target_text_length;
+ int saved_prev_line_interrupted;
+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/contrib/groff/src/roff/troff/env.cc b/contrib/groff/src/roff/troff/env.cc
new file mode 100644
index 0000000..56f357c
--- /dev/null
+++ b/contrib/groff/src/roff/troff/env.cc
@@ -0,0 +1,3439 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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 "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);
+ emitted_node = 1;
+ } 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" {
+
+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)
+{
+ int s;
+ 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, &s);
+ 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, &space_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;
+ hunits sw = env_space_width(this);
+ hunits ssw = env_sentence_space_width(this);
+ if (!translate_space_to_dummy) {
+ x = sw;
+ if (node_list_ends_sentence(line) == 1)
+ x += ssw;
+ }
+ width_list *w = new width_list(sw, ssw);
+ if (node_list_ends_sentence(line) == 1)
+ w->next = new width_list(sw, ssw);
+ if (line != 0 && line->merge_space(x, sw, ssw)) {
+ width_total += x;
+ return;
+ }
+ add_node(new word_space_node(x, w));
+ possibly_break_line(0, spread_flag);
+ spread_flag = 0;
+}
+
+void environment::space()
+{
+ space(env_space_width(this), env_sentence_space_width(this));
+}
+
+void environment::space(hunits space_width, hunits sentence_space_width)
+{
+ if (interrupted)
+ return;
+ if (current_field && padding_indicator_char == 0) {
+ add_padding();
+ return;
+ }
+ hunits x = translate_space_to_dummy ? H0 : space_width;
+ 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 : sentence_space_width;
+ if (p->merge_space(xx, space_width, sentence_space_width)) {
+ *tp += xx;
+ return;
+ }
+ }
+ if (p && p->merge_space(x, space_width, sentence_space_width)) {
+ *tp += x;
+ return;
+ }
+ add_node(new word_space_node(x,
+ new width_list(space_width,
+ sentence_space_width)));
+ possibly_break_line(0, spread_flag);
+ spread_flag = 0;
+}
+
+node *do_underline_special(int);
+
+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;
+ }
+ if (underline_spaces && fontno != prev_fontno) {
+ if (fontno == get_underline_fontno())
+ add_node(do_underline_special(1));
+ if (prev_fontno == get_underline_fontno())
+ add_node(do_underline_special(0));
+ }
+}
+
+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),
+ underline_spaces(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),
+ line_tabs(0),
+ 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 */
+ need_eol(0),
+ ignore_next_eol(0),
+ emitted_node(0),
+ 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),
+ underline_spaces(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),
+ line_tabs(e->line_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 */
+ need_eol(0),
+ ignore_next_eol(0),
+ 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)
+{
+}
+
+void environment::copy(const environment *e)
+{
+ 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;
+ prev_requested_size = e->prev_requested_size;
+ requested_size = e->requested_size;
+ char_height = e->char_height;
+ char_slant = e->char_slant;
+ 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;
+ have_temporary_indent = 0;
+ temporary_indent = 0;
+ underline_lines = 0;
+ underline_spaces = 0;
+ input_trap_count = 0;
+ prev_text_length = e->prev_text_length;
+ width_total = 0;
+ space_total = 0;
+ input_line_start = 0;
+ control_char = e->control_char;
+ no_break_control_char = e->no_break_control_char;
+ hyphen_indicator_char = e->hyphen_indicator_char;
+ spread_flag = 0;
+ line = 0;
+ pending_lines = 0;
+ discarding = 0;
+ tabs = e->tabs;
+ line_tabs = e->line_tabs;
+ current_tab = TAB_NONE;
+ current_field = 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_multiple = e->line_number_multiple;
+ line_number_indent = e->line_number_indent;
+ no_number_count = e->no_number_count;
+ tab_char = e->tab_char;
+ leader_char = e->leader_char;
+ hyphenation_flags = e->hyphenation_flags;
+ fontno = e->fontno;
+ prev_fontno = e->prev_fontno;
+ dummy = e->dummy;
+ family = e->family;
+ prev_family = e->prev_family;
+ leader_node = 0;
+#ifdef WIDOW_CONTROL
+ widow_control = e->widow_control;
+#endif /* WIDOW_CONTROL */
+ hyphen_line_max = e->hyphen_line_max;
+ hyphen_line_count = 0;
+ hyphenation_space = e->hyphenation_space;
+ hyphenation_margin = e->hyphenation_margin;
+ composite = 0;
+}
+
+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(i_to_a(n));
+ curenv = env_table[n];
+ }
+ else
+ nm = i_to_a(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();
+}
+
+void environment_copy()
+{
+ symbol nm;
+ environment *e=0;
+ tok.skip();
+ if (!tok.delimiter()) {
+ // It looks like a number.
+ int n;
+ if (get_integer(&n)) {
+ if (n >= 0 && n < NENVIRONMENTS)
+ e = env_table[n];
+ else
+ nm = i_to_a(n);
+ }
+ }
+ else
+ nm = get_long_name(1);
+ if (!e && !nm.is_null())
+ e = (environment *)env_dictionary.lookup(nm);
+ if (e == 0) {
+ error("No environment to copy from");
+ return;
+ }
+ else
+ curenv->copy(e);
+ 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();
+ 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);
+ curenv->add_html_tag(".ps", n);
+ }
+ else
+ curenv->set_size(0);
+ skip_line();
+}
+
+void space_size()
+{
+ int n;
+ if (get_integer(&n) && !compatible_flag) {
+ 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;
+ curenv->add_html_tag(".fi");
+ tok.next();
+}
+
+void no_fill()
+{
+ while (!tok.newline() && !tok.eof())
+ tok.next();
+ if (break_flag)
+ curenv->do_break();
+
+ curenv->fill = 0;
+ curenv->add_html_tag(".nf");
+ curenv->ignore_next_eol = 1;
+ curenv->add_html_tag(".po", topdiv->get_page_offset().to_units());
+ 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;
+ curenv->add_html_tag(".ce", 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;
+ curenv->add_html_tag(".rj", 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;
+ curenv->add_html_tag(".ll", temp.to_units());
+ 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;
+ curenv->add_html_tag(".in", temp.to_units());
+ 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;
+ curenv->add_html_tag(".ti", temp.to_units());
+ }
+ tok.next();
+}
+
+node *do_underline_special(int underline_spaces)
+{
+ macro m;
+ m.append_str("x u ");
+ m.append(underline_spaces + '0');
+ return new special_node(m, 1);
+}
+
+void do_underline(int underline_spaces)
+{
+ 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;
+ if (underline_spaces) {
+ curenv->underline_spaces = 0;
+ curenv->add_node(do_underline_special(0));
+ }
+ }
+ curenv->underline_lines = 0;
+ }
+ else {
+ curenv->underline_lines = n;
+ curenv->pre_underline_fontno = curenv->fontno;
+ curenv->fontno = get_underline_fontno();
+ if (underline_spaces) {
+ curenv->underline_spaces = 1;
+ curenv->add_node(do_underline_special(1));
+ }
+ }
+ skip_line();
+}
+
+void continuous_underline()
+{
+ do_underline(1);
+}
+
+void underline()
+{
+ do_underline(0);
+}
+
+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 (underline_spaces) {
+ underline_spaces = 0;
+ add_node(do_underline_special(0));
+ }
+ }
+ }
+ 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(int start_here)
+{
+ if (line == 0)
+ return;
+ hyphenation_type prev_type = line->get_hyphenation_type();
+ node **startp;
+ if (start_here)
+ startp = &line;
+ else
+ 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 start_here, 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(start_here);
+ 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();
+}
+
+/*
+ * add_html_tag_eol - add an end of line tag if appropriate.
+ */
+
+void environment::add_html_tag_eol()
+{
+ if (is_html) {
+ if (ignore_next_eol > 0)
+ ignore_next_eol--;
+ else if (need_eol > 0) {
+ need_eol--;
+ add_html_tag("eol");
+ }
+ else if (!fill && emitted_node) {
+ add_html_tag("eol");
+ emitted_node = 0;
+ }
+ }
+}
+
+/*
+ * add_html_tag - emits a special html-tag: to help post-grohtml understand
+ * the key troff commands
+ */
+
+void environment::add_html_tag(const char *name)
+{
+ if (is_html) {
+ /*
+ * need to emit tag for post-grohtml
+ * but we check to see whether we can emit specials
+ */
+ if (curdiv == topdiv && topdiv->before_first_page)
+ topdiv->begin_page();
+ macro *m = new macro;
+ m->append_str("html-tag:");
+ for (const char *p = name; *p; p++)
+ if (!illegal_input_char((unsigned char)*p))
+ m->append(*p);
+ add_node(new special_node(*m));
+ }
+}
+
+/*
+ * add_html_tag - emits a special html-tag: to help post-grohtml understand
+ * the key troff commands, it appends a string representation
+ * of i.
+ */
+
+void environment::add_html_tag(const char *name, int i)
+{
+ if (is_html) {
+ if (strcmp(name, ".ce") == 0) {
+ if (i == 0)
+ need_eol = 0;
+ else {
+ need_eol = i;
+ ignore_next_eol = 1; // since the .ce creates an eol
+ }
+ }
+
+ /*
+ * need to emit tag for post-grohtml
+ * but we check to see whether we can emit specials
+ */
+ if (curdiv == topdiv && topdiv->before_first_page)
+ topdiv->begin_page();
+ macro *m = new macro;
+ m->append_str("html-tag:");
+ for (const char *p = name; *p; p++)
+ if (!illegal_input_char((unsigned char)*p))
+ m->append(*p);
+ m->append(' ');
+ m->append_int(i);
+ // output_pending_lines();
+ output(new special_node(*m), !fill, 0, 0, 0);
+ // output_pending_lines();
+ }
+}
+
+/*
+ * add_html_tag_tabs - emits the tab settings for post-grohtml
+ */
+
+void environment::add_html_tag_tabs()
+{
+ if (is_html) {
+ /*
+ * need to emit tag for post-grohtml
+ * but we check to see whether we can emit specials
+ */
+ if (curdiv == topdiv && topdiv->before_first_page)
+ topdiv->begin_page();
+ macro *m = new macro;
+ hunits d, l;
+ enum tab_type t;
+ m->append_str("html-tag:.ta ");
+ do {
+ t = curenv->tabs.distance_to_next_tab(l, &d);
+ l += d;
+ switch (t) {
+ case TAB_LEFT:
+ m->append_str(" L ");
+ m->append_int(d.to_units());
+ break;
+ case TAB_CENTER:
+ m->append_str(" C ");
+ m->append_int(d.to_units());
+ break;
+ case TAB_RIGHT:
+ m->append_str(" R ");
+ m->append_int(d.to_units());
+ break;
+ case TAB_NONE:
+ break;
+ }
+ } while ((t != TAB_NONE) && (l < get_line_length()));
+ output_pending_lines();
+ output(new special_node(*m), !fill, 0, 0, 0);
+ output_pending_lines();
+ }
+}
+
+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();
+ curenv->add_html_tag(".br");
+ }
+ 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, i_to_a(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, i_to_a(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;
+ curenv->add_html_tag_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 line_tabs
+ ? curenv->tabs.distance_to_next_tab(get_text_length(), distance)
+ : 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 line_tabs_request()
+{
+ int n;
+ if (has_arg() && get_integer(&n))
+ curenv->line_tabs = n != 0;
+ else
+ curenv->line_tabs = 1;
+ skip_line();
+}
+
+int environment::get_line_tabs()
+{
+ return line_tabs;
+}
+
+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, 1, 0, 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_html_tag("tab left");
+ add_node(make_tab_node(d));
+ return;
+ case TAB_RIGHT:
+ case TAB_CENTER:
+ add_html_tag("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 i_to_a((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 i_to_a((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 i_to_a((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 i_to_a(sp);
+ if (sp % sizescale == 0)
+ return i_to_a(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 if_to_a(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 if_to_a(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("evc", environment_copy);
+ 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", continuous_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("linetabs", line_tabs_request);
+ 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(".int", get_prev_line_interrupted);
+ 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_int_env_reg(".linetabs", get_line_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 = mac_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/contrib/groff/src/roff/troff/env.h b/contrib/groff/src/roff/troff/env.h
new file mode 100644
index 0000000..256db51
--- /dev/null
+++ b/contrib/groff/src/roff/troff/env.h
@@ -0,0 +1,350 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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;
+ int underline_spaces;
+ 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;
+ int line_tabs;
+ 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 */
+ int need_eol;
+ int ignore_next_eol;
+ int emitted_node; // have we emitted a node since the last html eol tag?
+
+ 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 */
+ breakpoint *choose_breakpoint();
+ void hyphenate_line(int start_here = 0);
+ 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();
+ void copy(const 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_line_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 possibly_break_line(int start_here = 0, int forced = 0);
+ void do_break(); // .br
+ void final_break();
+ void add_html_tag_eol();
+ void add_html_tag(const char *);
+ void add_html_tag(const char *, int);
+ void add_html_tag_tabs();
+ 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(hunits, hunits);
+ 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 do_underline(int);
+ 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 line_tabs_request();
+ friend void title();
+#ifdef WIDOW_CONTROL
+ friend void widow_control_request();
+#endif /* WIDOW_CONTROL */
+
+ friend void do_divert(int append, int boxing);
+};
+
+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 int compatible_flag;
+extern symbol default_family;
+extern int translate_space_to_dummy;
diff --git a/contrib/groff/src/roff/troff/hvunits.h b/contrib/groff/src/roff/troff/hvunits.h
new file mode 100644
index 0000000..8efb5ab
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/troff/input.cc b/contrib/groff/src/roff/troff/input.cc
new file mode 100644
index 0000000..982e5bd
--- /dev/null
+++ b/contrib/groff/src/roff/troff/input.cc
@@ -0,0 +1,6891 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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 "stringclass.h"
+#include "font.h"
+#include "macropath.h"
+#include "defs.h"
+#include "input.h"
+
+// Needed for getpid().
+#include "posix.h"
+
+#include "nonposix.h"
+
+#ifdef NEED_DECLARATION_PUTENV
+extern "C" {
+ int putenv(const char *);
+}
+#endif /* NEED_DECLARATION_PUTENV */
+
+#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 MACRO_PREFIX "tmac."
+#define MACRO_POSTFIX ".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;
+int compatible_flag = 0;
+int ascii_output_flag = 0;
+int suppress_output_flag = 0;
+int is_html = 0;
+int begin_level = 0; // number of nested .begin requests
+
+int tcommand_flag = 0;
+int safer_flag = 1; // safer by default
+
+search_path *mac_path = &safer_macro_path;
+
+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);
+
+
+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();
+}
+
+static int saved_escape_char = '\\';
+
+void save_escape_char()
+{
+ saved_escape_char = escape_char;
+ skip_line();
+}
+
+void restore_escape_char()
+{
+ escape_char = saved_escape_char;
+ 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() { return 0; }
+ virtual int internal_level() { return 0; }
+ virtual int is_file() { return 0; }
+ virtual int is_macro() { 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;
+}
+
+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 input_return_boundary : public input_iterator {
+public:
+ int is_boundary() { return 2; }
+};
+
+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) {
+ curenv->add_html_tag_eol();
+ 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 add_return_boundary();
+ static int is_return_boundary();
+ static void remove_boundary();
+ static int get_level();
+ static void clear();
+ static void pop_macro();
+
+ 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::add_return_boundary()
+{
+ push(new input_return_boundary);
+}
+
+int input_stack::is_return_boundary()
+{
+ return top->is_boundary() == 2;
+}
+
+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_return_boundary();
+}
+
+void input_stack::pop_macro()
+{
+ int nboundaries = 0;
+ int is_macro = 0;
+ do {
+ if (top->next == &nil_iterator)
+ break;
+ if (top->is_boundary())
+ nboundaries++;
+ is_macro = top->is_macro();
+ input_iterator *tem = top;
+ top = top->next;
+ level--;
+ delete tem;
+ } while (!is_macro);
+ // Keep while_request happy.
+ for (; nboundaries > 0; --nboundaries)
+ add_return_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_TILDE;
+ case ':':
+ (void)input_stack::get(NULL);
+ return ESCAPE_COLON;
+ 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 force_tprint();
+};
+
+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";
+}
+
+int non_interpreted_char_node::force_tprint()
+{
+ return 0;
+}
+
+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 node *do_suppress();
+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;
+}
+
+static int do_expr_test()
+{
+ token start;
+ start.next();
+ int start_level = input_stack::get_level();
+ if (!start.delimiter(1))
+ return 0;
+ tok.next();
+ // disable all warning and error messages temporarily
+ int saved_warning_mask = warning_mask;
+ int saved_inhibit_errors = inhibit_errors;
+ warning_mask = 0;
+ inhibit_errors = 1;
+ int dummy;
+ int result = get_number_rigidly(&dummy, 'u');
+ warning_mask = saved_warning_mask;
+ inhibit_errors = saved_inhibit_errors;
+ if (tok == start && input_stack::get_level() == start_level)
+ return result;
+ // ignore everything up to the delimiter in case we aren't right there
+ for (;;) {
+ tok.next();
+ if (tok.newline() || tok.eof()) {
+ warning(WARN_DELIM, "missing closing delimiter");
+ break;
+ }
+ if (tok == start && input_stack::get_level() == start_level)
+ break;
+ }
+ return 0;
+}
+
+#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();
+ int force_tprint();
+};
+
+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";
+}
+
+int token_node::force_tprint()
+{
+ return 0;
+}
+
+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_TILDE:
+ ESCAPE_TILDE:
+ type = TOKEN_STRETCHABLE_SPACE;
+ return;
+ case ESCAPE_COLON:
+ ESCAPE_COLON:
+ type = TOKEN_NODE;
+ nd = new space_node(H0);
+ nd->freeze_space();
+ nd->is_escape_colon();
+ 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_TRANSPARENT_DUMMY;
+ 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 '~':
+ goto ESCAPE_TILDE;
+ case ':':
+ goto ESCAPE_COLON;
+ 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 'B':
+ c = '0' + do_expr_test();
+ type = TOKEN_CHAR;
+ 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 'O':
+ nd = do_suppress();
+ if (!nd)
+ break;
+ 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_STRETCHABLE_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_STRETCHABLE_SPACE:
+ return "`\\~'";
+ case TOKEN_TAB:
+ return "a tab character";
+ case TOKEN_TRANSPARENT:
+ return "`\\!'";
+ case TOKEN_TRANSPARENT_DUMMY:
+ 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 return_macro_request()
+{
+ input_stack::pop_macro();
+ tok.next();
+}
+
+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_STRETCHABLE_SPACE:
+ return ESCAPE_TILDE;
+ 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;
+}
+
+int word_space_node::reread(int *bolp)
+{
+ if (unformat) {
+ for (width_list *w = orig_width; w; w = w->next)
+ curenv->space(w->width, w->sentence_width);
+ unformat = 0;
+ return 1;
+ }
+ return 0;
+}
+
+int unbreakable_space_node::reread(int *)
+{
+ return 0;
+}
+
+int hmotion_node::reread(int *bolp)
+{
+ if (unformat && was_tab) {
+ curenv->handle_tab(0);
+ unformat = 0;
+ return 1;
+ }
+ return 0;
+}
+
+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;
+ curenv->possibly_break_line(1);
+ }
+ 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 {
+public:
+ 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_str(const char *s)
+{
+ int i = 0;
+
+ if (s) {
+ while (s[i] != (char)0) {
+ append(s[i]);
+ i++;
+ }
+ }
+}
+
+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::append_unsigned(unsigned int i)
+{
+ unsigned int j = i / 10;
+ if (j != 0)
+ append_unsigned(j);
+ append(((unsigned char)(((int)'0') + i % 10)));
+}
+
+void macro::append_int(int i)
+{
+ if (i < 0) {
+ append('-');
+ i = -i;
+ }
+ append_unsigned((unsigned int)i);
+}
+
+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);
+ int is_macro() { return 1; }
+};
+
+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 ? ':' : '\a', 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, int indirect)
+{
+ symbol nm, term;
+ if (indirect) {
+ symbol temp1 = get_name(1);
+ if (temp1.is_null()) {
+ skip_line();
+ return;
+ }
+ symbol temp2 = get_name();
+ input_stack::push(make_temp_iterator("\n"));
+ if (!temp2.is_null()) {
+ interpolate_string(temp2);
+ input_stack::push(make_temp_iterator(" "));
+ }
+ interpolate_string(temp1);
+ input_stack::push(make_temp_iterator(" "));
+ tok.next();
+ }
+ if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) {
+ nm = get_name(1);
+ if (nm.is_null()) {
+ skip_line();
+ return;
+ }
+ }
+ 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, 0);
+}
+
+void define_indirect_macro()
+{
+ do_define_macro(DEFINE_NORMAL, 1);
+}
+
+void append_macro()
+{
+ do_define_macro(DEFINE_APPEND, 0);
+}
+
+void ignore()
+{
+ ignoring = 1;
+ do_define_macro(DEFINE_IGNORE, 0);
+ 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 length_macro()
+{
+ symbol ret;
+ ret = get_name(1);
+ if (ret.is_null()) {
+ skip_line();
+ return;
+ }
+ int c;
+ node *n;
+ 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);
+ int len = 0;
+ while (c != '\n' && c != EOF) {
+ ++len;
+ c = get_copy(&n);
+ }
+ tok.next();
+ reg *r = (reg*)number_reg_dictionary.lookup(ret);
+ if (r)
+ r->set_value(len);
+ else
+ set_number_reg(ret, len);
+}
+
+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();
+}
+
+void unformat_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 unformat 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 {
+ if (nd->set_unformat_flag())
+ am.append(nd);
+ }
+ }
+ *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.transparent_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(i_to_a(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();
+ int force_tprint();
+};
+
+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";
+}
+
+int non_interpreted_node::force_tprint()
+{
+ return 0;
+}
+
+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);
+}
+
+node *do_suppress()
+{
+ tok.next();
+ int c = tok.ch();
+ switch (c) {
+ case '0':
+ if (begin_level == 1)
+ return new suppress_node(0, 0);
+ break;
+ case '1':
+ if (begin_level == 1)
+ return new suppress_node(1, 0);
+ break;
+ case '2':
+ if (begin_level == 1)
+ return new suppress_node(1, 1);
+ break;
+ case '3':
+ begin_level++;
+ break;
+ case '4':
+ begin_level--;
+ break;
+ case '5': {
+ symbol filename = get_delim_name();
+ if (begin_level == 1)
+ return new suppress_node(filename, 'i');
+ return 0;
+ break;
+ }
+ default:
+ error("`%1' is an invalid argument to \\O", char(c));
+ }
+ return 0;
+}
+
+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();
+}
+
+void nop_request()
+{
+ while (tok.space())
+ 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();
+ }
+}
+
+/*
+ * begin - if this is the outermost html_begin request then execute the
+ * rest of the line, else skip line
+ */
+
+void begin()
+{
+ begin_level++;
+ if (begin_level == 1)
+ begin_alternative();
+ else
+ skip_alternative();
+}
+
+/*
+ * end - if this is the outermost html_end request then execute the
+ * rest of the line, else skip line
+ */
+
+void end()
+{
+ begin_level--;
+ if (begin_level == 0)
+ begin_alternative();
+ else
+ skip_alternative();
+ if (begin_level < 0)
+ begin_level = 0;
+}
+
+/*
+ * image - implements the directive `.image {l|r|c|i} filename'
+ * which places the filename into a node which is later
+ * written out
+ *
+ * . either as a special in the form of an image tag for -Thtml
+ * . or as an image region definition for all other devices
+ *
+ */
+
+void image()
+{
+ if (has_arg()) {
+ char position = tok.ch();
+ if (!(position == 'l'
+ || position == 'r'
+ || position == 'c'
+ || position == 'i')) {
+ error("l, r, c, or i expected (got %1)", tok.description());
+ position = 'c';
+ }
+ tok.next();
+ symbol filename = get_long_name(1);
+ if (!filename.is_null())
+ curenv->add_node(new suppress_node(filename, position));
+ }
+ skip_line();
+}
+
+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 || input_stack::is_return_boundary()) {
+ 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()
+{
+ if (safer_flag) {
+ error(".pso request not allowed in safer mode");
+ skip_line();
+ }
+ else {
+#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, POPEN_RT);
+ 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;
+}
+
+inline void assign_registers(int llx, int lly, int urx, int ury)
+{
+ llx_reg_contents = llx;
+ lly_reg_contents = lly;
+ urx_reg_contents = urx;
+ ury_reg_contents = ury;
+}
+
+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) {
+ assign_registers(bb.llx, bb.lly, bb.urx, bb.ury);
+ return;
+ } 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) {
+ assign_registers(bb.llx, bb.lly, bb.urx, bb.ury);
+ return;
+ }
+ }
+ }
+ error("%%%%BoundingBox comment not found in `%1'", filename);
+}
+
+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;
+ // PS files might contain non-printable characters, such as ^Z
+ // and CRs not followed by an LF, so open them in binary mode.
+ FILE *fp = fopen(nm.contents(), FOPEN_RB);
+ if (fp) {
+ do_ps_file(fp, nm.contents());
+ fclose(fp);
+ }
+ 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_RIGHT_PARENTHESIS:
+ 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;
+ case ESCAPE_TILDE:
+ buf[1] = '~';
+ break;
+ case ESCAPE_COLON:
+ 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, .tm1, and .tmc
+
+void do_terminal(int newline, int string_like)
+{
+ if (!tok.newline() && !tok.eof()) {
+ int c;
+ for (;;) {
+ c = get_copy(NULL);
+ if (string_like && c == '"') {
+ c = get_copy(NULL);
+ break;
+ }
+ if (c != ' ' && c != '\t')
+ break;
+ }
+ for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ fputs(asciify(c), stderr);
+ }
+ if (newline)
+ fputc('\n', stderr);
+ fflush(stderr);
+ tok.next();
+}
+
+void terminal()
+{
+ do_terminal(1, 0);
+}
+
+void terminal1()
+{
+ do_terminal(1, 1);
+}
+
+void terminal_continue()
+{
+ do_terminal(0, 1);
+}
+
+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()
+{
+ if (safer_flag) {
+ error(".open request not allowed in safer mode");
+ skip_line();
+ }
+ else
+ do_open(0);
+}
+
+void opena_request()
+{
+ if (safer_flag) {
+ error(".opena request not allowed in safer mode");
+ skip_line();
+ }
+ else
+ 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, i_to_a(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.stretchable_space())
+ ci1->set_special_translation(charinfo::TRANSLATE_STRETCHABLE_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());
+}
+
+// this is for \Z
+
+int token::add_to_node_list(node **pp)
+{
+ hunits w;
+ int s;
+ node *n = 0;
+ switch (type) {
+ case TOKEN_CHAR:
+ *pp = (*pp)->add_char(charset_table[c], curenv, &w, &s);
+ 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, &s);
+ 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, &s);
+ 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, &s);
+ break;
+ case TOKEN_STRETCHABLE_SPACE:
+ n = new unbreakable_space_node(curenv->get_space_width());
+ break;
+ case TOKEN_TRANSPARENT_DUMMY:
+ n = new transparent_dummy_node;
+ 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_EMPTY:
+ assert(0);
+ break;
+ case TOKEN_EOF:
+ 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_STRETCHABLE_SPACE:
+ curenv->add_node(new unbreakable_space_node(curenv->get_space_width()));
+ break;
+ case TOKEN_TAB:
+ curenv->handle_tab(0);
+ break;
+ case TOKEN_TRANSPARENT:
+ break;
+ case TOKEN_TRANSPARENT_DUMMY:
+ curenv->add_node(new transparent_dummy_node);
+ break;
+ default:
+ assert(0);
+ }
+}
+
+class nargs_reg : public reg {
+public:
+ const char *get_string();
+};
+
+const char *nargs_reg::get_string()
+{
+ return i_to_a(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 i_to_a(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 i_to_a(*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()
+{
+ if (safer_flag) {
+ error(".pi request not allowed in safer mode");
+ skip_line();
+ }
+ else {
+#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()
+{
+ if (safer_flag) {
+ error(".sy request not allowed in safer mode");
+ skip_line();
+ }
+ else {
+ 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)
+{
+ // Try first FOOBAR.tmac, then tmac.FOOBAR
+ char *s1 = new char[strlen(mac)+strlen(MACRO_POSTFIX)+1];
+ strcpy(s1, mac);
+ strcat(s1, MACRO_POSTFIX);
+ FILE *fp = mac_path->open_file(s1, path);
+ a_delete s1;
+ if (!fp) {
+ char *s2 = new char[strlen(mac)+strlen(MACRO_PREFIX)+1];
+ strcpy(s2, MACRO_PREFIX);
+ strcat(s2, mac);
+ fp = mac_path->open_file(s2, path);
+ a_delete s2;
+ }
+ 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;
+ search_path *orig_mac_path = mac_path;
+ mac_path = &config_macro_path;
+ FILE *fp = mac_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();
+ }
+ mac_path = orig_mac_path;
+}
+
+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 = mac_path->open_file(nm.contents(), &path);
+ // .mso doesn't (and cannot) go through open_mac_file, so we
+ // need to do it here manually: If we have tmac.FOOBAR, try
+ // FOOBAR.tmac and vice versa
+ if (!fp) {
+ const char *fn = nm.contents();
+ if (strncasecmp(fn, MACRO_PREFIX, sizeof(MACRO_PREFIX) - 1) == 0) {
+ char *s = new char[strlen(fn) + sizeof(MACRO_POSTFIX)];
+ strcpy(s, fn + sizeof(MACRO_PREFIX) - 1);
+ strcat(s, MACRO_POSTFIX);
+ fp = mac_path->open_file(s, &path);
+ a_delete s;
+ }
+ if (!fp) {
+ if (strncasecmp(fn + strlen(fn) - sizeof(MACRO_POSTFIX) + 1,
+ MACRO_POSTFIX, sizeof(MACRO_POSTFIX) - 1) == 0) {
+ char *s = new char[strlen(fn) + sizeof(MACRO_PREFIX)];
+ strcpy(s, MACRO_PREFIX);
+ strncat(s, fn, strlen(fn) - sizeof(MACRO_POSTFIX) + 1);
+ fp = mac_path->open_file(s, &path);
+ a_delete s;
+ }
+ }
+ }
+ 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(FILE *stream, const char *prog)
+{
+ fprintf(stream,
+"usage: %s -abivzCERU -wname -Wname -dcs -ffam -mname -nnum -olist\n"
+" -rcn -Tname -Fdir -Mdir [files...]\n",
+ prog);
+}
+
+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 no_rc = 0; // don't process troffrc and troffrc-end
+ int next_page_number;
+ opterr = 0;
+ hresolution = vresolution = 1;
+ // restore $PATH if called from groff
+ char* groff_path = getenv("GROFF_PATH__");
+ if (groff_path) {
+ string e = "PATH";
+ e += '=';
+ if (*groff_path)
+ e += groff_path;
+ e += '\0';
+ if (putenv(strsave(e.contents())))
+ fatal("putenv failed");
+ }
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((c = getopt_long(argc, argv, "abivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU",
+ long_options, NULL))
+ != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *Version_string;
+ printf("GNU troff (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case 'T':
+ device = optarg;
+ tflag = 1;
+ is_html = (strcmp(device, "html") == 0);
+ break;
+ case 'C':
+ compatible_flag = 1;
+ break;
+ case 'M':
+ macro_path.command_line_dir(optarg);
+ safer_macro_path.command_line_dir(optarg);
+ config_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 CHAR_MAX + 1: // --help
+ usage(stdout, argv[0]);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr, argv[0]);
+ exit(1);
+ break; // never reached
+ default:
+ assert(0);
+ }
+ if (!safer_flag)
+ mac_path = &macro_path;
+ 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();
+ init_markup_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);
+ 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"));
+}
+
+/*
+ * registers associated with \O
+ */
+
+static int output_reg_minx_contents = -1;
+static int output_reg_miny_contents = -1;
+static int output_reg_maxx_contents = -1;
+static int output_reg_maxy_contents = -1;
+
+void check_output_limits(int x, int y)
+{
+ if ((output_reg_minx_contents == -1) || (x < output_reg_minx_contents))
+ output_reg_minx_contents = x;
+ if (x > output_reg_maxx_contents)
+ output_reg_maxx_contents = x;
+ if ((output_reg_miny_contents == -1) || (y < output_reg_miny_contents))
+ output_reg_miny_contents = y;
+ if (y > output_reg_maxy_contents)
+ output_reg_maxy_contents = y;
+}
+
+void reset_output_registers(int miny)
+{
+ // fprintf(stderr, "reset_output_registers\n");
+ output_reg_minx_contents = -1;
+ output_reg_miny_contents = -1;
+ output_reg_maxx_contents = -1;
+ output_reg_maxy_contents = -1;
+}
+
+void get_output_registers(int *minx, int *miny, int *maxx, int *maxy)
+{
+ *minx = output_reg_minx_contents;
+ *miny = output_reg_miny_contents;
+ *maxx = output_reg_maxx_contents;
+ *maxy = output_reg_maxy_contents;
+}
+
+void init_markup_requests()
+{
+ init_request("begin", begin);
+ init_request("end", end);
+ init_request("image", image);
+}
+
+void init_input_requests()
+{
+ init_request("ds", define_string);
+ init_request("as", append_string);
+ init_request("de", define_macro);
+ init_request("dei", define_indirect_macro);
+ init_request("am", append_macro);
+ init_request("ig", ignore);
+ init_request("rm", remove_macro);
+ init_request("rn", rename_macro);
+ init_request("nop", nop_request);
+ 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("ecs", save_escape_char);
+ init_request("ecr", restore_escape_char);
+ init_request("pc", set_page_character);
+ init_request("tm", terminal);
+ init_request("tm1", terminal1);
+ init_request("tmc", terminal_continue);
+ init_request("ex", exit_request);
+ init_request("return", return_macro_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("length", length_macro);
+ init_request("asciify", asciify_macro);
+ init_request("unformat", unformat_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));
+ number_reg_dictionary.define("opminx",
+ new variable_reg(&output_reg_minx_contents));
+ number_reg_dictionary.define("opminy",
+ new variable_reg(&output_reg_miny_contents));
+ number_reg_dictionary.define("opmaxx",
+ new variable_reg(&output_reg_maxx_contents));
+ number_reg_dictionary.define("opmaxy",
+ new variable_reg(&output_reg_maxy_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(i_to_a(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/contrib/groff/src/roff/troff/input.h b/contrib/groff/src/roff/troff/input.h
new file mode 100644
index 0000000..525e1ef
--- /dev/null
+++ b/contrib/groff/src/roff/troff/input.h
@@ -0,0 +1,92 @@
+// -*- C++ -*-
+/* Copyright (C) 2001 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. */
+
+
+/* special character codes */
+
+#ifndef IS_EBCDIC_HOST
+
+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;
+const int ESCAPE_TILDE = 0207;
+const int ESCAPE_COLON = 0210;
+
+#else /* IS_EBCDIC_HOST */
+
+const int ESCAPE_QUESTION = 010;
+const int BEGIN_TRAP = 011;
+const int END_TRAP = 013;
+const int PAGE_EJECTOR = 015;
+const int ESCAPE_NEWLINE = 016;
+const int ESCAPE_AMPERSAND = 017;
+const int ESCAPE_UNDERSCORE = 020;
+const int ESCAPE_BAR = 021;
+const int ESCAPE_CIRCUMFLEX = 022;
+const int ESCAPE_LEFT_BRACE = 023;
+const int ESCAPE_RIGHT_BRACE = 024;
+const int ESCAPE_LEFT_QUOTE = 027;
+const int ESCAPE_RIGHT_QUOTE = 030;
+const int ESCAPE_HYPHEN = 031;
+const int ESCAPE_BANG = 032;
+const int ESCAPE_c = 033;
+const int ESCAPE_e = 034;
+const int ESCAPE_PERCENT = 035;
+const int ESCAPE_SPACE = 036;
+
+const int TITLE_REQUEST = 060;
+const int COPY_FILE_REQUEST = 061;
+const int TRANSPARENT_FILE_REQUEST = 062;
+#ifdef COLUMN
+const int VJUSTIFY_REQUEST = 063;
+#endif /* COLUMN */
+const int ESCAPE_E = 064;
+const int LAST_PAGE_EJECTOR = 065;
+const int ESCAPE_RIGHT_PARENTHESIS = 066;
+const int ESCAPE_TILDE = 067;
+const int ESCAPE_COLON = 070;
+
+#endif /* IS_EBCDIC_HOST */
diff --git a/contrib/groff/src/roff/troff/node.cc b/contrib/groff/src/roff/troff/node.cc
new file mode 100644
index 0000000..2d2d799
--- /dev/null
+++ b/contrib/groff/src/roff/troff/node.cc
@@ -0,0 +1,5621 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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_UNISTD_H
+#include <unistd.h>
+#endif
+
+#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"
+#include "input.h"
+
+#include "nonposix.h"
+
+#ifdef _POSIX_VERSION
+
+#include <sys/wait.h>
+
+#else /* not _POSIX_VERSION */
+
+/* traditional Unix */
+
+#define WIFEXITED(s) (((s) & 0377) == 0)
+#define WEXITSTATUS(s) (((s) >> 8) & 0377)
+#define WTERMSIG(s) ((s) & 0177)
+#define WIFSTOPPED(s) (((s) & 0377) == 0177)
+#define WSTOPSIG(s) (((s) >> 8) & 0377)
+#define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177))
+
+#endif /* not _POSIX_VERSION */
+
+/*
+ * how many boundaries of images have been written? Useful for
+ * debugging grohtml
+ */
+
+static int image_no=0;
+static int suppress_start_page=0;
+
+#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; // decision via optional page list
+ int output_on; // .output 1 or .output 0 requests
+ virtual void really_transparent_char(unsigned char) = 0;
+ virtual void really_print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after, hunits width) = 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);
+ virtual void really_on();
+ virtual void really_off();
+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, hunits width);
+ void begin_page(int pageno, vunits page_length);
+ void put_filename(const char *filename);
+ void on();
+ void off();
+ int is_on();
+ 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, hunits width);
+ 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, hunits width);
+ 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(tfont *tf, int no_init_string = 0);
+ void start_special(int no_init_string = 0);
+ 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, hunits width);
+ 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 really_on();
+ void really_off();
+ void draw(char, hvpair *, int, font_size);
+ void determine_line_limits (char code, hvpair *point, int npoints);
+ void check_charinfo(tfont *tf, charinfo *ci);
+ 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(i_to_a(i), fp);
+}
+
+void troff_output_file::start_special(tfont *tf, int no_init_string)
+{
+ flush_tbuf();
+
+ /*
+ * although this is extremely unlikely to have an effect on other devices
+ * this way is safer. Currently this is only needed for html.
+ */
+ if (is_html && tf) {
+ if (tf != current_tfont)
+ set_font(tf);
+ }
+ do_motion();
+ if (!no_init_string)
+ put("x X ");
+}
+
+void troff_output_file::start_special(int no_init_string)
+{
+ flush_tbuf();
+ do_motion();
+ if (!no_init_string)
+ 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, hunits width)
+{
+ moveto(x, y);
+ while (n != 0) {
+ if (is_on() || (n->force_tprint()))
+ 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(' ');
+ }
+ check_output_limits(hpos, vpos);
+ check_output_limits(hpos, vpos + current_size + current_height);
+
+ for (int i = 0; i < tbuf_len; i++)
+ put(tbuf[i]);
+ put('\n');
+ tbuf_len = 0;
+}
+
+void troff_output_file::check_charinfo(tfont *tf, charinfo *ci)
+{
+ int size = tf->get_size().to_scaled_points();
+ int height = tf->get_char_height(ci).to_units();
+ int width = tf->get_width(ci).to_units()
+ + tf->get_italic_correction(ci).to_units();
+ int depth = tf->get_char_depth(ci).to_units();
+ check_output_limits(output_hpos,
+ output_vpos - height);
+ check_output_limits(output_hpos + width,
+ output_vpos + size + depth);
+}
+
+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();
+ check_charinfo(tf, ci);
+ 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) {
+ check_charinfo(tf, ci);
+ tbuf[tbuf_len++] = c;
+ output_hpos += w.to_units() + kk;
+ hpos = output_hpos;
+ return;
+ }
+ flush_tbuf();
+ do_motion();
+ check_charinfo(tf, ci);
+ tbuf[tbuf_len++] = c;
+ output_hpos += w.to_units() + kk;
+ tbuf_kern = kk;
+ hpos = output_hpos;
+ }
+ else {
+ // flush_tbuf();
+ int n = hpos - output_hpos;
+ check_charinfo(tf, ci);
+ // check_output_limits(output_hpos, output_vpos);
+ 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;
+}
+
+// determine_line_limits - works out the smallest box which will contain
+// the entity, code, built from the point array.
+void troff_output_file::determine_line_limits(char code, hvpair *point,
+ int npoints)
+{
+ int i, x, y;
+ switch (code) {
+ case 'c':
+ case 'C':
+ // only the h field is used when defining a circle
+ check_output_limits(output_hpos,
+ output_vpos - point[0].h.to_units()/2);
+ check_output_limits(output_hpos + point[0].h.to_units(),
+ output_vpos + point[0].h.to_units()/2);
+ break;
+ case 'E':
+ case 'e':
+ check_output_limits(output_hpos,
+ output_vpos - point[0].v.to_units()/2);
+ check_output_limits(output_hpos + point[0].h.to_units(),
+ output_vpos + point[0].v.to_units()/2);
+ break;
+ case 'P':
+ case 'p':
+ x = output_hpos;
+ y = output_vpos;
+ check_output_limits(x, y);
+ for (i = 0; i < npoints; i++) {
+ x += point[i].h.to_units();
+ y += point[i].v.to_units();
+ check_output_limits(x, y);
+ }
+ break;
+ case 't':
+ x = output_hpos;
+ y = output_vpos;
+ for (i = 0; i < npoints; i++) {
+ x += point[i].h.to_units();
+ y += point[i].v.to_units();
+ check_output_limits(x, y);
+ }
+ break;
+ default:
+ // remember this doesn't work for arc.. yet
+ x = output_hpos;
+ y = output_vpos;
+ for (i = 0; i < npoints; i++) {
+ x += point[i].h.to_units();
+ y += point[i].v.to_units();
+ check_output_limits(x, y);
+ }
+ }
+}
+
+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());
+ }
+
+ determine_line_limits(code, point, npoints);
+
+ 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_on ()
+{
+ flush_tbuf();
+}
+
+void troff_output_file::really_off ()
+{
+ flush_tbuf();
+}
+
+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)
+{
+}
+
+void output_file::on()
+{
+}
+
+void output_file::off()
+{
+}
+
+real_output_file::real_output_file()
+: printing(0), output_on(1)
+{
+#ifndef POPEN_MISSING
+ if (pipe_command) {
+ if ((fp = popen(pipe_command, POPEN_WT)) != 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 (!WIFEXITED(result))
+ error("output process `%1' got fatal signal %2",
+ pipe_command,
+ WIFSIGNALED(result) ? WTERMSIG(result) : WSTOPSIG(result));
+ else {
+ int exit_status = WEXITSTATUS(result);
+ 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 && output_on)
+ really_begin_page(pageno, page_length);
+}
+
+void real_output_file::copy_file(hunits x, vunits y, const char *filename)
+{
+ if (printing && output_on)
+ really_copy_file(x, y, filename);
+ check_output_limits(x.to_units(), y.to_units());
+}
+
+void real_output_file::transparent_char(unsigned char c)
+{
+ if (printing && output_on)
+ really_transparent_char(c);
+}
+
+void real_output_file::print_line(hunits x, vunits y, node *n,
+ vunits before, vunits after, hunits width)
+{
+ if (printing)
+ really_print_line(x, y, n, before, after, width);
+ 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)
+{
+}
+
+void real_output_file::on()
+{
+ really_on();
+ if (output_on == 0) {
+ output_on = 1;
+ }
+}
+
+void real_output_file::off()
+{
+ really_off();
+ output_on = 0;
+}
+
+int real_output_file::is_on()
+{
+ return( output_on );
+}
+
+void real_output_file::really_on()
+{
+}
+
+void real_output_file::really_off()
+{
+}
+
+/* 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, hunits width)
+{
+ 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, hunits)
+{
+}
+
+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();
+ int force_tprint();
+};
+
+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();
+ int force_tprint();
+};
+
+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();
+ int force_tprint();
+ 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();
+ int force_tprint();
+};
+
+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();
+ int force_tprint();
+ 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";
+}
+
+int hyphen_inhibitor_node::force_tprint()
+{
+ return 0;
+}
+
+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;
+}
+
+int node::force_tprint()
+{
+ 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 *);
+ 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();
+ int force_tprint();
+};
+
+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 *);
+ hyphenation_type get_hyphenation_type();
+ int overlaps_vertically();
+ int overlaps_horizontally();
+ units size();
+ tfont *get_tfont();
+ int same(node *);
+ const char *type();
+ int force_tprint();
+};
+
+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, was_tab, unformat);
+}
+
+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, hunits, 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), was_escape_colon(0)
+{
+}
+
+space_node::space_node(hunits nn, int s, int flag, node *p)
+: node(p), n(nn), set(s), was_escape_colon(flag)
+{
+}
+
+#if 0
+space_node::~space_node()
+{
+}
+#endif
+
+node *space_node::copy()
+{
+ return new space_node(n, set, was_escape_colon);
+}
+
+int space_node::force_tprint()
+{
+ return 0;
+}
+
+int space_node::nspaces()
+{
+ return set ? 0 : 1;
+}
+
+int space_node::merge_space(hunits h, hunits, hunits)
+{
+ 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;
+}
+
+void node::is_escape_colon()
+{
+}
+
+void space_node::is_escape_colon()
+{
+ was_escape_colon = 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::set_unformat_flag()
+{
+ return 1;
+}
+
+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;
+}
+
+void hmotion_node::asciify(macro *m)
+{
+ if (was_tab) {
+ m->append('\t');
+ delete this;
+ }
+ else
+ m->append(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(ESCAPE_SPACE);
+ delete this;
+}
+
+void space_node::asciify(macro *m)
+{
+ if (was_escape_colon) {
+ m->append(ESCAPE_COLON);
+ delete this;
+ }
+ else
+ m->append(this);
+}
+
+void word_space_node::asciify(macro *m)
+{
+ for (width_list *w = orig_width; w; w = w->next)
+ m->append(' ');
+ delete this;
+}
+
+void unbreakable_space_node::asciify(macro *m)
+{
+ m->append(ESCAPE_TILDE);
+ 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;
+}
+
+hyphenation_type hmotion_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+hyphenation_type space_char_hmotion_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+hyphenation_type overstrike_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+hyphenation_type space_node::get_hyphenation_type()
+{
+ if (was_escape_colon)
+ return HYPHEN_MIDDLE;
+ return HYPHEN_BOUNDARY;
+}
+
+hyphenation_type unbreakable_space_node::get_hyphenation_type()
+{
+ return HYPHEN_MIDDLE;
+}
+
+int node::interpret(macro *)
+{
+ return 0;
+}
+
+special_node::special_node(const macro &m, int n)
+: mac(m), no_init_string(n)
+{
+ font_size fs = curenv->get_font_size();
+ int char_height = curenv->get_char_height();
+ int char_slant = curenv->get_char_slant();
+ int fontno = curenv->get_font();
+ tf = font_table[fontno]->get_tfont(fs, char_height, char_slant,
+ fontno);
+ if (curenv->is_composite())
+ tf = tf->get_plain();
+}
+
+special_node::special_node(const macro &m, tfont *t, int n)
+: mac(m), tf(t), no_init_string(n)
+{
+}
+
+int special_node::same(node *n)
+{
+ return ((mac == ((special_node *)n)->mac)
+ && (tf == ((special_node *)n)->tf)
+ && (no_init_string == ((special_node *)n)->no_init_string));
+}
+
+const char *special_node::type()
+{
+ return "special_node";
+}
+
+int special_node::ends_sentence()
+{
+ return 2;
+}
+
+int special_node::force_tprint()
+{
+ return 0;
+}
+
+node *special_node::copy()
+{
+ return new special_node(mac, tf, no_init_string);
+}
+
+void special_node::tprint_start(troff_output_file *out)
+{
+ out->start_special(get_tfont(), no_init_string);
+}
+
+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();
+}
+
+tfont *special_node::get_tfont()
+{
+ return tf;
+}
+
+/* suppress_node */
+
+suppress_node::suppress_node(int on_or_off, int issue_limits)
+: is_on(on_or_off), emit_limits(issue_limits), filename(0), position(0)
+{
+}
+
+suppress_node::suppress_node(symbol f, char p)
+: is_on(2), emit_limits(0), filename(f), position(p)
+{
+}
+
+suppress_node::suppress_node(int issue_limits, int on_or_off,
+ symbol f, char p)
+: is_on(on_or_off), emit_limits(issue_limits), filename(f), position(p)
+{
+}
+
+int suppress_node::same(node *n)
+{
+ return ((is_on == ((suppress_node *)n)->is_on)
+ && (emit_limits == ((suppress_node *)n)->emit_limits)
+ && (filename == ((suppress_node *)n)->filename)
+ && (position == ((suppress_node *)n)->position));
+;
+}
+
+const char *suppress_node::type()
+{
+ return "suppress_node";
+}
+
+node *suppress_node::copy()
+{
+ return new suppress_node(emit_limits, is_on, filename, position);
+}
+
+int get_reg_int(const char *p)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(p);
+ units prev_value;
+ if (r && (r->get_value(&prev_value)))
+ return (int)prev_value;
+ else
+ warning(WARN_REG, "number register `%1' not defined", p);
+ return 0;
+}
+
+const char *get_reg_str(const char *p)
+{
+ reg *r = (reg *)number_reg_dictionary.lookup(p);
+ if (r)
+ return r->get_string();
+ else
+ warning(WARN_REG, "register `%1' not defined", p);
+ return 0;
+}
+
+void suppress_node::put(troff_output_file *out, const char *s)
+{
+ int i = 0;
+ while (s[i] != (char)0) {
+ out->special_char(s[i]);
+ i++;
+ }
+}
+
+/*
+ * We need to remember the start of the image and its name.
+ */
+
+static char last_position = 0;
+static const char *last_image_filename = 0;
+
+inline int min(int a, int b)
+{
+ return a < b ? a : b;
+}
+
+/*
+ * tprint - if (is_on == 2)
+ * remember current position (l, r, c, i) and filename
+ * else
+ * if (emit_limits)
+ * if (html)
+ * emit image tag
+ * else
+ * emit postscript bounds for image
+ * else
+ * if (suppress boolean differs from current state)
+ * alter state
+ * reset registers
+ * record current page
+ * set low water mark.
+ */
+
+void suppress_node::tprint(troff_output_file *out)
+{
+ int current_page = get_reg_int("%");
+ // firstly check to see whether this suppress node contains
+ // an image filename & position.
+ if (is_on == 2) {
+ // remember position and filename
+ last_position = position;
+ last_image_filename = filename.contents();
+ }
+ else {
+ // now check whether the suppress node requires us to issue limits.
+ if (emit_limits) {
+ char name[8192];
+ image_no++;
+ // remember that the filename will contain a %d in which the
+ // image_no is placed
+ sprintf(name, last_image_filename, image_no);
+ if (is_html) {
+ switch (last_position) {
+ case 'c':
+ out->start_special();
+ put(out, "html-tag:.centered-image");
+ break;
+ case 'r':
+ out->start_special();
+ put(out, "html-tag:.right-image");
+ break;
+ case 'l':
+ out->start_special();
+ put(out, "html-tag:.left-image");
+ break;
+ case 'i':
+ ;
+ default:
+ ;
+ }
+ out->end_special();
+ out->start_special();
+ put(out, "html-tag:.auto-image ");
+ put(out, name);
+ out->end_special();
+ }
+ else {
+ // postscript (or other device)
+ if (current_page != suppress_start_page)
+ error("suppression limit registers span more than one page;\n"
+ "image description %1 will be wrong", image_no);
+ // remember that the filename will contain a %d in which the
+ // image_no is placed
+ fprintf(stderr,
+ "grohtml-info:page %d %d %d %d %d %d %s %d %d %s\n",
+ current_page,
+ get_reg_int("opminx"), get_reg_int("opminy"),
+ get_reg_int("opmaxx"), get_reg_int("opmaxy"),
+ // page offset + line length
+ get_reg_int(".o") + get_reg_int(".l"),
+ name, hresolution, vresolution, get_reg_str(".F"));
+ fflush(stderr);
+ }
+ }
+ else {
+ if (is_on)
+ out->on();
+ else
+ out->off();
+ // lastly we reset the output registers
+ reset_output_registers(out->get_vpos());
+ suppress_start_page = current_page;
+ }
+ }
+}
+
+int suppress_node::force_tprint()
+{
+ return is_on;
+}
+
+hunits suppress_node::width()
+{
+ return H0;
+}
+
+/* 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();
+ int force_tprint();
+ 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);
+}
+
+width_list::width_list(hunits w, hunits s)
+: width(w), sentence_width(s), next(0)
+{
+}
+
+width_list::width_list(width_list *w)
+: width(w->width), sentence_width(w->sentence_width), next(0)
+{
+}
+
+word_space_node::word_space_node(hunits d, width_list *w, node *x)
+: space_node(d, x), orig_width(w), unformat(0)
+{
+}
+
+word_space_node::word_space_node(hunits d, int s, width_list *w,
+ int flag, node *x)
+: space_node(d, s, 0, x), orig_width(w), unformat(flag)
+{
+}
+
+word_space_node::~word_space_node()
+{
+ width_list *w = orig_width;
+ while (w != 0) {
+ width_list *tmp = w;
+ w = w->next;
+ delete tmp;
+ }
+}
+
+node *word_space_node::copy()
+{
+ assert(orig_width != 0);
+ width_list *w_old_curr = orig_width;
+ width_list *w_new_curr = new width_list(w_old_curr);
+ width_list *w_new = w_new_curr;
+ w_old_curr = w_old_curr->next;
+ while (w_old_curr != 0) {
+ w_new_curr->next = new width_list(w_old_curr);
+ w_new_curr = w_new_curr->next;
+ w_old_curr = w_old_curr->next;
+ }
+ return new word_space_node(n, set, w_new, unformat);
+}
+
+int word_space_node::set_unformat_flag()
+{
+ unformat = 1;
+ return 1;
+}
+
+void word_space_node::tprint(troff_output_file *out)
+{
+ out->word_marker();
+ space_node::tprint(out);
+}
+
+int word_space_node::merge_space(hunits h, hunits sw, hunits ssw)
+{
+ n += h;
+ assert(orig_width != 0);
+ width_list *w = orig_width;
+ for (; w->next; w = w->next)
+ ;
+ w->next = new width_list(sw, ssw);
+ return 1;
+}
+
+unbreakable_space_node::unbreakable_space_node(hunits d, node *x)
+: word_space_node(d, 0, x)
+{
+}
+
+unbreakable_space_node::unbreakable_space_node(hunits d, int s, node *x)
+: word_space_node(d, s, 0, 0, x)
+{
+}
+
+node *unbreakable_space_node::copy()
+{
+ return new unbreakable_space_node(n, set);
+}
+
+int unbreakable_space_node::force_tprint()
+{
+ return 0;
+}
+
+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, hunits, 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";
+}
+
+int draw_node::force_tprint()
+{
+ return 0;
+}
+
+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 if (s->nm.contents())
+ 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_STRETCHABLE_SPACE:
+ return new unbreakable_space_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, int *spacep)
+{
+ 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_STRETCHABLE_SPACE:
+ res = new unbreakable_space_node(env->get_space_width(), this);
+ *widthp += res->width();
+ *spacep += res->nspaces();
+ 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 extra_size_node::force_tprint()
+{
+ return 0;
+}
+
+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 vertical_size_node::set_unformat_flag()
+{
+ return 0;
+}
+
+int vertical_size_node::force_tprint()
+{
+ return 0;
+}
+
+int hmotion_node::same(node *nd)
+{
+ return n == ((hmotion_node *)nd)->n;
+}
+
+const char *hmotion_node::type()
+{
+ return "hmotion_node";
+}
+
+int hmotion_node::set_unformat_flag()
+{
+ unformat = 1;
+ return 1;
+}
+
+int hmotion_node::force_tprint()
+{
+ return 0;
+}
+
+node *hmotion_node::add_self(node *n, hyphen_list **p)
+{
+ next = n;
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return this;
+}
+
+hyphen_list *hmotion_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(0, tail);
+}
+
+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 space_char_hmotion_node::force_tprint()
+{
+ return 0;
+}
+
+node *space_char_hmotion_node::add_self(node *n, hyphen_list **p)
+{
+ next = n;
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return this;
+}
+
+hyphen_list *space_char_hmotion_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(0, tail);
+}
+
+int vmotion_node::same(node *nd)
+{
+ return n == ((vmotion_node *)nd)->n;
+}
+
+const char *vmotion_node::type()
+{
+ return "vmotion_node";
+}
+
+int vmotion_node::force_tprint()
+{
+ return 0;
+}
+
+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 hline_node::force_tprint()
+{
+ return 0;
+}
+
+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 vline_node::force_tprint()
+{
+ return 0;
+}
+
+int dummy_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *dummy_node::type()
+{
+ return "dummy_node";
+}
+
+int dummy_node::force_tprint()
+{
+ return 0;
+}
+
+int transparent_dummy_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *transparent_dummy_node::type()
+{
+ return "transparent_dummy_node";
+}
+
+int transparent_dummy_node::force_tprint()
+{
+ return 0;
+}
+
+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 zero_width_node::force_tprint()
+{
+ return 0;
+}
+
+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";
+}
+
+int italic_corrected_node::force_tprint()
+{
+ return 0;
+}
+
+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::force_tprint()
+{
+ return 0;
+}
+
+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 overstrike_node::force_tprint()
+{
+ return 0;
+}
+
+node *overstrike_node::add_self(node *n, hyphen_list **p)
+{
+ next = n;
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return this;
+}
+
+hyphen_list *overstrike_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(0, tail);
+}
+
+int bracket_node::same(node *nd)
+{
+ return same_node_list(list, ((bracket_node *)nd)->list);
+}
+
+const char *bracket_node::type()
+{
+ return "bracket_node";
+}
+
+int bracket_node::force_tprint()
+{
+ return 0;
+}
+
+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 composite_node::force_tprint()
+{
+ return 0;
+}
+
+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 glyph_node::force_tprint()
+{
+ return 0;
+}
+
+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 ligature_node::force_tprint()
+{
+ return 0;
+}
+
+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 kern_pair_node::force_tprint()
+{
+ return 0;
+}
+
+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 dbreak_node::force_tprint()
+{
+ return 0;
+}
+
+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 break_char_node::force_tprint()
+{
+ return 0;
+}
+
+int line_start_node::same(node * /*nd*/)
+{
+ return 1;
+}
+
+const char *line_start_node::type()
+{
+ return "line_start_node";
+}
+
+int line_start_node::force_tprint()
+{
+ return 0;
+}
+
+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 word_space_node::force_tprint()
+{
+ return 0;
+}
+
+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";
+}
+
+node *unbreakable_space_node::add_self(node *n, hyphen_list **p)
+{
+ next = n;
+ hyphen_list *pp = *p;
+ *p = (*p)->next;
+ delete pp;
+ return this;
+}
+
+hyphen_list *unbreakable_space_node::get_hyphen_list(hyphen_list *tail)
+{
+ return new hyphen_list(0, tail);
+}
+
+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_space_node::force_tprint()
+{
+ return 0;
+}
+
+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";
+}
+
+int diverted_copy_file_node::force_tprint()
+{
+ return 0;
+}
+
+// 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 i_to_a(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/contrib/groff/src/roff/troff/node.h b/contrib/groff/src/roff/troff/node.h
new file mode 100644
index 0000000..3e5f615
--- /dev/null
+++ b/contrib/groff/src/roff/troff/node.h
@@ -0,0 +1,584 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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, int *spacep);
+
+ virtual ~node();
+ virtual node *copy() = 0;
+ virtual int set_unformat_flag();
+ virtual int force_tprint() = 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, hunits, 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 void is_escape_colon();
+ 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 *);
+ int force_tprint();
+ 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;
+ char was_escape_colon;
+ space_node(hunits, int, 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, hunits, hunits);
+ void freeze_space();
+ void is_escape_colon();
+ 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 *);
+ void asciify(macro *);
+ const char *type();
+ int force_tprint();
+ hyphenation_type get_hyphenation_type();
+};
+
+struct width_list {
+ width_list *next;
+ hunits width;
+ hunits sentence_width;
+ width_list(hunits, hunits);
+ width_list(width_list *);
+};
+
+class word_space_node : public space_node {
+protected:
+ width_list *orig_width;
+ unsigned char unformat;
+ word_space_node(hunits, int, width_list *, int, node * = 0);
+public:
+ word_space_node(hunits, width_list *, node * = 0);
+ ~word_space_node();
+ node *copy();
+ int reread(int *);
+ int set_unformat_flag();
+ void tprint(troff_output_file *);
+ int same(node *);
+ void asciify(macro *);
+ const char *type();
+ int merge_space(hunits, hunits, hunits);
+ int force_tprint();
+};
+
+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 reread(int *);
+ int same(node *);
+ void asciify(macro *);
+ const char *type();
+ int force_tprint();
+ 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, hunits, hunits);
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ hyphenation_type get_hyphenation_type();
+};
+
+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();
+ int force_tprint();
+};
+
+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();
+ int force_tprint();
+};
+
+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();
+ int force_tprint();
+};
+
+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 set_unformat_flag();
+ int same(node *);
+ const char *type();
+ int force_tprint();
+};
+
+class hmotion_node : public node {
+protected:
+ hunits n;
+ unsigned char was_tab;
+ unsigned char unformat;
+public:
+ hmotion_node(hunits i, node *next = 0)
+ : node(next), n(i), was_tab(0), unformat(0) {}
+ hmotion_node(hunits i, int flag1, int flag2, node *next = 0)
+ : node(next), n(i), was_tab(flag1), unformat(flag2) {}
+ node *copy();
+ int reread(int *);
+ int set_unformat_flag();
+ void asciify(macro *);
+ void tprint(troff_output_file *);
+ hunits width();
+ void ascii_print(ascii_output_file *);
+ int same(node *);
+ const char *type();
+ int force_tprint();
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ hyphenation_type get_hyphenation_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();
+ int force_tprint();
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ hyphenation_type get_hyphenation_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();
+ int force_tprint();
+};
+
+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();
+ int force_tprint();
+};
+
+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();
+ int force_tprint();
+};
+
+
+class dummy_node : public node {
+public:
+ dummy_node(node *nd = 0) : node(nd) {}
+ node *copy();
+ int same(node *);
+ const char *type();
+ int force_tprint();
+ hyphenation_type get_hyphenation_type();
+};
+
+class transparent_dummy_node : public node {
+public:
+ transparent_dummy_node(node *nd = 0) : node(nd) {}
+ node *copy();
+ int same(node *);
+ const char *type();
+ int force_tprint();
+ 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();
+ int force_tprint();
+ 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();
+ int force_tprint();
+ 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();
+ int force_tprint();
+ node *add_self(node *, hyphen_list **);
+ hyphen_list *get_hyphen_list(hyphen_list *ss = 0);
+ hyphenation_type get_hyphenation_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();
+ int force_tprint();
+};
+
+class special_node : public node {
+ macro mac;
+ tfont *tf;
+ int no_init_string;
+ 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 &, int = 0);
+ special_node(const macro &, tfont *, int = 0);
+ node *copy();
+ void tprint(troff_output_file *);
+ int same(node *);
+ const char *type();
+ int force_tprint();
+ int ends_sentence();
+ tfont *get_tfont();
+};
+
+class suppress_node : public node {
+ int is_on;
+ int emit_limits; // must we issue the extent of the area written out?
+ symbol filename;
+ char position;
+public:
+ suppress_node(int, int);
+ suppress_node(symbol f, char p);
+ suppress_node(int, int, symbol f, char p);
+ node *copy();
+ void tprint(troff_output_file *);
+ hunits width();
+ int same(node *);
+ const char *type();
+ int force_tprint();
+private:
+ void put(troff_output_file *out, const char *s);
+};
+
+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();
+ int force_tprint();
+};
+
+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, hunits width) = 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);
+ virtual void on();
+ virtual void off();
+#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/contrib/groff/src/roff/troff/number.cc b/contrib/groff/src/roff/troff/number.cc
new file mode 100644
index 0000000..5393842
--- /dev/null
+++ b/contrib/groff/src/roff/troff/number.cc
@@ -0,0 +1,692 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2001 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, int rigid = 0);
+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;
+}
+
+// for \B
+
+int get_number_rigidly(units *res, unsigned char si)
+{
+ if (!start_number())
+ return 0;
+ units x;
+ if (parse_expr(&x, si, 0, 1)) {
+ *res = 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, int rigid);
+
+static int parse_expr(units *v, int scale_indicator,
+ int parenthesised, int rigid)
+{
+ int result = parse_term(v, scale_indicator, parenthesised, rigid);
+ 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, rigid))
+ 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 rigid)
+{
+ 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, rigid))
+ 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 == ')') {
+ if (rigid)
+ return 0;
+ 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, rigid))
+ return 0;
+ tok.skip();
+ if (tok.ch() != ')') {
+ if (rigid)
+ return 0;
+ 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 rigid ? 0 : 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/contrib/groff/src/roff/troff/reg.cc b/contrib/groff/src/roff/troff/reg.cc
new file mode 100644
index 0000000..254b0ff
--- /dev/null
+++ b/contrib/groff/src/roff/troff/reg.cc
@@ -0,0 +1,473 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 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 "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 char uppercase_array[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z',
+};
+
+static char lowercase_array[] = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z',
+};
+
+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 i_to_a(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 i_to_a(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 == 'a' ? lowercase_array[d - 1] :
+ uppercase_array[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/contrib/groff/src/roff/troff/reg.h b/contrib/groff/src/roff/troff/reg.h
new file mode 100644
index 0000000..8d403d4
--- /dev/null
+++ b/contrib/groff/src/roff/troff/reg.h
@@ -0,0 +1,76 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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);
+extern void check_output_limits(int x, int y);
+extern void reset_output_registers (int miny);
+
+reg *lookup_number_reg(symbol);
+#if 0
+void inline_define_reg();
+#endif
diff --git a/contrib/groff/src/roff/troff/request.h b/contrib/groff/src/roff/troff/request.h
new file mode 100644
index 0000000..5654b83
--- /dev/null
+++ b/contrib/groff/src/roff/troff/request.h
@@ -0,0 +1,84 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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 append_unsigned(unsigned int i);
+ void append_int(int i);
+ void append_str(const char *);
+ 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_markup_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);
+
+class charinfo;
+class environment;
+
+node *charinfo_to_node_list(charinfo *, const environment *);
diff --git a/contrib/groff/src/roff/troff/symbol.cc b/contrib/groff/src/roff/troff/symbol.cc
new file mode 100644
index 0000000..ce09e39
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/troff/symbol.h b/contrib/groff/src/roff/troff/symbol.h
new file mode 100644
index 0000000..88e0fff
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/roff/troff/token.h b/contrib/groff/src/roff/troff/token.h
new file mode 100644
index 0000000..40283ad
--- /dev/null
+++ b/contrib/groff/src/roff/troff/token.h
@@ -0,0 +1,218 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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_STRETCHABLE_SPACE, // \~
+ TOKEN_TAB, // tab
+ TOKEN_TRANSPARENT, // \!
+ TOKEN_TRANSPARENT_DUMMY, // \)
+ 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 the current token a space?
+ int stretchable_space(); // is the current token a stretchable 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_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_rigidly(units *result, unsigned char si);
+
+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::stretchable_space()
+{
+ return type == TOKEN_STRETCHABLE_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::transparent_dummy()
+{
+ return type == TOKEN_TRANSPARENT_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/contrib/groff/src/roff/troff/troff.h b/contrib/groff/src/roff/troff/troff.h
new file mode 100644
index 0000000..254c626
--- /dev/null
+++ b/contrib/groff/src/roff/troff/troff.h
@@ -0,0 +1,88 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
+ 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"
+#include "searchpath.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 is_html;
+
+extern int tcommand_flag;
+extern int vresolution;
+extern int hresolution;
+extern int sizescale;
+
+extern search_path *mac_path;
+
+#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/contrib/groff/src/roff/troff/troff.man b/contrib/groff/src/roff/troff/troff.man
new file mode 100644
index 0000000..7fe052b
--- /dev/null
+++ b/contrib/groff/src/roff/troff/troff.man
@@ -0,0 +1,2462 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-2000, 2001 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 @MAN1EXT@ "@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
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.
+.
+.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:
+.BR 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
+.IB name .tmac\fR.
+If it isn't found, try
+.BI tmac. name
+instead.
+It will be first searched for in directories given with the
+.B \-M
+command line option, then in directories given
+in the
+.B GROFF_TMAC_PATH
+environment variable, then in the current directory (only if in unsafe
+mode), the home directory, @SYSTEMMACRODIR@, @LOCALMACRODIR@, and
+@MACRODIR@.
+.TP
+.B \-U
+Unsafe mode.
+This will enable the following requests:
+.BR .open ,
+.BR .opena ,
+.BR .pso ,
+.BR .sy ,
+and
+.BR .pi .
+For security reasons, these potentially dangerous requests are disabled
+otherwise. It will also add the current directory to the macro search path.
+.TP
+.B \-R
+Don't load
+.B troffrc
+and
+.BR troffrc-end .
+.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 in directory (or directory path)
+.I dir
+for subdirectories
+.BI dev name
+.RI ( name
+is the name of the device) and there for the
+.B DESC
+file and font files.
+.I dir
+is scanned before all other font directories.
+.TP
+.BI \-M dir
+Search directory (or directory path)
+.I dir
+for macro files.
+This is scanned before all other macro directories.
+.
+.
+.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 \eB' anything '
+This expands to
+.B 1
+or
+.B 0
+according as
+.I anything
+is or is not a valid numeric expression.
+It will return
+.B 0
+if
+.I anything
+is empty.
+.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
+.IR 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 an 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:
+This causes the insertion of a zero-width break point.
+It is equal to
+.B \e%
+but without insertion of a soft hyphen character.
+.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 `unformats' the diversion
+.I xx
+in such a way that
+.SM ASCII
+and space characters (and some escape sequences) that were formatted and
+diverted into
+.I xx
+will be treated like ordinary input characters when
+.I xx
+is reread.
+Useful for diversions in conjunction with the
+.B .writem
+request.
+It can be also used for gross hacks; for example, this
+.RS
+.IP
+.ne 7v+\n(.Vu
+.ft B
+.nf
+\&.tr @.
+\&.di x
+\&@nr n 1
+\&.br
+\&.di
+\&.tr @@
+\&.asciify x
+\&.x
+.fi
+.RE
+.IP
+will set register
+.B n
+to 1.
+Note that glyph information (font, font size, etc.) is not preserved; use
+.B .unformat
+instead.
+.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
+.BI .box\ xx
+.TQ
+.BI .boxa\ xx
+These requests are similar to the
+.B di
+and
+.B da
+requests with the exception that a partially filled line will not become
+part of the diversion (i.e., the diversion always starts with a new line)
+but restored after ending the diversion, discarding the partially filled
+line which possibly comes from the diversion.
+.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 .dei\ xx\ yy
+Define macro indirectly.
+The following example
+.RS
+.IP
+.ne 2v+\n(.Vu
+.ft B
+.nf
+\&.ds xx aa
+\&.ds yy bb
+\&.dei xx yy
+.fi
+.RE
+.IP
+is equivalent to
+.RS
+.IP
+.B
+\&.de aa bb
+.RE
+.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
+.B .ecs
+Save current escape character.
+.TP
+.B .ecr
+Restore escape character saved with
+.BR ecs .
+Without a previous call to
+.BR ecs ,
+.RB ` \e '
+will be the new escape character.
+.TP
+.BI .evc\ xx
+Copy the contents of environment
+.I xx
+to the current environment.
+No pushing or popping of environents will be done.
+.TP
+.BI .fam\ xx
+Set the current font family to
+.IR xx .
+The current font family is part of the current environment.
+If
+.I xx
+is missing, switch back to previous font family.
+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
+.IB name .tmac
+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 .length\ xx\ string
+Compute the length of
+.I string
+and return it in the number register
+.I xx
+(which is not necessarily defined before).
+.TP
+.BI .linetabs\ n
+If
+.I n
+is non-zero or missing, enable line-tabs mode, otherwise disable it (which
+is the default).
+In line-tabs mode, tab distances are computed relative to the (current)
+output line.
+Otherwise they are taken relative to the input line.
+For example, the following
+.RS
+.IP
+.ne 6v+\n(.Vu
+.ft B
+.nf
+\&.ds x a\et\ec
+\&.ds y b\et\ec
+\&.ds z c
+\&.ta 1i 3i
+\e*x
+\e*y
+\e*z
+.fi
+.RE
+.IP
+yields
+.RS
+.IP
+a b c
+.RE
+.IP
+In line-tabs mode, the same code gives
+.RS
+.IP
+a b c
+.RE
+.IP
+Line-tabs mode is associated with the current environment; the read-only
+number register
+.B \\en[.linetabs]
+is set to\~1 if in line-tabs mode, and 0 otherwise.
+.TP
+.BI .mso\ file
+The same as the
+.B so
+request except that
+.I file
+is searched for in the same directories as macro files for the
+the
+.B \-m
+command line option.
+If the file name to be included
+has the form
+.IB name .tmac
+and it isn't found,
+.B mso
+tries to include
+.BI tmac. name
+instead and vice versa.
+.TP
+.BI .nop \ anything
+Execute
+.IR anything .
+This is similar to `.if\ 1'.
+.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 corner 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 .return
+Within a macro, return immediately.
+No effect otherwise.
+.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 .substring\ xx\ n1\ [ n2 ]
+Replace the string in register
+.I xx
+with the substring defined by the indices
+.I n1
+and
+.IR n2 .
+The first character in the string has index one.
+If
+.I n2
+is omitted, it is taken to be equal to the string's length. If the
+index value
+.I n1
+or
+.I n2
+is negative or zero, it will be counted from the end of the string,
+going backwards: The last character has index 0, the character before
+the last character has index -1, etc.
+.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 .tm1\ string
+Similar to the
+.B tm
+request,
+.I string
+is read in copy mode and written on the standard error, but an initial
+double quote in
+.I string
+is stripped off to allow initial blanks.
+.TP
+.BI .tmc\ string
+Similar to
+.BR tm1
+but without writing a final newline.
+.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
+.IP
+.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 .unformat\ xx
+This request `unformats' the diversion
+.IR xx .
+Contrary to the
+.B .asciify
+request, which tries to convert formatted elements of the diversion back
+to input tokens as much as possible,
+.B .unformat
+will only handle tabs and spaces between words (usually caused by spaces
+or newlines in the input) specially.
+The former are treated as if they were input tokens, and the latter are
+stretchable again.
+Note that the vertical size of lines is not preserved.
+Glyph information (font, font size, space width, etc.) is retained.
+Useful in conjunction with the
+.B .box
+and
+.B .boxa
+requests.
+.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.
+.TP
+.BI .writem\ stream\ xx
+Write the contents of the macro or string
+.I xx
+to the stream named
+.IR stream .
+.I stream
+must previously have been the subject of an
+.B open
+request.
+.I xx
+is read in copy mode.
+.
+.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.
+Contrary to UNIX troff, GNU troff handles this request in nroff mode
+also (if not in compatibility mode); a given value is then rounded down
+to the nearest multiple of\~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[.int]
+Set to a positive value if last output line is interrupted (i.e., if it
+contains
+.IR \ec ).
+.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[.linetabs]
+The current line-tabs mode (as set by the
+.B linetabs
+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 read/write 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
+Other available read/write number registers are:
+.TP
+.B \en[c.]
+The current input line number.
+.B \en[.c]
+is a read-only alias to this register.
+.TP
+.B \en[hp]
+The current horizontal position at input line.
+.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
+.
+.B @g@troff
+predefines a single (read/write) string-based register,
+.BR \e*(.T ,
+which contains the argument given to the
+.B -T
+command line option, namely the current output device (for example,
+.I latin1
+or
+.IR ascii ).
+Note that this is not the same as the (read-only) number register
+.B \en[.T]
+which is defined to be\ 1 if
+.B troff
+is called with the
+.B -T
+command line option, and zero otherwise. This behaviour is different to
+UNIX troff.
+.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.
+.LP
+The
+.B tr
+request can now map characters onto
+.BR \e~ .
+.
+.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.
+.B troff
+will scan directories given in
+the
+.B \-M
+option before these, and in standard directories (current directory if in
+unsafe mode, home directory,
+.BR @LOCALMACRODIR@ ,
+.BR @SYSTEMMACRODIR@ ,
+.BR @MACRODIR@ )
+after these.
+.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 scan 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 (called before any other macro package).
+.TP
+.B @MACRODIR@/troffrc-end
+Initialization file (called after any other macro package).
+.TP
+.BI @MACRODIR@/ name .tmac
+.TQ
+.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 .
+.LP
+Note that
+.B troffrc
+and
+.B troffrc-end
+are neither searched in the current nor in the home directory by default for
+security reasons (even if the
+.B \-U
+option is given).
+Use the
+.B \-M
+command line option or the
+.B GROFF_TMAC_PATH
+environment variable to add these directories to the search path if
+necessary.
+.
+.
+.SH "SEE ALSO"
+.
+.
+.BR groff (@MAN1EXT@),
+.BR @g@tbl (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@),
+.BR @g@eqn (@MAN1EXT@),
+.BR @g@refer (@MAN1EXT@),
+.BR @g@soelim (@MAN1EXT@),
+.BR @g@grn (@MAN1EXT@),
+.BR grops (@MAN1EXT@),
+.BR grodvi (@MAN1EXT@),
+.BR grotty (@MAN1EXT@),
+.BR grohtml (@MAN1EXT@),
+.BR grolj4 (@MAN1EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/contrib/groff/src/utils/addftinfo/Makefile.sub b/contrib/groff/src/utils/addftinfo/Makefile.sub
new file mode 100644
index 0000000..23848d5
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/addftinfo/addftinfo.cc b/contrib/groff/src/utils/addftinfo/addftinfo.cc
new file mode 100644
index 0000000..43a81bc
--- /dev/null
+++ b/contrib/groff/src/utils/addftinfo/addftinfo.cc
@@ -0,0 +1,218 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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(FILE *stream);
+static void usage();
+static void version();
+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];
+ for (int i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-v") || !strcmp(argv[i],"--version"))
+ version();
+ if (!strcmp(argv[i],"--help")) {
+ usage(stdout);
+ exit(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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-v] [-param value] ... "
+ "resolution unitwidth font\n",
+ program_name);
+}
+static void usage()
+{
+ usage(stderr);
+ exit(1);
+}
+
+static void version()
+{
+ extern const char *Version_string;
+ printf("GNU addftinfo (groff) version %s\n", Version_string);
+ exit(0);
+}
+
+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/contrib/groff/src/utils/addftinfo/addftinfo.man b/contrib/groff/src/utils/addftinfo/addftinfo.man
new file mode 100644
index 0000000..921f633
--- /dev/null
+++ b/contrib/groff/src/utils/addftinfo/addftinfo.man
@@ -0,0 +1,107 @@
+.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 ADDFTINFO @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+addftinfo \- add information to troff font files for use with groff
+.SH SYNOPSIS
+.B addftinfo
+[
+.B \-v
+]
+[
+.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
+.B \-v
+prints the version number.
+.LP
+All other 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 groff_font (@MAN5EXT@),
+.BR groff (@MAN1EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/contrib/groff/src/utils/addftinfo/guess.cc b/contrib/groff/src/utils/addftinfo/guess.cc
new file mode 100644
index 0000000..dcfd4c9
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/addftinfo/guess.h b/contrib/groff/src/utils/addftinfo/guess.h
new file mode 100644
index 0000000..4471dda
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/afmtodit/Makefile.sub b/contrib/groff/src/utils/afmtodit/Makefile.sub
new file mode 100644
index 0000000..9176924
--- /dev/null
+++ b/contrib/groff/src/utils/afmtodit/Makefile.sub
@@ -0,0 +1,23 @@
+MAN1=afmtodit.n
+CLEANADD=afmtodit
+
+all: afmtodit
+
+afmtodit: afmtodit.pl
+ if test -n "$(PERLPATH)"; then \
+ sed -e "s|/usr/bin/perl|$(PERLPATH)|" \
+ -e "s|@VERSION@|$(version)$(revision)|" \
+ $(srcdir)/afmtodit.pl >afmtodit; \
+ else \
+ sed -e "s|@VERSION@|$(version)$(revision)|" \
+ $(srcdir)/afmtodit.pl afmtodit; \
+ fi
+ chmod +x afmtodit
+
+install_data: afmtodit
+ -test -d $(bindir) || $(mkinstalldirs) $(bindir)
+ -rm -f $(bindir)/afmtodit
+ $(INSTALL_SCRIPT) afmtodit $(bindir)/afmtodit
+
+uninstall_sub:
+ -rm -f $(bindir)/afmtodit
diff --git a/contrib/groff/src/utils/afmtodit/afmtodit.man b/contrib/groff/src/utils/afmtodit/afmtodit.man
new file mode 100644
index 0000000..03a6e5c
--- /dev/null
+++ b/contrib/groff/src/utils/afmtodit/afmtodit.man
@@ -0,0 +1,225 @@
+.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.
+..
+.\" 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
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBafmtodit 'u
+.ti \niu
+.B afmtodit
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-nsv
+.OP \-d desc_file
+.OP \-e enc_file
+.OP \-i n
+.OP \-a n
+.I afm_file
+.I map_file
+.I font
+.br
+.ad \na
+.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 \-v
+Print version.
+.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/contrib/groff/src/utils/afmtodit/afmtodit.pl b/contrib/groff/src/utils/afmtodit/afmtodit.pl
new file mode 100644
index 0000000..661245a
--- /dev/null
+++ b/contrib/groff/src/utils/afmtodit/afmtodit.pl
@@ -0,0 +1,331 @@
+#! /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('ve:sd:i:a:n');
+
+if (opt_v) {
+ print "GNU afmtodit (groff) version @VERSION@\n";
+ exit 0;
+}
+
+if ($#ARGV != 2) {
+ die "Usage: $prog [-nsv] [-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/contrib/groff/src/utils/hpftodit/Makefile.sub b/contrib/groff/src/utils/hpftodit/Makefile.sub
new file mode 100644
index 0000000..f5ff13e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/hpftodit/hpftodit.cc b/contrib/groff/src/utils/hpftodit/hpftodit.cc
new file mode 100644
index 0000000..f81f5ad
--- /dev/null
+++ b/contrib/groff/src/utils/hpftodit/hpftodit.cc
@@ -0,0 +1,827 @@
+// -*- C++ -*-
+/* Copyright (C) 1994, 2000, 2001 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"
+#include "nonposix.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(FILE *stream);
+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;
+
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "dsvi:", long_options, NULL)) != 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;
+ printf("GNU hpftodit (groff) version %s\n", Version_string);
+ exit(0);
+ }
+ break;
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage();
+ break;
+ 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-s] [-i n] tfm_file map_file output_font\n",
+ program_name);
+}
+static
+void usage()
+{
+ usage(stderr);
+ exit(1);
+}
+
+File::File(const char *s)
+{
+ // We need to read the file in binary mode because hpftodit relies
+ // on byte counts.
+ int fd = open(s, O_RDONLY | O_BINARY);
+ 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;
+ // These are actually text files, so we must get rid of the `\r'
+ // characters. This is also enabled for Posix systems, in case the
+ // input came from Windows...
+ unsigned char *p = buf_, *q = buf_;
+ while (q < end_)
+ {
+ if (*q == '\r')
+ {
+ if (*++q != '\n')
+ *p++ = '\r';
+ }
+#if defined(__MSDOS__) || defined(_MSC_VER)
+ if (*q == '\032') // ^Z means ``software EOF''
+ break;
+#endif
+ *p++ = *q++;
+ }
+ end_ = p;
+}
+
+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)
+{
+ // DIR_SEPS[] are possible directory separator characters, see
+ // nonposix.h. We want the rightmost separator of all possible
+ // ones. Example: d:/foo\\bar.
+ const char *b = strrchr(s, DIR_SEPS[0]), *b1;
+ const char *sep = &DIR_SEPS[1];
+
+ while (*sep)
+ {
+ b1 = strrchr(s, *sep);
+ if (b1 && (!b || b1 > b))
+ b = b1;
+ sep++;
+ }
+ return b ? b + 1 : s;
+}
diff --git a/contrib/groff/src/utils/hpftodit/hpftodit.man b/contrib/groff/src/utils/hpftodit/hpftodit.man
new file mode 100644
index 0000000..d107e8c
--- /dev/null
+++ b/contrib/groff/src/utils/hpftodit/hpftodit.man
@@ -0,0 +1,155 @@
+.ig \"-*- nroff -*-
+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.
+
+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
+.PP
+It is possible to have whitespace between the
+.B \-i
+command line option and its parameter.
+.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/contrib/groff/src/utils/indxbib/Makefile.sub b/contrib/groff/src/utils/indxbib/Makefile.sub
new file mode 100644
index 0000000..add99eb
--- /dev/null
+++ b/contrib/groff/src/utils/indxbib/Makefile.sub
@@ -0,0 +1,31 @@
+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 $(dataprogramdir) || $(mkinstalldirs) $(dataprogramdir)
+ -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/contrib/groff/src/utils/indxbib/dirnamemax.c b/contrib/groff/src/utils/indxbib/dirnamemax.c
new file mode 100644
index 0000000..a8cd992
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/indxbib/eign b/contrib/groff/src/utils/indxbib/eign
new file mode 100644
index 0000000..7718c8b
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/indxbib/indxbib.cc b/contrib/groff/src/utils/indxbib/indxbib.cc
new file mode 100644
index 0000000..99a6baf
--- /dev/null
+++ b/contrib/groff/src/utils/indxbib/indxbib.cc
@@ -0,0 +1,805 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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"
+
+#include "nonposix.h"
+
+extern "C" {
+ // Solaris 2.5.1 has these functions,
+ // but its stdlib.h fails to declare them.
+ char *mktemp(char *);
+ int mkstemp(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(FILE *stream);
+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;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "c:o:h:i:k:l:t:n:c:d:f:vw",
+ long_options, NULL))
+ != 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;
+ printf("GNU indxbib (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ 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, DIR_SEPS[0]), *p1;
+ const char *sep = &DIR_SEPS[1];
+ while (*sep)
+ {
+ p1 = strrchr(basename, *sep);
+ if (p1 && (!p || p1 > p))
+ p = p1;
+ sep++;
+ }
+ 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);
+ }
+#ifndef HAVE_MKSTEMP
+ if (!mktemp(temp_index_file) || !temp_index_file[0])
+ fatal("cannot create file name for temporary file");
+#endif
+ catch_fatal_signals();
+#ifdef HAVE_MKSTEMP
+ int fd = mkstemp(temp_index_file);
+#else
+ int fd = creat(temp_index_file, S_IRUSR|S_IRGRP|S_IROTH);
+#endif
+ if (fd < 0)
+ fatal("can't create temporary index file: %1", strerror(errno));
+ indxfp = fdopen(fd, FOPEN_WB);
+ 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)
+ {
+#ifdef __MSDOS__
+ // RENAME could fail on plain MSDOS filesystems because
+ // INDEX_FILE is an invalid filename, e.g. it has multiple dots.
+ char *fname = p ? index_file + (p - basename) : 0;
+ char *dot = 0;
+
+ // Replace the dot with an underscore and try again.
+ if (fname
+ && (dot = strchr(fname, '.')) != 0
+ && strcmp(dot, INDEX_SUFFIX) != 0)
+ *dot = '_';
+ if (rename(temp_index_file, index_file) < 0)
+#endif
+ 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(FILE *stream)
+{
+ fprintf(stream,
+"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);
+}
+
+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;
+ // Need binary I/O for MS-DOS/MS-Windows, because indxbib relies on
+ // byte counts to be consistent with fseek.
+ FILE *fp = fopen(filename, FOPEN_RB);
+ 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;
+ // We opened the file in binary mode, so we need to skip
+ // every CR character before a Newline.
+ if (c == '\r') {
+ int peek = getc(fp);
+ if (peek = '\n') {
+ byte_count++;
+ c = peek;
+ }
+ else
+ ungetc(peek, fp);
+ }
+#if defined(__MSDOS__) || defined(_MSC_VER)
+ else if (c == 0x1a) // ^Z means EOF in text files
+ break;
+#endif
+ 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/contrib/groff/src/utils/indxbib/indxbib.man b/contrib/groff/src/utils/indxbib/indxbib.man
new file mode 100644
index 0000000..ed84cca
--- /dev/null
+++ b/contrib/groff/src/utils/indxbib/indxbib.man
@@ -0,0 +1,207 @@
+.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@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
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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/contrib/groff/src/utils/indxbib/signal.c b/contrib/groff/src/utils/indxbib/signal.c
new file mode 100644
index 0000000..8078472
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/lkbib/Makefile.sub b/contrib/groff/src/utils/lkbib/Makefile.sub
new file mode 100644
index 0000000..8f31e10
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/lkbib/lkbib.cc b/contrib/groff/src/utils/lkbib/lkbib.cc
new file mode 100644
index 0000000..4d3cadc
--- /dev/null
+++ b/contrib/groff/src/utils/lkbib/lkbib.cc
@@ -0,0 +1,137 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-nv] [-p database] [-i XYZ] [-t N] keys ...\n",
+ program_name);
+}
+
+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;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "nvVi:t:p:", long_options, NULL))
+ != 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;
+ printf("GNU lkbib (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case 'p':
+ list.add_file(optarg);
+ break;
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc) {
+ usage(stderr);
+ exit(1);
+ }
+ 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/contrib/groff/src/utils/lkbib/lkbib.man b/contrib/groff/src/utils/lkbib/lkbib.man
new file mode 100644
index 0000000..872313d
--- /dev/null
+++ b/contrib/groff/src/utils/lkbib/lkbib.man
@@ -0,0 +1,110 @@
+.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.
+..
+.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 \|.\|.\|.
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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/contrib/groff/src/utils/lookbib/Makefile.sub b/contrib/groff/src/utils/lookbib/Makefile.sub
new file mode 100644
index 0000000..91b1404
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/lookbib/lookbib.cc b/contrib/groff/src/utils/lookbib/lookbib.cc
new file mode 100644
index 0000000..dc55ed9
--- /dev/null
+++ b/contrib/groff/src/utils/lookbib/lookbib.cc
@@ -0,0 +1,140 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-v] [-i XYZ] [-t N] database ...\n",
+ program_name);
+}
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int opt;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "vVi:t:", long_options, NULL)) != 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;
+ printf("GNU lookbib (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc) {
+ usage(stderr);
+ exit(1);
+ }
+ 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/contrib/groff/src/utils/lookbib/lookbib.man b/contrib/groff/src/utils/lookbib/lookbib.man
new file mode 100644
index 0000000..846798d
--- /dev/null
+++ b/contrib/groff/src/utils/lookbib/lookbib.man
@@ -0,0 +1,78 @@
+.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@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 \|.\|.\|.
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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/contrib/groff/src/utils/pfbtops/Makefile.sub b/contrib/groff/src/utils/pfbtops/Makefile.sub
new file mode 100644
index 0000000..f731ff5
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/pfbtops/pfbtops.c b/contrib/groff/src/utils/pfbtops/pfbtops.c
new file mode 100644
index 0000000..2159dbd
--- /dev/null
+++ b/contrib/groff/src/utils/pfbtops/pfbtops.c
@@ -0,0 +1,131 @@
+/* This translates ps fonts in .pfb format to ASCII ps files. */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <limits.h>
+
+#include "nonposix.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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-v] [pfb_file]\n", program_name);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int opt;
+ extern int optind;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+
+ program_name = argv[0];
+
+ while ((opt = getopt_long(argc, argv, "v", long_options, NULL)) != EOF) {
+ switch (opt) {
+ case 'v':
+ {
+ extern char *Version_string;
+ printf("GNU pfbtops (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ }
+ }
+
+ if (argc - optind > 1) {
+ usage(stderr);
+ exit(1);
+ }
+ if (argc > optind && !freopen(argv[optind], "r", stdin))
+ {
+ perror(argv[optind]);
+ exit(1);
+ }
+#ifdef SET_BINARY
+ SET_BINARY(fileno(stdin));
+#endif
+ 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/contrib/groff/src/utils/pfbtops/pfbtops.man b/contrib/groff/src/utils/pfbtops/pfbtops.man
new file mode 100644
index 0000000..cfef3e0
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/tfmtodit/Makefile.sub b/contrib/groff/src/utils/tfmtodit/Makefile.sub
new file mode 100644
index 0000000..057bb3e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/utils/tfmtodit/tfmtodit.cc b/contrib/groff/src/utils/tfmtodit/tfmtodit.cc
new file mode 100644
index 0000000..96768d2
--- /dev/null
+++ b/contrib/groff/src/utils/tfmtodit/tfmtodit.cc
@@ -0,0 +1,874 @@
+// -*- C++ -*-
+/* Copyright (C) 1989-1992, 2000, 2001 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"
+#include "nonposix.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, FOPEN_RB);
+ 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, FOPEN_RB);
+ 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(FILE *stream);
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int special_flag = 0;
+ int skewchar = -1;
+ int opt;
+ const char *gf_file = 0;
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, CHAR_MAX + 1 },
+ { "version", no_argument, 0, 'v' },
+ { NULL, 0, 0, 0 }
+ };
+ while ((opt = getopt_long(argc, argv, "svg:k:", long_options, NULL)) != 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;
+ printf("GNU tfmtodit (groff) version %s\n", Version_string);
+ exit(0);
+ break;
+ }
+ case CHAR_MAX + 1: // --help
+ usage(stdout);
+ exit(0);
+ break;
+ case '?':
+ usage(stderr);
+ exit(1);
+ break;
+ case EOF:
+ assert(0);
+ }
+ if (argc - optind != 3) {
+ usage(stderr);
+ exit(1);
+ }
+ 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';
+ // DIR_SEPS[] are possible directory separator characters, see nonposix.h.
+ // We want the rightmost separator of all possible ones.
+ // Example: d:/foo\\bar.
+ const char *s = strrchr(internal_name, DIR_SEPS[0]), *s1;
+ const char *sep = &DIR_SEPS[1];
+ while (*sep)
+ {
+ s1 = strrchr(internal_name, *sep);
+ if (s1 && (!s || s1 > s))
+ s = s1;
+ sep++;
+ }
+ 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(FILE *stream)
+{
+ fprintf(stream, "usage: %s [-sv] [-g gf_file] [-k skewchar] tfm_file map_file font\n",
+ program_name);
+}
diff --git a/contrib/groff/src/utils/tfmtodit/tfmtodit.man b/contrib/groff/src/utils/tfmtodit/tfmtodit.man
new file mode 100644
index 0000000..6e50aa2
--- /dev/null
+++ b/contrib/groff/src/utils/tfmtodit/tfmtodit.man
@@ -0,0 +1,175 @@
+.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 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
+.nr a \n(.j
+.ad l
+.nr i \n(.i
+.in +\w'\fBtfmtodit 'u
+.ti \niu
+.B tfmtodit
+.de OP
+.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
+.el .RB "[\ " "\\$1" "\ ]"
+..
+.OP \-sv
+.OP \-g gf_file
+.OP \-k skewchar
+.I tfm_file
+.I map_file
+.I font
+.br
+.ad \na
+.PP
+It is possible to have whitespace between a command line option and its
+parameter.
+.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/contrib/groff/src/xditview/ChangeLog b/contrib/groff/src/xditview/ChangeLog
new file mode 100644
index 0000000..ef0a856
--- /dev/null
+++ b/contrib/groff/src/xditview/ChangeLog
@@ -0,0 +1,413 @@
+2001-01-04 Rob Daasch <daasch@ece.pdx.edu>
+
+ * parse.c (ParseInput): Added 'F' to command switch to swallow
+ filename strings as ignored comments.
+
+2000-12-02 Werner LEMBERG <wl@gnu.org>
+
+ * device.c (find_file): Remove home directory in search path.
+
+2000-11-14 Werner LEMBERG <wl@gnu.org>
+
+ * device.c (open_device_file): Remove `path' parameter.
+ (find_file): Construct font path similar to groff: First the contents
+ of GROFF_FONT_PATH, then the home directory, and finally the default
+ font path.
+ * Imakefile.in: Fix GROFF_DATAPROGRAMDIR and GROFF_FONTPATH.
+
+2000-10-23 Werner LEMBERG <wl@gnu.org>
+
+ Change installation structure for data files from .../groff/... to
+ .../groff/<version><revision>/... to be conform with other GNU
+ programs.
+
+ * Imakefile.in: Implement it.
+
+Version 1.16.1 released
+=======================
+
+Version 1.16 released
+=====================
+
+2000-05-18 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c: Adding `cq' as an alias for "'" in latin-1 map.
+
+2000-05-03 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c: Adding `dq' as an alias for `"' in latin-1 map.
+
+2000-04-28 Werner LEMBERG <wl@gnu.org>
+
+ * DviChar.c: Replacing `md' glyph name with `pc' in latin-1 map to
+ make it distinct from the `md' glyph in the symbol font.
+
+2000-03-03 Werner LEMBERG <wl@gnu.org>
+
+ * Imakefile replaced with Imakefile.in which will be configured by
+ the main configure script of groff. This will set the correct font
+ path, and it will make it possible to build xditview in a directory
+ different from $srcdir.
+
+2000-03-01 Colin Phipps <crp22@cam.ac.uk>
+
+ * Dvi.c (OpenFile): Use tmpdir() for security reasons.
+ * xtotroff.c (MapFont): Avoid race while opening file.
+
+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-13 Werner LEMBERG <wl@gnu.org>
+
+ * Makefile: Removed.
+
+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/contrib/groff/src/xditview/DESC b/contrib/groff/src/xditview/DESC
new file mode 100644
index 0000000..172170c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/Dvi.c b/contrib/groff/src/xditview/Dvi.c
new file mode 100644
index 0000000..08eb810
--- /dev/null
+++ b/contrib/groff/src/xditview/Dvi.c
@@ -0,0 +1,573 @@
+#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;
+{
+ dw->dvi.tmpFile = 0;
+ if (!dw->dvi.seek)
+ dw->dvi.tmpFile = tmpfile();
+ 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/contrib/groff/src/xditview/Dvi.h b/contrib/groff/src/xditview/Dvi.h
new file mode 100644
index 0000000..5aab7d8
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/DviChar.c b/contrib/groff/src/xditview/DviChar.c
new file mode 100644
index 0000000..2aaba45
--- /dev/null
+++ b/contrib/groff/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 */},
+{ "\"","dq", /* 34 */},
+{ "#","sh", /* 35 */},
+{ "$","Do", /* 36 */},
+{ "%", /* 37 */},
+{ "&", /* 38 */},
+{ "'","cq", /* 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 */},
+{ "pc", "\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/contrib/groff/src/xditview/DviChar.h b/contrib/groff/src/xditview/DviChar.h
new file mode 100644
index 0000000..b075240
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/DviP.h b/contrib/groff/src/xditview/DviP.h
new file mode 100644
index 0000000..851fdfe
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/FontMap b/contrib/groff/src/xditview/FontMap
new file mode 100644
index 0000000..90911f0
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/GXditview-ad.h b/contrib/groff/src/xditview/GXditview-ad.h
new file mode 100644
index 0000000..d9be3da
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/GXditview.ad b/contrib/groff/src/xditview/GXditview.ad
new file mode 100644
index 0000000..e99ff5e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/INSTALL b/contrib/groff/src/xditview/INSTALL
new file mode 100644
index 0000000..144118f
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/Imakefile.in b/contrib/groff/src/xditview/Imakefile.in
new file mode 100644
index 0000000..3ad244d
--- /dev/null
+++ b/contrib/groff/src/xditview/Imakefile.in
@@ -0,0 +1,104 @@
+srcdir=@srcdir@
+top_srcdir=@top_srcdir@
+VPATH=@srcdir@
+top_builddir=@top_builddir@
+
+version=`cat $(top_srcdir)/VERSION`
+# No additional number if revision is zero
+revision=`sed -e 's/^0$$//' -e 's/^[1-9].*$$/.&/' $(top_srcdir)/REVISION`
+
+GROFF_PREFIX = @prefix@
+GROFF_DATADIR = $(GROFF_PREFIX)/share
+GROFF_DATAPROGRAMDIR = $(GROFF_DATADIR)/groff
+GROFF_DATASUBDIR = $(GROFF_DATAPROGRAMDIR)/$(version)$(revision)
+GROFF_FONTDIR = $(GROFF_DATASUBDIR)/font
+GROFF_FONTPATH = $(GROFF_FONTDIR):/usr/local/lib/font:/usr/lib/font
+DPIS = 75 100
+
+PROGRAMS = \
+ gxditview \
+ xtotroff
+DEPLIBS = XawClientDepLibs
+LOCAL_LIBRARIES = XawClientLibs
+SRCS1 = \
+ $(srcdir)/xditview.c \
+ $(srcdir)/Dvi.c \
+ $(srcdir)/draw.c \
+ $(srcdir)/font.c \
+ $(srcdir)/lex.c \
+ $(srcdir)/page.c \
+ $(srcdir)/parse.c \
+ $(srcdir)/XFontName.c \
+ $(srcdir)/DviChar.c \
+ $(srcdir)/device.c
+OBJS1 = \
+ xditview.o \
+ Dvi.o \
+ draw.o \
+ font.o \
+ lex.o \
+ page.o \
+ parse.o \
+ XFontName.o \
+ DviChar.o \
+ device.o
+SRCS2 = \
+ $(srcdir)/xtotroff.c \
+ $(srcdir)/XFontName.c \
+ $(srcdir)/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 = $(top_builddir)/font
+MKINSTALLDIRS = $(top_srcdir)/mkinstalldirs
+
+ComplexProgramTarget_1(gxditview,$(LOCAL_LIBRARIES),$(MATHLIB))
+NormalProgramTarget(xtotroff,$(OBJS2),$(DEPXLIB),$(XLIB), /**/)
+
+InstallAppDefaults(GXditview)
+
+fonts: xtotroff $(srcdir)/DESC $(srcdir)/FontMap
+ @dir=`pwd`; \
+ fonts=`sed -e 's/[ ].*//' $(srcdir)/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/" $(srcdir)/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 $(srcdir)/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/' $(srcdir)/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 $(srcdir)/FontMap); \
+ done
+
+GXditview-ad.h: $(srcdir)/GXditview.ad
+ /bin/sh $(srcdir)/ad2c $(srcdir)/GXditview.ad >GXditview-ad.h
+
+extraclean: clean
+ -rm -f junk tmp grot old Makefile Imakefile
+
+FORCE:
diff --git a/contrib/groff/src/xditview/Menu.h b/contrib/groff/src/xditview/Menu.h
new file mode 100644
index 0000000..c306b27
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/README b/contrib/groff/src/xditview/README
new file mode 100644
index 0000000..b18f64a
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/TODO b/contrib/groff/src/xditview/TODO
new file mode 100644
index 0000000..161a7cf
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/XFontName.c b/contrib/groff/src/xditview/XFontName.c
new file mode 100644
index 0000000..5ca9bb8
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/XFontName.h b/contrib/groff/src/xditview/XFontName.h
new file mode 100644
index 0000000..efe9eb1
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/ad2c b/contrib/groff/src/xditview/ad2c
new file mode 100644
index 0000000..651ab8c
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/device.c b/contrib/groff/src/xditview/device.c
new file mode 100644
index 0000000..264f681
--- /dev/null
+++ b/contrib/groff/src/xditview/device.c
@@ -0,0 +1,600 @@
+/* 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, result)
+ char *file, **result;
+{
+ char *buf = NULL;
+ int bufsiz = 0;
+ int flen;
+ FILE *fp;
+ char *path;
+ char *env;
+
+ env = getenv(FONTPATH_ENV_VAR);
+ path = XtMalloc(((env && *env) ? strlen(env) + 1 : 0)
+ + strlen(FONTPATH) + 1);
+ *path = '\0';
+ if (env && *env) {
+ strcat(path, env);
+ strcat(path, ":");
+ }
+ strcat(path, FONTPATH);
+
+ *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);
+
+ 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);
+ fp = find_file(buf, 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/contrib/groff/src/xditview/device.h b/contrib/groff/src/xditview/device.h
new file mode 100644
index 0000000..2b9a64b
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/draw.c b/contrib/groff/src/xditview/draw.c
new file mode 100644
index 0000000..69e86cd
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/font.c b/contrib/groff/src/xditview/font.c
new file mode 100644
index 0000000..2e028aa
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray1.bm b/contrib/groff/src/xditview/gray1.bm
new file mode 100644
index 0000000..c40a95e
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray2.bm b/contrib/groff/src/xditview/gray2.bm
new file mode 100644
index 0000000..e87a1bc
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray3.bm b/contrib/groff/src/xditview/gray3.bm
new file mode 100644
index 0000000..d9313eb
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray4.bm b/contrib/groff/src/xditview/gray4.bm
new file mode 100644
index 0000000..dad142a
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray5.bm b/contrib/groff/src/xditview/gray5.bm
new file mode 100644
index 0000000..5f57618
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray6.bm b/contrib/groff/src/xditview/gray6.bm
new file mode 100644
index 0000000..b76701d
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray7.bm b/contrib/groff/src/xditview/gray7.bm
new file mode 100644
index 0000000..ef47bc6
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gray8.bm b/contrib/groff/src/xditview/gray8.bm
new file mode 100644
index 0000000..12de7cb
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/gxditview.man b/contrib/groff/src/xditview/gxditview.man
new file mode 100644
index 0000000..04cd446
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/lex.c b/contrib/groff/src/xditview/lex.c
new file mode 100644
index 0000000..32831bd
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/page.c b/contrib/groff/src/xditview/page.c
new file mode 100644
index 0000000..9284199
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/parse.c b/contrib/groff/src/xditview/parse.c
new file mode 100644
index 0000000..e1df8c9
--- /dev/null
+++ b/contrib/groff/src/xditview/parse.c
@@ -0,0 +1,335 @@
+/*
+ * 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 'F': /* input files */
+ 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/contrib/groff/src/xditview/xdit.bm b/contrib/groff/src/xditview/xdit.bm
new file mode 100644
index 0000000..67b9c8a
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/xdit_mask.bm b/contrib/groff/src/xditview/xdit_mask.bm
new file mode 100644
index 0000000..f34a4f8
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/xditview.c b/contrib/groff/src/xditview/xditview.c
new file mode 100644
index 0000000..e836cf5
--- /dev/null
+++ b/contrib/groff/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/contrib/groff/src/xditview/xtotroff.c b/contrib/groff/src/xditview/xtotroff.c
new file mode 100644
index 0000000..97cac0a
--- /dev/null
+++ b/contrib/groff/src/xditview/xtotroff.c
@@ -0,0 +1,311 @@
+/*
+ * xtotroff
+ *
+ * convert X font metrics into troff font metrics
+ */
+
+#include <X11/Xlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.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);
+
+ { /* Avoid race while opening file */
+ int fd;
+ (void) unlink (troff_name);
+ fd = open (troff_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ out = fdopen (fd, "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/contrib/groff/test-groff b/contrib/groff/test-groff
index 83492ea..16205be 100755
--- a/contrib/groff/test-groff
+++ b/contrib/groff/test-groff
@@ -19,6 +19,7 @@ $builddir/preproc/tbl:\
$builddir/preproc/grn:\
$builddir/preproc/refer:\
$builddir/preproc/soelim:\
+$builddir/preproc/html:\
$builddir/devices/grops:\
$builddir/devices/grodvi:\
$builddir/devices/grotty:\
@@ -35,7 +36,7 @@ export XENVIRONMENT
GROFF_COMMAND_PREFIX=
GROFF_FONT_PATH=$builddir:$srcdir/font
-GROFF_TMAC_PATH=$srcdir/tmac:$srcdir/src/roff/troff
+GROFF_TMAC_PATH=$srcdir/tmac
export PATH GROFF_COMMAND_PREFIX GROFF_FONT_PATH GROFF_TMAC_PATH
exec $builddir/roff/groff/groff ${1+"$@"}
diff --git a/contrib/groff/tmac/Makefile.sub b/contrib/groff/tmac/Makefile.sub
index be06cc7..954e177 100644
--- a/contrib/groff/tmac/Makefile.sub
+++ b/contrib/groff/tmac/Makefile.sub
@@ -4,24 +4,34 @@ MAN7=\
groff_ms.n \
groff_man.n \
groff_me.n \
- groff_msafer.n \
groff_mdoc.n \
- groff_mdoc.samples.n \
- groff_markup.n
+ groff_mwww.n
NORMALFILES=\
- tmac.mandoc 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.markup \
- tmac.arkup tmac.a4 tmac.trace tmac.me tmac.mdoc
-SPECIALFILES=tmac.an tmac.s tmac.man tmac.ms
-STRIPFILES=tmac.e tmac.doc tmac.doc.old
+ mandoc.tmac andoc.tmac an-old.tmac \
+ me.tmac \
+ mdoc.tmac \
+ pic.tmac \
+ a4.tmac \
+ safer.tmac \
+ trace.tmac \
+ ps.tmac psold.tmac pspic.tmac psatk.tmac \
+ dvi.tmac \
+ tty.tmac tty-char.tmac latin1.tmac \
+ X.tmac Xps.tmac \
+ lj4.tmac \
+ html.tmac mwww.tmac www.tmac \
+ eqnrc \
+ troffrc troffrc-end \
+ hyphen.us
+SPECIALFILES=an.tmac man.tmac s.tmac ms.tmac
+STRIPFILES=e.tmac doc.tmac doc-old.tmac
MDOCFILES=doc-common doc-ditroff doc-nroff doc-syms
mdocdir=$(tmacdir)/mdoc
CLEANADD=\
- stamp-strip stamp-wrap stamp-sed tmac.e-s tmac.doc-s tmac.doc.old-s \
- doc-common-s doc-ditroff-s doc-nroff-s doc-syms-s *-wrap \
- tmac.man-sed tmac.ms-sed
+ stamp-wrap stamp-sed *-wrap man.tmac-sed ms.tmac-sed \
+ stamp-strip e.tmac-s doc.tmac-s doc-old.tmac-s \
+ doc-common-s doc-ditroff-s doc-nroff-s doc-syms-s mdoc.local-s
tmac_s_prefix=
tmac_an_prefix=
tmac_wrap=
@@ -29,26 +39,28 @@ sys_tmac_prefix=
all: stamp-strip stamp-wrap stamp-sed
-install_data: $(NORMALFILES) $(SPECIALFILES) \
- stamp-wrap stamp-strip stamp-sed man.local
+install_data: $(NORMALFILES) $(SPECIALFILES) man.local \
+ stamp-strip stamp-wrap stamp-sed
-test -d $(tmacdir) || $(mkinstalldirs) $(tmacdir)
+ -test -d $(systemtmacdir) || $(mkinstalldirs) $(systemtmacdir)
+ -test -d $(localtmacdir) || $(mkinstalldirs) $(localtmacdir)
if test -n "$(tmac_wrap)"; then \
for m in ""$(tmac_wrap); do \
- $(INSTALL_DATA) $$m-wrap $(tmacdir)/tmac.$$m; \
+ $(INSTALL_DATA) $$m-wrap $(systemtmacdir)/$$m.tmac; \
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.ms
- $(INSTALL_DATA) tmac.ms-sed $(tmacdir)/tmac.ms
- -rm -f $(tmacdir)/tmac.$(tmac_an_prefix)an
- $(INSTALL_DATA) $(srcdir)/tmac.an $(tmacdir)/tmac.$(tmac_an_prefix)an
- -rm -f $(tmacdir)/tmac.man
- $(INSTALL_DATA) tmac.man-sed $(tmacdir)/tmac.man
+ -rm -f $(tmacdir)/$(tmac_s_prefix)s.tmac
+ $(INSTALL_DATA) $(srcdir)/s.tmac $(tmacdir)/$(tmac_s_prefix)s.tmac
+ -rm -f $(tmacdir)/ms.tmac
+ $(INSTALL_DATA) ms.tmac-sed $(tmacdir)/ms.tmac
+ -rm -f $(tmacdir)/$(tmac_an_prefix)an.tmac
+ $(INSTALL_DATA) $(srcdir)/an.tmac $(tmacdir)/$(tmac_an_prefix)an.tmac
+ -rm -f $(tmacdir)/man.tmac
+ $(INSTALL_DATA) man.tmac-sed $(tmacdir)/man.tmac
for f in $(STRIPFILES); do \
rm -f $(tmacdir)/$$f; \
$(INSTALL_DATA) $$f-s $(tmacdir)/$$f; \
@@ -58,12 +70,13 @@ install_data: $(NORMALFILES) $(SPECIALFILES) \
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
+ -test -f $(localtmacdir)/man.local || \
+ $(INSTALL_DATA) $(srcdir)/man.local $(localtmacdir)/man.local
+ -test -f $(localtmacdir)/mdoc.local || \
+ $(INSTALL_DATA) mdoc.local-s $(localtmacdir)/mdoc.local
-stamp-strip: $(STRIPFILES) $(MDOCFILES)
- for f in $(STRIPFILES) $(MDOCFILES); do \
+stamp-strip: $(STRIPFILES) $(MDOCFILES) mdoc.local
+ for f in $(STRIPFILES) $(MDOCFILES) mdoc.local; do \
rm -f $$f-s; \
sed -f $(srcdir)/strip.sed $(srcdir)/$$f >$$f-s; \
done
@@ -73,14 +86,17 @@ stamp-wrap:
if test -n "$(tmac_wrap)"; then \
for m in ""$(tmac_wrap); do \
rm -f $$m-wrap; \
- echo .cp 1 >$$m-wrap; \
+ if test "$$m" = an; then \
+ echo .do mso andoc.tmac >>$$m-wrap; \
+ fi; \
+ echo .cp 1 >>$$m-wrap; \
echo .so $(sys_tmac_prefix)$$m >>$$m-wrap; \
done; \
fi
touch $@
-stamp-sed: tmac.man tmac.ms
- for f in tmac.man tmac.ms; do \
+stamp-sed: man.tmac ms.tmac
+ for f in man.tmac ms.tmac; do \
rm -f $$f-sed; \
sed -e "s;@TMAC_AN_PREFIX@;$(tmac_an_prefix);g" \
-e "s;@TMAC_S_PREFIX@;$(tmac_s_prefix);g" \
@@ -91,15 +107,20 @@ stamp-sed: tmac.man tmac.ms
uninstall_sub:
-if test -n "$(tmac_wrap)"; then \
for m in ""$(tmac_wrap); do \
- rm -f $(tmacdir)/tmac.$$m; \
+ rm -f $(systemtmacdir)/$$m.tmac; \
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
- -rm -f $(tmacdir)/tmac.man $(tmacdir)/tmac.ms
- -if cmp -s $(tmacdir)/man.local $(srcdir)/man.local; then \
- rm -f $(tmacdir)/man.local; \
+ -for f in $(NORMALFILES) $(STRIPFILES); do \
+ rm -f $(tmacdir)/$$f; \
+ done
+ -rm -f $(tmacdir)/$(tmac_s_prefix)s.tmac
+ -rm -f $(tmacdir)/$(tmac_an_prefix)an.tmac
+ -rm -f $(tmacdir)/man.tmac $(tmacdir)/ms.tmac
+ -if cmp -s $(localtmacdir)/man.local $(srcdir)/man.local; then \
+ rm -f $(localtmacdir)/man.local; \
+ fi
+ -if cmp -s $(localtmacdir)/mdoc.local $(srcdir)/mdoc.local; then \
+ rm -f $(localtmacdir)/mdoc.local; \
fi
-for f in $(MDOCFILES); do rm -f $(mdocdir)/$$f; done
-rmdir $(mdocdir)
diff --git a/contrib/groff/tmac/X.tmac b/contrib/groff/tmac/X.tmac
new file mode 100644
index 0000000..464770c
--- /dev/null
+++ b/contrib/groff/tmac/X.tmac
@@ -0,0 +1,48 @@
+.\" X.tmac
+.\"
+.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 pspic.tmac
+.cp \n(_C
diff --git a/contrib/groff/tmac/Xps.tmac b/contrib/groff/tmac/Xps.tmac
new file mode 100644
index 0000000..ddb037a
--- /dev/null
+++ b/contrib/groff/tmac/Xps.tmac
@@ -0,0 +1,46 @@
+.\" Xps.tmac
+.\"
+.do mso ps.tmac
+.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/contrib/groff/tmac/a4.tmac b/contrib/groff/tmac/a4.tmac
new file mode 100644
index 0000000..5001939
--- /dev/null
+++ b/contrib/groff/tmac/a4.tmac
@@ -0,0 +1,12 @@
+.\" a4.tmac
+.\"
+.\" Set up groff for A4 paper. Must be called before any other macro
+.\" package. For correct PS output, you must also set the
+.\" `paperlength' keyword in devps/DESC to 841890 in case groff hasn't
+.\" guessed it correctly during configuration.
+.
+.pl 29.7c
+.ll 21c-2i
+.
+.\" for ms
+.if !rLL .nr LL \n[.l]u
diff --git a/contrib/groff/tmac/an-old.tmac b/contrib/groff/tmac/an-old.tmac
new file mode 100644
index 0000000..9ef041f
--- /dev/null
+++ b/contrib/groff/tmac/an-old.tmac
@@ -0,0 +1,478 @@
+.\" an-old.tmac
+.\"
+.\" Copyright (C) 1989, 1990, 1991, 1992, 2001 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.
+.\"
+.\" -rcR=1 => Create a single, very long page instead of multiple pages.
+.\" Useful for online display. Default in nroff mode.
+.\" Desactivate with -rcR=0.
+.\" -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.
+.\" -rSxx => Use size `xx'pt (either 10, 11, or 12) for document rather
+.\" than the default size of 10pt.
+.\" -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 !r D .nr D 0
+.if !r C .nr C 0
+.if !r S .nr S 10
+.\" we must use consecutive page numbers when using postscript to generate
+.\" html images, and we must not reset the page number at the beginning
+.\" (the `ps4html' register is automatically added to the command line by
+.\" the pre-html preprocessor)
+.if !r ps4html \
+. if r P .pn 0\n[P]
+.if !r cR \{\
+. ie n .nr cR 1
+. el .nr cR 0
+.\}
+.
+.nr an-html 0
+.if '\*(.T'html' .nr an-html 1
+.if \n[an-html] .nr C 1
+.if r ps4html .nr C 1
+.
+.de set-an-margin
+. nr an-margin \\n[IN]
+..
+.
+.\" .TH title section extra1 extra2 extra3
+.de TH
+. if \\n[an-html] \{\
+. HTML-TAG ".tl"
+\\$1
+. \}
+. 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
+.
+. nr PS 10z \" default point size
+. nr PS-SS 10z
+. nr PS-SH 10.95z
+. nr VS 12p
+.
+. \" use sizes similar to LaTeX
+. if t \{\
+. ie (\\n[S] == 11) \{\
+. nr PS 10.95z
+. nr PS-SS 10.95z
+. nr PS-SH 12z
+. nr VS 13.6p
+. \}
+. el \{\
+. if (\\n[S] == 12) \{\
+. nr PS 12z
+. nr PS-SS 12z
+. nr PS-SH 14.4z
+. nr VS 14.5p
+. \}
+. \}
+. \}
+.
+. ps \\n[PS]u
+. vs \\n[VS]u
+.
+. nr IN 7.2n
+. PD
+. 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
+.
+. ie \\n[cR] \
+. an-header
+. el \{\
+. wh 0 an-header
+. wh -1i an-footer
+. wh -.5i an-p-footer
+.
+. if (\\n[nl] > 0) \{\
+. ie \\n[C] .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
+. ps \\n[PS]u
+. vs \\n[VS]u
+. ie \\n[an-html] \
+. tl ''''
+. el \{\
+. if !\\n[cR] \
+. sp .5i
+. tl '\\*[an-title](\\*[an-section])'\\*[an-extra3]'\\*[an-title](\\*[an-section])'
+. ie !\\n[cR] \
+. sp |1i
+. el \
+. sp .5i
+. \}
+. ev
+. ns
+..
+.
+.de an-footer
+' bp
+..
+.
+.af an-page-letter a
+.
+.de an-p-footer
+. ev 1
+. ps \\n[PS]u
+. vs \\n[VS]u
+. ie \\n[an-html] \{\
+. ds an-page-string
+. ds an-extra1
+. ds an-extra2
+. \}
+. el \{\
+. ie r X \{\
+. if (\\n[%] > \\n[X]) \{\
+. nr an-page-letter (\\n[%] - \\n[X])
+. ds an-page-string \\n[X]\\n[an-page-letter]
+. \}
+. \}
+. el \{\
+. ie \\n[cR] \
+. ds an-page-string "\\*[an-title](\\*[an-section])
+. el \
+. ds an-page-string \\n[%]
+. \}
+. \}
+. ie \\n[D] \{\
+. 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]'
+. ev
+..
+.
+.de an-end
+. nr % 1
+. pl +3v
+. fl
+. sp 3
+. an-p-footer
+. pl \\n[nl]u
+..
+.
+.if \n[cR] .em an-end
+.
+.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
+. HTML-TAG ".NH \\n[an-level]"
+. it 1 an-trap
+. nr an-no-space-flag 1
+. nr an-break-flag 1
+. ps \\n[PS-SH]u
+. ft B
+. if !\\n[cR] .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-SS]u
+. ft B
+. if !\\n[cR] .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
+. ie \\n[an-html] .in \\n[an-margin]u
+. el \{\
+. in 0
+. ll -\\n[an-margin]u
+. \}
+. nr an-div? 1
+..
+.
+.de an-trap
+. ft R
+. ps \\n[PS]u
+. vs \\n[VS]u
+. 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
+. ll
+. di
+. ie (\\n[dl] + \\n[an-tag-sep] > \\n[an-prevailing-indent]) \{\
+. in \\n[an-margin]u
+. if !\\n[cR] .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
+. if !\\n[cR] .ne (1v + 1u)
+\\*[an-div]\\h'|\\n[an-prevailing-indent]u'\c
+. \}
+..
+.
+.de LP
+. br
+. sp \\n[PD]u
+. ps \\n[PS]u
+. vs \\n[VS]u
+. 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]u
+. vs \\n[VS]u
+. ft R
+. sp \\n[PD]u
+. if !\\n[cR] .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]u
+. vs \\n[VS]u
+. ft R
+. sp \\n[PD]u
+. if !\\n[cR] .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 \,\f[I]\\$1\f[R]\/\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \,\f[I]\\$1\f[R]
+\\*[an-result]
+. \}
+..
+.
+.de IR
+. if \\n[.$] \{\
+. ds an-result \&\f[I]\\$1\f[R]
+. shift
+. while (\\n[.$] >= 2) \{\
+. as an-result \/\\$1\f[I]\,\\$2\f[R]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \/\\$1
+\\*[an-result]
+. \}
+..
+.
+.de IB
+. if \\n[.$] \{\
+. ds an-result \&\f[I]\\$1
+. shift
+. while (\\n[.$] >= 2) \{\
+. as an-result \/\f[B]\\$1\f[I]\,\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \/\f[B]\\$1
+\\*[an-result]
+. ft R
+. \}
+..
+.
+.de BI
+. if \\n[.$] \{\
+. ds an-result \&\f[B]\\$1
+. shift
+. while (\\n[.$] >= 2) \{\
+. as an-result \,\f[I]\\$1\f[B]\/\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \,\f[I]\\$1
+\\*[an-result]
+. ft R
+. \}
+..
+.
+.de RB
+. ds an-result \&
+. while (\\n[.$] >= 2) \{\
+. as an-result \f[R]\\$1\f[B]\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \f[R]\\$1
+\\*[an-result]
+. ft R
+..
+.
+.de BR
+. ds an-result \&
+. while (\\n[.$] >= 2) \{\
+. as an-result \f[B]\\$1\f[R]\\$2\\*[an-empty]
+. shift 2
+. \}
+. if \\n[.$] .as an-result \f[B]\\$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
+.
+.if !\n[an-html] .hy 14
+.
+.\" Load local modifications.
+.mso man.local
+.
+.cp \n[_C]
+.
+.\" end of an-old.tmac
diff --git a/contrib/groff/tmac/an.tmac b/contrib/groff/tmac/an.tmac
new file mode 100644
index 0000000..2e3c243
--- /dev/null
+++ b/contrib/groff/tmac/an.tmac
@@ -0,0 +1,3 @@
+.\" an.tmac
+.\"
+.do mso andoc.tmac
diff --git a/contrib/groff/tmac/andoc.tmac b/contrib/groff/tmac/andoc.tmac
new file mode 100644
index 0000000..f6a16db
--- /dev/null
+++ b/contrib/groff/tmac/andoc.tmac
@@ -0,0 +1,14 @@
+.\" andoc.tmac
+.\"
+.\" Load either an-old.tmac or doc.tmac.
+.if !\n(.g .ab These macros require groff.
+.de Dd
+.rm Dd
+.do mso doc.tmac
+\\*(Dd\\
+..
+.de TH
+.rm TH
+.do mso an-old.tmac
+\\*(TH\\
+..
diff --git a/contrib/groff/tmac/doc-old.tmac b/contrib/groff/tmac/doc-old.tmac
new file mode 100644
index 0000000..5e5db59
--- /dev/null
+++ b/contrib/groff/tmac/doc-old.tmac
@@ -0,0 +1,1858 @@
+.\"
+.\" Copyright (c) 1990 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-old.tmac 5.2 (Berkeley) 3/13/91
+.\" Slightly modified by jjc@jclark.com to work with groff as well.
+.\"
+.\" Assume nroff on crt's only if cR==1
+.if n .nr cR 1
+.\" STRING CONSTANTS
+.\" DITROFF
+.if t \{\
+.\" Address Style
+.ds aD \fI
+.\" Argument Reference Style
+.ds aR \f(CO
+.\" Interactive Comand Modifier (flag)
+.ds cM \f(CB
+.\" Emphasis (in the English sense - usually italics)
+.ds eM \fI
+.\" Errno Style
+.ds eR \fC
+.\" Environment Variable Style
+.ds eV \fC
+.\" Command Line Flag Style
+.ds fL \f(CB
+.\" Header String Style
+.ds Hs \fR
+.\" Interactive Command Style
+.ds iC \f(CB
+.\" Literal Style
+.ds lI \fC
+.\" Left Parenthesis Style
+.ds lP \fR\|(\|\fP
+.\" Right Parenthesis Style
+.ds rP \fR\|)\|\fP
+.\" Options Open Bracket Style
+.ds lB \fR\^[\^\fP
+.\" Options Open Bracket Style
+.ds rB \fR\^]\fP
+.\" Name (subject of manpage) Style
+.ds nM \f(CB
+.\" Pathname Style
+.ds pA \fC
+.\" Accepted punctuation string for -mdoc syntax
+.ds Pu \fR[.,:;(\^)[\^]\fR]
+.\" Section Header Style
+.ds Sp \s12\fB
+.\" .ds sT \s-2\fR
+.\" Symbolic Emphasis (boldface)
+.ds sY \f(CB
+.\" Generic Variable Style
+.ds vA \fI
+.\" Volume Title Style
+.ds Vs \fR
+.\" Cross Reference STyle (man page only)
+.ds xR \fC
+.\" Math *
+.tr *\(**
+.\}
+.\" NROFF
+.if n \{\
+.\" Address Style
+.ds aD \fI
+.\" Argument Reference Style
+.ds aR \fI
+.\" Interactive Command Modifier (flag)
+.ds cM \fB
+.\" Emphasis (in the English sense - usually italics)
+.ds eM \fI
+.\" Errno Style
+.ds eR \fR
+.\" Environment Variable Style
+.ds eV \fR
+.\" Command Line Flag Style
+.ds fL \fB
+.\" Header String Style
+.ds Hs \fR
+.\" Interactive Command Style
+.ds iC \fB
+.\" Literal Style
+.ds lI \fR
+.\" Left Parenthesis Style
+.ds lP \fR\|(\fP
+.\" Right Parenthesis Style
+.ds rP \fR\|)\fP
+.\" Options Open Bracket Style
+.ds lB \fR\|[\|\fP
+.\" Options Open Bracket Style
+.ds rB \fR\|]\fP
+.\" Name (subject of manpage) Style
+.ds nM \fB
+.\" Pathname Style
+.ds pA \fI
+.\" Accepted punctuation string for -mdoc syntax
+.ds Pu [.,;:()[]]
+.\" Section Header Style
+.ds Sp \s12\fB
+.\" .ds sT \s-2\fR
+.\" .ds sT \s-2\fR
+.\" Symbol, Mode or Mask Style
+.ds sY \fB
+.\" Generic Variable Style
+.ds vA \fI
+.\" Volume Title Style
+.ds Vs \fR
+.\" Cross Reference Style (man page only)
+.ds xR \fR
+.\}
+.\" INDENTS - Subheaders(sI), Text(Ti) between Section Headers and Subsects
+.if t \{\
+. nr sI \w'\fC,'u*5
+. nr Ti \n(sIu
+.\}
+.if n \{\
+. nr sI .5i
+. nr Ti .5i
+.\}
+.\" Flags for macros names which are used only for .Ds
+.nr dI 6n
+.nr dC 1
+.nr dL 1
+.nr dR 1
+.\" INDENT WIDTHS (for Lists)
+.\" Width Needed for Address Tag (indented amount)
+.nr Ad 12n
+.\" Angle Quote Width
+.nr Aq 12n
+.\" Width Needed for Argument
+.nr Ar 12n
+.\" Width Needed for Column offset
+.nr Cl 15n
+.\" Width neeeded for Interactive Command Modifier
+.nr Cm 10n
+.\" Width Needed for Complex Expressions
+.nr Cx 20n
+.\" Indent Width Needed for Display (right and left margins)
+.nr Ds 6n
+.\" Double Quote Width
+.nr Dq 12n
+.\" tI is dependent on Ds and used by .Dp
+.nr tI \n(Dsu
+.\" Width Needed for Display
+.nr Em 10n
+.\" Width Needed for Errno Types
+.nr Er 15n
+.\" Width Needed for Environment Variables
+.nr Ev 15n
+.\" Width Needed for Example Indent
+.nr Ex 10n
+.\" Width Needed for Flag
+.nr Fl 10n
+.\" Width Needed for Function
+.nr Fn 16n
+.\" Width neeeded for Interactive Command Name
+.nr Ic 10n
+.\" Width Needed for Constant
+.nr Li 16n
+.\" Width Needed for Math Symbol ? not sure if needed
+.nr Ms 6n
+.\" Width Needed for Name
+.nr Nm 10n
+.\" Width Needed for Option Begin
+.nr Ob 14n
+.\" Width Needed for Option End
+.nr Oe 14n
+.\" Width Needed for Option (one line)
+.nr Op 14n
+.\" Width Needed for Pathname
+.nr Pa 32n
+.\" Parenthesis Quote Width
+.nr Pq 12n
+.\" Single Quote Width
+.nr Sq 12n
+.\" Width Needed for Symbols, Modes or Masks
+.nr Sy 6n
+.\" Width needed for default or unknown text width
+.nr Tx 22n
+.\" Width Needed for Generic Variable
+.nr Va 12n
+.\" Width Needed for Cross Reference, should the cross ref be annotated.
+.nr Xr 10n
+.\" PARAGRAPH SPACE
+.if t \{\
+. nr Pp .5v
+.\}
+.if n \{\
+. nr Pp 1v
+.\}
+.\" PAGE LAYOUT
+.\" .Li Tagged Paragraph Style - zero if break on oversized tag
+.\" one if add em space and continue filling line.
+.nr tP 0
+.\" Page Layout Macro
+.de pL
+.\" DITROFF
+.ie t \{\
+.\" Header Margin
+. nr Hm .5i
+.\" Footer Margin
+. nr Fm .5i
+.\" Line length
+. nr ll 5.5i
+.\" Line length
+. ll 5.5i
+.\" Title length
+. nr lt 5.5i
+.\" Title length
+. lt 5.5i
+.\" Page offset
+. nr po 1.56i
+.\" Page offset
+. po 1.56i
+.\" Vertical space distance (from Section headers/Lists/Subsections)
+. nr vV .5v
+.\" em space
+. ds tP \|\|\|\|\|\|
+.\}
+.el \{\
+.\" Line length
+. nr ll 78n
+. ll 78n
+.\" Title length
+. nr lt 78n
+.\" Title length
+. lt 78n
+.\" Page offset
+. nr po 0i
+.\" Page offset
+. po 0i
+.\" Vertical space distance (from Section headers/Lists/Subsections)
+. nr vV 1v
+.\" em space
+. ds tP \0\0
+.\" Test for crt
+. ie \\n(cR .nr Hm 0
+. el .nr Hm .5i
+.\" Footer Margin
+. nr Fm .5i
+.\}
+..
+.\" Adjustment mode
+.if n \{\
+.ad l
+.na
+..
+.\}
+.\" PREDEFINED STRINGS
+.if t \{\
+. ds <= \(<=
+. ds >= \(>=
+. ds Lq \&``
+. ds Rq \&''
+. ds ua \(ua
+. ds aa \(aa
+. ds ga \(ga
+. ds sR \(aa
+. ds sL \(ga
+.\}
+.if n \{\
+. ds <= \&<\&=
+. ds >= \&>\&=
+. ds Rq ''
+. ds Lq ``
+. ds ua ^
+. ds aa '
+. ds ga `
+. ds sL `
+. ds sR '
+.\}
+.\" Note: The distances from the bottom or top of the page are set
+.\" in headers (macro .hK): to -1.25 for troff, and -1.167 for nroff
+.\" bottoms, and top is 0.
+.\"
+.\" .Dt Document/manpage_title section/chapter volume
+.\" The \{ and \} is necessary as roff doesn't nest if-elses
+.\" properly, especially with .ds.
+.\" TODO: separate Dt into Dt, Ch and Vt for supp docs.
+.de Dt
+.ds dT UNTITLED
+.ds vT Local
+.ds cH Null
+.\" Volume and Section Number or Chapter Number
+.if !"\\$1"" .ds dT \\$1
+.if !"\\$2"" \{\
+. ds cH \\$2
+. if "\\$3"" \{\
+. \" Volume Title if none given
+. if \\$2>=1 .if \\$2<=8 \{\
+. ds vT UNIX Reference Manual
+. if \\$2>1 .if \\$2<6 .ds vT UNIX Programmer's Manual
+. if "\\$2"8" .ds vT UNIX System Manager's Manual
+. \}
+. if "\\$2"unass" .ds vT DRAFT
+. if "\\$2"draft" .ds vT DRAFT
+. if "\\$2"paper" .ds vT Null
+. \}
+.\}
+.if !"\\$3"" \{\
+. \" Volume Title if given
+. if "\\$3"USD" .ds vT UNIX User's Supplementary Documents
+. if "\\$3"PS1" .ds vT UNIX Programmers's Supplementary Documents
+. if "\\$3"AMD" .ds vT UNIX Ancestral Manual Documents
+. if "\\$3"SMM" .ds vT UNIX System Manager's Manual
+. if "\\$3"URM" .ds vT UNIX Reference Manual
+. if "\\$3"PRM" .ds vT UNIX Programmers's Manual
+. if "\\$3"IND" .ds vT UNIX Manual Master Index
+. if "\\$3"CON" .ds vT UNIX Contributed Software Manual
+. if "\\$3"IMP" .ds vT UNIX Implementation Notes
+. if "\\$3"HOW" .ds vT UNIX How Pocket Manual
+. if "\\$3"LOCAL" .ds vT UNIX Local Manual
+. if "\\*(vT"Local" .ds vT \\$3
+.\}
+..
+.\"
+.\" .Os Operating System/Standard and Release or Version Number
+.\"
+.de Os
+.ds oS Null
+.if "\\$1"" \{\
+. ds oS \fIBSD Experimental\fP
+.\" . ds oS (\fIBag o' Bits\fP)
+.\}
+.if "\\$2"" \{\
+. ds o1 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.3+" .ds oS 4.3+tahoe Berkeley Distribution
+.\}
+.if "\\*(oS"Null" .ds oS \\$1
+.if "\\*(o1"Non-Null" .as oS \0\\$2
+.rm o1
+..
+.\"
+.\" Standards
+.\"
+.\" .de St
+.\" .ds sT Null
+.\" .if "\\$1"POSIX" \{\
+.\" . ds sT IEEE Standard POSIX
+.\" . if \\$2 .as sT \0\\$2
+.\" .\}
+.\" .if "\\$1"ANSI" \{\
+.\" . ds sT ANSI Standard
+.\" . if \\$2 .as sT \0\\$2
+.\" .\}
+.\" .if "\\$1"ISO" \{\
+.\" . ds sT ISO Standard
+.\" . if \\$2 .as sT \0\\$2
+.\" .\}
+.\" .if "\\*(sT"Null" .ds sR \\$3
+.\" ..
+.\"
+.\" .de Gp
+.\" .ie !"\\$1"" .ds gP \&\\$1 \\$2 \\$3 \\$4 \\$5
+.\" .el .ds gP Null
+.\" ..
+.\"
+.\"
+.de Dd
+.nr aa 0
+.ie \\n(.$>0 \{\
+. ie \\n(.$<4 \{\
+. ds dD \\$1 \\$2 \\$3
+. \}
+. el .tm Usage: .Dd Month Day, Year (e.g July 4, 1977).
+.\}
+.el \{\
+. ds dD Epoch
+.\}
+..
+.\"
+.\" House Keeping Macro - Make sense of dT, cH, vT, sT, gP and dS
+.\" TODO: Try to get else's for efficiency
+.\" TODO: GET RID OF .wh -1.167i (its in v7)
+.\"
+.\"
+.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\|)
+.if t \{\
+. wh 0 hM
+. wh -1.25i fM
+.\}
+.if n \{\
+. ie \\n(cR \{\
+. hM
+. wh -0v fM
+. \}
+. el \{\
+. wh 0 hM
+. wh -1.167i fM
+. \}
+.\}
+.if n \{\
+. if \\n(nl==0:\\n(nl==-1 'bp
+.\}
+.if t 'bp
+.em lM
+..
+.\" Header Macro
+.\"
+.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
+.ev 1
+.pL
+.if !\\n(cR \{\
+' sp \\n(Fmu
+. tl @\\*(Hs\\*(oS\fP@\\*(Vs\\*(dD\fP@%@
+' bp
+.\}
+.if \\n(cR \{\
+.\" . tl @\\*(Hs\\*(oS\fP@\\*(Vs\\*(dD\fP@%@
+.\" ' bp
+.\}
+.ev
+..
+.de lM
+.fl
+.if \\n(cR \{\
+. fM
+. 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 Co
+.tm Not a \-mdoc command: .Co
+..
+.nr z. 1
+.nr z, 1
+.nr z: 1
+.nr z; 1
+.nr z) 1
+.nr z( 1
+.nr z[ 1
+.nr z] 1
+.\" This is disgusting, troff not parse if stmt properly
+.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 z0 0
+.nr z# 0
+.\"
+.de Ad
+.ie \\n(.$==0 \{\
+. tm Usage: .Ad address [...] \\*(Pu
+.\}
+.el \{\
+. ds sV \\*(aD
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.\" Command Line Argument Macro
+.\"
+.de Ar
+.ie \\n(.$==0 \{\
+. ie !"\\*(iM"" .as f1 \&[\|\\*(aRfile\ ...\fP\|]
+. el \&[\|\\*(aRfile\ ...\fP\|]
+.\}
+.el \{\
+. ds sV \\*(aR
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Em
+.ie \\n(.$==0 \{\
+. tm Usage: .Em text ... \\*(Pu
+.\}
+.el \{\
+. ds sV \\*(eM
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Er
+.ie \\n(.$==0 \{\
+. tm Usage: .Er ERRNOTYPE ... \\*(Pu
+. \}
+.el \{\
+. ds sV \\*(eR
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Ev
+.ie \\n(.$==0 \{\
+. tm Usage: .Ev ENVIRONMENT_VARIABLE(s) ... \\*(Pu
+. \}
+.el \{\
+. ds sV \\*(eV
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.\" Flag Name Macro
+.\"
+.de Fl
+.ie \\n(.$==0 \{\
+. ie !"\\*(iM"" .as f1 \&\\*(fL\-\fP
+. el \&\\*(fL\-\fP
+.\}
+.el \{\
+. nr rZ 0
+. sW \\$1
+. if (\\n(sW==1&\\n(.$==1) .rZ \\$1
+. ds sV \\*(fL
+. nr cF \\n(.f
+. ie \\n(rZ \{\
+. ie "\\*(iM"" .ds f1 \&\\*(sV\-\f\\n(cF\\$1
+. el \&\\*(sV\-\f\\n(cF\\$1
+. \}
+. el \{\
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. fB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+. \}
+.\}
+..
+.\" Interactive Commands Macro
+.\"
+.de Ic
+.ie \\n(.$==0 \{\
+. tm Usage: .Ic Interactive Commands(s) ... \\*(Pu
+.\}
+.el \{\
+. ds sV \\*(iC
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.\" Interactive Command Modifiers (flags)
+.\"
+.de Cm
+.ie \\n(.$==0 \{\
+. tm Usage: .Cm Interactive Command Modifier(s) ... \\*(Pu
+.\}
+.el \{\
+. ds sV \\*(cM
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Li
+.ie \\n(.$==0 \{\
+. tm Usage: .Li literal ... \\*(Pu
+. \}
+.el \{\
+. ds sV \\*(lI
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\" If in nroff or any other case where the default font
+.\" is constant width, and literal means zilch, single quote instead.
+.ie n \{\
+.de Ql
+. ie \\n(.$==0 \{\
+. tm Usage: .Ql literal ... \\*(Pu
+. \}
+. el \{\
+. Sq \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+..
+.\}
+.el \{\
+.de Ql
+. ie \\n(.$==0 \{\
+. tm Usage: .Ql literal ... \\*(Pu
+. \}
+. el \{\
+. Li \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+..
+.\}
+.\"
+.de Nm
+.ie \\n(.$==0 \{\
+. if "\\*(n1"" .tm Usage: .Nm Name(s) ... \\*(Pu
+. ie !"\\*(iM"" .as f1 \&\\*(nM\\*(n1\\$1\fP
+. el \&\\*(nM\\*(n1\\$1\fP
+.\}
+.el \{\
+. ds sV \\*(nM
+. nr cF \\n(.f
+. if \\n(nS \{\
+. rs
+. in -\\n(iSu
+. ie \\n(nS>1 .br
+. el \{\
+. sW \\$1
+. nr iS ((\\n(sW+1)*\\n(fW)u
+. \}
+. in +\\n(iSu
+. ti -\\n(iSu
+. nr nS \\n(nS+1
+. \}
+. if "\\*(n1"" .ds n1 \\$1
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Pa
+.ie \\n(.$==0 \{\
+\&\\*(pA~\fP
+.\}
+.el \{\
+. ds sV \\*(pA
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Sy
+.ie \\n(.$==0 \{\
+. tm Usage: .Sy Symbolic Text ... \\*(Pu
+. \}
+.el \{\
+. ds sV \\*(sY
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Ms
+.ie \\n(.$==0 \{\
+. tm Usage: .Ms Math Symbol ... \\*(Pu
+. \}
+.el \{\
+. ds sV \\*(sY
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de Va
+.ie \\n(.$==0 \{\
+. tm Usage: .Va variable_name(s) ... \\*(Pu
+.\}
+.el \{\
+. ds sV \\*(vA
+. nr cF \\n(.f
+. ie "\\*(iM"" .ds f1 \&\\*(sV
+. el .as f1 \&\\*(sV
+. nB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+.\}
+..
+.\"
+.de nB
+.hy 0
+.if \\n(.$==0 .tm Usage error: called with empty arguments (empty quotes)?
+.ie \\n(.$>1 \{\
+. rZ \\$1
+. ie \\n(rZ .as f1 \&\f\\n(cF\\$1\fP
+. el .as f1 \&\\$1
+. rZ \\$2
+. if !\\n(rZ \{\
+. ie !"\\*(iM""\{\
+.\" I surrender
+. if "\\*(iM"Tp" .as f1 \&\ \&
+. if "\\*(iM"Dp" .as f1 \&\ \&
+. if "\\*(iM"Op" .as f1 \&\ \&
+. if "\\*(iM"Cx" .as f1 \&\ \&
+. if "\\*(iM"Dq" .as f1 \& \&
+. if "\\*(iM"Sq" .as f1 \& \&
+. if "\\*(iM"Pq" .as f1 \& \&
+. if "\\*(iM"Aq" .as f1 \& \&
+. \}
+. el .as f1 \& \&
+. \}
+. nB \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.el \{\
+. rZ \\$1
+. ie \\n(rZ .as f1 \&\f\\n(cF\\$1
+. el .as f1 \&\\$1\f\\n(cF
+. if "\\*(iM"" \{\&\\*(f1
+. ds f1
+. \}
+. hy
+.\}
+..
+.de fB
+.hy 0
+.if \\n(.$==0 .tm Usage error: called with empty arguments (empty quotes)?
+.ie \\n(.$>1 \{\
+. rZ \\$1
+. ie \\n(rZ .as f1 \&\f\\n(cF\\$1\fP
+. el \{\
+. ie "\\$1"-" .as f1 \&\-\-
+. el .as f1 \&\-\\$1
+. \}
+. rZ \\$2
+. if !\\n(rZ \{\
+. ie !"\\*(iM""\{\
+.\" I surrender
+. if "\\*(iM"Tp" .as f1 \&\ \&
+. if "\\*(iM"Dp" .as f1 \&\ \&
+. if "\\*(iM"Op" .as f1 \&\ \&
+. if "\\*(iM"Cx" .as f1 \&\ \&
+. if "\\*(iM"Dq" .as f1 \& \&
+. if "\\*(iM"Sq" .as f1 \& \&
+. if "\\*(iM"Pq" .as f1 \& \&
+. if "\\*(iM"Aq" .as f1 \& \&
+. \}
+. el .as f1 \& \&
+. \}
+. fB \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.el \{\
+. rZ \\$1
+. ie \\n(rZ .as f1 \&\f\\n(cF\\$1
+. el \{\
+. ie "\\$1"-" .as f1 \&\-\-\f\\n(cF
+. el .as f1 \&\-\\$1\f\\n(cF
+. \}
+. if "\\*(iM"" \{\&\\*(f1
+. ds f1
+. \}
+. hy
+.\}
+..
+.\"
+.\" Single quoted Items
+.\" eF, sB g[0-9] and f2
+.de Sq
+.nr eF 0
+.ie \\n(.$==0 \{\
+. ie "\\*(iM"" \&\\*(sL\&\\*sR
+. el .as f1 \&\\*(sL\&\\*(sR
+.\}
+.el \{\
+. ie "\\*(iM"" \{\
+. ds f1 \&\\*(sL
+. ds iM Sq
+. \}
+. el .as f1 \&\\*(sL
+. sB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ie \\n(eF>0 .\\*(g1 \\*(g2 \\*(g3 \\*(g4 \\*(g5 \\*(g6 \\*(g7 \\*(g8
+. el .as f1 \\*(g0
+. as f1 \\*(sR
+. if !"\\*(f2"" .as f1 \\*(f2
+. if "\\*(iM"Sq" \{\
+\&\\*(f1
+. ds f1
+. ds iM
+. \}
+. ds f2
+. rm g0 g1 g2 g3 g4 g5 g6 g7 g8 g9
+. nr eF 0
+.\}
+..
+.\"
+.\" Double quoted Items
+.de Dq
+.nr Ef 0
+.ie \\n(.$==0 \{\
+. ie "\\*(iM"" \&\\*(Lq\&\\*(Rq
+. el .as f1 \&\\*(Lq\&\\*(Rq
+.\}
+.el \{\
+. ie "\\*(iM"" \{\
+. ds f1 \&\\*(Lq
+. ds iM Dq
+. \}
+. el .as f1 \&\\*(Lq
+. Sb \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ie \\n(Ef>0 .\\*(k1 \\*(k2 \\*(k3 \\*(k4 \\*(k5 \\*(k6 \\*(k7 \\*(k8
+. el .as f1 \\*(k0
+. as f1 \\*(Rq
+. if !"\\*(f4"" .as f1 \\*(f4
+. if "\\*(iM"Dq" \{\
+\&\\*(f1
+. ds f1
+. ds iM
+. \}
+. ds f4
+. rm k0 k1 k2 k3 k4 k5 k6 k7 k8 k9
+. nr Ef 0
+.\}
+..
+.\"
+.\" Parenthesis quoted Items
+.de Pq
+.nr pQ 0
+.ie \\n(.$==0 \{\
+. ie "\\*(iM"" \&(\&)
+. el .as f1 \&(\&)
+.\}
+.el \{\
+. ie "\\*(iM"" \{\
+. ds f1 \&(
+. ds iM Pq
+. \}
+. el .as f1 \&(
+. pB \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ie \\n(pQ>0 .\\*(y1 \\*(y2 \\*(y3 \\*(y4 \\*(y5 \\*(y6 \\*(y7 \\*(y8
+. el .as f1 \\*(y0
+. as f1 \&)
+. if !"\\*(f3"" .as f1 \\*(f3
+. if "\\*(iM"Pq" \{\
+\&\\*(f1
+. ds f1
+. ds iM
+. \}
+. ds f3
+. rm y0 y1 y2 y3 y4 y5 y6 y7 y8 y9
+. nr pQ 0
+.\}
+..
+.\" eF, sB g[0-9] and f2
+.de sB
+.hy 0
+.ie \\n(.$==0 .tm Sick Logic: macro sB
+.el \{\
+. ie \\n(eF>=1 .nr eF \\n(eF+1
+. el \{\
+. mN \\$1
+. if \\n(mN .nr eF \\n(eF+1
+. \}
+. rZ \\$1
+. ie \\n(rZ .as f2 \\$1
+. el \{\
+. ie \\n(eF<1 .as g\\n(eF \\$1
+. el .as g\\n(eF \\$1
+. \}
+. if \\n(.$>1 \{\
+. rZ \\$2
+. if \\n(rZ==0 \{\
+. if \\n(eF<1 \{\
+. as g\\n(eF \& \&
+. \}
+. \}
+. sB \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+..
+.de Sb
+.hy 0
+.ie \\n(.$==0 .tm Sick Logic: macro Sb
+.el \{\
+. ie \\n(Ef>=1 .nr Ef \\n(Ef+1
+. el \{\
+. mN \\$1
+. if \\n(mN .nr Ef \\n(Ef+1
+. \}
+. rZ \\$1
+. ie \\n(rZ .as f4 \\$1
+. el \{\
+. ie \\n(Ef<1 .as k\\n(Ef \\$1
+. el .as k\\n(Ef \\$1
+. \}
+. if \\n(.$>1 \{\
+. rZ \\$2
+. if \\n(rZ==0 \{\
+. if \\n(Ef<1 \{\
+. as k\\n(Ef \& \&
+. \}
+. \}
+. Sb \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+..
+.de pB
+.hy 0
+.ie \\n(.$==0 .tm Sick Logic: macro pB
+.el \{\
+. ie \\n(pQ>=1 .nr pQ \\n(pQ+1
+. el \{\
+. mN \\$1
+. if \\n(mN .nr pQ \\n(pQ+1
+. \}
+. rZ \\$1
+. ie \\n(rZ .as f3 \\$1
+. el \{\
+. ie \\n(pQ<1 .as y\\n(pQ \\$1
+. el .as y\\n(pQ \\$1
+. \}
+. if \\n(.$>1 \{\
+. rZ \\$2
+. if \\n(rZ==0 \{\
+. if \\n(pQ<1 \{\
+. as y\\n(pQ \& \&
+. \}
+. \}
+. pB \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+..
+.de aQ
+.hy 0
+.ie \\n(.$==0 .tm Bad Syntax: .Aq
+.el \{\
+. ie \\n(aQ>=1 .nr aQ \\n(aQ+1
+. el \{\
+. mN \\$1
+. if \\n(mN .nr aQ \\n(aQ+1
+. \}
+. rZ \\$1
+. ie \\n(rZ .as aZ \\$1
+. el \{\
+. ie \\n(aQ<1 .as a\\n(aQ \\$1
+. el .as a\\n(aQ \\$1
+. \}
+. if \\n(.$>1 \{\
+. rZ \\$2
+. if \\n(rZ==0 \{\
+. if \\n(aQ<1 \{\
+. as a\\n(aQ \& \&
+. \}
+. \}
+. aQ \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+..
+.\" Angle Bracket Quoted Items
+.de Aq
+.nr aQ 0
+.ie \\n(.$==0 \{\
+. ie "\\*(iM"" \&<\&>
+. el .as f1 \&<\&>
+.\}
+.el \{\
+. ie "\\*(iM"" \{\
+. ds f1 \&<
+. ds iM Aq
+. \}
+. el .as f1 \&<
+. aQ \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+. ie \\n(aQ>0 .\\*(a1 \\*(a2 \\*(a3 \\*(a4 \\*(a5 \\*(a6 \\*(a7 \\*(a8
+. el .as f1 \\*(a0
+. as f1 \&>
+. if !"\\*(aZ"" .as f1 \\*(aZ
+. if "\\*(iM"Aq" \{\
+\&\\*(f1
+. ds f1
+. ds iM
+. \}
+. ds aZ
+. rm a0 a1 a2 a3 a4 a5 a6 a7 a8
+. nr aQ 0
+.\}
+..
+.\" macro Name test, return macro register value if true
+.if \n(.g .ig
+.de mN
+.nr mN 0
+.sW \\$1
+.if \\n(sW==2 \{\
+. if \\n(\\$1 .nr mN \\n(\\$1
+.\}
+..
+.if !\n(.g .ig
+.de mN
+.nr mN 0
+.if \A'\\$1' \{\
+. sW \\$1
+. if \\n(sW==2 \{\
+. if \\n(\\$1 .nr mN \\n(\\$1
+. \}
+.\}
+..
+.\" Punctuation test (using z registers), return 1 if true
+.if \n(.g .ig
+.de rZ
+.nr rZ 0
+.sW \\$1
+.if \\n(sW==1 \{\
+. if \\n(z\\$1==1 \{\
+. nr rZ 1
+. \}
+.\}
+..
+.if !\n(.g .ig
+.de rZ
+.nr rZ 0
+.if \A'\\$1' \{\
+. sW \\$1
+. if \\n(sW==1 \{\
+. if \\n(z\\$1==1 \{\
+. nr rZ 1
+. \}
+. \}
+.\}
+..
+.\"
+.\" sW returns number of characters in a string
+.if t \{\
+.nr fW \w'\fC,'
+.de sW
+.nr sW \w'\fC\\$1'
+.\}
+.if n \{\
+.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
+..
+.\" Option Expression -
+.\" TODO - add line overflow check (right!)
+.nr eP 0
+.ds e1
+.nr oE 0
+.nr hP 0
+.ds hP
+.nr Ep 0
+.de Op
+.hy 0
+.if "\\*(iM"" \{\
+. ds iM Op
+. ds f1 \&
+.\}
+.as f1 \&\\*(lB
+.\" .tm Op: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.dO \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.ie !"\\$1"Cx" .oE
+.el .nr oE \\n(oE+1
+..
+.\"
+.\" just for mike, with every bite of garlic in mind (oops, i mean burp).
+.\" dO: go dOwn an argument vector and test each argument to see if
+.\" a macro name or punctuation. stash in respective place along
+.\" with its arguments.
+.nr oO 0
+.nr oP 0
+.nr aO 0
+.de dO
+.mN \\$1
+.ie \\n(mN \{\
+. if \\n(oP \{\
+. if \\n(hP \{\
+. nr oZ 1
+. oZ
+. Oz
+. \}
+. if \\n(e1==1 \{\
+.\\*(e1 \\*(e2 \\*(e3 \\*(e4 \\*(e5 \\*(e6 \\*(e7 \\*(e8 \\*(e9
+. \}
+. uO
+. if !(\\n(oO:\\n(aO) .as f1 \& \&
+. \}
+. ie "\\$1"Op" \{\
+. as f1 \&\\*(lB
+. nr aO \\n(aO+1
+. \}
+. el \{\
+. nr eP \\n(eP+1
+. ds e\\n(eP \\$1
+. nr e\\n(eP 1
+. \}
+.\}
+.el \{\
+.\" .tm dO: $1: \\$1: eP \\n(eP e[\\n(eP]: \\*(e\\n(ePEE
+. rZ \\$1
+. ie \\n(rZ \{\
+.\" .tm dO:rZ: $1: \\$1: eP \\n(eP e[\\n(eP]: \\*(e\\n(eP
+. nr hP \\n(hP+1
+. ds h\\n(hP \\$1
+. \}
+. el \{\
+.\" .tm dO:word $1: \\$1: eP \\n(eP e[\\n(eP]: \\*(e\\n(ePEE
+. if \\n(eP==0:\\n(e\\n(eP==1 .nr eP \\n(eP+1
+. if \\n(eZ .as e\\n(eP \& \&
+. as e\\n(eP " \&\\$1
+.\" . ds e\\n(eP \&\\$1
+. nr eZ \\n(eZ+1
+. \}
+.\}
+.nr oP 1
+.ie \\n(.$>1 \{\
+. dO \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.\}
+.el \{\
+. ie \\n(e1 \{\
+.\\*(e1 \\*(e2 \\*(e3 \\*(e4 \\*(e5 \\*(e6 \\*(e7 \\*(e8 \\*(e9
+. \}
+. el \{\
+. as f1 \\*(e1
+. \}
+.\}
+..
+.\" handle old style arguments such as the arg -Idir
+.\" in adb, .Oo is a toggle.
+.de Oo
+.ie \\n(oO .nr oO 0
+.el .nr oO 1
+..
+.\" stash punctuation
+.de oZ
+.if \\n(hP>=\\n(oZ \{\
+. nr eP \\n(eP+1
+. ds e\\n(eP \\*(h\\n(oZ
+. nr oZ \\n(oZ+1
+. oZ
+.\}
+..
+.\" clean up punctuation vector
+.de Oz
+.if \\n(hP>0 \{\
+. rm h\\n(hP
+. nr hP \\n(hP-1
+. Oz
+.\}
+..
+.\" uO: go back up created vector cleaning it up along the way
+.de uO
+.if \\n(eP>0 \{\
+. rm e\\n(eP
+. rr e\\n(eP
+. nr eP \\n(eP-1
+. nr oP 0
+. nr eZ 0
+. uO
+.\}
+..
+.\" option end
+.de oE
+.uO
+.ie \\n(hP \{\
+. as f1 \\*(rB\\*(h1\\*(h2\\*(h3
+. Oz
+. nr oZ 0
+.\}
+.el \{\
+. as f1 \\*(rB
+.\}
+.ie "\\*(iM"Op" \{\
+. if \\n(aO .aO
+.if t \{\
+. if (\\n(.lu-\\n(.ku-\\n(.ou-(2*\\n(fWu))<\w'\fC\\*(f1'u .br
+.\}
+.if n \{\
+. nr aa \w'\\*(f1'u
+.\" . nr qq \\n(.lu-\\n(.ku-\\n(.ou
+.\" \&aa == \\n(aa, f1==\\*(f1, qq==\\n(qq
+. if (\\n(.lu-\\n(.ku-\\n(.ou-\\n(aau)<=(8*\\n(fWu) .br
+.\}
+\&\\*(f1
+. ds iM
+. ds f1
+. hy
+.\}
+.el .nr oE \\n(oE-1
+..
+.de aO
+.as f1 \\*(rB
+.nr aO \\n(aO-1
+.if \\n(aO >0 .aO
+..
+.\"
+.de Xr
+.if \\n(.$<=1 \{\
+. ie \\n(.$==1 \{\
+. if !"\\*(iM"" .as f1 \&\\*(xR\\$1\fP
+. if "\\*(iM"" \&\\*(xR\\$1\fP
+. \}
+. el .tm Xr Usage: .Xr manpage_name [section#] \\*(Pu
+.\}
+.if \\n(.$==2 \{\
+. rZ \\$2
+. ie "\\*(iM"" \{\
+. ie \\n(rZ \&\\*(xR\\$1\fP\\$2
+. el \&\\*(xR\\$1\fP(\\$2)
+. \}
+. el \{\
+. ie \\n(rZ .as f1 \&\\*(xR\\$1\fP\\$2
+. el .as f1 \&\\*(xR\\$1\fP(\\$2)
+. \}
+.\}
+.if \\n(.$>=3 \{\
+. rZ \\$2
+. ie \\n(rZ \{\
+. ie !"\\*(iM"" .as f1 \&\\*(xR\\$1\fP\\$2\\$3\\$4\\$5\\$6\\$7\\$8
+. el \&\\*(xR\\$1\fP\\$2\\$3\\$4\\$5\\$6\\$7\\$8
+. \}
+. el \{\
+. rZ \\$3
+. ie \\n(rZ \{\
+. if !"\\*(iM"" \{\
+. as f1 \&\\*(xR\\$1\fP(\\$2)\\$3\\$4\\$5\\$6\\$7\\$8
+. \}
+. if "\\*(iM"" \{\
+\&\\*(xR\\$1\fP(\\$2)\\$3\\$4\\$5\\$6\\$7\\$8
+. \}
+. \}
+. el \{\
+. tm rZ = \\n(rZ the arg is \\$3
+. tm Xr-XX Usage: .Xr manpage_name [section#] \\*(Pu
+. \}
+. \}
+.\}
+..
+.\"
+.\"
+.de Ex
+.tm Ex defunct, Use .Dl: \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.\" Display (one) Line of text.
+.de Dl
+.ie "\\*(iM"" \{\
+' 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
+. mN \\$1
+. ie \\n(mN .\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. el \{\
+. nr cF \\n(.f
+.\" Literal font is none specified
+\&\\*(lI\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. ft \\n(cF
+. \}
+. in \\n(.iu-\\n(Dsu
+.\}
+.el \{\
+. mN \\$1
+. ie \\n(mN .\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+. el \{\
+. nr cF \\n(.f
+. ds f1 \&\\*(lI\\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+. as f1 \&\f\\n(cF
+. \}
+.\}
+..
+.\"
+.\"
+.\" user set Tagged Paragraph Width (used in both Dp and Tp)
+.de Tw
+.ie \\n(.$==0 \{\
+. nr aa 0
+.\}
+.el \{\
+. mN \\$1
+. ie \\n(sW>2 \{\
+. nr tW (\\n(sW+3)*\\n(fWu)
+. \}
+. el \{\
+. ie \\n(mN .nr tW \\n(mN
+. el .nr tW \\$1
+. \}
+. nr tF 1
+.\}
+..
+.\"
+.de Dw
+.Tw \\$1
+..
+.\"
+.de Di
+.ie \\n(.$==0 \{\
+. nr tI \\n(Dsu
+.\}
+.el \{\
+. sW \\$1
+. if \\n(sW>=2 \{\
+. nr tI \\$1u
+. \}
+. if \\n(sW<2 \{\
+. if "\\$1"L" \{\
+. nr tI 0
+. \}
+. \}
+.\}
+..
+.\" tagged paragraph
+.\" initialize baby stack variables
+.nr np 0
+.nr p1 0
+.ds s\n(np
+.\"
+.de Tp
+.ie "\\$1"" .pE p s np
+.el \{\
+. ds iM Tp
+. mN \\$1
+. ie \\n(tF \{\
+. ds tC Tw
+. nr tC 1
+. nr tF 0
+. \}
+. el \{\
+. if !"Tw"\\*(s\\n(np" \{\
+. ie \\n(mN \{\
+. ds tC \\$1
+. nr tW \\n(mN
+. \}
+. el \{\
+. ds tC Tx
+. nr tW \\n(Tx
+. \}
+. if !"\\*(tC"\\*(s\\n(np" .nr tC 1
+. \}
+. \}
+. sp \\n(vVu
+. if !\\n(cR .ne 2
+. if \\n(tC \{\
+. nr np \\n(np+1
+. nr p\\n(np \\n(tW
+. ds s\\n(np \\*(tC
+. nr tC 0
+. ds tC
+. in \\n(.iu+\\n(p\\n(npu
+. \}
+. ie \\n(mN \{\
+. ds f1
+. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. if !"\\$1"Cx" .pT st p np
+. \}
+. el \{\
+. br
+. ev 1
+. fi
+. di Td
+\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. br
+. di
+. ev
+. na
+. ds tD \\*(Td\\
+. pT di p np
+. \}
+.\}
+..
+.\"
+.\"
+.\" Complex Expression Macro
+.\"
+.\" TODO: add length across line boundary check (like Li)
+.de Cx
+.hy 0
+.ie \\n(.$==0 \{\
+. if "\\*(iM"Cx" \{\
+. ds iM
+. if \\n(oE .oE
+\&\\*(f1
+. ds f1
+. \}
+. if "\\*(iM"Tp" .pT st p np
+. if "\\*(iM"Dp" .pT st q mp
+.\}
+.el \{\
+. if "\\*(iM"" \{\
+. ds iM Cx
+. ds f1 \&
+. \}
+. mN \\$1
+.\" Here are the args: `\\$1' `\\$2' `\\$3' `\\$4'
+. ie \\n(mN .\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. el \{\
+. as f1 \&\\$1
+. if \\n(.$>1 .Cx \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+..
+.\" Prefix string in default font to content specified string
+.de Pf
+.Cx \\$1
+.\\$2 \\$3 \\$4 \\$5
+.Cx
+..
+.\" Suffix string in default font to content specified string
+.de Sf
+.Cx \\$1 \\$2
+.Cx \\$3
+.Cx
+..
+.\" Simple Option Begin
+.de Ob
+.hy 0
+.ie "\\*(iM"" \{\
+. ev 2
+. fi
+. di oB
+.\}
+.el \{\
+.tm shouldn't be here
+. as f1 \&[
+. mN \\$1
+. ie \\n(mN .\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. el \{\
+. as f1 \&\\$1
+. if \\n(.$>1 .Oc \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+.\}
+..
+.de Oc
+.as f1 \&\\$1
+.if \\n(.$>1 .Oc \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Oe
+.hy 0
+.ie "\\*(iM"" \{\
+. br
+. di
+. ev
+. ds bO \\*(oB\\
+\&[\\*(bO\&]
+.\}
+.el \{\
+. as f1 \&]
+.\}
+..
+.\" White space for Cx
+.de Ws
+.Cx \&\ \&
+..
+.\" tagged paragraph
+.\" initialize baby stack variables
+.nr mp 0
+.nr q1 0
+.ds r\n(np
+.\"
+.\" Complex Dp tag
+.de Dc
+.Dp Cx \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+..
+.\" Complex Tp tag
+.de Tc
+.Tp Cx \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+..
+.\" Tag with a flag and an argument with a space
+.de Ta
+.if "\\$2"" \{\
+. Tp Fl \\$1
+.\}
+.el \{\
+. Tp Fl \\$1
+. Cx \&\ \&
+. Ar \\$2 \\$3
+. Cx
+.\}
+..
+.de Da
+.Dp Cx Fl \\$1
+.Ws
+.Ar \\$2 \\$3
+.Cx
+..
+.de To
+.Tp Cx Fl \\$1
+.Ar \\$2 \\$3
+.Cx
+..
+.de Do
+.Dp Cx Fl \\$1
+.Ar \\$2 \\$3
+.Cx
+..
+.\" Blended tag toggle
+.de Bt
+.ie \\n(tP==0 .nr tP 1
+.el .nr tP 0
+..
+.\" Bullet paragraph
+.de Bu
+.Tp Sy \&\(bu
+..
+.\" Display tagged paragraph
+.de Dp
+.ie "\\$1"" \{\
+. pE q r mp
+. sp \\n(vVu
+.\}
+.el \{\
+. ds iM Dp
+. mN \\$1
+. ie \\n(tF \{\
+. ds tC Tw
+. nr tC 1
+. nr tF 0
+. \}
+. el \{\
+. if !"Tw"\\*(r\\n(mp" \{\
+. ie \\n(mN \{\
+. ds tC \\$1
+. nr tW \\n(mN
+. \}
+. el \{\
+. ds tC Tx
+. nr tW \\n(Tx
+. \}
+. if !"\\*(tC"\\*(r\\n(mp" .nr tC 1
+. \}
+. \}
+. if !\\n(cR .ne 2
+. if \\n(tC \{\
+. nr mp \\n(mp+1
+. nr q\\n(mp \\n(tW
+. ds r\\n(mp \\*(tC
+. nr tC 0
+. ds tC
+. ie \\n(tIu==\\n(Dsu .nr i\\n(mp \\n(Dsu
+. el \{\
+. nr i\\n(mp \\n(tIu
+. nr tI \\n(Dsu
+. \}
+. in \\n(.iu+\\n(i\\n(mpu
+. sp \\n(vVu
+. in \\n(.iu+\\n(\\q\\n(mpu
+. \}
+. ie \\n(mN \{\
+. \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. if !"\\$1"Cx" .pT st q mp
+. \}
+. el \{\
+. br
+. ev 1
+. fi
+. di Td
+\&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. br
+. di
+. ev
+. na
+. ds tD \\*(Td\\
+. pT di q mp
+. \}
+.\}
+..
+.\"
+.\" .pE number_stack string_stack counter
+.de pE
+.ie "\\$3"mp" \{\
+. in \\n(.iu-(\\n(\\$1\\n(\\$3u)-(\\n(i\\n(mpu)
+. rr i\\n(mp
+.\}
+.el .in \\n(.iu-\\n(\\$1\\n(\\$3u
+.\" .in \\n(.iu-\\n(\\$1\\n(\\$3u
+.if \\n(\\$3<=0 .tm Extraneous call .Tp or .Dp
+.rr \\$1\\n(\\$3
+.rm \\$2\\n(\\$3
+.nr \\$3 \\n(\\$3-1
+.ds iM
+..
+.\"
+.\" .pT [st or di] number_stack counter
+.de pT
+.ie "\\$1"st" \{\
+. nr bb \\n(\\$2\\n(\\$3u
+. ti -\\n(bbu
+. ie (\\n(\\$2\\n(\\$3u-2n)<=\w'\\*(f1'u \{\&\\*(f1\\*(tP
+. if \\n(tP==0 .br
+. \}
+. el \\*(f1\h'|\\n(\\$2\\n(\\$3u'\c
+.\}
+.el \{\
+. ti -\\n(\\$2\\n(\\$3u
+. ie (\\n(\\$2\\n(\\$3u-2n)<=\\n(dlu \{\&\\*(tD\\*(tP
+. if !\\n(tP .br
+. \}
+. el \\*(tD\h'|\\n(\\$2\\n(\\$3u'\c
+. if t 'ad
+.\}
+. ds iM
+. ds f1
+'fi
+..
+.\"
+.\" The new SH
+.\"
+.de Sh
+.\" set Sh state off, check for list state before calling indent (.In)
+.nr nS 0
+.nr sE 0
+.ie "\\$1"NAME" \{\
+.\" name state on, housekeep (headers & footers)
+. hK
+' in 0
+.\}
+.el \{\
+. if "\\$1"SYNOPSIS" .nr nS 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
+\&\fB\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\&
+.in \\n(.iu+\\n(Tiu
+.if "\\$1"SEE" .nr sE 1
+.ns
+..
+.\"
+.\" Nd minus sign for an en dash used in .Sh Name
+.de Nd
+\&\-\& \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.de Ss
+.sp
+.ti -.25i
+\&\fB\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6 \|\\$7 \|\\$8 \|\\$9
+\&\fP\&
+.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
+..
+.\" .if "\\$1"Ss" .in \\n(.iu+\\n(sIu
+.\"..
+.\"
+.\"
+.\" Column Macro
+.\"
+.hy 0
+.de Cw
+.ie \\n(.$==0 \{\
+. br
+. in \\n(.iu-\\n(eWu
+. ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+.\}
+.el \{\
+. Pp
+. if \\n(.$==1 \{\
+. ta \w'\\$1 'u
+. nr eW \w'\\$1 'u
+' in \\n(.iu+\\n(eWu
+. \}
+. if \\n(.$==2 \{\
+. ta \w'\\$1 'u +\w'\\$2 'u
+. nr eW \w'\\$1 'u+\w'\\$2 'u
+' in \\n(.iu+\\n(eWu
+. \}
+. if \\n(.$==3 \{\
+. ta \w'\\$1 'u +\w'\\$2 'u +\w'\\$3 'u
+. nr eW \w'\\$1 'u+\w'\\$2 'u+\w'\\$3 'u
+' in \\n(.iu+\\n(eWu
+. \}
+. if \\n(.$==4 \{\
+. ta \w'\\$1 'u +\w'\\$2 'u +\w'\\$3 'u +\w'\\$4 'u
+. nr eW \w'\\$1 'u+\w'\\$2 'u+\w'\\$3 'u +\w'\\$4 'u
+' in \\n(.iu+\\n(eWu
+. \}
+. if \\n(.$==5 \{\
+.ta \w'\\$1 'u +\w'\\$2 'u +\w'\\$3 'u +\w'\\$4 'u +\w'\\$5 'u
+.nr eW \w'\\$1 'u +\w'\\$2 'u +\w'\\$3 'u +\w'\\$4 'u +\w'\\$5 'u
+' in \\n(.iu+\\n(eWu
+. \}
+.\}
+..
+.de Cl
+.ti -\\n(eWu
+.mN \\$1
+.ie \\n(mN .\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.el \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+..
+.nr dQ 0
+.de Ds
+.ie !"\\$1"" \{\
+. mN d\\$1
+. if \\n(mN \{\
+. nr dQ \\n(dQ+1
+. d\\$1
+. \}
+.\}
+.el .br
+.nf
+..
+.de Df
+.ie !"\\$1"" \{\
+. mN d\\$1
+. if \\n(mN \{\
+. nr dQ \\n(dQ+1
+. d\\$1
+. \}
+.\}
+.el .br
+..
+.de Dn
+\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+.nf
+..
+.de dI
+.nr d\\n(dQ \\n(dIu
+.in \\n(.iu+\\n(dIu
+..
+.de dC
+.nr d\\n(dQ (\\n(.l-\\n(.i)/4u
+.in \\n(.iu+\\n(d\\n(dQu
+..
+.de dR
+.nr d\\n(dQ (\\n(.l/3)u
+.in \\n(.iu+\\n(d\\n(dQu
+..
+.de dL
+.nr aa 0
+..
+.de De
+.br
+.if \\n(d\\n(dQ \{\
+. in \\n(.iu-\\n(d\\n(dQu
+. rr d\\n(dQ
+. nr dQ \\n(dQ-1
+.\}
+.fi
+..
+.\"
+.de Fn
+.ie \\n(.$==0 \{\
+. tm Usage: .Fn function_name function_arg(s) ... \\*(Pu
+.\}
+.el \{\
+. nr cF \\n(.f
+. ie \\n(.$==1 .ds f1 \&\\*(nM\\$1\fP\\*(lP\fP\\*(rP\fP
+. el \{\
+. ds f1 \\*(nM\\$1\fP\\*(lP
+. nr aa 0
+. rC \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
+. \}
+. if "\\*(iM"" \{\\&\\*(f1
+. ds f1
+. \}
+.\}
+..
+.\"
+.de rC
+.rZ \\$1
+.ie \\n(rZ \{\
+. as f1 \f\\n(cF\\*(rP\f\\n(cF\\$1\\$2\\$3\\$4\\$5\\$6\\$7
+.\}
+.el \{\
+. ie \\n(aa .as f1 \fP, \\*(aR\\$1
+. el .as f1 \\*(aR\\$1
+. nr aa 1
+. ie \\n(.$>1 .rC \\$2 \\$3 \\$4 \\$5 \\$6 \\$7
+. el .as f1 \fP\\*(rP\fP
+.\}
+..
diff --git a/contrib/groff/tmac/doc.tmac b/contrib/groff/tmac/doc.tmac
new file mode 100644
index 0000000..815e3d4
--- /dev/null
+++ b/contrib/groff/tmac/doc.tmac
@@ -0,0 +1,6189 @@
+.\" 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.
+.\"
+.\" @(#)doc 8.1 (Berkeley) 06/08/93
+.\"
+.\" 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.
+.\"
+.\" Modified by
+.\"
+.\" Werner LEMBERG <wl@gnu.org> and
+.\" Ruslan Ermilov <ru@freebsd.org>
+.\"
+.\" to make it more readable: using long names and many groff features,
+.\" updating and extending documentation, etc.
+.\"
+.\" %beginstrip%
+.
+.
+.if !\n(.g \
+. ab This version of mdoc can be run with GNU troff only!
+.
+.
+.cp 0
+.
+.
+.if ((\n[.x] == 0) : ((\n[.x] == 1) & (\n[.y] < 17))) \
+. ab You need GNU troff version 1.17 or higher to run this version of mdoc!
+.
+.
+.\" Load start-up files
+.ie t \
+. mso mdoc/doc-ditroff
+.el \
+. mso mdoc/doc-nroff
+.
+.mso mdoc/doc-common
+.mso mdoc/doc-syms
+.
+.
+.eo
+.
+.
+.\" NS doc-macro-name global string
+.\" NS name of calling request (set in each user-requestable macro)
+.
+.ds doc-macro-name
+.als doc-arg0 doc-macro-name
+.
+.
+.\" NS doc-arg-limit global register
+.\" NS total number of arguments
+.
+.nr doc-arg-limit 0
+.
+.
+.\" NS doc-num-args global register
+.\" NS number of arguments to handle (must be set to \n[.$] prior to
+.\" NS `doc-parse-arg-vector' request)
+.
+.nr doc-num-args 0
+.
+.
+.\" NS doc-arg-ptr global register
+.\" NS argument pointer
+.
+.nr doc-arg-ptr 0
+.
+.
+.\" NS doc-argXXX global string
+.\" NS argument vector
+.\" NS
+.\" NS limit:
+.\" NS doc-arg-limit
+.
+.ds doc-arg1
+.
+.
+.\" NS doc-typeXXX global register
+.\" NS argument type vector (macro=1, string=2, punctuation suffix=3,
+.\" NS punctuation prefix=4)
+.\" NS
+.\" NS limit:
+.\" NS doc-arg-limit
+.
+.nr doc-type1 0
+.
+.
+.\" NS doc-spaceXXX global string
+.\" NS space vector
+.\" NS
+.\" NS limit:
+.\" NS doc-arg-limit
+.
+.ds doc-space1
+.
+.
+.\" NS doc-parse-args macro
+.\" NS parse arguments (recursively) (`.doc-parse-args arg ...')
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-limit
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-spaceXXX
+.\" NS doc-typeXXX
+.\" NS doc-arg-ptr
+.\" NS doc-have-space
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dpa
+.\" NS doc-reg-dpa1
+.\" NS doc-str-dpa
+.
+.de doc-parse-args
+. if !\n[doc-arg-limit] \
+. doc-set-spacing-1
+.
+. nr doc-have-space 0
+.
+. if !\n[.$] \
+. return
+.
+. nr doc-arg-limit +1
+.
+. \" handle `|' and `...' specially
+. ie "\$1"|" \
+. ds doc-arg\n[doc-arg-limit] \f[R]|\f[P]
+. el \{ .ie "\$1"..." \
+. ds doc-arg\n[doc-arg-limit] \|.\|.\|.
+. el \
+. ds doc-arg\n[doc-arg-limit] "\$1
+. \}
+.
+. \" get argument type and set spacing
+. doc-get-arg-type* \n[doc-arg-limit]
+. nr doc-type\n[doc-arg-limit] \n[doc-arg-type]
+. doc-set-spacing-\n[doc-arg-type]
+.
+. \" check whether we have processed the last parameter
+. ie (\n[.$] == 1) \
+. nr doc-arg-ptr 0
+. el \{\
+. shift
+. doc-parse-args \$@
+. \}
+.
+. nh
+..
+.
+.
+.\" NS doc-parse-arg-vector macro
+.\" NS parse argument vector (recursive)
+.\" NS
+.\" NS cf. comments in doc-parse-args
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-limit
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-num-args
+.\" NS doc-spaceXXX
+.\" NS doc-typeXXX
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dpav
+.\" NS doc-reg-dpav1
+.\" NS doc-str-dpav
+.
+.de doc-parse-arg-vector
+. if !\n[doc-arg-limit] \
+. doc-set-spacing-1
+.
+. nr doc-arg-limit +1
+.
+. ie "\*[doc-arg\n[doc-arg-limit]]"|" \
+. ds doc-arg\n[doc-arg-limit] \f[R]|\f[P]
+. el \{ .if "\*[doc-arg\n[doc-arg-limit]]"..." \
+. ds doc-arg\n[doc-arg-limit] \|.\|.\|.
+. \}
+.
+. doc-get-arg-type* \n[doc-arg-limit]
+. nr doc-type\n[doc-arg-limit] \n[doc-arg-type]
+. doc-set-spacing-\n[doc-arg-type]
+.
+. ie (\n[doc-num-args] == 1) \{\
+. nr doc-arg-ptr 0
+. nr doc-num-args 0
+. \}
+. el \{\
+. nr doc-num-args -1
+. doc-parse-arg-vector
+. \}
+.
+. nh
+..
+.
+.
+.\" NS doc-parse-space-vector macro
+.\" NS parse space vector (recursive)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-limit
+.\" NS doc-num-args
+.\" NS doc-spaceXXX
+.
+.de doc-parse-space-vector
+. nr doc-arg-limit +1
+.
+. doc-set-spacing-\n[doc-type\n[doc-arg-limit]]
+.
+. ie (\n[doc-num-args] == 1) \
+. nr doc-num-args 0
+. el \{\
+. nr doc-num-args -1
+. doc-parse-space-vector
+. \}
+..
+.
+.
+.\" NS doc-remaining-args macro
+.\" NS output remaining arguments as-is, separated by spaces (until
+.\" NS `doc-num-args' is exhausted)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-num-args
+.
+.de doc-remaining-args
+. nr doc-arg-ptr +1
+. nop \)\*[doc-arg\n[doc-arg-ptr]]\c
+.
+. ie (\n[doc-num-args] == 1) \{\
+. nr doc-arg-ptr 0
+. nr doc-num-args 0
+. \}
+. el \{\
+. nop \)\*[doc-space]\c
+. nr doc-num-args -1
+. doc-remaining-args
+. \}
+..
+.
+.
+.\" NS doc-append-arg macro
+.\" NS append one argument to argument vector:
+.\" NS `.doc-append-arg [arg] [type]'
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-limit
+.\" NS doc-argXXX
+.\" NS doc-typeXXX
+.
+.de doc-append-arg
+. nr doc-arg-limit +1
+. ds doc-arg\n[doc-arg-limit] "\$1
+. nr doc-type\n[doc-arg-limit] \$2
+. doc-set-spacing-\$2
+..
+.
+.
+.\" NS doc-print-and-reset macro
+.\" NS finish input line and clean up argument vectors
+.
+.de doc-print-and-reset
+. if \n[doc-space-mode] \
+. nop \)
+. doc-reset-args
+..
+.
+.
+.\" NS doc-reset-args macro
+.\" NS reset argument counters
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-limit
+.\" NS doc-arg-ptr
+.\" NS doc-have-slot
+.
+.de doc-reset-args
+. nr doc-arg-limit 0
+. nr doc-arg-ptr 0
+. nr doc-have-slot 0
+.
+. hy \n[doc-hyphen-flags]
+..
+.
+.
+.ec
+.
+.\" NS doc-curr-font global register
+.\" NS saved current font
+.
+.nr doc-curr-font \n[.f]
+.
+.
+.\" NS doc-curr-size global register
+.\" NS saved current font size
+.
+.nr doc-curr-size \n[.ps]
+.
+.eo
+.
+.
+.\" NS Fl user macro
+.\" NS handle flags (appends `-' and prints flags): `.Fl [arg ...]'
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-Fl (for communication with doc-flag-recursion)
+.\" NS
+.\" NS width register `Fl' set in doc-common
+.
+.de Fl
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Fl-font]\c
+.
+. if !\n[doc-arg-limit] \{\
+. ds doc-macro-name Fl
+. doc-parse-args \$@
+.
+. if !\n[.$] \{\
+. \" no arguments
+. nop \|\-\|\f[P]\s[0]
+. \}\}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. \" last argument
+. nop \|\-\f[P]\s[0]\c
+. doc-print-and-reset
+. \}
+. el \{\
+. ie (\n[doc-type\n[doc-arg-ptr]] == 1) \{\
+. nop \|\-\f[P]\s[0]\c
+. \*[doc-arg\n[doc-arg-ptr]]
+. \}
+. el \{\
+. if (\n[doc-type\n[doc-arg-ptr]] == 3) \
+. nop \|\-\|\c
+.
+. nr doc-reg-Fl 1
+. doc-flag-recursion
+. \}\}
+..
+.
+.
+.\" NS doc-flag-recursion macro
+.\" NS `Fl' flag recursion routine (special handling)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dfr
+.\" NS doc-reg-dfr1
+.\" NS doc-str-dfr
+.
+.de doc-flag-recursion
+. nr doc-reg-dfr1 \n[doc-type\n[doc-arg-ptr]]
+. ds doc-str-dfr "\*[doc-arg\n[doc-arg-ptr]]
+.
+. ie (\n[doc-reg-dfr1] == 1) \{\
+. nop \f[P]\s[0]\c
+. \*[doc-str-dfr]
+. \}
+. el \{\
+. nr doc-reg-dfr \n[doc-arg-ptr]
+.
+. ie (\n[doc-reg-dfr1] == 2) \{\
+. \" handle vertical bar -- doc-reg-Fl is set for the first call of
+. \" doc-flag-recursion only; we need this to make `.Fl | ...' work
+. \" correctly
+. ie "\*[doc-str-dfr]"\*[Ba]" \{\
+. if \n[doc-reg-Fl] \
+. nop \|\-\*[doc-space]\c
+. nop \)\*[Ba]\c
+. \}
+. el \{\
+. ie "\*[doc-str-dfr]"\f[R]|\f[P]" \{\
+. if \n[doc-reg-Fl] \
+. nop \|\-\*[doc-space]\c
+. nop \f[R]|\f[P]\c
+. \}
+. el \{\
+. \" two consecutive hyphen characters?
+. ie "\*[doc-str-dfr]"-" \
+. nop \|\-\^\-\|\c
+. el \
+. nop \|\%\-\*[doc-str-dfr]\c
+. \}\}\}
+. el \{\
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\c
+. nop \)\*[doc-str-dfr]\f[P]\s[0]\c
+. \}
+.
+. ie (\n[doc-arg-limit] == \n[doc-arg-ptr]) \{\
+. \" last argument
+. if (\n[doc-reg-dfr1] == 4) \
+. nop \|\-\c
+. nop \f[P]\s[0]\c
+. doc-print-and-reset
+. \}
+. el \{\
+. nr doc-arg-ptr +1
+. ie (\n[doc-type\n[doc-arg-ptr]] == 3) \{\
+. ie (\n[doc-type\n[doc-reg-dfr]] == 4) \
+. nop \|\-\c
+. el \
+. nop \)\*[doc-space\n[doc-reg-dfr]]\c
+. \}
+. el \
+. nop \)\*[doc-space\n[doc-reg-dfr]]\c
+.
+. shift
+. nr doc-reg-Fl 0
+. doc-flag-recursion \$@
+. \}\}
+..
+.
+.
+.\" NS doc-print-recursive macro
+.\" NS general name recursion routine (print remaining arguments)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dpr
+.\" NS doc-reg-dpr1
+.\" NS doc-str-dpr
+.
+.de doc-print-recursive
+. nr doc-reg-dpr1 \n[doc-type\n[doc-arg-ptr]]
+. ds doc-str-dpr "\*[doc-arg\n[doc-arg-ptr]]
+.
+. ie (\n[doc-reg-dpr1] == 1) \{\
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\c
+. \*[doc-str-dpr]
+. \}
+. el \{\
+. nr doc-reg-dpr \n[doc-arg-ptr]
+.
+. ie (\n[doc-reg-dpr1] == 2) \
+. \" the `\%' prevents hyphenation on a dash (`-')
+. nop \%\*[doc-str-dpr]\&\c
+. el \{\
+. \" punctuation character
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\c
+. nop \)\*[doc-str-dpr]\f[P]\s[0]\c
+. \}
+.
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. \" last argument
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\c
+. doc-print-and-reset
+. \}
+. el \{\
+. nop \)\*[doc-space\n[doc-reg-dpr]]\c
+. doc-print-recursive
+. \}\}
+..
+.
+.
+.\" NS doc-print-prefixes macro
+.\" NS print leading prefixes
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.
+.de doc-print-prefixes
+. while (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. if !(\n[doc-type\n[doc-arg-ptr]] == 4) \
+. break
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\c
+. nop \)\*[doc-arg\n[doc-arg-ptr]]\f[P]\s[0]\c
+. nr doc-arg-ptr +1
+. \}
+..
+.
+.
+.\" NS doc-generic-macro macro
+.\" NS this is the skeleton for most simple macros
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.
+.de doc-generic-macro
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name \$0
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .\$0 \*[doc-\$0-usage] ... (#\n[.c])
+. \}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. if (\n[doc-type\n[doc-arg-ptr]] == 1) \{\
+. tm Usage: .\$0 \*[doc-\$0-usage] ... (#\n[.c])
+.
+. \" the right action here would be to reset the argument counters
+. \" and bail out -- unfortunately, a small number of manual pages
+. \" (less than 2% for FreeBSD which has been used for testing)
+. \" relied on the old behaviour (silently ignore this error),
+. \" so it is commented out
+.
+.\" doc-reset-args
+. \}
+.\" el \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-\$0-font]\c
+. doc-print-recursive
+.\" \}
+. \}
+. el \{\
+. tm Usage: .\$0 \*[doc-\$0-usage] ... (#\n[.c])
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS Ar user macro
+.\" NS command line `argument' macro: `.Ar [args ...]'
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS
+.\" NS local variable:
+.\" NS doc-str-Ar-default
+.\" NS
+.\" NS width register `Ar' set in doc-common
+.
+.ds doc-str-Ar-default "file\ .\|.\|.
+.
+.de Ar
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Ar-font]\c
+.
+. if !\n[doc-arg-limit] \{\
+. ds doc-macro-name Ar
+. doc-parse-args \$@
+.
+. if !\n[.$] \{\
+. \" no argument
+. nop \)\*[doc-str-Ar-default]\&\f[P]\s[0]
+. \}\}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. ie (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. nop \)\*[doc-str-Ar-default]\&\f[P]\s[0]\c
+. doc-print-and-reset
+. \}
+. el \{\
+. if !(\n[doc-type\n[doc-arg-ptr]] == 2) \{\
+. \" replace previous argument (Ar) with default value
+. nr doc-arg-ptr -1
+. ds doc-arg\n[doc-arg-ptr] "\*[doc-str-Ar-default]
+. nr doc-type\n[doc-arg-ptr] 2
+. ds doc-space\n[doc-arg-ptr] "\*[doc-space]
+.
+. \" recompute space vector for remaining arguments
+. nr doc-num-args (\n[doc-arg-limit] - \n[doc-arg-ptr])
+. nr doc-arg-limit \n[doc-arg-ptr]
+. doc-parse-space-vector
+. \}
+. doc-print-recursive
+. \}
+..
+.
+.
+.\" NS Ad user macro
+.\" NS Addresses
+.\" NS
+.\" NS width register `Ad' set in doc-common
+.
+.als Ad doc-generic-macro
+.ds doc-Ad-usage address
+.
+.
+.\" NS doc-indent-synopsis global register
+.\" NS indentation in synopsis
+.
+.nr doc-indent-synopsis 0
+.
+.
+.\" NS doc-indent-synopsis-active global register (bool)
+.\" NS indentation in synopsis active
+.
+.nr doc-indent-synopsis-active 0
+.
+.
+.\" NS Cd user macro
+.\" NS config declaration (for section 4 SYNOPSIS)
+.\" NS
+.\" NS this function causes a break; it uses the `Nm' font
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-indent-synopsis
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Cd' set in doc-common
+.
+.de Cd
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Cd
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Cd configuration_file_declaration ... (#\n[.c])
+. \}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. ie \n[doc-in-synopsis-section] \{\
+. if "\*[doc-macro-name]"Cd" \{\
+. br
+. if !\n[doc-indent-synopsis] \
+. nr doc-indent-synopsis \n[doc-display-indent]u
+. if !\n[doc-indent-synopsis-active] \
+. in +\n[doc-indent-synopsis]u
+. ti -\n[doc-indent-synopsis]u
+. nop \*[doc-Nm-font]\c
+. doc-print-recursive
+. if !\n[doc-indent-synopsis-active] \
+. in -\n[doc-indent-synopsis]u
+. \}\}
+. el \{\
+. nop \*[doc-Nm-font]\c
+. doc-print-recursive
+. \}\}
+. el \{\
+. tm Usage: .Cd configuration_file_declaration ... (#\n[.c])
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS Cm user macro
+.\" NS interactive command modifier (flag)
+.\" NS
+.\" NS width register `Cm' set in doc-common
+.
+.als Cm doc-generic-macro
+.ds doc-Cm-usage interactive_command_modifier
+.
+.
+.\" NS Dv user macro
+.\" NS defined variable
+.\" NS
+.\" NS this function uses the `Er' font
+.\" NS
+.\" NS width register `Dv' set in doc-common
+.
+.als Dv doc-generic-macro
+.ds doc-Dv-usage defined_variable
+.als doc-Dv-font doc-Er-font
+.
+.
+.\" NS Em user macro
+.\" NS emphasis
+.\" NS
+.\" NS width register `Em' set in doc-common
+.
+.als Em doc-generic-macro
+.ds doc-Em-usage text
+.
+.
+.\" NS Er user macro
+.\" NS errno type
+.\" NS
+.\" NS width register `Er' set in doc-common
+.
+.als Er doc-generic-macro
+.ds doc-Er-usage text
+.
+.
+.\" NS Ev user macro
+.\" NS environment variable
+.\" NS
+.\" NS width register `Ev' set in doc-common
+.
+.als Ev doc-generic-macro
+.ds doc-Ev-usage text
+.
+.
+.\" NS doc-have-decl global register (bool)
+.\" NS subroutine test (in synopsis only)
+.
+.nr doc-have-decl 0
+.
+.
+.\" NS doc-have-var global register (bool)
+.\" NS whether last type is a variable type
+.
+.nr doc-have-var 0
+.
+.
+.\" NS doc-do-func-decl macro
+.\" NS do someting special while in SYNOPSIS
+.\" NS
+.\" NS modifies:
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-have-decl
+.\" NS doc-have-var
+.
+.de doc-do-func-decl
+. if \n[doc-in-synopsis-section] \{\
+. \" if a variable type was the last thing given, want vertical space
+. if \n[doc-have-var] \{\
+. doc-paragraph
+. nr doc-have-var 0
+. \}
+. \" if a subroutine was the last thing given, want vertical space
+. if \n[doc-have-func] \{\
+. ie \n[doc-have-decl] \
+. br
+. el \
+. doc-paragraph
+. \}
+. nr doc-have-decl 1
+. \}
+.
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+..
+.
+.
+.\" NS Fd user macro
+.\" NS function declaration -- not callable
+.\" NS
+.\" NS this function causes a break
+.\" NS
+.\" NS width register `Fd' set in doc-common
+.
+.de Fd
+. ie ((\n[.$] >= 1) & (\n[doc-arg-limit] == 0)) \{\
+. doc-do-func-decl
+. nop \*[doc-Fd-font]\$*
+. br
+. ft \n[doc-curr-font]
+. ps \n[doc-curr-size]u
+. \}
+. el \{\
+. tm Usage: .Fd function_declaration -- Fd is not callable (#\n[.c])
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS In user macro
+.\" NS #include statement - not callable
+.\" NS
+.\" NS this function causes a break; it uses the `Fd' font
+.\" NS
+.\" NS width register `In' set in doc-common
+.
+.de In
+. ie ((\n[.$] == 1) & (\n[doc-arg-limit] == 0)) \{\
+. doc-do-func-decl
+. nop \*[doc-Fd-font]#include <\$1>
+. br
+. ft \n[doc-curr-font]
+. ps \n[doc-curr-size]u
+. \}
+. el \{\
+. tm Usage: .In include_file -- In is not callable (#\n[.c])
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS Fr user macro
+.\" NS function return value
+.\" NS
+.\" NS this function uses the `Ar' font
+.\" NS
+.\" NS width register `Fr' set in doc-common
+.
+.als Fr doc-generic-macro
+.ds doc-Fr-usage function_return_value
+.als doc-Fr-font doc-Ar-font
+.
+.
+.\" NS Ic user macro
+.\" NS interactive command
+.\" NS
+.\" NS width register `Ic' set in doc-common
+.
+.als Ic doc-generic-macro
+.ds doc-Ic-usage interactive_command
+.
+.
+.\" NS Li user macro
+.\" NS literals
+.\" NS
+.\" NS width register `Li' set in doc-common
+.
+.als Li doc-generic-macro
+.ds doc-Li-usage argument
+.
+.
+.\" NS Ms user macro
+.\" NS math symbol
+.\" NS
+.\" NS this function uses the `Sy' font
+.\" NS
+.\" NS width register `Ms' set in doc-common
+.
+.als Ms doc-generic-macro
+.ds doc-Ms-usage math_symbol
+.als doc-Ms-font doc-Sy-font
+.
+.
+.\" NS doc-command-name global string
+.\" NS save first invocation of .Nm
+.
+.ds doc-command-name
+.
+.
+.\" NS Nm user macro
+.\" NS name of command or page topic
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-command-name
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-indent-synopsis
+.\" NS doc-indent-synopsis-active
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Nm' set in doc-common
+.
+.de Nm
+. if !\n[doc-arg-limit] \{\
+. ds doc-macro-name Nm
+. ie \n[.$] \
+. doc-parse-args \$@
+. el \{\
+. ie "\*[doc-command-name]"" \
+. tm Usage: .Nm name ... (#\n[.c])
+. el \
+. doc-parse-args \*[doc-command-name]
+. \}\}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. ie (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. \" last argument
+. ie "\*[doc-command-name]"" \{\
+. tm Usage: .Nm name ... (#\n[.c])
+. doc-reset-args
+. \}
+. el \{\
+. nop \*[doc-Nm-font]\*[doc-command-name]\f[P]\s[0]\c
+. doc-print-and-reset
+. \}\}
+. el \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. ie !(\n[doc-type\n[doc-arg-ptr]] == 2) \{\
+. ie "\*[doc-command-name]"" \
+. tm Usage: .Nm name ... (#\n[.c])
+. el \{\
+. \" replace previous argument (Nm) with default value
+. nr doc-arg-ptr -1
+. ds doc-arg\n[doc-arg-ptr] "\*[doc-Nm-font]\*[doc-command-name]\f[P]\s[0]
+. nr doc-type\n[doc-arg-ptr] 2
+. ds doc-space\n[doc-arg-ptr] "\*[doc-space]
+.
+. \" recompute space vector for remaining arguments
+. nr doc-num-args (\n[doc-arg-limit] - \n[doc-arg-ptr])
+. nr doc-arg-limit \n[doc-arg-ptr]
+. doc-parse-space-vector
+. \}\}
+. el \{\
+. \" handle `.Nm ...' in SYNOPSIS
+. if \n[doc-in-synopsis-section] \{\
+. if "\*[doc-macro-name]"Nm" \{\
+. br
+. if !\n[doc-indent-synopsis] \{\
+. doc-get-width "\*[doc-arg\n[doc-arg-ptr]]"
+. nr doc-indent-synopsis ((\n[doc-width]u + 1u) * \n[doc-fixed-width]u)
+. \}
+. if !\n[doc-indent-synopsis-active] \{\
+. in +\n[doc-indent-synopsis]u
+. nr doc-indent-synopsis-active 1
+. \}
+. ti -\n[doc-indent-synopsis]u
+. \}\}
+. if "\*[doc-command-name]"" \
+. ds doc-command-name "\*[doc-arg\n[doc-arg-ptr]]
+.
+. nop \*[doc-Nm-font]\c
+. \}
+. doc-print-recursive
+. \}
+..
+.
+.
+.\" NS Pa user macro
+.\" NS pathname: `.Pa [arg ...]'
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Pa' set in doc-common
+.
+.de Pa
+. if !\n[doc-arg-limit] \{\
+. ds doc-macro-name Pa
+. doc-parse-args \$@
+.
+. if !\n[.$] \{\
+. \" default value
+. nop \*[doc-Pa-font]~\f[P]\s[0]
+. \}\}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Pa-font]\c
+. if !(\n[doc-type\n[doc-arg-ptr]] == 2) \{\
+. \" replace previous argument (Pa) with default value
+. nr doc-arg-ptr -1
+. ds doc-arg\n[doc-arg-ptr] ~
+. nr doc-type\n[doc-arg-ptr] 2
+. ds doc-space\n[doc-arg-ptr] "\*[doc-space]
+.
+. \" recompute space vector for remaining arguments
+. nr doc-num-args (\n[doc-arg-limit] - \n[doc-arg-ptr])
+. nr doc-arg-limit \n[doc-arg-ptr]
+. doc-parse-space-vector
+. \}
+. doc-print-recursive
+. \}
+. el \{\
+. nop \*[doc-Pa-font]~\f[P]\s[0]\c
+. doc-print-and-reset
+. \}
+..
+.
+.
+.\" NS Sy user macro
+.\" NS symbolics
+.\" NS
+.\" NS width register `Sy' set in doc-common
+.
+.als Sy doc-generic-macro
+.ds doc-Sy-usage symbolic_text
+.
+.
+.\" NS Me user macro
+.\" NS menu entries
+.\" NS
+.\" NS width register `Me' set in doc-common
+.
+.als Me doc-generic-macro
+.ds doc-Me-usage menu_entry
+.
+.
+.\" NS Tn user macro
+.\" NS trade name
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Tn' set in doc-common
+.
+.de Tn
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Tn
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Tn trade_name ... (#\n[.c])
+. \}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \)\*[doc-Tn-font-size]\c
+. ie !\n[doc-is-reference] \{\
+. nop \)\*[doc-Tn-font-shape]\c
+. doc-print-recursive
+. \}
+. el \
+. doc-do-references
+. \}
+. el \{\
+. tm Usage: .Tn trade_name ... (#\n[.c])
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS Va user macro
+.\" NS variable name
+.\" NS
+.\" NS width register `Va' set in doc-common
+.
+.als Va doc-generic-macro
+.ds doc-Va-usage variable_name
+.
+.
+.\" NS No user macro
+.\" NS normal text macro (default text style if mess up)
+.\" NS
+.\" NS width register `No' set in doc-common
+.
+.als No doc-generic-macro
+.ds doc-No-usage normal_text
+.
+.
+.\" NS doc-quote-left global string
+.\" NS left quotation character for `doc-enclose-string' and
+.\" NS `doc-enclose-open'
+.
+.ds doc-quote-left
+.
+.
+.\" NS doc-quote-right global string
+.\" NS right quotation character for `doc-enclose-string' and
+.\" NS `doc-enclose-close'
+.
+.ds doc-quote-right
+.
+.
+.\" NS Op user macro
+.\" NS option expression (i.e., enclose string in square brackets)
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Op' set in doc-common
+.
+.de Op
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Op
+.
+. ds doc-quote-left "\*[doc-left-bracket]
+. ds doc-quote-right "\*[doc-right-bracket]
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Aq user macro
+.\" NS enclose string in angle brackets
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Aq' set in doc-common
+.
+.de Aq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Aq
+.
+. ds doc-quote-left \[la]
+. ds doc-quote-right \[ra]
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Bq user macro
+.\" NS enclose string in square brackets
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Bq' set in doc-common
+.
+.de Bq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Bq
+.
+. ds doc-quote-left "\*[doc-left-bracket]
+. ds doc-quote-right "\*[doc-right-bracket]
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Brq user macro
+.\" NS enclose string in braces
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Brq' set in doc-common
+.
+.de Brq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Brq
+.
+. ds doc-quote-left {
+. ds doc-quote-right }
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Dq user macro
+.\" NS enclose string in double quotes
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Dq' set in doc-common
+.
+.de Dq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Dq
+.
+. ds doc-quote-left "\*[Lq]
+. ds doc-quote-right "\*[Rq]
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Eq user macro
+.\" NS enclose string in user-defined quotes (args 1 and 2)
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Eq' set in doc-common
+.
+.de Eq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Eq
+.
+. ds doc-quote-left "\$1
+. ds doc-quote-right "\$2
+.
+. shift 2
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Pq user macro
+.\" NS enclose string in parentheses
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Pq' set in doc-common
+.
+.de Pq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Pq
+.
+. ds doc-quote-left "\*[doc-left-parenthesis]
+. ds doc-quote-right "\*[doc-right-parenthesis]
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Ql user macro
+.\" NS quoted literal
+.\"
+.\" is in file doc-[dit|n]roff
+.
+.
+.\" NS Qq user macro
+.\" NS enclose string in straight double quotes
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Qq' set in doc-common
+.
+.de Qq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Qq
+.
+. ds doc-quote-left "\*[q]
+. ds doc-quote-right "\*[q]
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Sq user macro
+.\" NS enclose string in single quotes
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Sq' set in doc-common
+.
+.de Sq
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Sq
+.
+. ds doc-quote-left "\*[doc-left-singlequote]
+. ds doc-quote-right "\*[doc-right-singlequote]
+.
+. doc-enclose-string \$@
+..
+.
+.
+.\" NS Es user macro
+.\" NS set up arguments (i.e., the left and right quotation character as
+.\" NS first and second argument) for .En call
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.
+.de Es
+. if !\n[doc-arg-limit] \{\
+. ie (\n[.$] > 2) \{\
+. ds doc-macro-name Es
+. doc-parse-args \$@
+. \}
+. el \{\
+. ds doc-quote-left "\$1
+. ds doc-quote-right "\$2
+. \}\}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. ds doc-quote-left "\*[doc-arg\n[doc-arg-ptr]]
+. nr doc-arg-ptr +1
+. ds doc-quote-right "\*[doc-arg\n[doc-arg-ptr]]
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \
+. doc-do-\n[doc-type\n[doc-arg-ptr]]
+. el \
+. doc-print-and-reset
+..
+.
+.
+.\" NS doc-have-slot global register (bool)
+.\" NS set if `doc-enclose-string' has created a slot for closing
+.\" NS delimiter
+.
+.nr doc-have-slot 0
+.
+.
+.\" NS doc-enclose-string macro
+.\" NS enclose string with given args (e.g. [ and ])
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-have-slot
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-des
+.\" NS doc-reg-des1
+.\" NS doc-reg-des2
+.\" NS
+.\" NS requires:
+.\" NS doc-quote-left
+.\" NS doc-quote-right
+.
+.de doc-enclose-string
+. if \n[doc-in-synopsis-section] \
+. doc-set-hard-space
+.
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \
+. doc-parse-args \$@
+. el \{\
+. nop \)\*[doc-quote-left]\*[doc-quote-right]
+. \}\}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. \" the final `\)' prevents hyphenation in case the next character is `\%'
+. nop \)\*[doc-quote-left]\)\c
+. ie (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. \" last argument
+. nop \)\*[doc-quote-right]\)\c
+. doc-print-and-reset
+. \}
+. el \{\
+. \" test whether last arguments are of type closing punctuation
+. \" resp. suffix
+. ie (\n[doc-type\n[doc-arg-limit]] == 3) \{\
+. nr doc-reg-des (\n[doc-arg-limit] - 1)
+. while (\n[doc-type\n[doc-reg-des]] == 3) \
+. nr doc-reg-des -1
+.
+. \" prepend closing delimiter
+. nr doc-reg-des +1
+. ds doc-arg\n[doc-reg-des] "\*[doc-quote-right]\)\*[doc-arg\n[doc-reg-des]]
+. \}
+. el \{\
+. \" test whether last arguments are macros which continue the line
+. \" logically
+. nr doc-reg-des \n[doc-arg-limit]
+. while (\n[doc-reg-des] >= \n[doc-arg-ptr]) \{\
+. if !\A\*[doc-arg\n[doc-reg-des]] \
+. break
+. if !d doc-after-\*[doc-arg\n[doc-reg-des]] \
+. break
+. nr doc-reg-des -1
+. \}
+.
+. \" if there are no trailing macros to be skipped, append argument
+. ie (\n[doc-reg-des] == \n[doc-arg-limit]) \
+. doc-append-arg "\)\*[doc-quote-right]\)" 3
+. el \{\
+. \" if a previous call to `doc-enclose-string' has already created
+. \" a slot, prepend argument
+. ie \n[doc-have-slot] \
+. ds doc-arg\n[doc-reg-des] "\*[doc-quote-right]\)\*[doc-arg\n[doc-reg-des]]
+. el \{\
+. \" we have to shift all arguments to the right
+. nr doc-reg-des +1
+. nr doc-reg-des1 \n[doc-arg-limit]
+. nr doc-reg-des2 (\n[doc-arg-limit] + 1)
+. while (\n[doc-reg-des1] >= \n[doc-reg-des]) \{\
+. rn doc-arg\n[doc-reg-des1] doc-arg\n[doc-reg-des2]
+. rnn doc-type\n[doc-reg-des1] doc-type\n[doc-reg-des2]
+. rn doc-space\n[doc-reg-des1] doc-space\n[doc-reg-des2]
+. nr doc-reg-des1 -1
+. nr doc-reg-des2 -1
+. \}
+. nr doc-arg-limit +1
+.
+. \" finally, insert closing delimiter into the freed slot and
+. \" recompute spacing vector
+. ds doc-arg\n[doc-reg-des] "\)\*[doc-quote-right]\)
+. nr doc-type\n[doc-reg-des] 3
+. nr doc-num-args (\n[doc-arg-limit] - \n[doc-reg-des] + 1)
+. nr doc-arg-limit (\n[doc-reg-des] - 1)
+. doc-parse-space-vector
+. nr doc-have-slot 1
+. \}\}\}
+.
+. doc-do-\n[doc-type\n[doc-arg-ptr]]
+. \}
+.
+. if \n[doc-in-synopsis-section] \
+. doc-set-soft-space
+..
+.
+.
+.\" NS En user macro
+.\" NS enclose arguments with quotation characters set up with `.Es'
+.
+.als En doc-enclose-string
+.
+.
+.\" NS Ao user macro
+.\" NS angle open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Ao' set in doc-common
+.
+.de Ao
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Ao
+.
+. ds doc-quote-left \[la]
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Ac user macro
+.\" NS angle close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Ac' set in doc-common
+.
+.de Ac
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Ac
+.
+. ds doc-quote-right \[ra]
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Bo user macro
+.\" NS bracket open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Bo' set in doc-common
+.
+.de Bo
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Bo
+.
+. ds doc-quote-left "\*[doc-left-bracket]
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Bc user macro
+.\" NS bracket close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Bc' set in doc-common
+.
+.de Bc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Bc
+.
+. ds doc-quote-right "\*[doc-right-bracket]
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Bro user macro
+.\" NS brace open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Bro' set in doc-common
+.
+.de Bro
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Bo
+.
+. ds doc-quote-left {
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Brc user macro
+.\" NS brace close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Brc' set in doc-common
+.
+.de Brc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Bc
+.
+. ds doc-quote-right }
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Do user macro
+.\" NS double quote open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Do' set in doc-common
+.
+.de Do
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Do
+.
+. ds doc-quote-left "\*[Lq]
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Dc user macro
+.\" NS double quote close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Dc' set in doc-common
+.
+.de Dc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Dc
+.
+. ds doc-quote-right "\*[Rq]
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Eo user macro
+.\" NS enclose open (using first argument as beginning of enclosure)
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Eo' set in doc-common
+.
+.de Eo
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Eo
+.
+. ds doc-quote-left "\$1
+.
+. shift
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Ec user macro
+.\" NS enclose close (using first argument as end of enclosure)
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Ec' set in doc-common
+.
+.de Ec
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Ec
+.
+. ds doc-quote-right "\$1
+.
+. shift
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Oo user macro
+.\" NS option open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Oo' set in doc-common
+.
+.de Oo
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Oo
+.
+. ds doc-quote-left [
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Oc user macro
+.\" NS option close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Oc' set in doc-common
+.
+.de Oc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Oc
+.
+. ds doc-quote-right ]
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Po user macro
+.\" NS parenthesis open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Po' set in doc-common
+.
+.de Po
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Po
+.
+. ds doc-quote-left "\*[doc-left-parenthesis]
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Pc user macro
+.\" NS parenthesis close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Pc' set in doc-common
+.
+.de Pc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Pc
+.
+. ds doc-quote-right "\*[doc-right-parenthesis]
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Qo user macro
+.\" NS straight double quote open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Qo' set in doc-common
+.
+.de Qo
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Qo
+.
+. ds doc-quote-left "\*[q]
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Qc user macro
+.\" NS straight double quote close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Qc' set in doc-common
+.
+.de Qc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Qc
+.
+. ds doc-quote-right "\*[q]
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS So user macro
+.\" NS single quote open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `So' set in doc-common
+.
+.de So
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name So
+.
+. ds doc-quote-left "\*[doc-left-singlequote]
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Sc user macro
+.\" NS single quote close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Sc' set in doc-common
+.
+.de Sc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Sc
+.
+. ds doc-quote-right "\*[doc-right-singlequote]
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS Xo user macro
+.\" NS extend open
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Xo' set in doc-common
+.
+.de Xo
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Xo
+.
+. ds doc-quote-left
+.
+. doc-enclose-open \$@
+..
+.
+.
+.\" NS Xc user macro
+.\" NS extend close
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS doc-quote-right
+.\" NS
+.\" NS width register `Xc' set in doc-common
+.
+.de Xc
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Xc
+.
+. ds doc-quote-right
+.
+. doc-enclose-close \$@
+..
+.
+.
+.\" NS doc-nesting-level global register
+.\" NS used by `doc-enclose-open' and `doc-enclose-close'
+.
+.nr doc-nesting-level 0
+.
+.
+.\" NS doc-in-list global register (bool)
+.\" NS whether we are in (logical) .It
+.
+.nr doc-in-list 0
+.
+.
+.\" NS doc-enclose-open macro
+.\" NS enclose string open
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-nesting-level
+.
+.de doc-enclose-open
+. if !\n[doc-arg-limit] \
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. nr doc-arg-ptr -1
+.
+. nop \)\*[doc-quote-left]\)\c
+.
+. \" start enclosure box
+. box doc-enclosure-box\n[doc-nesting-level]
+. ev doc-enclosure-env\n[doc-nesting-level]
+. evc 0
+. in 0
+. nf
+. \" we insert something to make .chop always work
+. nop \&\c
+.
+. \" increase nesting level *after* parsing of arguments
+. nr doc-nesting-level +1
+.
+. if \n[doc-arg-limit] \{\
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \
+. doc-print-recursive
+. el \
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS doc-enclose-close macro
+.\" NS enclose string close
+.\" NS
+.\" NS modifies:
+.\" NS doc-nesting-level
+.
+.de doc-enclose-close
+. nr doc-nesting-level -1
+.
+. \" finish enclosure box
+. br
+. ev
+. box
+. chop doc-enclosure-box\n[doc-nesting-level]
+. unformat doc-enclosure-box\n[doc-nesting-level]
+.
+. nh
+. nop \*[doc-enclosure-box\n[doc-nesting-level]]\c
+. nop \)\*[doc-quote-right]\)\c
+.
+. if !\n[doc-arg-limit] \{\
+. doc-parse-args \$@
+.
+. if !\n[.$] \
+. doc-print-and-reset
+. \}
+.
+. if \n[doc-arg-limit] \{\
+. ie (\n[doc-arg-limit] > \n[doc-arg-ptr]) \{\
+. nop \)\*[doc-space\n[doc-arg-ptr]]\c
+. nr doc-arg-ptr +1
+. doc-print-recursive
+. \}
+. el \
+. doc-print-and-reset
+. \}
+.
+. \" shall we finish .It request?
+. if !"\*[doc-macro-name]"It" \
+. if \n[doc-in-list] \
+. if !\n[doc-nesting-level] \
+. doc-\*[doc-list-type-stack\n[doc-list-depth]]
+..
+.
+.
+.\" NS Pf user macro
+.\" NS prefix: `.Pf prefix arg ...'
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-macro-name
+.\" NS doc-quote-left
+.\" NS
+.\" NS width register `Pf' set in doc-common
+.
+.de Pf
+. if !\n[doc-arg-limit] \
+. ds doc-macro-name Pf
+.
+. ie \n[doc-arg-limit] \{\
+. ie ((\n[doc-arg-limit] - \n[doc-arg-ptr]) > 1) \{\
+. nr doc-arg-ptr +1
+. nop \)\*[doc-arg\n[doc-arg-ptr]]\c
+. \}
+. el \
+. tm mdoc warning: .Pf: trailing prefix (#\n[.c])
+. \}
+. el \{\
+. nop \)\$1\)\c
+. shift
+. ie \n[.$] \
+. doc-parse-args \$@
+. el \{\
+. tm mdoc warning: .Pf: missing arguments (#\n[.c])
+. nop \)
+. \}\}
+.
+. if \n[doc-arg-limit] \{\
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] < \n[doc-arg-ptr]) \
+. doc-print-and-reset
+. el \
+. doc-do-\n[doc-type\n[doc-arg-ptr]]
+. \}
+..
+.
+.
+.\" NS Ns user macro
+.\" NS remove space (space removal done by `doc-parse-args')
+.\" NS
+.\" NS modifies:
+.\" NS doc-argXXX
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Ns' set in doc-common
+.
+.de Ns
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Ns
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Ns must be called with arguments (#\n[.c])
+. \}
+.
+. if \n[doc-arg-limit] \{\
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \
+. doc-print-recursive
+. el \
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS Ap user macro
+.\" NS append an apostrophe
+.\" NS
+.\" NS width register `Ap' set in doc-common
+.
+.de Ap
+. ie !\n[doc-arg-limit] \
+. tm Usage: `Ap' cannot be first request on a line (no `.Ap') (#\n[.c])
+. el \{\
+. nop \)'\)\c
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \
+. doc-print-recursive
+. el \
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS doc-space global string
+.\" NS current inter-argument space
+.
+.ds doc-space "\*[doc-soft-space]
+.
+.
+.\" NS doc-soft-space constant string
+.\" NS soft (stretchable) space (defined in doc-common)
+.
+.
+.\" NS doc-hard-space constant string
+.\" NS hard (unpaddable) space (defined in doc-common)
+.
+.
+.\" NS doc-set-hard-space macro
+.\" NS set current space string to hard (unpaddable) space.
+.\" NS
+.\" NS modifies:
+.\" NS doc-saved-space
+.\" NS doc-space
+.
+.de doc-set-hard-space
+. ie "\*[doc-space]"" \
+. ds doc-saved-space "\*[doc-hard-space]
+. el \
+. ds doc-space "\*[doc-hard-space]
+..
+.
+.
+.\" NS doc-set-soft-space macro
+.\" NS set current space string to soft space
+.\" NS
+.\" NS modifies:
+.\" NS doc-saved-space
+.\" NS doc-space
+.
+.de doc-set-soft-space
+. ie "\*[doc-space]"" \
+. ds doc-saved-space "\*[doc-soft-space]
+. el \
+. ds doc-space "\*[doc-soft-space]
+..
+.
+.
+.\" NS doc-space-mode global register (bool)
+.\" NS default is one (space mode on)
+.
+.nr doc-space-mode 1
+.
+.
+.\" NS doc-saved-space global string
+.\" NS saved value of `doc-space'
+.
+.ds doc-saved-space "\*[doc-space]
+.
+.
+.\" NS doc-have-space global register (bool)
+.\" NS set if last command was horizontal space
+.
+.nr doc-have-space 0
+.
+.
+.\" NS Sm user macro
+.\" NS space mode (`.Sm'/`.Sm on'/`.Sm off')
+.\" NS
+.\" NS without argument, toggle space mode
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-limit
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-macro-name
+.\" NS doc-num-args
+.\" NS doc-saved-space
+.\" NS doc-space
+.\" NS doc-space-mode
+.\" NS doc-spaceXXX
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-Sm
+.\" NS
+.\" NS width register `Sm' set in doc-common
+.
+.de Sm
+. ie \n[doc-have-space] \
+. nr doc-reg-Sm 0
+. el \
+. nr doc-reg-Sm 1
+.
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Sm
+. doc-parse-args \$@
+. \}
+. el \{\
+. ie \n[doc-space-mode] \
+. nr doc-space-mode 0
+. el \
+. nr doc-space-mode 1
+. \}\}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+.
+. \" avoid a warning message in case `Sm' is the last parameter
+. if !d doc-arg\n[doc-arg-ptr] \
+. ds doc-arg\n[doc-arg-ptr]
+.
+. ie "\*[doc-arg\n[doc-arg-ptr]]"on" \{\
+. ds doc-space "\*[doc-saved-space]
+. nr doc-space-mode 1
+. \}
+. el \{\
+. ie "\*[doc-arg\n[doc-arg-ptr]]"off" \{\
+. ds doc-saved-space "\*[doc-space]
+. ds doc-space
+. nr doc-space-mode 0
+. \}
+. el \{\
+. \" no argument for Sm
+. nr doc-arg-ptr -1
+. ie \n[doc-space-mode] \
+. nr doc-space-mode 0
+. el \
+. nr doc-space-mode 1
+. \}\}
+.
+. ie \n[doc-space-mode] \{\
+. \" recompute space vector for remaining arguments
+. nr doc-num-args (\n[doc-arg-limit] - \n[doc-arg-ptr])
+. nr doc-arg-limit \n[doc-arg-ptr]
+. if \n[doc-num-args] \
+. doc-parse-space-vector
+.
+. \" finish line only if it is interrupted and `doc-have-space'
+. \" isn't set
+. if \n[doc-reg-Sm] \
+. if \n[.int] \
+. nop \)
+. \}
+. el \{\
+. \" reset remaining space vector elements
+. nr doc-reg-Sm (\n[doc-arg-ptr] + 1)
+. while (\n[doc-reg-Sm] <= \n[doc-arg-limit]) \{\
+. ds doc-space\n[doc-reg-Sm]
+. nr doc-reg-Sm +1
+. \" the body of a `while' request must end with the fitting `\}'!
+. \}
+. \}
+.
+. \" do we have parameters to print?
+. ie (\n[doc-arg-limit] <= \n[doc-arg-ptr]) \{\
+. \" ignore `.Sm on' and `.Sm off' without additional parameters
+. ie (\n[doc-arg-ptr] > 1) \
+. doc-print-and-reset
+. el \
+. doc-reset-args
+. \}
+. el \{\
+. \" skip `Sm' argument
+. nr doc-arg-ptr +1
+. doc-print-recursive
+. \}
+..
+.
+.
+.\" NS doc-arg-type immediate register
+.\" NS argument type (macro=1, string=2, punctuation suffix=3,
+.\" NS punctuation prefix=4)
+.
+.nr doc-arg-type 0
+.
+.
+.\" NS doc-get-arg-type macro
+.\" NS get argument type
+.\" NS
+.\" NS this macro expects the width of the argument in `doc-width'
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-type
+.
+.de doc-get-arg-type
+. nr doc-arg-type 2
+.
+. if ((\n[doc-width] < 4) & \A\$1) \{\
+. ie (\n[doc-width] == 1) \{\
+. if r doc-punct\$1 \
+. nr doc-arg-type \n[doc-punct\$1]
+. \}
+. el \
+. if r \$1 \
+. if d \$1 \
+. nr doc-arg-type 1
+. \}
+..
+.
+.
+.\" NS doc-get-arg-type* macro
+.\" NS similar to as `doc-get-arg-type' but uses doc-argXXX strings
+.\" NS
+.\" NS this macro sets the `doc-width' register using the `length' request
+.\" NS to get the number of characters in a string literally
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-type
+.\" NS doc-width
+.
+.de doc-get-arg-type*
+. nr doc-arg-type 2
+. length doc-width "\*[doc-arg\$1]
+.
+. if ((\n[doc-width] < 4) & \A\*[doc-arg\$1]) \{\
+. ie (\n[doc-width] == 1) \{\
+. if r doc-punct\*[doc-arg\$1] \
+. nr doc-arg-type \n[doc-punct\*[doc-arg\$1]]
+. \}
+. el \
+. if r \*[doc-arg\$1] \
+. if d \*[doc-arg\$1] \
+. nr doc-arg-type 1
+. \}
+..
+.
+.
+.\" NS doc-set-spacing-1 macro
+.\" NS set spacing for macros
+.\" NS
+.\" NS modifies:
+.\" NS doc-spaceXXX
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dssfm
+.\" NS doc-reg-dssfm1
+.
+.de doc-set-spacing-1
+. nr doc-reg-dssfm1 \n[\*[doc-arg\n[doc-arg-limit]]]
+.
+. \" closing macros like .Ac, Bc., etc. have value 3 (remove space before
+. \" argument)
+. ie (\n[doc-reg-dssfm1] == 3) \{\
+. if \n[doc-arg-limit] \{\
+. nr doc-reg-dssfm (\n[doc-arg-limit] - 1)
+. ds doc-space\n[doc-reg-dssfm]
+. \}
+. ds doc-space\n[doc-arg-limit] "\*[doc-space]
+. \}
+. el \{\
+. \" macros like .Ap and .Ns have value 2 (remove space before and after
+. \" argument)
+. ie (\n[doc-reg-dssfm1] == 2) \{\
+. if \n[doc-arg-limit] \{\
+. nr doc-reg-dssfm (\n[doc-arg-limit] - 1)
+. ds doc-space\n[doc-reg-dssfm]
+. \}
+. ds doc-space\n[doc-arg-limit]
+. \}
+. el \
+. ds doc-space\n[doc-arg-limit]
+. \}
+..
+.
+.
+.\" NS doc-set-spacing-2 macro
+.\" NS set spacing for strings
+.\" NS
+.\" NS modifies:
+.\" NS doc-spaceXXX
+.
+.de doc-set-spacing-2
+. ds doc-space\n[doc-arg-limit] "\*[doc-space]
+..
+.
+.
+.\" NS doc-set-spacing-3 macro
+.\" NS set spacing for punctuation suffixes
+.\" NS
+.\" NS modifies:
+.\" NS doc-spaceXXX
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dssfps
+.
+.de doc-set-spacing-3
+. if \n[doc-arg-limit] \{\
+. nr doc-reg-dssfps (\n[doc-arg-limit] - 1)
+. ds doc-space\n[doc-reg-dssfps]
+. \}
+.
+. ds doc-space\n[doc-arg-limit] "\*[doc-space]
+..
+.
+.
+.\" NS doc-set-spacing-4 macro
+.\" NS set spacing for punctuation prefixes
+.\" NS
+.\" NS modifies:
+.\" NS doc-spaceXXX
+.
+.de doc-set-spacing-4
+. ds doc-space\n[doc-arg-limit]
+..
+.
+.
+.\" type switches (on current argument doc-arg-ptr)
+.
+.
+.\" NS doc-do-1 macro
+.\" NS call request if macro
+.
+.de doc-do-1
+. \*[doc-arg\n[doc-arg-ptr]]
+..
+.
+.
+.\" NS doc-do-2 macro
+.\" NS call .doc-print-recursive if string
+.
+.als doc-do-2 doc-print-recursive
+.
+.
+.\" NS doc-do-3 macro
+.\" NS call .doc-print-recursive if punctuation suffix
+.
+.als doc-do-3 doc-print-recursive
+.
+.
+.\" NS doc-do-4 macro
+.\" NS call .doc-print-recursive if punctuation prefix
+.
+.als doc-do-4 doc-print-recursive
+.
+.
+.\" NS doc-fontmode-depth global register
+.\" NS font mode level
+.
+.nr doc-fontmode-depth 0
+.
+.
+.\" NS doc-fontmode-font-stackXXX global register
+.\" NS stack of saved current font values from `Bf' request
+.\" NS
+.\" NS limit:
+.\" NS doc-fontmode-depth
+.
+.nr doc-fontmode-font-stack0 0
+.
+.
+.\" NS doc-fontmode-size-stackXXX global register
+.\" NS stack of saved current size values from `Bf' request
+.\" NS
+.\" NS limit:
+.\" NS doc-fontmode-depth
+.
+.nr doc-fontmode-size-stack0 0
+.
+.
+.\" NS Bf user macro
+.\" NS begin font mode (will be begin-mode/end-mode in groff & TeX)
+.\" NS
+.\" NS modifies:
+.\" NS doc-fontmode-depth
+.\" NS doc-fontmode-font-stackXXX
+.\" NS doc-fontmode-size-stackXXX
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Bf' set in doc-common
+.
+.de Bf
+. ds doc-macro-name Bf
+.
+. ie \n[.$] \{\
+. nr doc-fontmode-depth +1
+.
+. \" save current font and size
+. nr doc-fontmode-font-stack\n[doc-fontmode-depth] \n[.f]
+. nr doc-fontmode-size-stack\n[doc-fontmode-depth] \n[.ps]
+.
+. ie "\$1"Em" \
+. nop \*[doc-Em-font]\c
+. el \{ .ie "\$1"Li" \
+. nop \*[doc-Li-font]\c
+. el \{ .ie "\$1"Sy" \
+. nop \*[doc-Sy-font]\c
+. el \{ .ie "\$1"-emphasis" \
+. nop \*[doc-Em-font]\c
+. el \{ .ie "\$1"-literal" \
+. nop \*[doc-Li-font]\c
+. el \{ .ie "\$1"-symbolic" \
+. nop \*[doc-Sy-font]\c
+. el \{\
+. tmc mdoc warning: Unknown keyword `\$1' in .Bf request
+. tm1 " (#\n[.c])
+. \}\}\}\}\}\}\}
+. el \
+. tm Usage: .Bf [Em | -emphasis | Li | -literal | Sy | -symbolic] (#\n[.c])
+..
+.
+.
+.\" NS Ef user macro
+.\" NS end font mode
+.\" NS
+.\" NS modifies:
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Ef' set in doc-common
+.
+.de Ef
+. ds doc-macro-name Ef
+.
+. ie \n[doc-fontmode-depth] \{\
+. \" restore saved font and size
+. nop \)\f[\n[doc-fontmode-font-stack\n[doc-fontmode-depth]]]\c
+. nop \)\s[\n[doc-fontmode-size-stack\n[doc-fontmode-depth]]u]\c
+.
+. nr doc-fontmode-font-stack\n[doc-fontmode-depth] 0
+. nr doc-fontmode-size-stack\n[doc-fontmode-depth] 0
+. nr doc-fontmode-depth -1
+. \}
+. el \
+. tm mdoc warning: Extraneous .Ef (#\n[.c])
+..
+.
+.
+.\" NS doc-keep-type global register
+.\" NS current keep type; 1 is `-words', 2 is `-lines', 3 is unknown
+.
+.nr doc-keep-type 0
+.
+.
+.\" NS Bk user macro
+.\" NS begin keep
+.\" NS
+.\" NS modifies:
+.\" NS doc-keep-type
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Bk' set in doc-common
+.
+.de Bk
+. ds doc-macro-name Bk
+.
+. if \n[doc-keep-type] \
+. tm .Bk: nesting keeps not implemented yet. (#\n[.c])
+.
+. ie "\$1"-lines" \{\
+. nr doc-keep-type 2
+. tm .Bk -lines: Not implemented yet. (#\n[.c])
+. \}
+. el \{ .ie "\$1"-words" \{\
+. nr doc-keep-type 1
+. doc-set-hard-space
+. \}
+. el \{ .ie "\$1"" \{\
+. \" default
+. nr doc-keep-type 1
+. doc-set-hard-space
+. \}
+. el \{\
+. tm mdoc warning: Unknown keyword `\$1' in .Bk request (#\n[.c])
+. nr doc-keep-type 3
+. \}\}\}
+.
+\#. nr doc-nesting-level +1
+..
+.
+.
+.\" NS Ek user macro
+.\" NS end keep
+.\" NS
+.\" NS modifies:
+.\" NS doc-keep-type
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Ek' set in doc-common
+.
+.de Ek
+. ds doc-macro-name Ek
+.
+\#. nr doc-nesting-level -1
+.
+. ie \n[.$] \
+. tm Usage: .Ek (does not take arguments) (#\n[.c])
+. el \{\
+. if !\n[doc-keep-type] \
+. tm mdoc warning: .Ek found without .Bk before (#\n[.c])
+.
+. ie (\n[doc-keep-type] == 1) \
+. doc-set-soft-space
+. el \{ .if (\n[doc-keep-type] == 2) \
+. tm .Bk -lines: Not implemented yet. (#\n[.c])
+. \}\}
+.
+. nr doc-keep-type 0
+.
+\#. if !"\*[doc-out-string]"" \
+\#. doc-print-out-string
+..
+.
+.
+.\" NS doc-display-depth global register
+.\" NS display level
+.
+.nr doc-display-depth 0
+.
+.
+.\" NS doc-is-compact global register (bool)
+.\" NS set if the `compact' keyword is given
+.
+.nr doc-is-compact 0
+.
+.
+.\" NS doc-display-type-stackXXX global string
+.\" NS the display type stack
+.\" NS
+.\" NS limit:
+.\" NS doc-display-depth
+.
+.ds doc-display-type-stack0
+.
+.
+.\" NS doc-display-indent-stackXXX global register
+.\" NS stack of display indentation values
+.\" NS
+.\" NS limit:
+.\" NS doc-display-depth
+.
+.nr doc-display-indent-stack0 0
+.
+.
+.\" NS doc-display-ad-stackXXX global register
+.\" NS stack of saved adjustment modes
+.\" NS
+.\" NS limit:
+.\" NS doc-display-depth
+.
+.nr doc-display-ad-stack0 0
+.
+.
+.\" NS doc-display-fi-stackXXX global register
+.\" NS stack of saved fill modes
+.\" NS
+.\" NS limit:
+.\" NS doc-display-depth
+.
+.nr doc-display-fi-stack0 0
+.
+.
+.\" NS Bd user macro
+.\" NS begin display
+.\" NS
+.\" NS width register `Bd' set in doc-common
+.\" NS
+.\" NS modifies:
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-display-depth
+.\" NS doc-display-ad-stackXXX
+.\" NS doc-display-fi-stackXXX
+.\" NS doc-display-file
+.\" NS doc-display-indent-stackXXX
+.\" NS doc-display-type-stackXXX
+.\" NS doc-is-compact
+.\" NS doc-macro-name
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-Bd
+.
+.de Bd
+. ds doc-macro-name Bd
+.
+. if !\n[.$] \{\
+. tm1 "Usage: .Bd {-literal | -filled | -ragged | -centered | -unfilled}
+. tm1 " [-offset [string]] [-compact] [-file name] (#\n[.c])
+. return
+. \}
+.
+. nr doc-is-compact 0
+. ds doc-display-file
+. nr doc-reg-Bd 1
+. nr doc-display-depth +1
+.
+. \" save current adjustment and fill modes
+. nr doc-display-ad-stack\n[doc-display-depth] \n[.j]
+. nr doc-display-fi-stack\n[doc-display-depth] \n[.u]
+.
+. ie "\$1"-literal" \{\
+. ds doc-display-type-stack\n[doc-display-depth] literal
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. ie t \{\
+. nop \*[doc-Li-font]\c
+' ta T 9n
+. \}
+. el \
+' ta T 8n
+. nf
+. \}
+. el \{ .ie "\$1"-filled" \{\
+. ds doc-display-type-stack\n[doc-display-depth] filled
+. ad b
+. fi
+. \}
+. el \{ .ie "\$1"-ragged" \{\
+. ds doc-display-type-stack\n[doc-display-depth] ragged
+. na
+. fi
+. \}
+. el \{ .ie "\$1"-centered" \{\
+. ds doc-display-type-stack\n[doc-display-depth] centered
+. ad c
+. fi
+. \}
+. el \{ .ie "\$1"-unfilled" \{\
+. ds doc-display-type-stack\n[doc-display-depth] unfilled
+. nf
+. \}
+. el \{\
+. tm1 "mdoc warning: Unknown keyword `\$1' (or missing display type)
+. tm1 " in .Bd request (#\n[.c])
+. nr doc-reg-Bd 0
+. \}\}\}\}\}
+.
+. \" have we seen an argument?
+. if \n[doc-reg-Bd] \{\
+. shift
+. \" check other arguments
+. if \n[.$] \
+. doc-do-Bd-args \$@
+. \}
+.
+. \" avoid warning about non-existent register
+. if !r doc-display-indent-stack\n[doc-display-depth] \
+. nr doc-display-indent-stack\n[doc-display-depth] 0
+.
+. if \n[doc-display-indent-stack\n[doc-display-depth]] \
+' in +\n[doc-display-indent-stack\n[doc-display-depth]]u
+.
+. if !\n[doc-is-compact] \{\
+. if !\n[doc-in-synopsis-section] \{\
+. ie "\*[doc-display-type-stack\n[doc-display-depth]]"ragged" \
+. sp \n[doc-display-vertical]u
+. el \
+' sp \n[doc-display-vertical]u
+. \}\}
+.
+. if !\n[cR] \
+. ne 2v
+.
+. if !"\*[doc-display-file]"" \
+. so \*[doc-display-file]
+.
+. nr doc-is-compact 0
+. ds doc-display-file
+..
+.
+.
+.\" NS doc-do-Bd-args macro
+.\" NS resolve remaining .Bd arguments
+.\" NS
+.\" NS modifies:
+.\" NS doc-display-file
+.\" NS doc-display-indent-stackXXX
+.\" NS doc-is-compact
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-ddBa
+.\" NS doc-reg-ddBa1
+.\" NS doc-reg-ddBa2
+.\" NS doc-reg-ddBa3
+.\" NS doc-reg-ddBa4
+.\" NS doc-str-ddBa
+.
+.de doc-do-Bd-args
+. nr doc-reg-ddBa 1
+.
+. ie "\$1"-offset" \{\
+. nr doc-reg-ddBa 2
+.
+. ie "\$2"left" \
+. nr doc-display-indent-stack\n[doc-display-depth] 0
+. el \{ .ie "\$2"right" \
+. nr doc-display-indent-stack\n[doc-display-depth] (\n[.l]u / 3u)
+. el \{ .ie "\$2"center" \
+. nr doc-display-indent-stack\n[doc-display-depth] ((\n[.l]u - \n[.i]u) / 4u)
+. el \{ .ie "\$2"indent" \
+. nr doc-display-indent-stack\n[doc-display-depth] \n[doc-display-indent]u
+. el \{ .ie "\$2"indent-two" \
+. nr doc-display-indent-stack\n[doc-display-depth] (\n[doc-display-indent]u + \n[doc-display-indent]u)
+. el \
+. nr doc-reg-ddBa 1
+. \}\}\}\}
+.
+. \" not a known keyword
+. if (\n[doc-reg-ddBa] == 1) \{\
+. nr doc-reg-ddBa 2
+.
+. nr doc-reg-ddBa1 0
+. if \B(\$2) \{\
+. \" disable warnings related to scaling indicators (32)
+. nr doc-reg-ddBa2 \n[.warn]
+. warn (\n[.warn] - (\n[.warn] / 32 % 2 * 32))
+.
+. \" values without a scaling indicator are taken as strings;
+. \" we test whether the parameter string with and without the last
+. \" character yields identical numerical results (ignoring the
+. \" scaling indicator)
+. ds doc-str-ddBa "\$2
+. substring doc-str-ddBa 1 -1
+. if \B(\*[doc-str-ddBa]) \{\
+. nr doc-reg-ddBa3 (;(\$2))
+. nr doc-reg-ddBa4 (\*[doc-str-ddBa])
+. if (\n[doc-reg-ddBa3] == \n[doc-reg-ddBa4]) \
+. nr doc-reg-ddBa1 1
+. \}
+.
+. \" enable all warnings again
+. warn \n[doc-reg-ddBa2]
+. \}
+.
+. ie \n[doc-reg-ddBa1] \
+. nr doc-display-indent-stack\n[doc-display-depth] \$2
+. el \{\
+. doc-get-width "\$2"
+. ie (\n[doc-width] <= 3) \{\
+. \" if the offset parameter is a macro, use the macro's
+. \" width as specified in doc-common
+. doc-get-arg-type "\$2"
+. ie (\n[doc-arg-type] == 1) \
+. nr doc-display-indent-stack\n[doc-display-depth] \n[\$2]
+. el \
+. nr doc-display-indent-stack\n[doc-display-depth] (\n[doc-width]u * \n[doc-fixed-width]u)
+. \}
+. el \
+. nr doc-display-indent-stack\n[doc-display-depth] (\n[doc-width]u * \n[doc-fixed-width]u)
+. \}\}
+. \}
+. el \{ .ie "\$1"-compact" \
+. nr doc-is-compact 1
+. el \{ .ie "\$1"-file" \{\
+. ie !"\$2"" \{\
+. ds doc-display-file "\$2
+. nr doc-reg-ddBa 2
+. \}
+. el \
+. tm mdoc warning: .Bd `-file' keyword requires argument (#\n[.c])
+. \}
+. el \
+. tm mdoc warning: Unknown keyword `\$1' in .Bd request (#\n[.c])
+. \}\}
+.
+. if (\n[doc-reg-ddBa] < \n[.$]) \{\
+. shift \n[doc-reg-ddBa]
+. doc-do-Bd-args \$@
+. \}
+..
+.
+.
+.\" NS Ed user macro
+.\" NS end display
+.\" NS
+.\" NS modifies:
+.\" NS doc-display-depth
+.\" NS doc-display-indent-stackXXX
+.\" NS doc-display-type-stackXXX
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Ed' set in doc-common
+.
+.de Ed
+. ds doc-macro-name Ed
+.
+. br
+.
+. if !\n[doc-display-depth] \{\
+. tm mdoc warning: Extraneous .Ed (#\n[.c])
+. nr doc-display-depth 1
+. \}
+.
+. if "\*[doc-display-type-stack\n[doc-display-depth]]"literal" \{\
+. ft \n[doc-curr-font]
+. ps \n[doc-curr-size]u
+. \}
+.
+. in -\n[doc-display-indent-stack\n[doc-display-depth]]u
+.
+. \" restore saved adjustment and fill modes
+. ie \n[doc-display-fi-stack\n[doc-display-depth]] \
+. fi
+. el \
+. nf
+. ad \n[doc-display-ad-stack\n[doc-display-depth]]
+.
+. nr doc-display-indent-stack\n[doc-display-depth] 0
+. ds doc-display-type-stack\n[doc-display-depth]
+. nr doc-display-depth -1
+..
+.
+.
+.\" NS doc-list-type-stackXXX global string
+.\" NS stack of list types
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.ds doc-list-type-stack1
+.
+.
+.\" NS doc-list-indent-stackXXX global register
+.\" NS stack of list indentation values
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.nr doc-list-indent-stack1 0
+.
+.
+.\" NS doc-list-have-indent-stackXXX global register (bool)
+.\" NS an indentation value is active
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.nr doc-list-have-indent-stack1 0
+.
+.
+.\" NS Bl user macro
+.\" NS begin list
+.\" NS
+.\" NS width register `Bl' set in doc-common
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-list-depth
+.\" NS doc-list-have-indent-stackXXX
+.\" NS doc-list-indent-stackXXX
+.\" NS doc-list-type-stackXXX
+.\" NS doc-macro-name
+.\" NS doc-num-args
+.\" NS doc-num-columns
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-Bl
+.
+.de Bl
+. if !\n[.$] \{\
+. doc-Bl-usage
+. return
+. \}
+.
+. ds doc-macro-name Bl
+. nr doc-list-depth +1
+. nr doc-arg-ptr 1
+.
+. ie "\$1"-hang" \{\
+. ds doc-list-type-stack\n[doc-list-depth] hang-list
+. nr doc-list-indent-stack\n[doc-list-depth] 6n
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-tag" \{\
+. ds doc-list-type-stack\n[doc-list-depth] tag-list
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-item" \{\
+. ds doc-list-type-stack\n[doc-list-depth] item-list
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-enum" \{\
+. ds doc-list-type-stack\n[doc-list-depth] enum-list
+. nr doc-list-indent-stack\n[doc-list-depth] 3n
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-bullet" \{\
+. ds doc-list-type-stack\n[doc-list-depth] bullet-list
+. nr doc-list-indent-stack\n[doc-list-depth] 2n
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-dash" \{\
+. ds doc-list-type-stack\n[doc-list-depth] dash-list
+. nr doc-list-indent-stack\n[doc-list-depth] 2n
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-hyphen" \{\
+. ds doc-list-type-stack\n[doc-list-depth] dash-list
+. nr doc-list-indent-stack\n[doc-list-depth] 2n
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-inset" \{\
+. ds doc-list-type-stack\n[doc-list-depth] inset-list
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-diag" \{\
+. ds doc-list-type-stack\n[doc-list-depth] diag-list
+. \}
+. el \{ .ie "\$1"-ohang" \{\
+. ds doc-list-type-stack\n[doc-list-depth] ohang-list
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. el \{ .ie "\$1"-column" \{\
+. ds doc-list-type-stack\n[doc-list-depth] column-list
+. linetabs 1
+. \}
+. el \{\
+. tm1 "mdoc warning: Unknown list type `\$1' (or missing list type)
+. tm1 " in .Bl request
+. tm
+. nr doc-arg-ptr 0
+. \}\}\}\}\}\}\}\}\}\}\}
+.
+. \" we have seen a list type
+. if !\n[doc-arg-ptr] \{\
+. doc-Bl-usage
+. doc-reset-args
+. nr doc-list-depth -1
+. return
+. \}
+.
+. shift
+.
+. \" fill argument vector
+. nr doc-reg-Bl 1
+. while (\n[doc-reg-Bl] <= \n[.$]) \{\
+. ds doc-arg\n[doc-reg-Bl] "\$[\n[doc-reg-Bl]]
+. nr doc-reg-Bl +1
+. \}
+.
+. doc-increment-list-stack
+.
+. if \n[.$] \{\
+. nr doc-arg-limit \n[.$]
+. nr doc-arg-ptr 0
+. doc-do-Bl-args
+.
+. in +\n[doc-list-offset-stack\n[doc-list-depth]]u
+.
+. \" initialize column list
+. if "\*[doc-list-type-stack\n[doc-list-depth]]"column-list" \{\
+. doc-set-column-tab \n[doc-num-columns]
+' in -\n[doc-column-indent-width]u
+. if !\n[doc-compact-list-stack\n[doc-list-depth]] \
+. sp \n[doc-display-vertical]u
+.
+. nf
+. nr doc-num-columns 0
+. \}\}
+.
+. doc-reset-args
+..
+.
+.
+.\" NS doc-Bl-usage macro
+.
+.de doc-Bl-usage
+. tm1 "Usage: .Bl {-hang | -ohang | -tag | -diag | -inset}
+. tm1 " [-width <string>] [-xwidth <command>]
+. tm1 " [-offset <string>] [-compact]
+. tm1 " .Bl -column [-offset <string>] <string1> <string2> ...
+. tm1 " .Bl {-item | -enum [-nested] | -bullet | -hyphen | -dash}
+. tm1 " [-offset <string>] [-compact] (#\n[.c])
+..
+.
+.
+.\" NS doc-do-Bl-args macro
+.\" NS resolve remaining .Bl arguments
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-compact-list-stackXXX
+.\" NS doc-list-indent-stackXXX
+.\" NS doc-list-offset-stackXXX
+.\" NS doc-num-columns
+.\" NS doc-tag-prefix-stackXXX
+.\" NS doc-tag-width-stackXXX
+.\" NS
+.\" NS local variables:
+.\" NS doc-box-dBla
+.\" NS doc-env-dBla
+.\" NS doc-reg-dBla
+.\" NS doc-reg-dBla1
+.\" NS doc-reg-dBla2
+.\" NS doc-reg-dBla3
+.\" NS doc-reg-dBla4
+.\" NS doc-str-dBla
+.\" NS doc-str-dBla1
+.
+.de doc-do-Bl-args
+. nr doc-arg-ptr +1
+.
+. if (\n[doc-arg-limit] < \n[doc-arg-ptr]) \
+. return
+.
+. \" avoid a warning message in case e.g. `-offset' has no parameter
+. nr doc-reg-dBla (\n[doc-arg-ptr] + 1)
+. if !d doc-arg\n[doc-reg-dBla] \
+. ds doc-arg\n[doc-reg-dBla]
+.
+. nr doc-reg-dBla 1
+.
+. ie "\*[doc-arg\n[doc-arg-ptr]]"-compact" \
+. nr doc-compact-list-stack\n[doc-list-depth] 1
+.
+. el \{ .ie "\*[doc-arg\n[doc-arg-ptr]]"-nested" \{\
+. ie (\n[doc-list-depth] > 1) \{\
+. nr doc-reg-dBla1 (\n[doc-list-depth] - 1)
+. ds doc-tag-prefix-stack\n[doc-list-depth] "\*[doc-tag-prefix-stack\n[doc-reg-dBla1]]
+. as doc-tag-prefix-stack\n[doc-list-depth] \n[doc-enum-list-count-stack\n[doc-reg-dBla1]].
+. length doc-reg-dBla1 "\*[doc-tag-prefix-stack\n[doc-list-depth]]
+. nr doc-list-indent-stack\n[doc-list-depth] +\n[doc-reg-dBla1]n
+. \}
+. el \
+. tm mdoc warning: `-nested' allowed with nested .Bl requests only (#\n[.c])
+. \}
+.
+. el \{ .ie "\*[doc-arg\n[doc-arg-ptr]]"-width" \{\
+. nr doc-arg-ptr +1
+. ds doc-tag-width-stack\n[doc-list-depth] TagwidtH
+. ds doc-str-dBla "\*[doc-arg\n[doc-arg-ptr]]
+.
+. \" test whether argument is a valid numeric expression
+. nr doc-reg-dBla1 0
+. if \B(\*[doc-str-dBla]) \{\
+. \" disable warnings related to scaling indicators (32)
+. nr doc-reg-dBla2 \n[.warn]
+. warn (\n[.warn] - (\n[.warn] / 32 % 2 * 32))
+.
+. \" values without a scaling indicator are taken as strings;
+. \" we test whether the parameter string with and without the last
+. \" character yields identical numerical results (ignoring the
+. \" scaling indicator)
+. ds doc-str-dBla1 "\*[doc-str-dBla]
+. substring doc-str-dBla1 1 -1
+. if \B(\*[doc-str-dBla1]) \{\
+. nr doc-reg-dBla3 (;(\*[doc-str-dBla]))
+. nr doc-reg-dBla4 (\*[doc-str-dBla1])
+. if (\n[doc-reg-dBla3] == \n[doc-reg-dBla4]) \
+. nr doc-reg-dBla1 1
+. \}
+.
+. \" enable all warnings again
+. warn \n[doc-reg-dBla2]
+. \}
+.
+. ie \n[doc-reg-dBla1] \
+. nr doc-list-indent-stack\n[doc-list-depth] (\*[doc-str-dBla])
+. el \{\
+. doc-get-arg-width \n[doc-arg-ptr]
+. ie (\n[doc-width] == 2) \{\
+. \" if the width parameter is a macro, use the macro's
+. \" width as specified in doc-common
+. doc-get-arg-type \*[doc-str-dBla]
+. ie (\n[doc-arg-type] == 1) \
+. nr doc-list-indent-stack\n[doc-list-depth] \n[\*[doc-str-dBla]]
+. el \
+. nr doc-list-indent-stack\n[doc-list-depth] (\n[doc-width]u * \n[doc-fixed-width]u)
+. \}
+. el \
+. nr doc-list-indent-stack\n[doc-list-depth] (\n[doc-width]u * \n[doc-fixed-width]u)
+. \}\}
+.
+. el \{ .ie "\*[doc-arg\n[doc-arg-ptr]]"-xwidth" \{\
+. nr doc-arg-ptr +1
+. ds doc-tag-width-stack\n[doc-list-depth] TagwidtH
+.
+. ds doc-str-dBla \*[doc-arg\n[doc-arg-ptr]]
+. substring doc-str-dBla 1 2
+. if .\*[doc-str-dBla] \{\
+. \" execute string in a box to get the width of the diversion
+. ds doc-str-dBla \*[doc-arg\n[doc-arg-ptr]]
+. doc-save-global-vars
+. doc-reset-args
+. box doc-box-dBla
+. ev doc-env-dBla
+. evc 0
+. in 0
+. nf
+. nop \*[doc-str-dBla]
+. br
+. ev
+. box
+. doc-restore-global-vars
+. doc-get-width \h'\n[dl]u'
+. \}
+. nr doc-list-indent-stack\n[doc-list-depth] (\n[doc-width]u * \n[doc-fixed-width]u)
+. \}
+.
+. el \{ .ie "\*[doc-arg\n[doc-arg-ptr]]"-offset" \{\
+. nr doc-arg-ptr +1
+.
+. ie "\*[doc-arg\n[doc-arg-ptr]]"indent" \
+. nr doc-list-offset-stack\n[doc-list-depth] \n[doc-display-indent]u
+. el \{\
+. ds doc-str-dBla "\*[doc-arg\n[doc-arg-ptr]]
+. nr doc-reg-dBla1 0
+. if \B(\*[doc-str-dBla]) \{\
+. nr doc-reg-dBla2 \n[.warn]
+. warn (\n[.warn] - (\n[.warn] / 32 % 2 * 32))
+.
+. ds doc-str-dBla1 "\*[doc-str-dBla]
+. substring doc-str-dBla1 1 -1
+. if \B(\*[doc-str-dBla1]) \{\
+. nr doc-reg-dBla3 (;(\*[doc-str-dBla]))
+. nr doc-reg-dBla4 (\*[doc-str-dBla1])
+. if (\n[doc-reg-dBla3] == \n[doc-reg-dBla4]) \
+. nr doc-reg-dBla1 1
+. \}
+.
+. warn \n[doc-reg-dBla2]
+. \}
+.
+. ie \n[doc-reg-dBla1] \
+. nr doc-list-offset-stack\n[doc-list-depth] \*[doc-str-dBla]
+. el \{\
+. doc-get-arg-width \n[doc-arg-ptr]
+. ie (\n[doc-width] <= 3) \{\
+. \" if the offset parameter is a macro, use the macro's
+. \" width as specified in doc-common
+. doc-get-arg-type \*[doc-str-dBla]
+. ie (\n[doc-arg-type] == 1) \
+. nr doc-list-offset-stack\n[doc-list-depth] \n[\*[doc-str-dBla]]
+. el \
+. nr doc-list-offset-stack\n[doc-list-depth] (\n[doc-width]u * \n[doc-fixed-width]u)
+. \}
+. el \
+. nr doc-list-offset-stack\n[doc-list-depth] (\n[doc-width]u * \n[doc-fixed-width]u)
+. \}\}\}
+. el \
+. nr doc-reg-dBla 0
+. \}\}\}\}
+.
+. \" not a known keyword, so it specifies the width of the next column
+. \" (if it is a column list)
+. if !\n[doc-reg-dBla] \{\
+. ie "\*[doc-list-type-stack\n[doc-list-depth]]"column-list" \{\
+. nr doc-num-columns +1
+. ds doc-arg\n[doc-num-columns] "\*[doc-arg\n[doc-arg-ptr]]
+. \}
+. el \{\
+. tmc mdoc warning: Unknown keyword `\*[doc-arg\n[doc-arg-ptr]]'
+. tm1 " in .Bl request (#\n[.c])
+. \}\}
+.
+. if (\n[doc-arg-limit] > \n[doc-arg-ptr]) \
+. doc-do-Bl-args
+..
+.
+.
+.\" NS doc-save-global-vars macro
+.\" NS save all global variables
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dsgv
+.
+.de doc-save-global-vars
+. ds doc-macro-name-saved "\*[doc-macro-name]
+. nr doc-arg-limit-saved \n[doc-arg-limit]
+. nr doc-num-args-saved \n[doc-num-args]
+. nr doc-arg-ptr-saved \n[doc-arg-ptr]
+.
+. nr doc-reg-dsgv 1
+. while (\n[doc-reg-dsgv] <= \n[doc-arg-limit]) \{\
+. ds doc-arg\n[doc-reg-dsgv]-saved "\*[doc-arg\n[doc-reg-dsgv]]
+. nr doc-type\n[doc-reg-dsgv]-saved \n[doc-type\n[doc-reg-dsgv]]
+. ds doc-space\n[doc-reg-dsgv]-saved "\*[doc-space\n[doc-reg-dsgv]]
+. nr doc-reg-dsgv +1
+. \}
+.
+. nr doc-curr-font-saved \n[doc-curr-font]
+. nr doc-curr-size-saved \n[doc-curr-size]
+. nr doc-in-synopsis-section-saved \n[doc-in-synopsis-section]
+. nr doc-indent-synopsis-saved \n[doc-indent-synopsis]
+. nr doc-indent-synopsis-active-saved \n[doc-indent-synopsis-active]
+. nr doc-have-decl-saved \n[doc-have-decl]
+. nr doc-have-var-saved \n[doc-have-var]
+. ds doc-command-name-saved "\*[doc-command-name]
+. ds doc-quote-left-saved "\*[doc-quote-left]
+. ds doc-quote-right-saved "\*[doc-quote-right]
+. nr doc-nesting-level-saved \n[doc-nesting-level]
+. nr doc-in-list-saved \n[doc-in-list]
+. ds doc-space-saved "\*[doc-space]
+. ds doc-saved-space-saved "\*[doc-saved-space]
+. nr doc-space-mode-saved \n[doc-space-mode]
+. nr doc-have-space-saved \n[doc-have-space]
+. nr doc-have-slot-saved \n[doc-have-slot]
+. nr doc-keep-type-saved \n[doc-keep-type]
+. nr doc-display-depth-saved \n[doc-display-depth]
+. nr doc-is-compact-saved \n[doc-is-compact]
+.
+. nr doc-reg-dsgv 0
+. while (\n[doc-reg-dsgv] <= \n[doc-display-depth]) \{\
+. ds doc-display-type-stack\n[doc-reg-dsgv]-saved "\*[doc-display-type-stack\n[doc-reg-dsgv]]
+. nr doc-display-indent-stack\n[doc-reg-dsgv]-saved \n[doc-display-indent-stack\n[doc-reg-dsgv]]
+. nr doc-display-ad-stack\n[doc-reg-dsgv]-saved \n[doc-display-ad-stack\n[doc-reg-dsgv]]
+. nr doc-display-fi-stack\n[doc-reg-dsgv]-saved \n[doc-display-fi-stack\n[doc-reg-dsgv]]
+. nr doc-reg-dsgv +1
+. \}
+.
+. nr doc-fontmode-depth-saved \n[doc-fontmode-depth]
+.
+. nr doc-reg-dsgv 1
+. while (\n[doc-reg-dsgv] <= \n[doc-fontmode-depth]) \{\
+. nr doc-fontmode-font-stack\n[doc-reg-dsgv]-saved \n[doc-fontmode-font-stack\n[doc-reg-dsgv]]
+. nr doc-fontmode-size-stack\n[doc-reg-dsgv]-saved \n[doc-fontmode-size-stack\n[doc-reg-dsgv]]
+. nr doc-reg-dsgv +1
+. \}
+.
+. nr doc-list-depth-saved \n[doc-list-depth]
+.
+. nr doc-reg-dsgv 1
+. while (\n[doc-reg-dsgv] <= \n[doc-list-depth]) \{\
+. ds doc-list-type-stack\n[doc-reg-dsgv]-saved "\*[doc-list-type-stack\n[doc-reg-dsgv]]
+. nr doc-list-have-indent-stack\n[doc-reg-dsgv]-saved \n[doc-list-have-indent-stack\n[doc-reg-dsgv]]
+. nr doc-list-indent-stack\n[doc-reg-dsgv]-saved \n[doc-list-indent-stack\n[doc-reg-dsgv]]
+. nr doc-compact-list-stack\n[doc-reg-dsgv]-saved \n[doc-compact-list-stack\n[doc-reg-dsgv]]
+. ds doc-tag-prefix-stack\n[doc-reg-dsgv]-saved "\*[doc-tag-prefix-stack\n[doc-reg-dsgv]]
+. ds doc-tag-width-stack\n[doc-reg-dsgv]-saved "\*[doc-tag-width-stack\n[doc-reg-dsgv]]
+. nr doc-list-offset-stack\n[doc-reg-dsgv]-saved \n[doc-list-offset-stack\n[doc-reg-dsgv]]
+. nr doc-enum-list-count-stack\n[doc-reg-dsgv]-saved \n[doc-enum-list-count-stack\n[doc-reg-dsgv]]
+. nr doc-reg-dsgv +1
+. \}
+.
+. ds doc-saved-Pa-font-saved "\*[doc-saved-Pa-font]
+. nr doc-curr-type-saved \n[doc-curr-type]
+. ds doc-curr-arg-saved "\*[doc-curr-arg]
+. nr doc-diag-list-input-line-count-saved \n[doc-diag-list-input-line-count]
+. nr doc-num-columns-saved \n[doc-num-columns]
+. nr doc-column-indent-width-saved \n[doc-column-indent-width]
+. nr doc-is-func-saved \n[doc-is-func]
+. nr doc-have-old-func-saved \n[doc-have-old-func]
+. nr doc-func-arg-count-saved \n[doc-func-arg-count]
+. ds doc-func-arg-saved "\*[doc-func-arg]
+. nr doc-num-func-args-saved \n[doc-num-func-args]
+. nr doc-func-args-processed-saved \n[doc-func-args-processed]
+. nr doc-have-func-saved \n[doc-have-func]
+. nr doc-is-reference-saved \n[doc-is-reference]
+. nr doc-reference-count-saved \n[doc-reference-count]
+. nr doc-author-count-saved \n[doc-author-count]
+.
+. nr doc-reg-dsgv 0
+. while (\n[doc-reg-dsgv] <= \n[doc-author-count]) \{\
+. ds doc-author-name\n[doc-reg-dsgv]-saved "\*[doc-author-name\n[doc-reg-dsgv]]
+. nr doc-reg-dsgv +1
+. \}
+.
+. nr doc-book-count-saved \n[doc-book-count]
+. ds doc-book-name-saved "\*[doc-book-name]
+. nr doc-date-count-saved \n[doc-date-count]
+. ds doc-date-saved "\*[doc-date]
+. nr doc-publisher-count-saved \n[doc-publisher-count]
+. ds doc-publisher-name-saved "\*[doc-publisher-name]
+. nr doc-journal-count-saved \n[doc-journal-count]
+. ds doc-journal-name-saved "\*[doc-journal-name]
+. nr doc-issue-count-saved \n[doc-issue-count]
+. ds doc-issue-name-saved "\*[doc-issue-name]
+. nr doc-optional-count-saved \n[doc-optional-count]
+. ds doc-optional-string-saved "\*[doc-optional-string]
+. nr doc-page-number-count-saved \n[doc-page-number-count]
+. ds doc-page-number-string-saved "\*[doc-page-number-string]
+. nr doc-corporate-count-saved \n[doc-corporate-count]
+. ds doc-corporate-name-saved "\*[doc-corporate-name]
+. nr doc-report-count-saved \n[doc-report-count]
+. ds doc-report-name-saved "\*[doc-report-name]
+. nr doc-reference-title-count-saved \n[doc-reference-title-count]
+. ds doc-reference-title-name-saved "\*[doc-reference-title-name]
+. ds doc-reference-title-name-for-book-saved "\*[doc-reference-title-name-for-book]
+. nr doc-volume-count-saved \n[doc-volume-count]
+. ds doc-volume-name-saved "\*[doc-volume-name]
+. nr doc-have-author-saved \n[doc-have-author]
+.
+. ds doc-document-title-saved "\*[doc-document-title]
+. ds doc-volume-saved "\*[doc-volume]
+. ds doc-section-saved "\*[doc-section]
+. ds doc-operating-system-saved "\*[doc-operating-system]
+. ds doc-date-string-saved "\*[doc-date-string]
+. nr doc-header-space-saved \n[doc-header-space]
+. nr doc-footer-space-saved \n[doc-footer-space]
+. nr doc-display-vertical-saved \n[doc-display-vertical]
+. ds doc-header-string-saved "\*[doc-header-string]
+. nr doc-in-see-also-section-saved \n[doc-in-see-also-section]
+. nr doc-in-files-section-saved \n[doc-in-files-section]
+. nr doc-in-authors-section-saved \n[doc-in-authors-section]
+..
+.
+.
+.\" NS doc-restore-global-vars macro
+.\" NS restore all global variables
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-drgv
+.
+.de doc-restore-global-vars
+. ds doc-macro-name "\*[doc-macro-name-saved]
+. nr doc-arg-limit \n[doc-arg-limit-saved]
+. nr doc-num-args \n[doc-num-args-saved]
+. nr doc-arg-ptr \n[doc-arg-ptr-saved]
+.
+. nr doc-reg-drgv 1
+. while (\n[doc-reg-drgv] <= \n[doc-arg-limit]) \{\
+. ds doc-arg\n[doc-reg-drgv] "\*[doc-arg\n[doc-reg-drgv]-saved]
+. nr doc-type\n[doc-reg-drgv] \n[doc-type\n[doc-reg-drgv]-saved]
+. ds doc-space\n[doc-reg-drgv] "\*[doc-space\n[doc-reg-drgv]-saved]
+. nr doc-reg-drgv +1
+. \}
+.
+. nr doc-curr-font \n[doc-curr-font-saved]
+. nr doc-curr-size \n[doc-curr-size-saved]
+. nr doc-in-synopsis-section \n[doc-in-synopsis-section-saved]
+. nr doc-indent-synopsis \n[doc-indent-synopsis-saved]
+. nr doc-indent-synopsis-active \n[doc-indent-synopsis-active-saved]
+. nr doc-have-decl \n[doc-have-decl-saved]
+. nr doc-have-var \n[doc-have-var-saved]
+. ds doc-command-name "\*[doc-command-name-saved]
+. ds doc-quote-left "\*[doc-quote-left-saved]
+. ds doc-quote-right "\*[doc-quote-right-saved]
+. nr doc-nesting-level \n[doc-nesting-level-saved]
+. nr doc-in-list \n[doc-in-list-saved]
+. ds doc-space "\*[doc-space-saved]
+. ds doc-saved-space "\*[doc-saved-space-saved]
+. nr doc-space-mode \n[doc-space-mode-saved]
+. nr doc-have-space \n[doc-have-space-saved]
+. nr doc-have-slot \n[doc-have-slot-saved]
+. nr doc-keep-type \n[doc-keep-type-saved]
+. nr doc-display-depth \n[doc-display-depth-saved]
+. nr doc-is-compact \n[doc-is-compact-saved]
+.
+. nr doc-reg-drgv 0
+. while (\n[doc-reg-drgv] <= \n[doc-display-depth]) \{\
+. ds doc-display-type-stack\n[doc-reg-drgv] "\*[doc-display-type-stack\n[doc-reg-drgv]-saved]
+. nr doc-display-indent-stack\n[doc-reg-drgv] \n[doc-display-indent-stack\n[doc-reg-drgv]-saved]
+. nr doc-display-ad-stack\n[doc-reg-drgv] \n[doc-display-ad-stack\n[doc-reg-drgv]-saved]
+. nr doc-display-fi-stack\n[doc-reg-drgv] \n[doc-display-fi-stack\n[doc-reg-drgv]-saved]
+. nr doc-reg-drgv +1
+. \}
+.
+. nr doc-fontmode-depth \n[doc-fontmode-depth-saved]
+.
+. nr doc-reg-drgv 1
+. while (\n[doc-reg-drgv] <= \n[doc-fontmode-depth]) \{\
+. nr doc-fontmode-font-stack\n[doc-reg-drgv] \n[doc-fontmode-font-stack\n[doc-reg-drgv]]-saved
+. nr doc-fontmode-size-stack\n[doc-reg-drgv] \n[doc-fontmode-size-stack\n[doc-reg-drgv]]-saved
+. nr doc-reg-drgv +1
+. \}
+.
+. nr doc-list-depth \n[doc-list-depth-saved]
+.
+. nr doc-reg-drgv 1
+. while (\n[doc-reg-drgv] <= \n[doc-list-depth]) \{\
+. ds doc-list-type-stack\n[doc-reg-drgv] "\*[doc-list-type-stack\n[doc-reg-drgv]-saved]
+. nr doc-list-have-indent-stack\n[doc-reg-drgv] \n[doc-list-have-indent-stack\n[doc-reg-drgv]-saved]
+. nr doc-list-indent-stack\n[doc-reg-drgv] \n[doc-list-indent-stack\n[doc-reg-drgv]-saved]
+. nr doc-compact-list-stack\n[doc-reg-drgv] \n[doc-compact-list-stack\n[doc-reg-drgv]-saved]
+. ds doc-tag-prefix-stack\n[doc-reg-drgv] "\*[doc-tag-prefix-stack\n[doc-reg-drgv]-saved]
+. ds doc-tag-width-stack\n[doc-reg-drgv] "\*[doc-tag-width-stack\n[doc-reg-drgv]-saved]
+. nr doc-list-offset-stack\n[doc-reg-drgv] \n[doc-list-offset-stack\n[doc-reg-drgv]-saved]
+. nr doc-enum-list-count-stack\n[doc-reg-drgv] \n[doc-enum-list-count-stack\n[doc-reg-drgv]-saved]
+. nr doc-reg-drgv +1
+. \}
+.
+. ds doc-saved-Pa-font "\*[doc-saved-Pa-font-saved]
+. nr doc-curr-type \n[doc-curr-type-saved]
+. ds doc-curr-arg "\*[doc-curr-arg-saved]
+. nr doc-diag-list-input-line-count \n[doc-diag-list-input-line-count-saved]
+. nr doc-num-columns \n[doc-num-columns-saved]
+. nr doc-column-indent-width \n[doc-column-indent-width-saved]
+. nr doc-is-func \n[doc-is-func-saved]
+. nr doc-have-old-func \n[doc-have-old-func-saved]
+. nr doc-func-arg-count \n[doc-func-arg-count-saved]
+. ds doc-func-arg "\*[doc-func-arg-saved]
+. nr doc-num-func-args \n[doc-num-func-args-saved]
+. nr doc-func-args-processed \n[doc-func-args-processed-saved]
+. nr doc-have-func \n[doc-have-func-saved]
+. nr doc-is-reference \n[doc-is-reference-saved]
+. nr doc-reference-count \n[doc-reference-count-saved]
+. nr doc-author-count \n[doc-author-count-saved]
+.
+. nr doc-reg-drgv 0
+. while (\n[doc-reg-drgv] <= \n[doc-author-count]) \{\
+. ds doc-author-name\n[doc-reg-drgv] "\*[doc-author-name\n[doc-reg-drgv]-saved]
+. nr doc-reg-drgv +1
+. \}
+.
+. nr doc-book-count \n[doc-book-count-saved]
+. ds doc-book-name "\*[doc-book-name-saved]
+. nr doc-date-count \n[doc-date-count-saved]
+. ds doc-date "\*[doc-date-saved]
+. nr doc-publisher-count \n[doc-publisher-count-saved]
+. ds doc-publisher-name "\*[doc-publisher-name-saved]
+. nr doc-journal-count \n[doc-journal-count-saved]
+. ds doc-journal-name "\*[doc-journal-name-saved]
+. nr doc-issue-count \n[doc-issue-count-saved]
+. ds doc-issue-name "\*[doc-issue-name-saved]
+. nr doc-optional-count \n[doc-optional-count-saved]
+. ds doc-optional-string "\*[doc-optional-string-saved]
+. nr doc-page-number-count \n[doc-page-number-count-saved]
+. ds doc-page-number-string "\*[doc-page-number-string-saved]
+. nr doc-corporate-count \n[doc-corporate-count-saved]
+. ds doc-corporate-name "\*[doc-corporate-name-saved]
+. nr doc-report-count \n[doc-report-count-saved]
+. ds doc-report-name "\*[doc-report-name-saved]
+. nr doc-reference-title-count \n[doc-reference-title-count-saved]
+. ds doc-reference-title-name "\*[doc-reference-title-name-saved]
+. ds doc-reference-title-name-for-book "\*[doc-reference-title-name-for-book-saved]
+. nr doc-volume-count \n[doc-volume-count-saved]
+. ds doc-volume-name "\*[doc-volume-name-saved]
+. nr doc-have-author \n[doc-have-author-saved]
+.
+. ds doc-document-title "\*[doc-document-title-saved]
+. ds doc-volume "\*[doc-volume-saved]
+. ds doc-section "\*[doc-section-saved]
+. ds doc-operating-system "\*[doc-operating-system-saved]
+. ds doc-date-string "\*[doc-date-string-saved]
+. nr doc-header-space \n[doc-header-space-saved]
+. nr doc-footer-space \n[doc-footer-space-saved]
+. nr doc-display-vertical \n[doc-display-vertical-saved]
+. ds doc-header-string "\*[doc-header-string-saved]
+. nr doc-in-see-also-section \n[doc-in-see-also-section-saved]
+. nr doc-in-files-section \n[doc-in-files-section-saved]
+. nr doc-in-authors-section \n[doc-in-authors-section-saved]
+..
+.
+.
+.\" NS El user macro
+.\" NS end list
+.\" NS
+.\" NS modifies:
+.\" NS doc-list-depth
+.\" NS doc-macro-name
+.\" NS
+.\" NS local variables:
+.\" NS doc-str-El
+.\" NS
+.\" NS width register `El' set in doc-common
+.
+.de El
+. if \n[.$] \{\
+. tm Usage: .El (does not take arguments) (#\n[.c])
+. return
+. \}
+.
+. ds doc-macro-name El
+. ds doc-str-El \*[doc-list-type-stack\n[doc-list-depth]]
+.
+. ie "\*[doc-str-El]"diag-list" \
+. doc-end-list 0
+. el \{ .ie "\*[doc-str-El]"column-list" \
+. doc-end-column-list
+. el \{ .ie "\*[doc-str-El]"item-list" \
+. doc-end-list 0
+. el \{ .ie "\*[doc-str-El]"ohang-list" \
+. doc-end-list 0
+. el \{ .ie "\*[doc-str-El]"inset-list" \
+. doc-end-list 0
+. el \
+. doc-end-list 1
+. \}\}\}\}
+.
+. br
+..
+.
+.
+.\" NS doc-saved-Pa-font global string
+.\" NS saved doc-Pa-font string for section FILES (no underline if
+.\" NS nroff)
+.
+.ds doc-saved-Pa-font
+.
+.
+.\" NS doc-curr-type global register
+.\" NS current argument type
+.
+.nr doc-curr-type 0
+.
+.
+.\" NS doc-curr-arg global string
+.\" NS current argument
+.
+.ds doc-curr-arg
+.
+.
+.\" NS doc-item-boxXXX global box
+.\" NS item boxes associated list depth
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.
+.\" NS It user macro
+.\" NS list item
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-curr-arg
+.\" NS doc-curr-type
+.\" NS doc-in-list
+.\" NS doc-macro-name
+.\" NS doc-num-args
+.\" NS doc-saved-Pa-font
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-It
+.\" NS doc-str-It
+.\" NS doc-XXX-list-type
+.\" NS
+.\" NS width register `It' set in doc-common
+.
+.nr doc-bullet-list-type 1
+.nr doc-column-list-type 0
+.nr doc-dash-list-type 1
+.nr doc-diag-list-type 0
+.nr doc-enum-list-type 1
+.nr doc-hang-list-type 2
+.nr doc-inset-list-type 2
+.nr doc-item-list-type 1
+.nr doc-ohang-list-type 2
+.nr doc-tag-list-type 2
+.
+.de It
+. ds doc-str-It \*[doc-list-type-stack\n[doc-list-depth]]
+.
+. if "\*[doc-str-It]"" \
+. tm mdoc error: .It without preceding .Bl (#\n[.c])
+.
+. if \n[doc-nesting-level] \{\
+. tmc "mdoc error: .It found in enclosing (e.g. .Ac ... .It ... .Ao)
+. tm1 " (#\n[.c])
+. \}
+.
+. br
+. if !\n[cR] \
+. ne 3v
+.
+. if \n[.$] \{\
+. ds doc-macro-name It
+.
+. \" fill argument vector
+. nr doc-reg-It 1
+. while (\n[doc-reg-It] <= \n[.$]) \{\
+. ds doc-arg\n[doc-reg-It] "\$[\n[doc-reg-It]]
+. nr doc-reg-It +1
+. \}
+.
+. nr doc-num-args \n[.$]
+. nr doc-arg-ptr 0
+. \}
+.
+. nr doc-reg-It \n[doc-\*[doc-str-It]-type]
+.
+. if \n[doc-reg-It] \{\
+. \" start item box
+. box doc-item-box\n[doc-list-depth]
+. ev doc-item-env\n[doc-list-depth]
+. evc 0
+. in 0
+. nf
+. \}
+.
+. ie (\n[doc-reg-It] == 1) \{\
+. if \n[.$] \{\
+. tm1 "mdoc warning: .It requests in lists of type `\*[doc-str-It]'
+. tm1 " don't take arguments (#\n[.c])
+. \}\}
+. el \{\
+. ie \n[.$] \{\
+. if (\n[doc-reg-It] == 2) \{\
+. \" handle list types with arguments
+. doc-parse-arg-vector
+.
+. nr doc-in-list 1
+. nr doc-arg-ptr 1
+. nr doc-curr-type \n[doc-type1]
+. ds doc-curr-arg "\*[doc-arg1]
+.
+. if \n[doc-in-files-section] \{\
+. ds doc-saved-Pa-font "\*[doc-Pa-font]
+. if n \
+. ds doc-Pa-font "\*[doc-No-font]
+. \}
+.
+. ie (\n[doc-type1] == 1) \
+. \*[doc-arg1]
+. el \{\
+. nr doc-arg-ptr 1
+. doc-print-recursive
+. \}\}\}
+. el \{\
+. tm1 "mdoc warning: .It requests in lists of type `\*[doc-str-It]'
+. tm1 " require arguments (#\n[.c])
+. \}
+. \}
+.
+. \" the previous call of `.doc-print-recursive' can contain calls to
+. \" opening requests like `.Ao'; we then defer the call of `doc-xxx-list'
+. if !\n[doc-nesting-level] \
+. doc-\*[doc-str-It]
+..
+.
+.
+.\" NS doc-inset-list macro
+.\" NS .It item of list-type inset
+.\" NS
+.\" NS modifies:
+.\" NS doc-in-list
+.
+.de doc-inset-list
+. \" finish item box
+. br
+. ev
+. box
+. unformat doc-item-box\n[doc-list-depth]
+.
+. doc-set-vertical-and-indent 0
+. br
+.
+. nh
+. doc-item-box\n[doc-list-depth]
+.
+. nr doc-in-list 0
+. doc-reset-args
+..
+.
+.
+.\" NS doc-hang-list macro
+.\" NS .It item of list-type hanging tag (as opposed to tagged)
+.\" NS
+.\" NS modifies:
+.\" NS doc-have-space
+.\" NS doc-in-list
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dhl
+.\" NS doc-reg-dhl1
+.
+.de doc-hang-list
+. \" finish item box
+. br
+. ev
+. box
+. unformat doc-item-box\n[doc-list-depth]
+.
+. doc-set-vertical-and-indent 1
+. nr doc-reg-dhl (\n[doc-list-indent-stack\n[doc-list-depth]]u + \n[doc-digit-width]u)
+. ti -\n[doc-reg-dhl]u
+.
+. nh
+. ie (\n[dl]u > \n[doc-list-indent-stack\n[doc-list-depth]]u) \
+. doc-item-box\n[doc-list-depth]
+. el \{\
+. chop doc-item-box\n[doc-list-depth]
+. nr doc-reg-dhl1 \n[.k]u
+. nop \*[doc-item-box\n[doc-list-depth]]\c
+. nop \h'|(\n[doc-reg-dhl1]u - \n[.k]u + \n[doc-reg-dhl]u)'\c
+. nr doc-have-space 1
+. \}
+.
+. nr doc-in-list 0
+. doc-reset-args
+..
+.
+.
+.\" NS doc-ohang-list macro
+.\" NS .It item of list-type overhanging tag
+.\" NS
+.\" NS modifies:
+.\" NS doc-in-list
+.
+.de doc-ohang-list
+. \" finish item box
+. br
+. ev
+. box
+. unformat doc-item-box\n[doc-list-depth]
+.
+. doc-set-vertical-and-indent 0
+. nh
+. doc-item-box\n[doc-list-depth]
+. br
+.
+. nr doc-in-list 0
+. doc-reset-args
+..
+.
+.
+.\" NS doc-item-list macro
+.\" NS .It item of list-type [empty tag]
+.
+.de doc-item-list
+. \" finish (dummy) item box
+. br
+. ev
+. box
+.
+. doc-set-vertical-and-indent 0
+. br
+.
+. doc-reset-args
+..
+.
+.
+.\" NS doc-enum-list-count-stackXXX global register
+.\" NS stack of current enum count values
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.nr doc-enum-list-count-stack1 0
+.
+.
+.\" NS doc-enum-list macro
+.\" NS enumerated list
+.\" NS
+.\" NS modifies:
+.\" NS doc-enum-list-count-stackXXX
+.\" NS doc-in-list
+.
+.de doc-enum-list
+. nr doc-in-list 1
+. nr doc-enum-list-count-stack\n[doc-list-depth] +1
+\# XXX
+\#.ll \n[doc-list-indent-stack\n[doc-list-depth]]u
+\#.rj
+. nop \*[doc-tag-prefix-stack\n[doc-list-depth]]\c
+. nop \n[doc-enum-list-count-stack\n[doc-list-depth]].\&
+. doc-do-list
+..
+.
+.
+.\" NS doc-bullet-list macro
+.\" NS bullet paragraph list
+.\" NS
+.\" NS modifies:
+.\" NS doc-in-list
+.
+.de doc-bullet-list
+. nr doc-in-list 1
+. nop \)\*[doc-Sy-font]\[bu]\f[P]
+. doc-do-list
+..
+.
+.
+.\" NS doc-dash-list macro
+.\" NS hyphen paragraph list (sub bullet list)
+.\" NS
+.\" NS modifies:
+.\" NS doc-in-list
+.
+.de doc-dash-list
+. nr doc-in-list 1
+. nop \)\*[doc-Sy-font]\-\f[P]
+. doc-do-list
+..
+.
+.
+.\" NS doc-do-list macro
+.\" NS .It item of list-type enum/bullet/hyphen
+.
+.als doc-do-list doc-hang-list
+.
+.
+.\" NS doc-diag-list-input-line-count global register
+.\" NS saved line number to be checked in next diag-list item
+.
+.nr doc-diag-list-input-line-count 0
+.
+.
+.\" NS doc-diag-list macro
+.\" NS .It item of list-type diagnostic-message
+.\" NS
+.\" NS modifies:
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-diag-list-input-line-count
+.
+.de doc-diag-list
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. ie ((\n[.c] - \n[doc-diag-list-input-line-count]) > 1) \{\
+. ie !\n[doc-compact-list-stack\n[doc-list-depth]] \
+. doc-paragraph
+. el \
+. br
+. \}
+. el \
+. br
+. nr doc-diag-list-input-line-count \n[.c]
+.
+. nh
+. nop \*[doc-Sy-font]\c
+. if \n[doc-num-args] \
+. doc-remaining-args
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\*[doc-hard-space]\c
+.
+. doc-print-and-reset
+..
+.
+.
+.\" NS doc-tag-list macro
+.\" NS .It item of list-type `tag'
+.\" NS
+.\" NS modifies:
+.\" NS doc-have-space
+.\" NS doc-in-list
+.\" NS
+.\" NS local variables:
+.\" NS doc-box-dtl
+.\" NS doc-reg-dtl
+.\" NS doc-reg-dtl1
+.
+.de doc-tag-list
+. \" finish item box
+. br
+. ev
+. box
+. unformat doc-item-box\n[doc-list-depth]
+.
+. \" we use a box without `.nf' to compute the tag width (via `dl' register)
+. box doc-box-dtl
+. ev doc-env-dtl
+. evc 0
+. fi
+. ad 0
+. in 0
+. doc-item-box\n[doc-list-depth]
+. br
+. ev
+. box
+.
+. if !"TagwidtH"\*[doc-tag-width-stack\n[doc-list-depth]]" \{\
+. if !\n[doc-list-have-indent-stack\n[doc-list-depth]] \{\
+. in -(\n[doc-list-indent-stack\n[doc-list-depth]]u + \n[doc-digit-width]u)
+. nr doc-list-have-indent-stack\n[doc-list-depth] 1
+. \}
+. doc-get-tag-width
+. \}
+. doc-set-vertical-and-indent 1
+. nr doc-reg-dtl (\n[doc-list-indent-stack\n[doc-list-depth]]u + \n[doc-digit-width]u)
+. ti -\n[doc-reg-dtl]u
+.
+. nh
+. ie (\n[dl]u > \n[doc-list-indent-stack\n[doc-list-depth]]u) \{\
+. doc-item-box\n[doc-list-depth]
+. br
+. \}
+. el \{\
+. chop doc-item-box\n[doc-list-depth]
+. nr doc-reg-dtl1 \n[.k]u
+. nop \*[doc-item-box\n[doc-list-depth]]\c
+. nop \h'|(\n[doc-reg-dtl1]u - \n[.k]u + \n[doc-reg-dtl]u)'\c
+. nr doc-have-space 1
+. \}
+.
+. if \n[doc-in-files-section] \
+. if n \
+. ds doc-Pa-font "\*[doc-saved-Pa-font]
+.
+. nr doc-in-list 0
+. doc-reset-args
+..
+.
+.
+.\" NS doc-get-tag-width macro
+.\" NS resolve unknown tag width (`tag' list-type only)
+.\" NS
+.\" NS modifies:
+.\" NS doc-list-indent-stackXXX
+.\" NS doc-tag-width-stackXXX
+.\" NS
+.\" NS requires:
+.\" NS doc-curr-arg
+.\" NS doc-curr-type
+.
+.de doc-get-tag-width
+. ie (\n[doc-curr-type] == 1) \{\
+. ds doc-tag-width-stack\n[doc-list-depth] \*[doc-curr-arg]
+. nr doc-list-indent-stack\n[doc-list-depth] \n[\*[doc-curr-arg]]
+. \}
+. el \{\
+. ds doc-tag-width-stack\n[doc-list-depth] No
+. nr doc-list-indent-stack\n[doc-list-depth] \n[No]
+. \}
+..
+.
+.
+.\" NS doc-set-vertical-and-indent macro
+.\" NS set up vertical spacing (if not compact) and indentation (with
+.\" NS offset if argument is non-zero)
+.\" NS
+.\" NS modifies:
+.\" NS doc-list-have-indent-stackXXX
+.
+.de doc-set-vertical-and-indent
+. if !\n[doc-compact-list-stack\n[doc-list-depth]] \
+. sp \n[doc-display-vertical]u
+.
+. if \n[doc-list-have-indent-stack\n[doc-list-depth]] \{\
+. nr doc-list-have-indent-stack\n[doc-list-depth] 0
+. if \$1 \
+. in +(\n[doc-list-indent-stack\n[doc-list-depth]]u + \n[doc-digit-width]u)
+. \}
+.
+. if !\n[cR] \
+. ne 2v
+..
+.
+.
+.\" NS doc-list-depth global register
+.\" NS list type stack counter
+.
+.nr doc-list-depth 0
+.
+.
+.\" NS doc-num-columns global register
+.\" NS number of columns
+.
+.nr doc-num-columns 0
+.
+.
+.\" NS doc-compact-list-stackXXX global register (bool)
+.\" NS stack of flags to indicate whether a particular list is compact
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.nr doc-compact-list-stack1 0
+.
+.
+.\" NS doc-tag-prefix-stackXXX global string
+.\" NS stack of tag prefixes (currently used for -nested -enum lists)
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.ds doc-tag-prefix-stack1
+.
+.
+.\" NS doc-tag-width-stackXXX global string
+.\" NS stack of strings indicating how to set up current element of
+.\" NS doc-list-indent-stackXXX -- if set to TagwidtH, user has set it
+.\" NS directly; if it is a macro name, use the macro's width value;
+.\" NS otherwise, `doc-get-tag-width' uses width value of `No'.
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.ds doc-tag-width-stack0
+.ds doc-tag-width-stack1
+.
+.
+.\" NS doc-list-offset-stackXXX global register
+.\" NS stack of list offsets
+.\" NS
+.\" NS limit:
+.\" NS doc-list-depth
+.
+.nr doc-list-offset-stack1 0
+.
+.
+.\" NS doc-end-list macro
+.\" NS list end function; resets indentation (and offset if argument is
+.\" NS non-zero)
+.\" NS
+.\" NS modifies:
+.\" NS doc-list-depth
+.\" NS doc-list-offset-stackXXX
+.
+.de doc-end-list
+. if \$1 \
+' in -(\n[doc-list-indent-stack\n[doc-list-depth]]u + \n[doc-digit-width]u)
+.
+' in -\n[doc-list-offset-stack\n[doc-list-depth]]u
+.
+. if (\n[doc-list-depth] <= 0) \
+. tm mdoc warning: extraneous .El call (#\n[.c])
+.
+. doc-decrement-list-stack
+. nr doc-list-depth -1
+..
+.
+.
+.\" NS doc-increment-list-stack macro
+.\" NS set up next block for list
+.\" NS
+.\" NS modifies:
+.\" NS doc-compact-list-stackXXX
+.\" NS doc-list-have-indent-stackXXX
+.\" NS doc-list-indent-stackXXX
+.\" NS doc-list-offset-stackXXX
+.\" NS doc-list-type-stackXXX
+.\" NS doc-tag-prefix-stackXXX
+.\" NS doc-tag-width-stackXXX
+.\" NS doc-enum-list-count-stackXXX
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dils
+.
+.de doc-increment-list-stack
+. nr doc-reg-dils (\n[doc-list-depth] + 1)
+. nr doc-list-have-indent-stack\n[doc-reg-dils] 0
+. nr doc-list-indent-stack\n[doc-reg-dils] 0
+. nr doc-list-offset-stack\n[doc-reg-dils] 0
+. ds doc-tag-prefix-stack\n[doc-reg-dils]
+. ds doc-tag-width-stack\n[doc-reg-dils] \*[doc-tag-width-stack\n[doc-list-depth]]
+. ds doc-list-type-stack\n[doc-reg-dils]
+. nr doc-compact-list-stack\n[doc-reg-dils] 0
+. nr doc-enum-list-count-stack\n[doc-reg-dils] 0
+..
+.
+.
+.\" NS doc-decrement-list-stack macro
+.\" NS decrement stack
+.\" NS
+.\" NS modifies:
+.\" NS doc-compact-list-stackXXX
+.\" NS doc-list-have-indent-stackXXX
+.\" NS doc-list-indent-stackXXX
+.\" NS doc-list-offset-stackXXX
+.\" NS doc-list-type-stackXXX
+.\" NS doc-tag-prefix-stackXXX
+.\" NS doc-tag-width-stackXXX
+.\" NS doc-enum-list-count-stackXXX
+.
+.de doc-decrement-list-stack
+. ds doc-list-type-stack\n[doc-list-depth]
+. nr doc-list-have-indent-stack\n[doc-list-depth] 0
+. nr doc-list-indent-stack\n[doc-list-depth] 0
+. nr doc-list-offset-stack\n[doc-list-depth] 0
+. ds doc-tag-prefix-stack\n[doc-list-depth]
+. ds doc-tag-width-stack\n[doc-list-depth]
+. nr doc-compact-list-stack\n[doc-list-depth] 0
+. nr doc-enum-list-count-stack\n[doc-list-depth] 0
+..
+.
+.
+.\" NS Xr user macro
+.\" NS cross reference (for man pages only)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-macro-name
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-Xr
+.\" NS
+.\" NS width register `Xr' set in doc-common
+.
+.de Xr
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Xr
+. doc-parse-args \$@
+. \}
+. el \
+. doc-Xr-usage
+. \}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. \" first argument must be a string
+. ie (\n[doc-type\n[doc-arg-ptr]] == 2) \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. ds doc-arg\n[doc-arg-ptr] \*[doc-Xr-font]\*[doc-arg\n[doc-arg-ptr]]\f[P]\s[0]
+.
+. if (\n[doc-arg-limit] > \n[doc-arg-ptr]) \{\
+. nr doc-reg-Xr (\n[doc-arg-ptr] + 1)
+. \" modify second argument if it is a string and
+. \" remove space inbetween
+. if (\n[doc-type\n[doc-reg-Xr]] == 2) \{\
+. ds doc-arg\n[doc-reg-Xr] \*[lp]\*[doc-arg\n[doc-reg-Xr]]\*[rp]
+. ds doc-space\n[doc-arg-ptr]
+. \}
+. \}
+. doc-print-recursive
+. \}
+. el \
+. doc-Xr-usage
+. \}
+. el \
+. doc-Xr-usage
+..
+.
+.
+.\" NS doc-Xr-usage macro
+.
+.de doc-Xr-usage
+. tm Usage: .Xr manpage_name [section#] ... (#\n[.c])
+. doc-reset-args
+..
+.
+.
+.\" NS Sx user macro
+.\" NS cross section reference
+.\" NS
+.\" NS width register `Sx' set in doc-common
+.
+.als Sx doc-generic-macro
+.ds doc-Sx-usage section_header
+.
+.
+.\" NS doc-end-column-list macro
+.\" NS column-list end-list
+.\" NS
+.\" NS modifies:
+.\" NS doc-list-depth
+.
+.de doc-end-column-list
+. linetabs 0
+' in -(\n[doc-list-offset-stack\n[doc-list-depth]]u + \n[doc-list-indent-stack\n[doc-list-depth]]u)
+. ta T .5i
+. fi
+. doc-decrement-list-stack
+. nr doc-list-depth -1
+..
+.
+.
+.\" NS doc-column-indent-width global register
+.\" NS holds the indent width for a column list
+.
+.nr doc-column-indent-width 0
+.
+.
+.\" NS doc-set-column-tab macro
+.\" NS establish tabs for list-type column: `.doc-set-column-tab num_cols'
+.\" NS
+.\" NS modifies:
+.\" NS doc-column-indent-width
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dsct
+.\" NS doc-str-dsct
+.\" NS doc-str-dsct1
+.
+.de doc-set-column-tab
+. ds doc-str-dsct
+. nr doc-reg-dsct 1
+. nr doc-column-indent-width 0
+.
+. ie (\$1 < 5) \
+. ds doc-str-dsct1 " \"
+. el \{\
+. ie (\$1 == 5) \
+. ds doc-str-dsct1 " \"
+. el \{\
+. \" XXX: this is packed abnormally close -- intercolumn width
+. \" should be configurable
+. ds doc-str-dsct1 " \"
+. \}\}
+.
+. while (\n[doc-reg-dsct] <= \$1) \{\
+. as doc-str-dsct " +\w\*[doc-arg\n[doc-reg-dsct]]\*[doc-str-dsct1]u
+. nr doc-column-indent-width +\w\*[doc-arg\n[doc-reg-dsct]]\*[doc-str-dsct1]u
+. nr doc-reg-dsct +1
+. \}
+.
+. ta \*[doc-str-dsct]
+' in +\n[doc-column-indent-width]u
+..
+.
+.
+.\" NS doc-column-list macro
+.\" NS column items
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-list-indent-stackXXX
+.\" NS doc-spaceXXX
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dcl
+.
+.de doc-column-list
+. if \n[doc-num-args] \
+. doc-parse-arg-vector
+. nr doc-arg-ptr +1
+.
+. if (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. tm Usage: .It column_string [Ta [column_string ...] ] (#\n[.c])
+. return
+. \}
+.
+. if "\*[doc-arg\n[doc-arg-ptr]]"Ta" \{\
+. nr doc-reg-dcl (\n[doc-arg-ptr] - 1)
+. ds doc-space\n[doc-reg-dcl]
+. \}
+.
+. if !\n[doc-list-indent-stack\n[doc-list-depth]] \
+. nr doc-list-indent-stack\n[doc-list-depth] \n[doc-column-indent-width]u
+. if !\n[.u] \{\
+. fi
+' in +\n[doc-column-indent-width]u
+. \}
+. ti -\n[doc-column-indent-width]u
+.
+. doc-do-\n[doc-type\n[doc-arg-ptr]]
+..
+.
+.
+.\" NS Ta user macro
+.\" NS append tab (\t)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS
+.\" NS width register `Ta' set in doc-common
+.
+.de Ta
+. ie \n[doc-arg-limit] \{\
+. nr doc-arg-ptr +1
+. nop \*[doc-tab]\c
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \
+. doc-do-\n[doc-type\n[doc-arg-ptr]]
+. el \
+. doc-reset-args
+. \}
+. el \{\
+. tm1 "Usage: Ta must follow column entry: e.g.
+. tm1 " .It column_string [Ta [column_string ...]] (#\n[.c])
+. \}
+..
+.
+.
+.\" NS Dl user macro
+.\" NS display (one line) literal
+.\" NS
+.\" NS this function uses the `Li' font
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Dl' set in doc-common
+.
+.de Dl
+' ta T .5i
+. in +\n[doc-display-indent]u
+.
+. ie \n[doc-arg-limit] \{\
+. tm Usage: .Dl not callable by other macros (#\n[.c])
+. doc-reset-args
+. \}
+. el \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Dl
+. doc-parse-args \$@
+. nr doc-arg-ptr 1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Li-font]\c
+. doc-print-recursive
+. \}
+. el \
+. tm Usage: .Dl argument ... (#\n[.c])
+. \}
+.
+. in -\n[doc-display-indent]u
+..
+.
+.
+.\" NS D1 user macro
+.\" NS display (one line)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `D1' set in doc-common
+.
+.de D1
+' ta T .5i
+. in +\n[doc-display-indent]u
+.
+. ie \n[doc-arg-limit] \{\
+. tm Usage: .D1 not callable by other macros (#\n[.c])
+. doc-reset-args
+. \}
+. el \{\
+. ie \n[.$] \{\
+. ds doc-macro-name D1
+. doc-parse-args \$@
+. nr doc-arg-ptr 1
+. doc-print-recursive
+. \}
+. el \
+. tm Usage: .D1 argument ... (#\n[.c])
+. \}
+.
+. in -\n[doc-display-indent]u
+..
+.
+.
+.\" NS Vt user macro
+.\" NS variable type (for forcing old style variable declarations);
+.\" NS this is not done in the same manner as .Ot for fortrash --
+.\" NS clean up later
+.\" NS
+.\" NS modifies:
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-have-decl
+.\" NS doc-have-var
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Vt' set in doc-common
+.
+.de Vt
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Vt
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Vt variable_type ... (#\n[.c])
+. \}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. if (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. tm Usage: .Vt variable_type ... (#\n[.c])
+. doc-reset-args
+. return
+. \}
+.
+. if \n[doc-in-synopsis-section] \{\
+. \" if a function declaration was the last thing given,
+. \" want vertical space
+. if \n[doc-have-decl] \{\
+. doc-paragraph
+. nr doc-have-decl 0
+. \}
+.
+. \" if a subroutine was the last thing given, want vertical space
+. if \n[doc-have-func] \{\
+. ie \n[doc-have-var] \
+. br
+. el \
+. doc-paragraph
+. \}
+.
+. nr doc-have-var 1
+. \}
+.
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Ft-font]\c
+. doc-print-recursive
+.
+. if \n[doc-in-synopsis-section] \{\
+. ie \n[doc-have-old-func] \
+. nop \*[doc-soft-space]\c
+. el \
+. br
+. \}
+..
+.
+.
+.\" NS doc-is-func global register (bool)
+.\" NS set if subroutine (in synopsis only) (fortran only)
+.
+.nr doc-is-func 0
+.
+.
+.\" NS Ft user macro
+.\" NS function type
+.\" NS
+.\" NS modifies:
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-have-decl
+.\" NS doc-have-var
+.\" NS doc-is-func
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Ft' set in doc-common
+.
+.de Ft
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Ft
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Ft function_type ... (#\n[.c])
+. \}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. nr doc-arg-ptr +1
+. if (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. tm Usage: .Ft function_type ... (#\n[.c])
+. doc-reset-args
+. return
+. \}
+.
+. if \n[doc-in-synopsis-section] \{\
+. if (\n[doc-have-func] : \n[doc-have-decl]) \{\
+. doc-paragraph
+. nr doc-have-decl 0
+. nr doc-have-var 0
+. \}
+.
+. if \n[doc-have-var] \{\
+. doc-paragraph
+. nr doc-have-var 0
+. \}
+.
+. nr doc-is-func 1
+. \}
+.
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Ft-font]\c
+. doc-print-recursive
+..
+.
+.
+.\" NS doc-have-old-func global register (bool)
+.\" NS set if `Ot' has been called
+.
+.nr doc-have-old-func 0
+.
+.
+.\" NS Ot user macro
+.\" NS old function type (fortran -- no newline)
+.\" NS
+.\" NS modifies:
+.\" NS doc-have-decl
+.\" NS doc-have-old-func
+.\" NS doc-have-var
+.\" NS doc-is-func
+.\" NS
+.\" NS width register `Ot' set in doc-common
+.
+.de Ot
+. nr doc-have-old-func 1
+.
+. if \n[doc-in-synopsis-section] \{\
+. if (\n[doc-have-func] : \n[doc-have-decl]) \{\
+. doc-paragraph
+. nr doc-have-decl 0
+. nr doc-have-var 0
+. \}
+.
+. if \n[doc-have-var] \{\
+. doc-paragraph
+. nr doc-have-var 0
+. \}
+.
+. nr doc-is-func 1
+. \}
+.
+. if \n[.$] \
+. nop \*[doc-Ft-font]\$*\c
+. nop \ \f[P]\c
+..
+.
+.
+.\" NS Fa user macro
+.\" NS function arguments
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Fa' set in doc-common
+.
+.de Fa
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Fa
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Fa function_arguments ... (#\n[.c])
+. \}
+.
+. ie \n[doc-func-arg-count] \
+. doc-do-func
+. el \{\
+. nr doc-arg-ptr +1
+. if (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Fa-font]\c
+. doc-print-recursive
+.
+. if \n[doc-in-synopsis-section] \
+. if \n[doc-have-func] \
+. br
+. \}\}
+..
+.
+.
+.\" NS doc-func-arg-count global register
+.\" NS how many function arguments have been processed so far
+.
+.nr doc-func-arg-count 0
+.
+.
+.\" NS doc-func-arg global string
+.\" NS work buffer for function name strings
+.
+.ds doc-func-arg
+.
+.
+.\" NS doc-num-func-args global register
+.\" NS number of function arguments
+.
+.nr doc-num-func-args 0
+.
+.
+.\" NS doc-func-args-processed global register
+.\" NS function arguments processed so far
+.
+.nr doc-func-args-processed 0
+.
+.
+.\" NS doc-do-func macro
+.\" NS internal .Fa for .Fc
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-func-arg
+.\" NS doc-func-arg-count
+.\" NS doc-func-args-processed
+.\" NS doc-num-func-args
+.
+.de doc-do-func
+. if (\n[doc-arg-limit] <= \n[doc-arg-ptr]) \{\
+. doc-reset-args
+. return
+. \}
+.
+. nr doc-arg-ptr +1
+.
+. ds doc-func-arg
+. nr doc-num-func-args 0
+. nr doc-func-args-processed 0
+.
+. doc-build-func-string \*[doc-arg\n[doc-arg-ptr]]
+. if (\n[doc-num-func-args] > 1) \
+. ds doc-arg\n[doc-arg-ptr] "\*[doc-func-arg]
+.
+. if (\n[doc-func-arg-count] > 1) \{\
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\|,\)\c
+. nop \)\*[doc-space\n[doc-arg-ptr]]\*[doc-Fa-font]\c
+. nop \)\*[doc-arg\n[doc-arg-ptr]]\f[P]\s[0]\c
+. \}
+.
+. if (\n[doc-func-arg-count] == 1) \{\
+. nop \|\*[doc-Fa-font]\*[doc-arg\n[doc-arg-ptr]]\c
+. nop \f[P]\s[0]\c
+. \}
+. nr doc-func-arg-count +1
+. doc-do-func
+..
+.
+.
+.\" NS doc-have-func global register (bool)
+.\" NS whether we have more than one function in synopsis
+.
+.nr doc-have-func 0
+.
+.
+.\" NS Fn user macro
+.\" NS functions
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-have-decl
+.\" NS doc-have-func
+.\" NS doc-have-var
+.\" NS doc-indent-synopsis
+.\" NS doc-is-func
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Fn' set in doc-common
+.
+.de Fn
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Fn
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Fn function_name [function_arg] ... (#\n[.c])
+. \}
+.
+. if !\n[doc-arg-limit] \
+. return
+.
+. if \n[doc-in-synopsis-section] \{\
+. \" if there is/has been more than one subroutine declaration
+. ie \n[doc-is-func] \{\
+. br
+. nr doc-have-var 0
+. nr doc-have-decl 0
+. nr doc-is-func 0
+. \}
+. el \{\
+. if \n[doc-have-func] \{\
+. doc-paragraph
+. nr doc-have-var 0
+. nr doc-have-decl 0
+. \}\}
+.
+. if \n[doc-have-decl] \{\
+. doc-paragraph
+. nr doc-have-var 0
+. \}
+.
+. if \n[doc-have-var] \{\
+. doc-paragraph
+. nr doc-have-decl 0
+. \}
+.
+. nr doc-have-func 1
+. nr doc-is-func 0
+.
+. br
+. if !\n[doc-indent-synopsis] \
+. nr doc-indent-synopsis (8u * \n[doc-fixed-width]u)
+. if !\n[doc-indent-synopsis-active] \
+. in +\n[doc-indent-synopsis]u
+. ti -\n[doc-indent-synopsis]u
+. \}
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. if (\n[doc-arg-limit] < \n[doc-arg-ptr]) \{\
+. tm Usage: .Fn function_name [function_arg] ... (#\n[.c])
+. doc-reset-args
+. return
+. \}
+.
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. nop \*[doc-Fn-font]\*[doc-arg\n[doc-arg-ptr]]\c
+. nop \f[P]\s[0]\*[lp]\)\c
+.
+. nr doc-arg-ptr +1
+. if (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. if (\n[doc-type\n[doc-arg-ptr]] == 2) \{\
+. nop \*[doc-Fa-font]\c
+. doc-do-func-args
+. nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\c
+. \}\}
+.
+. nop \)\*[rp]\)\c
+. if \n[doc-in-synopsis-section] \
+. nop \);\)\c
+.
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. \" output the space (if needed)
+. nr doc-arg-ptr -1
+. nop \)\*[doc-space\n[doc-arg-ptr]]\c
+. nr doc-arg-ptr +1
+.
+. doc-print-recursive
+. \}
+. el \
+. doc-print-and-reset
+.
+. if \n[doc-in-synopsis-section] \
+. if !\n[doc-indent-synopsis-active] \
+. in -\n[doc-indent-synopsis]u
+..
+.
+.
+.\" NS doc-do-func-args macro
+.\" NS handle function arguments
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-argXXX
+.\" NS doc-func-arg
+.\" NS doc-func-args-processed
+.\" NS doc-num-func-args
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-ddfa
+.
+.de doc-do-func-args
+. if \n[doc-in-synopsis-section] \{\
+. ds doc-func-arg
+. nr doc-num-func-args 0
+. nr doc-func-args-processed 0
+.
+. doc-build-func-string \*[doc-arg\n[doc-arg-ptr]]
+. if (\n[doc-num-func-args] > 1) \
+. ds doc-arg\n[doc-arg-ptr] "\*[doc-func-arg]
+. \}
+.
+. nop \)\*[doc-arg\n[doc-arg-ptr]]\c
+. nr doc-arg-ptr +1
+.
+. if (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. if (\n[doc-type\n[doc-arg-ptr]] == 2) \{\
+. nr doc-reg-ddfa (\n[doc-arg-ptr] - 1)
+. nop \|\f[\n[doc-curr-font]]\s[\n[doc-curr-size]u],\)\c
+. nop \)\*[doc-space\n[doc-reg-ddfa]]\f[P]\s[0]\|\c
+. doc-do-func-args
+. \}\}
+..
+.
+.
+.\" NS doc-saved-nesting-level global register
+.
+.nr doc-saved-nesting-level 0
+.
+.
+.\" NS doc-in-func-enclosure global register (bool)
+.
+.nr doc-in-func-enclosure 0
+.
+.
+.\" NS Fo user macro
+.\" NS function open
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-func-arg-count
+.\" NS doc-have-decl
+.\" NS doc-have-func
+.\" NS doc-have-var
+.\" NS doc-in-func-enclosure
+.\" NS doc-indent-synopsis
+.\" NS doc-is-func
+.\" NS doc-macro-name
+.\" NS doc-saved-nesting-level
+.\" NS
+.\" NS width register `Fo' set in doc-common
+.
+.de Fo
+. if (\n[doc-in-func-enclosure]) \{\
+. tm mdoc error: .Fo/.Fc can't be nested (#\n[.c])
+. return
+. \}
+.
+. nr doc-saved-nesting-level \n[doc-nesting-level]
+. nr doc-in-func-enclosure 1
+.
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ds doc-macro-name Fo
+. doc-parse-args \$@
+. \}
+. el \
+. tm Usage: .Fo function_name (#\n[.c])
+. \}
+.
+. if \n[doc-in-synopsis-section] \{\
+. \" if there is/has been more than one subroutine declaration
+. ie \n[doc-is-func] \{\
+. br
+. nr doc-have-var 0
+. nr doc-have-decl 0
+. nr doc-is-func 0
+. \}
+. el \{\
+. if \n[doc-have-func] \{\
+. doc-paragraph
+. nr doc-have-var 0
+. nr doc-have-decl 0
+. \}\}
+.
+. if \n[doc-have-decl] \{\
+. doc-paragraph
+. nr doc-have-var 0
+. \}
+.
+. if \n[doc-have-var] \{\
+. doc-paragraph
+. nr doc-have-decl 0
+. \}
+.
+. nr doc-have-func 1
+. nr doc-is-func 0
+.
+. br
+. if !\n[doc-indent-synopsis] \
+. nr doc-indent-synopsis (8u * \n[doc-fixed-width]u)
+. \}
+.
+. \" start function box
+. box doc-func-box
+. ev doc-func-env
+. evc 0
+. in 0
+. nf
+.
+. nr doc-arg-ptr +1
+. doc-print-prefixes
+. if (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. nr doc-func-arg-count 1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. nop \*[doc-Fn-font]\*[doc-arg\n[doc-arg-ptr]]\c
+. nop \f[P]\s[0]\*[lp]\)\c
+. doc-reset-args
+. \}
+..
+.
+.
+.\" NS Fc user macro
+.\" NS function close
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-func-arg-count
+.\" NS doc-in-func-enclosure
+.\" NS doc-saved-nesting-level
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `Fc' set in doc-common
+.
+.de Fc
+. if !\n[doc-in-func-enclosure] \{\
+. tm mdoc warning: Extraneous .Fc (#\n[.c])
+. return
+. \}
+.
+. if \n[.$] \{\
+. ds doc-macro-name Fc
+. \" the first (dummy) argument is used to get the correct spacing
+. doc-parse-args \) \$@
+. \}
+.
+. if !(\n[doc-saved-nesting-level] == \n[doc-nesting-level]) \
+. tm mdoc warning: Unbalanced enclosure commands within .Fo/.Fc
+.
+. nr doc-func-arg-count 0
+. nr doc-in-func-enclosure 0
+.
+. ie \n[doc-in-synopsis-section] \
+. nop \|\*[rp];\)
+. el \
+. nop \|\*[rp]\)
+.
+. \" finish function box
+. br
+. ev
+. box
+. chop doc-func-box
+. unformat doc-func-box
+.
+. if \n[doc-in-synopsis-section] \{\
+. if !\n[doc-indent-synopsis-active] \
+. in +\n[doc-indent-synopsis]u
+. ti -\n[doc-indent-synopsis]u
+. \}
+.
+. nh
+. nop \*[doc-func-box]\c
+.
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. doc-print-recursive
+. \}
+. el \
+. doc-print-and-reset
+.
+. if \n[doc-in-synopsis-section] \
+. if !\n[doc-indent-synopsis-active] \
+. in -\n[doc-indent-synopsis]u
+..
+.
+.
+.\" NS doc-build-func-string macro
+.\" NS collect function arguments and set hard spaces inbetween
+.\" NS
+.\" NS modifies:
+.\" NS doc-func-arg
+.\" NS doc-func-args-processed
+.\" NS doc-num-func-args
+.
+.de doc-build-func-string
+. if !\n[doc-num-func-args] \{\
+. nr doc-num-func-args \n[.$]
+. nr doc-func-args-processed 0
+. ds doc-func-arg
+. \}
+.
+. nr doc-func-args-processed +1
+. as doc-func-arg "\$1
+.
+. if (\n[doc-func-args-processed] < \n[doc-num-func-args]) \{\
+. as doc-func-arg "\*[doc-hard-space]
+.
+. shift
+. doc-build-func-string \$@
+. \}
+..
+.
+.
+.\" Very crude references: Stash all reference info into boxes, 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 doc-is-reference global register (bool)
+.\" NS set if in reference
+.
+.nr doc-is-reference 0
+.
+.
+.\" NS doc-reference-count global register
+.\" NS reference element counter
+.
+.nr doc-reference-count 0
+.
+.
+.\" NS Rs user macro
+.\" NS reference start
+.\" NS
+.\" NS modifies:
+.\" NS doc-is-reference
+.\" NS doc-reference-count
+.\" NS
+.\" NS width register `Rs' set in doc-common
+.
+.de Rs
+. ie \n[.$] \
+. tm Usage: .Rs (does not take arguments) (#\n[.c])
+. el \{\
+. nr doc-is-reference 1
+. doc-reset-reference
+. if \n[doc-in-see-also-section] \
+. doc-paragraph
+. nr doc-reference-count 0
+. \}
+..
+.
+.
+.\" NS Re user macro
+.\" NS reference end
+.\" NS
+.\" NS modifies:
+.\" NS doc-is-reference
+.\" NS
+.\" NS width register `Re' set in doc-common
+.
+.de Re
+. ie \n[.$] \
+. tm Usage: .Re (does not take arguments) (#\n[.c])
+. el \{\
+. doc-print-reference
+. doc-reset-reference
+. nr doc-is-reference 0
+. \}
+..
+.
+.
+.\" NS doc-reset-reference macro
+.\" NS reference cleanup
+.\" NS
+.\" NS modifies:
+.\" NS doc-author-count
+.\" NS doc-author-nameXXX
+.\" NS doc-book-count
+.\" NS doc-book-name
+.\" NS doc-corporate-count
+.\" NS doc-corporate-name
+.\" NS doc-date
+.\" NS doc-date-count
+.\" NS doc-issue-count
+.\" NS doc-issue-name
+.\" NS doc-journal-count
+.\" NS doc-journam-name
+.\" NS doc-optional-count
+.\" NS doc-optional-string
+.\" NS doc-page-number-count
+.\" NS doc-page-number-string
+.\" NS doc-reference-title-count
+.\" NS doc-reference-title-name
+.\" NS doc-reference-title-name-for-book
+.\" NS doc-report-count
+.\" NS doc-report-name
+.\" NS doc-volume-count
+.\" NS doc-volume-name
+.
+.de doc-reset-reference
+. while (\n[doc-author-count]) \{\
+. ds doc-author-name\n[doc-author-count]
+. nr doc-author-count -1
+. \}
+. nr doc-journal-count 0
+. nr doc-issue-count 0
+. nr doc-optional-count 0
+. nr doc-corporate-count 0
+. nr doc-report-count 0
+. nr doc-reference-title-count 0
+. nr doc-volume-count 0
+. nr doc-date-count 0
+. nr doc-page-number-count 0
+. nr doc-book-count 0
+.
+. ds doc-journal-name
+. ds doc-issue-name
+. ds doc-optional-string
+. ds doc-corporate-name
+. ds doc-report-name
+. ds doc-reference-title-name
+. ds doc-reference-title-name-for-book
+. ds doc-volume-name
+. ds doc-date
+. ds doc-page-number-string
+. ds doc-book-name
+..
+.
+.
+.\" NS doc-finish-reference macro
+.\" NS auxiliary macro for doc-print-reference
+.\" NS
+.\" NS modifies:
+.\" NS doc-reference-count
+.
+.de doc-finish-reference
+. nr doc-reference-count -1
+. ie \n[doc-reference-count] \
+. nop \),
+. el \
+. nop \).
+..
+.
+.
+.\" NS doc-print-reference macro
+.\" NS reference print
+.\" NS
+.\" NS modifies:
+.\" NS doc-reference-count
+.
+.de doc-print-reference
+.
+. nh
+.
+. if \n[doc-author-count] \{\
+. doc-print-reference-authors
+. nr doc-reference-count -\n[doc-author-count]
+. \}
+.
+. if \n[doc-reference-title-count] \{\
+. unformat doc-reference-title-name
+. chop doc-reference-title-name
+. unformat doc-reference-title-name-for-book
+. chop doc-reference-title-name-for-book
+. ie ((\n[doc-journal-count] == 1) : (\n[doc-book-count] == 1)) \{\
+. nop \)\*[q]\)\*[doc-reference-title-name-for-book]\)\*[q]\c
+. doc-finish-reference
+. \}
+. el \{\
+. nop \*[doc-reference-title-name]\c
+. doc-finish-reference
+. \}\}
+.
+. if \n[doc-book-count] \{\
+. unformat doc-book-name
+. chop doc-book-name
+. nop \*[doc-book-name]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-publisher-count] \{\
+. unformat doc-publisher-name
+. chop doc-publisher-name
+. nop \*[doc-publisher-name]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-journal-count] \{\
+. unformat doc-journal-name
+. chop doc-journal-name
+. nop \*[doc-journal-name]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-report-count] \{\
+. unformat doc-report-name
+. chop doc-report-name
+. nop \*[doc-report-name]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-issue-count] \{\
+. unformat doc-issue-name
+. chop doc-issue-name
+. nop \*[doc-issue-name]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-volume-count] \{\
+. unformat doc-volume-name
+. chop doc-volume-name
+. nop \*[doc-volume-name]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-page-number-count] \{\
+. unformat doc-page-number-string
+. chop doc-page-number-string
+. nop \*[doc-page-number-string]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-corporate-count] \{\
+. unformat doc-corporate-name
+. chop doc-corporate-name
+. nop \*[doc-corporate-name]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-date-count] \{\
+. unformat doc-date
+. chop doc-date
+. nop \*[doc-date]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-optional-count] \{\
+. unformat doc-optional-string
+. chop doc-optional-string
+. nop \*[doc-optional-string]\c
+. doc-finish-reference
+. \}
+.
+. if \n[doc-reference-count] \
+. tm mdoc warning: unresolved reference problem
+.
+. hy \n[doc-hyphen-flags]
+..
+.
+.
+.\" NS doc-print-reference-authors macro
+.\" NS print out reference authors
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-dpra
+.\" NS doc-str-dpra
+.
+.ds doc-str-dpra "and
+.
+.de doc-print-reference-authors
+. nr doc-reg-dpra 1
+.
+. while (\n[doc-reg-dpra] < \n[doc-author-count]) \{\
+. unformat doc-author-name\n[doc-reg-dpra]
+. chop doc-author-name\n[doc-reg-dpra]
+. ie (\n[doc-author-count] > 2) \
+. nop \)\*[doc-author-name\n[doc-reg-dpra]],
+. el \
+. nop \)\*[doc-author-name\n[doc-reg-dpra]]
+. nr doc-reg-dpra +1
+. \}
+.
+. unformat doc-author-name\n[doc-reg-dpra]
+. chop doc-author-name\n[doc-reg-dpra]
+. if (\n[doc-author-count] > 1) \
+. nop \)\*[doc-str-dpra]
+. nop \)\*[doc-author-name\n[doc-reg-dpra]],
+..
+.
+.
+.\" NS doc-author-count global register
+.\" NS counter of author references
+.
+.nr doc-author-count 0
+.
+.
+.\" NS doc-author-nameXXX global box
+.\" NS array of author names
+.\" NS
+.\" NS limit:
+.\" NS doc-author-count
+.
+.ds doc-author-name0
+.
+.
+.\" NS %A user macro
+.\" NS reference author(s)
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-author-count
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%A
+.\" NS
+.\" NS width register `%A' set in doc-common
+.
+.de %A
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%A author_name ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-author-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %A
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" save to reference box
+. box doc-author-name\n[doc-author-count]
+. ev doc-env-%A
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-book-count global register
+.\" NS counter of book references
+.
+.nr doc-book-count 0
+.
+.
+.\" NS doc-book-name global box
+.\" NS string of collected book references
+.
+.ds doc-book-name
+.
+.
+.\" NS %B user macro
+.\" NS [reference] book name
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-book-count
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%B
+.\" NS
+.\" NS width register `%B' set in doc-common
+.
+.de %B
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%B book_name ... (#\n[.c])
+. return
+. \}
+.
+. if \n[doc-is-reference] \{\
+. nr doc-book-count +1
+. nr doc-reference-count +1
+. \}
+.
+. ds doc-macro-name %B
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. ie \n[doc-is-reference] \{\
+. \" append to reference box
+. boxa doc-book-name
+. ev doc-env-%B
+. evc 0
+. in 0
+. nf
+. nop \*[doc-Em-font]\c
+. doc-do-references
+. \}
+. el \{\
+. nop \*[doc-Em-font]\c
+. doc-print-recursive
+. \}
+..
+.
+.
+.\" NS doc-date-count global register
+.\" NS counter of date references
+.
+.nr doc-date-count 0
+.
+.
+.\" NS doc-date global box
+.\" NS string of collected date references
+.
+.ds doc-date
+.
+.
+.\" NS %D user macro
+.\" NS [reference] date
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-date-count
+.\" NS doc-macro-name
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%D
+.\" NS
+.\" NS width register `%D' set in doc-common
+.
+.de %D
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%D date ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-date-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %D
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-date
+. ev doc-env-%D
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-publisher-count global register
+.\" NS counter of publisher references
+.
+.nr doc-publisher-count 0
+.
+.
+.\" NS doc-publisher-name global box
+.\" NS string of collected publisher references
+.
+.ds doc-publisher-name
+.
+.
+.\" NS %I user macro
+.\" NS [reference] issuer/publisher name
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-publisher-count
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%I
+.\" NS
+.\" NS width register `%I' set in doc-common
+.
+.de %I
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%I issuer/publisher_name ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-publisher-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %I
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-publisher-name
+. ev doc-env-%I
+. evc 0
+. in 0
+. nf
+. nop \*[doc-Em-font]\c
+. doc-do-references
+..
+.
+.
+.\" NS doc-journal-count global register
+.\" NS counter of journal references
+.
+.nr doc-journal-count 0
+.
+.
+.\" NS doc-journal-name global box
+.\" NS string of collected journal references
+.
+.ds doc-journal-name
+.
+.
+.\" NS %J user macro
+.\" NS [reference] Journal Name
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-journal-count
+.\" NS doc-macro-name
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%J
+.\" NS
+.\" NS width register `%J' set in doc-common
+.
+.de %J
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%J journal_name ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-journal-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %J
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-journal-name
+. ev doc-env-%J
+. evc 0
+. in 0
+. nf
+. nop \*[doc-Em-font]\c
+. doc-do-references
+..
+.
+.
+.\" NS doc-issue-count global register
+.\" NS counter of issue number references
+.
+.nr doc-issue-count 0
+.
+.
+.\" NS doc-issue-name global box
+.\" NS string of collected issue number references
+.
+.ds doc-issue-name
+.
+.
+.\" NS %N user macro
+.\" NS [reference] issue number
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-issue-count
+.\" NS doc-macro-name
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%N
+.\" NS
+.\" NS width register `%N' set in doc-common
+.
+.de %N
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%N issue_number ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-issue-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %N
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-issue-name
+. ev doc-env-%N
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-optional-count global register
+.\" NS counter of optional information references
+.
+.nr doc-optional-count 0
+.
+.
+.\" NS doc-optional-string global box
+.\" NS string of collected optional information references
+.
+.ds doc-optional-string
+.
+.
+.\" NS %O user macro
+.\" NS [reference] optional information
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-optional-count
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%O
+.\" NS
+.\" NS width register `%O' set in doc-common
+.
+.de %O
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%O optional_information ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-optional-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %O
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-optional-string
+. ev doc-env-%O
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-page-number-count global register
+.\" NS counter of page number references
+.
+.nr doc-page-number-count 0
+.
+.
+.\" NS doc-page-number-string global box
+.\" NS string of collected page number references
+.
+.ds doc-page-number-string
+.
+.
+.\" NS %P user macro
+.\" NS [reference] page numbers
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-page-number-count
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%P
+.\" NS
+.\" NS width register `%P' set in doc-common
+.
+.de %P
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%P page_number ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-page-number-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %P
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-page-number-string
+. ev doc-env-%P
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-corporate-count global register
+.\" NS counter of corporate references
+.
+.nr doc-corporate-count 0
+.
+.
+.\" NS doc-corporate-name global box
+.\" NS string of collected corporate references
+.
+.ds doc-corporate-name
+.
+.
+.\" NS %Q user macro
+.\" NS corporate or foreign author
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-corporate-count
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-reference-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%Q
+.\" NS
+.\" NS width register `%Q' set in doc-common
+.
+.de %Q
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%Q corporate_or_foreign_author ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-corporate-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %Q
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-corporate-name
+. ev doc-env-%Q
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-report-count global register
+.\" NS counter of report references
+.
+.nr doc-report-count 0
+.
+.
+.\" NS doc-report-name global box
+.\" NS string of collected report references
+.
+.ds doc-report-name
+.
+.
+.\" NS %R user macro
+.\" NS [reference] report name
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-reference-count
+.\" NS doc-report-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%R
+.\" NS
+.\" NS width register `%R' set in doc-common
+.
+.de %R
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%R reference_report ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-report-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %R
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-report-name
+. ev doc-env-%R
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-reference-title-count global register
+.\" NS counter of reference title references
+.
+.nr doc-reference-title-count 0
+.
+.
+.\" NS doc-reference-title-name global box
+.\" NS string of collected reference title references
+.
+.ds doc-reference-title-name
+.
+.
+.\" NS doc-reference-title-name-for-book global box
+.\" NS string of collected reference title references
+.\" NS (saved with another font; this is a shortcoming of groff)
+.
+.ds doc-reference-title-name-for-book
+.
+.
+.\" NS %T user macro
+.\" NS reference title
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-reference-title-count
+.\" NS doc-report-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%T
+.\" NS
+.\" NS width register `%T' set in doc-common
+.
+.de %T
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%T reference_title ... (#\n[.c])
+. return
+. \}
+.
+. if \n[doc-is-reference] \{\
+. nr doc-reference-title-count +1
+. nr doc-reference-count +1
+. \}
+.
+. ds doc-macro-name %T
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. ie \n[doc-is-reference] \{\
+. \" append to reference box
+. boxa doc-reference-title-name-for-book
+. ev doc-env-%T
+. evc 0
+. in 0
+. nf
+. nop \*[doc-No-font]\c
+. doc-do-references
+.
+. \" do it a second time with another font
+. ds doc-macro-name %T
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. boxa doc-reference-title-name
+. ev doc-env-%T
+. evc 0
+. in 0
+. nf
+. nop \*[doc-Em-font]\c
+. doc-do-references
+. \}
+. el \{\
+. nop \*[doc-Em-font]\c
+. doc-print-recursive
+. \}
+..
+.
+.
+.\" NS doc-volume-count global register
+.\" NS counter of reference title references
+.
+.nr doc-volume-count 0
+.
+.
+.\" NS doc-volume-name global box
+.\" NS string of collected volume references
+.
+.ds doc-volume-name
+.
+.
+.\" NS %V user macro
+.\" NS reference volume
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-macro-name
+.\" NS doc-reference-title-count
+.\" NS doc-volume-count
+.\" NS
+.\" NS local variables:
+.\" NS doc-env-%V
+.\" NS
+.\" NS width register `%V' set in doc-common
+.
+.de %V
+. if (\n[doc-arg-limit] : (\n[.$] == 0)) \{\
+. tm Usage: .%V volume ... (#\n[.c])
+. return
+. \}
+.
+. nr doc-volume-count +1
+. nr doc-reference-count +1
+.
+. ds doc-macro-name %V
+. doc-parse-args \$@
+.
+. nr doc-arg-ptr +1
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+.
+. \" append to reference box
+. boxa doc-volume-name
+. ev doc-env-%V
+. evc 0
+. in 0
+. nf
+. doc-do-references
+..
+.
+.
+.\" NS doc-do-references macro
+.\" NS reference recursion routine
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-ddr
+.\" NS doc-reg-ddr1
+.
+.de doc-do-references
+. if !\n[doc-is-reference] \
+. tm mdoc error: .\*[doc-macro-name] found outside of .Rs ... .Re (#\n[.c])
+.
+. nr doc-reg-ddr1 \n[doc-type\n[doc-arg-ptr]]
+.
+. ie (\n[doc-reg-ddr1] == 1) \{\
+. \" .nop \f[\n[doc-curr-font]]\s[\n[doc-curr-size]u]\c
+. doc-append-arg \c 3
+. \*[doc-arg\n[doc-arg-ptr]]
+. \}
+. el \{\
+. nop \)\*[doc-arg\n[doc-arg-ptr]]\c
+.
+. ie (\n[doc-arg-limit] == \n[doc-arg-ptr]) \{\
+. \" finish reference box
+. br
+. ev
+. boxa
+.
+. doc-reset-args
+. \}
+. el \{\
+. nr doc-reg-ddr \n[doc-arg-ptr]
+. nr doc-arg-ptr +1
+. nop \)\*[doc-space\n[doc-reg-ddr]]\c
+. doc-do-references
+. \}\}
+..
+.
+.
+.\" NS Hf user macro
+.\" NS source include header files.
+.\" NS
+.\" NS modifies:
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS
+.\" NS width register `Hf' set in doc-common
+.
+.de Hf
+. ie ((\n[.$] == 1) & (\n[doc-arg-limit] == 0)) \{\
+. doc-paragraph
+. nop File:
+. Pa \$1
+.
+. Bd -literal
+. so \$1
+. Ed
+.
+. doc-paragraph
+. \}
+. el \
+. Usage: .Hf file (#\n[.c])
+..
+.
+.
+.\" NS doc-have-author global register (bool)
+.\" NS set in `An'
+.
+.nr doc-have-author 0
+.
+.
+.\" NS An user macro
+.\" NS author name
+.\" NS
+.\" NS modifies:
+.\" NS doc-arg-ptr
+.\" NS doc-curr-font
+.\" NS doc-curr-size
+.\" NS doc-have-author
+.\" NS doc-macro-name
+.\" NS
+.\" NS width register `An' set in doc-common
+.
+.de An
+. if !\n[doc-arg-limit] \{\
+. ie \n[.$] \{\
+. ie "\$1"-nosplit" \
+. nr doc-in-authors-section 0
+. el \{ .ie "\$1"-split" \
+. nr doc-in-authors-section 1
+. el \{\
+. ds doc-macro-name An
+. doc-parse-args \$@
+. \}\}\}
+. el \{\
+. tm1 "Usage: .An {-nosplit | -split}
+. tm1 .An author_name ... (#\n[.c])
+. \}\}
+.
+. if \n[doc-in-authors-section] \{\
+. ie \n[doc-have-author] \
+. br
+. el \
+. nr doc-have-author 1
+. \}
+.
+. if \n[doc-arg-limit] \{\
+. nr doc-arg-ptr +1
+. ie (\n[doc-arg-limit] >= \n[doc-arg-ptr]) \{\
+. nr doc-curr-font \n[.f]
+. nr doc-curr-size \n[.ps]
+. doc-print-recursive
+. \}
+. el \{\
+. tm Usage: .An author_name ... (#\n[.c])
+. doc-reset-args
+. \}\}
+..
+.
+.
+.\" NS Rv user macro
+.\" NS return values
+.\" NS
+.\" NS width register `Rv' set in doc-common
+.\" NS
+.\" NS local variables:
+.\" NS doc-str-Rv-prefix
+.\" NS doc-str-Rv-suffix
+.
+.ds doc-str-Rv-prefix "The
+.ds doc-str-Rv-suffix "function returns the value\~0 if successful;
+.as doc-str-Rv-suffix " otherwise the value\~-1 is returned and
+.as doc-str-Rv-suffix " the global variable \*[doc-Va-font]errno\f[P]
+.as doc-str-Rv-suffix " is set to indicate the error.
+.
+.de Rv
+.
+.\" XXX: what does this function without `-std'?
+.
+. if !\n[.$] \{\
+. tm Usage: .Rv [-std] (#\n[.c])
+. return
+. \}
+.
+. \" .ds doc-macro-name Rv
+. \" .nr doc-arg-ptr 0
+. \" .nr lR +1
+. \" .ds doc-arg1 \$2
+. \" .ds doc-arg2 \$3
+. \" .ds doc-arg3 \$4
+. \" .ds doc-arg4 \$5
+. \" .ds doc-arg5 \$6
+. \" .ds doc-arg6 \$7
+. \" .ds doc-arg7 \$8
+. \" .ds doc-arg8 \$9
+. \" .
+. \" .nr doc-num-args (\n[.$] - 1)
+.
+. if "\$1"-std" \{\
+. nr doc-reg-Rv \*[doc-section]
+. if ((\n[doc-reg-Rv] < 2) : (\n[doc-reg-Rv] > 3)) \
+. tm Usage: .Rv -std in sections 2 and 3 only (#\n[.c])
+. br
+. nop \)\*[doc-str-Rv-prefix]
+. Fn \$2
+. nop \)\*[doc-str-Rv-suffix]
+. \}
+..
+.
+.
+.\" NS Mt user macro
+.\" NS mailto (for conversion to HTML)
+.
+.de Mt
+. \" XXX: error handling missing
+. Pa \$@
+..
+.
+.
+.\" NS Lk user macro
+.\" NS link (for conversion to HTML)
+.\" NS
+.\" NS local variables:
+.\" NS doc-reg-Lk
+.\" NS doc-str-Lk
+.
+.de Lk
+. ds doc-str-Lk Sy \$@
+.
+. ie (\n[.$] > 1) \{\
+. doc-get-arg-type \$2
+. ie (\n[doc-arg-type] < 3) \{\
+. Em \)\$2:
+. ds doc-str-Lk Sy "\$1"
+. doc-get-width "\$1"
+. shift 2
+. if \n[.$] \
+. as doc-str-Lk " \$@
+. \}
+. el \
+. doc-get-width "\$1"
+. \}
+. el \
+. doc-get-width "\$1"
+.
+. ie n \
+. nr doc-reg-Lk 26
+. el \
+. nr doc-reg-Lk 38
+. ie (\n[doc-width] >= \n[doc-reg-Lk]) \
+. D1 \*[doc-str-Lk]
+. el \
+. \*[doc-str-Lk]
+..
+.
+.
+.\" NS doc-defunct-macro macro
+.\" NS this is the skeleton for defunct macros
+.\" NS
+.
+.de doc-defunct-macro
+. tmc mdoc error: .\$0 defunct
+. if d doc-\$0-usage \
+. tmc , \*[doc-\$0-usage]
+. tm1 " (#\n[.c])
+..
+.
+.
+.\" obsolete macros
+.
+.als Db doc-defunct-macro
+.
+.als Ds doc-defunct-macro
+.
+.als Ex doc-defunct-macro
+.ds doc-Ex-usage use .D1
+.
+.als Or doc-defunct-macro
+.ds doc-Or-usage use `|'
+.
+.als Sf doc-defunct-macro
+.ds doc-Sf-usage use .Pf or .Ns
+.
+.
+.rn em e@
+.
+.de em
+. tm1 "mdoc error: end-macro (.em) respecification is not allowed. (#\n[.c])
+. tm1 " Should this have been `.Em ...'?
+. ab
+..
+.
+.
+.\" NS doc-empty-line macro
+.\" NS emit warning and print empty line
+.
+.de doc-empty-line
+. if !\n[doc-display-depth] \
+. tm mdoc warning: Empty input line #\n[.c]
+. sp
+..
+.
+.blm doc-empty-line
+.
+.
+.ec
+.
+.
+.\" load local modifications
+.mso mdoc.local
+.
+.\" EOF
diff --git a/contrib/groff/tmac/dvi.tmac b/contrib/groff/tmac/dvi.tmac
new file mode 100644
index 0000000..5fec427
--- /dev/null
+++ b/contrib/groff/tmac/dvi.tmac
@@ -0,0 +1,147 @@
+.\" dvi.tmac
+.\"
+.nr _C \n(.C
+.cp 0
+.ftr CR CW
+.ftr C CW
+.ftr CO CWI
+.ftr CI CWI
+.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\s-2\(ci\s0\
+\h'\w'\s-2\(ci\s0'u-\w'\s-4C\s0'u/2u'\
+\s-4C\s0\
+\h'\w'\s-2\(ci\s0'u-\w'\s-4C\s0'u/2u'
+.if !c\[rg] .char \[rg] \
+\z\s-2\(ci\s0\
+\h'\w'\s-2\(ci\s0'u-\w'\s-4R\s0'u/2u'\
+\s-4R\s0\
+\h'\w'\s-2\(ci\s0'u-\w'\s-4R\s0'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 latin1.tmac
diff --git a/contrib/groff/tmac/e.tmac b/contrib/groff/tmac/e.tmac
new file mode 100644
index 0000000..8ea4074
--- /dev/null
+++ b/contrib/groff/tmac/e.tmac
@@ -0,0 +1,1663 @@
+.\" @(#)e.tmac 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
+..
+.de T&
+..
+.\"
+.\" 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 (u;\\n(.l-\\n(g7>?0/2)
+.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/contrib/groff/tmac/fixmacros.sed b/contrib/groff/tmac/fixmacros.sed
index 63cce22..56caf9f 100644
--- a/contrib/groff/tmac/fixmacros.sed
+++ b/contrib/groff/tmac/fixmacros.sed
@@ -1,3 +1,4 @@
+# try to fix macros for AT&T troff so that they work without groff's -C switch
s/^\([.'][ ]*[^\\ ][^ \\]\)\([^ ]\)/\1 \2/
s/^\(\\![.'][ ]*[^\\ ][^ \\]\)\([^ ]\)/\1 \2/
s/\([.'][ ]*i[ef] *[^ ]* [.'][ ]*[^\\0-9 ][^ \\]\)\([^ ]\)/\1 \2/
diff --git a/contrib/groff/tmac/groff_man.man b/contrib/groff/tmac/groff_man.man
index 14bd3b0..e35acab 100644
--- a/contrib/groff/tmac/groff_man.man
+++ b/contrib/groff/tmac/groff_man.man
@@ -30,7 +30,16 @@ groff_man \- groff `man' macros to support generation of man pages
.SH SYNOPSIS
.
.B groff
-.B \-m@TMAC_AN_PREFIX@an
+.B \-man
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.br
+.B groff
+.B \-m\ man
[
.IR options .\|.\|.
]
@@ -40,11 +49,11 @@ groff_man \- groff `man' macros to support generation of man pages
.
.SH DESCRIPTION
.
-The
-.B tmac.@TMAC_AN_PREFIX@an
-macros used to generate man pages with
+The
+.B man
+macros used to generate man pages with
.I groff
-were written by James Clark.
+were written by James Clark.
This document provides a brief summary of the use of each macro in that
package.
.
@@ -55,6 +64,13 @@ The
macros understand the following command line options (which define various
registers).
.TP
+.B \-rcR=1
+This option (the default if in nroff mode) will create a single, very long
+page instead of multiple pages.
+Say
+.B \-rcR=0
+to disable it.
+.TP
.B \-rC1
If more than one manual page is given on the command line, number the
pages continuously, rather than starting each at\ 1.
@@ -91,11 +107,12 @@ For example, the option `\-rX2' will produce the following page numbers:
This section describes the available macros for manual pages.
For further customization, put additional macros and requests into the file
.B man.local
-which will be loaded immediately after
-.BR tmac.@TMAC_AN_PREFIX@an .
+which will be loaded immediately after the
+.B man
+package.
.TP
.BI .TH " title section " [ extra1 "] [" extra2 "] [" extra3 ]
-Sets the title of the man page to
+Sets the title of the man page to
.I title
and the section to
.IR section ,
@@ -154,7 +171,7 @@ value.
.TP
.BI ".TP [" nnn ]
Sets up an indented paragraph with label.
-The indentation is set to
+The indentation is set to
.I nnn
if that argument is supplied (the default unit is `n' if omitted), otherwise
it is set to the default indentation value.
@@ -188,8 +205,8 @@ The font size and shape are reset to the default value (10pt resp. Roman).
Finally, the current left margin is restored.
.TP
.BI ".IP [" designator "] [" nnn ]
-Sets up an indented paragraph, using
-.I designator
+Sets up an indented paragraph, using
+.I designator
as a tag to mark its beginning.
The indentation is set to
.I nnn
@@ -205,9 +222,9 @@ designator, using `.IP\ \\(bu\ 4':
.RS
.IP \(bu 4
.B IP
-is one of the three macros used in
-.B tmac.@TMAC_AN_PREFIX@an
-to format lists.
+is one of the three macros used in the
+.B man
+package to format lists.
.IP \(bu 4
.B HP
is another.
@@ -345,7 +362,7 @@ of the next line appears in italic.
.
The default indentation is 7.2n for all output devices except for
.B grohtml
-which uses 1.2i instead.
+which ignores indentation.
.TP
.B .DT
Sets tabs every 0.5 inches.
@@ -413,15 +430,38 @@ Modern implementations of the
program read this first line and automatically call the right
preprocessor(s).
.
+.SH FILES
+.TP
+.B man.tmac
+.TQ
+.B an.tmac
+These are wrapper files to call
+.BR andoc.tmac .
+.TP
+.B andoc.tmac
+This file checks whether the
+.B man
+macros or the
+.B mdoc
+package should be used.
+.TP
+.B an-old.tmac
+All
+.B man
+macros are contained in this file.
+.TP
+.B man.local
+Local changes and customizations should be put into this file.
+.
.SH "SEE ALSO"
.
-Since the
-.B tmac.@TMAC_AN_PREFIX@an
-macros consist of groups of
-.I groff
+Since the
+.B man
+macros consist of groups of
+.I groff
requests, one can, in principle, supplement the functionality of the
-.B tmac.@TMAC_AN_PREFIX@an
-macros with individual
+.B man
+macros with individual
.I groff
requests where necessary.
A complete list of these requests is available on the WWW at
diff --git a/contrib/groff/tmac/groff_mdoc.man b/contrib/groff/tmac/groff_mdoc.man
index 2112eba..1144636 100644
--- a/contrib/groff/tmac/groff_mdoc.man
+++ b/contrib/groff/tmac/groff_mdoc.man
@@ -1,7 +1,15 @@
-.\" $NetBSD: mdoc.7,v 1.14 1999/08/30 00:41:28 ross Exp $
+.\" groff_mdoc.man
.\"
-.\" Copyright (c) 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
+.\" A complete reference of the mdoc macro package for GNU troff.
+.\"
+.\" Based on NetBSD's mdoc.samples.7, version 1.21.
+.\"
+.\"
+.\" Warning: You can't format this file with the old mdoc macros!
+.\"
+.\"
+.\" 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
@@ -13,8 +21,8 @@
.\" 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.
+.\" 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.
@@ -31,392 +39,3909 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)mdoc.7 8.2 (Berkeley) 12/30/93
+.\" @(#)mdoc.samples.7 8.2 (Berkeley) 12/30/93
.\"
-.Dd November 24, 1997
+.\" This reference invokes every macro in the package several
+.\" times and is guaranteed to give a worst case performance
+.\" for an already extremely slow package.
+.\"
+.
+.Dd April 10, 2001
.Os
-.Dt MDOC 7
+.Dt GROFF_MDOC 7
+.
+.
.Sh NAME
-.Nm mdoc
-.Nd quick reference guide for the
-.Nm \-mdoc
-macro package
+.
+.Nm groff_mdoc
+.Nd reference for groff's mdoc implementation
+.
+.
.Sh SYNOPSIS
-.Nm groff
-.Fl m Ns Ar doc
-.Ar files ...
+.
+.Nm groff Fl m Ns Cm doc Ar
+.
+.
.Sh DESCRIPTION
+.
+A complete reference for writing
+.Ux
+manual pages with the
+.Nm \-mdoc
+macro package; a
+.Em content Ns -based
+and
+.Em domain Ns -based
+formatting package for
+.Tn GNU
+.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
+.Em manual
+domain and the
+.Em 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
+.Ux
+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"
+.
+The material presented in the remainder of this document is outlined
+as follows:
+.
+.Bl -enum -width 3n -offset indent
+. It
+. Tn "TROFF IDIOSYNCRASIES"
+.
+. Bl -tag -width 2n -compact
+. It "Macro Usage"
+. It "Passing Space Characters in an Argument"
+. It "Trailing Blank Space Characters"
+. It "Escaping Special Characters"
+. It "Other Possible Pitfalls"
+. El
+.
+. It
+. Tn "A MANUAL PAGE TEMPLATE"
+.
+. It
+. Tn "CONVENTIONS"
+.
+. It
+. Tn "TITLE MACROS"
+.
+. It
+. Tn "INTRODUCTION OF MANUAL AND GENERAL TEXT DOMAINS"
+.
+. Bl -tag -width 2n -compact
+. It "What's in a Name" Ns ...
+. It "General Syntax"
+. El
+.
+. It
+. Tn "MANUAL DOMAIN"
+.
+. Bl -tag -width 2n -compact
+. It "Addresses"
+. It "Author Name"
+. It "Arguments"
+. It "Configuration Declarations (Section Four Only)"
+. It "Command Modifiers"
+. It "Defined Variables"
+. It "Errno's"
+. It "Environment Variables"
+. It "Flags"
+. It "Function Declarations"
+. It "Function Types"
+. It "Functions (Library Routines)"
+. It "Function Arguments"
+. It "Return Values"
+. \" .It "Header File (including source code)"
+. It "Interactive Commands"
+. It "Library Names"
+. It "Literals"
+. It "Names"
+. It "Options"
+. It "Pathnames"
+. It "Standards"
+. It "Variable Types"
+. It "Variables"
+. It "Manual Page Cross References"
+. El
+.
+. It
+. Tn "GENERAL TEXT DOMAIN"
+.
+. Bl -tag -width 2n -compact
+. It "AT&T Macro"
+. It "BSD Macro"
+. It "NetBSD Macro"
+. It "FreeBSD Macro"
+. It "OpenBSD Macro"
+. It "BSD/OS Macro"
+. It "UNIX Macro"
+. It "Emphasis Macro"
+. It "Font Mode"
+. It "Enclosure and Quoting Macros"
+. It "No-Op or Normal Text Macro"
+. It "No-Space Macro"
+. It "Section Cross References"
+. It "Symbolics"
+. It "Mathematical Symbols"
+. It "References and Citations"
+. It "Trade Names (or Acronyms and Type Names)"
+. It "Extended Arguments"
+. El
+.
+. It
+. Tn "PAGE STRUCTURE DOMAIN"
+.
+. Bl -tag -width 2n -compact
+. It "Section Headers"
+. It "Subsection Headers"
+. It "Paragraphs and Line Spacing"
+. It "Keeps"
+. It "Examples and Displays"
+. It "Lists and Columns"
+. El
+.
+. It
+. Tn "MISCELLANEOUS MACROS"
+.
+. It
+. Tn "PREDEFINED STRINGS"
+.
+. It
+. Tn "DIAGNOSTICS"
+.
+. It
+. Tn "FORMATTING WITH GROFF, TROFF, AND NROFF"
+.
+. It
+. Tn "FILES"
+.
+. It
+. Tn "SEE ALSO"
+.
+. It
+. Tn "BUGS"
+.El
+.
+.\" XXX
+.ne 7
+.
+.
+.Sh "TROFF IDIOSYNCRASIES"
+.
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
+package attempts to simplify the process of writing a man page.
+Theoretically, one should not have to learn the dirty details of
+.Tn GNU
+.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
+.Tn GNU
+.Xr troff 1 ,
+a macro is called by placing a
+.Ql .\&
+(dot character) at the beginning of a line followed by the two-character
+(or three-character) name for the macro.
+There can be space characters between the dot and the macro name (but
+.Em no
+tabs).
+Arguments may follow the macro separated by spaces (again, no tabs).
+It is the dot character at the beginning of the line which causes
+.Tn GNU
+.Xr troff 1
+to interpret the next two (or more) characters as a macro name.
+A single starting dot followed by nothing is ignored.
+To place a
+.Ql .\&
+(dot character) at the beginning of an input 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,
+.Tn GNU
+.Xr troff 1
+macros accept an unlimited number of arguments (contrary to other versions
+of troff which can't handle more than nine arguments).
+In limited cases, arguments may be continued or extended on the next
+line (See
+.Sx Extended Arguments
+below).
+Almost all 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 -xwidth ".Op Fl s Ar bytes" -offset indent
+.It Op Fl s Ar bytes
+is produced by
+.Ql ".Op Fl s Ar bytes"
+.El
+.
+.Pp
+To prevent a string from being interpreted as a macro name, precede the
+string with the escape sequence
+.Ql \e& :
+.
+.Bl -tag -xwidth ".Op \&Fl s \&Ar bytes" -offset indent
+.It Op \&Fl s \&Ar bytes
+is produced by
+.Ql ".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
+.Em parsed
+and macros which may be called from an argument list are referred to as
+.Em callable
+throughout this document.
+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 an argument a string containing one or
+more blank space characters.
+This may be necessary to specify arguments to macros which expect particular
+arrangement of items in the argument list. Additionally, it makes
+.Nm \-mdoc
+working faster.
+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.
+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.
+This method is useful for strings which are not expected to overlap a line
+boundary.
+An alternative is to use
+.Ql \e~ ,
+a paddable (i.e.\& stretchable), unbreakable space (this is a
+.Tn GNU
+.Xr troff 1
+extension).
+The second method is to enclose the string with double quotes.
+.Pp
+For example:
+.
+.Bl -tag -xwidth ".Fn 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
+before the space resp.\& the double 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
+.Ao blank-space Ac Ns Ao end-of-line Ac
+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.
+.
+.Ss "Other Possible Pitfalls"
+.
+A warning is emitted when an empty input line is found outside of displays
+(see below).
+Use
+.Ql .sp
+instead.
+(Well, it is even better to use
+.Nm \-mdoc
+macros to avoid the usage of low-level commands.)
+.Pp
+Leading spaces will cause a break and are output directly.
+Avoid this behaviour if possible.
+Similarly, do not use more than one space character between words in an
+ordinary text line; contrary to other text formatters, they are
+.Em not
+replaced with a single space.
+.Pp
+You can't pass
+.Ql \*[q]
+directly as an argument.
+Use
+.Ql \e*[q]
+(or
+.Ql \e*q )
+instead.
+.Pp
+By default,
+.Xr troff 1
+inserts two space characters after a punctuation mark closing a sentence;
+characters like
+.Ql \&)
+or
+.Ql \&'
+are treated transparently, not influencing the sentence-ending behaviour.
+To change this, insert
+.Ql \e&
+before or after the dot:
+.
+.Bd -literal -offset indent
+The
+\&.Ql .
+character.
+\&.Pp
+The
+\&.Ql \e&.
+character.
+\&.Pp
+\&.No test .
+test
+\&.Pp
+\&.No test.
+test
+.Ed
+.Pp
+.
+gives
+.
+.Bd -filled -offset indent
+The
+.Ql .
+character
+.Pp
+The
+.Ql \&.
+character.
+.Pp
+.No test .
+test
+.Pp
+.No test.
+test
+.Ed
+.Pp
+.
+As can be seen in the first and third line,
+.Nm \-mdoc
+handles punctuation characters specially in macro arguments.
+This will be explained in section
+.Sx General Syntax
+below.
+In the same way, you have to protect trailing full stops of abbreviations
+with a trailing zero-width space:
+.Ql e.g.\e& .
+.Pp
+A comment in the source file of a man page can be either started with
+.Ql .\e"
+on a single line,
+.Ql \e"
+after some input, or
+.Ql \e#
+anywhere (the latter is a
+.Tn GNU
+.Xr troff 1
+extension); the rest of such a line is ignored.
+.
+.
+.Sh "A MANUAL PAGE TEMPLATE"
+.
+The body of a man page is easily constructed from a basic template:
+.
+.Bd -literal -offset indent
+\&.\e" The following requests are required for all man pages.
+\&.Dd Month day, year
+\&.Os [OPERATING_SYSTEM] [version/release]
+\&.Dt DOCUMENT_TITLE [section number] [architecture/volume]
+\&.Sh NAME
+\&.Nm name
+\&.Nd one line description of name
+\&.\e" This next request is for sections 2 and 3 only.
+\&.\e" .Sh LIBRARY
+\&.Sh SYNOPSIS
+\&.Sh DESCRIPTION
+\&.\e" The following requests should be uncommented and
+\&.\e" used where appropriate.
+\&.\e" .Sh IMPLEMENTATION NOTES
+\&.\e" This next request is for sections 2, 3 and 9 function
+\&.\e" return values only.
+\&.\e" .Sh RETURN VALUES
+\&.\e" This next request is for sections 1, 6, 7 and 8 only.
+\&.\e" .Sh ENVIRONMENT
+\&.\e" .Sh FILES
+\&.\e" .Sh EXAMPLES
+\&.\e" This next request is for sections 1, 6, 7, 8 and 9 only
+\&.\e" (command return values (to shell) and
+\&.\e" fprintf/stderr type diagnostics).
+\&.\e" .Sh DIAGNOSTICS
+\&.\e" .Sh COMPATIBILITY
+\&.\e" This next request is for sections 2, 3 and 9 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
+.Ql .Dd ,
+.Ql .Os ,
+and
+.Ql .Dt ;
+the document date, the operating system the man page or subject source is
+developed or modified for, and the man page title (in
+.Em 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
+.Pf ( 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 CONVENTIONS
+.
+In the description of all macros below, optional arguments are put into
+brackets.
+An ellipsis
+.Pf ( Sq ... )
+represents zero or more additional arguments.
+Alternative values for a parameter are separated with
+.Ql | .
+If there are alternative values for a mandatory parameter, braces are used
+(together with
+.Ql | )
+to enclose the value set.
+Meta-variables are specified within angles.
+.Pp
+Example:
+.
+.Bl -tag -width 6n -offset indent
+.It Li .Xx Xo
+.Aq foo
+.Brq bar1 | bar2
+.Op \-test1 Op \-test2 | \-test3
+.No ...
+.Xc
+.El
+.
+.Pp
+Except stated explicitly, all macros are parsed and callable.
+.Pp
+Most macros have a default width value which can be used to specify a label
+width
+.Pf ( Fl width )
+or offset
+.Pf ( Fl offset )
+for the
+.Ql .Bl
+and
+.Ql .Bd
+macros.
+It is recommended not to use this rather obscure feature to avoid
+dependencies on local modifications of the
+.Nm \-mdoc
+package.
+.
+.
+.Sh "TITLE MACROS"
+.
+The title macros are part of the page structure domain but are presented
+first and separately 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 called once at the very beginning of the document and are
+used to construct headers and footers only.
+.
+.Bl -tag -width 6n
+.It Li .Dt Xo
+.Op Aq document title
+.Op Aq section number
+.Op Aq volume
+.Xc
+The document title is the subject of the man page and must be in
+.Tn CAPITALS
+due to troff limitations.
+If omitted,
+.Sq Tn UNTITLED
+is used.
+The section number may be a number in the range
+.No 1,\~ Ns ... Ns ,\~9
+or
+.Ql unass ,
+.Ql draft ,
+or
+.Ql paper .
+If it is specified, and no volume name is given, a default volume name is
+used.
+.
+.Pp
+Under
+.Tn \*[operating-system] ,
+the following sections are defined:
+.Pp
+.Bl -column LOCAL -offset indent -compact
+.It Li 1 Ta "\*[volume-ds-1]"
+.It Li 2 Ta "\*[volume-ds-2]"
+.It Li 3 Ta "\*[volume-ds-3]"
+.It Li 4 Ta "\*[volume-ds-4]"
+.It Li 5 Ta "\*[volume-ds-5]"
+.It Li 6 Ta "\*[volume-ds-6]"
+.It Li 7 Ta "\*[volume-ds-7]"
+.It Li 8 Ta "\*[volume-ds-8]"
+.It Li 9 Ta "\*[volume-ds-9]"
+.El
+.Pp
+.
+A volume name may be arbitrary or one of the following:
+.
+.Pp
+.Bl -column LOCAL -offset indent -compact
+.It Li USD Ta "\*[volume-ds-USD]"
+.It Li PS1 Ta "\*[volume-ds-PS1]"
+.It Li AMD Ta "\*[volume-ds-AMD]"
+.It Li SMM Ta "\*[volume-ds-SMM]"
+.It Li URM Ta "\*[volume-ds-URM]"
+.It Li PRM Ta "\*[volume-ds-PRM]"
+.It Li KM Ta "\*[volume-ds-KM]"
+.It Li IND Ta "\*[volume-ds-IND]"
+.It Li LOCAL Ta "\*[volume-ds-LOCAL]"
+.It Li CON Ta "\*[volume-ds-CON]"
+.El
+.Pp
+.
+For compatibility,
+.Ql MMI
+can be used for
+.Ql IND ,
+and
+.Ql LOC
+for
+.Ql LOCAL .
+Values from the previous table will specify a new volume name.
+If the third parameter is a keyword designating a computer architecture,
+its value is appended to the volume name as specified by the second
+parameter. By default, the following architecture keywords are defined:
+.
+\# we use `No' to avoid hyphenation
+.Bd -ragged -offset indent
+.No alpha , amiga , arc , arm26 , arm32 , atari , bebox , cobalt , evbsh3 ,
+.No hp300 , hpcmips , i386 , luna68k , m68k , mac68k , macppc , mips ,
+.No mmeye , mvme68k , news68k , newsmips , next68k , ofppc , pc532 , pmax ,
+.No powerpc , prep , sgimips , sh3 , sparc , sparc64 , sun3 , tahoe , vax ,
+.No x68k
+.Ed
+.Pp
+.
+In the following examples, the left (which is identical to the right) and
+the middle part of the manual page header strings are shown.
+.
+.Bd -ragged
+.Bl -tag -xwidth ".Li .Dt\ FOO\ 2\ mac68k" -compact -offset indent
+.It Li ".Dt FOO 7"
+.Ql FOO(7)
+.Ql System Reference Manual
+.It Li ".Dt FOO 2 mac68k"
+.Ql FOO(2)
+.Ql System Programmer's Manual (mac68k Architecture)
+.It Li ".Dt FOO \*[q]\*[q] bar"
+.Ql FOO
+.Ql bar
+.El
+.Ed
+.Pp
+.
+Local, OS-specific additions might be found in the file
+.Pa mdoc.local ;
+look for strings named
+.Ql volume-ds-XXX
+(for the former type) and
+.Ql volume-as-XXX
+(for the latter type);
+.Ql XXX
+then denotes the keyword to be used with the
+.Ql .Dt
+macro.
+.Pp
+This macro is neither callable nor parsed.
+.
+.It Li .Os Xo
+.Op Aq operating system
+.Op Aq release
+.Xc
+If the first parameter is empty,
+the default
+.Sq Tn "\*[operating-system]"
+is used.
+This may be overridden in the local configuration file,
+.Pa mdoc.local .
+In general, 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.
+In the following table, the possible second arguments for some predefined
+operating systems are listed.
+Similar to
+.Ql .Dt ,
+local additions might be defined in
+.Pa mdoc.local ;
+look for strings named
+.Ql operating-system-XXX-YYY ,
+where
+.Ql XXX
+is the acronym for the operating system and
+.Ql YYY
+the release ID.
+.
+.Bd -ragged -compact
+.Bl -tag -xwidth ".No FreeBSD" -offset indent
+.It ATT
+7th, 7, III, 3, V, V.2, V.3, V.4
+.It BSD
+3, 4, 4.1, 4.2, 4.3, 4.3t, 4.3T, 4.3r, 4.3R, 4.4
+.It NetBSD
+0.8, 0.8a, 0.9, 0.9a, 1.0, 1.0a, 1.1, 1.2, 1.2a, 1.2b, 1.2c, 1.2d, 1.2e,
+1.3, 1.3a, 1.4, 1.5
+.It FreeBSD
+1.0, 1.1, 1.1.5, 1.1.5.1, 2.0, 2.0.5, 2.1, 2.1.5, 2.1.6, 2.1.7, 2.2, 2.2.1,
+2.2.2, 2.2.5, 2.2.6, 2.2.7, 2.2.8, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 4.0, 4.1,
+4.2, 5.0
+.El
+.Ed
+.Pp
+.
+For
+.Tn ATT ,
+an unknown second parameter will be replaced with the string
+.Tn UNIX ;
+for the other predefined acronyms it will be ignored and a warning message
+emitted.
+Unrecognized arguments are displayed as given in the page footer.
+For instance, a typical footer might be:
+.Pp
+.Dl .Os BSD 4.3
+.Pp
+giving
+.Ql 4.3\~Berkeley Distribution ,
+or for a locally produced set
+.Pp
+.Dl .Os CS Department
+.Pp
+which will produce
+.Ql CS\~Department .
+.Pp
+If the
+.Ql .Os
+macro is not present, the bottom left corner of the manual page will be
+ugly.
+.Pp
+This macro is neither callable nor parsed.
+.
+.It Li .Dd Oo
+.Aq month
+.Aq day ,
+.Aq year
+.Oc
+If
+.Ql Dd
+has no arguments,
+.Ql Epoch
+is used for the date string.
+If it has exactly three arguments, they are concatenated, separated with
+unbreakable space:
+.Pp
+.Dl .Dd January 25, 2001
+.Pp
+Otherwise, the current date is used, ignoring the parameters.
+.Pp
+This macro is neither callable nor parsed.
+.El
+.
+.
+.Sh "INTRODUCTION OF MANUAL AND GENERAL TEXT DOMAINS"
+.
+.Ss "What's in a Name" Ns ...
+.
+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
+.Li ".Xx argument1 argument2" ...
+.Ed
+.Pp
+.
+.Ql .Xx
+is a macro command or request, and anything following it are arguments 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
+.Ao Ar infile Ac Ao Ar outfile Ac
+.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,
+.Ao Ar infile Ac
+and
+.Ao Ar outfile Ac
+are called
+.Em meta arguments ;
+in this example, the user has to replace the meta expressions given in angle
+brackets with real file names.
+Note that in this document meta arguments are used to describe
+.Nm \-mdoc
+commands; in most man pages, meta variables are not specifically written
+with angle brackets.
+The macros which formatted the above example:
+.
+.Bd -literal -offset indent
+\&.Nm filter
+\&.Op Fl flag
+\&.Ao Ar infile Ac Ao Ar outfile Ac
+.Ed
+.Pp
+.
+In the third case, discussion of commands and command syntax includes both
+examples above, but may add more detail.
+The arguments
+.Ao Ar infile Ac
+and
+.Ao Ar outfile Ac
+from the example above might be referred to as
+.Em operands
+or
+.Em file arguments .
+Some command line argument lists are quite long:
+.
+.Bd -ragged
+.Bl -tag -xwidth ".Nm make" -offset indent -compact
+.It 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 Ns = Ns Ar value
+.Bk
+.Op Ar target ...
+.Ek
+.El
+.Ed
+.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 Ns = Ns Ar value
+\&.Bk
+\&.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; most notably,
+.Ql .Ar ,
+.Ql .Fl ,
+.Ql .Nm ,
+and
+.Ql .Pa
+differ only when called without arguments; and
+.Ql .Fn
+and
+.Ql .Xr
+impose an order on their argument lists.
+All content macros are capable of recognizing and properly handling
+punctuation, provided each punctuation character is separated by a leading
+space.
+If a request is given:
+.Pp
+.Dl \&.Ar sptr, ptr),
+.Pp
+The result is:
+.Pp
+.Dl Ar sptr, ptr),
+.Pp
+The punctuation is not recognized and all is output in the
+font used by
+.Ql .Ar .
+If the punctuation is separated by a leading white space:
+.Pp
+.Dl \&.Ar "sptr , ptr ) ,"
+.Pp
+The result is:
+.Pp
+.Dl Ar sptr , ptr ) ,
+.Pp
+The punctuation is now recognized and output in the default font
+distinguishing it from the argument strings.
+To remove the special meaning from a punctuation character escape it with
+.Ql \e& .
+.Pp
+.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
-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.
+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 .
+.
+.
+.Sh "MANUAL DOMAIN"
+.
+.Ss Addresses
+.
+The address macro identifies an address construct.
+.Pp
+.Dl Usage: .Ad Ao address Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Ad\ f1\ ,\ f2\ ,\ f3\ :" -compact -offset 15n
+.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
+.
+The default width is 12n.
+.
+.Ss "Author Name"
+.
+The
+.Ql .An
+macro is used to specify the name of the author of the item being
+documented, or the name of the author of the actual manual page.
+.Pp
+.Dl Usage: .An Ao author name Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .An\ \*[q]Joe\ Author\*[q]\ )\ )\ ," -offset 15n
+.It Li ".An \*[q]Joe Author\*[q]"
+.An "Joe Author"
+.It Li ".An \*[q]Joe Author\*[q] ,"
+.An "Joe Author" ,
+.It Li ".An \*[q]Joe Author\*[q] Aq nobody@FreeBSD.org"
+.An "Joe Author" Aq nobody@FreeBSD.org
+.It Li ".An \*[q]Joe Author\*[q] ) ) ,"
+.An "Joe Author" ) ) ,
+.El
+.Pp
+.
+The default width is 12n.
+.Pp
+In the
+.Sx AUTHORS
+section, the
+.Ql .An
+request causes a line break allowing each new name to appear on its own
+line.
+If this is not desirable,
+.
+.Bd -literal -offset indent
+\&.An -nosplit
+.Ed
+.Pp
+.
+call will turn this off.
+To turn splitting back on, write
+.
+.Bd -literal -offset indent
+\&.An -split
+.Ed
+.
+.Ss "Arguments"
+.
+The
+.Li .Ar
+argument macro may be used whenever an argument is referenced.
+If called without arguments, the
+.Sq Ar
+string is output.
+.Pp
+.Dl Usage: .Ar Oo Ao argument Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .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
+.
+The default width is 12n.
+.
+.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.
+.Pp
+.Dl Usage: .Cd Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Cd\ Xdevice\ le0\ at\ scode?X" -offset 15n
+.It Li ".Cd \*[q]device le0 at scode?\*[q]"
+.Cd "device le0 at scode?"
+.El
+.Pp
+In the
+.Sx SYNOPSIS
+section a
+.Ql .Cd
+request causes a line break before and after its arguments are printed.
+.Pp
+.
+The default width is 12n.
+.
+.Ss "Command Modifiers"
+.
+The command modifier is identical to the
+.Ql .Fl
+(flag) command with the exception that the
+.Ql .Cm
+macro does not assert a dash in front of every argument.
+Traditionally flags are marked by the preceding dash, however, 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 .
+.Pp
+The default width is 10n.
+.
+.Ss "Defined Variables"
+.
+A variable (or constant) which is defined in an include file
+is specified by the macro
+.Ql .Dv .
+.Pp
+.Dl Usage: .Dv Ao defined variable Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Dv\ MAXHOSTNAMELEN" -compact -offset 15n
+.It Li ".Dv MAXHOSTNAMELEN"
+.Dv MAXHOSTNAMELEN
+.It Li ".Dv TIOCGPGRP )"
+.Dv TIOCGPGRP )
+.El
+.Pp
+.
+The default width is 12n.
+.
+.Ss Errno's
+.
+The
+.Ql .Er
+errno macro specifies the error return value for section 2, 3, and\~9 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 Ao errno type Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Bq\ Er\ ENOTDIR" -compact -offset 15n
+.It Li ".Er ENOENT"
+.Er ENOENT
+.It Li ".Er ENOENT ) ;"
+.Er ENOENT ) ;
+.It Li ".Bq Er ENOTDIR"
+.Bq Er ENOTDIR
+.El
+.Pp
+.
+The default width is 17n.
+.
+.Ss "Environment Variables"
+.
+The
+.Ql .Ev
+macro specifies an environment variable.
+.Pp
+.Dl Usage: .Ev Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Ev\ PRINTER\ )\ )\ ," -compact -offset 15n
+.It Li ".Ev DISPLAY"
+.Ev DISPLAY
+.It Li ".Ev PATH ."
+.Ev PATH .
+.It Li ".Ev PRINTER ) ) ,"
+.Ev PRINTER ) ) ,
+.El
+.Pp
+.
+The default width is 15n.
+.
+.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 Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Fl\ xyz\ )\ ," -compact -offset 15n
+.It Li .Fl
+.Fl
+.It Li ".Fl cfv"
+.Fl cfv
+.It Li ".Fl cfv ."
+.Fl cfv .
+.It Li ".Cm cfv ."
+.Cm cfv .
+.It Li ".Fl s v t"
+.Fl s v t
+.It Li ".Fl \- ,"
+.Fl \- ,
+.It Li ".Fl xyz ) ,"
+.Fl xyz ) ,
+.It Li ".Fl |"
+.Fl |
+.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.
+.Pp
+The default width is 12n.
+.
+.Ss "Function Declarations"
+.
+The
+.Ql .Fd
+macro is used in the
+.Sx SYNOPSIS
+section with section two or three functions.
+It is neither callable nor parsed.
+.Pp
+.Dl Usage: .Fd Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Fd\ X#include\ <sys/types.h>X" -compact -offset 15n
+.It Li ".Fd \*[q]#include <sys/types.h>\*[q]"
+.Fd "#include <sys/types.h>"
+.El
+.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.
+.
+.Pp
+The
+.Ql .In
+.Li ( #include
+statement)
+macro is the short form of the above example.
+It specifies the C\~header file as being included in a C\~program.
+It also causes a line break, and is neither callable nor parsed.
+.Pp
+.Dl Usage: .In Ao header file Ac
+.Pp
+.Bl -tag -xwidth ".Li .In\ stdio.h" -compact -offset 15n
+.It Li ".In stdio.h"
+.In stdio.h
+.El
+.
+.Ss "Function Types"
+.
+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 line break, allowing the function
+name to appear on the next line).
+.Pp
+.Dl Usage: .Ft Ao type Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Ft\ struct\ stat" -compact -offset 15n
+.It Li ".Ft struct stat"
+.Ft struct stat
+.El
+.
+.Ss "Functions (Library Routines)"
+.
+The
+.Ql .Fn
+macro is modeled on
+.Tn ANSI\~C
+conventions.
+.Pp
+.Dl Usage: .Fn Ao function Ac Oo Ao parameter Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Fn\ align\ Xchar\ *ptrX\ ," -compact -offset 15n
+.It Li ".Fn getchar"
+.Fn getchar
+.It Li ".Fn strlen ) ,"
+.Fn strlen ) ,
+.It Li ".Fn align \*[q]char *ptr\*[q] ,"
+.Fn align "char *ptr" ,
+.El
+.Pp
+Note that any call to another macro signals the end of the
+.Ql .Fn
+call (it will insert a closing parenthesis at that point).
+.Pp
+For functions with many parameters (which is rare), the macros
+.Ql .Fo
+(function open)
+and
+.Ql .Fc
+(function close)
+may be used with
+.Ql .Fa
+(function argument).
+.Pp
+Example:
+.
+.Bd -literal -offset indent
+\&.Ft int
+\&.Fo 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 -ragged -offset indent
+.Ft int
+.Fo 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
+.
+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.
+.Pp
+The default width values of
+.Ql .Fn
+and
+.Ql .Fo
+are 12n and 16n, respectively.
+.
+.Ss "Function Arguments"
+.
+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 if the enclosure macros
+.Ql .Fo
+and
+.Ql .Fc
+instead of
+.Ql .Fn
+are used.
+.Ql .Fa
+may also be used to refer to structure members.
+.Pp
+.Dl Usage: .Fa Ao function argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Fa\ d_namlen\ )\ )\ ," -compact -offset 15n
+.It Li ".Fa d_namlen ) ) ,"
+.Fa d_namlen ) ) ,
+.It Li ".Fa iov_len"
+.Fa iov_len
+.El
+.Pp
+.
+The default width is 12n.
+.
+.Ss "Return Values"
+.
+The
+.Ql .Rv
+macro generates text for use in the
+.Sx RETURN VALUES
+section.
+.Pp
+.Dl Usage: .Rv Oo -std Oc Ao function Ac ...
+.Pp
+For example,
+.Ql ".Rv -std atexit"
+produces:
+.
+.Bd -ragged -offset -indent
+\# a small hack to suppress a warning message
+.ds section-old "\*[section]
+.ds section 2
+.Rv -std atexit
+.ds section "\*[section-old]
+.Ed
+.Pp
+.
+The
+.Fl std
+option is valid only for manual page sections\~2 and\~3.
+Currently, this macro does nothing if used without the
+.Fl std
+flag.
+.
+.Ss "Interactive Commands"
+.
+The
+.Ql .Ic
+macro designates an interactive or internal command.
+.Pp
+.Dl Usage: .Ic Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Ic\ setenv\ ,\ unsetenv" -compact -offset 15n
+.It Li ".Ic :wq"
+.Ic :wq
+.It Li ".Ic \*[q]do while {...}\*[q]"
+.Ic "do while {...}"
+.It Li ".Ic setenv , unsetenv"
+.Ic setenv , unsetenv
+.El
+.Pp
+.
+The default width is 12n.
+.
+.Ss "Library Names"
+.
+The
+.Ql .Lb
+macro is used to specify the library where a particular function is compiled
+in.
+.Pp
+.Dl Usage: .Lb Ao argument Ac ...
+.Pp
+Available arguments to
+.Ql .Lb
+and their results are:
+.
+.Pp
+.Bl -tag -xwidth ".Li libossaudio" -compact -offset indent
+.It Li libarm32
+.Lb libarm32
+.It Li libc
+.Lb libc
+.It Li libcompat
+.Lb libcompat
+.It Li libcrypt
+.Lb libcrypt
+.It Li libcurses
+.Lb libcurses
+.It Li libedit
+.Lb libedit
+.It Li libi386
+.Lb libi386
+.It Li libipsec
+.Lb libipsec
+.It Li libkvm
+.Lb libkvm
+.It Li libm
+.Lb libm
+.It Li libmenu
+.Lb libmenu
+.It Li libossaudio
+.Lb libossaudio
+.It Li libposix
+.Lb libposix
+.It Li libresolv
+.Lb libresolv
+.It Li libtermcap
+.Lb libtermcap
+.It Li libutil
+.Lb libutil
+.It Li libz
+.Lb libz
+.El
+.Pp
+.
+Local, OS-specific additions might be found in the file
+.Pa mdoc.local ;
+look for strings named
+.Ql str-Lb-XXX .
+.Ql XXX
+then denotes the keyword to be used with the
+.Ql .Lb
+macro.
+.
+.Ss Literals
+.
+The
+.Ql .Li
+literal macro may be used for special characters, variable constants, etc.\&
+-- anything which should be displayed as it would be typed.
+.Pp
+.Dl Usage: .Li Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Li\ cntrl-D\ )\ ," -compact -offset 15n
+.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 default width is 16n.
+.
+.Ss Names
+.
+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.
+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
+.Ql .Ic
+is nearly identical
+to
+.Ql .Nm ,
+it can not recall the first argument it was invoked with.
+.Pp
+.Dl Usage: .Nm Oo Ao argument Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Nm\ groff_mdoc" -compact -offset 15n
+.It Li ".Nm groff_mdoc"
+.Nm groff_mdoc
+.It Li ".Nm \e-mdoc"
+.Nm \-mdoc
+.It Li ".Nm foo ) ) ,"
+.Nm foo ) ) ,
+.It Li ".Nm :"
+.Nm :
+.El
+.Pp
+.
+The default width is 10n.
+.
+.Ss Options
+.
+The
+.Ql .Op
+macro places option brackets around any remaining arguments on the
+command line, and places any trailing punctuation outside the brackets.
+The macros
+.Ql .Oo
+and
+.Ql .Oc
+(which produce an opening and a closing option bracket respectively) may be used
+across one or more lines or to specify the exact position of the closing
+parenthesis.
+.Pp
+.Dl Usage: .Op Oo Ao option Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Op\ Fl\ c\ Ar\ objfil\ Op\ Ar\ corfil\ ," -compact -offset 15n
+.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
+.It Li ".Li .Op Oo Ao option Ac Oc ..."
+.Li .Op Oo Ao options Ac Oc ...
+.El
+.Pp
+Here a typical example of the
+.Ql .Oo
+and
+.Ql .Oc
+macros:
+.
+.Bd -literal -offset indent
+\&.Oo
+\&.Op Fl k Ar kilobytes
+\&.Op Fl i Ar interval
+\&.Op Fl c Ar count
+\&.Oc
+.Ed
+.Pp
+.
+Produces:
+.
+.Bd -filled -offset indent
+.Oo
+.Op Fl k Ar kilobytes
+.Op Fl i Ar interval
+.Op Fl c Ar count
+.Oc
+.Ed
+.Pp
+.
+The default width values of
+.Ql .Op
+and
+.Ql .Oo
+are 14n and 10n, respectively.
+.
+.Ss Pathnames
+.
+The
+.Ql .Pa
+macro formats path or file names.
+If called without arguments, the
+.Sq Pa
+string is output, which represents the current user's home directory.
+.Pp
+.Dl Usage: .Pa Oo Ao pathname Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Pa\ /tmp/fooXXXXX\ )\ ." -compact -offset 15n
+.It Li .Pa
+.Pa
+.It Li ".Pa /usr/share"
+.Pa /usr/share
+.It Li ".Pa /tmp/fooXXXXX ) ."
+.Pa /tmp/fooXXXXX ) .
+.El
+.Pp
+.
+The default width is 32n.
+.
+.Ss Standards
+.
+The
+.Ql .St
+macro replaces standard abbreviations with their formal names.
+.Pp
+.Dl Usage: .St Ao abbreviation Ac ...
+.Pp
+Available pairs for
+.Dq Abbreviation/Formal Name
+are:
+.
+.Pp
+.Tn ANSI/ISO C
+.Pp
+.Bl -tag -xwidth ".Li -iso9945-1-90" -compact -offset indent
+.It Li -ansiC
+.St -ansiC
+.It Li -ansiC-89
+.St -ansiC-89
+.It Li -isoC
+.St -isoC
+.It Li -isoC-99
+.St -isoC-99
+.El
+.Pp
+.
+.Tn POSIX
+Part 1: System API
+.Pp
+.Bl -tag -xwidth ".Li -p1003.1g-2000" -compact -offset indent
+.It Li -iso9945-1-90
+.St -iso9945-1-90
+.It Li -iso9945-1-96
+.St -iso9945-1-96
+.It Li -p1003.1
+.St -p1003.1
+.It Li -p1003.1-88
+.St -p1003.1-88
+.It Li -p1003.1-90
+.St -p1003.1-90
+.It Li -p1003.1-96
+.St -p1003.1-96
+.It Li -p1003.1b-93
+.St -p1003.1b-93
+.It Li -p1003.1c-95
+.St -p1003.1c-95
+.It Li -p1003.1g-2000
+.St -p1003.1g-2000
+.It Li -p1003.1i-95
+.St -p1003.1i-95
+.El
+.Pp
+.
+.Tn POSIX
+Part 2: Shell and Utilities
+.Pp
+.Bl -tag -xwidth ".Li -p1003.1g-2000" -compact -offset indent
+.It Li -iso9945-2-93
+.St -iso9945-2-93
+.It Li -p1003.2
+.St -p1003.2
+.It Li -p1003.2-92
+.St -p1003.2-92
+.It Li -p1003.2a-92
+.St -p1003.2a-92
+.El
+.Pp
+.
+X/Open
+.Bl -tag -xwidth ".Li -p1003.1g-2000" -compact -offset indent
+.Pp
+.It Li -susv2
+.St -susv2
+.It Li -svid4
+.St -svid4
+.It Li -xbd5
+.St -xbd5
+.It Li -xcu5
+.St -xcu5
+.It Li -xcurses4.2
+.St -xcurses4.2
+.It Li -xns5
+.St -xns5
+.It Li -xns5.2
+.St -xns5.2
+.It Li -xpg3
+.St -xpg3
+.It Li -xpg4
+.St -xpg4
+.It Li -xpg4.2
+.St -xpg4.2
+.It Li -xsh5
+.St -xsh5
+.El
+.Pp
+.
+Miscellaneous
+.Pp
+.Bl -tag -xwidth ".Li -p1003.1g-2000" -compact -offset indent
+.It Li -ieee754
+.St -ieee754
+.It Li -iso8802-3
+.St -iso8802-3
+.El
+.
+.Ss "Variable Types"
+.
+The
+.Ql .Vt
+macro may be used whenever a type is referenced.
+In the
+.Sx SYNOPSIS
+section, it causes a line break (useful for old style variable declarations).
+.Pp
+.Dl Usage: .Vt Ao type Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Vt\ extern\ char\ *optarg\ ;" -compact -offset 15n
+.It Li ".Vt extern char *optarg ;"
+.Vt extern char *optarg ;
+.It Li ".Vt FILE *"
+.Vt FILE *
+.El
+.
+.Ss Variables
+.
+Generic variable reference.
+.Pp
+.Dl Usage: .Va Ao variable Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Va\ Xchar\ sX\ ]\ )\ )\ ," -compact -offset 15n
+.It Li ".Va count"
+.Va count
+.It Li ".Va settimer ,"
+.Va settimer ,
+.It Li ".Va \*[q]int *prt\*[q] ) :"
+.Va "int *prt" ) :
+.It Li ".Va \*[q]char s\*[q] ] ) ) ,"
+.Va "char s" ] ) ) ,
+.El
+.Pp
+.
+The default width is 12n.
+.
+.Ss "Manual Page Cross References"
+.
+The
+.Ql .Xr
+macro expects the first argument to be a manual page name.
+The optional second argument, if a string (defining the manual section), is
+put into parentheses.
+.Pp
+.Dl Usage: .Xr Ao man page name Ac Oo Ao section Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Xr\ xinit\ 1x\ ;" -compact -offset 15n
+.It Li ".Xr mdoc"
+.Xr mdoc
+.It Li ".Xr mdoc ,"
+.Xr mdoc ,
+.It Li ".Xr mdoc 7"
+.Xr mdoc 7
+.It Li ".Xr xinit 1x ;"
+.Xr xinit 1x ;
+.El
+.Pp
+.
+The default width is 10n.
+.
+.
+.Sh "GENERAL TEXT DOMAIN"
+.
+.Ss "AT&T Macro"
+.
+.Pp
+.Dl Usage: .At Oo Ao version Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .At\ v6\ ." -compact -offset 15n
+.It Li .At
+.At
+.It Li ".At v6 ."
+.At v6 .
+.El
+.Pp
+The following values for
+.Ao version Ac
+are possible:
+.Pp
+.Dl 32v, v1, v2, v3, v4, v5, v6, v7, V, V.1, V.2, V.3, V.4
+.
+.Ss "BSD Macro"
+.
+.Pp
+.Dl "Usage: .Bx" Bro -alpha | -beta | -devel Brc ...
+.Dl " .Bx" Oo Ao version Ac Oo Ao release Ac Oc Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Bx\ -devel" -compact -offset 15n
+.It Li .Bx
+.Bx
+.It Li ".Bx 4.3 ."
+.Bx 4.3 .
+.It Li ".Bx \-devel"
+.Bx -devel
+.El
+.Pp
+.Ao version Ac
+will be prepended to the string
+.Sq Bx .
+The following values for
+.Ao release Ac
+are possible:
+.Pp
+.Dl Reno, reno, Tahoe, tahoe, Lite, lite, Lite2, lite2
+.
+.Ss "NetBSD Macro"
+.
+.Pp
+.Dl Usage: .Nx Oo Ao version Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Nx\ 1.4\ ." -compact -offset 15n
+.It Li .Nx
+.Nx
+.It Li ".Nx 1.4 ."
+.Nx 1.4 .
+.El
+.Pp
+For possible values of
+.Ao version Ac
+see the description of the
+.Ql .Os
+request above in section
+.Sx "TITLE MACROS" .
+.
+.Ss "FreeBSD Macro"
+.
+.Pp
+.Dl Usage: .Fx Oo Ao version Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Fx\ 2.2\ ." -compact -offset 15n
+.It Li .Fx
+.Fx
+.It Li ".Fx 2.2 ."
+.Fx 2.2 .
+.El
+.Pp
+For possible values of
+.Ao version Ac
+see the description of the
+.Ql .Os
+request above in section
+.Sx "TITLE MACROS" .
+.
+.Ss "OpenBSD Macro"
+.
+.Pp
+.Dl Usage: .Ox Oo Ao version Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Ox\ 1.0" -compact -offset 15n
+.It Li ".Ox 1.0"
+.Ox 1.0
+.El
+.
+.Ss "BSD/OS Macro"
+.
+.Pp
+.Dl Usage: .Bsx Oo Ao version Ac Oc ...
+.Pp
+.Bl -tag -xwidth ".Li .Bsx\ 1.0" -compact -offset 15n
+.It Li ".Bsx 1.0"
+.Bsx 1.0
+.El
+.
+.Ss "UNIX Macro"
+.
+.Pp
+.Dl Usage: .Ux ...
+.Pp
+.Bl -tag -xwidth ".Li .Ux" -compact -offset 15n
+.It Li .Ux
+.Ux
+.El
+.
+.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 Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Em\ vide\ infra\ )\ )\ ," -compact -offset 15n
+.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 default width is 10n.
+.
+.Ss "Font Mode"
+.
+The
+.Ql .Bf
+font mode must be ended with the
+.Ql .Ef
+macro (the latter takes no arguments).
+Font modes may be nested within other font modes.
+.Pp
+.Ql .Bf
+has the following syntax:
+.Pp
+.Dl .Bf Ao font mode Ac
+.Pp
+.Ao font mode Ac
+must be one of the following three types:
+.Pp
+.Bl -tag -xwidth ".Sy \&Sy | Fl symbolic" -compact -offset indent
+.It Sy \&Em | Fl emphasis
+Same as if the
+.Ql .Em
+macro was used for the entire block of text.
+.It Sy \&Li | Fl literal
+Same as if the
+.Ql .Li
+macro was used for the entire block of text.
+.It Sy \&Sy | Fl symbolic
+Same as if the
+.Ql .Sy
+macro was used for the entire block of text.
+.El
+.Pp
+Both macros are neither callable nor parsed.
+.
+.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.
+.Pp
+\# XXX
+.if t \
+. ne 10
+.
+.Bd -filled -offset 4n
+.Bl -column "quote" "close" "open" "Angle Bracket Enclosure" "`string' or string"
+.Em Quote Ta Em Open Ta Em Close Ta Em Function Ta Em Result
+.No .Aq Ta .Ao Ta .Ac Ta "Angle Bracket Enclosure" Ta Ao string Ac
+.No .Bq Ta .Bo Ta .Bc Ta "Bracket Enclosure" Ta Bo string Bc
+.No .Brq Ta .Bro Ta .Brc Ta "Brace Enclosure" Ta Bro string Brc
+.No .Dq Ta .Do Ta .Dc Ta "Double Quote" Ta Do string Dc
+.No .Eq Ta .Eo Ta .Ec Ta "Enclose String (in XX)" Ta XXstringXX
+.No .Pq Ta .Po Ta .Pc Ta "Parenthesis Enclosure" Ta Po string Pc
+.No .Ql Ta Ta Ta "Quoted Literal" Ta So string Sc or Li string
+.No .Qq Ta .Qo Ta .Qc Ta "Straight Double Quote" Ta Qo string Qc
+.No .Sq Ta .So Ta .Sc Ta "Single Quote" Ta So string Sc
+.El
+.Ed
+.Pp
+All macros ending with
+.Sq q
+and
+.Sq o
+have a default width value of 12n.
+.
+.Bl -tag -xwidth ".Li .Ec , .Eo"
+.It Li .Eo , .Ec
+These macros expect the first argument to be the opening and closing strings
+respectively.
+.It Li .Es , .En
+Due to the nine-argument limit in the original troff program two other
+macros have been implemented which are now rather obsolete:
+.Ql .Es
+takes the first and second parameter as the left and right enclosure string,
+which are then used to enclose the arguments of
+.Ql .En .
+The default width value is 12n for both macros.
+.It Li .Eq
+The first and second arguments of this macro are the opening and
+closing strings respectively, followed by the arguments to be enclosed.
+.It Li .Ql
+The quoted literal macro behaves differently in troff and nroff mode.
+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.
+.Pp
+The default width is 16n.
+.It Li .Pf
+The prefix macro suppresses the whitespace between its first and second
+argument:
+.
+.Bl -tag -xwidth ".Li .Pf\ (\ Fa\ name2" -offset indent
+.It Li ".Pf ( Fa name2"
+.Pf ( Fa name2
+.El
+.Pp
+.
+The default width is 12n.
+.Pp
+The
+.Ql .Ns
+macro (see below) performs the analogous suffix function.
+.It Li .Ap
+The
+.Ql .Ap
+macro inserts an apostrophe and exits any special text modes, continuing in
+.Ql .No
+mode.
+.El
+.Pp
+.
+Examples of quoting:
+.
+.Pp
+.Bl -tag -xwidth ".Li .Bq\ Em\ Greek\ ,\ French\ ." -compact -offset indent
+.It Li .Aq
+.Aq
+.It Li ".Aq Pa ctype.h ) ,"
+.Aq Pa 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 are discussed below.
+.
+.Ss "No-Op or Normal Text Macro"
+.
+The
+.Ql .No
+macro can be used in a macro command line for parameters which should
+.Em not
+be formatted.
+Be careful to add
+.Ql \e&
+to the word
+.Ql \&No
+if you really want that English word (and not the macro) as a parameter.
+.Pp
+.Dl Usage: .No Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .No\ test\ Ta\ with\ Ta\ tabs" -compact -offset 15n
+.It Li ".No test Ta with Ta tabs"
+.No test Ta with Ta tabs
+.El
+.Pp
+.
+The default width is 12n.
+.
+.Ss "No-Space Macro"
+.
+The
+.Ql .Ns
+macro suppresses insertion of a space between the current position and its
+first parameter.
+For example, it is useful for old style argument lists where there is no
+space between the flag and argument:
+.Pp
+.Dl "Usage:" ... Ao argument Ac \&Ns Oo Ao argument Ac Oc ...
+.Dl " " .Ns Ao argument Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Op\ Fl\ I\ Ns\ Ar\ directory" -compact -offset 15n
+.It Li ".Op Fl I Ns Ar directory"
+.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.
+If used as a request (i.e., the second form above in the
+.Sq Usage
+line,
+.Ql .Ns
+is identical to
+.Ql .No .
+.
+.Ss "Section Cross References"
+.
+The
+.Ql .Sx
+macro designates a reference to a section header within the same document.
+.Pp
+.Dl Usage: .Sx Ao section reference Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Sx\ FILES" -offset 15n
+.It Li ".Sx FILES"
+.Sx FILES
+.El
+.Pp
+.
+The default width is 16n.
+.
+.Ss Symbolics
+.
+The symbolic emphasis macro is generally a boldface macro in either the
+symbolic sense or the traditional English usage.
+.Pp
+.Dl Usage: .Sy Ao symbol Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Sy\ Important\ Notice" -compact -offset 15n
+.It Li ".Sy Important Notice"
+.Sy Important Notice
+.El
+.Pp
+.
+The default width is 6n.
+.
+.Ss Mathematical Symbols
+.
+Use this macro for mathematical symbols and similar things.
+.Pp
+.Dl Usage: .Ms Ao math symbol Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Ms\ sigma" -compact -offset 15n
+.It Li ".Ms sigma"
+.Ms sigma
+.El
+.Pp
+.
+The default width is 6n.
+.
+.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
+.Xr refer 1
+style references.
+.Pp
+.Bl -tag -width 6n -offset indent -compact
+.It Li .Rs
+Reference start (does not take arguments).
+Causes a line break in the
+.Sx "SEE ALSO"
+section and begins collection of reference information until the reference
+end macro is read.
+.It Li .Re
+Reference end (does not take arguments).
+The reference is printed.
+.It Li .%A
+Reference author name; one name per invocation.
+.It Li .%B
+Book title.
+.It Li .%C
+City/place (not implemented yet).
+.It Li .%D
+Date.
+.It Li .%I
+Issuer/publisher name.
+.It Li .%J
+Journal name.
+.It Li .%N
+Issue number.
+.It Li .%O
+Optional information.
+.It Li .%P
+Page number.
+.It Li .%Q
+Corporate or foreign author.
+.It Li .%R
+Report name.
+.It Li .%T
+Title of article.
+.It Li .%V
+Volume.
+.El
+.Pp
+Macros beginning with
+.Ql %
+are not callable but accept multiple arguments in the usual way.
+Only the
+.Ql .Tn
+macro is handled properly as a parameter; other macros will cause strange
+output.
+.Ql .%B
+and
+.Ql .%T
+can be used outside of the
+.Ql .Rs/.Re
+environment.
+.Pp
+Example:
+.
+.Bd -literal -offset indent
+\&.Rs
+\&.%A "Matthew Bar"
+\&.%A "John Foo"
+\&.%T "Implementation Notes on foobar(1)"
+\&.%R "Technical Report ABC-DE-12-345"
+\&.%Q "Drofnats College, Nowhere"
+\&.%D "April 1991"
+\&.Re
+.Ed
+.Pp
+produces
+.
+.Bd -ragged -offset indent
+.Rs
+.%A "Matthew Bar"
+.%A "John Foo"
+.%T "Implementation Notes on foobar(1)"
+.%R "Technical Report ABC-DE-12-345"
+.%Q "Drofnats College, Nowhere"
+.%D "April 1991"
+.Re
+.Ed
+.
+.Ss "Trade Names (or Acronyms and Type Names)"
+.
+The trade name macro prints its arguments in a smaller font.
+Its intended use is to imitate a small caps fonts for uppercase acronyms.
+.Pp
+.Dl Usage: .Tn Ao symbol Ac ...
+.Pp
+.Bl -tag -xwidth ".Li .Tn\ ASCII" -compact -offset 15n
+.It Li ".Tn DEC"
+.Tn DEC
+.It Li ".Tn ASCII"
+.Tn ASCII
+.El
+.Pp
+.
+The default width is 10n.
+.
+.Ss "Extended Arguments"
+.
+The
+.Li .Xo
+and
+.Li .Xc
+macros allow one to extend an argument list on a macro boundary for the
+.Ql .It
+macro (see below).
+Note that
+.Li .Xo
+and
+.Li .Xc
+are implemented similarly to all other macros opening and closing an
+enclosure (without inserting characters, of course).
+This means that the following is true for those macros also.
+.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 -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 -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 enclosure macros: Test the value of a variable.
+.
+.Bd -literal -offset indent
+\&.It Xo
+\&.Ic .ifndef
+\&.Oo \e&! Oc Ns Ar variable Oo
+\&.Ar operator variable ...
+\&.Oc Xc
+.Ed
+.Pp
+.
+produces
+.
+.Bd -filled -offset indent
.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
+.It Xo
+.Ic .ifndef
+.Oo \&! Oc Ns Ar variable Oo
+.Ar operator variable ...
+.Oc Xc
+.El
+.Ed
+.Pp
+.
+.
+.Sh "PAGE STRUCTURE DOMAIN"
+.
+.Ss "Section Headers"
+.
+The following
+.Ql .Sh
+section header macros 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 is parsed but not generally callable.
+It can be used as an argument in a call to
+.Ql .Sh
+only; it then reactivates the default font for
+.Ql .Sh .
+.Pp
+The default width is 8n.
+.
+.Bl -tag -xwidth ".Li .Sh\ RETURN\ VALUES"
+.It Li ".Sh NAME"
+The
+.Ql ".Sh NAME"
+macro is mandatory.
+If not specified, 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.
+.Pp
+.Ql .Nd
+first prints
+.Ql - ,
+then all its arguments.
+.
+.It Li ".Sh LIBRARY"
+This section is for section two and three function calls.
+It should consist of a single
+.Ql .Lb
+macro call;
+see
+.Sx "Library Names" .
+.
+.It Li ".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 ,
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
+.Ql .Fn
+(and possibly
+.Ql .Fo ,
+.Ql .Fc ,
+.Ql .Fd ,
+and
+.Ql .Ft ) .
+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, and\~8.
+Section\~4 manuals require a
+.Ql .Nm ,
+.Ql .Fd
+or a
+.Ql .Cd
+configuration device usage macro.
+Several other macros may be necessary to produce the synopsis line as shown
+below:
+.
+.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
+.
+.It Li ".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).
+.
+.It Li ".Sh IMPLEMENTATION NOTES"
+Implementation specific information should be placed here.
+.
+.It Li ".Sh RETURN VALUES"
+Sections 2, 3 and\~9 function return values should go here.
+The
+.Ql .Rv
+macro may be used to generate text for use in the
+.Sx RETURN VALUES
+section for most section 2 and 3 library functions;
+see
+.Sx "Return Values" .
+.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 -xwidth ".Li .Sh\ COMPATIBILITY"
+.It Li ".Sh ENVIRONMENT"
+The
+.Sx ENVIRONMENT
+section should reveal any related environment variables and clues to their
+behavior and/or usage.
+.
+.It Li ".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 Li ".Sh EXAMPLES"
+There are several ways to create examples.
+See the
+.Sx EXAMPLES
+section below for details.
+.
+.It Li ".Sh DIAGNOSTICS"
+Diagnostic messages from a command should be placed in this section.
+.
+.It Li ".Sh COMPATIBILITY"
+Known compatibility issues (e.g. deprecated options or parameters)
+should be listed here.
+.
+.It Li ".Sh ERRORS"
+Specific error handling, especially from library functions (man page
+sections 2, 3, and\~9) should go here.
+The
+.Ql .Er
+macro is used to specify an error (errno).
+.
+.It Li ".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.
+Currently
+.Xr refer 1
+style references are not accommodated.
+.Pp
+It is recommended that the cross references are sorted on the section
+number, then alphabetically on the names within a section, and placed
+in that order and comma separated.
+Example:
+.Pp
+.Xr ls 1 ,
+.Xr ps 1 ,
+.Xr group 5 ,
+.Xr passwd 5
+.
+.It Li ".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 Li ".Sh HISTORY"
+Any command which does not adhere to any specific standards should be
+outlined historically in this section.
+.
+.It Li ".Sh AUTHORS"
+Credits should be placed here.
+The
+.Ql .An
+macro should be used to specify the name(s) of the person(s).
+.
+.It Li ".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 15n
+\&.Sh "PAGE STRUCTURE DOMAIN"
+.Ed
+.
+.Ss "Subsection Headers"
+.
+Subsection headers have exactly the same syntax as section headers:
+.Ql .Ss
+is parsed but not generally callable.
+It can be used as an argument in a call to
+.Ql .Ss
+only; it then reactivates the default font for
+.Ql .Ss .
+.Pp
+The default width is 8n.
+.
+.Ss "Paragraphs and Line Spacing"
+.
+.Bl -tag -xwidth ".Li .Pp"
+.It Li .Pp
+The
+.Ql .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
+or
+.Ql .Bd
+macro (which both assert a vertical distance unless the
+.Fl compact
+flag is given).
+.Pp
+The macro is neither callable nor parsed and takes no arguments; an
+alternative name is
+.Ql .Lp .
+.El
+.
+.\" XXX
+.
+.\" 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 .Bk
+accepts currently is
+.Fl words
+(this is also the default if no option is given) which 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.
+.Pp
+Both macros are neither callable nor parsed.
+.Pp
+More work needs to be done with the keep macros; specifically, a
+.Fl line
+option should be added.
+.
+.Ss "Examples and Displays"
+.
+There are seven types of displays.
+.Pp
+.Bl -tag -xwidth ".Li .D1"
+.It Li .D1
+(This is D-one.)
+Display one line of indented text.
+This macro is parsed but not callable.
+.Pp
+.D1 Fl ldghfstru
+.Pp
+The above was produced by:
+.Li ".D1 Fl ldghfstru" .
+.
+.It Li .Dl
+(This is D-ell.)
+Display one line of indented
+.Em literal
+text.
+The
+.Ql .Dl
+example macro has been used throughout this file.
+It allows the indentation (display) of one line of text.
+Its default font is set to constant width (literal).
+.Ql .Dl
+is parsed but not callable.
+.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.
+It has the following syntax:
+.Pp
+.Bl -tag -xwidth ".Li .Bd" -offset indent
+.It Li .Bd Xo
+.Bro \-literal | \-filled | \-unfilled | \-ragged | \-centered Brc
+.Oo \-offset Ao string Ac Oc Oo \-file Ao file name Ac Oc Oo \-compact Oc Xc
+.El
+.Pp
+.
+.Bl -tag -xwidth ".Fl file Ao Ar file name Ac " -compact
.It Fl ragged
-Unjustified (ragged edges).
-.It Fl filled
-Filled, and if
-.Xr troff 1 ,
-also justified.
+Fill, but do not adjust the right margin (only left-justify).
+.It Fl centered
+Center lines between the current left and right margin.
+Note that each single line is centered.
.It Fl unfilled
-Unfilled, unjustified.
+Do not fill; display a block of text as typed, using line breaks as
+specified by the user.
+This can produce overlong lines without warning messages.
+.It Fl filled
+Display a filled block.
+The block of text is formatted (i.e., the text is justified on both the left
+and right side).
.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
+Display block with literal font (usually fixed-width).
+Useful for source code or simple tabbed or spaced text.
+.It Fl file Ao Ar file name Ac
+The file whose name follows the
+.Fl file
+flag is read and displayed before any data enclosed with
+.Ql .Bd
+and
+.Ql .Ed ,
+using the selected display type.
+Any
+.Xr troff/ Ns Nm \-mdoc
+commands in the file will be processed.
+.It Fl offset Ao Ar string Ac
+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 -xwidth ".Ar indent-two" -compact
.It Ar left
-Align block on left (default).
+Align block on the current left margin; this is the default mode of
+.Ql .Bd .
.It Ar center
-Approximate center margin.
+Supposedly center the block.
+At this time unfortunately, the block merely gets left aligned about an
+imaginary center margin.
.It Ar indent
-Six constant width spaces (a tab).
+Indent by one default indent value or tab.
+The default indent value is also used for the
+.Ql .D1
+and
+.Ql .Dl
+macros, so one is guaranteed the two types of displays will line up.
+The indentation value is normally set to\~6n or about two thirds of an inch
+(six constant width characters).
.It Ar indent-two
-Two tabs.
+Indent two times the default indent value.
.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
+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 within
+.Xr troff .
.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.
+.Pp
+.
+If
+.Ao string Ac
+is a valid numeric expression instead
+.Pf ( Em with a scale indicator other than
+.Sq Em u ) ,
+use that value for indentation.
+The most useful scale indicators are
+.Sq m
+and
+.Sq n ,
+specifying the so-called
+.Em \&Em
+and
+.Em "En square" .
+This is approximately the width of the letter
+.Sq m
+resp.\& the letter
+.Sq n
+of the current font (for nroff output, both scale indicators give the same
+values).
+If
+.Ao string Ac
+isn't a numeric expression, it is tested whether it is an
+.Nm \-mdoc
+macro name, and the default offset value associated with this macro is used.
+Finally, if all tests fail,
+the width of
+.Ao string Ac
+(typeset with a fixed-width font) is taken as the offset.
.It Fl compact
-(All lists.)
-Suppresses blank lines.
+Suppress insertion of vertical space before begin of display.
.El
+.
+.It Li .Ed
+End display (takes no arguments).
.El
-.It Li \&.El
-End-list.
-.It Li \&.It
-List item.
+.
+.Ss "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 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
+.Pf ( Fl tag ) .
+.Pp
+It has the following syntax forms:
+.
+.Pp
+.Bl -tag -xwidth ".Li .Bl" -offset indent -compact
+.It Li .Bl Xo
+.Bro \-hang | \-ohang | \-tag | \-diag | \-inset Brc
+.Oo \-width Ao string Ac Oc Oo \-xwidth Ao command Ac Oc
+.Oo \-offset Ao string Ac Oc Oo \-compact Oc Xc
+.It Li .Bl Xo
+.No \-column Oo \-offset Ao string Ac Oc
+.Ao string1 Ac Ao string2 Ac ... Xc
+.It Li .Bl Xo
+.Bro \-item | \-enum Oo \-nested Oc | \-bullet | \-hyphen | \-dash Brc
+.Oo \-offset Ao string Ac Oc Oo \-compact Oc Xc
.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
+.Pp
+.
+And now a detailed description of the list types.
+.
+.Pp
+.Bl -tag -xwidth ".Fl column" -compact
+.It Fl bullet
+A bullet list.
+.
+.Bd -literal -offset indent
+\&.Bl -bullet -offset indent -compact
+\&.It
+Bullet one goes here.
+\&.It
+Bullet two here.
+\&.El
+.Ed
+.Pp
+.
+Produces:
+.
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+Bullet one goes here.
+.It
+Bullet two here.
.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
+.
+.It Fl dash No ( or Fl hyphen )
+A dash list.
+.
+.Bd -literal -offset indent
+\&.Bl -dash -offset indent -compact
+\&.It
+Dash one goes here.
+\&.It
+Dash two here.
+\&.El
+.Ed
+.Pp
+.
+Produces:
+.
+.Pp
+.Bl -dash -offset indent -compact
+.It
+Dash one goes here.
+.It
+Dash two here.
+.El
+.Pp
+.
+.It Fl enum
+An enumerated list.
+.
+.Bd -literal -offset indent
+\&.Bl -enum -offset indent -compact
+\&.It
+Item one goes here.
+\&.It
+And item two here.
+\&.El
+.Ed
+.Pp
+.
+The result:
+.
+.Pp
+.Bl -enum -offset indent -compact
+.It
+Item one goes here.
+.It
+And item two here.
+.El
+.Pp
+.
+If you want to nest enumerated lists, use the
+.Fl nested
+flag (starting with the second-level list):
+.
+.Bd -literal -offset indent
+\&.Bl -enum -offset indent -compact
+\&.It
+Item one goes here
+\&.Bl -enum -nested -compact
+\&.It
+Item two goes here.
+\&.It
+And item three here.
+\&.El
+\&.It
+And item four here.
+\&.El
+.Ed
+.Pp
+.
+Result:
+.
+.Pp
+.Bl -enum -offset indent -compact
+.It
+Item one goes here.
+.Bl -enum -nested -compact
+.It
+Item two goes here.
+.It
+And item three here.
+.El
+.It
+And item four here.
+.El
+.Pp
+.
+.It Fl item
+A list of type
+.Fl item
+without list markers.
+.
+.Bd -literal -offset indent
+\&.Bl -item -offset indent
+\&.It
+Item one goes here.
+Item one goes here.
+Item one goes here.
+\&.It
+Item two here.
+Item two here.
+Item two here.
+\&.El
+.Ed
+.Pp
+.
+Produces:
+.
+.Pp
+.Bl -item -offset indent
+.It
+Item one goes here.
+Item one goes here.
+Item one goes here.
+.It
+Item two here.
+Item two here.
+Item two here.
+.El
+.Pp
+.
+.It Fl tag
+A list with tags.
+Use
+.Fl width
+or
+.Fl xwidth
+to specify the tag width.
+.
+.Pp
+.Bl -tag -width "PPID" -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 priority
+(non-positive when in non-interruptible wait)
+.El
+.Pp
+.
+The raw text:
+.
+.Bd -literal -offset indent
+\&.Bl -tag -width "PPID" -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 priority
+(non-positive when in non-interruptible wait)
+\&.El
+.Ed
+.Pp
+.
+.It Fl diag
+Diag lists create section four diagnostic lists and are similar to inset
+lists except callable macros are ignored.
+The flags
+.Fl width
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 .
+.Fl xwidth
+are not meaningful in this context.
+.Pp
+Example:
+.
+.Bd -literal -offset indent
+\&.Bl -diag
+\&.It You can't use Sy here.
+The message says all.
+\&.El
+.Ed
+.Pp
+.
+produces
+.
+.Bl -diag
+.It You can't use Sy here.
+The message says all.
+.El
+.Pp
+.
+.It Fl hang
+A list with hanging tags.
+.
+.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 into 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 into the paragraph unlike
+tagged paragraph labels.
+\&.El
+.Ed
+.Pp
+.
+.It Fl ohang
+Lists with overhanging tags do not use indentation for the items; tags are
+written to a separate line.
+.Pp
+.Bl -ohang -offset indent
+.It Sy SL
+sleep time of the process (seconds blocked)
+.It Sy PAGEIN
+number of disk
+.Tn I/O Ns 's
+resulting from references by the process
+to pages not loaded in core.
+.It Sy UID
+numerical user-id of process owner
+.It Sy PPID
+numerical id of parent of process priority
+(non-positive when in non-interruptible wait)
+.El
+.Pp
+.
+The raw text:
+.
+.Bd -literal -offset indent
+\&.Bl -ohang -offset indent
+\&.It Sy SL
+sleep time of the process (seconds blocked)
+\&.It Sy PAGEIN
+number of disk
+\&.Tn I/O Ns 's
+resulting from references by the process
+to pages not loaded in core.
+\&.It Sy UID
+numerical user-id of process owner
+\&.It Sy PPID
+numerical id of parent of process priority
+(non-positive when in non-interruptible wait)
+\&.El
+.Ed
+.Pp
+.
+.It Fl inset
+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
+.
+.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.
+.Pp
+The table:
+.
+.Bl -column -offset indent String Nroff Troff
+.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 -offset indent String Nroff Troff
+\&.It Sy String Ta Sy Nroff Ta Sy Troff
+\&.It Li <= Ta <= Ta \e*(<=
+\&.It Li >= Ta >= Ta \e*(>=
+\&.El
+.Ed
+.El
+.Pp
+.
+Other keywords:
+.
+.Bl -tag -xwidth ".Fl indent Ao Ar string Ac"
+.It Fl width Ao Ar string Ac
+If
+.Ao string Ac
+is a valid numeric expression
+.Pf ( Em with a scale indicator other than
+.Sq Em u ) ,
+use that value for indentation.
+The most useful scale indicators are
+.Sq m
+and
+.Sq n ,
+specifying the so-called
+.Em \&Em
+and
+.Em "En square" .
+This is approximately the width of the letter
+.Sq m
+resp.\& the letter
+.Sq n
+of the current font (for nroff output, both scale indicators give the same
+values).
+If
+.Ao string Ac
+isn't a numeric expression, it is tested whether it is an
+.Nm \-mdoc
+macro name, and the default offset value associated with this macro is used.
+Finally, if all tests fail,
+the width of
+.Ao string Ac
+(typeset with a fixed-width font) is taken as the offset.
+.Pp
+If a width is not specified for the tag list type, every 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;
+otherwise, the default width of
+.Ql .No
+is used.
+.It Fl xwidth Ao Ar string Ac
+Interpret
+.Ao string Ac
+and use the width of the result.
+Almost all lists in this document use this option.
+.Pp
+Example:
+.
+.Bd -literal -offset indent
+\&.Bl -tag -xwidth ".Fl test Ao Ar string Ac"
+\&.It Fl test Ao Ar string Ac
+This is a longer sentence to show how the
+\&.Fl xwidth
+flag works in combination with a tag list.
+\&.El
+.Ed
+.Pp
+.
+gives:
+.
+.Bl -tag -xwidth ".Fl test Ao Ar string Ac"
+.It Fl test Ao Ar string Ac
+This is a longer sentence to show how the
+.Fl xwidth
+flag works in combination with a tag list.
+.El
+.Pp
+.
+Note that the current state of
+.Nm \-mdoc
+is saved before
+.Ao string Ac
+is interpreted; afterwards, all variables are restored again.
+However, boxes (used for enclosures) can't be saved in
+.Tn GNU
+.Xr troff 1 ;
+as a consequence, arguments must always be
+.Em balanced
+to avoid nasty errors.
+For example, do not write
+.Ql ".Ao string"
+but
+.Ql ".Ao string Xc"
+instead if you really need only an opening angle bracket.
+.It Fl offset Ao Ar string Ac
+If
+.Ao string Ac
+is
+.Ar indent ,
+a default indent value (normally set to\~6n, similar to the value used in
+.Ql .Dl
+or
+.Ql .Bd )
+is used.
+If
+.Ao string Ac
+is a valid numeric expression instead
+.Pf ( Em with a scale indicator other than
+.Sq Em u ) ,
+use that value for indentation.
+The most useful scale indicators are
+.Sq m
+and
+.Sq n ,
+specifying the so-called
+.Em \&Em
+and
+.Em "En square" .
+This is approximately the width of the letter
+.Sq m
+resp.\& the letter
+.Sq n
+of the current font (for nroff output, both scale indicators give the same
+values).
+If
+.Ao string Ac
+isn't a numeric expression, it is tested whether it is an
+.Nm \-mdoc
+macro name, and the default offset value associated with this macro is used.
+Finally, if all tests fail,
+the width of
+.Ao string Ac
+(typeset with a fixed-width font) is taken as the offset.
+.It Fl compact
+Suppress insertion of vertical space before the list and between list items.
+.El
+.
+.
+.Sh "MISCELLANEOUS MACROS"
+.
+Here a list of the remaining macros which do not fit well into one of the
+above sections.
+We couldn't find real examples for the following macros:
+.Ql .Me
+and
+.Ql .Ot .
+They are documented here for completeness \- if you know how to use them
+properly please send a mail to
+.Mt bug-groff@gnu.org
+(including an example).
+.
+.Bl -tag -xwidth ".Li .Bt"
+.It Li .Bt
+prints
+.
+.Bd -ragged -offset indent
+.Bt
+.Ed
+.Pp
+It is neither callable nor parsed and takes no arguments.
+.
+.It Li .Fr
+.Pp
+.Dl Usage: .Fr Ao function return value Ac ...
+.Pp
+Don't use this macro.
+It allows a break right before the return value (usually a single digit)
+which is bad typographical behaviour.
+Use
+.Ql \e~
+to tie the return value to the previous word.
+.
+.It Li .Hf
+Use this macro to include a (header) file literally.
+It first prints
+.Ql File:
+followed by the file name, then the contents of
+.Ao file Ac .
+.Pp
+.Dl Usage: .Hf Ao file Ac
+.Pp
+It is neither callable nor parsed.
+.
+.It Li .Lk
+To be written.
+.
+.It Li .Me
+Exact usage unknown.
+The documentation in the
+.Nm \-mdoc
+source file describes it as a macro for
+.Dq "menu entries" .
+.Pp
+Its default width is 6n.
+.
+.It Li .Mt
+To be written.
+.
+.It Li .Ot
+Exact usage unknown.
+The documentation in the
+.Nm \-mdoc
+source file describes it as
+.Dq old function type (fortran) .
+.
+.It Li .Sm
+Activate (toggle) space mode.
+.Pp
+.Dl Usage: .Sm Oo on | off Oc ...
+.Pp
+If space mode is off, no spaces between macro arguments are inserted.
+If called without a parameter (or if the next parameter is neither
+.Ql on
+nor
+.Ql off ,
+.Ql .Sm
+toggles space mode.
+.
+.It Li .Ud
+prints
+.
+.Bd -ragged -offset indent
+.Ud
+.Ed
+.Pp
+It is neither callable nor parsed and takes no arguments.
+.El
+.
+.
+.Sh "PREDEFINED STRINGS"
+.
+The following strings are predefined:
+.Pp
+.Bl -column String infinity "Troff " "straight double quote" -offset indent
+.It Sy String Ta Sy Nroff Ta Sy Troff Ta Sy Meaning
+.It Li <= Ta <= Ta \*[<=] Ta "less equal"
+.It Li >= Ta >= Ta \*[>=] Ta "greater equal"
+.It Li Rq Ta '' Ta \*[Rq] Ta "right double quote"
+.It Li Lq Ta `` Ta \*[Lq] Ta "left double quote"
+.It Li ua Ta ^ Ta \*[ua] Ta "upwards arrow"
+.It Li aa Ta \' Ta \*[aa] Ta "acute accent"
+.It Li ga Ta \` Ta \*[ga] Ta "grave accent"
+.It Li q Ta \&" Ta \*[q] Ta "straight double quote"
+.It Li Pi Ta pi Ta \*[Pi] Ta "greek pi"
+.It Li Ne Ta != Ta \*[Ne] Ta "not equal"
+.It Li Le Ta <= Ta \*[Le] Ta "less equal"
+.It Li Ge Ta >= Ta \*[Ge] Ta "greater equal"
+.It Li Lt Ta < Ta \*[Lt] Ta "less than"
+.It Li Gt Ta > Ta \*[Gt] Ta "greater than"
+.It Li Pm Ta +\- Ta \*[Pm] Ta "plus minus"
+.It Li If Ta infinity Ta \*[If] Ta "infinity"
+.It Li Na Ta \*[Na] Ta \*[Na] Ta "not a number"
+.It Li Ba Ta \*[Ba] Ta \*[Ba] Ta "vertical bar"
+.El
+.Pp
+The names of the columns
+.Sy Nroff
+and
+.Sy Troff
+are a bit misleading;
+.Sy Nroff
+shows the
+.Tn ASCII
+representation, while
+.Sy Troff
+gives the best glyph form available.
+For example, a Unicode enabled
+.Tn TTY Ns - Ns
+device will have proper glyph representations for all strings, whereas the
+enhancement for a Latin1
+.Tn TTY Ns - Ns
+device is only the plus-minus sign.
+.Pp
+String names which consist of two characters can be written as
+.Ql \e*(xx ;
+string names which consist of one character can be written as
+.Ql \e*x .
+A generic syntax for a string name of any length is
+.Ql \e*[xxx]
+(this is a
+.Tn GNU
+.Xr troff 1
+extension).
+.
+.
+\#
+\#=====================================================================
+\#
+.Sh DIAGNOSTICS
+.
+The debugging macro
+.Ql .Db
+available in previous versions of
+.Nm \-mdoc
+has been removed since
+.Tn GNU
+.Xr troff 1
+provides better facilities to check parameters; additionally, many error and
+warning messages have been added to this macro package, making it both more
+robust and verbose.
+.Pp
+The only remaining debugging macro is
+.Ql .Rd
+which yields a register dump of all global registers and strings.
+A normal user will never need it.
+.
+.
+.Sh "FORMATTING WITH GROFF, TROFF, AND NROFF"
+.
+By default, the package inhibits page breaks, headers, and footers if
+displayed with a
+.Tn TTY
+device like
+.Sq latin1
+or
+.Sq unicode
+to make the manual more efficient for viewing on-line.
+This behaviour can be changed (e.g.\& to create a hardcopy of the
+.Tn TTY
+output) by setting the register
+.Ql cR
+to zero while calling
+.Xr groff :
+.Pp
+.Dl groff -Tlatin1 -rcR=0 -mdoc foo.man > foo.txt
+.Pp
+For double-sided printing, set register
+.Ql D
+to\~1:
+.Pp
+.Dl groff -Tps -rD1 -mdoc foo.man > foo.ps
+.Pp
+To change the document font size to 11pt or 12pt, set register
+.Ql S
+accordingly:
+.Pp
+.Dl groff -Tdvi -rS11 -mdoc foo.man > foo.dvi
+.Pp
+Register
+.Ql S
+is ignored for
+.Tn TTY
+devices.
+.
+.
.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).
+.
+.Bl -tag -width mdoc/doc-ditroff -compact
+.It Pa doc.tmac
+The main manual macro package.
+.It Pa mdoc.tmac
+A wrapper file to call
+.Pa doc.tmac .
+.It Pa mdoc/doc-common
+Common strings, definitions, stuff related typographic output.
+.It Pa mdoc/doc-nroff
+Definitions used for a
+.Tn TTY
+output device.
+.It Pa mdoc/doc-ditroff
+Definitions used for all other devices.
+.It Pa mdoc.local
+Local additions and customizations.
+.It Pa andoc.tmac
+This file checks whether the
+.Nm \-mdoc
+or the
+.Nm \-man
+package should be used.
.El
-.Sh SEE ALSO
-.Xr mdoc.samples 7
+.
+.
+.Sh "SEE ALSO"
+.
+.Xr groff 1 ,
+.Xr man 1 ,
+.Xr troff 1 ,
+.Xr groff_man 7
+.
+.
+.Sh BUGS
+.
+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 list and display macros do 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/contrib/groff/tmac/groff_me.man b/contrib/groff/tmac/groff_me.man
index 4919621..7debe29 100644
--- a/contrib/groff/tmac/groff_me.man
+++ b/contrib/groff/tmac/groff_me.man
@@ -24,16 +24,16 @@ groff_me \- troff macros for formatting papers
.SH SYNOPSIS
.B "groff \-me"
[ options ]
-file ...
+file ...
.br
-.B "troff \-me"
+.B "groff \-m\ me"
[ options ]
-file ...
+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
+This package of
.I troff
macro definitions provides a canned formatting
facility for tech%nical papers in various formats.
@@ -65,7 +65,9 @@ and
preprocessors
is acceptable as input.
.SH FILES
-@MACRODIR@/tmac.e
+@MACRODIR@/me.tmac (a wrapper file for e.tmac)
+.br
+@MACRODIR@/e.tmac
.SH "SEE ALSO"
.BR groff (@MAN1EXT@),
.BR @g@troff (@MAN1EXT@)
@@ -74,7 +76,7 @@ is acceptable as input.
.br
Writing Papers with Groff Using \-me
.tr &.
-.SH REQUESTS
+.SH REQUESTS
This list is incomplete;
see
.I "The \-me Reference Manual"
@@ -86,6 +88,7 @@ for interesting details.
\ka
.br
.di
+.na
.in \nau
.ti 0
Request Initial Cause Explanation
@@ -272,3 +275,4 @@ points.
.ti 0
\&.xp \fIx\fR - no Print index
.I x.
+.ad
diff --git a/contrib/groff/tmac/groff_ms.man b/contrib/groff/tmac/groff_ms.man
index 0e1f64c..91463d8 100644
--- a/contrib/groff/tmac/groff_ms.man
+++ b/contrib/groff/tmac/groff_ms.man
@@ -21,7 +21,16 @@ the original English.
groff_ms \- groff ms macros
.SH SYNOPSIS
.B groff
-.B \-m@TMAC_S_PREFIX@s
+.B \-ms
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.br
+.B groff
+.B \-m\ ms
[
.IR options .\|.\|.
]
@@ -224,7 +233,11 @@ names containing
.IP \(bu
names containing only uppercase letters and digits.
.SH FILES
-.B @MACRODIR@/tmac.@TMAC_S_PREFIX@s
+.B @MACRODIR@/ms.tmac
+(a wrapper file for
+.BR s.tmac )
+.br
+.B @MACRODIR@/s.tmac
.SH "SEE ALSO"
.BR groff (@MAN1EXT@),
.BR @g@troff (@MAN1EXT@),
diff --git a/contrib/groff/tmac/groff_mwww.man b/contrib/groff/tmac/groff_mwww.man
new file mode 100644
index 0000000..bec719c
--- /dev/null
+++ b/contrib/groff/tmac/groff_mwww.man
@@ -0,0 +1,275 @@
+.TH GROFF_MWWW @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 -mwww macroset
+.\"
+.do mso www.tmac
+.\" we need the .LINKS here as we use it in the middle as an example
+.\" once the user requests .LINKS then the automatic generation of links
+.\" at the top of the document is suppresed.
+.LINKS
+.SH NAME
+groff_mwww \- groff macros for authoring web pages
+.LINE
+.SH SYNOPSIS
+.B "groff \-mwww"
+[ options ]
+file ...
+.SH DESCRIPTION
+This manual page describes the GNU \-mwww 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 )
+has been completely rewritten but still remains as in an alpha state.
+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.
+Another method for switching automatic headings is via the command line
+switch \fC-P-l\fP.
+.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"
+\&.MAILTO Ted.Harding@nessie.mcc.ac.uk "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, \fCwww.tmac\fP inserts a zero-width character which
+expands to a harmless space (only if run with -Thtml).
+.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
+.nf
+\s-2\fC\&.FTP "current groff development distribution" \\
+ftp://ftp.ffii.org/pub/groff/devel/groff-current.tar.gz .\fP\s+2
+.fi
+.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
+.nf
+\s-2\fC\&.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.\fP\s+2
+.fi
+.sp
+.TP
+.B LINE
+generates a full width horizontal rule.
+Example:
+.sp
+.nf
+\fC\s-2\&.LINE\fP\s+2
+.fi
+.sp
+.TP
+.B LINKS
+.TAG LINK
+requests that grohtml place the automatically generated links at this position.
+For example:
+.LINKS
+.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. (See
+.URL LINKS #LINK
+for details of how to switch this off or alter the position.
+.SH
+LIMITATIONS OF GROHTML
+.LP
+Tbl information is currently rendered as a png image.
+.SH FILES
+@MACRODIR@/mwww.tmac (a wrapper for www.tmac)
+.br
+@MACRODIR@/www.tmac
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@)
+.BR grohtml (@MAN1EXT@),
+.LP
+.SH AUTHOR
+.B Grohtml
+was written by
+.MAILTO gaius@glam.ac.uk "Gaius Mulley"
+.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.
diff --git a/contrib/groff/tmac/groff_tmac.man b/contrib/groff/tmac/groff_tmac.man
index 9e1f8e0..4eb731c 100644
--- a/contrib/groff/tmac/groff_tmac.man
+++ b/contrib/groff/tmac/groff_tmac.man
@@ -1,4 +1,4 @@
-.\" -*- nroff -*-
+.\" -*- nroff -*-
.ig /
groff_tmac.5
@@ -24,7 +24,7 @@ FDL in the main directory of the groff source package.
.\" --------------------------------------------------------------------
.
.if n \{\
-. mso tmac.tty-char
+. mso tty-char.tmac
. ftr CR R
. ftr CI I
. ftr CB B
@@ -37,7 +37,7 @@ FDL in the main directory of the groff source package.
.
.de BIR
. ie (\\n[.$] < 3) \
-. BI $@
+. BI \\$@
. el \{\
. ds @tmp@ \fB\\$1\fP\fI\\$2\fP
. shift 2
@@ -111,13 +111,16 @@ this letter was omitted, e.g., the macro package for the man pages
was called
.I an
and its macro file
-.IR tmac.an .
+.I tmac.an
+(note that in recent versions of groff this file is called
+.I an.tmac
+instead).
.LP
By a similar reasoning, macro packages that did not start with an
.'char m
were often referred to by adding an
.'char m ,
- e.g., the package corresponding to
+e.g., the package corresponding to
.I tmac.doc
was called
.I mdoc
@@ -149,11 +152,13 @@ macro package may be specified as
.RE
.LP
The easiest way to find out which macro packages are available on a
-system is to check the content of the
+system is to check the contents of the
.I tmac
directories.
For example, a file called
.BI tmac. anything
+or
+.IB anything .tmac
determines a macro package named
.IR anything .
.LP
@@ -172,11 +177,14 @@ run-time, the groff option
.option \-m \ \c
.argument name
makes the definitions in the macro file
-.BI tmac. name
+.IB name .tmac
available as described in the section
.BR NAMING .
+If this file isn't found,
+.BI tmac. name
+will be searched.
.LP
-It is also possible to include the macro file into the document by using
+It is also possible to include the macro file into the document by using
the groff requests
.request .so
or
@@ -188,7 +196,14 @@ directory where it is kept.
If the macro file is stored in one of the tmac directories it is more
convenient to use
.request .mso
-instead because it additionally searches the tmac path for the filename.
+instead because it searches the tmac path for the filename.
+Additionally, if the file name to be included has the form
+.IB name .tmac
+and it isn't found,
+.request .mso
+will try to open
+.BI tmac. name
+instead and vice versa.
.LP
Note that in order to resolve the
.request .so
@@ -196,8 +211,9 @@ and
.request .mso
requests the roff preprocessor
.shellcommand soelim
-must be called. This can be done either directly by a pipeline on the
-command line or by using the
+must be called if the files to be included needs preprocessing.
+This can be done either directly by a pipeline on the command line or by
+using the
.option \-s
option of
.shellcommand groff .
@@ -208,7 +224,7 @@ in the preprocessor word as described in section
.BR CONVENTION .
.LP
For example, suppose a macro file is stored as
-.I /usr/share/groff/tmac/tmac.macros
+.I @MACRODIR@/macros.tmac
and is used in some document called
.IR docu.roff .
.LP
@@ -225,13 +241,13 @@ At run-time, the formatter call for this is
To include the macro file directly in the document either
.RS
.ft CR
-\&\.mso tmac.macros
+\&\.mso macros.tmac
.ft P
.RE
is used or
.RS
.ft CR
-\&\.so /usr/share/groff/tmac/tmac.macros
+\&\.so @MACRODIR@/macros.tmac
.ft P
.RE
.LP
@@ -257,8 +273,8 @@ comment characters and a blank) constitutes the
.BR word .
That means that the letters of this word are interpreted as
abbreviations for those preprocessor commands that should be run
-when formatting the document. Mostly, only the letters corresponding to
-the options for the preprocessors are recognized,
+when formatting the document. Mostly, only the letters corresponding to
+the options for the preprocessors are recognized,
.'char e ,
.'char G ,
.'char g ,
@@ -285,8 +301,10 @@ request as described in the
section.
.LP
To use the tmac functionality, call the macro file
-.BI tmac. whatever
-and put it in some directory of the tmac path, cf. section
+.IB whatever .tmac
+(or
+.BI tmac. whatever\c
+) and put it in some directory of the tmac path, cf. section
.BR FILES .
Then documents can include it with the
.request .mso
@@ -333,38 +351,51 @@ and
.\" --------------------------------------------------------------------
.SH FILES
.\" --------------------------------------------------------------------
-All macro names that want to use the tmac mechanism must be named
-according to the form
-.BIR tmac. name .
+All macro names must be named
+.IB name .tmac
+or
+.BI tmac. name
+to use the tmac mechanism.
.LP
The macro files are kept in the
.B tmac
.BR directories ,
-all of which constitue the
+all of which constitute the
.B tmac
.BR path.
-In accordance with the Filesystem Hierarchy Standard (FHS), the standard
-tmac directory location for groff is
-.IR /usr/share/groff/tmac ,
-a local installation will use
-.IR /usr/local/share/groff/tmac .
-Older systems used a subdirectory of
-.IR /usr/lib .
-Independently of the default tmac path, the tmac path actually used by a
-document can always be set by a shell environment variable, cf. section
-.BR ENVIRONMENT .
+.LP
+The elements of the search path for macro files are (in that order):
+.IP \(bu 4
+the directories specified with troff's resp. groff's
+.B \-M
+command line option
+.IP \(bu 4
+the directories given in the
+.B GROFF_TMAC_PATH
+environment variable
+.IP \(bu 4
+the current directory (only if in unsafe mode using the
+.B \-U
+command line switch)
+.IP \(bu 4
+the home directory
+.IP \(bu 4
+a site-specific (platform-independent) directory, a platform-specific
+directory, and the main tmac directory:
+.IP "" 6
+@LOCALMACRODIR@
+.br
+@SYSTEMMACRODIR@
+.br
+@MACRODIR@
.\" --------------------------------------------------------------------
.SH ENVIRONMENT
.\" --------------------------------------------------------------------
.TP
.B GROFF_TMAC_PATH
-A colon separated list of tmac directories in which to search for macro
-files, the
-.B tmac
-.BR path .
-If unset a default path is used as is outlined in the
-.B FILES
-section.
+A colon separated list of additional tmac directories in which to search
+for macro files.
+See the previous section for a detailed description.
.\" --------------------------------------------------------------------
.SH BUGS
.\" --------------------------------------------------------------------
@@ -400,14 +431,14 @@ in the groff source package.
.LP
The groff tmac macro packages are
.BR groff_man (@MAN7EXT@),
-.BR groff_markup (@MAN7EXT@),
+.BR groff_mwww (@MAN7EXT@),
.BR groff_mdoc (@MAN7EXT@),
.BR groff_mdoc.samples (@MAN7EXT@),
.BR groff_me (@MAN7EXT@),
.BR groff_mm (@MAN7EXT@),
.BR groff_mmroff (@MAN7EXT@),
-.BR groff_ms (@MAN7EXT@),
-.BR groff_msafer (@MAN7EXT@).
+and
+.BR groff_ms (@MAN7EXT@).
.LP
The groff language is described in
.BR groff (@MAN7EXT@)
@@ -417,4 +448,3 @@ and the formatters in
.LP
The Filesystem Hierarchy Standard (FHS) is available at
.BR http://www.pathname.com/fhs/ .
-
diff --git a/contrib/groff/tmac/html.tmac b/contrib/groff/tmac/html.tmac
new file mode 100644
index 0000000..c5591c8
--- /dev/null
+++ b/contrib/groff/tmac/html.tmac
@@ -0,0 +1,47 @@
+.\" html.tmac
+.\"
+.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
+.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\(lq .char \(lq ``
+.if !c\(rq .char \(rq ''
+.if !c\(Bq .char \(bq ,,
+.if !c\(OE .char \(OE OE
+.if !c\(oe .char \(oe oe
+.if !c\(lh .char \(lh <-
+.if !c\(rh .char \(rh ->
+.if !c\(bq .tr \(bq,
+.if !c\(aq .tr \(aq'
+.if !\n(_C .mso pspic.tmac
+.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 ''''
+.tl ''''
+.\" 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\[shc]
+.pl 99999
+.\" eof of file, make sure this is the last time
diff --git a/contrib/groff/tmac/hyphen.us b/contrib/groff/tmac/hyphen.us
new file mode 100644
index 0000000..d86c3d5
--- /dev/null
+++ b/contrib/groff/tmac/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/contrib/groff/tmac/latin1.tmac b/contrib/groff/tmac/latin1.tmac
new file mode 100644
index 0000000..9cc15cc
--- /dev/null
+++ b/contrib/groff/tmac/latin1.tmac
@@ -0,0 +1,103 @@
+.\" latin1.tmac
+.\"
+.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] \[shc]
+.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] \(pc
+.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/contrib/groff/tmac/lbp.tmac b/contrib/groff/tmac/lbp.tmac
new file mode 100644
index 0000000..0d17b63
--- /dev/null
+++ b/contrib/groff/tmac/lbp.tmac
@@ -0,0 +1,15 @@
+.\" lbp.tmac
+.\"
+.nr _C \n(.C
+.cp 0
+.ftr CW CR
+.ftr C CR
+.ftr CO CI
+.ftr H HR
+.ftr HO HI
+.ftr HX HBI
+.ftr Hr HNR
+.ftr Hi HNI
+.ftr Hb HNB
+.ftr Hx HNBI
+.cp \n(_C
diff --git a/contrib/groff/tmac/lj4.tmac b/contrib/groff/tmac/lj4.tmac
new file mode 100644
index 0000000..b5644e4
--- /dev/null
+++ b/contrib/groff/tmac/lj4.tmac
@@ -0,0 +1,20 @@
+.\" lj4.tmac
+.\"
+.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/contrib/groff/tmac/man.local b/contrib/groff/tmac/man.local
index 7bb8f50..c47b243 100644
--- a/contrib/groff/tmac/man.local
+++ b/contrib/groff/tmac/man.local
@@ -1,2 +1,2 @@
-.\" This file is loaded after tmac.an.
-.\" Put any local modifications to tmac.an here.
+.\" This file is loaded after an-old.tmac.
+.\" Put any local modifications to an-old.tmac here.
diff --git a/contrib/groff/tmac/man.tmac b/contrib/groff/tmac/man.tmac
new file mode 100644
index 0000000..ca7d14da
--- /dev/null
+++ b/contrib/groff/tmac/man.tmac
@@ -0,0 +1,3 @@
+.\" man.tmac
+.\"
+.do mso andoc.tmac
diff --git a/contrib/groff/tmac/mandoc.tmac b/contrib/groff/tmac/mandoc.tmac
new file mode 100644
index 0000000..ee21497
--- /dev/null
+++ b/contrib/groff/tmac/mandoc.tmac
@@ -0,0 +1,3 @@
+.\" mandoc.tmac
+.\"
+.do mso andoc.tmac
diff --git a/contrib/groff/tmac/mdoc.local b/contrib/groff/tmac/mdoc.local
new file mode 100644
index 0000000..2de6621
--- /dev/null
+++ b/contrib/groff/tmac/mdoc.local
@@ -0,0 +1,2 @@
+.\" This file is loaded after doc.tmac.
+.\" Put any local modifications to doc.tmac here.
diff --git a/contrib/groff/tmac/mdoc.tmac b/contrib/groff/tmac/mdoc.tmac
new file mode 100644
index 0000000..250d615
--- /dev/null
+++ b/contrib/groff/tmac/mdoc.tmac
@@ -0,0 +1,3 @@
+.\" mdoc.tmac
+.\"
+.do mso doc.tmac
diff --git a/contrib/groff/tmac/me.tmac b/contrib/groff/tmac/me.tmac
new file mode 100644
index 0000000..0c90a9b
--- /dev/null
+++ b/contrib/groff/tmac/me.tmac
@@ -0,0 +1,3 @@
+.\" me.tmac
+.\"
+.do mso e.tmac
diff --git a/contrib/groff/tmac/ms.tmac b/contrib/groff/tmac/ms.tmac
new file mode 100644
index 0000000..50e0370
--- /dev/null
+++ b/contrib/groff/tmac/ms.tmac
@@ -0,0 +1,3 @@
+.\" ms.tmac
+.\"
+.do mso s.tmac
diff --git a/contrib/groff/tmac/mwww.tmac b/contrib/groff/tmac/mwww.tmac
new file mode 100644
index 0000000..b258688
--- /dev/null
+++ b/contrib/groff/tmac/mwww.tmac
@@ -0,0 +1,3 @@
+.\" mwww.tmac
+.\"
+.do mso www.tmac
diff --git a/contrib/groff/tmac/pic.tmac b/contrib/groff/tmac/pic.tmac
new file mode 100644
index 0000000..ac3b024
--- /dev/null
+++ b/contrib/groff/tmac/pic.tmac
@@ -0,0 +1,12 @@
+.\" pic.tmac
+.\"
+.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/contrib/groff/tmac/ps.tmac b/contrib/groff/tmac/ps.tmac
new file mode 100644
index 0000000..1aeacfd
--- /dev/null
+++ b/contrib/groff/tmac/ps.tmac
@@ -0,0 +1,54 @@
+.\" ps.tmac
+.\"
+.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 pspic.tmac
diff --git a/contrib/groff/tmac/psatk.tmac b/contrib/groff/tmac/psatk.tmac
new file mode 100644
index 0000000..dc6d2f38
--- /dev/null
+++ b/contrib/groff/tmac/psatk.tmac
@@ -0,0 +1,63 @@
+.\" psatk.tmac
+.\"
+.\" Implementation of the ATK PB and PE macros for use with groff and grops.
+.\" Load this after atk.tmac.
+.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/contrib/groff/tmac/psfig.tmac b/contrib/groff/tmac/psfig.tmac
new file mode 100644
index 0000000..f966822
--- /dev/null
+++ b/contrib/groff/tmac/psfig.tmac
@@ -0,0 +1,89 @@
+.\" psfig.tmac
+.\"
+.\" 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/contrib/groff/tmac/psold.tmac b/contrib/groff/tmac/psold.tmac
new file mode 100644
index 0000000..28a446b
--- /dev/null
+++ b/contrib/groff/tmac/psold.tmac
@@ -0,0 +1,61 @@
+.\" psold.tmac
+.\"
+.\" In newer PostScript printers, 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
+.\" such old printers.
+.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/contrib/groff/tmac/pspic.tmac b/contrib/groff/tmac/pspic.tmac
new file mode 100644
index 0000000..ab06668
--- /dev/null
+++ b/contrib/groff/tmac/pspic.tmac
@@ -0,0 +1,60 @@
+.\" pspic.tmac
+.\"
+.\" 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
+.ie '\\$1'-L' \{\
+. nr ps-offset-mode 1
+. shift
+. HTML-DO-IMAGE \\$1 l
+.\}
+.el \{\
+. ie '\\$1'-R' \{\
+. nr ps-offset-mode 2
+. shift
+. HTML-DO-IMAGE \\$1 r
+. \}
+. el \{\
+. if '\\$1'-I' \{\
+. nr ps-offset-mode 3
+. nr ps-offset (m;\\$2)
+. shift 2
+. \}
+. HTML-DO-IMAGE \\$1 i
+. \}
+.\}
+.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
+.\}
+.HTML-IMAGE-END
+..
diff --git a/contrib/groff/tmac/s.tmac b/contrib/groff/tmac/s.tmac
new file mode 100644
index 0000000..7d1ad49
--- /dev/null
+++ b/contrib/groff/tmac/s.tmac
@@ -0,0 +1,1934 @@
+.\" -*- nroff -*-
+.ig
+
+s.tmac
+
+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
+.CHECK-FOOTER-AND-KEEP
+..
+.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
+.if !'\*(.T'html' .di cov*tl-div
+.par@reset
+.ft B
+.ps +2
+.vs +3p
+.ll (u;\\n[LL]*5/6)
+.nr cov*n-au 0
+.HTML-TAG ".tl"
+..
+.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
+.if !'\*(.T'html' .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
+.if !'\*(.T'html' .di cov*ab-div
+.par@ab-indent
+.par@reset
+.if !'\\$1'no' \{\
+. ft I
+. ce 1
+\\*[ABSTRACT]
+. sp
+. ft R
+.\}
+.ns
+.@PP
+.if '\*(.T'html' \{\
+. cov*tl-au-print
+. als cov*tl-au-print @nop
+. par@reset-env
+. par@reset
+. cov*print
+.\}
+..
+.de AE
+.ie '\*(.T'html' \{\
+. als AE cov*err-not-again
+.\}
+.el \{\
+. 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
+. CHECK-FOOTER-AND-KEEP
+. \}
+. br
+.\}
+..
+.de cov*rp-print
+.nr cov*page-length \\n[.p]
+.pl 1000i
+.cov*tl-au-print
+.sp 3
+.if d cov*ab-div \{\
+. if !'\*(.T'html' . 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
+.CHECK-FOOTER-AND-KEEP
+.\" 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
+.if d cov*tl-div .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
+.\}
+.HTML-TAG ".mc \\n[pg@ncols] \\n[pg@colw] \\n[pg*gutw]"
+.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>?0)
+. 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>?0)
+. 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
+.CHECK-FOOTER-AND-KEEP
+..
+.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]
+.if !'\*(.T'html' .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
+. ie '\*(.T'html' \{\
+. if \\n[dl]+1n<=\\n[\\n[.ev]:ai] .HTML-TAG ".ip"
+. ti 0
+\&\\$1
+. br
+. \}
+. el \{\
+. 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
+.HTML-IMAGE
+.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
+.HTML-IMAGE-END
+..
+.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
+.HTML-TAG ".SH 1"
+..
+.\" 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
+.HTML-TAG ".tl"
+..
+.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
+.HTML-TAG ".NH \\$1"
+.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 !
+..
+.de CHECK-FOOTER-AND-KEEP
+.\" it might be better to als FS -> B1 and FE -> B2
+.\" however this produced wierd results, so I've moved back to a more reliable
+.\" but less interesting solution --fixme--
+. if '\*(.T'html' \{\
+. rm KF
+. als KF KS
+. rm FS
+. de FS
+. br
+. HTML-IMAGE
+\\..
+. rm FE
+. de FE
+. br
+. HTML-IMAGE-END
+\\..
+. \}
+. if r ps4html \{\
+. rm FS
+. de FS
+. br
+. HTML-IMAGE
+\\..
+. rm FE
+. de FE
+. br
+. HTML-IMAGE-END
+\\..
+. \}
+..
+.par@load-init
+.\" Make sure that no blank lines creep in at the end of this file.
diff --git a/contrib/groff/tmac/safer.tmac b/contrib/groff/tmac/safer.tmac
new file mode 100644
index 0000000..1e7d03d
--- /dev/null
+++ b/contrib/groff/tmac/safer.tmac
@@ -0,0 +1,5 @@
+.\" This file is no longer needed; it has been replaced with a built-in
+.\" solution.
+.\"
+.\" It just exists for compatibility reasons with older man programs
+.\" which explicitly load this file.
diff --git a/contrib/groff/tmac/trace.tmac b/contrib/groff/tmac/trace.tmac
new file mode 100644
index 0000000..143f954
--- /dev/null
+++ b/contrib/groff/tmac/trace.tmac
@@ -0,0 +1,29 @@
+.\" trace.tmac
+.\"
+.\" Load this before a macro package that you want to trace.
+.
+.eo
+.
+.rn de !!de
+.
+.!!de de
+. ecs
+. ec
+. !!de \$1
+. ie "\$1"\\$0" .tm *** trace enter: \\$0 \\$@
+. el .tm *** trace enter \$1: \\$0 \\$@
+. nop \\*[!!\$1]\\
+. ie "\$1"\\$0" .tm *** trace exit: \\$0 \\$@
+. el .tm *** trace exit \$1: \\$0 \\$@
+\..
+.
+. ds !!d1 !!\$1
+. ds !!d2 \$2
+.
+. ecr
+. dei !!d1 !!d2
+..
+.
+.ec
+.
+.\" EOF
diff --git a/contrib/groff/tmac/troffrc-end b/contrib/groff/tmac/troffrc-end
index edd23e4..631f6b0 100644
--- a/contrib/groff/tmac/troffrc-end
+++ b/contrib/groff/tmac/troffrc-end
@@ -2,5 +2,18 @@
.\" 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
+.do if '\*(.T'html' .mso html.tmac
+.\" if we are running the postscript device for html images then load -mwww
+.\"
+.do if r ps4html .mso www.tmac
+.\"
+.\" for all other devices blank out these macros
+.\"
+.do if !d HTML-IMAGE-INLINE .ds HTML-IMAGE-INLINE
+.do if !d HTML-IMAGE .ds HTML-IMAGE
+.do if !d HTML-IMAGE-RIGHT .ds HTML-IMAGE-RIGHT
+.do if !d HTML-IMAGE-LEFT .ds HTML-IMAGE-LEFT
+.do if !d HTML-IMAGE-END .ds HTML-IMAGE-END
+.do if !d HTML-TAG .ds HTML-TAG
+.do if !d HTML-DO-IMAGE .ds HTML-DO-IMAGE
+.\" Don't let blank lines creep in here.
diff --git a/contrib/groff/tmac/tty-char.tmac b/contrib/groff/tmac/tty-char.tmac
new file mode 100644
index 0000000..02a1071
--- /dev/null
+++ b/contrib/groff/tmac/tty-char.tmac
@@ -0,0 +1,204 @@
+.\" tty-char.tmac
+.\"
+.\" This file defines standard troff characters and some groff characters for
+.\" use with -Tascii, -Tlatin1, -Tutf8, and -Tcp1047.
+.\"
+.\" These definitions are chosen so that, as far as possible, they:
+.\" - work with all of -Tascii, -Tlatin1, -Tutf8, and -Tcp1047.
+.\" - 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 \(pc \(md
+.if c\(pc .tty-char \(md \(pc
+.if c\(pc .tty-char \(a. \(pc
+.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 \(pc .
+.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
+.if !'\*(.T'cp1047' \
+. do mso latin1.tmac
diff --git a/contrib/groff/tmac/tty.tmac b/contrib/groff/tmac/tty.tmac
new file mode 100644
index 0000000..e680435
--- /dev/null
+++ b/contrib/groff/tmac/tty.tmac
@@ -0,0 +1,50 @@
+.\" tty.tmac
+.\"
+.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\[shc] .shc \[shc]
+.de tty-char
+.if !c\\$1 .char \\$1 "\\$2
+..
+.ie c\(pc .tr \(bu\(pc
+.el .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 tty-char.tmac to be loaded
+.\" automatically, remove the `\"' from the next line.
+.\"do mso tty-char.tmac
diff --git a/contrib/groff/tmac/www.tmac b/contrib/groff/tmac/www.tmac
new file mode 100644
index 0000000..8358c86
--- /dev/null
+++ b/contrib/groff/tmac/www.tmac
@@ -0,0 +1,211 @@
+.\" www.tmac
+.\"
+.\" A simple set of macros to provide HTML documents with basic
+.\" www functionality. It will work with any macro set.
+.\"
+.nr _C \n(.C
+.cp 0
+.nr www-html 0
+.if '\*(.T'html' .nr www-html 1
+.\"
+.\"
+.\"
+.de HTML
+. if \\n[www-html] \{\
+.\" the following line makes the vertical mode leave, so to say
+\&
+\X^html:\\$*^
+. \}
+..
+.de HTMLINDEX
+. if \\n[www-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 \\n[www-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 \\n[www-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 \\n[www-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 \\n[www-html] \{\
+. nr HTMLWIDTH 400
+. if !'\\$2'' \{\
+. nr HTMLWIDTH \\$2
+. \}
+. nr HTMLHEIGHT \\n[HTMLWIDTH]
+. if !'\\$3'' \{\
+. nr HTMLHEIGHT \\$3
+. \}
+. HTML-TAG ".centered-image"
+. HTML <img src="\\$1" width=\\n[HTMLWIDTH] height=\\n[HTMLHEIGHT]>
+. \}
+. el \{\
+. B1
+\(la\fC\\$1\fP\(ra
+. B2
+. \}
+..
+.\" HTML-TAG - emit a tag for the new grohtml
+.de HTML-TAG
+. if \\n[www-html] \{\
+.\" the following line makes the vertical mode leave, so to say
+\&
+\X^html-tag:\\$*^
+. \}
+..
+.\" LINKS - emit the automatically collected links derived from section/numbered
+.\" headings at this position.
+.de LINKS
+. HTML-TAG ".links"
+..
+.\"
+.\" LINE - produce a horizontal line
+.\"
+.de LINE
+. ti 0
+. HTML <hr>
+..
+.\"
+.\" supplimentary macros used by other macro sets
+.\"
+.\" here are some tags specially for -Tps or -Thtml when invoked by pre-html
+.\" to generate png images from postscript.
+.\"
+.\" HTML-DO-IMAGE - tells troff to issue an image marker which can be
+.\" read back by pre-html
+.\"
+.de HTML-DO-IMAGE
+. if r ps4html .begin \{\
+. image \\$2 \\$1.png
+. bp
+. tl ''''
+\O0\O1
+. \}
+. if \\n[www-html] .begin \{
+. image \\$2 \\$1.png
+\O0
+. \}
+..
+.\"
+.\" HTML-IMAGE-END - terminates an image for html
+.\"
+.de HTML-IMAGE-END
+. if r ps4html \O2\O1\O4
+. if \\n[www-html] \O2\O1\O4
+..
+.nr png-no 0
+.\"
+.\" MAKE-UNIQUE-NAME - generates another unique name
+.\"
+.de MAKE-UNIQUE-NAME
+. nr png-no \\n[png-no]+1
+. ds HTML-UNIQUE-NAME \\n(.F-auto-\\n[png-no]
+..
+.\"
+.\" HTML-IMAGE - is the same name as a tag generated from eqn/tbl/pic.
+.\" Although the tags generated via the preprocessor
+.\" are given image names by pre-html and troff.
+.\" The macros below can only be invoked by *other macro sets*
+.\" not user troff input since the contents of macro sets are
+.\" not seen by pre-html.
+.\"
+.de HTML-IMAGE
+.\" generates a centered image
+. MAKE-UNIQUE-NAME
+. HTML-DO-IMAGE \\*[HTML-UNIQUE-NAME] c
+..
+.de HTML-IMAGE-RIGHT
+. MAKE-UNIQUE-NAME
+. HTML-DO-IMAGE \\*[HTML-UNIQUE-NAME] r
+..
+.de HTML-IMAGE-LEFT
+. MAKE-UNIQUE-NAME
+. HTML-DO-IMAGE \\*[HTML-UNIQUE-NAME] l
+..
+.de HTML-IMAGE-INLINE
+. MAKE-UNIQUE-NAME
+. HTML-DO-IMAGE \\*[HTML-UNIQUE-NAME] i
+..
+.nr HY 0
+.nh
+.cp \n(_C
diff --git a/contrib/groff/win32-diffs b/contrib/groff/win32-diffs
index 055c733..f00f1b9 100644
--- a/contrib/groff/win32-diffs
+++ b/contrib/groff/win32-diffs
@@ -1,7 +1,7 @@
diff -aruN groff/Makefile.msc groff.win32/Makefile.msc
--- groff/Makefile.msc Thu Jan 1 00:00:00 1970
+++ groff.win32/Makefile.msc Wed May 17 09:15:07 2000
-@@ -0,0 +1,37 @@
+@@ -0,0 +1,36 @@
+
+
+MAKECMD = $(MAKE) -nologo -f makefile.msc
@@ -38,7 +38,6 @@ diff -aruN groff/Makefile.msc groff.win32/Makefile.msc
+ copy src\preproc\pic\pic.exe bin
+ copy src\preproc\tbl\tbl.exe bin
+ copy src\roff\troff\troff.exe bin
-+ copy src\roff\troff\hyphen.us tmac
diff -aruN groff/bin/gs.cmd groff.win32/bin/gs.cmd
--- groff/bin/gs.cmd Thu Jan 1 00:00:00 1970
+++ groff.win32/bin/gs.cmd Wed May 17 08:57:48 2000
@@ -2891,9 +2890,9 @@ diff -aruN groff/src/libs/libgroff/version.cc groff.win32/src/libs/libgroff/vers
--- groff/src/libs/libgroff/version.cc Thu Jan 1 00:00:00 1970
+++ groff.win32/src/libs/libgroff/version.cc Wed May 17 08:57:48 2000
@@ -0,0 +1,3 @@
-+const char *version_string = "1.16";
-+const char *revision_string = "1";
-+const char *Version_string = "1.16";
++const char *version_string = "1.17";
++const char *revision_string = "0";
++const char *Version_string = "1.17";
diff -aruN groff/src/preproc/eqn/Makefile.msc groff.win32/src/preproc/eqn/Makefile.msc
--- groff/src/preproc/eqn/Makefile.msc Thu Jan 1 00:00:00 1970
+++ groff.win32/src/preproc/eqn/Makefile.msc Wed May 17 08:57:48 2000
@@ -3045,5 +3044,5 @@ diff -aruN groff/src/roff/troff/majorminor.cc groff.win32/src/roff/troff/majormi
+++ groff.win32/src/roff/troff/majorminor.cc Wed May 17 08:57:48 2000
@@ -0,0 +1,3 @@
+const char *major_version = "1";
-+const char *minor_version = "16";
++const char *minor_version = "17";
+const char *revision = "0";
OpenPOWER on IntegriCloud