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