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