Annotation of mandoc/html.c, Revision 1.20
1.20 ! kristaps 1: /* $Id: html.c,v 1.19 2008/12/10 00:52:46 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2008 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
7: * above copyright notice and this permission notice appear in all
8: * copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11: * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12: * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13: * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16: * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17: * PERFORMANCE OF THIS SOFTWARE.
18: */
1.4 kristaps 19: #include <sys/param.h>
20: #include <sys/stat.h>
21:
1.1 kristaps 22: #include <assert.h>
1.4 kristaps 23: #include <err.h>
24: #include <fcntl.h>
1.1 kristaps 25: #include <stdlib.h>
1.4 kristaps 26: #include <stdio.h>
1.2 kristaps 27: #include <string.h>
1.4 kristaps 28: #include <unistd.h>
1.1 kristaps 29:
1.19 kristaps 30: #include "html.h"
1.2 kristaps 31: #include "ml.h"
32:
1.8 kristaps 33: /* TODO: allow head/tail-less invocations (just "div" start). */
34:
1.7 kristaps 35: struct htmlnode {
1.8 kristaps 36: int tok;
37: enum md_ns ns;
1.10 kristaps 38: int argc[ROFF_MAXLINEARG];
1.7 kristaps 39: char *argv[ROFF_MAXLINEARG];
40: struct htmlnode *parent;
41: };
42:
43: struct htmlq {
44: struct htmlnode *last;
45: };
46:
47:
1.19 kristaps 48: static int html_loadcss(struct md_mbuf *,
49: const char *);
1.9 kristaps 50: static int html_alloc(void **);
51: static void html_free(void *);
1.8 kristaps 52: static ssize_t html_endtag(struct md_mbuf *, void *,
1.2 kristaps 53: const struct md_args *,
54: enum md_ns, int);
1.14 kristaps 55: static ssize_t html_beginstring(struct md_mbuf *,
56: const struct md_args *,
57: const char *, size_t);
58: static ssize_t html_beginhttp(struct md_mbuf *,
59: const struct md_args *,
60: const char *, size_t);
61: static ssize_t html_endstring(struct md_mbuf *,
62: const struct md_args *,
63: const char *, size_t);
64: static ssize_t html_endhttp(struct md_mbuf *,
65: const struct md_args *,
66: const char *, size_t);
1.8 kristaps 67: static ssize_t html_begintag(struct md_mbuf *, void *,
1.2 kristaps 68: const struct md_args *,
69: enum md_ns, int,
70: const int *, const char **);
1.4 kristaps 71: static int html_begin(struct md_mbuf *,
72: const struct md_args *,
73: const struct tm *,
74: const char *, const char *,
1.15 kristaps 75: enum roffmsec, const char *);
1.7 kristaps 76: static int html_printargs(struct md_mbuf *, int,
77: const char *, const int *,
78: const char **, size_t *);
1.2 kristaps 79: static int html_end(struct md_mbuf *,
80: const struct md_args *);
1.7 kristaps 81: static int html_blocktagname(struct md_mbuf *,
1.10 kristaps 82: const struct md_args *, int,
83: struct htmlq *, const int *,
84: const char **, size_t *);
1.7 kristaps 85: static int html_blocktagargs(struct md_mbuf *,
1.2 kristaps 86: const struct md_args *, int,
1.7 kristaps 87: const int *, const char **, size_t *);
1.10 kristaps 88: static int html_headtagname(struct md_mbuf *,
89: const struct md_args *, int,
90: struct htmlq *, const int *,
91: const char **, size_t *);
92: static int html_headtagargs(struct md_mbuf *,
1.3 kristaps 93: const struct md_args *, int,
1.7 kristaps 94: const int *, const char **, size_t *);
1.12 kristaps 95: static int html_bodytagname(struct md_mbuf *,
1.10 kristaps 96: const struct md_args *,
97: int, struct htmlq *, const int *,
98: const char **, size_t *);
1.12 kristaps 99: static int html_bodytagargs(struct md_mbuf *,
1.3 kristaps 100: const struct md_args *, int,
1.7 kristaps 101: const int *, const char **, size_t *);
102: static int html_inlinetagname(struct md_mbuf *,
103: const struct md_args *, int, size_t *);
104: static int html_inlinetagargs(struct md_mbuf *,
1.2 kristaps 105: const struct md_args *, int,
1.7 kristaps 106: const int *, const char **, size_t *);
1.10 kristaps 107: static int html_Bl_bodytagname(struct md_mbuf *,
108: struct htmlq *, const int *,
109: const char **, size_t *);
110: static int html_It_blocktagname(struct md_mbuf *,
111: struct htmlq *, const int *,
112: const char **, size_t *);
113: static int html_It_headtagname(struct md_mbuf *,
114: struct htmlq *, const int *,
115: const char **, size_t *);
116: static int html_It_bodytagname(struct md_mbuf *,
117: struct htmlq *, const int *,
118: const char **, size_t *);
1.19 kristaps 119: static int html_tputln(struct md_mbuf *,
120: enum ml_scope, int, enum html_tag);
121: static int html_aputln(struct md_mbuf *, enum ml_scope,
122: int, enum html_tag,
123: int, const struct html_pair *);
1.10 kristaps 124:
125:
126: /* ARGSUSED */
127: static int
128: html_It_headtagname(struct md_mbuf *mbuf, struct htmlq *q,
129: const int *argc, const char **argv, size_t *res)
130: {
131: struct htmlnode *n;
1.11 kristaps 132: int i;
1.10 kristaps 133:
134: for (n = q->last; n; n = n->parent)
135: if (n->tok == ROFF_Bl)
136: break;
137:
138: assert(n);
1.13 kristaps 139:
140: /* LINTED */
1.11 kristaps 141: for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10 kristaps 142: i < ROFF_MAXLINEARG; i++) {
143: switch (n->argc[i]) {
1.14 kristaps 144: case (ROFF_Ohang):
1.19 kristaps 145: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10 kristaps 146: case (ROFF_Tag):
147: /* FALLTHROUGH */
148: case (ROFF_Column):
1.19 kristaps 149: return(html_stput(mbuf, HTML_TAG_TD, res));
1.10 kristaps 150: default:
151: break;
152: }
153: }
154:
1.16 kristaps 155: return(0);
1.10 kristaps 156: }
157:
158:
159: /* ARGSUSED */
160: static int
161: html_It_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
162: const int *argc, const char **argv, size_t *res)
163: {
164: struct htmlnode *n;
1.11 kristaps 165: int i;
1.10 kristaps 166:
167: for (n = q->last; n; n = n->parent)
168: if (n->tok == ROFF_Bl)
169: break;
170:
171: assert(n);
1.13 kristaps 172:
173: /* LINTED */
1.11 kristaps 174: for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10 kristaps 175: i < ROFF_MAXLINEARG; i++) {
176: switch (n->argc[i]) {
177: case (ROFF_Enum):
178: /* FALLTHROUGH */
179: case (ROFF_Bullet):
180: /* FALLTHROUGH */
181: case (ROFF_Dash):
182: /* FALLTHROUGH */
183: case (ROFF_Hyphen):
184: /* FALLTHROUGH */
185: case (ROFF_Item):
186: /* FALLTHROUGH */
187: case (ROFF_Diag):
188: /* FALLTHROUGH */
189: case (ROFF_Hang):
190: /* FALLTHROUGH */
191: case (ROFF_Ohang):
192: /* FALLTHROUGH */
193: case (ROFF_Inset):
1.19 kristaps 194: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10 kristaps 195: case (ROFF_Tag):
196: /* FALLTHROUGH */
197: case (ROFF_Column):
1.19 kristaps 198: return(html_stput(mbuf, HTML_TAG_TD, res));
1.10 kristaps 199: default:
200: break;
201: }
202: }
203:
204: assert(i != ROFF_MAXLINEARG);
1.16 kristaps 205: return(0);
1.10 kristaps 206: }
207:
208:
209: /* ARGSUSED */
210: static int
211: html_Bl_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
212: const int *argc, const char **argv, size_t *res)
213: {
1.11 kristaps 214: int i;
1.10 kristaps 215:
1.11 kristaps 216: for (i = 0; ROFF_ARGMAX != argc[i]
1.10 kristaps 217: && i < ROFF_MAXLINEARG; i++) {
218: switch (argc[i]) {
219: case (ROFF_Enum):
1.19 kristaps 220: return(html_stput(mbuf, HTML_TAG_OL, res));
1.10 kristaps 221: case (ROFF_Bullet):
222: /* FALLTHROUGH */
223: case (ROFF_Dash):
224: /* FALLTHROUGH */
225: case (ROFF_Hyphen):
226: /* FALLTHROUGH */
227: case (ROFF_Item):
228: /* FALLTHROUGH */
229: case (ROFF_Diag):
230: /* FALLTHROUGH */
231: case (ROFF_Hang):
232: /* FALLTHROUGH */
233: case (ROFF_Ohang):
234: /* FALLTHROUGH */
235: case (ROFF_Inset):
1.19 kristaps 236: return(html_stput(mbuf, HTML_TAG_UL, res));
1.10 kristaps 237: case (ROFF_Tag):
238: /* FALLTHROUGH */
239: case (ROFF_Column):
1.19 kristaps 240: return(html_stput(mbuf, HTML_TAG_TABLE, res));
1.10 kristaps 241: default:
242: break;
243: }
244: }
245:
246: assert(i != ROFF_MAXLINEARG);
1.16 kristaps 247: return(0);
1.10 kristaps 248: }
249:
250:
251: /* ARGSUSED */
252: static int
253: html_It_blocktagname(struct md_mbuf *mbuf, struct htmlq *q,
254: const int *argc, const char **argv, size_t *res)
255: {
256: struct htmlnode *n;
1.11 kristaps 257: int i;
1.10 kristaps 258:
259: for (n = q->last; n; n = n->parent)
260: if (n->tok == ROFF_Bl)
261: break;
262:
263: assert(n);
1.13 kristaps 264:
265: /* LINTED */
1.11 kristaps 266: for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10 kristaps 267: i < ROFF_MAXLINEARG; i++) {
268: switch (n->argc[i]) {
269: case (ROFF_Enum):
270: /* FALLTHROUGH */
271: case (ROFF_Bullet):
272: /* FALLTHROUGH */
273: case (ROFF_Dash):
274: /* FALLTHROUGH */
275: case (ROFF_Hyphen):
276: /* FALLTHROUGH */
277: case (ROFF_Item):
278: /* FALLTHROUGH */
279: case (ROFF_Diag):
280: /* FALLTHROUGH */
281: case (ROFF_Hang):
282: /* FALLTHROUGH */
283: case (ROFF_Ohang):
284: /* FALLTHROUGH */
285: case (ROFF_Inset):
1.19 kristaps 286: return(html_stput(mbuf, HTML_TAG_LI, res));
1.10 kristaps 287: case (ROFF_Tag):
288: /* FALLTHROUGH */
289: case (ROFF_Column):
1.19 kristaps 290: return(html_stput(mbuf, HTML_TAG_TR, res));
1.10 kristaps 291: default:
292: break;
293: }
294: }
295:
296: assert(i != ROFF_MAXLINEARG);
1.16 kristaps 297: return(0);
1.10 kristaps 298: }
1.2 kristaps 299:
300:
1.4 kristaps 301: static int
302: html_loadcss(struct md_mbuf *mbuf, const char *css)
303: {
304: size_t res, bufsz;
305: char *buf;
306: struct stat st;
307: int fd, c;
308: ssize_t ssz;
309:
310: c = 0;
311: res = 0;
312: buf = NULL;
313:
314: if (-1 == (fd = open(css, O_RDONLY, 0))) {
315: warn("%s", css);
316: return(0);
317: }
318:
319: if (-1 == fstat(fd, &st)) {
320: warn("%s", css);
321: goto out;
322: }
323:
324: bufsz = MAX(st.st_blksize, BUFSIZ);
325: if (NULL == (buf = malloc(bufsz))) {
326: warn("malloc");
327: goto out;
328: }
329:
330: for (;;) {
331: if (-1 == (ssz = read(fd, buf, bufsz))) {
332: warn("%s", css);
333: goto out;
334: } else if (0 == ssz)
335: break;
336: if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
337: goto out;
338: }
339:
340: c = 1;
341:
342: out:
343: if (-1 == close(fd)) {
344: warn("%s", css);
345: c = 0;
346: }
347:
348: if (buf)
349: free(buf);
350:
351: return(c);
352: }
353:
354:
1.18 kristaps 355: static int
1.19 kristaps 356: html_tputln(struct md_mbuf *mbuf, enum ml_scope scope,
357: int i, enum html_tag tag)
1.18 kristaps 358: {
359:
1.19 kristaps 360: if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18 kristaps 361: return(0);
1.19 kristaps 362: if ( ! html_tput(mbuf, scope, tag, NULL))
1.18 kristaps 363: return(0);
1.19 kristaps 364: return(ml_nputs(mbuf, "\n", 1, NULL));
1.18 kristaps 365: }
366:
367:
368: static int
1.19 kristaps 369: html_aputln(struct md_mbuf *mbuf, enum ml_scope scope, int i,
370: enum html_tag tag, int sz, const struct html_pair *p)
1.18 kristaps 371: {
372:
1.19 kristaps 373: if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18 kristaps 374: return(0);
1.19 kristaps 375: if ( ! html_aput(mbuf, scope, tag, NULL, sz, p))
376: return(0);
377: return(ml_nputs(mbuf, "\n", 1, NULL));
1.18 kristaps 378: }
379:
380:
1.3 kristaps 381: /* ARGSUSED */
1.2 kristaps 382: static int
1.4 kristaps 383: html_begin(struct md_mbuf *mbuf, const struct md_args *args,
384: const struct tm *tm, const char *os,
1.19 kristaps 385: const char *name, enum roffmsec msec, const char *vol)
1.2 kristaps 386: {
1.19 kristaps 387: struct html_pair attr[4];
388: char ts[32];
389: int i;
1.2 kristaps 390:
1.19 kristaps 391: (void)snprintf(ts, sizeof(ts), "%s(%s)",
392: name, roff_msecname(msec));
1.4 kristaps 393:
1.18 kristaps 394: i = 0;
1.4 kristaps 395:
1.19 kristaps 396: if ( ! html_typeput(mbuf, HTML_TYPE_4_01_STRICT, NULL))
1.17 kristaps 397: return(0);
1.19 kristaps 398: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_HTML))
1.17 kristaps 399: return(0);
1.19 kristaps 400: if ( ! html_tputln(mbuf, ML_OPEN, i++, HTML_TAG_HEAD))
1.17 kristaps 401: return(0);
1.19 kristaps 402:
403: attr[0].attr = HTML_ATTR_HTTP_EQUIV;
404: attr[0].val = "content-type";
405: attr[1].attr = HTML_ATTR_CONTENT;
406: attr[1].val = "text/html;charset=utf-8";
407:
408: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17 kristaps 409: return(0);
1.19 kristaps 410:
411: attr[0].attr = HTML_ATTR_NAME;
412: attr[0].val = "resource-type";
413: attr[1].attr = HTML_ATTR_CONTENT;
414: attr[1].val = "document";
415:
416: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17 kristaps 417: return(0);
1.19 kristaps 418:
419: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TITLE))
1.17 kristaps 420: return(0);
1.19 kristaps 421: if ( ! ml_putstring(mbuf, ts, NULL))
1.17 kristaps 422: return(0);
1.19 kristaps 423: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TITLE))
1.2 kristaps 424: return(0);
1.4 kristaps 425:
426: if (HTML_CSS_EMBED & args->params.html.flags) {
1.19 kristaps 427: attr[0].attr = HTML_ATTR_TYPE;
428: attr[0].val = "text/css";
429:
430: if ( ! html_aputln(mbuf, ML_OPEN, i,
431: HTML_TAG_STYLE, 1, attr))
1.4 kristaps 432: return(0);
1.19 kristaps 433: if ( ! html_commentput(mbuf, ML_OPEN, NULL))
434: return(NULL);
435:
1.4 kristaps 436: if ( ! html_loadcss(mbuf, args->params.html.css))
437: return(0);
1.19 kristaps 438:
439: if ( ! html_commentput(mbuf, ML_CLOSE, NULL))
440: return(NULL);
441: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_STYLE))
1.4 kristaps 442: return(0);
1.19 kristaps 443: } else {
444: attr[0].attr = HTML_ATTR_REL;
445: attr[0].val = "stylesheet";
446: attr[1].attr = HTML_ATTR_TYPE;
447: attr[1].val = "text/css";
448: attr[2].attr = HTML_ATTR_HREF;
449: attr[2].val = args->params.html.css;
450:
451: if ( ! html_aputln(mbuf, ML_OPEN, i,
452: HTML_TAG_LINK, 3, attr))
453: return(0);
454: }
1.4 kristaps 455:
1.19 kristaps 456: if ( ! html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_HEAD))
1.18 kristaps 457: return(0);
1.19 kristaps 458: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_BODY))
1.18 kristaps 459: return(0);
1.19 kristaps 460:
461: attr[0].attr = HTML_ATTR_CLASS;
462: attr[0].val = "mdoc";
463:
464: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_DIV, 1, attr))
1.18 kristaps 465: return(0);
1.19 kristaps 466:
467: attr[0].attr = HTML_ATTR_WIDTH;
468: attr[0].val = "100%";
469:
470: if ( ! html_aputln(mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 1, attr))
1.18 kristaps 471: return(0);
1.19 kristaps 472: if ( ! html_tputln(mbuf, ML_OPEN, i++, HTML_TAG_TR))
1.18 kristaps 473: return(0);
1.19 kristaps 474:
475: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TD))
1.2 kristaps 476: return(0);
1.19 kristaps 477: if ( ! ml_putstring(mbuf, ts, NULL))
1.18 kristaps 478: return(0);
1.19 kristaps 479: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18 kristaps 480: return(0);
1.19 kristaps 481:
482: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TD))
1.18 kristaps 483: return(0);
1.19 kristaps 484: /* TODO: middle. */
485: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18 kristaps 486: return(0);
1.19 kristaps 487:
1.20 ! kristaps 488: attr[0].attr = HTML_ATTR_ALIGN;
! 489: attr[0].val = "right";
! 490:
! 491: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_TD, 1, attr))
1.18 kristaps 492: return(0);
1.19 kristaps 493: if ( ! ml_putstring(mbuf, ts, NULL))
1.17 kristaps 494: return(0);
1.19 kristaps 495: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.17 kristaps 496: return(0);
1.19 kristaps 497:
498: if ( ! html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_TR))
1.17 kristaps 499: return(0);
1.19 kristaps 500: return(html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_TABLE));
1.2 kristaps 501: }
502:
503:
1.3 kristaps 504: /* ARGSUSED */
1.2 kristaps 505: static int
506: html_end(struct md_mbuf *mbuf, const struct md_args *args)
507: {
508:
1.19 kristaps 509: if ( ! html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_DIV))
1.18 kristaps 510: return(0);
1.19 kristaps 511: if ( ! html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_BODY))
1.18 kristaps 512: return(0);
1.19 kristaps 513: return(html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_HTML));
1.2 kristaps 514: }
515:
516:
1.3 kristaps 517: /* ARGSUSED */
1.7 kristaps 518: static int
1.12 kristaps 519: html_bodytagname(struct md_mbuf *mbuf,
1.10 kristaps 520: const struct md_args *args, int tok, struct htmlq *q,
521: const int *argc, const char **argv, size_t *res)
1.2 kristaps 522: {
1.3 kristaps 523:
1.10 kristaps 524: switch (tok) {
525: case (ROFF_Bl):
526: return(html_Bl_bodytagname(mbuf, q, argc, argv, res));
1.12 kristaps 527: case (ROFF_Fo):
1.19 kristaps 528: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 529: case (ROFF_It):
530: return(html_It_bodytagname(mbuf, q, argc, argv, res));
1.12 kristaps 531: case (ROFF_Oo):
1.19 kristaps 532: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 533: default:
534: break;
535: }
536:
1.19 kristaps 537: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3 kristaps 538: }
539:
540:
541: /* ARGSUSED */
1.7 kristaps 542: static int
1.10 kristaps 543: html_headtagname(struct md_mbuf *mbuf,
544: const struct md_args *args, int tok, struct htmlq *q,
545: const int *argc, const char **argv, size_t *res)
1.3 kristaps 546: {
547:
1.10 kristaps 548: switch (tok) {
549: case (ROFF_It):
550: return(html_It_headtagname(mbuf, q, argc, argv, res));
1.12 kristaps 551: case (ROFF_Fo):
1.19 kristaps 552: /* FALLTHROUGH */
1.12 kristaps 553: case (ROFF_Oo):
1.19 kristaps 554: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 555: case (ROFF_Sh):
1.19 kristaps 556: return(html_stput(mbuf, HTML_TAG_H1, res));
1.10 kristaps 557: case (ROFF_Ss):
1.19 kristaps 558: return(html_stput(mbuf, HTML_TAG_H2, res));
1.10 kristaps 559: default:
560: break;
561: }
562:
1.19 kristaps 563: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3 kristaps 564: }
565:
566:
567: /* ARGSUSED */
1.7 kristaps 568: static int
1.10 kristaps 569: html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args,
570: int tok, struct htmlq *q, const int *argc,
571: const char **argv, size_t *res)
1.3 kristaps 572: {
573:
1.10 kristaps 574: switch (tok) {
1.12 kristaps 575: case (ROFF_Fo):
1.19 kristaps 576: /* FALLTHROUGH */
1.12 kristaps 577: case (ROFF_Oo):
1.19 kristaps 578: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 579: case (ROFF_It):
580: return(html_It_blocktagname(mbuf, q, argc, argv, res));
581: default:
582: break;
583: }
584:
1.19 kristaps 585: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3 kristaps 586: }
587:
588:
1.9 kristaps 589: /* ARGSUSED */
1.7 kristaps 590: static int
591: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
592: const int *argc, const char **argv, size_t *res)
1.3 kristaps 593: {
594:
1.19 kristaps 595: /* FIXME: use API in ml.h. */
596:
1.7 kristaps 597: if ( ! ml_puts(mbuf, " class=\"", res))
598: return(0);
599: if ( ! ml_puts(mbuf, ns, res))
600: return(0);
601: if ( ! ml_puts(mbuf, "-", res))
1.3 kristaps 602: return(0);
1.7 kristaps 603: if ( ! ml_puts(mbuf, toknames[tok], res))
1.3 kristaps 604: return(0);
1.9 kristaps 605: return(ml_puts(mbuf, "\"", res));
1.3 kristaps 606: }
607:
608:
609: /* ARGSUSED */
1.7 kristaps 610: static int
1.10 kristaps 611: html_headtagargs(struct md_mbuf *mbuf,
1.7 kristaps 612: const struct md_args *args, int tok,
613: const int *argc, const char **argv, size_t *res)
1.3 kristaps 614: {
615:
1.7 kristaps 616: return(html_printargs(mbuf, tok, "head", argc, argv, res));
617: }
1.3 kristaps 618:
619:
1.7 kristaps 620: /* ARGSUSED */
621: static int
1.12 kristaps 622: html_bodytagargs(struct md_mbuf *mbuf,
1.7 kristaps 623: const struct md_args *args, int tok,
624: const int *argc, const char **argv, size_t *res)
625: {
1.3 kristaps 626:
1.7 kristaps 627: return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2 kristaps 628: }
629:
630:
631: /* ARGSUSED */
1.7 kristaps 632: static int
633: html_blocktagargs(struct md_mbuf *mbuf,
634: const struct md_args *args, int tok,
635: const int *argc, const char **argv, size_t *res)
1.2 kristaps 636: {
1.3 kristaps 637:
1.7 kristaps 638: return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2 kristaps 639: }
1.1 kristaps 640:
641:
642: /* ARGSUSED */
1.7 kristaps 643: static int
644: html_inlinetagargs(struct md_mbuf *mbuf,
645: const struct md_args *args, int tok,
646: const int *argc, const char **argv, size_t *res)
1.2 kristaps 647: {
648:
1.12 kristaps 649: if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res))
650: return(0);
651:
652: switch (tok) {
653: case (ROFF_Sx):
1.19 kristaps 654:
655: /* FIXME: use API in ml.h. */
656:
1.12 kristaps 657: assert(*argv);
658: if ( ! ml_nputs(mbuf, " href=\"#", 8, res))
659: return(0);
660: if ( ! ml_putstring(mbuf, *argv, res))
661: return(0);
662: if ( ! ml_nputs(mbuf, "\"", 1, res))
663: return(0);
1.13 kristaps 664: break;
1.12 kristaps 665: default:
666: break;
667: }
668:
669: return(1);
1.2 kristaps 670: }
671:
672:
1.3 kristaps 673: /* ARGSUSED */
1.7 kristaps 674: static int
1.2 kristaps 675: html_inlinetagname(struct md_mbuf *mbuf,
1.7 kristaps 676: const struct md_args *args, int tok, size_t *res)
1.2 kristaps 677: {
678:
679: switch (tok) {
1.4 kristaps 680: case (ROFF_Pp):
1.19 kristaps 681: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.12 kristaps 682: case (ROFF_Sx):
1.19 kristaps 683: return(html_stput(mbuf, HTML_TAG_A, res));
1.2 kristaps 684: default:
1.9 kristaps 685: break;
1.2 kristaps 686: }
1.9 kristaps 687:
1.19 kristaps 688: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.2 kristaps 689: }
690:
691:
692: static ssize_t
1.8 kristaps 693: html_begintag(struct md_mbuf *mbuf, void *data,
694: const struct md_args *args, enum md_ns ns,
695: int tok, const int *argc, const char **argv)
1.2 kristaps 696: {
1.7 kristaps 697: size_t res;
1.8 kristaps 698: struct htmlq *q;
699: struct htmlnode *node;
1.11 kristaps 700: int i;
1.2 kristaps 701:
702: assert(ns != MD_NS_DEFAULT);
1.7 kristaps 703: res = 0;
704:
1.8 kristaps 705: assert(data);
706: q = (struct htmlq *)data;
707:
708: if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
709: warn("calloc");
710: return(-1);
711: }
712:
713: node->parent = q->last;
714: node->tok = tok;
715: node->ns = ns;
716:
1.10 kristaps 717: if (argc) {
718: /* TODO: argv. */
719:
720: assert(argv);
1.13 kristaps 721: /* LINTED */
1.11 kristaps 722: for (i = 0; ROFF_ARGMAX != argc[i]
1.10 kristaps 723: && i < ROFF_MAXLINEARG; i++)
724: node->argc[i] = argc[i];
725: assert(i != ROFF_MAXLINEARG);
1.12 kristaps 726: }
1.10 kristaps 727:
728:
1.8 kristaps 729: q->last = node;
730:
1.3 kristaps 731: switch (ns) {
732: case (MD_NS_BLOCK):
1.10 kristaps 733: if ( ! html_blocktagname(mbuf, args, tok,
734: q, argc, argv, &res))
1.7 kristaps 735: return(-1);
736: if ( ! html_blocktagargs(mbuf, args, tok,
737: argc, argv, &res))
738: return(-1);
739: break;
1.3 kristaps 740: case (MD_NS_BODY):
1.12 kristaps 741: if ( ! html_bodytagname(mbuf, args, tok,
1.10 kristaps 742: q, argc, argv, &res))
1.7 kristaps 743: return(-1);
1.12 kristaps 744: if ( ! html_bodytagargs(mbuf, args, tok,
1.7 kristaps 745: argc, argv, &res))
746: return(-1);
747: break;
1.3 kristaps 748: case (MD_NS_HEAD):
1.10 kristaps 749: if ( ! html_headtagname(mbuf, args, tok, q,
750: argc, argv, &res))
1.7 kristaps 751: return(-1);
1.10 kristaps 752: if ( ! html_headtagargs(mbuf, args, tok,
1.7 kristaps 753: argc, argv, &res))
754: return(-1);
755: break;
1.3 kristaps 756: default:
1.7 kristaps 757: if ( ! html_inlinetagname(mbuf, args, tok, &res))
758: return(-1);
759: if ( ! html_inlinetagargs(mbuf, args, tok,
760: argc, argv, &res))
761: return(-1);
1.3 kristaps 762: break;
1.2 kristaps 763: }
764:
1.7 kristaps 765: return((ssize_t)res);
1.2 kristaps 766: }
767:
768:
769: static ssize_t
1.8 kristaps 770: html_endtag(struct md_mbuf *mbuf, void *data,
771: const struct md_args *args, enum md_ns ns, int tok)
1.2 kristaps 772: {
1.7 kristaps 773: size_t res;
1.8 kristaps 774: struct htmlq *q;
775: struct htmlnode *node;
1.2 kristaps 776:
777: assert(ns != MD_NS_DEFAULT);
1.7 kristaps 778: res = 0;
779:
1.8 kristaps 780: assert(data);
781: q = (struct htmlq *)data;
1.10 kristaps 782: node = q->last;
1.8 kristaps 783:
1.3 kristaps 784: switch (ns) {
785: case (MD_NS_BLOCK):
1.10 kristaps 786: if ( ! html_blocktagname(mbuf, args, tok,
787: q, node->argc,
788: (const char **)node->argv, &res))
1.7 kristaps 789: return(-1);
790: break;
1.3 kristaps 791: case (MD_NS_BODY):
1.12 kristaps 792: if ( ! html_bodytagname(mbuf, args, tok,
1.10 kristaps 793: q, node->argc,
794: (const char **)node->argv, &res))
1.7 kristaps 795: return(-1);
796: break;
1.3 kristaps 797: case (MD_NS_HEAD):
1.10 kristaps 798: if ( ! html_headtagname(mbuf, args, tok,
799: q, node->argc,
800: (const char **)node->argv, &res))
1.7 kristaps 801: return(-1);
802: break;
1.3 kristaps 803: default:
1.7 kristaps 804: if ( ! html_inlinetagname(mbuf, args, tok, &res))
805: return(-1);
1.3 kristaps 806: break;
807: }
1.2 kristaps 808:
1.8 kristaps 809: q->last = node->parent;
810:
1.9 kristaps 811: free(node);
1.8 kristaps 812:
1.7 kristaps 813: return((ssize_t)res);
1.2 kristaps 814: }
815:
816:
1.9 kristaps 817: static int
818: html_alloc(void **p)
819: {
820:
821: if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
822: warn("calloc");
823: return(0);
824: }
825: return(1);
826: }
827:
828:
829: static void
830: html_free(void *p)
831: {
832: struct htmlq *q;
833: struct htmlnode *n;
834:
835: assert(p);
836: q = (struct htmlq *)p;
837:
1.13 kristaps 838: /* LINTED */
1.9 kristaps 839: while ((n = q->last)) {
840: q->last = n->parent;
841: free(n);
842: }
843:
844: free(q);
845: }
846:
847:
1.14 kristaps 848: static ssize_t
849: html_beginhttp(struct md_mbuf *mbuf,
850: const struct md_args *args,
851: const char *buf, size_t sz)
852: {
853: size_t res;
1.19 kristaps 854: struct html_pair pair;
1.14 kristaps 855:
856: res = 0;
1.19 kristaps 857: pair.attr = HTML_ATTR_HREF;
858: pair.val = (char *)buf;
1.14 kristaps 859:
1.19 kristaps 860: if ( ! html_aput(mbuf, ML_OPEN, HTML_TAG_A, &res, 1, &pair))
1.14 kristaps 861: return(-1);
862: return((ssize_t)res);
863: }
864:
865:
866: static ssize_t
867: html_endhttp(struct md_mbuf *mbuf,
868: const struct md_args *args,
869: const char *buf, size_t sz)
870: {
871: size_t res;
872:
873: res = 0;
1.19 kristaps 874: if ( ! html_tput(mbuf, ML_CLOSE, HTML_TAG_A, &res))
1.14 kristaps 875: return(-1);
876: return((ssize_t)res);
877: }
878:
879:
880: /* ARGSUSED */
881: static ssize_t
882: html_beginstring(struct md_mbuf *mbuf,
883: const struct md_args *args,
884: const char *buf, size_t sz)
885: {
886:
887: if (0 == strncmp(buf, "http://", 7))
888: return(html_beginhttp(mbuf, args, buf, sz));
889:
890: return(0);
891: }
892:
893:
894: /* ARGSUSED */
895: static ssize_t
896: html_endstring(struct md_mbuf *mbuf,
897: const struct md_args *args,
898: const char *buf, size_t sz)
899: {
900:
901: if (0 == strncmp(buf, "http://", 7))
902: return(html_endhttp(mbuf, args, buf, sz));
903:
904: return(0);
905: }
906:
907:
1.1 kristaps 908: int
909: md_line_html(void *data, char *buf)
910: {
911:
1.2 kristaps 912: return(mlg_line((struct md_mlg *)data, buf));
1.1 kristaps 913: }
914:
915:
916: int
917: md_exit_html(void *data, int flush)
918: {
919:
1.2 kristaps 920: return(mlg_exit((struct md_mlg *)data, flush));
1.1 kristaps 921: }
922:
923:
924: void *
925: md_init_html(const struct md_args *args,
926: struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
927: {
1.9 kristaps 928: struct ml_cbs cbs;
1.8 kristaps 929:
1.9 kristaps 930: cbs.ml_alloc = html_alloc;
931: cbs.ml_free = html_free;
932: cbs.ml_begintag = html_begintag;
933: cbs.ml_endtag = html_endtag;
934: cbs.ml_begin = html_begin;
935: cbs.ml_end = html_end;
1.14 kristaps 936: cbs.ml_beginstring = html_beginstring;
937: cbs.ml_endstring = html_endstring;
1.1 kristaps 938:
1.9 kristaps 939: return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1 kristaps 940: }
CVSweb