1 /* $OpenBSD: roff_term.c,v 1.20 2020/09/03 17:37:06 schwarze Exp $ */
3 * Copyright (c) 2010,2014,2015,2017-2020 Ingo Schwarze <schwarze@openbsd.org>
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.
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.
19 #include <sys/types.h>
30 #define ROFF_TERM_ARGS struct termp *p, const struct roff_node *n
32 typedef void (*roff_term_pre_fp
)(ROFF_TERM_ARGS
);
34 static void roff_term_pre_br(ROFF_TERM_ARGS
);
35 static void roff_term_pre_ce(ROFF_TERM_ARGS
);
36 static void roff_term_pre_ft(ROFF_TERM_ARGS
);
37 static void roff_term_pre_ll(ROFF_TERM_ARGS
);
38 static void roff_term_pre_mc(ROFF_TERM_ARGS
);
39 static void roff_term_pre_po(ROFF_TERM_ARGS
);
40 static void roff_term_pre_sp(ROFF_TERM_ARGS
);
41 static void roff_term_pre_ta(ROFF_TERM_ARGS
);
42 static void roff_term_pre_ti(ROFF_TERM_ARGS
);
44 static const roff_term_pre_fp roff_term_pre_acts
[ROFF_MAX
] = {
45 roff_term_pre_br
, /* br */
46 roff_term_pre_ce
, /* ce */
47 roff_term_pre_br
, /* fi */
48 roff_term_pre_ft
, /* ft */
49 roff_term_pre_ll
, /* ll */
50 roff_term_pre_mc
, /* mc */
51 roff_term_pre_br
, /* nf */
52 roff_term_pre_po
, /* po */
53 roff_term_pre_ce
, /* rj */
54 roff_term_pre_sp
, /* sp */
55 roff_term_pre_ta
, /* ta */
56 roff_term_pre_ti
, /* ti */
61 roff_term_pre(struct termp
*p
, const struct roff_node
*n
)
63 assert(n
->tok
< ROFF_MAX
);
64 (*roff_term_pre_acts
[n
->tok
])(p
, n
);
68 roff_term_pre_br(ROFF_TERM_ARGS
)
71 if (p
->flags
& TERMP_BRIND
) {
72 p
->tcol
->offset
= p
->tcol
->rmargin
;
73 p
->tcol
->rmargin
= p
->maxrmargin
;
75 p
->flags
&= ~(TERMP_NOBREAK
| TERMP_BRIND
);
76 p
->flags
|= TERMP_NOSPACE
;
81 roff_term_pre_ce(ROFF_TERM_ARGS
)
83 const struct roff_node
*nc1
, *nc2
;
85 roff_term_pre_br(p
, n
);
86 p
->flags
|= n
->tok
== ROFF_ce
? TERMP_CENTER
: TERMP_RIGHT
;
92 } while (nc2
!= NULL
&& (nc2
->type
!= ROFFT_TEXT
||
93 (nc2
->flags
& NODE_LINE
) == 0));
95 if (nc1
->type
== ROFFT_TEXT
)
96 term_word(p
, nc1
->string
);
98 roff_term_pre(p
, nc1
);
101 p
->flags
|= TERMP_NOSPACE
;
104 p
->flags
&= ~(TERMP_CENTER
| TERMP_RIGHT
);
108 roff_term_pre_ft(ROFF_TERM_ARGS
)
112 cp
= n
->child
->string
;
113 switch (mandoc_font(cp
, (int)strlen(cp
))) {
114 case ESCAPE_FONTBOLD
:
115 term_fontrepl(p
, TERMFONT_BOLD
);
117 case ESCAPE_FONTITALIC
:
118 term_fontrepl(p
, TERMFONT_UNDER
);
121 term_fontrepl(p
, TERMFONT_BI
);
123 case ESCAPE_FONTPREV
:
126 case ESCAPE_FONTROMAN
:
128 term_fontrepl(p
, TERMFONT_NONE
);
136 roff_term_pre_ll(ROFF_TERM_ARGS
)
138 term_setwidth(p
, n
->child
!= NULL
? n
->child
->string
: NULL
);
142 roff_term_pre_mc(ROFF_TERM_ARGS
)
145 p
->flags
|= TERMP_NOBREAK
;
147 p
->flags
&= ~(TERMP_NOBREAK
| TERMP_NOSPACE
);
149 if (n
->child
!= NULL
) {
150 p
->mc
= n
->child
->string
;
151 p
->flags
|= TERMP_NEWMC
;
153 p
->flags
|= TERMP_ENDMC
;
157 roff_term_pre_po(ROFF_TERM_ARGS
)
160 static int po
, pouse
, polast
;
163 /* Revert the currently active page offset. */
164 p
->tcol
->offset
-= pouse
;
166 /* Determine the requested page offset. */
167 if (n
->child
!= NULL
&&
168 a2roffsu(n
->child
->string
, &su
, SCALE_EM
) != NULL
) {
169 ponew
= term_hen(p
, &su
);
170 if (*n
->child
->string
== '+' ||
171 *n
->child
->string
== '-')
176 /* Remeber both the previous and the newly requested offset. */
180 /* Truncate to the range [-offset, 60], remember, and apply it. */
181 pouse
= po
>= 60 ? 60 :
182 po
< -(int)p
->tcol
->offset
? -p
->tcol
->offset
: po
;
183 p
->tcol
->offset
+= pouse
;
187 roff_term_pre_sp(ROFF_TERM_ARGS
)
192 if (n
->child
!= NULL
) {
193 if (a2roffsu(n
->child
->string
, &su
, SCALE_VS
) == NULL
)
195 len
= term_vspan(p
, &su
);
205 roff_term_pre_br(p
, n
);
209 roff_term_pre_ta(ROFF_TERM_ARGS
)
211 term_tab_set(p
, NULL
);
212 for (n
= n
->child
; n
!= NULL
; n
= n
->next
)
213 term_tab_set(p
, n
->string
);
217 roff_term_pre_ti(ROFF_TERM_ARGS
)
221 const size_t maxoff
= 72;
224 roff_term_pre_br(p
, n
);
226 if (n
->child
== NULL
)
228 cp
= n
->child
->string
;
232 } else if (*cp
== '-') {
238 if (a2roffsu(cp
, &su
, SCALE_EM
) == NULL
)
240 len
= term_hen(p
, &su
);
244 if (p
->tcol
->offset
+ len
<= maxoff
)
246 else if (p
->tcol
->offset
< maxoff
)
247 p
->ti
= maxoff
- p
->tcol
->offset
;
252 if ((size_t)len
< p
->tcol
->offset
)
255 p
->ti
= -p
->tcol
->offset
;
258 if ((size_t)len
> maxoff
)
260 p
->ti
= len
- p
->tcol
->offset
;
263 p
->tcol
->offset
+= p
->ti
;