aboutsummaryrefslogtreecommitdiff
path: root/pkg/system/help/manout.x
blob: b81abc8b84c1d7b7af1fe8e3fbf4e7852fe2afbb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<chars.h>
include	<ctype.h>
include	"help.h"

.help man_output, man_close
.nf ___________________________________________________________________________
Process a stream of output lines containing forms control codes.  This mode is
used when manual page format is desired.  Input is a sequence of manual pages.
A manual page consists of a formfeed, a two line page header, and then an
arbitrary number of lines of text.  Pages are broken every H_NLPP lines,
the page header is printed at the top of each page, and the page number is
printed at the bottom of each page.  The following special directives may
be inserted in the text as control character forms codes; the forms code must
be the first character in a line but may be followed by text.

	FC_BREAKPAGE		Start a new page, unless already at the
				top of a page.

	FC_TESTPAGE n		Test if there are at least N (binary code)
				lines left on the page.  If no, break the
				page before more text is output.

	FC_STARTKEEP		Start spooling lines into an internal buffer.
				Try to output the keep block all on one page.

	FC_ENDKEEP		Stop spooling and output the keep block.

MAN_CLOSE should be called at program termination to return buffer space and
reinit variables.
.endhelp ______________________________________________________________________

define	LEN_HEADER		2
define	LEN_FOOTER		3
define	LEN_KEEP		1024
define	SZ_PAGELABEL		6
define	SZ_HEADER_GAP		2

define	IN_HEADER		1
define	IN_TEXT			2
define	IN_KEEP			3
define	FLUSH_KEEP		4


# MAN_OUTPUT -- Output a line, optionally preceded by one or more forms control
# characters.  Start a new manual page, save lines in header, save lines in keep
# buffer, or write line to output.

procedure man_output (fd, lbuf, nlines_per_page, lmargin, rmargin)

int	fd			# output file
char	lbuf[ARB]		# next output line
int	nlines_per_page
int	lmargin, rmargin

char	end_keep_chars[3]
int	ip, mode, max_lineno, i

int	nlines_in_keep, nlines_in_header, init
int	lineno, pageno, center_col, nlpp
pointer	header_lines[LEN_HEADER], keep_lines[LEN_KEEP]
common	/hlpman/ lineno, pageno, nlpp, center_col, init,
	nlines_in_header, nlines_in_keep, header_lines, keep_lines

int	stridx()
pointer	man_putstr()
data	end_keep_chars /FC_STARTKEEP, FC_BREAKPAGE, '\f', EOS/

begin
	if (init == YES) {
	    # Initialize internal variables.
	    lineno = 0
	    pageno = 0
	    mode = IN_TEXT
	    nlines_in_header = 0
	    nlines_in_keep = 0
	    nlpp = nlines_per_page
	    max_lineno = max(1, min(LEN_KEEP, nlpp - LEN_FOOTER))
	    center_col = (lmargin + rmargin) / 2
	    init = NO
	}

	for (ip=1;  lbuf[ip] != EOS;  ) {
	    switch (mode) {

	    case IN_HEADER:
		# Just started a new manual page; still accumulating header
		# lines.  Forms control chars not recognized in header area.
		# Output header to start new page as soon as we have all the
		# lines.

		nlines_in_header = nlines_in_header + 1
		header_lines[nlines_in_header] = man_putstr (lbuf[ip])
		if (nlines_in_header == LEN_HEADER) {
		    mode = IN_TEXT
		    call man_breakpage (fd, header_lines, nlines_in_header,
			lineno, pageno, nlpp, center_col)
		    pageno = 1
		}
		break

	    case IN_KEEP:
		# Any forms control character in a keep ends the keep, in case
		# the KE is missing.  Don't bump input pointer unless sentinel
		# is ENDKEEP, else forms control character will be skipped.

		if (lbuf[ip] == FC_ENDKEEP) {
		    mode = FLUSH_KEEP
		    ip = ip + 1
		} else if (stridx (lbuf[ip], end_keep_chars) > 0) {
		    mode = FLUSH_KEEP
		} else if (lineno + nlines_in_keep > max_lineno) {
		    mode = FLUSH_KEEP
		} else {
		    # Put line in keep buffer.
		    nlines_in_keep = nlines_in_keep + 1
		    keep_lines[nlines_in_keep] = man_putstr (lbuf[ip])
		    break
		}

	    case FLUSH_KEEP:
		# Break page and output header if insufficient room left on
		# page.
		if (lineno + nlines_in_keep > max_lineno)
		    call man_breakpage (fd, header_lines, nlines_in_header,
			lineno, pageno, nlpp, center_col)

		# Output contents of keep buffer and return buffer space.
		for (i=1;  i <= nlines_in_keep;  i=i+1) {
		    call putline (fd, Memc[keep_lines[i]])
		    call mfree (keep_lines[i], TY_CHAR)
		    lineno = lineno + 1
		}
		nlines_in_keep = 0
		mode = IN_TEXT

	    case IN_TEXT:
		# Not in any special mode.  Check for forms chars and loop if
		# one is found.  Otherwise output line and bump line pointer.
		# Break page when it fills.

		switch (lbuf[ip]) {
		case FC_BREAKPAGE:
		    call man_breakpage (fd, header_lines, nlines_in_header,
			lineno, pageno, nlpp, center_col)
		    ip = ip + 1

		case FC_TESTPAGE:
		    # The first char following the testpage forms control char
		    # is the number of lines to test for, in binary.

		    if (lineno + lbuf[ip+1] > max_lineno)
			call man_breakpage (fd, header_lines, nlines_in_header,
			    lineno, pageno, nlpp, center_col)
		    ip = ip + 2

		case FC_STARTKEEP:
		    mode = IN_KEEP
		    ip = ip + 1
		case FC_ENDKEEP:
		    ip = ip + 1

		case '\f':
		    # Start accumulating new header.  Page cannot be broken
		    # until we have the header.

		    for (i=1;  i <= nlines_in_header;  i=i+1)
			call mfree (header_lines[i], TY_CHAR)
		    nlines_in_header = 0
		    mode = IN_HEADER
		    ip = ip + 1

		default:
		    # This is the case that gets called most often; output an
		    # ordinary line, not in any special mode.  Eat blank lines
		    # at top of page.

		    if (lineno <= nlines_in_header + SZ_HEADER_GAP + 1) {
			for (i=ip;  IS_WHITE (lbuf[i]);  i=i+1)
			    ;
			if (lbuf[i] == '\n' || lbuf[i] == EOS)
			    break
		    }
		    call putline (fd, lbuf[ip])
		    lineno = lineno + 1
		    if (lineno > max_lineno)
			call man_breakpage (fd, header_lines, nlines_in_header,
			    lineno, pageno, nlpp, center_col)
		    break
		}
	    }
	}	   
