Полезная информация



TOC
BACK
FORWARD
HOME

UNIX Unleashed, Internet Edition

- 8 -

Basic Formatting with troff/nroff

by James C. Armstrong and David B. Horvath, CCP

UNIX was originally developed by Ken Thompson on a little-used PDP-7. The justification for the purchase of a PDP-11/20 for the second version was to provide a text editing and formatting system. The purpose of that system was to develop, maintain, and track documents and memos within the telephone company (AT&T/Bell Telephone).

Many products are available for text editing and formatting for the PC, including Microsoft Word and WordPerfect. Versions of these products and others are available for UNIX systems, but the most common are the nroff and troff text processors. nroff stands for "next run-off," and troff stands for "typesetter run-off," both of which are based on roff ("run-off"). The original version of RUNOFF was developed by J. E. Saltzer for the CTSS operating system effort at MIT during the 1960s. Most text processors can trace their beginnings to the original RUNOFF; they include SCRIPT (for IBM mainframes), Scribe (by Brian Reid), DSR (Digital Standard Runoff), Donald Knuth's Tex, and, of course, UNIX roff.

In the early 1970s, Joe Ossanna rewrote roff to produce nroff. He added flexibility and an internal programming language to aid in document formatting. nroff was enhanced (and renamed troff) to support the Graphics Systems CAT typesetter with multiple fonts, font sizes, and additional characters that regular printers did not support.

In 1979, Brian Kernighan rewrote troff to support more typesetting machines. Although alternatives were investigated, the Bell Labs portion of the telephone company had already invested a great deal of effort in troff, including macro packages and preprocessors that made document preparation easier for users. One of these macro packages is used to format the UNIX manual pages.

troff and nroff are closely related. They both use the same set of commands to format text. The biggest exception is that nroff does not support commands for changing character fonts and sizes; it supports a limited number of character set changes. nroff also provides ASCII output, so you can see the results of an nroff command onscreen. Although third-party products can show the results of a troff command onscreen if they have graphics capabilities, on a standard UNIX system, the only way to see the exact troff output is to send it to a printer. (troff can produce only an approximation of its output to normal terminals.)

This chapter will show you:

  • How to format documents using nroff and troff

  • How to display and print the formatted documents

  • The various embedded commands (primitives) used with nroff and troff

  • How to format program output through nroff/troff

  • How to post-process troff output to send it to various devices

Formatting with nroff/troff: An Overview

Many word processors, such as Microsoft Word and WordPerfect, are WYSIWYG (What You See Is What You Get) processors. With these word processors, as you type and format your text, you see exactly how they are going to print. Text processors such as nroff and troff are called descriptive markup languages, which means that you embed the formatting codes into your document like any other text, and you don't see the effects of the instructions until you print the file.

Some other text formatting or markup languages are Standard Generalized Markup Language (SGML), HyperText Markup Language (HTML), Encapsulated PostScript (EPS), and others. Although their syntax, or command format, may be different from nroff/troff, they share the same heritage. See Chapter 15, "HTML--A Brief Introduction," for more information about HTML.

Several building blocks are available for formatting files using nroff and troff, including the following:

Primitive requests: The standard command in troff, called a primitive request, has the form of a period followed by two lowercase letters. The period must appear in the first column, and any text after the request is an argument. You use primitives to do all kinds of formatting, such as indenting paragraphs, adding space between paragraphs, changing fonts, and centering text. This chapter provides examples of using the more common primitives and a quick reference that briefly describes all primitives. If you're new to nroff/troff, you might want to try using a macro package before you dive into primitives.

Macros: Most UNIX systems provide standard macro packages, which enable you to format documents more easily than with primitives. Macros perform operations more or less automatically, such as formatting bulleted lists, headings, and indented paragraphs. Four macro packages--mm, ms, me, and man--are described in detail in Chapter 9, "Formatting with Macro Packages." Chapter 10, "Writing Your Own Macros," shows you the ins and outs of creating macros. You can create a file using only macro package commands, or you can mix macros and primitives in the same file.

Preprocessors: Most UNIX systems provide standard preprocessors. Each preprocessor is a set of commands devoted to a special task. You can format tables with the tbl preprocessor, equations with eqn or neqn, line drawings with pic, and graphs with grap (described in Chapter 11, "Tools for Writers"). You can create a file containing only preprocessor commands, and you can embed preprocessor commands in regular documents formatted with primitives, a macro package, or both.

Strings: You can define strings, just as you can define macros. For example, if you're writing about a new product whose name hasn't been decided yet, you can define a string for the temporary name "Hot New Product." When the name is finally chosen, you don't have to do a global search and replace for "Hot New Product." You can just redefine the string to produce "XYZZY Thingo." Specific instructions for defining strings are in the section titled "Strings and Macros" later in this chapter, and in Chapter 10, "Writing Your Own Macros."

Number registers: You use number registers to keep track of values such as your current font and point size, your current indentation, and the current list item. These registers are really nothing more than storage locations. Some are read-only; others can be manipulated. You can define your own number registers and use them in macros. Specific examples are given in the section titled "Number Registers" later in this chapter, and in Chapter 10, "Writing Your Own Macros."


NOTE: troff insists on calling these registers "number registers," but in fact they don't need to contain numbers; they can--and often do--contain alphabetic characters.

Escape sequences: You can use escape sequences (backslash-character or backslash-open-parenthesis-character-character) to change fonts and point sizes and for many other tasks. Some escape sequences enable you to enter troff primitives inline with the text they affect rather than on lines by themselves. You can find specific examples in the section "Inline Escape Sequences" later in this chapter and in other chapters where they apply.

Special characters: Although special characters are system-dependent, several of them are usually available on all systems, such as a long dash, a degree symbol, and a copyright symbol. You can find specific examples in the section "Special Characters" later in this chapter and in other chapters where they apply.

Chapters 8 through 11 give you an introduction to the nroff/troff family of text processing tools, but many more features are available than room allows me to describe. You can find online man pages for each of the commands described. You also can find books and papers dedicated to this topic; for example, The NROFF/TROFF User's Manual by J. F. Ossanna and A TROFF Tutorial by B. W. Kernighan are the original documents from the UNIX Programmer's Manual, Volume 2.

Basic Printing with nroff and troff

UNIX offers a variety of commands and utilities for printing. In addition, your system may have a number of local commands. Check with your colleagues or the system administrator. If they tell you that they use a shell script called prinnumup to send their files to the printer, you should use prinnumup too.

Because you can print in so many ways (as with many tasks in UNIX), asking the system administrator is often the best way to get information. Most of administrators do not mind being asked these questions. Just be sure to write down the answer so that you don't ask the same question again.

The truth is that versions of UNIX differ, printers differ, and ways of getting the data from your file to a printer differ (because of different networks and connections). New models and entirely new printers are being introduced all the time.

Displaying nroff Files

nroff enables you to format your file on the screen instead of (or before) formatting it for a printer. troff does the same if you have a graphics terminal, and it also produces an approximation of the printed results for a regular screen.

To use nroff on a file containing only nroff/troff primitives to the standard output device (screen), use one of the following commands:

nroff filename | pg
nroff filename | more

The choice between piping to pg or to more depends on your system and your personal preference. Sometimes more produces just a single line of additional text rather than a new screenful. You need to use one or the other to prevent the text from scrolling off your screen. Remember, these tools are designed to produce full pages for a printer; most pages have more lines than your screen can show.

Differences Between nroff Output and troff Output

Printed files look different, depending on whether they are formatted with nroff or troff. In general, files printed using nroff exhibit the following characteristics: All values are treated as a number of character positions (spaces) or line spaces. Vertical space is in multiples of a full linespace. Tabs are set every eight characters by default. Certain troff requests are not available (for example, .fp, .lg, .ss). Text in italic font is underlined; text in bold font is emboldened by overstriking. Point size and vertical space requests (.ps and .vs) are ignored. Right-margin justification is turned off for the mm macros. In addition, the default left margin is flush with the left edge of the physical page.

When printing to the screen, some of the formatting may not be obvious because the terminal cannot handle it.

The output from troff looks a lot more like a typeset document (like this book for instance)--as the name, typesetting roff, implies. You can have fonts of different sizes, overprinting of characters, proportional fonts, and even italics.

Printing troff Files

