1241675Suqs/* $Id: man_html.c,v 1.86 2012/01/03 15:16:24 kristaps Exp $ */ 2241675Suqs/* 3241675Suqs * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> 4241675Suqs * 5241675Suqs * Permission to use, copy, modify, and distribute this software for any 6241675Suqs * purpose with or without fee is hereby granted, provided that the above 7241675Suqs * copyright notice and this permission notice appear in all copies. 8241675Suqs * 9241675Suqs * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10241675Suqs * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11241675Suqs * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12241675Suqs * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13241675Suqs * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14241675Suqs * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15241675Suqs * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16241675Suqs */ 17241675Suqs#ifdef HAVE_CONFIG_H 18241675Suqs#include "config.h" 19241675Suqs#endif 20241675Suqs 21241675Suqs#include <sys/types.h> 22241675Suqs 23241675Suqs#include <assert.h> 24241675Suqs#include <ctype.h> 25241675Suqs#include <stdio.h> 26241675Suqs#include <stdlib.h> 27241675Suqs#include <string.h> 28241675Suqs 29241675Suqs#include "mandoc.h" 30241675Suqs#include "out.h" 31241675Suqs#include "html.h" 32241675Suqs#include "man.h" 33241675Suqs#include "main.h" 34241675Suqs 35241675Suqs/* TODO: preserve ident widths. */ 36241675Suqs/* FIXME: have PD set the default vspace width. */ 37241675Suqs 38241675Suqs#define INDENT 5 39241675Suqs 40241675Suqs#define MAN_ARGS const struct man_meta *m, \ 41241675Suqs const struct man_node *n, \ 42241675Suqs struct mhtml *mh, \ 43241675Suqs struct html *h 44241675Suqs 45241675Suqsstruct mhtml { 46241675Suqs int fl; 47241675Suqs#define MANH_LITERAL (1 << 0) /* literal context */ 48241675Suqs}; 49241675Suqs 50241675Suqsstruct htmlman { 51241675Suqs int (*pre)(MAN_ARGS); 52241675Suqs int (*post)(MAN_ARGS); 53241675Suqs}; 54241675Suqs 55241675Suqsstatic void print_bvspace(struct html *, 56241675Suqs const struct man_node *); 57241675Suqsstatic void print_man(MAN_ARGS); 58241675Suqsstatic void print_man_head(MAN_ARGS); 59241675Suqsstatic void print_man_nodelist(MAN_ARGS); 60241675Suqsstatic void print_man_node(MAN_ARGS); 61241675Suqsstatic int a2width(const struct man_node *, 62241675Suqs struct roffsu *); 63241675Suqsstatic int man_B_pre(MAN_ARGS); 64241675Suqsstatic int man_HP_pre(MAN_ARGS); 65241675Suqsstatic int man_IP_pre(MAN_ARGS); 66241675Suqsstatic int man_I_pre(MAN_ARGS); 67241675Suqsstatic int man_OP_pre(MAN_ARGS); 68241675Suqsstatic int man_PP_pre(MAN_ARGS); 69241675Suqsstatic int man_RS_pre(MAN_ARGS); 70241675Suqsstatic int man_SH_pre(MAN_ARGS); 71241675Suqsstatic int man_SM_pre(MAN_ARGS); 72241675Suqsstatic int man_SS_pre(MAN_ARGS); 73241675Suqsstatic int man_alt_pre(MAN_ARGS); 74241675Suqsstatic int man_br_pre(MAN_ARGS); 75241675Suqsstatic int man_ign_pre(MAN_ARGS); 76241675Suqsstatic int man_in_pre(MAN_ARGS); 77241675Suqsstatic int man_literal_pre(MAN_ARGS); 78241675Suqsstatic void man_root_post(MAN_ARGS); 79241675Suqsstatic void man_root_pre(MAN_ARGS); 80241675Suqs 81241675Suqsstatic const struct htmlman mans[MAN_MAX] = { 82241675Suqs { man_br_pre, NULL }, /* br */ 83241675Suqs { NULL, NULL }, /* TH */ 84241675Suqs { man_SH_pre, NULL }, /* SH */ 85241675Suqs { man_SS_pre, NULL }, /* SS */ 86241675Suqs { man_IP_pre, NULL }, /* TP */ 87241675Suqs { man_PP_pre, NULL }, /* LP */ 88241675Suqs { man_PP_pre, NULL }, /* PP */ 89241675Suqs { man_PP_pre, NULL }, /* P */ 90241675Suqs { man_IP_pre, NULL }, /* IP */ 91241675Suqs { man_HP_pre, NULL }, /* HP */ 92241675Suqs { man_SM_pre, NULL }, /* SM */ 93241675Suqs { man_SM_pre, NULL }, /* SB */ 94241675Suqs { man_alt_pre, NULL }, /* BI */ 95241675Suqs { man_alt_pre, NULL }, /* IB */ 96241675Suqs { man_alt_pre, NULL }, /* BR */ 97241675Suqs { man_alt_pre, NULL }, /* RB */ 98241675Suqs { NULL, NULL }, /* R */ 99241675Suqs { man_B_pre, NULL }, /* B */ 100241675Suqs { man_I_pre, NULL }, /* I */ 101241675Suqs { man_alt_pre, NULL }, /* IR */ 102241675Suqs { man_alt_pre, NULL }, /* RI */ 103241675Suqs { man_ign_pre, NULL }, /* na */ 104241675Suqs { man_br_pre, NULL }, /* sp */ 105241675Suqs { man_literal_pre, NULL }, /* nf */ 106241675Suqs { man_literal_pre, NULL }, /* fi */ 107241675Suqs { NULL, NULL }, /* RE */ 108241675Suqs { man_RS_pre, NULL }, /* RS */ 109241675Suqs { man_ign_pre, NULL }, /* DT */ 110241675Suqs { man_ign_pre, NULL }, /* UC */ 111241675Suqs { man_ign_pre, NULL }, /* PD */ 112241675Suqs { man_ign_pre, NULL }, /* AT */ 113241675Suqs { man_in_pre, NULL }, /* in */ 114241675Suqs { man_ign_pre, NULL }, /* ft */ 115241675Suqs { man_OP_pre, NULL }, /* OP */ 116241675Suqs}; 117241675Suqs 118241675Suqs/* 119241675Suqs * Printing leading vertical space before a block. 120241675Suqs * This is used for the paragraph macros. 121241675Suqs * The rules are pretty simple, since there's very little nesting going 122241675Suqs * on here. Basically, if we're the first within another block (SS/SH), 123241675Suqs * then don't emit vertical space. If we are (RS), then do. If not the 124241675Suqs * first, print it. 125241675Suqs */ 126241675Suqsstatic void 127241675Suqsprint_bvspace(struct html *h, const struct man_node *n) 128241675Suqs{ 129241675Suqs 130241675Suqs if (n->body && n->body->child) 131241675Suqs if (MAN_TBL == n->body->child->type) 132241675Suqs return; 133241675Suqs 134241675Suqs if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok) 135241675Suqs if (NULL == n->prev) 136241675Suqs return; 137241675Suqs 138241675Suqs print_otag(h, TAG_P, 0, NULL); 139241675Suqs} 140241675Suqs 141241675Suqsvoid 142241675Suqshtml_man(void *arg, const struct man *m) 143241675Suqs{ 144241675Suqs struct mhtml mh; 145241675Suqs 146241675Suqs memset(&mh, 0, sizeof(struct mhtml)); 147241675Suqs print_man(man_meta(m), man_node(m), &mh, (struct html *)arg); 148241675Suqs putchar('\n'); 149241675Suqs} 150241675Suqs 151241675Suqsstatic void 152241675Suqsprint_man(MAN_ARGS) 153241675Suqs{ 154241675Suqs struct tag *t, *tt; 155241675Suqs struct htmlpair tag; 156241675Suqs 157241675Suqs PAIR_CLASS_INIT(&tag, "mandoc"); 158241675Suqs 159241675Suqs if ( ! (HTML_FRAGMENT & h->oflags)) { 160241675Suqs print_gen_decls(h); 161241675Suqs t = print_otag(h, TAG_HTML, 0, NULL); 162241675Suqs tt = print_otag(h, TAG_HEAD, 0, NULL); 163241675Suqs print_man_head(m, n, mh, h); 164241675Suqs print_tagq(h, tt); 165241675Suqs print_otag(h, TAG_BODY, 0, NULL); 166241675Suqs print_otag(h, TAG_DIV, 1, &tag); 167241675Suqs } else 168241675Suqs t = print_otag(h, TAG_DIV, 1, &tag); 169241675Suqs 170241675Suqs print_man_nodelist(m, n, mh, h); 171241675Suqs print_tagq(h, t); 172241675Suqs} 173241675Suqs 174241675Suqs 175241675Suqs/* ARGSUSED */ 176241675Suqsstatic void 177241675Suqsprint_man_head(MAN_ARGS) 178241675Suqs{ 179241675Suqs 180241675Suqs print_gen_head(h); 181241675Suqs assert(m->title); 182241675Suqs assert(m->msec); 183241675Suqs bufcat_fmt(h, "%s(%s)", m->title, m->msec); 184241675Suqs print_otag(h, TAG_TITLE, 0, NULL); 185241675Suqs print_text(h, h->buf); 186241675Suqs} 187241675Suqs 188241675Suqs 189241675Suqsstatic void 190241675Suqsprint_man_nodelist(MAN_ARGS) 191241675Suqs{ 192241675Suqs 193241675Suqs print_man_node(m, n, mh, h); 194241675Suqs if (n->next) 195241675Suqs print_man_nodelist(m, n->next, mh, h); 196241675Suqs} 197241675Suqs 198241675Suqs 199241675Suqsstatic void 200241675Suqsprint_man_node(MAN_ARGS) 201241675Suqs{ 202241675Suqs int child; 203241675Suqs struct tag *t; 204241675Suqs 205241675Suqs child = 1; 206241675Suqs t = h->tags.head; 207241675Suqs 208241675Suqs switch (n->type) { 209241675Suqs case (MAN_ROOT): 210241675Suqs man_root_pre(m, n, mh, h); 211241675Suqs break; 212241675Suqs case (MAN_TEXT): 213241675Suqs /* 214241675Suqs * If we have a blank line, output a vertical space. 215241675Suqs * If we have a space as the first character, break 216241675Suqs * before printing the line's data. 217241675Suqs */ 218241675Suqs if ('\0' == *n->string) { 219241675Suqs print_otag(h, TAG_P, 0, NULL); 220241675Suqs return; 221241675Suqs } 222241675Suqs 223241675Suqs if (' ' == *n->string && MAN_LINE & n->flags) 224241675Suqs print_otag(h, TAG_BR, 0, NULL); 225241675Suqs else if (MANH_LITERAL & mh->fl && n->prev) 226241675Suqs print_otag(h, TAG_BR, 0, NULL); 227241675Suqs 228241675Suqs print_text(h, n->string); 229241675Suqs return; 230241675Suqs case (MAN_EQN): 231241675Suqs print_eqn(h, n->eqn); 232241675Suqs break; 233241675Suqs case (MAN_TBL): 234241675Suqs /* 235241675Suqs * This will take care of initialising all of the table 236241675Suqs * state data for the first table, then tearing it down 237241675Suqs * for the last one. 238241675Suqs */ 239241675Suqs print_tbl(h, n->span); 240241675Suqs return; 241241675Suqs default: 242241675Suqs /* 243241675Suqs * Close out scope of font prior to opening a macro 244241675Suqs * scope. 245241675Suqs */ 246241675Suqs if (HTMLFONT_NONE != h->metac) { 247241675Suqs h->metal = h->metac; 248241675Suqs h->metac = HTMLFONT_NONE; 249241675Suqs } 250241675Suqs 251241675Suqs /* 252241675Suqs * Close out the current table, if it's open, and unset 253241675Suqs * the "meta" table state. This will be reopened on the 254241675Suqs * next table element. 255241675Suqs */ 256241675Suqs if (h->tblt) { 257241675Suqs print_tblclose(h); 258241675Suqs t = h->tags.head; 259241675Suqs } 260241675Suqs if (mans[n->tok].pre) 261241675Suqs child = (*mans[n->tok].pre)(m, n, mh, h); 262241675Suqs break; 263241675Suqs } 264241675Suqs 265241675Suqs if (child && n->child) 266241675Suqs print_man_nodelist(m, n->child, mh, h); 267241675Suqs 268241675Suqs /* This will automatically close out any font scope. */ 269241675Suqs print_stagq(h, t); 270241675Suqs 271241675Suqs switch (n->type) { 272241675Suqs case (MAN_ROOT): 273241675Suqs man_root_post(m, n, mh, h); 274241675Suqs break; 275241675Suqs case (MAN_EQN): 276241675Suqs break; 277241675Suqs default: 278241675Suqs if (mans[n->tok].post) 279241675Suqs (*mans[n->tok].post)(m, n, mh, h); 280241675Suqs break; 281241675Suqs } 282241675Suqs} 283241675Suqs 284241675Suqs 285241675Suqsstatic int 286241675Suqsa2width(const struct man_node *n, struct roffsu *su) 287241675Suqs{ 288241675Suqs 289241675Suqs if (MAN_TEXT != n->type) 290241675Suqs return(0); 291241675Suqs if (a2roffsu(n->string, su, SCALE_BU)) 292241675Suqs return(1); 293241675Suqs 294241675Suqs return(0); 295241675Suqs} 296241675Suqs 297241675Suqs 298241675Suqs/* ARGSUSED */ 299241675Suqsstatic void 300241675Suqsman_root_pre(MAN_ARGS) 301241675Suqs{ 302241675Suqs struct htmlpair tag[3]; 303241675Suqs struct tag *t, *tt; 304241675Suqs char b[BUFSIZ], title[BUFSIZ]; 305241675Suqs 306241675Suqs b[0] = 0; 307241675Suqs if (m->vol) 308241675Suqs (void)strlcat(b, m->vol, BUFSIZ); 309241675Suqs 310241675Suqs assert(m->title); 311241675Suqs assert(m->msec); 312241675Suqs snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec); 313241675Suqs 314241675Suqs PAIR_SUMMARY_INIT(&tag[0], "Document Header"); 315241675Suqs PAIR_CLASS_INIT(&tag[1], "head"); 316241675Suqs PAIR_INIT(&tag[2], ATTR_WIDTH, "100%"); 317241675Suqs t = print_otag(h, TAG_TABLE, 3, tag); 318241675Suqs PAIR_INIT(&tag[0], ATTR_WIDTH, "30%"); 319241675Suqs print_otag(h, TAG_COL, 1, tag); 320241675Suqs print_otag(h, TAG_COL, 1, tag); 321241675Suqs print_otag(h, TAG_COL, 1, tag); 322241675Suqs 323241675Suqs print_otag(h, TAG_TBODY, 0, NULL); 324241675Suqs 325241675Suqs tt = print_otag(h, TAG_TR, 0, NULL); 326241675Suqs 327241675Suqs PAIR_CLASS_INIT(&tag[0], "head-ltitle"); 328241675Suqs print_otag(h, TAG_TD, 1, tag); 329241675Suqs print_text(h, title); 330241675Suqs print_stagq(h, tt); 331241675Suqs 332241675Suqs PAIR_CLASS_INIT(&tag[0], "head-vol"); 333241675Suqs PAIR_INIT(&tag[1], ATTR_ALIGN, "center"); 334241675Suqs print_otag(h, TAG_TD, 2, tag); 335241675Suqs print_text(h, b); 336241675Suqs print_stagq(h, tt); 337241675Suqs 338241675Suqs PAIR_CLASS_INIT(&tag[0], "head-rtitle"); 339241675Suqs PAIR_INIT(&tag[1], ATTR_ALIGN, "right"); 340241675Suqs print_otag(h, TAG_TD, 2, tag); 341241675Suqs print_text(h, title); 342241675Suqs print_tagq(h, t); 343241675Suqs} 344241675Suqs 345241675Suqs 346241675Suqs/* ARGSUSED */ 347241675Suqsstatic void 348241675Suqsman_root_post(MAN_ARGS) 349241675Suqs{ 350241675Suqs struct htmlpair tag[3]; 351241675Suqs struct tag *t, *tt; 352241675Suqs 353241675Suqs PAIR_SUMMARY_INIT(&tag[0], "Document Footer"); 354241675Suqs PAIR_CLASS_INIT(&tag[1], "foot"); 355241675Suqs PAIR_INIT(&tag[2], ATTR_WIDTH, "100%"); 356241675Suqs t = print_otag(h, TAG_TABLE, 3, tag); 357241675Suqs PAIR_INIT(&tag[0], ATTR_WIDTH, "50%"); 358241675Suqs print_otag(h, TAG_COL, 1, tag); 359241675Suqs print_otag(h, TAG_COL, 1, tag); 360241675Suqs 361241675Suqs tt = print_otag(h, TAG_TR, 0, NULL); 362241675Suqs 363241675Suqs PAIR_CLASS_INIT(&tag[0], "foot-date"); 364241675Suqs print_otag(h, TAG_TD, 1, tag); 365241675Suqs 366241675Suqs assert(m->date); 367241675Suqs print_text(h, m->date); 368241675Suqs print_stagq(h, tt); 369241675Suqs 370241675Suqs PAIR_CLASS_INIT(&tag[0], "foot-os"); 371241675Suqs PAIR_INIT(&tag[1], ATTR_ALIGN, "right"); 372241675Suqs print_otag(h, TAG_TD, 2, tag); 373241675Suqs 374241675Suqs if (m->source) 375241675Suqs print_text(h, m->source); 376241675Suqs print_tagq(h, t); 377241675Suqs} 378241675Suqs 379241675Suqs 380241675Suqs/* ARGSUSED */ 381241675Suqsstatic int 382241675Suqsman_br_pre(MAN_ARGS) 383241675Suqs{ 384241675Suqs struct roffsu su; 385241675Suqs struct htmlpair tag; 386241675Suqs 387241675Suqs SCALE_VS_INIT(&su, 1); 388241675Suqs 389241675Suqs if (MAN_sp == n->tok) { 390241675Suqs if (NULL != (n = n->child)) 391241675Suqs if ( ! a2roffsu(n->string, &su, SCALE_VS)) 392241675Suqs SCALE_VS_INIT(&su, atoi(n->string)); 393241675Suqs } else 394241675Suqs su.scale = 0; 395241675Suqs 396241675Suqs bufinit(h); 397241675Suqs bufcat_su(h, "height", &su); 398241675Suqs PAIR_STYLE_INIT(&tag, h); 399241675Suqs print_otag(h, TAG_DIV, 1, &tag); 400241675Suqs 401241675Suqs /* So the div isn't empty: */ 402241675Suqs print_text(h, "\\~"); 403241675Suqs 404241675Suqs return(0); 405241675Suqs} 406241675Suqs 407241675Suqs/* ARGSUSED */ 408241675Suqsstatic int 409241675Suqsman_SH_pre(MAN_ARGS) 410241675Suqs{ 411241675Suqs struct htmlpair tag; 412241675Suqs 413241675Suqs if (MAN_BLOCK == n->type) { 414241675Suqs mh->fl &= ~MANH_LITERAL; 415241675Suqs PAIR_CLASS_INIT(&tag, "section"); 416241675Suqs print_otag(h, TAG_DIV, 1, &tag); 417241675Suqs return(1); 418241675Suqs } else if (MAN_BODY == n->type) 419241675Suqs return(1); 420241675Suqs 421241675Suqs print_otag(h, TAG_H1, 0, NULL); 422241675Suqs return(1); 423241675Suqs} 424241675Suqs 425241675Suqs/* ARGSUSED */ 426241675Suqsstatic int 427241675Suqsman_alt_pre(MAN_ARGS) 428241675Suqs{ 429241675Suqs const struct man_node *nn; 430241675Suqs int i, savelit; 431241675Suqs enum htmltag fp; 432241675Suqs struct tag *t; 433241675Suqs 434241675Suqs if ((savelit = mh->fl & MANH_LITERAL)) 435241675Suqs print_otag(h, TAG_BR, 0, NULL); 436241675Suqs 437241675Suqs mh->fl &= ~MANH_LITERAL; 438241675Suqs 439241675Suqs for (i = 0, nn = n->child; nn; nn = nn->next, i++) { 440241675Suqs t = NULL; 441241675Suqs switch (n->tok) { 442241675Suqs case (MAN_BI): 443241675Suqs fp = i % 2 ? TAG_I : TAG_B; 444241675Suqs break; 445241675Suqs case (MAN_IB): 446241675Suqs fp = i % 2 ? TAG_B : TAG_I; 447241675Suqs break; 448241675Suqs case (MAN_RI): 449241675Suqs fp = i % 2 ? TAG_I : TAG_MAX; 450241675Suqs break; 451241675Suqs case (MAN_IR): 452241675Suqs fp = i % 2 ? TAG_MAX : TAG_I; 453241675Suqs break; 454241675Suqs case (MAN_BR): 455241675Suqs fp = i % 2 ? TAG_MAX : TAG_B; 456241675Suqs break; 457241675Suqs case (MAN_RB): 458241675Suqs fp = i % 2 ? TAG_B : TAG_MAX; 459241675Suqs break; 460241675Suqs default: 461241675Suqs abort(); 462241675Suqs /* NOTREACHED */ 463241675Suqs } 464241675Suqs 465241675Suqs if (i) 466241675Suqs h->flags |= HTML_NOSPACE; 467241675Suqs 468241675Suqs if (TAG_MAX != fp) 469241675Suqs t = print_otag(h, fp, 0, NULL); 470241675Suqs 471241675Suqs print_man_node(m, nn, mh, h); 472241675Suqs 473241675Suqs if (t) 474241675Suqs print_tagq(h, t); 475241675Suqs } 476241675Suqs 477241675Suqs if (savelit) 478241675Suqs mh->fl |= MANH_LITERAL; 479241675Suqs 480241675Suqs return(0); 481241675Suqs} 482241675Suqs 483241675Suqs/* ARGSUSED */ 484241675Suqsstatic int 485241675Suqsman_SM_pre(MAN_ARGS) 486241675Suqs{ 487241675Suqs 488241675Suqs print_otag(h, TAG_SMALL, 0, NULL); 489241675Suqs if (MAN_SB == n->tok) 490241675Suqs print_otag(h, TAG_B, 0, NULL); 491241675Suqs return(1); 492241675Suqs} 493241675Suqs 494241675Suqs/* ARGSUSED */ 495241675Suqsstatic int 496241675Suqsman_SS_pre(MAN_ARGS) 497241675Suqs{ 498241675Suqs struct htmlpair tag; 499241675Suqs 500241675Suqs if (MAN_BLOCK == n->type) { 501241675Suqs mh->fl &= ~MANH_LITERAL; 502241675Suqs PAIR_CLASS_INIT(&tag, "subsection"); 503241675Suqs print_otag(h, TAG_DIV, 1, &tag); 504241675Suqs return(1); 505241675Suqs } else if (MAN_BODY == n->type) 506241675Suqs return(1); 507241675Suqs 508241675Suqs print_otag(h, TAG_H2, 0, NULL); 509241675Suqs return(1); 510241675Suqs} 511241675Suqs 512241675Suqs/* ARGSUSED */ 513241675Suqsstatic int 514241675Suqsman_PP_pre(MAN_ARGS) 515241675Suqs{ 516241675Suqs 517241675Suqs if (MAN_HEAD == n->type) 518241675Suqs return(0); 519241675Suqs else if (MAN_BLOCK == n->type) 520241675Suqs print_bvspace(h, n); 521241675Suqs 522241675Suqs return(1); 523241675Suqs} 524241675Suqs 525241675Suqs/* ARGSUSED */ 526241675Suqsstatic int 527241675Suqsman_IP_pre(MAN_ARGS) 528241675Suqs{ 529241675Suqs const struct man_node *nn; 530241675Suqs 531241675Suqs if (MAN_BODY == n->type) { 532241675Suqs print_otag(h, TAG_DD, 0, NULL); 533241675Suqs return(1); 534241675Suqs } else if (MAN_HEAD != n->type) { 535241675Suqs print_otag(h, TAG_DL, 0, NULL); 536241675Suqs return(1); 537241675Suqs } 538241675Suqs 539241675Suqs /* FIXME: width specification. */ 540241675Suqs 541241675Suqs print_otag(h, TAG_DT, 0, NULL); 542241675Suqs 543241675Suqs /* For IP, only print the first header element. */ 544241675Suqs 545241675Suqs if (MAN_IP == n->tok && n->child) 546241675Suqs print_man_node(m, n->child, mh, h); 547241675Suqs 548241675Suqs /* For TP, only print next-line header elements. */ 549241675Suqs 550241675Suqs if (MAN_TP == n->tok) 551241675Suqs for (nn = n->child; nn; nn = nn->next) 552241675Suqs if (nn->line > n->line) 553241675Suqs print_man_node(m, nn, mh, h); 554241675Suqs 555241675Suqs return(0); 556241675Suqs} 557241675Suqs 558241675Suqs/* ARGSUSED */ 559241675Suqsstatic int 560241675Suqsman_HP_pre(MAN_ARGS) 561241675Suqs{ 562241675Suqs struct htmlpair tag; 563241675Suqs struct roffsu su; 564241675Suqs const struct man_node *np; 565241675Suqs 566241675Suqs if (MAN_HEAD == n->type) 567241675Suqs return(0); 568241675Suqs else if (MAN_BLOCK != n->type) 569241675Suqs return(1); 570241675Suqs 571241675Suqs np = n->head->child; 572241675Suqs 573241675Suqs if (NULL == np || ! a2width(np, &su)) 574241675Suqs SCALE_HS_INIT(&su, INDENT); 575241675Suqs 576241675Suqs bufinit(h); 577241675Suqs 578241675Suqs print_bvspace(h, n); 579241675Suqs bufcat_su(h, "margin-left", &su); 580241675Suqs su.scale = -su.scale; 581241675Suqs bufcat_su(h, "text-indent", &su); 582241675Suqs PAIR_STYLE_INIT(&tag, h); 583241675Suqs print_otag(h, TAG_P, 1, &tag); 584241675Suqs return(1); 585241675Suqs} 586241675Suqs 587241675Suqs/* ARGSUSED */ 588241675Suqsstatic int 589241675Suqsman_OP_pre(MAN_ARGS) 590241675Suqs{ 591241675Suqs struct tag *tt; 592241675Suqs struct htmlpair tag; 593241675Suqs 594241675Suqs print_text(h, "["); 595241675Suqs h->flags |= HTML_NOSPACE; 596241675Suqs PAIR_CLASS_INIT(&tag, "opt"); 597241675Suqs tt = print_otag(h, TAG_SPAN, 1, &tag); 598241675Suqs 599241675Suqs if (NULL != (n = n->child)) { 600241675Suqs print_otag(h, TAG_B, 0, NULL); 601241675Suqs print_text(h, n->string); 602241675Suqs } 603241675Suqs 604241675Suqs print_stagq(h, tt); 605241675Suqs 606241675Suqs if (NULL != n && NULL != n->next) { 607241675Suqs print_otag(h, TAG_I, 0, NULL); 608241675Suqs print_text(h, n->next->string); 609241675Suqs } 610241675Suqs 611241675Suqs print_stagq(h, tt); 612241675Suqs h->flags |= HTML_NOSPACE; 613241675Suqs print_text(h, "]"); 614241675Suqs return(0); 615241675Suqs} 616241675Suqs 617241675Suqs 618241675Suqs/* ARGSUSED */ 619241675Suqsstatic int 620241675Suqsman_B_pre(MAN_ARGS) 621241675Suqs{ 622241675Suqs 623241675Suqs print_otag(h, TAG_B, 0, NULL); 624241675Suqs return(1); 625241675Suqs} 626241675Suqs 627241675Suqs/* ARGSUSED */ 628241675Suqsstatic int 629241675Suqsman_I_pre(MAN_ARGS) 630241675Suqs{ 631241675Suqs 632241675Suqs print_otag(h, TAG_I, 0, NULL); 633241675Suqs return(1); 634241675Suqs} 635241675Suqs 636241675Suqs/* ARGSUSED */ 637241675Suqsstatic int 638241675Suqsman_literal_pre(MAN_ARGS) 639241675Suqs{ 640241675Suqs 641241675Suqs if (MAN_nf != n->tok) { 642241675Suqs print_otag(h, TAG_BR, 0, NULL); 643241675Suqs mh->fl &= ~MANH_LITERAL; 644241675Suqs } else 645241675Suqs mh->fl |= MANH_LITERAL; 646241675Suqs 647241675Suqs return(0); 648241675Suqs} 649241675Suqs 650241675Suqs/* ARGSUSED */ 651241675Suqsstatic int 652241675Suqsman_in_pre(MAN_ARGS) 653241675Suqs{ 654241675Suqs 655241675Suqs print_otag(h, TAG_BR, 0, NULL); 656241675Suqs return(0); 657241675Suqs} 658241675Suqs 659241675Suqs/* ARGSUSED */ 660241675Suqsstatic int 661241675Suqsman_ign_pre(MAN_ARGS) 662241675Suqs{ 663241675Suqs 664241675Suqs return(0); 665241675Suqs} 666241675Suqs 667241675Suqs/* ARGSUSED */ 668241675Suqsstatic int 669241675Suqsman_RS_pre(MAN_ARGS) 670241675Suqs{ 671241675Suqs struct htmlpair tag; 672241675Suqs struct roffsu su; 673241675Suqs 674241675Suqs if (MAN_HEAD == n->type) 675241675Suqs return(0); 676241675Suqs else if (MAN_BODY == n->type) 677241675Suqs return(1); 678241675Suqs 679241675Suqs SCALE_HS_INIT(&su, INDENT); 680241675Suqs if (n->head->child) 681241675Suqs a2width(n->head->child, &su); 682241675Suqs 683241675Suqs bufinit(h); 684241675Suqs bufcat_su(h, "margin-left", &su); 685241675Suqs PAIR_STYLE_INIT(&tag, h); 686241675Suqs print_otag(h, TAG_DIV, 1, &tag); 687241675Suqs return(1); 688241675Suqs} 689