tmac.gnu: .kern and .dei requests
[neatroff_make.git] / demo / neatroff.ms
blob6dd9aa37812d35fb13be0df1a6069bc04b529e74
1 .\" PSTITLE: Neatroff Introduction
2 .so neat__.ms
3 .ds en.cl "#237
4 .post.info Title "Neatroff Introduction"
5 .post.info Author "Ali Gholami Rudi"
6 .de MH
7 .       sp
8 .       LP
9 .       ne 2
10 \m[#237]\fI\\$1\fP\m[]
11 .       IP
13 .de NR
14 .       sp
15 .       LP
16 .       ne 2
17 .       ta 4.5i 6iR
18 .       nf
19 .       lg 0
20 \f(CB\m[#237]\\$1\m0\fP \s-3\m[#237]\fB\\$2\fP  \fB\\$4\m0\fP
21 .       lg 1
22 .       IP
24 .HD
25 .TL
26 \s+8Neatroff\m0\s-8
27 .AU
28 \fIAli Gholami Rudi\fP
29 .ce
30 \s-3\fIUpdated in April 2018\s+3\fP\&
31 .sp 3
32 Neatroff is a new implementation of Troff typesetting system in C
33 programming language, which tries to address, as neatly as possible,
34 some of the shortcomings of the original Troff based on the ideas and
35 features available in Plan 9 Troff, Heirloom Troff, and Groff.
36 The latest versions of Neatroff, its PostScript and PDF post-processor,
37 Neatpost, and its eqn preprocessor, Neateqn,
38 are available at their home page (\*[post.url http://litcave.rudi.ir/ link]).
39 This document enumerates Neatroff's features, its new requests, and
40 its differences compared to other Troff implementations.  On the other
41 hand, the document \(lqGetting Started with Neatroff\(rq
42 (\*[post.url http://litcave.rudi.ir/neatstart.pdf link])
43 explains how to set up and use Neatroff.
45 .bp
46 .SH "Noteworthy Features"
47 The following list describes the main extensions of Neatroff compared
48 to the original Troff (many of these extensions are available in
49 Groff and Heirloom Troff as well).  The number register \&.neat,
50 which is always one in Neatroff, can be used to distinguish Neatroff
51 from other Troff implementations.
53 .MH "UTF-8 encoding
54 In Neatroff, input files and characters, glyph names, ligatures,
55 hyphenation patterns and dictionary, as well as quoted escape sequence
56 delimiters and arguments of commands like .tr, .hc, .tc, .lc, .mc, and
57 \&.fc are in UTF-8 encoding.
59 .MH "Long macro, register, and environment names
60 When not in compatibility mode (activated with -C command line option or the .cp
61 request, as in Groff), Neatroff supports long macro, register, and environment
62 names.  It also supports Groff-style escape sequences with long arguments
63 (for \\[], \\*[], \\$[], \\f[], \\g[], \\k[], \\m[], \\n[], and \\s[])
64 and interpolating string registers with arguments (\\*[xyz arg1 arg2 ...]).
65 Note that like Groff, Neatroff supports named environments and
66 is not limited to original Troff's three fixed environments.
68 .MH "Advanced font features, ligature, and pairwise kerning
69 Neatroff and Neatmkfn (which generates Neatroff's font descriptions)
70 support many of the advanced font features available in OpenType
71 fonts.  In a font, a set of substitution and positioning rules may be
72 specified, which are grouped into several features and scripts.  In
73 Neatroff, features can be enabled with \&.ff and the active script and
74 language can be selected with \&.ffsc.
75 Neatmkfn supports PostScript Type 1 fonts, TrueType fonts (TTF), and
76 OpenType fonts (OTF).  For the latter, however, it cannot extract
77 glyph bounding boxes, which is used by the Neateqn preprocessor.
78 Therefore, if an OpenType font is supposed to be used in Neateqn
79 blocks, it should be converted to TrueType first (the script that
80 comes with Neatmkfn does this automatically).
82 .MH "Whole paragraph text formatting
83 Neatroff supports filling whole paragraphs at once, to achieve
84 more uniform word spacing.  Like Heirloom Troff, the \&.ad request
85 accepts arguments p or pb, pl, and pr, which are equivalent to b, l,
86 and r, except that the filling is done for whole paragraphs, i.e.,
87 words are collected until a line break is issued.
88 This inevitably changes the behaviour of some requests and traps: several
89 lines may be collected and ready to be output while executing them.
90 For the end macro, Troff invokes the macro specified
91 with \&.em request without flushing the last incomplete line.
92 Neatroff follows the same behaviour even when formatting whole
93 paragraphs and does not write any of the collected lines to the output.
94 Since after the end macro no new page is started, collected lines may
95 be unexpectedly written to the end of the last page of the document.
96 To change that, the end macro can invoke the \&.br request.
97 For requests that cause break, using \(aq as the control character
98 prevents writing any line of the collected paragraph to the output,
99 as expected.
100 The exception to this rule is \(aqbr, which formats the words
101 collected so far and outputs all resulting lines except the final
102 incomplete line (this is useful, for instance, for footnotes, which
103 should be inserted in the same page).
105 .MH "Paragraph formatting algorithm
106 For deciding at what points to break a paragraph into lines, Neatroff
107 assigns a cost to each possible outcome: a cost of 100 is assigned to
108 each stretchable space that has to be stretched 100 percent.  The cost
109 grows quadratically and the cost of stretching a space 200 percent is 400.
110 There are requests that adjust the algorithm Neatroff uses for
111 performing paragraph formatting.
112 The \&.hycost request changes the cost of hyphenating words.  The
113 default value is zero.
114 The \\j escape sequence, as in Heirloom Troff, specifies the extra
115 cost of line break after a word; for instance, in \(lqHello\\j'10000'
116 world\(rq, the words are not split by the line breaking algorithm,
117 unless absolutely necessary (i.e., if other options are more costly).
118 The escape sequence \\\(ti introduces non-breakable stretchable space.
119 Also, to prevent paragraphs with
120 very short last lines, the \&.pmll (paragraph minimum line length)
121 sets the minimum length of a formatted line, specified as a
122 percentage of \\n(.l; \(lq.pmll 15\(rq, for instance, ensures that
123 the length of last line of each paragraph is at least 15% of its other
124 lines; otherwise, a cost proportional to the value specified
125 as its second argument is added.
127 .MH "Controlling word spaces
128 The \&.ssh request sets the amount (in percentage) by which the
129 stretchable spaces in a line may be shrunk while formatting lines.
130 The default value is zero.
131 Also, the second
132 argument of \&.ss request specifies sentence space, as in Groff or
133 Heirloom Troff.
135 .MH "Macros and their arguments
136 In a macro, \\$* is replaced with macro's argument separated
137 by spaces.  \\$@ is like \\$*, but quotes the arguments as well.
138 \\$\(ha is like \\$@, except that it escapes the double quotes
139 in the arguments.
140 The arguments can be shifted with \&.shift request.
141 Neatroff also supports blank line macro (.blm) and
142 leading space macro (.lsm).
144 .MH "Text direction
145 Neatroff supports text direction to render right-to-left languages.
146 \&.<< and \&.>> requests specify text direction and \\< and \\> escape
147 sequences change it temporarily for including words in the reverse
148 direction.  The value of number registers \&.td and \&.cd indicate the
149 current text and temporary directions respectively; zero means
150 left-to-right and one means right-to-left.  Neatroff starts processing
151 text direction, after the first invocation of \&.<< or \&.>>.
153 .MH "Keshideh justification and cursive scripts
154 A new adjustment type (.ad k) allows inserting Keshideh characters
155 before justifying text with hyphenation and spaces.  Neatroff also
156 supports cursive scripts, which require connecting glyphs at their
157 cursive attachment positions, as defined in the fonts.
159 .MH "Font manipulation
160 In Neatroff, the mapping between Troff character names and glyphs in a
161 font can be modified with \&.fmap request: \(lq.fmap F C G\(rq
162 maps Troff character C to the glyph with device-specific name G for
163 font F.  When this glyph does not exist in F, Neatroff assumes that
164 the character C is not present in the font.  When G is missing, the
165 effect of \&.fmap for character C is cancelled.  Neatroff also implements
166 Groff's \&.fspecial and \&.fzoom requests: after \(lq.fspecial FN S1
167 S2 ...\(rq, when the current font is FN, the fonts S1, S2, ... are
168 assumed to be special.  Also, \(lq.fzoom FN zoom\(rq scales font FN by
169 the second argument after dividing it by 1000.
171 .MH "Colour support
172 Neatroff supports colours with .cl request and \\m[] escape sequence.
173 Unlike Groff, colours need not be defined beforehand and can be
174 specified directly.  The argument of \\m can be predefined colour
175 names (e.g. blue), predefined colour numbers (0 for black, 1 for red,
176 2 for green, 3 for yellow, 4 for blue, 5 for magenta, 6 for cyan, and
177 7 for white), #rgb and #rrggbb for specifying colours in hexadecimal
178 RGB format, #g and #gg for specifying grey with the given hexadecimal
179 level, and empty (\\m[]) for the previous colour.  The current colour
180 is available in \&.m number register.
182 .MH "Hyphenation language
183 The \&.hpf request loads hyphenation patterns, exceptions, and
184 character mappings from the addresses specified via its arguments.
185 The specified files should contain nothing but utf-8 patterns,
186 exceptions and mappings respectively (i.e. no TeX code), just like the
187 files whose names end with \&.pat.txt, \&.hyp.txt and \&.chr.txt in
188 CTAN for TeX (\*[post.url ftp://ftp.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/txt/ link]).
189 The \&.hpfa request is like \&.hpf, except that it does not clear the
190 previous hyphenation patterns and exceptions.  The second and third
191 arguments of these requests are optional.  With no arguments, these
192 requests load English hyphenation patterns and exceptions.  Also the
193 \&\(lq.hcode abcd...\(rq request, assigns the hyphenation code of b to
194 a and the hyphenation code of d to c; initially all upper-case ASCII
195 letters are mapped to their lower-case forms.
197 .MH "Filled drawing objects
198 Neatroff supports Groff-style polygons and filled drawing objects (p,
199 C, E and P commands for \\D escape sequence).  In Neatroff, however,
200 there is no specific background colour; objects are filled with the
201 current colour (.m number register).  Furthermore, in Neatroff
202 the edges of polygons can be lines, arcs, or splines; a letter among the
203 arguments of \\D'p ..' specifies the type of the subsequent
204 edges: \(oql\(cq, \(oqa\(cq, and \(oq\(ti\(cq for lines, arcs,
205 and splines respectively.
207 .MH "Conditional escape sequence
208 Neatroff supports a new escape sequence for conditional interpolation:
209 the escape sequence \\?'cond@expr1@expr2@', evaluates cond (exactly as
210 if it is a \&.if condition) and interpolates expr1, if the condition
211 is true, and expr2, otherwise.  The delimiter (@ in this example) can
212 be any character that cannot be part of the condition; for numerical
213 expressions, for instance, it cannot be a digit, an operator sign, or
214 a scale indicator, unless separated from the condition with \\&.  The
215 final delimiter, and even expr2, may be omitted, thus \\?'cond@expr'
216 is valid; Neatroff interpolates expr if cond is true.
218 .MH "Neatpost-specific device commands
219 Neatpost can produce both PostScript and PDF.  The escape sequences
220 \\X'eps img.eps [width [height]]' and \\X'pdf img.pdf [width [height]]'
221 in Neatroff instruct Neatpost to include the given EPS or PDF file;
222 the former works only when the output is PostScript and the latter
223 when the output is PDF.  They include the given EPS/PDF file with its
224 lower left corner at the current point.  If the width or height are
225 given (in basic units), the image is scaled appropriately.  Neatroff
226 also supports \\X'rotate deg' for rotating the current page around the
227 current point.
229 .MH "Helper Macro Packages
230 In addition to the standard Troff macro packages, such as -ms, -mm,
231 and -me, which are imported from Plan 9 Troff, Neatroff comes with a
232 few convenient helper macro packages as follows (these macros are
233 included in neatroff_make): for drawing simple tables without the tbl
234 preprocessor -mtbl, for including EPS and PDF images -meps, for
235 drawing simple charts and graphs -mgr, for floating objects -mkeep.
236 Some Groff-specific macros are implemented in -mgnu, such as open,
237 opena, close, write, pso, and mso.  Also, -men and -mfa include
238 -ms-like macros for creating short English and Farsi documents.
241 .SH "Summary of New Requests"
242 This is the list of new requests available in Neatroff compared
243 to those documented in \(lqTroff User's Manual\(rq by Ossanna
244 and Kernighan.
246 .NR "\&.ad p*" "b" "adjust" "E"
247 With values pl, pr, pb, and p, this request instructs Neatroff to perform
248 whole-paragraph line formatting.  Also, the value k enables Keshideh
249 justification (kp is the equivalent for whole-paragraph formatting).
251 .NR "\&.blm M" "\-" "disabled" "\-"
252 Specify the blank line macro.  If specified, each blank line is
253 treated as an invocation of this macro.
255 .NR "\&.chop R" "\-" "none" "\-"
256 Remove the last character of a string register.
258 .NR "\&.cl C" "0" "previous" "E"
259 Change text colour.  The current colour is available in the number
260 register \\n(.m.  With no arguments, the previous colour is selected.
261 The format of the argument and the \\m escape sequence are described
262 in the previous section.
264 .NR "\&.co SRC DST" "\-" "none" "\-"
265 Copy the contents of register SRC into register DST.
267 .NR "\&.co+ SRC DST" "\-" "none" "\-"
268 Append the contents of register SRC to register DST.
270 .NR "\&.co> R F" "\-" "none" "\-"
271 Copy the contents of register R into file F.
273 .NR "\&.co< R F" "\-" "none" "\-"
274 Read the contents of register R from file F.
276 .NR "\&.char C DEF" "\-" "\-" "\-"
277 Define Troff character C.
278 If DEF is missing, previous definitions for character C are removed.
280 .NR "\&.ochar FN C DEF" "\-" "\-" "\-"
281 Define Troff character C only for font FN.
282 If DEF is missing, previous definitions
283 for character C are removed.
285 .NR "\&.rchar C" "\-" "\-" "\-"
286 Remove the definition of character C.
288 .NR "\&.eos S T" "S=\&.?!  T='"")]*" "none" "\-"
289 Specify sentence characters.  The first argument specifies
290 the characters that end a sentence and the second argument
291 specifies the characters ignored after them.
293 .NR "\&.fzoom F N" "1000" "none" "\-"
294 Magnify the given font by N/1000.
296 .NR "\&.fp N F L" "\-" "none" "\-"
297 In Neatroff, if instead of the position of the font to be mounted, N
298 is a dash, the position of the font is decided automatically: if a
299 font with the same name is already mounted, the same position is
300 reused.  Otherwise the font is mounted on the next available
301 position.
303 .NR "\&.ff F +F1 -F2" "\-" "none" "\-"
304 Enable or disable font features; the first argument specifies the
305 font and the rest of the arguments specify feature names,
306 prefixed with a plus to enable or a minus to disable.
307 When a feature is enabled, all substitution and positioning rules
308 of a font with that feature name are applied when laying out the
309 glyphs.
311 .NR "\&.ffsc F SC LN" "\-" "none" "\-"
312 Specify font's script and language.  A Neatroff font description
313 specifies a set of rules for each script and language, grouped into
314 several features.  With this request, only the rules for the specified
315 script and language are enabled.  By default, or when SC is missing,
316 all scripts are selected.  When LN is missing, the rules of the
317 default language of the selected script are enabled.
319 .NR "\&.fspecial F S1 S2" "\-" "none" "\-"
320 Set special fonts when the current font is F.
322 .NR "\&.fmap FN CH GID" "\-" "none" "\-"
323 Map Troff character CH to glyph with device dependent name GID for
324 font FN.  When gid is missing, the effect of mapping CH is cancelled.
325 Neatroff implicitly calls \&.fmap for all aliases in font descriptions
326 (character definitions whose second column is ").
328 .NR "\&.hycost N N2 N3" "0" "none" "E"
329 Change the cost of hyphenating words when adjusting lines.
330 An argument of 100 assigns to each hyphenation the cost of stretching
331 a space one hundred percent while formatting.  The second and third
332 arguments specify additional costs for two and three consecutive
333 hyphenated lines (only when formatting whole paragraphs).
335 .NR "\&.hlm n" "0" "0" "E"
336 Set the maximum number of consecutive hyphenated lines (only when
337 formatting whole paragraphs).  The current value is available via
338 \\n[.hlm].  An argument of zero or a negative number implies no
339 limitation.
341 .NR "\&.hydash C" "\\\\:\\\\(hy\\\\(en\\\\(em-\\\\-\\\\(--" "none" "\-"
342 Specify the list of characters after which words may be broken (even
343 when hyphenation is disabled) without inserting hyphens.
345 .NR "\&.hystop C" "\\\\%" "none" "\-"
346 Specify hyphenation inhibiting characters.  Words containing any of
347 the given characters are not hyphenated, unless after dashes
348 (characters specified via \&.hydash) or hyphenation indicators (\\%).
350 .NR "\&.hpf P H C" "\-" "English" "\-"
351 Set hyphenation files for patterns, exceptions, and mappings.
352 With no arguments, loads English hyphenation patterns and exceptions.
354 .NR "\&.hpfa P H C" "\-" "English" "\-"
355 Like, \&.hpf, but do not clear the previous hyphenation patterns.
357 .NR "\&.hcode abcd..." "\-" "none" "\-"
358 Assign the hyphenation code of b to a and the hyphenation code of d to c.
360 .NR "\&.in2" "0" "previous" "E"
361 Right-side indentation.  The current right-side indentation is
362 available in register \\n(.I.
364 .NR "\&.ti2" "0" "\-" "E"
365 Right-side temporary indentation.
367 .NR "\&.kn N" "1" "none" "E"
368 Enable or disable pairwise kerning (current value available through \\n[.kn]).
370 .NR "\&.lsm M" "\-" "disabled" "\-"
371 Specify the leading space macro.  If specified, for each line with
372 leading spaces, this macro is invoked.  The register \\n[lsn] holds
373 the number of leading spaces removed from the line.
375 .NR "\&.pmll N C" "0" "0" "E"
376 Set paragraph minimum line length in percentage.  To shorter lines,
377 Neatroff assigns a cost proportional to the value specified as the
378 second argument (or 100, if missing) when formatting paragraphs.
379 Number registers \\n[.pmll] and \\n[.pmllcost] store the
380 values passed to \&.pmll.
382 .NR "\&.>>  \&.<<" "left-to-right" "\-" "E"
383 Render text in left-to-right or right-to-left direction.  See the
384 first section for an explanation of escape sequences \\> and \\<.
386 .NR "\&.shift N" "\-" "N=1" "\-"
387 Shift macro arguments by N positions.
389 .NR "\&.ssh N" "0" "0" "E"
390 Set the amount stretchable spaces in formatted lines may be
391 shrunk in percentage (available through \\n[.ssh]).
393 .NR "\&.ss M N" "M=12 N=12" "none" "E"
394 The second argument sets sentence space size (available in \\n[.sss]).
396 .NR "\&.tkf FN S1 N1 S2 N2" "\-" "none" "\-"
397 Enable track kerning for font FN.  If the point size is at most
398 S1, the width of each character is increased by N1 points, if it
399 is at least S2, the width of each character is increased by N2
400 points, and if it is between S1 and S2, the width of each character
401 is increased by a value between N1 and N2, relative to the
402 difference between the current point size and S1.
405 .SH "Notes"
406 .sp -1
407 .MH "The standard macro packages
408 The standard Troff macro packages and a top-level build script to
409 obtain and install Neatroff are available in neatroff_make git
410 repository (\*[post.url http://litcave.rudi.ir/ link]).
411 \(lqGetting Started with Neatroff\(rq (\*[post.url http://litcave.rudi.ir/neatstart.pdf link])
412 explains how to use this repository.
414 .MH "Formatting equations with Neateqn
415 Neateqn is an eqn preprocessor for Neatroff.  It implements many
416 of the extensions introduced in Groff's eqn preprocessor.  It
417 can use TeX's Computer Modern-style bracket-building symbols, if
418 available.
419 \(lqTypesetting Mathematics with Neateqn\(rq (\*[post.url http://litcave.rudi.ir/neateqn.pdf link])
420 introduces Neateqn.
422 .MH "Generating the output device
423 The Neatmkfn program (\*[post.url https://github.com/aligrudi/neatmkfn link])
424 generates Neatroff font descriptions for AFM or TrueType fonts
425 (OpenType fonts are converted to TrueType first).  It includes a
426 script to create a complete output device for Neatroff.
428 .MH "Missing requests
429 A few requests of the original Troff are not implemented:
430 \&.pi, .cf, .rd, .pm, .ul, .cu, .uf, \\H, and \\S.
432 .MH "Porting and distribution
433 Given that Neatroff, Neatpost, Neatmkfn, and Neateqn can be compiled
434 with Neatcc, porting them to other Unix variants besides Linux should
435 not be difficult.  Note that Neatroff is released under the ISC
436 licence.
438 .MH "List of OpenType font features
439 As mentioned in previous sections, font features can be enabled and
440 disabled with \&.ff request.  For the list of OpenType features in
441 general and their descriptions, see
442 the list of typographic features in Wikipedia (\*[post.url https://en.wikipedia.org/wiki/List_of_typographic_features link])
443 or OpenType specification (\*[post.url http://www.microsoft.com/typography/OTSPEC/featurelist.htm link]).
446 .SH "Font Description Files"
447 The format of font description files in Neatroff, although still mostly
448 backward compatible, has been slightly changed.  The value of special,
449 spacewidth, and ligatures parameters retain their old meanings; sizes
450 and name parameters are ignored, however.  The value of the fontname
451 parameter in Neatroff specifies the device name of the font
452 (e.g. Times-Roman); Neatpost uses it to map Troff fonts to PostScript fonts.
453 In the charset section, the forth field is always the
454 device-specific name of the glyph (accessible with \\N escape sequence)
455 and the optional fifth field specifies glyph's code (the fourth field
456 of the original Troff).
458 In addition to the old charset section of the original Troff, Neatroff
459 supports a new syntax for defining characters and kerning pairs.  Lines
460 starting with the word \(lqchar\(rq define characters (similar to lines in
461 the charset section) and lines starting with \(lqkern\(rq specify kerning pairs.
462 For the latter, \(lqkern\(rq is followed by three tokens: the name of the
463 first glyph, the name of the second glyph, and the amount of kerning
464 between them.  Specifying the name of glyphs (the fourth field after \(lqchar\(rq)
465 instead of character names allows specifying kerning pairs for glyphs
466 not mapped to any characters (may be later with \&.fmap request) or
467 specifying kerning pairs only once for all aliases of a character.
468 Here are a few lines of a font description file for Neatroff, created
469 with Neatmkfn.
471 .cc.beg
472 .ta 5 10 15 20 25
473 name R
474 fontname Times-Roman
475 spacewidth 25
476 ligatures fi fl 0
477 # the list of characters
478 char    !       33      2       exclam  33
479 char    .       25      0       period  46
480 char    A       72      2       A       65
481 char    B       67      2       B       66
482 char    C       67      2       C       67
483 # the kerning pairs
484 kern    A       C       -5
485 kern    A       period  -1
486 .cc.end
488 The width column of the character definition lines can optionally
489 include four more numbers, separated with commas, that describe the
490 bounding boxes of the glyphs.  The bounding boxes are used in the \\w
491 escape sequence; after this escape sequence, the value of the bbllx,
492 bblly, bburx and bbury number registers are modified to represent the
493 bounding box of the argument of \\w.
495 To use the advanced features present in TrueType and OpenType fonts,
496 Neatroff supports lines that define substitution and positioning
497 rules (lines starting with \(lqgsub\(rq and \(lqgpos\(rq respectively).
498 Note that unlike Heirloom Troff, which implements non-contextual
499 single-character substitutions, Neatroff implements many of the more
500 complex OpenType substitution and positioning features.  The following
501 example shows how such features are defined in Neatroff font
502 descriptions:
504 .cc.beg
505 .ta 5 10 15 20 25
506 gsub liga:latn 4 -gl1 -gl2 -gl3 +gl123
507 gpos kern:latn 2 gl1:+0+0-5+0 gl2
508 .cc.end
510 In this example, the first line defines a 3-character ligature (with
511 feature name \(lqliga\(rq and script name \(lqlatn\(rq) and the second
512 defines pairwise kerning for the pair of glyphs gl1 and gl2
513 (decreasing the horizontal advance of gl1 by 5 basic units; with
514 feature name \(lqkern\(rq and script name \(lqlatn\(rq).  The patterns
515 can be longer and more detailed, defining context or glyph groups, to
516 support OpenType features that require them; for examples, see the
517 files generated by Neatmkfn.
520 .SH "Source Code Organization
521 The following figure shows where Neatroff's major
522 layers and features are implemented in its source tree.
523 .sp -1
528 # part(title, description)
529 define part { [
530 M:      box ht 0.5 wid 2.3
531 .ps 15
532         $1 at 1/2 <M.w, M.nw> + (.2, 0) ljust
533 .ps 9
534         $2 at 1/2 <M.w, M.sw> + (.2, 0) ljust
535 .ps 20
536 ] }
537 # part2(title, description)
538 define part2 { [
539 M:      box ht 0.3 wid 2.6
540 .ps 13
541         $1 ljust at M.w + (.2, 0)
542 .ps 9
543         $2 ljust at M + (-.4, 0)
544 .ps 20
545 ] }
546 .ps 20
547 lineht = .3
548 HEAD:   "\s(17\fI\fP\s0"
549         down
550         move .3
551 IN:     part("in.c", "Input handling")
552         arrow
553 CP:     part("cp.c", "Copy-mode interpretation")
554         arrow
555 TR:     part("tr.c", "Troff request/macro execution")
556         arrow
557 REN:    part("ren.c", "Rendering, traps, and diversions")
558         arrow
559 OUT:    part("out.c", "Generating Troff output")
560         "\s(17\fI\fP\s0" at HEAD + (3, 0)
561         move .3
562 REG:    part2("reg.c", "Registers and environments")
563         move down 0.2
564 FMT:    part2("wb.c", "Word buffer")
565         move same
566         part2("eval.c", "Integer expression evaluation")
567         move same
568         part2("fmt.c", "Line formatting")
569         move same
570 DEV:    part2("dev.c", "Output device")
571         move same
572 FONT:   part2("font.c", "Fonts")
573         move same
574         part2("hyph.c", "Tex hyphenation")
575         move same
576         part2("dir.c", "Text direction")