]> git.cameronkatri.com Git - mandoc.git/blob - man_html.c
SS, SH, PP, P, LP, br, sp tags in -man -Thtml.
[mandoc.git] / man_html.c
1 /* $Id: man_html.c,v 1.4 2009/10/04 09:35:26 kristaps Exp $ */
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
20 #include <err.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "html.h"
26 #include "man.h"
27
28 #define INDENT 7
29 #define HALFINDENT 3
30
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);
42 static void print_man_nodelist(MAN_ARGS);
43 static void print_man_node(MAN_ARGS);
44
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
56
57 static const struct htmlman mans[MAN_MAX] = {
58 { man_br_pre, NULL }, /* br */
59 { NULL, NULL }, /* TH */
60 { man_SH_pre, NULL }, /* SH */
61 { man_SS_pre, NULL }, /* SS */
62 { NULL, NULL }, /* TP */
63 { man_PP_pre, NULL }, /* LP */
64 { man_PP_pre, NULL }, /* PP */
65 { man_PP_pre, NULL }, /* P */
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 */
81 { man_br_pre, NULL }, /* sp */
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
91
92 void
93 html_man(void *arg, const struct man *m)
94 {
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
126 print_man_nodelist(m, n, h);
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);
143 }
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 }