Annotation of mandoc/man_html.c, Revision 1.4
1.4 ! kristaps 1: /* $Id: man_html.c,v 1.3 2009/10/03 19:57:53 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: */
17: #include <sys/types.h>
18: #include <sys/queue.h>
19:
1.4 ! kristaps 20: #include <err.h>
1.2 kristaps 21: #include <stdio.h>
1.1 kristaps 22: #include <stdlib.h>
1.4 ! kristaps 23: #include <string.h>
1.1 kristaps 24:
25: #include "html.h"
26: #include "man.h"
27:
1.4 ! kristaps 28: #define INDENT 7
! 29: #define HALFINDENT 3
! 30:
1.3 kristaps 31: #define MAN_ARGS const struct man_meta *m, \
32: const struct man_node *n, \
33: struct html *h
34:
35: struct htmlman {
36: int (*pre)(MAN_ARGS);
37: int (*post)(MAN_ARGS);
38: };
39:
40: static void print_man(MAN_ARGS);
41: static void print_man_head(MAN_ARGS);
1.4 ! kristaps 42: static void print_man_nodelist(MAN_ARGS);
! 43: static void print_man_node(MAN_ARGS);
1.3 kristaps 44:
1.4 ! kristaps 45: static int man_br_pre(MAN_ARGS);
! 46: static int man_PP_pre(MAN_ARGS);
! 47: static void man_root_post(MAN_ARGS);
! 48: static int man_root_pre(MAN_ARGS);
! 49: static int man_SH_pre(MAN_ARGS);
! 50: static int man_SS_pre(MAN_ARGS);
! 51:
! 52: #ifdef __linux__
! 53: extern size_t strlcpy(char *, const char *, size_t);
! 54: extern size_t strlcat(char *, const char *, size_t);
! 55: #endif
1.3 kristaps 56:
57: static const struct htmlman mans[MAN_MAX] = {
1.4 ! kristaps 58: { man_br_pre, NULL }, /* br */
1.3 kristaps 59: { NULL, NULL }, /* TH */
1.4 ! kristaps 60: { man_SH_pre, NULL }, /* SH */
! 61: { man_SS_pre, NULL }, /* SS */
1.3 kristaps 62: { NULL, NULL }, /* TP */
1.4 ! kristaps 63: { man_PP_pre, NULL }, /* LP */
! 64: { man_PP_pre, NULL }, /* PP */
! 65: { man_PP_pre, NULL }, /* P */
1.3 kristaps 66: { NULL, NULL }, /* IP */
67: { NULL, NULL }, /* HP */
68: { NULL, NULL }, /* SM */
69: { NULL, NULL }, /* SB */
70: { NULL, NULL }, /* BI */
71: { NULL, NULL }, /* IB */
72: { NULL, NULL }, /* BR */
73: { NULL, NULL }, /* RB */
74: { NULL, NULL }, /* R */
75: { NULL, NULL }, /* B */
76: { NULL, NULL }, /* I */
77: { NULL, NULL }, /* IR */
78: { NULL, NULL }, /* RI */
79: { NULL, NULL }, /* na */
80: { NULL, NULL }, /* i */
1.4 ! kristaps 81: { man_br_pre, NULL }, /* sp */
1.3 kristaps 82: { NULL, NULL }, /* nf */
83: { NULL, NULL }, /* fi */
84: { NULL, NULL }, /* r */
85: { NULL, NULL }, /* RE */
86: { NULL, NULL }, /* RS */
87: { NULL, NULL }, /* DT */
88: { NULL, NULL }, /* UC */
89: };
90:
1.1 kristaps 91:
92: void
93: html_man(void *arg, const struct man *m)
94: {
1.3 kristaps 95: struct html *h;
96: struct tag *t;
97:
98: h = (struct html *)arg;
99:
100: print_gen_doctype(h);
101:
102: t = print_otag(h, TAG_HTML, 0, NULL);
103: print_man(man_meta(m), man_node(m), h);
104: print_tagq(h, t);
105:
106: printf("\n");
107: }
108:
109:
110: static void
111: print_man(MAN_ARGS)
112: {
113: struct tag *t;
114: struct htmlpair tag;
115:
116: t = print_otag(h, TAG_HEAD, 0, NULL);
117:
118: print_man_head(m, n, h);
119: print_tagq(h, t);
120: t = print_otag(h, TAG_BODY, 0, NULL);
121:
122: tag.key = ATTR_CLASS;
123: tag.val = "body";
124: print_otag(h, TAG_DIV, 1, &tag);
125:
1.4 ! kristaps 126: print_man_nodelist(m, n, h);
1.3 kristaps 127:
128: print_tagq(h, t);
129: }
130:
131:
132: /* ARGSUSED */
133: static void
134: print_man_head(MAN_ARGS)
135: {
136:
137: print_gen_head(h);
138: bufinit(h);
139: buffmt(h, "%s(%d)", m->title, m->msec);
140:
141: print_otag(h, TAG_TITLE, 0, NULL);
142: print_text(h, h->buf);
1.1 kristaps 143: }
1.4 ! kristaps 144:
! 145:
! 146: static void
! 147: print_man_nodelist(MAN_ARGS)
! 148: {
! 149:
! 150: print_man_node(m, n, h);
! 151: if (n->next)
! 152: print_man_nodelist(m, n->next, h);
! 153: }
! 154:
! 155:
! 156: static void
! 157: print_man_node(MAN_ARGS)
! 158: {
! 159: int child;
! 160: struct tag *t;
! 161:
! 162: child = 1;
! 163: t = SLIST_FIRST(&h->tags);
! 164:
! 165: bufinit(h);
! 166:
! 167: switch (n->type) {
! 168: case (MAN_ROOT):
! 169: child = man_root_pre(m, n, h);
! 170: break;
! 171: case (MAN_TEXT):
! 172: print_text(h, n->string);
! 173: break;
! 174: default:
! 175: if (mans[n->tok].pre)
! 176: child = (*mans[n->tok].pre)(m, n, h);
! 177: break;
! 178: }
! 179:
! 180: if (child && n->child)
! 181: print_man_nodelist(m, n->child, h);
! 182:
! 183: print_stagq(h, t);
! 184:
! 185: bufinit(h);
! 186:
! 187: switch (n->type) {
! 188: case (MAN_ROOT):
! 189: man_root_post(m, n, h);
! 190: break;
! 191: case (MAN_TEXT):
! 192: break;
! 193: default:
! 194: if (mans[n->tok].post)
! 195: (*mans[n->tok].post)(m, n, h);
! 196: break;
! 197: }
! 198: }
! 199:
! 200:
! 201: /* ARGSUSED */
! 202: static int
! 203: man_root_pre(MAN_ARGS)
! 204: {
! 205: struct htmlpair tag[2];
! 206: struct tag *t, *tt;
! 207: char b[BUFSIZ], title[BUFSIZ];
! 208:
! 209: b[0] = 0;
! 210: if (m->vol)
! 211: (void)strlcat(b, m->vol, BUFSIZ);
! 212:
! 213: (void)snprintf(title, BUFSIZ - 1,
! 214: "%s(%d)", m->title, m->msec);
! 215:
! 216: tag[0].key = ATTR_CLASS;
! 217: tag[0].val = "header";
! 218: tag[1].key = ATTR_STYLE;
! 219: tag[1].val = "width: 100%;";
! 220: t = print_otag(h, TAG_TABLE, 2, tag);
! 221: tt = print_otag(h, TAG_TR, 0, NULL);
! 222:
! 223: tag[0].key = ATTR_STYLE;
! 224: tag[0].val = "width: 10%;";
! 225: print_otag(h, TAG_TD, 1, tag);
! 226: print_text(h, title);
! 227: print_stagq(h, tt);
! 228:
! 229: tag[0].key = ATTR_STYLE;
! 230: tag[0].val = "width: 80%; white-space: nowrap; text-align: center;";
! 231: print_otag(h, TAG_TD, 1, tag);
! 232: print_text(h, b);
! 233: print_stagq(h, tt);
! 234:
! 235: tag[0].key = ATTR_STYLE;
! 236: tag[0].val = "width: 10%; text-align: right;";
! 237: print_otag(h, TAG_TD, 1, tag);
! 238: print_text(h, title);
! 239: print_tagq(h, t);
! 240:
! 241: return(1);
! 242: }
! 243:
! 244:
! 245: /* ARGSUSED */
! 246: static void
! 247: man_root_post(MAN_ARGS)
! 248: {
! 249: struct tm tm;
! 250: struct htmlpair tag[2];
! 251: struct tag *t, *tt;
! 252: char b[BUFSIZ];
! 253:
! 254: (void)localtime_r(&m->date, &tm);
! 255:
! 256: if (0 == strftime(b, BUFSIZ - 1, "%B %e, %Y", &tm))
! 257: err(EXIT_FAILURE, "strftime");
! 258:
! 259: tag[0].key = ATTR_CLASS;
! 260: tag[0].val = "footer";
! 261: tag[1].key = ATTR_STYLE;
! 262: tag[1].val = "width: 100%;";
! 263: t = print_otag(h, TAG_TABLE, 2, tag);
! 264: tt = print_otag(h, TAG_TR, 0, NULL);
! 265:
! 266: tag[0].key = ATTR_STYLE;
! 267: tag[0].val = "width: 50%;";
! 268: print_otag(h, TAG_TD, 1, tag);
! 269: print_text(h, b);
! 270: print_stagq(h, tt);
! 271:
! 272: tag[0].key = ATTR_STYLE;
! 273: tag[0].val = "width: 50%; text-align: right;";
! 274: print_otag(h, TAG_TD, 1, tag);
! 275: if (m->source)
! 276: print_text(h, m->source);
! 277: print_tagq(h, t);
! 278: }
! 279:
! 280:
! 281:
! 282: /* ARGSUSED */
! 283: static int
! 284: man_br_pre(MAN_ARGS)
! 285: {
! 286: int len;
! 287: struct htmlpair tag;
! 288:
! 289: switch (n->tok) {
! 290: case (MAN_sp):
! 291: len = n->child ? atoi(n->child->string) : 1;
! 292: break;
! 293: case (MAN_br):
! 294: len = 0;
! 295: break;
! 296: default:
! 297: len = 1;
! 298: break;
! 299: }
! 300:
! 301: buffmt(h, "height: %dem;", len);
! 302: tag.key = ATTR_STYLE;
! 303: tag.val = h->buf;
! 304: print_otag(h, TAG_DIV, 1, &tag);
! 305: return(1);
! 306: }
! 307:
! 308:
! 309: /* ARGSUSED */
! 310: static int
! 311: man_SH_pre(MAN_ARGS)
! 312: {
! 313: struct htmlpair tag[2];
! 314:
! 315: if (MAN_BODY == n->type) {
! 316: buffmt(h, "margin-left: %dem;", INDENT);
! 317:
! 318: tag[0].key = ATTR_CLASS;
! 319: tag[0].val = "sec-body";
! 320: tag[1].key = ATTR_STYLE;
! 321: tag[1].val = h->buf;
! 322:
! 323: print_otag(h, TAG_DIV, 2, tag);
! 324: return(1);
! 325: } else if (MAN_BLOCK == n->type) {
! 326: tag[0].key = ATTR_CLASS;
! 327: tag[0].val = "sec-block";
! 328:
! 329: if (n->prev && MAN_SH == n->prev->tok)
! 330: if (NULL == n->prev->body->child) {
! 331: print_otag(h, TAG_DIV, 1, tag);
! 332: return(1);
! 333: }
! 334:
! 335: bufcat(h, "margin-top: 1em;");
! 336: if (NULL == n->next)
! 337: bufcat(h, "margin-bottom: 1em;");
! 338:
! 339: tag[1].key = ATTR_STYLE;
! 340: tag[1].val = h->buf;
! 341:
! 342: print_otag(h, TAG_DIV, 2, tag);
! 343: return(1);
! 344: }
! 345:
! 346: tag[0].key = ATTR_CLASS;
! 347: tag[0].val = "sec-head";
! 348:
! 349: print_otag(h, TAG_DIV, 1, tag);
! 350: return(1);
! 351: }
! 352:
! 353:
! 354: /* ARGSUSED */
! 355: static int
! 356: man_SS_pre(MAN_ARGS)
! 357: {
! 358: struct htmlpair tag[3];
! 359: int i;
! 360:
! 361: i = 0;
! 362:
! 363: if (MAN_BODY == n->type) {
! 364: tag[i].key = ATTR_CLASS;
! 365: tag[i++].val = "ssec-body";
! 366:
! 367: if (n->parent->next && n->child) {
! 368: bufcat(h, "margin-bottom: 1em;");
! 369: tag[i].key = ATTR_STYLE;
! 370: tag[i++].val = h->buf;
! 371: }
! 372:
! 373: print_otag(h, TAG_DIV, i, tag);
! 374: return(1);
! 375: } else if (MAN_BLOCK == n->type) {
! 376: tag[i].key = ATTR_CLASS;
! 377: tag[i++].val = "ssec-block";
! 378:
! 379: if (n->prev && MAN_SS == n->prev->tok)
! 380: if (n->prev->body->child) {
! 381: bufcat(h, "margin-top: 1em;");
! 382: tag[i].key = ATTR_STYLE;
! 383: tag[i++].val = h->buf;
! 384: }
! 385:
! 386: print_otag(h, TAG_DIV, i, tag);
! 387: return(1);
! 388: }
! 389:
! 390: buffmt(h, "margin-left: -%dem;", INDENT - HALFINDENT);
! 391:
! 392: tag[0].key = ATTR_CLASS;
! 393: tag[0].val = "ssec-head";
! 394: tag[1].key = ATTR_STYLE;
! 395: tag[1].val = h->buf;
! 396:
! 397: print_otag(h, TAG_DIV, 2, tag);
! 398: return(1);
! 399: }
! 400:
! 401:
! 402: /* ARGSUSED */
! 403: static int
! 404: man_PP_pre(MAN_ARGS)
! 405: {
! 406: struct htmlpair tag;
! 407:
! 408: if (MAN_BLOCK != n->type)
! 409: return(1);
! 410:
! 411: buffmt(h, "margin-left: %dem;", INDENT);
! 412: if (n->next && n->next->child)
! 413: bufcat(h, "margin-bottom: 1em;");
! 414:
! 415: tag.key = ATTR_STYLE;
! 416: tag.val = h->buf;
! 417: print_otag(h, TAG_DIV, 1, &tag);
! 418: return(1);
! 419: }
CVSweb