Annotation of mandoc/man_html.c, Revision 1.50
1.50 ! kristaps 1: /* $Id: man_html.c,v 1.49 2010/12/06 14:12:48 kristaps Exp $ */
1.1 kristaps 2: /*
1.42 schwarze 3: * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
1.1 kristaps 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.35 kristaps 29: #include "mandoc.h"
1.7 kristaps 30: #include "out.h"
1.1 kristaps 31: #include "html.h"
32: #include "man.h"
1.10 kristaps 33: #include "main.h"
1.1 kristaps 34:
1.6 kristaps 35: /* TODO: preserve ident widths. */
1.13 kristaps 36: /* FIXME: have PD set the default vspace width. */
1.6 kristaps 37:
38: #define INDENT 5
1.4 kristaps 39: #define HALFINDENT 3
40:
1.3 kristaps 41: #define MAN_ARGS const struct man_meta *m, \
42: const struct man_node *n, \
1.45 kristaps 43: struct mhtml *mh, \
1.3 kristaps 44: struct html *h
45:
1.45 kristaps 46: struct mhtml {
47: int fl;
48: #define MANH_LITERAL (1 << 0) /* literal context */
49: };
50:
1.3 kristaps 51: struct htmlman {
52: int (*pre)(MAN_ARGS);
53: int (*post)(MAN_ARGS);
54: };
55:
56: static void print_man(MAN_ARGS);
57: static void print_man_head(MAN_ARGS);
1.4 kristaps 58: static void print_man_nodelist(MAN_ARGS);
59: static void print_man_node(MAN_ARGS);
1.3 kristaps 60:
1.7 kristaps 61: static int a2width(const struct man_node *,
62: struct roffsu *);
1.5 kristaps 63:
1.8 kristaps 64: static int man_alt_pre(MAN_ARGS);
1.4 kristaps 65: static int man_br_pre(MAN_ARGS);
1.8 kristaps 66: static int man_ign_pre(MAN_ARGS);
1.45 kristaps 67: static int man_in_pre(MAN_ARGS);
68: static int man_literal_pre(MAN_ARGS);
1.8 kristaps 69: static void man_root_post(MAN_ARGS);
70: static int man_root_pre(MAN_ARGS);
71: static int man_B_pre(MAN_ARGS);
1.6 kristaps 72: static int man_HP_pre(MAN_ARGS);
1.8 kristaps 73: static int man_I_pre(MAN_ARGS);
1.5 kristaps 74: static int man_IP_pre(MAN_ARGS);
1.4 kristaps 75: static int man_PP_pre(MAN_ARGS);
1.9 kristaps 76: static int man_RS_pre(MAN_ARGS);
1.8 kristaps 77: static int man_SB_pre(MAN_ARGS);
1.4 kristaps 78: static int man_SH_pre(MAN_ARGS);
1.8 kristaps 79: static int man_SM_pre(MAN_ARGS);
1.4 kristaps 80: static int man_SS_pre(MAN_ARGS);
81:
1.3 kristaps 82: static const struct htmlman mans[MAN_MAX] = {
1.4 kristaps 83: { man_br_pre, NULL }, /* br */
1.3 kristaps 84: { NULL, NULL }, /* TH */
1.4 kristaps 85: { man_SH_pre, NULL }, /* SH */
86: { man_SS_pre, NULL }, /* SS */
1.6 kristaps 87: { man_IP_pre, NULL }, /* TP */
1.4 kristaps 88: { man_PP_pre, NULL }, /* LP */
89: { man_PP_pre, NULL }, /* PP */
90: { man_PP_pre, NULL }, /* P */
1.5 kristaps 91: { man_IP_pre, NULL }, /* IP */
1.6 kristaps 92: { man_HP_pre, NULL }, /* HP */
1.8 kristaps 93: { man_SM_pre, NULL }, /* SM */
94: { man_SB_pre, NULL }, /* SB */
95: { man_alt_pre, NULL }, /* BI */
96: { man_alt_pre, NULL }, /* IB */
97: { man_alt_pre, NULL }, /* BR */
98: { man_alt_pre, NULL }, /* RB */
1.3 kristaps 99: { NULL, NULL }, /* R */
1.8 kristaps 100: { man_B_pre, NULL }, /* B */
101: { man_I_pre, NULL }, /* I */
102: { man_alt_pre, NULL }, /* IR */
103: { man_alt_pre, NULL }, /* RI */
1.3 kristaps 104: { NULL, NULL }, /* na */
105: { NULL, NULL }, /* i */
1.4 kristaps 106: { man_br_pre, NULL }, /* sp */
1.45 kristaps 107: { man_literal_pre, NULL }, /* nf */
108: { man_literal_pre, NULL }, /* fi */
1.3 kristaps 109: { NULL, NULL }, /* r */
110: { NULL, NULL }, /* RE */
1.9 kristaps 111: { man_RS_pre, NULL }, /* RS */
1.8 kristaps 112: { man_ign_pre, NULL }, /* DT */
113: { man_ign_pre, NULL }, /* UC */
1.13 kristaps 114: { man_ign_pre, NULL }, /* PD */
1.34 joerg 115: { man_ign_pre, NULL }, /* AT */
1.45 kristaps 116: { man_in_pre, NULL }, /* in */
1.50 ! kristaps 117: { man_in_pre, NULL }, /* ft */
1.3 kristaps 118: };
119:
1.1 kristaps 120:
121: void
122: html_man(void *arg, const struct man *m)
123: {
1.3 kristaps 124: struct html *h;
125: struct tag *t;
1.45 kristaps 126: struct mhtml mh;
1.3 kristaps 127:
128: h = (struct html *)arg;
129:
1.26 kristaps 130: print_gen_decls(h);
1.3 kristaps 131:
1.45 kristaps 132: memset(&mh, 0, sizeof(struct mhtml));
133:
1.3 kristaps 134: t = print_otag(h, TAG_HTML, 0, NULL);
1.45 kristaps 135: print_man(man_meta(m), man_node(m), &mh, h);
1.3 kristaps 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.45 kristaps 150: print_man_head(m, n, mh, h);
1.3 kristaps 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.45 kristaps 158: print_man_nodelist(m, n, mh, h);
1.3 kristaps 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.31 kristaps 171: buffmt(h, "%s(%s)", m->title, m->msec);
1.3 kristaps 172:
173: print_otag(h, TAG_TITLE, 0, NULL);
174: print_text(h, h->buf);
1.1 kristaps 175: }
1.4 kristaps 176:
177:
178: static void
179: print_man_nodelist(MAN_ARGS)
180: {
181:
1.45 kristaps 182: print_man_node(m, n, mh, h);
1.4 kristaps 183: if (n->next)
1.45 kristaps 184: print_man_nodelist(m, n->next, mh, h);
1.4 kristaps 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.14 kristaps 195: t = h->tags.head;
1.4 kristaps 196:
197: bufinit(h);
198:
1.28 kristaps 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.4 kristaps 205: switch (n->type) {
206: case (MAN_ROOT):
1.45 kristaps 207: child = man_root_pre(m, n, mh, h);
1.4 kristaps 208: break;
209: case (MAN_TEXT):
210: print_text(h, n->string);
1.45 kristaps 211:
212: if (MANH_LITERAL & mh->fl)
213: print_otag(h, TAG_BR, 0, NULL);
214:
1.19 kristaps 215: return;
1.4 kristaps 216: default:
1.21 kristaps 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: */
1.20 kristaps 222: if (h->metaf) {
223: assert(h->metaf == t);
224: print_tagq(h, h->metaf);
1.21 kristaps 225: assert(NULL == h->metaf);
1.20 kristaps 226: t = h->tags.head;
227: }
1.4 kristaps 228: if (mans[n->tok].pre)
1.45 kristaps 229: child = (*mans[n->tok].pre)(m, n, mh, h);
1.4 kristaps 230: break;
231: }
232:
1.21 kristaps 233: if (child && n->child)
1.45 kristaps 234: print_man_nodelist(m, n->child, mh, h);
1.21 kristaps 235:
1.24 kristaps 236: /* This will automatically close out any font scope. */
1.4 kristaps 237: print_stagq(h, t);
238:
239: bufinit(h);
240:
241: switch (n->type) {
242: case (MAN_ROOT):
1.45 kristaps 243: man_root_post(m, n, mh, h);
1.4 kristaps 244: break;
245: case (MAN_TEXT):
246: break;
247: default:
248: if (mans[n->tok].post)
1.45 kristaps 249: (*mans[n->tok].post)(m, n, mh, h);
1.4 kristaps 250: break;
251: }
252: }
253:
254:
1.5 kristaps 255: static int
1.7 kristaps 256: a2width(const struct man_node *n, struct roffsu *su)
1.5 kristaps 257: {
258:
1.6 kristaps 259: if (MAN_TEXT != n->type)
1.7 kristaps 260: return(0);
1.11 kristaps 261: if (a2roffsu(n->string, su, SCALE_BU))
1.7 kristaps 262: return(1);
1.5 kristaps 263:
1.7 kristaps 264: return(0);
1.5 kristaps 265: }
266:
267:
1.40 kristaps 268: /* ARGSUSED */
1.4 kristaps 269: static int
270: man_root_pre(MAN_ARGS)
271: {
1.15 kristaps 272: struct htmlpair tag[3];
1.4 kristaps 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.31 kristaps 280: snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
1.4 kristaps 281:
1.7 kristaps 282: PAIR_CLASS_INIT(&tag[0], "header");
283: bufcat_style(h, "width", "100%");
284: PAIR_STYLE_INIT(&tag[1], h);
1.15 kristaps 285: PAIR_SUMMARY_INIT(&tag[2], "header");
286:
287: t = print_otag(h, TAG_TABLE, 3, tag);
1.4 kristaps 288: tt = print_otag(h, TAG_TR, 0, NULL);
289:
1.7 kristaps 290: bufinit(h);
291: bufcat_style(h, "width", "10%");
292: PAIR_STYLE_INIT(&tag[0], h);
1.4 kristaps 293: print_otag(h, TAG_TD, 1, tag);
294: print_text(h, title);
295: print_stagq(h, tt);
296:
1.7 kristaps 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);
1.4 kristaps 302: print_otag(h, TAG_TD, 1, tag);
303: print_text(h, b);
304: print_stagq(h, tt);
305:
1.7 kristaps 306: bufinit(h);
307: bufcat_style(h, "width", "10%");
308: bufcat_style(h, "text-align", "right");
309: PAIR_STYLE_INIT(&tag[0], h);
1.4 kristaps 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.15 kristaps 321: struct htmlpair tag[3];
1.4 kristaps 322: struct tag *t, *tt;
1.12 kristaps 323: char b[DATESIZ];
1.4 kristaps 324:
1.36 kristaps 325: if (m->rawdate)
326: strlcpy(b, m->rawdate, DATESIZ);
327: else
328: time2a(m->date, b, DATESIZ);
1.4 kristaps 329:
1.7 kristaps 330: PAIR_CLASS_INIT(&tag[0], "footer");
331: bufcat_style(h, "width", "100%");
332: PAIR_STYLE_INIT(&tag[1], h);
1.15 kristaps 333: PAIR_SUMMARY_INIT(&tag[2], "footer");
334:
335: t = print_otag(h, TAG_TABLE, 3, tag);
1.4 kristaps 336: tt = print_otag(h, TAG_TR, 0, NULL);
337:
1.7 kristaps 338: bufinit(h);
339: bufcat_style(h, "width", "50%");
340: PAIR_STYLE_INIT(&tag[0], h);
1.4 kristaps 341: print_otag(h, TAG_TD, 1, tag);
342: print_text(h, b);
343: print_stagq(h, tt);
344:
1.7 kristaps 345: bufinit(h);
346: bufcat_style(h, "width", "50%");
347: bufcat_style(h, "text-align", "right");
348: PAIR_STYLE_INIT(&tag[0], h);
1.4 kristaps 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: {
1.7 kristaps 361: struct roffsu su;
362: struct htmlpair tag;
1.4 kristaps 363:
1.7 kristaps 364: SCALE_VS_INIT(&su, 1);
365:
1.49 kristaps 366: if (MAN_sp == n->tok) {
1.29 kristaps 367: if (n->child)
368: a2roffsu(n->child->string, &su, SCALE_VS);
1.49 kristaps 369: } else
1.7 kristaps 370: su.scale = 0;
1.4 kristaps 371:
1.7 kristaps 372: bufcat_su(h, "height", &su);
373: PAIR_STYLE_INIT(&tag, h);
1.4 kristaps 374: print_otag(h, TAG_DIV, 1, &tag);
1.24 kristaps 375:
1.16 kristaps 376: /* So the div isn't empty: */
377: print_text(h, "\\~");
378:
1.7 kristaps 379: return(0);
1.4 kristaps 380: }
381:
382:
383: /* ARGSUSED */
384: static int
385: man_SH_pre(MAN_ARGS)
386: {
1.7 kristaps 387: struct htmlpair tag[2];
388: struct roffsu su;
1.4 kristaps 389:
390: if (MAN_BODY == n->type) {
1.7 kristaps 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);
1.4 kristaps 395: print_otag(h, TAG_DIV, 2, tag);
396: return(1);
397: } else if (MAN_BLOCK == n->type) {
1.7 kristaps 398: PAIR_CLASS_INIT(&tag[0], "sec-block");
1.4 kristaps 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:
1.7 kristaps 405: SCALE_VS_INIT(&su, 1);
406: bufcat_su(h, "margin-top", &su);
1.4 kristaps 407: if (NULL == n->next)
1.7 kristaps 408: bufcat_su(h, "margin-bottom", &su);
409: PAIR_STYLE_INIT(&tag[1], h);
1.4 kristaps 410: print_otag(h, TAG_DIV, 2, tag);
411: return(1);
412: }
413:
1.7 kristaps 414: PAIR_CLASS_INIT(&tag[0], "sec-head");
1.4 kristaps 415: print_otag(h, TAG_DIV, 1, tag);
416: return(1);
417: }
418:
419:
420: /* ARGSUSED */
421: static int
1.8 kristaps 422: man_alt_pre(MAN_ARGS)
423: {
424: const struct man_node *nn;
425: struct tag *t;
426: int i;
1.23 kristaps 427: enum htmlfont fp;
1.8 kristaps 428:
429: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
430: switch (n->tok) {
431: case (MAN_BI):
1.23 kristaps 432: fp = i % 2 ? HTMLFONT_ITALIC : HTMLFONT_BOLD;
1.8 kristaps 433: break;
434: case (MAN_IB):
1.23 kristaps 435: fp = i % 2 ? HTMLFONT_BOLD : HTMLFONT_ITALIC;
1.8 kristaps 436: break;
437: case (MAN_RI):
1.23 kristaps 438: fp = i % 2 ? HTMLFONT_ITALIC : HTMLFONT_NONE;
1.8 kristaps 439: break;
440: case (MAN_IR):
1.23 kristaps 441: fp = i % 2 ? HTMLFONT_NONE : HTMLFONT_ITALIC;
1.8 kristaps 442: break;
443: case (MAN_BR):
1.23 kristaps 444: fp = i % 2 ? HTMLFONT_NONE : HTMLFONT_BOLD;
1.8 kristaps 445: break;
446: case (MAN_RB):
1.23 kristaps 447: fp = i % 2 ? HTMLFONT_BOLD : HTMLFONT_NONE;
1.8 kristaps 448: break;
449: default:
450: abort();
451: /* NOTREACHED */
452: }
453:
454: if (i)
455: h->flags |= HTML_NOSPACE;
456:
1.24 kristaps 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: */
1.23 kristaps 462: t = print_ofont(h, fp);
1.45 kristaps 463: print_man_node(m, nn, mh, h);
1.21 kristaps 464: print_tagq(h, t);
1.8 kristaps 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.23 kristaps 477: /* FIXME: print_ofont(). */
1.8 kristaps 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
1.4 kristaps 498: man_SS_pre(MAN_ARGS)
499: {
500: struct htmlpair tag[3];
1.7 kristaps 501: struct roffsu su;
1.4 kristaps 502:
1.7 kristaps 503: SCALE_VS_INIT(&su, 1);
1.4 kristaps 504:
505: if (MAN_BODY == n->type) {
1.7 kristaps 506: PAIR_CLASS_INIT(&tag[0], "ssec-body");
1.4 kristaps 507: if (n->parent->next && n->child) {
1.7 kristaps 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);
1.4 kristaps 512: }
513:
1.7 kristaps 514: print_otag(h, TAG_DIV, 1, tag);
1.4 kristaps 515: return(1);
516: } else if (MAN_BLOCK == n->type) {
1.7 kristaps 517: PAIR_CLASS_INIT(&tag[0], "ssec-block");
1.4 kristaps 518: if (n->prev && MAN_SS == n->prev->tok)
519: if (n->prev->body->child) {
1.7 kristaps 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);
1.4 kristaps 524: }
525:
1.7 kristaps 526: print_otag(h, TAG_DIV, 1, tag);
1.4 kristaps 527: return(1);
528: }
529:
1.7 kristaps 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);
1.4 kristaps 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: {
1.5 kristaps 543: struct htmlpair tag;
1.7 kristaps 544: struct roffsu su;
1.5 kristaps 545: int i;
1.4 kristaps 546:
1.47 kristaps 547: if (MAN_BODY == n->type)
1.4 kristaps 548: return(1);
1.47 kristaps 549: if (MAN_HEAD == n->type)
550: return(0);
1.4 kristaps 551:
1.5 kristaps 552: i = 0;
553:
1.22 kristaps 554: if (MAN_ROOT == n->parent->type) {
1.7 kristaps 555: SCALE_HS_INIT(&su, INDENT);
556: bufcat_su(h, "margin-left", &su);
1.22 kristaps 557: i = 1;
1.5 kristaps 558: }
1.22 kristaps 559: if (n->prev) {
1.7 kristaps 560: SCALE_VS_INIT(&su, 1);
1.22 kristaps 561: bufcat_su(h, "margin-top", &su);
562: i = 1;
1.5 kristaps 563: }
1.4 kristaps 564:
1.7 kristaps 565: PAIR_STYLE_INIT(&tag, h);
1.22 kristaps 566: print_otag(h, TAG_DIV, i, &tag);
1.47 kristaps 567:
1.5 kristaps 568: return(1);
569: }
570:
571:
572: /* ARGSUSED */
573: static int
574: man_IP_pre(MAN_ARGS)
575: {
1.7 kristaps 576: struct roffsu su;
1.5 kristaps 577: struct htmlpair tag;
578: const struct man_node *nn;
1.7 kristaps 579: int width;
1.5 kristaps 580:
1.7 kristaps 581: /*
582: * This scattering of 1-BU margins and pads is to make sure that
583: * when text overruns its box, the subsequent text isn't flush
584: * up against it. However, the rest of the right-hand box must
585: * also be adjusted in consideration of this 1-BU space.
586: */
587:
588: if (MAN_BODY == n->type) {
589: SCALE_HS_INIT(&su, INDENT);
590: bufcat_su(h, "margin-left", &su);
591: PAIR_STYLE_INIT(&tag, h);
592: print_otag(h, TAG_DIV, 1, &tag);
1.6 kristaps 593: return(1);
594: }
595:
596: nn = MAN_BLOCK == n->type ?
597: n->head->child : n->parent->head->child;
598:
1.7 kristaps 599: SCALE_HS_INIT(&su, INDENT);
600: width = 0;
1.6 kristaps 601:
1.28 kristaps 602: /* Width is the last token. */
603:
1.7 kristaps 604: if (MAN_IP == n->tok && NULL != nn)
1.5 kristaps 605: if (NULL != (nn = nn->next)) {
606: for ( ; nn->next; nn = nn->next)
607: /* Do nothing. */ ;
1.7 kristaps 608: width = a2width(nn, &su);
1.5 kristaps 609: }
610:
1.28 kristaps 611: /* Width is the first token. */
612:
1.27 kristaps 613: if (MAN_TP == n->tok && NULL != nn) {
1.28 kristaps 614: /* Skip past non-text children. */
1.27 kristaps 615: while (nn && MAN_TEXT != nn->type)
616: nn = nn->next;
1.28 kristaps 617: if (nn)
618: width = a2width(nn, &su);
1.27 kristaps 619: }
1.7 kristaps 620:
1.5 kristaps 621: if (MAN_BLOCK == n->type) {
1.7 kristaps 622: bufcat_su(h, "margin-left", &su);
1.9 kristaps 623: SCALE_VS_INIT(&su, 1);
624: bufcat_su(h, "margin-top", &su);
1.7 kristaps 625: bufcat_style(h, "clear", "both");
626: PAIR_STYLE_INIT(&tag, h);
1.5 kristaps 627: print_otag(h, TAG_DIV, 1, &tag);
628: return(1);
1.6 kristaps 629: }
630:
1.7 kristaps 631: bufcat_su(h, "min-width", &su);
632: SCALE_INVERT(&su);
633: bufcat_su(h, "margin-left", &su);
634: SCALE_HS_INIT(&su, 1);
635: bufcat_su(h, "margin-right", &su);
636: bufcat_style(h, "clear", "left");
1.6 kristaps 637:
638: if (n->next && n->next->child)
1.7 kristaps 639: bufcat_style(h, "float", "left");
1.6 kristaps 640:
1.7 kristaps 641: PAIR_STYLE_INIT(&tag, h);
1.6 kristaps 642: print_otag(h, TAG_DIV, 1, &tag);
643:
1.28 kristaps 644: /*
645: * Without a length string, we can print all of our children.
646: */
1.7 kristaps 647:
648: if ( ! width)
1.6 kristaps 649: return(1);
1.27 kristaps 650:
1.28 kristaps 651: /*
652: * When a length has been specified, we need to carefully print
653: * our child context: IP gets all children printed but the last
654: * (the width), while TP gets all children printed but the first
655: * (the width).
656: */
1.6 kristaps 657:
1.7 kristaps 658: if (MAN_IP == n->tok)
659: for (nn = n->child; nn->next; nn = nn->next)
1.45 kristaps 660: print_man_node(m, nn, mh, h);
1.7 kristaps 661: if (MAN_TP == n->tok)
662: for (nn = n->child->next; nn; nn = nn->next)
1.45 kristaps 663: print_man_node(m, nn, mh, h);
1.6 kristaps 664:
665: return(0);
666: }
667:
668:
669: /* ARGSUSED */
670: static int
671: man_HP_pre(MAN_ARGS)
672: {
673: const struct man_node *nn;
674: struct htmlpair tag;
1.7 kristaps 675: struct roffsu su;
1.6 kristaps 676:
677: if (MAN_HEAD == n->type)
678: return(0);
679:
680: nn = MAN_BLOCK == n->type ?
681: n->head->child : n->parent->head->child;
682:
1.7 kristaps 683: SCALE_HS_INIT(&su, INDENT);
1.6 kristaps 684:
685: if (NULL != nn)
1.7 kristaps 686: (void)a2width(nn, &su);
1.6 kristaps 687:
688: if (MAN_BLOCK == n->type) {
1.7 kristaps 689: bufcat_su(h, "margin-left", &su);
1.9 kristaps 690: SCALE_VS_INIT(&su, 1);
691: bufcat_su(h, "margin-top", &su);
1.7 kristaps 692: bufcat_style(h, "clear", "both");
693: PAIR_STYLE_INIT(&tag, h);
1.5 kristaps 694: print_otag(h, TAG_DIV, 1, &tag);
1.6 kristaps 695: return(1);
696: }
1.5 kristaps 697:
1.7 kristaps 698: bufcat_su(h, "margin-left", &su);
699: SCALE_INVERT(&su);
700: bufcat_su(h, "text-indent", &su);
1.5 kristaps 701:
1.7 kristaps 702: PAIR_STYLE_INIT(&tag, h);
1.6 kristaps 703: print_otag(h, TAG_DIV, 1, &tag);
1.4 kristaps 704: return(1);
705: }
1.6 kristaps 706:
1.8 kristaps 707:
708: /* ARGSUSED */
709: static int
710: man_B_pre(MAN_ARGS)
711: {
712:
1.23 kristaps 713: print_ofont(h, HTMLFONT_BOLD);
1.8 kristaps 714: return(1);
715: }
716:
717:
718: /* ARGSUSED */
719: static int
720: man_I_pre(MAN_ARGS)
721: {
1.23 kristaps 722:
723: print_ofont(h, HTMLFONT_ITALIC);
1.8 kristaps 724: return(1);
1.45 kristaps 725: }
726:
727:
728: /* ARGSUSED */
729: static int
730: man_literal_pre(MAN_ARGS)
731: {
732:
1.48 kristaps 733: if (MAN_nf == n->tok) {
1.45 kristaps 734: print_otag(h, TAG_BR, 0, NULL);
735: mh->fl |= MANH_LITERAL;
1.48 kristaps 736: } else
1.45 kristaps 737: mh->fl &= ~MANH_LITERAL;
738:
739: return(1);
740: }
741:
742:
743: /* ARGSUSED */
744: static int
745: man_in_pre(MAN_ARGS)
746: {
747:
748: print_otag(h, TAG_BR, 0, NULL);
749: return(0);
1.8 kristaps 750: }
751:
752:
753: /* ARGSUSED */
754: static int
755: man_ign_pre(MAN_ARGS)
756: {
757:
758: return(0);
759: }
1.9 kristaps 760:
761:
762: /* ARGSUSED */
763: static int
764: man_RS_pre(MAN_ARGS)
765: {
766: struct htmlpair tag;
767: struct roffsu su;
768:
769: if (MAN_HEAD == n->type)
770: return(0);
771: else if (MAN_BODY == n->type)
772: return(1);
773:
774: SCALE_HS_INIT(&su, INDENT);
775: bufcat_su(h, "margin-left", &su);
776:
777: if (n->head->child) {
778: SCALE_VS_INIT(&su, 1);
779: a2width(n->head->child, &su);
780: bufcat_su(h, "margin-top", &su);
781: }
782:
783: PAIR_STYLE_INIT(&tag, h);
784: print_otag(h, TAG_DIV, 1, &tag);
785: return(1);
786: }
CVSweb