summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2000-04-09 07:58:38 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2000-04-09 07:58:38 +0000
commit098fe4a0b368c914c7d1f7ce086634958df8796a (patch)
tree35c4467b0223be7d6cd8bf4a8d03b0010b342e2a /gnu
parent972922b0b73ac8052cf5ab98e029ac4e27c752f3 (diff)
groff 1.15
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/groff/devhtml/CB306
-rw-r--r--gnu/usr.bin/groff/devhtml/CBI306
-rw-r--r--gnu/usr.bin/groff/devhtml/CI306
-rw-r--r--gnu/usr.bin/groff/devhtml/CR306
-rw-r--r--gnu/usr.bin/groff/devhtml/DESC10
-rw-r--r--gnu/usr.bin/groff/devhtml/HB306
-rw-r--r--gnu/usr.bin/groff/devhtml/HBI306
-rw-r--r--gnu/usr.bin/groff/devhtml/HI306
-rw-r--r--gnu/usr.bin/groff/devhtml/HR306
-rw-r--r--gnu/usr.bin/groff/devhtml/Makefile.sub2
-rw-r--r--gnu/usr.bin/groff/devhtml/NB306
-rw-r--r--gnu/usr.bin/groff/devhtml/NBI306
-rw-r--r--gnu/usr.bin/groff/devhtml/NI306
-rw-r--r--gnu/usr.bin/groff/devhtml/NR306
-rw-r--r--gnu/usr.bin/groff/devhtml/S226
-rw-r--r--gnu/usr.bin/groff/devhtml/TB306
-rw-r--r--gnu/usr.bin/groff/devhtml/TBI306
-rw-r--r--gnu/usr.bin/groff/devhtml/TI306
-rw-r--r--gnu/usr.bin/groff/devhtml/TR306
-rw-r--r--gnu/usr.bin/groff/doc/groff.texinfo5762
-rw-r--r--gnu/usr.bin/groff/grohtml/ChangeLog104
-rw-r--r--gnu/usr.bin/groff/grohtml/Makefile.dep3
-rw-r--r--gnu/usr.bin/groff/grohtml/Makefile.sub6
-rw-r--r--gnu/usr.bin/groff/grohtml/design.ms156
-rw-r--r--gnu/usr.bin/groff/grohtml/grohtml.man173
-rw-r--r--gnu/usr.bin/groff/grohtml/html.cc5183
-rw-r--r--gnu/usr.bin/groff/grohtml/html.h57
-rw-r--r--gnu/usr.bin/groff/grohtml/ordered_list.h193
-rw-r--r--gnu/usr.bin/groff/tmac/groff_man.man171
-rw-r--r--gnu/usr.bin/groff/tmac/groff_mdoc.man422
-rw-r--r--gnu/usr.bin/groff/tmac/groff_mdoc.samples.man2925
-rw-r--r--gnu/usr.bin/groff/tmac/groff_me.man274
-rw-r--r--gnu/usr.bin/groff/tmac/groff_msafer.man59
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.arkup178
-rw-r--r--gnu/usr.bin/groff/tmac/tmac.html58
-rw-r--r--gnu/usr.bin/groff/xditview/GXditview-ad.h52
-rw-r--r--gnu/usr.bin/groff/xditview/ad2c62
-rw-r--r--gnu/usr.bin/groff/xditview/gray1.bm4
-rw-r--r--gnu/usr.bin/groff/xditview/gray2.bm4
-rw-r--r--gnu/usr.bin/groff/xditview/gray3.bm4
-rw-r--r--gnu/usr.bin/groff/xditview/gray4.bm4
-rw-r--r--gnu/usr.bin/groff/xditview/gray5.bm4
-rw-r--r--gnu/usr.bin/groff/xditview/gray6.bm4
-rw-r--r--gnu/usr.bin/groff/xditview/gray7.bm4
-rw-r--r--gnu/usr.bin/groff/xditview/gray8.bm4
45 files changed, 21004 insertions, 0 deletions
diff --git a/gnu/usr.bin/groff/devhtml/CB b/gnu/usr.bin/groff/devhtml/CB
new file mode 100644
index 00000000000..7ca40b89c0e
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/CB
@@ -0,0 +1,306 @@
+name CB
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,10,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,9,2 0 050
+) 9,9,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,9,2 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,9,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,9,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,9,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,9,1 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,10,1 0 0247
+§ "
+ad 9,10 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 9,5 0 055
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,9 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,9 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,10,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,4 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,10 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,4 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,10 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/CBI b/gnu/usr.bin/groff/devhtml/CBI
new file mode 100644
index 00000000000..551ed26161d
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/CBI
@@ -0,0 +1,306 @@
+name CBI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,10 0 041
+" 9,9 0 042
+# 9,11,1 0 043
+sh "
+$ 9,11,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,9 0 047
+( 9,9,2 0 050
+) 9,9,2 0 051
+* 9,10 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,9,2 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,9,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,9 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,9,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,9,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,3 0 0241
+¡ "
+ct 9,9,1 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,10,2 0 0246
+¦ "
+sc 9,10,1 0 0247
+§ "
+ad 9,10 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 055
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,10 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,10,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,4 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,12 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,12 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,12 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,4 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,10 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,8 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/CI b/gnu/usr.bin/groff/devhtml/CI
new file mode 100644
index 00000000000..6b26256beee
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/CI
@@ -0,0 +1,306 @@
+name CI
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,10,1 0 043
+sh "
+$ 9,10,1 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,10,3 0 050
+) 9,10,3 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,2 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,3 0 0133
+lB "
+\ 9,10,2 0 0134
+rs "
+] 9,10,3 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,3 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,3 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,10 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,9,1 0 0247
+§ "
+ad 9,9 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 055
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,9 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,9,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,1,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,11 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,9 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,3 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,9 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,9 0 0357
+ï "
+Sd 9,10 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,9 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/CR b/gnu/usr.bin/groff/devhtml/CR
new file mode 100644
index 00000000000..d8020a1b539
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/CR
@@ -0,0 +1,306 @@
+name CR
+spacewidth 9
+charset
+--- 9,1 0 040
+! 9,9 0 041
+" 9,10 0 042
+# 9,9,1 0 043
+sh "
+$ 9,11,2 0 044
+Do "
+% 9,10 0 045
+& 9,8 0 046
+' 9,10 0 047
+( 9,10,2 0 050
+) 9,10,2 0 051
+* 9,9 0 052
++ 9,8 0 053
+, 9,2,2 0 054
+\- 9,5 0 055
+. 9,2 0 056
+/ 9,10,1 0 057
+sl "
+0 9,10 0 060
+1 9,10 0 061
+2 9,10 0 062
+3 9,10 0 063
+4 9,10 0 064
+5 9,10 0 065
+6 9,10 0 066
+7 9,10 0 067
+8 9,10 0 070
+9 9,10 0 071
+: 9,7 0 072
+; 9,7,2 0 073
+< 9,8 0 074
+= 9,6 0 075
+eq "
+> 9,8 0 076
+? 9,9 0 077
+@ 9,9,1 0 0100
+at "
+A 9,9 0 0101
+B 9,9 0 0102
+C 9,9 0 0103
+D 9,9 0 0104
+E 9,9 0 0105
+F 9,9 0 0106
+G 9,9 0 0107
+H 9,9 0 0110
+I 9,9 0 0111
+J 9,9 0 0112
+K 9,9 0 0113
+L 9,9 0 0114
+M 9,9 0 0115
+N 9,9 0 0116
+O 9,9 0 0117
+P 9,9 0 0120
+Q 9,9,2 0 0121
+R 9,9 0 0122
+S 9,9 0 0123
+T 9,9 0 0124
+U 9,9 0 0125
+V 9,9 0 0126
+W 9,9 0 0127
+X 9,9 0 0130
+Y 9,9 0 0131
+Z 9,9 0 0132
+[ 9,10,2 0 0133
+lB "
+\ 9,10,1 0 0134
+rs "
+] 9,10,2 0 0135
+rB "
+^ 9,9 0 0136
+a^ "
+ha "
+_ 9,0,3 0 0137
+` 9,10 0 0140
+oq "
+a 9,7 0 0141
+b 9,10 0 0142
+c 9,7 0 0143
+d 9,10 0 0144
+e 9,7 0 0145
+f 9,10 0 0146
+g 9,7,3 0 0147
+h 9,10 0 0150
+i 9,10 0 0151
+j 9,10,3 0 0152
+k 9,10 0 0153
+l 9,10 0 0154
+m 9,7 0 0155
+n 9,7 0 0156
+o 9,7 0 0157
+p 9,7,3 0 0160
+q 9,7,3 0 0161
+r 9,7 0 0162
+s 9,7 0 0163
+t 9,9 0 0164
+u 9,7 0 0165
+v 9,7 0 0166
+w 9,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 9,10,2 0 0173
+lC "
+| 9,9,2 0 0174
+or "
+ba "
+} 9,10,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 9,7,2 0 0241
+¡ "
+ct 9,9 0 0242
+¢ "
+Po 9,9 0 0243
+£ "
+Cs 9,7 0 0244
+¤ "
+Ye 9,9 0 0245
+¥ "
+bb 9,9,2 0 0246
+¦ "
+sc 9,9,1 0 0247
+§ "
+ad 9,9 0 0250
+¨ "
+co 9,9 0 0251
+© "
+Of 9,9 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 9,5 0 055
+hy "
+­ "
+rg 9,9 0 0256
+® "
+a- 9,9 0 0257
+¯ "
+de 9,10 0 0260
+° "
++- 9,8 0 0261
+± "
+S2 9,10 0 0262
+² "
+S3 9,10 0 0263
+³ "
+aa 9,10 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,9,1 0 0266
+¶ "
+md 9,5 0 0267
+· "
+ac 9,0,3 0 0270
+¸ "
+S1 9,10 0 0271
+¹ "
+Om 9,9 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 9,10 0 0274
+¼ "
+12 9,10 0 0275
+½ "
+34 9,10 0 0276
+¾ "
+r? 9,7,2 0 0277
+¿ "
+`A 9,12 0 0300
+À "
+'A 9,12 0 0301
+Á "
+^A 9,12 0 0302
+Â "
+~A 9,12 0 0303
+Ã "
+:A 9,11 0 0304
+Ä "
+oA 9,12 0 0305
+Å "
+AE 9,9 0 0306
+Æ "
+,C 9,9,3 0 0307
+Ç "
+`E 9,12 0 0310
+È "
+'E 9,12 0 0311
+É "
+^E 9,12 0 0312
+Ê "
+:E 9,11 0 0313
+Ë "
+`I 9,12 0 0314
+Ì "
+'I 9,12 0 0315
+Í "
+^I 9,12 0 0316
+Î "
+:I 9,11 0 0317
+Ï "
+-D 9,9 0 0320
+Ð "
+~N 9,12 0 0321
+Ñ "
+`O 9,12 0 0322
+Ò "
+'O 9,12 0 0323
+Ó "
+^O 9,12 0 0324
+Ô "
+~O 9,12 0 0325
+Õ "
+:O 9,11 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 9,9 0 0330
+Ø "
+`U 9,12 0 0331
+Ù "
+'U 9,12 0 0332
+Ú "
+^U 9,12 0 0333
+Û "
+:U 9,11 0 0334
+Ü "
+'Y 9,12 0 0335
+Ý "
+TP 9,9 0 0336
+Þ "
+ss 9,9 0 0337
+ß "
+`a 9,10 0 0340
+à "
+'a 9,10 0 0341
+á "
+^a 9,10 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,9 0 0344
+ä "
+oa 9,10 0 0345
+å "
+ae 9,7 0 0346
+æ "
+,c 9,7,3 0 0347
+ç "
+`e 9,10 0 0350
+è "
+'e 9,10 0 0351
+é "
+^e 9,10 0 0352
+ê "
+:e 9,9 0 0353
+ë "
+`i 9,10 0 0354
+ì "
+'i 9,10 0 0355
+í "
+^i 9,10 0 0356
+î "
+:i 9,9 0 0357
+ï "
+Sd 9,12 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 9,10 0 0362
+ò "
+'o 9,10 0 0363
+ó "
+^o 9,10 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,9 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,7 0 0370
+ø "
+`u 9,10 0 0371
+ù "
+'u 9,10 0 0372
+ú "
+^u 9,10 0 0373
+û "
+:u 9,9 0 0374
+ü "
+'y 9,10,3 0 0375
+ý "
+Tp 9,9,3 0 0376
+þ "
+:y 9,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/DESC b/gnu/usr.bin/groff/devhtml/DESC
new file mode 100644
index 00000000000..dcab7cd4adf
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/DESC
@@ -0,0 +1,10 @@
+styles R I B BI
+fonts 6 0 0 0 0 0 S
+sizes 8 10 12 14 18 24 0
+res 100
+tcommand
+html
+hor 1
+vert 1
+unitwidth 10
+postpro grohtml
diff --git a/gnu/usr.bin/groff/devhtml/HB b/gnu/usr.bin/groff/devhtml/HB
new file mode 100644
index 00000000000..06f2bf95f61
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/HB
@@ -0,0 +1,306 @@
+name HB
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 7,11 0 042
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,1 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,1 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 8,7 0 076
+? 9,11 0 077
+@ 14,11,1 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 9,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 8,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 9,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,5 0 055
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 9,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 9,8,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,14 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,14 0 0322
+Ò "
+'O 12,14 0 0323
+Ó "
+^O 12,14 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 9,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,11 0 0357
+ï "
+Sd 9,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 9,11 0 0362
+ò "
+'o 9,11 0 0363
+ó "
+^o 9,11 0 0364
+ô "
+~o 9,11 0 0365
+õ "
+:o 9,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 9,8 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 8,11,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 8,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/HBI b/gnu/usr.bin/groff/devhtml/HBI
new file mode 100644
index 00000000000..bb2031a06c9
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/HBI
@@ -0,0 +1,306 @@
+name HBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 7,11 0 042
+# 10,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 11,10 0 046
+' 5,11 0 047
+( 5,11,3 0 050
+) 6,11,3 0 051
+* 6,11 0 052
++ 9,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 5,8 0 072
+; 5,8,2 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 9,7 0 076
+? 9,11 0 077
+@ 14,11,2 0 0100
+at "
+A 9,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 13,11 0 0115
+N 11,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11 0 0121
+R 10,11 0 0122
+S 10,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 10,11 0 0126
+W 14,11 0 0127
+X 9,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 5,11 0 0140
+oq "
+a 8,8 0 0141
+b 9,11 0 0142
+c 8,8 0 0143
+d 9,11 0 0144
+e 8,8 0 0145
+f 5,11 0 0146
+g 9,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 12,8 0 0155
+n 9,8 0 0156
+o 8,8 0 0157
+p 9,8,3 0 0160
+q 9,8,3 0 0161
+r 6,8 0 0162
+s 8,8 0 0163
+t 5,10 0 0164
+u 9,8 0 0165
+v 8,8 0 0166
+w 11,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 6,8 0 0172
+{ 6,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 6,11,3 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 9,8 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 9,11,3 0 0247
+§ "
+ad 5,11 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 11,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,5 0 055
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 5,11 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 11,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 13,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 9,14 0 0300
+À "
+'A 9,14 0 0301
+Á "
+^A 9,14 0 0302
+Â "
+~A 9,14 0 0303
+Ã "
+:A 9,14 0 0304
+Ä "
+oA 9,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 12,14 0 0322
+Ò "
+'O 12,14 0 0323
+Ó "
+^O 12,14 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 9,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,8 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 9,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/HI b/gnu/usr.bin/groff/devhtml/HI
new file mode 100644
index 00000000000..1c66db735f3
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/HI
@@ -0,0 +1,306 @@
+name HI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 9,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 8,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,8 0 072
+; 4,8,2 0 073
+< 9,7 0 074
+= 9,6 0 075
+eq "
+> 9,7 0 076
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 9,11 0 0106
+G 11,11 0 0107
+H 11,11 0 0110
+I 5,11 0 0111
+J 9,11 0 0112
+K 10,11 0 0113
+L 8,11 0 0114
+M 14,11 0 0115
+N 11,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 8,11 0 0124
+U 11,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 5,11,3 0 0133
+lB "
+\ 6,11 0 0134
+rs "
+] 5,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 8,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 4,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 8,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 4,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 4,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 5,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,5 0 055
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 4,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 4,11 0 0264
+´ "
+µ 8,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 3,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,13 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,11 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 11,14 0 0331
+Ù "
+'U 11,14 0 0332
+Ú "
+^U 11,14 0 0333
+Û "
+:U 11,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 9,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 12,8 0 0346
+æ "
+,c 7,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,9,1 0 0370
+ø "
+`u 8,11 0 0371
+ù "
+'u 8,11 0 0372
+ú "
+^u 8,11 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,11,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/HR b/gnu/usr.bin/groff/devhtml/HR
new file mode 100644
index 00000000000..756ef71120c
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/HR
@@ -0,0 +1,306 @@
+name HR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 10,10 0 046
+' 3,11 0 047
+( 5,11,3 0 050
+) 5,11,3 0 051
+* 7,11 0 052
++ 9,8 0 053
+, 3,2,2 0 054
+\- 9,5 0 055
+. 3,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 3,8 0 072
+; 4,8,2 0 073
+< 8,7 0 074
+= 9,6 0 075
+eq "
+> 8,7 0 076
+? 8,11 0 077
+@ 13,11,1 0 0100
+at "
+A 9,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 10,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 11,11 0 0107
+H 10,11 0 0110
+I 4,11 0 0111
+J 7,11 0 0112
+K 9,11 0 0113
+L 8,11 0 0114
+M 12,11 0 0115
+N 10,11 0 0116
+O 11,11 0 0117
+P 9,11 0 0120
+Q 11,11 0 0121
+R 10,11 0 0122
+S 9,11 0 0123
+T 9,11 0 0124
+U 10,11 0 0125
+V 9,11 0 0126
+W 13,11 0 0127
+X 9,11 0 0130
+Y 9,11 0 0131
+Z 9,11 0 0132
+[ 4,11,3 0 0133
+lB "
+\ 4,11 0 0134
+rs "
+] 4,11,3 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 8,0,3 0 0137
+` 3,11 0 0140
+oq "
+a 8,8 0 0141
+b 7,11 0 0142
+c 7,8 0 0143
+d 8,11 0 0144
+e 8,8 0 0145
+f 4,11 0 0146
+g 8,8,3 0 0147
+h 8,11 0 0150
+i 3,11 0 0151
+j 3,11,3 0 0152
+k 7,11 0 0153
+l 3,11 0 0154
+m 11,8 0 0155
+n 8,8 0 0156
+o 8,8 0 0157
+p 8,8,3 0 0160
+q 8,8,3 0 0161
+r 5,8 0 0162
+s 7,8 0 0163
+t 4,10 0 0164
+u 7,8 0 0165
+v 7,8 0 0166
+w 10,8 0 0167
+x 7,8 0 0170
+y 7,8,3 0 0171
+z 7,8 0 0172
+{ 5,11,3 0 0173
+lC "
+| 3,11,3 0 0174
+or "
+ba "
+} 5,11,3 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,1 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 7,11 0 0245
+¥ "
+bb 3,11,3 0 0246
+¦ "
+sc 8,11,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,5 0 055
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 4,10 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 8,8,3 0 0265
+ps 8,11,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 8,8,3 0 0277
+¿ "
+`A 9,14 0 0300
+À "
+'A 9,14 0 0301
+Á "
+^A 9,14 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,14 0 0304
+Ä "
+oA 9,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 4,14 0 0314
+Ì "
+'I 4,14 0 0315
+Í "
+^I 4,14 0 0316
+Î "
+:I 4,13 0 0317
+Ï "
+-D 10,11 0 0320
+Ð "
+~N 10,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 9,8 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 9,11 0 0336
+Þ "
+ss 7,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,11 0 0343
+ã "
+:a 8,11 0 0344
+ä "
+oa 8,12 0 0345
+å "
+ae 13,8 0 0346
+æ "
+,c 8,8,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,11 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,11 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 8,11 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,11 0 0365
+õ "
+:o 8,11 0 0366
+ö "
+di 9,8 0 0367
+÷ "
+/o 8,8 0 0370
+ø "
+`u 8,11 0 0371
+ù "
+'u 8,11 0 0372
+ú "
+^u 8,11 0 0373
+û "
+:u 8,11 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/Makefile.sub b/gnu/usr.bin/groff/devhtml/Makefile.sub
new file mode 100644
index 00000000000..57c9f44de77
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/Makefile.sub
@@ -0,0 +1,2 @@
+DEV=html
+DEVFILES=DESC TR TI TB TBI CR CI CB CBI HR HI HB HBI NR NI NB NBI S
diff --git a/gnu/usr.bin/groff/devhtml/NB b/gnu/usr.bin/groff/devhtml/NB
new file mode 100644
index 00000000000..88ef29f0e59
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/NB
@@ -0,0 +1,306 @@
+name NB
+spacewidth 11
+charset
+--- 11,1 0 040
+! 4,11 0 041
+" 5,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,3,2 0 054
+\- 8,5 0 055
+. 4,3 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 6,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,8 0 074
+= 8,6 0 075
+eq "
+> 8,8 0 076
+? 7,11 0 077
+@ 14,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 12,11 0 0107
+H 12,11 0 0110
+I 7,11 0 0111
+J 9,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 12,11 0 0117
+P 10,11 0 0120
+Q 12,11,3 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 14,11 0 0127
+X 12,11 0 0130
+Y 11,11 0 0131
+Z 9,11 0 0132
+[ 5,11,2 0 0133
+lB "
+\ 7,11 0 0134
+rs "
+] 5,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 10,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 9,7 0 0145
+f 6,11 0 0146
+g 8,8,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 5,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 9,7 0 0157
+p 10,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 6,10 0 0164
+u 10,7 0 0165
+v 7,7 0 0166
+w 12,7 0 0167
+x 9,7 0 0170
+y 7,7,3 0 0171
+z 7,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 8,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 8,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 9,10 0 0244
+¤ "
+Ye 11,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 7,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,5 0 055
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 7,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 6,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 10,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 7,8,3 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 7,15 0 0314
+Ì "
+'I 7,15 0 0315
+Í "
+^I 7,15 0 0316
+Î "
+:I 7,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 11,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 9,11 0 0337
+ß "
+`a 9,11 0 0340
+à "
+'a 9,11 0 0341
+á "
+^a 9,11 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 14,7 0 0346
+æ "
+,c 8,7,3 0 0347
+ç "
+`e 9,11 0 0350
+è "
+'e 9,11 0 0351
+é "
+^e 9,11 0 0352
+ê "
+:e 9,10 0 0353
+ë "
+`i 5,11 0 0354
+ì "
+'i 5,11 0 0355
+í "
+^i 5,11 0 0356
+î "
+:i 5,10 0 0357
+ï "
+Sd 9,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 9,11 0 0362
+ò "
+'o 9,11 0 0363
+ó "
+^o 9,11 0 0364
+ô "
+~o 9,10 0 0365
+õ "
+:o 9,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 9,8,1 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 10,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/NBI b/gnu/usr.bin/groff/devhtml/NBI
new file mode 100644
index 00000000000..58d9522ebde
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/NBI
@@ -0,0 +1,306 @@
+name NBI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+# 8,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 13,11,1 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 8,8 0 053
+, 4,2,3 0 054
+\- 8,5 0 055
+. 4,2 0 056
+/ 5,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 5,7,3 0 073
+< 9,9 0 074
+= 9,7 0 075
+eq "
+> 9,9 0 076
+? 7,11 0 077
+@ 13,11 0 0100
+at "
+A 11,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 12,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 8,11 0 0112
+K 12,11 0 0113
+L 10,11 0 0114
+M 15,11 0 0115
+N 13,11 0 0116
+O 12,11 0 0117
+P 11,11 0 0120
+Q 12,11,2 0 0121
+R 12,11 0 0122
+S 10,11 0 0123
+T 11,11 0 0124
+U 12,11 0 0125
+V 11,11 0 0126
+W 15,11 0 0127
+X 11,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 7,11,2 0 0133
+lB "
+\ 9,11 0 0134
+rs "
+] 7,11,2 0 0135
+rB "
+^ 8,11 0 0136
+a^ "
+ha "
+_ 9,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 10,7 0 0141
+b 8,11 0 0142
+c 8,7 0 0143
+d 10,11 0 0144
+e 8,7 0 0145
+f 5,11,3 0 0146
+g 8,9,3 0 0147
+h 10,11 0 0150
+i 5,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 5,11 0 0154
+m 15,7 0 0155
+n 10,7 0 0156
+o 8,7 0 0157
+p 8,7,3 0 0160
+q 9,7,3 0 0161
+r 7,7 0 0162
+s 8,7 0 0163
+t 5,9 0 0164
+u 10,7 0 0165
+v 8,7 0 0166
+w 13,7 0 0167
+x 9,7 0 0170
+y 9,7,3 0 0171
+z 9,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 11,6 0 0176
+a~ "
+ap "
+ti "
+r! 5,8,3 0 0241
+¡ "
+ct 8,8,1 0 0242
+¢ "
+Po 10,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 10,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 9,11,2 0 0247
+§ "
+ad 6,10 0 0250
+¨ "
+co 12,11 0 0251
+© "
+Of 8,11 0 0252
+ª "
+Fo 10,7 0 0253
+« "
+no 9,7 0 0254
+¬ "
+- 5,5 0 055
+hy "
+­ "
+rg 12,11 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 10,7,3 0 0265
+ps 9,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 8,11 0 0272
+º "
+Fc 10,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 7,8,3 0 0277
+¿ "
+`A 11,15 0 0300
+À "
+'A 11,15 0 0301
+Á "
+^A 11,15 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,15 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,15 0 0310
+È "
+'E 10,15 0 0311
+É "
+^E 10,15 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,15 0 0314
+Ì "
+'I 6,15 0 0315
+Í "
+^I 6,15 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 12,11 0 0320
+Ð "
+~N 13,14 0 0321
+Ñ "
+`O 12,15 0 0322
+Ò "
+'O 12,15 0 0323
+Ó "
+^O 12,15 0 0324
+Ô "
+~O 12,14 0 0325
+Õ "
+:O 12,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 12,11 0 0330
+Ø "
+`U 12,15 0 0331
+Ù "
+'U 12,15 0 0332
+Ú "
+^U 12,15 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,15 0 0335
+Ý "
+TP 11,11 0 0336
+Þ "
+ss 10,11,3 0 0337
+ß "
+`a 10,11 0 0340
+à "
+'a 10,11 0 0341
+á "
+^a 10,11 0 0342
+â "
+~a 10,10 0 0343
+ã "
+:a 10,10 0 0344
+ä "
+oa 10,11 0 0345
+å "
+ae 13,7 0 0346
+æ "
+,c 8,7,3 0 0347
+ç "
+`e 8,11 0 0350
+è "
+'e 8,11 0 0351
+é "
+^e 8,11 0 0352
+ê "
+:e 8,10 0 0353
+ë "
+`i 5,11 0 0354
+ì "
+'i 5,11 0 0355
+í "
+^i 5,11 0 0356
+î "
+:i 5,10 0 0357
+ï "
+Sd 8,11 0 0360
+ð "
+~n 10,10 0 0361
+ñ "
+`o 8,11 0 0362
+ò "
+'o 8,11 0 0363
+ó "
+^o 8,11 0 0364
+ô "
+~o 8,10 0 0365
+õ "
+:o 8,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 8,7 0 0370
+ø "
+`u 10,11 0 0371
+ù "
+'u 10,11 0 0372
+ú "
+^u 10,11 0 0373
+û "
+:u 10,10 0 0374
+ü "
+'y 9,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 9,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/NI b/gnu/usr.bin/groff/devhtml/NI
new file mode 100644
index 00000000000..b76ed021789
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/NI
@@ -0,0 +1,306 @@
+name NI
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,11 0 041
+" 6,11 0 042
+# 11,10 0 043
+sh "
+$ 8,12,1 0 044
+Do "
+% 12,11,1 0 045
+& 11,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 5,11,2 0 051
+* 6,11 0 052
++ 8,8 0 053
+, 4,2,2 0 054
+\- 9,5 0 055
+. 4,2 0 056
+/ 9,11,3 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 9,8 0 074
+= 8,6 0 075
+eq "
+> 9,8 0 076
+? 6,11 0 077
+@ 12,11 0 0100
+at "
+A 11,11 0 0101
+B 9,11 0 0102
+C 10,11 0 0103
+D 11,11 0 0104
+E 9,11 0 0105
+F 8,11 0 0106
+G 10,11 0 0107
+H 11,11 0 0110
+I 7,11 0 0111
+J 8,11 0 0112
+K 10,11 0 0113
+L 9,11 0 0114
+M 14,11 0 0115
+N 12,11 0 0116
+O 10,11 0 0117
+P 10,11 0 0120
+Q 10,11,2 0 0121
+R 11,11 0 0122
+S 10,11 0 0123
+T 10,11 0 0124
+U 12,11 0 0125
+V 10,11 0 0126
+W 13,11 0 0127
+X 10,11 0 0130
+Y 9,11 0 0131
+Z 10,11 0 0132
+[ 6,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 6,11,2 0 0135
+rB "
+^ 6,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 9,7 0 0141
+b 7,11 0 0142
+c 6,7 0 0143
+d 9,11 0 0144
+e 6,7 0 0145
+f 5,11,3 0 0146
+g 7,8,3 0 0147
+h 9,11 0 0150
+i 4,11 0 0151
+j 4,11,3 0 0152
+k 8,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 8,7,3 0 0161
+r 7,7 0 0162
+s 7,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 8,7 0 0170
+y 7,7,3 0 0171
+z 8,7 0 0172
+{ 6,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 6,11,2 0 0175
+rC "
+~ 9,6 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,2 0 0242
+¢ "
+Po 9,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 9,11 0 0245
+¥ "
+bb 8,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 7,10 0 0250
+¨ "
+co 13,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 8,7 0 0253
+« "
+no 8,6 0 0254
+¬ "
+- 5,5 0 055
+hy "
+­ "
+rg 13,11 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 8,8 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 4,11 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,11 0 0266
+¶ "
+md 5,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 6,11 0 0272
+º "
+Fc 8,7 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 6,8,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,14 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 14,11 0 0306
+Æ "
+,C 10,11,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,14 0 0313
+Ë "
+`I 7,14 0 0314
+Ì "
+'I 7,14 0 0315
+Í "
+^I 7,14 0 0316
+Î "
+:I 7,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 12,14 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,14 0 0325
+Õ "
+:O 10,14 0 0326
+Ö "
+mu 8,8 0 0327
+× "
+/O 10,11 0 0330
+Ø "
+`U 12,14 0 0331
+Ù "
+'U 12,14 0 0332
+Ú "
+^U 12,14 0 0333
+Û "
+:U 12,14 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11,3 0 0337
+ß "
+`a 9,11 0 0340
+à "
+'a 9,11 0 0341
+á "
+^a 9,11 0 0342
+â "
+~a 9,10 0 0343
+ã "
+:a 9,10 0 0344
+ä "
+oa 9,11 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 6,11 0 0350
+è "
+'e 6,11 0 0351
+é "
+^e 6,11 0 0352
+ê "
+:e 6,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,8 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 7,11,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/NR b/gnu/usr.bin/groff/devhtml/NR
new file mode 100644
index 00000000000..dd756b794bf
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/NR
@@ -0,0 +1,306 @@
+name NR
+spacewidth 4
+charset
+--- 4,1 0 040
+! 3,11 0 041
+" 5,11 0 042
+# 8,11 0 043
+sh "
+$ 8,12,2 0 044
+Do "
+% 12,11 0 045
+& 13,11 0 046
+' 4,11 0 047
+( 5,11,2 0 050
+) 6,11,2 0 051
+* 7,11 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 4,2 0 056
+/ 4,11 0 057
+sl "
+0 8,11 0 060
+1 8,11 0 061
+2 8,11 0 062
+3 8,11 0 063
+4 8,11 0 064
+5 8,11 0 065
+6 8,11 0 066
+7 8,11 0 067
+8 8,11 0 070
+9 8,11 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 10,7 0 074
+= 9,6 0 075
+eq "
+> 10,7 0 076
+? 6,11 0 077
+@ 13,11 0 0100
+at "
+A 10,11 0 0101
+B 10,11 0 0102
+C 11,11 0 0103
+D 11,11 0 0104
+E 10,11 0 0105
+F 10,11 0 0106
+G 11,11 0 0107
+H 12,11 0 0110
+I 6,11 0 0111
+J 7,11 0 0112
+K 11,11 0 0113
+L 10,11 0 0114
+M 16,11 0 0115
+N 13,11 0 0116
+O 11,11 0 0117
+P 10,11 0 0120
+Q 11,11,2 0 0121
+R 11,11 0 0122
+S 8,11 0 0123
+T 10,11 0 0124
+U 13,11 0 0125
+V 10,11 0 0126
+W 16,11 0 0127
+X 13,11 0 0130
+Y 10,11 0 0131
+Z 9,11 0 0132
+[ 4,11,2 0 0133
+lB "
+\ 8,11 0 0134
+rs "
+] 4,11,2 0 0135
+rB "
+^ 7,11 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 4,11 0 0140
+oq "
+a 8,7 0 0141
+b 7,11 0 0142
+c 7,7 0 0143
+d 8,11 0 0144
+e 7,7 0 0145
+f 5,11 0 0146
+g 8,7,3 0 0147
+h 9,11 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 9,11 0 0153
+l 4,11 0 0154
+m 14,7 0 0155
+n 9,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 7,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 9,7 0 0165
+v 8,7 0 0166
+w 12,7 0 0167
+x 8,7 0 0170
+y 8,7,3 0 0171
+z 7,7 0 0172
+{ 4,11,2 0 0173
+lC "
+| 9,11 0 0174
+or "
+ba "
+} 5,11,2 0 0175
+rC "
+~ 9,5 0 0176
+a~ "
+ap "
+ti "
+r! 4,8,3 0 0241
+¡ "
+ct 8,9,2 0 0242
+¢ "
+Po 8,11 0 0243
+£ "
+Cs 8,9 0 0244
+¤ "
+Ye 8,11 0 0245
+¥ "
+bb 9,11 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 6,10 0 0250
+¨ "
+co 14,11 0 0251
+© "
+Of 6,11 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,4 0 055
+hy "
+­ "
+rg 14,11 0 0256
+® "
+a- 5,9 0 0257
+¯ "
+de 6,11 0 0260
+° "
++- 9,7 0 0261
+± "
+S2 5,11 0 0262
+² "
+S3 5,11 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 9,7,3 0 0265
+ps 9,11,2 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,1,3 0 0270
+¸ "
+S1 5,11 0 0271
+¹ "
+Om 5,11 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 12,11 0 0274
+¼ "
+12 12,11 0 0275
+½ "
+34 12,11 0 0276
+¾ "
+r? 6,8,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,14 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 15,11 0 0306
+Æ "
+,C 11,11,3 0 0307
+Ç "
+`E 10,14 0 0310
+È "
+'E 10,14 0 0311
+É "
+^E 10,14 0 0312
+Ê "
+:E 10,14 0 0313
+Ë "
+`I 6,14 0 0314
+Ì "
+'I 6,14 0 0315
+Í "
+^I 6,14 0 0316
+Î "
+:I 6,14 0 0317
+Ï "
+-D 11,11 0 0320
+Ð "
+~N 13,14 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,14 0 0325
+Õ "
+:O 11,14 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 11,11 0 0330
+Ø "
+`U 13,14 0 0331
+Ù "
+'U 13,14 0 0332
+Ú "
+^U 13,14 0 0333
+Û "
+:U 13,14 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 10,11 0 0336
+Þ "
+ss 8,11 0 0337
+ß "
+`a 8,11 0 0340
+à "
+'a 8,11 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,10 0 0343
+ã "
+:a 8,10 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 12,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,11 0 0360
+ð "
+~n 9,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 9,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 9,11 0 0371
+ù "
+'u 9,11 0 0372
+ú "
+^u 9,11 0 0373
+û "
+:u 9,10 0 0374
+ü "
+'y 8,11,3 0 0375
+ý "
+Tp 8,11,3 0 0376
+þ "
+:y 8,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/S b/gnu/usr.bin/groff/devhtml/S
new file mode 100644
index 00000000000..59af889e130
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/S
@@ -0,0 +1,226 @@
+name S
+special
+spacewidth 4
+charset
+--- 4,1 0 040
+! 5,10 0 041
+fa 9,10 0 042
+# 7,10 0 043
+sh "
+te 8,10 0 044
+% 12,10 0 045
+& 11,10 0 046
+st 6,7 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+** 7,8 0 052
++ 8,7 0 053
+pl "
+, 3,2,2 0 054
+\- 8,4 0 055
+mi "
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,10 0 077
+=~ 8,7 0 0100
+*A 11,10 0 0101
+*B 9,10 0 0102
+*X 11,10 0 0103
+*D 9,10 0 0104
+*E 9,10 0 0105
+*F 11,10 0 0106
+*G 9,10 0 0107
+*Y 11,10 0 0110
+*I 5,10 0 0111
++h 9,10 0 0112
+*K 10,10 0 0113
+*L 10,10 0 0114
+*M 13,10 0 0115
+*N 11,10 0 0116
+*O 10,10 0 0117
+*P 11,10 0 0120
+*H 10,10 0 0121
+*R 8,10 0 0122
+*S 9,10 0 0123
+*T 9,10 0 0124
+--- 9,10 0 0125
+ts 7,7,3 0 0126
+*W 11,10 0 0127
+*C 9,10 0 0130
+*Q 11,10 0 0131
+*Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+tf 10,7 0 0134
+3d "
+] 5,10,3 0 0135
+rB "
+pp 10,10 0 0136
+_ 7,0,3 0 0137
+radicalex 7,12 0 0140
+*a 9,7 0 0141
+*b 8,11,3 0 0142
+*x 8,7,3 0 0143
+*d 7,11 0 0144
+*e 6,7 0 0145
+*f 9,10,3 0 0146
+*g 6,7,3 0 0147
+*y 8,7,3 0 0150
+*i 5,7 0 0151
++f 9,7,3 0 0152
+*k 8,7 0 0153
+*l 8,10 0 0154
+*m 8,7,2 0 0155
+µ "
+*n 8,7 0 0156
+*o 8,7 0 0157
+*p 8,7 0 0160
+*h 7,10 0 0161
+*r 8,7,3 0 0162
+*s 8,7 0 0163
+*t 6,7 0 0164
+*u 8,7 0 0165
++p 11,8 0 0166
+*w 11,7 0 0167
+*c 7,12,3 0 0170
+*q 9,7,3 0 0171
+*z 7,11,3 0 0172
+lC 7,10,3 0 0173
+{ "
+ba 3,10,3 0 0174
+or "
+| "
+rC 7,10,3 0 0175
+} "
+ap 8,5 0 0176
+*U 9,10 0 0241
+fm 4,10 0 0242
+<= 8,9 0 0243
+f/ 4,10 0 0244
+if 10,6 0 0245
+Fn 7,10,3 0 0246
+CL 11,7 0 0247
+DI 11,7 0 0250
+HE 11,7 0 0251
+SP 11,7 0 0252
+<> 15,7 0 0253
+<- 14,7 0 0254
+ua 9,12,3 0 0255
+arrowverttp "
+-> 14,7 0 0256
+da 9,12,3 0 0257
+arrowvertbt "
+de 6,10 0 0260
+° "
++- 8,9 0 0261
+± "
+sd 6,10 0 0262
+>= 8,9 0 0263
+mu 8,7 0 0264
+× "
+pt 10,6 0 0265
+pd 7,11 0 0266
+bu 7,6 0 0267
+di 8,7 0 0270
+÷ "
+!= 8,7 0 0271
+== 8,6 0 0272
+~= 8,7 0 0273
+~~ "
+--- 15,2 0 0274
+arrowvertex 9,12,3 0 0275
+an 15,4 0 0276
+CR 10,9 0 0277
+Ah 12,10 0 0300
+Im 10,11,1 0 0301
+Re 12,11 0 0302
+wp 12,9,3 0 0303
+c* 11,9 0 0304
+c+ 11,9 0 0305
+es 12,11 0 0306
+ca 10,7 0 0307
+cu 10,7 0 0310
+sp 10,7 0 0311
+ip 10,7,2 0 0312
+--- 10,8,1 0 0313
+sb 10,7 0 0314
+ib 10,7,2 0 0315
+mo 10,7 0 0316
+nm 10,8,1 0 0317
+/_ 11,10 0 0320
+gr 10,11 0 0321
+rg 12,10 0 0322
+co 12,10 0 0323
+tm 11,10 0 0324
+--- 12,11,1 0 0325
+sr 8,12 0 0326
+md 4,5 0 0327
+no 10,5 0 0330
+¬ "
+AN 9,7 0 0331
+OR 9,7 0 0332
+hA 15,7 0 0333
+lA 14,7 0 0334
+uA 9,12 0 0335
+rA 14,7 0 0336
+dA 9,12 0 0337
+lz 7,11 0 0340
+la 5,12,3 0 0341
+--- 12,10 0 0342
+--- 12,10 0 0343
+--- 11,10 0 0344
+--- 10,11,1 0 0345
+parenlefttp 6,12,3 0 0346
+parenleftex 6,12,3 0 0347
+parenleftbt 6,12,3 0 0350
+bracketlefttp 6,12,3 0 0351
+lc "
+bracketleftex 6,12,3 0 0352
+bracketleftbt 6,12,3 0 0353
+lf "
+bracelefttp 7,12,3 0 0354
+lt "
+braceleftmid 7,12,3 0 0355
+lk "
+braceleftbt 7,12,3 0 0356
+lb "
+bracerightex 7,12,3 0 0357
+braceleftex "
+bv "
+--- 12,12 0 0360
+ra 5,12,3 0 0361
+is 4,12,1 0 0362
+--- 10,12,3 0 0363
+--- 10,12,3 0 0364
+--- 10,12,3 0 0365
+parenrighttp 6,12,3 0 0366
+parenrightex 6,12,3 0 0367
+parenrightbt 6,12,3 0 0370
+bracketrighttp 6,12,3 0 0371
+rc "
+bracketrightex 6,12,3 0 0372
+bracketrightbt 6,12,3 0 0373
+rf "
+bracerighttp 7,12,3 0 0374
+rt "
+bracerightmid 7,12,3 0 0375
+rk "
+bracerightbt 7,12,3 0 0376
+rb "
diff --git a/gnu/usr.bin/groff/devhtml/TB b/gnu/usr.bin/groff/devhtml/TB
new file mode 100644
index 00000000000..fbc4c8b20e7
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/TB
@@ -0,0 +1,306 @@
+name TB
+spacewidth 3
+charset
+--- 3,1 0 040
+! 4,10 0 041
+" 7,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 12,10 0 046
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 3,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 7,10 0 077
+@ 14,10,2 0 0100
+at "
+A 10,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 10,10 0 0116
+O 11,10 0 0117
+P 9,10 0 0120
+Q 11,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 14,10 0 0127
+X 10,10 0 0130
+Y 10,10 0 0131
+Z 9,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 8,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 6,7 0 0145
+f 5,10 0 0146
+g 7,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 8,10 0 0153
+l 4,10 0 0154
+m 12,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 8,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 10,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10,2 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,7 0 0176
+a~ "
+ap "
+ti "
+r! 4,7,3 0 0241
+¡ "
+ct 7,9,2 0 0242
+¢ "
+Po 8,10 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 8,10 0 0245
+¥ "
+bb 3,10,2 0 0246
+¦ "
+sc 7,10,2 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 5,10 0 0252
+ª "
+Fo 9,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 4,4 0 055
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 5,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 8,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,6 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 9,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 7,7,3 0 0277
+¿ "
+`A 10,14 0 0300
+À "
+'A 10,14 0 0301
+Á "
+^A 10,14 0 0302
+Â "
+~A 10,13 0 0303
+Ã "
+:A 10,13 0 0304
+Ä "
+oA 10,14 0 0305
+Å "
+AE 14,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 11,10 0 0320
+Ð "
+~N 10,13 0 0321
+Ñ "
+`O 11,14 0 0322
+Ò "
+'O 11,14 0 0323
+Ó "
+^O 11,14 0 0324
+Ô "
+~O 11,13 0 0325
+Õ "
+:O 11,13 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 11,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 10,14 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 8,10 0 0337
+ß "
+`a 7,11 0 0340
+à "
+'a 7,11 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,10 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,11 0 0354
+ì "
+'i 4,11 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 8,10 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,11 0 0371
+ù "
+'u 7,11 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 8,10,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/TBI b/gnu/usr.bin/groff/devhtml/TBI
new file mode 100644
index 00000000000..56c55cf30db
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/TBI
@@ -0,0 +1,306 @@
+name TBI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 7,10 0 041
+" 7,10 0 042
+# 8,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 14,10 0 045
+& 10,10 0 046
+' 5,10 0 047
+( 6,10,3 0 050
+) 6,10,3 0 051
+* 7,10 0 052
++ 9,7 0 053
+, 4,2,2 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 6,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 5,7 0 072
+; 4,7,2 0 073
+< 8,6 0 074
+= 10,5 0 075
+eq "
+> 8,6 0 076
+? 8,10 0 077
+@ 15,10,2 0 0100
+at "
+A 9,10 0 0101
+B 9,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 10,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 11,10 0 0110
+I 5,10 0 0111
+J 7,10,1 0 0112
+K 11,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 10,10 0 0122
+S 8,10 0 0123
+T 10,10 0 0124
+U 10,10 0 0125
+V 10,10 0 0126
+W 13,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 6,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 8,10 0 0136
+a^ "
+ha "
+_ 7,0,2 0 0137
+` 5,10 0 0140
+oq "
+a 8,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 8,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 11,7 0 0155
+n 8,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 6,7 0 0162
+s 6,7 0 0163
+t 4,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 6,7 0 0170
+y 6,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 4,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 10,5 0 0176
+a~ "
+ap "
+ti "
+r! 7,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 7,10 0 0243
+£ "
+Cs 8,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 4,10 0 0246
+¦ "
+sc 8,10,3 0 0247
+§ "
+ad 6,9 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 6,10 0 0252
+ª "
+Fo 8,6 0 0253
+« "
+no 9,5 0 0254
+¬ "
+- 5,4 0 055
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 6,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 9,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 6,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 6,10 0 0272
+º "
+Fc 8,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 8,7,3 0 0277
+¿ "
+`A 9,13 0 0300
+À "
+'A 9,13 0 0301
+Á "
+^A 9,13 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,13 0 0304
+Ä "
+oA 9,13 0 0305
+Å "
+AE 14,10 0 0306
+Æ "
+,C 9,10,3 0 0307
+Ç "
+`E 10,13 0 0310
+È "
+'E 10,13 0 0311
+É "
+^E 10,13 0 0312
+Ê "
+:E 10,13 0 0313
+Ë "
+`I 5,13 0 0314
+Ì "
+'I 5,13 0 0315
+Í "
+^I 5,13 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,13 0 0321
+Ñ "
+`O 10,13 0 0322
+Ò "
+'O 10,13 0 0323
+Ó "
+^O 10,13 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 9,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,13 0 0331
+Ù "
+'U 10,13 0 0332
+Ú "
+^U 10,13 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 8,13 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 7,10,3 0 0337
+ß "
+`a 8,10 0 0340
+à "
+'a 8,10 0 0341
+á "
+^a 8,11 0 0342
+â "
+~a 8,10 0 0343
+ã "
+:a 8,10 0 0344
+ä "
+oa 8,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 4,10 0 0354
+ì "
+'i 4,10 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 8,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 9,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 6,10,2 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 6,10,2 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/TI b/gnu/usr.bin/groff/devhtml/TI
new file mode 100644
index 00000000000..fddf4b74fbf
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/TI
@@ -0,0 +1,306 @@
+name TI
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 5,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 10,7 0 053
+, 4,2,1 0 054
+\- 9,4 0 055
+. 3,2 0 056
+/ 4,10 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,1 0 073
+< 10,7,1 0 074
+= 10,5 0 075
+eq "
+> 10,7,1 0 076
+? 7,10 0 077
+@ 13,10,3 0 0100
+at "
+A 9,10 0 0101
+B 8,10 0 0102
+C 9,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 9,10 0 0106
+G 10,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 8,10 0 0114
+M 12,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 9,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 7,10 0 0123
+T 8,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 11,10 0 0127
+X 9,10 0 0130
+Y 8,10 0 0131
+Z 8,10 0 0132
+[ 6,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 6,10,3 0 0135
+rB "
+^ 6,10 0 0136
+a^ "
+ha "
+_ 7,0,4 0 0137
+` 5,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 6,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 5,10,3 0 0146
+g 6,7,3 0 0147
+h 7,10 0 0150
+i 4,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 4,10 0 0154
+m 10,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 5,9 0 0164
+u 7,7 0 0165
+v 6,7 0 0166
+w 9,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 6,10,3 0 0173
+lC "
+| 4,10,3 0 0174
+or "
+ba "
+} 6,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 6,7,3 0 0241
+¡ "
+ct 7,9,2 0 0242
+¢ "
+Po 7,10 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 4,10,3 0 0246
+¦ "
+sc 7,11,2 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 5,10 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 5,4 0 055
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 5,10 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 10,9 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 4,10 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 8,10,3 0 0266
+¶ "
+md 4,4 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 7,7,3 0 0277
+¿ "
+`A 9,13 0 0300
+À "
+'A 9,13 0 0301
+Á "
+^A 9,13 0 0302
+Â "
+~A 9,13 0 0303
+Ã "
+:A 9,12 0 0304
+Ä "
+oA 9,13 0 0305
+Å "
+AE 13,10 0 0306
+Æ "
+,C 9,10,3 0 0307
+Ç "
+`E 9,13 0 0310
+È "
+'E 9,13 0 0311
+É "
+^E 9,13 0 0312
+Ê "
+:E 9,12 0 0313
+Ë "
+`I 5,13 0 0314
+Ì "
+'I 5,13 0 0315
+Í "
+^I 5,13 0 0316
+Î "
+:I 5,12 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,13 0 0321
+Ñ "
+`O 10,13 0 0322
+Ò "
+'O 10,13 0 0323
+Ó "
+^O 10,13 0 0324
+Ô "
+~O 10,13 0 0325
+Õ "
+:O 10,12 0 0326
+Ö "
+mu 10,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,13 0 0331
+Ù "
+'U 10,13 0 0332
+Ú "
+^U 10,13 0 0333
+Û "
+:U 10,12 0 0334
+Ü "
+'Y 8,13 0 0335
+Ý "
+TP 9,10 0 0336
+Þ "
+ss 7,10,3 0 0337
+ß "
+`a 7,10 0 0340
+à "
+'a 7,10 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,10 0 0343
+ã "
+:a 7,9 0 0344
+ä "
+oa 7,10 0 0345
+å "
+ae 10,7 0 0346
+æ "
+,c 6,7,3 0 0347
+ç "
+`e 7,10 0 0350
+è "
+'e 7,10 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,9 0 0353
+ë "
+`i 4,10 0 0354
+ì "
+'i 4,10 0 0355
+í "
+^i 4,11 0 0356
+î "
+:i 4,9 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,10 0 0361
+ñ "
+`o 7,10 0 0362
+ò "
+'o 7,10 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,10 0 0365
+õ "
+:o 7,9 0 0366
+ö "
+di 10,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,10 0 0371
+ù "
+'u 7,10 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,9 0 0374
+ü "
+'y 7,10,3 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 7,9,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/devhtml/TR b/gnu/usr.bin/groff/devhtml/TR
new file mode 100644
index 00000000000..c5c5f54e6b9
--- /dev/null
+++ b/gnu/usr.bin/groff/devhtml/TR
@@ -0,0 +1,306 @@
+name TR
+spacewidth 3
+charset
+--- 3,1 0 040
+! 5,10 0 041
+" 6,10 0 042
+# 7,10 0 043
+sh "
+$ 7,11,1 0 044
+Do "
+% 12,10 0 045
+& 11,10 0 046
+' 4,10 0 047
+( 5,10,3 0 050
+) 5,10,3 0 051
+* 7,10 0 052
++ 8,7 0 053
+, 4,1,2 0 054
+\- 9,4 0 055
+. 4,1 0 056
+/ 4,10,2 0 057
+sl "
+0 7,10 0 060
+1 7,10 0 061
+2 7,10 0 062
+3 7,10 0 063
+4 7,10 0 064
+5 7,10 0 065
+6 7,10 0 066
+7 7,10 0 067
+8 7,10 0 070
+9 7,10 0 071
+: 4,7 0 072
+; 4,7,2 0 073
+< 8,7 0 074
+= 8,5 0 075
+eq "
+> 8,7 0 076
+? 6,10 0 077
+@ 13,10,2 0 0100
+at "
+A 11,10 0 0101
+B 9,10 0 0102
+C 10,10 0 0103
+D 10,10 0 0104
+E 9,10 0 0105
+F 8,10 0 0106
+G 11,10 0 0107
+H 10,10 0 0110
+I 5,10 0 0111
+J 6,10 0 0112
+K 10,10 0 0113
+L 9,10 0 0114
+M 13,10 0 0115
+N 11,10 0 0116
+O 10,10 0 0117
+P 8,10 0 0120
+Q 10,10,3 0 0121
+R 9,10 0 0122
+S 8,10 0 0123
+T 9,10 0 0124
+U 10,10 0 0125
+V 9,10 0 0126
+W 13,10 0 0127
+X 10,10 0 0130
+Y 9,10 0 0131
+Z 8,10 0 0132
+[ 5,10,3 0 0133
+lB "
+\ 4,10 0 0134
+rs "
+] 5,10,3 0 0135
+rB "
+^ 7,10 0 0136
+a^ "
+ha "
+_ 7,0,3 0 0137
+` 4,10 0 0140
+oq "
+a 7,7 0 0141
+b 7,10 0 0142
+c 7,7 0 0143
+d 7,10 0 0144
+e 7,7 0 0145
+f 4,10 0 0146
+g 7,7,3 0 0147
+h 7,10 0 0150
+i 3,10 0 0151
+j 4,10,3 0 0152
+k 7,10 0 0153
+l 3,10 0 0154
+m 11,7 0 0155
+n 7,7 0 0156
+o 7,7 0 0157
+p 7,7,3 0 0160
+q 7,7,3 0 0161
+r 5,7 0 0162
+s 6,7 0 0163
+t 4,8 0 0164
+u 7,7 0 0165
+v 7,7 0 0166
+w 11,7 0 0167
+x 7,7 0 0170
+y 7,7,3 0 0171
+z 6,7 0 0172
+{ 7,10,3 0 0173
+lC "
+| 3,10 0 0174
+or "
+ba "
+} 7,10,3 0 0175
+rC "
+~ 8,5 0 0176
+a~ "
+ap "
+ti "
+r! 5,7,3 0 0241
+¡ "
+ct 7,8,1 0 0242
+¢ "
+Po 8,10 0 0243
+£ "
+Cs 7,8 0 0244
+¤ "
+Ye 7,10 0 0245
+¥ "
+bb 3,10 0 0246
+¦ "
+sc 7,10,3 0 0247
+§ "
+ad 5,10 0 0250
+¨ "
+co 12,10 0 0251
+© "
+Of 4,10 0 0252
+ª "
+Fo 7,6 0 0253
+« "
+no 9,6 0 0254
+¬ "
+- 4,4 0 055
+hy "
+­ "
+rg 12,10 0 0256
+® "
+a- 4,9 0 0257
+¯ "
+de 6,10 0 0260
+° "
++- 8,7 0 0261
+± "
+S2 4,10 0 0262
+² "
+S3 4,10 0 0263
+³ "
+aa 5,11 0 0264
+´ "
+µ 7,7,3 0 0265
+ps 7,10,3 0 0266
+¶ "
+md 4,5 0 0267
+· "
+ac 5,0,3 0 0270
+¸ "
+S1 4,10 0 0271
+¹ "
+Om 5,10 0 0272
+º "
+Fc 7,6 0 0273
+» "
+14 10,10 0 0274
+¼ "
+12 10,10 0 0275
+½ "
+34 10,10 0 0276
+¾ "
+r? 6,7,3 0 0277
+¿ "
+`A 11,14 0 0300
+À "
+'A 11,14 0 0301
+Á "
+^A 11,14 0 0302
+Â "
+~A 11,14 0 0303
+Ã "
+:A 11,13 0 0304
+Ä "
+oA 11,14 0 0305
+Å "
+AE 13,10 0 0306
+Æ "
+,C 10,10,3 0 0307
+Ç "
+`E 9,14 0 0310
+È "
+'E 9,14 0 0311
+É "
+^E 9,14 0 0312
+Ê "
+:E 9,13 0 0313
+Ë "
+`I 5,14 0 0314
+Ì "
+'I 5,14 0 0315
+Í "
+^I 5,14 0 0316
+Î "
+:I 5,13 0 0317
+Ï "
+-D 10,10 0 0320
+Ð "
+~N 11,14 0 0321
+Ñ "
+`O 10,14 0 0322
+Ò "
+'O 10,14 0 0323
+Ó "
+^O 10,14 0 0324
+Ô "
+~O 10,14 0 0325
+Õ "
+:O 10,13 0 0326
+Ö "
+mu 8,7 0 0327
+× "
+/O 10,11,1 0 0330
+Ø "
+`U 10,14 0 0331
+Ù "
+'U 10,14 0 0332
+Ú "
+^U 10,14 0 0333
+Û "
+:U 10,13 0 0334
+Ü "
+'Y 9,14 0 0335
+Ý "
+TP 8,10 0 0336
+Þ "
+ss 7,10 0 0337
+ß "
+`a 7,11 0 0340
+à "
+'a 7,11 0 0341
+á "
+^a 7,11 0 0342
+â "
+~a 7,11 0 0343
+ã "
+:a 7,10 0 0344
+ä "
+oa 7,11 0 0345
+å "
+ae 11,7 0 0346
+æ "
+,c 7,7,3 0 0347
+ç "
+`e 7,11 0 0350
+è "
+'e 7,11 0 0351
+é "
+^e 7,11 0 0352
+ê "
+:e 7,10 0 0353
+ë "
+`i 3,11 0 0354
+ì "
+'i 3,11 0 0355
+í "
+^i 3,11 0 0356
+î "
+:i 3,10 0 0357
+ï "
+Sd 7,10 0 0360
+ð "
+~n 7,11 0 0361
+ñ "
+`o 7,11 0 0362
+ò "
+'o 7,11 0 0363
+ó "
+^o 7,11 0 0364
+ô "
+~o 7,11 0 0365
+õ "
+:o 7,10 0 0366
+ö "
+di 8,7 0 0367
+÷ "
+/o 7,8,1 0 0370
+ø "
+`u 7,11 0 0371
+ù "
+'u 7,11 0 0372
+ú "
+^u 7,11 0 0373
+û "
+:u 7,10 0 0374
+ü "
+'y 7,11,3 0 0375
+ý "
+Tp 7,10,3 0 0376
+þ "
+:y 7,10,3 0 0377
+ÿ "
diff --git a/gnu/usr.bin/groff/doc/groff.texinfo b/gnu/usr.bin/groff/doc/groff.texinfo
new file mode 100644
index 00000000000..d3b7367c3f8
--- /dev/null
+++ b/gnu/usr.bin/groff/doc/groff.texinfo
@@ -0,0 +1,5762 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header (This is for running Texinfo on a region.)
+@setfilename groff
+@settitle The GNU Troff Manual
+@setchapternewpage odd
+@footnotestyle separate
+@c %**end of header (This is for running Texinfo on a region.)
+
+
+@dircategory Miscellaneous
+@direntry
+* Groff: (groff). The GNU troff document formatting system.
+@end direntry
+
+
+@smallbook
+
+
+@iftex
+@finalout
+@end iftex
+
+
+@ifinfo
+This Info file documents GNU troff version 1.12.
+
+Published by the Free Software Foundation
+59 Temple Place, Suite 330
+Boston, MA 02111-1307 USA
+
+Copyright (C) 1994, 1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation
+approved by the Foundation.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included exactly as
+in the original, and provided that the entire resulting derived work is
+distributed under the terms of a permission notice identical to this
+one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' may be
+included in a translation approved by the Free Software Foundation
+instead of in the original English.
+@end ifinfo
+
+
+@titlepage
+@title groff
+@subtitle The GNU implementation of @code{groff}
+@subtitle Edition 1.12
+@subtitle October 1999
+@author by Trent A.@w{ }Fisher
+@author and the maintainer of groff
+
+@c Include the Distribution inside the titlepage environment so
+@c that headings are turned off. Headings on and off do not work.
+
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1994, 1999 Free Software Foundation, Inc.
+
+@sp 2
+Version 1.13 of @code{groff}, @*
+October 1999
+@sp 2
+Published by the Free Software Foundation @*
+59 Temple Place, Suite 330 @*
+Boston, MA 02111-1307 USA
+
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+section entitled ``GNU General Public License'' is included
+exactly as in the original, and provided that the entire resulting
+derived work is distributed under the terms of a permission notice
+identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that the section entitled ``GNU General Public License'' may be
+included in a translation approved by the Free Software Foundation
+instead of in the original English.
+
+Cover art by Etienne Suvasa.
+@end titlepage
+@page
+
+
+
+@node Top, Copying, (dir), (dir)
+
+@ifinfo
+This Info file documents groff version 1.13, the GNU implementation of
+the troff typesetting system.
+
+This is an in-progress document; contributions, comments, or
+contributions are welcome. Send them to bug-groff@@gnu.org.
+@end ifinfo
+
+@menu
+* Copying::
+* Introduction::
+* Invoking groff::
+* Tutorial for Macro Users::
+* -man::
+* -ms::
+* -me::
+* -mm::
+* Programming Tutorial::
+* geqn::
+* gtbl::
+* gpic::
+* grap::
+* grefer::
+* gsoelim::
+* Devices::
+* File formats::
+* Installation::
+* Request Index::
+* Register Index::
+* String Index::
+* Macro Index::
+* Program Index::
+* Concept Index::
+@end menu
+
+
+
+@node Copying, Introduction, Top, Top
+@cindex copying
+@unnumbered GNU GENERAL PUBLIC LICENSE
+@center Version 2, June 1991
+
+@display
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+@end display
+
+@unnumberedsec Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is
+intended to guarantee your freedom to share and change free software --
+to make sure the software is free for all its users. This General
+Public License applies to most of the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+(Some other Free Software Foundation software is covered by the GNU
+Library General Public License instead.) You can apply it to your
+programs, too.
+
+When we speak of free software, we are referring to freedom, not price.
+Our General Public Licenses are designed to make sure that you have the
+freedom to distribute copies of free software (and charge for this
+service if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone
+to deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis
+or for a fee, you must give the recipients all the rights that you have.
+You must make sure that they, too, receive or can get the source code.
+And you must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1)@w{ }copyright the software,
+and (2)@w{ }offer you this license which gives you legal permission to
+copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+Finally, any free program is threatened constantly by software patents.
+We wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program
+proprietary. To prevent this, we have made it clear that any patent
+must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+@iftex
+@unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end iftex
+@ifinfo
+@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+@end ifinfo
+
+@enumerate 0
+@item
+This License applies to any program or other work which contains a
+notice placed by the copyright holder saying it may be distributed under
+the terms of this General Public License. The ``Program'', below,
+refers to any such program or work, and a ``work based on the Program''
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it, either
+verbatim or with modifications and/or translated into another language.
+(Hereinafter, translation is included without limitation in the term
+``modification''.) Each licensee is addressed as ``you''.
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of running
+the Program is not restricted, and the output from the Program is
+covered only if its contents constitute a work based on the Program
+(independent of having been made by running the Program). Whether that
+is true depends on what the Program does.
+
+@item
+You may copy and distribute verbatim copies of the Program's source code
+as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+License and to the absence of any warranty; and give any other
+recipients of the Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+@item
+You may modify your copy or copies of the Program or any portion of it,
+thus forming a work based on the Program, and copy and distribute such
+modifications or work under the terms of Section@w{ }1 above, provided
+that you also meet all of these conditions:
+
+@enumerate a
+@item
+You must cause the modified files to carry prominent notices stating
+that you changed the files and the date of any change.
+
+@item
+You must cause any work that you distribute or publish, that in whole or
+in part contains or is derived from the Program or any part thereof, to
+be licensed as a whole at no charge to all third parties under the terms
+of this License.
+
+@item
+If the modified program normally reads commands interactively when run,
+you must cause it, when started running for such interactive use in the
+most ordinary way, to print or display an announcement including an
+appropriate copyright notice and a notice that there is no warranty (or
+else, saying that you provide a warranty) and that users may
+redistribute the program under these conditions, and telling the user
+how to view a copy of this License. (Exception: if the Program itself
+is interactive but does not normally print such an announcement, your
+work based on the Program is not required to print an announcement.)
+@end enumerate
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program, and
+can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based on
+the Program, the distribution of the whole must be on the terms of this
+License, whose permissions for other licensees extend to the entire
+whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of a
+storage or distribution medium does not bring the other work under the
+scope of this License.
+
+@item
+You may copy and distribute the Program (or a work based on it, under
+Section@w{ }2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+@enumerate a
+@item
+Accompany it with the complete corresponding machine-readable source
+code, which must be distributed under the terms of Sections 1 and 2
+above on a medium customarily used for software interchange; or,
+
+@item
+Accompany it with a written offer, valid for at least three years, to
+give any third party, for a charge no more than your cost of physically
+performing source distribution, a complete machine-readable copy of the
+corresponding source code, to be distributed under the terms of Sections
+1 and 2 above on a medium customarily used for software interchange; or,
+
+@item
+Accompany it with the information you received as to the offer to
+distribute corresponding source code. (This alternative is allowed only
+for noncommercial distribution and only if you received the program in
+object code or executable form with such an offer, in accord with
+Subsection b above.)
+@end enumerate
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to control
+compilation and installation of the executable. However, as a special
+exception, the source code distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies the
+executable.
+
+If distribution of executable or object code is made by offering access
+to copy from a designated place, then offering equivalent access to copy
+the source code from the same place counts as distribution of the source
+code, even though third parties are not compelled to copy the source
+along with the object code.
+
+@item
+You may not copy, modify, sublicense, or distribute the Program except
+as expressly provided under this License. Any attempt otherwise to
+copy, modify, sublicense or distribute the Program is void, and will
+automatically terminate your rights under this License. However,
+parties who have received copies, or rights, from you under this License
+will not have their licenses terminated so long as such parties remain
+in full compliance.
+
+@item
+You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute
+the Program or its derivative works. These actions are prohibited by
+law if you do not accept this License. Therefore, by modifying or
+distributing the Program (or any work based on the Program), you
+indicate your acceptance of this License to do so, and all its terms and
+conditions for copying, distributing or modifying the Program or works
+based on it.
+
+@item
+Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further restrictions
+on the recipients' exercise of the rights granted herein. You are not
+responsible for enforcing compliance by third parties to this License.
+
+@item
+If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent license
+would not permit royalty-free redistribution of the Program by all those
+who receive copies directly or indirectly through you, then the only way
+you could satisfy both it and this License would be to refrain entirely
+from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is implemented
+by public license practices. Many people have made generous
+contributions to the wide range of software distributed through that
+system in reliance on consistent application of that system; it is up to
+the author/donor to decide if he or she is willing to distribute
+software through any other system and a licensee cannot impose that
+choice.
+
+This section is intended to make thoroughly clear what is believed to be
+a consequence of the rest of this License.
+
+@item
+If the distribution and/or use of the Program is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Program under this License may add an
+explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+@item
+The Free Software Foundation may publish revised and/or new versions of
+the General Public License from time to time. Such new versions will be
+similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and ``any
+later version'', you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Program does not specify a version
+number of this License, you may choose any version ever published by the
+Free Software Foundation.
+
+@item
+If you wish to incorporate parts of the Program into other free programs
+whose distribution conditions are different, write to the author to ask
+for permission. For software which is copyrighted by the Free Software
+Foundation, write to the Free Software Foundation; we sometimes make
+exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+@iftex
+@heading NO WARRANTY
+@end iftex
+@ifinfo
+@center NO WARRANTY
+@end ifinfo
+
+@item
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW@. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE@.
+THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+YOU@. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+@item
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
+OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+@end enumerate
+
+@iftex
+@heading END OF TERMS AND CONDITIONS
+@end iftex
+@ifinfo
+@center END OF TERMS AND CONDITIONS
+@end ifinfo
+
+
+@page
+@unnumberedsec How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+``copyright'' line and a pointer to where the full notice is found.
+
+@smallexample
+@var{one line to give the program's name and an idea of what it does.}
+Copyright (C) 19@var{yy} @var{name of author}
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE@. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111, USA.
+@end smallexample
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+@smallexample
+Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
+Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type
+`show w'. This is free software, and you are welcome to redistribute it
+under certain conditions; type `show c' for details.
+@end smallexample
+
+The hypothetical commands @samp{show w} and @samp{show c} should show
+the appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than @samp{show w} and
+@samp{show c}; they could even be mouse-clicks or menu items---whatever
+suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a ``copyright disclaimer'' for the program, if
+necessary. Here is a sample; alter the names:
+
+@smallexample
+@group
+Yoyodyne, Inc., hereby disclaims all copyright
+interest in the program `Gnomovision'
+(which makes passes at compilers) written
+by James Hacker.
+
+@var{signature of Ty Coon}, 1 April 1989
+Ty Coon, President of Vice
+@end group
+@end smallexample
+
+This General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications
+with the library. If this is what you want to do, use the GNU Library
+General Public License instead of this License.
+
+
+
+@node Introduction, Invoking groff, Copying, Top
+@chapter Introduction
+@cindex introduction
+
+GNU @code{troff} (or @code{groff}) is a system for typesetting
+documents. @code{troff} is very flexible and has been in existence (and
+use) for about 3@w{ }decades. It is quite widespread and firmly
+entrenched in the @sc{Unix} community.
+
+
+
+@menu
+* What Is groff?::
+* History::
+* groff Capabilities::
+* Macro Packages::
+* Preprocessors::
+* Postprocessors::
+* Credits::
+@end menu
+
+@node What Is groff?, History, Introduction, Introduction
+@section What Is @code{groff}?
+@cindex what is @code{groff}?
+@cindex @code{groff} -- what is it?
+
+
+@code{groff} is of an older generation of document preparation systems,
+which operate more like compilers than the more recent interactive
+WYSIWYG @footnote{What You See Is What You Get} systems. @code{groff}
+and its contemporary counterpart, @TeX{}, both work using a @dfn{batch}
+paradigm: The input (or @dfn{source}) files are normal text files with
+embedded formatting commands. These files can then be processed by
+@code{groff} to produce a typeset document on a variety of devices.
+
+Likewise, @code{groff} should not be confused with a @dfn{word
+processor}, since that term connotes an integrated system which includes
+an editor and a text formatter. Also, many word processors follow the
+WYSIWYG paradigm which was discussed earlier.
+
+Although WYSIWYG systems may be easier to use, they have a number of
+disadvantages compared to @code{troff}:
+
+@itemize @bullet{}
+@item
+They must be used on a bitmapped display to do any operations on your
+document.
+@item
+Most of the WYSIWYG systems are either non-free or are not very
+portable.
+@item
+@code{troff} is firmly entrenched in all @sc{Unix} systems.
+@item
+It is difficult to have a wide range of capabilities available within
+the confines of a GUI/window system.
+@item
+It is more difficult to make global changes to a document.
+@end itemize
+
+@quotation
+``GUIs normally make it simple to accomplish simple actions and
+impossible to accomplish complex actions.'' --Doug Gwyn (22/Jun/91 in
+@code{comp.unix.wizards})
+@end quotation
+
+
+
+@node History, groff Capabilities, What Is groff?, Introduction
+@section History
+@cindex history
+
+@code{troff} can trace its origins back to a formatting program called
+@code{runoff} which ran on MIT's CTSS system. This name came from the
+common phrase of the time ``I'll run off a document.''
+
+The first version of @sc{Unix} was developed on a PDP-7 which was
+sitting around Bell Labs. In 1971 the developers wanted to get a PDP-11
+for further work on the operating system. In order to justify the cost
+for this system, they proposed that they would implement a document
+formatting system for the AT&T patents division. This first formatting
+program was a reimplementation of @code{runoff}. In accordance with
+@sc{Unix}'s penchant for abreviations, it was named @code{roff} (an
+abreviation of @code{runoff}).
+
+When they needed a more flexible language, a new version of @code{roff}
+called @code{nroff} (Newer @code{roff}) was written. It had a much more
+complicated syntax, but provided the basis for all future versions.
+When they got a Graphic Systems CAT Phototypesetter, J.@w{ }F.@w{
+}Ossanna wrote a version of @code{nroff} which would drive it. It was
+dubbed @code{troff} for typesetter @code{roff}, although many people
+have speculated that it actually means Times @code{roff} because of
+@code{troff}'s use of the Times font family by default. As such, the
+name @code{troff} is pronounced t-roff rather than trough.
+
+With @code{troff} came @code{nroff} (they were actually the same program
+except for some @samp{#ifdefs}), which was for producing output for line
+printers and ascii terminals. It understood everything @code{troff}
+did, and ignored the commands which were not aplicable (i.e.@: font
+changes).
+
+Since there are several things which cannot be done easily in
+@code{troff}, work on several preprocessors began. These programs would
+transform certain parts of a document into @code{troff}, which made a
+very natural use of pipes in @sc{Unix}.
+
+The @code{eqn} preprocessor allowed mathematical formul@ae{} to be
+specified in a much simpler and more intuitive manner. @code{tbl} is a
+preprocessor for formatting tables. The @code{refer} preprocessor (and
+the similar program, @code{bib}) processes citations in a document
+according to a bibliographic database.
+
+Unfortunately, Ossanna's @code{troff} was written in PDP-11 assembly
+language and produced output specifically for the CAT phototypesetter.
+He rewrote it in C, although it was now 7000@w{ }lines of uncommented
+code and still dependent on the CAT. As the CAT became less common, and
+was no longer supported by the manufacturer, the need to make it support
+other devices became a priority. However, before this could be done, he
+was killed in an auto accident.
+
+@pindex ditroff
+So, Brian Kernighan took on the task of rewriting @code{troff}. The
+newly rewritten version produced a device independent code which was
+very easy for postprocessors to read and translate to the appropriate
+printer codes. Also, this new version of @code{troff} (called
+@code{ditroff}) had several extentions, which included drawing
+functions.
+
+Due to the additional abilities of the new version of @code{troff},
+several new preprocessors appeared. The @code{pic} preprocessor
+provides a wide range of drawing functions. Likewise the @code{ideal}
+preprocessor did the same, although via a much different paradigm. The
+@code{grap} preprocessor took specifications for graphs, but, unlike
+other preprocessors, produced @code{pic} code.
+
+James Clark began work on a GNU implementation of @code{ditroff} in
+early@w{ }1989. The first version, @code{groff}@w{ }0.3.1, was released
+June@w{ }1990. @code{groff} included
+
+@itemize @bullet{}
+@item
+A replacement for @code{ditroff} with many extentions.
+@item
+The @code{soelim}, @code{pic}, @code{tbl}, and @code{eqn} preprocessors.
+@item
+Postprocessors for ascii devices, PostScript, @TeX{} DVI, and X@w{
+}windows. GNU @code{troff} also eliminated the need for a separate
+@code{nroff} program with a postprocessor which would produce ascii
+output.
+@item
+A version of the @code{-me} macros and an implementation of the
+@code{-man} macros.
+@end itemize
+
+Also, a front-end was included which could construct the, sometimes
+painfully long, pipelines required for all the post- and preprocessors.
+
+Development of GNU @code{troff} progressed rapidly, and saw the
+additions of a replacement for @code{refer}, an implementation of the
+@code{-ms} and @code{-mm} macros, and a program to deduce how to format
+a document (@code{grog}).
+
+It was declared a stable (i.e.@: non beta) package with the release of
+version@w{ }1.04 around November@w{ }1991.
+
+
+
+@node groff Capabilities, Macro Packages, History, Introduction
+@section @code{groff} Capabilities
+@cindex @code{groff} capabilities
+@cindex capabilities of @code{groff}
+
+So what exactly is @code{groff} capable of doing? @code{groff} provides
+a wide range of low-level text formatting operations. Using these, you
+can perform a wide range of formatting tasks, such as footnotes, table
+of contents, multiple columns, etc.
+
+@itemize @bullet{}
+@item
+Text filling, adjusting, and centering
+@item
+Hyphenation
+@item
+Page control
+@item
+Font and character size control
+@item
+Vertical spacing (i.e.@: double spacing)
+@item
+Line length and indenting
+@item
+Macros, strings, diversions, and traps
+@item
+Number registers
+@item
+Tabs, leaders, and fields
+@item
+Input and output conventions and character translation
+@item
+Overstrike, bracket, line drawing, and zero-width functions
+@item
+Local horizontal and vertical motions and the width function
+@item
+Three-part titles
+@item
+Output line numbering
+@item
+Conditional acceptance of input
+@item
+Environment switching
+@item
+Insertions from the standard input
+@item
+Input/output file switching
+@item
+Output and error messages
+@end itemize
+
+
+@node Macro Packages, Preprocessors, groff Capabilities, Introduction
+@section Macro Packages
+@cindex macro packages
+
+Since @code{groff} provides such low level facilities, it can be quite
+difficult to use by itself. However, @code{groff} provides a
+@dfn{macro} facility which allows you to specify how certain routine
+operations (e.g.@w{ }starting paragraphs, printing headers and footers,
+etc.)@: should be done. These macros can be collected together into a
+@dfn{macro package}. There are a number of macro packages available;
+the most common (and the ones described in this manual) are @code{-man},
+@code{-me}, @code{-ms}, and @code{-mm}.
+
+
+@node Preprocessors, Postprocessors, Macro Packages, Introduction
+@section Preprocessors
+@cindex preprocessors
+
+Although @code{groff} provides most functions needed to format a
+document, some operations would be unwieldy (i.e.@: drawing pictures).
+Therefore, programs called preprocessors were written which understand
+their own language and produce the necessary groff operations. These
+preprocessors are able to differentiate their own input from the rest of
+the document via markers.
+
+To use a preprocessor, @sc{Unix} pipes are used to feed the output from
+the preprocessor into @code{groff}. Any number of preprocessors may be
+used on a given document; in this case, the preprocessors are linked
+together into one pipeline. However, in @code{groff}, the user does not
+need to construct the pipe, but only tell @code{groff} what
+preprocessors to use.
+
+@code{groff} currently has preprocessors for producing tables
+(@code{tbl}), typesetting equations (@code{eqn}), drawing pictures
+(@code{pic}), and for processing bibliographies (@code{refer}). An
+associated program which is useful when dealing with preprocessors is
+@code{soelim}.
+
+There are other preprocessors in existence, but there are,
+unfortunately, no free implementations available. They are for drawing
+pictures (@code{ideal} and @code{gremlin}), for drawing graphs
+(@code{grap}), and chemical structures (@code{chem}).
+
+
+@node Postprocessors, Credits, Preprocessors, Introduction
+@section Postprocessors
+@cindex postprocessors
+
+@code{groff} actually produces device independent code which may be fed
+into a postprocessor which will produce output for a particular device.
+Currently, @code{groff} has postprocessors for PostScript, ascii
+terminals, X@w{ }windows (for previewing), @TeX{} DVI format, and HTML.
+
+
+@node Credits, , Postprocessors, Introduction
+@section Credits
+@cindex credits
+
+
+Large portions of this manual were taken from existing documents, most
+notably, the manual pages for the @code{groff} package by James Clark,
+and Eric Allman's papers on the @code{-me} macro package.
+
+
+
+@node Invoking groff, Tutorial for Macro Users, Introduction, Top
+@chapter Invoking @code{groff}
+@cindex invoking @code{groff}
+@cindex @code{groff} invocation
+
+
+@pindex groff
+@pindex gtroff
+This section focuses on how to invoke the @code{groff} front end. This
+front end takes care of the details of constructing the pipeline among
+the preprocessors, @code{gtroff} and the postprocessor.
+
+It has become a tradition that GNU programs get the prefix @dfn{g} to
+distinguish it from its original counterparts provided by the host
+(@pxref{Environment}, for more details). Thus, for example, @code{geqn}
+is GNU @code{eqn}. On operating systems like Linux or the Hurd, which
+don't contain proprietary software, this prefix is omitted since GNU
+@code{troff} is the only used incarnation of @code{troff}. Exception:
+@code{groff} is never replaced by `roff'.
+
+
+@menu
+* Options::
+* Environment::
+* Invocation Examples::
+@end menu
+
+@node Options, Environment, Invoking groff, Invoking groff
+@section Options
+@cindex options
+
+
+@pindex groff
+@pindex gtroff
+@pindex gpic
+@pindex geqn
+@pindex gtbl
+@pindex grefer
+@pindex gsoelim
+@code{groff} is a front-end to the groff document formatting system.
+Normally it runs the @code{gtroff} program and a postprocessor
+appropriate for the selected device. The default device is @samp{ps}.
+It can optionally preprocess with any of @code{gpic}, @code{geqn},
+@code{gtbl}, @code{grefer}, or @code{gsoelim}.
+
+This section only documents options to the @code{groff} front end. Many
+of the arguments to @code{groff} are passed on to @code{gtroff},
+therefore those are also included. Arguments to pre- or postprocessors
+can be found in @ref{Invoking gpic}, @ref{Invoking geqn}, @ref{Invoking
+gtbl}, @ref{Invoking grefer}, @ref{Invoking gsoelim}, @ref{Invoking
+grotty}, @ref{Invoking grops}, @ref{Invoking grohtml}, @ref{Invoking
+grodvi}, and @ref{Invoking gxditview}
+
+The command line format for @code{groff} is:
+
+@example
+groff [ -abehilpstvzCENRSVXZ ] [ -F@var{dir} ] [ -m@var{name} ]
+ [ -T@var{def} ] [ -f@var{fam} ] [ -w@var{name} ] [ -W@var{name} ]
+ [ -M@var{dir} ] [ -d@var{cs} ] [ -r@var{cn} ] [ -n@var{num} ]
+ [ -o@var{list} ] [ -P@var{arg} ] [ -L@var{arg} ]
+ [ @var{files}@dots{} ]
+@end example
+
+The command line format for @code{gtroff} is as follows. As you can
+see, many of the options to @code{groff} are actually passed on to
+@code{gtroff}.
+
+@example
+gtroff [ -abivzCER ] [ -w@var{name} ] [ -W@var{name} ] [ -d@var{cs} ]
+ [ -f@var{fam} ] [ -m@var{name} ] [ -n@var{num} ]
+ [ -o@var{list} ] [ -r@var{cn} ] [ -T@var{name} ]
+ [ -F@var{dir} ] [ -M@var{dir} ] [ @var{files}@dots{} ]
+@end example
+
+Options without an argument can be grouped behind a single @samp{-}. A
+filename of @samp{-} denotes the standard input.
+
+@pindex grog
+The @code{grog} command can be used to guess the correct @code{groff}
+command to use to format a file.
+
+@table @samp
+@item -h
+Print a help message.
+@item -e
+Preprocess with @code{geqn}.
+@item -t
+Preprocess with @code{gtbl}.
+@item -p
+Preprocess with @code{gpic}.
+@item -s
+Preprocess with @code{gsoelim}.
+@item -R
+Preprocess with @code{grefer}. No mechanism is provided for passing
+arguments to @code{grefer} because most @code{grefer} options have
+equivalent commands which can be included in the file. @xref{grefer},
+for more details.
+
+@pindex troffrc
+Note that @code{gtroff} also accepts a @samp{-R} option, which is not
+accessible via @code{groff}. This option prevents the loading of the
+@file{troffrc} file.
+@item -v
+Make programs run by @code{groff} print out their version number.
+@item -V
+Print the pipeline on stdout instead of executing it.
+@item -z
+Suppress output from @code{gtroff}. Only error messages will be printed.
+@item -Z
+Do not postprocess the output of @code{gtroff}. Normally @code{groff}
+will automatically run the appropriate postprocessor.
+@item -P@var{arg}
+Pass @var{arg} to the postprocessor. Each argument should be passed
+with a separate @samp{-P} option. Note that groff does not prepend
+@samp{-} to @var{arg} before passing it to the postprocessor.
+@item -l
+Send the output to a printer. The command used for this is specified by
+the print command in the device description file.
+@item -L@var{arg}
+Pass @var{arg} to the spooler. Each argument should be passed with a
+separate @samp{-L} option. Note that @code{groff} does not prepend a
+@samp{-} to @var{arg} before passing it to the postprocessor.
+@item -T@var{dev}
+Prepare output for device @var{dev}. The default device is @samp{ps}.
+The following are the output devices currently available:
+@table @samp
+@item ps
+For PostScript printers and previewers.
+@item dvi
+For TeX dvi format.
+@item X75
+For a 75 dpi X11 previewer.
+@item X100
+For a 100dpi X11 previewer.
+@item ascii
+For typewriter-like devices.
+@item latin1
+For typewriter-like devices using the ISO Latin-1 character set.
+@item lj4
+For an HP LaserJet4-compatible (or other PCL5-compatible) printer.
+@item html
+To produce HTML output.
+@end table
+
+The postprocessor to be used for a device is specified by the
+@code{postpro} command in the device description file. (@xref{Font
+Files}, for more info.) This can be overridden with the @samp{-X}
+option.
+@item -X
+Preview with @code{gxditview} instead of using the usual postprocessor.
+This is unlikely to produce good results except with @samp{-Tps}.
+@item -N
+Don't allow newlines with @code{eqn} delimiters. This is the same as
+the @samp{-N} option in @code{geqn}.
+@item -S
+Safer mode. Pass the @samp{-S} option to @code{gpic} and use the
+@samp{-msafer} macros with @code{gtroff}.
+@item -a
+Generate an ASCII approximation of the typeset output.
+@item -b
+Print a backtrace with each warning or error message. This backtrace
+should help track down the cause of the error. The line numbers given
+in the backtrace may not always be correct: @code{troff}'s idea of line
+numbers gets confused by @code{as} or @code{am} requests.
+@item -i
+Read the standard input after all the named input files have been
+processed.
+@item -w@var{name}
+Enable warning @var{name}. Available warnings are described in
+@ref{Debugging}. Multiple @samp{-w} options are allowed.
+@item -W@var{name}
+Inhibit warning @var{name}. Multiple @samp{-W} options are allowed.
+@item -E
+Inhibit all error messages.
+@item -C
+Enable compatibility mode.
+@item -d@var{cs}
+@itemx -d@var{name}=s
+Define @var{c} or @var{name} to be a string @var{s}; @var{c} must be a
+one-letter @var{name}.
+@item -f@var{fam}
+Use @var{fam} as the default font family.
+@item -m@var{name}
+Read in the file @file{tmac.@var{name}}. Normally this will be searched
+for in @code{groff}'s lib directory.
+@item -n@var{num}
+Number the first page @var{num}.
+@item -o@var{list}
+Output only pages in @var{list}, which is a comma-separated list of page
+ranges; @var{n} means print page @var{n}, @samp{@var{m}-@var{n}} means
+print every page between @var{m} and @var{n}, @samp{-@var{n}} means
+print every page up to @var{n}, @samp{@var{n}-} means print every page
+from @var{n}. @code{troff} will exit after printing the last page in
+the list.
+@item -r@var{cn}
+@itemx -r@var{name}=@var{n}
+Set number register @var{c} or @var{name} to @var{n}; @var{c} must be a
+one-letter @var{name}; @var{n} can be any troff numeric expression.
+@item -F@var{dir}
+Search @var{dir} for subdirectories dev@var{name} (@var{name} is the
+name of the device) for the @file{DESC} file and font files before the
+normal directory.
+@item -M@var{dir}
+Search directory @var{dir} for macro files before the normal directory.
+@end table
+
+
+
+@node Environment, Invocation Examples, Options, Invoking groff
+@section Environment
+@cindex environment
+
+
+There are also several environment variables which can modify groff's
+behavior.
+
+@table @code
+@item GROFF_COMMAND_PREFIX
+If this is set to @var{X}, then @code{groff} will run
+@var{X}@code{troff} instead of @code{gtroff}. This also applies to
+@code{tbl}, @code{pic}, @code{eqn}, @code{refer}, and @code{soelim}. It
+does not apply to @code{grops}, @code{grodvi}, @code{grotty},
+@code{grohtml}, @code{grolj4}, and @code{gxditview}.
+@item GROFF_TMAC_PATH
+A colon separated list of directories in which to search for macro
+files.
+@item GROFF_TYPESETTER
+Default device.
+@item GROFF_FONT_PATH
+A colon separated list of directories in which to search for the
+@code{dev}@var{name} directory.
+@item PATH
+The search path for commands executed by groff.
+@item GROFF_TMPDIR
+The directory in which temporary files will be created. If this is not
+set and @code{TMPDIR} is set, temporary files will be created in that
+directory. Otherwise temporary files will be created in @code{/tmp}.
+The @code{grops} and @code{grefer} commands can create temporary files.
+@end table
+
+
+@node Invocation Examples, , Environment, Invoking groff
+@section Invocation Examples
+@cindex invocation examples
+@cindex examples of invocation
+
+
+This section will list several common uses of @code{groff} and the
+command line which will accomplish it.
+
+@example
+groff file
+groff -X -me file
+groff -mm -rD1 -z file
+groff -tps -me file | lpr -Plw2
+... any more?? ...
+@end example
+
+@subsection @code{grog}
+
+@code{grog} reads files and guesses which of the @code{groff}
+preprocessors and/or macro packages are are required for formatting
+them, and prints the @code{groff} command including those options on the
+standard output. The options generated are one of @samp{-e},
+@samp{-man}, @samp{-me}, @samp{-mm}, @samp{-ms}, @samp{-p}, @samp{-s},
+and @samp{-t}.
+
+A filename of @samp{-} is taken to refer to the standard input. If no
+files are specified the standard input will be read. Any specified
+options will be included in the printed command. No space is allowed
+between options and their arguments. For example,
+
+@example
+grog -Tdvi paper.ms
+@end example
+
+will guess the approriate command to print @file{paper.ms} and then run
+it after adding the @samp{-Tdvi} option.
+
+
+@node Tutorial for Macro Users, -man, Invoking groff, Top
+@chapter Tutorial for Macro Users
+@cindex tutorial for macro users
+@cindex macro tutorial for users
+@cindex user's tutorial for macros
+@cindex user's macro tutorial
+
+Most users tend to use a macro package to format their papers. This
+means that the whole breadth of @code{groff} is not neccessary for most
+people. This chapter covers the material needed to efficiently use a
+macro package.
+
+
+@menu
+* Basics::
+* Common Features::
+@end menu
+
+@node Basics, Common Features, Tutorial for Macro Users, Tutorial for Macro Users
+@section Basics
+@cindex basics
+
+
+This section covers some of the basic concepts you will need to
+understand to use a macro package.@footnote{This section is derived from
+@cite{Writing Papers with nroff using -me} by Eric P.@w{ }Allman}
+References are made throughout to more detailed information, if desired.
+
+@code{groff} reads an input file prepared by the user and outputs a
+formatted paper suitable for publication or framing. The input consists
+of text, or words to be printed, and embedded commands (@dfn{requests}
+and @dfn{escapes}), which tell @code{groff} how to format the printed
+copy. For more detail on this @pxref{Embedded Commands}.
+
+The word @dfn{argument} is used in this manual to mean a word or number
+which appears on the same line as a request which modifies the meaning
+of that request. For example, the request
+
+@example
+.sp
+@end example
+
+@noindent
+spaces one line, but
+
+@example
+.sp 4
+@end example
+
+@noindent
+spaces four lines. The number@w{ }4 is an argument to the @code{sp}
+request which says to space four lines instead of one. Arguments are
+separated from the request and from each other by spaces. More details
+on this can be found in @ref{Request Arguments}.
+
+The primary function of @code{groff} is to collect words from input
+lines, fill output lines with those words, justify the right hand margin
+by inserting extra spaces in the line, and output the result. For
+example, the input:
+
+@example
+Now is the time
+for all good men
+to come to the aid
+of their party.
+Four score and seven
+years ago,...
+@end example
+
+@noindent
+will be read, packed onto output lines, and justified to produce:
+
+@quotation
+Now is the time for all good men to come to the aid of their party.
+Four score and seven years ago,...
+@end quotation
+
+@cindex break
+@cindex line break
+Sometimes you may want to start a new output line even though the line
+you are on is not yet full; for example, at the end of a paragraph. To
+do this you can cause a @dfn{break}, which starts a new output line.
+Some requests cause a break automatically, as do blank input lines and
+input lines beginning with a space.
+
+Not all input lines are text to be formatted. Some of the input lines
+are requests which describe how to format the text. Requests always
+have a period or an apostrophe (@samp{'}) as the first character of the
+input line.
+
+The text formatter also does more complex things, such as automatically
+numbering pages, skipping over page boundaries putting footnotes in the
+correct place, and so forth.
+
+Here a few hints for preparing text for input to @code{groff}. First,
+keep the input lines short. Short input lines are easier to edit, and
+@code{groff} will pack words onto longer lines for you anyhow. In
+keeping with this, it is helpful to begin a new line after every period,
+comma, or phrase, since common corrections are to add or delete
+sentences or phrases. Secondly, do not hyphenate words at the end of
+lines -- @code{groff} is smart enough to hyphenate words for you as
+needed, but is not smart enough to take hyphens out and join a word back
+together. Also, words such as ``mother-in-law'' should not be broken
+over a line, since then you will get a space where not wanted, such as
+``mother- in-law''.
+
+@findex ls
+@cindex double spacing
+@cindex spacing
+Groff will double space output text automatically if you use the request
+@samp{.ls 2}. You can revert to single spaced mode by typing @samp{.ls
+1}.
+
+A number of requests allow you to change the way the printed copy looks,
+sometimes called the @dfn{layout} of the output page. Most of these
+requests adjust the placing of @dfn{white space} (blank lines or
+spaces).
+
+@findex bp
+@cindex new page
+The @samp{.bp} request starts a new page.
+
+@findex sp
+@cindex blank lines
+@cindex empty lines
+The request @samp{.sp @var{N}} leaves @var{N} lines of blank space.
+@var{N} can be omitted (meaning skip a single line) or can be of the
+form @var{N}i (for @var{N} inches) or @var{N}c (for @var{N}
+centimeters). For example, the input:
+
+@example
+.sp 1.5i
+My thoughts on the subject
+.sp
+@end example
+
+@noindent
+leaves one and a half inches of space, followed by the line ``My
+thoughts on the subject'', followed by a single blank line.
+
+@findex ce
+@cindex centering lines
+Text lines can be centered by using the @samp{.ce} request. The line
+after @samp{.ce} is centered (horizontally) on the page. To center more
+than one line, use @samp{.ce @var{N}} (where @var{N} is the number of
+lines to center), followed by the @var{N} lines. If you want to center
+many lines but don't want to count them, type:
+
+@example
+.ce 1000
+lines to center
+.ce 0
+@end example
+
+@noindent
+The @samp{.ce 0} request tells @code{groff} to center zero more lines,
+in other words, stop centering.
+
+@findex br
+@cindex line break
+@cindex break
+All of these requests cause a break; that is, they always start a new
+line. If you want to start a new line without performing any other
+action, use @samp{.br}.
+
+
+@node Common Features, , Basics, Tutorial for Macro Users
+@section Common Features
+@cindex common features
+@cindex features, common
+
+
+Groff provides very low level operations for formatting a document.
+There are many common routine operations which are done in all documents.
+These common operations are written into @dfn{macros} and collected into a
+@dfn{macro package}.
+
+All macro packages provide certain common capabilities which fall
+into the following categories.
+
+@subsection Paragraphs
+@cindex paragraphs
+
+One of the most common and most used capability is starting a
+paragraph. There are a number of different types of paragraphs,
+any of which can be initiated with macros supplied by the macro
+package. Normally paragraphs start with a blank line and the first
+line indented, like the text in this manual. There are also block
+style paragraphs, which omit the indentation:
+
+@example
+Some men look at constitutions with sanctimonious
+reverence, and deem them like the ark of the covenant, too
+sacred to be touched.
+@end example
+
+And there are also indented paragraphs which begin with a tag or label
+at the margin and the remaining text indented.
+
+@example
+one This is the first paragraph. Notice how the first
+ line of the resulting paragraph lines up with the
+ other lines in the paragraph.
+longlabel
+ This paragraph had a long label. The first
+ character of text on the first line will not line up
+ with the text on second and subsequent lines,
+ although they will line up with each other.
+@end example
+
+A variation of this is a bulleted list....
+
+@subsection Sections and Chapters
+
+Most macro packages supply some form of section headers.
+The simplest kind is simply the heading on a line by itself in bold
+type. Others supply automatically numbered section heading or
+different heading styles at different levels.
+Some, more sophisticated, macro packages supply macros for starting
+chapters and appendicies.
+
+@subsection Headers and Footers
+
+Every macro packages gives you some way to manipulate the headers and
+footers (or @dfn{titles} on each page. Some packages will allow you
+to have different ones on the even and odd pages (for material
+printed in a book form).
+The titles are called three-part titles, that is, there is a
+left-justified part, a centered part, and a right-justified part.
+An automatically generated page number may be put in any of these
+fields with the @samp{%} character.
+
+@subsection Page Layout
+
+Most macro packages let you specify top and bottom margins and other
+details about the appearance of the printed pages.
+
+@subsection Displays
+@cindex displays
+
+Displays are sections of text to be set off from the body
+of the paper. Major quotes, tables, and figures are types of
+displays, as are all the examples used in this document.
+
+@cindex quotes, major
+@cindex major quotes
+Major quotes are quotes which are several lines long,
+and hence are set in from the rest of the text without
+quote marks around them.
+
+@cindex list
+A list is an indented, single spaced, unfilled display. Lists should
+be used when the material to be printed
+should not be filled and justified like normal text, such
+as columns of figures or the examples used in this paper.
+
+@cindex keep
+A keep is a display of lines which are kept on a single page if
+possible. An example of where you would use a
+keep might be a diagram. Keeps differ from lists in that
+lists may be broken over a page boundary whereas keeps will
+not.
+
+@cindex keep, floating
+@cindex floating keep
+Floating keeps move relative to the text. Hence, they
+are good for things which will be referred to by name, such
+as ``See figure 3''. A floating keep will appear at the bottom of the
+current page if it will fit; otherwise, it will
+appear at the top of the next page. Meanwhile, the surrounding text
+will `flow' around the keep, thus leaving now blank areas.
+
+@subsection Footnotes and annotations
+@cindex footnotes
+@cindex annotations
+
+There are a number of requests to save text for later
+printing. Footnotes are printed at the bottom of the current
+page. Delayed text is intended to be a variant form of foot-
+note; the text is printed only when explicitly called for,
+such as at the end of each chapter.
+
+Delayed text is very similar to a footnote except that
+it is printed when called for explicitly. This allows a
+list of references to appear (for example) at the end of
+each chapter, as is the convention in some disciplines.
+
+Most macro packages which supply this functionality also supply a
+means of automatically numbering either type of annotation.
+
+@subsection Table of Contents
+
+Tables of contents are a type of
+delayed text having a tag (usually the page number) attached
+to each entry after a row of dots. The table accumulates
+throughought the paper until printed, usually after the paper has
+ended. Many macro packages will provide the abilitly to have several
+tables of contents (i.e. one standard one, one for tables, &c.)
+
+@subsection Indexes
+
+While some macro packages will use the term @dfn{index}, none
+actually provide that functionality. The facilities they call
+indexes are actually more appropriate for tables of contents.
+
+@subsection Paper formats
+
+Some macro packages provide stock formats for various kinds of
+documents. Many of them provide a common format for the title and
+opening pages of a technical paper. The -mm macros in particular
+provide formats for letters and memorandums.
+
+@subsection Multiple Columns
+
+Some macro packages (except -man) provide the ability to have two or
+more columns on a page.
+
+@subsection Font and Size changes
+
+The builtin font and size functions are not always intuitive, so all
+macro packages provide macros to make these operations simpler.
+
+@subsection Predefined Strings
+
+Most macro packages provide various predefined strings for a variety
+of uses, examples are sub- and super-scripts, printable dates, quotes
+and various special characters.
+
+@subsection Preprocessor Support
+
+All macro packages provide support for the various preprocessors.
+
+@subsection Configuration and Customization
+
+Some macro packages provide means of customizing many of details of
+how the package behaves. This ranges from setting the default type
+size to changing the appearance of section headers.
+
+
+@node -man, -ms, Tutorial for Macro Users, Top
+@chapter -man
+@cindex @code{-man}
+
+
+
+@node -ms, -me, -man, Top
+@chapter -ms
+@cindex @code{-ms}
+
+
+
+@node -me, -mm, -ms, Top
+@chapter -me
+@cindex @code{-me}
+
+
+
+@node -mm, Programming Tutorial, -me, Top
+@chapter -mm
+@cindex @code{-mm}
+
+
+
+@node Programming Tutorial, geqn, -mm, Top
+@chapter Programming Tutorial
+@cindex programming tutorial
+@cindex tutorial for programming
+
+This chapter covers @strong{all} of the facilities of groff.
+If you are intending to use a macro package, you probably do not want
+to read this chapter.
+
+
+@menu
+* Text::
+* Input Conventions::
+* Measurements::
+* Expressions::
+* Identifiers::
+* Embedded Commands::
+* Registers::
+* Manipulating Filling and Adjusting::
+* Manipulating Hyphenation::
+* Manipulating Spacing::
+* Tabs and Fields::
+* Character Translations::
+* Line Layout::
+* Page Layout::
+* Page Control::
+* Fonts::
+* Sizes::
+* Strings::
+* Conditionals and Loops::
+* Writing Macros::
+* Page Motions::
+* Drawing Functions::
+* Traps::
+* Diversions::
+* Environments::
+* I/O::
+* Postprocessor Access::
+* Miscellany::
+* Debugging::
+* Implementation Differences::
+* Summary::
+@end menu
+
+@node Text, Input Conventions, Programming Tutorial, Programming Tutorial
+@section Text
+@cindex text
+
+@code{groff} input files contain text with control commands
+interspersed throughout. But, even without control codes,
+@code{groff} will still do several things with your text:
+filling and adjusting,
+adding additional space after sentences,
+hyphenating
+and
+inserting implicit line breaks.
+
+
+@menu
+* Filling and Adjusting::
+* Hyphenation::
+* Sentences::
+* Tab Stops::
+* Implicit Line Breaks::
+@end menu
+
+@node Filling and Adjusting, Hyphenation, Text, Text
+@subsection Filling and Adjusting
+@cindex filling and adjusting
+@cindex adjusting and filling
+
+
+When troff reads in text it collects words from input and fits as many
+of them together on one output line as it can. This is known as
+@dfn{filling}.
+
+Once troff has a @dfn{filled} line it will try to @dfn{adjust} it.
+which means it will widen the spacing between words until
+the text reaches the right margin (in the default adjustment mode).
+Extra spaces between words are preserved, but
+spaces at the end of lines are ignored.
+Spaces at the front of a line will cause a @dfn{break}
+(breaks will be explained in @ref{Implicit Line Breaks})
+
+@c distribute these through the text
+@xref{Manipulating Filling and Adjusting}
+
+@node Hyphenation, Sentences, Filling and Adjusting, Text
+@subsection Hyphenation
+@cindex hyphenation
+
+
+Since the odds of finding a set of words, for every output line,
+which will fit nicely on a
+line without inserting excessive amounts of space between words
+is not great,
+troff will hyphenate words so that lines can be justified
+without there being too much space between words.
+It uses an internal hyphenation algorithm, to indicate which words can
+be hyphenated and how to do so.
+When a word is hyphenated the first part of the word will be added
+to the current filled line being output (with an attached hyphen),
+and the other portion will be added to the next line to be filled.
+
+@c distribute these through the text
+@xref{Manipulating Hyphenation}
+
+@node Sentences, Tab Stops, Hyphenation, Text
+@subsection Sentences
+@cindex sentences
+
+
+Although it is often debated,
+some typesetting rules say there should be different amounts of space
+after various puctuation marks.
+For example, a period at the end of a sentence
+should have twice as much space following it
+as would a comma or a period as part of an abbreviation.
+
+@cindex sentence spaces
+@cindex spaces between sentences
+Troff does this by flagging certain characters (normally
+@samp{!}, @samp{?} and @samp{.})
+as @dfn{end of sentence} characters.
+When troff encounters one of these characters at the end of a line it
+will append two @dfn{sentence spaces} in the formatted output.
+(thus, one of the conventions mentioned in @ref{Input Conventions}).
+
+@c also describe how characters like ) are treated here -jjc
+@c gotta do some research on this -trent
+
+
+
+@node Tab Stops, Implicit Line Breaks, Sentences, Text
+@subsection Tab Stops
+@cindex tab stops
+@cindex stops, tabulator
+
+
+Groff translates tabs in the input into movements to the next tab
+stop. These tab stops are initially located every half inch across
+the page.
+Using this you can make simple tables. However, this can often be
+deceptive as the appearance (and width) of your text on a terminal and
+the results from groff can vary greatly.
+
+Also, a possible sticking point is that lines beginning with tab
+characters will still be filled, again producing unexpected results.
+For example, the following input
+
+@example
+ 1 2 3
+ 4 5
+@end example
+
+@noindent
+will produce
+
+@example
+ 1 2 3 4 5
+@end example
+
+@c Tab stops are with respect to the input line. -jjc
+@c did that last section address that?? -trent
+
+
+
+@c distribute these through the text
+@xref{Tabs and Fields}
+
+@node Implicit Line Breaks, , Tab Stops, Text
+@subsection Implicit Line Breaks
+@cindex implicit line breaks
+@cindex implicit breaks of lines
+@cindex line, implicit breaks
+@cindex break
+@cindex break, implicit
+@cindex line break
+
+An important concept in troff is the @dfn{break}. When a @dfn{break}
+occurs, troff will output the partially filled line (unadjusted),
+and resume collecting and filling text on the next output line.
+
+@cindex blank line
+@cindex empty line
+@cindex line, blank
+There are several ways to cause a break in troff.
+A blank line will not only cause a break, but it will also cause a
+one line vertical space (effectively a blank line) to be output.
+
+A line which begins with a space will cause a break and the space
+will be output at the beginning of the next line.
+Note that this space isn't adjusted, even in fill mode.
+
+The end of file will also cause a break (otherwise the last line of
+your document may vanish!)
+
+Certain @dfn{requests} also cause breaks, implicitly or explicity.
+This will be discussed later.
+
+@c distribute these through the text
+@xref{Manipulating Filling and Adjusting}
+
+@node Input Conventions, Measurements, Text, Programming Tutorial
+@section Input Conventions
+@cindex input conventions
+@cindex conventions for input
+
+
+Since groff does filling automatically, it is traditional in groff not
+to try and type things in as nicely formatted paragraphs. These are
+some conventions commonly used when typing groff text:
+
+@itemize @bullet{}
+@item
+Break lines after punctuation, particularily at the ends of
+sentences, and in other logical places. Keep separate phrases on
+lines by themselves, as entire phrases are often added or deleted
+when editing.
+@item
+Try to keep lines less than 40-60 characters,
+to allow space for inserting more text.
+@item
+Do not try to do any formatting in a WYSIWYG manner (i.e. don't
+try and use spaces to get proper indentation).
+@end itemize
+
+
+@node Measurements, Expressions, Input Conventions, Programming Tutorial
+@section Measurements
+@cindex measurements
+
+
+@cindex units of measurement
+@cindex basic units
+@cindex machine units
+Troff (like any other programs) requires numeric parameters to
+specify various measurements. Most numeric parameters
+@footnote{those that specify vertical or horizontal motion or a type
+size} may have a measurement unit attached.
+These units are specified as a single
+character which immediately follows the number or expression.
+Each of these units are understood, by troff, to be a multiple of its
+@dfn{basic unit}. So, whenever a different measurement unit is
+specified troff converts this into its basic units.
+This basic unit, represented by a @samp{u} is a
+device dependent measurement which is quite small, ranging from
+1/75th to 1/72000th of an inch.
+
+Some of the measurement units are compleatly independent of any of
+the current settings (e.g. type size) of groff.
+
+@table @samp
+@item i
+@cindex inch
+Inches. An antiquated measurement unit still in use in certain
+backwards countries.
+@item c
+@cindex centimeter
+Centimeters.
+@item p
+@cindex points
+Points. This is a typesetter's measurement used for measure type size.
+It is 72 points to an inch.
+@item P
+@cindex pica
+Pica. Another typesetting measurement. 6 Picas to an inch.
+@item s
+@item z
+@end table
+
+The other measurements understood by troff are dependent on settings
+currently in effect in troff. These are very useful for specifying
+measurements which should look proper with any size of text.
+
+@table @samp
+@item m
+@cindex em
+Ems. This unit is equal to the current font size in points.
+So called because it is @emph{approximately} the width of the letter
+@samp{m} in the current font.
+@item n
+@cindex en
+Ens. This is half of an em.
+@item v
+@cindex vertical space
+@cindex space, vertical
+Vertical space. This is equivalent to the current line spacing.
+@xref{Sizes}, for more information about this.
+@item M
+100ths of an em.
+@end table
+
+@c distribute these through the text
+@xref{Fractional Type Sizes}
+
+@menu
+* Default Units::
+@end menu
+
+@node Default Units, , Measurements, Measurements
+@subsection Default Units
+@cindex default units
+@cindex units, default
+
+
+Many requests take a default unit. While this can be helpful at
+times, it can cause strange errors in some expressions.
+For example, the line length request expects em's.
+Here are several attempts to get 3.5 inches and the results:
+
+@example
+3.5i @result{} 3.5i
+7/2 @result{} 0i
+7/2i @result{} 0i
+7i/2 @result{} .1i
+7i/2u @result{} 3.5i
+@end example
+
+As you can see, the safest way to specify measurements is to always
+attach a scaling indicator.
+
+@node Expressions, Identifiers, Measurements, Programming Tutorial
+@section Expressions
+@cindex expressions
+
+
+Troff has most of operators common to other languages:
+
+@itemize @bullet
+@item
+Arithmetic: +, -, /, *, %
+@item
+Comparison: <, >, >=, <=, =, == (the last two are the same)
+@item
+Logical: &, :
+@item
+Unary operators: -, +, ! (if/while only??)
+@item
+Maximum and minimum: >?, <?
+@item
+Scaling: (@var{c};@var{e})
+Evaluate @var{e} using @var{c} as the default scaling indicator.
+If @var{c} is missing, ignore scaling indicators in the
+evaluation of @var{e}.
+@end itemize
+
+Parenthesis may be used as in any other language.
+However, in groff they are necessary to ensure order of evaluation.
+Groff has no operator precedence,
+expressions are evaluated left to right.
+This means that @samp{3+5*4} is evaluated as if it were parenthesized
+like @samp{(3+5)*4}, not as @samp{3+(5*4)}, like you may expect.
+
+For many requests which cause a motion on the page, the unary
+operators work differently.
+The @samp{+} and @samp{-} operators indicate a motion relative to the
+current position (down or up, respectively). The @samp{|} operator
+indicates an absolute position on the page or input line. (????)
+@code{+} and @code{-} are also treated differently by @code{nr} (?)
+
+Due to the way arguments are parsed, spaces are not allowed in
+expressions, unless the entire expression is surrounded by parenthesis.
+
+@c distribute these through the text
+@xref{Request Arguments}
+@c distribute these through the text
+@xref{Conditionals and Loops}
+
+@node Identifiers, Embedded Commands, Expressions, Programming Tutorial
+@section Identifiers
+@cindex identifiers
+
+Like any other language troff, has rules for properly formed
+identifiers.
+In troff an identifier can be made up of most any printable
+character.
+The only exception is characters which are interpreted by troff
+(backslash, square bracket and ?). So, for example, any of the following
+are valid.
+
+@example
+br
+PP
+(l
+end-list
+@@_
+@end example
+
+You can test whether an identifier is valid in groff with the
+@code{\A} escape. It expands to 1 or 0 according whether its argument
+(given in quotes) is or is not acceptable as the name of a string,
+macro, diversion, number register, environment or font. It will return
+0 if no argument is given. This is useful if you want to lookup user
+input in some sort of associative table.
+
+Identifiers in groff can be any length, but, in some contexts,
+groff needs to told
+where identifiers end and text begins (and in different ways
+depending on their length)
+
+@itemize @bullet{}
+@item
+Single character
+@item
+Two characters
+Must be prefixed with @samp{(} in some situations.
+@item
+Arbitrary length (groff only)
+Must be bracketed with @samp{[}, @samp{]} in some situations.
+Any length identifier can be put in brackets.
+@end itemize
+
+Unlike many other programming languages, undefined identifiers are
+silently ignored or expanded to nothing.
+
+
+@c distribute these through the text
+@xref{Interpolating Registers}
+@c distribute these through the text
+@xref{Strings}
+
+@node Embedded Commands, Registers, Identifiers, Programming Tutorial
+@section Embedded Commands
+@cindex embedded commands
+@cindex commands, embedded
+
+
+With most documents you need more funtionality beyond filling,
+adjusting and implicit line breaking.
+In order to gain further functionality, groff allows commands to be
+embeded into your text, in two ways.
+
+The first is a @dfn{request} which takes up an entire line, and does
+some large scale operation (e.g. break lines, start new pages).
+
+The other is an @dfn{escape} which can be embedded anywhere
+in your text, or even as an argument to a request. (Not always?)
+Escapes generally do more minor operations like sub- and super-
+scripts, print a symbol, &c.
+
+
+
+@menu
+* Requests::
+* Macros::
+* Escapes::
+@end menu
+
+@node Requests, Macros, Embedded Commands, Embedded Commands
+@subsection Requests
+@cindex requests
+
+
+@cindex control character
+@cindex character, control
+A request line begins with a control character,
+which is either a single quote (@samp{'}) or a period (@samp{.}).
+These can be changed @pxref{Character Translations}, for details.
+After this there may be optional tabs or spaces followed by an
+identifier which is the name of the request.
+This may be followed by any number of space separated arguments.
+
+@findex \&
+If you want to begin a line with a control character without it being
+interpreted, precede it with a @code{\&}. This represents a zero
+width space, which means it will not affect you output.
+
+In most cases you will use the period as a control character.
+Several requests will cause a break, using the single quote control
+character will prevent this.
+
+
+@menu
+* Request Arguments::
+@end menu
+
+@node Request Arguments, , Requests, Requests
+@subsubsection Request Arguments
+@cindex request arguments
+@cindex arguments to requests
+
+
+Argument to requests (and macros) are processed much like the shell:
+The line is split into arguments according to spaces.
+An argument which is intended to contain spaces can either be enclosed
+in quotes (single or double), or have the spaces @dfn{escaped} with
+backslashes.
+
+So, for example:
+
+@example
+.uh The Mouse Problem
+.uh "The Mouse Problem"
+.uh The\ Mouse\ Problem
+@end example
+
+The first line is the @code{.uh} macro being called with 3 arguments,
+@samp{The}, @samp{Mouse}, and @samp{Problem}.
+The latter two have the same effect or calling the @code{.uh} macro
+with one argument @samp{The Mouse Problem}.
+
+Note, however, that the @code{.ds} request works differently.
+
+@c distribute these through the text
+@xref{Strings}
+
+@node Macros, Escapes, Requests, Embedded Commands
+@subsection Macros
+@cindex macros
+
+
+Troff has a @dfn{macro} facility for defining a series of lines which
+can be invoked by name.
+They are called in the same manner as requests
+and arguments may be passed in the same manner.
+
+
+@c distribute these through the text
+@xref{Writing Macros}
+@c distribute these through the text
+@xref{Request Arguments}
+
+@node Escapes, , Macros, Embedded Commands
+@subsection Escapes
+@cindex escapes
+
+
+@findex \e
+@findex \\
+Escapes may occur anywhere in the input to groff.
+They begin with a backslash and are followed by a single character
+which indicates the function to be performed.
+If you want to have a backslash appear in your document, you should
+use the escape sequence @code{\e}. Merely escaping the backslash
+with another backslash will work in @emph{some} curcumstances.
+
+Many escapes have no parameters, those that do, do so in one of two
+ways. For escapes which require an identifier there must be a way for
+groff to tell where the identifier ends and the text begins.
+It assumes that the next single character is the identifier, but if
+that character is an open parenthesis, it takes the next two
+characters as the identifier; and if the next character is an open
+bracket, all characters until a close bracket are taken as the
+identifier. Note that in the second case there is no closing
+parenthesis. For example:
+
+@example
+\fB
+\n(XX
+\*[TeX]
+@end example
+
+Other escapes may require several arguments and/or some special
+format. In these cases the @dfn{argument} is enclosed in single
+quotes (not required??) and the enclosing text is decoded according
+to what that escape expects.
+
+@example
+\l'1.5i\(bu'
+@end example
+
+@findex \\
+@findex \e
+@findex \E
+If you want to have a backslash appear in your output, you can use several
+escapes: @code{\\}, @code{\e} or @code{\E}.
+These are very similar, and only differ with respect to being used in
+macros or diversions (@xref{Copy-in Mode}, and @ref{Diversions}, for
+more information)
+
+
+
+@c distribute these through the text
+@xref{Identifiers}
+
+@menu
+* Comments::
+@end menu
+
+@node Comments, , Escapes, Escapes
+@subsubsection Comments
+@cindex comments
+
+
+@findex \"
+Probably one of the most@footnote{Unfortunately, this is a lie. But
+hopefully future troff hackers will believe it :-)}
+common forms of escapes is the comment.
+They begin with the @code{\"} escape and end at the end of the input
+line.
+
+This may sound simple, but it can be tricky to keep the comments from
+interfering with the apperarance of your final outupt.
+
+If the escape is to the right of some text or a request, that portion
+of the line will be ignored, but the space leading up to it will be
+noticed by groff. This only affects the @code{.ds} request (any
+others?).
+
+One possibly irritating idiosyncracy is that you mustn't use tabs to
+line up your comments.
+Tabs are not treated as white space between request and macro
+arguments.
+
+If you have a comment on a line by itself, it will be treated as a
+blank line, because after eliminating the comment, that is all that
+remains. So, it is common to start the line with @code{.\"} which
+will cause the line to be treated as an undefined request.
+
+Another commenting scheme seen sometimes is three consecutive single
+quotes (@code{'''}) at the begining of a line. This works, but groff
+will give a warning about an undefined macro, which is harmless, but
+irritating.
+
+@findex \#
+Now to avoid all this groff has a new comment mechanism using the
+@code{\#} escape. This escape works the same as @code{\"} except
+that the newline is also ignored.
+
+@findex ig
+For large blocks of text, the @code{ig} request may be useful.
+@c distribute these through the text
+@xref{Strings}
+
+@node Registers, Manipulating Filling and Adjusting, Embedded Commands, Programming Tutorial
+@section Registers
+@cindex registers
+
+
+Registers are groff's numeric variables. groff has a number of
+builtin registers, supplying anything from the date to details of
+formatting parameters.
+
+@c distribute these through the text
+@xref{Identifiers}
+
+@menu
+* Setting Registers::
+* Interpolating Registers::
+* Auto-increment::
+* Assigning Formats::
+* Builtin Registers::
+@end menu
+
+@node Setting Registers, Interpolating Registers, Registers, Registers
+@subsection Setting Registers
+@cindex setting registers
+@cindex registers, setting
+
+
+@findex nr
+@findex \R
+Registers are defined/set via the @code{nr}
+request or the @code{\R} escape, for example, the following two lines
+are equivalent:
+
+@example
+.nr a 1
+\R'a 1'
+@end example
+
+@findex rr
+The @code{rr} request will
+remove the register specified by the argument.
+
+@findex rnn
+The @code{rnn} request will rename a number register.
+The format is @samp{.rnn @var{x} @var{y}}, which will
+rename number register @var{x} to @var{y}.
+
+@findex aln
+Aliases can be created for a number register. The format is
+@samp{.aln @var{xx} @var{yy}}, which will create an alias @var{xx} for
+number register object named @var{yy}. The new name and the old name
+will be exactly equivalent. If @var{yy} is undefined, a warning of
+type @samp{reg} will be generated, and the request will be ignored.
+@xref{Debugging}, for information about warnings.
+
+
+@node Interpolating Registers, Auto-increment, Setting Registers, Registers
+@subsection Interpolating Registers
+@cindex interpolating registers
+@cindex registers, interpolating
+
+
+@findex \n
+Numeric registers are @dfn{interpolated} via the @code{\n} escape.
+@c the following is wrong. Should I say any more than the above??
+@c This means that the value of the number register in expanded in-place
+@c on the input line before any other actions, i.e. before requests and
+@c escapes are interpreted.
+
+@example
+.nr as \na+\na
+\n(as
+@end example
+
+
+@node Auto-increment, Assigning Formats, Interpolating Registers, Registers
+@subsection Auto-increment
+@cindex auto-increment
+@cindex increment, automatic
+
+Number registers can also be auto incremented/decremented. You can
+specify the increment/decrement factor with third argument to the
+@code{nr} request. The default value is 0. For example:
+
+@example
+.nr a 0 1
+.nr xx 0 5
+\n+a, \n+a, \n+a, \n+a, \n+a
+.br
+\n+(xx, \n+(xx, \n+(xx, \n+(xx, \n+(xx
+@end example
+
+Produces:
+
+@example
+1, 2, 3, 4, 5
+5, 10, 15, 20, 25
+@end example
+
+If you want to change the increment factor without changing the value
+of a register, the following can be used.
+
+@example
+.nr a \na 10
+@end example
+
+
+@node Assigning Formats, Builtin Registers, Auto-increment, Registers
+@subsection Assigning Formats
+@cindex assigning formats
+@cindex formats, assigning
+
+
+@findex af
+When a register is used in the text of an input file
+(as opposed to part of an expression)
+it is textually replaced (or interpolated) with a representation of
+that number.
+This output format can be changed to a variety of formats
+(numbers, roman numerals, etc)
+This is done using the @code{af} request.
+The first argument to @code{af} is the name of the number register to
+be changed,
+and the second argument is the output format.
+The following output formats are available:
+
+@table @samp
+@item 1
+This is the default format, decimal numbers:
+1, 2, 3, @dots{}
+@item 001
+Decimal numbers with as many leading zeros as specified.
+So, @samp{001} would result in 001, 002, 003, @dots{}
+@item I
+@cindex roman numerals
+@cindex numerals, roman
+Upper-case roman numerals:
+0, I, II, III, IV, @dots{}
+@item i
+Lower-case roman numerals:
+0, i, ii, iii, iv, @dots{}
+@item A
+Upper-case letters:
+A, B, C, @dots{}, Z, AA, AB, @dots{}
+@item a
+Lower-case letters:
+a, b, c, @dots{}, z, aa, ab, @dots{}
+@end table
+
+The following example will produce @samp{10, X, j, 010}.
+
+@example
+.nr a 10
+.af a 1 \" the default format
+\na,
+.af a I
+\na,
+.af a a
+\na,
+.af a 001
+\na
+@end example
+
+@findex \g
+The @code{\g} escape returns the current format of the specified
+register. For example, @samp{\ga} after the following example would
+produce @samp{001}.
+
+
+
+@node Builtin Registers, , Assigning Formats, Registers
+@subsection Builtin Registers
+@cindex builtin registers
+@cindex registers, builtin
+
+
+The following are some builtin registers, which are not listed
+elsewhere in this manual. Any registers which begin with a @samp{.}
+are read-only. A compleat listing of all builtin registers can be
+found in @ref{Register Index}.
+
+@table @code
+@item .H
+@vindex .H
+Horizontal resolution in basic units.
+@item .V
+@vindex .V
+Vertical resolution in basic units.
+@item dw
+@vindex dw
+Day of the week (1-7).
+@item dy
+@vindex dy
+Day of the year (1-31).
+@item mo
+@vindex mo
+Current month (1-12).
+@item yr
+@vindex yr
+Last two digits of the current year (see you in 7 years :-)
+@item .c
+@vindex .c
+@itemx c.
+@vindex c.
+The current @emph{input} line number.
+@item ln
+@vindex ln
+The current @emph{output} line number.
+@item .x
+@vindex .x
+The major version number. For example, if the version number is 1.03
+then @code{.x} will contain 1.
+@item .y
+@vindex .y
+The minor version number. For example, if the version number is 1.03
+then @code{.y} will contain 03.
+@item .g
+@vindex .g
+Always 1.
+Macros should use this to determine whether they are running
+under GNU troff.
+@item .A
+@vindex .A
+If the current output device is ascii, this is set to 1,
+zero otherwise.
+@item .P
+@vindex .P
+This register indicates whether the current page is actualy being
+printed, i.e. if the @samp{-o} option is being used to only print
+selected pages.
+@xref{Options}, for more information.
+@end table
+
+@node Manipulating Filling and Adjusting, Manipulating Hyphenation, Registers, Programming Tutorial
+@section Manipulating Filling and Adjusting
+@cindex manipulating filling and adjusting
+@cindex filling and adjusting, manipulating
+@cindex adjusting and filling, manipulating
+
+
+@findex br
+@cindex break
+@cindex line break
+Several ways of causing @dfn{breaks} were given in
+@ref{Implicit Line Breaks}.
+The @code{br} request will likewise cause a break.
+Several other requests will also cause breaks, implicitly.
+They are
+@code{bp},
+@code{ce},
+@code{fi},
+@code{fl},
+@code{in},
+@code{nf},
+@code{sp} and
+@code{ti}.
+
+@findex nf
+@findex fi
+@vindex .u
+Initially, groff will fill and ajust text to both margins.
+Filling can be disabled via the @code{nf} request
+and re-enabled with the @code{fi} request.
+These implicitly disable and re-enable adjusting.
+Both of these will cause break in text currently being filled.
+The number register @code{.u} is equal to 1 in fill mode and 0 in
+no-fill mode.
+
+@findex ad
+@findex na
+@vindex .j
+Adjusting can be disabled with the @code{ad} request and re-enabled
+with the @code{na} request.
+The @code{ad} request takes a single argument to indicate how to
+adjust text.
+The current adjustment mode is available in the number register
+@code{.j}.
+
+@table @samp
+@item l
+@cindex ragged-right
+Adjust text to the left margin. This produces what is traditionally
+called ragged-right text.
+@item r
+Adjust text to the right margin.
+@item c
+Center filled text.
+@item b
+@itemx n
+Justify to both margins. This is groff's default.
+@end table
+
+With no argument to @code{ad}, troff will adjust lines the same way
+it was the last time it was filling. For example:
+
+@example
+text
+.ad r
+text
+.ad c
+text
+.na
+text
+.ad \" back to centering
+text
+@end example
+
+@findex \p
+The escape @code{\p} will cause a break and cause the remaining text
+to be adjusted.
+
+@findex ss
+The @code{ss} request allows you to change the minimum size of a
+space between filled words.
+This request takes it's units as one twelfth of the
+spacewidth parameter for the current font. Initially both the word
+space size and the sentence space size are 12.
+
+When two arguments are given to the @code{ss} request, the second argument
+gives the sentence space size. If the second argument is not given, the
+sentence space size will be the same as the word space size.
+The sentence space size
+is used in two circumstances: if the end of a sentence occurs at the end
+of a line in fill mode, then both an inter-word space and a sentence
+space will be added; if two spaces follow the end of a sentence in the
+middle of a line, then the second space will be a sentence space. Note
+that the behaviour of @sc{Unix} troff will be exactly that exhibited by GNU
+troff if a second argument is never given to the @code{ss} request. In GNU
+troff, as in @sc{Unix} troff, you should always follow a sentence with either
+a newline or two spaces.
+
+@vindex .ss
+@vindex .sss
+The number registers @code{.ss} and @code{.sss} are
+the values of the parameters set by the first and second
+arguments of the @code{ss} request.
+
+@findex ce
+The @code{ce} request will center text.
+While the @samp{ad c} request will also center text, it has the side
+effect of filling the text. The @code{.ce} request will not fill the
+text it affects.
+This request causes a break.
+
+With no arguments, @code{ce} will fill the next line of text.
+The single argument @code{ce} takes is a number indicating the
+number of lines to be centered. With no argument centering is
+disabled.
+
+A common idiom is to turn on centering for a large number of lines,
+and then turn off centering when you are done with the centered text.
+This is useful for any request which takes a number of lines as an
+argument.
+
+@example
+.ce 1000
+replace this
+with
+something
+more interesting
+@dots{}
+.ce 0
+@end example
+
+@vindex .ce
+The @code{.ce} number register contains the number of lines remaining
+to be centered, as set by the @code{ce} request.
+
+
+@findex rj
+@vindex .rj
+A similar request is @code{rj} request which will justify unfilled
+text to the right margin. Its arguments are identical to the
+@code{ce} request.
+The @code{.rj} number register is
+the number of lines to be right-justified as set by the @code{rj}
+request.
+
+
+
+@node Manipulating Hyphenation, Manipulating Spacing, Manipulating Filling and Adjusting, Programming Tutorial
+@section Manipulating Hyphenation
+@cindex manipulating hyphenation
+@cindex hyphenation, manipulating
+
+
+As discussed in @ref{Hyphenation}, groff will hyphenate words.
+There are a number of ways to modify the how hyphenation is done.
+
+@findex nh
+@findex hy
+@vindex .hy
+This hyphenation can be turned off with the @code{nh} request, and
+turned back on with the @code{hy} request. However, troff's
+hyphenation facilities are far more flexible than this. The @code{hy}
+request can be used to tell troff to restrict hypenation to certain
+cases. The request takes a single numeric argument.
+The current hyphenation restrictions can be found in the number
+register @code{.hy}
+
+@table @samp
+@item 1
+The default argument, which
+indicates to hyphenate without restrictions.
+@item 2
+Do not hyphenate the last word on a page or column.
+@item 4
+Do not hyphenate the last two characters of a word.
+@item 8
+Do not hyphenate the first two characters of a word.
+@end table
+
+@findex hlm
+@vindex .hlc
+@vindex .hlm
+The @code{hlm} request will
+set the maximum number of consecutive hyphenated lines to the value
+given as the first argument.
+If this number is
+negative, there is no maximum. The default value is -1.
+This value is
+associated with the current environment. Only lines output from an
+environment count towards the maximum associated with that environment.
+Hyphens resulting from @code{\%} are counted; explicit hyphens are not.
+The current setting of this is available in the @code{.hlm} request.
+Also the number of immediately preceding consecutive hyphenated lines
+are available in the number register @code{.hlc}.
+
+@findex hw
+The @code{hw} request allows you to specify how a specific word is
+to be hyphenated. It takes only one argument which is the word with
+hyphens at the hyphenation points. For example:
+@samp{.hw in-sa-lub-rious}.
+@c In old versions of troff there was a
+@c limited amount of space to store such information, fortunately,
+@c with groff, this is no longer a restriction.
+
+@findex \%
+@cindex hyphenation character
+@cindex character, hyphenation
+You can also tell troff how to hyphenate words on the fly with the
+use of the @code{\%} escape, also known as the @dfn{hyphenation
+character}. Preceding a word with this character will prevent it
+from being hyphenated, putting it in a word will indicate to troff
+that the word may be hyphenated at that point. Note that this
+mechanism will only affect one word, if you want to change the
+hyphenation of a word for the entire document, use the @code{hw}
+request.
+
+@findex hc
+The @code{hc} request allows you to change the hyphenation character.
+The character specified as an argument will then work the same as the
+@code{\%} escape, and, thus, no longer appear in the output. Without
+an argument it will return the hyphenation character to @code{\%}.
+
+@findex hpf
+To further customize hyphenation the @code{hpf} request will read in
+a file of hyphenation patterns.
+This file will be searched for in the
+same way that @file{tmac.@var{name}} is searched for when the
+@samp{-m@var{name}} option is specified.
+
+It should have the same format as the argument to the
+\patterns primitive in @TeX{}; the letters appearing in this file are
+interpreted as hyphenation codes.
+A @samp{%} character in the patterns file
+introduces a comment that continues to the end of the line.
+
+@findex hla
+@findex hpf
+@pindex troffrc
+The set of
+hyphenation patterns is associated with the current language set by the
+@code{hla} request. The @code{hpf} request is usually invoked by the
+@file{troffrc} file.
+
+@findex hcode
+@code{.hcode @var{c1 code1 c2 code2...}}
+Set the hyphenation code of character @var{c1} to code1 and that of
+@var{c2} to @var{code2}.
+A hyphenation code must be a single input character (not a
+special character) other than a digit or a space. Initially each
+lower-case letter has a hyphenation code, which is itself, and each
+upper-case letter has a hyphenation code which is the lower case
+version of itself.
+
+@findex hym
+@vindex .hym
+The @code{hym} request will set the hyphenation margin to the value
+given as the first argument: when the current adjustment mode is not
+@samp{b}, the line will not be hyphenated if the line is no more than
+that amount short.
+The default hyphenation margin is 0. The default scaling
+indicator for this request is m. The hyphenation margin is associated
+with the current environment. The current hyphenation margin is
+available in the @code{.hym} register.
+
+@findex hys
+@vindex .hys
+The @code{hys} request set the hyphenation space to the value given as
+the first argument: when the current adjustment mode is b, don't
+hyphenate the line if the line can be justified by adding no more than
+that amount of extra space to each word space. The default
+hyphenation space is 0. The default scaling indicator for this
+request is m. The hyphenation space is associated with the current
+environment. The current hyphenation space is available in the
+@code{.hys} register.
+
+@findex shc
+The @code{shc} request will set the soft hyphen character to the
+argument given as an argument. If the argument is omitted, the soft
+hyphen character will be set to the default @code{\(hy}. The soft
+hyphen character is the character which will be inserted when a word
+is hyphenated at a line break. If the soft hyphen character does not
+exist in the font of the character immediately preceding a potential
+break point, then the line will not be broken at that point. Neither
+definitions (specified with the @code{char} request) nor translations
+(specified with the @code{tr} request) are considered when finding the soft
+hyphen character.
+
+@findex hla
+@vindex .hla
+@pindex troffrc
+The @code{hla} request will set the current hyphenation language to
+that given by the first argument. Hyphenation exceptions specified
+with the @code{hw} request and hyphenation patterns specified with the
+@code{hpf} request are both associated with the current hyphenation
+language. The @code{hla} request is usually invoked by the
+@file{troffrc} file. The current hyphenation language is available
+in the number register @code{.hla}.
+
+
+
+@node Manipulating Spacing, Tabs and Fields, Manipulating Hyphenation, Programming Tutorial
+@section Manipulating Spacing
+@cindex manipulating spacing
+@cindex spacing, manipulating
+
+
+@findex sp
+The @code{sp} request will cause troff to space downwards the
+distance specified as the first argument. With no argument it will
+advance 1 line.
+A negative argument will cause troff to move up the page the
+specified distance.
+If the argument is preceded by a @samp{|} troff will move that
+distance from the top of the page.
+
+@findex ls
+@vindex .L
+Often you may want your output to be double or triple spaced.
+The @code{ls} request will cause troff to output @var{n}-1 blank
+lines after each line of text, where @var{n} is the argument given to
+the @code{ls} request. With no argument troff will go back to single
+spacing. The number register @code{.L} contains the current line
+spacing setting.
+
+@findex \x
+@vindex .a
+Sometimes, extra vertical spacing is only needed occasionaly,
+i.e. to allow space for a tall construct (like an equation).
+The @code{\x} escape will do this.
+The escape is given a numerical argument (like @samp{\x'3p'}).
+If this number is positive extra vertical space will be inserted
+below the current line. A negative number will add space above.
+If this escape is used multiple times on the same line, the maximum
+values are used.
+The @code{.a} number register contains the most recent
+extra vertical @strong{emph} line space.
+
+@example
+... example of inline equation ...
+@end example
+
+@findex ns
+@findex rs
+@cindex no-space mode
+@cindex mode, no-space
+Spacing (via either @code{sp} or via blank lines) can be disabled
+with the @code{ns} request. This will enable @dfn{no-space mode}.
+This mode will end when actual text is output or the @code{rs}
+request is encountered. No-space mode will also prevent requests to
+advance to the next page unless they are accompanied by a page number
+(@pxref{Page Control}, for more information.)
+
+
+@node Tabs and Fields, Character Translations, Manipulating Spacing, Programming Tutorial
+@section Tabs and Fields
+@cindex tabs and fields
+@cindex fields and tabs
+
+
+@findex \t
+Tab stops are much like those on a typewriter: a tab character (or the
+@code{\t} escape) on input will cause horizontal motion to the next
+tab stop.
+
+@findex ta
+Tab stops can be changed with the @code{ta} request.
+This request takes a series of numbers as arguments which indicate
+where each tab stop is to be (overriding any previous settings).
+These can be specified absolutely,
+i.e. as the distance from the left margin.
+For example, the following wil set tab stops every one inch.
+
+@example
+.ta 1i 2i 3i 4i 5i 6i
+@end example
+
+Tab stops can also be specified relatively (using a leading @samp{+})
+which means that the specified tab stop will be set that distance
+from the previous tab stop. For example the following is equivalent
+to the previous example.
+
+@example
+.ta 1i +1i +1i +1i +1i +1i
+@end example
+
+After the specified tab stops repeat values may be set for tabs beyond
+the last one specified. This is most commonly used to specify tabs
+set at equal intervals. The compleat syntax for setting tabs is
+@code{ta @var{n1} @var{n2} @dots{} @var{nn} T @var{r1} @var{r2}
+@dots{} @var{rn}} This will set tabs at positions @var{n1}, @var{n2},
+@dots{}, @var{nn} and then set tabs at @var{nn}+@var{r1},
+@var{nn}+@var{r2}, @dots{}, @var{nn}+@var{rn} and then at
+@var{nn}+@var{rn}+@var{r1}, @var{nn}+@var{rn}+@var{r2}, @dots{},
+@var{nn}+@var{rn}+@var{rn}, and so on. For example the following is,
+yet again, the same as the previous examples.
+
+@example
+.ta T 1i
+@end example
+
+The material in each tab column may be justified to the right or left
+or centered in the column. This is specified by appending an
+@samp{R}, @samp{L} or @samp{C} to the number specifying that tab stop.
+The default justification is @samp{L}.
+
+@example
+.ta 1i 2iC 2iR
+@end example
+
+@vindex .tabs
+The number register @code{.tabs} contains
+a string representation of the current tab settings suitable for use as
+an argument to the @code{ta} request.
+
+@findex tc
+Normally troff will fill the space to the next tab stop with spaces.
+In some cases you may wish to change this. The @code{tc} request
+will do this. With no argument troff will revert to using spaces.
+
+@subsection Leaders
+@cindex leaders
+
+@findex lc
+Sometimes you may wish to use the @code{tc} request to fill a tab
+stop with a given character, but also, you want to use normal tab
+stops on the rest of the line. For this groff provides an alternate
+tab mechanism, called @dfn{leaders} which will do just that.
+They are used exclusively to produce a repeated run of characters to
+the next tab stop.
+
+You can declare what character will be repeated with the @code{lc}
+request. If you do not give it an argument, the leaders will act the
+same as tabs.
+
+@findex \a
+The difference is that a leader is invoked by using the @code{\a}
+escape.
+
+@cindex table of contents
+@cindex contents, table of
+So for a table of contents you may want to have tab stops defined so
+that the section number is one tab stop, the title is the second with
+the remaining space being filled with a line of dots and then the
+page number slightly separated from the dots.
+
+@example
+.lc .
+.ta .5iR 5i +.25i
+1.1\tFoo\a\t12
+@end example
+
+@subsection Fields
+@cindex fields
+
+@findex fc
+Fields are a more general way of laying out tabular data.
+@code{fc}
+
+@node Character Translations, Line Layout, Tabs and Fields, Programming Tutorial
+@section Character Translations
+@cindex character translations
+@cindex translations of characters
+
+
+@findex cc
+@findex c2
+The control character (@samp{.}) and the no-break control character
+(@samp{'}) can be changed with the @code{cc} and @code{c2} requests,
+respectively.
+The single argument is the new character to be used, with no argument
+the normal control character is restored.
+
+@findex ec
+@findex eo
+The @code{eo} request will compleatly disable the escape mechanism.
+The @code{ec} request can be used to change the escape character from
+the default @samp{\} to what is specified as an argument.
+
+@findex tr
+The @code{tr} request will translate characters.
+
+@findex trnt
+@findex \!
+@code{trnt}
+This is the same as the @code{tr} request except that the
+translations do not
+apply to text that is transparently throughput into a diversion with
+@code{\!}. @xref{Diversions}, for more information.
+For example,
+
+@example
+.tr ab
+.di x
+\!.tm a
+.di
+.x
+@end example
+
+will print @samp{b}; if @code{trnt} is used instead of @code{tr} it
+will print @samp{a}.
+
+
+@node Line Layout, Page Layout, Character Translations, Programming Tutorial
+@section Line Layout
+@cindex line layout
+@cindex layout, line
+
+
+@cindex dimensions, line
+@cindex line dimensions
+The following drawing shows the dimensions which troff uses for
+placing a line of output onto the page. They are labeled with the
+request which manipulates that dimension.
+
+@example
+@group
+ | -->| in |<-- |
+ -->| po |<-----------ll------------>|
+ +----+----+----------------------+----+
+ | : : : |
+ +----+----+----------------------+----+
+@end group
+@end example
+
+These dimensions are:
+
+@ftable @code
+@item po
+@vindex .o
+@dfn{Page offset}--This is the leftmost postition of text on the final
+output. This can be adjusted with the @code{po} request, and the
+current setting can be found in the builtin number register @code{.o}
+Note, that this request does not cause a break, so changing the page
+offset in the middle of text being filled may not do what you expect.
+@item in
+@vindex .i
+@dfn{Indentation}--This is the distance from the left margin where text
+will be printed. This can be adjusted with the @code{in} request, and
+the current setting can be found in the builtin number register.
+@code{.i}
+This request causes a break.
+
+@findex ti
+@findex .in
+There is also the request @code{ti} which will cause one output line
+to be indented, after which the indentation returns to 0.
+This request causes a break.
+The number register @code{.in} is the indent that applies to the
+current output line.
+@item ll
+@findex .l
+@findex .ll
+@dfn{Line length}--This is the distance from the left margin to right
+margin. This can be adjusted with the @code{.ll} request, and the
+current setting can be found in the builtin number register @code{.l}
+Note, as the figure implies, line length is not affected by the current
+indentation.
+The number register @code{.ll} is
+the line length that applies to the current output line.
+@end ftable
+
+@example
+.in +.5i
+.ll -.5i
+A bunch of really boring text which should
+be indented from both margins.
+replace me with a better (and more) example!
+.in -.5i
+.ll +.5i
+@end example
+
+
+@node Page Layout, Page Control, Line Layout, Programming Tutorial
+@section Page Layout
+@cindex page layout
+@cindex layout, page
+
+
+Troff provides some very primitive operations for controlling page
+layout.
+
+@findex pl
+@vindex .p
+Troff lets you specify the @dfn{page length} via the @code{pl} request.
+This is the length of the physical output page.
+The current setting can
+be found in the builtin number register @code{.p}. Note that this only
+specifies the size of the page, not the not the top and bottom margins.
+Those are not done by groff directly, @xref{Traps}, for further
+information on how to do this.
+
+@cindex headers
+@cindex footers
+@cindex titles
+Troff provides several operations which help in setting up top and
+bottom titles (or headers and footers)
+
+@findex tl
+The @code{tl} request will print a @dfn{title line}, which consists
+of three parts: a left justified portion, a centered portion and a
+right justified portion. The argument to @code{tl} is specified as
+@code{'@var{left}'@var{center}'@var{right}'}
+The @samp{%} character is replaced with the current page number.
+
+@findex lt
+@vindex .lt
+The title line is printed using its own line length, which is
+specified with the @code{lt} request. The current setting of this is
+available in the @code{.lt} number register.
+
+@findex pn
+The @code{pn} request will change the page number of the @emph{next}
+page. The only argument is the page number.
+
+@vindex %
+@vindex .pn
+The current page number is stored in the number register @code{%}.
+The number register @code{.pn} contains the
+number of the next page:
+either the value set by a @code{pn} request, or
+the number of the current page plus 1.
+
+@findex pc
+The @code{pc} request will change the page number character (used by
+the @code{tl} request) to a different character. With no argument,
+this mechanism is disabled.
+
+
+@c distribute these through the text
+@xref{Traps}
+
+@node Page Control, Fonts, Page Layout, Programming Tutorial
+@section Page Control
+@cindex page control
+@cindex control, page
+
+
+@findex bp
+To stop processing the current page, and move to the next page, you
+can invoke the @code{bp} request. This request will also cause a
+break. This request can also take an argument of what the next page
+should be numbered.
+The only difference
+between @code{bp} and @code{pn} is that @code{pn} does not cause a
+break or actually eject a page.
+
+@example
+.de newpage
+'bp
+'sp .5i
+.tl 'left top'center top'right top'
+'sp .3i
+..
+@end example
+
+@cindex orphan
+@findex ne
+Often you may want to make sure that you have a certain amount of
+space before a new page occurs. This is most useful to make sure
+that there is not a single @dfn{orphan} line left at the bottom of a
+page. The @code{ne} request will ensure that there is a certain
+distance, specified by the first argument, before the next page is
+triggered (@pxref{Traps}, for further information).
+The default unit for @code{ne} is v's and the default argument
+is 1v.
+
+For example, to make sure that no fewer than 2 lines get orphaned,
+you can do the following before each paragraph.
+
+@example
+.ne 2
+.ti +5n
+text
+@end example
+
+@findex sv
+@findex os
+The @code{sv} is similar to the @code{ne} request, it reserves the
+specified amount of vertical space. If the desired amount of space
+exists before the next trap (bottom page boundary), the space will be
+output immediately. If there is not enough space, it is stored for
+later output via the @code{os} request.
+The default argument is 1v and the default units are v's.
+
+
+@node Fonts, Sizes, Page Control, Programming Tutorial
+@section Fonts
+@cindex fonts
+
+
+@findex ft
+@findex \f
+Groff gives you the ability to switch fonts at any point in your
+text. There are two ways to do this, via the @code{ft} request and
+the @code{\f} escape.
+
+Fonts are generaly specified as uppercase strings, which are usually
+1 to 4 characters representing an abreviation of acronym of the font
+name.
+
+The basic set of fonts are R, I, B, and BI. These are Times Roman,
+Italic, Bold, and Bold Italic. There is also at least one symbol
+font which contains various special symbols (greek, mathematics).
+These latter fonts cannot be used directly, but should be used via an
+escape.
+
+
+@menu
+* Changing Fonts::
+* Font Families::
+* Font Positions::
+* Using Symbols::
+* Artificial Fonts::
+* Ligatures and Kerning::
+@end menu
+
+@node Changing Fonts, Font Families, Fonts, Fonts
+@subsection Changing Fonts
+@cindex changing fonts
+@cindex fonts, changing
+
+
+@findex ft
+You can change fonts with both the @code{ft} request.
+With no arguments it
+will switch to the previous font (also known as P).
+
+@example
+eggs, bacon,
+.ft B
+spam
+.ft
+and sausage.
+@end example
+
+@findex \f
+The @code{\f} escape is useful for changing fonts in the middle of words
+
+@example
+eggs, bacon, \fBspam\fP and sausage.
+@end example
+
+Both of the above examples will produce the same output.
+
+Sometimes when putting letters of different fonts, you need more or
+less space at such boundaries. There are two escapes to help with
+this.
+
+@findex \/
+The @code{\/} escape
+increases the width of the preceding character so that the spacing
+between that character and the following character will be correct if
+the following character is a roman character. For example, if an italic
+f is immediately followed by a roman right parenthesis, then in many
+fonts the top right portion of the f will overlap the top left of the
+right parenthesis.
+It is a good idea to use this escape sequence
+whenever an italic character is immediately followed by a roman
+character without any intervening space.
+
+@c producing @i{f}), which is ugly. Inserting \/ produces f) and avoids this problem.
+
+@findex \,
+The @code{\,} escape
+modifies the spacing of the following character so that the spacing
+between that character and the preceding character will correct if the
+preceding character is a roman character.
+It is a good idea
+to use this escape sequence whenever a roman character is immediately
+followed by an italic character without any intervening space.
+
+@c For example, inserting \, between the parenthesis and the f changes (f to (f.
+
+@findex ftr
+The @code{ftr} request will translate fonts, it is called as
+@samp{.ftr @var{F G}}, which
+Translate font @var{F} to @var{G}.
+Whenever a font named @var{F} is referred to in @code{\f}
+escape sequence,
+or in the @code{ft}, @var{ul}, @var{bd}, @var{cs}, @var{tkf},
+@var{special}, @var{fspecial}, @var{fp},
+or @var{sty} requests, font @var{G} will be used. If @var{G} is
+missing, or equal to @var{F} then font @var{F} will not be translated.
+
+
+@node Font Families, Font Positions, Changing Fonts, Fonts
+@subsection Font Families
+@cindex font families
+@cindex families, font
+
+
+Due to the variety of fonts available, groff has added the concept of
+font families. Each of these families has four styles (R, I, B and BI),
+
+The fonts are specified as the concatenation of the font family and
+style. Specifying a font without the family part will cause groff to
+use that style of the current family.
+By default, groff uses the Times family.
+
+This way, you can just use the basic four fonts and select a
+different font family on the command line.
+
+@findex fam
+@vindex .fam
+You can also switch font families with the @code{fam} request
+The current font family is available in the number register
+@code{.fam}.
+This is a string-valued register.
+
+@example
+spam,
+.fam H
+spam,
+.ft B
+spam,
+.fam T
+spam,
+.ft AR
+baked beans,
+.ft R
+and spam.
+@end example
+
+
+
+@node Font Positions, Using Symbols, Font Families, Fonts
+@subsection Font Positions
+@cindex font positions
+@cindex positions, font
+
+
+For the sake of old phototypesetters and compatability with old
+versions of troff, groff has the concept of font
+@dfn{positions}, on which various fonts are mounted.
+The last one or two are reserved for the symbol font(s).
+
+@findex fp
+New fonts can be mounted with the @code{fp} request.
+These numeric positions can then be referred to with font changing commands.
+When groff starts it is using font number one.
+
+@example
+.fp 1 H
+.fp 2 HI
+.fp 3 HB
+wink, wink,
+.ft 2
+nudge, nudge,
+.ft
+.ft 3
+say no more!
+.ft
+@end example
+
+(note that after these font changes have taken place the original
+font is restored.)
+
+@vindex .f
+The current font in use, as a font position.
+This can be useful to remember the current font, for later recall.
+
+@example
+.nr save-font \n(.f
+... lots 'o text ...
+.ft \n[save-font]
+@end example
+
+@vindex .fp
+The number of the next free font position is available in the number
+register @code{.fp}. This is useful when mounting a new font, like so:
+
+@example
+.fp \n[.fp] NEATOFONT
+@end example
+
+@pindex DESC
+Fonts not listed in the @file{DESC} file are automatically mounted on
+the next available font position when they are referenced.
+If a font is to be
+mountfed explicitly with the @code{fp} request on an unused font position, it
+should be mounted on the first unused font position, which can be found
+in the @code{.fp} register; although troff does not enforce this strictly,
+it will not allow a font to be mounted at a position whose number is
+much greater than that of any currently used position.
+
+The @code{fp} request has an optional third argument.
+This argument gives the
+external name of the font, which is used for finding the font
+description file. The second argument gives the internal name of the
+font which is used to refer to the font in troff after it has been
+mounted. If there is no third argument then the internal name will be
+used as the external name. This feature allows you to use fonts with
+long names in compatibility mode.
+
+
+
+@node Using Symbols, Artificial Fonts, Font Positions, Fonts
+@subsection Using Symbols
+@cindex using symbols
+@cindex symbols, using
+
+
+@findex \(
+@findex \[
+Symbols can be inserted by using a special escape sequence.
+This escape is simply the escape character (a backslash) followed by
+an identifier. The symbol identifiers have to be two or more
+characters, since single characters conflict with all the other
+escapes. The identifier can be either preceded by a parenthesis if
+it is two character, or surrounded by square brackets.
+So, the symbol for pi can be produced either by @code{\(*p} or
+@code{\[*p]}.
+
+@example
+area = \(*p\fIr\fP\u2\d
+@end example
+
+@findex \C
+The escape @code{\C'@var{xxx}'} will typeset character named
+@var{xxx}. Normally it is more convenient to use @code{\[@var{xxx}]}.
+But @code{\C} has the advantage that it is compatible with recent
+versions of ditroff and is available in compatibility mode.
+
+@findex \N
+The escape @code{\N'@var{n}'} will typeset the character with code
+@var{n} in the current font. @var{n} can be any integer. Most devices only
+have characters with codes between 0 and 255. If the current font
+does not contain a character with that code, special fonts will not be
+searched. The @code{\N} escape sequence can be conveniently used on
+conjunction with the @code{char} request:
+
+@example
+.char \[phone] \f(ZD\N'37'
+@end example
+
+The code of each character is given in the fourth column in the font
+description file after the charset command. It is possible to include
+unnamed characters in the font description file by using a name of
+@samp{---}; the @code{\N} escape sequence is the only way to use these.
+
+@findex cflags
+Each character has certain properties associated with it.
+These properties can be modified with the @code{cflags} request.
+The first argument is the the sum of the desired flags and the
+remaining arguments are the characters to have those properties.
+@table @code
+@item 1
+the character ends sentences (initially characters @samp{.?!} have this
+property);
+@item 2
+lines can be broken before the character (initially no characters have
+this property);
+@item 4
+lines can be broken after the character (initially characters
+@samp{-\(hy\(em} have this property);
+@item 8
+the character overlaps horizontally (initially characters
+@samp{\(ul\(rn\(ru} have this property);
+@item 16
+the character overlaps vertically (initially character @samp{\(br} has
+this property);
+@item 32
+an end of sentence character followed by any number of characters with
+this property will be treated as the end of a sentence if followed by a
+newline or two spaces; in other words the character is transparent for
+the purposes of end of sentence recognition; this is the same as having
+a zero space factor in @TeX{} (initially characters
+@samp{"')]*\(dg\(rq} have this property).
+@end table
+
+@findex char
+You can create new characters with the @code{char} request. It is
+called as @samp{.char @var{c} @var{string}} Define character @var{c}
+to be @var{string}. Every time character @var{c} needs to be printed,
+@var{string} will be processed in a temporary environment and the
+result will be wrapped up into a single object. Compatibility mode
+will be turned off and the escape character will be set to \ while
+@var{string} is being processed. Any emboldening, constant spacing or
+track kerning will be applied to this object rather than to individual
+characters in @var{string}. A character defined by this request can
+be used just like a normal character provided by the output device.
+In particular other characters can be translated to it with the
+@code{tr} request; it can be made the leader character by the
+@code{lc} request; repeated patterns can be drawn with the character
+using the @code{\l} and @code{\L} escape sequences; words containing
+the character can be hyphenated correctly, if the @code{hcode} request
+is used to give the character a hyphenation code. There is a special
+anti-recursion feature: use of character within the character's
+definition will be handled like normal characters not defined with
+@code{char}.
+
+@findex rchar
+A character definition can be removed with the @code{rchar} request. Its
+arguments are the characters to be removed. This undoes the effect of
+a @code{char} request.
+
+@c distribute these through the text
+@xref{Special Characters}
+
+@node Artificial Fonts, Ligatures and Kerning, Using Symbols, Fonts
+@subsection Artificial Fonts
+@cindex artificial fonts
+@cindex fonts, artificial
+
+
+There are a number of requests for artificially creating fonts.
+These are largely vestigal remains from the days when output devices
+did not have a wide variety of fonts, and when nroff and troff were
+separate programs.
+These are no longer necessary in GNU Troff.
+
+@findex ul
+The @code{ul} request will print subsequent lines in italics on a
+device capable of it, or underline the text on an ascii output device.
+The single argument is the number of lines to be ``underlined,''
+with no argument, the next line will be underlined.
+
+@findex cu
+The @code{cu} request is similar to @code{ul} ...
+
+@findex uf
+The @code{uf} request will set the underline font used by @code{ul}
+and @code{cu}.
+
+@findex bd
+The @code{bd} request artificially creates a bold font by printing
+each character twice, slightly offset.
+The first argument specifies the font to embolden, and the second is
+the number of basic units, minus one, by which the two characters
+will be offset. If the second argument is missing, emboldening will
+be turned off.
+
+
+@node Ligatures and Kerning, , Artificial Fonts, Fonts
+@subsection Ligatures and Kerning
+@cindex ligatures and kerning
+@cindex kerning and ligatures
+
+
+@findex lg
+@vindex .lg
+@code{lg}
+@code{.lg}
+The current ligature mode.
+
+What is kerning??
+
+If the font description file contains pairwise kerning information,
+characters from that font will be kerned. Kerning between two
+characters can be inhibited by placing a @code{\&} between them.
+
+@findex kern
+@vindex .kern
+@code{kern}
+If n is non-zero or missing, enable pairwise kerning, otherwise disable
+it.
+@code{.kern}
+1 if pairwise kerning is enabled, 0 otherwise.
+
+@findex tkf
+.tkf f s1 n1 s2 n2
+Enable track kerning for font f. When the current font is f the width
+of every character will be increased by an amount between n1 and n2;
+when the current point size is less than or equal to s1 the width will
+be increased by n1; when it is greater than or equal to s2 the width
+will be increased by n2; when the point size is greater than or equal to
+s1 and less than or equal to s2 the increase in width is a linear
+function of the point size.
+
+
+@node Sizes, Strings, Fonts, Programming Tutorial
+@section Sizes
+@cindex sizes
+
+
+@cindex baseline
+Groff uses two dimensions with each line of text, type size and
+vertical spacing. The type size is the height from the text
+@dfn{baseline} to the top of the tallest character (decenders may drop
+below this baseline). Vertical spacing is the amount of space groff
+allows for a line of text, normally, this is about 20% larger than the
+current type size. Ratios smaller than this can result in
+hard-to-read text, larger that this, it will spread your text out more
+vertically (useful for term papers). By default, troff uses 10 point
+type on 12 point spacing.
+
+@cindex leading
+The difference between type size and vertical spacing is known, by
+typesetters, as @dfn{leading}.
+
+
+@menu
+* Changing Type Sizes::
+* Fractional Type Sizes::
+@end menu
+
+@node Changing Type Sizes, Fractional Type Sizes, Sizes, Sizes
+@subsection Changing Type Sizes
+@cindex changing type sizes
+@cindex type sizes, changing
+
+
+@findex ps
+@findex vs
+@findex \s
+@vindex .s
+@vindex .v
+Using the @code{ps} request and the @code{\s} escape you can change
+the type size. The @code{vs} request will change the vertical
+spacing. The default unit for the @code{ps} and @code{vs} requests are
+points.
+The number registers @code{.s} and @code{.v} contain the current
+type size and vertical spacing.
+
+These requests take parameters in units of points. You can specify
+sizes as an absolute size, or as a relative change from the current
+size. The size 0 means go back to the previous size. With no
+argument it will revert to the previous size.
+
+@example
+snap, snap,
+.ps +2
+grin, grin,
+.ps +2
+wink, wink, \s+2nudge, nudge,\s+8 say no more!
+.ps 10
+@end example
+
+The @code{\s} escape may be called in a variety of ways.
+Much like other escapes there must be a way to determine where the
+argument ends and the text begins.
+Any of the following forms are valid:
+@code{\s@var{n}},
+@code{\s+@var{n}},
+@code{\s-@var{n}},
+@code{\s(@var{nn}},
+@code{\s+(@var{nn}},
+@code{\s-(@var{nn}},
+@code{\s[+@var{nnn}]},
+@code{\s[-@var{nnn}]},
+@code{\s+[@var{nnn}]},
+@code{\s-[@var{nnn}]}.
+
+Some devices may only have certain permissible sizes, in which case
+groff will round to the nearest permissible size.
+
+@example
+... .sz macro example?? ...
+@end example
+
+@node Fractional Type Sizes, , Changing Type Sizes, Sizes
+@subsection Fractional Type Sizes
+@cindex fractional type sizes
+@cindex type sizes, fractional
+
+
+A @dfn{scaled point} is equal to 1/@var{sizescale} points, where
+@var{sizescale} is specified in the @file{DESC} file (1 by default.)
+There is a new scale indicator @samp{z} which has the effect of
+multiplying by @var{sizescale}. Requests and escape sequences in
+troff interpret arguments that represent a pointsize as being in units
+of scaled points, but they evaluate each such argument using a default
+scale indicator of @samp{z}. Arguments treated in this way are the
+argument to the @code{ps} request, the third argument to the @code{cs}
+request, the second and fourth arguments to the @code{tkf} request,
+the argument to the @code{\H} escape sequence, and those variants of
+the @code{\s} escape sequence that take a numeric expression as their
+argument.
+
+For example, suppose @var{sizescale} is 1000; then a scaled point will be
+equivalent to a millipoint; the request @samp{.ps 10.25} is equivalent to
+@samp{.ps 10.25z} and so sets the pointsize to 10250 scaled points, which is
+equal to 10.25 points.
+
+The number register @code{\n(.s} returns the pointsize in points as
+decimal fraction. There is also a new number register @code{\n[.ps]}
+that returns the pointsize in scaled points.
+
+It would make no sense to use the @samp{z} scale indicator in a
+numeric expression whose default scale indicator was neither @samp{u}
+nor @samp{z}, and so troff disallows this. Similarily it would make
+no sense to use a scaling indicator other than @samp{z} or @samp{u} in a
+numeric expression whose default scale indicator was @samp{z}, and so
+troff disallows this as well.
+
+There is also new scale indicator @samp{s} which multiplies by the
+number of units in a scaled point. So, for example, @samp{\n[.ps]s}
+is equal to 1m. Be sure not to confuse the @samp{s} and @samp{z}
+scale indicators.
+
+@code{\s'+@var{n}'}
+@code{\s'-@var{n}'}
+@code{\s+'@var{n}'}
+@code{\s-'@var{n}'}
+Set the point size to @var{n} scaled points; @var{n} is a numeric
+expression with a default scale indicator of @samp{z}.
+
+@code{\n[.ps]}
+The current pointsize in scaled points.
+
+@code{\n[.psr]}
+The last-requested pointsize in scaled points.
+
+@code{\n[.sr]}
+The last requested pointsize in points as a decimal fraction. This is a
+string-valued register.
+
+
+@c distribute these through the text
+@xref{Font Files}
+
+@node Strings, Conditionals and Loops, Sizes, Programming Tutorial
+@section Strings
+@cindex strings
+
+
+@findex ds
+Groff has string variables, which are entirely for user convenience
+(i.e. there are no builtin strings) They are defined via the
+@code{ds} request.
+
+@example
+.ds UX \s-1UNIX\s0\u\s-3tm\s0\d
+@end example
+
+@findex \*
+The are interpolated, or expanded in-place, via the @code{\*} escape:
+
+@example
+The \*(UX Operating System
+@end example
+
+Will produce:
+
+@example
+The UNIXtm Operating System
+@end example
+
+If the string named by the @code{\*} does not exist, the escape will
+be replaced by nothing.
+
+@cindex comments, with @code{ds}
+NOTE: Unlike other requests the third argument takes up the entire
+line including trailing spaces. This means that comments on a line
+with such a request can introduce unwanted space into a string.
+
+@example
+.ds UX \s-1UNIX\s0\u\s-3tm\s0\d \" trademark of you-know-who
+@end example
+
+Instead you should either put the comment on another line or
+have the comment escape adjacent with the end of the string.
+
+@example
+.ds UX \s-1UNIX\s0\u\s-3tm\s0\d\" trademark of you-know-who
+@end example
+
+If you need leading space you can start the string with a double
+quote. No trailing quote is needed, in fact any trailing quote is
+included in your string.
+
+@cindex canibalism
+@example
+.ds sign " Yours in a white wine sauce,
+@end example
+
+@findex as
+@cindex appending to strings
+@cindex strings, appending
+You can also append onto a string with the @code{as} request.
+It works the same as the @code{ds} request except that it appends the
+second argument onto the string named by the first argument.
+
+@example
+.as sign " with shallots, onions and garlic,
+@end example
+
+@findex \@key{ret}
+Strings are not limited to a sigle line of text. A string can span
+several lines by escaping the newlines with a backslash. The
+resulting string will be stored @emph{without} the newlines.
+
+@example
+.ds foo lots and lots \
+of text are on these \
+next several lines
+@end example
+
+@findex rn
+@code{rn}
+
+@findex rm
+@code{rm}
+
+@findex als
+@code{als}
+
+@findex chop
+@code{chop}
+
+@c distribute these through the text
+@xref{Identifiers}
+@c distribute these through the text
+@xref{Comments}
+
+@node Conditionals and Loops, Writing Macros, Strings, Programming Tutorial
+@section Conditionals and Loops
+@cindex conditionals and loops
+@cindex loops and conditionals
+
+
+@findex if
+@findex while
+In @code{if} and @code{while} requests, there are several more operators
+available:
+
+@table @code
+@item e
+@itemx o
+True if the current page is even or odd numbered (respectively)
+@item n
+@itemx t
+True if the document is being processed by
+nroff (or an ascii device) or troff.
+@item '@var{xxx}'@var{yyy}'
+True if the string @var{xxx} is equal to the string @var{yyy}.
+Other characters can be used in place of the single quotes.
+(Which?)
+The strings are `formatted' before being compared. (?)
+@item r@var{xxx}
+True if there is a number register named @var{xxx}.
+@item d@var{xxx}
+True if there is a string, macro, diversion, or request named @var{xxx}.
+@item c@var{ch}
+True if there is a character @var{ch} available; @var{ch} is
+either an ASCII character or a special character @code{\(@var{ch}} or
+@code{\[@var{ch}]}; the condition will also be true if @var{ch} has been
+defined by the @code{char} request.
+@end table
+
+
+@menu
+* if-else::
+* while::
+@end menu
+
+@node if-else, while, Conditionals and Loops, Conditionals and Loops
+@subsection if-else
+@cindex if-else
+
+
+Troff has if-then-else constructs like other languages, although
+the formatting can be painful.
+
+@findex if
+The @code{if} request is troff's if statement, it is called as
+@samp{.if @var{expr} @var{anything}}, where @var{expr} is the
+expression to be evaluated,
+and @var{anything} (the remainder of the line)
+which will be executed if
+the @var{expr} evaluates to non-zero (true).
+@var{anything} will be interpreted as though it was on a line by
+itself.
+@xref{Expressions}, for more info.
+
+Here are some examples:
+
+@example
+.if t .ls 2 \" double spacing in troff
+.if 0 .ab how'd this happen??
+@end example
+
+@findex ie
+@findex el
+An if-then-else is written using two requests @code{ie} and @code{el}
+the first request is the if part and the latter is the else part.
+
+@example
+.ie
+.el
+@end example
+
+@findex \@{
+@findex \@}
+In many cases you will want more than one request to be executed as a
+result of any of these requests, this can be done using the \@{ and
+\@} escapes.
+The following example shows the possible ways to use these escapes.
+
+@example
+.ie t \@{\
+. ds lq ``
+. ds rq ''
+.\@}
+.el \
+.\@{\
+. ds lq "
+. ds rq "\@}
+.ds qq "
+@end example
+
+
+@c distribute these through the text
+@xref{Expressions}
+
+@node while, , if-else, Conditionals and Loops
+@subsection while
+@cindex while
+
+
+@findex while
+Groff provides a looping construct using the @code{while} request,
+which is used much like the @code{if} (and related) requests.
+The first argument is an expression which will be evaluated.
+The @code{while} request will interpret the remainder of the line
+until the expression evaluates to 0 or false.
+
+@example
+.nr a 0 1
+.while (\na<9) \&\n+a,
+\&\n+a
+@end example
+
+The preceding example produces:
+
+@example
+1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+@end example
+
+@findex break
+@findex continue
+The @code{break} request will
+@dfn{break} out of a while loop.
+Be sure not to confuse this with the @code{.br} request.
+The @code{continue} request will
+finish the current iteration of a while loop.
+
+@c distribute these through the text
+@xref{Expressions}
+
+@node Writing Macros, Page Motions, Conditionals and Loops, Programming Tutorial
+@section Writing Macros
+@cindex writing macros
+@cindex macros, writing
+
+
+@findex de
+A macro is a collection of text and embedded commands which can be
+invoked multiple times. Macros are used for defining common operations.
+Macros are defined using the @code{de} request. This request takes
+a name for the macro as the first argument. Subsequent lines are
+copied into an internal buffer until the line @code{..} is
+encountered. The optional second argument to @code{de} can change
+this ending token.
+
+For example, suppose at the beginning of each paragraph, you want
+cause a break, move down a partial line and indent the first line.
+Such a macro could be defined as follows:
+
+@example
+.de P
+.br
+.sp .8v
+..
+@end example
+
+@findex am
+The @code{am} request works similarily to @code{de} except it appends
+onto the macro named by the first argument. So, if we decide we want
+our previously @code{P} macro to actually do indented instead of
+block paragraphs we can add the necessary code to our existing macro.
+
+@example
+.am P
+.ti +5n
+..
+@end example
+
+@findex als
+@cindex aliases, macro
+@cindex macro aliases
+Macros can be aliased with the @code{als} request.
+
+@findex rn
+@code{rn}
+
+@findex rm
+@code{rm}
+
+@findex chop
+@code{chop}
+
+
+@menu
+* Copy-in Mode::
+* Parameters::
+@end menu
+
+@node Copy-in Mode, Parameters, Writing Macros, Writing Macros
+@subsection Copy-in Mode
+@cindex copy-in mode
+@cindex mode, copy-in
+
+
+@findex \n
+@findex \$
+@findex \*
+@findex \\
+@findex \@key{RET}
+When troff reads in the test for a macro or diversion it copies the
+text (including request lines) into an internal buffer, except for
+escapes. Escapes will be converted into an internal form, except for
+@code{\n}, @code{\$}, @code{\*}, @code{\\} and @code{\@key{RET}} which
+are evaluated and inserted into the text where the escape was located.
+This is known as @dfn{copy-in} mode.
+
+What this means is that you can specify when these escapes are to be
+evaluated (copy-in time or time of use) by insulating the escapes
+with an extra backslash.
+
+For example, the following will result in the numbers 20 and 10 being
+printed.
+
+@example
+.nr x 20
+.de y
+.nr x 10
+\&\nx
+\&\\nx
+..
+.y
+@end example
+
+
+
+@node Parameters, , Copy-in Mode, Writing Macros
+@subsection Parameters
+@cindex parameters
+
+
+@findex \$
+@vindex .$
+The arguments to a macro can be examined using a variety of escapes.
+The number of arguments is available in the @code{.$} number register.
+Any individual argument can be retrieved with one of the following
+escapes:
+
+The escapes @code{\$@var{n}}, @code{\$(@var{nn}}
+and @code{\$[@var{nnn}]}
+will result in the @var{n}th, @var{nn}th or @var{nnn}th
+argument. Macros can have a unlimited number of arguments.
+Note that due to copy-in mode, you will want to have two backslashes
+on these in actual use, since you do not want them interpolated until
+the macro is actually invoked.
+
+@findex shift
+The request @code{shift} will shift the arguments 1 position, or as
+many positions as specified by the first argument.
+After executing this request, argument
+@var{i} will become argument @var{i}-@var{n}; arguments 1 to @var{n}
+will no longer be available.
+Shifting by negative amounts is currently undefined.
+
+@findex \$*
+@findex \$@@
+In some cases you will want to just use all of the arguments at once.
+For example if you pass the arguments along to another macro.
+The @code{\$*} escape is
+the concatenation of all the arguments separated by spaces.
+A similar escape is @code{\$@@},
+which is
+the concatenation of all the arguments with each surrounded
+by double quotes, and separated by spaces.
+
+@findex \$0
+@findex als
+The @code{\$0} escape is
+the name by which the current macro was invoked. The @code{als}
+request can make a macro have more than one name.
+
+@example
+.de vl
+.ie \\n(.$=1 .ds Vl Pre-Release Version
+.el .ds Vl Version \\$3, \\$4.
+..
+@end example
+
+This would be called as
+
+@example
+.vl $Id: groff.texinfo,v 1.1 2000/04/09 07:58:37 millert Exp $
+@end example
+
+
+@c distribute these through the text
+@xref{Request Arguments}
+
+@node Page Motions, Drawing Functions, Writing Macros, Programming Tutorial
+@section Page Motions
+@cindex page motions
+@cindex motions, page
+
+
+@findex sp
+Motions up and down the page can be done with the @code{sp} request.
+However, this causes a break so that the actual effect is to move to
+the left margin and then to the specified location.
+
+@findex mk
+@findex rt
+The request @code{mk} can be used to mark a location on a page, for
+movement to later. This request takes a register name as an
+argument in which to store the current page location, with no
+argument it will store the location in an internal register.
+The results of this can be used later by the @code{rt} or the
+@code{sp} request. The @code{rt} request will return
+@strong{upwards} to the location given in the register name given as
+an argument, with no argument it will return to the location marked
+with the @code{mk} request
+
+@example
+... dual column example ...
+@end example
+
+There are escapes which will give you much finer control of movements
+about the page.
+
+@findex \v
+The @code{\v'@var{e}'} will let you do arbitrary vertical motion from
+the current location on the page. The argument @var{e} specifies the
+distance to move, positive is downwards and negative upwards. The
+default unit for this escape is vertical spaces, @code{v}'s. Beware,
+however, that troff will leave text processing to continue wherever
+the motion ends, so if you don't want to interfere with text
+processing, make sure your motions are balanced.
+
+There are some special case escapes for vertical motion.
+
+@ftable @code
+@item \r
+move upwards 1v.
+@item \u
+move upwards .5v.
+@item \d
+move down .5v.
+@end ftable
+
+@findex \h
+Horizontal motions can be done via the @code{\h'@var{e}'} escape.
+The expression @var{e} indicates how far to move: positive is
+rightwards and negative leftwards.
+
+There are a number of special case escapes for horizontal motion:
+
+@ftable @code
+@item \@key{SP}
+An unbreakable and unpadable (i.e. not expanded during filling) space.
+(Note: it is a backslash followed by a space.)
+@item \~
+This produces an unbreakable space that stretches like a normal
+interword space when a line is adjusted.
+@item \|
+a 1/6th em space.
+@item \^
+a 1/12th em space.
+@item \0
+a space the size of a digit.
+@item \&
+A zero width space.
+@item \)
+Like @code{\&} except that it behaves like a character declared with
+the @code{cflags} request to be transparent for the purposes of end
+of sentence recognition.
+@end ftable
+
+@example
+... tex logo example ...
+@end example
+
+@findex \w
+@cindex width escape
+@cindex escape, width
+Often you will want to do horizontal movement based on the width of
+some arbitrary text (e.g. given as an argument to a macro).
+For that, there is the escape @code{\w'@var{text}'} which will
+interpolate to the width of the given @var{text} in basic units.
+
+@example
+... strlen example ...
+@end example
+
+Font changes may occur in @var{text} and not affect current settings.
+
+Also after use, @code{\w} sets several registers:
+
+@table @code
+@item st
+@vindex st
+@itemx sb
+@vindex sb
+The highest and lowest point, respectively, in @var{text}.
+@item rst
+@vindex rst
+@itemx rsb
+@vindex rsb
+Like the @code{st} and @code{sb} registers, but takes account of the
+heights and depths of characters.
+@item ct
+@vindex ct
+is set according to what kinds of characters occur in @var{text}.
+@table @asis
+@item 0
+all short characters, no decenders or tall characters.
+@item 1
+decender
+@item 2
+tall character
+@item 3
+both a decender and a tall character
+@end table
+@item ssc
+@vindex ssc
+The amount of horizontal space (possibly negative) that should be
+added to the last character before a subscript.
+@item skw
+@vindex skw
+How far to right of the center of the last character in the @code{\w}
+argument, the center of an accent from a roman font should be
+placed over that character.
+@end table
+
+@findex \k
+@vindex .k
+@code{\k}
+@code{.k}
+
+@node Drawing Functions, Traps, Page Motions, Programming Tutorial
+@section Drawing Functions
+@cindex drawing functions
+@cindex functions for drawing
+
+
+Groff provides a number of ways to draw lines, and other figures on
+the page. Used in combination with the page motion commands
+(@pxref{Page Motions}, for more info) you can draw a wide variety of
+figures. However, for complex drawings these operations can be quite
+cumbersome, and it may be wise to use the pic preprocessor.
+@xref{gpic}, for more information.
+
+All drawing is done via escapes.
+
+@findex \l
+The @code{\l} will draw a line rightwards from the current location.
+The full syntax for this escape is @samp{\l'@var{l}@var{c}'}, where
+@var{l} is the length of the line to be drawn, starting at the
+current location, positive numbers will draw to the right, and
+negative will draw towards the left. This can also be specified
+absolutely (i.e. with a leading |) which will draw back to the
+begining of the line.
+
+The optional second parameter @var{c} is a character to draw the line
+with. If this second argument is not specified, troff will use the
+underscore character.
+
+If you need to separate the two arguments (to prevent troff from
+interpreting a drawing character as a scaling indicator), you can
+separate them with @code{\&}.
+
+And now, for a useful example:
+
+@example
+.de box
+\(br\\$*\(br\l'|0\(rn'\l'|0\(ul'
+..
+@end example
+
+Note that this works by outputing a box rule (a vertical line), then
+the text given as an argument and then another box rule.
+Then the line drawing escapes both draw from the current location to
+the beginning of the @emph{input} line.
+
+@findex \L
+Vertical lines are drawn using the @code{\L} escape. It's parameters
+are specified the same as the @code{\l} escape. If the length is
+positive, the movement will be downwards, and upwards for negative.
+The default character is the box rule character.
+As with the vertical motion escapes, text processing will blindly
+continue where the line ends.
+
+@example
+...box macro...
+@end example
+
+@findex \D
+More flexible drawing functions are available via the @code{\D}
+escape. While the previous escapes will work on an ascii device,
+these escapes will not.
+
+@table @code
+@item \D'l @var{x} @var{y}'
+Draw a line from the current location to the relative point specified
+by @var{x}, @var{y}.
+
+@example
+...revised box macro...
+@end example
+
+@item \D'c @var{d}'
+Draw a circle with a diameter of @var{d} with the leftmost point at
+the current position.
+@item \D'C @var{d}'
+Draw a solid circle with the same parameters as an outlined circle.
+@item \D'e @var{dx} @var{dy}'
+Draw an ellipse with a horizontal diameter of @var{dx} and a vertical
+diameter of @var{dy} with the leftmost point at the current position.
+@item \D'E @var{dx} @var{dy}'
+Draw a solid elipse with the same parameters as an outlined elipse.
+@item \D'a @var{dx1} @var{dy1} @var{dx2} @var{dy2}'
+Draw an arc clockwise from the current location through the two
+specified locations.
+@item \D'~ @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
+Draw a spline from the current location to
+@var{dx1}, @var{dy1} and then to @var{dx2}, @var{dy2}, and so on.
+@item \D'f @var{n}'
+Set the shade of gray to be used for filling solid objects to @var{n};
+@var{n} must be an integer between 0 and 1000, where 0 corresponds
+solid white and 1000 to solid black, and values in between correspond
+to intermediate shades of gray. This applies only to solid circles,
+solid ellipses and solid polygons. By default, a level of 1000 will
+be used.
+@item \D'p @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
+Draw a polygon from the current location to @var{dx1}, @var{dy1}
+and then to @var{dx2}, @var{dy2} and so on. When the specified data
+points are exhausted, a line is drawn back to the starting point.
+
+@example
+... box example (yes, again)...
+@end example
+
+@itemx \D'P @var{dx1} @var{dy1} @var{dx2} @var{dy2} ...'
+Draw a solid polygon with the same parameters as an outlined polygon.
+
+@example
+... shaded box example ...
+@end example
+
+@item \D't @var{n}'
+Set the current line thickness to @var{n} machine units.
+A value of zero selects the smallest available line thickness.
+
+@end table
+
+Current position
+
+@findex \b
+@cindex pile, character
+@cindex character pile
+The @code{\b} escape will @dfn{pile} a sequence of characters
+vertically, and center it vertically on the current line.
+This can be used to build large brackets and braces.
+
+@example
+\b'\(lt\(bv\(lk\(bv\(lb'
+@end example
+
+
+
+
+@node Traps, Diversions, Drawing Functions, Programming Tutorial
+@section Traps
+@cindex traps
+
+
+Traps are locations, which, when reached, will call a specified macro.
+These traps can occur at a given location on the page, at a given
+location in the current diversion, after a certain number of input
+lines or at the end of input.
+
+@findex ch
+Any of these traps can be changed after they have been set with the
+@code{ch} request. The first arguemnt is the name of the trap or
+macro, and the second is the new value for that trap.
+
+
+@menu
+* Page Location Traps::
+* Diversion Traps::
+* Input Line Traps::
+* End-of-input Traps::
+@end menu
+
+@node Page Location Traps, Diversion Traps, Traps, Traps
+@subsection Page Location Traps
+@cindex page location traps
+@cindex traps, page location
+
+
+Page location traps are frequently used for page headers and
+footers. The following is a simple example of this.
+
+@example
+.de hd \" Page header
+'sp .5i
+.tl 'Title''date'
+'sp .3i
+..
+.de fo \" Page footer
+'sp 1v
+.tl ''%''
+'bp
+..
+.wh 0 hd \" top of the page
+.wh -1i fo \" one inch from bottom
+@end example
+
+@vindex .t
+The number register @code{.t} is the distance to the next trap.
+
+@findex ch
+The location of a trap can be changed later on with the @code{ch}
+request.
+The first argument is the name of the macro to be invoked at the trap
+and the second argument is the new location for the trap.
+This is useful when you are building up footnotes in a diversion, and
+you need to allow more space at the bottom of the page for them.
+
+@example
+... (simplified) footnote example ...
+@end example
+
+@findex vpt
+@findex wh
+@findex dt
+@vindex .vpt
+The @code{vpt} request will enable vertical position traps if the argment is
+non-zero, disable them otherwise. Vertical position traps are traps
+set by the @code{wh} or @code{dt} requests. Traps set by the
+@code{it} request are not vertical position traps. The parameter that
+controls whether vertical position traps are enabled is global.
+Initially vertical position traps are enabled. The current setting of
+this is available in the number register @code{.vpt}.
+
+@vindex .trunc
+@findex ne
+The number register @code{.trunc} contains
+the amount of vertical space truncated by the most recently
+sprung vertical position trap, or, if the trap was sprung by a
+@code{ne} request, minus the amount of vertical motion produced by
+the @code{ne} request. In other words, at the point a trap is
+sprung, it represents the difference of what the vertical position
+would have been but for the trap, and what the vertical position
+actually is.
+
+@vindex .ne
+The number register @code{.ne} contains
+the amount of space that was needed in the last @code{ne} request that caused
+a trap to be sprung. Useful in conjunction with the @code{.trunc}
+register. @xref{Page Control}, for more information.
+
+
+
+@node Diversion Traps, Input Line Traps, Page Location Traps, Traps
+@subsection Diversion Traps
+@cindex diversion traps
+@cindex traps, diversion
+
+
+@findex dt
+@vindex .t
+Traps can also be set @emph{within} a diversion using the @code{dt}
+request. Like @code{wh} the first argument is the location of the
+trap and the second argument is the name of the macro to be invoked.
+The number register @code{.t} will still work within diversions.
+@xref{Diversions}, for more information.
+
+@node Input Line Traps, End-of-input Traps, Diversion Traps, Traps
+@subsection Input Line Traps
+@cindex input line traps
+@cindex traps, input line
+
+
+@findex it
+The @code{it} request will set an input line trap. The format for
+calling this is @samp{.it @var{n} @var{name}}, where @var{n} is the
+number of lines of input which may be read before @dfn{springing} the
+trap, @var{name} is the macro to be invoked. Request lines are not
+counted as input lines.
+
+For example, one possible use is to have a macro which will print the
+next @var{n} lines in a bold font.
+
+@example
+.de B
+.it B-end \\$1
+.ft B
+..
+.de B-end
+.ft R
+..
+@end example
+
+@node End-of-input Traps, , Input Line Traps, Traps
+@subsection End-of-input Traps
+@cindex end-of-input traps
+@cindex traps, end-of-input
+
+
+@findex em
+The @code{em} request will set a trap at the end of input.
+The macro specified as an arguement will be executed after the last
+line of the input file has been processed.
+
+For example, if your document had to have a section at the bottom of
+the last page for someone to approve you document, you could set it
+up with @code{em}.
+
+@example
+.de approval
+.ne 5v
+.sp |(\\n(.t-6v)
+.in +4i
+.lc _
+.br
+Approved:\t\a
+.sp
+Date:\t\t\a
+..
+.em approval
+@end example
+
+
+@node Diversions, Environments, Traps, Programming Tutorial
+@section Diversions
+@cindex diversions
+
+
+In Troff you can divert text into a named storage area, due to the
+similarity to defining macros it is sometimes said to be stored in a
+macro. This is used for saving text for output at a later time,
+which is useful for keeping blocks of text on the same page,
+footnotes, tables of contents and indexes.
+
+@findex di
+@findex da
+Diversion is initiated by the @code{di} request, like the @code{de}
+request it takes an argument of a macro name to divert subsequent
+text to into. The @code{da} macro will append to an existing diversion.
+
+@example
+... end-note example ...
+@end example
+
+@vindex .z
+@vindex .d
+@vindex nl
+@vindex .h
+Diversions may be nested.
+The number register @code{.z} contains the name of the current diversion.
+The number register @code{.d} contains the current vertical place in
+the diversion. If not in a diversion it is the same as the register
+@code{nl}.
+@code{.h}
+
+@vindex dn
+@vindex dl
+After compleating a diversion, the builtin number registers @code{dn}
+and @code{dl} contain the vertical and horizontal size of the diversion.
+
+@example
+.\" Center text both horizontally & vertically
+.de (c
+.br
+.nf
+.di @@c
+..
+.de )c
+.br
+.di
+.nr @@s (((\\n(.tu-\\n(dnu)/2u)-1v)
+.sp \\n(@@su
+.ce 1000
+.nf
+.@c
+.br
+.ce 0
+.sp \\n(@@su
+.br
+.fi
+.rr @@s
+..
+@end example
+
+@findex \!
+Requests, macros and escapes are interpreted when read into a
+diversion.
+There are two ways to prevent this, either way will take the given
+text and @dfn{transparently} embed it into the diversion.
+The first method is to prefix the line with @code{\!}. This will
+cause the entire line to be transparently inserted into the diversion.
+This is useful for macros you do not want invoked until the diverted
+text is actually output.
+
+@c anything is read in copy mode. (what about \! ??)
+
+@findex \?
+The other way is to surround the text by the @code{\?} escape, i.e.
+@samp{\?@var{anything}\?}.
+@var{anything} may not contain
+newlines; use @code{\!} if you want to embed newlines in a diversion. The
+escape sequence @code{\?} is also recognised in copy mode and turned into a
+single internal code; it is this code that terminates anything. Thus
+the followin example will print 4.
+
+@example
+.nr x 1
+.nf
+.di d
+\?\\?\\\\?\\\\\\\\nx\\\\?\\?\?
+.di
+.nr x 2
+.di e
+.d
+.di
+.nr x 3
+.di f
+.e
+.di
+.nr x 4
+.f
+@end example
+
+@findex rn
+@code{rn}
+
+@findex rm
+@code{rm}
+
+@findex als
+@code{als}
+
+@findex chop
+@code{chop}
+
+@findex asciify
+@code{asciify}
+This request only exists in order to make it possible to make certain
+gross hacks work with GNU troff. It @dfn{unformats} the diversion
+specified as an argument in
+such a way that ASCII characters that were formatted and diverted
+will be treated like ordinary input characters when the diversion is
+reread. For example, the following will set register @code{n} to 1.
+
+@example
+.tr @@.
+.di x
+@@nr\ n\ 1
+.br
+.di
+.tr @@@@
+.asciify x
+.x
+@end example
+
+
+@c distribute these through the text
+@xref{Copy-in Mode}
+
+@node Environments, I/O, Diversions, Programming Tutorial
+@section Environments
+@cindex environments
+
+
+Often you will need to print some text in a certain format regardless
+of what may be in effect at the time, for example, in a trap invoked
+macro to print headers and footers.
+To solve this groff has @dfn{environments} in which text is processed.
+An environment contains most of the parameters that control
+text processing. You can switch amongst these environments, by
+default groff processes text in environment 0.
+The following is the information kept in an environment.
+
+@itemize @bullet{}
+@item
+Type size
+@item
+Font (family and style)
+@item
+Page parameters
+@item
+Fill/adjust mode
+@item
+Tab stops
+@item
+Partially collected lines
+@end itemize
+
+These environments may be given arbitrary names
+(@pxref{Identifiers}, for more info.)
+Old versions of troff only had environments named 0, 1 and 2.
+
+@findex ev
+@vindex .ev
+The @code{ev} request will switch among these environments.
+The single argument is the name of the environment to switch to, with
+no argument groff will switch back to the previous enviroment.
+There is no limit on the number of named environments;
+they will be created the first time that they are referenced.
+The @code{.ev} number register contains
+the name or number of the current environment. This is a string-valued
+register.
+
+@example
+... page break macro, revised ...
+@end example
+
+@example
+.ev footnote-env
+.fam N
+.ps 6
+.vs 8
+.ll -.5i
+.ev
+...
+.ev footnote-env
+\(dg Note the large, friendly letters.
+.ev
+@end example
+
+
+
+
+@node I/O, Postprocessor Access, Environments, Programming Tutorial
+@section I/O
+@cindex i/o
+
+
+@findex so
+The @code{so} request will read in the file given as an argument and
+include it in place of the @code{so} request. This is quite useful
+for large documents, i.e. keeping each chapter in a separate file.
+@xref{gsoelim}, for more information.
+
+@findex mso
+The @code{mso} request is
+the same as the @code{so} request except that file is searched for in
+the same way that @file{tmac.@var{name}} is searched for when the
+@samp{-m@var{name}} option is specified.
+
+@findex cf
+@findex trf
+The @code{cf} and @code{trf} requests are to include a file.
+It will transparently output the contents of file filename. Each
+line is output
+as it would be were it preceded by @code{\!}; however, the lines are not
+subject to copy-mode interpretation. If the file does not end with a
+newline, then a newline will be added. For example, you can define a
+macro @code{x} containing the contents of file @file{f}, using
+
+@example
+.di x
+.trf f
+.di
+@end example
+
+.cf filename
+When used in a diversion, this will embed in the diversion an object
+which, when reread, will cause the contents of filename to be
+transparently copied through to the output. In @sc{Unix} troff, the contents
+of filename is immediately copied through to the output regardless of
+whether there is a current diversion; this behaviour is so anomalous
+that it must be considered a bug.
+
+
+With @code{trf}, unlike @code{cf}, the file cannot contain characters
+such as NUL that are not legal troff input characters.
+
+@findex nx
+The @code{nx} request will force groff to continue processing of the
+file specified as an argument.
+
+@findex rd
+The @code{rd} request will read from standard input, and include what
+is read as though it were part of the input file. Text is read until
+a blank line is encountered.
+
+@cindex form letters
+@cindex letters, form
+Using these two requests you can set up form letters.
+The form letter template is constructed like this:
+
+@example
+.ce
+\*(td
+.sp 2
+.nf
+.rd
+.sp
+.rd
+.fi
+Body of letter.
+.bp
+.nx repeat.let
+@end example
+
+@findex ex
+When this is run, the following file should be redirected in.
+Note that requests included in this file are executed as though they
+were part of the form letter. The last block of input is the
+@code{ex} requests which tells groff to stop processing. If this was
+not there, groff would not know when to stop.
+
+@cindex Beagle Brothers
+@example
+Trent A. Fisher
+708 NW 19th Av., #202
+Portland, OR 97209
+
+Dear Trent,
+
+Len Adollar
+4315 Sierra Vista
+San Diego, CA 92103
+
+Dear Mr. Adollar,
+
+.ex
+@end example
+
+@findex pi
+@code{pi}
+
+@findex sy
+The @code{sy} request will allow arbitrary system commands to be
+executed from within a groff document. The output is not saved
+anyplace, so it is up to you to do so.
+
+For example, the following example will introduce the current time
+into your document:
+
+@cindex time
+@pindex perl
+@example
+.sy perl -e 'printf ".nr H %d\\n.nr M %d\\n.nr S %d\\n",\
+ (localtime(time))[2,1,0]' > /tmp/x\n[$$]
+.so /tmp/x\n[$$]
+.sy rm /tmp/x\n[$$]
+\nH:\nM:\nS
+@end example
+
+Note that this works by having the perl script (run by @code{sy})
+print out the @code{nr} requests which will set the number registers
+@samp{H}, @samp{M} and @samp{S}, and then reads those commands in
+with the @code{so} request.
+
+@vindex systat
+The @code{systat} number register contains
+The return value of the @code{system()} function executed by the last
+@code{sy} request.
+
+@findex open
+The @code{open} request will open
+a file (specified as the second argument) for writing and associate
+the stream (specified as the first argument) with it.
+
+@findex opena
+The @code{opena} is
+like open, but if filename exists, append to it instead of truncating
+it.
+
+@findex write
+@findex ds
+@cindex copy-in mode
+@cindex mode, copy-in
+The @code{write} request will write to the file associated with the
+stream specified by the first argument. The stream must previously
+have been the subject of an open request. The remainder of the line
+in interpreted as the @code{ds} request reads its second argument: a
+leading @code{"} will be stripped, and it will be read in copy-in mode.
+
+@findex close
+The @code{close} request will
+close the stream specified by the first argument; stream will no
+longer be an acceptable argument to the @code{write} request.
+
+@example
+... example of open write &c...
+@end example
+
+@findex \v
+The @code{\V} escape will
+interpolate the contents of the specified environment variable, as returned
+by getenv(3).
+The argument to @code{\V} is specified as an identifier, i.e.
+@samp{\V@var{x}}, @samp{\V(@var{xx}} or @samp{\V[@var{xxx}]}.
+@code{\V} is interpreted in copy-in mode.
+
+
+@node Postprocessor Access, Miscellany, I/O, Programming Tutorial
+@section Postprocessor Access
+@cindex postprocessor access
+@cindex access of postprocessor
+
+
+There are two escapes which will allow you to give information
+directly to the postprocessor. This is particularly useful for
+embedding PostScript into your final document.
+
+@findex \X
+The @code{\X} escape will embed its argument into the gtroff output
+preceded with @samp{x X}.
+
+@findex \Y
+The @code{\Y} escape is called with an identifier (i.e.
+@code{\Y@var{x}},
+@code{\Y(@var{xx}} or
+@code{\Y[@var{xxx}]}).
+This is approximately equivalent to @samp{\X'\*[@var{xxx}]'}.
+However the contents
+of the string or macro @var{xxx} are not interpreted; also it is
+permitted for
+@var{xxx} to have been defined as a macro and thus contain newlines
+(it is not permitted for the argument to @code{\X} to contain newlines).
+The inclusion of
+newlines requires an extetension to the @sc{Unix} troff output format, and will
+confuse drivers that do not know about this extension.
+
+
+@c distribute these through the text
+@xref{Devices}
+
+@node Miscellany, Debugging, Postprocessor Access, Programming Tutorial
+@section Miscellany
+@cindex miscellany
+
+
+This section contains parts of troff which cannot (yet) be
+categorized elsewhere in this manual.
+
+@findex nm
+Line numbers can be printed in the left margin
+using the @code{nm} request.
+The first argument is the line number of the @emph{next} output line,
+this defaults to 1.
+The second argument indicates on which lines numbers will be printed,
+i.e. 5 means put line numbers on every 5 lines, this defaults to 1.
+The third argument is the space to be left between the number and
+your text, this defaults to 1.
+The fourth argument is the indentation of the line numbers.
+Without arguments, line numbers are turned off.
+
+@findex nn
+The @code{nn} request will temporarily turn off line numbering.
+The first argument is the number of lines not to be numbered,
+this defaults to 1. (does this disable incrementing or display?)
+
+@example
+... line numbering example ...
+@end example
+
+@findex mc
+margin characters can be automatically printed to the right of your
+text with the @code{mc} request.
+The first argument is the character to be printed and the second
+argument is the distance away from your text.
+With no arguments the margin characters are turned off.
+If this occurs before a break, no margin character will be printed.
+
+This is quite useful for indicating text that has changed, and, in
+fact, there are programs available for doing this (they are called
+@code{nrchbar} and @code{changebar} and can be found in any
+@samp{comp.sources.unix} archive.
+
+@example
+... margin char example ...
+@end example
+
+@findex lf
+@pindex soelim
+The @code{lf} primary reason for existence is to make debugging
+documents which are split into many files, which are then put
+together with @code{soelim} and other preprocessors.
+The first argument is the name of the file and the second argument is
+the input line number in that file.
+This way troff can produce error messages which are intelligible to
+the user.
+
+@example
+... example of soelim'ed doc ...
+@end example
+
+@node Debugging, Implementation Differences, Miscellany, Programming Tutorial
+@section Debugging
+@cindex debugging
+
+
+Troff is not easy to debug, but there are some useful features and
+strategies for debugging.
+
+@itemize @bullet{}
+@item
+@findex tm
+The @code{tm} request will send output to stderr, this is very useful for
+printing debugging output.
+@item
+When doing something involved it is useful to leave the debugging
+statements in the code and have them turned on by a command line
+flag.
+
+@example
+.if \n(DB .tm debugging output
+@end example
+
+Then you can activate these statements with:
+
+@example
+groff -rDB=1 file
+@end example
+
+@item
+@findex ab
+The @code{ab} request is similar to the @code{tm} request,
+except that it will cause groff to stop processing.
+With no argument it will print @samp{User Abort}.
+@item
+@findex ex
+The @code{ex} request will also cause groff to stop processing.
+@item
+If you know you are going to get many errors and no useful output,
+you can tell groff to suppress formatted output with the @samp{-z}
+flag.
+@item
+@findex pm
+The @code{pm} request will dump out the entire symbol table.
+@item
+@findex pnr
+The @code{pnr} request will print the names and contents of all
+currently defined number registers on stderr.
+@item
+@findex ptr
+The @code{ptr} request will
+print the names and positions of all traps (not including input line
+traps and diversion traps) on stderr. Empty slots in the page trap list
+are printed as well, because they can affect the priority of
+subsequently planted traps.
+@item
+@findex fl
+The @code{fl} request instructs groff to flush its output immediately.
+The intention is that this be used when using troff interactively.
+There is little other use for it.
+@item
+@findex backtrace
+The @code{backtrace} request will
+print a backtrace of the input stack on stderr.
+@item
+Groff has command line options for printing out more warnings
+(@samp{-w}) and for printing backtraces (@samp{-b}) when a warning or
+an error occurs. The most verbose level of warnings is @samp{-ww}.
+@item
+@findex warn
+@vindex .warn
+The @code{warn} request controls the level of warnings checked for.
+The one argument is the sum of the numbers associated with each
+warning that is to be enabled; all other warnings will be disabled.
+The number associated with each warning is listed below.
+For example, @code{.warn 0} will disable all warnings, and
+@code{.warn 1} will disable
+all warnings except that about missing characters. If an argument
+is not given, all warnings will be enabled.
+The number register @code{.warn} contains the current warning level.
+@end itemize
+
+@subsection Warnings
+@cindex warnings
+
+The warnings that can be given by troff are divided into the
+following categories. The name associated with each warning is used
+by the @samp{-w} and @samp{-W} options; the number is used by the
+@code{warn} request, and by the @code{.warn} register.
+
+@table @samp
+@item char
+@itemx 1
+Non-existent characters. This is enabled by default.
+@item number
+@itemx 2
+Invalid numeric expressions. This is enabled by default.
+@item break
+@itemx 4
+In fill mode, lines which could not be broken so that
+their length was less than the line length. This is
+enabled by default.
+@item delim
+@itemx 8
+Missing or mismatched closing delimiters.
+@item el
+@itemx 16
+Use of the @code{el} request with no matching @code{ie} request.
+@xref{if-else}, for more information.
+@item scale
+@itemx 32
+Meaningless scaling indicators.
+@item range
+@itemx 64
+Out of range arguments.
+@item syntax
+@itemx 128
+Dubious syntax in numeric expressions.
+@item di
+@itemx 256
+@findex di
+@findex da
+Use of @code{di} or @code{da} without an argument when there is no
+current diversion.
+@item mac
+@itemx 512
+Use of undefined strings, macros and diversions.
+When an undefined string, macro or diversion is used,
+that string is automatically defined as empty. So,
+in most cases, at most one warning will be given for
+each name.
+@item reg
+@itemx 1024
+Use of undefined number registers. When an undefined
+number register is used, that register is
+automatically defined to have a value of 0. a
+definition is automatically made with a value of 0.
+So, in most cases, at most one warning will be given
+for use of a particular name.
+@item tab
+@itemx 2048
+Use of a tab character where a number was expected.
+@item right-brace
+@itemx 4096
+@findex \@}
+Use of @code{\@}} where a number was expected.
+@item missing
+@itemx 8192
+Requests that are missing non-optional arguments.
+@item input
+@itemx 16384
+Illegal input characters.
+@item escape
+@itemx 32768
+Unrecognized escape sequences. When an unrecognized
+escape sequence is encountered, the escape character
+is ignored.
+@item space
+@itemx 65536
+Missing space between a request or macro and its
+argument. This warning will be given when an
+undefined name longer than two characters is
+encountered, and the first two characters of the name
+make a defined name. The request or macro will not
+be invoked. When this warning is given, no macro is
+automatically defined. This is enabled by default.
+This warning will never occur in compatibility mode.
+@item font
+@itemx 131072
+Non-existent fonts. This is enabled by default.
+@item all
+All warnings except @samp{di}, @samp{mac} and @samp{reg}. It is
+intended that this covers
+all warnings that are useful with traditional macro packages.
+@item w
+All warnings.
+@end table
+
+
+@node Implementation Differences, Summary, Debugging, Programming Tutorial
+@section Implementation Differences
+@cindex implementation differences
+@cindex differences in implementation
+
+
+GNU troff has a number of features which cause incompatibilites with
+documents written with old versions of troff.
+
+Long names cause some incompatibilities. @sc{Unix} troff will interpret
+
+@example
+.dsabcd
+@end example
+
+@findex \*
+@findex \n
+@findex cp
+@vindex .C
+as defining a string @samp{ab} with contents @samp{cd}.
+Normally, GNU troff will interpret this as a call of a macro named
+@code{dsabcd}. Also @sc{Unix} troff will interpret @code{\*[} or
+@code{\n[} as references to a string or number register called
+@samp{[}. In GNU troff, however, this will normally be interpreted as the
+start of a long name. In compatibility mode GNU troff will interpret
+these things in the traditional way. In compatibility mode, however,
+long names are not recognised. Compatibility mode can be turned on with
+the @samp{-C} command line option, and turned on or off with the
+@code{cp} request.
+The number register @code{.C} is 1 if compatibility mode is on, 0 otherwise.
+
+@findex \A
+GNU troff does not allow the use of the escape sequences
+@samp{\| \^ \& \@} \@{ \@key{SP} \' \` \- \_ \! \% \c} in names of
+strings, macros,
+diversions, number registers, fonts or environments; @sc{Unix} troff does.
+The @code{\A} escape sequence may be helpful in avoiding use of these escape
+sequences in names.
+
+@cindex fractional point sizes
+@cindex point sizes, fractional
+@findex ps
+Fractional pointsizes cause one noteworthy incompatibility. In @sc{Unix}
+troff the @code{ps} request ignores scale indicators and so
+
+@example
+.ps 10u
+@end example
+
+will set the pointsize to 10 points, whereas in GNU troff it will set
+the pointsize to 10 scaled points.
+@xref{Fractional Type Sizes}, for more information.
+
+@findex bd
+@findex cs
+@findex tkf
+@findex tr
+@findex fp
+In GNU troff there is a fundamental difference between unformatted,
+input characters, and formatted, output characters. Everything that
+affects how an output character will be output is stored with the
+character; once an output character has been constructed it is
+unaffected by any subsequent requests that are executed, including
+@code{bd}, @code{cs}, @code{tkf}, @code{tr}, or @code{fp}
+requests. Normally output characters are constructed
+from input characters at the moment immediately before the character is
+added to the current output line. Macros, diversions and strings are
+all, in fact, the same type of object; they contain lists of input
+characters and output characters in any combination. An output
+character does not behave like an input character for the purposes of
+macro processing; it does not inherit any of the special properties that
+the input character from which it was constructed might have had. For
+example,
+
+@example
+.di x
+\\\\
+.br
+.di
+.x
+@end example
+
+@findex \e
+@findex \!
+@findex \?
+will print @samp{\\} in GNU troff; each pair of input backslashes is
+turned into one
+output backslash and the resulting output backslashes are not
+interpreted as escape
+characters when they are reread. @sc{Unix} troff would interpret them as
+escape characters when they were reread and would end up printing one
+@samp{\}.
+The correct way to obtain a printable backslash is to use the
+@code{\e} escape
+sequence: this will always print a single instance of the current escape
+character, regardless of whether or not it is used in a diversion; it
+will also work in both GNU troff and @sc{Unix} troff. If you wish for some
+reason to store in a diversion an escape sequence that will be
+interpreted when the diversion is reread, you can either use the
+traditional @code{\!} transparent output facility, or, if this is unsuitable,
+the new @code{\?} escape sequence. @xref{Diversions}, for more information.
+
+
+@node Summary, , Implementation Differences, Programming Tutorial
+@section Summary
+@cindex summary
+
+
+@node geqn, gtbl, Programming Tutorial, Top
+@chapter @code{geqn}
+@cindex @code{eqn}
+@cindex @code{geqn}
+
+
+@menu
+* Invoking geqn::
+@end menu
+
+@node Invoking geqn, , geqn, geqn
+@section Invoking @code{geqn}
+@cindex invoking @code{geqn}
+@cindex @code{geqn}, invoking
+
+
+
+@node gtbl, gpic, geqn, Top
+@chapter @code{gtbl}
+@cindex @code{tbl}
+@cindex @code{gtbl}
+
+
+@menu
+* Invoking gtbl::
+@end menu
+
+@node Invoking gtbl, , gtbl, gtbl
+@section Invoking @code{gtbl}
+@cindex invoking @code{gtbl}
+@cindex @code{gtbl}, invoking
+
+
+@node gpic, grap, gtbl, Top
+@chapter @code{gpic}
+@cindex @code{pic}
+@cindex @code{gpic}
+
+
+@menu
+* Invoking gpic::
+@end menu
+
+@node Invoking gpic, , gpic, gpic
+@section Invoking @code{gpic}
+@cindex invoking @code{gpic}
+@cindex @code{gpic}, invoking
+
+
+
+@node grap, grefer, gpic, Top
+@chapter @code{grap}
+@cindex @code{grap}
+
+
+
+@node grefer, gsoelim, grap, Top
+@chapter @code{grefer}
+@cindex @code{refer}
+@cindex @code{grefer}
+
+
+@menu
+* Invoking grefer::
+@end menu
+
+@node Invoking grefer, , grefer, grefer
+@section Invoking @code{grefer}
+@cindex invoking @code{grefer}
+@cindex @code{grefer}, invoking
+
+
+
+@node gsoelim, Devices, grefer, Top
+@chapter @code{gsoelim}
+@cindex @code{soelim}
+@cindex @code{gsoelim}
+
+
+@menu
+* Invoking gsoelim::
+@end menu
+
+@node Invoking gsoelim, , gsoelim, gsoelim
+@section Invoking @code{gsoelim}
+@cindex invoking @code{gsoelim}
+@cindex @code{gsoelim}, invoking
+
+
+
+@node Devices, File formats, gsoelim, Top
+@chapter Devices
+@cindex devices
+
+
+
+@menu
+* Special Characters::
+* grotty::
+* grops::
+* grodvi::
+* grolj4::
+* grohtml::
+* gxditview::
+@end menu
+
+@node Special Characters, grotty, Devices, Devices
+@section Special Characters
+@cindex special characters
+@cindex characters, special
+
+
+@c distribute these through the text
+@xref{Font Files}
+
+@node grotty, grops, Special Characters, Devices
+@section @code{grotty}
+@cindex @code{grotty}
+
+
+
+@menu
+* Invoking grotty::
+@end menu
+
+@node Invoking grotty, , grotty, grotty
+@subsection Invoking @code{grotty}
+@cindex invoking @code{grotty}
+@cindex @code{grotty}, invoking
+
+
+
+@node grops, grodvi, grotty, Devices
+@section @code{grops}
+@cindex @code{grops}
+
+
+
+@menu
+* Invoking grops::
+* Embedding PostScript::
+@end menu
+
+@node Invoking grops, Embedding PostScript, grops, grops
+@subsection Invoking @code{grops}
+@cindex invoking @code{grops}
+@cindex @code{grops}, invoking
+
+
+
+@node Embedding PostScript, , Invoking grops, grops
+@subsection Embedding PostScript
+@cindex embedding postscript
+@cindex postscript, embedding
+
+
+
+@node grodvi, grolj4, grops, Devices
+@section @code{grodvi}
+@cindex @code{grodvi}
+
+
+
+@menu
+* Invoking grodvi::
+@end menu
+
+@node Invoking grodvi, , grodvi, grodvi
+@subsection Invoking @code{grodvi}
+@cindex invoking @code{grodvi}
+@cindex @code{grodvi}, invoking
+
+
+
+@node grolj4, grohtml, grodvi, Devices
+@section @code{grolj4}
+@cindex @code{grolj4}
+
+
+
+@menu
+* Invoking grolj4::
+@end menu
+
+@node Invoking grolj4, , grolj4, grolj4
+@subsection Invoking @code{grolj4}
+@cindex invoking @code{grolj4}
+@cindex @code{grolj4}, invoking
+
+
+
+@node grohtml, gxditview, grolj4, Devices
+@section @code{grohtml}
+@cindex @code{grohtml}
+
+
+
+@menu
+* Invoking grohtml::
+@end menu
+
+@node Invoking grohtml, , grohtml, grohtml
+@subsection Invoking @code{grohtml}
+@cindex invoking @code{grohtml}
+@cindex @code{grohtml}, invoking
+
+
+
+@node gxditview, , grohtml, Devices
+@section @code{gxditview}
+@cindex @code{gxditview}
+
+
+
+@menu
+* Invoking gxditview::
+@end menu
+
+@node Invoking gxditview, , gxditview, gxditview
+@subsection Invoking @code{gxditview}
+@cindex invoking @code{gxditview}
+@cindex @code{gxditview}, invoking
+
+
+
+@node File formats, Installation, Devices, Top
+@chapter File formats
+@cindex file formats
+@cindex formats, file
+
+
+
+@menu
+* gtroff Output::
+* Font Files::
+@end menu
+
+@node gtroff Output, Font Files, File formats, File formats
+@section @code{gtroff} Output
+@cindex @code{gtroff} output
+@cindex output, @code{gtroff}
+
+
+This section describes the format output by GNU troff. The output
+format used by GNU troff is very similar to that used by @sc{Unix}
+device-independent troff.
+
+The output format is ascii based, as opposed to a binary format (like
+@TeX{} dvi).
+The output format is 8 bit clean, thus single characters can have the
+eighth bit set, as can the names of fonts and special characters.
+
+The output format consists of single command characters with attached
+parameters which are separated from subsequent text by whitespace, or
+a newline.
+
+The names of characters and fonts an be of arbitrary length; drivers
+should not assume that they will be only two characters long (as
+device-independent troff did).
+
+When a character is to be printed, that character will always be in the
+current font.
+Unlike device-independent troff, it is not necessary for
+drivers to search special fonts to find a character.
+
+@table @code
+@item H@var{n}
+@item V@var{n}
+@item h@var{n}
+@item v@var{n}
+@item c@var{n}
+@item C@var{n}
+@item @var{nn}@var{c}
+@item t@var{xxx}
+@var{xxx} is any sequence of characters terminated by a space or a
+newline; the first character should be printed at the current
+position, the the current horizontal position should be increased by
+the width of the first character, and so on for each character.
+The width of the character is that given in the font file,
+appropriately scaled for the current point size,
+and rounded so that it is a multiple of the horizontal resolution.
+Special characters cannot be printed using this command.
+
+This command is only allowed if the @samp{tcommand} line is present
+in the @file{DESC} file.
+@item u@var{n} @var{xxx}
+@pindex DESC
+This is same as the @code{t} command except that after printing each
+character, the current horizontal position is increased by the sum of
+the width of that character and @code{n}.
+
+This command is only allowed if the @samp{tcommand} line is present
+in the @file{DESC} file.
+@item n@var{a}@var{b}
+@item p@var{n}
+@item s@var{n}
+The argument to the s command is in scaled points (units of points/n,
+where n is the argument to the sizescale command in the DESC file.)
+@item f@var{n}
+@item x @dots{} \n
+Device control.
+@item D@var{c} @var{x}@dots{}\n
+@end table
+
+@subsection Device Control
+
+The @code{x} command is normally followed by a letter or word
+indicating the function to perform, followed by white space separated
+arguments.
+
+The first argument can be abreviated to the first letter.
+
+@table @code
+@item x init
+@item x T
+@item x res @var{n} @var{h} @var{v}
+@item x H
+The argument to the x Height command is also in scaled points.
+@end table
+
+The first three output commands are guaranteed to be:
+
+@example
+x T device
+x res n h v
+x init
+@end example
+
+For example, the input @samp{crunchy \fH\s+2frog\s0\fP!?} will produce:
+
+@example
+... sample output here ...
+@end example
+
+@subsection Drawing Functions
+
+The D drawing command has been extended. These extensions will only be
+used by GNU pic if the -x option is given.
+
+@table @code
+...
+@item Df n\n
+Set the shade of gray to be used for filling solid objects to n; n must
+be an integer between 0 and 1000, where 0 corresponds solid white and
+1000 to solid black, and values in between correspond to intermediate
+shades of gray. This applies only to solid circles, solid ellipses and
+solid polygons. By default, a level of 1000 will be used. Whatever
+color a solid object has, it should completely obscure everything
+beneath it. A value greater than 1000 or less than 0 can also be used:
+this means fill with the shade of gray that is currently being used for
+lines and text. Normally this will be black, but some drivers may
+provide a way of changing this.
+@item DC d\n
+Draw a solid circle with a diameter of d with the leftmost point at the
+current position.
+@item DE dx dy\n
+Draw a solid ellipse with a horizontal diameter of dx and a vertical
+diameter of dy with the leftmost point at the current position.
+@item Dp $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub
+n$\n
+Draw a polygon with, for $i = 1 ,..., n+1$, the i-th vertex at the
+current position $+ sum from j=1 to i-1 ( dx sub j , dy sub j )$. At
+the moment, GNU pic only uses this command to generate triangles and
+rectangles.
+@item DP $dx sub 1$ $dy sub 1$ $dx sub 2$ $dy sub 2$ $...$ $dx sub n$ $dy sub
+n$\n
+Like Dp but draw a solid rather than outlined polygon.
+@item Dt n\n
+Set the current line thickness to n machine units. Traditionally @sc{Unix}
+troff drivers use a line thickness proportional to the current point
+size; drivers should continue to do this if no Dt command has been
+given, or if a Dt command has been given with a negative value of n. A
+zero value of n selects the smallest available line thickness.
+@end table
+
+A difficulty arises in how the current position should be changed after
+the execution of these commands. This is not of great importance since
+the code generated by GNU pic does not depend on this. Given a drawing
+command of the form
+
+\D'c $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$'
+
+where c is not one of c, e, l, a or ~, @sc{Unix} troff will treat each of the
+$x sub i$ as a horizontal quantity, and each of the $y sub i$ as a
+vertical quantity and will assume that the width of the drawn object is
+$sum from i=1 to n x sub i$, and that the height is $sum from i=1 to n y
+sub i$. (The assumption about the height can be seen by examining the
+st and sb registers after using such a D command in a \w escape
+sequence.) This rule also holds for all the original drawing commands
+with the exception of De. For the sake of compatibility GNU troff also
+follows this rule, even though it produces an ugly result in the case of
+the Df, Dt, and, to a lesser extent, DE commands. Thus after executing
+a D command of the form
+
+Dc $x sub 1$ $y sub 1$ $x sub 2$ $y sub 2$ $...$ $x sub n$ $y sub n$\n
+
+the current position should be increased by $( sum from i=1 to n x sub i
+, sum from i=1 to n y sub i )$.
+
+@subsection Line Continuation
+
+There is a continuation convention which permits the argument to the x X
+command to contain newlines: when outputting the argument to the x X
+command, GNU troff will follow each newline in the argument with a +
+character (as usual, it will terminate the entire argument with a
+newline); thus if the line after the line containing the x X command
+starts with +, then the newline ending the line containing the x X
+command should be treated as part of the argument to the x X command,
+the + should be ignored, and the part of the line following the + should
+be treated like the part of the line following the x X command.
+
+
+
+
+@node Font Files, , gtroff Output, File formats
+@section Font Files
+@cindex font files
+@cindex files, font
+
+
+The groff font format is roughly a superset of the ditroff font
+format. Unlike the ditroff font format, there is no associated binary
+format. The font files for device name are stored in a directory
+@file{dev@var{name}}. There are two types of file: a device
+description file called @file{DESC} and for each font @samp{F} a font
+file called @file{F}. These are text files; there is no associated
+binary format.
+
+@subsection @file{DESC} file format
+@pindex DESC
+
+The @file{DESC} file can contain the following types of line:
+
+@table @code
+@item res @var{n}
+There are @var{n} machine units per inch.
+@item hor @var{n}
+The horizontal resolution is @var{n} machine units.
+@item vert @var{n}
+The vertical resolution is @var{n} machine units.
+@item sizescale @var{n}
+The scale factor for pointsizes. By default this has a value of 1. One
+scaled point is equal to one point/@var{n}. The arguments to the
+@code{unitwidth} and @code{sizes} commands are given in scaled points.
+@xref{Fractional Type Sizes}, for more information.
+@item unitwidth @var{n}
+Quantities in the font files are given in machine units for fonts whose
+point size is @var{n} scaled points.
+@item tcommand
+This means that the postprocessor can handle the @code{t} and
+@code{u} output commands.
+@item sizes @var{s1} @var{s2}@dots{}@var{sn} 0
+This means that the device has fonts at @var{s1}, @var{s2},
+@dots{}@var{sn} scaled points. The list of sizes must be terminated
+by a 0. Each @var{si} can also be a range of
+sizes @var{m}-@var{n}. The list can extend over more than one line.
+@item styles @var{S1 S2@dots{}Sm}
+The first @var{m} font positions will be associated with styles
+@var{S1}@dots{}@var{Sm}.
+@item fonts @var{n} @var{F1 F2 F3@dots{}Fn}
+Fonts @var{F1@dots{}Fn} will be mounted in the font positions
+@var{m}+1, @dots{}, @var{m}+@var{n} where @var{m}
+is the number of styles. This command may extend over more than one
+line. A font name of 0 will cause no font to be mounted on the
+corresponding font position.
+@item family @var{fam}
+The default font family is @var{fam}.
+@item charset
+This line and everything following in the file are ignored. It is
+allowed for the sake of backwards compatibility.
+@end table
+
+The @code{res}, @code{unitwidth}, @code{fonts} and @code{sizes} lines
+are compulsory. Other commands are ignored by troff but may be used
+by postprocessors to store arbitrary information about the device in
+the @file{DESC} file.
+
+
+@subsection Font file format
+
+A font file has two sections. The first section is a sequence of lines
+each containing a sequence of blank delimited words; the first word in
+the line is a key, and subsequent words give a value for that key.
+
+@table @code
+@item name @var{F}
+The name of the font is @var{F}.
+@item spacewidth @var{n}
+The normal width of a space is @var{n}.
+@item slant @var{n}
+The characters of the font have a slant of @var{n} degrees.
+(Positive means forward.)
+@item ligatures @var{lig1} @var{lig2}@dots{}@var{lign} [0]
+Characters @var{lig1}, @var{lig2}, @dots{}, @var{lign} are ligatures;
+possible ligatures are ff, fi, fl and ffl. For backwards
+compatibiliy, the list of ligatures may be terminated with a 0. The
+list of ligatures may not extend over more than one line.
+@item special
+The font is special; this means that when a character is requested that
+is not present in the current font, it will be searched for in any
+special fonts that are mounted.
+@end table
+
+Other commands are ignored by troff but may be used by postprocessors to
+store arbitrary information about the font in the font file.
+
+The first section can contain comments which start with the # character
+and extend to the end of a line.
+
+The second section contains one or two subsections. It must contain a
+@code{charset} subsection and it may also contain a @code{kernpairs}
+subsection. These subsections can appear in any order. Each
+subsection starts with a word on a line by itself.
+
+The word @code{charset} starts the @code{charset} subsection. The
+@code{charset} line is followed by a sequence of lines. Each line
+gives information for one character. A line comprises a number of
+fields separated by blanks or tabs. The format is
+
+@display
+@var{name} @var{metrics} @var{type} @var{code} @var{comment}
+@end display
+
+@var{name} identifies the character: if @var{name} is a single
+character @var{c} then it corresponds to the groff input character
+@var{c}; if it is of the form @samp{\@var{c}} where @var{c} is a
+single character, then it corresponds to the groff input character
+@samp{\@var{c}}; otherwise it corresponds to the groff input character
+@samp{\[@var{name}]} (if it is exactly two characters @var{xx} it can
+be entered as @samp{\(@var{xx}}.) Groff supports eight bit characters;
+however some utilities has difficulties with eight bit characters.
+For this reason, there is a convention that the @var{name}
+@samp{char@var{n}} is equivalent to the single character whose code is
+@var{n}. For example, @samp{char163} would be equivalent to the
+character with @var{code} 163 which is the pounds sterling sign in ISO
+Latin-1 character set. The name @samp{---} is special and indicates
+that the character is unnamed; such characters can only be used by
+means of the @code{\N} escape sequence in troff.
+
+The @var{type} field gives the character type:
+
+@table @code
+@item 1
+means the character has an descender, for example, p;
+@item 2
+means the character has an ascender, for example, b;
+@item 3
+means the character has both an ascender and a descender, for example,
+@samp{(}.
+@end table
+
+The @var{code} field gives the code which the postprocessor uses to
+print the character. The character can also be input to groff using
+this code by means of the @code{\N} escape sequence. The code can be any
+integer. If it starts with a 0 it will be interpreted as octal; if it
+starts with 0x or 0X it will be intepreted as hexdecimal.
+
+Anything on the line after the @var{code} field will be ignored.
+
+The @var{metrics} field has the form:
+
+@smallexample
+@var{width[,height[,depth[,italic_correction[,left_italic_correction[,subscript_correction]]]]]}
+@end smallexample
+
+There must not be any spaces between these subfields. Missing
+subfields are assumed to be 0. The subfields are all decimal
+integers. Since there is no associated binary format, these values
+are not required to fit into a variable of type @samp{char} as they
+are in ditroff. The @var{width} subfields gives the width of the
+character. The @var{height} subfield gives the height of the
+character (upwards is positive); if a character does not extend above
+the baseline, it should be given a zero height, rather than a negative
+height. The @var{depth} subfield gives the depth of the character,
+that is, the distance below the lowest point below the baseline to
+which the character extends (downwards is positive); if a character
+does not extend below above the baseline, it should be given a zero
+depth, rather than a negative depth. The @var{italic_correction}
+subfield gives the amount of space that should be added after the
+character when it is immediately to be followed by a character from a
+roman font. The @var{left_italic_correction} subfield gives the
+amount of space that should be added before the character when it is
+immediately to be preceded by a character from a roman font. The
+@var{subscript_correction} gives the amount of space that should be
+added after a character before adding a subscript. This should be less
+than the italic correction.
+
+A line in the @code{charset} section can also have the format
+
+@example
+@var{name} "
+@end example
+
+This indicates that @var{name} is just another name for the character
+mentioned in the preceding line.
+
+The word @code{kernpairs} starts the kernpairs section. This contains a
+sequence of lines of the form:
+
+@display
+@var{c1 c2 n}
+@end display
+
+This means that when character @var{c1} appears next to character
+@var{c2} the space between them should be increased by @var{n}. Most
+entries in kernpairs section will have a negative value for @var{n}.
+
+
+
+@node Installation, Request Index, File formats, Top
+@chapter Installation
+@cindex installation
+
+
+
+@node Request Index, Register Index, Installation, Top
+@chapter Request Index
+
+@printindex fn
+
+
+@node Register Index, String Index, Request Index, Top
+@chapter Register Index
+
+@printindex vr
+
+
+@node String Index, Macro Index, Register Index, Top
+@chapter String Index
+
+
+
+@node Macro Index, Program Index, String Index, Top
+@chapter Macro Index
+
+
+
+@node Program Index, Concept Index, Macro Index, Top
+@chapter Program Index
+
+@printindex pg
+
+
+
+@node Concept Index, , Program Index, Top
+@chapter Concept Index
+
+@printindex cp
+
+
+
+@summarycontents
+@contents
+@bye
diff --git a/gnu/usr.bin/groff/grohtml/ChangeLog b/gnu/usr.bin/groff/grohtml/ChangeLog
new file mode 100644
index 00000000000..e7c1265769e
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/ChangeLog
@@ -0,0 +1,104 @@
+1999-12-21 Werner LEMBERG <wl@gnu.org>
+
+ * grohtml.man: Fixed copyright year.
+
+1999-12-15 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Some other fixes.
+
+1999-12-13 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc (main): Added new option `-x' to help debugging tables.
+
+1999-12-11 Gaius Mulley <gaius@glam.ac.uk>
+
+ * html.cc: Fixed image position bugs. However, three major bugs
+ remain: Firstly, grohtml sometimes miscalculates the end of an
+ html table resulting in text which appears twice. Secondly,
+ equation numbers are not handled correctly. Thirdly, equation
+ macros and pic macros can confuse grohtml; this can be seen by
+ nested `graphic-start's -- I believe the best method to solve this
+ is to detect .EQ, .EN, .TS, .TE, .PS, .PE sequences in troff and
+ add the graphic-start special character at this point.
+
+ * grohtml.man: Minor fixes.
+
+1999-11-29 Gaius Mulley <gaius@glam.ac.uk>
+
+ * design.ms: More updates; added some basic introductional
+ information.
+
+ * html.cc: Fixed more bugs mainly in the table handling code.
+ Making the code terminate a table at the correct position.
+ Indented .IPs appear to work now. Region ends also correctly
+ terminate tables.
+
+1999-11-16 Gaius Mulley <gaius@glam.ac.uk>
+
+ * design.ms, grohtml.man: Updated.
+
+ * html.cc, ordered_list.h: Fixed many bugs in the table handling
+ code. Reverted the -t switch so that table handling code is used
+ by default and users must turn it off with -t.
+
+ Manual page generation using `groff -Thtml -man' is much better
+ due in large part to the table code and minor alterations in
+ tmac.an.
+
+1999-10-30 Gaius Mulley <gaius@glam.ac.uk>
+
+ * implemented auto formatting and introduced html table
+ code. Fixed several text handling bugs and grohtml will
+ detect centered lines - an offshoot of the html table code.
+
+ * reverted meaning of grohtml's `-a' switch: using -a means that
+ output will be preformatted.
+
+1999-10-05 Gaius Mulley <gaius@glam.ac.uk>
+
+ * Introduced command line options -r to determine the resolution
+ of generated images, -I to determine the format of images
+ generated.
+
+ * Fixed many bugs to do with superscripts, subscripts,
+ indentation, font changes, and extraneous spaces.
+
+ * Fixed bug in determining the range of polygons and splines.
+
+ * Updated the manual page to reflect the new options.
+
+ * The default image type is png format, however this will only
+ work if you have a gs with a png output device. If you don't have
+ a gs with this ability you can either reconfigure html to generate
+ gif images by default (alter a #define in html.cc). Or
+ alternatively you can use the -Igif option.
+
+1999-09-27 Werner LEMBERG <wl@gnu.org>
+
+ * html.cc (move_horizontal): Fonts have changed one character too
+ late.
+
+1999-09-26 Werner LEMBERG <wl@gnu.org>
+
+ * grohtml.man: Minor cosmetic fixes.
+
+1999-09-25 Gaius Mulley <gaius@glam.ac.uk>
+
+ * grohtml.man, html.cc: Rewrite of the html text component. Basic
+ font faces supported together with font types. Superscript and
+ subscript have also been implemented. Temporarily removed the
+ -P-a switch on grohtml as it is not working (never worked). This
+ is the next `to do'. Added a simple macro tmac.arkup which
+ contains simple html features. This macro needs further work.
+ Arc, spline, polygon fill have all been added and arc max/min xy
+ limits are calculated, the same needs to be done for spline. Many
+ bugs have been fixed regarding basic html text.
+
+ * design.ms: New file describing how html.cc works.
+
+Aug 1999
+
+ Initial release, very basic html text generated, quite ugly text
+ is generated according to many reports :-) Equations, tables,
+ pictures generate gif files via gs and ppmquant, ppmtogif, grops.
+
diff --git a/gnu/usr.bin/groff/grohtml/Makefile.dep b/gnu/usr.bin/groff/grohtml/Makefile.dep
new file mode 100644
index 00000000000..782d72116ee
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/Makefile.dep
@@ -0,0 +1,3 @@
+html.o: html.cc ordered_list.h ../include/driver.h ../include/errarg.h \
+ ../include/error.h ../include/font.h ../include/printer.h \
+ ../include/lib.h
diff --git a/gnu/usr.bin/groff/grohtml/Makefile.sub b/gnu/usr.bin/groff/grohtml/Makefile.sub
new file mode 100644
index 00000000000..3faa1e30125
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/Makefile.sub
@@ -0,0 +1,6 @@
+PROG=grohtml
+MAN1=grohtml.n
+XLIBS=$(LIBDRIVER) $(LIBGROFF)
+MLIB=$(LIBM)
+OBJS=html.o
+CCSRCS=html.cc
diff --git a/gnu/usr.bin/groff/grohtml/design.ms b/gnu/usr.bin/groff/grohtml/design.ms
new file mode 100644
index 00000000000..e62e2233096
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/design.ms
@@ -0,0 +1,156 @@
+.nr PS 12
+.nr VS 14
+.LP
+.TL
+Design of grohtml
+.sp 1i
+.SH
+What is grohtml
+.LP
+Grohtml is a back end for groff which generates html.
+The aim of grohtml is to produce respectible html given
+fairly typical groff input.
+.SH
+Limitations of grohtml
+.LP
+Although basic text can be translated
+in a straightforward fashion there are some areas where grohtml
+has to try and guess text relationship. In particular whenever
+grohtml encounters text tables and indented paragraphs or
+two column mode it will try and utilize the html table construct
+to preserve columns. Grohtml also attempts to work out which
+lines should be automatically formatted by the browser.
+Ultimately in trying to make reasonable guesses most of the time
+it will make mistakes occasionally.
+.PP
+Tbl, pic, eqn's are also generated using images which may be
+considered a limitation.
+.SH
+Overview of html.cc
+.LP
+This file briefly provides an overview of how html.cc operates.
+The html device driver works as follows:
+.IP (i) .5i
+firstly it creates a linked list of all words on a page.
+.IP (ii) .5i
+it runs through the page and finds the left most margin. Later
+on when generating the page it removes the margin.
+.IP (iii) .5i
+scans a page and builds two kinds of regions ascii text and graphical.
+The graphical regions consist of tbl's, eqn's, pic's
+(basically anything that cannot be textually displayed).
+It will scan through a page to find lines (such as footer etc)
+and places these into tiny graphical regions. Certain fonts
+also are treated as a graphical region - as html has no easy
+equivalent. For example Greek math symbols.
+.LP
+Finally all graphical regions are translated into png files and
+all text regions into html text.
+.PP
+To give grohtml a sporting chance of accuratly deciding which
+is a graphical region and which is text, the front end programs
+tbl, eqn, pic have all been tweeked to encapsulate pictures, tables
+and equations with the following lines:
+.sp
+.nf
+\f[CR]\&.if '\\*(.T'html' \\X(graphic-start(\c
+
+\&.if '\\*(.T'html' \\X(graphic-end(\c
+\fP
+.fi
+.sp
+these appear to grohtml as:
+.sp
+.nf
+\f[CR]\&x X graphic-start
+
+\&...
+
+\&x X graphic-end\fP
+.fi
+.sp
+.LP
+In addition to graphic-start and graphic-end there are two
+other "special characters" which are used.
+.sp
+\f[CR]\&x X index:N\fP
+.sp
+where N is a number. The purpose of this sequence is to stop
+devhtml from automatically producing links to headings which
+have a header level >N.
+The line:
+.sp
+\f[CR]\&x X html:STRING\fR
+.sp
+.LP
+allows a STRING to be passed through to the output file with
+no processing whatsoever. Ie it allows users to include html
+commands, via macro, such as:
+.sp
+\f[CR]\&.URL "Latest Emacs" "ftp://somewonderful.gnu.software"\fP
+.sp
+.LP
+Where the URL macro bundles the info into STRING above.
+For more info consult: \f[CR]tmac/tmac.arkup\fP.
+.PP
+While scanning through a page the html device copies headings and titles
+into a list of links which are later written to the beginning
+of the html document.
+.SH
+Table handling code
+.LP
+Provided that the -t option is not present when grohtml is run the grohtml
+driver will attempt to find textual tables and generate html tables.
+This allows .RS and .RE commands to operate with auto formatting. It also
+should grohtml to process .2C correctly. However, the table handling code
+has to examine the troff output and \fIguess\fR when a table starts and
+finishes. It is well to know the limitations of this approach as it
+sometimes makes the wrong decision.
+.LP
+Here are some of the rules that grohtml uses for terminating a html table:
+.LP
+.IP "(i)" .5i
+A table will be terminated when grohtml finds line which is all in bold
+font (it believes that this is a header which is outside of a table).
+This might be considered incorrect behaviour especially if you use .2C
+which generates a heading on the left column when the corresponding
+right row is blank.
+.IP "(ii)" .5i
+A table is terminated when grohtml sees that the complete line is
+has been spanned by words. Ie no gaps exist.
+.IP "(nb)" .5i
+the documentation about these rules is particularly incomplete and needs finishing
+when time prevails.
+.SH
+To do
+.LP
+.IP (i) .5i
+finish working out the max and min x, y, extents for splines.
+.IP (ii) .5i
+check and test thoroughly all the character descriptions in devhtml
+(originally taken from devX100)
+.IP (iii) .5i
+improve tmac.arkup
+.IP (vi) .5i
+also improve documentation.
+.IP (v) .5i
+fix the bugs which are exposed by Eric Raymonds pic guide,
+\fBMaking Pictures With GNU PIC\fR. It appears that grohtml becomes confused
+about which sections of the document are text and which sections need
+to be rendered as an image.
+.IP (vi) .5i
+it would be nice to modularise the source. A natural division might be
+to extract the table handling code from html.cc into table.cc.
+The table.cc could be expanded to recognise output from tbl and try
+and generate html tables with lines/rules/boxes. The code as it stands
+should cope with very simple plain text tables. But of course at present
+it does not get a chance to do this because the output of gtbl is
+bracketed by \fCgraphic-start\fR and \fCgraphic-end\fR.
+.IP (vii) .5i
+introduce anti aliasing for the images as mentioned by Werner.
+.SH
+Dependencies
+.LP
+Grohtml is dependent upon grops, gs which are invoked to
+generate all png files. Png files are generated whenever a table, picture,
+equation or line is encountered.
diff --git a/gnu/usr.bin/groff/grohtml/grohtml.man b/gnu/usr.bin/groff/grohtml/grohtml.man
new file mode 100644
index 00000000000..63b05edd358
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/grohtml.man
@@ -0,0 +1,173 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of this
+manual provided the copyright notice and this permission notice are
+preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.el .TP "\\$1"
+..
+.TH GROHTML @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+grohtml \- html driver for groff
+.SH SYNOPSIS
+.B grohtml
+[
+.B \-atvdgm?
+] [
+.BI \-F dir
+] [
+.BI \-I imagetype
+] [
+.BI \-r resolution
+] [
+.IR files \|.\|.\|.
+]
+.SH DESCRIPTION
+.B grohtml
+translates the output of GNU
+.B troff
+to html.
+Normally
+.B grohtml
+should be invoked by using the groff command with a
+.B \-Thtml
+option.
+If no files are given,
+.B grohtml
+will read the standard input.
+A filename of
+.B \-
+will also cause
+.B grohtml
+to read the standard input.
+Html output is written to the standard output.
+When
+.B grohtml
+is run by
+.B groff
+options can be passed to
+.B grohtml
+using the
+.B groff
+.B \-P
+option.
+.SH OPTIONS
+.TP
+.B \-a
+force
+.B grohtml
+to generate html line breaks in the same position as troff dictates.
+Without this option
+.B grohtml
+generates text in paragraphs which is formatted by the html browser.
+.TP
+.B \-d
+turn on internal debugging.
+.TP
+.B \-g
+tell
+.B grohtml
+not to try and guess titles and headings.
+By using this flag together with the -m and -a flag
+.B grohtml
+will treat the html browser as a printer, not as a formatter.
+.TP
+.B \-m
+leave margins alone.
+.B grohtml
+will not remove left margins.
+.TP
+.B \-t
+forbids
+.B grohtml
+from generating html tables when implementing indentation and tabular text.
+.B grohtml
+can implement .IP by tables or html indents.
+However if .2C is used it can only be sensibly converted to html using a
+table structure.
+As a few known bugs still exist with the html table code this option is
+present to supress execution of this development code.
+The default in
+.B grohtml
+is that html tables are generated when appropriate.
+.TP
+.BI \-F dir
+Search the directory
+.IB dir /dev name
+for font and device description files;
+.I name
+is the name of the device, usually
+.BR html .
+.TP
+.BI \-I imagetype
+select the type of image generated when grohtml encounters an equation,
+table, or picture.
+By default this is png256.
+Legal image types are: gif and any of the png formats which are supported by
+ghostscript gs(1).
+.TP
+.BI \-r resolution
+select the resolution for all images.
+By default this is 80 pixels per inch.
+Example: -r100 indicates 100 pixels per inch.
+.TP
+.B \-v
+Print the version number.
+.TP
+.B \-?
+Display usage.
+.SH USAGE
+There are styles called
+.BR R ,
+.BR I ,
+.BR B ,
+and
+.B BI
+mounted at font positions 1 to 4.
+It is advisable to invoke groff with the -mhtml macro set, which turns off
+headers, footers, and hyphenation; additionally, it will right justify text.
+.SH DEPENDENCIES
+.B grohtml
+is dependent upon grops and gs.
+If
+.B grohtml
+has been configured to generate gif files then it is further dependent upon,
+ppmtogif, and ppmquant.
+However if it has been configured to generate png files (the default) then
+it is dependent upon gs having a png output device.
+Images are generated whenever a table, picture, equation or line is
+encountered.
+.SH BUGS
+This is still very alpha.
+At least three major bugs remain:
+Firstly,
+.B grohtml
+sometimes miscalculates the end of an html table resulting in text which
+appears twice.
+Secondly equation numbers are not handled correctly.
+Thirdly equation macros and pic macros can confuse
+.BR grohtml .
+.SH "SEE ALSO"
+.BR afmtodit (@MAN1EXT@),
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR psbb (@MAN1EXT@),
+.BR groff_out (@MAN5EXT@),
+.BR groff_font (@MAN5EXT@),
+.BR groff_char (@MAN7EXT@)
diff --git a/gnu/usr.bin/groff/grohtml/html.cc b/gnu/usr.bin/groff/grohtml/html.cc
new file mode 100644
index 00000000000..26b9279da69
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/html.cc
@@ -0,0 +1,5183 @@
+// -*- C++ -*-
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk) wrote grohtml
+ * but it owes a huge amount of ideas and raw code from
+ * James Clark (jjc@jclark.com) grops/ps.cc.
+ */
+
+/*
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "driver.h"
+#include "stringclass.h"
+#include "cset.h"
+
+#include "html.h"
+#include <time.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "ordered_list.h"
+
+#if !defined(TRUE)
+# define TRUE (1==1)
+#endif
+#if !defined(FALSE)
+# define FALSE (1==0)
+#endif
+
+#define MAX_TEMP_NAME 1024
+#define MAX_STRING_LENGTH 4096
+
+#define Y_FUDGE_MARGIN +0.83
+#define A4_PAGE_LENGTH (11.6944-Y_FUDGE_MARGIN)
+#define DEFAULT_IMAGE_RES 80
+#define IMAGE_BOARDER_PIXELS 10
+#define MAX_WORDS_PER_LINE 1000 // only used for table indentation
+#define GAP_SPACES 3 // how many spaces needed to guess a gap?
+#define GAP_WIDTH_ONE_LINE 2 // 1/GAP_WIDTH_ONE_LINE inches required for one line table
+#define CENTER_TOLERANCE 2 // how many pixels off center will we think a line or region is centered
+#define MIN_COLUMN 7 // minimum column size pixels
+
+
+/*
+ * Only uncomment one of the following to determine default image type.
+ */
+
+#define IMAGE_DEFAULT_PNG
+/* #define IMAGE_DEFAULT_GIF */
+
+
+#if defined(IMAGE_DEFAULT_GIF)
+static enum { gif, png } image_type = gif;
+static char *image_device = "gif";
+#elif defined(IMAGE_DEFAULT_PNG)
+static enum { gif, png } image_type = png;
+static char *image_device = "png256";
+#else
+# error "you must define either IMAGE_DEFAULT_GIF or IMAGE_DEFAULT_PNG"
+#endif
+
+static int debug_on = FALSE;
+static int guess_on = TRUE;
+static int margin_on = FALSE;
+static int auto_on = TRUE;
+static int table_on = TRUE;
+static int image_res = DEFAULT_IMAGE_RES;
+static int debug_table_on = FALSE;
+
+static int linewidth = -1;
+
+#define DEFAULT_LINEWIDTH 40 /* in ems/1000 */
+#define MAX_LINE_LENGTH 72
+#define FILL_MAX 1000
+
+void stop () {}
+
+
+/*
+ * start with a few favorites
+ */
+
+static int min (int a, int b)
+{
+ if (a < b) {
+ return( a );
+ } else {
+ return( b );
+ }
+}
+
+static int max (int a, int b)
+{
+ if (a > b) {
+ return( a );
+ } else {
+ return( b );
+ }
+}
+
+
+/*
+ * is_subsection - returns TRUE if a1..a2 is within b1..b2
+ */
+
+static int is_subsection (int a1, int a2, int b1, int b2)
+{
+ // easier to see whether this is not the case
+ return( !((a1 < b1) || (a1 > b2) || (a2 < b1) || (a2 > b2)) );
+}
+
+
+/*
+ * is_intersection - returns TRUE if range a1..a2 intersects with b1..b2
+ */
+
+static int is_intersection (int a1, int a2, int b1, int b2)
+{
+ // again easier to prove NOT outside limits
+ return( ! ((a1 > b2) || (a2 < b1)) );
+}
+
+
+/*
+ * is_digit - returns TRUE if character, ch, is a digit.
+ */
+
+static int is_digit (char ch)
+{
+ return( (ch >= '0') && (ch <= '9') );
+}
+
+
+/*
+ * more_than_line_break - returns TRUE should v1 and v2 differ by more than
+ * a simple line break.
+ */
+
+static int more_than_line_break (int v1, int v2, int size)
+{
+ return( abs(v1-v2)>size );
+}
+
+
+/*
+ * the class and methods for styles
+ */
+
+struct style {
+ font *f;
+ int point_size;
+ int font_no;
+ int height;
+ int slant;
+ style ();
+ style (font *, int, int, int, int);
+ int operator == (const style &) const;
+ int operator != (const style &) const;
+};
+
+style::style()
+ : f(0)
+{
+}
+
+style::style(font *p, int sz, int h, int sl, int no)
+ : f(p), point_size(sz), height(h), slant(sl), font_no(no)
+{
+}
+
+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()
+: next(0), used(0)
+{
+}
+
+class char_buffer {
+public:
+ char_buffer();
+ ~char_buffer();
+ char *add_string(char *, unsigned int);
+private:
+ char_block *head;
+ char_block *tail;
+};
+
+char_buffer::char_buffer()
+: head(0), tail(0)
+{
+}
+
+char_buffer::~char_buffer()
+{
+ while (head != 0) {
+ char_block *temp = head;
+ head = head->next;
+ delete temp;
+ }
+}
+
+char *char_buffer::add_string (char *s, unsigned int length)
+{
+ int i=0;
+ unsigned int old_used;
+
+ if (tail == 0) {
+ tail = new char_block;
+ head = tail;
+ } else {
+ if (tail->used + length+1 > char_block::SIZE) {
+ tail->next = new char_block;
+ tail = tail->next;
+ }
+ }
+ // at this point we have a tail which is ready for the string.
+ if (tail->used + length+1 > char_block::SIZE) {
+ fatal("need to increase char_block::SIZE");
+ }
+
+ old_used = tail->used;
+ do {
+ tail->buffer[tail->used] = s[i];
+ tail->used++;
+ i++;
+ length--;
+ } while (length>0);
+
+ // add terminating nul character
+
+ tail->buffer[tail->used] = '\0';
+ tail->used++;
+
+ // and return start of new string
+
+ return( &tail->buffer[old_used] );
+}
+
+/*
+ * the classes and methods for maintaining pages and text positions and graphic regions
+ */
+
+class text_glob {
+public:
+ int is_less (text_glob *a, text_glob *b);
+ text_glob (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal, int is_command, int is_html);
+ text_glob (void);
+ ~text_glob (void);
+
+ style text_style;
+ char *text_string;
+ unsigned int text_length;
+ int minv, maxv, minh, maxh;
+ int is_raw_command; // should the text be sent directly to the device?
+ int is_html_command; // is the raw command definitely for the html device ie not an eqn?
+};
+
+text_glob::text_glob (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal, int is_command, int is_html)
+ : text_style(*s), text_string(string), text_length(length),
+ minv(min_vertical), minh(min_horizontal), maxv(max_vertical), maxh(max_horizontal),
+ is_raw_command(is_command), is_html_command(is_html)
+{
+}
+
+text_glob::text_glob ()
+ : text_string(0), text_length(0), minv(-1), maxv(-1), minh(-1), maxh(-1),
+ is_raw_command(FALSE), is_html_command(FALSE)
+{
+}
+
+text_glob::~text_glob ()
+{
+}
+
+int text_glob::is_less (text_glob *a, text_glob *b)
+{
+ if (is_intersection(a->minv, a->maxv, b->minv, b->maxv)) {
+ return( a->minh < b->minh );
+ } else {
+ return( a->maxv < b->maxv );
+ }
+}
+
+struct xycoord {
+ int x;
+ int y;
+};
+
+class graphic_glob {
+public:
+ int is_less (graphic_glob *a, graphic_glob *b);
+ graphic_glob (int troff_code);
+ graphic_glob (void);
+ ~graphic_glob (void);
+
+ int minv, maxv, minh, maxh;
+ int xc, yc;
+ int nopoints; // number of points allocated in array below
+ struct xycoord *point;
+ int size;
+ int fill;
+ int code;
+};
+
+graphic_glob::graphic_glob ()
+ : minv(-1), maxv(-1), minh(-1), maxh(-1), code(0), size(0), nopoints(0), point(0)
+{
+}
+
+graphic_glob::~graphic_glob ()
+{
+ if (point != 0) {
+ free(point);
+ }
+}
+
+graphic_glob::graphic_glob (int troff_code)
+ : minv(-1), maxv(-1), minh(-1), maxh(-1), code(troff_code), size(0), nopoints(0), point(0)
+{
+}
+
+int graphic_glob::is_less (graphic_glob *a, graphic_glob *b)
+{
+ return( (a->minv < b->minv) || ((a->minv == b->minv) && (a->minh < b->minh)) );
+}
+
+class region_glob {
+public:
+ region_glob (void);
+ ~region_glob (void);
+ int is_less (region_glob *a, region_glob *b);
+
+ int minv, maxv, minh, maxh;
+};
+
+int region_glob::is_less (region_glob *a, region_glob *b)
+{
+ return( (a->minv < b->minv) || ((a->minv == b->minv) && (a->minh < b->minh)) );
+}
+
+region_glob::region_glob (void)
+ : minv(-1), maxv(-1), minh(-1), maxh(-1)
+{
+}
+
+region_glob::~region_glob (void)
+{
+}
+
+class page {
+public:
+ page (void);
+ void add (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_html_command (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_special_char (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal);
+ void add_line (int code, int x1, int y1, int x2, int y2, int size, int fill);
+ void add_arc (int code, int xc, int yc, int *p, double *c, int size, int fill);
+ void add_polygon (int code, int np, int *p, int oh, int ov, int size, int fill);
+ void add_spline (int code, int xc, int yc, int np, int *p, int size, int fill);
+ void calculate_region (void);
+ int is_in_region (graphic_glob *g);
+ int can_grow_region (graphic_glob *g);
+ void make_new_region (graphic_glob *g);
+ int has_line (region_glob *r);
+ int has_word (region_glob *r);
+ int no_raw_commands (int minv, int maxv);
+
+ // and the data
+
+ ordered_list <region_glob> regions; // squares of bitmapped pics,eqn,tbl's
+ ordered_list <text_glob> words; // position of words on page
+ ordered_list <graphic_glob> lines; // position of lines on page
+ char_buffer buffer; // all characters for this page
+ int is_in_graphic; // should graphics and words go below or above
+ ordered_list <text_glob> region_words; // temporary accumulation of words in a region
+ ordered_list <graphic_glob> region_lines; // (as above) and used so that we can determine
+ // the regions vertical limits
+};
+
+page::page()
+ : is_in_graphic(FALSE)
+{
+}
+
+void page::add (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
+{
+ if (length > 0) {
+ text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
+ min_vertical, min_horizontal, max_vertical, max_horizontal, FALSE, FALSE);
+ if (is_in_graphic) {
+ region_words.add(g);
+ } else {
+ words.add(g);
+ }
+ }
+}
+
+/*
+ * add_html_command - it only makes sense to add html commands when we are not inside
+ * a graphical entity.
+ */
+
+void page::add_html_command (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
+{
+ if ((length > 0) && (! is_in_graphic)) {
+ text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
+ min_vertical, min_horizontal, max_vertical, max_horizontal, TRUE, TRUE);
+ words.add(g);
+ }
+}
+
+/*
+ * add_special_char - it only makes sense to add special characters when we are inside
+ * a graphical entity.
+ */
+
+void page::add_special_char (style *s, char *string, unsigned int length,
+ int min_vertical, int min_horizontal,
+ int max_vertical, int max_horizontal)
+{
+ if ((length > 0) && (is_in_graphic)) {
+ text_glob *g=new text_glob(s, buffer.add_string(string, length), length,
+ min_vertical, min_horizontal, max_vertical, max_horizontal, TRUE, FALSE);
+ region_words.add(g);
+ }
+}
+
+void page::add_line (int code, int x1, int y1, int x2, int y2, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+
+ g->minh = min(x1, x2);
+ g->maxh = max(x1, x2);
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*2);
+ g->nopoints = 2;
+ g->point[0].x = x1 ;
+ g->point[0].y = y1 ;
+ g->point[1].x = x2 ;
+ g->point[1].y = y2 ;
+ g->xc = 0;
+ g->yc = 0;
+ g->size = size;
+ g->fill = fill;
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+/*
+ * assign_min_max_for_arc - works out the smallest box that will encompass an
+ * arc defined by: origin: g->xc, g->xc
+ * and vector (p[0], p[1]) and (p[2], p[3])
+ */
+
+void assign_min_max_for_arc (graphic_glob *g, int *p, double *c)
+{
+ int radius = (int) sqrt(c[0]*c[0]+c[1]*c[1]);
+ int xv1 = p[0];
+ int yv1 = p[1];
+ int xv2 = p[2];
+ int yv2 = p[3];
+ int x1 = g->xc+xv1;
+ int y1 = g->yc+yv1;
+ int x2 = g->xc+xv1+xv2;
+ int y2 = g->yc+yv1+yv2;
+
+ // firstly lets use the 'circle' limitation
+ g->minh = x1-radius;
+ g->maxh = x1+radius;
+ g->minv = y1-radius;
+ g->maxv = y1+radius;
+
+ // incidentally I'm sure there is a better way to do this, but I don't know it
+ // please can someone let me know or "improve" this function
+
+ // now see which min/max can be reduced and increased for the limits of the arc
+ //
+ //
+ // Q2 | Q1
+ // -----+-----
+ // Q3 | Q4
+ //
+
+
+ if ((xv1>=0) && (yv1>=0)) {
+ // first vector in Q3
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ g->maxh = x2;
+ g->minv = y1;
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ g->maxh = x2;
+ g->minv = y1;
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ g->minv = min(y1, y2);
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ if (x1>=x2) {
+ g->minh = x2;
+ g->maxh = x1;
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ } else {
+ // xv2, yv2 could all be zero?
+ }
+ }
+ } else if ((xv1>=0) && (yv1<0)) {
+ // first vector in Q2
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ g->maxh = max(x1, x2);
+ g->minh = min(x1, x2);
+ g->minv = y1;
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ if (x1<x2) {
+ g->maxh = x2;
+ g->minh = x1;
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ } else {
+ // otherwise almost full circle anyway
+ }
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ g->minv = y2;
+ g->minh = x1;
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ g->minh = min(x1, x2);
+ }
+ } else if ((xv1<0) && (yv1<0)) {
+ // first vector in Q1
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ if (x1<x2) {
+ g->minh = x1;
+ g->maxh = x2;
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ } else {
+ // nearly full circle
+ }
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ g->maxv = max(y1, y2);
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ g->minh = min(x1, x2);
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ g->minh = x2;
+ g->maxv = y1;
+ }
+ } else if ((xv1<0) && (yv1>=0)) {
+ // first vector in Q4
+ if ((xv2>=0) && (yv2>=0)) {
+ // second in Q1
+ g->maxh = max(x1, x2);
+ } else if ((xv2<0) && (yv2>=0)) {
+ // second in Q2
+ g->maxv = max(y1, y2);
+ g->maxh = max(x1, x2);
+ } else if ((xv2>=0) && (yv2<0)) {
+ // second in Q4
+ if (x1>=x2) {
+ g->minv = min(y1, y2);
+ g->maxv = max(y1, y2);
+ g->minh = min(x1, x2);
+ g->maxh = max(x2, x2);
+ } else {
+ // nearly full circle
+ }
+ } else if ((xv2<0) && (yv2<0)) {
+ // second in Q3
+ g->maxv = max(y1, y2);
+ g->minh = min(x1, x2);
+ g->maxh = max(x1, x2);
+ }
+ }
+ // this should *never* happen but if it does it means a case above is wrong..
+
+ // this code is only present for safety sake
+ if (g->maxh < g->minh) {
+ if (debug_on) {
+ fprintf(stderr, "assert failed minh > maxh\n"); fflush(stderr);
+ stop();
+ }
+ g->maxh = g->minh;
+ }
+ if (g->maxv < g->minv) {
+ if (debug_on) {
+ fprintf(stderr, "assert failed minv > maxv\n"); fflush(stderr);
+ stop();
+ }
+ g->maxv = g->minv;
+ }
+}
+
+void page::add_arc (int code, int xc, int yc, int *p, double *c, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*2);
+ g->nopoints = 2;
+ g->point[0].x = p[0] ;
+ g->point[0].y = p[1] ;
+ g->point[1].x = p[2] ;
+ g->point[1].y = p[3] ;
+ g->xc = xc;
+ g->yc = yc;
+ g->size = size;
+ g->fill = fill;
+
+ assign_min_max_for_arc(g, p, c);
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+
+void page::add_polygon (int code, int np, int *p, int oh, int ov, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+ int j = 0;
+ int i;
+
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*np/2);
+ g->nopoints = np/2;
+
+ for (i=0; i<g->nopoints; i++) {
+ g->point[i].x = p[j];
+ j++;
+ g->point[i].y = p[j];
+ j++;
+ }
+ // now calculate min/max
+ g->minh = g->point[0].x;
+ g->minv = g->point[0].y;
+ g->maxh = g->point[0].x;
+ g->maxv = g->point[0].y;
+ for (i=1; i<g->nopoints; i++) {
+ g->minh = min(g->minh, g->point[i].x);
+ g->minv = min(g->minv, g->point[i].y);
+ g->maxh = max(g->maxh, g->point[i].x);
+ g->maxv = max(g->maxv, g->point[i].y);
+ }
+ g->size = size;
+ g->xc = oh;
+ g->yc = ov;
+ g->fill = fill;
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+void page::add_spline (int code, int xc, int yc, int np, int *p, int size, int fill)
+{
+ graphic_glob *g = new graphic_glob(code);
+ int j = 0;
+ int i;
+
+ g->point = (struct xycoord *)malloc(sizeof(xycoord)*np/2);
+ g->nopoints = np/2;
+
+ for (i=0; i<g->nopoints; i++) {
+ g->point[i].x = p[j];
+ j++;
+ g->point[i].y = p[j];
+ j++;
+ }
+ // now calculate min/max
+ g->minh = min(g->point[0].x, g->point[0].x/2);
+ g->minv = min(g->point[0].y, g->point[0].y/2);
+ g->maxh = max(g->point[0].x, g->point[0].x/2);
+ g->maxv = max(g->point[0].y, g->point[0].y/2);
+
+ /* tnum/tden should be between 0 and 1; the closer it is to 1
+ the tighter the curve will be to the guiding lines; 2/3
+ is the standard value */
+ const int tnum = 2;
+ const int tden = 3;
+
+ for (i=1; i<g->nopoints-1; i++) {
+ g->minh = min(g->minh, g->point[i].x*tnum/(2*tden));
+ g->minv = min(g->minv, g->point[i].y*tnum/(2*tden));
+ g->maxh = max(g->maxh, g->point[i].x*tnum/(2*tden));
+ g->maxv = max(g->maxv, g->point[i].y*tnum/(2*tden));
+
+ g->minh = min(g->minh, g->point[i].x/2+(g->point[i+1].x*(tden-tden))/(2*tden));
+ g->minv = min(g->minv, g->point[i].y/2+(g->point[i+1].y*(tden-tden))/(2*tden));
+ g->maxh = max(g->maxh, g->point[i].x/2+(g->point[i+1].x*(tden-tden))/(2*tden));
+ g->maxv = max(g->maxv, g->point[i].y/2+(g->point[i+1].y*(tden-tden))/(2*tden));
+
+ g->minh = min(g->minh, (g->point[i].x-g->point[i].x/2) + g->point[i+1].x/2);
+ g->minv = min(g->minv, (g->point[i].y-g->point[i].y/2) + g->point[i+1].y/2);
+ g->maxh = max(g->maxh, (g->point[i].x-g->point[i].x/2) + g->point[i+1].x/2);
+ g->maxv = max(g->maxv, (g->point[i].y-g->point[i].y/2) + g->point[i+1].y/2);
+ }
+ i = g->nopoints-1;
+
+ g->minh = min(g->minh, (g->point[i].x-g->point[i].x/2)) + xc;
+ g->minv = min(g->minv, (g->point[i].y-g->point[i].y/2)) + yc;
+ g->maxh = max(g->maxh, (g->point[i].x-g->point[i].x/2)) + xc;
+ g->maxv = max(g->maxv, (g->point[i].y-g->point[i].y/2)) + yc;
+
+ g->size = size;
+ g->xc = xc;
+ g->yc = yc;
+ g->fill = fill;
+
+ if (is_in_graphic) {
+ region_lines.add(g);
+ } else {
+ lines.add(g);
+ }
+}
+
+/*
+ * the classes and methods for simple_output manipulation
+ */
+
+simple_output::simple_output(FILE *f, int n)
+: fp(f), max_line_length(n), col(0), need_space(0), fixed_point(0)
+{
+}
+
+simple_output &simple_output::set_file(FILE *f)
+{
+ fp = f;
+ col = 0;
+ return *this;
+}
+
+simple_output &simple_output::copy_file(FILE *infp)
+{
+ int c;
+ while ((c = getc(infp)) != EOF)
+ putc(c, fp);
+ return *this;
+}
+
+simple_output &simple_output::end_line()
+{
+ if (col != 0) {
+ putc('\n', fp);
+ col = 0;
+ need_space = 0;
+ }
+ return *this;
+}
+
+simple_output &simple_output::special(const char *s)
+{
+ return *this;
+}
+
+simple_output &simple_output::simple_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ fputs("<!-- ", fp);
+ fputs(s, fp);
+ fputs(" -->\n", fp);
+ col = 0;
+ need_space = 0;
+ return *this;
+}
+
+simple_output &simple_output::begin_comment(const char *s)
+{
+ if (col != 0)
+ putc('\n', fp);
+ fputs("<!-- ", fp);
+ fputs(s, fp);
+ col = 5 + strlen(s);
+ return *this;
+}
+
+simple_output &simple_output::end_comment()
+{
+ if (need_space) {
+ putc(' ', fp);
+ }
+ fputs(" -->\n", fp);
+ col = 0;
+ need_space = 0;
+ return *this;
+}
+
+simple_output &simple_output::comment_arg(const char *s)
+{
+ int len = strlen(s);
+
+ if (col + len + 1 > max_line_length) {
+ fputs("\n ", fp);
+ col = 1;
+ }
+ fputs(s, fp);
+ col += len + 1;
+ return *this;
+}
+
+simple_output &simple_output::set_fixed_point(int n)
+{
+ assert(n >= 0 && n <= 10);
+ fixed_point = n;
+ return *this;
+}
+
+simple_output &simple_output::put_delimiter(char c)
+{
+ putc(c, fp);
+ col++;
+ need_space = 0;
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s, int n)
+{
+ int i=0;
+
+ while (i<n) {
+ fputc(s[i], fp);
+ i++;
+ }
+ col += n;
+ return *this;
+}
+
+simple_output &simple_output::put_translated_string(const char *s)
+{
+ int i=0;
+
+ while (s[i] != (char)0) {
+ if ((s[i] & 0x7f) == s[i]) {
+ fputc(s[i], fp);
+ }
+ i++;
+ }
+ col += i;
+ return *this;
+}
+
+simple_output &simple_output::put_string(const char *s)
+{
+ int i=0;
+
+ while (s[i] != '\0') {
+ fputc(s[i], fp);
+ i++;
+ }
+ col += i;
+ return *this;
+}
+
+struct html_2_postscript {
+ char *html_char;
+ char *postscript_char;
+};
+
+static struct html_2_postscript char_conversions[] = {
+ "+-", "char177",
+ "eq", "=",
+ "mu", "char215",
+ NULL, NULL,
+};
+
+
+// this is an aweful hack which attempts to translate html characters onto
+// postscript characters. Can this be done inside the devhtml files?
+//
+// or should we read the devps files and find out the translations?
+//
+
+simple_output &simple_output::put_translated_char (const char *s)
+{
+ int i=0;
+
+ while (char_conversions[i].html_char != NULL) {
+ if (strcmp(s, char_conversions[i].html_char) == 0) {
+ put_string(char_conversions[i].postscript_char);
+ return *this;
+ } else {
+ i++;
+ }
+ }
+ put_string(s);
+ return *this;
+}
+
+simple_output &simple_output::put_number(int n)
+{
+ char buf[1 + INT_DIGITS + 1];
+ sprintf(buf, "%d", n);
+ int len = strlen(buf);
+ put_string(buf, len);
+ need_space = 1;
+ return *this;
+}
+
+simple_output &simple_output::put_float(double d)
+{
+ char buf[128];
+
+ sprintf(buf, "%.4f", d);
+ int len = strlen(buf);
+ put_string(buf, len);
+ need_space = 1;
+ return *this;
+}
+
+
+simple_output &simple_output::put_symbol(const char *s)
+{
+ int len = strlen(s);
+
+ if (need_space) {
+ putc(' ', fp);
+ col++;
+ }
+ fputs(s, fp);
+ col += len;
+ need_space = 1;
+ return *this;
+}
+
+class html_font : public font {
+ html_font(const char *);
+public:
+ int encoding_index;
+ char *encoding;
+ char *reencoded_name;
+ ~html_font();
+ void handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno);
+ static html_font *load_html_font(const char *);
+};
+
+html_font *html_font::load_html_font(const char *s)
+{
+ html_font *f = new html_font(s);
+ if (!f->load()) {
+ delete f;
+ return 0;
+ }
+ return f;
+}
+
+html_font::html_font(const char *nm)
+: font(nm)
+{
+}
+
+html_font::~html_font()
+{
+}
+
+void html_font::handle_unknown_font_command(const char *command, const char *arg,
+ const char *filename, int lineno)
+{
+ if (strcmp(command, "encoding") == 0) {
+ if (arg == 0)
+ error_with_file_and_line(filename, lineno,
+ "`encoding' command requires an argument");
+ else
+ encoding = strsave(arg);
+ }
+}
+
+
+/*
+ * a simple class to contain the header to this document
+ */
+
+class title_desc {
+public:
+ title_desc ();
+ ~title_desc ();
+
+ int has_been_written;
+ int has_been_found;
+ char text[MAX_STRING_LENGTH];
+};
+
+
+title_desc::title_desc ()
+ : has_been_found(FALSE), has_been_written(FALSE)
+{
+}
+
+title_desc::~title_desc ()
+{
+}
+
+class header_desc {
+public:
+ header_desc ();
+ ~header_desc ();
+
+ int no_of_headings; // how many headings have we found?
+ char_buffer headings; // all the headings used in the document
+ ordered_list <text_glob> headers;
+ int header_level; // current header level
+ int written_header; // have we written the header yet?
+ char header_buffer[MAX_STRING_LENGTH]; // current header text
+
+ void write_headings (FILE *f);
+};
+
+header_desc::header_desc ()
+ : no_of_headings(0), header_level(2), written_header(0)
+{
+}
+
+header_desc::~header_desc ()
+{
+}
+
+/*
+ * paragraph_type - alignment for a new paragraph
+ */
+
+typedef enum { left_alignment, center_alignment } paragraph_type;
+
+/*
+ * text_defn - defines the limit of text, initially these are stored in the
+ * column array as words. Later we examine the white space between
+ * the words in successive lines to find out whether we can detect
+ * distinct columns. The columns are generated via html tables.
+ */
+
+struct text_defn {
+ int left; // the start of a word or text
+ int right; // the end of the text and beginning of white space
+ int is_used; // will this this column be used for words or space
+};
+
+
+/*
+ * note that html_tables are currently only used to provide a better
+ * indentation mechanism for html text (in particular it allows grohtml
+ * to render .IP and .2C together with autoformatting).
+ */
+
+class html_table {
+public:
+ html_table ();
+ ~html_table ();
+
+ int no_of_columns; // how many columns are we using?
+ struct text_defn *columns; // left and right margins for each column
+ int vertical_limit; // the limit of the table
+};
+
+html_table::html_table ()
+ : no_of_columns(0), columns(0), vertical_limit(0)
+{
+}
+
+html_table::~html_table ()
+{
+}
+
+class html_printer : public printer {
+ FILE *tempfp;
+ simple_output html;
+ simple_output troff;
+ int res;
+ int postscript_res;
+ int space_char_index;
+ int no_of_printed_pages;
+ int paper_length;
+ enum { SBUF_SIZE = 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;
+ string defs;
+ char *inside_font_style;
+ int page_number;
+ title_desc title;
+ header_desc header;
+ page *page_contents;
+ html_table indentation;
+ int left_margin_indent;
+ int right_margin_indent;
+ int need_one_newline;
+ int issued_newline;
+ int in_paragraph;
+ int need_paragraph;
+ paragraph_type para_type;
+ char image_name[MAX_STRING_LENGTH];
+ int image_number;
+ int graphic_level;
+
+ int start_region_vpos;
+ int start_region_hpos;
+ int end_region_vpos;
+ int end_region_hpos;
+ int cutoff_heading;
+
+ struct graphic_glob *start_graphic;
+ struct text_glob *start_text;
+
+
+ void flush_sbuf ();
+ void set_style (const style &);
+ void set_space_code (unsigned char c);
+ void do_exec (char *, const environment *);
+ void do_import (char *, const environment *);
+ void do_def (char *, const environment *);
+ void do_mdef (char *, const environment *);
+ void do_file (char *, const environment *);
+ void set_line_thickness (const environment *);
+ void change_font (text_glob *g, int is_to_html);
+ void terminate_current_font (void);
+ void flush_font (void);
+ void flush_page (void);
+ void display_word (text_glob *g, int is_to_html);
+ void html_display_word (text_glob *g);
+ void troff_display_word (text_glob *g);
+ void display_line (graphic_glob *g, int is_to_html);
+ void display_fill (graphic_glob *g);
+ void calculate_margin (void);
+ void traverse_page_regions (void);
+ void dump_page (void);
+ int is_within_region (graphic_glob *g);
+ int is_within_region (text_glob *t);
+ int is_less (graphic_glob *g, text_glob *t);
+ void display_globs (int is_to_html);
+ void move_horizontal (text_glob *g, int left_margin);
+ void move_vertical (text_glob *g, paragraph_type p);
+ void write_html_font_face (const char *fontname, const char *left, const char *right);
+ void write_html_font_type (const char *fontname, const char *left, const char *right);
+ void html_change_font (text_glob *g, const char *fontname, int size);
+ char *html_position_text (text_glob *g, int left_margin, int right_margin);
+ int html_position_region (void);
+ void troff_change_font (const char *fontname, int size, int font_no);
+ void troff_position_text (text_glob *g);
+ int pretend_is_on_same_line (text_glob *g, int left_margin, int right_margin);
+ int is_on_same_line (text_glob *g, int vpos);
+ int looks_like_subscript (text_glob *g);
+ int looks_like_superscript (text_glob *g);
+ void begin_paragraph (paragraph_type p);
+ void begin_paragraph_no_height (paragraph_type p);
+ void force_begin_paragraph (void);
+ void end_paragraph (void);
+ void html_newline (void);
+ void convert_to_image (char *name);
+ void write_title (int in_head);
+ void find_title (void);
+ int is_bold (text_glob *g);
+ void write_header (void);
+ void determine_header_level (void);
+ void build_header (text_glob *g);
+ void make_html_indent (int indent);
+ int is_whole_line_bold (text_glob *g);
+ int is_a_header (text_glob *g);
+ int processed_header (text_glob *g);
+ void make_new_image_name (void);
+ void create_temp_name (char *name, char *extension);
+ void calculate_region_margins (region_glob *r);
+ void remove_redundant_regions (void);
+ void remove_duplicate_regions (void);
+ void move_region_to_page (void);
+ void calculate_region_range (graphic_glob *r);
+ void flush_graphic (void);
+ void write_string (graphic_glob *g, int is_to_html);
+ void prologue (void);
+ int gs_x (int x);
+ int gs_y (int y);
+ void display_regions (void);
+ int check_able_to_use_table (text_glob *g);
+ int using_table_for_indent (void);
+ int collect_columns (struct text_defn *line, struct text_defn *last, int max_words);
+ void include_into_list (struct text_defn *line, struct text_defn *item);
+ int is_in_column (struct text_defn *line, struct text_defn *item, int max_words);
+ int is_column_match (struct text_defn *match, struct text_defn *line1, struct text_defn *line2, int max_words);
+ int count_columns (struct text_defn *line);
+ void rewind_text_to (text_glob *g);
+ int found_use_for_table (text_glob *start);
+ void column_display_word (int vert, int left, int right, int next);
+ void start_table (void);
+ void end_table (void);
+ void foreach_column_include_text (text_glob *start);
+ void define_cell (int left, int right);
+ int column_calculate_left_margin (int left, int right);
+ int column_calculate_right_margin (int left, int right);
+ void display_columns (const char *word, const char *name, text_defn *line);
+ void calculate_right (struct text_defn *line, int max_words);
+ void determine_right_most_column (struct text_defn *line, int max_words);
+ int remove_white_using_words (struct text_defn *next_guess, struct text_defn *last_guess, struct text_defn *next_line);
+ int copy_line (struct text_defn *dest, struct text_defn *src);
+ void combine_line (struct text_defn *dest, struct text_defn *src);
+ int conflict_with_words (struct text_defn *column_guess, struct text_defn *words);
+ void remove_entry_in_line (struct text_defn *line, int j);
+ void remove_redundant_columns (struct text_defn *line);
+ void add_column_gaps (struct text_defn *line);
+ int continue_searching_column (text_defn *next_col, text_defn *last_col, text_defn *all_words);
+ void add_right_full_width (struct text_defn *line, int mingap);
+ int is_continueous_column (text_defn *last_col, text_defn *next_line);
+ int is_exact_left (text_defn *last_col, text_defn *next_line);
+ void emit_space (text_glob *g, int force_space);
+ int is_in_middle (int left, int right);
+ int check_able_to_use_center (text_glob *g);
+ void write_centered_line (text_glob *g);
+ int single_centered_line (text_defn *first, text_defn *second, text_glob *g);
+ int determine_row_limit (text_glob *start, int v);
+ void assign_used_columns (text_glob *start);
+ int find_column_index (text_glob *t);
+ int large_enough_gap (text_defn *last_col);
+ int is_worth_column (int left, int right);
+ int is_subset_of_columns (text_defn *a, text_defn *b);
+ void count_hits (text_defn *col);
+ int calculate_min_gap (text_glob *g);
+
+public:
+ html_printer();
+ ~html_printer();
+ void set_char(int i, font *f, const environment *env, int w, const char *name);
+ void draw(int code, int *p, int np, const environment *env);
+ void begin_page(int);
+ void end_page(int);
+ void special(char *arg, const environment *env);
+ font *make_font(const char *);
+ void end_of_line();
+};
+
+html_printer::html_printer()
+: no_of_printed_pages(0),
+ sbuf_len(0),
+ output_hpos(-1),
+ output_vpos(-1),
+ html(0, MAX_LINE_LENGTH),
+ troff(0, MAX_LINE_LENGTH),
+ line_thickness(-1),
+ inside_font_style(0),
+ fill(FILL_MAX + 1),
+ page_number(0),
+ left_margin_indent(0),
+ right_margin_indent(0),
+ start_region_vpos(0),
+ start_region_hpos(0),
+ end_region_vpos(0),
+ end_region_hpos(0),
+ need_one_newline(0),
+ issued_newline(0),
+ image_number(0),
+ graphic_level(0),
+ cutoff_heading(100),
+ in_paragraph(0),
+ need_paragraph(0),
+ para_type(left_alignment)
+{
+ tempfp = xtmpfile();
+ html.set_file(tempfp);
+ if (linewidth < 0)
+ linewidth = DEFAULT_LINEWIDTH;
+ if (font::hor != 1)
+ fatal("horizontal resolution must be 1");
+ if (font::vert != 1)
+ fatal("vertical resolution must be 1");
+#if 0
+ // should be sorted html..
+ if (font::res % (font::sizescale*72) != 0)
+ fatal("res must be a multiple of 72*sizescale");
+#endif
+ int r = font::res;
+ int point = 0;
+ while (r % 10 == 0) {
+ r /= 10;
+ point++;
+ }
+ res = r;
+ html.set_fixed_point(point);
+ space_char_index = font::name_to_index("space");
+ paper_length = font::paperlength;
+ if (paper_length == 0)
+ paper_length = 11*font::res;
+ page_contents = new page;
+
+ postscript_res = 72000;
+}
+
+
+void html_printer::set_char(int i, font *f, const environment *env, int w, const char *name)
+{
+ unsigned char code = f->get_code(i);
+
+ style sty(f, env->size, env->height, env->slant, env->fontno);
+ if (sty.slant != 0) {
+ if (sty.slant > 80 || sty.slant < -80) {
+ error("silly slant `%1' degrees", sty.slant);
+ sty.slant = 0;
+ }
+ }
+ if ((name != 0) && (page_contents->is_in_graphic)) {
+ flush_sbuf();
+ int r=font::res; // resolution of the device actually
+ page_contents->add_special_char(&sty, (char *)name, strlen(name),
+ env->vpos-sty.point_size*r/72, env->hpos,
+ env->vpos, env->hpos+w);
+ sbuf_end_hpos = env->hpos + w;
+ sbuf_start_hpos = env->hpos;
+ sbuf_vpos = env->vpos;
+ sbuf_style = sty;
+ sbuf_kern = 0;
+ return;
+ }
+
+ 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_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 0
+ sbuf_space_code = ' ';
+ sbuf_space_count++;
+ sbuf_space_width = env->hpos - sbuf_end_hpos;
+ sbuf_end_hpos = env->hpos + w + sbuf_kern;
+ sbuf[sbuf_len++] = ' ';
+ sbuf[sbuf_len++] = code;
+ return;
+#endif
+ } else {
+ int diff = env->hpos - sbuf_end_hpos - sbuf_space_width;
+ if (diff == 0) {
+ 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;
+}
+
+
+/*
+ * make_new_image_name - creates a new file name ready for a image file.
+ * it leaves the extension off.
+ */
+
+void html_printer::make_new_image_name (void)
+{
+ image_number++;
+ sprintf(image_name, "groff-html-%d-%d", image_number, getpid());
+}
+
+/*
+ * write_title - writes the title to this document
+ */
+
+void html_printer::write_title (int in_head)
+{
+ if (title.has_been_found) {
+ if (in_head) {
+ html.put_string("<title>");
+ html.put_string(title.text);
+ html.put_string("</title>\n");
+ } else {
+ title.has_been_written = TRUE;
+ html.put_string("<h1 align=center>");
+ html.put_string(title.text);
+ html.put_string("</h1>\n");
+ }
+ }
+}
+
+
+/*
+ * find_title - finds a title to this document, if it exists.
+ */
+
+void html_printer::find_title (void)
+{
+ text_glob *t;
+ int r=font::res;
+ int removed_from_head;
+
+ if ((page_number == 1) && (guess_on)) {
+ if (! page_contents->words.is_empty()) {
+
+ int end_title_hpos = 0;
+ int start_title_hpos = 0;
+ int start_title_vpos = 0;
+ int found_title_start = FALSE;
+ int height = 0;
+ int start_region =-1;
+
+ if (! page_contents->regions.is_empty()) {
+ region_glob *r;
+
+ page_contents->regions.start_from_head();
+ r = page_contents->regions.get_data();
+ if (r->minv > 0) {
+ start_region = r->minv;
+ }
+ }
+
+ page_contents->words.start_from_head();
+ do {
+ t = page_contents->words.get_data();
+ removed_from_head = FALSE;
+ if ((found_title_start) && (start_region != -1) && (t->maxv >= start_region)) {
+ /*
+ * we have just encountered the first graphic region so
+ * we stop looking for a title.
+ */
+ title.has_been_found = TRUE;
+ return;
+ } else if (t->is_raw_command) {
+ // skip raw commands
+ } else if ((!found_title_start) && (t->minh > left_margin_indent) &&
+ ((start_region == -1) || (t->maxv < start_region))) {
+ start_title_vpos = t->minv;
+ end_title_hpos = t->minh;
+ strcpy((char *)title.text, (char *)t->text_string);
+ height = t->text_style.point_size*r/72;
+ found_title_start = TRUE;
+ page_contents->words.sub_move_right();
+ removed_from_head = ((!page_contents->words.is_empty()) &&
+ (page_contents->words.is_equal_to_head()));
+ } else if (found_title_start) {
+ if ((t->minv == start_title_vpos) ||
+ ((!more_than_line_break(start_title_vpos, t->minv, (height*3)/2)) &&
+ (t->minh > left_margin_indent)) ||
+ (is_bold(t) && (t->minh > left_margin_indent))) {
+ start_title_vpos = min(t->minv, start_title_vpos);
+ end_title_hpos = max(t->maxh, end_title_hpos);
+ strcat(title.text, " ");
+ strcat(title.text, (char *)t->text_string);
+ page_contents->words.sub_move_right();
+ removed_from_head = ((!page_contents->words.is_empty()) &&
+ (page_contents->words.is_equal_to_head()));
+ } else {
+ // end of title
+ title.has_been_found = TRUE;
+ return;
+ }
+ } else if (t->minh == left_margin_indent) {
+ // no margin exists
+ return;
+ } else {
+ // move onto next word
+ page_contents->words.move_right();
+ }
+ } while ((! page_contents->words.is_equal_to_head()) || (removed_from_head));
+ }
+ }
+}
+
+/*
+ * html_newline - generates a newline <br>
+ */
+
+void html_printer::html_newline (void)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ if (in_paragraph) {
+ // safe to generate a pretty newline
+ html.put_string("<br>\n");
+ } else {
+ html.put_string("<br>");
+ }
+ output_vpos += height;
+ issued_newline = TRUE;
+}
+
+/*
+ * force_begin_paragraph - force the begin_paragraph to be emitted.
+ */
+
+void html_printer::force_begin_paragraph (void)
+{
+ if (in_paragraph && need_paragraph) {
+ switch (para_type) {
+
+ case left_alignment: html.put_string("<p>");
+ break;
+ case center_alignment: html.put_string("<p align=center>");
+ break;
+ default: fatal("unknown paragraph alignment type");
+ }
+ need_paragraph = FALSE;
+ }
+}
+
+/*
+ * begin_paragraph - starts a new paragraph. It does nothing if a paragraph
+ * has already been started.
+ */
+
+void html_printer::begin_paragraph (paragraph_type p)
+{
+ if (! in_paragraph) {
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ if (output_vpos >=0) {
+ // we leave it alone if it is set to the top of page
+ output_vpos += height;
+ }
+ need_paragraph = TRUE; // delay the <p> just in case we don't actually emit text
+ in_paragraph = TRUE;
+ issued_newline = TRUE;
+ para_type = p;
+ }
+}
+
+
+/*
+ * begin_paragraph_no_height - starts a new paragraph. It does nothing if a paragraph
+ * has already been started. Note it does not alter output_vpos.
+ */
+
+void html_printer::begin_paragraph_no_height (paragraph_type p)
+{
+ if (! in_paragraph) {
+ need_paragraph = TRUE; // delay the <p> just in case we don't actually emit text
+ in_paragraph = TRUE;
+ issued_newline = TRUE;
+ para_type = p;
+ }
+}
+
+/*
+ * end_paragraph - end the current paragraph. It does nothing if a paragraph
+ * has not been started.
+ */
+
+void html_printer::end_paragraph (void)
+{
+ if (in_paragraph) {
+ // check whether we have generated any text inbetween the potential paragraph begin end
+ if (! need_paragraph) {
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+
+ output_vpos += height;
+ html.put_string("</p>\n");
+ }
+ terminate_current_font();
+ para_type = left_alignment;
+ in_paragraph = FALSE;
+ }
+}
+
+/*
+ * calculate_margin - runs through the words and graphics globs
+ * and finds the start of the left most margin.
+ */
+
+void html_printer::calculate_margin (void)
+{
+ if (! margin_on) {
+ text_glob *w;
+ graphic_glob *g;
+
+ // remove margin
+
+ right_margin_indent = 0;
+
+ if (! page_contents->words.is_empty()) {
+
+ // firstly check the words right margin
+
+ page_contents->words.start_from_head();
+ do {
+ w = page_contents->words.get_data();
+ if ((w->maxh >= 0) && (w->maxh > right_margin_indent)) {
+ right_margin_indent = w->maxh;
+#if 0
+ if (right_margin_indent == 950) stop();
+#endif
+ }
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ }
+
+ if (! page_contents->lines.is_empty()) {
+ // now check for diagrams for right margin
+ page_contents->lines.start_from_head();
+ do {
+ g = page_contents->lines.get_data();
+ if ((g->maxh >= 0) && (g->maxh > right_margin_indent)) {
+ right_margin_indent = g->maxh;
+#if 0
+ if (right_margin_indent == 950) stop();
+#endif
+ }
+ page_contents->lines.move_right();
+ } while (! page_contents->lines.is_equal_to_head());
+ }
+
+ // now we know the right margin lets do the same to find left margin
+
+ left_margin_indent = right_margin_indent;
+
+ if (! page_contents->words.is_empty()) {
+ do {
+ w = page_contents->words.get_data();
+ if ((w->minh >= 0) && (w->minh < left_margin_indent)) {
+ left_margin_indent = w->minh;
+ }
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ }
+
+ if (! page_contents->lines.is_empty()) {
+ // now check for diagrams
+ page_contents->lines.start_from_head();
+ do {
+ g = page_contents->lines.get_data();
+ if ((g->minh >= 0) && (g->minh < left_margin_indent)) {
+ left_margin_indent = g->minh;
+ }
+ page_contents->lines.move_right();
+ } while (! page_contents->lines.is_equal_to_head());
+ }
+ }
+}
+
+
+/*
+ * calculate_region - runs through the graphics globs and text globs
+ * and ensures that all graphic routines
+ * are defined by the region lists.
+ * This then allows us to easily
+ * determine the range of vertical and
+ * horizontal boundaries for pictures,
+ * tbl's and eqn's.
+ *
+ */
+
+void page::calculate_region (void)
+{
+ graphic_glob *g;
+
+ if (! lines.is_empty()) {
+ lines.start_from_head();
+ do {
+ g = lines.get_data();
+ if (! is_in_region(g)) {
+ if (! can_grow_region(g)) {
+ make_new_region(g);
+ }
+ }
+ lines.move_right();
+ } while (! lines.is_equal_to_head());
+ }
+}
+
+/*
+ * remove_redundant_regions - runs through the regions and ensures that
+ * all are needed. This is required as
+ * a picture may be empty, or EQ EN pair
+ * maybe empty.
+ */
+
+void html_printer::remove_redundant_regions (void)
+{
+ region_glob *r;
+ graphic_glob *g;
+
+ // firstly run through the region making sure that all are needed
+ // ie all contain a line or word
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_tail();
+ do {
+ r = page_contents->regions.get_data();
+ calculate_region_margins(r);
+ if (page_contents->has_line(r) || page_contents->has_word(r)) {
+ page_contents->regions.move_right();
+ } else {
+ page_contents->regions.sub_move_right();
+ }
+ } while ((! page_contents->regions.is_empty()) &&
+ (! page_contents->regions.is_equal_to_tail()));
+ }
+}
+
+void html_printer::display_regions (void)
+{
+ if (debug_table_on) {
+ region_glob *r;
+
+ fprintf(stderr, "==========s t a r t===========\n");
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_head();
+ do {
+ r = page_contents->regions.get_data();
+ fprintf(stderr, "region minv %d maxv %d\n", r->minv, r->maxv);
+ page_contents->regions.move_right();
+ } while (! page_contents->regions.is_equal_to_head());
+ }
+ fprintf(stderr, "============e n d=============\n");
+ fflush(stderr);
+ }
+}
+
+/*
+ * remove_duplicate_regions - runs through the regions and ensures that
+ * no duplicates exist.
+ */
+
+void html_printer::remove_duplicate_regions (void)
+{
+ region_glob *r;
+ region_glob *l=0;
+
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_head();
+ l = page_contents->regions.get_data();
+ page_contents->regions.move_right();
+ r = page_contents->regions.get_data();
+ if (l != r) {
+ do {
+ r = page_contents->regions.get_data();
+ // we have a legit region so we check for an intersection
+ if (is_intersection(r->minv, r->minv, l->minv, l->maxv) &&
+ is_intersection(r->minh, r->maxh, l->minh, l->maxh)) {
+ l->minv = min(r->minv, l->minv);
+ l->maxv = max(r->maxv, l->maxv);
+ l->minh = min(r->minh, l->minh);
+ l->maxh = max(r->maxh, l->maxh);
+ calculate_region_margins(l);
+ page_contents->regions.sub_move_right();
+ } else {
+ l = r;
+ page_contents->regions.move_right();
+ }
+ } while ((! page_contents->regions.is_empty()) &&
+ (! page_contents->regions.is_equal_to_head()));
+ }
+ }
+}
+
+int page::has_line (region_glob *r)
+{
+ graphic_glob *g;
+
+ if (! lines.is_empty()) {
+ lines.start_from_head();
+ do {
+ g = lines.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv) &&
+ is_subsection(g->minh, g->maxh, r->minh, r->maxh)) {
+ return( TRUE );
+ }
+ lines.move_right();
+ } while (! lines.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+int page::has_word (region_glob *r)
+{
+ text_glob *g;
+
+ if (! words.is_empty()) {
+ words.start_from_head();
+ do {
+ g = words.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv) &&
+ is_subsection(g->minh, g->maxh, r->minh, r->maxh)) {
+ return( TRUE );
+ }
+ words.move_right();
+ } while (! words.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+void html_printer::calculate_region_margins (region_glob *r)
+{
+ text_glob *w;
+ graphic_glob *g;
+
+ r->minh = right_margin_indent;
+ r->maxh = left_margin_indent;
+
+ if (! page_contents->lines.is_empty()) {
+ page_contents->lines.start_from_head();
+ do {
+ g = page_contents->lines.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv)) {
+ r->minh = min(r->minh, g->minh);
+ r->maxh = max(r->maxh, g->maxh);
+ }
+ page_contents->lines.move_right();
+ } while (! page_contents->lines.is_equal_to_head());
+ }
+ if (! page_contents->words.is_empty()) {
+ page_contents->words.start_from_head();
+ do {
+ w = page_contents->words.get_data();
+ if (is_subsection(w->minv, w->maxv, r->minv, r->maxv)) {
+ r->minh = min(r->minh, w->minh);
+ r->maxh = max(r->maxh, w->maxh);
+ }
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ }
+}
+
+
+int page::is_in_region (graphic_glob *g)
+{
+ region_glob *r;
+
+ if (! regions.is_empty()) {
+ regions.start_from_head();
+ do {
+ r = regions.get_data();
+ if (is_subsection(g->minv, g->maxv, r->minv, r->maxv) &&
+ is_subsection(g->minh, g->maxh, r->minh, r->maxh)) {
+ return( TRUE );
+ }
+ regions.move_right();
+ } while (! regions.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+/*
+ * no_raw_commands - returns TRUE if no html raw commands exist between
+ * minv and maxv.
+ */
+
+int page::no_raw_commands (int minv, int maxv)
+{
+ text_glob *g;
+
+ if (! words.is_empty()) {
+ words.start_from_head();
+ do {
+ g = words.get_data();
+ if ((g->is_raw_command) && (g->is_html_command) &&
+ (is_intersection(g->minv, g->maxv, minv, maxv))) {
+ return( FALSE );
+ }
+ words.move_right();
+ } while (! words.is_equal_to_head());
+ }
+ return( TRUE );
+}
+
+/*
+ * can_grow_region - returns TRUE if a region exists which can be extended
+ * to include graphic_glob *g. The region is extended.
+ */
+
+int page::can_grow_region (graphic_glob *g)
+{
+ region_glob *r;
+ int quarter_inch=font::res/4;
+
+ if (! regions.is_empty()) {
+ regions.start_from_head();
+ do {
+ r = regions.get_data();
+ // must prevent grohtml from growing a region through a html raw command
+ if (is_intersection(g->minv, g->maxv, r->minv, r->maxv+quarter_inch) &&
+ (no_raw_commands(r->minv, r->maxv+quarter_inch))) {
+#if defined(DEBUGGING)
+ stop();
+ printf("r minh=%d minv=%d maxh=%d maxv=%d\n",
+ r->minh, r->minv, r->maxh, r->maxv);
+ printf("g minh=%d minv=%d maxh=%d maxv=%d\n",
+ g->minh, g->minv, g->maxh, g->maxv);
+#endif
+ r->minv = min(r->minv, g->minv);
+ r->maxv = max(r->maxv, g->maxv);
+ r->minh = min(r->minh, g->minh);
+ r->maxh = max(r->maxh, g->maxh);
+#if defined(DEBUGGING)
+ printf(" r minh=%d minv=%d maxh=%d maxv=%d\n",
+ r->minh, r->minv, r->maxh, r->maxv);
+#endif
+ return( TRUE );
+ }
+ regions.move_right();
+ } while (! regions.is_equal_to_head());
+ }
+ return( FALSE );
+}
+
+
+/*
+ * make_new_region - creates a new region to contain, g.
+ */
+
+void page::make_new_region (graphic_glob *g)
+{
+ region_glob *r=new region_glob;
+
+ r->minv = g->minv;
+ r->maxv = g->maxv;
+ r->minh = g->minh;
+ r->maxv = g->maxv;
+ regions.add(r);
+}
+
+
+void html_printer::dump_page(void)
+{
+ text_glob *g;
+
+ printf("\n\ndebugging start\n");
+ page_contents->words.start_from_head();
+ do {
+ g = page_contents->words.get_data();
+ printf("%s ", g->text_string);
+ page_contents->words.move_right();
+ } while (! page_contents->words.is_equal_to_head());
+ printf("\ndebugging end\n\n");
+}
+
+
+/*
+ * traverse_page_regions - runs through the regions in current_page
+ * and generate html for text, and troff output
+ * for all graphics.
+ */
+
+void html_printer::traverse_page_regions (void)
+{
+ region_glob *r;
+
+ start_region_vpos = 0;
+ start_region_hpos = 0;
+ end_region_vpos = -1;
+ end_region_hpos = -1;
+
+ if (! page_contents->regions.is_empty()) {
+ page_contents->regions.start_from_head();
+ do {
+ r = page_contents->regions.get_data();
+ if (r->minv > 0) {
+ end_region_vpos = r->minv-1;
+ } else {
+ end_region_vpos = 0;
+ }
+ end_region_hpos = -1;
+ display_globs(TRUE);
+ calculate_region_margins(r);
+ start_region_vpos = end_region_vpos;
+ end_region_vpos = r->maxv;
+ start_region_hpos = r->minh;
+ end_region_hpos = r->maxh;
+ display_globs(FALSE);
+ start_region_vpos = end_region_vpos+1;
+ start_region_hpos = 0;
+ page_contents->regions.move_right();
+ } while (! page_contents->regions.is_equal_to_head());
+ start_region_vpos = end_region_vpos+1;
+ start_region_hpos = 0;
+ end_region_vpos = -1;
+ end_region_hpos = -1;
+ }
+ display_globs(TRUE);
+}
+
+int html_printer::is_within_region (text_glob *t)
+{
+ int he, ve, hs;
+
+ if (start_region_hpos == -1) {
+ hs = t->minh;
+ } else {
+ hs = start_region_hpos;
+ }
+ if (end_region_vpos == -1) {
+ ve = t->maxv;
+ } else {
+ ve = end_region_vpos;
+ }
+ if (end_region_hpos == -1) {
+ he = t->maxh;
+ } else {
+ he = end_region_hpos;
+ }
+ return( is_subsection(t->minv, t->maxv, start_region_vpos, ve) &&
+ is_subsection(t->minh, t->maxh, hs, he) );
+}
+
+int html_printer::is_within_region (graphic_glob *g)
+{
+ int he, ve, hs;
+
+ if (start_region_hpos == -1) {
+ hs = g->minh;
+ } else {
+ hs = start_region_hpos;
+ }
+ if (end_region_vpos == -1) {
+ ve = g->maxv;
+ } else {
+ ve = end_region_vpos;
+ }
+ if (end_region_hpos == -1) {
+ he = g->maxh;
+ } else {
+ he = end_region_hpos;
+ }
+ return( is_subsection(g->minv, g->maxv, start_region_vpos, ve) &&
+ is_subsection(g->minh, g->maxh, hs, he) );
+}
+
+int html_printer::is_less (graphic_glob *g, text_glob *t)
+{
+ return( (g->minv < t->minv) || ((g->minv == t->minv) && (g->minh < t->minh)) );
+}
+
+static FILE *create_file (char *filename)
+{
+ FILE *f;
+
+ errno = 0;
+ f = fopen(filename, "w");
+ if (f == 0) {
+ error("can't create `%1'", filename);
+ return( 0 );
+ } else {
+ return( f );
+ }
+}
+
+void html_printer::convert_to_image (char *name)
+{
+ char buffer[1024];
+
+ sprintf(buffer, "grops %s > %s.ps\n", name, name);
+ if (debug_on) {
+ fprintf(stderr, "%s", buffer);
+ }
+ system(buffer);
+
+ if (image_type == gif) {
+ sprintf(buffer,
+ "echo showpage | gs -q -dSAFER -sDEVICE=ppmraw -r%d -g%dx%d -sOutputFile=- %s.ps - | ppmquant 256 2> /dev/null | ppmtogif 2> /dev/null > %s.gif \n",
+ image_res,
+ (end_region_hpos-start_region_hpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ (end_region_vpos-start_region_vpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ name, image_name);
+ } else {
+ sprintf(buffer,
+ "echo showpage | gs -q -dSAFER -sDEVICE=%s -r%d -g%dx%d -sOutputFile=- %s.ps - 2> /dev/null > %s.png \n",
+ image_device,
+ image_res,
+ (end_region_hpos-start_region_hpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ (end_region_vpos-start_region_vpos)*image_res/font::res+IMAGE_BOARDER_PIXELS,
+ name, image_name);
+ }
+ if (debug_on) {
+ fprintf(stderr, "%s", buffer);
+ }
+ system(buffer);
+ sprintf(buffer, "/bin/rm -f %s %s.ps\n", name, name);
+ if (debug_on) {
+ fprintf(stderr, "%s", buffer);
+ } else {
+ system(buffer);
+ }
+}
+
+void html_printer::prologue (void)
+{
+ troff.put_string("x T ps\nx res ");
+ troff.put_number(postscript_res);
+ troff.put_string(" 1 1\nx init\np1\n");
+}
+
+void html_printer::create_temp_name (char *name, char *extension)
+{
+ make_new_image_name();
+ sprintf(name, "/tmp/%s.%s", image_name, extension);
+}
+
+void html_printer::display_globs (int is_to_html)
+{
+ text_glob *t=0;
+ graphic_glob *g=0;
+ FILE *f=0;
+ char name[MAX_TEMP_NAME];
+ char buffer[1024];
+ int r=font::res;
+ int something=FALSE;
+ int is_center=FALSE;
+
+ end_paragraph();
+
+ if (! is_to_html) {
+ is_center = html_position_region();
+ create_temp_name(name, "troff");
+ f = create_file(name);
+ troff.set_file(f);
+ prologue();
+ output_style.f = 0;
+ }
+ if (! page_contents->words.is_empty()) {
+ page_contents->words.start_from_head();
+ t = page_contents->words.get_data();
+ }
+
+ if (! page_contents->lines.is_empty()) {
+ page_contents->lines.start_from_head();
+ g = page_contents->lines.get_data();
+ }
+
+ do {
+#if 0
+ if ((t != 0) && (strcmp(t->text_string, "(1.a)") == 0)) {
+ stop();
+ }
+#endif
+ if ((t == 0) && (g != 0)) {
+ if (is_within_region(g)) {
+ something = TRUE;
+ display_line(g, is_to_html);
+ }
+ if (page_contents->lines.is_empty() || page_contents->lines.is_equal_to_tail()) {
+ g = 0;
+ } else {
+ g = page_contents->lines.move_right_get_data();
+ }
+ } else if ((g == 0) && (t != 0)) {
+ if (is_within_region(t)) {
+ display_word(t, is_to_html);
+ something = TRUE;
+ }
+ if (page_contents->words.is_empty() || page_contents->words.is_equal_to_tail()) {
+ t = 0;
+ } else {
+ t = page_contents->words.move_right_get_data();
+ }
+ } else {
+ if ((g == 0) || (t == 0)) {
+ // hmm nothing to print out...
+ } else if (is_less(g, t)) {
+ if (is_within_region(g)) {
+ display_line(g, is_to_html);
+ something = TRUE;
+ }
+ if (page_contents->lines.is_empty() || page_contents->lines.is_equal_to_tail()) {
+ g = 0;
+ } else {
+ g = page_contents->lines.move_right_get_data();
+ }
+ } else {
+ if (is_within_region(t)) {
+ display_word(t, is_to_html);
+ something = TRUE;
+ }
+ if (page_contents->words.is_empty() || page_contents->words.is_equal_to_tail()) {
+ t = 0;
+ } else {
+ t = page_contents->words.move_right_get_data();
+ }
+ }
+ }
+ } while ((t != 0) || (g != 0));
+
+ if ((! is_to_html) && (f != 0)) {
+ fclose(troff.get_file());
+ if (something) {
+ convert_to_image(name);
+
+ if (is_center) {
+ begin_paragraph(center_alignment);
+ } else {
+ begin_paragraph(left_alignment);
+ }
+ force_begin_paragraph();
+ html.put_string("<img src=\"");
+ html.put_string(image_name);
+ if (image_type == gif) {
+ html.put_string(".gif\"");
+ } else {
+ html.put_string(".png\"");
+ }
+ if (is_center) {
+ html.put_string(" align=\"middle\"");
+ }
+ html.put_string(">\n");
+ html_newline();
+ end_paragraph();
+
+ output_vpos = end_region_vpos;
+ output_hpos = 0;
+ need_one_newline = FALSE;
+ output_style.f = 0;
+ }
+ // unlink(name); // remove troff file
+ }
+}
+
+void html_printer::flush_page (void)
+{
+ calculate_margin();
+ output_vpos = -1;
+ output_hpos = left_margin_indent;
+#if 0
+ dump_page();
+#endif
+ html.begin_comment("left margin: ").comment_arg(itoa(left_margin_indent)).end_comment();;
+ html.begin_comment("right margin: ").comment_arg(itoa(right_margin_indent)).end_comment();;
+ remove_redundant_regions();
+ page_contents->calculate_region();
+ remove_duplicate_regions();
+ find_title();
+
+ traverse_page_regions();
+ terminate_current_font();
+ if (need_one_newline) {
+ html_newline();
+ }
+ end_paragraph();
+
+ // move onto a new page
+ delete page_contents;
+ page_contents = new page;
+}
+
+static int convertSizeToHTML (int size)
+{
+ if (size < 6) {
+ return( 0 );
+ } else if (size < 8) {
+ return( 1 );
+ } else if (size < 10) {
+ return( 2 );
+ } else if (size < 12) {
+ return( 3 );
+ } else if (size < 14) {
+ return( 4 );
+ } else if (size < 16) {
+ return( 5 );
+ } else if (size < 18) {
+ return( 6 );
+ } else {
+ return( 7 );
+ }
+}
+
+
+void html_printer::write_html_font_face (const char *fontname, const char *left, const char *right)
+{
+ switch (fontname[0]) {
+
+ case 'C': html.put_string(left) ; html.put_string("tt"); html.put_string(right);
+ break;
+ case 'H': break;
+ case 'T': break;
+ default: break;
+ }
+}
+
+
+void html_printer::write_html_font_type (const char *fontname, const char *left, const char *right)
+{
+ if (strcmp(&fontname[1], "B") == 0) {
+ html.put_string(left) ; html.put_string("B"); html.put_string(right);
+ } else if (strcmp(&fontname[1], "I") == 0) {
+ html.put_string(left) ; html.put_string("I"); html.put_string(right);
+ } else if (strcmp(&fontname[1], "BI") == 0) {
+ html.put_string(left) ; html.put_string("EM"); html.put_string(right);
+ }
+}
+
+
+void html_printer::html_change_font (text_glob *g, const char *fontname, int size)
+{
+ char buffer[1024];
+
+ if (output_style.f != 0) {
+ const char *oldfontname = output_style.f->get_name();
+
+ // firstly terminate the current font face and type
+ if ((oldfontname != 0) && (oldfontname != fontname)) {
+ write_html_font_face(oldfontname, "</", ">");
+ write_html_font_type(oldfontname, "</", ">");
+ }
+ }
+ if (fontname != 0) {
+ // now emit the size if it has changed
+ if (((output_style.f == 0) || (output_style.point_size != size)) && (size != 0)) {
+ sprintf(buffer, "<font size=%d>", convertSizeToHTML(size));
+ html.put_string(buffer);
+ output_style.point_size = size; // and remember the size
+ }
+
+ if (! g->is_raw_command) {
+ // now emit the new font
+ write_html_font_face(fontname, "<", ">");
+
+ // now emit the new font type
+ write_html_font_type(fontname, "<", ">");
+
+ output_style = g->text_style; // remember style for next time
+ }
+ } else {
+ output_style.f = 0; // no style at present
+ }
+}
+
+
+void html_printer::change_font (text_glob *g, int is_to_html)
+{
+ if (is_to_html) {
+ if (output_style != g->text_style) {
+ const char *fontname=0;
+ int size=0;
+
+ if (g->text_style.f != 0) {
+ fontname = g->text_style.f->get_name();
+ size = (font::res/(72*font::sizescale))*g->text_style.point_size;
+
+ html_change_font(g, fontname, size);
+ } else {
+ html_change_font(g, fontname, size);
+ }
+ }
+ } else {
+ // is to troff
+ if (output_style != g->text_style) {
+ if (g->text_style.f != 0) {
+ const char *fontname = g->text_style.f->get_name();
+ int size = (font::res/(72*font::sizescale))*g->text_style.point_size;
+
+ if (fontname == 0) {
+ fatal("no internalname specified for font");
+ }
+
+ troff_change_font(fontname, size, g->text_style.font_no);
+ output_style = g->text_style; // remember style for next time
+ }
+ }
+ }
+}
+
+
+/*
+ * is_bold - returns TRUE if the text inside, g, is using a bold face.
+ * It returns FALSE is g contains a raw html command, even if this uses
+ * a bold font.
+ */
+
+int html_printer::is_bold (text_glob *g)
+{
+ if (g->text_style.f == 0) {
+ // unknown font
+ return( FALSE );
+ } else if (g->is_raw_command) {
+ return( FALSE );
+ } else {
+ const char *fontname = g->text_style.f->get_name();
+
+ if (strlen(fontname) >= 2) {
+ return( fontname[1] == 'B' );
+ } else {
+ return( FALSE );
+ }
+ }
+}
+
+void html_printer::terminate_current_font (void)
+{
+ text_glob g;
+
+ // we create a dummy glob just so we can tell html_change_font not to start up
+ // a new font
+ g.is_raw_command = TRUE;
+ html_change_font(&g, 0, 0);
+}
+
+void html_printer::write_header (void)
+{
+ if (strlen(header.header_buffer) > 0) {
+ if (header.header_level > 7) {
+ header.header_level = 7;
+ }
+
+ if (cutoff_heading+2 > header.header_level) {
+ // firstly we must terminate any font and type faces
+ terminate_current_font();
+ end_paragraph();
+
+ // secondly we generate a tag
+ html.put_string("<a name=\"");
+ html.put_string(header.header_buffer);
+ html.put_string("\"></a>");
+ // now we save the header so we can issue a list of link
+ style st;
+
+ header.no_of_headings++;
+
+ text_glob *g=new text_glob(&st,
+ header.headings.add_string(header.header_buffer, strlen(header.header_buffer)),
+ strlen(header.header_buffer),
+ header.no_of_headings, header.header_level,
+ header.no_of_headings, header.header_level,
+ FALSE, FALSE);
+ header.headers.add(g); // and add this header to the header list
+ }
+
+ end_paragraph();
+ // and now we issue the real header
+ html.put_string("<h");
+ html.put_number(header.header_level);
+ html.put_string(">");
+ html.put_string(header.header_buffer);
+ html.put_string("</h");
+ html.put_number(header.header_level);
+ html.put_string(">");
+ need_one_newline = FALSE;
+ begin_paragraph(left_alignment);
+ header.written_header = TRUE;
+ }
+}
+
+/*
+ * write_headings - emits a list of links for the headings in this document
+ */
+
+void header_desc::write_headings (FILE *f)
+{
+ text_glob *g;
+
+ if (! headers.is_empty()) {
+ headers.start_from_head();
+ do {
+ g = headers.get_data();
+ fprintf(f, "<a href=\"#%s\">%s</a><br>\n", g->text_string, g->text_string);
+ headers.move_right();
+ } while (! headers.is_equal_to_head());
+ }
+}
+
+void html_printer::determine_header_level (void)
+{
+ int i;
+ int l=strlen(header.header_buffer);
+ int stops=0;
+
+ for (i=0; ((i<l) && ((header.header_buffer[i] == '.') || is_digit(header.header_buffer[i]))) ; i++) {
+ if (header.header_buffer[i] == '.') {
+ stops++;
+ }
+ }
+ if (stops > 0) {
+ header.header_level = stops;
+ }
+}
+
+
+void html_printer::build_header (text_glob *g)
+{
+ int r = font::res;
+ int height = g->text_style.point_size*r/72;
+ text_glob *l;
+ int current_vpos;
+
+ strcpy(header.header_buffer, "");
+ do {
+ l = g;
+ current_vpos = g->minv;
+ strcat(header.header_buffer, (char *)g->text_string);
+ page_contents->words.move_right();
+ g = page_contents->words.get_data();
+ if (g->minv == current_vpos) {
+ strcat(header.header_buffer, " ");
+ }
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ ((g->minv == current_vpos) || (l->maxh == right_margin_indent)));
+
+ determine_header_level();
+ // finally set the output to neutral for after the header
+
+ g = page_contents->words.get_data();
+ output_vpos = g->minv; // set output_vpos to the next line since
+ output_hpos = left_margin_indent; // html header forces a newline anyway
+ page_contents->words.move_left(); // so that next time we use old g
+
+ need_one_newline = FALSE;
+}
+
+
+/*
+ * is_whole_line_bold - returns TRUE if the whole line is bold.
+ */
+
+int html_printer::is_whole_line_bold (text_glob *g)
+{
+ text_glob *n=g;
+ int current_vpos=g->minv;
+
+ do {
+ if (is_bold(n)) {
+ page_contents->words.move_right();
+ n = page_contents->words.get_data();
+ } else {
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( FALSE );
+ }
+ } while ((! page_contents->words.is_equal_to_head()) && (is_on_same_line(n, current_vpos)));
+ // was (n->minv == current_vpos)
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( TRUE );
+}
+
+
+/*
+ * is_a_header - returns TRUE if the whole sequence of contineous lines are bold.
+ * It checks to see whether a line is likely to be contineous and
+ * then checks that all words are bold.
+ */
+
+int html_printer::is_a_header (text_glob *g)
+{
+ text_glob *l;
+ text_glob *n=g;
+ int current_vpos;
+
+ do {
+ l = n;
+ current_vpos = n->minv;
+ if (is_bold(n)) {
+ page_contents->words.move_right();
+ n = page_contents->words.get_data();
+ } else {
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( FALSE );
+ }
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ ((n->minv == current_vpos) || (l->maxh == right_margin_indent)));
+ while (page_contents->words.get_data() != g) {
+ page_contents->words.move_left();
+ }
+ return( TRUE );
+}
+
+
+int html_printer::processed_header (text_glob *g)
+{
+ if ((guess_on) && (g->minh == left_margin_indent) && (! using_table_for_indent()) &&
+ (is_a_header(g))) {
+ build_header(g);
+ write_header();
+ return( TRUE );
+ } else {
+ return( FALSE );
+ }
+}
+
+int is_punctuation (char *s, int length)
+{
+ return( (length == 1) &&
+ ((s[0] == '(') || (s[0] == ')') || (s[0] == '!') || (s[0] == '.') || (s[0] == '[') ||
+ (s[0] == ']') || (s[0] == '?') || (s[0] == ',') || (s[0] == ';') || (s[0] == ':') ||
+ (s[0] == '@') || (s[0] == '#') || (s[0] == '$') || (s[0] == '%') || (s[0] == '^') ||
+ (s[0] == '&') || (s[0] == '*') || (s[0] == '+') || (s[0] == '-') || (s[0] == '=') ||
+ (s[0] == '{') || (s[0] == '}') || (s[0] == '|') || (s[0] == '\"') || (s[0] == '\''))
+ );
+}
+
+/*
+ * move_horizontal - moves right into the position, g->minh.
+ */
+
+void html_printer::move_horizontal (text_glob *g, int left_margin)
+{
+ if (g->text_style.f != 0) {
+ int w = g->text_style.f->get_space_width(g->text_style.point_size);
+
+ if (w == 0) {
+ fatal("space width is zero");
+ }
+ if ((output_hpos == left_margin) && (g->minh > output_hpos)) {
+ make_html_indent(g->minh-output_hpos);
+ } else {
+ emit_space(g, FALSE);
+ }
+ output_hpos = g->maxh;
+ output_vpos = g->minv;
+
+ change_font(g, TRUE);
+ }
+}
+
+int html_printer::looks_like_subscript (text_glob *g)
+{
+ return(((output_vpos < g->minv) && (output_style.point_size != 0) &&
+ (output_style.point_size > g->text_style.point_size)));
+}
+
+
+int html_printer::looks_like_superscript (text_glob *g)
+{
+ return(((output_vpos > g->minv) && (output_style.point_size != 0) &&
+ (output_style.point_size > g->text_style.point_size)));
+}
+
+/*
+ * pretend_is_on_same_line - returns TRUE if we think, g, is on the same line as the previous glob.
+ * Note that it believes a single word spanning the left..right as being
+ * on a different line.
+ */
+
+int html_printer::pretend_is_on_same_line (text_glob *g, int left_margin, int right_margin)
+{
+ return( auto_on && (right_margin == output_hpos) && (left_margin == g->minh) &&
+ (right_margin != g->maxh) && ((! is_whole_line_bold(g)) || (g->text_style.f == output_style.f)) );
+}
+
+int html_printer::is_on_same_line (text_glob *g, int vpos)
+{
+ return(
+ (vpos >= 0) &&
+ is_intersection(vpos, vpos+g->text_style.point_size*font::res/72-1, g->minv, g->maxv)
+ );
+}
+
+
+/*
+ * make_html_indent - creates a relative indentation.
+ */
+
+void html_printer::make_html_indent (int indent)
+{
+ int r=font::res;
+
+ html.put_string("<span style=\" text-indent: ");
+ html.put_float(((double)(indent)/((double)r)));
+ html.put_string("in;\"></span>");
+}
+
+/*
+ * using_table_for_indent - returns TRUE if we currently using a table for indentation
+ * purposes.
+ */
+
+int html_printer::using_table_for_indent (void)
+{
+ return( indentation.no_of_columns != 0 );
+}
+
+/*
+ * calculate_min_gap - returns the minimum gap by which we deduce columns.
+ * This is a rough heuristic.
+ */
+
+int html_printer::calculate_min_gap (text_glob *g)
+{
+ return( g->text_style.f->get_space_width(g->text_style.point_size)*GAP_SPACES );
+}
+
+/*
+ * collect_columns - place html text in a column and return the vertical limit reached.
+ */
+
+int html_printer::collect_columns (struct text_defn *line, struct text_defn *last, int max_words)
+{
+ text_glob *start = page_contents->words.get_data();
+ text_glob *t = start;
+ int upper_limit = 0;
+
+ line[0].left = 0;
+ line[0].right = 0;
+ if (start != 0) {
+ int graphic_limit = end_region_vpos;
+
+ if (is_whole_line_bold(t) && (t->minh == left_margin_indent)) {
+ // found header therefore terminate indentation table
+ upper_limit = -t->minv; // so we know a header has stopped the column
+ } else {
+ int i =0;
+ int j =0;
+ int prevh =0;
+ int mingap =calculate_min_gap(start);
+
+ while ((t != 0) && (is_on_same_line(t, start->minv) && (i<max_words)) &&
+ ((graphic_limit == -1) || (graphic_limit > t->minv))) {
+ while ((last != 0) && (j<max_words) && (last[j].left != 0) && (last[j].left < t->minh)) {
+ j++;
+ }
+ // t->minh might equal t->maxh when we are passing a special device character via \X
+ // we currently ignore these when considering tables
+ if (((t->minh - prevh >= mingap) || ((last != 0) && (last[j].left != 0) && (t->minh == last[j].left))) &&
+ (t->minh != t->maxh)) {
+ line[i].left = t->minh;
+ line[i].right = t->maxh;
+ i++;
+ } else if (i>0) {
+ line[i-1].right = t->maxh;
+ }
+
+ // and record the vertical upper limit
+ upper_limit = max(t->minv, upper_limit);
+
+ prevh = t->maxh;
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ if (page_contents->words.is_equal_to_head()) {
+ t = 0;
+ }
+ }
+
+ if (i<max_words) {
+ line[i].left = 0;
+ line[i].right = 0;
+ }
+ }
+ }
+ return( upper_limit );
+}
+
+/*
+ * conflict_with_words - returns TRUE if a word sequence crosses a column.
+ */
+
+int html_printer::conflict_with_words (struct text_defn *column_guess, struct text_defn *words)
+{
+ int i=0;
+ int j;
+
+ while ((column_guess[i].left != 0) && (i<MAX_WORDS_PER_LINE)) {
+ j=0;
+ while ((words[j].left != 0) && (j<MAX_WORDS_PER_LINE)) {
+ if ((words[j].left <= column_guess[i].right) && (i+1<MAX_WORDS_PER_LINE) &&
+ (column_guess[i+1].left != 0) && (words[j].right >= column_guess[i+1].left)) {
+ if (debug_table_on) {
+ fprintf(stderr, "is a conflict with words\n");
+ fflush(stderr);
+ }
+ return( TRUE );
+ }
+ j++;
+ }
+ i++;
+ }
+ if (debug_table_on) {
+ fprintf(stderr, "is NOT a conflict with words\n");
+ fflush(stderr);
+ }
+ return( FALSE );
+}
+
+/*
+ * combine_line - combines dest and src.
+ */
+
+void html_printer::combine_line (struct text_defn *dest, struct text_defn *src)
+{
+ int i;
+
+ for (i=0; (i<MAX_WORDS_PER_LINE) && (src[i].left != 0); i++) {
+ include_into_list(dest, &src[i]);
+ }
+ remove_redundant_columns(dest);
+}
+
+/*
+ * remove_entry_in_line - removes an entry, j, in, line.
+ */
+
+void html_printer::remove_entry_in_line (struct text_defn *line, int j)
+{
+ while (line[j].left != 0) {
+ line[j].left = line[j+1].left;
+ line[j].right = line[j+1].right;
+ j++;
+ }
+}
+
+/*
+ * remove_redundant_columns - searches through the array columns and removes any redundant entries.
+ */
+
+void html_printer::remove_redundant_columns (struct text_defn *line)
+{
+ int i=0;
+ int j=0;
+
+ while (line[i].left != 0) {
+ if ((i<MAX_WORDS_PER_LINE) && (line[i+1].left != 0)) {
+ j = 0;
+ while ((j<MAX_WORDS_PER_LINE) && (line[j].left != 0)) {
+ if ((j != i) && (is_intersection(line[i].left, line[i].right, line[j].left, line[j].right))) {
+ line[i].left = min(line[i].left , line[j].left);
+ line[i].right = max(line[i].right, line[j].right);
+ remove_entry_in_line(line, j);
+ } else {
+ j++;
+ }
+ }
+ }
+ i++;
+ }
+}
+
+/*
+ * include_into_list - performs an order set inclusion
+ */
+
+void html_printer::include_into_list (struct text_defn *line, struct text_defn *item)
+{
+ int i=0;
+
+ while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0) && (line[i].left<item->left)) {
+ i++;
+ }
+
+ if (line[i].left == 0) {
+ // add to the end
+ if (i<MAX_WORDS_PER_LINE) {
+ if ((i>0) && (line[i-1].left > item->left)) {
+ fatal("insertion error");
+ }
+ line[i].left = item->left;
+ line[i].right = item->right;
+ i++;
+ line[i].left = 0;
+ line[i].right = 0;
+ }
+ } else {
+ if (line[i].left == item->left) {
+ line[i].right = max(item->right, line[i].right);
+ } else {
+ // insert
+ int left = item->left;
+ int right = item->right;
+ int l = line[i].left;
+ int r = line[i].right;
+
+ while ((i+1<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
+ line[i].left = left;
+ line[i].right = right;
+ i++;
+ left = l;
+ right = r;
+ l = line[i].left;
+ r = line[i].right;
+ }
+ if (i+1<MAX_WORDS_PER_LINE) {
+ line[i].left = left;
+ line[i].right = right;
+ line[i+1].left = 0;
+ line[i+1].right = 0;
+ }
+ }
+ }
+}
+
+/*
+ * is_in_column - return TRUE if value is present in line.
+ */
+
+int html_printer::is_in_column (struct text_defn *line, struct text_defn *item, int max_words)
+{
+ int i=0;
+
+ while ((i<max_words) && (line[i].left != 0)) {
+ if (line[i].left == item->left) {
+ return( TRUE );
+ } else {
+ i++;
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * calculate_right - calculate the right most margin for each column in line.
+ */
+
+void html_printer::calculate_right (struct text_defn *line, int max_words)
+{
+ int i=0;
+
+ while ((i<max_words) && (line[i].left != 0)) {
+ if (i>0) {
+ line[i-1].right = line[i].left;
+ }
+ i++;
+ }
+}
+
+/*
+ * add_right_full_width - adds an extra column to the right to bring the table up to
+ * full width.
+ */
+
+void html_printer::add_right_full_width (struct text_defn *line, int mingap)
+{
+ int i=0;
+
+ while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
+ i++;
+ }
+
+ if ((i>0) && (line[i-1].right != right_margin_indent) && (i+1<MAX_WORDS_PER_LINE)) {
+ line[i].left = min(line[i-1].right+mingap, right_margin_indent);
+ line[i].right = right_margin_indent;
+ i++;
+ if (i<MAX_WORDS_PER_LINE) {
+ line[i].left = 0;
+ line[i].right = 0;
+ }
+ }
+}
+
+/*
+ * determine_right_most_column - works out the right most limit of the right most column.
+ * Required as we might be performing a .2C and only
+ * have enough text to fill the left column.
+ */
+
+void html_printer::determine_right_most_column (struct text_defn *line, int max_words)
+{
+ int i=0;
+
+ while ((i<max_words) && (line[i].left != 0)) {
+ i++;
+ }
+ if (i>0) {
+ // remember right_margin_indent is the right most position for this page
+ line[i-1].right = column_calculate_right_margin(line[i-1].left, right_margin_indent);
+ }
+}
+
+/*
+ * is_column_match - returns TRUE if a word is aligned in the same horizontal alignment
+ * between two lines, line1 and line2. If so then this horizontal
+ * position is saved in match.
+ */
+
+int html_printer::is_column_match (struct text_defn *match,
+ struct text_defn *line1, struct text_defn *line2, int max_words)
+{
+ int i=0;
+ int j=0;
+ int found=FALSE;
+ int first=(match[0].left==0);
+
+ if (first) {
+ struct text_defn t;
+
+ t.left = left_margin_indent;
+ t.right = 0;
+
+ include_into_list(match, &t);
+ }
+ while ((line1[i].left != 0) && (line2[i].left != 0)) {
+ if (line1[i].left == line2[j].left) {
+ // same horizontal alignment found
+ include_into_list(match, &line1[i]);
+ i++;
+ j++;
+ found = TRUE;
+ } else if (line1[i].left < line2[j].left) {
+ i++;
+ } else {
+ j++;
+ }
+ }
+ calculate_right(match, max_words);
+ return( found );
+}
+
+
+/*
+ * remove_white_using_words - remove white space in, last_guess, by examining, next_line
+ * placing results into next_guess.
+ * It returns TRUE if the same columns exist in next_guess and last_guess
+ * we do allow columns to shrink but if a column disappears then we return FALSE.
+ */
+
+int html_printer::remove_white_using_words (struct text_defn *next_guess,
+ struct text_defn *last_guess, struct text_defn *next_line)
+{
+ int i=0;
+ int j=0;
+ int k=0;
+ int removed=FALSE;
+
+ while ((last_guess[j].left != 0) && (next_line[k].left != 0)) {
+ if (last_guess[j].left == next_line[k].left) {
+ // same horizontal alignment found
+ next_guess[i].left = last_guess[j].left;
+ next_guess[i].right = max(last_guess[j].right, next_line[k].right);
+ i++;
+ j++;
+ k++;
+ if ((next_guess[i-1].right > last_guess[j].left) && (last_guess[j].left != 0)) {
+ removed = TRUE;
+ }
+ } else if (last_guess[j].right < next_line[k].left) {
+ next_guess[i].left = last_guess[j].left;
+ next_guess[i].right = last_guess[j].right;
+ i++;
+ j++;
+ } else if (last_guess[j].left > next_line[k].right) {
+ // insert a word sequence from next_line[k]
+ next_guess[i].left = next_line[k].left;
+ next_guess[i].right = next_line[k].right;
+ i++;
+ k++;
+ } else if (is_intersection(last_guess[j].left, last_guess[j].right, next_line[k].left, next_line[k].right)) {
+ // potential for a column disappearing
+ next_guess[i].left = min(last_guess[j].left , next_line[k].left);
+ next_guess[i].right = max(last_guess[j].right, next_line[k].right);
+ i++;
+ j++;
+ k++;
+ if ((next_guess[i-1].right > last_guess[j].left) && (last_guess[j].left != 0)) {
+ removed = TRUE;
+ }
+ }
+ }
+ if (i<MAX_WORDS_PER_LINE) {
+ next_guess[i].left = 0;
+ next_guess[i].right = 0;
+ }
+ if (debug_table_on) {
+ if (removed) {
+ fprintf(stderr, "have removed column\n");
+ } else {
+ fprintf(stderr, "have NOT removed column\n");
+ }
+ fflush(stderr);
+ }
+ remove_redundant_columns(next_guess);
+ return( removed );
+}
+
+/*
+ * count_columns - returns the number of elements inside, line.
+ */
+
+int html_printer::count_columns (struct text_defn *line)
+{
+ int i=0;
+
+ while (line[i].left != 0) {
+ i++;
+ }
+ return( i );
+}
+
+/*
+ * rewind_text_to - moves backwards until page_contents is looking at, g.
+ */
+
+void html_printer::rewind_text_to (text_glob *g)
+{
+ while (page_contents->words.get_data() != g) {
+ if (page_contents->words.is_equal_to_head()) {
+ page_contents->words.start_from_tail();
+ } else {
+ page_contents->words.move_left();
+ }
+ }
+}
+
+/*
+ * display_columns - a long overdue debugging function, as this column code is causing me grief :-(
+ */
+
+void html_printer::display_columns (const char *word, const char *name, text_defn *line)
+{
+ int i=0;
+
+ fprintf(stderr, "[%s:%s]", name, word);
+ while (line[i].left != 0) {
+ fprintf(stderr, " <left=%d right=%d> ", line[i].left, line[i].right);
+ i++;
+ }
+ fprintf(stderr, "\n");
+ fflush(stderr);
+}
+
+/*
+ * copy_line - dest = src
+ */
+
+int html_printer::copy_line (struct text_defn *dest, struct text_defn *src)
+{
+ int k;
+
+ for (k=0; ((src[k].left != 0) && (k<MAX_WORDS_PER_LINE)); k++) {
+ dest[k].left = src[k].left;
+ dest[k].right = src[k].right;
+ }
+ if (k<MAX_WORDS_PER_LINE) {
+ dest[k].left = 0;
+ dest[k].right = 0;
+ }
+}
+
+/*
+ * add_column_gaps - adds empty columns between columns which don't exactly align
+ */
+
+void html_printer::add_column_gaps (struct text_defn *line)
+{
+ int i=0;
+ struct text_defn t;
+
+ // firstly lets see whether we need an initial column on the left hand side
+ if ((line[0].left != left_margin_indent) && (line[0].left != 0) &&
+ (left_margin_indent < line[0].left) && (is_worth_column(left_margin_indent, line[0].left))) {
+ t.left = left_margin_indent;
+ t.right = line[0].left;
+ include_into_list(line, &t);
+ }
+
+ while ((i<MAX_WORDS_PER_LINE) && (line[i].left != 0)) {
+ if ((i+1<MAX_WORDS_PER_LINE) && (line[i+1].left != 0) && (line[i].right != line[i+1].left) &&
+ (is_worth_column(line[i].right, line[i+1].left))) {
+ t.left = line[i].right;
+ t.right = line[i+1].left;
+ include_into_list(line, &t);
+ i=0;
+ } else {
+ i++;
+ }
+ }
+ // lastly lets see whether we need a final column on the right hand side
+ if ((i>0) && (line[i-1].right != right_margin_indent) &&
+ (is_worth_column(line[i-1].right, right_margin_indent))) {
+ t.left = line[i-1].right;
+ t.right = right_margin_indent;
+ include_into_list(line, &t);
+ }
+}
+
+/*
+ * is_continueous_column - returns TRUE if a line has a word on one
+ * of the last_col right most boundaries.
+ */
+
+int html_printer::is_continueous_column (text_defn *last_col, text_defn *next_line)
+{
+ int w = count_columns(next_line);
+ int c = count_columns(last_col);
+ int i, j;
+
+ for (i=0; i<c; i++) {
+ for (j=0; j<w; j++) {
+ if (last_col[i].right == next_line[j].right) {
+ return( TRUE );
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * is_exact_left - returns TRUE if a line has a word on one
+ * of the last_col left most boundaries.
+ */
+
+int html_printer::is_exact_left (text_defn *last_col, text_defn *next_line)
+{
+ int w = count_columns(next_line);
+ int c = count_columns(last_col);
+ int i, j;
+
+ for (i=0; i<c; i++) {
+ for (j=0; j<w; j++) {
+ if ((last_col[i].left == next_line[j].left) ||
+ (last_col[i].left != left_margin_indent)) {
+ return( TRUE );
+ }
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * continue_searching_column - decides whether we should carry on searching text for a column.
+ */
+
+int html_printer::continue_searching_column (text_defn *next_col,
+ text_defn *last_col,
+ text_defn *all_words)
+{
+ int count = count_columns(next_col);
+ int words = count_columns(all_words);
+
+ if ((words == 0) || ((words == 1) &&
+ (all_words[0].left == left_margin_indent) &&
+ (all_words[0].right == right_margin_indent))) {
+ // no point as we have now seen a full line of contineous text
+ return( FALSE );
+ }
+ return( (count == count_columns(last_col)) &&
+ (last_col[0].left != left_margin_indent) || (last_col[0].right != right_margin_indent) );
+}
+
+/*
+ * is_worth_column - returns TRUE if the size of this column is worth defining.
+ */
+
+int html_printer::is_worth_column (int left, int right)
+{
+#if 0
+ return( abs(right-left) >= MIN_COLUMN );
+#endif
+ return( TRUE );
+}
+
+/*
+ * large_enough_gap - returns TRUE if a large enough gap for one line was seen.
+ * We need to make sure that a single line definitely warrents
+ * a table.
+ * It also removes other smaller gaps.
+ */
+
+int html_printer::large_enough_gap (text_defn *last_col)
+{
+ int i=0;
+ int found=FALSE;
+ int r=font::res;
+ int gap=r/GAP_WIDTH_ONE_LINE;
+
+ if (abs(last_col[i].left - left_margin_indent) >= gap) {
+ found = TRUE;
+ }
+ while ((last_col[i].left != 0) && (last_col[i+1].left != 0)) {
+ if (abs(last_col[i+1].left-last_col[i].right) >= gap) {
+ found = TRUE;
+ i++;
+ } else {
+ // not good enough for a single line, remove it
+ if (i>0) {
+ last_col[i-1].right = last_col[i].right;
+ }
+ remove_entry_in_line(last_col, i);
+ }
+ }
+ return( found );
+}
+
+/*
+ * is_subset_of_columns - returns TRUE if line, a, is a subset of line, b.
+ */
+
+int html_printer::is_subset_of_columns (text_defn *a, text_defn *b)
+{
+ int i;
+ int j;
+
+ i=0;
+ while ((i<MAX_WORDS_PER_LINE) && (a[i].left != 0)) {
+ j=0;
+ while ((j<MAX_WORDS_PER_LINE) && (b[j].left != 0) &&
+ ((b[j].left != a[i].left) || (b[j].right != a[i].right))) {
+ j++;
+ }
+ if ((j==MAX_WORDS_PER_LINE) || (b[j].left == 0)) {
+ // found a different column - not a subset
+ return( FALSE );
+ }
+ i++;
+ }
+ return( TRUE );
+}
+
+/*
+ * count_hits - counts the number of hits per column. A hit is when the
+ * left hand position of a glob hits the left hand column.
+ */
+
+void html_printer::count_hits (text_defn *col)
+{
+ int i;
+ text_glob *start = page_contents->words.get_data();
+ text_glob *g = start;
+ int r = font::res;
+ int gap = r/GAP_WIDTH_ONE_LINE;
+ int n = count_columns(col);
+ int left;
+
+ // firstly reset the used field
+ for (i=0; i<n; i++) {
+ col[i].is_used = 0;
+ }
+ // now calculate the left hand hits
+ while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
+ i=0;
+ while ((col[i].left < g->minh) && (col[i].left != 0)) {
+ i++;
+ }
+ if ((col[i].left == g->minh) && (col[i].left != 0)) {
+ col[i].is_used++;
+ }
+ page_contents->words.move_right();
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+ g=page_contents->words.get_data();
+ }
+ }
+ // now remove any column which is less than the
+ // minimal gap for one hit.
+ // column 0 is excempt
+
+ left = col[0].left;
+ i=1;
+ while (i<count_columns(col)) {
+ if (col[i].is_used == 1) {
+ if (col[i].left - left < gap) {
+ col[i-1].right = col[i].right;
+ remove_entry_in_line(col, i);
+ left = col[i].left;
+ } else {
+ left = col[i].left;
+ i++;
+ }
+ } else {
+ left = col[i].left;
+ i++;
+ }
+ }
+}
+
+/*
+ * found_use_for_table - checks whether the some words on one line directly match
+ * the horizontal alignment of the line below.
+ */
+
+int html_printer::found_use_for_table (text_glob *start)
+{
+ text_glob *t;
+ struct text_defn all_words [MAX_WORDS_PER_LINE];
+ struct text_defn last_raw [MAX_WORDS_PER_LINE];
+ struct text_defn next_line [MAX_WORDS_PER_LINE];
+ struct text_defn prev_guess[MAX_WORDS_PER_LINE];
+ struct text_defn last_guess[MAX_WORDS_PER_LINE];
+ struct text_defn next_guess[MAX_WORDS_PER_LINE];
+ int i =0;
+ int lines =0;
+ int mingap=calculate_min_gap(start);
+ int limit;
+
+#if 0
+ if (strcmp(start->text_string, "man") == 0) {
+ stop();
+ }
+#endif
+
+ // get first set of potential columns into line1
+ limit = collect_columns(last_guess, 0, MAX_WORDS_PER_LINE);
+ copy_line(last_raw, last_guess);
+ // add_right_full_width(last_guess, mingap); // adds extra right column to bring table to full width
+
+ copy_line(all_words, last_guess);
+ indentation.vertical_limit = limit;
+
+ if (page_contents->words.is_equal_to_head() || (limit == 0)) {
+ next_line[0].left = 0;
+ next_line[0].right = 0;
+ } else {
+ // and get the next line for finding columns
+ limit = collect_columns(next_line, last_guess, MAX_WORDS_PER_LINE);
+ lines++;
+ }
+
+ // now check to see whether the first line looks like a single centered line
+
+ if (single_centered_line(last_raw, next_line, start)) {
+ rewind_text_to(start);
+ write_centered_line(start);
+ indentation.no_of_columns = 0; // center instead
+ return( TRUE );
+ } else if (! table_on) {
+ rewind_text_to(start);
+ return( FALSE );
+ }
+
+ combine_line(all_words, next_line);
+ if (debug_table_on) {
+ display_columns(start->text_string, "[b] all_words", all_words);
+ }
+
+ if ((! remove_white_using_words(next_guess, last_guess, next_line))) {
+ }
+
+ if ((! conflict_with_words(next_guess, all_words)) &&
+ (continue_searching_column(next_guess, next_guess, all_words)) &&
+ (! page_contents->words.is_equal_to_head()) &&
+ ((end_region_vpos < 0) || (limit < end_region_vpos)) &&
+ (limit > 0)) {
+
+ combine_line(last_guess, next_line);
+ // subtract any columns which are bridged by a sequence of words
+ do {
+ copy_line(prev_guess, next_guess);
+ combine_line(last_guess, next_guess);
+
+ if (debug_table_on) {
+ t = page_contents->words.get_data();
+ display_columns(t->text_string, "[l] last_guess", last_guess);
+ }
+ indentation.vertical_limit = limit;
+
+ copy_line(last_raw, next_line);
+ if (page_contents->words.is_equal_to_head()) {
+ next_line[0].left = 0;
+ next_line[0].right = 0;
+ } else {
+ limit = collect_columns(next_line, last_guess, MAX_WORDS_PER_LINE);
+ lines++;
+ }
+
+ combine_line(all_words, next_line);
+ if (debug_table_on) {
+ display_columns(t->text_string, "[l] all_words", all_words);
+ display_columns(t->text_string, "[l] last_raw ", last_raw);
+ }
+
+ if (debug_table_on) {
+ display_columns(t->text_string, "[l] next_line", next_line);
+ }
+ t = page_contents->words.get_data();
+#if 0
+ if (strcmp(t->text_string, "market,") == 0) {
+ stop();
+ }
+#endif
+
+ } while ((! remove_white_using_words(next_guess, last_guess, next_line)) &&
+ (! conflict_with_words(next_guess, all_words)) &&
+ (continue_searching_column(next_guess, last_guess, all_words)) &&
+ ((is_continueous_column(prev_guess, last_raw)) || (is_exact_left(last_guess, next_line))) &&
+ (! page_contents->words.is_equal_to_head()) &&
+ ((end_region_vpos <= 0) || (t->minv < end_region_vpos)) &&
+ (limit >= 0));
+ }
+ lines--;
+
+ if (limit < 0) {
+ indentation.vertical_limit = limit;
+ }
+
+ if (page_contents->words.is_equal_to_head()) {
+ // end of page check whether we should include everything
+ if ((! conflict_with_words(next_guess, all_words)) &&
+ (continue_searching_column(next_guess, last_guess, all_words)) &&
+ ((is_continueous_column(prev_guess, last_raw)) || (is_exact_left(last_guess, next_line)))) {
+ // end of page reached - therefore include everything
+ page_contents->words.start_from_tail();
+ t = page_contents->words.get_data();
+ indentation.vertical_limit = t->minv;
+ }
+ } else {
+ t = page_contents->words.get_data();
+ if ((end_region_vpos > 0) && (t->minv > end_region_vpos)) {
+ indentation.vertical_limit = min(indentation.vertical_limit, end_region_vpos+1);
+ } else if (indentation.vertical_limit < 0) {
+ // -1 as we don't want to include section heading itself
+ indentation.vertical_limit = -indentation.vertical_limit-1;
+ }
+ }
+
+ if (debug_table_on) {
+ display_columns(start->text_string, "[x] last_guess", last_guess);
+ }
+ rewind_text_to(start);
+
+ i = count_columns(last_guess);
+ if (((lines > 2) && ((i>1) || (continue_searching_column(last_guess, last_guess, all_words)))) ||
+ ((lines == 1) && (large_enough_gap(last_guess)))) {
+ // copy match into permenant html_table
+
+ if (indentation.columns != 0) {
+ free(indentation.columns);
+ }
+ if (debug_table_on) {
+ display_columns(start->text_string, "[x] last_guess", last_guess);
+ }
+ add_column_gaps(last_guess);
+ if (debug_table_on) {
+ display_columns(start->text_string, "[g] last_guess", last_guess);
+ }
+
+ indentation.no_of_columns = count_columns(last_guess);
+ indentation.columns = (struct text_defn *)malloc(indentation.no_of_columns*sizeof(struct text_defn));
+
+ i=0;
+ while (i<indentation.no_of_columns) {
+ indentation.columns[i].left = last_guess[i].left;
+ indentation.columns[i].right = last_guess[i].right;
+ i++;
+ }
+ return( TRUE );
+ } else {
+ return( FALSE );
+ }
+}
+
+void html_printer::define_cell (int left, int right)
+{
+ float f=((float)(right-left))/((float)(right_margin_indent-left_margin_indent))*100.0;
+
+ html.put_string("<td valign=\"top\" align=\"left\" width=\"");
+ if (f > 1.0) {
+ html.put_float(f);
+ } else {
+ html.put_float(1.0);
+ }
+ html.put_string("%\">\n");
+}
+
+/*
+ * column_display_word - given a left, right pair and the indentation.vertical_limit
+ * write out html text within this region.
+ */
+
+void html_printer::column_display_word (int vert, int left, int right, int next)
+{
+ text_glob *g=page_contents->words.get_data();
+
+ if (left != next) {
+ define_cell(left, next);
+ begin_paragraph_no_height(left_alignment);
+ while ((g != 0) && (g->minv <= vert)) {
+ if ((left <= g->minh) && (g->minh<right)) {
+ char *postword=html_position_text(g, left, right);
+
+ if (header.written_header) {
+ fatal("should never generate a header inside a table");
+ } else {
+ if (g->is_raw_command) {
+ html.put_string((char *)g->text_string);
+ } else {
+ html.html_write_string((char *)g->text_string);
+ }
+ if (postword != 0) {
+ html.put_string(postword);
+ }
+ issued_newline = FALSE;
+ }
+ }
+ if (page_contents->words.is_equal_to_tail()) {
+ g = 0;
+ } else {
+ page_contents->words.move_right();
+ g=page_contents->words.get_data();
+ }
+#if 0
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+
+ }
+#endif
+ }
+ end_paragraph();
+ html.put_string("</td>\n");
+ if (g != 0) {
+ page_contents->words.move_left();
+ // and correct output_vpos
+ g=page_contents->words.get_data();
+ output_vpos = g->minv;
+ }
+ }
+}
+
+/*
+ * start_table - creates a table according with parameters contained within class html_table.
+ */
+
+void html_printer::start_table (void)
+{
+ int i;
+
+ end_paragraph();
+ html.put_string("\n<table width=\"100%\" rules=\"none\" frame=\"none\" cols=\"");
+ html.put_number(indentation.no_of_columns);
+ html.put_string("\">\n");
+}
+
+/*
+ * end_table - finishes off a table.
+ */
+
+void html_printer::end_table (void)
+{
+ html.put_string("</table>\n");
+ indentation.no_of_columns = 0;
+}
+
+/*
+ * column_calculate_right_margin - scan through the column and find the right most margin
+ */
+
+int html_printer::column_calculate_right_margin (int left, int right)
+{
+ if (left == right) {
+ return( right );
+ } else {
+ int rightmost =-1;
+ int count = 0;
+ text_glob *start = page_contents->words.get_data();
+ text_glob *g = start;
+
+ while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
+ if ((left <= g->minh) && (g->minh<right)) {
+ if (debug_on) {
+ fprintf(stderr, "right word = %s %d\n", g->text_string, g->maxh); fflush(stderr);
+ }
+ if (g->maxh == rightmost) {
+ count++;
+ } else if (g->maxh > rightmost) {
+ count = 1;
+ rightmost = g->maxh;
+ }
+ if (g->maxh > right) {
+ if (debug_on) {
+ fprintf(stderr, "problem as right word = %s %d [%d..%d]\n",
+ g->text_string, right, g->minh, g->maxh); fflush(stderr);
+ stop();
+ }
+ }
+ }
+ page_contents->words.move_right();
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+ g=page_contents->words.get_data();
+ }
+ }
+ rewind_text_to(start);
+ if (rightmost == -1) {
+ return( right ); // no words in this column
+ } else {
+ if (count == 1) {
+ return( rightmost+1 );
+ } else {
+ return( rightmost );
+ }
+ }
+ }
+}
+
+/*
+ * column_calculate_left_margin - scan through the column and find the left most margin
+ */
+
+int html_printer::column_calculate_left_margin (int left, int right)
+{
+ if (left == right) {
+ return( left );
+ } else {
+ int leftmost=right;
+ text_glob *start = page_contents->words.get_data();
+ text_glob *g = start;
+
+ while ((g != 0) && (g->minv <= indentation.vertical_limit)) {
+ if ((left <= g->minh) && (g->minh<right)) {
+ leftmost = min(g->minh, leftmost);
+ }
+ page_contents->words.move_right();
+ if (page_contents->words.is_equal_to_head()) {
+ g = 0;
+ page_contents->words.start_from_tail();
+ } else {
+ g=page_contents->words.get_data();
+ }
+ }
+ rewind_text_to(start);
+ if (leftmost == right) {
+ return( left ); // no words in this column
+ } else {
+ return( leftmost );
+ }
+ }
+}
+
+/*
+ * find_column_index - returns the index to the column in which glob, t, exists.
+ */
+
+int html_printer::find_column_index (text_glob *t)
+{
+ int i=0;
+
+ while ((i<indentation.no_of_columns) &&
+ (! ((indentation.columns[i].left<=t->minh) &&
+ (indentation.columns[i].right>t->minh)))) {
+ i++;
+ }
+ return( i );
+}
+
+/*
+ * determine_row_limit - checks each row to see if there is a gap in a cell.
+ * We return the vertical position after the empty cell
+ * at the start of the next line.
+ */
+
+int html_printer::determine_row_limit (text_glob *start, int v)
+{
+ text_glob *t;
+ int i;
+ int vpos, prev, last;
+ int is_gap[MAX_WORDS_PER_LINE];
+
+ if (v >= indentation.vertical_limit) {
+ return( v+1 );
+ } else {
+ // initially we start with all gaps in our table
+ // after a gap we start a new row
+ // here we set the gap array to the previous line
+
+ if (v>=0) {
+ t = page_contents->words.get_data();
+ if (t->minv < v) {
+ do {
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ (t->minv <= v));
+ }
+ }
+ if (! page_contents->words.is_equal_to_head()) {
+ page_contents->words.move_left();
+ }
+ t = page_contents->words.get_data();
+ prev = t->minv;
+ for (i=0; i<indentation.no_of_columns; i++) {
+ is_gap[i] = prev;
+ }
+
+ if (! page_contents->words.is_equal_to_tail()) {
+ page_contents->words.move_right();
+ }
+ t = page_contents->words.get_data();
+ vpos = t->minv;
+
+ // now check each row for a gap
+ do {
+ last = vpos;
+ vpos = t->minv;
+ i = find_column_index(t);
+ if (! is_on_same_line(t, last)) {
+ prev = last;
+ }
+
+ if ((is_gap[i] != vpos) && (is_gap[i] != prev) &&
+ (indentation.columns[i].is_used)) {
+ // no word on previous line - must be a gap - force alignment of row
+ rewind_text_to(start);
+ return( last );
+ }
+ is_gap[i] = vpos;
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ } while ((! page_contents->words.is_equal_to_head()) &&
+ (vpos < indentation.vertical_limit) && (vpos >= last));
+ page_contents->words.move_left();
+ t = page_contents->words.get_data();
+ rewind_text_to(start);
+ return( indentation.vertical_limit );
+ }
+}
+
+/*
+ * assign_used_columns - sets the is_used field of the column array of records.
+ */
+
+void html_printer::assign_used_columns (text_glob *start)
+{
+ text_glob *t = start;
+ int i;
+
+ for (i=0; i<indentation.no_of_columns; i++) {
+ indentation.columns[i].is_used = FALSE;
+ }
+
+ rewind_text_to(start);
+ if (! page_contents->words.is_empty()) {
+ do {
+ i = find_column_index(t);
+ if (indentation.columns[i].left != 0) {
+ if (debug_table_on) {
+ fprintf(stderr, "[%s] in column %d at %d..%d limit %d\n", t->text_string,
+ i, t->minv, t->maxv, indentation.vertical_limit); fflush(stderr);
+ }
+ indentation.columns[i].is_used = TRUE;
+ }
+ page_contents->words.move_right();
+ t = page_contents->words.get_data();
+ } while ((t->minv<indentation.vertical_limit) &&
+ (! page_contents->words.is_equal_to_head()));
+ }
+ if (debug_table_on) {
+ for (i=0; i<indentation.no_of_columns; i++) {
+ fprintf(stderr, " <left=%d right=%d is_used=%d> ",
+ indentation.columns[i].left,
+ indentation.columns[i].right,
+ indentation.columns[i].is_used);
+ }
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+}
+
+/*
+ * foreach_column_include_text - foreach column in a table place the
+ * appropriate html text.
+ */
+
+void html_printer::foreach_column_include_text (text_glob *start)
+{
+ if (indentation.no_of_columns>0) {
+ int i;
+ int left, right;
+ int limit=-1;
+
+ assign_used_columns(start);
+ start_table();
+ rewind_text_to(start);
+
+ do {
+ limit = determine_row_limit(start, limit); // find the bottom of the next row
+ html.put_string("<tr valign=\"top\" align=\"left\">\n");
+ i=0;
+ start = page_contents->words.get_data();
+ while (i<indentation.no_of_columns) {
+ // reset the output position to the start of column
+ rewind_text_to(start);
+ output_vpos = start->minv;
+ output_hpos = indentation.columns[i].left;
+ // and display each column until limit
+ right = column_calculate_right_margin(indentation.columns[i].left,
+ indentation.columns[i].right);
+ left = column_calculate_left_margin(indentation.columns[i].left,
+ indentation.columns[i].right);
+
+ if (right>indentation.columns[i].right) {
+ if (debug_on) {
+ fprintf(stderr, "assert calculated right column edge is greater than column\n"); fflush(stderr);
+ stop();
+ }
+ }
+
+ if (left<indentation.columns[i].left) {
+ if (debug_on) {
+ fprintf(stderr, "assert calculated left column edge is less than column\n"); fflush(stderr);
+ stop();
+ }
+ }
+
+ column_display_word(limit, left, right, indentation.columns[i].right);
+ i++;
+ }
+
+ if (page_contents->words.is_equal_to_tail()) {
+ start = 0;
+ } else {
+ page_contents->words.sub_move_right();
+ if (page_contents->words.is_empty()) {
+ start = 0;
+ } else {
+ start = page_contents->words.get_data();
+ }
+ }
+
+ html.put_string("</tr>\n");
+ } while ((limit < indentation.vertical_limit) && (start != 0) &&
+ (! page_contents->words.is_empty()));
+ end_table();
+
+ if (start == 0) {
+ // finished page remove all words
+ page_contents->words.start_from_head();
+ while (! page_contents->words.is_empty()) {
+ page_contents->words.sub_move_right();
+ }
+ } else if (! page_contents->words.is_empty()) {
+ page_contents->words.move_left();
+ }
+ }
+}
+
+/*
+ * write_centered_line - generates a line of centered text.
+ */
+
+void html_printer::write_centered_line (text_glob *g)
+{
+ int current_vpos=g->minv;
+
+ move_vertical(g, center_alignment);
+
+ header.written_header = FALSE;
+ output_vpos = g->minv;
+ output_hpos = g->minh;
+ do {
+ char *postword=html_position_text(g, left_margin_indent, right_margin_indent);
+
+ if (! header.written_header) {
+ if (g->is_raw_command) {
+ html.put_string((char *)g->text_string);
+ } else {
+ html.html_write_string((char *)g->text_string);
+ }
+ if (postword != 0) {
+ html.put_string(postword);
+ }
+ need_one_newline = TRUE;
+ issued_newline = FALSE;
+ }
+ page_contents->words.move_right();
+ g = page_contents->words.get_data();
+ } while ((! page_contents->words.is_equal_to_head()) && (g->minv == current_vpos));
+ page_contents->words.move_left(); // so when we move right we land on the word following this centered line
+ need_one_newline = TRUE;
+}
+
+/*
+ * is_in_middle - returns TRUE if the text defn, t, is in the middle of the page.
+ */
+
+int html_printer::is_in_middle (int left, int right)
+{
+ return( abs(abs(left-left_margin_indent) - abs(right_margin_indent-right)) <= CENTER_TOLERANCE );
+}
+
+/*
+ * single_centered_line - returns TRUE if first is a centered line with a different
+ * margin to second.
+ */
+
+int html_printer::single_centered_line (text_defn *first, text_defn *second, text_glob *g)
+{
+ return(
+ ((count_columns(first) == 1) && (first[0].left != left_margin_indent) &&
+ (first[0].left != second[0].left) && is_in_middle(first->left, first->right))
+ );
+}
+
+/*
+ * check_able_to_use_center - returns TRUE if we can see a centered line.
+ */
+
+int html_printer::check_able_to_use_center (text_glob *g)
+{
+ if (auto_on && table_on && ((! is_on_same_line(g, output_vpos)) || issued_newline) && (! using_table_for_indent())) {
+ // we are allowed to check for centered line
+ // first check to see whether we might be looking at a set of columns
+ struct text_defn last_guess[MAX_WORDS_PER_LINE];
+ int limit = collect_columns(last_guess, 0, MAX_WORDS_PER_LINE);
+
+ rewind_text_to(g);
+ if ((count_columns(last_guess) == 1) && (is_in_middle(last_guess[0].left, last_guess[0].right))) {
+ write_centered_line(g);
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * check_able_to_use_table - examines forthcoming text to see whether we can
+ * better format it by using an html transparent table.
+ */
+
+int html_printer::check_able_to_use_table (text_glob *g)
+{
+ if (auto_on && ((! is_on_same_line(g, output_vpos)) || issued_newline) && (! using_table_for_indent())) {
+ // we are allowed to check for table
+
+ if ((output_hpos != right_margin_indent) && (found_use_for_table(g))) {
+ foreach_column_include_text(g);
+ return( TRUE );
+ }
+ }
+ return( FALSE );
+}
+
+/*
+ * move_vertical - if we are using html auto formatting then decide whether to
+ * break the line via a <br> or a </p><p> sequence.
+ */
+
+void html_printer::move_vertical (text_glob *g, paragraph_type p)
+{
+ int r =font::res;
+ int height = (g->text_style.point_size+2)*r/72; // --fixme-- we always assume VS is PS+2 (could do better)
+ int temp_vpos;
+
+ if (auto_on) {
+ if ((more_than_line_break(output_vpos, g->minv, height)) || (p != para_type)) {
+ end_paragraph();
+ begin_paragraph(p);
+ } else {
+ html_newline();
+ }
+ } else {
+ if (output_vpos == -1) {
+ temp_vpos = g->minv;
+ } else {
+ temp_vpos = output_vpos;
+ }
+
+ force_begin_paragraph();
+ if (need_one_newline) {
+ html_newline();
+ temp_vpos += height;
+ } else {
+ need_one_newline = TRUE;
+ }
+
+ while ((temp_vpos < g->minv) && (more_than_line_break(temp_vpos, g->minv, height))) {
+ html_newline();
+ temp_vpos += height;
+ }
+ }
+}
+
+/*
+ * emit_space - emits a space within html, it checks for the font type and
+ * will change font depending upon, g. Courier spaces are larger
+ * than roman so we need consistancy when changing between them.
+ */
+
+void html_printer::emit_space (text_glob *g, int force_space)
+{
+ if (! need_paragraph) {
+ // only generate a space if we have written a word - as html will ignore it otherwise
+ if ((output_style != g->text_style) && (g->text_style.f != 0)) {
+ terminate_current_font();
+ }
+ if (force_space || (g->minh > output_hpos)) {
+ html.put_string(" ");
+ }
+ change_font(g, TRUE);
+ }
+}
+
+/*
+ * html_position_text - determine whether the text is subscript/superscript/normal
+ * or a header.
+ */
+
+char *html_printer::html_position_text (text_glob *g, int left_margin, int right_margin)
+{
+ char *postword=0;
+
+#if 0
+ if (strcmp(g->text_string, "increased.") == 0) {
+ stop();
+ }
+#endif
+ begin_paragraph(left_alignment);
+
+ if ((! header.written_header) &&
+ (is_on_same_line(g, output_vpos) ||
+ pretend_is_on_same_line(g, left_margin, right_margin))) {
+ // check whether the font was reset after generating an image
+
+ header.written_header = FALSE;
+ force_begin_paragraph();
+
+ // check whether we need to insert white space between words on 'same' line
+ if (pretend_is_on_same_line(g, left_margin, right_margin)) {
+ emit_space(g, TRUE);
+ }
+
+ if (output_style.f == 0) {
+ change_font(g, TRUE);
+ }
+
+ if (looks_like_subscript(g)) {
+
+ g->text_style.point_size = output_style.point_size;
+ g->minv = output_vpos; // this ensures that output_vpos doesn't alter
+ // which allows multiple subscripted words
+ move_horizontal(g, left_margin);
+ html.put_string("<sub>");
+ postword = "</sub>";
+ } else if (looks_like_superscript(g)) {
+
+ g->text_style.point_size = output_style.point_size;
+ g->minv = output_vpos;
+
+ move_horizontal(g, left_margin);
+ html.put_string("<sup>");
+ postword = "</sup>";
+ } else {
+ move_horizontal(g, left_margin);
+ }
+ } else {
+ // we have found a new line
+ if (! header.written_header) {
+ move_vertical(g, left_alignment);
+ }
+ header.written_header = FALSE;
+
+ if (processed_header(g)) {
+ // we must not alter output_vpos as we have peeped at the next word
+ // and set vpos to this - to ensure we do not generate a <br> after
+ // a heading. (The html heading automatically generates a line break)
+ output_hpos = left_margin;
+ return( postword );
+ } else {
+ force_begin_paragraph();
+ if (g->minh-left_margin != 0) {
+ make_html_indent(g->minh-left_margin);
+ }
+ change_font(g, TRUE);
+ }
+ }
+ output_vpos = g->minv;
+ output_hpos = g->maxh;
+ return( postword );
+}
+
+
+int html_printer::html_position_region (void)
+{
+ int r = font::res;
+ int height = output_style.point_size*r/72;
+ int temp_vpos;
+ int is_center = FALSE;
+
+ if (output_style.point_size != 0) {
+ if (output_vpos != start_region_vpos) {
+
+ // graphic starts on a different line
+ if (output_vpos == -1) {
+ temp_vpos = start_region_vpos;
+ } else {
+ temp_vpos = output_vpos;
+ }
+
+#if 1
+ if (need_one_newline) {
+ html_newline();
+ temp_vpos += height;
+ } else {
+ need_one_newline = TRUE;
+ }
+#else
+ html_newline();
+ temp_vpos += height;
+#endif
+
+ while ((temp_vpos < start_region_vpos) &&
+ (more_than_line_break(temp_vpos, start_region_vpos, height))) {
+ html_newline();
+ temp_vpos += height;
+ }
+ }
+ }
+ if (auto_on && (is_in_middle(start_region_hpos, end_region_hpos))) {
+ is_center = TRUE;
+ } else {
+ if (start_region_hpos > left_margin_indent) {
+ html.put_string("<span style=\" text-indent: ");
+ html.put_float(((double)(start_region_hpos-left_margin_indent)/((double)r)));
+ html.put_string("in;\"></span>");
+ }
+ }
+#if 0
+ } else {
+ // on the same line
+ if (start_region_hpos > output_hpos) {
+ html.put_string("<span style=\" text-indent: ");
+ html.put_float(((double)(start_region_hpos-output_hpos)/((double)r)));
+ html.put_string("in;\"></span>");
+ }
+ }
+ }
+#endif
+ output_vpos = start_region_vpos;
+ output_hpos = start_region_hpos;
+ return( is_center );
+}
+
+
+/*
+ * gs_x - translate and scale the x axis
+ */
+
+int html_printer::gs_x (int x)
+{
+ x += IMAGE_BOARDER_PIXELS/2;
+ return((x-start_region_hpos)*postscript_res/font::res);
+}
+
+
+/*
+ * gs_y - translate and scale the y axis
+ */
+
+int html_printer::gs_y (int y)
+{
+ int yoffset=((int)(A4_PAGE_LENGTH*(double)font::res))-end_region_vpos;
+
+ y += IMAGE_BOARDER_PIXELS/2;
+ return( (y+yoffset)*postscript_res/font::res );
+}
+
+
+void html_printer::troff_position_text (text_glob *g)
+{
+ change_font(g, FALSE);
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->maxv));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->minh));
+ troff.put_string("\n");
+}
+
+void html_printer::troff_change_font (const char *fontname, int size, int font_no)
+{
+ troff.put_string("x font ");
+ troff.put_number(font_no);
+ troff.put_string(" ");
+ troff.put_string(fontname);
+ troff.put_string("\nf");
+ troff.put_number(font_no);
+ troff.put_string("\ns");
+ troff.put_number(size*1000);
+ troff.put_string("\n");
+}
+
+
+void html_printer::set_style(const style &sty)
+{
+#if 0
+ const char *fontname = sty.f->get_name();
+ if (fontname == 0)
+ fatal("no internalname specified for font");
+
+ change_font(fontname, (font::res/(72*font::sizescale))*sty.point_size);
+#endif
+}
+
+void html_printer::end_of_line()
+{
+ flush_sbuf();
+ output_hpos = -1;
+}
+
+void html_printer::html_display_word (text_glob *g)
+{
+#if 0
+ if (strcmp(g->text_string, "increased.") == 0) {
+ stop();
+ }
+#endif
+ if (! check_able_to_use_table(g)) {
+ char *postword=html_position_text(g, left_margin_indent, right_margin_indent);
+
+ if (! header.written_header) {
+ if (g->is_raw_command) {
+ html.put_string((char *)g->text_string);
+ } else {
+ html.html_write_string((char *)g->text_string);
+ }
+ if (postword != 0) {
+ html.put_string(postword);
+ }
+ need_one_newline = TRUE;
+ issued_newline = FALSE;
+ }
+ }
+}
+
+void html_printer::troff_display_word (text_glob *g)
+{
+ troff_position_text(g);
+ if (g->is_raw_command) {
+ int l=strlen((char *)g->text_string);
+ if (l == 1) {
+ troff.put_string("c");
+ troff.put_string((char *)g->text_string);
+ troff.put_string("\n");
+ } else if (l > 1) {
+ troff.put_string("C");
+ troff.put_translated_char((char *)g->text_string);
+ troff.put_string("\n");
+ }
+ } else {
+ troff_position_text(g);
+ troff.put_string("t");
+ troff.put_translated_string((const char *)g->text_string);
+ troff.put_string("\n");
+ }
+}
+
+void html_printer::display_word (text_glob *g, int is_to_html)
+{
+ if (is_to_html) {
+ html_display_word(g);
+ } else if ((g->is_raw_command) && (g->is_html_command)) {
+ // found a raw html command inside a graphic glob.
+ // We should emit the command to the html device, but of course we
+ // cannot place it correctly as we are dealing with troff words.
+ // Remember output_vpos will refer to troff and not html.
+ html.put_string((char *)g->text_string);
+ } else {
+ troff_display_word(g);
+ }
+}
+
+
+/*
+ * this information may be better placed inside some of the font files
+ * in devhtml - however one must bare in mind that we need the ability
+ * to write out to TWO devices (image and html) and image
+ * invokes ghostscript.
+ */
+
+simple_output &simple_output::html_write_string (const char *s)
+{
+ int i=0;
+
+ while (s[i] != (char)0) {
+ if (s[i] == '<') {
+ put_string("&lt;");
+ } else if (s[i] == '>') {
+ put_string("&gt;");
+ } else {
+ fputc(s[i], fp);
+ col++;
+ }
+ i++;
+ }
+ return *this;
+}
+
+/*
+ * display_fill - generates a troff format fill command
+ */
+
+void html_printer::display_fill (graphic_glob *g)
+{
+ troff.put_string("Df ") ;
+ troff.put_number(g->fill);
+ troff.put_string(" 0\n");
+}
+
+/*
+ * display_line - displays a line using troff format
+ */
+
+void html_printer::display_line (graphic_glob *g, int is_to_html)
+{
+ if (is_to_html) {
+ fatal("cannot emit lines in html");
+ }
+ if (g->code == 'l') {
+ // straight line
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->point[0].y));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->point[0].x));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ troff.put_string("Dl ");
+ troff.put_number((g->point[1].x-g->point[0].x)*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number((g->point[1].y-g->point[0].y)*postscript_res/font::res);
+ troff.put_string("\n");
+ // printf("line %c %d %d %d %d size %d\n", (char)g->code, g->point[0].x, g->point[0].y,
+ // g->point[1].x, g->point[1].y, g->size);
+ } else if ((g->code == 'c') || (g->code == 'C')) {
+ // circle
+
+ int xradius = (g->maxh - g->minh) / 2;
+ int yradius = (g->maxv - g->minv) / 2;
+ // center of circle or elipse
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->minv+yradius));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->minh));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ if (g->code == 'c') {
+ troff.put_string("Dc ");
+ } else {
+ troff.put_string("DC ");
+ }
+
+ troff.put_number(xradius*2*postscript_res/font::res);
+ troff.put_string("\n");
+
+ } else if ((g->code == 'e') || (g->code == 'E')) {
+ // ellipse
+
+ int xradius = (g->maxh - g->minh) / 2;
+ int yradius = (g->maxv - g->minv) / 2;
+ // center of elipse - this is untested
+
+ troff.put_string("V");
+ troff.put_number(gs_y(g->minv+yradius));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->minh));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ if (g->code == 'e') {
+ troff.put_string("De ");
+ } else {
+ troff.put_string("DE ");
+ }
+
+ troff.put_number(xradius*2*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number(yradius*2*postscript_res/font::res);
+ troff.put_string("\n");
+ } else if ((g->code == 'p') || (g->code == 'P')) {
+ // polygon
+ troff.put_string("V");
+ troff.put_number(gs_y(g->yc));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->xc));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ if (g->code == 'p') {
+ troff.put_string("Dp");
+ } else {
+ troff.put_string("DP");
+ }
+
+ int i;
+ int xc=g->xc;
+ int yc=g->yc;
+ for (i=0; i<g->nopoints; i++) {
+ troff.put_string(" ");
+ troff.put_number((g->point[i].x-xc)*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number((g->point[i].y-yc)*postscript_res/font::res);
+ xc = g->point[i].x;
+ yc = g->point[i].y;
+ }
+ troff.put_string("\n");
+ } else if (g->code == 'a') {
+ // arc
+ troff.put_string("V");
+ troff.put_number(gs_y(g->yc));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->xc));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ troff.put_string("Da");
+
+ int i;
+
+ for (i=0; i<g->nopoints; i++) {
+ troff.put_string(" ");
+ troff.put_number(g->point[i].x*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number(g->point[i].y*postscript_res/font::res);
+ }
+ troff.put_string("\n");
+ } else if (g->code == '~') {
+ // spline
+ troff.put_string("V");
+ troff.put_number(gs_y(g->yc));
+ troff.put_string("\n");
+
+ troff.put_string("H");
+ troff.put_number(gs_x(g->xc));
+ troff.put_string("\n");
+
+ display_fill(g);
+
+ troff.put_string("D~");
+
+ int i;
+ int xc=g->xc;
+ int yc=g->yc;
+ for (i=0; i<g->nopoints; i++) {
+ troff.put_string(" ");
+ troff.put_number((g->point[i].x-xc)*postscript_res/font::res);
+ troff.put_string(" ");
+ troff.put_number((g->point[i].y-yc)*postscript_res/font::res);
+ xc = g->point[i].x;
+ yc = g->point[i].y;
+ }
+ troff.put_string("\n");
+ }
+}
+
+
+void html_printer::flush_sbuf()
+{
+ if (sbuf_len > 0) {
+ int r=font::res; // resolution of the device actually
+ set_style(sbuf_style);
+
+ page_contents->add(&sbuf_style, sbuf, sbuf_len,
+ sbuf_vpos-sbuf_style.point_size*r/72, sbuf_start_hpos,
+ sbuf_vpos, sbuf_end_hpos);
+
+ output_hpos = sbuf_end_hpos;
+ output_vpos = sbuf_vpos;
+ sbuf_len = 0;
+ }
+
+#if 0
+ 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) {
+ 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)
+ html.put_number(extra_space);
+ if (sbuf_kern != 0)
+ html.put_number(sbuf_kern);
+
+ html.put_string(sbuf, sbuf_len);
+
+ char sym[2];
+ sym[0] = 'A' + motion*4 + space_flag + 2*(sbuf_kern != 0);
+ sym[1] = '\0';
+ switch (motion) {
+ case NONE:
+ break;
+ case ABSOLUTE:
+ html.put_number(sbuf_start_hpos)
+ .put_number(sbuf_vpos);
+ break;
+ case RELATIVE_H:
+ html.put_number(sbuf_start_hpos - output_hpos);
+ break;
+ case RELATIVE_V:
+ html.put_number(sbuf_vpos - output_vpos);
+ break;
+ case RELATIVE_HV:
+ html.put_number(sbuf_start_hpos - output_hpos)
+ .put_number(sbuf_vpos - output_vpos);
+ break;
+ default:
+ assert(0);
+ }
+
+ output_hpos = sbuf_end_hpos;
+ output_vpos = sbuf_vpos;
+ sbuf_len = 0;
+#endif
+}
+
+
+void html_printer::set_line_thickness(const environment *env)
+{
+ line_thickness = env->size;
+ printf("line thickness = %d\n", line_thickness);
+}
+
+void html_printer::draw(int code, int *p, int np, const environment *env)
+{
+ switch (code) {
+
+ case 'l':
+ if (np == 2) {
+ page_contents->add_line(code,
+ env->hpos, env->vpos, env->hpos+p[0], env->vpos+p[1],
+ env->size, fill);
+ } else {
+ error("2 arguments required for line");
+ }
+ break;
+ case 't':
+ {
+ if (np == 0) {
+ line_thickness = -1;
+ } else {
+ // troff gratuitously adds an extra 0
+ if (np != 1 && np != 2) {
+ error("0 or 1 argument required for thickness");
+ break;
+ }
+ line_thickness = p[0];
+ }
+ break;
+ }
+
+ case 'P':
+ // fall through
+ case 'p':
+ {
+ if (np & 1) {
+ error("even number of arguments required for polygon");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for polygon");
+ break;
+ }
+ // firstly lets add our current position to polygon
+ int oh=env->hpos;
+ int ov=env->vpos;
+ int i=0;
+
+ while (i<np) {
+ p[i+0] += oh;
+ p[i+1] += ov;
+ oh = p[i+0];
+ ov = p[i+1];
+ i += 2;
+ }
+ // now store polygon in page
+ page_contents->add_polygon(code, np, p, env->hpos, env->vpos, env->size, fill);
+ }
+ break;
+ case 'E':
+ // fall through
+ case 'e':
+ if (np != 2) {
+ error("2 arguments required for ellipse");
+ break;
+ }
+ page_contents->add_line(code,
+ env->hpos, env->vpos-p[1]/2, env->hpos+p[0], env->vpos+p[1]/2,
+ env->size, fill);
+
+ break;
+ case 'C':
+ // fill circle
+
+ case 'c':
+ {
+ // troff adds an extra argument to C
+ if (np != 1 && !(code == 'C' && np == 2)) {
+ error("1 argument required for circle");
+ break;
+ }
+ page_contents->add_line(code,
+ env->hpos, env->vpos-p[0]/2, env->hpos+p[0], env->vpos+p[0]/2,
+ env->size, fill);
+ }
+ break;
+ case 'a':
+ {
+ if (np == 4) {
+ double c[2];
+
+ if (adjust_arc_center(p, c)) {
+ page_contents->add_arc('a', env->hpos, env->vpos, p, c, env->size, fill);
+ } else {
+ // a straignt line
+ page_contents->add_line('l', env->hpos, env->vpos, p[0]+p[2], p[1]+p[3], env->size, fill);
+ }
+ } else {
+ error("4 arguments required for arc");
+ }
+ }
+ break;
+ case '~':
+ {
+ if (np & 1) {
+ error("even number of arguments required for spline");
+ break;
+ }
+ if (np == 0) {
+ error("no arguments for spline");
+ break;
+ }
+ // firstly lets add our current position to spline
+ int oh=env->hpos;
+ int ov=env->vpos;
+ int i=0;
+
+ while (i<np) {
+ p[i+0] += oh;
+ p[i+1] += ov;
+ oh = p[i+0];
+ ov = p[i+1];
+ i += 2;
+ }
+ page_contents->add_spline('~', env->hpos, env->vpos, np, p, env->size, fill);
+ }
+ break;
+ case 'f':
+ {
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
+ break;
+ }
+ fill = p[0];
+ if (fill < 0 || fill > FILL_MAX) {
+ // This means fill with the current color.
+ fill = FILL_MAX + 1;
+ }
+ break;
+ }
+
+ default:
+ error("unrecognised drawing command `%1'", char(code));
+ break;
+ }
+}
+
+
+void html_printer::begin_page(int n)
+{
+ page_number = n;
+ html.begin_comment("Page: ").comment_arg(itoa(page_number)).end_comment();;
+ no_of_printed_pages++;
+
+ output_style.f = 0;
+ output_space_code = 32;
+ output_draw_point_size = -1;
+ output_line_thickness = -1;
+ output_hpos = -1;
+ output_vpos = -1;
+}
+
+void testing (text_glob *g) {}
+
+void html_printer::flush_graphic (void)
+{
+ graphic_glob g;
+
+ graphic_level = 0;
+ page_contents->is_in_graphic = FALSE;
+
+ g.minv = -1;
+ g.maxv = -1;
+ calculate_region_range(&g);
+ if (g.minv != -1) {
+ page_contents->make_new_region(&g);
+ }
+ move_region_to_page();
+}
+
+void html_printer::end_page(int)
+{
+ flush_sbuf();
+ flush_graphic();
+ flush_page();
+}
+
+font *html_printer::make_font(const char *nm)
+{
+ return html_font::load_html_font(nm);
+}
+
+html_printer::~html_printer()
+{
+ if (fseek(tempfp, 0L, 0) < 0)
+ fatal("fseek on temporary file failed");
+ html.set_file(stdout);
+ fputs("<html>\n", stdout);
+ fputs("<head>\n", stdout);
+ fputs("<meta name=\"Content-Style\" content=\"text/css\">\n", stdout);
+ write_title(TRUE);
+ fputs("</head>\n", stdout);
+ fputs("<body>\n", stdout);
+ write_title(FALSE);
+ header.write_headings(stdout);
+ {
+ extern const char *version_string;
+ html.begin_comment("Creator : ")
+ .comment_arg("groff ")
+ .comment_arg("version ")
+ .comment_arg(version_string)
+ .end_comment();
+ }
+ {
+#ifdef LONG_FOR_TIME_T
+ long
+#else
+ time_t
+#endif
+ t = time(0);
+ html.begin_comment("CreationDate: ")
+ .comment_arg(ctime(&t))
+ .end_comment();
+ }
+ for (font_pointer_list *f = font_list; f; f = f->next) {
+ html_font *psf = (html_font *)(f->p);
+ }
+ html.begin_comment("Total number of pages: ").comment_arg(itoa(no_of_printed_pages)).end_comment();
+ html.end_line();
+ html.copy_file(tempfp);
+ fputs("</body>\n", stdout);
+ fputs("</html>\n", stdout);
+ fclose(tempfp);
+}
+
+
+/*
+ * calculate_region_range - calculates the vertical range for words and lines
+ * within the region lists.
+ */
+
+void html_printer::calculate_region_range (graphic_glob *r)
+{
+ text_glob *w;
+ graphic_glob *g;
+
+ if (! page_contents->region_lines.is_empty()) {
+ page_contents->region_lines.start_from_head();
+ do {
+ g = page_contents->region_lines.get_data();
+ if ((r->minv == -1) || (g->minv < r->minv)) {
+ r->minv = g->minv;
+ }
+ if ((r->maxv == -1) || (g->maxv > r->maxv)) {
+ r->maxv = g->maxv;
+ }
+ page_contents->region_lines.move_right();
+ } while (! page_contents->region_lines.is_equal_to_head());
+ }
+ if (! page_contents->region_words.is_empty()) {
+ page_contents->region_words.start_from_head();
+ do {
+ w = page_contents->region_words.get_data();
+
+ if ((r->minv == -1) || (w->minv < r->minv)) {
+ r->minv = w->minv;
+ }
+ if ((r->maxv == -1) || (w->maxv > r->maxv)) {
+ r->maxv = w->maxv;
+ }
+ page_contents->region_words.move_right();
+ } while (! page_contents->region_words.is_equal_to_head());
+ }
+}
+
+
+/*
+ * move_region_to_page - moves lines and words held in the temporary region
+ * list to the page list.
+ */
+
+void html_printer::move_region_to_page (void)
+{
+ text_glob *w;
+ graphic_glob *g;
+
+ page_contents->region_lines.start_from_head();
+ while (! page_contents->region_lines.is_empty()) {
+ g = page_contents->region_lines.get_data(); // remove from our temporary region list
+ page_contents->lines.add(g); // and add to the page list
+ page_contents->region_lines.sub_move_right();
+ }
+ page_contents->region_words.start_from_head();
+ while (! page_contents->region_words.is_empty()) {
+ w = page_contents->region_words.get_data(); // remove from our temporary region list
+ page_contents->words.add(w); // and add to the page list
+ page_contents->region_words.sub_move_right();
+ }
+}
+
+
+void html_printer::special(char *s, const environment *env)
+{
+ if (s != 0) {
+ if (strcmp(s, "graphic-start") == 0) {
+ graphic_level++;
+ if (graphic_level == 1) {
+ page_contents->is_in_graphic = TRUE; // add words and lines to temporary region lists
+ }
+ } else if ((strcmp(s, "graphic-end") == 0) && (graphic_level > 0)) {
+ graphic_level--;
+ if (graphic_level == 0) {
+ flush_graphic();
+ }
+ } else if (strncmp(s, "html:", 5) == 0) {
+ int r=font::res; // resolution of the device actually
+
+ page_contents->add_html_command(&sbuf_style, &s[5], strlen(s)-5,
+
+ // need to pass rest of string through to html output during flush
+
+ env->vpos-env->size*r/72, env->hpos,
+ env->vpos , env->hpos);
+ // assume that the html command has no width, if it does then we hopefully troff
+ // will have fudged this in a macro and requested that the formatting move right by
+ // the appropriate width
+ } else if (strncmp(s, "index:", 6) == 0) {
+ cutoff_heading = atoi(&s[6]);
+ }
+ }
+}
+
+void set_image_type (char *type)
+{
+ if (strcmp(type, "gif") == 0) {
+ image_type = gif;
+ } else if (strcmp(type, "png") == 0) {
+ image_type = png;
+ image_device = "png256";
+ } else if (strncmp(type, "png", 3) == 0) {
+ image_type = png;
+ image_device = type;
+ }
+}
+
+// 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;
+}
+
+printer *make_printer()
+{
+ return new html_printer;
+}
+
+static void usage();
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ static char stderr_buf[BUFSIZ];
+ setbuf(stderr, stderr_buf);
+ int c;
+ while ((c = getopt(argc, argv, "F:atvdgmx?I:r:")) != EOF)
+ switch(c) {
+ case 'v':
+ {
+ extern const char *version_string;
+ fprintf(stderr, "grohtml version %s\n", version_string);
+ fflush(stderr);
+ break;
+ }
+ case 'a':
+ auto_on = FALSE;
+ break;
+ case 't':
+ table_on = FALSE;
+ break;
+ case 'F':
+ font::command_line_font_dir(optarg);
+ break;
+ case 'I':
+ // user specifying the type of images we should generate
+ set_image_type(optarg);
+ break;
+ case 'r':
+ // resolution (dots per inch for an image)
+ image_res = atoi(optarg);
+ break;
+ case 'd':
+ // debugging on
+ debug_on = TRUE;
+ break;
+ case 'x':
+ debug_table_on = TRUE;
+ break;
+ case 'g':
+ // do not guess title and headings
+ guess_on = FALSE;
+ break;
+ case 'm':
+ // leave margins alone
+ margin_on = TRUE;
+ break;
+ case '?':
+ usage();
+ break;
+ default:
+ assert(0);
+ }
+ if (optind >= argc) {
+ do_file("-");
+ } else {
+ for (int i = optind; i < argc; i++)
+ do_file(argv[i]);
+ }
+ delete pr;
+ return 0;
+}
+
+static void usage()
+{
+ fprintf(stderr, "usage: %s [-avdgmt?] [-r resolution] [-F dir] [-I imagetype] [files ...]\n",
+ program_name);
+ exit(1);
+}
diff --git a/gnu/usr.bin/groff/grohtml/html.h b/gnu/usr.bin/groff/grohtml/html.h
new file mode 100644
index 00000000000..d61a391a1de
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/html.h
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License along
+with groff; see the file COPYING. If not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+class simple_output {
+public:
+ simple_output(FILE *, int max_line_length);
+ simple_output &put_string(const char *, int);
+ simple_output &put_string(const char *s);
+ simple_output &html_write_string(const char *s);
+ simple_output &put_translated_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_delimiter(char);
+ simple_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 *simple_output::get_file()
+{
+ return fp;
+}
+
diff --git a/gnu/usr.bin/groff/grohtml/ordered_list.h b/gnu/usr.bin/groff/grohtml/ordered_list.h
new file mode 100644
index 00000000000..52fe1c9e605
--- /dev/null
+++ b/gnu/usr.bin/groff/grohtml/ordered_list.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * Ordered list, a template module for simple ordered list manipulation.
+ *
+ * Gaius Mulley (gaius@glam.ac.uk)
+ */
+
+template <class T> class list_element
+{
+ public:
+ list_element *right;
+ list_element *left;
+
+ list_element (T *in);
+ T *data;
+};
+
+template <class T> class ordered_list
+{
+ private:
+ list_element<T> *head;
+ list_element<T> *tail;
+ list_element<T> *ptr;
+ public:
+ ordered_list (void);
+ ~ ordered_list (void);
+ void add (T* in);
+ void sub_move_right (void);
+ void move_right (void);
+ void move_left (void);
+ int is_empty (void);
+ int is_equal_to_tail (void);
+ int is_equal_to_head (void);
+ void start_from_head (void);
+ void start_from_tail (void);
+ T *move_right_get_data (void);
+ T *move_left_get_data (void);
+ T *get_data (void);
+};
+
+
+template <class T> ordered_list<T>::ordered_list()
+ : head(0), tail(0), ptr(0)
+{
+}
+
+template <class T> ordered_list<T>::~ordered_list()
+{
+ list_element<T> *temp=head;
+
+ do {
+ temp = head;
+ if (temp != 0) {
+ head = head->right;
+ delete temp;
+ }
+ } while ((head != 0) && (head != tail));
+}
+
+template <class T> list_element<T>::list_element(T *in)
+ : right(0), left(0)
+{
+ data = in;
+}
+
+template <class T> void ordered_list<T>::add(T *in)
+{
+ list_element<T> *t = new list_element<T>(in); // create a new list element with data field initialized
+ list_element<T> *last;
+
+ if (in == 0) {
+ fatal("cannot add NULL to ordered list");
+ }
+
+ if (head == 0) {
+ head = t;
+ tail = t;
+ t->left = t;
+ t->right = t;
+ } else {
+ last = tail;
+
+ while ((last != head) && (in->is_less(in, last->data))) {
+ last = last->left;
+ }
+
+ if (in->is_less(in, last->data)) {
+ t->right = last;
+ last->left->right = t;
+ t->left = last->left;
+ last->left = t;
+ // now check for a new head
+ if (last == head) {
+ head = t;
+ }
+ } else {
+ // add t onto beyond last
+ t->right = last->right;
+ t->left = last;
+ last->right->left = t;
+ last->right = t;
+ // now check for a new tail
+ if (last == tail) {
+ tail = t;
+ }
+ }
+ }
+}
+
+template <class T> void ordered_list<T>::sub_move_right (void)
+{
+ list_element<T> *t=ptr->right;
+
+ if (head == tail) {
+ head = 0;
+ if (tail != 0) {
+ delete tail;
+ }
+ tail = 0;
+ ptr = 0;
+ } else {
+ if (head == ptr) {
+ head = head->right;
+ }
+ if (tail == ptr) {
+ tail = tail->left;
+ }
+ ptr->left->right = ptr->right;
+ ptr->right->left = ptr->left;
+ ptr=t;
+ }
+}
+
+template <class T> void ordered_list<T>::start_from_head (void)
+{
+ ptr = head;
+}
+
+template <class T> void ordered_list<T>::start_from_tail (void)
+{
+ ptr = tail;
+}
+
+template <class T> int ordered_list<T>::is_empty (void)
+{
+ return( head == 0 );
+}
+
+template <class T> int ordered_list<T>::is_equal_to_tail (void)
+{
+ return( ptr == tail );
+}
+
+template <class T> int ordered_list<T>::is_equal_to_head (void)
+{
+ return( ptr == head );
+}
+
+template <class T> void ordered_list<T>::move_left (void)
+{
+ ptr = ptr->left;
+}
+
+template <class T> void ordered_list<T>::move_right (void)
+{
+ ptr = ptr->right;
+}
+
+template <class T> T* ordered_list<T>::get_data (void)
+{
+ return( ptr->data );
+}
+
+template <class T> T* ordered_list<T>::move_right_get_data (void)
+{
+ ptr = ptr->right;
+ if (ptr == head) {
+ return( 0 );
+ } else {
+ return( ptr->data );
+ }
+}
+
+template <class T> T* ordered_list<T>::move_left_get_data (void)
+{
+ ptr = ptr->left;
+ if (ptr == tail) {
+ return( 0 );
+ } else {
+ return( ptr->data );
+ }
+}
diff --git a/gnu/usr.bin/groff/tmac/groff_man.man b/gnu/usr.bin/groff/tmac/groff_man.man
new file mode 100644
index 00000000000..57eb9ec4555
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/groff_man.man
@@ -0,0 +1,171 @@
+.TH GROFF_MAN @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
+.SH NAME
+.
+groff_man \- groff `an' macros to support generation of man pages
+.SH SYNOPSIS
+.B groff
+.B \-m@TMAC_AN_PREFIX@an
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.
+.SH DESCRIPTION
+.
+The
+.B tmac.an
+macros used to generate man pages with
+.I groff
+were written by James Clark.
+This document provides a brief summary of the use of each macro in that
+package.
+.TP
+.BI .TP " title section " [ extra1 "] [" extra2 "] [" extra3 ]
+Sets the title of the man page to
+.I title
+and the section to
+.IR section ,
+which must take on a value between 1 and\ 8.
+The value
+.I section
+may also have a string appended, e.g. `.pm', to indicate a specific
+subsection of the man pages.
+.TP
+.BI .SH " text for a heading"
+Sets up an unindented and unnumbered section heading.
+Prints out all the text following `.SH' up to the end of the line in bold
+face, with a size slightly smaller than that for indented section headings.
+.TP
+.BI .SS " text for a heading"
+Sets up an indented section heading.
+Prints out all the text following `.SS' up to the end of the line in bold
+face, with a size slightly larger than that for unindented section headings.
+.TP
+.BI ".TP [" nnn ]
+Sets up an indented paragraph.
+The indentation is set to
+.I nnn
+if that argument is supplied.
+The first line of text following this macro is interpreted as a string to be
+printed flush-left, as it is appropriate for a label.
+It is not interpreted as part of a paragraph, so there is no attempt to fill
+the first line with text from the following input lines.
+Nevertheless, if the label is not as wide as the indentation, then the
+paragraph starts at the same line (but indented), continuing on the
+following lines.
+If the label is wider than the indentation, then the descriptive part of the
+paragraph begins on the line following the label, entirely indented.
+The `.TP' macro is the macro used for the explanations you are just reading.
+.TP
+.BR ".LP " or " .PP " or " .P"
+These macros are mutual aliases.
+Any of them causes a line break at the current position, followed by a
+vertical space downwards by the amount that is set in the `PD' counter.
+.TP
+.BI ".IP [" designator "] [" nnn ]
+Sets up an indented paragraph, using
+.I designator
+as a tag to mark its beginning.
+The indentation is permanently set to
+.I nnn
+if that argument is supplied.
+To set the indentation back to the previous level, one must call some other
+macro that uses indented paragraphs, and explicitly provide it with the
+value of the previous indentation.
+.IP
+For example, the following paragraphs were all set up with bullets as the
+designator, using `.IP \\(bu 4':
+.IP \(bu 4
+`IP' is one of the three macros used in
+.B tmac.an
+to format lists.
+.IP \(bu 4
+`HP' is another.
+This macro produces a paragraph with a left hanging indentation.
+.IP \(bu 4
+`TP' is another.
+This macro produces an unindented label (given by the text on the first line
+following `TP'), followed by an indented paragraph with appropriately
+descriptive text.
+.TP
+.BI ".HP [" nnn ]
+Sets up paragraphs with hanging left indentation.
+The indentation is set to
+.I nnn
+if that argument is supplied.
+The following pargraph illustrates the effect of this macro with the hanging
+indentation set to\ 2:
+.HP 2
+This is a pagraph following an invocation of the `.HP' macro.
+As you can see, it produces a paragraph where all lines but the first are
+flushed right and are shorter than the preceding lines.
+.
+.SH "MACROS TO SET FONTS"
+.
+.TP
+.BI .SM
+Causes the text on the same line or the text on the next line to appear in a
+font that is one point size smaller than the default font.
+.TP
+.BI .SB
+Causes the text on the same line or the text on the next line to appear in
+small boldface font.
+.TP
+.BI ".BI " text
+Causes text on the same line to appear alternately in bold face and italic.
+The text must be on the same line as the macro call.
+Thus `.BI this word and that' would cause `this' and `and' to appear in bold
+face, while `word' and `that' appear in italics.
+.TP
+.BI ".IB " text
+Causes text to appear alternately in italic and bold face.
+The text must be on the same line as the macro call.
+.TP
+.BI ".BR " text
+Causes text on the same line to appear alternately in bold face and roman.
+The text must be on the same line as the macro call.
+.TP
+.BI ".RB " text
+Causes text on the same line to appear alternately in roman and bold face.
+The text must be on the same line as the macro call.
+.TP
+.BI ".R " text
+Causes text to appear in roman font.
+If no text is present on the line where the macro is called, then the text
+of the next line appears in roman.
+This is the default font to which text is returned at the end of processing
+of the other macros.
+.TP
+.BI ".B " text
+Causes text to appear in bold face.
+If no text is present on the line where the macro is called, then the text
+of the next line appears in bold face.
+.TP
+.BI ".I " text
+Causes text to appear in italic.
+If no text is present on the line where the macro is called, then the text
+of the next line appears in italic.
+.
+.SH "SEE ALSO"
+.
+Since the
+.B tmac.an
+macros consist of groups of
+.I groff
+requests, one can, in principle, supplement the functionality of the
+.B tmac.an
+macros with individual
+.I groff
+requests where necessary.
+A complete list of these requests is available on the WWW at
+.ce 1
+http://www.cs.pdx.edu/~trent/gnu/groff/groff_toc.html
+.
+.SH AUTHOR
+.
+This manual page was originally written for the Debian GNU/Linux system by
+Susan G. Kleinmann <sgk@debian.org>, corrected by Werner Lemberg
+<wl@gnu.org>, and is now part of the GNU troff distribution.
diff --git a/gnu/usr.bin/groff/tmac/groff_mdoc.man b/gnu/usr.bin/groff/tmac/groff_mdoc.man
new file mode 100644
index 00000000000..2112eba4eba
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/groff_mdoc.man
@@ -0,0 +1,422 @@
+.\" $NetBSD: mdoc.7,v 1.14 1999/08/30 00:41:28 ross Exp $
+.\"
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mdoc.7 8.2 (Berkeley) 12/30/93
+.\"
+.Dd November 24, 1997
+.Os
+.Dt MDOC 7
+.Sh NAME
+.Nm mdoc
+.Nd quick reference guide for the
+.Nm \-mdoc
+macro package
+.Sh SYNOPSIS
+.Nm groff
+.Fl m Ns Ar doc
+.Ar files ...
+.Sh DESCRIPTION
+The
+.Nm \-mdoc
+package is a set of content-based and domain-based macros
+used to format the
+.Bx
+man pages.
+The macro names and their meanings are
+listed below for quick reference; for
+a detailed explanation on using the package,
+see the tutorial sampler
+.Xr mdoc.samples 7 .
+.Pp
+The macros are described in two groups, the first
+includes the structural and physical page layout macros.
+The second contains the manual and general text domain
+macros which differentiate the
+.Nm -\mdoc
+package from other
+.Xr troff
+formatting packages.
+.Sh PAGE STRUCTURE DOMAIN
+.Ss Title Macros
+To create a valid manual page, these three macros, in this order,
+are required:
+.Bl -tag -width "xxxx.Os OPERATINGxSYSTEM [version/release]" -compact
+.It Li "\&.Dd " Ar "Month day, year"
+Document date.
+.It Li "\&.Dt " Ar "DOCUMENT_TITLE [section] [volume]"
+Title, in upper case.
+.It Li "\&.Os " Ar "OPERATING_SYSTEM [version/release]"
+Operating system
+.Pq Tn BSD .
+.El
+.Ss Page Layout Macros
+Section headers, paragraph breaks, lists and displays.
+.Bl -tag -width flag -compact
+.It Li \&.Sh
+Section Headers.
+Valid headers, in the order of presentation:
+.Bl -tag -width "RETURN VALUES" -compact
+.It Ar NAME
+Name section, should include the
+.Ql \&.Nm
+or
+.Ql \&.Fn
+and the
+.Ql \&.Nd
+macros.
+.It Ar SYNOPSIS
+Usage.
+.It Ar DESCRIPTION
+General description, should include
+options and parameters.
+.It Ar RETURN VALUES
+Sections two and three function calls.
+.It Ar ENVIRONMENT
+Describe environment variables.
+.It Ar FILES
+Files associated with the subject.
+.It Ar EXAMPLES
+Examples and suggestions.
+.It Ar DIAGNOSTICS
+Normally used for section four device interface diagnostics.
+.It Ar ERRORS
+Sections two and three error and signal
+handling.
+.It Ar SEE ALSO
+Cross references and citations.
+.It Ar STANDARDS
+Conformance to standards if applicable.
+.It Ar HISTORY
+If a standard is not applicable, the history
+of the subject should be given.
+.It Ar BUGS
+Gotchas and caveats.
+.It Ar SECURITY CONSIDERATIONS
+Security issues to be aware of.
+.It Ar other
+Customized headers may be added at
+the authors discretion.
+.El
+.It Li \&.Ss
+Subsection Headers.
+.It Li \&.Pp
+Paragraph Break.
+Vertical space (one line).
+.It Li \&.D1
+(D-one) Display-one
+Indent and display one text line.
+.It Li \&.Dl
+(D-ell) Display-one literal.
+Indent and display one line of literal text.
+.It Li \&.Bd
+Begin-display block.
+Display options:
+.Bl -tag -width "xoffset string " -compact
+.It Fl ragged
+Unjustified (ragged edges).
+.It Fl filled
+Filled, and if
+.Xr troff 1 ,
+also justified.
+.It Fl unfilled
+Unfilled, unjustified.
+.It Fl literal
+Literal text or code.
+.It Fl file Ar name
+Read in named
+.Ar file
+and display.
+.It Fl offset Ar string
+Offset display.
+Acceptable
+.Ar string
+values:
+.Bl -tag -width indent-two -compact
+.It Ar left
+Align block on left (default).
+.It Ar center
+Approximate center margin.
+.It Ar indent
+Six constant width spaces (a tab).
+.It Ar indent-two
+Two tabs.
+.It Ar right
+Left aligns block 2 inches from
+right.
+.It Ar xx Ns Cm n
+Where
+.Ar xx
+is a number from
+.No \&4 Ns Cm n
+to
+.No \&9\&9 Ns Cm n .
+.It Ar Aa
+Where
+.Ar Aa
+is a callable macro name.
+.It Ar string
+The width of
+.Ar string
+is used.
+.El
+.El
+.It Li \&.Ed
+End-display (matches \&.Bd).
+.It Li \&.Bl
+Begin-list.
+Create lists or columns. Options:
+.Bl -tag -width flag -compact
+.It Em List-types
+.Bl -column "xbullet " -compact
+.It Fl bullet Ta "Bullet Item List"
+.It Fl dash Ta "Dash Item List"
+.It Fl hyphen Ta "(as per" Fl dash ")"
+.It Fl item Ta "Unlabeled List"
+.It Fl enum Ta "Enumerated List"
+.It Fl tag Ta "Tag Labeled List"
+.It Fl diag Ta "Diagnostic List"
+.It Fl hang Ta "Hanging Labeled List"
+.It Fl ohang Ta "Overhanging Labeled List"
+.It Fl inset Ta "Inset or Run-on Labeled List"
+.It Fl column Ta "Multiple Columns"
+.El
+.It Em List-parameters
+.Bl -tag -width "xcompact " -compact
+.It Fl offset
+(All lists.) See
+.Ql \&.Bd
+begin-display above.
+.It Fl width
+.Pf ( Fl tag
+and
+.Fl hang
+lists only.)
+See
+.Ql \&.Bd .
+This parameter is effectively required for
+.Fl tag
+lists.
+.It Fl compact
+(All lists.)
+Suppresses blank lines.
+.El
+.El
+.It Li \&.El
+End-list.
+.It Li \&.It
+List item.
+.El
+.Sh MANUAL AND GENERAL TEXT DOMAIN MACROS
+The manual and general text domain macros are special in that
+most of them are parsed for callable macros
+for example:
+.Bl -tag -width ".Op Fl s Ar filex" -offset indent
+.It Li "\&.Op Fl s Ar file"
+Produces
+.Op Fl s Ar file
+.El
+.Pp
+In this example, the option enclosure macro
+.Ql \&.Op
+is parsed, and calls the callable content macro
+.Ql \&Fl
+which operates on the argument
+.Ql s
+and then calls the callable content macro
+.Ql \&Ar
+which operates on the argument
+.Ql file .
+Some macros may be callable, but are not parsed and vice versa.
+These macros are indicated in the
+.Em parsed
+and
+.Em callable
+columns below.
+.Pp
+Unless stated, manual domain macros share a common syntax:
+.Pp
+.Dl \&.Va argument [\ .\ ,\ ;\ :\ (\ )\ [\ ]\ argument \...\ ]
+.Pp
+.Sy Note :
+Opening and closing
+punctuation characters are only recognized as such if they are presented
+one at a time.
+The string
+.Ql "),"
+is not recognized as punctuation and will be output with a leading white
+space and in what ever font the calling macro uses.
+The
+argument list
+.Ql "] ) ,"
+is recognized as three sequential closing punctuation characters
+and a leading white space is not output between the characters
+and the previous argument (if any).
+The special meaning of a punctuation character may be escaped
+with the string
+.Ql \e& .
+For example the following string,
+.Bl -tag -width "&.Ar file1\ , file2\ , file3\ )\ ." -offset indent
+.It Li "\&.Ar file1\ , file2\ , file3\ )\ ."
+Produces
+.Ar file1 , file2 , file3 ) .
+.El
+.ne 1i
+.Ss Manual Domain Macros
+.Bl -column "Name" "Parsed" "Callable" -compact
+.It Em Name Parsed Callable Description
+.It Li \&Ad Ta Yes Ta Yes Ta Address. "(This macro may be deprecated.)"
+.It Li \&Ar Ta Yes Ta Yes Ta "Command line argument."
+.It Li \&Cd Ta \&No Ta \&No Ta "Configuration declaration (section four only)."
+.It Li \&Cm Ta Yes Ta Yes Ta "Command line argument modifier."
+.It Li \&Dv Ta Yes Ta Yes Ta "Defined variable (source code)."
+.It Li \&Er Ta Yes Ta Yes Ta "Error number (source code)."
+.It Li \&Ev Ta Yes Ta Yes Ta "Environment variable."
+.It Li \&Fa Ta Yes Ta Yes Ta "Function argument."
+.It Li \&Fd Ta \&No Ta \&No Ta "Function declaration."
+.It Li \&Fl Ta Yes Ta Yes Ta "Command line flag."
+.It Li \&Fn Ta Yes Ta Yes Ta "Function call (also .Fo and .Fc)."
+.It Li \&Ic Ta Yes Ta Yes Ta "Interactive command."
+.It Li \&Li Ta Yes Ta Yes Ta "Literal text."
+.It Li \&Nm Ta Yes Ta Yes Ta "Command name."
+.It Li \&Op Ta Yes Ta Yes Ta "Option (also .Oo and .Oc)."
+.It Li \&Ot Ta Yes Ta Yes Ta "Old style function type (Fortran only)."
+.It Li \&Pa Ta Yes Ta Yes Ta "Pathname or file name."
+.It Li \&St Ta Yes Ta Yes Ta "Standards (-p1003.2, -p1003.1 or -ansiC)"
+.It Li \&Va Ta Yes Ta Yes Ta "Variable name."
+.It Li \&Vt Ta Yes Ta Yes Ta "Variable type (Fortran only)."
+.It Li \&Xr Ta Yes Ta Yes Ta "Manual Page Cross Reference."
+.El
+.Ss General Text Domain Macros
+.Bl -column "Name" "Parsed" "Callable" -compact
+.It Em "Name Parsed Callable Description"
+.It Li \&%A Ta Yes Ta \&No Ta "Reference author."
+.It Li \&%B Ta Yes Ta Yes Ta "Reference book title."
+.It Li \&%\&C Ta \&No Ta \&No Ta "Reference place of publishing (city)."
+.It Li \&%\&D Ta \&No Ta \&No Ta "Reference date."
+.It Li \&%J Ta Yes Ta Yes Ta "Reference journal title."
+.It Li \&%N Ta \&No Ta \&No Ta "Reference issue number."
+.It Li \&%\&O Ta \&No Ta \&No Ta "Reference optional information."
+.It Li \&%P Ta \&No Ta \&No Ta "Reference page number(s)."
+.It Li \&%R Ta \&No Ta \&No Ta "Reference report Name."
+.It Li \&%T Ta Yes Ta Yes Ta "Reference article title."
+.It Li \&%V Ta \&No Ta \&No Ta "Reference volume."
+.It Li \&Ac Ta Yes Ta Yes Ta "Angle close quote."
+.It Li \&Ao Ta Yes Ta Yes Ta "Angle open quote."
+.It Li \&Ap Ta Yes Ta Yes Ta "Insert apostrophe; switch to .No mode "
+.It Li \&Aq Ta Yes Ta Yes Ta "Angle quote."
+.It Li \&At Ta \&No Ta \&No Ta Tn "AT&T UNIX."
+.It Li \&Bc Ta Yes Ta Yes Ta "Bracket close quote."
+.It Li \&Bf Ta \&No Ta \&No Ta "Begin font mode."
+.It Li \&Bo Ta Yes Ta Yes Ta "Bracket open quote."
+.It Li \&Bq Ta Yes Ta Yes Ta "Bracket quote."
+.It Li \&Bx Ta Yes Ta Yes Ta "BSD" .
+.It Li \&Db Ta \&No Ta \&No Ta "Debug (default is \\*qoff\\*q)."
+.It Li \&Dc Ta Yes Ta Yes Ta "Double close quote."
+.It Li \&Do Ta Yes Ta Yes Ta "Double open quote."
+.It Li \&Dq Ta Yes Ta Yes Ta "Double quote."
+.It Li \&Ec Ta Yes Ta Yes Ta "Enclose string close quote."
+.It Li \&Ef Ta \&No Ta \&No Ta "End font mode."
+.It Li \&Em Ta Yes Ta Yes Ta "Emphasis (traditional English)."
+.It Li \&Eo Ta Yes Ta Yes Ta "Enclose string open quote."
+.It Li \&Fx Ta \&No Ta \&No Ta "FreeBSD."
+.It Li \&No Ta Yes Ta Yes Ta "Normal text (no-op)."
+.It Li \&Ns Ta Yes Ta Yes Ta "No space."
+.It Li \&Nx Ta \&No Ta \&No Ta "NetBSD."
+.It Li \&Pc Ta Yes Ta Yes Ta "Parenthesis close quote."
+.It Li \&Pf Ta Yes Ta \&No Ta "Prefix string."
+.It Li \&Po Ta Yes Ta Yes Ta "Parenthesis open quote."
+.It Li \&Pq Ta Yes Ta Yes Ta "Parentheses quote."
+.It Li \&Qc Ta Yes Ta Yes Ta "Strait Double close quote."
+.It Li \&Ql Ta Yes Ta Yes Ta "Quoted literal."
+.It Li \&Qo Ta Yes Ta Yes Ta "Strait Double open quote."
+.It Li \&Qq Ta Yes Ta Yes Ta "Strait Double quote."
+.It Li \&Re Ta \&No Ta \&No Ta "Reference end."
+.It Li \&Rs Ta \&No Ta \&No Ta "Reference start."
+.It Li \&Sc Ta Yes Ta Yes Ta "Single close quote."
+.It Li \&So Ta Yes Ta Yes Ta "Single open quote."
+.It Li \&Sq Ta Yes Ta Yes Ta "Single quote."
+.It Li \&Sm Ta \&No Ta \&No Ta "Space mode (default is \\*qon\\*q)."
+.It Li \&Sx Ta Yes Ta Yes Ta "Section Cross Reference."
+.It Li \&Sy Ta Yes Ta Yes Ta "Symbolic (traditional English)."
+.It Li \&Tn Ta Yes Ta Yes Ta "Trade or type name (small Caps)."
+.It Li \&Ux Ta Yes Ta Yes Ta "UNIX."
+.It Li \&Xc Ta Yes Ta Yes Ta "Extend argument list close."
+.It Li \&Xo Ta Yes Ta Yes Ta "Extend argument list open."
+.El
+.\" .It Sy \&Hf Ta \&No Ta \&No Ta "Include file with header"
+.Pp
+Macro names ending in
+.Ql q
+quote remaining items on the argument list.
+Macro names ending in
+.Ql o
+begin a quote which may span more than one line of input and
+are close quoted with the matching macro name ending in
+.Ql c .
+Enclosure macros may be nested and are limited to
+eight arguments.
+.Pp
+Note: the extended argument list macros
+.Pf ( Ql \&.Xo ,
+.Ql \&.Xc )
+and the function enclosure macros
+.Pf ( Ql \&.Fo ,
+.Ql \&.Fc )
+are irregular.
+The extended list macros are used when the number of macro arguments
+would exceed the
+.Xr troff
+limitation of nine arguments.
+.Sh CONFIGURATION
+For site specific configuration of the macro package,
+see the file
+.Pa /usr/src/share/tmac/README .
+.Sh FILES
+.Bl -tag -width "tmac.doc-ditroff" -compact
+.It Pa tmac.doc
+Manual and general text domain macros.
+.It Pa tmac.doc-common
+Common structural macros and definitions.
+.It Pa tmac.doc-nroff
+Site dependent
+.Xr nroff
+style file.
+.It Pa tmac.doc-ditroff
+Site dependent
+.Xr troff
+style file.
+.It Pa tmac.doc-syms
+Special defines (such as the standards macro).
+.El
+.Sh SEE ALSO
+.Xr mdoc.samples 7
diff --git a/gnu/usr.bin/groff/tmac/groff_mdoc.samples.man b/gnu/usr.bin/groff/tmac/groff_mdoc.samples.man
new file mode 100644
index 00000000000..cdbbc21c4f6
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/groff_mdoc.samples.man
@@ -0,0 +1,2925 @@
+.\" $NetBSD: mdoc.samples.7,v 1.21 1999/08/23 21:54:20 ross Exp $
+.\"
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mdoc.samples.7 8.2 (Berkeley) 12/30/93
+.\"
+.\" This tutorial sampler invokes every macro in the package several
+.\" times and is guaranteed to give a worst case performance
+.\" for an already extremely slow package.
+.\"
+.Dd November 24, 1997
+.Os
+.Dt MDOC.SAMPLES 7
+.Sh NAME
+.Nm mdoc.samples
+.Nd tutorial sampler for writing
+.Bx
+manuals with
+.Nm \-mdoc
+.Sh SYNOPSIS
+.Nm man mdoc.samples
+.Sh DESCRIPTION
+A tutorial sampler for writing
+.Bx
+manual pages with the
+.Nm \-mdoc
+macro package, a
+.Em content Ns \-based
+and
+.Em domain Ns \-based
+formatting
+package for
+.Xr troff 1 .
+Its predecessor, the
+.Xr \-man 7
+package,
+addressed page layout leaving the
+manipulation of fonts and other
+typesetting details to the individual author.
+In
+.Nm \-mdoc ,
+page layout macros
+make up the
+.Em "page structure domain"
+which consists of macros for titles, section headers, displays
+and lists. Essentially items which affect the physical position
+of text on a formatted page.
+In addition to the page structure domain, there are two more domains,
+the manual domain and the general text domain.
+The general text domain is defined as macros which
+perform tasks such as quoting or emphasizing pieces of text.
+The manual domain is defined as macros that are a subset of the
+day to day informal language used to describe commands, routines
+and related
+.Bx
+files.
+Macros in the manual domain handle
+command names, command line arguments and options, function names,
+function parameters, pathnames, variables, cross
+references to other manual pages, and so on.
+These domain
+items have value
+for both the author and the future user of the manual page.
+It is hoped the consistency gained
+across the manual set will provide easier
+translation to future documentation tools.
+.Pp
+Throughout the
+.Ux
+manual pages, a manual entry
+is simply referred
+to as a man page, regardless of actual length and without
+sexist intention.
+.Sh GETTING STARTED
+Since a tutorial document is normally read when a person
+desires to use the material immediately, the assumption has
+been made that the user of this document may be impatient.
+The material presented in the remained of this document is
+outlined as follows:
+.Bl -enum -offset indent
+.It
+.Tn "TROFF IDIOSYNCRASIES"
+.Bl -tag -width flag -compact -offset indent
+.It "Macro Usage" .
+.It "Passing Space Characters in an Argument" .
+.It "Trailing Blank Space Characters (a warning)" .
+.It "Escaping Special Characters" .
+.El
+.It
+.Tn "THE ANATOMY OF A MAN PAGE"
+.Bl -tag -width flag -compact -offset indent
+.It "A manual page template" .
+.El
+.It
+.Tn "INTRODUCTION OF TITLE MACROS" .
+.It
+.Tn "INTRODUCTION OF MANUAL AND GENERAL TEXT DOMAINS" .
+.Bl -tag -width flag -compact -offset indent
+.It "What's in a name..." .
+.It "General Syntax" .
+.El
+.It
+.Tn "MANUAL DOMAIN"
+.Bl -tag -width flag -compact -offset indent
+.It "Addresses" .
+.It "Arguments" .
+.It "Configuration Declarations (section four only)" .
+.It "Command Modifier" .
+.It "Defined Variables" .
+.It "Errno's (Section two only)" .
+.It "Environment Variables" .
+.It "Function Argument" .
+.It "Function Declaration" .
+.It "Flags" .
+.It "Functions (library routines)" .
+.It "Function Types" .
+.\" .It "Header File (including source code)" .
+.It "Interactive Commands" .
+.It "Literals" .
+.It "Names" .
+.It "Options" .
+.It "Pathnames" .
+.It "Variables" .
+.It "Cross References" .
+.El
+.It
+.Tn "GENERAL TEXT DOMAIN"
+.Bl -tag -width flag -compact -offset indent
+.It "AT&T Macro" .
+.It "BSD Macro" .
+.It "UNIX Macro" .
+.It "Emphasis Macro" .
+.It "Enclosure/Quoting Macros"
+.Bl -tag -width flag -compact -offset indent
+.It "Angle Bracket Quote/Enclosure" .
+.It "Bracket Quotes/Enclosure" .
+.It "Double Quote macro/Enclosure" .
+.It "Parenthesis Quote/Enclosure" .
+.It "Single Quotes/Enclosure" .
+.It "Prefix Macro" .
+.El
+.It "Extended Arguments" .
+.It "No\-Op or Normal Text Macro" .
+.It "No Space Macro" .
+.It "Section Cross References" .
+.It "Symbolic Macro" .
+.It "References and Citations" .
+.It "Trade Names (Acronyms and Type Names)" .
+.El
+.It
+.Tn "PAGE STRUCTURE DOMAIN"
+.Bl -tag -width flag -compact -offset indent
+.It "Section Headers" .
+.It "Paragraphs and Line Spacing" .
+.It "Keeps" .
+.It "Displays" .
+.It "Lists and Columns" .
+.El
+.It
+.Tn "PREDEFINED STRINGS"
+.It
+.Tn "DIAGNOSTICS"
+.It
+.Tn "FORMATTING WITH GROFF, TROFF AND NROFF"
+.It
+.Tn "BUGS"
+.El
+.ne 7
+.Sh TROFF IDIOSYNCRASIES
+The
+.Nm \-mdoc
+package attempts to simplify the process of writing a man page.
+Theoretically, one should not have to learn the dirty details of
+.Xr troff 1
+to use
+.Nm \-mdoc ;
+however, there are a few
+limitations which are unavoidable and best gotten out
+of the way.
+And, too, be forewarned, this package is
+.Em not
+fast.
+.Ss Macro Usage
+As in
+.Xr troff 1 ,
+a macro is called by placing a
+.Ql \&\.
+(dot character)
+at the beginning of
+a line followed by the two character name for the macro.
+Arguments may follow the macro separated by spaces.
+It is the dot character at the beginning of the line which causes
+.Xr troff 1
+to interpret the next two characters as a macro name.
+To place a
+.Ql \&\.
+(dot character)
+at the beginning of a line in some context other than
+a macro invocation, precede the
+.Ql \&\.
+(dot) with the
+.Ql \e&
+escape sequence.
+The
+.Ql \e&
+translates literally to a zero width space, and is never displayed in the
+output.
+.Pp
+In general,
+.Xr troff 1
+macros accept up to nine arguments, any
+extra arguments are ignored.
+Most macros in
+.Nm \-mdoc
+accept nine arguments and,
+in limited cases, arguments may be continued or extended
+on the
+next line (See
+.Sx Extended Arguments ) .
+A few macros handle quoted arguments (see
+.Sx Passing Space Characters in an Argument
+below).
+.Pp
+Most of the
+.Nm \-mdoc
+general text domain and manual domain macros are special
+in that their argument lists are
+.Em parsed
+for callable macro names.
+This means an argument on the argument list which matches
+a general text or manual domain macro name and is determined
+to be callable will be executed
+or called when it is processed.
+In this case
+the argument, although the name of a macro,
+is not preceded by a
+.Ql \&\.
+(dot).
+It is in this manner that many macros are nested; for
+example
+the option macro,
+.Ql \&.Op ,
+may
+.Em call
+the flag and argument macros,
+.Ql \&Fl
+and
+.Ql \&Ar ,
+to specify an optional flag with an argument:
+.Bl -tag -width "\&.Op \&Fl s \&Ar bytes" -offset indent
+.It Op Fl s Ar bytes
+is produced by
+.Li \&.Op \&Fl s \&Ar bytes
+.El
+.Pp
+To prevent a two character
+string from being interpreted as a macro name, precede
+the string with the
+escape sequence
+.Ql \e& :
+.Bl -tag -width "\&.Op \&Fl s \&Ar bytes" -offset indent
+.It Op \&Fl s \&Ar bytes
+is produced by
+.Li \&.Op \e&Fl s \e&Ar bytes
+.El
+.Pp
+Here the strings
+.Ql \&Fl
+and
+.Ql \&Ar
+are not interpreted as macros.
+Macros whose argument lists are parsed for callable arguments
+are referred to
+as parsed and macros which may be called from an argument
+list are referred to as callable
+throughout this document and in the companion quick reference
+manual
+.Xr mdoc 7 .
+This is a technical
+.Em faux pas
+as almost all of the macros in
+.Nm \-mdoc
+are parsed, but as it was cumbersome to constantly refer to macros
+as being callable and being able to call other macros,
+the term parsed has been used.
+.Ss Passing Space Characters in an Argument
+Sometimes it is desirable to give as one argument a string
+containing one or more blank space characters.
+This may be necessary
+to defeat the nine argument limit or to specify arguments to macros
+which expect particular arrangement of items in the argument list.
+For example,
+the function macro
+.Ql \&.Fn
+expects the first argument to be the name of a function and any
+remaining arguments to be function parameters.
+As
+.Tn "ANSI C"
+stipulates the declaration of function parameters in the
+parenthesized parameter list, each parameter is guaranteed
+to be at minimum a two word string.
+For example,
+.Fa int foo .
+.Pp
+There are two possible ways to pass an argument which contains
+an embedded space.
+.Em Implementation note :
+Unfortunately, the most convenient way
+of passing spaces in between quotes by reassigning individual
+arguments before parsing was fairly expensive speed wise
+and space wise to implement in all the macros for
+.Tn AT&T
+.Xr troff .
+It is not expensive for
+.Xr groff
+but for the sake of portability, has been limited
+to the following macros which need
+it the most:
+.Pp
+.Bl -tag -width 4n -offset indent -compact
+.It Li \&Cd
+Configuration declaration (section 4
+.Sx SYNOPSIS )
+.It Li \&Bl
+Begin list (for the width specifier).
+.It Li \&Em
+Emphasized text.
+.It Li \&Fn
+Functions (sections two and four).
+.It Li \&It
+List items.
+.It Li \&Li
+Literal text.
+.It Li \&Sy
+Symbolic text.
+.It Li \&%B
+Book titles.
+.It Li \&%J
+Journal names.
+.It Li \&%O
+Optional notes for a reference.
+.It Li \&%R
+Report title (in a reference).
+.It Li \&%T
+Title of article in a book or journal.
+.El
+.Pp
+One way of passing a string
+containing blank spaces is to use the hard or unpaddable space character
+.Ql \e\ ,
+that is, a blank space preceded by the escape character
+.Ql \e .
+This method may be used with any macro but has the side effect
+of interfering with the adjustment of text
+over the length of a line.
+.Xr Troff
+sees the hard space as if it were any other printable character and
+cannot split the string into blank or newline separated pieces as one
+would expect.
+The method is useful for strings which are not expected
+to overlap a line boundary.
+For example:
+.Bl -tag -width "fetch(char *str)" -offset indent
+.It Fn fetch char\ *str
+is created by
+.Ql \&.Fn fetch char\e *str
+.It Fn fetch "char *str"
+can also be created by
+.Ql \&.Fn fetch "\\*q*char *str\\*q"
+.El
+.Pp
+If the
+.Ql \e
+or quotes
+were omitted,
+.Ql \&.Fn
+would see three arguments and
+the result would be:
+.Pp
+.Dl Fn fetch char *str
+.Pp
+For an example of what happens when the parameter list overlaps
+a newline boundary, see the
+.Sx BUGS
+section.
+.Ss Trailing Blank Space Characters
+.Xr Troff
+can be confused by blank space characters at the end of a line.
+It
+is a wise preventive measure to globally remove all blank spaces
+from <blank-space><end-of-line> character sequences.
+Should the need
+arise to force a blank character at the end of a line,
+it may be forced with an unpaddable space and the
+.Ql \e&
+escape character.
+For example,
+.Ql string\e\ \e& .
+.Ss Escaping Special Characters
+Special characters
+like the newline character
+.Ql \en ,
+are handled by replacing the
+.Ql \e
+with
+.Ql \ee
+(e.g.
+.Ql \een )
+to preserve
+the backslash.
+.Sh THE ANATOMY OF A MAN PAGE
+The body of a man page is easily constructed from a basic
+template found in the file:
+.Bd -literal -offset indent
+\&.\e" /usr/share/misc/mdoc.template:
+\&.\e" The following six lines are required.
+\&.Dd Month day, year
+\&.Os OPERATING_SYSTEM [version/release]
+\&.Dt DOCUMENT_TITLE [section number] [volume]
+\&.Sh NAME
+\&.Sh SYNOPSIS
+\&.Sh DESCRIPTION
+\&.\e" The following requests should be uncommented and
+\&.\e" used where appropriate. This next request is
+\&.\e" for sections 2 and 3 function return values only.
+\&.\e" .Sh RETURN VALUES
+\&.\e" This next request is for sections 1, 6, 7 & 8 only
+\&.\e" .Sh ENVIRONMENT
+\&.\e" .Sh FILES
+\&.\e" .Sh EXAMPLES
+\&.\e" This next request is for sections 1, 6, 7 & 8 only
+\&.\e" (command return values (to shell) and
+\&.\e" fprintf/stderr type diagnostics)
+\&.\e" .Sh DIAGNOSTICS
+\&.\e" The next request is for sections 2 and 3 error
+\&.\e" and signal handling only.
+\&.\e" .Sh ERRORS
+\&.\e" .Sh SEE ALSO
+\&.\e" .Sh STANDARDS
+\&.\e" .Sh HISTORY
+\&.\e" .Sh AUTHORS
+\&.\e" .Sh BUGS
+.Ed
+.Pp
+The first items in the template are the macros
+.Pq Li \&.Dd , \&.Os , \&.Dt ;
+the document date,
+the operating system the man page or subject source is developed
+or modified for,
+and the man page title
+.Pq Em in upper case
+along with the section of the manual the page
+belongs in.
+These macros identify the page,
+and are discussed below in
+.Sx TITLE MACROS .
+.Pp
+The remaining items in the template are section headers
+.Pq Li \&.Sh ;
+of which
+.Sx NAME ,
+.Sx SYNOPSIS
+and
+.Sx DESCRIPTION
+are mandatory.
+The
+headers are
+discussed in
+.Sx PAGE STRUCTURE DOMAIN ,
+after
+presentation of
+.Sx MANUAL DOMAIN .
+Several content macros are used to demonstrate page layout macros;
+reading about content macros before page layout macros is
+recommended.
+.Sh TITLE MACROS
+The title macros are the first portion of the page structure
+domain, but are presented first and separate for someone who
+wishes to start writing a man page yesterday.
+Three header macros designate the document title or manual page title,
+the operating system,
+and the date of authorship.
+These macros are one called once at the very beginning of the document
+and are used to construct the headers and footers only.
+.Bl -tag -width 6n
+.It Li \&.Dt DOCUMENT_TITLE section# [volume]
+The document title is the
+subject of the man page and must be in
+.Tn CAPITALS
+due to troff
+limitations.
+The section number may be 1,\ ...,\ 9,
+and if it is specified,
+the volume title may be omitted.
+A volume title may be arbitrary or one of the following:
+.\" .Cl
+.\" USD UNIX User's Supplementary Documents
+.\" .Cl
+.\" PS1 UNIX Programmer's Supplementary Documents
+.Pp
+.Bl -column SMM -offset indent -compact
+.It Li AMD NetBSD Ancestral Manual Documents
+.It Li SMM NetBSD System Manager's Manual
+.It Li URM NetBSD Reference Manual
+.It Li PRM NetBSD Programmer's Manual
+.It Li KM NetBSD Kernel Manual
+.El
+.Pp
+The default volume labeling is
+.Li URM
+for sections 1, 6, and 7;
+.Li SMM
+for section 8;
+.Li PRM
+for sections 2, 3, 4, and 5;
+.Li KM
+for section 9.
+.\" .Cl
+.\" MMI UNIX Manual Master Index
+.\" .Cl
+.\" CON UNIX Contributed Software Manual
+.\" .Cl
+.\" LOC UNIX Local Manual
+.It Li \&.Os operating_system release#
+The name of the operating system
+should be the common acronym, e.g.
+.Tn BSD
+or
+.Tn ATT .
+The release should be the standard release
+nomenclature for the system specified, e.g. 4.3, 4.3+Tahoe, V.3,
+V.4.
+Unrecognized arguments are displayed as given in the page footer.
+For instance, a typical footer might be:
+.Pp
+.Dl \&.Os BSD 4.3
+.Pp
+or for a locally produced set
+.Pp
+.Dl \&.Os CS Department
+.Pp
+The Berkeley default,
+.Ql \&.Os
+without an argument, has been defined as
+.Nx 1.4
+in the site specific file
+.Pa /usr/share/tmac/tmac.doc-common .
+Note, if the
+.Ql \&.Os
+macro is not present, the bottom left corner of the page
+will be ugly.
+.It Li \&.Dd month day, year
+The date should be written formally:
+.Pp
+.ne 5
+.Dl January 25, 1989
+.sp
+Note that the date must not be placed in quotes!
+.El
+.Sh MANUAL DOMAIN
+.Ss What's in a name...
+The manual domain macro names are derived from the day to day
+informal language used to describe commands, subroutines and related
+files.
+Slightly
+different variations of this language are used to describe
+the three different aspects of writing a man page.
+First, there is the description of
+.Nm \-mdoc
+macro request usage.
+Second is the description of a
+.Ux
+command
+.Em with
+.Nm \-mdoc
+macros and third,
+the
+description of a command to a user in the verbal sense;
+that is, discussion of a command in the text of a man page.
+.Pp
+In the first case,
+.Xr troff 1
+macros are themselves a type of command;
+the general syntax for a troff command is:
+.Bd -filled -offset indent
+\&.Va argument1 argument2 ... argument9
+.Ed
+.Pp
+The
+.Ql \&.Va
+is a macro command or request, and anything following it is an argument to
+be processed.
+In the second case,
+the description of a
+.Ux
+command using the content macros is a
+bit more involved;
+a typical
+.Sx SYNOPSIS
+command line might be displayed as:
+.Bd -filled -offset indent
+.Nm filter
+.Op Fl flag
+.Ar infile outfile
+.Ed
+.Pp
+Here,
+.Nm filter
+is the command name and the
+bracketed string
+.Fl flag
+is a
+.Em flag
+argument designated as optional by the option brackets.
+In
+.Nm \-mdoc
+terms,
+.Ar infile
+and
+.Ar outfile
+are
+called
+.Em arguments .
+The macros which formatted the above example:
+.Bd -literal -offset indent
+\&.Nm filter
+\&.Op \&Fl flag
+\&.Ar infile outfile
+.Ed
+.Pp
+In the third case, discussion of commands and command syntax
+includes both examples above, but may add more detail.
+The
+arguments
+.Ar infile
+and
+.Ar outfile
+from the example above might be referred to as
+.Em operands
+or
+.Em file arguments .
+Some command line argument lists are quite long:
+.Bl -tag -width make -offset indent
+.It Nm make
+.Op Fl eiknqrstv
+.Op Fl D Ar variable
+.Op Fl d Ar flags
+.Op Fl f Ar makefile
+.Bk -words
+.Op Fl I Ar directory
+.Ek
+.Op Fl j Ar max_jobs
+.Op Ar variable=value
+.Bk -words
+.Op Ar target ...
+.Ek
+.El
+.Pp
+Here one might talk about the command
+.Nm make
+and qualify the argument
+.Ar makefile ,
+as an argument to the flag,
+.Fl f ,
+or discuss the optional
+file
+operand
+.Ar target .
+In the verbal context, such detail can prevent confusion,
+however the
+.Nm \-mdoc
+package
+does not have a macro for an argument
+.Em to
+a flag.
+Instead the
+.Ql \&Ar
+argument macro is used for an operand or file argument like
+.Ar target
+as well as an argument to a flag like
+.Ar variable .
+The make command line was produced from:
+.Bd -literal -offset indent
+\&.Nm make
+\&.Op Fl eiknqrstv
+\&.Op Fl D Ar variable
+\&.Op Fl d Ar flags
+\&.Op Fl f Ar makefile
+\&.Op Fl I Ar directory
+\&.Op Fl j Ar max_jobs
+\&.Op Ar variable=value
+\&.Bk -words
+\&.Op Ar target ...
+\&.Ek
+.Ed
+.Pp
+The
+.Ql \&.Bk
+and
+.Ql \&.Ek
+macros are explained in
+.Sx Keeps .
+.Ss General Syntax
+The manual domain and general text domain macros share a similar
+syntax with a few minor deviations:
+.Ql \&.Ar ,
+.Ql \&.Fl ,
+.Ql \&.Nm ,
+and
+.Ql \&.Pa
+differ only when called without arguments;
+.Ql \&.Fn
+and
+.Ql \&.Xr
+impose an order on their argument lists
+and the
+.Ql \&.Op
+and
+.Ql \&.Fn
+macros
+have nesting limitations.
+All content macros
+are capable of recognizing and properly handling punctuation,
+provided each punctuation character is separated by a leading space.
+If an request is given:
+.Pp
+.Dl \&.Li sptr, ptr),
+.Pp
+The result is:
+.Pp
+.Dl Li sptr, ptr),
+.Pp
+The punctuation is not recognized and all is output in the
+literal font. If the punctuation is separated by a leading
+white space:
+.Pp
+.Dl \&.Li "sptr , ptr ) ,"
+.Pp
+The result is:
+.Pp
+.Dl Li sptr , ptr ) ,
+.Pp
+The punctuation is now recognized and is output in the
+default font distinguishing it from the strings in literal font.
+.Pp
+To remove the special meaning from a punctuation character
+escape it with
+.Ql \e& .
+.Xr Troff
+is limited as a macro language, and has difficulty
+when presented with a string containing
+a member of the mathematical, logical or
+quotation set:
+.Bd -literal -offset indent-two
+\&{+,\-,/,*,\&%,<,>,<=,>=,=,==,&,`,',"}
+.Ed
+.Pp
+The problem is that
+.Xr troff
+may assume it is supposed to actually perform the operation
+or evaluation suggested by the characters. To prevent
+the accidental evaluation of these characters,
+escape them with
+.Ql \e& .
+Typical syntax is shown in the first content macro displayed
+below,
+.Ql \&.Ad .
+.Ss Address Macro
+The address macro identifies an address construct
+of the form addr1[,addr2[,addr3]].
+.Pp
+.Dl Usage: .Ad address ... \*(Pu
+.Bl -tag -width ".Ad f1 , f2 , f3 :" -compact -offset 14n
+.It Li \&.Ad addr1
+.Ad addr1
+.It Li \&.Ad addr1\ .
+.Ad addr1 .
+.It Li \&.Ad addr1\ , file2
+.Ad addr1 , file2
+.It Li \&.Ad f1\ , f2\ , f3\ :
+.Ad f1 , f2 , f3 :
+.It Li \&.Ad addr\ )\ )\ ,
+.Ad addr ) ) ,
+.El
+.Pp
+It is an error to call
+.Li \&.Ad
+without arguments.
+.Li \&.Ad
+is callable by other macros and is parsed.
+.Ss Argument Macro
+The
+.Li \&.Ar
+argument macro may be used whenever
+a command line argument is referenced.
+.Pp
+.Dl Usage: .Ar argument ... \*(Pu
+.Bl -tag -width ".Ar file1 file2" -compact -offset 15n
+.It Li \&.Ar
+.Ar
+.It Li \&.Ar file1
+.Ar file1
+.It Li \&.Ar file1\ .
+.Ar file1 .
+.It Li \&.Ar file1 file2
+.Ar file1 file2
+.It Li \&.Ar f1 f2 f3\ :
+.Ar f1 f2 f3 :
+.It Li \&.Ar file\ )\ )\ ,
+.Ar file ) ) ,
+.El
+.Pp
+If
+.Li \&.Ar
+is called without arguments
+.Ql Ar
+is assumed.
+The
+.Li \&.Ar
+macro is parsed and is callable.
+.Ss Configuration Declaration (section four only)
+The
+.Ql \&.Cd
+macro is used to demonstrate a
+.Xr config 8
+declaration for a device interface in a section four manual.
+This macro accepts quoted arguments (double quotes only).
+.Pp
+.Bl -tag -width "device le0 at scode?" -offset indent
+.It Cd "device le0 at scode?"
+produced by:
+.Ql ".Cd device le0 at scode?" .
+.El
+.Ss Command Modifier
+The command modifier is identical to the
+.Ql \&.Fl
+(flag) command with the exception
+the
+.Ql \&.Cm
+macro does not assert a dash
+in front of every argument.
+Traditionally flags are marked by the
+preceding dash, some commands or subsets of commands do not use them.
+Command modifiers may also be specified in conjunction with interactive
+commands such as editor commands.
+See
+.Sx Flags .
+.Ss Defined Variables
+A variable which is defined in an include file is specified
+by the macro
+.Ql \&.Dv .
+.Pp
+.Dl Usage: .Dv defined_variable ... \*(Pu
+.Bl -tag -width ".Dv MAXHOSTNAMELEN" -compact -offset 14n
+.It Li ".Dv MAXHOSTNAMELEN"
+.Dv MAXHOSTNAMELEN
+.It Li ".Dv TIOCGPGRP )"
+.Dv TIOCGPGRP )
+.El
+.Pp
+It is an error to call
+.Ql \&.Dv
+without arguments.
+.Ql \&.Dv
+is parsed and is callable.
+.Ss Errno's (Section two only)
+The
+.Ql \&.Er
+errno macro specifies the error return value
+for section two library routines.
+The second example
+below shows
+.Ql \&.Er
+used with the
+.Ql \&.Bq
+general text domain macro, as it would be used in
+a section two manual page.
+.Pp
+.Dl Usage: .Er ERRNOTYPE ... \*(Pu
+.Bl -tag -width ".Bq Er ENOTDIR" -compact -offset 14n
+.It Li \&.Er ENOENT
+.Er ENOENT
+.It Li \&.Er ENOENT\ )\ ;
+.Er ENOENT ) ;
+.It Li \&.Bq \&Er ENOTDIR
+.Bq Er ENOTDIR
+.El
+.Pp
+It is an error to call
+.Ql \&.Er
+without arguments.
+The
+.Ql \&.Er
+macro is parsed and is callable.
+.Ss Environment Variables
+The
+.Ql \&.Ev
+macro specifies an environment variable.
+.Pp
+.Dl Usage: .Ev argument ... \*(Pu
+.Bl -tag -width ".Ev PRINTER ) ) ," -compact -offset 14n
+.It Li \&.Ev DISPLAY
+.Ev DISPLAY
+.It Li \&.Ev PATH\ .
+.Ev PATH .
+.It Li \&.Ev PRINTER\ )\ )\ ,
+.Ev PRINTER ) ) ,
+.El
+.Pp
+It is an error to call
+.Ql \&.Ev
+without arguments.
+The
+.Ql \&.Ev
+macro is parsed and is callable.
+.Ss Function Argument
+The
+.Ql \&.Fa
+macro is used to refer to function arguments (parameters)
+outside of the
+.Sx SYNOPSIS
+section of the manual or inside
+the
+.Sx SYNOPSIS
+section should a parameter list be too
+long for the
+.Ql \&.Fn
+macro and the enclosure macros
+.Ql \&.Fo
+and
+.Ql \&.Fc
+must be used.
+.Ql \&.Fa
+may also be used to refer to structure members.
+.Pp
+.Dl Usage: .Fa function_argument ... \*(Pu
+.Bl -tag -width ".Fa d_namlen\ )\ )\ ," -compact -offset 14n
+.It Li \&.Fa d_namlen\ )\ )\ ,
+.Fa d_namlen ) ) ,
+.It Li \&.Fa iov_len
+.Fa iov_len
+.El
+.Pp
+It is an error to call
+.Ql \&.Fa
+without arguments.
+.Ql \&.Fa
+is parsed and is callable.
+.Ss Function Declaration
+The
+.Ql \&.Fd
+macro is used in the
+.Sx SYNOPSIS
+section with section two or three
+functions.
+The
+.Ql \&.Fd
+macro does not call other macros and is not callable by other
+macros.
+.Pp
+.Dl Usage: .Fd include_file (or defined variable)
+.Pp
+In the
+.Sx SYNOPSIS
+section a
+.Ql \&.Fd
+request causes a line break if a function has already been presented
+and a break has not occurred.
+This leaves a nice vertical space
+in between the previous function call and the declaration for the
+next function.
+.Ss Flags
+The
+.Ql \&.Fl
+macro handles command line flags.
+It prepends
+a dash,
+.Ql \- ,
+to the flag.
+For interactive command flags, which
+are not prepended with a dash, the
+.Ql \&.Cm
+(command modifier)
+macro is identical, but without the dash.
+.Pp
+.Dl Usage: .Fl argument ... \*(Pu
+.Bl -tag -width ".Fl \-s \-t \-v" -compact -offset 14n
+.It Li \&.Fl
+.Fl
+.It Li \&.Fl cfv
+.Fl cfv
+.It Li \&.Fl cfv\ .
+.Fl cfv .
+.It Li \&.Fl s v t
+.Fl s v t
+.It Li \&.Fl -\ ,
+.Fl - ,
+.It Li \&.Fl xyz\ )\ ,
+.Fl xyz ) ,
+.El
+.Pp
+The
+.Ql \&.Fl
+macro without any arguments results
+in a dash representing stdin/stdout.
+Note that giving
+.Ql \&.Fl
+a single dash, will result in two dashes.
+The
+.Ql \&.Fl
+macro is parsed and is callable.
+.Ss Functions (library routines)
+The .Fn macro is modeled on ANSI C conventions.
+.Bd -literal
+Usage: .Fn [type] function [[type] parameters ... \*(Pu]
+.Ed
+.Bl -tag -width ".Fn .int align. .const * char *sptrsxx" -compact
+.It Li "\&.Fn getchar"
+.Fn getchar
+.It Li "\&.Fn strlen ) ,"
+.Fn strlen ) ,
+.It Li \&.Fn "\\*qint align\\*q" "\\*qconst * char *sptrs\\*q" ,
+.Fn "int align" "const * char *sptrs" ,
+.El
+.Pp
+It is an error to call
+.Ql \&.Fn
+without any arguments.
+The
+.Ql \&.Fn
+macro
+is parsed and is callable,
+note that any call to another macro signals the end of
+the
+.Ql \&.Fn
+call (it will close-parenthesis at that point).
+.Pp
+For functions that have more than eight parameters (and this
+is rare), the
+macros
+.Ql \&.Fo
+(function open)
+and
+.Ql \&.Fc
+(function close)
+may be used with
+.Ql \&.Fa
+(function argument)
+to get around the limitation. For example:
+.Bd -literal -offset indent
+\&.Fo "int res_mkquery"
+\&.Fa "int op"
+\&.Fa "char *dname"
+\&.Fa "int class"
+\&.Fa "int type"
+\&.Fa "char *data"
+\&.Fa "int datalen"
+\&.Fa "struct rrec *newrr"
+\&.Fa "char *buf"
+\&.Fa "int buflen"
+\&.Fc
+.Ed
+.Pp
+Produces:
+.Bd -filled -offset indent
+.Fo "int res_mkquery"
+.Fa "int op"
+.Fa "char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "char *data"
+.Fa "int datalen"
+.Fa "struct rrec *newrr"
+.Fa "char *buf"
+.Fa "int buflen"
+.Fc
+.Ed
+.Pp
+The
+.Ql \&.Fo
+and
+.Ql \&.Fc
+macros are parsed and are callable.
+In the
+.Sx SYNOPSIS
+section, the function will always begin at
+the beginning of line.
+If there is more than one function
+presented in the
+.Sx SYNOPSIS
+section and a function type has not been
+given, a line break will occur, leaving a nice vertical space
+between the current function name and the one prior.
+At the moment,
+.Ql \&.Fn
+does not check its word boundaries
+against troff line lengths and may split across a newline
+ungracefully.
+This will be fixed in the near future.
+.Ss Function Type
+This macro is intended for the
+.Sx SYNOPSIS
+section.
+It may be used
+anywhere else in the man page without problems, but its main purpose
+is to present the function type in kernel normal form for the
+.Sx SYNOPSIS
+of sections two and three
+(it causes a page break allowing the function name to appear
+on the next line).
+.Pp
+.Dl Usage: .Ft type ... \*(Pu
+.Bl -tag -width "\&.Ft struct stat" -offset 14n -compact
+.It Li \&.Ft struct stat
+.Ft struct stat
+.El
+.Pp
+The
+.Ql \&.Ft
+request is not callable by other macros.
+.Ss Interactive Commands
+The
+.Ql \&.Ic
+macro designates an interactive or internal command.
+.Pp
+.Dl Usage: .Li argument ... \*(Pu
+.Bl -tag -width ".Ic setenv , unsetenvxx" -compact -offset 14n
+.It Li \&.Ic :wq
+.Ic :wq
+.It Li \&.Ic do while {...}
+.Ic do while {...}
+.It Li \&.Ic setenv\ , unsetenv
+.Ic setenv , unsetenv
+.El
+.Pp
+It is an error to call
+.Ql \&.Ic
+without arguments.
+The
+.Ql \&.Ic
+macro is parsed and is callable.
+.Ss Literals
+The
+.Ql \&.Li
+literal macro may be used for special characters,
+variable constants, anything which should be displayed as it
+would be typed.
+.Pp
+.Dl Usage: .Li argument ... \*(Pu
+.Bl -tag -width ".Li cntrl-D ) ," -compact -offset 14n
+.It Li \&.Li \een
+.Li \en
+.It Li \&.Li M1 M2 M3\ ;
+.Li M1 M2 M3 ;
+.It Li \&.Li cntrl-D\ )\ ,
+.Li cntrl-D ) ,
+.It Li \&.Li 1024\ ...
+.Li 1024 ...
+.El
+.Pp
+The
+.Ql \&.Li
+macro is parsed and is callable.
+.Ss Name Macro
+The
+.Ql \&.Nm
+macro is used for the document title or subject name.
+It has the peculiarity of remembering the first
+argument it was called with, which should
+always be the subject name of the page.
+When called without
+arguments,
+.Ql \&.Nm
+regurgitates this initial name for the sole purpose
+of making less work for the author.
+If trailing punctuation is required with this feature,
+use
+.Qq
+as a first argument to
+.Ql \&.Nm .
+Note:
+a section two
+or three document function name is addressed with the
+.Ql \&.Nm
+in the
+.Sx NAME
+section, and with
+.Ql \&.Fn
+in the
+.Sx SYNOPSIS
+and remaining sections.
+For interactive commands, such as the
+.Ql while
+command keyword in
+.Xr csh 1 ,
+the
+.Ql \&.Ic
+macro should be used.
+While the
+.Ql \&.Ic
+is nearly identical
+to
+.Ql \&.Nm ,
+it can not recall the first argument it was invoked with.
+.Pp
+.Dl Usage: .Nm argument ... \*(Pu
+.Bl -tag -width ".Nm mdoc.samples" -compact -offset 14n
+.It Li \&.Nm mdoc.samples
+.Nm mdoc.samples
+.It Li \&.Nm \e-mdoc
+.Nm \-mdoc
+.It Li \&.Nm foo\ )\ )\ ,
+.Nm foo ) ) ,
+.It Li \&.Nm
+.Nm
+.It Li \&.Nm \&"\&"\ :
+.Nm "" :
+.El
+.Pp
+The
+.Ql \&.Nm
+macro is parsed and is callable.
+.Ss Options
+The
+.Ql \&.Op
+macro
+places option brackets around the any remaining arguments on the command
+line, and places any
+trailing punctuation outside the brackets.
+The macros
+.Ql \&.Oc
+and
+.Ql \&.Oo
+may be used across one or more lines.
+.Pp
+.Dl Usage: .Op options ... \*(Pu
+.Bl -tag -width ".Op Fl c Ar objfil Op Ar corfil ," -compact -offset indent
+.It Li \&.Op
+.Op
+.It Li ".Op Fl k"
+.Op Fl k
+.It Li ".Op Fl k ) ."
+.Op Fl k ) .
+.It Li ".Op Fl k Ar kookfile"
+.Op Fl k Ar kookfile
+.It Li ".Op Fl k Ar kookfile ,"
+.Op Fl k Ar kookfile ,
+.It Li ".Op Ar objfil Op Ar corfil"
+.Op Ar objfil Op Ar corfil
+.It Li ".Op Fl c Ar objfil Op Ar corfil ,"
+.Op Fl c Ar objfil Op Ar corfil ,
+.It Li \&.Op word1 word2
+.Op word1 word2
+.El
+.Pp
+The
+.Ql \&.Oc
+and
+.Ql \&.Oo
+macros:
+.Bd -literal -offset indent
+\&.Oo
+\&.Op \&Fl k \&Ar kilobytes
+\&.Op \&Fl i \&Ar interval
+\&.Op \&Fl c \&Ar count
+\&.Oc
+.Ed
+.Pp
+Produce:
+.Oo
+.Op Fl k Ar kilobytes
+.Op Fl i Ar interval
+.Op Fl c Ar count
+.Oc
+.Pp
+The macros
+.Ql \&.Op ,
+.Ql \&.Oc
+and
+.Ql \&.Oo
+are parsed and are callable.
+.Ss Pathnames
+The
+.Ql \&.Pa
+macro formats path or file names.
+.Pp
+.Dl Usage: .Pa pathname \*(Pu
+.Bl -tag -width ".Pa /tmp/fooXXXXX ) ." -compact -offset 14n
+.It Li \&.Pa /usr/share
+.Pa /usr/share
+.It Li \&.Pa /tmp/fooXXXXX\ )\ .
+.Pa /tmp/fooXXXXX ) .
+.El
+.Pp
+The
+.Ql \&.Pa
+macro is parsed and is callable.
+.Ss Variables
+Generic variable reference:
+.Pp
+.Dl Usage: .Va variable ... \*(Pu
+.Bl -tag -width ".Va char s ] ) ) ," -compact -offset 14n
+.It Li \&.Va count
+.Va count
+.It Li \&.Va settimer ,
+.Va settimer ,
+.It Li \&.Va int\ *prt\ )\ :
+.Va int\ *prt ) :
+.It Li \&.Va char\ s\ ]\ )\ )\ ,
+.Va char\ s ] ) ) ,
+.El
+.Pp
+It is an error to call
+.Ql \&.Va
+without any arguments.
+The
+.Ql \&.Va
+macro is parsed and is callable.
+.Ss Manual Page Cross References
+The
+.Ql \&.Xr
+macro expects the first argument to be
+a manual page name, and the second argument, if it exists,
+to be either a section page number or punctuation.
+Any
+remaining arguments are assumed to be punctuation.
+.Pp
+.Dl Usage: .Xr man_page [1,...,9] \*(Pu
+.Bl -tag -width ".Xr mdoc 7 ) ) ," -compact -offset 14n
+.It Li \&.Xr mdoc
+.Xr mdoc
+.It Li \&.Xr mdoc\ ,
+.Xr mdoc ,
+.It Li \&.Xr mdoc 7
+.Xr mdoc 7
+.It Li \&.Xr mdoc 7\ )\ )\ ,
+.Xr mdoc 7 ) ) ,
+.El
+.Pp
+The
+.Ql \&.Xr
+macro is parsed and is callable.
+It is an error to call
+.Ql \&.Xr
+without
+any arguments.
+.Sh GENERAL TEXT DOMAIN
+.Ss AT&T Macro
+.Bd -literal -offset indent -compact
+Usage: .At [v1 .. v7 | 32v | V.1 | V.4] ... \*(Pu
+.Ed
+.Bl -tag -width ".At v6 ) ," -compact -offset 14n
+.It Li ".At"
+.At
+.It Li ".At v6 ."
+.At v6 .
+.El
+.Pp
+The
+.Ql \&.At
+macro is
+.Em not
+parsed and
+.Em not
+callable. It accepts at most two arguments.
+.Ss BSD Macro
+.Dl Usage: .Bx [Version/release] ... \*(Pu
+.Bl -tag -width ".Bx 4.3 ) ," -compact -offset 14n
+.It Li ".Bx"
+.Bx
+.It Li ".Bx 4.3 ."
+.Bx 4.3 .
+.El
+.Pp
+The
+.Ql \&.Bx
+macro is parsed and is callable.
+.Ss NetBSD Macro
+.Dl Usage: .Nx [Version/release] ... \*(Pu
+.Bl -tag -width ".Nx 1.4 ) ," -compact -offset 14n
+.It Li ".Nx"
+.Nx
+.It Li ".Nx 1.4 ."
+.Nx 1.4 .
+.El
+.Pp
+The
+.Ql \&.Nx
+macro is parsed and is callable.
+.Ss FreeBSD Macro
+.Dl Usage: .Fx [Version/release] ... \*(Pu
+.Bl -tag -width ".Fx 2.2 ) ," -compact -offset 14n
+.It Li ".Fx"
+.Fx
+.It Li ".Fx 2.2 ."
+.Fx 2.2 .
+.El
+.Pp
+The
+.Ql \&.Fx
+macro is parsed and is callable.
+.Ss UNIX Macro
+.Dl Usage: .Ux ... \*(Pu
+.Bl -tag -width ".Ux 4.3 ) ," -compact -offset 14n
+.It Li ".Ux"
+.Ux
+.El
+.Pp
+The
+.Ql \&.Ux
+macro is parsed and is callable.
+.Ss Emphasis Macro
+Text may be stressed or emphasized with the
+.Ql \&.Em
+macro.
+The usual font for emphasis is italic.
+.Pp
+.Dl Usage: .Em argument ... \*(Pu
+.Bl -tag -width ".Em vide infra ) ) ," -compact -offset 14n
+.It Li ".Em does not"
+.Em does not
+.It Li ".Em exceed 1024 ."
+.Em exceed 1024 .
+.It Li ".Em vide infra ) ) ,"
+.Em vide infra ) ) ,
+.El
+.\" .Pp
+.\" The emphasis can be forced across several lines of text by using
+.\" the
+.\" .Ql \&.Bf
+.\" macro discussed in
+.\" .Sx Modes
+.\" under
+.\" .Sx PAGE STRUCTURE DOMAIN .
+.\" .Pp
+.\" .Bf -emphasis
+.\" We are certain the reason most people desire a Harvard MBA
+.\" so they can become to be successful philanthropists. Only
+.\" mathematicians and physicists go to graduate school strictly
+.\" to acquire infinite wealthy and fame. Its that inifinity
+.\" word that does it to them. Ruins them.
+.\" .Ef
+.Pp
+The
+.Ql \&.Em
+macro is parsed and is callable.
+It is an error to call
+.Ql \&.Em
+without arguments.
+.Ss Enclosure and Quoting Macros
+The concept of enclosure is similar to quoting.
+The object being to enclose one or more strings between
+a pair of characters like quotes or parentheses.
+The terms quoting and enclosure are used
+interchangeably throughout this document.
+Most of the
+one line enclosure macros end
+in small letter
+.Ql q
+to give a hint of quoting, but there are a few irregularities.
+For each enclosure macro
+there is also a pair of open and close macros which end
+in small letters
+.Ql o
+and
+.Ql c
+respectively.
+These can be used across one or more lines of text
+and while they have nesting limitations, the one line quote macros
+can be used inside
+of them.
+.Pp
+.ne 5
+.Bd -filled -offset indent
+.Bl -column "quote " "close " "open " "Enclose Stringx(in XX) " XXstringXX
+.Em " Quote Close Open Function Result"
+\&.Aq .Ac .Ao Angle Bracket Enclosure <string>
+\&.Bq .Bc .Bo Bracket Enclosure [string]
+\&.Dq .Dc .Do Double Quote ``string''
+ .Ec .Eo Enclose String (in XX) XXstringXX
+\&.Pq .Pc .Po Parenthesis Enclosure (string)
+\&.Ql Quoted Literal `st' or string
+\&.Qq .Qc .Qo Straight Double Quote "string"
+\&.Sq .Sc .So Single Quote `string'
+.El
+.Ed
+.Pp
+Except for the irregular macros noted below, all
+of the quoting macros are parsed and callable.
+All handle punctuation properly, as long as it
+is presented one character at a time and separated by spaces.
+The quoting macros examine opening and closing punctuation
+to determine whether it comes before or after the
+enclosing string. This makes some nesting possible.
+.Bl -tag -width xxx,xxxx
+.It Li \&.Ec , \&.Eo
+These macros expect the first argument to be the
+opening and closing strings respectively.
+.It Li \&.Ql
+The quoted literal macro behaves differently for
+.Xr troff
+than
+.Xr nroff .
+If formatted with
+.Xr nroff ,
+a quoted literal is always quoted. If formatted with
+troff, an item is only quoted if the width
+of the item is less than three constant width characters.
+This is to make short strings more visible where the font change
+to literal (constant width) is less noticeable.
+.It Li \&.Pf
+The prefix macro is not callable, but it is parsed:
+.Bl -tag -width "(namexx" -offset indent
+.It Li ".Pf ( Fa name2"
+becomes
+.Pf ( Fa name2 .
+.El
+.It Li \&.Ns
+The
+.Ql \&.Ns
+(no space) macro, which
+.Em is
+callable,
+performs the analogous suffix function.
+.It Li ".Ap
+The \&.Ap macro inserts an apostrophe and exits any special text modes,
+continuing in
+.Li \&.No
+mode.
+.El
+.Pp
+.ne 4
+Examples of quoting:
+.Bl -tag -width ".Aq Pa ctype.h ) ,xxxxxxxx" -compact -offset indent
+.It Li \&.Aq
+.Aq
+.It Li \&.Aq \&Ar ctype.h\ )\ ,
+.Aq Ar ctype.h ) ,
+.It Li \&.Bq
+.Bq
+.It Li \&.Bq \&Em Greek \&, French \&.
+.Bq Em Greek , French .
+.It Li \&.Dq
+.Dq
+.It Li ".Dq string abc ."
+.Dq string abc .
+.It Li ".Dq \'^[A-Z]\'"
+.Dq \'^[A-Z]\'
+.It Li "\&.Ql man mdoc"
+.Ql man mdoc
+.It Li \&.Qq
+.Qq
+.It Li "\&.Qq string ) ,"
+.Qq string ) ,
+.It Li "\&.Qq string Ns ),"
+.Qq string Ns ),
+.It Li \&.Sq
+.Sq
+.It Li "\&.Sq string
+.Sq string
+.It Li "\&.Em or Ap ing
+.Em or Ap ing
+.El
+.Pp
+For a good example of nested enclosure macros, see the
+.Ql \&.Op
+option macro.
+It was created from the same
+underlying enclosure macros as those presented in the list
+above.
+The
+.Ql \&.Xo
+and
+.Ql \&.Xc
+extended argument list macros
+were also built from the same underlying routines and are a good
+example of
+.Nm \-mdoc
+macro usage at its worst.
+.Ss No\-Op or Normal Text Macro
+The macro
+.Li \&.No
+is
+a hack for words in a macro command line which should
+.Em not
+be formatted and follows the conventional syntax
+for content macros.
+.Ss No Space Macro
+The
+.Ql \&.Ns
+macro eliminates unwanted spaces in between macro requests.
+It is useful for old style argument lists where there is no space
+between the flag and argument:
+.Bl -tag -width ".Op Fl I Ns Ar directoryxx" -offset indent
+.It Li ".Op Fl I Ns Ar directory"
+produces
+.Op Fl I Ns Ar directory
+.El
+.Pp
+Note: the
+.Ql \&.Ns
+macro always invokes the
+.Ql \&.No
+macro after eliminating the space unless another macro name
+follows it.
+The macro
+.Ql \&.Ns
+is parsed and is callable.
+.Ss Section Cross References
+The
+.Ql \&.Sx
+macro designates a reference to a section header
+within the same document.
+It is parsed and is callable.
+.Pp
+.Bl -tag -width "Li \&.Sx FILES" -offset 14n
+.It Li \&.Sx FILES
+.Sx FILES
+.El
+.Ss Symbolic
+The symbolic emphasis macro is generally a boldface macro in
+either the symbolic sense or the traditional English usage.
+.Pp
+.Dl Usage: .Sy symbol ... \*(Pu
+.Bl -tag -width ".Sy Important Noticex" -compact -offset 14n
+.It Li \&.Sy Important Notice
+.Sy Important Notice
+.El
+.Pp
+The
+.Ql \&.Sy
+macro is parsed and is callable.
+Arguments to
+.Ql \&.Sy
+may be quoted.
+.Ss References and Citations
+The following macros make a modest attempt to handle references.
+At best, the macros make it convenient to manually drop in a subset of
+refer style references.
+.Pp
+.Bl -tag -width 6n -offset indent -compact
+.It Li ".Rs"
+Reference Start.
+Causes a line break and begins collection
+of reference information until the
+reference end macro is read.
+.It Li ".Re"
+Reference End.
+The reference is printed.
+.It Li ".%A"
+Reference author name, one name per invocation.
+.It Li ".%B"
+Book title.
+.It Li ".\&%C"
+City/place.
+.It Li ".\&%D"
+Date.
+.It Li ".%J"
+Journal name.
+.It Li ".%N"
+Issue number.
+.It Li ".%O"
+Optional information.
+.It Li ".%P"
+Page number.
+.It Li ".%R"
+Report name.
+.It Li ".%T"
+Title of article.
+.It Li ".%V"
+Volume(s).
+.El
+.Pp
+The macros beginning with
+.Ql %
+are not callable, and are parsed only for the trade name macro which
+returns to its caller.
+(And not very predictably at the moment either.)
+The purpose is to allow trade names
+to be pretty printed in
+.Xr troff Ns / Ns Xr ditroff
+output.
+.Ss Trade Names (or Acronyms and Type Names)
+The trade name macro is generally a small caps macro for
+all upper case words longer than two characters.
+.Pp
+.Dl Usage: .Tn symbol ... \*(Pu
+.Bl -tag -width ".Tn ASCII" -compact -offset 14n
+.It Li \&.Tn DEC
+.Tn DEC
+.It Li \&.Tn ASCII
+.Tn ASCII
+.El
+.Pp
+The
+.Ql \&.Tn
+macro
+is parsed and is callable by other macros.
+.Ss Extended Arguments
+The
+.Li \&.Xo
+and
+.Li \&.Xc
+macros allow one to extend an argument list
+on a macro boundary.
+Argument lists cannot
+be extended within a macro
+which expects all of its arguments on one line such
+as
+.Ql \&.Op .
+.Pp
+Here is an example of
+.Ql \&.Xo
+using the space mode macro to turn spacing off:
+.Bd -literal -offset indent
+\&.Sm off
+\&.It Xo Sy I Ar operation
+\&.No \een Ar count No \een
+\&.Xc
+\&.Sm on
+.Ed
+.Pp
+Produces
+.Bd -filled -offset indent
+.Bl -tag -width flag -compact
+.Sm off
+.It Xo Sy I Ar operation
+.No \en Ar count No \en
+.Xc
+.Sm on
+.El
+.Ed
+.Pp
+Another one:
+.Bd -literal -offset indent
+\&.Sm off
+\&.It Cm S No \&/ Ar old_pattern Xo
+\&.No \&/ Ar new_pattern
+\&.No \&/ Op Cm g
+\&.Xc
+\&.Sm on
+.Ed
+.Pp
+Produces
+.Bd -filled -offset indent
+.Bl -tag -width flag -compact
+.Sm off
+.It Cm S No \&/ Ar old_pattern Xo
+.No \&/ Ar new_pattern
+.No \&/ Op Cm g
+.Xc
+.Sm on
+.El
+.Ed
+.Pp
+Another example of
+.Ql \&.Xo
+and using enclosure macros:
+Test the value of an variable.
+.Bd -literal -offset indent
+\&.It Xo
+\&.Ic .ifndef
+\&.Oo \e&! Oc Ns Ar variable
+\&.Op Ar operator variable ...
+\&.Xc
+.Ed
+.Pp
+Produces
+.Bd -filled -offset indent
+.Bl -tag -width flag -compact
+.It Xo
+.Ic .ifndef
+.Oo \&! Oc Ns Ar variable
+.Op Ar operator variable ...
+.Xc
+.El
+.Ed
+.Pp
+All of the above examples have used the
+.Ql \&.Xo
+macro on the argument list of the
+.Ql \&.It
+(list-item)
+macro.
+The extend macros are not used very often, and when they are
+it is usually to extend the list-item argument list.
+Unfortunately, this is also where the extend macros are the
+most finicky.
+In the first two examples, spacing was turned off;
+in the third, spacing was desired in part of the output but
+not all of it.
+To make these macros work in this situation make sure
+the
+.Ql \&.Xo
+and
+.Ql \&.Xc
+macros are placed as shown in the third example.
+If the
+.Ql \&.Xo
+macro is not alone on the
+.Ql \&.It
+argument list, spacing will be unpredictable.
+The
+.Ql \&.Ns
+(no space macro)
+must not occur as the first or last macro on a line
+in this situation.
+Out of 900 manual pages (about 1500 actual pages)
+currently released with
+.Bx
+only fifteen use the
+.Ql \&.Xo
+macro.
+.Sh PAGE STRUCTURE DOMAIN
+.Ss Section Headers
+The first three
+.Ql \&.Sh
+section header macros
+list below are required in every
+man page.
+The remaining section headers
+are recommended at the discretion of the author
+writing the manual page.
+The
+.Ql \&.Sh
+macro can take up to nine arguments.
+It is parsed and but is not callable.
+.Bl -tag -width ".Sh SYNOPSIS"
+.It \&.Sh NAME
+The
+.Ql \&.Sh NAME
+macro is mandatory.
+If not specified,
+the headers, footers and page layout defaults
+will not be set and things will be rather unpleasant.
+The
+.Sx NAME
+section consists of at least three items.
+The first is the
+.Ql \&.Nm
+name macro naming the subject of the man page.
+The second is the Name Description macro,
+.Ql \&.Nd ,
+which separates the subject
+name from the third item, which is the description.
+The
+description should be the most terse and lucid possible,
+as the space available is small.
+.It \&.Sh SYNOPSIS
+The
+.Sx SYNOPSIS
+section describes the typical usage of the
+subject of a man page.
+The macros required
+are either
+.Ql ".Nm" ,
+.Ql ".Cd" ,
+.Ql ".Fn" ,
+(and possibly
+.Ql ".Fo" ,
+.Ql ".Fc" ,
+.Ql ".Fd" ,
+.Ql ".Ft"
+macros).
+The function name
+macro
+.Ql ".Fn"
+is required
+for manual page sections 2 and 3, the command and general
+name macro
+.Ql \&.Nm
+is required for sections 1, 5, 6, 7, 8.
+Section 4 manuals require a
+.Ql ".Nm" , ".Fd"
+or a
+.Ql ".Cd"
+configuration device usage macro.
+Several other macros may be necessary to produce
+the synopsis line as shown below:
+.Pp
+.Bd -filled -offset indent
+.Nm cat
+.Op Fl benstuv
+.Op Fl
+.Ar
+.Ed
+.Pp
+The following macros were used:
+.Pp
+.Dl \&.Nm cat
+.Dl \&.Op \&Fl benstuv
+.Dl \&.Op \&Fl
+.Dl \&.Ar
+.Pp
+.Sy Note :
+The macros
+.Ql \&.Op ,
+.Ql \&.Fl ,
+and
+.Ql \&.Ar
+recognize the pipe bar character
+.Ql \*(Ba ,
+so a command line such as:
+.Pp
+.Dl ".Op Fl a | Fl b"
+.Pp
+will not go orbital.
+.Xr Troff
+normally interprets a \*(Ba as a special operator.
+See
+.Sx PREDEFINED STRINGS
+for a usable \*(Ba
+character in other situations.
+.It \&.Sh DESCRIPTION
+In most cases the first text in the
+.Sx DESCRIPTION
+section
+is a brief paragraph on the command, function or file,
+followed by a lexical list of options and respective
+explanations.
+To create such a list, the
+.Ql \&.Bl
+begin-list,
+.Ql \&.It
+list-item and
+.Ql \&.El
+end-list
+macros are used (see
+.Sx Lists and Columns
+below).
+.El
+.Pp
+The following
+.Ql \&.Sh
+section headers are part of the
+preferred manual page layout and must be used appropriately
+to maintain consistency.
+They are listed in the order
+in which they would be used.
+.Bl -tag -width SYNOPSIS
+.It \&.Sh ENVIRONMENT
+The
+.Sx ENVIRONMENT
+section should reveal any related
+environment
+variables and clues to their behavior and/or usage.
+.It \&.Sh EXAMPLES
+There are several ways to create examples.
+See
+the
+.Sx EXAMPLES
+section below
+for details.
+.It \&.Sh FILES
+Files which are used or created by the man page subject
+should be listed via the
+.Ql \&.Pa
+macro in the
+.Sx FILES
+section.
+.It \&.Sh SEE ALSO
+References to other material on the man page topic and
+cross references to other relevant man pages should
+be placed in the
+.Sx SEE ALSO
+section.
+Cross references
+are specified using the
+.Ql \&.Xr
+macro.
+At this time
+.Xr refer 1
+style references are not accommodated.
+.Pp
+It is recommended that the cross references are sorted on the section
+number, and then alphabetically on the names within a section.
+.It \&.Sh STANDARDS
+If the command, library function or file adheres to a
+specific implementation such as
+.St -p1003.2
+or
+.St -ansiC
+this should be noted here.
+If the
+command does not adhere to any standard, its history
+should be noted in the
+.Sx HISTORY
+section.
+.It \&.Sh HISTORY
+Any command which does not adhere to any specific standards
+should be outlined historically in this section.
+.It \&.Sh AUTHORS
+Credits, if need be, should be placed here.
+.It \&.Sh DIAGNOSTICS
+Diagnostics from a command should be placed in this section.
+.It \&.Sh ERRORS
+Specific error handling, especially from library functions
+(man page sections 2 and 3) should go here.
+The
+.Ql \&.Er
+macro is used to specify an errno.
+.It \&.Sh BUGS
+Blatant problems with the topic go here...
+.El
+.Pp
+User specified
+.Ql \&.Sh
+sections may be added,
+for example, this section was set with:
+.Bd -literal -offset 14n
+\&.Sh PAGE LAYOUT MACROS
+.Ed
+.Ss Paragraphs and Line Spacing.
+.Bl -tag -width 6n
+.It \&.Pp
+The \&.Pp paragraph command may
+be used to specify a line space where necessary.
+The macro is not necessary after a
+.Ql \&.Sh
+or
+.Ql \&.Ss
+macro or before
+a
+.Ql \&.Bl
+macro.
+(The
+.Ql \&.Bl
+macro asserts a vertical distance unless the -compact flag is given).
+.El
+.\" This worked with version one, need to redo for version three
+.\" .Pp
+.\" .Ds I
+.\" .Cw (ax+bx+c) \ is\ produced\ by\ \&
+.\" .\".Cw (ax+bx+c) \&.Va_by_) \&_and_\& \&[?/]m_b1_e1_f1[?/]\&
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx\ (
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va ax
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy \+
+.\" .Cx
+.\" .Cl Cx \&(\&
+.\" .Va ax
+.\" .Cx +
+.\" .Va by
+.\" .Cx +
+.\" .Va c )
+.\" .Cx \t
+.\" .Em is produced by
+.\" .Cx \t
+.\" .Li \&.Va by
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy \+
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va c )
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx
+.\" .Cx
+.\" .Cw
+.\" .De
+.\" .Pp
+.\" This example shows the same equation in a different format.
+.\" The spaces
+.\" around the
+.\" .Li \&+
+.\" signs were forced with
+.\" .Li \e :
+.\" .Pp
+.\" .Ds I
+.\" .Cw (ax\ +\ bx\ +\ c) \ is\ produced\ by\ \&
+.\" .\".Cw (ax+bx+c) \&.Va_by_) \&_and_\& \&[?/]m_b1_e1_f1[?/]\&
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx\ (
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va a
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy x
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx \e\ +\e\ \e&
+.\" .Cx
+.\" .Cl Cx \&(\&
+.\" .Va a
+.\" .Sy x
+.\" .Cx \ +\ \&
+.\" .Va b
+.\" .Sy y
+.\" .Cx \ +\ \&
+.\" .Va c )
+.\" .Cx \t
+.\" .Em is produced by
+.\" .Cl Cx \t\t
+.\" .Li \&.Va b
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Sy y
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx \e\ +\e\ \e&
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Va c )
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx
+.\" .Cx
+.\" .Cw
+.\" .De
+.\" .Pp
+.\" The incantation below was
+.\" lifted from the
+.\" .Xr adb 1
+.\" manual page:
+.\" .Pp
+.\" .Ds I
+.\" .Cw \&[?/]m_b1_e1_f1[?/]\& is\ produced\ by
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx Op Sy ?/
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Nm m
+.\" .Cx
+.\" .Cl Cx Op Sy ?/
+.\" .Nm m
+.\" .Ad \ b1 e1 f1
+.\" .Op Sy ?/
+.\" .Cx \t
+.\" .Em is produced by
+.\" .Cx \t
+.\" .Li \&.Ar \e\ b1 e1 f1
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Op Sy ?/
+.\" .Cx
+.\" .Cl Cx \t\t
+.\" .Li \&.Cx
+.\" .Cx
+.\" .Cw
+.\" .De
+.\" .Pp
+.Ss Keeps
+The only keep that is implemented at this time is for words.
+The macros are
+.Ql \&.Bk
+(begin-keep)
+and
+.Ql \&.Ek
+(end-keep).
+The only option that
+.Ql \&.Bl
+accepts is
+.Fl words
+and is useful for preventing line breaks in the middle of options.
+In the example for the make command line arguments (see
+.Sx What's in a name ) ,
+the keep prevented
+.Xr nroff
+from placing up the
+flag and the argument
+on separate lines.
+(Actually, the option macro used to prevent this from occurring,
+but was dropped when the decision (religious) was made to force
+right justified margins in
+.Xr troff
+as options in general look atrocious when spread across a sparse
+line.
+More work needs to be done with the keep macros, a
+.Fl line
+option needs to be added.)
+.Ss Examples and Displays
+There are six types of displays, a quickie one line indented display
+.Ql \&.D1 ,
+a quickie one line literal display
+.Ql \&.Dl ,
+and block literal, block filled, block unfilled, and block ragged which use
+the
+.Ql \&.Bd
+begin-display
+and
+.Ql \&.Ed
+end-display macros.
+.Pp
+.Bl -tag -width \&.Dlxx
+.It Li \&.D1
+(D-one) Display one line of indented text.
+This macro is parsed, but it is not callable.
+.Pp
+.Dl Fl ldghfstru
+.Pp
+The above was produced by:
+.Li \&.Dl Fl ldghfstru .
+.It Li \&.Dl
+(D-ell)
+Display one line of indented
+.Em literal
+text.
+The
+.Ql \&.Dl
+example macro has been used throughout this
+file.
+It allows
+the indent (display) of one line of text.
+Its default font is set to
+constant width (literal) however
+it is parsed and will recognized other macros.
+It is not callable however.
+.Pp
+.Dl % ls -ldg /usr/local/bin
+.Pp
+The above was produced by
+.Li \&.Dl % ls -ldg /usr/local/bin .
+.It Li \&.Bd
+Begin-display.
+The
+.Ql \&.Bd
+display must be ended with the
+.Ql \&.Ed
+macro.
+Displays may be nested within lists, but may
+.Em not
+contain other displays; this also prohibits nesting
+of .D1 and .Dl one-line displays.
+.Ql \&.Bd
+has the following syntax:
+.Pp
+.Dl ".Bd display-type [-offset offset_value] [-compact]"
+.Pp
+The display-type must be one of the following four types and
+may have an offset specifier for indentation:
+.Ql \&.Bd .
+.Pp
+.Bl -tag -width "file file_name " -compact
+.It Fl ragged
+Fill, but do not adjust the right margin.
+.It Fl unfilled
+Do not fill: display a block of text as typed, the
+right (and left) margin edges are left ragged.
+.It Fl filled
+Display a filled (formatted) block.
+The block of text is formatted (the edges are filled \-
+not left unjustified).
+.It Fl literal
+Display a literal block, useful for source code or
+simple tabbed or spaced text.
+.It Fl file Ar file_name
+The file name following the
+.Fl file
+flag is read and displayed.
+Literal mode is
+asserted and tabs are set at 8 constant width character
+intervals, however any
+.Xr troff/ Ns Nm \-mdoc
+commands in file will be processed.
+.It Fl offset Ar string
+If
+.Fl offset
+is specified with one of the following strings, the string
+is interpreted to indicate the level of indentation for the
+forthcoming block of text:
+.Pp
+.Bl -tag -width "indent-two" -compact
+.It Ar left
+Align block on the current left margin,
+this is the default mode of
+.Ql \&.Bd .
+.It Ar center
+Supposedly center the block.
+At this time
+unfortunately, the block merely gets
+left aligned about an imaginary center margin.
+.It Ar indent
+Indents by one default indent value or tab.
+The default
+indent value is also used for the
+.Ql \&.D1
+display so one is guaranteed the two types of displays
+will line up.
+This indent is normally set to 6n or about two
+thirds of an inch (six constant width characters).
+.It Ar indent-two
+Indents two times the default indent value.
+.It Ar right
+This
+.Em left
+aligns the block about two inches from
+the right side of the page.
+This macro needs
+work and perhaps may never do the right thing by
+.Xr troff .
+.El
+.El
+.It ".Ed"
+End-display.
+.El
+.Ss Tagged Lists and Columns
+There are several types of lists which may be initiated with the
+.Ql ".Bl"
+begin-list macro.
+Items within the list
+are specified with the
+.Ql ".It"
+item macro and
+each list must end with the
+.Ql ".El"
+macro.
+Lists other than
+.Li \-enum
+may be nested within themselves and within displays.
+The use of columns inside of lists or lists inside of columns
+is unproven.
+.Pp
+In addition, several list attributes may be specified such as
+the width of a tag, the list offset, and compactness
+(blank lines between items allowed or disallowed).
+Most of this document has been formatted with a tag style list
+.Pq Fl tag .
+For a change of pace, the list-type used to present the list-types
+is an over-hanging list
+.Pq Fl ohang .
+This type of list is quite popular with
+.Tn TeX
+users, but might look a bit funny after having read many pages of
+tagged lists.
+The following list types are accepted by
+.Ql ".Bl" :
+.Pp
+.Bl -ohang -compact
+.It Fl bullet
+.It Fl dash
+.It Fl enum
+.It Fl hyphen
+.It Fl item
+These five are the simplest types of lists.
+Once the
+.Ql ".Bl"
+macro has been given, items in the list are merely
+indicated by a line consisting solely of the
+.Ql ".It"
+macro.
+For example, the source text for a simple enumerated list
+would look like:
+.Bd -literal -offset indent-two
+\&.Bl -enum -compact
+\&.It
+\&Item one goes here.
+\&.It
+\&And item two here.
+\&.It
+\&Lastly item three goes here.
+\&.El
+.Ed
+.Pp
+The results:
+.Pp
+.Bl -enum -offset indent-two -compact
+.It
+Item one goes here.
+.It
+And item two here.
+.It
+Lastly item three goes here.
+.El
+.Pp
+A simple bullet list construction:
+.Bd -literal -offset indent-two
+\&.Bl -bullet -compact
+\&.It
+\&Bullet one goes here.
+\&.It
+\&Bullet two here.
+\&.El
+.Ed
+.Pp
+Produces:
+.Bl -bullet -offset indent-two -compact
+.It
+Bullet one goes here.
+.It
+Bullet two here.
+.El
+.Pp
+.It Fl tag
+.It Fl diag
+.It Fl hang
+.It Fl ohang
+.It Fl inset
+These list-types collect arguments specified with the
+.Ql \&.It
+macro and create a label which may be
+.Em inset
+into the forthcoming text,
+.Em hanged
+from the forthcoming text,
+.Em overhanged
+from above and not indented or
+.Em tagged .
+This
+list was constructed with the
+.Ql Fl ohang
+list-type.
+The
+.Ql \&.It
+macro is parsed only for the inset, hang
+and tag list-types and is not callable.
+Here is an example of inset labels:
+.Bl -inset -offset indent
+.It Em Tag
+The tagged list (also called a tagged paragraph) is the
+most common type of list used in the Berkeley manuals. Use a
+.Fl width
+attribute as described below.
+.It Em Diag
+Diag lists create section four diagnostic lists
+and are similar to inset lists except callable
+macros are ignored.
+.It Em Hang
+Hanged labels are a matter of taste.
+.It Em Ohang
+Overhanging labels are nice when space is constrained.
+.It Em Inset
+Inset labels are useful for controlling blocks of
+paragraphs and are valuable for converting
+.Nm \-mdoc
+manuals to other formats.
+.El
+.Pp
+Here is the source text which produced the above example:
+.Bd -literal -offset indent
+\&.Bl -inset -offset indent
+\&.It Em Tag
+\&The tagged list (also called a tagged paragraph) is the
+\&most common type of list used in the Berkeley manuals.
+\&.It Em Diag
+\&Diag lists create section four diagnostic lists
+\&and are similar to inset lists except callable
+\&macros are ignored.
+\&.It Em Hang
+\&Hanged labels are a matter of taste.
+\&.It Em Ohang
+\&Overhanging labels are nice when space is constrained.
+\&.It Em Inset
+\&Inset labels are useful for controlling blocks of
+\&paragraphs and are valuable for converting
+\&.Nm \-mdoc
+\&manuals to other formats.
+\&.El
+.Ed
+.Pp
+Here is a hanged list with just one item:
+.Bl -hang -offset indent
+.It Em Hanged
+labels appear similar to tagged lists when the
+label is smaller than the label width.
+.It Em Longer hanged list labels
+blend in to the paragraph unlike
+tagged paragraph labels.
+.El
+.Pp
+And the unformatted text which created it:
+.Bd -literal -offset indent
+\&.Bl -hang -offset indent
+\&.It Em Hanged
+\&labels appear similar to tagged lists when the
+\&label is smaller than the label width.
+\&.It Em Longer hanged list labels
+\&blend in to the paragraph unlike
+\&tagged paragraph labels.
+\&.El
+.Ed
+.Pp
+The tagged list which follows uses a width specifier to control
+the width of the tag.
+.Pp
+.Bl -tag -width "PAGEIN" -compact -offset indent
+.It SL
+sleep time of the process (seconds blocked)
+.It PAGEIN
+number of disk
+.Tn I/O Ns 's
+resulting from references
+by the process to pages not loaded in core.
+.It UID
+numerical user-id of process owner
+.It PPID
+numerical id of parent of process process priority
+(non-positive when in non-interruptible wait)
+.El
+.Pp
+The raw text:
+.Bd -literal -offset indent
+\&.Bl -tag -width "PAGEIN" -compact -offset indent
+\&.It SL
+\&sleep time of the process (seconds blocked)
+\&.It PAGEIN
+\&number of disk
+\&.Tn I/O Ns 's
+\&resulting from references
+\&by the process to pages not loaded in core.
+\&.It UID
+\&numerical user-id of process owner
+\&.It PPID
+\&numerical id of parent of process process priority
+\&(non-positive when in non-interruptible wait)
+\&.El
+.Ed
+.Pp
+Acceptable width specifiers:
+.Bl -tag -width Ar -offset indent
+.It Fl width Ar "\&Fl"
+sets the width to the default width for a flag.
+All callable
+macros have a default width value.
+The
+.Ql \&.Fl ,
+value is presently
+set to ten constant width characters or about five sixth of
+an inch.
+.It Fl width Ar "24n"
+sets the width to 24 constant width characters or about two
+inches.
+The
+.Ql n
+is absolutely necessary for the scaling to work correctly.
+.It Fl width Ar "ENAMETOOLONG"
+sets width to the constant width length of the
+string given.
+.It Fl width Ar "\\*qint mkfifo\\*q"
+again, the width is set to the constant width of the string
+given.
+.El
+.Pp
+If a width is not specified for the tag list type, the first
+time
+.Ql \&.It
+is invoked, an attempt is made to determine an appropriate
+width.
+If the first argument to
+.Ql ".It"
+is a callable macro, the default width for that macro will be used
+as if the macro name had been supplied as the width.
+However,
+if another item in the list is given with a different callable
+macro name, a new and nested list is assumed. This effectively
+means that
+.Fl width
+is required for the tag list type.
+.Pp
+.It Fl column
+This list type generates multiple columns.
+The number of columns and the width of each column is determined by
+the arguments to the
+.Fl column
+list.
+Each
+.Ql ".It"
+argument is parsed to make a row, each column within the
+row is a separate argument separated by a tab or the
+.Ql ".Ta"
+macro.
+.El
+The table:
+.Bl -column "String" "Nroff" "Troff" -offset indent
+.It Sy "String" Ta Sy "Nroff" Ta Sy "Troff"
+.It Li "<=" Ta \&<\&= Ta \*(<=
+.It Li ">=" Ta \&>\&= Ta \*(>=
+.El
+.Pp
+was produced by:
+.Bd -literal -offset indent
+\&.Bl -column "String" "Nroff" "Troff" -offset indent
+\&.It Sy "String" Ta Sy "Nroff" Ta Sy "Troff"
+\&.It Li "<=" Ta \&<\&= Ta \*(<=
+\&.It Li ">=" Ta \&>\&= Ta \*(>=
+\&.El
+.Ed
+.Sh PREDEFINED STRINGS
+The following strings are predefined as may be used by
+preceding with the troff string interpreting sequence
+.Ql \&\e*(xx
+where
+.Em xx
+is the name of the defined string or as
+.Ql \&\e*x
+where
+.Em x
+is the name of the string.
+The interpreting sequence may be used any where in the text.
+.Pp
+.Bl -column "String " "Nroff " "Troff " -offset indent
+.It Sy "String Nroff Troff"
+.It Li "<=" Ta \&<\&= Ta \*(<=
+.It Li ">=" Ta \&>\&= Ta \*(>=
+.It Li "Rq" Ta "''" Ta \*(Rq
+.It Li "Lq" Ta "``" Ta \*(Lq
+.It Li "ua" Ta ^ Ta \*(ua
+.It Li "aa" Ta ' Ta \*(aa
+.It Li "ga" Ta \` Ta \*(ga
+.\" .It Li "sL" Ta ` Ta \*(sL
+.\" .It Li "sR" Ta ' Ta \*(sR
+.It Li "q" Ta \&" Ta \*q
+.It Li "Pi" Ta pi Ta \*(Pi
+.It Li "Ne" Ta != Ta \*(Ne
+.It Li "Le" Ta <= Ta \*(Le
+.It Li "Ge" Ta >= Ta \*(Ge
+.It Li "Lt" Ta < Ta \*(Gt
+.It Li "Gt" Ta > Ta \*(Lt
+.It Li "Pm" Ta +- Ta \*(Pm
+.It Li "If" Ta infinity Ta \*(If
+.It Li "Na" Ta \fINaN\fP Ta \*(Na
+.It Li "Ba" Ta \fR\&|\fP Ta \*(Ba
+.El
+.Pp
+.Sy Note :
+The string named
+.Ql q
+should be written as
+.Ql \e*q
+since it is only one char.
+.Sh DIAGNOSTICS
+The debugging facilities for
+.Nm \-mdoc
+are limited, but can help detect subtle errors such
+as the collision of an argument name with an internal
+register or macro name.
+(A what?)
+A register is an arithmetic storage class for
+.Xr troff
+with a one or two character name.
+All registers internal to
+.Nm \-mdoc
+for
+.Xr troff
+and
+.Xr ditroff
+are two characters and
+of the form <upper_case><lower_case> such as
+.Ql \&Ar ,
+<lower_case><upper_case> as
+.Ql \&aR
+or
+<upper or lower letter><digit> as
+.Ql \&C\&1 .
+And adding to the muddle,
+.Xr troff
+has its own internal registers all of which are either
+two lower case characters or a dot plus a letter or meta-character
+character.
+In one of the introduction examples, it was shown how to
+prevent the interpretation of a macro name with the escape sequence
+.Ql \e& .
+This is sufficient for the internal register names also.
+.Pp
+.\" Every callable macro name has a corresponding register
+.\" of the same name (<upper_case><lower_case>).
+.\" There are also specific registers which have
+.\" been used for stacks and arrays and are listed in the
+.\" .Sx Appendix .
+.\" .Bd -ragged -offset 4n
+.\" [A-Z][a-z] registers corresponding to macro names (example ``Ar'')
+.\" [a-z][A-Z] registers corresponding to macro names (example ``aR'')
+.\" C[0-9] argument types (example C1)
+.\" O[0-9] offset stack (displays)
+.\" h[0-9] horizontal spacing stack (lists)
+.\" o[0-9] offset (stack) (lists)
+.\" t[0-9] tag stack (lists)
+.\" v[0-9] vertical spacing stack (lists)
+.\" w[0-9] width tag/label stack
+.\" .Ed
+.\" .Pp
+If a non-escaped register name is given in the argument list of a request
+unpredictable behavior will occur.
+In general, any time huge portions
+of text do not appear where expected in the output, or small strings
+such as list tags disappear, chances are there is a misunderstanding
+about an argument type in the argument list.
+Your mother never intended for you to remember this evil stuff - so here
+is a way to find out whether or not your arguments are valid: The
+.Ql \&.Db
+(debug)
+macro displays the interpretation of the argument list for most
+macros.
+Macros such as the
+.Ql \&.Pp
+(paragraph)
+macro do not contain debugging information.
+All of the callable macros do,
+and it is strongly advised whenever in doubt,
+turn on the
+.Ql \&.Db
+macro.
+.Pp
+.Dl Usage: \&.Db [on | off]
+.Pp
+An example of a portion of text with
+the debug macro placed above and below an
+artificially created problem (a flag argument
+.Ql \&aC
+which should be
+.Ql \e&aC
+in order to work):
+.Bd -literal -offset indent
+\&.Db on
+\&.Op Fl aC Ar file )
+\&.Db off
+.Ed
+.Pp
+The resulting output:
+.Bd -literal -offset indent
+DEBUGGING ON
+DEBUG(argv) MACRO: `.Op' Line #: 2
+ Argc: 1 Argv: `Fl' Length: 2
+ Space: `' Class: Executable
+ Argc: 2 Argv: `aC' Length: 2
+ Space: `' Class: Executable
+ Argc: 3 Argv: `Ar' Length: 2
+ Space: `' Class: Executable
+ Argc: 4 Argv: `file' Length: 4
+ Space: ` ' Class: String
+ Argc: 5 Argv: `)' Length: 1
+ Space: ` ' Class: Closing Punctuation or suffix
+ MACRO REQUEST: .Op Fl aC Ar file )
+DEBUGGING OFF
+.Ed
+.Pp
+The first line of information tells the name of the calling
+macro, here
+.Ql \&.Op ,
+and the line number it appears on.
+If one or more files are involved
+(especially if text from another file is included) the line number
+may be bogus.
+If there is only one file, it should be accurate.
+The second line gives the argument count, the argument
+.Pq Ql \&Fl
+and its length.
+If the length of an argument is two characters, the
+argument is tested to see if it is executable (unfortunately, any
+register which contains a non-zero value appears executable).
+The third line gives the space allotted for a class, and the
+class type.
+The problem here is the argument aC should not be
+executable.
+The four types of classes are string, executable, closing
+punctuation and opening punctuation.
+The last line shows the entire
+argument list as it was read.
+In this next example, the offending
+.Ql \&aC
+is escaped:
+.Bd -literal -offset indent
+\&.Db on
+\&.Em An escaped \e&aC
+\&.Db off
+.Ed
+.Bd -literal -offset indent
+DEBUGGING ON
+DEBUG(fargv) MACRO: `.Em' Line #: 2
+ Argc: 1 Argv: `An' Length: 2
+ Space: ` ' Class: String
+ Argc: 2 Argv: `escaped' Length: 7
+ Space: ` ' Class: String
+ Argc: 3 Argv: `aC' Length: 2
+ Space: ` ' Class: String
+ MACRO REQUEST: .Em An escaped &aC
+DEBUGGING OFF
+.Ed
+.Pp
+The argument
+.Ql \e&aC
+shows up with the same length of 2 as the
+.Ql \e&
+sequence produces a zero width, but a register
+named
+.Ql \e&aC
+was not found and the type classified as string.
+.Pp
+Other diagnostics consist of usage statements and are self explanatory.
+.Sh GROFF, TROFF AND NROFF
+The
+.Nm \-mdoc
+package does not need compatibility mode with
+.Xr groff .
+.Pp
+The package inhibits page breaks, and the headers and footers
+which normally occur at those breaks with
+.Xr nroff ,
+to make the manual more efficient for viewing on-line.
+At the moment,
+.Xr groff
+with
+.Fl T Ns Ar ascii
+does eject the imaginary remainder of the page at end of file.
+The inhibiting of the page breaks makes
+.Xr nroff Ns 'd
+files unsuitable for hardcopy.
+There is a register named
+.Ql \&cR
+which can be set to zero in the site dependent style file
+.Pa /usr/src/share/tmac/doc-nroff
+to restore the old style behavior.
+.Sh FILES
+.Bl -tag -width /usr/share/misc/mdoc.template -compact
+.It Pa /usr/share/tmac/tmac.doc
+manual macro package
+.It Pa /usr/share/misc/mdoc.template
+template for writing a man page
+.El
+.Sh SEE ALSO
+.Xr mdoc 7 ,
+.Xr man 1 ,
+.Xr troff 1
+.Sh BUGS
+Undesirable hyphenation on the dash of a flag
+argument is not yet resolved, and causes
+occasional mishaps in the
+.Sx DESCRIPTION
+section.
+(line break on the hyphen).
+.Pp
+Predefined strings are not declared in documentation.
+.Pp
+Section 3f has not been added to the header routines.
+.Pp
+.Ql \&.Nm
+font should be changed in
+.Sx NAME
+section.
+.Pp
+.Ql \&.Fn
+needs to have a check to prevent splitting up
+if the line length is too short.
+Occasionally it
+separates the last parenthesis, and sometimes
+looks ridiculous if a line is in fill mode.
+.Pp
+The method used to prevent header and footer page
+breaks (other than the initial header and footer) when using
+nroff occasionally places an unsightly partially filled line (blank)
+at the would be bottom of the page.
+.Pp
+If the outer-most list definition doesn't have a
+.Fl width
+argument, the
+.Ql ".It"
+elements of inner lists may not work (producing a list where
+each successive element
+.Sq walks
+to the right).
+.Pp
+The list and display macros to not do any keeps
+and certainly should be able to.
+.\" Note what happens if the parameter list overlaps a newline
+.\" boundary.
+.\" to make sure a line boundary is crossed:
+.\" .Bd -literal
+.\" \&.Fn struct\e\ dictionarytable\e\ *dictionarylookup struct\e\ dictionarytable\e\ *tab[]
+.\" .Ed
+.\" .Pp
+.\" produces, nudge nudge,
+.\" .Fn struct\ dictionarytable\ *dictionarylookup char\ *h struct\ dictionarytable\ *tab[] ,
+.\" .Fn struct\ dictionarytable\ *dictionarylookup char\ *h struct\ dictionarytable\ *tab[] ,
+.\" nudge
+.\" .Fn struct\ dictionarytable\ *dictionarylookup char\ *h struct\ dictionarytable\ *tab[] .
+.\" .Pp
+.\" If double quotes are used, for example:
+.\" .Bd -literal
+.\" \&.Fn \*qstruct dictionarytable *dictionarylookup\*q \*qchar *h\*q \*qstruct dictionarytable *tab[]\*q
+.\" .Ed
+.\" .Pp
+.\" produces, nudge nudge,
+.\" .Fn "struct dictionarytable *dictionarylookup" "char *h" "struct dictionarytable *tab[]" ,
+.\" nudge
+.\" .Fn "struct dictionarytable *dictionarylookup" "char *h" "struct dictionarytable *tab[]" ,
+.\" nudge
+.\" .Fn "struct dictionarytable *dictionarylookup" "char *h" "struct dictionarytable *tab[]" .
+.\" .Pp
+.\" Not a pretty sight...
+.\" In a paragraph, a long parameter containing unpaddable spaces as
+.\" in the former example will cause
+.\" .Xr troff
+.\" to break the line and spread
+.\" the remaining words out.
+.\" The latter example will adjust nicely to
+.\" justified margins, but may break in between an argument and its
+.\" declaration.
+.\" In
+.\" .Xr nroff
+.\" the right margin adjustment is normally ragged and the problem is
+.\" not as severe.
diff --git a/gnu/usr.bin/groff/tmac/groff_me.man b/gnu/usr.bin/groff/tmac/groff_me.man
new file mode 100644
index 00000000000..49196212391
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/groff_me.man
@@ -0,0 +1,274 @@
+.\" Copyright (c) 1980 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley. The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\" @(#)me.7 6.4 (Berkeley) 4/13/90
+.\"
+.\" Modified for groff by jjc@jclark.com
+.hc %
+.TH GROFF_ME @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.UC 3
+.SH NAME
+groff_me \- troff macros for formatting papers
+.SH SYNOPSIS
+.B "groff \-me"
+[ options ]
+file ...
+.br
+.B "troff \-me"
+[ options ]
+file ...
+.SH DESCRIPTION
+This manual page describes the GNU version of the \-me macros,
+which is part of the groff document formatting system.
+This version can be used with both GNU troff and Unix troff.
+This package of
+.I troff
+macro definitions provides a canned formatting
+facility for tech%nical papers in various formats.
+.PP
+The macro requests are defined below.
+Many
+.I troff
+requests are unsafe in conjunction with
+this package, however, these requests may be used with
+impunity after the first .pp:
+.nf
+.IP
+.ta \w'.sz +n 'u
+\&.bp begin new page
+\&.br break output line here
+\&.sp n insert n spacing lines
+\&.ls n (line spacing) n=1 single, n=2 double space
+\&.na no alignment of right margin
+\&.ce n center next n lines
+\&.ul n underline next n lines
+.fi
+.PP
+Output of the
+.I pic,
+.I eqn,
+.I refer,
+and
+.I tbl
+preprocessors
+is acceptable as input.
+.SH FILES
+@MACRODIR@/tmac.e
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@)
+.br
+\-me Reference Manual, Eric P. Allman
+.br
+Writing Papers with Groff Using \-me
+.tr &.
+.SH REQUESTS
+This list is incomplete;
+see
+.I "The \-me Reference Manual"
+for interesting details.
+.PP
+.ta \w'.eh \'x\'y\'z\' 'u +\w'Initial 'u +\w'Cause 'u
+.br
+.di x
+ \ka
+.br
+.di
+.in \nau
+.ti 0
+Request Initial Cause Explanation
+.ti 0
+ Value Break
+.br
+.in \nau
+.ti 0
+\&.(c - yes Begin centered block
+.ti 0
+\&.(d - no Begin delayed text
+.ti 0
+\&.(f - no Begin footnote
+.ti 0
+\&.(l - yes Begin list
+.ti 0
+\&.(q - yes Begin major quote
+.ti 0
+\&.(x \fIx\fR - no Begin indexed item in index
+.I x
+.ti 0
+\&.(z - no Begin floating keep
+.ti 0
+\&.)c - yes End centered block
+.ti 0
+\&.)d - yes End delayed text
+.ti 0
+\&.)f - yes End footnote
+.ti 0
+\&.)l - yes End list
+.ti 0
+\&.)q - yes End major quote
+.ti 0
+\&.)x - yes End index item
+.ti 0
+\&.)z - yes End floating keep
+.ti 0
+\&.++ \fIm H\fR - no Define paper section.
+.I m
+defines the part of the paper, and can be
+.B C
+(chapter),
+.B A
+(appendix),
+.B P
+(preliminary, e.g., abstract, table of contents, etc.),
+.B B
+(bibliography),
+.B RC
+(chapters renumbered from page one each chapter),
+or
+.B RA
+(appendix renumbered from page one).
+.ti 0
+\&.+c \fIT\fR - yes Begin chapter (or appendix, etc., as
+set by .++).
+.I T
+is the chapter title.
+.ti 0
+\&.1c 1 yes One column format on a new page.
+.ti 0
+\&.2c 1 yes Two column format.
+.ti 0
+\&.EN - yes Space after equation
+produced by
+.I eqn
+or
+.IR neqn .
+.ti 0
+\&.EQ \fIx y\fR - yes Precede equation; break out and
+add space.
+Equation number is
+.IR y .
+The optional argument \fIx\fR
+may be
+.I I
+to indent equation (default),
+.I L
+to left-adjust the equation, or
+.I C
+to center the equation.
+.ti 0
+\&.GE - yes End \fIgremlin\fP picture.
+.ti 0
+\&.GS - yes Begin \fIgremlin\fP picture.
+.ti 0
+\&.PE - yes End \fIpic\fP picture.
+.ti 0
+\&.PS - yes Begin \fIpic\fP picture.
+.ti 0
+\&.TE - yes End table.
+.ti 0
+\&.TH - yes End heading section of table.
+.ti 0
+\&.TS \fIx\fR - yes Begin table; if \fIx\fR is
+.I H
+table has repeated heading.
+.ti 0
+\&.b \fIx\fR no no Print
+.I x
+in boldface; if no argument switch to boldface.
+.ti 0
+\&.ba \fI+n\fR 0 yes Augments the base indent by
+.I n.
+This indent is used to set the indent on regular text
+(like paragraphs).
+.ti 0
+\&.bc no yes Begin new column
+.ti 0
+\&.bi \fIx\fR no no Print
+.I x
+in bold italics (nofill only)
+.ti 0
+\&.bu - yes Begin bulleted paragraph
+.ti 0
+\&.bx \fIx\fR no no Print \fIx\fR in a box (nofill only).
+.ti 0
+\&.ef \fI\'x\'y\'z\'\fR \'\'\'\' no Set even footer to x y z
+.ti 0
+\&.eh \fI\'x\'y\'z\'\fR \'\'\'\' no Set even header to x y z
+.ti 0
+\&.fo \fI\'x\'y\'z\'\fR \'\'\'\' no Set footer to x y z
+.ti 0
+\&.hx - no Suppress headers and footers on next page.
+.ti 0
+\&.he \fI\'x\'y\'z\'\fR \'\'\'\' no Set header to x y z
+.ti 0
+\&.hl - yes Draw a horizontal line
+.ti 0
+\&.i \fIx\fR no no Italicize
+.I x;
+if
+.I x
+missing, italic text follows.
+.ti 0
+\&.ip \fIx y\fR no yes Start indented paragraph,
+with hanging tag
+.IR x .
+Indentation is
+.I y
+ens (default 5).
+.ti 0
+\&.lp yes yes Start left-blocked paragraph.
+.ti 0
+\&.np 1 yes Start numbered paragraph.
+.ti 0
+\&.of \fI\'x\'y\'z\'\fR \'\'\'\' no Set odd footer to x y z
+.ti 0
+\&.oh \fI\'x\'y\'z\'\fR \'\'\'\' no Set odd header to x y z
+.ti 0
+\&.pd - yes Print delayed text.
+.ti 0
+\&.pp no yes Begin paragraph.
+First line indented.
+.ti 0
+\&.r yes no Roman text follows.
+.ti 0
+\&.re - no Reset tabs to default values.
+.ti 0
+\&.sh \fIn x\fR - yes Section head follows,
+font automatically bold.
+.I n
+is level of section,
+.I x
+is title of section.
+.ti 0
+\&.sk no no Leave the next page blank.
+Only one page is remembered ahead.
+.ti 0
+\&.sm \fIx\fR - no Set
+.I x
+in a smaller pointsize.
+.ti 0
+\&.sz \fI+n\fR 10p no Augment the point size by
+.I n
+points.
+.ti 0
+\&.tp no yes Begin title page.
+.ti 0
+\&.u \fIx\fR - no Underline argument (even in \fItroff\fR).
+(Nofill only).
+.ti 0
+\&.uh - yes Like .sh but unnumbered.
+.ti 0
+\&.xp \fIx\fR - no Print index
+.I x.
diff --git a/gnu/usr.bin/groff/tmac/groff_msafer.man b/gnu/usr.bin/groff/tmac/groff_msafer.man
new file mode 100644
index 00000000000..0e0de775b63
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/groff_msafer.man
@@ -0,0 +1,59 @@
+.ig \"-*- nroff -*-
+Copyright (C) 1989-1999 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH GROFF_MSAFER @MAN7EXT@ "@MDATE@" "Groff Version @VERSION@"
+.SH NAME
+groff_msafer \- groff -msafer macros
+.SH SYNOPSIS
+.B groff
+.B \-msafer
+[
+.IR options .\|.\|.
+]
+[
+.IR files .\|.\|.
+]
+.SH DESCRIPTION
+The -msafer macros remove the
+.BR open ,
+.BR opena ,
+.BR pso ,
+.BR sy ,
+and
+.B pi
+requests.
+These macros should be used when processing input from
+an untrustworthy source.
+For maximum safety,
+they should be the first -m option on the command-line.
+Normally they are invoked using the
+.B \-S
+option of groff, which will also pass
+.B @g@pic
+the
+.B \-S
+flag.
+This is now the default; to get the old behaviour, use the
+.B \-U
+flag.
+.SH FILES
+.B @MACRODIR@/tmac.safer
+.SH "SEE ALSO"
+.BR groff (@MAN1EXT@),
+.BR @g@troff (@MAN1EXT@),
+.BR @g@pic (@MAN1EXT@)
diff --git a/gnu/usr.bin/groff/tmac/tmac.arkup b/gnu/usr.bin/groff/tmac/tmac.arkup
new file mode 100644
index 00000000000..b8c94df257a
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.arkup
@@ -0,0 +1,178 @@
+.\"
+.\" a simple set of macros to provide HTML documents with basic www functionality
+.\"
+.\" please can someone with more skill at creating macros improve on this
+.\" many thanks - Gaius
+.\"
+.\" suggestion: maybe when run with non -Thtml all the urls should appear as
+.\" references.
+.\"
+.\" some simple html additions to any macro set
+.\"
+.de HTML
+.if '\*(.T'html' \X^html:\\$*^
+..
+.de HTMLINDEX
+.if '\*(.T'html' \X^index:\\$*^
+..
+.\"
+.\" BODYCOLOR - $1 is foreground color
+.\" $2 is background color
+.\" $3 is the color of an active hypertext link
+.\" $4 is the color of a hypertext link not yet visited
+.\" $5 is the color of a visited hypertext link
+.\"
+.de BODYCOLOR
+. HTML <body text=\\$1 bgcolor=\\$2 link=\\$3 alink=\\$4 vlink=\\$5>
+..
+.\"
+.\" BACKGROUND - $1 is the background image file
+.\"
+.de BACKGROUND
+. HTML <body background=\\$1>
+..
+.\"
+.\" URL - $1 is the classical underlined blue text
+.\" $2 is the url
+.\"
+.de URL
+. ie '\*(.T'html' \{\
+. HTML <a href="\\$2">\\$1</a>
+. \}
+. el \{\
+\\$1 (<url: \\$2>)
+. \}
+..
+.\"
+.\" LINK - $1 is the classical underlined blue text
+.\" $2 is the URL *with* the textual reference within a document
+.\"
+.\" example: .LINK "a nice heading" "#heading123"
+.\"
+.\" provides a link from "a nice heading" to the
+.\" textual name reference "heading123"
+.\"
+.\" .LINK "The GNU FSF" "" "www.gnu.org"
+.\"
+.\" deprecated - use the URL macro instead
+.\"
+.\"
+.de LINK
+. ie !'\\$3'' \{\
+. @error the LINK macro has changed, use the URL (or FTP if appropriate) macro here
+. @error you are advised to replace with URL or FTP macro "\\$1" "\\$3#\\$2"
+. URL "\\$1" "\\$3#\\$2"
+. \}
+. el \{\
+. ie '\*(.T'html' \{\
+. HTML <a href=\\$2>\\$1</a>
+. \}
+. el \{\
+. URL "\\$1" "\\$2"
+. \}
+. \}
+..
+.\"
+.\" FTP - $1 is the classical underlined blue text
+.\" $2 is the ftp url
+.de FTP
+. ie '\*(.T'html' \{\
+. HTML <a href=\\$2>\\$1</a>
+. \}
+. el \{\
+$1 (<ftp:\\$2>)
+. \}
+..
+.\"
+.\" MAILTO - generate html email reference
+.\" $1 is the email address
+.\" $2 is the optional name
+.\"
+.\" example .MAILTO fred@foo.bar "Fredrick Bloggs"
+.\"
+.de MAILTO
+.\"
+.\" force reset after a potential heading by performing some motion..
+.\" how do we do this --fixme--
+.\" \h'\w' ''\h'-\w' '' doesn't work..
+. ie '\*(.T'html' \{\
+. ie '\\$2'' \{\
+. HTML "<a href=mailto:\\$1>\\$1</a>"
+. \}
+. el \{\
+. HTML "<a href=mailto:\\$1>\\$2</a>"
+. \}
+. \}
+. el \{\
+\s-2\fB<email:\\$1>\fP\s+2
+. \}
+..
+.\"
+.\"
+.\" TAG - generate an html name $1
+.\"
+.de TAG
+.HTML <a name="\\$1"></a>
+..
+.\"
+.\" IMAGE - reference an image
+.\" $1 is the image file
+.\" $2 is the x width (default if absent 400 pixels)
+.\" $3 is the y width (default if absent is the x value)
+.\"
+.de IMAGE
+. ie '\*(.T'html' \{\
+. nr HTMLWIDTH 400
+. if '\\$2'' \{\
+. nr HTMLWIDTH \\$2
+. \}
+. nr HTMLHEIGHT \\n[HTMLWIDTH]
+. if '\\$3'' \{\
+. nr HTMLHEIGHT \\$3
+. \}
+. HTML <img src="\\$1" width=\\n[HTMLWIDTH height=\\n[HTMLHEIGHT]>
+. \}
+. el \{\
+. B1
+\fB\s-2<img src=\\$1>\fP\s+2
+. B2
+. \}
+..
+.\"
+.\" CDFTP - if we are processing this on machine \\$1 then we create a
+.\" FTP reference using \\$2 --> \\$3
+.\"
+.\" otherwise we create a URL from \\$2 --> \\$4
+.\"
+.\" example:
+.\"
+.\" .CDFTP "foobar" "somegnusoftware.tar.gz" \
+.\" "ftp://ftp.gnu.org/gnu/somegnusoftware.tar.gz" \
+.\" "../../../TARGZ/somegnusoftware.tar.gz"
+.\"
+.\" meaning if we are on machine foobar then generate an ftp url
+.\" to the GNU anonymous ftp server otherwise generate a file url
+.\" to a local copy (cdrom maybe)
+.\"
+.\" Useful when one machine is designated as a cdrom burner and another
+.\" designated as an appache server.
+.\" The same source for web pages can be burnt onto a CD and also
+.\" served across the network. It doesn't solve the problem of one
+.\" machine doing both though :-(
+.\"
+.\"
+.de CDFTP
+. sy /bin/rm -f /tmp/tmac.n
+. sy /bin/echo ".ds HOSTNAME `hostname --short`" > /tmp/tmac.n
+. so /tmp/tmac.n
+. sy /bin/rm -f /tmp/tmac.n
+. ie '\\*[HOSTNAME]'\\$1' \{\
+. FTP "\\$2" "\\$3"
+. \}
+. el \{\
+. URL "\\$2" "\\$4"
+. \}
+..
+.\" it doesn't make sense to use hyphenation with html, so we turn it off.
+.hy 0
+.nr HY 0
diff --git a/gnu/usr.bin/groff/tmac/tmac.html b/gnu/usr.bin/groff/tmac/tmac.html
new file mode 100644
index 00000000000..cd8a518a7f2
--- /dev/null
+++ b/gnu/usr.bin/groff/tmac/tmac.html
@@ -0,0 +1,58 @@
+.nr _C \n(.C
+.cp 0
+.ftr CW CR
+.ftr C CR
+.ftr CO CI
+.ftr CX CBI
+.ftr H HR
+.ftr HO HI
+.ftr HX HBI
+.ftr NX NBI
+.char \(ru \D'l .5m 0'
+.char \(ul \v'.25m'\D'l .5m 0'\v'-.25m'
+.char \(br \v'.25m'\D'l 0 -1m'\v'.75m'
+.char \(rn \v'-.75m'\D'l .5m 0'\v'.75m'
+.char ~ \v'-.55m'\\s[\\n(.s/2u]\v'.2m'\(ti\v'-.2m'\s0\v'.55m'
+.char ^ \v'-.55m'\\s[\\n(.s/2u]\v'.3m'\(ha\v'-.3m'\s0\v'.55m'
+.if !c\(va .char \(va \o'\(ua\(da'
+.if !c\(em .char \(em --
+.if !c\(en .char \(en \-
+.if !c\(fi .char \(fi fi
+.if !c\(fl .char \(fl fl
+.if !c\(ff .char \(ff ff
+.if !c\(Fi .char \(Fi ffi
+.if !c\(Fl .char \(Fl ffl
+.if !c\(ci .char \(ci \v'-.25m'\h'.05m'\D'c .5m'\h'.05m'\v'.25m'
+.if !c\(sq .char \(sq \h'.05m'\D'l .5m 0'\D'l 0 -.5m'\D'l -.5m 0'\D'l 0 .5m'\h'.55m'
+.if !c\(ga .char \(ga \Z'\v'-.7m'\D'l .22m .18m''\h'.33m'
+.if !c\(dg .char \(dg \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0''\h'.5m'
+.if !c\(dd .char \(dd \Z'\h'.25m'\v'.15m'\D'l 0 -.8m'\v'.2m'\h'-.195m'\
+\D'l .39m 0'\v'.4m'\D'l -.39m 0''\h'.5m'
+.if !c\(lq .char \(lq ``
+.if !c\(rq .char \(rq ''
+.if !c\(Bq .char \(bq ,,
+.if !c\(OE .char \(OE O\h'-.25m'E
+.if !c\(oe .char \(oe o\h'-.14m'e
+.if !c\(ah .char \(ah \v'-.55m'\s[\En[.s]/2u]v\s0\v'.55m'
+.if !c\(ao .char \(ao \v'-.55m'\s[\En[.s]*6u/10u]\D'c .25m'\s0\v'.55m'
+.if !c\(ho .char \(ho \s[\En[.s]/2u]\v'.4m'c\v'-.4m'\s0
+.if !c\(lh .char \(lh <-
+.if !c\(rh .char \(rh ->
+.if !c\(bq .tr \(bq,
+.if !c\(aq .tr \(aq'
+.if '\*(.T'html' .char \[radicalex] \h'-\w'\(sr'u'\[radicalex]\h'\w'\(sr'u'
+.if !\n(_C .mso tmac.pspic
+.cp \n(_C
+.\" now turn off all headers and footers for ms, me and mm macro sets
+.if d EF .EF '''
+.if d EH .EH '''
+.if d OF .OF '''
+.if d OH .OH '''
+.if d ef .ef '''
+.if d of .of '''
+.if d oh .oh '''
+.if d eh .eh '''
+.\" it doesn't make sense to use hyphenation with html, so we turn it off.
+.hy 0
+.nr HY 0
diff --git a/gnu/usr.bin/groff/xditview/GXditview-ad.h b/gnu/usr.bin/groff/xditview/GXditview-ad.h
new file mode 100644
index 00000000000..d9be3da256b
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/ad2c b/gnu/usr.bin/groff/xditview/ad2c
new file mode 100644
index 00000000000..651ab8c40c5
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray1.bm b/gnu/usr.bin/groff/xditview/gray1.bm
new file mode 100644
index 00000000000..c40a95e6eab
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray2.bm b/gnu/usr.bin/groff/xditview/gray2.bm
new file mode 100644
index 00000000000..e87a1bcc073
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray3.bm b/gnu/usr.bin/groff/xditview/gray3.bm
new file mode 100644
index 00000000000..d9313ebd5e8
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray4.bm b/gnu/usr.bin/groff/xditview/gray4.bm
new file mode 100644
index 00000000000..dad142a9b0f
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray5.bm b/gnu/usr.bin/groff/xditview/gray5.bm
new file mode 100644
index 00000000000..5f576184172
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray6.bm b/gnu/usr.bin/groff/xditview/gray6.bm
new file mode 100644
index 00000000000..b76701db16d
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray7.bm b/gnu/usr.bin/groff/xditview/gray7.bm
new file mode 100644
index 00000000000..ef47bc692e9
--- /dev/null
+++ b/gnu/usr.bin/groff/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/gnu/usr.bin/groff/xditview/gray8.bm b/gnu/usr.bin/groff/xditview/gray8.bm
new file mode 100644
index 00000000000..12de7cb6f57
--- /dev/null
+++ b/gnu/usr.bin/groff/xditview/gray8.bm
@@ -0,0 +1,4 @@
+#define gray8_width 3
+#define gray8_height 3
+static char gray8_bits[] = {
+ 0x05, 0x07, 0x07};