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