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 */
8 #define R_M(wb) ((wb)->r_m >= 0 ? (wb)->r_m : n_m) /* current color */
10 void wb_init(struct wb
*wb
)
12 memset(wb
, 0, sizeof(*wb
));
22 void wb_done(struct wb
*wb
)
27 /* update wb->st and wb->sb */
28 static void wb_stsb(struct wb
*wb
)
30 wb
->st
= MIN(wb
->st
, wb
->v
- SC_HT
);
31 wb
->sb
= MAX(wb
->sb
, wb
->v
);
34 /* append font and size to the buffer if needed */
35 static void wb_font(struct wb
*wb
)
37 if (wb
->f
!= R_F(wb
)) {
38 sbuf_printf(&wb
->sbuf
, "%cf(%02d", c_ec
, R_F(wb
));
41 if (wb
->s
!= R_S(wb
)) {
42 sbuf_printf(&wb
->sbuf
, "%cs(%02d", c_ec
, R_S(wb
));
45 if (!n_cp
&& wb
->m
!= R_M(wb
)) {
46 sbuf_printf(&wb
->sbuf
, "%cm[%s]", c_ec
, clr_str(R_M(wb
)));
52 void wb_hmov(struct wb
*wb
, int n
)
55 sbuf_printf(&wb
->sbuf
, "%ch'%du'", c_ec
, n
);
58 void wb_vmov(struct wb
*wb
, int n
)
61 sbuf_printf(&wb
->sbuf
, "%cv'%du'", c_ec
, n
);
64 void wb_els(struct wb
*wb
, int els
)
66 if (els
> wb
->els_pos
)
68 if (els
< wb
->els_neg
)
70 sbuf_printf(&wb
->sbuf
, "%cx'%du'", c_ec
, els
);
73 void wb_etc(struct wb
*wb
, char *x
)
76 sbuf_printf(&wb
->sbuf
, "%cX\x02%s\x02", c_ec
, x
);
79 void wb_put(struct wb
*wb
, char *c
)
87 wb_hmov(wb
, charwid(dev_spacewid(), R_S(wb
)));
90 if (c
[0] == '\t' || c
[0] == '\x01' ||
91 (c
[0] == c_ni
&& (c
[1] == '\t' || c
[1] == '\x01'))) {
92 sbuf_append(&wb
->sbuf
, c
);
95 g
= dev_glyph(c
, R_F(wb
));
97 if (!c
[1] || c
[0] == c_ec
|| c
[0] == c_ni
||
98 utf8len((unsigned char) c
[0]) == strlen(c
)) {
99 if (c
[0] == c_ni
&& c
[1] == c_ec
)
100 sbuf_printf(&wb
->sbuf
, "%c%c", c_ec
, c_ec
);
102 sbuf_append(&wb
->sbuf
, c
);
105 sbuf_printf(&wb
->sbuf
, "%c(%s", c_ec
, c
);
107 sbuf_printf(&wb
->sbuf
, "%cC'%s'", c_ec
, c
);
109 if (strcmp(c_hc
, c
)) {
110 strcpy(wb
->prev_c
, c
);
111 wb
->prev_l
= sbuf_len(&wb
->sbuf
);
113 wb
->h
+= charwid(g
? g
->wid
: SC_DW
, R_S(wb
));
114 wb
->ct
|= g
? g
->type
: 0;
119 /* return zero if c formed a ligature with its previous character */
120 int wb_lig(struct wb
*wb
, char *c
)
123 if (wb
->prev_l
!= sbuf_len(&wb
->sbuf
) || !wb
->prev_c
[0])
125 sprintf(lig
, "%s%s", wb
->prev_c
, c
);
126 if (font_lig(dev_font(R_F(wb
)), lig
)) {
135 /* return 0 if pairwise kerning was done */
136 int wb_kern(struct wb
*wb
, char *c
)
139 if (wb
->prev_l
!= sbuf_len(&wb
->sbuf
) || !wb
->prev_c
[0])
141 val
= font_kern(dev_font(R_F(wb
)), wb
->prev_c
, c
);
143 wb_hmov(wb
, charwid(val
, R_S(wb
)));
147 int wb_part(struct wb
*wb
)
152 void wb_setpart(struct wb
*wb
)
157 void wb_drawl(struct wb
*wb
, int h
, int v
)
160 sbuf_printf(&wb
->sbuf
, "%cD'l %du %du'", c_ec
, h
, v
);
166 void wb_drawc(struct wb
*wb
, int r
)
169 sbuf_printf(&wb
->sbuf
, "%cD'c %du'", c_ec
, r
);
173 void wb_drawe(struct wb
*wb
, int h
, int v
)
176 sbuf_printf(&wb
->sbuf
, "%cD'e %du %du'", c_ec
, h
, v
);
180 void wb_drawa(struct wb
*wb
, int h1
, int v1
, int h2
, int v2
)
183 sbuf_printf(&wb
->sbuf
, "%cD'a %du %du %du %du'", c_ec
, h1
, v1
, h2
, v2
);
189 void wb_drawxbeg(struct wb
*wb
, int c
)
192 sbuf_printf(&wb
->sbuf
, "%cD'%c", c_ec
, c
);
195 void wb_drawxdot(struct wb
*wb
, int h
, int v
)
197 sbuf_printf(&wb
->sbuf
, " %du %du", h
, v
);
203 void wb_drawxend(struct wb
*wb
)
205 sbuf_printf(&wb
->sbuf
, "'");
208 static void wb_reset(struct wb
*wb
)
214 static void wb_putc(struct wb
*wb
, int t
, char *s
)
228 wb_hmov(wb
, atoi(s
));
231 wb
->r_m
= clr_get(s
);
237 wb_vmov(wb
, atoi(s
));
248 void wb_cat(struct wb
*wb
, struct wb
*src
)
250 char *s
= sbuf_buf(&src
->sbuf
);
253 while ((c
= out_readc(&s
, d
)) >= 0)
263 int wb_wid(struct wb
*wb
)
268 int wb_empty(struct wb
*wb
)
270 return sbuf_empty(&wb
->sbuf
);
273 void wb_wconf(struct wb
*wb
, int *ct
, int *st
, int *sb
)
280 /* skip troff requests; return 1 if read c_hc */
281 static int skipreqs(char **s
, struct wb
*w1
)
287 while ((c
= out_readc(s
, d
)) > 0) {
291 if (c
< 0 || !strcmp(c_hc
, d
))
297 static char *dashpos(char *s
, int w
, struct wb
*w1
, int any
)
303 while ((c
= out_readc(&s
, d
)) >= 0) {
305 if (wb_wid(w1
) > w
&& (!any
|| r
))
307 if (!c
&& (!strcmp("-", d
) || (!strcmp("em", d
) || !strcmp("hy", d
))))
313 static int wb_dashwid(struct wb
*wb
)
315 struct glyph
*g
= dev_glyph("hy", R_F(wb
));
316 return charwid(g
? g
->wid
: SC_DW
, R_S(wb
));
319 static char *indicatorpos(char *s
, int w
, struct wb
*w1
, int flg
)
325 while ((c
= out_readc(&s
, d
)) >= 0) {
327 if (wb_wid(w1
) + wb_dashwid(w1
) > w
&& (!(flg
& HY_ANY
) || r
))
329 if (!c
&& !strcmp(c_hc
, d
))
335 static char *hyphpos(char *s
, int w
, struct wb
*w1
, int flg
)
337 char *map
[ILNLEN
] = {NULL
}; /* mapping from word to s */
338 int fits
[ILNLEN
] = {0}; /* fits[i] if word[0..i]- fits w */
344 char *wp
= word
, *we
= word
+ sizeof(word
);
348 while ((c
= out_readc(&s
, d
)) >= 0 && wp
+ strlen(d
) + 1 < we
) {
352 map
[wp
- word
] = prev_s
;
353 wp
= strchr(wp
, '\0');
354 fits
[wp
- word
] = wb_wid(w1
) + wb_dashwid(w1
) <= w
;
358 if (strlen(word
) < 4)
360 hyphenate(hyph
, word
);
361 beg
= flg
& HY_FIRSTTWO
? 3 : 2;
362 end
= strlen(word
) - (flg
& HY_FINAL
? 2 : 1);
363 for (i
= beg
; i
< end
; i
++)
364 if (map
[i
] && hyph
[i
] && (fits
[i
] || ((flg
& HY_ANY
) && !r
)))
369 static void dohyph(char *s
, char *pos
, int dash
, struct wb
*w1
, struct wb
*w2
)
375 while (s
!= pos
&& (c
= out_readc(&s
, d
)) >= 0)
378 wb_putc(w1
, 0, "hy");
382 while ((c
= out_readc(&s
, d
)) >= 0)
386 /* hyphenate wb into w1 and w2; return zero on success */
387 int wb_hyph(struct wb
*wb
, int w
, struct wb
*w1
, struct wb
*w2
, int flg
)
389 char *s
= sbuf_buf(&wb
->sbuf
);
391 if (skipreqs(&s
, w1
))
393 dp
= dashpos(sbuf_buf(&wb
->sbuf
), w
, w1
, flg
& HY_ANY
);
394 hp
= indicatorpos(sbuf_buf(&wb
->sbuf
), w
, w1
, flg
& HY_ANY
);
395 p
= flg
& HY_ANY
? MIN(dp
, hp
) : MAX(dp
, hp
);
396 if (!p
&& flg
& HY_MASK
)
397 p
= hyphpos(sbuf_buf(&wb
->sbuf
), w
, w1
, flg
& HY_ANY
);
399 dohyph(sbuf_buf(&wb
->sbuf
), p
, p
!= dp
, w1
, w2
);