Annotation of mandoc/html.c, Revision 1.5
1.5 ! kristaps 1: /* $Id: html.c,v 1.4 2008/12/04 11:25:29 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:
30: #include "libmdocml.h"
31: #include "private.h"
1.2 kristaps 32: #include "ml.h"
33:
34:
1.4 kristaps 35: static int html_loadcss(struct md_mbuf *, const char *);
36:
1.2 kristaps 37: static ssize_t html_endtag(struct md_mbuf *,
38: const struct md_args *,
39: enum md_ns, int);
40: static ssize_t html_begintag(struct md_mbuf *,
41: const struct md_args *,
42: enum md_ns, int,
43: const int *, const char **);
1.4 kristaps 44: static int html_begin(struct md_mbuf *,
45: const struct md_args *,
46: const struct tm *,
47: const char *, const char *,
48: const char *, const char *);
1.2 kristaps 49: static int html_end(struct md_mbuf *,
50: const struct md_args *);
51: static ssize_t html_blocktagname(struct md_mbuf *,
52: const struct md_args *, int);
53: static ssize_t html_blocktagargs(struct md_mbuf *,
54: const struct md_args *, int,
55: const int *, const char **);
1.3 kristaps 56: static ssize_t html_blockheadtagname(struct md_mbuf *,
57: const struct md_args *, int);
58: static ssize_t html_blockheadtagargs(struct md_mbuf *,
59: const struct md_args *, int,
60: const int *, const char **);
61: static ssize_t html_blockbodytagname(struct md_mbuf *,
62: const struct md_args *, int);
63: static ssize_t html_blockbodytagargs(struct md_mbuf *,
64: const struct md_args *, int,
65: const int *, const char **);
1.2 kristaps 66: static ssize_t html_inlinetagname(struct md_mbuf *,
67: const struct md_args *, int);
68: static ssize_t html_inlinetagargs(struct md_mbuf *,
69: const struct md_args *, int,
70: const int *, const char **);
71:
72:
1.4 kristaps 73: static int
74: html_loadcss(struct md_mbuf *mbuf, const char *css)
75: {
76: size_t res, bufsz;
77: char *buf;
78: struct stat st;
79: int fd, c;
80: ssize_t ssz;
81:
82: c = 0;
83: res = 0;
84: buf = NULL;
85:
86: if (-1 == (fd = open(css, O_RDONLY, 0))) {
87: warn("%s", css);
88: return(0);
89: }
90:
91: if (-1 == fstat(fd, &st)) {
92: warn("%s", css);
93: goto out;
94: }
95:
96: bufsz = MAX(st.st_blksize, BUFSIZ);
97: if (NULL == (buf = malloc(bufsz))) {
98: warn("malloc");
99: goto out;
100: }
101:
102: for (;;) {
103: if (-1 == (ssz = read(fd, buf, bufsz))) {
104: warn("%s", css);
105: goto out;
106: } else if (0 == ssz)
107: break;
108: if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
109: goto out;
110: }
111:
112: c = 1;
113:
114: out:
115: if (-1 == close(fd)) {
116: warn("%s", css);
117: c = 0;
118: }
119:
120: if (buf)
121: free(buf);
122:
123: return(c);
124: }
125:
126:
1.3 kristaps 127: /* ARGSUSED */
1.2 kristaps 128: static int
1.4 kristaps 129: html_begin(struct md_mbuf *mbuf, const struct md_args *args,
130: const struct tm *tm, const char *os,
131: const char *title, const char *section,
132: const char *vol)
1.2 kristaps 133: {
1.4 kristaps 134: const char *preamble, *css, *trail;
135: char buf[512];
1.2 kristaps 136: size_t res;
137:
1.4 kristaps 138: preamble =
139: "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n"
140: " \"http://www.w3.org/TR/html4/strict.dtd\">\n"
141: "<html>\n"
142: "<head>\n"
143: " <meta http-equiv=\"Content-Type\"\n"
144: " content=\"text/html;charset=utf-8\">\n"
145: " <meta name=\"resource-type\" content=\"document\">\n"
146: " <title>Manual Page for %s(%s)</title>\n";
147:
148: css =
149: " <link rel=\"stylesheet\" type=\"text/css\"\n"
150: " href=\"%s\">\n";
151: trail =
152: "</head>\n"
153: "<body>\n"
154: "<div class=\"mdoc\">\n";
155:
1.2 kristaps 156: res = 0;
1.4 kristaps 157:
158: (void)snprintf(buf, sizeof(buf) - 1,
159: preamble, title, section);
160:
161: if ( ! ml_puts(mbuf, buf, &res))
1.2 kristaps 162: return(0);
1.4 kristaps 163:
164: assert(args->params.html.css);
165: if (HTML_CSS_EMBED & args->params.html.flags) {
1.5 ! kristaps 166: if ( ! ml_puts(mbuf, " <style type=\"text/css\"><!--\n", &res))
1.4 kristaps 167: return(0);
168: if ( ! html_loadcss(mbuf, args->params.html.css))
169: return(0);
170: if ( ! ml_puts(mbuf, " --!></style>\n", &res))
171: return(0);
172: } else {
173: (void)snprintf(buf, sizeof(buf) - 1, css,
174: args->params.html.css);
175: if ( ! ml_puts(mbuf, buf, &res))
176: return(0);
177: }
178:
179: if ( ! ml_puts(mbuf, trail, &res))
1.2 kristaps 180: return(0);
181:
182: return(1);
183: }
184:
185:
1.3 kristaps 186: /* ARGSUSED */
1.2 kristaps 187: static int
188: html_end(struct md_mbuf *mbuf, const struct md_args *args)
189: {
190: size_t res;
191:
192: res = 0;
1.4 kristaps 193: if ( ! ml_puts(mbuf, "</div></body>\n</html>", &res))
1.2 kristaps 194: return(0);
195:
196: return(1);
197: }
198:
199:
1.3 kristaps 200: /* ARGSUSED */
1.2 kristaps 201: static ssize_t
1.3 kristaps 202: html_blockbodytagname(struct md_mbuf *mbuf,
1.2 kristaps 203: const struct md_args *args, int tok)
204: {
205: size_t res;
206:
207: res = 0;
1.4 kristaps 208: if ( ! ml_puts(mbuf, "div", &res))
209: return(-1);
1.3 kristaps 210:
211: return((ssize_t)res);
212: }
213:
214:
215:
216:
217: /* ARGSUSED */
218: static ssize_t
219: html_blockheadtagname(struct md_mbuf *mbuf,
220: const struct md_args *args, int tok)
221: {
222: size_t res;
223:
224: res = 0;
1.4 kristaps 225: if ( ! ml_puts(mbuf, "div", &res))
226: return(-1);
1.3 kristaps 227:
228: return((ssize_t)res);
229: }
230:
231:
232: /* ARGSUSED */
233: static ssize_t
234: html_blocktagname(struct md_mbuf *mbuf,
235: const struct md_args *args, int tok)
236: {
237: size_t res;
238:
239: res = 0;
1.4 kristaps 240: if ( ! ml_puts(mbuf, "div", &res))
241: return(-1);
1.2 kristaps 242:
1.3 kristaps 243: return((ssize_t)res);
244: }
245:
246:
247: /* ARGSUSED */
248: static ssize_t
249: html_blockheadtagargs(struct md_mbuf *mbuf, const struct md_args *args,
250: int tok, const int *argc, const char **argv)
251: {
252: size_t res;
253:
254: res = 0;
255:
1.4 kristaps 256: if ( ! ml_puts(mbuf, " class=\"head-", &res))
1.3 kristaps 257: return(0);
258: if ( ! ml_puts(mbuf, toknames[tok], &res))
259: return(0);
260: if ( ! ml_puts(mbuf, "\"", &res))
261: return(0);
262:
263: switch (tok) {
264: default:
265: break;
266: }
267:
268: return(0);
269: }
270:
271:
272: /* ARGSUSED */
273: static ssize_t
274: html_blockbodytagargs(struct md_mbuf *mbuf, const struct md_args *args,
275: int tok, const int *argc, const char **argv)
276: {
277: size_t res;
278:
279: res = 0;
280:
1.4 kristaps 281: if ( ! ml_puts(mbuf, " class=\"body-", &res))
1.3 kristaps 282: return(0);
283: if ( ! ml_puts(mbuf, toknames[tok], &res))
284: return(0);
285: if ( ! ml_puts(mbuf, "\"", &res))
286: return(0);
287:
288: switch (tok) {
289: default:
290: break;
291: }
292:
293: return(res);
1.2 kristaps 294: }
295:
296:
297: /* ARGSUSED */
298: static ssize_t
299: html_blocktagargs(struct md_mbuf *mbuf, const struct md_args *args,
300: int tok, const int *argc, const char **argv)
301: {
1.3 kristaps 302: size_t res;
303:
304: res = 0;
305:
1.4 kristaps 306: if ( ! ml_puts(mbuf, " class=\"block-", &res))
1.3 kristaps 307: return(0);
308: if ( ! ml_puts(mbuf, toknames[tok], &res))
309: return(0);
310: if ( ! ml_puts(mbuf, "\"", &res))
311: return(0);
1.2 kristaps 312:
313: switch (tok) {
314: default:
1.3 kristaps 315: break;
1.2 kristaps 316: }
317:
1.3 kristaps 318: return(0);
1.2 kristaps 319: }
1.1 kristaps 320:
321:
322: /* ARGSUSED */
1.2 kristaps 323: static ssize_t
324: html_inlinetagargs(struct md_mbuf *mbuf, const struct md_args *args,
325: int tok, const int *argc, const char **argv)
326: {
1.3 kristaps 327: size_t res;
328:
329: res = 0;
330:
1.4 kristaps 331: if ( ! ml_puts(mbuf, " class=\"inline-", &res))
1.3 kristaps 332: return(0);
333: if ( ! ml_puts(mbuf, toknames[tok], &res))
334: return(0);
335: if ( ! ml_puts(mbuf, "\"", &res))
336: return(0);
337:
1.2 kristaps 338:
339: switch (tok) {
340: default:
1.3 kristaps 341: break;
1.2 kristaps 342: }
343:
1.3 kristaps 344: return(0);
1.2 kristaps 345: }
346:
347:
1.3 kristaps 348: /* ARGSUSED */
1.2 kristaps 349: static ssize_t
350: html_inlinetagname(struct md_mbuf *mbuf,
351: const struct md_args *args, int tok)
352: {
353: size_t res;
354:
355: res = 0;
356:
357: switch (tok) {
1.4 kristaps 358: case (ROFF_Pp):
359: if ( ! ml_puts(mbuf, "div", &res))
360: return(-1);
361: break;
1.2 kristaps 362: default:
363: if ( ! ml_puts(mbuf, "span", &res))
364: return(-1);
365: break;
366: }
367:
368: return((ssize_t)res);
369: }
370:
371:
372: static ssize_t
373: html_begintag(struct md_mbuf *mbuf, const struct md_args *args,
374: enum md_ns ns, int tok,
375: const int *argc, const char **argv)
376: {
377:
378: assert(ns != MD_NS_DEFAULT);
1.3 kristaps 379: switch (ns) {
380: case (MD_NS_BLOCK):
1.2 kristaps 381: if ( ! html_blocktagname(mbuf, args, tok))
382: return(0);
383: return(html_blocktagargs(mbuf, args,
384: tok, argc, argv));
1.3 kristaps 385: case (MD_NS_BODY):
386: if ( ! html_blockbodytagname(mbuf, args, tok))
387: return(0);
388: return(html_blockbodytagargs(mbuf, args,
389: tok, argc, argv));
390: case (MD_NS_HEAD):
391: if ( ! html_blockheadtagname(mbuf, args, tok))
392: return(0);
393: return(html_blockheadtagargs(mbuf, args,
394: tok, argc, argv));
395: default:
396: break;
1.2 kristaps 397: }
398:
399: if ( ! html_inlinetagname(mbuf, args, tok))
400: return(0);
401: return(html_inlinetagargs(mbuf, args, tok, argc, argv));
402: }
403:
404:
405: static ssize_t
406: html_endtag(struct md_mbuf *mbuf, const struct md_args *args,
407: enum md_ns ns, int tok)
408: {
409:
410: assert(ns != MD_NS_DEFAULT);
1.3 kristaps 411: switch (ns) {
412: case (MD_NS_BLOCK):
1.2 kristaps 413: return(html_blocktagname(mbuf, args, tok));
1.3 kristaps 414: case (MD_NS_BODY):
415: return(html_blockbodytagname(mbuf, args, tok));
416: case (MD_NS_HEAD):
417: return(html_blockheadtagname(mbuf, args, tok));
418: default:
419: break;
420: }
1.2 kristaps 421:
422: return(html_inlinetagname(mbuf, args, tok));
423: }
424:
425:
1.1 kristaps 426: int
427: md_line_html(void *data, char *buf)
428: {
429:
1.2 kristaps 430: return(mlg_line((struct md_mlg *)data, buf));
1.1 kristaps 431: }
432:
433:
434: int
435: md_exit_html(void *data, int flush)
436: {
437:
1.2 kristaps 438: return(mlg_exit((struct md_mlg *)data, flush));
1.1 kristaps 439: }
440:
441:
442: void *
443: md_init_html(const struct md_args *args,
444: struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
445: {
446:
1.2 kristaps 447: return(mlg_alloc(args, rbuf, mbuf, html_begintag,
448: html_endtag, html_begin, html_end));
1.1 kristaps 449: }
1.2 kristaps 450:
CVSweb