The original versions of troff produced output in the format required by the phototypesetter. The new version is more device independent and requires its output to be post-processed before it can be accepted by most printers. Although some implementations on UNIX refer to this as the ditroff command ("Device Independent troff"), most just replaced the original troff with the new version.

Using the troff command to print your file on a Hewlett-Packard LaserJet series printer (which is common in office environments), for example, you enter the following:

troff filename | hplj | lpr -Phpprinter
troff -Thplj filename | hplj | lpr -Phpprinter

The hplj command post-processes the troff output into a form that the laser printer can handle. The lpr -Phpprinter command sends your output to the physical printer assigned to hpprinter; note that some installations may use the lp -dhpprinter command instead. If you use the -Thplj option on the troff command, the page is properly formatted and available fonts are adjusted. (The nroff/troff options and other post-processors are discussed later in this chapter.)

You can also print the source file (showing the nroff/troff embedded commands) by using the lp or lpr commands as follows:

lpr -Phpprinter filename
lp -dhpprinter filename

You need to check with your system administrator to determine the local command and printer names.

Printing nroff Files

Printing nroff output is similar to printing troff output except that post-processing is not required.

Using nroff to print your document and send it to the same printer as used in the preceding troff example, you enter the following:

nroff filename | lpr -Phpprinter
nroff -Thplj filename | lpr -Phpprinter

If you use the -Thplj option on the nroff command, the page is properly formatted and available fonts are adjusted.

Text Filling and Adjusting

You get the cleanest look to any document when the text looks symmetric, with one or two smooth margins, and spread across the page--like this paragraph. The default settings for nroff and troff are to "fill" each line with text, and to "adjust" the position of the text so that all lines begin at the left margin and the right margin is justified. In the simplest case, the input file does not need any troff requests to format a basic document. Listing 8.1 illustrates a basic input file, and Figure 8.1 illustrates the output produced by nroff.

Listing 8.1. Basic nroff/troff source with no requests.

We, the people of the United States, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our posterity do
ordain and establish this Constitution for the United States of
America.

Figure 8.1.
nroff output with no requests.

The raw text file has a ragged right margin, with some lines very short and one line longer than desired. If you put the text through nroff, the lines are set to an even length, and the margins are smooth. Two words are broken across lines. If you look closely at the output in Figure 8.1, you'll see that nroff justifies the right margin by inserting extra spaces between words, at alternating ends of each line. The first line needs no extra spaces, but to even the margin on the second line, an extra space is included between perfect and Union, and the third line needs four extra spaces.

troff output of the same text, shown in Figure 8.2, shows that the lines are expanded to justify the margins by changing the spacing of letters across the entire line.

Figure 8.2.
troff
output of Figure 8.1.

You can set the ability to fill the text by using two requests. The first, .fi, tells troff that you want the text to be filled with input. This setting is the default. The request .nf tells troff that you don't want text filled but that you want the right margin to be ragged. This request is useful for cases in which a block of text is inappropriate, such as a return address or poetry. Listing 8.2 shows a sample input file for a letter, with no fill in places and some fill in places. Figure 8.3 shows the output.

Listing 8.2. troff source illustrating the fill requests.

.nf
101 Main Street
Morristown, NJ  07960
15 March, 1997

Dear Sir,

.fi
I just wanted to drop you a note to thank you for spending the
time to give me a tour of your facilities. I found the experience
both educational and enjoyable. I hope that we can work together
to produce a product we can sell.

Figure 8.3.
troff output showing filled and non-filled text.

Note that a blank line separates blocks of text. On a longer document, you can use these blank lines to separate paragraphs. Another way to separate blocks is to use .br, which interrupts the filling of the current line and starts a new block of text. You can do the same by starting a line of text with a space. Figure 8.4 shows the output of Listing 8.1, but output includes a break after the words the general welfare.

Figure 8.4.
troff
output showing the effect of a break in midsentence.

Although smooth margins are the default, you also have control of the margins. The .ad command controls adjustment. It can take the following as arguments: l means to adjust the left margin only; r is to adjust the right margin only; c is to center each line; and b or n means to adjust both margins. Figure 8.5 shows the effects of using .ad l, .ad r, and .ad c on the first text example. .ad b is the default starting value and is effectively demonstrated in the first example.

Figure 8.5.
troff
output showing the effects of different line adjustments.

Obviously, adjustment makes no sense if the text is not filled. You also can turn off right margin adjustment by using .na. The adjustment mode is not changed.

The last type of text adjustment is centering. It is somewhat different from .ad c, which continues to fill lines before centering the text but only if .fi is specified. The centering request is .ce, which can be followed by a number. This request centers the next line or lines, without filling text. If the text is filled, each input line is treated as if it were followed by a break. Non-filled lines are treated the same as .ce. Chapter titles are an example of text centering. Listing 8.3 shows the source for a centering command, and the output is illustrated in Figure 8.6.

Listing 8.3. troff source for the centering command.

.ce 3
Scientific Methods of Computing
A Simulation
by John Smith

Figure 8.6.
The effects of the centering request.

Vertical Spacing

troff includes three types of vertical space controls. Baseline spacing controls the basic spacing between consecutive lines of text. The next type is extra line spacing; with this type, you can double-space text, or more, both on a regular basis and on a per case basis. The last is a block of vertical space.

Space measurements have different scales. When a request needs a distance, you can use the default type or modify the number with an indicator. The measurement types are inches, centimeters, picas, ems, ens, points, units, and vertical line spaces. A pica is one-sixth of an inch. An em is the width of the letter m and is dependent on the font used in troff. An en is half an em. The modifiers are listed in Table 8.1.

Table 8.1. troff space measurement modifiers.

Measurement Option Description
i inch
c centimeter
p pica
m em
n en
p point
u unit
v vertical space

The default vertical spacing between lines of text is dependent on the text processor used. For nroff, it is one-sixth of an inch. For troff, it is 12 points. You can change this setting by using .vs. For nroff, the command argument is rounded to picas, so if you need extra space regularly, .ls is clearer. With troff, the default space measurement is points, although any measurement type can be used. Figure 8.7 shows examples of different spacings using the initial text example.

Figure 8.7.
Different vertical spacing using troff.

The .ls request, mentioned previously, is used to indicate the number of blank lines between each line of text. The default value is 1, for single spacing. You can double-space text by using .ls 2. Figure 8.8 shows the first text example with .ls 2.

Figure 8.8.
Different line spacing using troff.

You can achieve block spacing by using the .sp request. With no arguments, this request gives a single blank line. It can take arguments of any size, with the default unit being the vertical spacing. Negative numbers space back up the page; positive numbers head down the page. Spacing changes requested here do not leave the page; if the requested space is beyond the bottom of the page, the text starts at the top of the next page. Using the sample letter started earlier in this chapter, you can leave an inch of space between the date and the salutation. The source is changed in Listing 8.4, with the output in Figure 8.9.

Listing 8.4. troff source for block spacing.

.nf
101 Main Street
Morristown, NJ  07960
15 March, 1997
.sp 1i
Dear Sir,

.fi
I just wanted to drop you a note to thank you for spending the
time to give me a tour of your facilities. I found the experience
both educational and enjoyable. I hope that we can work together
to produce a product we can sell.

Figure 8.9.
troff output with a block of space.

Another method to grab a block of vertical space is to use the .sv request. It takes the same arguments as .sp but has some different behaviors. You cannot request space at the top of a page using .sp, for example. Also, if a space request exceeds the size of the page, the space is truncated at the bottom of the page with .sp. With .sv, the space is not generated unless room is available on the page for the space. In this case, the space requested is remembered and can be released on a new page with .os. Normally, .os appears only in complicated macro definitions, which are discussed later.

For the sample letter, save a half inch of space at the top of the page. The modified source is shown in Listing 8.5, and the output is shown in Figure 8.10.

Listing 8.5. troff source using .sv.

.sv 0.5i
.nf
101 Main Street
Morristown, NJ  07960
15 March, 1997
.sp 1i
Dear Sir,

.fi
I just wanted to drop you a note to thank you for spending the
time to give me a tour of your facilities. I found the experience
both educational and enjoyable. I hope that we can work together
to produce a product we can sell.

Figure 8.10.
troff
output with requested space using .sv.

Two other spacing controls are also available. The request .ns turns off spacing mode, effectively disabling the .sp command. To restore spacing, you can use .rs. These commands are more likely to be found in macros.

Line Controls

In addition to requests for filling and adjusting lines of text and for changing position on a page are requests to change lines themselves.

