roff_term.c revision 1.1.1.2 1 1.1.1.2 christos /* Id: roff_term.c,v 1.19 2019/01/04 03:24:33 schwarze Exp */
2 1.1 christos /*
3 1.1.1.2 christos * Copyright (c) 2010,2014,2015,2017-2019 Ingo Schwarze <schwarze (at) openbsd.org>
4 1.1 christos *
5 1.1 christos * Permission to use, copy, modify, and distribute this software for any
6 1.1 christos * purpose with or without fee is hereby granted, provided that the above
7 1.1 christos * copyright notice and this permission notice appear in all copies.
8 1.1 christos *
9 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 1.1 christos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 1.1 christos */
17 1.1 christos #include <sys/types.h>
18 1.1 christos
19 1.1 christos #include <assert.h>
20 1.1.1.2 christos #include <stdio.h>
21 1.1.1.2 christos #include <string.h>
22 1.1 christos
23 1.1 christos #include "mandoc.h"
24 1.1 christos #include "roff.h"
25 1.1 christos #include "out.h"
26 1.1 christos #include "term.h"
27 1.1 christos
28 1.1 christos #define ROFF_TERM_ARGS struct termp *p, const struct roff_node *n
29 1.1 christos
30 1.1 christos typedef void (*roff_term_pre_fp)(ROFF_TERM_ARGS);
31 1.1 christos
32 1.1 christos static void roff_term_pre_br(ROFF_TERM_ARGS);
33 1.1 christos static void roff_term_pre_ce(ROFF_TERM_ARGS);
34 1.1 christos static void roff_term_pre_ft(ROFF_TERM_ARGS);
35 1.1 christos static void roff_term_pre_ll(ROFF_TERM_ARGS);
36 1.1 christos static void roff_term_pre_mc(ROFF_TERM_ARGS);
37 1.1 christos static void roff_term_pre_po(ROFF_TERM_ARGS);
38 1.1 christos static void roff_term_pre_sp(ROFF_TERM_ARGS);
39 1.1 christos static void roff_term_pre_ta(ROFF_TERM_ARGS);
40 1.1 christos static void roff_term_pre_ti(ROFF_TERM_ARGS);
41 1.1 christos
42 1.1 christos static const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
43 1.1 christos roff_term_pre_br, /* br */
44 1.1 christos roff_term_pre_ce, /* ce */
45 1.1.1.2 christos roff_term_pre_br, /* fi */
46 1.1 christos roff_term_pre_ft, /* ft */
47 1.1 christos roff_term_pre_ll, /* ll */
48 1.1 christos roff_term_pre_mc, /* mc */
49 1.1.1.2 christos roff_term_pre_br, /* nf */
50 1.1 christos roff_term_pre_po, /* po */
51 1.1 christos roff_term_pre_ce, /* rj */
52 1.1 christos roff_term_pre_sp, /* sp */
53 1.1 christos roff_term_pre_ta, /* ta */
54 1.1 christos roff_term_pre_ti, /* ti */
55 1.1 christos };
56 1.1 christos
57 1.1 christos
58 1.1 christos void
59 1.1 christos roff_term_pre(struct termp *p, const struct roff_node *n)
60 1.1 christos {
61 1.1 christos assert(n->tok < ROFF_MAX);
62 1.1 christos (*roff_term_pre_acts[n->tok])(p, n);
63 1.1 christos }
64 1.1 christos
65 1.1 christos static void
66 1.1 christos roff_term_pre_br(ROFF_TERM_ARGS)
67 1.1 christos {
68 1.1 christos term_newln(p);
69 1.1 christos if (p->flags & TERMP_BRIND) {
70 1.1 christos p->tcol->offset = p->tcol->rmargin;
71 1.1 christos p->tcol->rmargin = p->maxrmargin;
72 1.1.1.2 christos p->trailspace = 0;
73 1.1 christos p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
74 1.1.1.2 christos p->flags |= TERMP_NOSPACE;
75 1.1 christos }
76 1.1 christos }
77 1.1 christos
78 1.1 christos static void
79 1.1 christos roff_term_pre_ce(ROFF_TERM_ARGS)
80 1.1 christos {
81 1.1 christos const struct roff_node *nc1, *nc2;
82 1.1 christos
83 1.1 christos roff_term_pre_br(p, n);
84 1.1.1.2 christos p->flags |= n->tok == ROFF_ce ? TERMP_CENTER : TERMP_RIGHT;
85 1.1 christos nc1 = n->child->next;
86 1.1 christos while (nc1 != NULL) {
87 1.1 christos nc2 = nc1;
88 1.1 christos do {
89 1.1 christos nc2 = nc2->next;
90 1.1 christos } while (nc2 != NULL && (nc2->type != ROFFT_TEXT ||
91 1.1 christos (nc2->flags & NODE_LINE) == 0));
92 1.1 christos while (nc1 != nc2) {
93 1.1 christos if (nc1->type == ROFFT_TEXT)
94 1.1 christos term_word(p, nc1->string);
95 1.1 christos else
96 1.1 christos roff_term_pre(p, nc1);
97 1.1 christos nc1 = nc1->next;
98 1.1 christos }
99 1.1 christos p->flags |= TERMP_NOSPACE;
100 1.1 christos term_flushln(p);
101 1.1 christos }
102 1.1.1.2 christos p->flags &= ~(TERMP_CENTER | TERMP_RIGHT);
103 1.1 christos }
104 1.1 christos
105 1.1 christos static void
106 1.1 christos roff_term_pre_ft(ROFF_TERM_ARGS)
107 1.1 christos {
108 1.1.1.2 christos const char *cp;
109 1.1.1.2 christos
110 1.1.1.2 christos cp = n->child->string;
111 1.1.1.2 christos switch (mandoc_font(cp, (int)strlen(cp))) {
112 1.1.1.2 christos case ESCAPE_FONTBOLD:
113 1.1 christos term_fontrepl(p, TERMFONT_BOLD);
114 1.1 christos break;
115 1.1.1.2 christos case ESCAPE_FONTITALIC:
116 1.1 christos term_fontrepl(p, TERMFONT_UNDER);
117 1.1 christos break;
118 1.1.1.2 christos case ESCAPE_FONTBI:
119 1.1.1.2 christos term_fontrepl(p, TERMFONT_BI);
120 1.1.1.2 christos break;
121 1.1.1.2 christos case ESCAPE_FONTPREV:
122 1.1 christos term_fontlast(p);
123 1.1 christos break;
124 1.1.1.2 christos case ESCAPE_FONTROMAN:
125 1.1.1.2 christos case ESCAPE_FONTCW:
126 1.1 christos term_fontrepl(p, TERMFONT_NONE);
127 1.1 christos break;
128 1.1 christos default:
129 1.1 christos break;
130 1.1 christos }
131 1.1 christos }
132 1.1 christos
133 1.1 christos static void
134 1.1 christos roff_term_pre_ll(ROFF_TERM_ARGS)
135 1.1 christos {
136 1.1 christos term_setwidth(p, n->child != NULL ? n->child->string : NULL);
137 1.1 christos }
138 1.1 christos
139 1.1 christos static void
140 1.1 christos roff_term_pre_mc(ROFF_TERM_ARGS)
141 1.1 christos {
142 1.1 christos if (p->col) {
143 1.1 christos p->flags |= TERMP_NOBREAK;
144 1.1 christos term_flushln(p);
145 1.1 christos p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE);
146 1.1 christos }
147 1.1 christos if (n->child != NULL) {
148 1.1 christos p->mc = n->child->string;
149 1.1 christos p->flags |= TERMP_NEWMC;
150 1.1 christos } else
151 1.1 christos p->flags |= TERMP_ENDMC;
152 1.1 christos }
153 1.1 christos
154 1.1 christos static void
155 1.1 christos roff_term_pre_po(ROFF_TERM_ARGS)
156 1.1 christos {
157 1.1 christos struct roffsu su;
158 1.1 christos static int po, polast;
159 1.1 christos int ponew;
160 1.1 christos
161 1.1 christos if (n->child != NULL &&
162 1.1 christos a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
163 1.1 christos ponew = term_hen(p, &su);
164 1.1 christos if (*n->child->string == '+' ||
165 1.1 christos *n->child->string == '-')
166 1.1 christos ponew += po;
167 1.1 christos } else
168 1.1 christos ponew = polast;
169 1.1 christos polast = po;
170 1.1 christos po = ponew;
171 1.1 christos
172 1.1 christos ponew = po - polast + (int)p->tcol->offset;
173 1.1 christos p->tcol->offset = ponew > 0 ? ponew : 0;
174 1.1 christos }
175 1.1 christos
176 1.1 christos static void
177 1.1 christos roff_term_pre_sp(ROFF_TERM_ARGS)
178 1.1 christos {
179 1.1 christos struct roffsu su;
180 1.1 christos int len;
181 1.1 christos
182 1.1 christos if (n->child != NULL) {
183 1.1 christos if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL)
184 1.1 christos su.scale = 1.0;
185 1.1 christos len = term_vspan(p, &su);
186 1.1 christos } else
187 1.1 christos len = 1;
188 1.1 christos
189 1.1 christos if (len < 0)
190 1.1 christos p->skipvsp -= len;
191 1.1 christos else
192 1.1 christos while (len--)
193 1.1 christos term_vspace(p);
194 1.1 christos
195 1.1 christos roff_term_pre_br(p, n);
196 1.1 christos }
197 1.1 christos
198 1.1 christos static void
199 1.1 christos roff_term_pre_ta(ROFF_TERM_ARGS)
200 1.1 christos {
201 1.1 christos term_tab_set(p, NULL);
202 1.1 christos for (n = n->child; n != NULL; n = n->next)
203 1.1 christos term_tab_set(p, n->string);
204 1.1 christos }
205 1.1 christos
206 1.1 christos static void
207 1.1 christos roff_term_pre_ti(ROFF_TERM_ARGS)
208 1.1 christos {
209 1.1 christos struct roffsu su;
210 1.1 christos const char *cp;
211 1.1 christos int len, sign;
212 1.1 christos
213 1.1 christos roff_term_pre_br(p, n);
214 1.1 christos
215 1.1 christos if (n->child == NULL)
216 1.1 christos return;
217 1.1 christos cp = n->child->string;
218 1.1 christos if (*cp == '+') {
219 1.1 christos sign = 1;
220 1.1 christos cp++;
221 1.1 christos } else if (*cp == '-') {
222 1.1 christos sign = -1;
223 1.1 christos cp++;
224 1.1 christos } else
225 1.1 christos sign = 0;
226 1.1 christos
227 1.1 christos if (a2roffsu(cp, &su, SCALE_EM) == NULL)
228 1.1 christos return;
229 1.1 christos len = term_hen(p, &su);
230 1.1 christos
231 1.1 christos if (sign == 0) {
232 1.1 christos p->ti = len - p->tcol->offset;
233 1.1 christos p->tcol->offset = len;
234 1.1 christos } else if (sign == 1) {
235 1.1 christos p->ti = len;
236 1.1 christos p->tcol->offset += len;
237 1.1 christos } else if ((size_t)len < p->tcol->offset) {
238 1.1 christos p->ti = -len;
239 1.1 christos p->tcol->offset -= len;
240 1.1 christos } else {
241 1.1 christos p->ti = -p->tcol->offset;
242 1.1 christos p->tcol->offset = 0;
243 1.1 christos }
244 1.1 christos }
245