6 #define R_F(wb) ((wb)->r_f >= 0 ? (wb)->r_f : n_f) /* current font */
7 #define R_S(wb) ((wb)->r_s >= 0 ? (wb)->r_s : n_s) /* current size */
9 void wb_init(struct wb
*wb
)
11 memset(wb
, 0, sizeof(*wb
));
19 void wb_done(struct wb
*wb
)
24 /* update wb->st and wb->sb */
25 static void wb_stsb(struct wb
*wb
)
27 wb
->st
= MIN(wb
->st
, wb
->v
- SC_HT
);
28 wb
->sb
= MAX(wb
->sb
, wb
->v
);
31 /* append font and size to the buffer if needed */
32 static void wb_font(struct wb
*wb
)
34 if (wb
->f
!= R_F(wb
)) {
35 sbuf_printf(&wb
->sbuf
, "%cf(%02d", c_ec
, R_F(wb
));
38 if (wb
->s
!= R_S(wb
)) {
39 sbuf_printf(&wb
->sbuf
, "%cs(%02d", c_ec
, R_S(wb
));
45 void wb_hmov(struct wb
*wb
, int n
)
48 sbuf_printf(&wb
->sbuf
, "%ch'%du'", c_ec
, n
);
51 void wb_vmov(struct wb
*wb
, int n
)
54 sbuf_printf(&wb
->sbuf
, "%cv'%du'", c_ec
, n
);
57 void wb_els(struct wb
*wb
, int els
)
59 if (els
> wb
->els_pos
)
61 if (els
< wb
->els_neg
)
63 sbuf_printf(&wb
->sbuf
, "%cx'%du'", c_ec
, els
);
66 void wb_etc(struct wb
*wb
, char *x
)
69 sbuf_printf(&wb
->sbuf
, "%cX\x02%s\x02", c_ec
, x
);
72 void wb_put(struct wb
*wb
, char *c
)
80 wb_hmov(wb
, charwid(dev_spacewid(), R_S(wb
)));
83 if (c
[0] == '\t' || c
[0] == '\x01' ||
84 (c
[0] == c_ni
&& (c
[1] == '\t' || c
[1] == '\x01'))) {
85 sbuf_append(&wb
->sbuf
, c
);
88 g
= dev_glyph(c
, R_F(wb
));
90 sbuf_append(&wb
->sbuf
, c
);
91 if (strcmp(c_hc
, c
)) {
92 wb
->h
+= charwid(g
? g
->wid
: SC_DW
, R_S(wb
));
93 wb
->ct
|= g
? g
->type
: 0;
98 int wb_part(struct wb
*wb
)
103 void wb_setpart(struct wb
*wb
)
108 void wb_drawl(struct wb
*wb
, int h
, int v
)
111 sbuf_printf(&wb
->sbuf
, "%cD'l %du %du'", c_ec
, h
, v
);
117 void wb_drawc(struct wb
*wb
, int r
)
120 sbuf_printf(&wb
->sbuf
, "%cD'c %du'", c_ec
, r
);
124 void wb_drawe(struct wb
*wb
, int h
, int v
)
127 sbuf_printf(&wb
->sbuf
, "%cD'e %du %du'", c_ec
, h
, v
);
131 void wb_drawa(struct wb
*wb
, int h1
, int v1
, int h2
, int v2
)
134 sbuf_printf(&wb
->sbuf
, "%cD'a %du %du %du %du'", c_ec
, h1
, v1
, h2
, v2
);
140 void wb_drawxbeg(struct wb
*wb
, int c
)
143 sbuf_printf(&wb
->sbuf
, "%cD'%c", c_ec
, c
);
146 void wb_drawxdot(struct wb
*wb
, int h
, int v
)
148 sbuf_printf(&wb
->sbuf
, " %du %du", h
, v
);
154 void wb_drawxend(struct wb
*wb
)
156 sbuf_printf(&wb
->sbuf
, "'");
159 static void wb_reset(struct wb
*wb
)
165 static void wb_putc(struct wb
*wb
, int t
, char *s
)
178 wb_hmov(wb
, atoi(s
));
184 wb_vmov(wb
, atoi(s
));
195 void wb_cat(struct wb
*wb
, struct wb
*src
)
197 char *s
= sbuf_buf(&src
->sbuf
);
200 while ((c
= out_readc(&s
, d
)) >= 0)
209 int wb_wid(struct wb
*wb
)
214 int wb_empty(struct wb
*wb
)
216 return sbuf_empty(&wb
->sbuf
);
219 void wb_wconf(struct wb
*wb
, int *ct
, int *st
, int *sb
)
226 /* skip troff requests; return 1 if read c_hc */
227 static int skipreqs(char **s
, struct wb
*w1
)
233 while ((c
= out_readc(s
, d
)) > 0) {
237 if (c
< 0 || !strcmp(c_hc
, d
))
243 static char *dashpos(char *s
, int w
, struct wb
*w1
, int any
)
249 while ((c
= out_readc(&s
, d
)) == 0) {
251 if (wb_wid(w1
) > w
&& (!any
|| r
))
253 if (!strcmp("-", d
) || (d
[0] == c_ec
&& (!strcmp("(em", d
+ 1) ||
254 !strcmp("(hy", d
+ 1))))
260 static int wb_dashwid(struct wb
*wb
)
262 struct glyph
*g
= dev_glyph("hy", R_F(wb
));
263 return charwid(g
? g
->wid
: SC_DW
, R_S(wb
));
266 static char *indicatorpos(char *s
, int w
, struct wb
*w1
, int flg
)
272 while ((c
= out_readc(&s
, d
)) == 0) {
274 if (wb_wid(w1
) + wb_dashwid(w1
) > w
&& (!(flg
& HY_ANY
) || r
))
276 if (!strcmp(c_hc
, d
))
282 static char *hyphpos(char *s
, int w
, struct wb
*w1
, int flg
)
288 char *hy_beg
, *hy_wid
= NULL
, *hy_end
= NULL
;
294 while ((c
= out_readc(&s
, d
)) == 0) {
296 if (wb_wid(w1
) + wb_dashwid(w1
) <= w
)
300 wp
= strchr(wp
, '\0');
302 if (strlen(word
) < 4)
304 hyphenate(hyph
, word
);
305 beg
= flg
& HY_FIRSTTWO
? 3 : 2;
306 end
= hy_end
- hy_beg
- (flg
& HY_FINAL
? 1 : 0);
307 for (i
= beg
; i
< end
; i
++)
308 if (hyph
[i
] && (hy_beg
+ i
<= hy_wid
|| ((flg
& HY_ANY
) && !r
)))
313 static void dohyph(char *s
, char *pos
, int dash
, struct wb
*w1
, struct wb
*w2
)
316 char hy
[GNLEN
] = {c_ec
, '(', 'h', 'y'};
320 while (s
!= pos
&& (c
= out_readc(&s
, d
)) >= 0)
326 while ((c
= out_readc(&s
, d
)) >= 0)
330 /* hyphenate wb into w1 and w2; return zero on success */
331 int wb_hyph(struct wb
*wb
, int w
, struct wb
*w1
, struct wb
*w2
, int flg
)
333 char *s
= sbuf_buf(&wb
->sbuf
);
335 if (skipreqs(&s
, w1
))
337 dp
= dashpos(sbuf_buf(&wb
->sbuf
), w
, w1
, flg
& HY_ANY
);
338 hp
= indicatorpos(sbuf_buf(&wb
->sbuf
), w
, w1
, flg
& HY_ANY
);
339 p
= flg
& HY_ANY
? MIN(dp
, hp
) : MAX(dp
, hp
);
340 if (!p
&& flg
& HY_MASK
)
341 p
= hyphpos(sbuf_buf(&wb
->sbuf
), w
, w1
, flg
& HY_ANY
);
343 dohyph(sbuf_buf(&wb
->sbuf
), p
, p
!= dp
, w1
, w2
);