By default, the length of a line of text is 6.5 inches in nroff and 7.54 inches in troff. You can change this length by using the .ll request. The default space measurement is in ems, but most people prefer using inches or centimeters.

Listing 8.6 shows the modified source for the same letter, with the line length changed to 4 inches; its effect on the output is shown in Figure 8.11.

You also can indent lines of text, both for a single line and for all text. The .in request indents all lines of text a common distance. Listing 8.6 shows how you can indent the return address. You can request a temporary indent, such as might lead a paragraph, by using .ti. This request is also illustrated in Listing 8.6 and shown in the output in Figure 8.11.

Listing 8.6. troff source illustrating line indents and lengths.

.nf
.ll 4.0i
.in 2.0i
101 Main Street
Morristown, NJ  07960
15 March, 1997
.sp 1i
.in 0
Dear Sir,

.fi
.ti 0.25i
I just wanted to drop you a note to thank you for spending the
time to give me a tour of your facilities. I found the experience
both educational and enjoyable. I hope that we can work together
to produce a product we can sell.

Figure 8.11.
troff
output with line indents and lengths.

Using text indents can help you organize a document.

Page Control

For most documents, not only must you format the text, but you also must control the page. Both nroff and troff default to an 11-inch page. troff has a one-inch left margin, and nroff has no left margin. Pages start at page one and are sequentially numbered. You can change each of these details if you want.

The .pl request sets the length of a page; the default space measurement is in vertical spaces. Again, inches can be better used here. For the sample letter, assume a page length of 8 inches. (Some other normal page lengths are 12 inches for A4 paper and 14 inches for legal-sized paper. troff can support pages up to 75 inches long, and nroff can support up to 136 inches.)

You can force new pages by using the .bp request. An argument can affect the number of pages output. The .ns request, which I mentioned earlier, disables the .bp request, unless you specify a specific number of pages.

The .pn request assigns a page number to the next page printed. This request does not affect the present page, only subsequent pages. These three requests are illustrated in the source in Listing 8.7 and the output in Figure 8.12, showing an extended form of the letter.

Listing 8.7. troff source illustrating page controls.

.nf
.ll 5.0i
.pl 8.0i
.in 2.5i
101 Main Street
Morristown, NJ  07960
15 March, 1997
.in 0
.sp 1i
Dear Sir,

.fi
.ti 0.5i
I just wanted to drop you a note to thank you for spending the
time to give me a tour of your facilities. I found the experience
both educational and enjoyable. I hope that we can work together
to produce a product we can sell.
.pn 4
I am sending a copy of our proposal on the next page. I look forward
to hearing from you.
.sp 2
.in 2.5i
Yours,
.sp 0.5i
Joe Smith, President Any Corp.
.bp
.in 0
We propose to build our widget tools with your widget makers.

Figure 8.12.
troff
output with page controls.

Note that the page number is not printed in Figure 8.12. Page numbers are printed only if you explicitly request them. These techniques are discussed later in this chapter in the section "Flotsam and Jetsam," which discusses page titling.

You can offset the text on the page by using the .po request. It is different from the .in request. .po sets the 0 value for indents and temporary indents. Figure 8.13 shows a page offset of two inches to the preamble of the Constitution.

Figure 8.13.
troff
output with a two-inch page offset.

Two very powerful page controls are the .mk and the .rt requests. The .mk request saves the current vertical location in an internal register (which can be specified in the argument). This request sets a flag at the current location. The .rt request returns to that previous location. One good use for these requests is to establish multiple column output. You can set the mark at the top of the page and at the bottom of the page return to the mark. This use is illustrated in the source in Listing 8.8 and output in Figure 8.14. Note that the simple multiple column approach also requires the use of the .ll and .po requests.

Listing 8.8. troff source using .mk and .rt requests.

.ll 3i
.mk a
.ce
Preamble
.sp
We, the people of the United States, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our posterity do
ordain and establish this Constitution for the United States of
America.
.sp
.ce
Article I
.sp
Section 1  Legislative powers; in whom vested:
.sp
All legislative powers herein granted shall be vested in a
Congress of the United States, which shall consist of a Senate
and a House of Representatives.
.sp
Section 2  House of Representatives, how and by whom chosen,
Qualifications of a Representative. Representatives and direct
taxes, how apportioned. Enumeration. Vacancies to be filled.
Power of choosing officers and of impeachment.
.sp
1. The House of Representatives shall be composed of members
chosen every second year by the people of the several states,
and the electors in each State shall have the qualifications
requisite for electors of the most numerous branch of the
State Legislature.
.sp
2. No person shall be a Representative who shall not have
attained to the age of twenty-five years, and been seven years
a citizen of the United States, and who shall not, when elected,
be an inhabitant of that State in which he shall be chosen.
.sp
.rt
.po 4.5i
3. Representatives and direct taxes shall be apportioned among
the several States which maybe included within this Union,
according to their respective numbers, which shall be determined
by adding to the whole number of free persons, including those
bound for service for a term of years, and excluding Indians not
taxed, three-fifths of all other persons. The actual enumeration
shall be made within three years after the first meeting of the
Congress of the United States, and within every subsequent term
of ten years, in such manner as they shall by law direct. The
number of Representatives shall not exceed one for every thirty
thousand, but each State shall have at least one Representative;
and until such enumeration shall be made, the State of New
Hampshire shall be entitled to choose three, Massachusetts eight,
Rhode Island and Providence Plantations one, Connecticut five,
New York six, New Jersey four, Pennsylvania eight, Delaware one,
Maryland six, Virginia ten, North Carolina five, South Carolina
five, and Georgia three.
.sp
4. When vacancies happen in the representation from any State,
the Executive Authority thereof shall issue writs of election
to fill such vacancies.
.sp
5. The House of Representatives shall choose their Speaker and
other officers; and shall have the sole power of impeachment.

Figure 8.14.
troff output showing the work of .mk and .rt.

The last page control is .ne. It is used to indicate that a certain amount of space is needed before the end of a page. Using this request, you can avoid starting paragraphs at the bottom of a page. Normally, .ne would be included in a macro. If the space requested is available, nothing happens. If the space is not available, the end of page processing is triggered.

Fonts and Style Controls

In the preceding sections, you learned about the positioning of text on the page but did not learn about the actual modification of the text itself. In this section, you learn about different fonts and point sizes.

The standard font is a Times Roman font. Italic, bold, and special fonts are also available on all systems. Some sites may also include Helvetica, Bold-Helvetica, Italic-Helvetica, and Constant-Width fonts. Check your local system for which fonts are available.

On most systems the fonts are stored in /usr/lib/font/devNAME, where NAME is the device specified with the -T option. Some systems store the fonts in /usr/ucblib/doctools/font/devNAME.

The request .ft sets the appropriate font. The process of mounting and unmounting fonts is performed automatically with this request. You must specify the requested font in the argument; if no argument is present, the previous font is restored. The arguments are shown in Table 8.2.

Table 8.2. Standard troff and nroff fonts.

Identifier Font
B Bold
I Italic
R Roman
P Previous
H Helvetica
CW Constant Width
HB Helvetica Bold
HI Helvetica Italic

Fonts have limited meaning in nroff. The font used is a constant-width font. If you specify bold, characters are overstruck in printing. Italic is interpreted as an underline. Other fonts have no meaning.

By setting fonts, you can italicize the preamble to the Constitution and print each section header in bold. The modified source is shown in Listing 8.9, and the output is shown in Figure 8.15.

Listing 8.9. Font selection in troff.

.ce
.ft B
Preamble
.sp
.ft I
We, the people of the United States, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our
posterity do ordain and establish this Constitution for the
United States of America.
.sp
.ce
.ft B
Article I
.sp
.ft R
Section 1  Legislative powers; in whom vested:
.sp
All legislative powers herein granted shall be vested in a
Congress of the United States, which shall consist of a Senate
and a House of Representatives.

Figure 8.15.
troff
output using multiple fonts.

The .bd request sets an artificial bold capability by offsetting a second printing of the character by a number of points. You can use this request to make the italic font appear to be bold by using .bd I 3. There is no effect in nroff.

You can create different sizes of text by using the .ps request. You can specify either a relative change or an absolute point size. Closely related is the .ss request, which sets the width of the space character. Similarly, when you change the point size, you also can change the vertical spacing; otherwise, parts of consecutive lines may overlap. Using these requests, you can increase the size of the section headers in the Constitution and increase the size of the words We the people. See the source in Listing 8.10 and the output in Figure 8.16.

