1 /* $Id: mdoc_html.c,v 1.169 2011/05/17 11:38:18 kristaps Exp $ */
3 * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
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.
21 #include <sys/types.h>
39 #define MDOC_ARGS const struct mdoc_meta *m, \
40 const struct mdoc_node *n, \
44 #define MIN(a,b) ((/*CONSTCOND*/(a)<(b))?(a):(b))
48 int (*pre)(MDOC_ARGS);
49 void (*post)(MDOC_ARGS);
52 static void print_mdoc(MDOC_ARGS);
53 static void print_mdoc_head(MDOC_ARGS);
54 static void print_mdoc_node(MDOC_ARGS);
55 static void print_mdoc_nodelist(MDOC_ARGS);
56 static void synopsis_pre(struct html *,
57 const struct mdoc_node *);
59 static void a2width(const char *, struct roffsu *);
60 static void a2offs(const char *, struct roffsu *);
62 static void mdoc_root_post(MDOC_ARGS);
63 static int mdoc_root_pre(MDOC_ARGS);
65 static void mdoc__x_post(MDOC_ARGS);
66 static int mdoc__x_pre(MDOC_ARGS);
67 static int mdoc_ad_pre(MDOC_ARGS);
68 static int mdoc_an_pre(MDOC_ARGS);
69 static int mdoc_ap_pre(MDOC_ARGS);
70 static int mdoc_ar_pre(MDOC_ARGS);
71 static int mdoc_bd_pre(MDOC_ARGS);
72 static int mdoc_bf_pre(MDOC_ARGS);
73 static void mdoc_bk_post(MDOC_ARGS);
74 static int mdoc_bk_pre(MDOC_ARGS);
75 static int mdoc_bl_pre(MDOC_ARGS);
76 static int mdoc_bt_pre(MDOC_ARGS);
77 static int mdoc_bx_pre(MDOC_ARGS);
78 static int mdoc_cd_pre(MDOC_ARGS);
79 static int mdoc_d1_pre(MDOC_ARGS);
80 static int mdoc_dv_pre(MDOC_ARGS);
81 static int mdoc_fa_pre(MDOC_ARGS);
82 static int mdoc_fd_pre(MDOC_ARGS);
83 static int mdoc_fl_pre(MDOC_ARGS);
84 static int mdoc_fn_pre(MDOC_ARGS);
85 static int mdoc_ft_pre(MDOC_ARGS);
86 static int mdoc_em_pre(MDOC_ARGS);
87 static int mdoc_er_pre(MDOC_ARGS);
88 static int mdoc_ev_pre(MDOC_ARGS);
89 static int mdoc_ex_pre(MDOC_ARGS);
90 static void mdoc_fo_post(MDOC_ARGS);
91 static int mdoc_fo_pre(MDOC_ARGS);
92 static int mdoc_ic_pre(MDOC_ARGS);
93 static int mdoc_igndelim_pre(MDOC_ARGS);
94 static int mdoc_in_pre(MDOC_ARGS);
95 static int mdoc_it_pre(MDOC_ARGS);
96 static int mdoc_lb_pre(MDOC_ARGS);
97 static int mdoc_li_pre(MDOC_ARGS);
98 static int mdoc_lk_pre(MDOC_ARGS);
99 static int mdoc_mt_pre(MDOC_ARGS);
100 static int mdoc_ms_pre(MDOC_ARGS);
101 static int mdoc_nd_pre(MDOC_ARGS);
102 static int mdoc_nm_pre(MDOC_ARGS);
103 static int mdoc_ns_pre(MDOC_ARGS);
104 static int mdoc_pa_pre(MDOC_ARGS);
105 static void mdoc_pf_post(MDOC_ARGS);
106 static int mdoc_pp_pre(MDOC_ARGS);
107 static void mdoc_quote_post(MDOC_ARGS);
108 static int mdoc_quote_pre(MDOC_ARGS);
109 static int mdoc_rs_pre(MDOC_ARGS);
110 static int mdoc_rv_pre(MDOC_ARGS);
111 static int mdoc_sh_pre(MDOC_ARGS);
112 static int mdoc_sm_pre(MDOC_ARGS);
113 static int mdoc_sp_pre(MDOC_ARGS);
114 static int mdoc_ss_pre(MDOC_ARGS);
115 static int mdoc_sx_pre(MDOC_ARGS);
116 static int mdoc_sy_pre(MDOC_ARGS);
117 static int mdoc_ud_pre(MDOC_ARGS);
118 static int mdoc_va_pre(MDOC_ARGS);
119 static int mdoc_vt_pre(MDOC_ARGS);
120 static int mdoc_xr_pre(MDOC_ARGS);
121 static int mdoc_xx_pre(MDOC_ARGS);
123 static const struct htmlmdoc mdocs[MDOC_MAX] = {
124 {mdoc_ap_pre, NULL}, /* Ap */
125 {NULL, NULL}, /* Dd */
126 {NULL, NULL}, /* Dt */
127 {NULL, NULL}, /* Os */
128 {mdoc_sh_pre, NULL }, /* Sh */
129 {mdoc_ss_pre, NULL }, /* Ss */
130 {mdoc_pp_pre, NULL}, /* Pp */
131 {mdoc_d1_pre, NULL}, /* D1 */
132 {mdoc_d1_pre, NULL}, /* Dl */
133 {mdoc_bd_pre, NULL}, /* Bd */
134 {NULL, NULL}, /* Ed */
135 {mdoc_bl_pre, NULL}, /* Bl */
136 {NULL, NULL}, /* El */
137 {mdoc_it_pre, NULL}, /* It */
138 {mdoc_ad_pre, NULL}, /* Ad */
139 {mdoc_an_pre, NULL}, /* An */
140 {mdoc_ar_pre, NULL}, /* Ar */
141 {mdoc_cd_pre, NULL}, /* Cd */
142 {mdoc_fl_pre, NULL}, /* Cm */
143 {mdoc_dv_pre, NULL}, /* Dv */
144 {mdoc_er_pre, NULL}, /* Er */
145 {mdoc_ev_pre, NULL}, /* Ev */
146 {mdoc_ex_pre, NULL}, /* Ex */
147 {mdoc_fa_pre, NULL}, /* Fa */
148 {mdoc_fd_pre, NULL}, /* Fd */
149 {mdoc_fl_pre, NULL}, /* Fl */
150 {mdoc_fn_pre, NULL}, /* Fn */
151 {mdoc_ft_pre, NULL}, /* Ft */
152 {mdoc_ic_pre, NULL}, /* Ic */
153 {mdoc_in_pre, NULL}, /* In */
154 {mdoc_li_pre, NULL}, /* Li */
155 {mdoc_nd_pre, NULL}, /* Nd */
156 {mdoc_nm_pre, NULL}, /* Nm */
157 {mdoc_quote_pre, mdoc_quote_post}, /* Op */
158 {NULL, NULL}, /* Ot */
159 {mdoc_pa_pre, NULL}, /* Pa */
160 {mdoc_rv_pre, NULL}, /* Rv */
161 {NULL, NULL}, /* St */
162 {mdoc_va_pre, NULL}, /* Va */
163 {mdoc_vt_pre, NULL}, /* Vt */
164 {mdoc_xr_pre, NULL}, /* Xr */
165 {mdoc__x_pre, mdoc__x_post}, /* %A */
166 {mdoc__x_pre, mdoc__x_post}, /* %B */
167 {mdoc__x_pre, mdoc__x_post}, /* %D */
168 {mdoc__x_pre, mdoc__x_post}, /* %I */
169 {mdoc__x_pre, mdoc__x_post}, /* %J */
170 {mdoc__x_pre, mdoc__x_post}, /* %N */
171 {mdoc__x_pre, mdoc__x_post}, /* %O */
172 {mdoc__x_pre, mdoc__x_post}, /* %P */
173 {mdoc__x_pre, mdoc__x_post}, /* %R */
174 {mdoc__x_pre, mdoc__x_post}, /* %T */
175 {mdoc__x_pre, mdoc__x_post}, /* %V */
176 {NULL, NULL}, /* Ac */
177 {mdoc_quote_pre, mdoc_quote_post}, /* Ao */
178 {mdoc_quote_pre, mdoc_quote_post}, /* Aq */
179 {NULL, NULL}, /* At */
180 {NULL, NULL}, /* Bc */
181 {mdoc_bf_pre, NULL}, /* Bf */
182 {mdoc_quote_pre, mdoc_quote_post}, /* Bo */
183 {mdoc_quote_pre, mdoc_quote_post}, /* Bq */
184 {mdoc_xx_pre, NULL}, /* Bsx */
185 {mdoc_bx_pre, NULL}, /* Bx */
186 {NULL, NULL}, /* Db */
187 {NULL, NULL}, /* Dc */
188 {mdoc_quote_pre, mdoc_quote_post}, /* Do */
189 {mdoc_quote_pre, mdoc_quote_post}, /* Dq */
190 {NULL, NULL}, /* Ec */ /* FIXME: no space */
191 {NULL, NULL}, /* Ef */
192 {mdoc_em_pre, NULL}, /* Em */
193 {NULL, NULL}, /* Eo */
194 {mdoc_xx_pre, NULL}, /* Fx */
195 {mdoc_ms_pre, NULL}, /* Ms */
196 {mdoc_igndelim_pre, NULL}, /* No */
197 {mdoc_ns_pre, NULL}, /* Ns */
198 {mdoc_xx_pre, NULL}, /* Nx */
199 {mdoc_xx_pre, NULL}, /* Ox */
200 {NULL, NULL}, /* Pc */
201 {mdoc_igndelim_pre, mdoc_pf_post}, /* Pf */
202 {mdoc_quote_pre, mdoc_quote_post}, /* Po */
203 {mdoc_quote_pre, mdoc_quote_post}, /* Pq */
204 {NULL, NULL}, /* Qc */
205 {mdoc_quote_pre, mdoc_quote_post}, /* Ql */
206 {mdoc_quote_pre, mdoc_quote_post}, /* Qo */
207 {mdoc_quote_pre, mdoc_quote_post}, /* Qq */
208 {NULL, NULL}, /* Re */
209 {mdoc_rs_pre, NULL}, /* Rs */
210 {NULL, NULL}, /* Sc */
211 {mdoc_quote_pre, mdoc_quote_post}, /* So */
212 {mdoc_quote_pre, mdoc_quote_post}, /* Sq */
213 {mdoc_sm_pre, NULL}, /* Sm */
214 {mdoc_sx_pre, NULL}, /* Sx */
215 {mdoc_sy_pre, NULL}, /* Sy */
216 {NULL, NULL}, /* Tn */
217 {mdoc_xx_pre, NULL}, /* Ux */
218 {NULL, NULL}, /* Xc */
219 {NULL, NULL}, /* Xo */
220 {mdoc_fo_pre, mdoc_fo_post}, /* Fo */
221 {NULL, NULL}, /* Fc */
222 {mdoc_quote_pre, mdoc_quote_post}, /* Oo */
223 {NULL, NULL}, /* Oc */
224 {mdoc_bk_pre, mdoc_bk_post}, /* Bk */
225 {NULL, NULL}, /* Ek */
226 {mdoc_bt_pre, NULL}, /* Bt */
227 {NULL, NULL}, /* Hf */
228 {NULL, NULL}, /* Fr */
229 {mdoc_ud_pre, NULL}, /* Ud */
230 {mdoc_lb_pre, NULL}, /* Lb */
231 {mdoc_pp_pre, NULL}, /* Lp */
232 {mdoc_lk_pre, NULL}, /* Lk */
233 {mdoc_mt_pre, NULL}, /* Mt */
234 {mdoc_quote_pre, mdoc_quote_post}, /* Brq */
235 {mdoc_quote_pre, mdoc_quote_post}, /* Bro */
236 {NULL, NULL}, /* Brc */
237 {mdoc__x_pre, mdoc__x_post}, /* %C */
238 {NULL, NULL}, /* Es */ /* TODO */
239 {NULL, NULL}, /* En */ /* TODO */
240 {mdoc_xx_pre, NULL}, /* Dx */
241 {mdoc__x_pre, mdoc__x_post}, /* %Q */
242 {mdoc_sp_pre, NULL}, /* br */
243 {mdoc_sp_pre, NULL}, /* sp */
244 {mdoc__x_pre, mdoc__x_post}, /* %U */
245 {NULL, NULL}, /* Ta */
248 static const char * const lists[LIST_MAX] = {
264 html_mdoc(void *arg, const struct mdoc *m)
269 h = (struct html *)arg;
272 t = print_otag(h, TAG_HTML, 0, NULL);
273 print_mdoc(mdoc_meta(m), mdoc_node(m), h);
281 * Calculate the scaling unit passed in a `-width' argument. This uses
282 * either a native scaling unit (e.g., 1i, 2m) or the string length of
286 a2width(const char *p, struct roffsu *su)
289 if ( ! a2roffsu(p, su, SCALE_MAX)) {
291 su->scale = html_strlen(p);
297 * See the same function in mdoc_term.c for documentation.
300 synopsis_pre(struct html *h, const struct mdoc_node *n)
303 if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
306 if (n->prev->tok == n->tok &&
310 print_otag(h, TAG_BR, 0, NULL);
314 switch (n->prev->tok) {
324 print_otag(h, TAG_P, 0, NULL);
327 if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
328 print_otag(h, TAG_P, 0, NULL);
333 print_otag(h, TAG_BR, 0, NULL);
340 * Calculate the scaling unit passed in an `-offset' argument. This
341 * uses either a native scaling unit (e.g., 1i, 2m), one of a set of
342 * predefined strings (indent, etc.), or the string length of the value.
345 a2offs(const char *p, struct roffsu *su)
348 /* FIXME: "right"? */
350 if (0 == strcmp(p, "left"))
351 SCALE_HS_INIT(su, 0);
352 else if (0 == strcmp(p, "indent"))
353 SCALE_HS_INIT(su, INDENT);
354 else if (0 == strcmp(p, "indent-two"))
355 SCALE_HS_INIT(su, INDENT * 2);
356 else if ( ! a2roffsu(p, su, SCALE_MAX)) {
358 su->scale = html_strlen(p);
364 print_mdoc(MDOC_ARGS)
368 t = print_otag(h, TAG_HEAD, 0, NULL);
369 print_mdoc_head(m, n, h);
372 t = print_otag(h, TAG_BODY, 0, NULL);
373 print_mdoc_nodelist(m, n, h);
380 print_mdoc_head(MDOC_ARGS)
385 bufcat_fmt(h, "%s(%s)", m->title, m->msec);
388 bufcat_fmt(h, " (%s)", m->arch);
390 print_otag(h, TAG_TITLE, 0, NULL);
391 print_text(h, h->buf);
396 print_mdoc_nodelist(MDOC_ARGS)
399 print_mdoc_node(m, n, h);
401 print_mdoc_nodelist(m, n->next, h);
406 print_mdoc_node(MDOC_ARGS)
417 child = mdoc_root_pre(m, n, h);
420 /* No tables in this mode... */
421 assert(NULL == h->tblt);
424 * Make sure that if we're in a literal mode already
425 * (i.e., within a <PRE>) don't print the newline.
427 if (' ' == *n->string && MDOC_LINE & n->flags)
428 if ( ! (HTML_LITERAL & h->flags))
429 print_otag(h, TAG_BR, 0, NULL);
430 if (MDOC_DELIMC & n->flags)
431 h->flags |= HTML_NOSPACE;
432 print_text(h, n->string);
433 if (MDOC_DELIMO & n->flags)
434 h->flags |= HTML_NOSPACE;
437 PAIR_CLASS_INIT(&tag, "eqn");
438 print_otag(h, TAG_SPAN, 1, &tag);
439 print_text(h, n->eqn->data);
443 * This will take care of initialising all of the table
444 * state data for the first table, then tearing it down
447 print_tbl(h, n->span);
451 * Close out the current table, if it's open, and unset
452 * the "meta" table state. This will be reopened on the
453 * next table element.
460 assert(NULL == h->tblt);
461 if (mdocs[n->tok].pre && ENDBODY_NOT == n->end)
462 child = (*mdocs[n->tok].pre)(m, n, h);
466 if (HTML_KEEP & h->flags) {
467 if (n->prev && n->prev->line != n->line) {
468 h->flags &= ~HTML_KEEP;
469 h->flags |= HTML_PREKEEP;
470 } else if (NULL == n->prev) {
471 if (n->parent && n->parent->line != n->line) {
472 h->flags &= ~HTML_KEEP;
473 h->flags |= HTML_PREKEEP;
478 if (child && n->child)
479 print_mdoc_nodelist(m, n->child, h);
485 mdoc_root_post(m, n, h);
490 if (mdocs[n->tok].post && ENDBODY_NOT == n->end)
491 (*mdocs[n->tok].post)(m, n, h);
498 mdoc_root_post(MDOC_ARGS)
500 struct htmlpair tag[3];
503 PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
504 PAIR_CLASS_INIT(&tag[1], "foot");
505 if (NULL == h->style) {
506 PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
507 t = print_otag(h, TAG_TABLE, 3, tag);
508 PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
509 print_otag(h, TAG_COL, 1, tag);
510 print_otag(h, TAG_COL, 1, tag);
512 t = print_otag(h, TAG_TABLE, 2, tag);
514 t = print_otag(h, TAG_TBODY, 0, NULL);
516 tt = print_otag(h, TAG_TR, 0, NULL);
518 PAIR_CLASS_INIT(&tag[0], "foot-date");
519 print_otag(h, TAG_TD, 1, tag);
521 print_text(h, m->date);
524 PAIR_CLASS_INIT(&tag[0], "foot-os");
525 if (NULL == h->style) {
526 PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
527 print_otag(h, TAG_TD, 2, tag);
529 print_otag(h, TAG_TD, 1, tag);
531 print_text(h, m->os);
538 mdoc_root_pre(MDOC_ARGS)
540 struct htmlpair tag[3];
542 char b[BUFSIZ], title[BUFSIZ];
544 strlcpy(b, m->vol, BUFSIZ);
547 strlcat(b, " (", BUFSIZ);
548 strlcat(b, m->arch, BUFSIZ);
549 strlcat(b, ")", BUFSIZ);
552 snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
554 PAIR_SUMMARY_INIT(&tag[0], "Document Header");
555 PAIR_CLASS_INIT(&tag[1], "head");
556 if (NULL == h->style) {
557 PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
558 t = print_otag(h, TAG_TABLE, 3, tag);
559 PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
560 print_otag(h, TAG_COL, 1, tag);
561 print_otag(h, TAG_COL, 1, tag);
562 print_otag(h, TAG_COL, 1, tag);
564 t = print_otag(h, TAG_TABLE, 2, tag);
566 print_otag(h, TAG_TBODY, 0, NULL);
568 tt = print_otag(h, TAG_TR, 0, NULL);
570 PAIR_CLASS_INIT(&tag[0], "head-ltitle");
571 print_otag(h, TAG_TD, 1, tag);
573 print_text(h, title);
576 PAIR_CLASS_INIT(&tag[0], "head-vol");
577 if (NULL == h->style) {
578 PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
579 print_otag(h, TAG_TD, 2, tag);
581 print_otag(h, TAG_TD, 1, tag);
586 PAIR_CLASS_INIT(&tag[0], "head-rtitle");
587 if (NULL == h->style) {
588 PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
589 print_otag(h, TAG_TD, 2, tag);
591 print_otag(h, TAG_TD, 1, tag);
593 print_text(h, title);
601 mdoc_sh_pre(MDOC_ARGS)
605 if (MDOC_BLOCK == n->type) {
606 PAIR_CLASS_INIT(&tag, "section");
607 print_otag(h, TAG_DIV, 1, &tag);
609 } else if (MDOC_BODY == n->type)
613 for (n = n->child; n; n = n->next) {
614 bufcat_id(h, n->string);
619 PAIR_ID_INIT(&tag, h->buf);
620 print_otag(h, TAG_H1, 1, &tag);
627 mdoc_ss_pre(MDOC_ARGS)
631 if (MDOC_BLOCK == n->type) {
632 PAIR_CLASS_INIT(&tag, "subsection");
633 print_otag(h, TAG_DIV, 1, &tag);
635 } else if (MDOC_BODY == n->type)
639 for (n = n->child; n; n = n->next) {
640 bufcat_id(h, n->string);
645 PAIR_ID_INIT(&tag, h->buf);
646 print_otag(h, TAG_H2, 1, &tag);
653 mdoc_fl_pre(MDOC_ARGS)
657 PAIR_CLASS_INIT(&tag, "flag");
658 print_otag(h, TAG_B, 1, &tag);
660 /* `Cm' has no leading hyphen. */
662 if (MDOC_Cm == n->tok)
665 print_text(h, "\\-");
668 h->flags |= HTML_NOSPACE;
669 else if (n->next && n->next->line == n->line)
670 h->flags |= HTML_NOSPACE;
678 mdoc_nd_pre(MDOC_ARGS)
682 if (MDOC_BODY != n->type)
685 /* XXX: this tag in theory can contain block elements. */
687 print_text(h, "\\(em");
688 PAIR_CLASS_INIT(&tag, "desc");
689 print_otag(h, TAG_SPAN, 1, &tag);
695 mdoc_nm_pre(MDOC_ARGS)
704 PAIR_CLASS_INIT(&tag, "name");
705 print_otag(h, TAG_B, 1, &tag);
706 if (NULL == n->child && m->name)
707 print_text(h, m->name);
710 print_otag(h, TAG_TD, 0, NULL);
711 if (NULL == n->child && m->name)
712 print_text(h, m->name);
715 print_otag(h, TAG_TD, 0, NULL);
722 PAIR_CLASS_INIT(&tag, "synopsis");
723 print_otag(h, TAG_TABLE, 1, &tag);
725 for (len = 0, n = n->child; n; n = n->next)
726 if (MDOC_TEXT == n->type)
727 len += html_strlen(n->string);
729 if (0 == len && m->name)
730 len = html_strlen(m->name);
732 SCALE_HS_INIT(&su, (double)len);
734 bufcat_su(h, "width", &su);
735 PAIR_STYLE_INIT(&tag, h);
736 print_otag(h, TAG_COL, 1, &tag);
737 print_otag(h, TAG_COL, 0, NULL);
738 print_otag(h, TAG_TBODY, 0, NULL);
739 print_otag(h, TAG_TR, 0, NULL);
746 mdoc_xr_pre(MDOC_ARGS)
748 struct htmlpair tag[2];
750 if (NULL == n->child)
753 PAIR_CLASS_INIT(&tag[0], "link-man");
756 buffmt_man(h, n->child->string,
758 n->child->next->string : NULL);
759 PAIR_HREF_INIT(&tag[1], h->buf);
760 print_otag(h, TAG_A, 2, tag);
762 print_otag(h, TAG_A, 1, tag);
765 print_text(h, n->string);
767 if (NULL == (n = n->next))
770 h->flags |= HTML_NOSPACE;
772 h->flags |= HTML_NOSPACE;
773 print_text(h, n->string);
774 h->flags |= HTML_NOSPACE;
782 mdoc_ns_pre(MDOC_ARGS)
785 if ( ! (MDOC_LINE & n->flags))
786 h->flags |= HTML_NOSPACE;
793 mdoc_ar_pre(MDOC_ARGS)
797 PAIR_CLASS_INIT(&tag, "arg");
798 print_otag(h, TAG_I, 1, &tag);
805 mdoc_xx_pre(MDOC_ARGS)
834 PAIR_CLASS_INIT(&tag, "unix");
835 print_otag(h, TAG_SPAN, 1, &tag);
840 h->flags |= HTML_KEEP;
841 print_text(h, n->child->string);
850 mdoc_bx_pre(MDOC_ARGS)
854 PAIR_CLASS_INIT(&tag, "unix");
855 print_otag(h, TAG_SPAN, 1, &tag);
857 if (NULL != (n = n->child)) {
858 print_text(h, n->string);
859 h->flags |= HTML_NOSPACE;
860 print_text(h, "BSD");
862 print_text(h, "BSD");
866 if (NULL != (n = n->next)) {
867 h->flags |= HTML_NOSPACE;
869 h->flags |= HTML_NOSPACE;
870 print_text(h, n->string);
878 mdoc_it_pre(MDOC_ARGS)
882 struct htmlpair tag[2];
883 const struct mdoc_node *bl;
886 while (bl && MDOC_Bl != bl->tok)
891 type = bl->norm->Bl.type;
894 PAIR_CLASS_INIT(&tag[0], lists[type]);
898 if (MDOC_HEAD == n->type) {
919 SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
920 bufcat_su(h, "margin-top", &su);
921 PAIR_STYLE_INIT(&tag[1], h);
922 print_otag(h, TAG_DT, 2, tag);
923 if (LIST_diag != type)
925 PAIR_CLASS_INIT(&tag[0], "diag");
926 print_otag(h, TAG_B, 1, tag);
933 } else if (MDOC_BODY == n->type) {
944 SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
945 bufcat_su(h, "margin-top", &su);
946 PAIR_STYLE_INIT(&tag[1], h);
947 print_otag(h, TAG_LI, 2, tag);
958 if (NULL == bl->norm->Bl.width) {
959 print_otag(h, TAG_DD, 1, tag);
962 a2width(bl->norm->Bl.width, &su);
963 bufcat_su(h, "margin-left", &su);
964 PAIR_STYLE_INIT(&tag[1], h);
965 print_otag(h, TAG_DD, 2, tag);
968 SCALE_VS_INIT(&su, ! bl->norm->Bl.comp);
969 bufcat_su(h, "margin-top", &su);
970 PAIR_STYLE_INIT(&tag[1], h);
971 print_otag(h, TAG_TD, 2, tag);
979 print_otag(h, TAG_TR, 1, tag);
991 mdoc_bl_pre(MDOC_ARGS)
994 struct htmlpair tag[3];
1000 if (MDOC_BODY == n->type) {
1001 if (LIST_column == n->norm->Bl.type)
1002 print_otag(h, TAG_TBODY, 0, NULL);
1006 if (MDOC_HEAD == n->type) {
1007 if (LIST_column != n->norm->Bl.type)
1011 * For each column, print out the <COL> tag with our
1012 * suggested width. The last column gets min-width, as
1013 * in terminal mode it auto-sizes to the width of the
1014 * screen and we want to preserve that behaviour.
1017 for (i = 0; i < (int)n->norm->Bl.ncols; i++) {
1018 a2width(n->norm->Bl.cols[i], &su);
1019 if (i < (int)n->norm->Bl.ncols - 1)
1020 bufcat_su(h, "width", &su);
1022 bufcat_su(h, "min-width", &su);
1023 PAIR_STYLE_INIT(&tag[0], h);
1024 print_otag(h, TAG_COL, 1, tag);
1030 SCALE_VS_INIT(&su, 0);
1031 bufcat_su(h, "margin-top", &su);
1032 bufcat_su(h, "margin-bottom", &su);
1033 PAIR_STYLE_INIT(&tag[0], h);
1035 assert(lists[n->norm->Bl.type]);
1036 strlcpy(buf, "list ", BUFSIZ);
1037 strlcat(buf, lists[n->norm->Bl.type], BUFSIZ);
1038 PAIR_INIT(&tag[1], ATTR_CLASS, buf);
1040 /* Set the block's left-hand margin. */
1042 if (n->norm->Bl.offs) {
1043 a2offs(n->norm->Bl.offs, &su);
1044 bufcat_su(h, "margin-left", &su);
1047 switch (n->norm->Bl.type) {
1055 print_otag(h, TAG_UL, 2, tag);
1058 print_otag(h, TAG_OL, 2, tag);
1069 print_otag(h, TAG_DL, 2, tag);
1072 print_otag(h, TAG_TABLE, 2, tag);
1084 mdoc_ex_pre(MDOC_ARGS)
1087 struct htmlpair tag;
1091 print_otag(h, TAG_BR, 0, NULL);
1093 PAIR_CLASS_INIT(&tag, "utility");
1095 print_text(h, "The");
1098 for (n = n->child; n; n = n->next) {
1099 assert(MDOC_TEXT == n->type);
1101 t = print_otag(h, TAG_B, 1, &tag);
1102 print_text(h, n->string);
1105 if (nchild > 2 && n->next) {
1106 h->flags |= HTML_NOSPACE;
1110 if (n->next && NULL == n->next->next)
1111 print_text(h, "and");
1115 print_text(h, "utilities exit");
1117 print_text(h, "utility exits");
1119 print_text(h, "0 on success, and >0 if an error occurs.");
1126 mdoc_em_pre(MDOC_ARGS)
1128 struct htmlpair tag;
1130 PAIR_CLASS_INIT(&tag, "emph");
1131 print_otag(h, TAG_SPAN, 1, &tag);
1138 mdoc_d1_pre(MDOC_ARGS)
1140 struct htmlpair tag[2];
1143 if (MDOC_BLOCK != n->type)
1146 SCALE_VS_INIT(&su, 0);
1148 bufcat_su(h, "margin-top", &su);
1149 bufcat_su(h, "margin-bottom", &su);
1150 PAIR_STYLE_INIT(&tag[0], h);
1151 print_otag(h, TAG_BLOCKQUOTE, 1, tag);
1153 /* BLOCKQUOTE needs a block body. */
1155 PAIR_CLASS_INIT(&tag[0], "display");
1156 print_otag(h, TAG_DIV, 1, tag);
1158 if (MDOC_Dl == n->tok) {
1159 PAIR_CLASS_INIT(&tag[0], "lit");
1160 print_otag(h, TAG_CODE, 1, tag);
1169 mdoc_sx_pre(MDOC_ARGS)
1171 struct htmlpair tag[2];
1175 for (n = n->child; n; n = n->next) {
1176 bufcat_id(h, n->string);
1181 PAIR_CLASS_INIT(&tag[0], "link-sec");
1182 PAIR_HREF_INIT(&tag[1], h->buf);
1184 print_otag(h, TAG_I, 1, tag);
1185 print_otag(h, TAG_A, 2, tag);
1192 mdoc_bd_pre(MDOC_ARGS)
1194 struct htmlpair tag[2];
1196 const struct mdoc_node *nn;
1199 if (MDOC_HEAD == n->type)
1202 if (MDOC_BLOCK == n->type) {
1203 comp = n->norm->Bd.comp;
1204 for (nn = n; nn && ! comp; nn = nn->parent) {
1205 if (MDOC_BLOCK != nn->type)
1207 if (MDOC_Ss == nn->tok || MDOC_Sh == nn->tok)
1213 print_otag(h, TAG_P, 0, NULL);
1217 SCALE_HS_INIT(&su, 0);
1218 if (n->norm->Bd.offs)
1219 a2offs(n->norm->Bd.offs, &su);
1222 bufcat_su(h, "margin-left", &su);
1223 PAIR_STYLE_INIT(&tag[0], h);
1225 if (DISP_unfilled != n->norm->Bd.type &&
1226 DISP_literal != n->norm->Bd.type) {
1227 PAIR_CLASS_INIT(&tag[1], "display");
1228 print_otag(h, TAG_DIV, 2, tag);
1232 PAIR_CLASS_INIT(&tag[1], "lit display");
1233 print_otag(h, TAG_PRE, 2, tag);
1235 /* This can be recursive: save & set our literal state. */
1237 sv = h->flags & HTML_LITERAL;
1238 h->flags |= HTML_LITERAL;
1240 for (nn = n->child; nn; nn = nn->next) {
1241 print_mdoc_node(m, nn, h);
1243 * If the printed node flushes its own line, then we
1244 * needn't do it here as well. This is hacky, but the
1245 * notion of selective eoln whitespace is pretty dumb
1246 * anyway, so don't sweat it.
1268 if (nn->next && nn->next->line == nn->line)
1271 print_text(h, "\n");
1273 h->flags |= HTML_NOSPACE;
1277 h->flags &= ~HTML_LITERAL;
1285 mdoc_pa_pre(MDOC_ARGS)
1287 struct htmlpair tag;
1289 PAIR_CLASS_INIT(&tag, "file");
1290 print_otag(h, TAG_I, 1, &tag);
1297 mdoc_ad_pre(MDOC_ARGS)
1299 struct htmlpair tag;
1301 PAIR_CLASS_INIT(&tag, "addr");
1302 print_otag(h, TAG_I, 1, &tag);
1309 mdoc_an_pre(MDOC_ARGS)
1311 struct htmlpair tag;
1313 /* TODO: -split and -nosplit (see termp_an_pre()). */
1315 PAIR_CLASS_INIT(&tag, "author");
1316 print_otag(h, TAG_SPAN, 1, &tag);
1323 mdoc_cd_pre(MDOC_ARGS)
1325 struct htmlpair tag;
1328 PAIR_CLASS_INIT(&tag, "config");
1329 print_otag(h, TAG_B, 1, &tag);
1336 mdoc_dv_pre(MDOC_ARGS)
1338 struct htmlpair tag;
1340 PAIR_CLASS_INIT(&tag, "define");
1341 print_otag(h, TAG_SPAN, 1, &tag);
1348 mdoc_ev_pre(MDOC_ARGS)
1350 struct htmlpair tag;
1352 PAIR_CLASS_INIT(&tag, "env");
1353 print_otag(h, TAG_SPAN, 1, &tag);
1360 mdoc_er_pre(MDOC_ARGS)
1362 struct htmlpair tag;
1364 PAIR_CLASS_INIT(&tag, "errno");
1365 print_otag(h, TAG_SPAN, 1, &tag);
1372 mdoc_fa_pre(MDOC_ARGS)
1374 const struct mdoc_node *nn;
1375 struct htmlpair tag;
1378 PAIR_CLASS_INIT(&tag, "farg");
1379 if (n->parent->tok != MDOC_Fo) {
1380 print_otag(h, TAG_I, 1, &tag);
1384 for (nn = n->child; nn; nn = nn->next) {
1385 t = print_otag(h, TAG_I, 1, &tag);
1386 print_text(h, nn->string);
1389 h->flags |= HTML_NOSPACE;
1394 if (n->child && n->next && n->next->tok == MDOC_Fa) {
1395 h->flags |= HTML_NOSPACE;
1405 mdoc_fd_pre(MDOC_ARGS)
1407 struct htmlpair tag[2];
1415 if (NULL == (n = n->child))
1418 assert(MDOC_TEXT == n->type);
1420 if (strcmp(n->string, "#include")) {
1421 PAIR_CLASS_INIT(&tag[0], "macro");
1422 print_otag(h, TAG_B, 1, tag);
1426 PAIR_CLASS_INIT(&tag[0], "includes");
1427 print_otag(h, TAG_B, 1, tag);
1428 print_text(h, n->string);
1430 if (NULL != (n = n->next)) {
1431 assert(MDOC_TEXT == n->type);
1432 strlcpy(buf, '<' == *n->string || '"' == *n->string ?
1433 n->string + 1 : n->string, BUFSIZ);
1436 if (sz && ('>' == buf[sz - 1] || '"' == buf[sz - 1]))
1439 PAIR_CLASS_INIT(&tag[0], "link-includes");
1442 if (h->base_includes) {
1443 buffmt_includes(h, buf);
1444 PAIR_HREF_INIT(&tag[i], h->buf);
1448 t = print_otag(h, TAG_A, i, tag);
1449 print_text(h, n->string);
1455 for ( ; n; n = n->next) {
1456 assert(MDOC_TEXT == n->type);
1457 print_text(h, n->string);
1466 mdoc_vt_pre(MDOC_ARGS)
1468 struct htmlpair tag;
1470 if (MDOC_BLOCK == n->type) {
1473 } else if (MDOC_ELEM == n->type) {
1475 } else if (MDOC_HEAD == n->type)
1478 PAIR_CLASS_INIT(&tag, "type");
1479 print_otag(h, TAG_SPAN, 1, &tag);
1486 mdoc_ft_pre(MDOC_ARGS)
1488 struct htmlpair tag;
1491 PAIR_CLASS_INIT(&tag, "ftype");
1492 print_otag(h, TAG_I, 1, &tag);
1499 mdoc_fn_pre(MDOC_ARGS)
1502 struct htmlpair tag[2];
1504 const char *sp, *ep;
1507 pretty = MDOC_SYNPRETTY & n->flags;
1510 /* Split apart into type and name. */
1511 assert(n->child->string);
1512 sp = n->child->string;
1514 ep = strchr(sp, ' ');
1516 PAIR_CLASS_INIT(&tag[0], "ftype");
1517 t = print_otag(h, TAG_I, 1, tag);
1520 sz = MIN((int)(ep - sp), BUFSIZ - 1);
1521 (void)memcpy(nbuf, sp, (size_t)sz);
1523 print_text(h, nbuf);
1525 ep = strchr(sp, ' ');
1530 PAIR_CLASS_INIT(&tag[0], "fname");
1533 * FIXME: only refer to IDs that we know exist.
1537 if (MDOC_SYNPRETTY & n->flags) {
1539 html_idcat(nbuf, sp, BUFSIZ);
1540 PAIR_ID_INIT(&tag[1], nbuf);
1542 strlcpy(nbuf, "#", BUFSIZ);
1543 html_idcat(nbuf, sp, BUFSIZ);
1544 PAIR_HREF_INIT(&tag[1], nbuf);
1548 t = print_otag(h, TAG_B, 1, tag);
1551 strlcpy(nbuf, sp, BUFSIZ);
1552 print_text(h, nbuf);
1557 h->flags |= HTML_NOSPACE;
1559 h->flags |= HTML_NOSPACE;
1561 PAIR_CLASS_INIT(&tag[0], "farg");
1563 bufcat_style(h, "white-space", "nowrap");
1564 PAIR_STYLE_INIT(&tag[1], h);
1566 for (n = n->child->next; n; n = n->next) {
1568 if (MDOC_SYNPRETTY & n->flags)
1570 t = print_otag(h, TAG_I, i, tag);
1571 print_text(h, n->string);
1574 h->flags |= HTML_NOSPACE;
1579 h->flags |= HTML_NOSPACE;
1583 h->flags |= HTML_NOSPACE;
1593 mdoc_sm_pre(MDOC_ARGS)
1596 assert(n->child && MDOC_TEXT == n->child->type);
1597 if (0 == strcmp("on", n->child->string)) {
1599 * FIXME: no p->col to check. Thus, if we have
1606 * the "3" is preceded by a space.
1608 h->flags &= ~HTML_NOSPACE;
1609 h->flags &= ~HTML_NONOSPACE;
1611 h->flags |= HTML_NONOSPACE;
1618 mdoc_pp_pre(MDOC_ARGS)
1621 print_otag(h, TAG_P, 0, NULL);
1628 mdoc_sp_pre(MDOC_ARGS)
1631 struct htmlpair tag;
1633 SCALE_VS_INIT(&su, 1);
1635 if (MDOC_sp == n->tok) {
1637 a2roffsu(n->child->string, &su, SCALE_VS);
1642 bufcat_su(h, "height", &su);
1643 PAIR_STYLE_INIT(&tag, h);
1644 print_otag(h, TAG_DIV, 1, &tag);
1646 /* So the div isn't empty: */
1647 print_text(h, "\\~");
1655 mdoc_lk_pre(MDOC_ARGS)
1657 struct htmlpair tag[2];
1659 if (NULL == (n = n->child))
1662 assert(MDOC_TEXT == n->type);
1664 PAIR_CLASS_INIT(&tag[0], "link-ext");
1665 PAIR_HREF_INIT(&tag[1], n->string);
1667 print_otag(h, TAG_A, 2, tag);
1669 for (n = n->next; n; n = n->next) {
1670 assert(MDOC_TEXT == n->type);
1671 print_text(h, n->string);
1680 mdoc_mt_pre(MDOC_ARGS)
1682 struct htmlpair tag[2];
1685 PAIR_CLASS_INIT(&tag[0], "link-mail");
1687 for (n = n->child; n; n = n->next) {
1688 assert(MDOC_TEXT == n->type);
1691 bufcat(h, "mailto:");
1692 bufcat(h, n->string);
1694 PAIR_HREF_INIT(&tag[1], h->buf);
1695 t = print_otag(h, TAG_A, 2, tag);
1696 print_text(h, n->string);
1706 mdoc_fo_pre(MDOC_ARGS)
1708 struct htmlpair tag;
1711 if (MDOC_BODY == n->type) {
1712 h->flags |= HTML_NOSPACE;
1714 h->flags |= HTML_NOSPACE;
1716 } else if (MDOC_BLOCK == n->type) {
1721 /* XXX: we drop non-initial arguments as per groff. */
1724 assert(n->child->string);
1726 PAIR_CLASS_INIT(&tag, "fname");
1727 t = print_otag(h, TAG_B, 1, &tag);
1728 print_text(h, n->child->string);
1736 mdoc_fo_post(MDOC_ARGS)
1739 if (MDOC_BODY != n->type)
1741 h->flags |= HTML_NOSPACE;
1743 h->flags |= HTML_NOSPACE;
1750 mdoc_in_pre(MDOC_ARGS)
1753 struct htmlpair tag[2];
1758 PAIR_CLASS_INIT(&tag[0], "includes");
1759 print_otag(h, TAG_B, 1, tag);
1762 * The first argument of the `In' gets special treatment as
1763 * being a linked value. Subsequent values are printed
1764 * afterward. groff does similarly. This also handles the case
1768 if (MDOC_SYNPRETTY & n->flags && MDOC_LINE & n->flags)
1769 print_text(h, "#include");
1772 h->flags |= HTML_NOSPACE;
1774 if (NULL != (n = n->child)) {
1775 assert(MDOC_TEXT == n->type);
1777 PAIR_CLASS_INIT(&tag[0], "link-includes");
1780 if (h->base_includes) {
1781 buffmt_includes(h, n->string);
1782 PAIR_HREF_INIT(&tag[i], h->buf);
1786 t = print_otag(h, TAG_A, i, tag);
1787 print_text(h, n->string);
1793 h->flags |= HTML_NOSPACE;
1796 for ( ; n; n = n->next) {
1797 assert(MDOC_TEXT == n->type);
1798 print_text(h, n->string);
1807 mdoc_ic_pre(MDOC_ARGS)
1809 struct htmlpair tag;
1811 PAIR_CLASS_INIT(&tag, "cmd");
1812 print_otag(h, TAG_B, 1, &tag);
1819 mdoc_rv_pre(MDOC_ARGS)
1821 struct htmlpair tag;
1826 print_otag(h, TAG_BR, 0, NULL);
1828 PAIR_CLASS_INIT(&tag, "fname");
1830 print_text(h, "The");
1833 for (n = n->child; n; n = n->next) {
1834 assert(MDOC_TEXT == n->type);
1836 t = print_otag(h, TAG_B, 1, &tag);
1837 print_text(h, n->string);
1840 h->flags |= HTML_NOSPACE;
1841 print_text(h, "()");
1843 if (nchild > 2 && n->next) {
1844 h->flags |= HTML_NOSPACE;
1848 if (n->next && NULL == n->next->next)
1849 print_text(h, "and");
1853 print_text(h, "functions return");
1855 print_text(h, "function returns");
1857 print_text(h, "the value 0 if successful; otherwise the value "
1858 "-1 is returned and the global variable");
1860 PAIR_CLASS_INIT(&tag, "var");
1861 t = print_otag(h, TAG_B, 1, &tag);
1862 print_text(h, "errno");
1864 print_text(h, "is set to indicate the error.");
1871 mdoc_va_pre(MDOC_ARGS)
1873 struct htmlpair tag;
1875 PAIR_CLASS_INIT(&tag, "var");
1876 print_otag(h, TAG_B, 1, &tag);
1883 mdoc_ap_pre(MDOC_ARGS)
1886 h->flags |= HTML_NOSPACE;
1887 print_text(h, "\\(aq");
1888 h->flags |= HTML_NOSPACE;
1895 mdoc_bf_pre(MDOC_ARGS)
1897 struct htmlpair tag[2];
1900 if (MDOC_HEAD == n->type)
1902 else if (MDOC_BODY != n->type)
1905 if (FONT_Em == n->norm->Bf.font)
1906 PAIR_CLASS_INIT(&tag[0], "emph");
1907 else if (FONT_Sy == n->norm->Bf.font)
1908 PAIR_CLASS_INIT(&tag[0], "symb");
1909 else if (FONT_Li == n->norm->Bf.font)
1910 PAIR_CLASS_INIT(&tag[0], "lit");
1912 PAIR_CLASS_INIT(&tag[0], "none");
1915 * We want this to be inline-formatted, but needs to be div to
1916 * accept block children.
1919 bufcat_style(h, "display", "inline");
1920 SCALE_HS_INIT(&su, 1);
1921 /* Needs a left-margin for spacing. */
1922 bufcat_su(h, "margin-left", &su);
1923 PAIR_STYLE_INIT(&tag[1], h);
1924 print_otag(h, TAG_DIV, 2, tag);
1931 mdoc_ms_pre(MDOC_ARGS)
1933 struct htmlpair tag;
1935 PAIR_CLASS_INIT(&tag, "symb");
1936 print_otag(h, TAG_SPAN, 1, &tag);
1943 mdoc_igndelim_pre(MDOC_ARGS)
1946 h->flags |= HTML_IGNDELIM;
1953 mdoc_pf_post(MDOC_ARGS)
1956 h->flags |= HTML_NOSPACE;
1962 mdoc_rs_pre(MDOC_ARGS)
1964 struct htmlpair tag;
1966 if (MDOC_BLOCK != n->type)
1969 if (n->prev && SEC_SEE_ALSO == n->sec)
1970 print_otag(h, TAG_P, 0, NULL);
1972 PAIR_CLASS_INIT(&tag, "ref");
1973 print_otag(h, TAG_SPAN, 1, &tag);
1981 mdoc_li_pre(MDOC_ARGS)
1983 struct htmlpair tag;
1985 PAIR_CLASS_INIT(&tag, "lit");
1986 print_otag(h, TAG_SPAN, 1, &tag);
1993 mdoc_sy_pre(MDOC_ARGS)
1995 struct htmlpair tag;
1997 PAIR_CLASS_INIT(&tag, "symb");
1998 print_otag(h, TAG_SPAN, 1, &tag);
2005 mdoc_bt_pre(MDOC_ARGS)
2008 print_text(h, "is currently in beta test.");
2015 mdoc_ud_pre(MDOC_ARGS)
2018 print_text(h, "currently under development.");
2025 mdoc_lb_pre(MDOC_ARGS)
2027 struct htmlpair tag;
2029 if (SEC_LIBRARY == n->sec && MDOC_LINE & n->flags && n->prev)
2030 print_otag(h, TAG_BR, 0, NULL);
2032 PAIR_CLASS_INIT(&tag, "lib");
2033 print_otag(h, TAG_SPAN, 1, &tag);
2040 mdoc__x_pre(MDOC_ARGS)
2042 struct htmlpair tag[2];
2049 PAIR_CLASS_INIT(&tag[0], "ref-auth");
2050 if (n->prev && MDOC__A == n->prev->tok)
2051 if (NULL == n->next || MDOC__A != n->next->tok)
2052 print_text(h, "and");
2055 PAIR_CLASS_INIT(&tag[0], "ref-book");
2059 PAIR_CLASS_INIT(&tag[0], "ref-city");
2062 PAIR_CLASS_INIT(&tag[0], "ref-date");
2065 PAIR_CLASS_INIT(&tag[0], "ref-issue");
2069 PAIR_CLASS_INIT(&tag[0], "ref-jrnl");
2073 PAIR_CLASS_INIT(&tag[0], "ref-num");
2076 PAIR_CLASS_INIT(&tag[0], "ref-opt");
2079 PAIR_CLASS_INIT(&tag[0], "ref-page");
2082 PAIR_CLASS_INIT(&tag[0], "ref-corp");
2085 PAIR_CLASS_INIT(&tag[0], "ref-rep");
2088 PAIR_CLASS_INIT(&tag[0], "ref-title");
2091 PAIR_CLASS_INIT(&tag[0], "link-ref");
2094 PAIR_CLASS_INIT(&tag[0], "ref-vol");
2101 if (MDOC__U != n->tok) {
2102 print_otag(h, t, 1, tag);
2106 PAIR_HREF_INIT(&tag[1], n->child->string);
2107 print_otag(h, TAG_A, 2, tag);
2115 mdoc__x_post(MDOC_ARGS)
2118 if (MDOC__A == n->tok && n->next && MDOC__A == n->next->tok)
2119 if (NULL == n->next->next || MDOC__A != n->next->next->tok)
2120 if (NULL == n->prev || MDOC__A != n->prev->tok)
2125 if (NULL == n->parent || MDOC_Rs != n->parent->tok)
2128 h->flags |= HTML_NOSPACE;
2129 print_text(h, n->next ? "," : ".");
2135 mdoc_bk_pre(MDOC_ARGS)
2144 if (n->parent->args || 0 == n->prev->nchild)
2145 h->flags |= HTML_PREKEEP;
2158 mdoc_bk_post(MDOC_ARGS)
2161 if (MDOC_BODY == n->type)
2162 h->flags &= ~(HTML_KEEP | HTML_PREKEEP);
2168 mdoc_quote_pre(MDOC_ARGS)
2170 struct htmlpair tag;
2172 if (MDOC_BODY != n->type)
2179 print_text(h, "\\(la");
2184 print_text(h, "\\(lC");
2189 print_text(h, "\\(lB");
2194 print_text(h, "\\(lB");
2195 h->flags |= HTML_NOSPACE;
2196 PAIR_CLASS_INIT(&tag, "opt");
2197 print_otag(h, TAG_SPAN, 1, &tag);
2206 print_text(h, "\\(lq");
2218 print_text(h, "\\(oq");
2225 h->flags |= HTML_NOSPACE;
2232 mdoc_quote_post(MDOC_ARGS)
2235 if (MDOC_BODY != n->type)
2238 h->flags |= HTML_NOSPACE;
2244 print_text(h, "\\(ra");
2249 print_text(h, "\\(rC");
2258 print_text(h, "\\(rB");
2267 print_text(h, "\\(rq");
2279 print_text(h, "\\(aq");