]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/mdocml/roff_term.c
Fix ipfw invalid mbuf handling.
[FreeBSD/FreeBSD.git] / contrib / mdocml / roff_term.c
1 /*      $Id: roff_term.c,v 1.14 2017/06/24 14:38:33 schwarze Exp $ */
2 /*
3  * Copyright (c) 2010, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
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>
20 #include <stddef.h>
21
22 #include "mandoc.h"
23 #include "roff.h"
24 #include "out.h"
25 #include "term.h"
26
27 #define ROFF_TERM_ARGS struct termp *p, const struct roff_node *n
28
29 typedef void    (*roff_term_pre_fp)(ROFF_TERM_ARGS);
30
31 static  void      roff_term_pre_br(ROFF_TERM_ARGS);
32 static  void      roff_term_pre_ce(ROFF_TERM_ARGS);
33 static  void      roff_term_pre_ft(ROFF_TERM_ARGS);
34 static  void      roff_term_pre_ll(ROFF_TERM_ARGS);
35 static  void      roff_term_pre_mc(ROFF_TERM_ARGS);
36 static  void      roff_term_pre_po(ROFF_TERM_ARGS);
37 static  void      roff_term_pre_sp(ROFF_TERM_ARGS);
38 static  void      roff_term_pre_ta(ROFF_TERM_ARGS);
39 static  void      roff_term_pre_ti(ROFF_TERM_ARGS);
40
41 static  const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
42         roff_term_pre_br,  /* br */
43         roff_term_pre_ce,  /* ce */
44         roff_term_pre_ft,  /* ft */
45         roff_term_pre_ll,  /* ll */
46         roff_term_pre_mc,  /* mc */
47         roff_term_pre_po,  /* po */
48         roff_term_pre_ce,  /* rj */
49         roff_term_pre_sp,  /* sp */
50         roff_term_pre_ta,  /* ta */
51         roff_term_pre_ti,  /* ti */
52 };
53
54
55 void
56 roff_term_pre(struct termp *p, const struct roff_node *n)
57 {
58         assert(n->tok < ROFF_MAX);
59         (*roff_term_pre_acts[n->tok])(p, n);
60 }
61
62 static void
63 roff_term_pre_br(ROFF_TERM_ARGS)
64 {
65         term_newln(p);
66         if (p->flags & TERMP_BRIND) {
67                 p->tcol->offset = p->tcol->rmargin;
68                 p->tcol->rmargin = p->maxrmargin;
69                 p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND);
70         }
71 }
72
73 static void
74 roff_term_pre_ce(ROFF_TERM_ARGS)
75 {
76         const struct roff_node  *nc1, *nc2;
77         size_t                   len, lm;
78
79         roff_term_pre_br(p, n);
80         lm = p->tcol->offset;
81         nc1 = n->child->next;
82         while (nc1 != NULL) {
83                 nc2 = nc1;
84                 len = 0;
85                 do {
86                         if (nc2->type == ROFFT_TEXT) {
87                                 if (len)
88                                         len++;
89                                 len += term_strlen(p, nc2->string);
90                         }
91                         nc2 = nc2->next;
92                 } while (nc2 != NULL && (nc2->type != ROFFT_TEXT ||
93                     (nc2->flags & NODE_LINE) == 0));
94                 p->tcol->offset = len >= p->tcol->rmargin ? 0 :
95                     lm + len >= p->tcol->rmargin ? p->tcol->rmargin - len :
96                     n->tok == ROFF_rj ? p->tcol->rmargin - len :
97                     (lm + p->tcol->rmargin - len) / 2;
98                 while (nc1 != nc2) {
99                         if (nc1->type == ROFFT_TEXT)
100                                 term_word(p, nc1->string);
101                         else
102                                 roff_term_pre(p, nc1);
103                         nc1 = nc1->next;
104                 }
105                 p->flags |= TERMP_NOSPACE;
106                 term_flushln(p);
107         }
108         p->tcol->offset = lm;
109 }
110
111 static void
112 roff_term_pre_ft(ROFF_TERM_ARGS)
113 {
114         switch (*n->child->string) {
115         case '4':
116         case '3':
117         case 'B':
118                 term_fontrepl(p, TERMFONT_BOLD);
119                 break;
120         case '2':
121         case 'I':
122                 term_fontrepl(p, TERMFONT_UNDER);
123                 break;
124         case 'P':
125                 term_fontlast(p);
126                 break;
127         case '1':
128         case 'C':
129         case 'R':
130                 term_fontrepl(p, TERMFONT_NONE);
131                 break;
132         default:
133                 break;
134         }
135 }
136
137 static void
138 roff_term_pre_ll(ROFF_TERM_ARGS)
139 {
140         term_setwidth(p, n->child != NULL ? n->child->string : NULL);
141 }
142
143 static void
144 roff_term_pre_mc(ROFF_TERM_ARGS)
145 {
146         if (p->col) {
147                 p->flags |= TERMP_NOBREAK;
148                 term_flushln(p);
149                 p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE);
150         }
151         if (n->child != NULL) {
152                 p->mc = n->child->string;
153                 p->flags |= TERMP_NEWMC;
154         } else
155                 p->flags |= TERMP_ENDMC;
156 }
157
158 static void
159 roff_term_pre_po(ROFF_TERM_ARGS)
160 {
161         struct roffsu    su;
162         static int       po, polast;
163         int              ponew;
164
165         if (n->child != NULL &&
166             a2roffsu(n->child->string, &su, SCALE_EM) != NULL) {
167                 ponew = term_hen(p, &su);
168                 if (*n->child->string == '+' ||
169                     *n->child->string == '-')
170                         ponew += po;
171         } else
172                 ponew = polast;
173         polast = po;
174         po = ponew;
175
176         ponew = po - polast + (int)p->tcol->offset;
177         p->tcol->offset = ponew > 0 ? ponew : 0;
178 }
179
180 static void
181 roff_term_pre_sp(ROFF_TERM_ARGS)
182 {
183         struct roffsu    su;
184         int              len;
185
186         if (n->child != NULL) {
187                 if (a2roffsu(n->child->string, &su, SCALE_VS) == NULL)
188                         su.scale = 1.0;
189                 len = term_vspan(p, &su);
190         } else
191                 len = 1;
192
193         if (len < 0)
194                 p->skipvsp -= len;
195         else
196                 while (len--)
197                         term_vspace(p);
198
199         roff_term_pre_br(p, n);
200 }
201
202 static void
203 roff_term_pre_ta(ROFF_TERM_ARGS)
204 {
205         term_tab_set(p, NULL);
206         for (n = n->child; n != NULL; n = n->next)
207                 term_tab_set(p, n->string);
208 }
209
210 static void
211 roff_term_pre_ti(ROFF_TERM_ARGS)
212 {
213         struct roffsu    su;
214         const char      *cp;
215         int              len, sign;
216
217         roff_term_pre_br(p, n);
218
219         if (n->child == NULL)
220                 return;
221         cp = n->child->string;
222         if (*cp == '+') {
223                 sign = 1;
224                 cp++;
225         } else if (*cp == '-') {
226                 sign = -1;
227                 cp++;
228         } else
229                 sign = 0;
230
231         if (a2roffsu(cp, &su, SCALE_EM) == NULL)
232                 return;
233         len = term_hen(p, &su);
234
235         if (sign == 0) {
236                 p->ti = len - p->tcol->offset;
237                 p->tcol->offset = len;
238         } else if (sign == 1) {
239                 p->ti = len;
240                 p->tcol->offset += len;
241         } else if ((size_t)len < p->tcol->offset) {
242                 p->ti = -len;
243                 p->tcol->offset -= len;
244         } else {
245                 p->ti = -p->tcol->offset;
246                 p->tcol->offset = 0;
247         }
248 }