Figure 8.16.
Multiple point sizes in troff output.

Listing 8.10. troff source showing multiple point sizes.

.ce
.ft B
.ps 24
.ss 28
.vs 28
Preamble
.sp
.ft I
We, the people
.ps 12
.ss 14
.vs 14
of the United States, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our
posterity do ordain and establish this Constitution for the
United States of America.
.sp
.ce
.ft B
Article I
.sp
.ft R
Section 1  Legislative powers; in whom vested:
.sp
All legislative powers herein granted shall be vested in a
Congress of the United States, which shall consist of a Senate
and a House of Representatives.

The last text request is .cs, which sets a constant character width for a given font in troff. This request takes three arguments. The first is a font, the second is the width of the space, and the last is the character point size. If the third argument is absent, the default is the current character width. If the second argument is also absent, the constant width is turned off.

Listing 8.11 shows this request for the default Times Roman font in the preamble and turns it off for the remainder of the Constitution. Figure 8.17 shows the output.

Listing 8.11. troff source illustrating the .cs request.

.ce
.ft B
.ps 24
.ss 28
.vs 28
Preamble
.sp
.ft I
We, the people
.ps 12
.ss 14
.vs 14
.ft R
.cs R 15
of the United States, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our
posterity do ordain and establish this Constitution for the
United States of America.
.sp
.cs R
.ce
.ft B
Article I
.sp
.ft R
Section 1  Legislative powers; in whom vested:
.sp
All legislative powers herein granted shall be vested in a
Congress of the United States, which shall consist of a Senate
and a House of Representatives.

Figure 8.17.
troff
output using .cs.

You can also specify fonts by position: font 1, font 2, font 3, and so on. In the early versions of troff, before device-independent troff (ditroff), only four font positions were available. Quite naturally, 1 was the body type (Times Roman), 2 was the italic version of 1, and 3 was the bold version of 1. You got one elective--position 4--but it was usually used for the Special font (the one with Greek letters and mathematical symbols). As a consequence, specifying fonts by position is not done frequently.


TIP: You are better off specifying fonts by using the .ft request. You can guarantee the way your document will print even if the positional fonts differ.

Inline Escape Sequences

In addition to requests in the form .xx, you also can use inline requests that can make document preparation easier. These requests can generate special characters, change fonts, change point sizes, and produce local motions.

You can use escape sequences (backslash-character or backslash-open-parenthesis-character-character) to change fonts and point sizes and for many other tasks. Table 8.3 lists troff escape sequences.

Table 8.3. troff escape sequences.

