Annotation of src/usr.bin/mandoc/man_html.c, Revision 1.20
1.20 ! schwarze 1: /* $Id: man_html.c,v 1.19 2010/10/15 20:45:03 schwarze Exp $ */
1.1 schwarze 2: /*
1.17 schwarze 3: * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
1.20 ! schwarze 4: * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
1.1 schwarze 5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18: #include <sys/types.h>
19:
20: #include <assert.h>
21: #include <ctype.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25:
1.14 schwarze 26: #include "mandoc.h"
1.1 schwarze 27: #include "out.h"
28: #include "html.h"
29: #include "man.h"
30: #include "main.h"
31:
32: /* TODO: preserve ident widths. */
1.2 schwarze 33: /* FIXME: have PD set the default vspace width. */
1.1 schwarze 34:
35: #define INDENT 5
36: #define HALFINDENT 3
37:
38: #define MAN_ARGS const struct man_meta *m, \
39: const struct man_node *n, \
1.18 schwarze 40: struct mhtml *mh, \
1.1 schwarze 41: struct html *h
42:
1.18 schwarze 43: struct mhtml {
44: int fl;
45: #define MANH_LITERAL (1 << 0) /* literal context */
46: };
47:
1.1 schwarze 48: struct htmlman {
49: int (*pre)(MAN_ARGS);
50: int (*post)(MAN_ARGS);
51: };
52:
53: static void print_man(MAN_ARGS);
54: static void print_man_head(MAN_ARGS);
55: static void print_man_nodelist(MAN_ARGS);
56: static void print_man_node(MAN_ARGS);
57:
58: static int a2width(const struct man_node *,
59: struct roffsu *);
60:
61: static int man_alt_pre(MAN_ARGS);
62: static int man_br_pre(MAN_ARGS);
63: static int man_ign_pre(MAN_ARGS);
1.20 ! schwarze 64: static int man_ft_pre(MAN_ARGS);
1.18 schwarze 65: static int man_in_pre(MAN_ARGS);
66: static int man_literal_pre(MAN_ARGS);
1.1 schwarze 67: static void man_root_post(MAN_ARGS);
68: static int man_root_pre(MAN_ARGS);
69: static int man_B_pre(MAN_ARGS);
70: static int man_HP_pre(MAN_ARGS);
71: static int man_I_pre(MAN_ARGS);
72: static int man_IP_pre(MAN_ARGS);
73: static int man_PP_pre(MAN_ARGS);
74: static int man_RS_pre(MAN_ARGS);
75: static int man_SB_pre(MAN_ARGS);
76: static int man_SH_pre(MAN_ARGS);
77: static int man_SM_pre(MAN_ARGS);
78: static int man_SS_pre(MAN_ARGS);
79:
80: static const struct htmlman mans[MAN_MAX] = {
81: { man_br_pre, NULL }, /* br */
82: { NULL, NULL }, /* TH */
83: { man_SH_pre, NULL }, /* SH */
84: { man_SS_pre, NULL }, /* SS */
85: { man_IP_pre, NULL }, /* TP */
86: { man_PP_pre, NULL }, /* LP */
87: { man_PP_pre, NULL }, /* PP */
88: { man_PP_pre, NULL }, /* P */
89: { man_IP_pre, NULL }, /* IP */
90: { man_HP_pre, NULL }, /* HP */
91: { man_SM_pre, NULL }, /* SM */
92: { man_SB_pre, NULL }, /* SB */
93: { man_alt_pre, NULL }, /* BI */
94: { man_alt_pre, NULL }, /* IB */
95: { man_alt_pre, NULL }, /* BR */
96: { man_alt_pre, NULL }, /* RB */
97: { NULL, NULL }, /* R */
98: { man_B_pre, NULL }, /* B */
99: { man_I_pre, NULL }, /* I */
100: { man_alt_pre, NULL }, /* IR */
101: { man_alt_pre, NULL }, /* RI */
102: { NULL, NULL }, /* na */
103: { NULL, NULL }, /* i */
104: { man_br_pre, NULL }, /* sp */
1.18 schwarze 105: { man_literal_pre, NULL }, /* nf */
106: { man_literal_pre, NULL }, /* fi */
1.1 schwarze 107: { NULL, NULL }, /* r */
108: { NULL, NULL }, /* RE */
109: { man_RS_pre, NULL }, /* RS */
110: { man_ign_pre, NULL }, /* DT */
111: { man_ign_pre, NULL }, /* UC */
1.2 schwarze 112: { man_ign_pre, NULL }, /* PD */
1.6 schwarze 113: { man_br_pre, NULL }, /* Sp */
1.18 schwarze 114: { man_literal_pre, NULL }, /* Vb */
115: { man_literal_pre, NULL }, /* Ve */
1.13 schwarze 116: { man_ign_pre, NULL }, /* AT */
1.18 schwarze 117: { man_in_pre, NULL }, /* in */
1.19 schwarze 118: { NULL, NULL }, /* TS */
119: { NULL, NULL }, /* TE */
1.20 ! schwarze 120: { man_ft_pre, NULL }, /* ft */
1.1 schwarze 121: };
122:
123:
124: void
125: html_man(void *arg, const struct man *m)
126: {
127: struct html *h;
128: struct tag *t;
1.18 schwarze 129: struct mhtml mh;
1.1 schwarze 130:
131: h = (struct html *)arg;
132:
1.5 schwarze 133: print_gen_decls(h);
1.1 schwarze 134:
1.18 schwarze 135: memset(&mh, 0, sizeof(struct mhtml));
136:
1.1 schwarze 137: t = print_otag(h, TAG_HTML, 0, NULL);
1.18 schwarze 138: print_man(man_meta(m), man_node(m), &mh, h);
1.1 schwarze 139: print_tagq(h, t);
140:
141: printf("\n");
142: }
143:
144:
145: static void
146: print_man(MAN_ARGS)
147: {
148: struct tag *t;
149: struct htmlpair tag;
150:
151: t = print_otag(h, TAG_HEAD, 0, NULL);
152:
1.18 schwarze 153: print_man_head(m, n, mh, h);
1.1 schwarze 154: print_tagq(h, t);
155: t = print_otag(h, TAG_BODY, 0, NULL);
156:
157: tag.key = ATTR_CLASS;
158: tag.val = "body";
159: print_otag(h, TAG_DIV, 1, &tag);
160:
1.18 schwarze 161: print_man_nodelist(m, n, mh, h);
1.1 schwarze 162:
163: print_tagq(h, t);
164: }
165:
166:
167: /* ARGSUSED */
168: static void
169: print_man_head(MAN_ARGS)
170: {
171:
172: print_gen_head(h);
173: bufinit(h);
1.10 schwarze 174: buffmt(h, "%s(%s)", m->title, m->msec);
1.1 schwarze 175:
176: print_otag(h, TAG_TITLE, 0, NULL);
177: print_text(h, h->buf);
178: }
179:
180:
181: static void
182: print_man_nodelist(MAN_ARGS)
183: {
184:
1.18 schwarze 185: print_man_node(m, n, mh, h);
1.1 schwarze 186: if (n->next)
1.18 schwarze 187: print_man_nodelist(m, n->next, mh, h);
1.1 schwarze 188: }
189:
190:
191: static void
192: print_man_node(MAN_ARGS)
193: {
194: int child;
195: struct tag *t;
196:
197: child = 1;
1.2 schwarze 198: t = h->tags.head;
1.1 schwarze 199:
200: bufinit(h);
201:
1.7 schwarze 202: /*
203: * FIXME: embedded elements within next-line scopes (e.g., `br'
204: * within an empty `B') will cause formatting to be forgotten
205: * due to scope closing out.
206: */
207:
1.1 schwarze 208: switch (n->type) {
209: case (MAN_ROOT):
1.18 schwarze 210: child = man_root_pre(m, n, mh, h);
1.1 schwarze 211: break;
212: case (MAN_TEXT):
213: print_text(h, n->string);
1.18 schwarze 214:
215: if (MANH_LITERAL & mh->fl)
216: print_otag(h, TAG_BR, 0, NULL);
217:
1.4 schwarze 218: return;
1.1 schwarze 219: default:
1.4 schwarze 220: /*
221: * Close out scope of font prior to opening a macro
222: * scope. Assert that the metafont is on the top of the
223: * stack (it's never nested).
224: */
225: if (h->metaf) {
226: assert(h->metaf == t);
227: print_tagq(h, h->metaf);
228: assert(NULL == h->metaf);
229: t = h->tags.head;
230: }
1.1 schwarze 231: if (mans[n->tok].pre)
1.18 schwarze 232: child = (*mans[n->tok].pre)(m, n, mh, h);
1.1 schwarze 233: break;
234: }
235:
236: if (child && n->child)
1.18 schwarze 237: print_man_nodelist(m, n->child, mh, h);
1.1 schwarze 238:
1.4 schwarze 239: /* This will automatically close out any font scope. */
1.1 schwarze 240: print_stagq(h, t);
241:
242: bufinit(h);
243:
244: switch (n->type) {
245: case (MAN_ROOT):
1.18 schwarze 246: man_root_post(m, n, mh, h);
1.1 schwarze 247: break;
248: case (MAN_TEXT):
249: break;
250: default:
251: if (mans[n->tok].post)
1.18 schwarze 252: (*mans[n->tok].post)(m, n, mh, h);
1.1 schwarze 253: break;
254: }
255: }
256:
257:
258: static int
259: a2width(const struct man_node *n, struct roffsu *su)
260: {
261:
262: if (MAN_TEXT != n->type)
263: return(0);
264: if (a2roffsu(n->string, su, SCALE_BU))
265: return(1);
266:
267: return(0);
268: }
269:
270:
271: /* ARGSUSED */
272: static int
273: man_root_pre(MAN_ARGS)
274: {
1.3 schwarze 275: struct htmlpair tag[3];
1.1 schwarze 276: struct tag *t, *tt;
277: char b[BUFSIZ], title[BUFSIZ];
278:
279: b[0] = 0;
280: if (m->vol)
281: (void)strlcat(b, m->vol, BUFSIZ);
282:
1.10 schwarze 283: snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
1.1 schwarze 284:
285: PAIR_CLASS_INIT(&tag[0], "header");
286: bufcat_style(h, "width", "100%");
287: PAIR_STYLE_INIT(&tag[1], h);
1.3 schwarze 288: PAIR_SUMMARY_INIT(&tag[2], "header");
289:
290: t = print_otag(h, TAG_TABLE, 3, tag);
1.1 schwarze 291: tt = print_otag(h, TAG_TR, 0, NULL);
292:
293: bufinit(h);
294: bufcat_style(h, "width", "10%");
295: PAIR_STYLE_INIT(&tag[0], h);
296: print_otag(h, TAG_TD, 1, tag);
297: print_text(h, title);
298: print_stagq(h, tt);
299:
300: bufinit(h);
301: bufcat_style(h, "width", "80%");
302: bufcat_style(h, "white-space", "nowrap");
303: bufcat_style(h, "text-align", "center");
304: PAIR_STYLE_INIT(&tag[0], h);
305: print_otag(h, TAG_TD, 1, tag);
306: print_text(h, b);
307: print_stagq(h, tt);
308:
309: bufinit(h);
310: bufcat_style(h, "width", "10%");
311: bufcat_style(h, "text-align", "right");
312: PAIR_STYLE_INIT(&tag[0], h);
313: print_otag(h, TAG_TD, 1, tag);
314: print_text(h, title);
315: print_tagq(h, t);
316: return(1);
317: }
318:
319:
320: /* ARGSUSED */
321: static void
322: man_root_post(MAN_ARGS)
323: {
1.3 schwarze 324: struct htmlpair tag[3];
1.1 schwarze 325: struct tag *t, *tt;
1.2 schwarze 326: char b[DATESIZ];
1.1 schwarze 327:
1.15 schwarze 328: if (m->rawdate)
329: strlcpy(b, m->rawdate, DATESIZ);
330: else
331: time2a(m->date, b, DATESIZ);
1.1 schwarze 332:
333: PAIR_CLASS_INIT(&tag[0], "footer");
334: bufcat_style(h, "width", "100%");
335: PAIR_STYLE_INIT(&tag[1], h);
1.3 schwarze 336: PAIR_SUMMARY_INIT(&tag[2], "footer");
337:
338: t = print_otag(h, TAG_TABLE, 3, tag);
1.1 schwarze 339: tt = print_otag(h, TAG_TR, 0, NULL);
340:
341: bufinit(h);
342: bufcat_style(h, "width", "50%");
343: PAIR_STYLE_INIT(&tag[0], h);
344: print_otag(h, TAG_TD, 1, tag);
345: print_text(h, b);
346: print_stagq(h, tt);
347:
348: bufinit(h);
349: bufcat_style(h, "width", "50%");
350: bufcat_style(h, "text-align", "right");
351: PAIR_STYLE_INIT(&tag[0], h);
352: print_otag(h, TAG_TD, 1, tag);
353: if (m->source)
354: print_text(h, m->source);
355: print_tagq(h, t);
356: }
357:
358:
359:
360: /* ARGSUSED */
361: static int
362: man_br_pre(MAN_ARGS)
363: {
364: struct roffsu su;
365: struct htmlpair tag;
366:
367: SCALE_VS_INIT(&su, 1);
368:
1.8 schwarze 369: switch (n->tok) {
370: case (MAN_Sp):
371: SCALE_VS_INIT(&su, 0.5);
372: break;
373: case (MAN_sp):
374: if (n->child)
375: a2roffsu(n->child->string, &su, SCALE_VS);
376: break;
377: default:
1.1 schwarze 378: su.scale = 0;
1.8 schwarze 379: break;
380: }
1.1 schwarze 381:
382: bufcat_su(h, "height", &su);
383: PAIR_STYLE_INIT(&tag, h);
384: print_otag(h, TAG_DIV, 1, &tag);
1.4 schwarze 385:
1.3 schwarze 386: /* So the div isn't empty: */
387: print_text(h, "\\~");
388:
1.1 schwarze 389: return(0);
390: }
391:
392:
393: /* ARGSUSED */
394: static int
395: man_SH_pre(MAN_ARGS)
396: {
397: struct htmlpair tag[2];
398: struct roffsu su;
399:
400: if (MAN_BODY == n->type) {
401: SCALE_HS_INIT(&su, INDENT);
402: bufcat_su(h, "margin-left", &su);
403: PAIR_CLASS_INIT(&tag[0], "sec-body");
404: PAIR_STYLE_INIT(&tag[1], h);
405: print_otag(h, TAG_DIV, 2, tag);
406: return(1);
407: } else if (MAN_BLOCK == n->type) {
408: PAIR_CLASS_INIT(&tag[0], "sec-block");
409: if (n->prev && MAN_SH == n->prev->tok)
410: if (NULL == n->prev->body->child) {
411: print_otag(h, TAG_DIV, 1, tag);
412: return(1);
413: }
414:
415: SCALE_VS_INIT(&su, 1);
416: bufcat_su(h, "margin-top", &su);
417: if (NULL == n->next)
418: bufcat_su(h, "margin-bottom", &su);
419: PAIR_STYLE_INIT(&tag[1], h);
420: print_otag(h, TAG_DIV, 2, tag);
421: return(1);
422: }
423:
424: PAIR_CLASS_INIT(&tag[0], "sec-head");
425: print_otag(h, TAG_DIV, 1, tag);
426: return(1);
427: }
428:
429:
430: /* ARGSUSED */
431: static int
432: man_alt_pre(MAN_ARGS)
433: {
434: const struct man_node *nn;
435: struct tag *t;
436: int i;
1.4 schwarze 437: enum htmlfont fp;
1.1 schwarze 438:
439: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
440: switch (n->tok) {
441: case (MAN_BI):
1.4 schwarze 442: fp = i % 2 ? HTMLFONT_ITALIC : HTMLFONT_BOLD;
1.1 schwarze 443: break;
444: case (MAN_IB):
1.4 schwarze 445: fp = i % 2 ? HTMLFONT_BOLD : HTMLFONT_ITALIC;
1.1 schwarze 446: break;
447: case (MAN_RI):
1.4 schwarze 448: fp = i % 2 ? HTMLFONT_ITALIC : HTMLFONT_NONE;
1.1 schwarze 449: break;
450: case (MAN_IR):
1.4 schwarze 451: fp = i % 2 ? HTMLFONT_NONE : HTMLFONT_ITALIC;
1.1 schwarze 452: break;
453: case (MAN_BR):
1.4 schwarze 454: fp = i % 2 ? HTMLFONT_NONE : HTMLFONT_BOLD;
1.1 schwarze 455: break;
456: case (MAN_RB):
1.4 schwarze 457: fp = i % 2 ? HTMLFONT_BOLD : HTMLFONT_NONE;
1.1 schwarze 458: break;
459: default:
460: abort();
461: /* NOTREACHED */
462: }
463:
464: if (i)
465: h->flags |= HTML_NOSPACE;
466:
1.4 schwarze 467: /*
468: * Open and close the scope with each argument, so that
469: * internal \f escapes, which are common, are also
470: * closed out with the scope.
471: */
472: t = print_ofont(h, fp);
1.18 schwarze 473: print_man_node(m, nn, mh, h);
1.4 schwarze 474: print_tagq(h, t);
1.1 schwarze 475: }
476:
477: return(0);
478: }
479:
480:
481: /* ARGSUSED */
482: static int
483: man_SB_pre(MAN_ARGS)
484: {
485: struct htmlpair tag;
486:
1.4 schwarze 487: /* FIXME: print_ofont(). */
1.1 schwarze 488: PAIR_CLASS_INIT(&tag, "small bold");
489: print_otag(h, TAG_SPAN, 1, &tag);
490: return(1);
491: }
492:
493:
494: /* ARGSUSED */
495: static int
496: man_SM_pre(MAN_ARGS)
497: {
498: struct htmlpair tag;
499:
500: PAIR_CLASS_INIT(&tag, "small");
501: print_otag(h, TAG_SPAN, 1, &tag);
502: return(1);
503: }
504:
505:
506: /* ARGSUSED */
507: static int
508: man_SS_pre(MAN_ARGS)
509: {
510: struct htmlpair tag[3];
511: struct roffsu su;
512:
513: SCALE_VS_INIT(&su, 1);
514:
515: if (MAN_BODY == n->type) {
516: PAIR_CLASS_INIT(&tag[0], "ssec-body");
517: if (n->parent->next && n->child) {
518: bufcat_su(h, "margin-bottom", &su);
519: PAIR_STYLE_INIT(&tag[1], h);
520: print_otag(h, TAG_DIV, 2, tag);
521: return(1);
522: }
523:
524: print_otag(h, TAG_DIV, 1, tag);
525: return(1);
526: } else if (MAN_BLOCK == n->type) {
527: PAIR_CLASS_INIT(&tag[0], "ssec-block");
528: if (n->prev && MAN_SS == n->prev->tok)
529: if (n->prev->body->child) {
530: bufcat_su(h, "margin-top", &su);
531: PAIR_STYLE_INIT(&tag[1], h);
532: print_otag(h, TAG_DIV, 2, tag);
533: return(1);
534: }
535:
536: print_otag(h, TAG_DIV, 1, tag);
537: return(1);
538: }
539:
540: SCALE_HS_INIT(&su, INDENT - HALFINDENT);
541: bufcat_su(h, "margin-left", &su);
542: PAIR_CLASS_INIT(&tag[0], "ssec-head");
543: PAIR_STYLE_INIT(&tag[1], h);
544: print_otag(h, TAG_DIV, 2, tag);
545: return(1);
546: }
547:
548:
549: /* ARGSUSED */
550: static int
551: man_PP_pre(MAN_ARGS)
552: {
553: struct htmlpair tag;
554: struct roffsu su;
555: int i;
556:
557: if (MAN_BLOCK != n->type)
558: return(1);
559:
560: i = 0;
561:
1.4 schwarze 562: if (MAN_ROOT == n->parent->type) {
1.1 schwarze 563: SCALE_HS_INIT(&su, INDENT);
564: bufcat_su(h, "margin-left", &su);
1.4 schwarze 565: i = 1;
1.1 schwarze 566: }
1.4 schwarze 567: if (n->prev) {
1.1 schwarze 568: SCALE_VS_INIT(&su, 1);
1.4 schwarze 569: bufcat_su(h, "margin-top", &su);
570: i = 1;
1.1 schwarze 571: }
572:
573: PAIR_STYLE_INIT(&tag, h);
1.4 schwarze 574: print_otag(h, TAG_DIV, i, &tag);
1.1 schwarze 575: return(1);
576: }
577:
578:
579: /* ARGSUSED */
580: static int
581: man_IP_pre(MAN_ARGS)
582: {
583: struct roffsu su;
584: struct htmlpair tag;
585: const struct man_node *nn;
586: int width;
587:
588: /*
589: * This scattering of 1-BU margins and pads is to make sure that
590: * when text overruns its box, the subsequent text isn't flush
591: * up against it. However, the rest of the right-hand box must
592: * also be adjusted in consideration of this 1-BU space.
593: */
594:
595: if (MAN_BODY == n->type) {
596: SCALE_HS_INIT(&su, INDENT);
597: bufcat_su(h, "margin-left", &su);
598: PAIR_STYLE_INIT(&tag, h);
599: print_otag(h, TAG_DIV, 1, &tag);
600: return(1);
601: }
602:
603: nn = MAN_BLOCK == n->type ?
604: n->head->child : n->parent->head->child;
605:
606: SCALE_HS_INIT(&su, INDENT);
607: width = 0;
608:
1.7 schwarze 609: /* Width is the last token. */
610:
1.1 schwarze 611: if (MAN_IP == n->tok && NULL != nn)
612: if (NULL != (nn = nn->next)) {
613: for ( ; nn->next; nn = nn->next)
614: /* Do nothing. */ ;
615: width = a2width(nn, &su);
616: }
617:
1.7 schwarze 618: /* Width is the first token. */
619:
620: if (MAN_TP == n->tok && NULL != nn) {
621: /* Skip past non-text children. */
622: while (nn && MAN_TEXT != nn->type)
623: nn = nn->next;
624: if (nn)
625: width = a2width(nn, &su);
626: }
1.1 schwarze 627:
628: if (MAN_BLOCK == n->type) {
629: bufcat_su(h, "margin-left", &su);
630: SCALE_VS_INIT(&su, 1);
631: bufcat_su(h, "margin-top", &su);
632: bufcat_style(h, "clear", "both");
633: PAIR_STYLE_INIT(&tag, h);
634: print_otag(h, TAG_DIV, 1, &tag);
635: return(1);
636: }
637:
638: bufcat_su(h, "min-width", &su);
639: SCALE_INVERT(&su);
640: bufcat_su(h, "margin-left", &su);
641: SCALE_HS_INIT(&su, 1);
642: bufcat_su(h, "margin-right", &su);
643: bufcat_style(h, "clear", "left");
644:
645: if (n->next && n->next->child)
646: bufcat_style(h, "float", "left");
647:
648: PAIR_STYLE_INIT(&tag, h);
649: print_otag(h, TAG_DIV, 1, &tag);
650:
1.7 schwarze 651: /*
652: * Without a length string, we can print all of our children.
653: */
1.1 schwarze 654:
655: if ( ! width)
656: return(1);
1.7 schwarze 657:
658: /*
659: * When a length has been specified, we need to carefully print
660: * our child context: IP gets all children printed but the last
661: * (the width), while TP gets all children printed but the first
662: * (the width).
663: */
1.1 schwarze 664:
665: if (MAN_IP == n->tok)
666: for (nn = n->child; nn->next; nn = nn->next)
1.18 schwarze 667: print_man_node(m, nn, mh, h);
1.1 schwarze 668: if (MAN_TP == n->tok)
669: for (nn = n->child->next; nn; nn = nn->next)
1.18 schwarze 670: print_man_node(m, nn, mh, h);
1.1 schwarze 671:
672: return(0);
673: }
674:
675:
676: /* ARGSUSED */
677: static int
678: man_HP_pre(MAN_ARGS)
679: {
680: const struct man_node *nn;
681: struct htmlpair tag;
682: struct roffsu su;
683:
684: if (MAN_HEAD == n->type)
685: return(0);
686:
687: nn = MAN_BLOCK == n->type ?
688: n->head->child : n->parent->head->child;
689:
690: SCALE_HS_INIT(&su, INDENT);
691:
692: if (NULL != nn)
693: (void)a2width(nn, &su);
694:
695: if (MAN_BLOCK == n->type) {
696: bufcat_su(h, "margin-left", &su);
697: SCALE_VS_INIT(&su, 1);
698: bufcat_su(h, "margin-top", &su);
699: bufcat_style(h, "clear", "both");
700: PAIR_STYLE_INIT(&tag, h);
701: print_otag(h, TAG_DIV, 1, &tag);
702: return(1);
703: }
704:
705: bufcat_su(h, "margin-left", &su);
706: SCALE_INVERT(&su);
707: bufcat_su(h, "text-indent", &su);
708:
709: PAIR_STYLE_INIT(&tag, h);
710: print_otag(h, TAG_DIV, 1, &tag);
711: return(1);
712: }
713:
714:
715: /* ARGSUSED */
716: static int
717: man_B_pre(MAN_ARGS)
718: {
719:
1.4 schwarze 720: print_ofont(h, HTMLFONT_BOLD);
1.1 schwarze 721: return(1);
722: }
723:
724:
725: /* ARGSUSED */
726: static int
727: man_I_pre(MAN_ARGS)
728: {
1.4 schwarze 729:
730: print_ofont(h, HTMLFONT_ITALIC);
1.1 schwarze 731: return(1);
1.20 ! schwarze 732: }
! 733:
! 734:
! 735: /* ARGSUSED */
! 736: static int
! 737: man_ft_pre(MAN_ARGS)
! 738: {
! 739: const char *cp;
! 740:
! 741: if (NULL == n->child) {
! 742: print_ofont(h, h->metal);
! 743: return(0);
! 744: }
! 745:
! 746: cp = n->child->string;
! 747: switch (*cp) {
! 748: case ('4'):
! 749: /* FALLTHROUGH */
! 750: case ('3'):
! 751: /* FALLTHROUGH */
! 752: case ('B'):
! 753: print_ofont(h, HTMLFONT_BOLD);
! 754: break;
! 755: case ('2'):
! 756: /* FALLTHROUGH */
! 757: case ('I'):
! 758: print_ofont(h, HTMLFONT_ITALIC);
! 759: break;
! 760: case ('P'):
! 761: print_ofont(h, h->metal);
! 762: break;
! 763: case ('1'):
! 764: /* FALLTHROUGH */
! 765: case ('C'):
! 766: /* FALLTHROUGH */
! 767: case ('R'):
! 768: print_ofont(h, HTMLFONT_NONE);
! 769: break;
! 770: default:
! 771: break;
! 772: }
! 773: return(0);
1.18 schwarze 774: }
775:
776:
777: /* ARGSUSED */
778: static int
779: man_literal_pre(MAN_ARGS)
780: {
781:
782: switch (n->tok) {
783: case (MAN_nf):
784: /* FALLTHROUGH */
785: case (MAN_Vb):
786: print_otag(h, TAG_BR, 0, NULL);
787: mh->fl |= MANH_LITERAL;
788: return(MAN_Vb != n->tok);
789: default:
790: mh->fl &= ~MANH_LITERAL;
791: break;
792: }
793:
794: return(1);
795: }
796:
797:
798: /* ARGSUSED */
799: static int
800: man_in_pre(MAN_ARGS)
801: {
802:
803: print_otag(h, TAG_BR, 0, NULL);
804: return(0);
1.1 schwarze 805: }
806:
807:
808: /* ARGSUSED */
809: static int
810: man_ign_pre(MAN_ARGS)
811: {
812:
813: return(0);
814: }
815:
816:
817: /* ARGSUSED */
818: static int
819: man_RS_pre(MAN_ARGS)
820: {
821: struct htmlpair tag;
822: struct roffsu su;
823:
824: if (MAN_HEAD == n->type)
825: return(0);
826: else if (MAN_BODY == n->type)
827: return(1);
828:
829: SCALE_HS_INIT(&su, INDENT);
830: bufcat_su(h, "margin-left", &su);
831:
832: if (n->head->child) {
833: SCALE_VS_INIT(&su, 1);
834: a2width(n->head->child, &su);
835: bufcat_su(h, "margin-top", &su);
836: }
837:
838: PAIR_STYLE_INIT(&tag, h);
839: print_otag(h, TAG_DIV, 1, &tag);
840: return(1);
841: }