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