Sequence Description
\ Prevents the next character from being processed by troff
\e Prints the escape character; default is the backslash (\)
\' Prints acute accent
\' Prints grave accent
\- Prints a minus sign in the current font
\[space] Creates an unpaddable 1-en space
\0 Prints a space the width of a digit
\| Prints a one-sixth em width space
\^ Prints a one-twelfth em width space
\& Non-printing zero-width character
\! Transparent line indicator
\" Begins a comment
\\$n Interpolates argument
\% Before word, prevents hyphenation; in middle of word, indicates where word can be hyphenated
\(xx Specifies character named xx
\\*x , \*(xx Specifies string named x or xx
\a Specifies leader character used in macros
\b'abc...' Bracket-building function
\c Interrupts text processing
\d Moves down half a line space
\D Draws line, circle, ellipse, arc, or spline
\fx, \f(xx, \fn Requests a font change; font with one-character name is specified as \fH; font with two-character name is specified as \f(HB; numeric positional fonts are specified by replacing n with the appropriate value
\h'n' Moves horizontally to the right; use a negative value for n to move left
\H'n' Sets character height to n points
\jx Marks horizontal place on output line in register x
\kx Marks horizontal place on input line in register x
\l Draws horizontal line
\L Draws vertical line
\nx, \n(xx Interpolates number register x or xx
\o Overstrikes specified characters
\p Breaks output line
\r Reverse 1-em vertical motion
\s Requests a change in point size; can be specified as an absolute value or with +/-
\S'n' Slants output n degrees to the right
\t Horizontal tab
\u Moves up half a line space
\v'n' Moves vertically down; to move up the page, specify negative number
\w Interpolates width of specified string
\x Extra line-space function
\zc Prints c with zero width (without spacing)
\{ Begins conditional input
\} Ends conditional input
\[newline] Concealed (ignored) newline
\X X, any character not listed above

Listing 8.12 shows troff input with inline font and size changes, and Figure 8.18 shows the output.

Listing 8.12. troff source with inline font changes.

\fB\s+4We, the people\s-4\fP of the United States, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our
posterity do ordain and establish this Constitution for the
United States of America.

Figure 8.18.
troff
output with inline font changes.

Two other inline escapes are \& and \p. You can use the \& escape, which is a zero-length control character, to enable the printing of a control character (.) at the start of a line. The \p escape generates a break but also requests that the line be spread to the current input line length.

Similarly, if a word requires extra vertical space, you can use the inline escape \x to request the additional vertical space. You must enclose the amount of space you need in single quotation marks.

The next inline escape deals with unfilled text only. If a line of unfilled text is terminated with a \c, the next text present is treated as a continuation of that line. This capability allows you to include a sequence of requests in the middle of a line, even if those requests do not have associated inline escapes. The .cs request is an example of a case in which you can use \c.

You can change fonts inline by using the \f escape. You can designate single-character font identifiers with \fB, but for two-character identifiers, you need a ( to group the letters. An example is \f(HI for a change to Helvetica-Italic. You can change point sizes similarly by using \s. Here, two-digit fonts are acceptable. Relative changes can be made, too. Figure 8.18 shows a case in which the words We the people are bold and four points larger than surrounding text.

Special Characters

Although special characters are system-dependent, you can expect to have several special characters in your system. Table 8.4 list the special characters typically available for the standard fonts.

The ASCII standard is limited to a small number of printable characters; fortunately, troff provides access to many more characters and symbols needed for mathematics and other applications. A few are escape sequences, but most are two-character escapes. Several two-character printing symbols are available--some on the default font, and some on a special font. They include Greek characters, mathematical characters, and editing symbols.

Table 8.4. Special characters.

Inline Request Character Produced
\\ backslash
\" close quotation mark
\´´ open quotation mark
- hyphen
\- current font minus sign
\(bu bullet
\(co copyright
\(ct cent sign
\(de degree
\(dg dagger
\(em [3/4] em dash
\(ff ff ligature
\(fi fi ligature
\(Fi ffi ligature
\(fl fl ligature
\(Fl ffl ligature
\(fm foot mark
\(hy hyphen
\(rg registered trademark
\(ru rule
\(sq square
\(14 [1/4]
\(12 [1/2]
\(34 [3/4]

Listing 8.13 shows an example of the source for mathematical expressions, and Figure 8.19 shows the output.

Listing 8.13. Inline character requests for troff.

2\(*pr

\(issin\(*td\(*t\(eqcos\(*t

\(*S(\(*a\(mu\(*b)\(->\(if

Figure 8.19.
troff
output of special characters.

Other characters that can come in handy are bullets, (·), the copyright symbol, (©), and daggers, (dg). Four characters have their own commands. To print a backslash, use (\). A minus sign is (-), an open quotation mark is ("), and a close quotation mark is (´´).

Strings and Macros

troff and nroff enable you to specify strings that you can use repeatedly. The strings can be given one- or two-character identifiers, and those identifiers can be referenced later. You can define strings by using the .ds request. The next argument must be the identifier, and the string that follows is assigned to the identifier. The .as request appends additional text to the string. The string is accessed with the inline escape \*. The Constitution provides an example; the source is shown in Listing 8.14, and the output is shown in Figure 8.20.

Listing 8.14. troff source defining a string.

.ce
.ds us United States
Preamble
.sp
We, the people
of the \*(us, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our
posterity do ordain and establish this Constitution for the
\*(us of America.
.sp
.ce
Article I
.sp
Section 1  Legislative powers; in whom vested:
.sp
All legislative powers herein granted shall be vested in a
Congress of the \*(us, which shall consist of a Senate and a
House of Representatives.

Figure 8.20.
troff
output with a defined string.


TIP: Using a defined string for repeated text ensures a consistent look to the document.

Macros provide a technique for you to group repeated requests into a single troff request. If you notice that groups of requests are being repeated, those requests are ideal candidates for making a macro. Examples include quotations, paragraphs, and section headers. The basics of macros are introduced in this section, and Chapter 10 goes into greater detail.

You define macros by using the .de request. A one- or two-character label should follow the request. By convention, macro names are often uppercase, although using this case is not a requirement. A macro name cannot duplicate the name of a request, hence the convention of uppercase names. The troff requests then follow the .de until the .. request is present. These requests are then executed whenever the macro is called. You call the macro by starting the line with a . followed by the macro name, without a space.

You also can design macros to take arguments. Up to nine arguments can be passed to a macro and are accessed as \$N, where N is the argument position from 1 to 9. These arguments can be treated as ordinary variables and can be used anywhere in the macro. When you define a macro, the contents of the commands are interpreted. Therefore, the presence of strings, variables, and comments are translated when the macro is read. To ensure that the argument is not interpreted until the macro is used, you should list the argument in the definition as \\$N. The \\ is interpreted as \. You can use \\ whenever you want the escape to be interpreted when the macro is invoked.

Two examples are illustrated in the source in Listing 8.15 and the output in Figure 8.21. The first macro defined, PP, signals a new paragraph. You first request a space, and then you temporarily indent the first line by a quarter-inch. You also ensure that the font is Times Roman. The second macro defined, HD, is for a header. Here you give it two arguments: the first is the point size you want for the header, and the second is the text of the header. In this macro, you first request a space and then change the point size to the requested size. Next, you request that the text be centered and made bold. Finally, you issue the text, reset the point size and font, and request an additional space.

Listing 8.15. troff source defining macros.

.de PP
.sp
.ti +0.25i
.ft R
..
.de HD
.sp
.ps \\$1
.ce
.ft B
\\$2
.ps
.ft P
.sp
..
.HD 14 "A sample header"
.PP
We begin the text of the first paragraph here. This is indented
and formatted. We continue with the text of the first paragraph
until we want the second paragraph.
.PP
We re-issue the macro, and get the space and indent.

Figure 8.21.
troff
output with a defined macro.

You can change macros after creating them by using the .am request. It appends troff requests to the already existing macro, given in the first argument. For the preceding example, assume that you want the second and subsequent paragraphs to have a point size of 10 for the text. You can make this change by including the following commands after the first call to PP:

.am PP
.ss 10
..

You could have redefined the macro with .de, but the .am request is quicker. You can also rename macros by using .rn. You can use it even with standard troff requests and strings. The original name is the first argument, and the new name is the second argument. The old name is not retained.

Finally, you can remove macros, strings, and other requests by using .rm. Any subsequent commands to the macro are ignored.

Number Registers

troff provides number registers for the tracking of parameters for troff. They can be accessed with the escape sequence \n. For single-character names like x, use \nx. For multiple-character names like xx, use \n(xx. Number registers are used for items such as page numbers and line length. The predefined registers include % for page number, dw for the day of the week, dy for the day, mo for the month, and yr for the year. nl also shows the position of the last printed line. Listing 8.16 shows how you can use some of these registers, and Figure 8.22 shows the output.

Listing 8.16. Using number registers.

.nf
.ll 5.0i
.in 2.5i
101 Main Street
Morristown, NJ  07960
\n(mo/\n(dy/\n(yr
.in 0
.sp
Dear Sir,

Figure 8.22.
troff
number registers in output.

Many read-only registers contain configuration parameters; some of them are listed in Table 8.5. All the registers (read-only and read-write) are listed in Chapter 10 in Tables 10.1 and 10.2.

Table 8.5. Common number registers in troff.

Register Description
.$ Number of arguments to a macro
.A Set to 1 if -a is used on troff command line; always 1 for nroff
.T Set to 1 if -T is used on nroff command line; always 1 for troff
.a Value of extra space most recently used
.c Number of lines read from current input file
.f Current font
.h Text high water mark for current page
.i Current indent
.l Current line length
.n Length of text on previous output line
.o Current page offset
.p Current page length
.s Current point size
.u Fill more flag (1 for on, 0 for off)
.v Current vertical line spacing

A short script to list default values is shown in Listing 8.17, and Figure 8.23 shows the output.

Listing 8.17. troff source to identify register values.

.nf
The current font is \n(.f
The current point size is \n(.s
The line length is \n(.l
The page length is \n(.p
The page offset is \n(.o

Figure 8.23.
troff
output with register values.

These registers provide useful information; however, the real power of registers comes from the ability to define your own registers. They can be used to track headers, paragraph numbers, and section numbers. The .nr request initializes and modifies user-specified registers. It takes two or three arguments: the first is the register name, and the second is the register modification. When first created, a register is assigned the value of zero. A positive number is added to the value; a negative number is subtracted. An optional third argument sets a default increment and decrement value. The automatic increment can be used in escape sequences: \n+(xx adds the increment to register xx, and \n-(xx subtracts the decrement.

You set the appearance of the number by using the .af request. The first argument is the register, and the second is one of six formats: 1 is for an Arabic number sequence; 001 is for a zero-filled Arabic number sequence; i and I are for Times Roman numbers, upper- and lowercase; and a and A are for alphabetic sequences.

Last, the .rr request removes a number register. A limited number of registers is available, identified by the read-only register .R. You might need to remove registers if space becomes a problem.

Listing 8.18 illustrates the source of a macro that numbers sections of the Constitution. The output is shown in Figure 8.24. The section header macros are for Articles, sections, and paragraphs of the constitution. First, you define the aR number register to count the articles and set its display format to Times Roman numerals. You then define the AR macro. It centers a 16-point bold text, with the word Article and the number register. Note that you increment the number register every time you print the value. You also set the sE number register to zero, as an Arabic number. You then reset the point size and font. The SE macro is similar, printing the section and number, and setting pP to zero. The PP macro increments pP.

Listing 8.18. troff source using number registers.

.ce
Preamble
.sp
We, the people of the United States, in order
to form a more perfect Union, establish justice, insure
domestic tranquility, provide for the common defense, promote
the general welfare,
and secure the blessing of liberty to ourselves and our
posterity do ordain and establish this Constitution for the
United States of America.
.sp
.nr aR 0 1
.af aR I
.de AR
.ce
.ps 16
.ft B
Article \\n+(aR
.nr sE 0 1
.af sE 1
.ps 12
.ft P
..
.de SE
.sp
.ft B
\\s-2SECTION \\n+(sE:\\s+2
.ft P
.nr pP 0 1
.af pP 1
..
.de PP
.sp
.ft I
\\s-3Paragraph \\n+(pP:\\s+3
.ft P
..
.AR
.SE
Legislative powers; in whom vested:
.PP
All legislative powers herein granted shall be vested in a
Congress of the United States, which shall consist of a Senate
and a House of Representatives.
.SE
House of Representatives, how and by whom chosen, Qualifications
of a Representative. Representatives and direct taxes, how
apportioned. Enumeration. Vacancies to be filled. Power of
choosing officers and of impeachment.
.PP
The House of Representatives shall be composed of members chosen
every second year by the people of the several states, and the
electors in each State shall have the qualifications requisite
for electors of the most numerous branch of the State Legislature.
.PP
No person shall be a Representative who shall not have attained
to the age of twenty-five years, and been seven years a citizen
of the United States, and who shall not, when elected, be an
inhabitant of that State in which he shall be chosen.
.PP
Representatives and direct taxes shall be apportioned among the
several States which maybe included within this Union, according
to their respective numbers, which shall be determined by adding
to the whole number of free persons, including those bound for
service for a term of years, and excluding Indians not taxed,
three-fifths of all other persons. The actual enumeration shall
be made within three years after the first meeting of the
Congress of the United States, and within every subsequent term
of ten years, in such manner as they shall by law direct. The
number of Representatives shall not exceed one for every thirty
thousand, but each State shall have at least one Representative;
and until such enumeration shall be made, the State of New
Hampshire shall be entitled to choose three, Massachusetts eight,
Rhode Island and Providence Plantations one, Connecticut
five, New York six, New Jersey four, Pennsylvania eight,
Delaware one, Maryland six, Virginia ten, North Carolina five,
South Carolina five, and Georgia three.
.PP
When vacancies happen in the representation from any State, the
Executive Authority thereof shall issue writs of election to fill
such vacancies.
.PP
The House of Representatives shall choose their Speaker and other
officers; and shall have the sole power of impeachment.

Figure 8.24.
troff
output with number registers.

Traps and Diversions

Most of the time, troff requests execute where they are placed in your document. You can execute these requests in other ways, however; you can specify macros to be executed at any given physical position on a document. These macros are called traps, and they can be triggered by page position, diversions, and input line count. A common use for page traps is to place headers or footers on pages. You can use diversion traps to create footnotes in text or to create a reference list for the end of a chapter. Input line traps count the number of lines since the request. They are useful when macros are meant to be a single line.

You can use diversions to direct output to a macro, instead of to the page. The diversion requests are usually in macros, and traps must be set to produce the diversion output. You create diversions by using the .di request, the call followed by the name of the diversion macro. If no argument is present, the diversion ends, and output resumes on the page. You can add text to the diversion by using the .da request. You can also request diversions by page position by using .dt, followed by the position and diversion macro name.

Traps are set with the .wh request. This request is followed by a position and a macro name. If a macro was previously set at that position, then that trap is removed. If no macro is passed as an argument, then any traps at that position are removed. You can change the position of a macro trap by using the .ch request, followed by the macro name and position. If a position is missing, the macro is removed. Input traps are set with the .it request, followed by a text position and macro name. Finally, you can set a trailing macro by using .em, which sets a macro to be run at the end of input.

The use of diversions and traps is illustrated in Chapter 10, "Writing Your Own Macros."

Tabs, Character Conversions, and Controls

In troff, you can set tabs and tab spacing. This way, you can create simple tables by lining up columns and using tabs. The .ta request sets the tab stops, and if a stop value is preceded by a +, then the stop is relative to the previous tab stop. You can specify the tab repetition character (the character that fills the space between text and tab stops) by using the .tc request. The nature of the tab stop can also be specified right after the tab stop distance. The text left-adjusts within the tab space by default. To center the text, use a C after the distance (no space), and use an R to right-adjust.

A simple table is illustrated in Listing 8.19, and the output is shown in Figure 8.25.

Listing 8.19. Formatting a table using tabs.

.nf
.ta 3i 4.5i
Name           Birthday  Telephone

John Smith     1/1/70    (410) 555-1111
Dave Jones     2/2/63    (311) 800-0000
.tc -
Bob Williams   3/3/56    (999) 555-2222

Figure 8.25.
A formatted table with tabs.

Some characters are considered control characters. They are the . used to signal a troff request, \ to indicate an inline escape, and ' to indicate a breakless command. You can reset the escape character by using the .ec request and turn it off by using the .eo request. .ec takes an argument, which is the new escape character. If no argument is present, it returns to the default. The .cc request changes the basic control character, ., to whatever is specified. This capability is particularly useful if you want to show a sample of troff input in a document, as shown in the source in Listing 8.20 and the output in Figure 8.26. Finally, .c2 changes the no-break control character from ' to the specified argument.

You also can invoke underlining in nroff and italics in troff by using the .ul and .cu requests. These requests turn on underline mode. In troff, the two requests have an identical effect; in nroff, .cu is for continuous underlining, and .ul underlines characters. The underlining font can be changed with the .uf request.

Character translations are also possible with troff requests in a document. The .tr request is analogous to the UNIX tr command. Instead of two groups of characters, though, the from-to pairs of characters are side by side in a single character string argument. This use is also illustrated in Listing 8.20 and Figure 8.26.

Listing 8.20. troff source illustrating character translations.

.nf
A sample of troff input:
.sp
.cc ,
.de PP
.br
.sp
.it +0.5i
..
,sp
,cc
And another sample:
.tr ,.
.sp
,de PP
,br
,sp
,it +0.5i
,,

Figure 8.26.
troff
output with character translations.

You can make input transparent to troff by prepending the input line with \!. You can do so to pass information to a post-processor. You can also embed comments in the troff source document by using \. It must come after the requests. It can appear at the start of a line if prepended with the control character.

Local Motions

Besides the .sp and related requests, you can use inline techniques to move the current output location in troff. These techniques, called local motions, can be vertical or horizontal.

The four types of vertical motions are all inline escapes. The first, \r, moves up a single line. You use \d to move down half a line for subscripts, and you use \u to move up half a line for superscripts. Finally, you use \v'N' to make a local motion of vertical distance N. A negative number moves up the page, and a positive number moves down the page. You cannot leave the page with a local motion. An example is shown in Listing 8.21, with output in Figure 8.27.

Listing 8.21. troff source with local motions.

Jan 26\u\s-2th\s+2\d is a sample.
.sp 2
We can move up \r easily.
.sp 2
Here is some space \0\0\0for us.

Figure 8.27.
troff
output with local motions.

You can use five types of horizontal motions. Two simple space functions are \ , which is an unpadded space-sized space (as defined by .ss). The \0 request is a digit-sized space. \| produces one-sixth of a character width, and \^ produces one-twelfth. Finally, generic local motion is produced by \h'N'. The rules for vertical motions also apply to horizontal motions.

You can determine the width of a string by using the \w escape. The string follows in single quotation marks. You can use this width in local motions and for other situations in which you need space measures. Listing 8.22 illustrates how you can use this escape to place paragraph numbers outside the left margin of some text.

You can also mark the horizontal space by using the \k request. Listing 8.22 also shows a primitive use of this request to embolden a word, and Figure 8.28 shows the output.

Listing 8.22. troff source with width.

.sp 0.5i
.in 1i
.ti -\w'1.\0'u
1.\0This is a paragraph with a number indented out the
\kxleft\h'|\nxu+2u'left margin. We continue with the text to prove
the indent.

Figure 8.28.
troff output with local motions and width calculations.

Overstrikes, Lines, and Arcs

Characters can be overstruck with the \o escape. Up to nine characters can be overstruck, each appearing in the string following the escape.

You can draw both vertical and horizontal lines in troff. You do so by using escape sequences \l, \L, and \D. The first draws a line of length specified in quotation marks after the escape. You can use an optional character after the length, and it is used instead of the line. The second escape draws a horizontal line. The \D escape is the drawing escape, and it draws lines, circles, ellipses, and arcs. The specific format is the first character, followed by one to four arguments:

A line is drawn with two arguments, and the line is drawn from the present location to the specified location. The first character argument is l.

A circle of a fixed diameter is drawn with c. The single argument is the diameter.

An ellipse is drawn with e, and the two arguments are the two diameters of the ellipse.

An arc is drawn with a. This escape has four arguments, in two pairs. The arc is drawn from the present position to the first argument, assuming that the second argument is the center of the circle.

A spline can be drawn with the character ~. This escape can take an unlimited group of pairings, drawing the spline from the current position through the pairs of points.

Because the escapes are difficult to use, the pic preprocessor is often used. pic generates the escape sequences based on a language of primitives. The grap, tbl, and eqn/neqn preprocessors also generate these escape sequences to create graphs, tables, and mathematical equations respectively. The preprocessors are described in Chapter 11, "Tools for Writers."

Conditional Text

Like any programming language, troff and nroff provide for a conditional execution of requests. The if request has two forms: .if followed by a condition and then requests; and an if-else construct, .ie and .el. .if has six conditional formats, and there is a format for grouping requests after an if: \{-requests-\}.

The six conditional forms are as follow:

.if c

.if !c

.if N

.if !N

.if 'string1'string2'

.if !'string1'string2'

In each of the six conditional forms, the ! represents the negation of the basic form. In the first two cases, c represents one of four special condition flags: o for an odd-numbered page, e for an even-numbered page, t for troff, and n for nroff. The middle two cases are for a numerical value N. The third case is for N>0, and the fourth case is for N<=0. In the last two cases, the strings are compared: if they are identical, the fifth is true; if not, the sixth is true.

if requests are rarely included in a normal document but are essential tools of macro writers. Macro writing is explored in greater depth in Chapter 10. Sometimes, however you might use the conditional. The source in Listing 8.23 and the output in Figure 8.29 show a simple case.

Listing 8.23. troff source with conditional input.

This text is formatted with the
.if n nroff
.if t troff
text processor.

Figure 8.29.
troff conditional output.

File Switching and Environments

These text processors also enable you to change input files and to modify output files. You can modify input in three ways:

You can request input by using the .rd request. A prompt can be provided as an argument, and the input is read from the terminal until two consecutive newlines are input. This approach is often used for insertion into form-letter-type documents.

An entire file can be interpreted with the .so command. If you create your own macro set, you might want to keep it in a separate file and include that file in subsequent documentation using this request. After the file has been read and interpreted, the text processor continues to read from the current file. This approach is also useful for embedding standard text, like a company's address.

The .nx request is similar to the .so request, except that when the file is completed, the text processor is considered to have finished its input.

An example of these three requests is shown in Listing 8.24. Listing 8.25 shows the contents of the header file, which defines a few macros. Listing 8.26 shows the terminal session.

Listing 8.24. troff source with file requests.

.so headers
.in 3i
.nf
1 Main Street
Myhometown, ST  98765
\n(mo/\n(dy/\n(yr
.sp 2
.in 0
.rd Please_enter_the_company_address
.sp
Dear Sir,
.PP
I read your add in the \fISan Jose Mercury News\fP advertising
positions with
.rd Please_enter_the_company_name
for software engineers. I'd like to express my interest in
a position. My resume is enclosed.
.sp
.in 3i
Yours sincerely,
.sp 3
Joe Smith
.in 0
.bp
.nx resume

Listing 8.25. Contents of the header file.

.de PP
.sp
.ti +0.5i
.fi
.ad b
..

Listing 8.26. Terminal session with terminal input.

$ troff -t fig21.58src
Please_enter_the_company_address:The Fixture Company
1001 Main Street
Anytown, USA  77777

Please_enter_the_company_name:The Fixture Company

$

Note that the .rd request needs the underscores between words. The space would normally end the argument, even with surrounding double quotation marks. Also, note that the text read in is processed based on the fill and adjustment settings.

A fourth type of file input is .cf. It copies a file directly onto the output, without interpolation.

Output from nroff and troff can be piped automatically through a program. The .pi request must be placed before any output is generated, and it can receive no arguments.

The current settings for troff are considered the troff environment. These settings include indentation, page length, line length, fonts, and other values that describe the page. Sometimes, you might need to save this environment. Three environments are allowed, and you can set the specific environment by using the .ev request. The environments are numbered 0, 1, and 2. Environments are usually included in macro calls that include diversions, such as for footnotes.

Two other controls are for aborts and exits. The .ex request terminates input processing as if the file were complete. This request is often used for debugging macros. The .ab request aborts all processing. Any arguments are printed on the diagnostic output, usually the terminal, and the program exits without terminal processing.

A last control is for system calls. The .sy request executes a UNIX command. The output is not captured anywhere, and there is no input.

Flotsam and Jetsam

A few requests have not been covered previously in this chapter because they do not conveniently fit into any of the other categories. They include hyphenation, three-part titles, and line numbering.

Four requests affect word hyphenation. The .nh request turns off all hyphenation, except for input with hyphens, such as sister-in-law. The .hy request provides a greater control over hyphenation. It accepts a numeric argument. If 0, hyphenation is turned off. If 2, lines that will trigger a trap are not hyphenated. If 4, the first two characters of a word are not split off, and if 8, the last two are not split off. You can add the values to create a single hyphenation request. The .hw request enables you to specify hyphenation points within words by using an embedded minus sign. An example might be .hw fish-head. The buffer for these words is only 128 characters long.

Lastly, you can specify word hyphenation by using an embedded character with a word. By default, this character is \%, although you can change it by using the .hc request.

You can specify a three-part title by using the .tl request. It takes three strings as arguments, separated by a single quotation mark and surrounded by single quotation marks, as follows: .tl 'left'center'right'. Any string can be empty. The title length is set with .lt and is separate from the .ll request. You can change the page character, initially %, by using .pc.

To number output lines, you can use the .nm request. It takes up to four arguments: a start number, a multiplier, a spacing value, and an indent value. If a multiplier is present, only those lines that are even multiples have numbers attached. You use the .nn request to ignore a number of lines for line numbering. These requests are useful for preparing code segments, legal documents, and literary material to make referencing specific lines easier.

You can specify a margin character for the right margin using the .mc request. It takes two arguments: the margin character and a distance to the right for the character. You often use it to highlight changed sections of text between document revisions.

You can use the .tm request to print a line to the invoking terminal.

The .ig request ignores all subsequent lines until the terminating request is issued, usually ...

The .pm request prints all the macros defined and their associated sizes. The sizes are in 128-character blocks.

The .fl request flushes the output buffer.

The .lf request sets the current line number and filename.

You can change character heights in troff by using the \H'n' inline request. Doing so can result in a disproportionate font. The value n is the point size height of the text.

Also illustrated is the ability to put the text at a slant. To do so, you use the \S'n' request. The value n is the degree of slant.

Using nroff/troff to Format Program Output

One of the banes of most programmers' existence is generating text that will be sent to customers outside an organization. Because the material will be seen by the general public, even if a limited subset, it is very important that the text looks good. Writing code that handles formatting, centering, page breaks, headers, and bolding (especially if different printers might be used) is a lot of work and requires much work to debug.

Instead of worrying about the small details, you can take advantage of nroff/troff to do the formatting work. You just create a file with the proper nroff/troff commands and let the tool do the hard work.

Figure 8.30 shows the final result of using troff to format program output. Listing 8.27 shows an example program written in the C language that lets nroff/troff handle the text formatting. Listing 8.28 shows the output of this program. Note that the C language uses the backslash character as its own escape sequence; as a result, any time one is needed in the output, two must appear in the printf statement. The single quotation mark also has special meaning to the C language and must be escaped to appear properly in the output.

Figure 8.30.
Output from C program processed by troff.

Listing 8.27. C program using nroff/troff to format output.

#include <stdio.h>
#include <stdlib.h>

main ( )
{
   int index;
   char *sayings[6] = {
  "To Err is human. To really foul things up takes a COMPUTER.",
"Rome wasn't built in a day, why should this system be?",
  "Do unto others and run!",
  "Do unto others, then split!",
  "Oh well, I can't think of any saying now.",
  "It's later than you think." };

   printf("\\\" This file produced by a program!\n");
   printf(".ad l \n");
   printf(".nf \n");
   printf(".pl 9i \n");
   printf(".ll 6.5i \n");
   printf(".sp 20 \n");
   printf(".ce 2 \n");
   printf("Sayings\n as of \\n(mo/\\n(dy/\\n(yr \n");
   printf(".bp 1 \n");
   printf(".tl \'\\d\\dSayings\'\' \\n(mo/\\n(dy/\\n(yr \' \n");
   printf(".sp 1 \n");
   printf(".ce 1 \n");
   printf("\\fB First Set of Sayings \\fP \n");
   for (index = 0; index < 6; index++)
   {
      printf(".sp 1 \n");
      printf("%s\n", sayings[index]);
   }
}

Listing 8.28. Output of C program.

\" This file produced by a program!
.ad l
.nf
.pl 9i
.ll 6.5i
.sp 20
.ce 2
Sayings
 as of \n(mo/\n(dy/\n(yr
.bp 1
.tl '\d\dSayings'' \n(mo/\n(dy/\n(yr '
.sp 1
.ce 1
\fB First Set of Sayings \fP
.sp 1
To Err is human. To really foul things up takes a COMPUTER.
.sp 1
Rome wasn't built in a day, why should this system be?
.sp 1
Do unto others and run!
.sp 1
Do unto others, then split!
.sp 1
Oh well, I can't think of any saying now.
.sp 1
It's later than you think.

Because of odd behavior by my printer, I had to force the title line down one full em line (one full line in nroff) by using the \d escape sequence; otherwise, the top of the title would be cut off.

You can use the same technique in programs that create form letters or print labels. Due to the complexity involved, standard reports (detail or summary data) probably are not good candidates for this type of processing.

Quick Reference of nroff/troff Requests

Table 8.6 presents all the nroff/troff requests along with their syntax. Arguments not in brackets are arguments that you must specify for the request. Arguments in brackets are optional arguments that you can specify for the request. Italicized arguments indicate that you need to substitute something specific; for example, .so file means that you need to provide a real filename as an argument to the .so request.

Table 8.6. nroff/troff requests.

Request Description
.ab [text] Abort and print message
.ad [c] Adjust text margins
.af r c Assign format c to register r
.am xx yy Append following commands to macro xx, terminated with yy
.as xx string Append string to defined string xx
.bd f n Embolden font f with n overstrikes
.bd s f n Embolden special font when current font is f, with n overstrikes
.bp [n] Begin a page and set page number to n
.br Break--stop filling text
.c2 c Set no break control character
.cc c Set control character
.ce [n] Center text
.cf filename Copy file
.ch xx [n] Change trap position for macro xx to n
.cs f n m Use constant character spacing for font f
.cu [n] Constant underlining
.da [xx] Direct and append text to macro xx
.de xx [yy] Define macro
.di [xx] Direct text to macro xx
.ds xx string Define string
.dt n xx Install division trap
.ec [c] Set escape character
.el action Else portion of if-else
.em xx Set macro to run at the end of the document
.eo Turn off inline escapes
.ev [n] Change environment to n or restore environment
.ex Exit formatter
.fc a b Set field character and padding character
.fi Fill text
.fl Flush output buffer
.fp n f Change font positions
.ft f Change font in output
.hc [c] Set hyphenation character
.hw words Set hyphenation exception list
.hy n Set hyphenation mode
.ie c action If else
.if c action If c is true, perform action
.if !c action If condition is false, perform action
.if n action If n>0, perform action
.if !n action If n>=0, perform action
.if !'string1'string2' action If strings are equal, perform action
.if !'string1'string2' action If strings are different, perform action
.ig yy Ignore subsequent text to yy
.in +/-[n] Set indent
.it n xx Set input trap
.lc c Set leader repetition character
.lg n Set ligature mode
.ll +/-[n] Set line length
.ls n Set line spacing
.lt n Set title length
.mc [c] [m] Set margin character
.mk [r] Mark vertical place in register
.na Do not adjust text
.ne n If n lines do not remain on the page, get a new page
.nf Turn off filling
.nh Turn off hyphenation
.nm [n m s i] Number output lines
.nn n Disable numbering output but track line numbers
.nr r n [m] Assign number register
.ns Turn on no-space mode
.nx file Go to the next file
.os Output saved space
.pc c Set page number character
.pi command Pipe output of troff to command
.pl +/-[n] Set page length
.pm Print names and sizes of macros
.pn +/-[n] Set next page number
.po +/-[n] Set page offset
.ps n Set font point size
.rd [prompt] Read input from #y
.rm xx Remove macro or string
.rn xx yy Rename macro, request, or string
.rr r Remove register
.rs xx yy Restore spacing
.rt +/-[n] Return back to marked place
.so file Include file
.sp n Leave n blank lines
.ss n Set character size
.sv n Save n lines of space
.sy command [arguments] Execute command
.ta n[t] m[t] Set tab stops
.tc c Set tab character
.ti +/-[n] Set temporary indent
.tl 'l'c'r' Indicate three-part title
.tm message Display message on terminal
.tr ab Translate characters
.uf f Set underline font
.ul [n] Underline lines
.vs [n] Set vertical space
.wh n xx Set trap locations

Options for the nroff and troff Commands

The options shown in Table 8.7 are available with current versions of nroff and (device-independent) troff.

Table 8.7. nroff/troff options.

Option Effect
- Accepts input from stdin (not required when piping output of another program into nroff/troff).
-F directory (troff only) Uses fonts in directory/devNAME instead of the default directory (/usr/lib/font/devNAME or /usr/ucblib/doctools/font/devNAME).
-a (troff only) Produces an ASCII approximation for viewing on text-only terminal screens.
-e (nroff only) Produces equally spaced words in adjusted lines instead of using multiples of space character.
-h (nroff only) Uses output tabs (instead of spaces) during horizontal spacing to spread output and reduce output character count; tab settings are assumed to be every eight characters.
-i Reads from standard input after files are exhausted.
-mname Prepends the macro file /usr/lib/tmac.name to the input file--in other words, uses the macros in filename; name can be e, m, ptx, an, s, or v.
-nN Numbers the first output page N.
-olist Prints only the pages specified in list. Use commas to separate page numbers; use hyphens (-) to indicate page range. For example, -12 prints all the pages up to and including page 12; 12- prints page 12 and all subsequent pages in the file. (Example: -01,3,7,12-20,35,40-)
-q Invokes the simultaneous input/output of the .rd primitive; that is, the file to be processed contains at least one .rd primitive.
-raN Sets register a to value N; the register name can be no more than one character.
-sN (nroff only) Stops printing every N pages (default is N=1); this way, you can add or change paper. To resume printing, use a linefeed (a newline also works if no pipeline is involved).
-Tname (troff only) Prepares output for typesetter/printer specified as name; the default is post but may include devices such as hplj, aps (typesetter), graphic display terminals (X100), and psc (PostScript).
-Ttype (nroff only) Prepares output for the terminal (printer) specified as type. The following types should be known to any system:

2631 Hewlett-Packard 2631 printer in regular mode
2631-c Hewlett-Packard 2631 printer in compressed mode
2631-e Hewlett-Packard 2631 printer in expanded mode
300 DASI-300 printer
300-12 DASI-300 terminal set to 12 pitch (12 cpi)
300s DASI 300s printer
300s-12 DASI-300s printer set to 12 pitch
37 Teletype Model 37 terminal (default)
382 DTC-382
4000a Trendata 4000a terminal
450 DASI-450 (Diablo Hyterm) printer
450-12 DASI-450 terminal set to 12 pitch
832 Anderson Jacobson 832 terminal
8510 C.Itoh printer
lp Generic name for printers that can underline and tab; all text using reverse linefeeds (such as files having tables) sent to lp must be processed with col.
tn300 GE Terminet 300 terminal
-uN (nroff only) Sets the emboldening factor (number of character overstrikes) to N, or to 0 if N is not specified.
-z Prints only messages generated by the .tm primitive; useful for debugging or, if you're using .tm, to generate a list of some kind.

Post-Processing troff Output

With the device-independent version of troff (ditroff), the output is in a device-independent form, hence the name. To print the output, you must convert it from the device-independent form to one that the specific printer can handle. As I mentioned in the "Printing troff Files" section of this chapter, the hplj command performs this translation for Hewlett-Packard LaserJet Series printers. If you want troff output to go to a PostScript printer, you can use the psedit command; psc is a synonym for psedit. To view troff output on an X station, you can use the xpreview command. xpreview can also be used to view files formatted with psc/psedit or any other PostScript format file.

The following commands send the output of troff to a Hewlett-Packard LaserJet Series printer, PostScript printers, and to the screen of an X station:

troff -Thplj filename | hplj | lpr -Phpprinter
troff -Tpsc filename | psc | lpr -Ppsprinter
troff -Tpsc filename | psedit | lpr -Ppsprinter
troff -Tpsc filename | xpreview
troff -Tx100 filename | xpreview

You also can use these commands with files previously created with troff as follows:

hplj filename | lpr -Phpprinter
psc filename | lpr -Ppsprinter
psedit filename | lpr -Ppsprinter
xpreview filename

The options shown in Table 8.8 are available with many versions of hplj, psc/psedit, and xpreview.

Table 8.8. hplj, psc/psedit, and xpreview options.

Option Effect
- Accepts input from stdin (not required when piping output of another program into hplj).
-F directory (hpjl only) Uses fonts in directory/devhplj instead of the default directory (/usr/lib/font/devhplj or /usr/ucblib/doctools/font/devhplj).
-quietly (hpjl and psc/psedit only) Suppresses non-fatal error messages.
-Mmedia (psc/psedit only) Specifies print media (paper type). The default is letter; most installations also support legal.
-ppsprolog (psc/psedit only) Specifies PostScript prologue (heading prefix) instead of using the default.
-olist (psc/psedit only) Prints only the pages specified in list. Use commas to separate page numbers; use hyphens (-) to indicate page range. For example, -12 prints all the pages up to and including page 12; 12- prints page 12 and all subsequent pages in the file. (Example: -01,3,7,12-20,35,40-)
-page Number (xpreview only) Specifies the first page of the document to be displayed.
-help (xpreview only) Displays command-line options.

Summary

The essentials of nroff/troff allow you to format documents. After you format the document, you must print or view it for it to be of any real use. Although many tools are available to format text in the current data processing environment including PC-based WYSIWYG word processors, nroff and troff still have value, especially for extremely large documents, program output, and the system manual pages. If you use nroff/troff, you really become productive when you use one of the standard macro packages such as man, ms, or me, which are described in the next chapter.

TOCBACKFORWARDHOME


©Copyright, Macmillan Computer Publishing. All rights reserved.