mandoc 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/COPYING +674 -0
- data/README.md +117 -0
- data/ext/mandoc/extconf.rb +59 -0
- data/ext/mandoc/rb_mandoc.c +548 -0
- data/ext/mandoc/rb_mandoc.h +22 -0
- data/lib/mandoc/version.rb +19 -0
- data/lib/mandoc.rb +26 -0
- data/mandoc-1.14.6/LICENSE +55 -0
- data/mandoc-1.14.6/arch.c +54 -0
- data/mandoc-1.14.6/att.c +49 -0
- data/mandoc-1.14.6/catman.c +260 -0
- data/mandoc-1.14.6/cgi.c +1279 -0
- data/mandoc-1.14.6/chars.c +507 -0
- data/mandoc-1.14.6/compat_err.c +103 -0
- data/mandoc-1.14.6/compat_fts.c +696 -0
- data/mandoc-1.14.6/compat_fts.h +106 -0
- data/mandoc-1.14.6/compat_getline.c +59 -0
- data/mandoc-1.14.6/compat_getsubopt.c +87 -0
- data/mandoc-1.14.6/compat_isblank.c +23 -0
- data/mandoc-1.14.6/compat_mkdtemp.c +50 -0
- data/mandoc-1.14.6/compat_mkstemps.c +63 -0
- data/mandoc-1.14.6/compat_ohash.c +330 -0
- data/mandoc-1.14.6/compat_ohash.h +72 -0
- data/mandoc-1.14.6/compat_progname.c +31 -0
- data/mandoc-1.14.6/compat_reallocarray.c +40 -0
- data/mandoc-1.14.6/compat_recallocarray.c +99 -0
- data/mandoc-1.14.6/compat_strcasestr.c +64 -0
- data/mandoc-1.14.6/compat_stringlist.c +135 -0
- data/mandoc-1.14.6/compat_stringlist.h +48 -0
- data/mandoc-1.14.6/compat_strlcat.c +57 -0
- data/mandoc-1.14.6/compat_strlcpy.c +52 -0
- data/mandoc-1.14.6/compat_strndup.c +42 -0
- data/mandoc-1.14.6/compat_strsep.c +70 -0
- data/mandoc-1.14.6/compat_strtonum.c +67 -0
- data/mandoc-1.14.6/compat_vasprintf.c +47 -0
- data/mandoc-1.14.6/config.h +52 -0
- data/mandoc-1.14.6/dba.c +508 -0
- data/mandoc-1.14.6/dba.h +50 -0
- data/mandoc-1.14.6/dba_array.c +190 -0
- data/mandoc-1.14.6/dba_array.h +47 -0
- data/mandoc-1.14.6/dba_read.c +74 -0
- data/mandoc-1.14.6/dba_write.c +127 -0
- data/mandoc-1.14.6/dba_write.h +30 -0
- data/mandoc-1.14.6/dbm.c +480 -0
- data/mandoc-1.14.6/dbm.h +68 -0
- data/mandoc-1.14.6/dbm_map.c +194 -0
- data/mandoc-1.14.6/dbm_map.h +29 -0
- data/mandoc-1.14.6/demandoc.c +260 -0
- data/mandoc-1.14.6/eqn.c +1132 -0
- data/mandoc-1.14.6/eqn.h +72 -0
- data/mandoc-1.14.6/eqn_html.c +246 -0
- data/mandoc-1.14.6/eqn_parse.h +48 -0
- data/mandoc-1.14.6/eqn_term.c +174 -0
- data/mandoc-1.14.6/html.c +1102 -0
- data/mandoc-1.14.6/html.h +142 -0
- data/mandoc-1.14.6/lib.c +35 -0
- data/mandoc-1.14.6/libman.h +42 -0
- data/mandoc-1.14.6/libmandoc.h +85 -0
- data/mandoc-1.14.6/libmdoc.h +87 -0
- data/mandoc-1.14.6/main.c +1375 -0
- data/mandoc-1.14.6/main.h +53 -0
- data/mandoc-1.14.6/man.c +345 -0
- data/mandoc-1.14.6/man.h +21 -0
- data/mandoc-1.14.6/man_html.c +640 -0
- data/mandoc-1.14.6/man_macro.c +470 -0
- data/mandoc-1.14.6/man_term.c +1143 -0
- data/mandoc-1.14.6/man_validate.c +660 -0
- data/mandoc-1.14.6/manconf.h +58 -0
- data/mandoc-1.14.6/mandoc.c +669 -0
- data/mandoc-1.14.6/mandoc.h +329 -0
- data/mandoc-1.14.6/mandoc_aux.c +118 -0
- data/mandoc-1.14.6/mandoc_aux.h +27 -0
- data/mandoc-1.14.6/mandoc_msg.c +375 -0
- data/mandoc-1.14.6/mandoc_ohash.c +65 -0
- data/mandoc-1.14.6/mandoc_ohash.h +23 -0
- data/mandoc-1.14.6/mandoc_parse.h +44 -0
- data/mandoc-1.14.6/mandoc_xr.c +123 -0
- data/mandoc-1.14.6/mandoc_xr.h +31 -0
- data/mandoc-1.14.6/mandocd.c +282 -0
- data/mandoc-1.14.6/mandocdb.c +2448 -0
- data/mandoc-1.14.6/manpath.c +363 -0
- data/mandoc-1.14.6/mansearch.c +851 -0
- data/mandoc-1.14.6/mansearch.h +118 -0
- data/mandoc-1.14.6/mdoc.c +433 -0
- data/mandoc-1.14.6/mdoc.h +158 -0
- data/mandoc-1.14.6/mdoc_argv.c +682 -0
- data/mandoc-1.14.6/mdoc_html.c +1762 -0
- data/mandoc-1.14.6/mdoc_macro.c +1600 -0
- data/mandoc-1.14.6/mdoc_man.c +1850 -0
- data/mandoc-1.14.6/mdoc_markdown.c +1610 -0
- data/mandoc-1.14.6/mdoc_state.c +256 -0
- data/mandoc-1.14.6/mdoc_term.c +1964 -0
- data/mandoc-1.14.6/mdoc_validate.c +3062 -0
- data/mandoc-1.14.6/msec.c +37 -0
- data/mandoc-1.14.6/out.c +544 -0
- data/mandoc-1.14.6/out.h +70 -0
- data/mandoc-1.14.6/preconv.c +179 -0
- data/mandoc-1.14.6/read.c +732 -0
- data/mandoc-1.14.6/roff.c +4390 -0
- data/mandoc-1.14.6/roff.h +561 -0
- data/mandoc-1.14.6/roff_html.c +119 -0
- data/mandoc-1.14.6/roff_int.h +94 -0
- data/mandoc-1.14.6/roff_term.c +266 -0
- data/mandoc-1.14.6/roff_validate.c +151 -0
- data/mandoc-1.14.6/soelim.c +182 -0
- data/mandoc-1.14.6/st.c +82 -0
- data/mandoc-1.14.6/tag.c +327 -0
- data/mandoc-1.14.6/tag.h +35 -0
- data/mandoc-1.14.6/tbl.c +183 -0
- data/mandoc-1.14.6/tbl.h +121 -0
- data/mandoc-1.14.6/tbl_data.c +323 -0
- data/mandoc-1.14.6/tbl_html.c +293 -0
- data/mandoc-1.14.6/tbl_int.h +47 -0
- data/mandoc-1.14.6/tbl_layout.c +376 -0
- data/mandoc-1.14.6/tbl_opts.c +173 -0
- data/mandoc-1.14.6/tbl_parse.h +30 -0
- data/mandoc-1.14.6/tbl_term.c +948 -0
- data/mandoc-1.14.6/term.c +1113 -0
- data/mandoc-1.14.6/term.h +158 -0
- data/mandoc-1.14.6/term_ascii.c +424 -0
- data/mandoc-1.14.6/term_ps.c +1362 -0
- data/mandoc-1.14.6/term_tab.c +130 -0
- data/mandoc-1.14.6/term_tag.c +227 -0
- data/mandoc-1.14.6/term_tag.h +34 -0
- data/mandoc-1.14.6/tree.c +536 -0
- metadata +170 -0
|
@@ -0,0 +1,1143 @@
|
|
|
1
|
+
/* $Id: man_term.c,v 1.236 2021/06/28 19:50:15 schwarze Exp $ */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2010-2015, 2017-2020 Ingo Schwarze <schwarze@openbsd.org>
|
|
4
|
+
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
5
|
+
*
|
|
6
|
+
* Permission to use, copy, modify, and distribute this software for any
|
|
7
|
+
* purpose with or without fee is hereby granted, provided that the above
|
|
8
|
+
* copyright notice and this permission notice appear in all copies.
|
|
9
|
+
*
|
|
10
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
|
11
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
12
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
|
13
|
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
14
|
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
15
|
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
16
|
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
17
|
+
*
|
|
18
|
+
* Plain text formatter for man(7), used by mandoc(1)
|
|
19
|
+
* for ASCII, UTF-8, PostScript, and PDF output.
|
|
20
|
+
*/
|
|
21
|
+
#include "config.h"
|
|
22
|
+
|
|
23
|
+
#include <sys/types.h>
|
|
24
|
+
|
|
25
|
+
#include <assert.h>
|
|
26
|
+
#include <ctype.h>
|
|
27
|
+
#include <limits.h>
|
|
28
|
+
#include <stdio.h>
|
|
29
|
+
#include <stdlib.h>
|
|
30
|
+
#include <string.h>
|
|
31
|
+
|
|
32
|
+
#include "mandoc_aux.h"
|
|
33
|
+
#include "mandoc.h"
|
|
34
|
+
#include "roff.h"
|
|
35
|
+
#include "man.h"
|
|
36
|
+
#include "out.h"
|
|
37
|
+
#include "term.h"
|
|
38
|
+
#include "term_tag.h"
|
|
39
|
+
#include "main.h"
|
|
40
|
+
|
|
41
|
+
#define MAXMARGINS 64 /* maximum number of indented scopes */
|
|
42
|
+
|
|
43
|
+
struct mtermp {
|
|
44
|
+
int lmargin[MAXMARGINS]; /* margins (incl. vis. page) */
|
|
45
|
+
int lmargincur; /* index of current margin */
|
|
46
|
+
int lmarginsz; /* actual number of nested margins */
|
|
47
|
+
size_t offset; /* default offset to visible page */
|
|
48
|
+
int pardist; /* vert. space before par., unit: [v] */
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
#define DECL_ARGS struct termp *p, \
|
|
52
|
+
struct mtermp *mt, \
|
|
53
|
+
struct roff_node *n, \
|
|
54
|
+
const struct roff_meta *meta
|
|
55
|
+
|
|
56
|
+
struct man_term_act {
|
|
57
|
+
int (*pre)(DECL_ARGS);
|
|
58
|
+
void (*post)(DECL_ARGS);
|
|
59
|
+
int flags;
|
|
60
|
+
#define MAN_NOTEXT (1 << 0) /* Never has text children. */
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
static void print_man_nodelist(DECL_ARGS);
|
|
64
|
+
static void print_man_node(DECL_ARGS);
|
|
65
|
+
static void print_man_head(struct termp *,
|
|
66
|
+
const struct roff_meta *);
|
|
67
|
+
static void print_man_foot(struct termp *,
|
|
68
|
+
const struct roff_meta *);
|
|
69
|
+
static void print_bvspace(struct termp *,
|
|
70
|
+
struct roff_node *, int);
|
|
71
|
+
|
|
72
|
+
static int pre_B(DECL_ARGS);
|
|
73
|
+
static int pre_DT(DECL_ARGS);
|
|
74
|
+
static int pre_HP(DECL_ARGS);
|
|
75
|
+
static int pre_I(DECL_ARGS);
|
|
76
|
+
static int pre_IP(DECL_ARGS);
|
|
77
|
+
static int pre_OP(DECL_ARGS);
|
|
78
|
+
static int pre_PD(DECL_ARGS);
|
|
79
|
+
static int pre_PP(DECL_ARGS);
|
|
80
|
+
static int pre_RS(DECL_ARGS);
|
|
81
|
+
static int pre_SH(DECL_ARGS);
|
|
82
|
+
static int pre_SS(DECL_ARGS);
|
|
83
|
+
static int pre_SY(DECL_ARGS);
|
|
84
|
+
static int pre_TP(DECL_ARGS);
|
|
85
|
+
static int pre_UR(DECL_ARGS);
|
|
86
|
+
static int pre_abort(DECL_ARGS);
|
|
87
|
+
static int pre_alternate(DECL_ARGS);
|
|
88
|
+
static int pre_ign(DECL_ARGS);
|
|
89
|
+
static int pre_in(DECL_ARGS);
|
|
90
|
+
static int pre_literal(DECL_ARGS);
|
|
91
|
+
|
|
92
|
+
static void post_IP(DECL_ARGS);
|
|
93
|
+
static void post_HP(DECL_ARGS);
|
|
94
|
+
static void post_RS(DECL_ARGS);
|
|
95
|
+
static void post_SH(DECL_ARGS);
|
|
96
|
+
static void post_SY(DECL_ARGS);
|
|
97
|
+
static void post_TP(DECL_ARGS);
|
|
98
|
+
static void post_UR(DECL_ARGS);
|
|
99
|
+
|
|
100
|
+
static const struct man_term_act man_term_acts[MAN_MAX - MAN_TH] = {
|
|
101
|
+
{ NULL, NULL, 0 }, /* TH */
|
|
102
|
+
{ pre_SH, post_SH, 0 }, /* SH */
|
|
103
|
+
{ pre_SS, post_SH, 0 }, /* SS */
|
|
104
|
+
{ pre_TP, post_TP, 0 }, /* TP */
|
|
105
|
+
{ pre_TP, post_TP, 0 }, /* TQ */
|
|
106
|
+
{ pre_abort, NULL, 0 }, /* LP */
|
|
107
|
+
{ pre_PP, NULL, 0 }, /* PP */
|
|
108
|
+
{ pre_abort, NULL, 0 }, /* P */
|
|
109
|
+
{ pre_IP, post_IP, 0 }, /* IP */
|
|
110
|
+
{ pre_HP, post_HP, 0 }, /* HP */
|
|
111
|
+
{ NULL, NULL, 0 }, /* SM */
|
|
112
|
+
{ pre_B, NULL, 0 }, /* SB */
|
|
113
|
+
{ pre_alternate, NULL, 0 }, /* BI */
|
|
114
|
+
{ pre_alternate, NULL, 0 }, /* IB */
|
|
115
|
+
{ pre_alternate, NULL, 0 }, /* BR */
|
|
116
|
+
{ pre_alternate, NULL, 0 }, /* RB */
|
|
117
|
+
{ NULL, NULL, 0 }, /* R */
|
|
118
|
+
{ pre_B, NULL, 0 }, /* B */
|
|
119
|
+
{ pre_I, NULL, 0 }, /* I */
|
|
120
|
+
{ pre_alternate, NULL, 0 }, /* IR */
|
|
121
|
+
{ pre_alternate, NULL, 0 }, /* RI */
|
|
122
|
+
{ NULL, NULL, 0 }, /* RE */
|
|
123
|
+
{ pre_RS, post_RS, 0 }, /* RS */
|
|
124
|
+
{ pre_DT, NULL, 0 }, /* DT */
|
|
125
|
+
{ pre_ign, NULL, MAN_NOTEXT }, /* UC */
|
|
126
|
+
{ pre_PD, NULL, MAN_NOTEXT }, /* PD */
|
|
127
|
+
{ pre_ign, NULL, 0 }, /* AT */
|
|
128
|
+
{ pre_in, NULL, MAN_NOTEXT }, /* in */
|
|
129
|
+
{ pre_SY, post_SY, 0 }, /* SY */
|
|
130
|
+
{ NULL, NULL, 0 }, /* YS */
|
|
131
|
+
{ pre_OP, NULL, 0 }, /* OP */
|
|
132
|
+
{ pre_literal, NULL, 0 }, /* EX */
|
|
133
|
+
{ pre_literal, NULL, 0 }, /* EE */
|
|
134
|
+
{ pre_UR, post_UR, 0 }, /* UR */
|
|
135
|
+
{ NULL, NULL, 0 }, /* UE */
|
|
136
|
+
{ pre_UR, post_UR, 0 }, /* MT */
|
|
137
|
+
{ NULL, NULL, 0 }, /* ME */
|
|
138
|
+
};
|
|
139
|
+
static const struct man_term_act *man_term_act(enum roff_tok);
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
static const struct man_term_act *
|
|
143
|
+
man_term_act(enum roff_tok tok)
|
|
144
|
+
{
|
|
145
|
+
assert(tok >= MAN_TH && tok <= MAN_MAX);
|
|
146
|
+
return man_term_acts + (tok - MAN_TH);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
void
|
|
150
|
+
terminal_man(void *arg, const struct roff_meta *man)
|
|
151
|
+
{
|
|
152
|
+
struct mtermp mt;
|
|
153
|
+
struct termp *p;
|
|
154
|
+
struct roff_node *n, *nc, *nn;
|
|
155
|
+
size_t save_defindent;
|
|
156
|
+
|
|
157
|
+
p = (struct termp *)arg;
|
|
158
|
+
save_defindent = p->defindent;
|
|
159
|
+
if (p->synopsisonly == 0 && p->defindent == 0)
|
|
160
|
+
p->defindent = 7;
|
|
161
|
+
p->tcol->rmargin = p->maxrmargin = p->defrmargin;
|
|
162
|
+
term_tab_set(p, NULL);
|
|
163
|
+
term_tab_set(p, "T");
|
|
164
|
+
term_tab_set(p, ".5i");
|
|
165
|
+
|
|
166
|
+
memset(&mt, 0, sizeof(mt));
|
|
167
|
+
mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
|
|
168
|
+
mt.offset = term_len(p, p->defindent);
|
|
169
|
+
mt.pardist = 1;
|
|
170
|
+
|
|
171
|
+
n = man->first->child;
|
|
172
|
+
if (p->synopsisonly) {
|
|
173
|
+
for (nn = NULL; n != NULL; n = n->next) {
|
|
174
|
+
if (n->tok != MAN_SH)
|
|
175
|
+
continue;
|
|
176
|
+
nc = n->child->child;
|
|
177
|
+
if (nc->type != ROFFT_TEXT)
|
|
178
|
+
continue;
|
|
179
|
+
if (strcmp(nc->string, "SYNOPSIS") == 0)
|
|
180
|
+
break;
|
|
181
|
+
if (nn == NULL && strcmp(nc->string, "NAME") == 0)
|
|
182
|
+
nn = n;
|
|
183
|
+
}
|
|
184
|
+
if (n == NULL)
|
|
185
|
+
n = nn;
|
|
186
|
+
p->flags |= TERMP_NOSPACE;
|
|
187
|
+
if (n != NULL && (n = n->child->next->child) != NULL)
|
|
188
|
+
print_man_nodelist(p, &mt, n, man);
|
|
189
|
+
term_newln(p);
|
|
190
|
+
} else {
|
|
191
|
+
term_begin(p, print_man_head, print_man_foot, man);
|
|
192
|
+
p->flags |= TERMP_NOSPACE;
|
|
193
|
+
if (n != NULL)
|
|
194
|
+
print_man_nodelist(p, &mt, n, man);
|
|
195
|
+
term_end(p);
|
|
196
|
+
}
|
|
197
|
+
p->defindent = save_defindent;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/*
|
|
201
|
+
* Printing leading vertical space before a block.
|
|
202
|
+
* This is used for the paragraph macros.
|
|
203
|
+
* The rules are pretty simple, since there's very little nesting going
|
|
204
|
+
* on here. Basically, if we're the first within another block (SS/SH),
|
|
205
|
+
* then don't emit vertical space. If we are (RS), then do. If not the
|
|
206
|
+
* first, print it.
|
|
207
|
+
*/
|
|
208
|
+
static void
|
|
209
|
+
print_bvspace(struct termp *p, struct roff_node *n, int pardist)
|
|
210
|
+
{
|
|
211
|
+
struct roff_node *nch;
|
|
212
|
+
int i;
|
|
213
|
+
|
|
214
|
+
term_newln(p);
|
|
215
|
+
|
|
216
|
+
if (n->body != NULL &&
|
|
217
|
+
(nch = roff_node_child(n->body)) != NULL &&
|
|
218
|
+
nch->type == ROFFT_TBL)
|
|
219
|
+
return;
|
|
220
|
+
|
|
221
|
+
if (n->parent->tok != MAN_RS && roff_node_prev(n) == NULL)
|
|
222
|
+
return;
|
|
223
|
+
|
|
224
|
+
for (i = 0; i < pardist; i++)
|
|
225
|
+
term_vspace(p);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
static int
|
|
230
|
+
pre_abort(DECL_ARGS)
|
|
231
|
+
{
|
|
232
|
+
abort();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
static int
|
|
236
|
+
pre_ign(DECL_ARGS)
|
|
237
|
+
{
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static int
|
|
242
|
+
pre_I(DECL_ARGS)
|
|
243
|
+
{
|
|
244
|
+
term_fontrepl(p, TERMFONT_UNDER);
|
|
245
|
+
return 1;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static int
|
|
249
|
+
pre_literal(DECL_ARGS)
|
|
250
|
+
{
|
|
251
|
+
term_newln(p);
|
|
252
|
+
|
|
253
|
+
/*
|
|
254
|
+
* Unlike .IP and .TP, .HP does not have a HEAD.
|
|
255
|
+
* So in case a second call to term_flushln() is needed,
|
|
256
|
+
* indentation has to be set up explicitly.
|
|
257
|
+
*/
|
|
258
|
+
if (n->parent->tok == MAN_HP && p->tcol->rmargin < p->maxrmargin) {
|
|
259
|
+
p->tcol->offset = p->tcol->rmargin;
|
|
260
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
261
|
+
p->trailspace = 0;
|
|
262
|
+
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
|
|
263
|
+
p->flags |= TERMP_NOSPACE;
|
|
264
|
+
}
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
static int
|
|
269
|
+
pre_PD(DECL_ARGS)
|
|
270
|
+
{
|
|
271
|
+
struct roffsu su;
|
|
272
|
+
|
|
273
|
+
n = n->child;
|
|
274
|
+
if (n == NULL) {
|
|
275
|
+
mt->pardist = 1;
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
assert(n->type == ROFFT_TEXT);
|
|
279
|
+
if (a2roffsu(n->string, &su, SCALE_VS) != NULL)
|
|
280
|
+
mt->pardist = term_vspan(p, &su);
|
|
281
|
+
return 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
static int
|
|
285
|
+
pre_alternate(DECL_ARGS)
|
|
286
|
+
{
|
|
287
|
+
enum termfont font[2];
|
|
288
|
+
struct roff_node *nn;
|
|
289
|
+
int i;
|
|
290
|
+
|
|
291
|
+
switch (n->tok) {
|
|
292
|
+
case MAN_RB:
|
|
293
|
+
font[0] = TERMFONT_NONE;
|
|
294
|
+
font[1] = TERMFONT_BOLD;
|
|
295
|
+
break;
|
|
296
|
+
case MAN_RI:
|
|
297
|
+
font[0] = TERMFONT_NONE;
|
|
298
|
+
font[1] = TERMFONT_UNDER;
|
|
299
|
+
break;
|
|
300
|
+
case MAN_BR:
|
|
301
|
+
font[0] = TERMFONT_BOLD;
|
|
302
|
+
font[1] = TERMFONT_NONE;
|
|
303
|
+
break;
|
|
304
|
+
case MAN_BI:
|
|
305
|
+
font[0] = TERMFONT_BOLD;
|
|
306
|
+
font[1] = TERMFONT_UNDER;
|
|
307
|
+
break;
|
|
308
|
+
case MAN_IR:
|
|
309
|
+
font[0] = TERMFONT_UNDER;
|
|
310
|
+
font[1] = TERMFONT_NONE;
|
|
311
|
+
break;
|
|
312
|
+
case MAN_IB:
|
|
313
|
+
font[0] = TERMFONT_UNDER;
|
|
314
|
+
font[1] = TERMFONT_BOLD;
|
|
315
|
+
break;
|
|
316
|
+
default:
|
|
317
|
+
abort();
|
|
318
|
+
}
|
|
319
|
+
for (i = 0, nn = n->child; nn != NULL; nn = nn->next, i = 1 - i) {
|
|
320
|
+
term_fontrepl(p, font[i]);
|
|
321
|
+
assert(nn->type == ROFFT_TEXT);
|
|
322
|
+
term_word(p, nn->string);
|
|
323
|
+
if (nn->flags & NODE_EOS)
|
|
324
|
+
p->flags |= TERMP_SENTENCE;
|
|
325
|
+
if (nn->next != NULL)
|
|
326
|
+
p->flags |= TERMP_NOSPACE;
|
|
327
|
+
}
|
|
328
|
+
return 0;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
static int
|
|
332
|
+
pre_B(DECL_ARGS)
|
|
333
|
+
{
|
|
334
|
+
term_fontrepl(p, TERMFONT_BOLD);
|
|
335
|
+
return 1;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
static int
|
|
339
|
+
pre_OP(DECL_ARGS)
|
|
340
|
+
{
|
|
341
|
+
term_word(p, "[");
|
|
342
|
+
p->flags |= TERMP_KEEP | TERMP_NOSPACE;
|
|
343
|
+
|
|
344
|
+
if ((n = n->child) != NULL) {
|
|
345
|
+
term_fontrepl(p, TERMFONT_BOLD);
|
|
346
|
+
term_word(p, n->string);
|
|
347
|
+
}
|
|
348
|
+
if (n != NULL && n->next != NULL) {
|
|
349
|
+
term_fontrepl(p, TERMFONT_UNDER);
|
|
350
|
+
term_word(p, n->next->string);
|
|
351
|
+
}
|
|
352
|
+
term_fontrepl(p, TERMFONT_NONE);
|
|
353
|
+
p->flags &= ~TERMP_KEEP;
|
|
354
|
+
p->flags |= TERMP_NOSPACE;
|
|
355
|
+
term_word(p, "]");
|
|
356
|
+
return 0;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
static int
|
|
360
|
+
pre_in(DECL_ARGS)
|
|
361
|
+
{
|
|
362
|
+
struct roffsu su;
|
|
363
|
+
const char *cp;
|
|
364
|
+
size_t v;
|
|
365
|
+
int less;
|
|
366
|
+
|
|
367
|
+
term_newln(p);
|
|
368
|
+
|
|
369
|
+
if (n->child == NULL) {
|
|
370
|
+
p->tcol->offset = mt->offset;
|
|
371
|
+
return 0;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
cp = n->child->string;
|
|
375
|
+
less = 0;
|
|
376
|
+
|
|
377
|
+
if (*cp == '-')
|
|
378
|
+
less = -1;
|
|
379
|
+
else if (*cp == '+')
|
|
380
|
+
less = 1;
|
|
381
|
+
else
|
|
382
|
+
cp--;
|
|
383
|
+
|
|
384
|
+
if (a2roffsu(++cp, &su, SCALE_EN) == NULL)
|
|
385
|
+
return 0;
|
|
386
|
+
|
|
387
|
+
v = term_hen(p, &su);
|
|
388
|
+
|
|
389
|
+
if (less < 0)
|
|
390
|
+
p->tcol->offset -= p->tcol->offset > v ? v : p->tcol->offset;
|
|
391
|
+
else if (less > 0)
|
|
392
|
+
p->tcol->offset += v;
|
|
393
|
+
else
|
|
394
|
+
p->tcol->offset = v;
|
|
395
|
+
if (p->tcol->offset > SHRT_MAX)
|
|
396
|
+
p->tcol->offset = term_len(p, p->defindent);
|
|
397
|
+
|
|
398
|
+
return 0;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static int
|
|
402
|
+
pre_DT(DECL_ARGS)
|
|
403
|
+
{
|
|
404
|
+
term_tab_set(p, NULL);
|
|
405
|
+
term_tab_set(p, "T");
|
|
406
|
+
term_tab_set(p, ".5i");
|
|
407
|
+
return 0;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
static int
|
|
411
|
+
pre_HP(DECL_ARGS)
|
|
412
|
+
{
|
|
413
|
+
struct roffsu su;
|
|
414
|
+
const struct roff_node *nn;
|
|
415
|
+
int len;
|
|
416
|
+
|
|
417
|
+
switch (n->type) {
|
|
418
|
+
case ROFFT_BLOCK:
|
|
419
|
+
print_bvspace(p, n, mt->pardist);
|
|
420
|
+
return 1;
|
|
421
|
+
case ROFFT_HEAD:
|
|
422
|
+
return 0;
|
|
423
|
+
case ROFFT_BODY:
|
|
424
|
+
break;
|
|
425
|
+
default:
|
|
426
|
+
abort();
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (n->child == NULL)
|
|
430
|
+
return 0;
|
|
431
|
+
|
|
432
|
+
if ((n->child->flags & NODE_NOFILL) == 0) {
|
|
433
|
+
p->flags |= TERMP_NOBREAK | TERMP_BRIND;
|
|
434
|
+
p->trailspace = 2;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/* Calculate offset. */
|
|
438
|
+
|
|
439
|
+
if ((nn = n->parent->head->child) != NULL &&
|
|
440
|
+
a2roffsu(nn->string, &su, SCALE_EN) != NULL) {
|
|
441
|
+
len = term_hen(p, &su);
|
|
442
|
+
if (len < 0 && (size_t)(-len) > mt->offset)
|
|
443
|
+
len = -mt->offset;
|
|
444
|
+
else if (len > SHRT_MAX)
|
|
445
|
+
len = term_len(p, p->defindent);
|
|
446
|
+
mt->lmargin[mt->lmargincur] = len;
|
|
447
|
+
} else
|
|
448
|
+
len = mt->lmargin[mt->lmargincur];
|
|
449
|
+
|
|
450
|
+
p->tcol->offset = mt->offset;
|
|
451
|
+
p->tcol->rmargin = mt->offset + len;
|
|
452
|
+
return 1;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
static void
|
|
456
|
+
post_HP(DECL_ARGS)
|
|
457
|
+
{
|
|
458
|
+
switch (n->type) {
|
|
459
|
+
case ROFFT_BLOCK:
|
|
460
|
+
case ROFFT_HEAD:
|
|
461
|
+
break;
|
|
462
|
+
case ROFFT_BODY:
|
|
463
|
+
term_newln(p);
|
|
464
|
+
|
|
465
|
+
/*
|
|
466
|
+
* Compatibility with a groff bug.
|
|
467
|
+
* The .HP macro uses the undocumented .tag request
|
|
468
|
+
* which causes a line break and cancels no-space
|
|
469
|
+
* mode even if there isn't any output.
|
|
470
|
+
*/
|
|
471
|
+
|
|
472
|
+
if (n->child == NULL)
|
|
473
|
+
term_vspace(p);
|
|
474
|
+
|
|
475
|
+
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
|
|
476
|
+
p->trailspace = 0;
|
|
477
|
+
p->tcol->offset = mt->offset;
|
|
478
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
479
|
+
break;
|
|
480
|
+
default:
|
|
481
|
+
abort();
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
static int
|
|
486
|
+
pre_PP(DECL_ARGS)
|
|
487
|
+
{
|
|
488
|
+
switch (n->type) {
|
|
489
|
+
case ROFFT_BLOCK:
|
|
490
|
+
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
|
|
491
|
+
print_bvspace(p, n, mt->pardist);
|
|
492
|
+
break;
|
|
493
|
+
case ROFFT_HEAD:
|
|
494
|
+
return 0;
|
|
495
|
+
case ROFFT_BODY:
|
|
496
|
+
p->tcol->offset = mt->offset;
|
|
497
|
+
break;
|
|
498
|
+
default:
|
|
499
|
+
abort();
|
|
500
|
+
}
|
|
501
|
+
return 1;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
static int
|
|
505
|
+
pre_IP(DECL_ARGS)
|
|
506
|
+
{
|
|
507
|
+
struct roffsu su;
|
|
508
|
+
const struct roff_node *nn;
|
|
509
|
+
int len;
|
|
510
|
+
|
|
511
|
+
switch (n->type) {
|
|
512
|
+
case ROFFT_BLOCK:
|
|
513
|
+
print_bvspace(p, n, mt->pardist);
|
|
514
|
+
return 1;
|
|
515
|
+
case ROFFT_HEAD:
|
|
516
|
+
p->flags |= TERMP_NOBREAK;
|
|
517
|
+
p->trailspace = 1;
|
|
518
|
+
break;
|
|
519
|
+
case ROFFT_BODY:
|
|
520
|
+
p->flags |= TERMP_NOSPACE;
|
|
521
|
+
break;
|
|
522
|
+
default:
|
|
523
|
+
abort();
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/* Calculate the offset from the optional second argument. */
|
|
527
|
+
if ((nn = n->parent->head->child) != NULL &&
|
|
528
|
+
(nn = nn->next) != NULL &&
|
|
529
|
+
a2roffsu(nn->string, &su, SCALE_EN) != NULL) {
|
|
530
|
+
len = term_hen(p, &su);
|
|
531
|
+
if (len < 0 && (size_t)(-len) > mt->offset)
|
|
532
|
+
len = -mt->offset;
|
|
533
|
+
else if (len > SHRT_MAX)
|
|
534
|
+
len = term_len(p, p->defindent);
|
|
535
|
+
mt->lmargin[mt->lmargincur] = len;
|
|
536
|
+
} else
|
|
537
|
+
len = mt->lmargin[mt->lmargincur];
|
|
538
|
+
|
|
539
|
+
switch (n->type) {
|
|
540
|
+
case ROFFT_HEAD:
|
|
541
|
+
p->tcol->offset = mt->offset;
|
|
542
|
+
p->tcol->rmargin = mt->offset + len;
|
|
543
|
+
if (n->child != NULL)
|
|
544
|
+
print_man_node(p, mt, n->child, meta);
|
|
545
|
+
return 0;
|
|
546
|
+
case ROFFT_BODY:
|
|
547
|
+
p->tcol->offset = mt->offset + len;
|
|
548
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
549
|
+
break;
|
|
550
|
+
default:
|
|
551
|
+
abort();
|
|
552
|
+
}
|
|
553
|
+
return 1;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
static void
|
|
557
|
+
post_IP(DECL_ARGS)
|
|
558
|
+
{
|
|
559
|
+
switch (n->type) {
|
|
560
|
+
case ROFFT_BLOCK:
|
|
561
|
+
break;
|
|
562
|
+
case ROFFT_HEAD:
|
|
563
|
+
term_flushln(p);
|
|
564
|
+
p->flags &= ~TERMP_NOBREAK;
|
|
565
|
+
p->trailspace = 0;
|
|
566
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
567
|
+
break;
|
|
568
|
+
case ROFFT_BODY:
|
|
569
|
+
term_newln(p);
|
|
570
|
+
p->tcol->offset = mt->offset;
|
|
571
|
+
break;
|
|
572
|
+
default:
|
|
573
|
+
abort();
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
static int
|
|
578
|
+
pre_TP(DECL_ARGS)
|
|
579
|
+
{
|
|
580
|
+
struct roffsu su;
|
|
581
|
+
struct roff_node *nn;
|
|
582
|
+
int len;
|
|
583
|
+
|
|
584
|
+
switch (n->type) {
|
|
585
|
+
case ROFFT_BLOCK:
|
|
586
|
+
if (n->tok == MAN_TP)
|
|
587
|
+
print_bvspace(p, n, mt->pardist);
|
|
588
|
+
return 1;
|
|
589
|
+
case ROFFT_HEAD:
|
|
590
|
+
p->flags |= TERMP_NOBREAK | TERMP_BRTRSP;
|
|
591
|
+
p->trailspace = 1;
|
|
592
|
+
break;
|
|
593
|
+
case ROFFT_BODY:
|
|
594
|
+
p->flags |= TERMP_NOSPACE;
|
|
595
|
+
break;
|
|
596
|
+
default:
|
|
597
|
+
abort();
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/* Calculate offset. */
|
|
601
|
+
|
|
602
|
+
if ((nn = n->parent->head->child) != NULL &&
|
|
603
|
+
nn->string != NULL && ! (NODE_LINE & nn->flags) &&
|
|
604
|
+
a2roffsu(nn->string, &su, SCALE_EN) != NULL) {
|
|
605
|
+
len = term_hen(p, &su);
|
|
606
|
+
if (len < 0 && (size_t)(-len) > mt->offset)
|
|
607
|
+
len = -mt->offset;
|
|
608
|
+
else if (len > SHRT_MAX)
|
|
609
|
+
len = term_len(p, p->defindent);
|
|
610
|
+
mt->lmargin[mt->lmargincur] = len;
|
|
611
|
+
} else
|
|
612
|
+
len = mt->lmargin[mt->lmargincur];
|
|
613
|
+
|
|
614
|
+
switch (n->type) {
|
|
615
|
+
case ROFFT_HEAD:
|
|
616
|
+
p->tcol->offset = mt->offset;
|
|
617
|
+
p->tcol->rmargin = mt->offset + len;
|
|
618
|
+
|
|
619
|
+
/* Don't print same-line elements. */
|
|
620
|
+
nn = n->child;
|
|
621
|
+
while (nn != NULL && (nn->flags & NODE_LINE) == 0)
|
|
622
|
+
nn = nn->next;
|
|
623
|
+
|
|
624
|
+
while (nn != NULL) {
|
|
625
|
+
print_man_node(p, mt, nn, meta);
|
|
626
|
+
nn = nn->next;
|
|
627
|
+
}
|
|
628
|
+
return 0;
|
|
629
|
+
case ROFFT_BODY:
|
|
630
|
+
p->tcol->offset = mt->offset + len;
|
|
631
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
632
|
+
p->trailspace = 0;
|
|
633
|
+
p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP);
|
|
634
|
+
break;
|
|
635
|
+
default:
|
|
636
|
+
abort();
|
|
637
|
+
}
|
|
638
|
+
return 1;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
static void
|
|
642
|
+
post_TP(DECL_ARGS)
|
|
643
|
+
{
|
|
644
|
+
switch (n->type) {
|
|
645
|
+
case ROFFT_BLOCK:
|
|
646
|
+
break;
|
|
647
|
+
case ROFFT_HEAD:
|
|
648
|
+
term_flushln(p);
|
|
649
|
+
break;
|
|
650
|
+
case ROFFT_BODY:
|
|
651
|
+
term_newln(p);
|
|
652
|
+
p->tcol->offset = mt->offset;
|
|
653
|
+
break;
|
|
654
|
+
default:
|
|
655
|
+
abort();
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
static int
|
|
660
|
+
pre_SS(DECL_ARGS)
|
|
661
|
+
{
|
|
662
|
+
int i;
|
|
663
|
+
|
|
664
|
+
switch (n->type) {
|
|
665
|
+
case ROFFT_BLOCK:
|
|
666
|
+
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
|
|
667
|
+
mt->offset = term_len(p, p->defindent);
|
|
668
|
+
|
|
669
|
+
/*
|
|
670
|
+
* No vertical space before the first subsection
|
|
671
|
+
* and after an empty subsection.
|
|
672
|
+
*/
|
|
673
|
+
|
|
674
|
+
if ((n = roff_node_prev(n)) == NULL ||
|
|
675
|
+
(n->tok == MAN_SS && roff_node_child(n->body) == NULL))
|
|
676
|
+
break;
|
|
677
|
+
|
|
678
|
+
for (i = 0; i < mt->pardist; i++)
|
|
679
|
+
term_vspace(p);
|
|
680
|
+
break;
|
|
681
|
+
case ROFFT_HEAD:
|
|
682
|
+
term_fontrepl(p, TERMFONT_BOLD);
|
|
683
|
+
p->tcol->offset = term_len(p, 3);
|
|
684
|
+
p->tcol->rmargin = mt->offset;
|
|
685
|
+
p->trailspace = mt->offset;
|
|
686
|
+
p->flags |= TERMP_NOBREAK | TERMP_BRIND;
|
|
687
|
+
break;
|
|
688
|
+
case ROFFT_BODY:
|
|
689
|
+
p->tcol->offset = mt->offset;
|
|
690
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
691
|
+
p->trailspace = 0;
|
|
692
|
+
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
|
|
693
|
+
break;
|
|
694
|
+
default:
|
|
695
|
+
break;
|
|
696
|
+
}
|
|
697
|
+
return 1;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
static int
|
|
701
|
+
pre_SH(DECL_ARGS)
|
|
702
|
+
{
|
|
703
|
+
int i;
|
|
704
|
+
|
|
705
|
+
switch (n->type) {
|
|
706
|
+
case ROFFT_BLOCK:
|
|
707
|
+
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
|
|
708
|
+
mt->offset = term_len(p, p->defindent);
|
|
709
|
+
|
|
710
|
+
/*
|
|
711
|
+
* No vertical space before the first section
|
|
712
|
+
* and after an empty section.
|
|
713
|
+
*/
|
|
714
|
+
|
|
715
|
+
if ((n = roff_node_prev(n)) == NULL ||
|
|
716
|
+
(n->tok == MAN_SH && roff_node_child(n->body) == NULL))
|
|
717
|
+
break;
|
|
718
|
+
|
|
719
|
+
for (i = 0; i < mt->pardist; i++)
|
|
720
|
+
term_vspace(p);
|
|
721
|
+
break;
|
|
722
|
+
case ROFFT_HEAD:
|
|
723
|
+
term_fontrepl(p, TERMFONT_BOLD);
|
|
724
|
+
p->tcol->offset = 0;
|
|
725
|
+
p->tcol->rmargin = mt->offset;
|
|
726
|
+
p->trailspace = mt->offset;
|
|
727
|
+
p->flags |= TERMP_NOBREAK | TERMP_BRIND;
|
|
728
|
+
break;
|
|
729
|
+
case ROFFT_BODY:
|
|
730
|
+
p->tcol->offset = mt->offset;
|
|
731
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
732
|
+
p->trailspace = 0;
|
|
733
|
+
p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
|
|
734
|
+
break;
|
|
735
|
+
default:
|
|
736
|
+
abort();
|
|
737
|
+
}
|
|
738
|
+
return 1;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
static void
|
|
742
|
+
post_SH(DECL_ARGS)
|
|
743
|
+
{
|
|
744
|
+
switch (n->type) {
|
|
745
|
+
case ROFFT_BLOCK:
|
|
746
|
+
break;
|
|
747
|
+
case ROFFT_HEAD:
|
|
748
|
+
case ROFFT_BODY:
|
|
749
|
+
term_newln(p);
|
|
750
|
+
break;
|
|
751
|
+
default:
|
|
752
|
+
abort();
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
static int
|
|
757
|
+
pre_RS(DECL_ARGS)
|
|
758
|
+
{
|
|
759
|
+
struct roffsu su;
|
|
760
|
+
|
|
761
|
+
switch (n->type) {
|
|
762
|
+
case ROFFT_BLOCK:
|
|
763
|
+
term_newln(p);
|
|
764
|
+
return 1;
|
|
765
|
+
case ROFFT_HEAD:
|
|
766
|
+
return 0;
|
|
767
|
+
case ROFFT_BODY:
|
|
768
|
+
break;
|
|
769
|
+
default:
|
|
770
|
+
abort();
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
n = n->parent->head;
|
|
774
|
+
n->aux = SHRT_MAX + 1;
|
|
775
|
+
if (n->child == NULL)
|
|
776
|
+
n->aux = mt->lmargin[mt->lmargincur];
|
|
777
|
+
else if (a2roffsu(n->child->string, &su, SCALE_EN) != NULL)
|
|
778
|
+
n->aux = term_hen(p, &su);
|
|
779
|
+
if (n->aux < 0 && (size_t)(-n->aux) > mt->offset)
|
|
780
|
+
n->aux = -mt->offset;
|
|
781
|
+
else if (n->aux > SHRT_MAX)
|
|
782
|
+
n->aux = term_len(p, p->defindent);
|
|
783
|
+
|
|
784
|
+
mt->offset += n->aux;
|
|
785
|
+
p->tcol->offset = mt->offset;
|
|
786
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
787
|
+
|
|
788
|
+
if (++mt->lmarginsz < MAXMARGINS)
|
|
789
|
+
mt->lmargincur = mt->lmarginsz;
|
|
790
|
+
|
|
791
|
+
mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
|
|
792
|
+
return 1;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
static void
|
|
796
|
+
post_RS(DECL_ARGS)
|
|
797
|
+
{
|
|
798
|
+
switch (n->type) {
|
|
799
|
+
case ROFFT_BLOCK:
|
|
800
|
+
case ROFFT_HEAD:
|
|
801
|
+
return;
|
|
802
|
+
case ROFFT_BODY:
|
|
803
|
+
break;
|
|
804
|
+
default:
|
|
805
|
+
abort();
|
|
806
|
+
}
|
|
807
|
+
term_newln(p);
|
|
808
|
+
mt->offset -= n->parent->head->aux;
|
|
809
|
+
p->tcol->offset = mt->offset;
|
|
810
|
+
if (--mt->lmarginsz < MAXMARGINS)
|
|
811
|
+
mt->lmargincur = mt->lmarginsz;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
static int
|
|
815
|
+
pre_SY(DECL_ARGS)
|
|
816
|
+
{
|
|
817
|
+
const struct roff_node *nn;
|
|
818
|
+
int len;
|
|
819
|
+
|
|
820
|
+
switch (n->type) {
|
|
821
|
+
case ROFFT_BLOCK:
|
|
822
|
+
if ((nn = roff_node_prev(n)) == NULL || nn->tok != MAN_SY)
|
|
823
|
+
print_bvspace(p, n, mt->pardist);
|
|
824
|
+
return 1;
|
|
825
|
+
case ROFFT_HEAD:
|
|
826
|
+
case ROFFT_BODY:
|
|
827
|
+
break;
|
|
828
|
+
default:
|
|
829
|
+
abort();
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
nn = n->parent->head->child;
|
|
833
|
+
len = nn == NULL ? 1 : term_strlen(p, nn->string) + 1;
|
|
834
|
+
|
|
835
|
+
switch (n->type) {
|
|
836
|
+
case ROFFT_HEAD:
|
|
837
|
+
p->tcol->offset = mt->offset;
|
|
838
|
+
p->tcol->rmargin = mt->offset + len;
|
|
839
|
+
if (n->next->child == NULL ||
|
|
840
|
+
(n->next->child->flags & NODE_NOFILL) == 0)
|
|
841
|
+
p->flags |= TERMP_NOBREAK;
|
|
842
|
+
term_fontrepl(p, TERMFONT_BOLD);
|
|
843
|
+
break;
|
|
844
|
+
case ROFFT_BODY:
|
|
845
|
+
mt->lmargin[mt->lmargincur] = len;
|
|
846
|
+
p->tcol->offset = mt->offset + len;
|
|
847
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
848
|
+
p->flags |= TERMP_NOSPACE;
|
|
849
|
+
break;
|
|
850
|
+
default:
|
|
851
|
+
abort();
|
|
852
|
+
}
|
|
853
|
+
return 1;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
static void
|
|
857
|
+
post_SY(DECL_ARGS)
|
|
858
|
+
{
|
|
859
|
+
switch (n->type) {
|
|
860
|
+
case ROFFT_BLOCK:
|
|
861
|
+
break;
|
|
862
|
+
case ROFFT_HEAD:
|
|
863
|
+
term_flushln(p);
|
|
864
|
+
p->flags &= ~TERMP_NOBREAK;
|
|
865
|
+
break;
|
|
866
|
+
case ROFFT_BODY:
|
|
867
|
+
term_newln(p);
|
|
868
|
+
p->tcol->offset = mt->offset;
|
|
869
|
+
break;
|
|
870
|
+
default:
|
|
871
|
+
abort();
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
static int
|
|
876
|
+
pre_UR(DECL_ARGS)
|
|
877
|
+
{
|
|
878
|
+
return n->type != ROFFT_HEAD;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
static void
|
|
882
|
+
post_UR(DECL_ARGS)
|
|
883
|
+
{
|
|
884
|
+
if (n->type != ROFFT_BLOCK)
|
|
885
|
+
return;
|
|
886
|
+
|
|
887
|
+
term_word(p, "<");
|
|
888
|
+
p->flags |= TERMP_NOSPACE;
|
|
889
|
+
|
|
890
|
+
if (n->child->child != NULL)
|
|
891
|
+
print_man_node(p, mt, n->child->child, meta);
|
|
892
|
+
|
|
893
|
+
p->flags |= TERMP_NOSPACE;
|
|
894
|
+
term_word(p, ">");
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
static void
|
|
898
|
+
print_man_node(DECL_ARGS)
|
|
899
|
+
{
|
|
900
|
+
const struct man_term_act *act;
|
|
901
|
+
int c;
|
|
902
|
+
|
|
903
|
+
if (n->flags & NODE_ID)
|
|
904
|
+
term_tag_write(n, p->line);
|
|
905
|
+
|
|
906
|
+
switch (n->type) {
|
|
907
|
+
case ROFFT_TEXT:
|
|
908
|
+
/*
|
|
909
|
+
* If we have a blank line, output a vertical space.
|
|
910
|
+
* If we have a space as the first character, break
|
|
911
|
+
* before printing the line's data.
|
|
912
|
+
*/
|
|
913
|
+
if (*n->string == '\0') {
|
|
914
|
+
if (p->flags & TERMP_NONEWLINE)
|
|
915
|
+
term_newln(p);
|
|
916
|
+
else
|
|
917
|
+
term_vspace(p);
|
|
918
|
+
return;
|
|
919
|
+
} else if (*n->string == ' ' && n->flags & NODE_LINE &&
|
|
920
|
+
(p->flags & TERMP_NONEWLINE) == 0)
|
|
921
|
+
term_newln(p);
|
|
922
|
+
else if (n->flags & NODE_DELIMC)
|
|
923
|
+
p->flags |= TERMP_NOSPACE;
|
|
924
|
+
|
|
925
|
+
term_word(p, n->string);
|
|
926
|
+
goto out;
|
|
927
|
+
case ROFFT_COMMENT:
|
|
928
|
+
return;
|
|
929
|
+
case ROFFT_EQN:
|
|
930
|
+
if ( ! (n->flags & NODE_LINE))
|
|
931
|
+
p->flags |= TERMP_NOSPACE;
|
|
932
|
+
term_eqn(p, n->eqn);
|
|
933
|
+
if (n->next != NULL && ! (n->next->flags & NODE_LINE))
|
|
934
|
+
p->flags |= TERMP_NOSPACE;
|
|
935
|
+
return;
|
|
936
|
+
case ROFFT_TBL:
|
|
937
|
+
if (p->tbl.cols == NULL)
|
|
938
|
+
term_vspace(p);
|
|
939
|
+
term_tbl(p, n->span);
|
|
940
|
+
return;
|
|
941
|
+
default:
|
|
942
|
+
break;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
if (n->tok < ROFF_MAX) {
|
|
946
|
+
roff_term_pre(p, n);
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
act = man_term_act(n->tok);
|
|
951
|
+
if ((act->flags & MAN_NOTEXT) == 0 && n->tok != MAN_SM)
|
|
952
|
+
term_fontrepl(p, TERMFONT_NONE);
|
|
953
|
+
|
|
954
|
+
c = 1;
|
|
955
|
+
if (act->pre != NULL)
|
|
956
|
+
c = (*act->pre)(p, mt, n, meta);
|
|
957
|
+
|
|
958
|
+
if (c && n->child != NULL)
|
|
959
|
+
print_man_nodelist(p, mt, n->child, meta);
|
|
960
|
+
|
|
961
|
+
if (act->post != NULL)
|
|
962
|
+
(*act->post)(p, mt, n, meta);
|
|
963
|
+
if ((act->flags & MAN_NOTEXT) == 0 && n->tok != MAN_SM)
|
|
964
|
+
term_fontrepl(p, TERMFONT_NONE);
|
|
965
|
+
|
|
966
|
+
out:
|
|
967
|
+
/*
|
|
968
|
+
* If we're in a literal context, make sure that words
|
|
969
|
+
* together on the same line stay together. This is a
|
|
970
|
+
* POST-printing call, so we check the NEXT word. Since
|
|
971
|
+
* -man doesn't have nested macros, we don't need to be
|
|
972
|
+
* more specific than this.
|
|
973
|
+
*/
|
|
974
|
+
if (n->flags & NODE_NOFILL &&
|
|
975
|
+
! (p->flags & (TERMP_NOBREAK | TERMP_NONEWLINE)) &&
|
|
976
|
+
(n->next == NULL || n->next->flags & NODE_LINE)) {
|
|
977
|
+
p->flags |= TERMP_BRNEVER | TERMP_NOSPACE;
|
|
978
|
+
if (n->string != NULL && *n->string != '\0')
|
|
979
|
+
term_flushln(p);
|
|
980
|
+
else
|
|
981
|
+
term_newln(p);
|
|
982
|
+
p->flags &= ~TERMP_BRNEVER;
|
|
983
|
+
if (p->tcol->rmargin < p->maxrmargin &&
|
|
984
|
+
n->parent->tok == MAN_HP) {
|
|
985
|
+
p->tcol->offset = p->tcol->rmargin;
|
|
986
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (n->flags & NODE_EOS)
|
|
990
|
+
p->flags |= TERMP_SENTENCE;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
static void
|
|
994
|
+
print_man_nodelist(DECL_ARGS)
|
|
995
|
+
{
|
|
996
|
+
while (n != NULL) {
|
|
997
|
+
print_man_node(p, mt, n, meta);
|
|
998
|
+
n = n->next;
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
static void
|
|
1003
|
+
print_man_foot(struct termp *p, const struct roff_meta *meta)
|
|
1004
|
+
{
|
|
1005
|
+
char *title;
|
|
1006
|
+
size_t datelen, titlen;
|
|
1007
|
+
|
|
1008
|
+
assert(meta->title);
|
|
1009
|
+
assert(meta->msec);
|
|
1010
|
+
assert(meta->date);
|
|
1011
|
+
|
|
1012
|
+
term_fontrepl(p, TERMFONT_NONE);
|
|
1013
|
+
|
|
1014
|
+
if (meta->hasbody)
|
|
1015
|
+
term_vspace(p);
|
|
1016
|
+
|
|
1017
|
+
/*
|
|
1018
|
+
* Temporary, undocumented option to imitate mdoc(7) output.
|
|
1019
|
+
* In the bottom right corner, use the operating system
|
|
1020
|
+
* instead of the title.
|
|
1021
|
+
*/
|
|
1022
|
+
|
|
1023
|
+
if ( ! p->mdocstyle) {
|
|
1024
|
+
mandoc_asprintf(&title, "%s(%s)",
|
|
1025
|
+
meta->title, meta->msec);
|
|
1026
|
+
} else if (meta->os != NULL) {
|
|
1027
|
+
title = mandoc_strdup(meta->os);
|
|
1028
|
+
} else {
|
|
1029
|
+
title = mandoc_strdup("");
|
|
1030
|
+
}
|
|
1031
|
+
datelen = term_strlen(p, meta->date);
|
|
1032
|
+
|
|
1033
|
+
/* Bottom left corner: operating system. */
|
|
1034
|
+
|
|
1035
|
+
p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
|
|
1036
|
+
p->trailspace = 1;
|
|
1037
|
+
p->tcol->offset = 0;
|
|
1038
|
+
p->tcol->rmargin = p->maxrmargin > datelen ?
|
|
1039
|
+
(p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0;
|
|
1040
|
+
|
|
1041
|
+
if (meta->os)
|
|
1042
|
+
term_word(p, meta->os);
|
|
1043
|
+
term_flushln(p);
|
|
1044
|
+
|
|
1045
|
+
/* At the bottom in the middle: manual date. */
|
|
1046
|
+
|
|
1047
|
+
p->tcol->offset = p->tcol->rmargin;
|
|
1048
|
+
titlen = term_strlen(p, title);
|
|
1049
|
+
p->tcol->rmargin = p->maxrmargin > titlen ?
|
|
1050
|
+
p->maxrmargin - titlen : 0;
|
|
1051
|
+
p->flags |= TERMP_NOSPACE;
|
|
1052
|
+
|
|
1053
|
+
term_word(p, meta->date);
|
|
1054
|
+
term_flushln(p);
|
|
1055
|
+
|
|
1056
|
+
/* Bottom right corner: manual title and section. */
|
|
1057
|
+
|
|
1058
|
+
p->flags &= ~TERMP_NOBREAK;
|
|
1059
|
+
p->flags |= TERMP_NOSPACE;
|
|
1060
|
+
p->trailspace = 0;
|
|
1061
|
+
p->tcol->offset = p->tcol->rmargin;
|
|
1062
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
1063
|
+
|
|
1064
|
+
term_word(p, title);
|
|
1065
|
+
term_flushln(p);
|
|
1066
|
+
|
|
1067
|
+
/*
|
|
1068
|
+
* Reset the terminal state for more output after the footer:
|
|
1069
|
+
* Some output modes, in particular PostScript and PDF, print
|
|
1070
|
+
* the header and the footer into a buffer such that it can be
|
|
1071
|
+
* reused for multiple output pages, then go on to format the
|
|
1072
|
+
* main text.
|
|
1073
|
+
*/
|
|
1074
|
+
|
|
1075
|
+
p->tcol->offset = 0;
|
|
1076
|
+
p->flags = 0;
|
|
1077
|
+
|
|
1078
|
+
free(title);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
static void
|
|
1082
|
+
print_man_head(struct termp *p, const struct roff_meta *meta)
|
|
1083
|
+
{
|
|
1084
|
+
const char *volume;
|
|
1085
|
+
char *title;
|
|
1086
|
+
size_t vollen, titlen;
|
|
1087
|
+
|
|
1088
|
+
assert(meta->title);
|
|
1089
|
+
assert(meta->msec);
|
|
1090
|
+
|
|
1091
|
+
volume = NULL == meta->vol ? "" : meta->vol;
|
|
1092
|
+
vollen = term_strlen(p, volume);
|
|
1093
|
+
|
|
1094
|
+
/* Top left corner: manual title and section. */
|
|
1095
|
+
|
|
1096
|
+
mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec);
|
|
1097
|
+
titlen = term_strlen(p, title);
|
|
1098
|
+
|
|
1099
|
+
p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
|
|
1100
|
+
p->trailspace = 1;
|
|
1101
|
+
p->tcol->offset = 0;
|
|
1102
|
+
p->tcol->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ?
|
|
1103
|
+
(p->maxrmargin - vollen + term_len(p, 1)) / 2 :
|
|
1104
|
+
vollen < p->maxrmargin ? p->maxrmargin - vollen : 0;
|
|
1105
|
+
|
|
1106
|
+
term_word(p, title);
|
|
1107
|
+
term_flushln(p);
|
|
1108
|
+
|
|
1109
|
+
/* At the top in the middle: manual volume. */
|
|
1110
|
+
|
|
1111
|
+
p->flags |= TERMP_NOSPACE;
|
|
1112
|
+
p->tcol->offset = p->tcol->rmargin;
|
|
1113
|
+
p->tcol->rmargin = p->tcol->offset + vollen + titlen <
|
|
1114
|
+
p->maxrmargin ? p->maxrmargin - titlen : p->maxrmargin;
|
|
1115
|
+
|
|
1116
|
+
term_word(p, volume);
|
|
1117
|
+
term_flushln(p);
|
|
1118
|
+
|
|
1119
|
+
/* Top right corner: title and section, again. */
|
|
1120
|
+
|
|
1121
|
+
p->flags &= ~TERMP_NOBREAK;
|
|
1122
|
+
p->trailspace = 0;
|
|
1123
|
+
if (p->tcol->rmargin + titlen <= p->maxrmargin) {
|
|
1124
|
+
p->flags |= TERMP_NOSPACE;
|
|
1125
|
+
p->tcol->offset = p->tcol->rmargin;
|
|
1126
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
1127
|
+
term_word(p, title);
|
|
1128
|
+
term_flushln(p);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
p->flags &= ~TERMP_NOSPACE;
|
|
1132
|
+
p->tcol->offset = 0;
|
|
1133
|
+
p->tcol->rmargin = p->maxrmargin;
|
|
1134
|
+
|
|
1135
|
+
/*
|
|
1136
|
+
* Groff prints three blank lines before the content.
|
|
1137
|
+
* Do the same, except in the temporary, undocumented
|
|
1138
|
+
* mode imitating mdoc(7) output.
|
|
1139
|
+
*/
|
|
1140
|
+
|
|
1141
|
+
term_vspace(p);
|
|
1142
|
+
free(title);
|
|
1143
|
+
}
|