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