Annotation of src/usr.bin/mandoc/man_html.c, Revision 1.38
1.38 ! schwarze 1: /* $Id: man_html.c,v 1.37 2011/04/21 22:59:54 schwarze Exp $ */
1.1 schwarze 2: /*
1.29 schwarze 3: * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.1 schwarze 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>
18:
19: #include <assert.h>
20: #include <ctype.h>
21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <string.h>
24:
1.14 schwarze 25: #include "mandoc.h"
1.1 schwarze 26: #include "out.h"
27: #include "html.h"
28: #include "man.h"
29: #include "main.h"
30:
31: /* TODO: preserve ident widths. */
1.2 schwarze 32: /* FIXME: have PD set the default vspace width. */
1.1 schwarze 33:
34: #define INDENT 5
35: #define HALFINDENT 3
36:
37: #define MAN_ARGS const struct man_meta *m, \
38: const struct man_node *n, \
1.18 schwarze 39: struct mhtml *mh, \
1.1 schwarze 40: struct html *h
41:
1.18 schwarze 42: struct mhtml {
43: int fl;
44: #define MANH_LITERAL (1 << 0) /* literal context */
45: };
46:
1.1 schwarze 47: struct htmlman {
48: int (*pre)(MAN_ARGS);
49: int (*post)(MAN_ARGS);
50: };
51:
52: static void print_man(MAN_ARGS);
53: static void print_man_head(MAN_ARGS);
54: static void print_man_nodelist(MAN_ARGS);
55: static void print_man_node(MAN_ARGS);
56:
57: static int a2width(const struct man_node *,
58: struct roffsu *);
59:
60: static int man_alt_pre(MAN_ARGS);
61: static int man_br_pre(MAN_ARGS);
62: static int man_ign_pre(MAN_ARGS);
1.18 schwarze 63: static int man_in_pre(MAN_ARGS);
64: static int man_literal_pre(MAN_ARGS);
1.1 schwarze 65: static void man_root_post(MAN_ARGS);
1.38 ! schwarze 66: static void man_root_pre(MAN_ARGS);
1.1 schwarze 67: static int man_B_pre(MAN_ARGS);
68: static int man_HP_pre(MAN_ARGS);
69: static int man_I_pre(MAN_ARGS);
70: static int man_IP_pre(MAN_ARGS);
71: static int man_PP_pre(MAN_ARGS);
72: static int man_RS_pre(MAN_ARGS);
73: static int man_SH_pre(MAN_ARGS);
74: static int man_SM_pre(MAN_ARGS);
75: static int man_SS_pre(MAN_ARGS);
76:
77: static const struct htmlman mans[MAN_MAX] = {
78: { man_br_pre, NULL }, /* br */
79: { NULL, NULL }, /* TH */
80: { man_SH_pre, NULL }, /* SH */
81: { man_SS_pre, NULL }, /* SS */
82: { man_IP_pre, NULL }, /* TP */
83: { man_PP_pre, NULL }, /* LP */
84: { man_PP_pre, NULL }, /* PP */
85: { man_PP_pre, NULL }, /* P */
86: { man_IP_pre, NULL }, /* IP */
87: { man_HP_pre, NULL }, /* HP */
88: { man_SM_pre, NULL }, /* SM */
1.26 schwarze 89: { man_SM_pre, NULL }, /* SB */
1.1 schwarze 90: { man_alt_pre, NULL }, /* BI */
91: { man_alt_pre, NULL }, /* IB */
92: { man_alt_pre, NULL }, /* BR */
93: { man_alt_pre, NULL }, /* RB */
94: { NULL, NULL }, /* R */
95: { man_B_pre, NULL }, /* B */
96: { man_I_pre, NULL }, /* I */
97: { man_alt_pre, NULL }, /* IR */
98: { man_alt_pre, NULL }, /* RI */
1.34 schwarze 99: { man_ign_pre, NULL }, /* na */
1.1 schwarze 100: { man_br_pre, NULL }, /* sp */
1.18 schwarze 101: { man_literal_pre, NULL }, /* nf */
102: { man_literal_pre, NULL }, /* fi */
1.1 schwarze 103: { NULL, NULL }, /* RE */
104: { man_RS_pre, NULL }, /* RS */
105: { man_ign_pre, NULL }, /* DT */
106: { man_ign_pre, NULL }, /* UC */
1.2 schwarze 107: { man_ign_pre, NULL }, /* PD */
1.13 schwarze 108: { man_ign_pre, NULL }, /* AT */
1.18 schwarze 109: { man_in_pre, NULL }, /* in */
1.23 schwarze 110: { man_ign_pre, NULL }, /* ft */
1.1 schwarze 111: };
112:
113:
114: void
115: html_man(void *arg, const struct man *m)
116: {
117: struct html *h;
118: struct tag *t;
1.18 schwarze 119: struct mhtml mh;
1.1 schwarze 120:
121: h = (struct html *)arg;
122:
1.5 schwarze 123: print_gen_decls(h);
1.1 schwarze 124:
1.18 schwarze 125: memset(&mh, 0, sizeof(struct mhtml));
126:
1.1 schwarze 127: t = print_otag(h, TAG_HTML, 0, NULL);
1.18 schwarze 128: print_man(man_meta(m), man_node(m), &mh, h);
1.1 schwarze 129: print_tagq(h, t);
130:
131: printf("\n");
132: }
133:
134:
135: static void
136: print_man(MAN_ARGS)
137: {
138: struct tag *t;
139:
140: t = print_otag(h, TAG_HEAD, 0, NULL);
1.18 schwarze 141: print_man_head(m, n, mh, h);
1.1 schwarze 142: print_tagq(h, t);
1.25 schwarze 143:
1.1 schwarze 144: t = print_otag(h, TAG_BODY, 0, NULL);
1.18 schwarze 145: print_man_nodelist(m, n, mh, h);
1.1 schwarze 146: print_tagq(h, t);
147: }
148:
149:
150: /* ARGSUSED */
151: static void
152: print_man_head(MAN_ARGS)
153: {
154:
155: print_gen_head(h);
1.38 ! schwarze 156: bufcat_fmt(h, "%s(%s)", m->title, m->msec);
1.1 schwarze 157: print_otag(h, TAG_TITLE, 0, NULL);
158: print_text(h, h->buf);
159: }
160:
161:
162: static void
163: print_man_nodelist(MAN_ARGS)
164: {
165:
1.18 schwarze 166: print_man_node(m, n, mh, h);
1.1 schwarze 167: if (n->next)
1.18 schwarze 168: print_man_nodelist(m, n->next, mh, h);
1.1 schwarze 169: }
170:
171:
172: static void
173: print_man_node(MAN_ARGS)
174: {
175: int child;
176: struct tag *t;
1.37 schwarze 177: struct htmlpair tag;
1.1 schwarze 178:
179: child = 1;
1.2 schwarze 180: t = h->tags.head;
1.1 schwarze 181:
182: switch (n->type) {
183: case (MAN_ROOT):
1.38 ! schwarze 184: man_root_pre(m, n, mh, h);
1.1 schwarze 185: break;
186: case (MAN_TEXT):
1.38 ! schwarze 187: /*
! 188: * If we have a blank line, output a vertical space.
! 189: * If we have a space as the first character, break
! 190: * before printing the line's data.
! 191: */
1.31 schwarze 192: if ('\0' == *n->string) {
193: print_otag(h, TAG_P, 0, NULL);
194: return;
1.32 schwarze 195: } else if (' ' == *n->string && MAN_LINE & n->flags)
1.31 schwarze 196: print_otag(h, TAG_BR, 0, NULL);
197:
1.1 schwarze 198: print_text(h, n->string);
1.31 schwarze 199:
1.38 ! schwarze 200: /*
! 201: * If we're in a literal context, make sure that words
! 202: * togehter on the same line stay together. This is a
! 203: * POST-printing call, so we check the NEXT word. Since
! 204: * -man doesn't have nested macros, we don't need to be
! 205: * more specific than this.
! 206: */
1.32 schwarze 207: if (MANH_LITERAL & mh->fl &&
208: (NULL == n->next ||
209: n->next->line > n->line))
1.18 schwarze 210: print_otag(h, TAG_BR, 0, NULL);
1.36 schwarze 211: return;
212: case (MAN_EQN):
1.37 schwarze 213: PAIR_CLASS_INIT(&tag, "eqn");
214: print_otag(h, TAG_SPAN, 1, &tag);
1.36 schwarze 215: print_text(h, n->eqn->data);
1.37 schwarze 216: break;
1.29 schwarze 217: case (MAN_TBL):
1.33 schwarze 218: /*
219: * This will take care of initialising all of the table
220: * state data for the first table, then tearing it down
221: * for the last one.
222: */
1.29 schwarze 223: print_tbl(h, n->span);
1.32 schwarze 224: return;
1.1 schwarze 225: default:
1.4 schwarze 226: /*
227: * Close out scope of font prior to opening a macro
1.33 schwarze 228: * scope.
1.4 schwarze 229: */
1.27 schwarze 230: if (HTMLFONT_NONE != h->metac) {
231: h->metal = h->metac;
232: h->metac = HTMLFONT_NONE;
1.33 schwarze 233: }
234:
235: /*
236: * Close out the current table, if it's open, and unset
237: * the "meta" table state. This will be reopened on the
238: * next table element.
239: */
240: if (h->tblt) {
241: print_tblclose(h);
242: t = h->tags.head;
1.4 schwarze 243: }
1.1 schwarze 244: if (mans[n->tok].pre)
1.18 schwarze 245: child = (*mans[n->tok].pre)(m, n, mh, h);
1.1 schwarze 246: break;
247: }
248:
249: if (child && n->child)
1.18 schwarze 250: print_man_nodelist(m, n->child, mh, h);
1.1 schwarze 251:
1.4 schwarze 252: /* This will automatically close out any font scope. */
1.1 schwarze 253: print_stagq(h, t);
254:
255: switch (n->type) {
256: case (MAN_ROOT):
1.18 schwarze 257: man_root_post(m, n, mh, h);
1.37 schwarze 258: break;
259: case (MAN_EQN):
1.1 schwarze 260: break;
261: default:
262: if (mans[n->tok].post)
1.18 schwarze 263: (*mans[n->tok].post)(m, n, mh, h);
1.1 schwarze 264: break;
265: }
266: }
267:
268:
269: static int
270: a2width(const struct man_node *n, struct roffsu *su)
271: {
272:
273: if (MAN_TEXT != n->type)
274: return(0);
275: if (a2roffsu(n->string, su, SCALE_BU))
276: return(1);
277:
278: return(0);
279: }
280:
281:
282: /* ARGSUSED */
1.38 ! schwarze 283: static void
1.1 schwarze 284: man_root_pre(MAN_ARGS)
285: {
1.26 schwarze 286: struct htmlpair tag[3];
1.1 schwarze 287: struct tag *t, *tt;
288: char b[BUFSIZ], title[BUFSIZ];
289:
290: b[0] = 0;
291: if (m->vol)
292: (void)strlcat(b, m->vol, BUFSIZ);
293:
1.10 schwarze 294: snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
1.1 schwarze 295:
1.26 schwarze 296: PAIR_SUMMARY_INIT(&tag[0], "Document Header");
297: PAIR_CLASS_INIT(&tag[1], "head");
298: if (NULL == h->style) {
299: PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
300: t = print_otag(h, TAG_TABLE, 3, tag);
301: PAIR_INIT(&tag[0], ATTR_WIDTH, "30%");
302: print_otag(h, TAG_COL, 1, tag);
303: print_otag(h, TAG_COL, 1, tag);
304: print_otag(h, TAG_COL, 1, tag);
305: } else
306: t = print_otag(h, TAG_TABLE, 2, tag);
307:
308: print_otag(h, TAG_TBODY, 0, NULL);
1.3 schwarze 309:
1.1 schwarze 310: tt = print_otag(h, TAG_TR, 0, NULL);
311:
1.25 schwarze 312: PAIR_CLASS_INIT(&tag[0], "head-ltitle");
1.1 schwarze 313: print_otag(h, TAG_TD, 1, tag);
1.25 schwarze 314:
1.1 schwarze 315: print_text(h, title);
316: print_stagq(h, tt);
317:
1.25 schwarze 318: PAIR_CLASS_INIT(&tag[0], "head-vol");
1.26 schwarze 319: if (NULL == h->style) {
320: PAIR_INIT(&tag[1], ATTR_ALIGN, "center");
321: print_otag(h, TAG_TD, 2, tag);
322: } else
323: print_otag(h, TAG_TD, 1, tag);
1.25 schwarze 324:
1.1 schwarze 325: print_text(h, b);
326: print_stagq(h, tt);
327:
1.25 schwarze 328: PAIR_CLASS_INIT(&tag[0], "head-rtitle");
1.26 schwarze 329: if (NULL == h->style) {
330: PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
331: print_otag(h, TAG_TD, 2, tag);
332: } else
333: print_otag(h, TAG_TD, 1, tag);
1.25 schwarze 334:
1.1 schwarze 335: print_text(h, title);
336: print_tagq(h, t);
337: }
338:
339:
340: /* ARGSUSED */
341: static void
342: man_root_post(MAN_ARGS)
343: {
1.26 schwarze 344: struct htmlpair tag[3];
1.1 schwarze 345: struct tag *t, *tt;
346:
1.26 schwarze 347: PAIR_SUMMARY_INIT(&tag[0], "Document Footer");
348: PAIR_CLASS_INIT(&tag[1], "foot");
349: if (NULL == h->style) {
350: PAIR_INIT(&tag[2], ATTR_WIDTH, "100%");
351: t = print_otag(h, TAG_TABLE, 3, tag);
352: PAIR_INIT(&tag[0], ATTR_WIDTH, "50%");
353: print_otag(h, TAG_COL, 1, tag);
354: print_otag(h, TAG_COL, 1, tag);
355: } else
356: t = print_otag(h, TAG_TABLE, 2, tag);
1.3 schwarze 357:
1.1 schwarze 358: tt = print_otag(h, TAG_TR, 0, NULL);
359:
1.25 schwarze 360: PAIR_CLASS_INIT(&tag[0], "foot-date");
1.1 schwarze 361: print_otag(h, TAG_TD, 1, tag);
1.25 schwarze 362:
1.35 schwarze 363: print_text(h, m->date);
1.1 schwarze 364: print_stagq(h, tt);
365:
1.25 schwarze 366: PAIR_CLASS_INIT(&tag[0], "foot-os");
1.26 schwarze 367: if (NULL == h->style) {
368: PAIR_INIT(&tag[1], ATTR_ALIGN, "right");
369: print_otag(h, TAG_TD, 2, tag);
370: } else
371: print_otag(h, TAG_TD, 1, tag);
1.25 schwarze 372:
1.1 schwarze 373: if (m->source)
374: print_text(h, m->source);
375: print_tagq(h, t);
376: }
377:
378:
379:
380: /* ARGSUSED */
381: static int
382: man_br_pre(MAN_ARGS)
383: {
384: struct roffsu su;
385: struct htmlpair tag;
386:
387: SCALE_VS_INIT(&su, 1);
388:
1.21 schwarze 389: if (MAN_sp == n->tok) {
1.8 schwarze 390: if (n->child)
391: a2roffsu(n->child->string, &su, SCALE_VS);
1.21 schwarze 392: } else
1.1 schwarze 393: su.scale = 0;
394:
1.38 ! schwarze 395: bufinit(h);
1.1 schwarze 396: bufcat_su(h, "height", &su);
397: PAIR_STYLE_INIT(&tag, h);
398: print_otag(h, TAG_DIV, 1, &tag);
1.4 schwarze 399:
1.3 schwarze 400: /* So the div isn't empty: */
401: print_text(h, "\\~");
402:
1.1 schwarze 403: return(0);
404: }
405:
406:
407: /* ARGSUSED */
408: static int
409: man_SH_pre(MAN_ARGS)
410: {
1.25 schwarze 411: struct htmlpair tag;
1.1 schwarze 412:
1.25 schwarze 413: if (MAN_BLOCK == n->type) {
414: PAIR_CLASS_INIT(&tag, "section");
415: print_otag(h, TAG_DIV, 1, &tag);
1.1 schwarze 416: return(1);
1.25 schwarze 417: } else if (MAN_BODY == n->type)
1.1 schwarze 418: return(1);
419:
1.25 schwarze 420: print_otag(h, TAG_H1, 0, NULL);
1.1 schwarze 421: return(1);
422: }
423:
424:
425: /* ARGSUSED */
426: static int
427: man_alt_pre(MAN_ARGS)
428: {
429: const struct man_node *nn;
1.27 schwarze 430: int i;
431: enum htmltag fp;
432: struct tag *t;
1.1 schwarze 433:
434: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
1.27 schwarze 435: t = NULL;
1.1 schwarze 436: switch (n->tok) {
437: case (MAN_BI):
1.27 schwarze 438: fp = i % 2 ? TAG_I : TAG_B;
1.1 schwarze 439: break;
440: case (MAN_IB):
1.27 schwarze 441: fp = i % 2 ? TAG_B : TAG_I;
1.1 schwarze 442: break;
443: case (MAN_RI):
1.27 schwarze 444: fp = i % 2 ? TAG_I : TAG_MAX;
1.1 schwarze 445: break;
446: case (MAN_IR):
1.27 schwarze 447: fp = i % 2 ? TAG_MAX : TAG_I;
1.1 schwarze 448: break;
449: case (MAN_BR):
1.27 schwarze 450: fp = i % 2 ? TAG_MAX : TAG_B;
1.1 schwarze 451: break;
452: case (MAN_RB):
1.27 schwarze 453: fp = i % 2 ? TAG_B : TAG_MAX;
1.1 schwarze 454: break;
455: default:
456: abort();
457: /* NOTREACHED */
458: }
459:
460: if (i)
461: h->flags |= HTML_NOSPACE;
462:
1.27 schwarze 463: if (TAG_MAX != fp)
464: t = print_otag(h, fp, 0, NULL);
465:
1.18 schwarze 466: print_man_node(m, nn, mh, h);
1.27 schwarze 467:
468: if (t)
469: print_tagq(h, t);
1.1 schwarze 470: }
471:
472: return(0);
473: }
474:
475:
476: /* ARGSUSED */
477: static int
1.26 schwarze 478: man_SM_pre(MAN_ARGS)
1.1 schwarze 479: {
480:
1.27 schwarze 481: print_otag(h, TAG_SMALL, 0, NULL);
1.26 schwarze 482: if (MAN_SB == n->tok)
1.27 schwarze 483: print_otag(h, TAG_B, 0, NULL);
1.1 schwarze 484: return(1);
485: }
486:
487:
488: /* ARGSUSED */
489: static int
490: man_SS_pre(MAN_ARGS)
491: {
1.25 schwarze 492: struct htmlpair tag;
1.1 schwarze 493:
1.25 schwarze 494: if (MAN_BLOCK == n->type) {
495: PAIR_CLASS_INIT(&tag, "subsection");
496: print_otag(h, TAG_DIV, 1, &tag);
1.1 schwarze 497: return(1);
1.25 schwarze 498: } else if (MAN_BODY == n->type)
1.1 schwarze 499: return(1);
500:
1.25 schwarze 501: print_otag(h, TAG_H2, 0, NULL);
1.1 schwarze 502: return(1);
503: }
504:
505:
506: /* ARGSUSED */
507: static int
508: man_PP_pre(MAN_ARGS)
509: {
510:
1.22 schwarze 511: if (MAN_HEAD == n->type)
512: return(0);
1.26 schwarze 513: else if (MAN_BODY == n->type && n->prev)
514: print_otag(h, TAG_P, 0, NULL);
1.22 schwarze 515:
1.1 schwarze 516: return(1);
517: }
518:
519:
520: /* ARGSUSED */
521: static int
522: man_IP_pre(MAN_ARGS)
523: {
524: struct roffsu su;
525: struct htmlpair tag;
526: const struct man_node *nn;
527:
528: /*
529: * This scattering of 1-BU margins and pads is to make sure that
530: * when text overruns its box, the subsequent text isn't flush
531: * up against it. However, the rest of the right-hand box must
532: * also be adjusted in consideration of this 1-BU space.
533: */
534:
535: if (MAN_BODY == n->type) {
1.26 schwarze 536: print_otag(h, TAG_TD, 0, NULL);
1.1 schwarze 537: return(1);
538: }
539:
540: nn = MAN_BLOCK == n->type ?
541: n->head->child : n->parent->head->child;
542:
543: SCALE_HS_INIT(&su, INDENT);
544:
1.28 schwarze 545: /* Width is the second token. */
1.7 schwarze 546:
1.1 schwarze 547: if (MAN_IP == n->tok && NULL != nn)
1.28 schwarze 548: if (NULL != (nn = nn->next))
1.30 schwarze 549: a2width(nn, &su);
1.1 schwarze 550:
1.7 schwarze 551: /* Width is the first token. */
552:
553: if (MAN_TP == n->tok && NULL != nn) {
554: /* Skip past non-text children. */
555: while (nn && MAN_TEXT != nn->type)
556: nn = nn->next;
557: if (nn)
1.30 schwarze 558: a2width(nn, &su);
1.7 schwarze 559: }
1.1 schwarze 560:
561: if (MAN_BLOCK == n->type) {
1.26 schwarze 562: print_otag(h, TAG_P, 0, NULL);
563: print_otag(h, TAG_TABLE, 0, NULL);
1.38 ! schwarze 564: bufinit(h);
1.26 schwarze 565: bufcat_su(h, "width", &su);
1.1 schwarze 566: PAIR_STYLE_INIT(&tag, h);
1.26 schwarze 567: print_otag(h, TAG_COL, 1, &tag);
568: print_otag(h, TAG_COL, 0, NULL);
569: print_otag(h, TAG_TBODY, 0, NULL);
570: print_otag(h, TAG_TR, 0, NULL);
1.1 schwarze 571: return(1);
572: }
573:
1.26 schwarze 574: print_otag(h, TAG_TD, 0, NULL);
1.1 schwarze 575:
1.28 schwarze 576: /* For IP, only print the first header element. */
1.1 schwarze 577:
1.28 schwarze 578: if (MAN_IP == n->tok && n->child)
579: print_man_node(m, n->child, mh, h);
1.7 schwarze 580:
1.28 schwarze 581: /* For TP, only print next-line header elements. */
1.1 schwarze 582:
583: if (MAN_TP == n->tok)
1.28 schwarze 584: for (nn = n->child; nn; nn = nn->next)
585: if (nn->line > n->line)
586: print_man_node(m, nn, mh, h);
1.1 schwarze 587:
588: return(0);
589: }
590:
591:
592: /* ARGSUSED */
593: static int
594: man_HP_pre(MAN_ARGS)
595: {
1.26 schwarze 596: struct htmlpair tag;
597: struct roffsu su;
598: const struct man_node *np;
1.1 schwarze 599:
1.38 ! schwarze 600: bufinit(h);
! 601:
1.26 schwarze 602: np = MAN_BLOCK == n->type ?
603: n->head->child :
604: n->parent->head->child;
1.1 schwarze 605:
1.26 schwarze 606: if (NULL == np || ! a2width(np, &su))
607: SCALE_HS_INIT(&su, INDENT);
1.1 schwarze 608:
1.26 schwarze 609: if (MAN_HEAD == n->type) {
610: print_otag(h, TAG_TD, 0, NULL);
611: return(0);
612: } else if (MAN_BLOCK == n->type) {
613: print_otag(h, TAG_P, 0, NULL);
614: print_otag(h, TAG_TABLE, 0, NULL);
615: bufcat_su(h, "width", &su);
1.1 schwarze 616: PAIR_STYLE_INIT(&tag, h);
1.26 schwarze 617: print_otag(h, TAG_COL, 1, &tag);
618: print_otag(h, TAG_COL, 0, NULL);
619: print_otag(h, TAG_TBODY, 0, NULL);
620: print_otag(h, TAG_TR, 0, NULL);
1.1 schwarze 621: return(1);
622: }
623:
1.26 schwarze 624: su.scale = -su.scale;
1.1 schwarze 625: bufcat_su(h, "text-indent", &su);
626: PAIR_STYLE_INIT(&tag, h);
1.26 schwarze 627: print_otag(h, TAG_TD, 1, &tag);
1.1 schwarze 628: return(1);
629: }
630:
631:
632: /* ARGSUSED */
633: static int
634: man_B_pre(MAN_ARGS)
635: {
636:
1.27 schwarze 637: print_otag(h, TAG_B, 0, NULL);
1.1 schwarze 638: return(1);
639: }
640:
641:
642: /* ARGSUSED */
643: static int
644: man_I_pre(MAN_ARGS)
645: {
1.4 schwarze 646:
1.27 schwarze 647: print_otag(h, TAG_I, 0, NULL);
1.1 schwarze 648: return(1);
1.18 schwarze 649: }
650:
651:
652: /* ARGSUSED */
653: static int
654: man_literal_pre(MAN_ARGS)
655: {
656:
1.21 schwarze 657: if (MAN_nf == n->tok) {
1.18 schwarze 658: print_otag(h, TAG_BR, 0, NULL);
659: mh->fl |= MANH_LITERAL;
1.21 schwarze 660: } else
1.18 schwarze 661: mh->fl &= ~MANH_LITERAL;
662:
1.34 schwarze 663: return(0);
1.18 schwarze 664: }
665:
666:
667: /* ARGSUSED */
668: static int
669: man_in_pre(MAN_ARGS)
670: {
671:
672: print_otag(h, TAG_BR, 0, NULL);
673: return(0);
1.1 schwarze 674: }
675:
676:
677: /* ARGSUSED */
678: static int
679: man_ign_pre(MAN_ARGS)
680: {
681:
682: return(0);
683: }
684:
685:
686: /* ARGSUSED */
687: static int
688: man_RS_pre(MAN_ARGS)
689: {
690: struct htmlpair tag;
691: struct roffsu su;
692:
693: if (MAN_HEAD == n->type)
694: return(0);
695: else if (MAN_BODY == n->type)
696: return(1);
697:
698: SCALE_HS_INIT(&su, INDENT);
1.26 schwarze 699: if (n->head->child)
1.1 schwarze 700: a2width(n->head->child, &su);
701:
1.38 ! schwarze 702: bufinit(h);
1.26 schwarze 703: bufcat_su(h, "margin-left", &su);
1.1 schwarze 704: PAIR_STYLE_INIT(&tag, h);
705: print_otag(h, TAG_DIV, 1, &tag);
706: return(1);
707: }