end


# MAN_INIT -- Called to initialize the manpage internal data structures.

procedure man_init()

int	i
bool	first_time
data	first_time /true/

int	nlines_in_keep, nlines_in_header, init
int	lineno, pageno, center_col, nlpp
pointer	header_lines[LEN_HEADER], keep_lines[LEN_KEEP]
common	/hlpman/ lineno, pageno, nlpp, center_col, init,
	nlines_in_header, nlines_in_keep, header_lines, keep_lines

begin
	# Clean up in the event of an interrupt.
	if (!first_time) {
	    for (i=1;  i <= nlines_in_header;  i=i+1)
		call mfree (header_lines[i], TY_CHAR)
	    for (i=1;  i <= nlines_in_keep;  i=i+1)
		call mfree (keep_lines[i], TY_CHAR)
	}

	init = YES
	first_time = false
end


# MAN_CLOSE -- Called at program termination to write the page number at the
# bottom of the last manual page.

procedure man_close (fd)

int	fd
int	nlines_in_keep, nlines_in_header, i
int	lineno, pageno, center_col, nlpp, init
pointer	header_lines[LEN_HEADER], keep_lines[LEN_KEEP]
common	/hlpman/ lineno, pageno, nlpp, center_col, init,
	nlines_in_header, nlines_in_keep, header_lines, keep_lines

begin
	if (init == YES)
	    return

	# Trash any data in keep buffer if missing the KE by the time we are
	# called (at program termination).

	call man_breakpage (fd, header_lines, 0, lineno, pageno, nlpp,
	    center_col)

	for (i=1;  i <= nlines_in_header;  i=i+1)
	    call mfree (header_lines[i], TY_CHAR)
	for (i=1;  i <= nlines_in_keep;  i=i+1)
	    call mfree (keep_lines[i], TY_CHAR)

	nlines_in_header = 0
	nlines_in_keep = 0
	init = YES
end


# MAN_BREAKPAGE -- Advance to bottom of page, print page number, bump page
# number, init line counter, formfeed, output page header of new page.

procedure man_breakpage (fd, header_lines, nlines_in_header, lineno, pageno,
			 nlines_per_page, center_col)
int	fd
pointer	header_lines[ARB]
int	nlines_in_header
int	lineno, pageno
int	nlines_per_page
int	center_col

char	pagelabel[SZ_PAGELABEL]
int	i, destcol
int	strlen()

begin
	# Output page footer if there is anything on the page and if there
	# was a page header.

	if (lineno > 0 && nlines_in_header > 0) {
	    while (lineno <= nlines_per_page - 1) {
		call putline (fd, "\n")
		lineno = lineno + 1
	    }

	    call sprintf (pagelabel, SZ_PAGELABEL, "-%d-")
		call pargi (pageno)

	    destcol = max (1, center_col - strlen (pagelabel) / 2)
	    for (i=1;  i < destcol;  i=i+1)
		call putci (fd, ' ')
	    call putline (fd, pagelabel)
	    call putci (fd, '\n')
	}

	# Break page and output page header if there are any header lines.
	# Leave two blank lines between header and first line of text.

	if (nlines_in_header > 0) {
	    if (pageno > 0)
		call putci (fd, '\f')
	    lineno = 1
	    pageno = pageno + 1

	    for (i=1;  i <= nlines_in_header;  i=i+1) {
		call putline (fd, Memc[header_lines[i]])
		lineno = lineno + 1
	    }
	    for (i=1;  i <= SZ_HEADER_GAP;  i=i+1) {
		call putline (fd, "\n")
		lineno = lineno + 1
	   }
	}
end


# MAN_PUTSTR -- Save a string on the heap and return a pointer to the string.

pointer procedure man_putstr (str)

char	str[ARB]
int	nchars
pointer	bp
int	strlen()

begin
	nchars = strlen (str)
	call malloc (bp, nchars, TY_CHAR)
	call strcpy (str, Memc[bp], nchars)

	return (bp)
end