Annotation of mandoc/mdoc_html.c, Revision 1.15
1.15 ! kristaps 1: /* $Id: mdoc_html.c,v 1.14 2009/09/26 18:02:51 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
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>
1.7 kristaps 18: #include <sys/param.h>
1.1 kristaps 19: #include <sys/queue.h>
20:
21: #include <assert.h>
22: #include <ctype.h>
23: #include <err.h>
24: #include <stdio.h>
25: #include <stdlib.h>
26: #include <string.h>
27: #include <unistd.h>
28:
29: #include "html.h"
30: #include "mdoc.h"
31:
32: #define INDENT 5
33: #define HALFINDENT 3
34:
35: #define MDOC_ARGS const struct mdoc_meta *m, \
36: const struct mdoc_node *n, \
37: struct html *h
38: #define MAN_ARGS const struct man_meta *m, \
39: const struct man_node *n, \
40: struct html *h
41:
42: struct htmlmdoc {
43: int (*pre)(MDOC_ARGS);
44: void (*post)(MDOC_ARGS);
45: };
46:
47: static void print_mdoc(MDOC_ARGS);
48: static void print_mdoc_head(MDOC_ARGS);
49: static void print_mdoc_node(MDOC_ARGS);
50: static void print_mdoc_nodelist(MDOC_ARGS);
51:
52: static int a2width(const char *);
53: static int a2offs(const char *);
54: static int a2list(const struct mdoc_node *);
55:
56: static void mdoc_root_post(MDOC_ARGS);
57: static int mdoc_root_pre(MDOC_ARGS);
58: static int mdoc_tbl_pre(MDOC_ARGS, int);
59: static int mdoc_tbl_block_pre(MDOC_ARGS, int, int, int, int);
60: static int mdoc_tbl_body_pre(MDOC_ARGS, int, int);
61: static int mdoc_tbl_head_pre(MDOC_ARGS, int, int);
62:
1.10 kristaps 63: static void mdoc__x_post(MDOC_ARGS);
64: static int mdoc__x_pre(MDOC_ARGS);
1.1 kristaps 65: static int mdoc_ad_pre(MDOC_ARGS);
66: static int mdoc_an_pre(MDOC_ARGS);
1.5 kristaps 67: static int mdoc_ap_pre(MDOC_ARGS);
1.1 kristaps 68: static void mdoc_aq_post(MDOC_ARGS);
69: static int mdoc_aq_pre(MDOC_ARGS);
70: static int mdoc_ar_pre(MDOC_ARGS);
71: static int mdoc_bd_pre(MDOC_ARGS);
1.5 kristaps 72: static int mdoc_bf_pre(MDOC_ARGS);
1.1 kristaps 73: static void mdoc_bl_post(MDOC_ARGS);
74: static int mdoc_bl_pre(MDOC_ARGS);
1.4 kristaps 75: static void mdoc_bq_post(MDOC_ARGS);
76: static int mdoc_bq_pre(MDOC_ARGS);
1.2 kristaps 77: static void mdoc_brq_post(MDOC_ARGS);
78: static int mdoc_brq_pre(MDOC_ARGS);
1.6 kristaps 79: static int mdoc_bt_pre(MDOC_ARGS);
1.4 kristaps 80: static int mdoc_bx_pre(MDOC_ARGS);
1.1 kristaps 81: static int mdoc_cd_pre(MDOC_ARGS);
82: static int mdoc_d1_pre(MDOC_ARGS);
83: static void mdoc_dq_post(MDOC_ARGS);
84: static int mdoc_dq_pre(MDOC_ARGS);
85: static int mdoc_dv_pre(MDOC_ARGS);
86: static int mdoc_fa_pre(MDOC_ARGS);
87: static int mdoc_fd_pre(MDOC_ARGS);
88: static int mdoc_fl_pre(MDOC_ARGS);
89: static int mdoc_fn_pre(MDOC_ARGS);
90: static int mdoc_ft_pre(MDOC_ARGS);
91: static int mdoc_em_pre(MDOC_ARGS);
92: static int mdoc_er_pre(MDOC_ARGS);
93: static int mdoc_ev_pre(MDOC_ARGS);
94: static int mdoc_ex_pre(MDOC_ARGS);
1.4 kristaps 95: static void mdoc_fo_post(MDOC_ARGS);
96: static int mdoc_fo_pre(MDOC_ARGS);
97: static int mdoc_ic_pre(MDOC_ARGS);
98: static int mdoc_in_pre(MDOC_ARGS);
1.1 kristaps 99: static int mdoc_it_pre(MDOC_ARGS);
1.6 kristaps 100: static int mdoc_lb_pre(MDOC_ARGS);
101: static int mdoc_li_pre(MDOC_ARGS);
1.2 kristaps 102: static int mdoc_lk_pre(MDOC_ARGS);
103: static int mdoc_mt_pre(MDOC_ARGS);
1.5 kristaps 104: static int mdoc_ms_pre(MDOC_ARGS);
1.1 kristaps 105: static int mdoc_nd_pre(MDOC_ARGS);
106: static int mdoc_nm_pre(MDOC_ARGS);
107: static int mdoc_ns_pre(MDOC_ARGS);
108: static void mdoc_op_post(MDOC_ARGS);
109: static int mdoc_op_pre(MDOC_ARGS);
110: static int mdoc_pa_pre(MDOC_ARGS);
1.5 kristaps 111: static void mdoc_pf_post(MDOC_ARGS);
112: static int mdoc_pf_pre(MDOC_ARGS);
1.1 kristaps 113: static void mdoc_pq_post(MDOC_ARGS);
114: static int mdoc_pq_pre(MDOC_ARGS);
1.5 kristaps 115: static int mdoc_rs_pre(MDOC_ARGS);
1.4 kristaps 116: static int mdoc_rv_pre(MDOC_ARGS);
1.1 kristaps 117: static int mdoc_sh_pre(MDOC_ARGS);
118: static int mdoc_sp_pre(MDOC_ARGS);
119: static void mdoc_sq_post(MDOC_ARGS);
120: static int mdoc_sq_pre(MDOC_ARGS);
121: static int mdoc_ss_pre(MDOC_ARGS);
122: static int mdoc_sx_pre(MDOC_ARGS);
1.6 kristaps 123: static int mdoc_sy_pre(MDOC_ARGS);
124: static int mdoc_ud_pre(MDOC_ARGS);
1.4 kristaps 125: static int mdoc_va_pre(MDOC_ARGS);
1.1 kristaps 126: static int mdoc_vt_pre(MDOC_ARGS);
127: static int mdoc_xr_pre(MDOC_ARGS);
128: static int mdoc_xx_pre(MDOC_ARGS);
129:
130: #ifdef __linux__
131: extern size_t strlcpy(char *, const char *, size_t);
132: extern size_t strlcat(char *, const char *, size_t);
133: #endif
134:
135: static const struct htmlmdoc mdocs[MDOC_MAX] = {
1.5 kristaps 136: {mdoc_ap_pre, NULL}, /* Ap */
1.1 kristaps 137: {NULL, NULL}, /* Dd */
138: {NULL, NULL}, /* Dt */
139: {NULL, NULL}, /* Os */
140: {mdoc_sh_pre, NULL }, /* Sh */
141: {mdoc_ss_pre, NULL }, /* Ss */
142: {mdoc_sp_pre, NULL}, /* Pp */
143: {mdoc_d1_pre, NULL}, /* D1 */
144: {mdoc_d1_pre, NULL}, /* Dl */
145: {mdoc_bd_pre, NULL}, /* Bd */
146: {NULL, NULL}, /* Ed */
147: {mdoc_bl_pre, mdoc_bl_post}, /* Bl */
148: {NULL, NULL}, /* El */
149: {mdoc_it_pre, NULL}, /* It */
150: {mdoc_ad_pre, NULL}, /* Ad */
151: {mdoc_an_pre, NULL}, /* An */
152: {mdoc_ar_pre, NULL}, /* Ar */
153: {mdoc_cd_pre, NULL}, /* Cd */
154: {mdoc_fl_pre, NULL}, /* Cm */
155: {mdoc_dv_pre, NULL}, /* Dv */
156: {mdoc_er_pre, NULL}, /* Er */
157: {mdoc_ev_pre, NULL}, /* Ev */
158: {mdoc_ex_pre, NULL}, /* Ex */
159: {mdoc_fa_pre, NULL}, /* Fa */
160: {mdoc_fd_pre, NULL}, /* Fd */
161: {mdoc_fl_pre, NULL}, /* Fl */
162: {mdoc_fn_pre, NULL}, /* Fn */
163: {mdoc_ft_pre, NULL}, /* Ft */
1.4 kristaps 164: {mdoc_ic_pre, NULL}, /* Ic */
165: {mdoc_in_pre, NULL}, /* In */
1.6 kristaps 166: {mdoc_li_pre, NULL}, /* Li */
1.1 kristaps 167: {mdoc_nd_pre, NULL}, /* Nd */
168: {mdoc_nm_pre, NULL}, /* Nm */
169: {mdoc_op_pre, mdoc_op_post}, /* Op */
170: {NULL, NULL}, /* Ot */
171: {mdoc_pa_pre, NULL}, /* Pa */
1.4 kristaps 172: {mdoc_rv_pre, NULL}, /* Rv */
1.1 kristaps 173: {NULL, NULL}, /* St */
1.4 kristaps 174: {mdoc_va_pre, NULL}, /* Va */
1.1 kristaps 175: {mdoc_vt_pre, NULL}, /* Vt */
176: {mdoc_xr_pre, NULL}, /* Xr */
1.10 kristaps 177: {mdoc__x_pre, mdoc__x_post}, /* %A */
178: {mdoc__x_pre, mdoc__x_post}, /* %B */
179: {mdoc__x_pre, mdoc__x_post}, /* %D */
180: {mdoc__x_pre, mdoc__x_post}, /* %I */
181: {mdoc__x_pre, mdoc__x_post}, /* %J */
182: {mdoc__x_pre, mdoc__x_post}, /* %N */
183: {mdoc__x_pre, mdoc__x_post}, /* %O */
184: {mdoc__x_pre, mdoc__x_post}, /* %P */
185: {mdoc__x_pre, mdoc__x_post}, /* %R */
186: {mdoc__x_pre, mdoc__x_post}, /* %T */
187: {mdoc__x_pre, mdoc__x_post}, /* %V */
1.1 kristaps 188: {NULL, NULL}, /* Ac */
189: {mdoc_aq_pre, mdoc_aq_post}, /* Ao */
190: {mdoc_aq_pre, mdoc_aq_post}, /* Aq */
191: {NULL, NULL}, /* At */
192: {NULL, NULL}, /* Bc */
1.5 kristaps 193: {mdoc_bf_pre, NULL}, /* Bf */
1.4 kristaps 194: {mdoc_bq_pre, mdoc_bq_post}, /* Bo */
195: {mdoc_bq_pre, mdoc_bq_post}, /* Bq */
1.1 kristaps 196: {mdoc_xx_pre, NULL}, /* Bsx */
1.4 kristaps 197: {mdoc_bx_pre, NULL}, /* Bx */
1.1 kristaps 198: {NULL, NULL}, /* Db */
199: {NULL, NULL}, /* Dc */
1.4 kristaps 200: {mdoc_dq_pre, mdoc_dq_post}, /* Do */
1.1 kristaps 201: {mdoc_dq_pre, mdoc_dq_post}, /* Dq */
202: {NULL, NULL}, /* Ec */
203: {NULL, NULL}, /* Ef */
204: {mdoc_em_pre, NULL}, /* Em */
205: {NULL, NULL}, /* Eo */
206: {mdoc_xx_pre, NULL}, /* Fx */
1.5 kristaps 207: {mdoc_ms_pre, NULL}, /* Ms */ /* FIXME: convert to symbol? */
1.1 kristaps 208: {NULL, NULL}, /* No */
209: {mdoc_ns_pre, NULL}, /* Ns */
210: {mdoc_xx_pre, NULL}, /* Nx */
211: {mdoc_xx_pre, NULL}, /* Ox */
212: {NULL, NULL}, /* Pc */
1.5 kristaps 213: {mdoc_pf_pre, mdoc_pf_post}, /* Pf */
1.1 kristaps 214: {mdoc_pq_pre, mdoc_pq_post}, /* Po */
215: {mdoc_pq_pre, mdoc_pq_post}, /* Pq */
216: {NULL, NULL}, /* Qc */
1.4 kristaps 217: {mdoc_sq_pre, mdoc_sq_post}, /* Ql */
1.5 kristaps 218: {mdoc_dq_pre, mdoc_dq_post}, /* Qo */
219: {mdoc_dq_pre, mdoc_dq_post}, /* Qq */
1.1 kristaps 220: {NULL, NULL}, /* Re */
1.5 kristaps 221: {mdoc_rs_pre, NULL}, /* Rs */
1.1 kristaps 222: {NULL, NULL}, /* Sc */
223: {mdoc_sq_pre, mdoc_sq_post}, /* So */
224: {mdoc_sq_pre, mdoc_sq_post}, /* Sq */
1.6 kristaps 225: {NULL, NULL}, /* Sm */ /* FIXME - no idea. */
1.1 kristaps 226: {mdoc_sx_pre, NULL}, /* Sx */
1.6 kristaps 227: {mdoc_sy_pre, NULL}, /* Sy */
1.1 kristaps 228: {NULL, NULL}, /* Tn */
229: {mdoc_xx_pre, NULL}, /* Ux */
230: {NULL, NULL}, /* Xc */
231: {NULL, NULL}, /* Xo */
1.4 kristaps 232: {mdoc_fo_pre, mdoc_fo_post}, /* Fo */
1.1 kristaps 233: {NULL, NULL}, /* Fc */
1.4 kristaps 234: {mdoc_op_pre, mdoc_op_post}, /* Oo */
1.1 kristaps 235: {NULL, NULL}, /* Oc */
236: {NULL, NULL}, /* Bk */
237: {NULL, NULL}, /* Ek */
1.6 kristaps 238: {mdoc_bt_pre, NULL}, /* Bt */
1.1 kristaps 239: {NULL, NULL}, /* Hf */
240: {NULL, NULL}, /* Fr */
1.6 kristaps 241: {mdoc_ud_pre, NULL}, /* Ud */
242: {mdoc_lb_pre, NULL}, /* Lb */
1.1 kristaps 243: {mdoc_sp_pre, NULL}, /* Lp */
1.2 kristaps 244: {mdoc_lk_pre, NULL}, /* Lk */
245: {mdoc_mt_pre, NULL}, /* Mt */
246: {mdoc_brq_pre, mdoc_brq_post}, /* Brq */
247: {mdoc_brq_pre, mdoc_brq_post}, /* Bro */
1.1 kristaps 248: {NULL, NULL}, /* Brc */
1.10 kristaps 249: {mdoc__x_pre, mdoc__x_post}, /* %C */
1.2 kristaps 250: {NULL, NULL}, /* Es */ /* TODO */
251: {NULL, NULL}, /* En */ /* TODO */
1.1 kristaps 252: {mdoc_xx_pre, NULL}, /* Dx */
1.10 kristaps 253: {mdoc__x_pre, mdoc__x_post}, /* %Q */
1.1 kristaps 254: {mdoc_sp_pre, NULL}, /* br */
255: {mdoc_sp_pre, NULL}, /* sp */
256: };
257:
258: static char buf[BUFSIZ]; /* XXX */
259:
260: #define bufcat(x) (void)strlcat(buf, (x), BUFSIZ)
261: #define bufinit() buf[0] = 0
262: #define buffmt(...) (void)snprintf(buf, BUFSIZ - 1, __VA_ARGS__)
263:
264: void
265: html_mdoc(void *arg, const struct mdoc *m)
266: {
267: struct html *h;
268: struct tag *t;
269:
270: h = (struct html *)arg;
271:
272: print_gen_doctype(h);
273: t = print_otag(h, TAG_HTML, 0, NULL);
274: print_mdoc(mdoc_meta(m), mdoc_node(m), h);
275: print_tagq(h, t);
276:
277: printf("\n");
278: }
279:
280:
281: static int
282: a2list(const struct mdoc_node *n)
283: {
284: int i;
285:
286: assert(MDOC_BLOCK == n->type && MDOC_Bl == n->tok);
287: assert(n->args);
288:
289: for (i = 0; i < (int)n->args->argc; i++)
290: switch (n->args->argv[i].arg) {
291: case (MDOC_Enum):
292: /* FALLTHROUGH */
293: case (MDOC_Dash):
294: /* FALLTHROUGH */
295: case (MDOC_Hyphen):
296: /* FALLTHROUGH */
297: case (MDOC_Bullet):
298: /* FALLTHROUGH */
299: case (MDOC_Tag):
300: /* FALLTHROUGH */
301: case (MDOC_Hang):
302: /* FALLTHROUGH */
303: case (MDOC_Inset):
304: /* FALLTHROUGH */
305: case (MDOC_Diag):
306: /* FALLTHROUGH */
307: case (MDOC_Item):
308: /* FALLTHROUGH */
309: case (MDOC_Column):
310: /* FALLTHROUGH */
311: case (MDOC_Ohang):
312: return(n->args->argv[i].arg);
313: default:
314: break;
315: }
316:
317: abort();
318: /* NOTREACHED */
319: }
320:
321:
322: static int
323: a2width(const char *p)
324: {
325: int i, len;
326:
327: if (0 == (len = (int)strlen(p)))
328: return(0);
329: for (i = 0; i < len - 1; i++)
330: if ( ! isdigit((u_char)p[i]))
331: break;
332:
333: if (i == len - 1)
334: if ('n' == p[len - 1] || 'm' == p[len - 1])
335: return(atoi(p) + 2);
336:
337: return(len + 2);
338: }
339:
340:
341: static int
342: a2offs(const char *p)
343: {
344: int len, i;
345:
346: if (0 == strcmp(p, "left"))
347: return(0);
348: if (0 == strcmp(p, "indent"))
349: return(INDENT + 1);
350: if (0 == strcmp(p, "indent-two"))
351: return((INDENT + 1) * 2);
352:
353: if (0 == (len = (int)strlen(p)))
354: return(0);
355:
356: for (i = 0; i < len - 1; i++)
357: if ( ! isdigit((u_char)p[i]))
358: break;
359:
360: if (i == len - 1)
361: if ('n' == p[len - 1] || 'm' == p[len - 1])
362: return(atoi(p));
363:
364: return(len);
365: }
366:
367:
368: static void
369: print_mdoc(MDOC_ARGS)
370: {
371: struct tag *t;
372: struct htmlpair tag;
373:
374: t = print_otag(h, TAG_HEAD, 0, NULL);
375: print_mdoc_head(m, n, h);
376: print_tagq(h, t);
377:
378: t = print_otag(h, TAG_BODY, 0, NULL);
379:
380: tag.key = ATTR_CLASS;
381: tag.val = "body";
382: print_otag(h, TAG_DIV, 1, &tag);
383:
384: print_mdoc_nodelist(m, n, h);
385: print_tagq(h, t);
386: }
387:
388:
389: /* ARGSUSED */
390: static void
391: print_mdoc_head(MDOC_ARGS)
392: {
393: char b[BUFSIZ];
394:
395: print_gen_head(h);
396:
397: (void)snprintf(b, BUFSIZ - 1,
398: "%s(%d)", m->title, m->msec);
399:
400: if (m->arch) {
401: (void)strlcat(b, " (", BUFSIZ);
402: (void)strlcat(b, m->arch, BUFSIZ);
403: (void)strlcat(b, ")", BUFSIZ);
404: }
405:
406: print_otag(h, TAG_TITLE, 0, NULL);
407: print_text(h, b);
408: }
409:
410:
411: static void
412: print_mdoc_nodelist(MDOC_ARGS)
413: {
414:
415: print_mdoc_node(m, n, h);
416: if (n->next)
417: print_mdoc_nodelist(m, n->next, h);
418: }
419:
420:
421: static void
422: print_mdoc_node(MDOC_ARGS)
423: {
424: int child;
425: struct tag *t;
426:
427: child = 1;
428: t = SLIST_FIRST(&h->tags);
429:
430: bufinit();
431:
432: switch (n->type) {
433: case (MDOC_ROOT):
434: child = mdoc_root_pre(m, n, h);
435: break;
436: case (MDOC_TEXT):
437: print_text(h, n->string);
438: break;
439: default:
440: if (mdocs[n->tok].pre)
441: child = (*mdocs[n->tok].pre)(m, n, h);
442: break;
443: }
444:
445: if (child && n->child)
446: print_mdoc_nodelist(m, n->child, h);
447:
448: print_stagq(h, t);
449:
450: bufinit();
451:
452: switch (n->type) {
453: case (MDOC_ROOT):
454: mdoc_root_post(m, n, h);
455: break;
456: case (MDOC_TEXT):
457: break;
458: default:
459: if (mdocs[n->tok].post)
460: (*mdocs[n->tok].post)(m, n, h);
461: break;
462: }
463: }
464:
465:
466: /* ARGSUSED */
467: static void
468: mdoc_root_post(MDOC_ARGS)
469: {
470: struct tm tm;
471: struct htmlpair tag[2];
472: struct tag *t, *tt;
473: char b[BUFSIZ];
474:
475: (void)localtime_r(&m->date, &tm);
476:
477: if (0 == strftime(b, BUFSIZ - 1, "%B %e, %Y", &tm))
478: err(EXIT_FAILURE, "strftime");
479:
480: tag[0].key = ATTR_CLASS;
481: tag[0].val = "footer";
482: tag[1].key = ATTR_STYLE;
483: tag[1].val = "width: 100%;";
484: t = print_otag(h, TAG_TABLE, 2, tag);
485: tt = print_otag(h, TAG_TR, 0, NULL);
486:
487: tag[0].key = ATTR_STYLE;
488: tag[0].val = "width: 50%;";
489: print_otag(h, TAG_TD, 1, tag);
490: print_text(h, b);
491: print_stagq(h, tt);
492:
493: tag[0].key = ATTR_STYLE;
494: tag[0].val = "width: 50%; text-align: right;";
495: print_otag(h, TAG_TD, 1, tag);
496: print_text(h, m->os);
497: print_tagq(h, t);
498: }
499:
500:
501: /* ARGSUSED */
502: static int
503: mdoc_root_pre(MDOC_ARGS)
504: {
505: struct htmlpair tag[2];
506: struct tag *t, *tt;
507: char b[BUFSIZ], title[BUFSIZ];
508:
509: (void)strlcpy(b, m->vol, BUFSIZ);
510:
511: if (m->arch) {
512: (void)strlcat(b, " (", BUFSIZ);
513: (void)strlcat(b, m->arch, BUFSIZ);
514: (void)strlcat(b, ")", BUFSIZ);
515: }
516:
517: (void)snprintf(title, BUFSIZ - 1,
518: "%s(%d)", m->title, m->msec);
519:
520: tag[0].key = ATTR_CLASS;
521: tag[0].val = "header";
522: tag[1].key = ATTR_STYLE;
523: tag[1].val = "width: 100%;";
524: t = print_otag(h, TAG_TABLE, 2, tag);
525: tt = print_otag(h, TAG_TR, 0, NULL);
526:
527: tag[0].key = ATTR_STYLE;
1.11 kristaps 528: tag[0].val = "width: 10%;";
1.1 kristaps 529: print_otag(h, TAG_TD, 1, tag);
1.2 kristaps 530: print_text(h, title);
1.1 kristaps 531: print_stagq(h, tt);
532:
533: tag[0].key = ATTR_STYLE;
1.11 kristaps 534: tag[0].val = "width: 80%; white-space: nowrap; text-align: center;";
1.1 kristaps 535: print_otag(h, TAG_TD, 1, tag);
1.2 kristaps 536: print_text(h, b);
1.1 kristaps 537: print_stagq(h, tt);
538:
539: tag[0].key = ATTR_STYLE;
1.11 kristaps 540: tag[0].val = "width: 10%; text-align: right;";
1.1 kristaps 541: print_otag(h, TAG_TD, 1, tag);
1.2 kristaps 542: print_text(h, title);
1.1 kristaps 543: print_tagq(h, t);
544:
545: return(1);
546: }
547:
548:
549: /* ARGSUSED */
550: static int
551: mdoc_sh_pre(MDOC_ARGS)
552: {
553: struct htmlpair tag[2];
554: const struct mdoc_node *nn;
555:
556: if (MDOC_HEAD == n->type) {
557: tag[0].key = ATTR_CLASS;
558: tag[0].val = "sec-head";
559: print_otag(h, TAG_DIV, 1, tag);
560: print_otag(h, TAG_SPAN, 1, tag);
561:
562: for (nn = n->child; nn; nn = nn->next) {
563: bufcat(nn->string);
564: if (nn->next)
565: bufcat(" ");
566: }
567: tag[0].key = ATTR_NAME;
568: tag[0].val = buf;
569: print_otag(h, TAG_A, 1, tag);
570: return(1);
571: } else if (MDOC_BLOCK == n->type) {
572: tag[0].key = ATTR_CLASS;
573: tag[0].val = "sec-block";
574:
575: if (n->prev && NULL == n->prev->body->child) {
576: print_otag(h, TAG_DIV, 1, tag);
577: return(1);
578: }
579:
580: bufcat("margin-top: 1em;");
581: if (NULL == n->next)
582: bufcat("margin-bottom: 1em;");
583:
584: tag[1].key = ATTR_STYLE;
585: tag[1].val = buf;
586:
587: print_otag(h, TAG_DIV, 2, tag);
588: return(1);
589: }
590:
591: buffmt("margin-left: %dem;", INDENT);
592:
593: tag[0].key = ATTR_CLASS;
594: tag[0].val = "sec-body";
595: tag[1].key = ATTR_STYLE;
596: tag[1].val = buf;
597:
598: print_otag(h, TAG_DIV, 2, tag);
599: return(1);
600: }
601:
602:
603: /* ARGSUSED */
604: static int
605: mdoc_ss_pre(MDOC_ARGS)
606: {
607: struct htmlpair tag[2];
608: int i;
609: const struct mdoc_node *nn;
610:
611: i = 0;
612:
613: if (MDOC_BODY == n->type) {
614: tag[i].key = ATTR_CLASS;
615: tag[i++].val = "ssec-body";
616: if (n->parent->next && n->child) {
617: bufcat("margin-bottom: 1em;");
618: tag[i].key = ATTR_STYLE;
619: tag[i++].val = buf;
620: }
621: print_otag(h, TAG_DIV, i, tag);
622: return(1);
623: } else if (MDOC_BLOCK == n->type) {
624: tag[i].key = ATTR_CLASS;
625: tag[i++].val = "ssec-block";
626: if (n->prev) {
627: bufcat("margin-top: 1em;");
628: tag[i].key = ATTR_STYLE;
629: tag[i++].val = buf;
630: }
631: print_otag(h, TAG_DIV, i, tag);
632: return(1);
633: }
634:
635: buffmt("margin-left: -%dem;", INDENT - HALFINDENT);
636:
637: tag[0].key = ATTR_CLASS;
638: tag[0].val = "ssec-head";
639: tag[1].key = ATTR_STYLE;
640: tag[1].val = buf;
641:
642: print_otag(h, TAG_DIV, 2, tag);
643: print_otag(h, TAG_SPAN, 1, tag);
644:
645: bufinit();
646: for (nn = n->child; nn; nn = nn->next) {
647: bufcat(nn->string);
648: if (nn->next)
649: bufcat(" ");
650: }
651: tag[0].key = ATTR_NAME;
652: tag[0].val = buf;
653: print_otag(h, TAG_A, 1, tag);
654:
655: return(1);
656: }
657:
658:
659: /* ARGSUSED */
660: static int
661: mdoc_fl_pre(MDOC_ARGS)
662: {
663: struct htmlpair tag;
664:
665: tag.key = ATTR_CLASS;
666: tag.val = "flag";
667:
668: print_otag(h, TAG_SPAN, 1, &tag);
669: if (MDOC_Fl == n->tok) {
670: print_text(h, "\\-");
671: h->flags |= HTML_NOSPACE;
672: }
673: return(1);
674: }
675:
676:
677: /* ARGSUSED */
678: static int
679: mdoc_nd_pre(MDOC_ARGS)
680: {
681: struct htmlpair tag;
682:
683: if (MDOC_BODY != n->type)
684: return(1);
685:
686: /* XXX - this can contain block elements! */
687: print_text(h, "\\(em");
688: tag.key = ATTR_CLASS;
689: tag.val = "desc-body";
690: print_otag(h, TAG_SPAN, 1, &tag);
691: return(1);
692: }
693:
694:
695: /* ARGSUSED */
696: static int
697: mdoc_op_pre(MDOC_ARGS)
698: {
699: struct htmlpair tag;
700:
701: if (MDOC_BODY != n->type)
702: return(1);
703:
704: /* XXX - this can contain block elements! */
705: print_text(h, "\\(lB");
706: h->flags |= HTML_NOSPACE;
707: tag.key = ATTR_CLASS;
708: tag.val = "opt";
709: print_otag(h, TAG_SPAN, 1, &tag);
710: return(1);
711: }
712:
713:
714: /* ARGSUSED */
715: static void
716: mdoc_op_post(MDOC_ARGS)
717: {
718:
719: if (MDOC_BODY != n->type)
720: return;
721: h->flags |= HTML_NOSPACE;
722: print_text(h, "\\(rB");
723: }
724:
725:
726: static int
727: mdoc_nm_pre(MDOC_ARGS)
728: {
729: struct htmlpair tag;
730:
731: if ( ! (HTML_NEWLINE & h->flags))
732: if (SEC_SYNOPSIS == n->sec) {
733: tag.key = ATTR_STYLE;
734: tag.val = "clear: both;";
735: print_otag(h, TAG_BR, 1, &tag);
736: }
737:
738: tag.key = ATTR_CLASS;
739: tag.val = "name";
740:
741: print_otag(h, TAG_SPAN, 1, &tag);
742: if (NULL == n->child)
743: print_text(h, m->name);
744:
745: return(1);
746: }
747:
748:
749: /* ARGSUSED */
750: static int
751: mdoc_xr_pre(MDOC_ARGS)
752: {
753: struct htmlpair tag[2];
754: const char *name, *sec;
755: const struct mdoc_node *nn;
756:
757: nn = n->child;
758: name = nn && nn->string ? nn->string : "";
759: nn = nn ? nn->next : NULL;
760: sec = nn && nn->string ? nn->string : "";
761:
762: buffmt("%s%s%s.html", name, name && sec ? "." : "", sec);
763:
764: tag[0].key = ATTR_CLASS;
765: tag[0].val = "link-man";
766: tag[1].key = ATTR_HREF;
767: tag[1].val = buf;
768: print_otag(h, TAG_A, 2, tag);
769:
770: nn = n->child;
771: print_text(h, nn->string);
772: if (NULL == (nn = nn->next))
773: return(0);
774:
775: h->flags |= HTML_NOSPACE;
776: print_text(h, "(");
777: h->flags |= HTML_NOSPACE;
778: print_text(h, nn->string);
779: h->flags |= HTML_NOSPACE;
780: print_text(h, ")");
781:
782: return(0);
783: }
784:
785:
786: /* ARGSUSED */
787: static int
788: mdoc_ns_pre(MDOC_ARGS)
789: {
790:
791: h->flags |= HTML_NOSPACE;
792: return(1);
793: }
794:
795:
796: /* ARGSUSED */
797: static int
798: mdoc_ar_pre(MDOC_ARGS)
799: {
800: struct htmlpair tag;
801:
802: tag.key = ATTR_CLASS;
803: tag.val = "arg";
804:
805: print_otag(h, TAG_SPAN, 1, &tag);
806: return(1);
807: }
808:
809:
810: /* ARGSUSED */
811: static int
812: mdoc_xx_pre(MDOC_ARGS)
813: {
814: const char *pp;
815: struct htmlpair tag;
816:
817: switch (n->tok) {
818: case (MDOC_Bsx):
819: pp = "BSDI BSD/OS";
820: break;
821: case (MDOC_Dx):
822: pp = "DragonFlyBSD";
823: break;
824: case (MDOC_Fx):
825: pp = "FreeBSD";
826: break;
827: case (MDOC_Nx):
828: pp = "NetBSD";
829: break;
830: case (MDOC_Ox):
831: pp = "OpenBSD";
832: break;
833: case (MDOC_Ux):
834: pp = "UNIX";
835: break;
836: default:
837: return(1);
838: }
839:
840: tag.key = ATTR_CLASS;
841: tag.val = "unix";
842:
843: print_otag(h, TAG_SPAN, 1, &tag);
844: print_text(h, pp);
845: return(1);
846: }
847:
848:
849: /* ARGSUSED */
850: static int
1.4 kristaps 851: mdoc_bx_pre(MDOC_ARGS)
852: {
853: const struct mdoc_node *nn;
854: struct htmlpair tag;
855:
856: tag.key = ATTR_CLASS;
857: tag.val = "unix";
858:
859: print_otag(h, TAG_SPAN, 1, &tag);
860:
861: for (nn = n->child; nn; nn = nn->next)
862: print_mdoc_node(m, nn, h);
863:
864: if (n->child)
865: h->flags |= HTML_NOSPACE;
866:
867: print_text(h, "BSD");
868: return(0);
869: }
870:
871:
872: /* ARGSUSED */
873: static int
1.1 kristaps 874: mdoc_tbl_block_pre(MDOC_ARGS, int t, int w, int o, int c)
875: {
1.14 kristaps 876: struct htmlpair tag;
877: const struct mdoc_node *nn;
1.1 kristaps 878:
879: switch (t) {
880: case (MDOC_Column):
881: /* FALLTHROUGH */
882: case (MDOC_Item):
883: /* FALLTHROUGH */
884: case (MDOC_Ohang):
885: buffmt("margin-left: %dem; clear: both;", o);
886: break;
887: default:
888: buffmt("margin-left: %dem; clear: both;", w + o);
889: break;
890: }
891:
892: if ( ! c && MDOC_Column != t) {
1.14 kristaps 893: for (nn = n; nn; nn = nn->parent) {
894: if (MDOC_BLOCK != nn->type)
895: continue;
896: switch (nn->tok) {
897: case (MDOC_Ss):
898: /* FALLTHROUGH */
899: case (MDOC_Sh):
900: c = 1;
901: break;
902: default:
903: break;
904: }
905: if (nn->prev)
906: break;
907: }
908: if (MDOC_Diag == t && n->prev)
909: if (NULL == n->prev->body->child)
910: c = 1;
911: if ( ! c)
912: bufcat("padding-top: 1em;");
1.1 kristaps 913: }
914:
915: tag.key = ATTR_STYLE;
916: tag.val = buf;
917: print_otag(h, TAG_DIV, 1, &tag);
918: return(1);
919: }
920:
921:
922: /* ARGSUSED */
923: static int
924: mdoc_tbl_body_pre(MDOC_ARGS, int t, int w)
925: {
926:
927: print_otag(h, TAG_DIV, 0, NULL);
928: return(1);
929: }
930:
931:
932: /* ARGSUSED */
933: static int
934: mdoc_tbl_head_pre(MDOC_ARGS, int t, int w)
935: {
936: struct htmlpair tag;
937: struct ord *ord;
938: char nbuf[BUFSIZ];
939:
940: switch (t) {
941: case (MDOC_Item):
942: /* FALLTHROUGH */
943: case (MDOC_Ohang):
944: print_otag(h, TAG_DIV, 0, NULL);
945: break;
946: case (MDOC_Column):
947: buffmt("min-width: %dem;", w);
948: bufcat("clear: none;");
949: if (n->next && MDOC_HEAD == n->next->type)
950: bufcat("float: left;");
951: tag.key = ATTR_STYLE;
952: tag.val = buf;
953: print_otag(h, TAG_DIV, 1, &tag);
954: break;
955: default:
1.4 kristaps 956: buffmt("margin-left: -%dem; min-width: %dem;",
957: w, w ? w - 1 : 0);
1.1 kristaps 958: bufcat("clear: left;");
1.2 kristaps 959: if (n->next && n->next->child)
960: bufcat("float: left;");
1.1 kristaps 961: bufcat("padding-right: 1em;");
962: tag.key = ATTR_STYLE;
963: tag.val = buf;
964: print_otag(h, TAG_DIV, 1, &tag);
965: break;
966: }
967:
968: switch (t) {
969: case (MDOC_Diag):
970: tag.key = ATTR_CLASS;
971: tag.val = "diag";
972: print_otag(h, TAG_SPAN, 1, &tag);
973: break;
974: case (MDOC_Enum):
975: ord = SLIST_FIRST(&h->ords);
976: assert(ord);
977: nbuf[BUFSIZ - 1] = 0;
978: (void)snprintf(nbuf, BUFSIZ - 1, "%d.", ord->pos++);
979: print_text(h, nbuf);
980: return(0);
981: case (MDOC_Dash):
982: print_text(h, "\\(en");
983: return(0);
984: case (MDOC_Hyphen):
1.4 kristaps 985: print_text(h, "\\(hy");
1.1 kristaps 986: return(0);
987: case (MDOC_Bullet):
988: print_text(h, "\\(bu");
989: return(0);
990: default:
991: break;
992: }
993:
994: return(1);
995: }
996:
997:
998: static int
999: mdoc_tbl_pre(MDOC_ARGS, int type)
1000: {
1001: int i, w, o, c, wp;
1002: const struct mdoc_node *bl, *nn;
1003:
1004: bl = n->parent->parent;
1005: if (MDOC_BLOCK != n->type)
1006: bl = bl->parent;
1007:
1008: assert(bl->args);
1009:
1010: w = o = c = 0;
1011: wp = -1;
1012:
1013: for (i = 0; i < (int)bl->args->argc; i++)
1014: if (MDOC_Width == bl->args->argv[i].arg) {
1015: assert(bl->args->argv[i].sz);
1016: wp = i;
1017: w = a2width(bl->args->argv[i].value[0]);
1018: } else if (MDOC_Offset == bl->args->argv[i].arg) {
1019: assert(bl->args->argv[i].sz);
1020: o = a2offs(bl->args->argv[i].value[0]);
1021: } else if (MDOC_Compact == bl->args->argv[i].arg)
1022: c = 1;
1023:
1024: if (MDOC_HEAD == n->type && MDOC_Column == type) {
1025: nn = n->parent->child;
1026: assert(nn && MDOC_HEAD == nn->type);
1027: for (i = 0; nn && nn != n; nn = nn->next, i++)
1028: /* Counter... */ ;
1029: assert(nn);
1030: if (wp >= 0 && i < (int)bl->args[wp].argv->sz)
1031: w = a2width(bl->args->argv[wp].value[i]);
1032: }
1033:
1034: switch (type) {
1035: case (MDOC_Enum):
1036: /* FALLTHROUGH */
1037: case (MDOC_Dash):
1038: /* FALLTHROUGH */
1039: case (MDOC_Hyphen):
1040: /* FALLTHROUGH */
1041: case (MDOC_Bullet):
1042: if (w < 4)
1043: w = 4;
1044: break;
1045: case (MDOC_Inset):
1046: /* FALLTHROUGH */
1047: case (MDOC_Diag):
1048: w = 1;
1049: break;
1050: default:
1051: if (0 == w)
1052: w = 10;
1053: break;
1054: }
1055:
1056: switch (n->type) {
1057: case (MDOC_BLOCK):
1058: break;
1059: case (MDOC_HEAD):
1060: return(mdoc_tbl_head_pre(m, n, h, type, w));
1061: case (MDOC_BODY):
1062: return(mdoc_tbl_body_pre(m, n, h, type, w));
1063: default:
1064: abort();
1065: /* NOTREACHED */
1066: }
1067:
1068: return(mdoc_tbl_block_pre(m, n, h, type, w, o, c));
1069: }
1070:
1071:
1072: /* ARGSUSED */
1073: static int
1074: mdoc_bl_pre(MDOC_ARGS)
1075: {
1076: struct ord *ord;
1077:
1078: if (MDOC_BLOCK != n->type)
1079: return(1);
1080: if (MDOC_Enum != a2list(n))
1081: return(1);
1082:
1.14 kristaps 1083: /* Allocate an -enum on the stack of indices. */
1084:
1.1 kristaps 1085: ord = malloc(sizeof(struct ord));
1086: if (NULL == ord)
1087: err(EXIT_FAILURE, "malloc");
1088: ord->cookie = n;
1089: ord->pos = 1;
1090: SLIST_INSERT_HEAD(&h->ords, ord, entry);
1091:
1092: return(1);
1093: }
1094:
1095:
1096: /* ARGSUSED */
1097: static void
1098: mdoc_bl_post(MDOC_ARGS)
1099: {
1100: struct ord *ord;
1101:
1102: if (MDOC_BLOCK != n->type)
1103: return;
1104: if (MDOC_Enum != a2list(n))
1105: return;
1106:
1107: ord = SLIST_FIRST(&h->ords);
1108: assert(ord);
1109: SLIST_REMOVE_HEAD(&h->ords, entry);
1110: free(ord);
1111: }
1112:
1113:
1114: static int
1115: mdoc_it_pre(MDOC_ARGS)
1116: {
1117: int type;
1118:
1119: if (MDOC_BLOCK == n->type)
1120: type = a2list(n->parent->parent);
1121: else
1122: type = a2list(n->parent->parent->parent);
1123:
1124: return(mdoc_tbl_pre(m, n, h, type));
1125: }
1126:
1127:
1128: /* ARGSUSED */
1129: static int
1130: mdoc_ex_pre(MDOC_ARGS)
1131: {
1132: const struct mdoc_node *nn;
1133: struct tag *t;
1134: struct htmlpair tag;
1135:
1136: print_text(h, "The");
1137:
1138: tag.key = ATTR_CLASS;
1139: tag.val = "utility";
1140:
1141: for (nn = n->child; nn; nn = nn->next) {
1142: t = print_otag(h, TAG_SPAN, 1, &tag);
1143: print_text(h, nn->string);
1144: print_tagq(h, t);
1145:
1146: h->flags |= HTML_NOSPACE;
1147:
1148: if (nn->next && NULL == nn->next->next)
1149: print_text(h, ", and");
1150: else if (nn->next)
1151: print_text(h, ",");
1152: else
1153: h->flags &= ~HTML_NOSPACE;
1154: }
1155:
1156: if (n->child->next)
1157: print_text(h, "utilities exit");
1158: else
1159: print_text(h, "utility exits");
1160:
1161: print_text(h, "0 on success, and >0 if an error occurs.");
1162: return(0);
1163: }
1164:
1165:
1166: /* ARGSUSED */
1167: static int
1168: mdoc_dq_pre(MDOC_ARGS)
1169: {
1170:
1171: if (MDOC_BODY != n->type)
1172: return(1);
1173: print_text(h, "\\(lq");
1174: h->flags |= HTML_NOSPACE;
1175: return(1);
1176: }
1177:
1178:
1179: /* ARGSUSED */
1180: static void
1181: mdoc_dq_post(MDOC_ARGS)
1182: {
1183:
1184: if (MDOC_BODY != n->type)
1185: return;
1186: h->flags |= HTML_NOSPACE;
1187: print_text(h, "\\(rq");
1188: }
1189:
1190:
1191: /* ARGSUSED */
1192: static int
1193: mdoc_pq_pre(MDOC_ARGS)
1194: {
1195:
1196: if (MDOC_BODY != n->type)
1197: return(1);
1198: print_text(h, "\\&(");
1199: h->flags |= HTML_NOSPACE;
1200: return(1);
1201: }
1202:
1203:
1204: /* ARGSUSED */
1205: static void
1206: mdoc_pq_post(MDOC_ARGS)
1207: {
1208:
1209: if (MDOC_BODY != n->type)
1210: return;
1211: print_text(h, ")");
1212: }
1213:
1214:
1215: /* ARGSUSED */
1216: static int
1217: mdoc_sq_pre(MDOC_ARGS)
1218: {
1219:
1220: if (MDOC_BODY != n->type)
1221: return(1);
1222: print_text(h, "\\(oq");
1223: h->flags |= HTML_NOSPACE;
1224: return(1);
1225: }
1226:
1227:
1228: /* ARGSUSED */
1229: static void
1230: mdoc_sq_post(MDOC_ARGS)
1231: {
1232:
1233: if (MDOC_BODY != n->type)
1234: return;
1235: h->flags |= HTML_NOSPACE;
1236: print_text(h, "\\(aq");
1237: }
1238:
1239:
1240: /* ARGSUSED */
1241: static int
1242: mdoc_em_pre(MDOC_ARGS)
1243: {
1244: struct htmlpair tag;
1245:
1246: tag.key = ATTR_CLASS;
1247: tag.val = "emph";
1248:
1249: print_otag(h, TAG_SPAN, 1, &tag);
1250: return(1);
1251: }
1252:
1253:
1254: /* ARGSUSED */
1255: static int
1256: mdoc_d1_pre(MDOC_ARGS)
1257: {
1258: struct htmlpair tag[2];
1259:
1260: if (MDOC_BLOCK != n->type)
1261: return(1);
1262:
1263: buffmt("margin-left: %dem;", INDENT);
1264:
1265: tag[0].key = ATTR_CLASS;
1.5 kristaps 1266: tag[0].val = "lit";
1.1 kristaps 1267: tag[1].key = ATTR_STYLE;
1268: tag[1].val = buf;
1269:
1270: print_otag(h, TAG_DIV, 2, tag);
1271: return(1);
1272: }
1273:
1274:
1275: /* ARGSUSED */
1276: static int
1277: mdoc_sx_pre(MDOC_ARGS)
1278: {
1279: struct htmlpair tag[2];
1280: const struct mdoc_node *nn;
1281:
1282: bufcat("#");
1283: for (nn = n->child; nn; nn = nn->next) {
1284: bufcat(nn->string);
1285: if (nn->next)
1286: bufcat(" ");
1287: }
1288:
1289: tag[0].key = ATTR_HREF;
1290: tag[0].val = buf;
1291: tag[1].key = ATTR_CLASS;
1292: tag[1].val = "link-sec";
1293:
1294: print_otag(h, TAG_A, 2, tag);
1295: return(1);
1296: }
1297:
1298:
1299: /* ARGSUSED */
1300: static int
1301: mdoc_aq_pre(MDOC_ARGS)
1302: {
1303:
1304: if (MDOC_BODY != n->type)
1305: return(1);
1306: print_text(h, "\\(la");
1307: h->flags |= HTML_NOSPACE;
1308: return(1);
1309: }
1310:
1311:
1312: /* ARGSUSED */
1313: static void
1314: mdoc_aq_post(MDOC_ARGS)
1315: {
1316:
1317: if (MDOC_BODY != n->type)
1318: return;
1319: h->flags |= HTML_NOSPACE;
1320: print_text(h, "\\(ra");
1321: }
1322:
1323:
1324: /* ARGSUSED */
1325: static int
1326: mdoc_bd_pre(MDOC_ARGS)
1327: {
1328: struct htmlpair tag[2];
1329: int t, c, o, i;
1.14 kristaps 1330: const struct mdoc_node *bl, *nn;
1.1 kristaps 1331:
1332: if (MDOC_BLOCK == n->type)
1333: bl = n;
1334: else if (MDOC_HEAD == n->type)
1335: return(0);
1336: else
1337: bl = n->parent;
1338:
1339: t = o = c = 0;
1340:
1341: for (i = 0; i < (int)bl->args->argc; i++)
1342: switch (bl->args->argv[i].arg) {
1343: case (MDOC_Offset):
1344: assert(bl->args->argv[i].sz);
1.13 kristaps 1345: o = a2offs(bl->args->argv[i].value[0]);
1.1 kristaps 1346: break;
1347: case (MDOC_Compact):
1348: c = 1;
1349: break;
1350: case (MDOC_Ragged):
1351: /* FALLTHROUGH */
1352: case (MDOC_Filled):
1353: /* FALLTHROUGH */
1354: case (MDOC_Unfilled):
1355: /* FALLTHROUGH */
1356: case (MDOC_Literal):
1357: t = bl->args->argv[i].arg;
1358: break;
1359: }
1360:
1361: if (MDOC_BLOCK == n->type) {
1362: if (o)
1363: buffmt("margin-left: %dem;", o);
1.14 kristaps 1364: if ( ! c) {
1365: for (nn = n; nn; nn = nn->parent) {
1366: if (MDOC_BLOCK != nn->type)
1367: continue;
1368: switch (nn->tok) {
1369: case (MDOC_Ss):
1370: /* FALLTHROUGH */
1371: case (MDOC_Sh):
1372: c = 1;
1373: break;
1374: default:
1375: break;
1376: }
1377: if (nn->prev)
1378: break;
1379: }
1380: if ( ! c)
1381: bufcat("margin-top: 1em;");
1382: }
1.1 kristaps 1383: tag[0].key = ATTR_STYLE;
1384: tag[0].val = buf;
1385: print_otag(h, TAG_DIV, 1, tag);
1386: return(1);
1387: }
1388:
1.14 kristaps 1389: if (MDOC_Unfilled != t && MDOC_Literal != t)
1.1 kristaps 1390: return(1);
1391:
1392: bufcat("white-space: pre;");
1393: tag[0].key = ATTR_STYLE;
1394: tag[0].val = buf;
1395: tag[1].key = ATTR_CLASS;
1.5 kristaps 1396: tag[1].val = "lit";
1.1 kristaps 1397:
1398: print_otag(h, TAG_DIV, 2, tag);
1399:
1.14 kristaps 1400: for (nn = n->child; nn; nn = nn->next) {
1401: print_mdoc_node(m, nn, h);
1402: if (NULL == nn->next)
1403: continue;
1404: if (nn->prev && nn->prev->line < nn->line)
1.1 kristaps 1405: print_text(h, "\n");
1406: }
1407:
1408: return(0);
1409: }
1410:
1411:
1412: /* ARGSUSED */
1413: static int
1414: mdoc_pa_pre(MDOC_ARGS)
1415: {
1416: struct htmlpair tag;
1417:
1418: tag.key = ATTR_CLASS;
1419: tag.val = "file";
1420:
1421: print_otag(h, TAG_SPAN, 1, &tag);
1422: return(1);
1423: }
1424:
1425:
1426: /* ARGSUSED */
1427: static int
1428: mdoc_ad_pre(MDOC_ARGS)
1429: {
1430: struct htmlpair tag;
1431:
1432: tag.key = ATTR_CLASS;
1433: tag.val = "addr";
1434: print_otag(h, TAG_SPAN, 1, &tag);
1435: return(1);
1436: }
1437:
1438:
1439: /* ARGSUSED */
1440: static int
1441: mdoc_an_pre(MDOC_ARGS)
1442: {
1443: struct htmlpair tag;
1444:
1445: tag.key = ATTR_CLASS;
1446: tag.val = "author";
1447: print_otag(h, TAG_SPAN, 1, &tag);
1448: return(1);
1449: }
1450:
1451:
1452: /* ARGSUSED */
1453: static int
1454: mdoc_cd_pre(MDOC_ARGS)
1455: {
1456: struct htmlpair tag;
1457:
1458: tag.key = ATTR_CLASS;
1459: tag.val = "config";
1460: print_otag(h, TAG_SPAN, 1, &tag);
1461: return(1);
1462: }
1463:
1464:
1465: /* ARGSUSED */
1466: static int
1467: mdoc_dv_pre(MDOC_ARGS)
1468: {
1469: struct htmlpair tag;
1470:
1471: tag.key = ATTR_CLASS;
1472: tag.val = "define";
1473: print_otag(h, TAG_SPAN, 1, &tag);
1474: return(1);
1475: }
1476:
1477:
1478: /* ARGSUSED */
1479: static int
1480: mdoc_ev_pre(MDOC_ARGS)
1481: {
1482: struct htmlpair tag;
1483:
1484: tag.key = ATTR_CLASS;
1485: tag.val = "env";
1486: print_otag(h, TAG_SPAN, 1, &tag);
1487: return(1);
1488: }
1489:
1490:
1491: /* ARGSUSED */
1492: static int
1493: mdoc_er_pre(MDOC_ARGS)
1494: {
1495: struct htmlpair tag;
1496:
1497: tag.key = ATTR_CLASS;
1498: tag.val = "errno";
1499: print_otag(h, TAG_SPAN, 1, &tag);
1500: return(1);
1501: }
1502:
1503:
1504: /* ARGSUSED */
1505: static int
1506: mdoc_fa_pre(MDOC_ARGS)
1507: {
1508: const struct mdoc_node *nn;
1509: struct htmlpair tag;
1510: struct tag *t;
1511:
1512: tag.key = ATTR_CLASS;
1513: tag.val = "farg";
1514:
1515: if (n->parent->tok != MDOC_Fo) {
1516: print_otag(h, TAG_SPAN, 1, &tag);
1517: return(1);
1518: }
1519:
1520: for (nn = n->child; nn; nn = nn->next) {
1521: t = print_otag(h, TAG_SPAN, 1, &tag);
1522: print_text(h, nn->string);
1523: print_tagq(h, t);
1524: if (nn->next)
1525: print_text(h, ",");
1526: }
1527:
1528: if (n->child && n->next && n->next->tok == MDOC_Fa)
1529: print_text(h, ",");
1530:
1531: return(0);
1532: }
1533:
1534:
1535: /* ARGSUSED */
1536: static int
1537: mdoc_fd_pre(MDOC_ARGS)
1538: {
1539: struct htmlpair tag;
1540:
1541: if (SEC_SYNOPSIS == n->sec) {
1542: if (n->next && MDOC_Fd != n->next->tok) {
1543: tag.key = ATTR_STYLE;
1544: tag.val = "margin-bottom: 1em;";
1545: print_otag(h, TAG_DIV, 1, &tag);
1546: } else
1547: print_otag(h, TAG_DIV, 0, NULL);
1548: }
1549:
1550: tag.key = ATTR_CLASS;
1551: tag.val = "macro";
1552: print_otag(h, TAG_SPAN, 1, &tag);
1553: return(1);
1554: }
1555:
1556:
1557: /* ARGSUSED */
1558: static int
1559: mdoc_vt_pre(MDOC_ARGS)
1560: {
1561: struct htmlpair tag;
1562:
1563: if (SEC_SYNOPSIS == n->sec) {
1564: if (n->next && MDOC_Vt != n->next->tok) {
1565: tag.key = ATTR_STYLE;
1566: tag.val = "margin-bottom: 1em;";
1567: print_otag(h, TAG_DIV, 1, &tag);
1568: } else
1569: print_otag(h, TAG_DIV, 0, NULL);
1570: }
1571:
1572: tag.key = ATTR_CLASS;
1573: tag.val = "type";
1574: print_otag(h, TAG_SPAN, 1, &tag);
1575: return(1);
1576: }
1577:
1.2 kristaps 1578:
1.1 kristaps 1579: /* ARGSUSED */
1580: static int
1581: mdoc_ft_pre(MDOC_ARGS)
1582: {
1583: struct htmlpair tag;
1584:
1585: if (SEC_SYNOPSIS == n->sec) {
1586: if (n->prev && MDOC_Fo == n->prev->tok) {
1587: tag.key = ATTR_STYLE;
1.4 kristaps 1588: tag.val = "margin-top: 1em;";
1.1 kristaps 1589: print_otag(h, TAG_DIV, 1, &tag);
1590: } else
1591: print_otag(h, TAG_DIV, 0, NULL);
1592: }
1593:
1594: tag.key = ATTR_CLASS;
1.7 kristaps 1595: tag.val = "ftype";
1.1 kristaps 1596: print_otag(h, TAG_SPAN, 1, &tag);
1597: return(1);
1598: }
1599:
1600:
1601: /* ARGSUSED */
1602: static int
1603: mdoc_fn_pre(MDOC_ARGS)
1604: {
1605: struct tag *t;
1.15 ! kristaps 1606: struct htmlpair tag[2];
1.1 kristaps 1607: const struct mdoc_node *nn;
1.7 kristaps 1608: char nbuf[BUFSIZ];
1609: const char *sp, *ep;
1.15 ! kristaps 1610: int sz, i;
1.1 kristaps 1611:
1612: if (SEC_SYNOPSIS == n->sec) {
1.15 ! kristaps 1613: bufcat("margin-left: 6em;");
! 1614: bufcat("text-indent: -6em;");
! 1615: if (n->next)
! 1616: bufcat("margin-bottom: 1em;");
! 1617: tag[0].key = ATTR_STYLE;
! 1618: tag[0].val = buf;
! 1619: print_otag(h, TAG_DIV, 1, tag);
1.1 kristaps 1620: }
1621:
1.7 kristaps 1622: /* Split apart into type and name. */
1623:
1.15 ! kristaps 1624: tag[0].key = ATTR_CLASS;
! 1625: tag[0].val = "ftype";
! 1626: t = print_otag(h, TAG_SPAN, 1, tag);
1.7 kristaps 1627:
1628: assert(n->child->string);
1629: sp = n->child->string;
1.12 kristaps 1630: while (NULL != (ep = strchr(sp, ' '))) {
1.9 kristaps 1631: sz = MIN((int)(ep - sp), BUFSIZ - 1);
1632: (void)memcpy(nbuf, sp, (size_t)sz);
1.7 kristaps 1633: nbuf[sz] = '\0';
1634: print_text(h, nbuf);
1635: sp = ++ep;
1636: }
1.1 kristaps 1637:
1.7 kristaps 1638: print_tagq(h, t);
1.4 kristaps 1639:
1.15 ! kristaps 1640: tag[0].key = ATTR_CLASS;
! 1641: tag[0].val = "fname";
! 1642: t = print_otag(h, TAG_SPAN, 1, tag);
1.7 kristaps 1643:
1644: if (sp) {
1645: (void)strlcpy(nbuf, sp, BUFSIZ);
1646: print_text(h, nbuf);
1647: }
1648:
1.1 kristaps 1649: print_tagq(h, t);
1650:
1651: h->flags |= HTML_NOSPACE;
1652: print_text(h, "(");
1653:
1654: for (nn = n->child->next; nn; nn = nn->next) {
1.15 ! kristaps 1655: i = 0;
! 1656: tag[i].key = ATTR_CLASS;
! 1657: tag[i++].val = "farg";
! 1658: if (SEC_SYNOPSIS == n->sec) {
! 1659: tag[i].key = ATTR_STYLE;
! 1660: tag[i++].val = "white-space: nowrap;";
! 1661: }
! 1662:
! 1663: t = print_otag(h, TAG_SPAN, i, tag);
1.1 kristaps 1664: print_text(h, nn->string);
1665: print_tagq(h, t);
1666: if (nn->next)
1667: print_text(h, ",");
1668: }
1669:
1670: print_text(h, ")");
1671:
1672: if (SEC_SYNOPSIS == n->sec)
1673: print_text(h, ";");
1674:
1675: return(0);
1676: }
1677:
1678:
1679: /* ARGSUSED */
1680: static int
1681: mdoc_sp_pre(MDOC_ARGS)
1682: {
1683: int len;
1684: struct htmlpair tag;
1685:
1686: switch (n->tok) {
1687: case (MDOC_sp):
1688: len = n->child ? atoi(n->child->string) : 1;
1689: break;
1690: case (MDOC_br):
1691: len = 0;
1692: break;
1693: default:
1694: len = 1;
1695: break;
1696: }
1697:
1698: buffmt("height: %dem", len);
1699: tag.key = ATTR_STYLE;
1700: tag.val = buf;
1701: print_otag(h, TAG_DIV, 1, &tag);
1702: return(1);
1703:
1704: }
1.2 kristaps 1705:
1706:
1707: /* ARGSUSED */
1708: static int
1709: mdoc_brq_pre(MDOC_ARGS)
1710: {
1711:
1712: if (MDOC_BODY != n->type)
1713: return(1);
1714: print_text(h, "\\(lC");
1715: h->flags |= HTML_NOSPACE;
1716: return(1);
1717: }
1718:
1719:
1720: /* ARGSUSED */
1721: static void
1722: mdoc_brq_post(MDOC_ARGS)
1723: {
1724:
1725: if (MDOC_BODY != n->type)
1726: return;
1727: h->flags |= HTML_NOSPACE;
1728: print_text(h, "\\(rC");
1729: }
1730:
1731:
1732: /* ARGSUSED */
1733: static int
1734: mdoc_lk_pre(MDOC_ARGS)
1735: {
1736: const struct mdoc_node *nn;
1737: struct htmlpair tag[2];
1738:
1739: nn = n->child;
1740:
1741: tag[0].key = ATTR_CLASS;
1742: tag[0].val = "link-ext";
1743: tag[1].key = ATTR_HREF;
1744: tag[1].val = nn->string;
1745:
1746: print_otag(h, TAG_A, 2, tag);
1747:
1748: if (NULL == nn->next)
1749: return(1);
1750:
1751: for (nn = nn->next; nn; nn = nn->next)
1752: print_text(h, nn->string);
1753:
1754: return(0);
1755: }
1756:
1757:
1758: /* ARGSUSED */
1759: static int
1760: mdoc_mt_pre(MDOC_ARGS)
1761: {
1762: struct htmlpair tag[2];
1763: struct tag *t;
1764: const struct mdoc_node *nn;
1765:
1766: tag[0].key = ATTR_CLASS;
1767: tag[0].val = "link-mail";
1768:
1769: for (nn = n->child; nn; nn = nn->next) {
1770: bufinit();
1771: bufcat("mailto:");
1772: bufcat(nn->string);
1773:
1774: tag[1].key = ATTR_HREF;
1775: tag[1].val = buf;
1776:
1777: t = print_otag(h, TAG_A, 2, tag);
1778: print_text(h, nn->string);
1779: print_tagq(h, t);
1780: }
1781:
1782: return(0);
1783: }
1.4 kristaps 1784:
1785:
1786: /* ARGSUSED */
1787: static int
1788: mdoc_fo_pre(MDOC_ARGS)
1789: {
1790: struct htmlpair tag;
1791:
1792: if (MDOC_BODY == n->type) {
1793: h->flags |= HTML_NOSPACE;
1794: print_text(h, "(");
1795: h->flags |= HTML_NOSPACE;
1796: return(1);
1797: } else if (MDOC_BLOCK == n->type)
1798: return(1);
1799:
1800: tag.key = ATTR_CLASS;
1801: tag.val = "fname";
1802: print_otag(h, TAG_SPAN, 1, &tag);
1803: return(1);
1804: }
1805:
1806:
1807: /* ARGSUSED */
1808: static void
1809: mdoc_fo_post(MDOC_ARGS)
1810: {
1811: if (MDOC_BODY != n->type)
1812: return;
1813: h->flags |= HTML_NOSPACE;
1814: print_text(h, ")");
1815: h->flags |= HTML_NOSPACE;
1816: print_text(h, ";");
1817: }
1818:
1819:
1820: /* ARGSUSED */
1821: static int
1822: mdoc_in_pre(MDOC_ARGS)
1823: {
1824: const struct mdoc_node *nn;
1825: struct htmlpair tag;
1826:
1827: if (SEC_SYNOPSIS == n->sec) {
1828: if (n->next && MDOC_In != n->next->tok) {
1829: tag.key = ATTR_STYLE;
1830: tag.val = "margin-bottom: 1em;";
1831: print_otag(h, TAG_DIV, 1, &tag);
1832: } else
1833: print_otag(h, TAG_DIV, 0, NULL);
1834: }
1835:
1836: tag.key = ATTR_CLASS;
1837: tag.val = "includes";
1838:
1839: print_otag(h, TAG_SPAN, 1, &tag);
1840:
1841: if (SEC_SYNOPSIS == n->sec)
1842: print_text(h, "#include");
1843:
1844: print_text(h, "<");
1845: h->flags |= HTML_NOSPACE;
1846:
1847: /* XXX -- see warning in termp_in_post(). */
1848:
1849: for (nn = n->child; nn; nn = nn->next)
1850: print_mdoc_node(m, nn, h);
1851:
1852: h->flags |= HTML_NOSPACE;
1853: print_text(h, ">");
1854:
1855: return(0);
1856: }
1857:
1858:
1859: /* ARGSUSED */
1860: static int
1861: mdoc_ic_pre(MDOC_ARGS)
1862: {
1863: struct htmlpair tag;
1864:
1865: tag.key = ATTR_CLASS;
1866: tag.val = "cmd";
1867:
1868: print_otag(h, TAG_SPAN, 1, &tag);
1869: return(1);
1870: }
1871:
1872:
1873: /* ARGSUSED */
1874: static int
1875: mdoc_rv_pre(MDOC_ARGS)
1876: {
1877: const struct mdoc_node *nn;
1878: struct htmlpair tag;
1879: struct tag *t;
1880:
1881: print_otag(h, TAG_DIV, 0, NULL);
1882:
1883: print_text(h, "The");
1884:
1885: for (nn = n->child; nn; nn = nn->next) {
1886: tag.key = ATTR_CLASS;
1887: tag.val = "fname";
1888: t = print_otag(h, TAG_SPAN, 1, &tag);
1889: print_text(h, nn->string);
1890: print_tagq(h, t);
1891:
1892: h->flags |= HTML_NOSPACE;
1893: if (nn->next && NULL == nn->next->next)
1894: print_text(h, "(), and");
1895: else if (nn->next)
1896: print_text(h, "(),");
1897: else
1898: print_text(h, "()");
1899: }
1900:
1901: if (n->child->next)
1902: print_text(h, "functions return");
1903: else
1904: print_text(h, "function returns");
1905:
1906: print_text(h, "the value 0 if successful; otherwise the value "
1907: "-1 is returned and the global variable");
1908:
1909: tag.key = ATTR_CLASS;
1910: tag.val = "var";
1911: t = print_otag(h, TAG_SPAN, 1, &tag);
1912: print_text(h, "errno");
1913: print_tagq(h, t);
1914: print_text(h, "is set to indicate the error.");
1915: return(0);
1916: }
1917:
1918:
1919: /* ARGSUSED */
1920: static int
1921: mdoc_va_pre(MDOC_ARGS)
1922: {
1923: struct htmlpair tag;
1924:
1925: tag.key = ATTR_CLASS;
1926: tag.val = "var";
1927: print_otag(h, TAG_SPAN, 1, &tag);
1928: return(1);
1929: }
1930:
1931:
1932: /* ARGSUSED */
1933: static int
1934: mdoc_bq_pre(MDOC_ARGS)
1935: {
1936:
1937: if (MDOC_BODY != n->type)
1938: return(1);
1939: print_text(h, "\\(lB");
1940: h->flags |= HTML_NOSPACE;
1941: return(1);
1942: }
1943:
1944:
1945: /* ARGSUSED */
1946: static void
1947: mdoc_bq_post(MDOC_ARGS)
1948: {
1949:
1950: if (MDOC_BODY != n->type)
1951: return;
1952: h->flags |= HTML_NOSPACE;
1953: print_text(h, "\\(rB");
1954: }
1.5 kristaps 1955:
1956:
1957: /* ARGSUSED */
1958: static int
1959: mdoc_ap_pre(MDOC_ARGS)
1960: {
1961:
1962: h->flags |= HTML_NOSPACE;
1963: print_text(h, "\\(aq");
1964: h->flags |= HTML_NOSPACE;
1965: return(1);
1966: }
1967:
1968:
1969: /* ARGSUSED */
1970: static int
1971: mdoc_bf_pre(MDOC_ARGS)
1972: {
1973: int i;
1974: struct htmlpair tag[2];
1975:
1976: if (MDOC_HEAD == n->type)
1977: return(0);
1978: else if (MDOC_BLOCK != n->type)
1979: return(1);
1980:
1981: tag[0].key = ATTR_CLASS;
1982: tag[0].val = NULL;
1983:
1984: if (n->head->child) {
1985: if ( ! strcmp("Em", n->head->child->string))
1986: tag[0].val = "emph";
1987: else if ( ! strcmp("Sy", n->head->child->string))
1988: tag[0].val = "symb";
1989: else if ( ! strcmp("Li", n->head->child->string))
1990: tag[0].val = "lit";
1991: } else {
1992: assert(n->args);
1993: for (i = 0; i < (int)n->args->argc; i++)
1994: switch (n->args->argv[i].arg) {
1995: case (MDOC_Symbolic):
1996: tag[0].val = "symb";
1997: break;
1998: case (MDOC_Literal):
1999: tag[0].val = "lit";
2000: break;
2001: case (MDOC_Emphasis):
2002: tag[0].val = "emph";
2003: break;
2004: default:
2005: break;
2006: }
2007: }
2008:
2009: /* FIXME: div's have spaces stripped--we want them. */
2010:
2011: assert(tag[0].val);
2012: tag[1].key = ATTR_STYLE;
2013: tag[1].val = "display: inline; margin-right: 1em;";
2014: print_otag(h, TAG_DIV, 2, tag);
2015: return(1);
2016: }
2017:
2018:
2019: /* ARGSUSED */
2020: static int
2021: mdoc_ms_pre(MDOC_ARGS)
2022: {
2023: struct htmlpair tag;
2024:
2025: tag.key = ATTR_CLASS;
2026: tag.val = "symb";
2027: print_otag(h, TAG_SPAN, 1, &tag);
2028: return(1);
2029: }
2030:
2031:
2032: /* ARGSUSED */
2033: static int
2034: mdoc_pf_pre(MDOC_ARGS)
2035: {
2036:
2037: h->flags |= HTML_IGNDELIM;
2038: return(1);
2039: }
2040:
2041:
2042: /* ARGSUSED */
2043: static void
2044: mdoc_pf_post(MDOC_ARGS)
2045: {
2046:
2047: h->flags &= ~HTML_IGNDELIM;
2048: h->flags |= HTML_NOSPACE;
2049: }
2050:
2051:
2052: /* ARGSUSED */
2053: static int
2054: mdoc_rs_pre(MDOC_ARGS)
2055: {
1.8 kristaps 2056: struct htmlpair tag;
1.5 kristaps 2057:
2058: if (MDOC_BLOCK != n->type)
2059: return(1);
2060:
1.8 kristaps 2061: if (n->prev && SEC_SEE_ALSO == n->sec) {
2062: tag.key = ATTR_STYLE;
2063: tag.val = "margin-top: 1em;";
2064: print_otag(h, TAG_DIV, 1, &tag);
1.5 kristaps 2065: }
2066:
1.8 kristaps 2067: tag.key = ATTR_CLASS;
2068: tag.val = "ref";
2069: print_otag(h, TAG_SPAN, 1, &tag);
1.5 kristaps 2070: return(1);
2071: }
1.6 kristaps 2072:
2073:
2074:
2075: /* ARGSUSED */
2076: static int
2077: mdoc_li_pre(MDOC_ARGS)
2078: {
2079: struct htmlpair tag;
2080:
2081: tag.key = ATTR_CLASS;
2082: tag.val = "lit";
2083:
2084: print_otag(h, TAG_SPAN, 1, &tag);
2085: return(1);
2086: }
2087:
2088:
2089: /* ARGSUSED */
2090: static int
2091: mdoc_sy_pre(MDOC_ARGS)
2092: {
2093: struct htmlpair tag;
2094:
2095: tag.key = ATTR_CLASS;
2096: tag.val = "symb";
2097:
2098: print_otag(h, TAG_SPAN, 1, &tag);
2099: return(1);
2100: }
2101:
2102:
2103: /* ARGSUSED */
2104: static int
2105: mdoc_bt_pre(MDOC_ARGS)
2106: {
2107:
2108: print_text(h, "is currently in beta test.");
2109: return(0);
2110: }
2111:
2112:
2113: /* ARGSUSED */
2114: static int
2115: mdoc_ud_pre(MDOC_ARGS)
2116: {
2117:
2118: print_text(h, "currently under development.");
2119: return(0);
2120: }
2121:
2122:
2123: /* ARGSUSED */
2124: static int
2125: mdoc_lb_pre(MDOC_ARGS)
2126: {
2127: struct htmlpair tag;
2128:
2129: tag.key = ATTR_CLASS;
2130: tag.val = "lib";
2131:
2132: if (SEC_SYNOPSIS == n->sec)
2133: print_otag(h, TAG_DIV, 0, NULL);
2134:
2135: print_otag(h, TAG_SPAN, 1, &tag);
2136: return(1);
2137: }
1.10 kristaps 2138:
2139:
2140: /* ARGSUSED */
2141: static int
2142: mdoc__x_pre(MDOC_ARGS)
2143: {
2144: struct htmlpair tag;
2145:
2146: tag.key = ATTR_CLASS;
2147:
2148: switch (n->tok) {
2149: case(MDOC__A):
2150: tag.val = "ref-auth";
2151: break;
2152: case(MDOC__B):
2153: tag.val = "ref-book";
2154: break;
2155: case(MDOC__C):
2156: tag.val = "ref-city";
2157: break;
2158: case(MDOC__D):
2159: tag.val = "ref-date";
2160: break;
2161: case(MDOC__I):
2162: tag.val = "ref-issue";
2163: break;
2164: case(MDOC__J):
2165: tag.val = "ref-jrnl";
2166: break;
2167: case(MDOC__N):
2168: tag.val = "ref-num";
2169: break;
2170: case(MDOC__O):
2171: tag.val = "ref-opt";
2172: break;
2173: case(MDOC__P):
2174: tag.val = "ref-page";
2175: break;
2176: case(MDOC__Q):
2177: tag.val = "ref-corp";
2178: break;
2179: case(MDOC__R):
2180: tag.val = "ref-rep";
2181: break;
2182: case(MDOC__T):
2183: print_text(h, "\\(lq");
2184: h->flags |= HTML_NOSPACE;
2185: tag.val = "ref-title";
2186: break;
2187: case(MDOC__V):
2188: tag.val = "ref-vol";
2189: break;
2190: default:
2191: abort();
2192: /* NOTREACHED */
2193: }
2194:
2195: print_otag(h, TAG_SPAN, 1, &tag);
2196: return(1);
2197: }
2198:
2199:
2200: /* ARGSUSED */
2201: static void
2202: mdoc__x_post(MDOC_ARGS)
2203: {
2204:
2205: h->flags |= HTML_NOSPACE;
2206: switch (n->tok) {
2207: case (MDOC__T):
2208: print_text(h, "\\(rq");
2209: h->flags |= HTML_NOSPACE;
2210: break;
2211: default:
2212: break;
2213: }
2214: print_text(h, n->next ? "," : ".");
2215: }
CVSweb