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