]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_html.c
Split html.c into html.h, mdoc_html.c, man_html.c.
[mandoc.git] / mdoc_html.c
1 /* $Id: mdoc_html.c,v 1.1 2009/09/21 14:56:57 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 <assert.h>
21 #include <ctype.h>
22 #include <err.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27
28 #include "html.h"
29 #include "mdoc.h"
30
31 #define INDENT 5
32 #define HALFINDENT 3
33
34 #define MDOC_ARGS const struct mdoc_meta *m, \
35 const struct mdoc_node *n, \
36 struct html *h
37 #define MAN_ARGS const struct man_meta *m, \
38 const struct man_node *n, \
39 struct html *h
40
41 struct htmlmdoc {
42 int (*pre)(MDOC_ARGS);
43 void (*post)(MDOC_ARGS);
44 };
45
46 static void print_mdoc(MDOC_ARGS);
47 static void print_mdoc_head(MDOC_ARGS);
48 static void print_mdoc_node(MDOC_ARGS);
49 static void print_mdoc_nodelist(MDOC_ARGS);
50
51 static int a2width(const char *);
52 static int a2offs(const char *);
53 static int a2list(const struct mdoc_node *);
54
55 static void mdoc_root_post(MDOC_ARGS);
56 static int mdoc_root_pre(MDOC_ARGS);
57 static int mdoc_tbl_pre(MDOC_ARGS, int);
58 static int mdoc_tbl_block_pre(MDOC_ARGS, int, int, int, int);
59 static int mdoc_tbl_body_pre(MDOC_ARGS, int, int);
60 static int mdoc_tbl_head_pre(MDOC_ARGS, int, int);
61
62 static int mdoc_ad_pre(MDOC_ARGS);
63 static int mdoc_an_pre(MDOC_ARGS);
64 static void mdoc_aq_post(MDOC_ARGS);
65 static int mdoc_aq_pre(MDOC_ARGS);
66 static int mdoc_ar_pre(MDOC_ARGS);
67 static int mdoc_bd_pre(MDOC_ARGS);
68 static void mdoc_bl_post(MDOC_ARGS);
69 static int mdoc_bl_pre(MDOC_ARGS);
70 static int mdoc_cd_pre(MDOC_ARGS);
71 static int mdoc_d1_pre(MDOC_ARGS);
72 static void mdoc_dq_post(MDOC_ARGS);
73 static int mdoc_dq_pre(MDOC_ARGS);
74 static int mdoc_dv_pre(MDOC_ARGS);
75 static int mdoc_fa_pre(MDOC_ARGS);
76 static int mdoc_fd_pre(MDOC_ARGS);
77 static int mdoc_fl_pre(MDOC_ARGS);
78 static int mdoc_fn_pre(MDOC_ARGS);
79 static int mdoc_ft_pre(MDOC_ARGS);
80 static int mdoc_em_pre(MDOC_ARGS);
81 static int mdoc_er_pre(MDOC_ARGS);
82 static int mdoc_ev_pre(MDOC_ARGS);
83 static int mdoc_ex_pre(MDOC_ARGS);
84 static int mdoc_it_pre(MDOC_ARGS);
85 static int mdoc_nd_pre(MDOC_ARGS);
86 static int mdoc_nm_pre(MDOC_ARGS);
87 static int mdoc_ns_pre(MDOC_ARGS);
88 static void mdoc_op_post(MDOC_ARGS);
89 static int mdoc_op_pre(MDOC_ARGS);
90 static int mdoc_pa_pre(MDOC_ARGS);
91 static void mdoc_pq_post(MDOC_ARGS);
92 static int mdoc_pq_pre(MDOC_ARGS);
93 static void mdoc_qq_post(MDOC_ARGS);
94 static int mdoc_qq_pre(MDOC_ARGS);
95 static int mdoc_sh_pre(MDOC_ARGS);
96 static int mdoc_sp_pre(MDOC_ARGS);
97 static void mdoc_sq_post(MDOC_ARGS);
98 static int mdoc_sq_pre(MDOC_ARGS);
99 static int mdoc_ss_pre(MDOC_ARGS);
100 static int mdoc_sx_pre(MDOC_ARGS);
101 static int mdoc_vt_pre(MDOC_ARGS);
102 static int mdoc_xr_pre(MDOC_ARGS);
103 static int mdoc_xx_pre(MDOC_ARGS);
104
105 #ifdef __linux__
106 extern size_t strlcpy(char *, const char *, size_t);
107 extern size_t strlcat(char *, const char *, size_t);
108 #endif
109
110 static const struct htmlmdoc mdocs[MDOC_MAX] = {
111 {NULL, NULL}, /* Ap */
112 {NULL, NULL}, /* Dd */
113 {NULL, NULL}, /* Dt */
114 {NULL, NULL}, /* Os */
115 {mdoc_sh_pre, NULL }, /* Sh */
116 {mdoc_ss_pre, NULL }, /* Ss */
117 {mdoc_sp_pre, NULL}, /* Pp */
118 {mdoc_d1_pre, NULL}, /* D1 */
119 {mdoc_d1_pre, NULL}, /* Dl */
120 {mdoc_bd_pre, NULL}, /* Bd */
121 {NULL, NULL}, /* Ed */
122 {mdoc_bl_pre, mdoc_bl_post}, /* Bl */
123 {NULL, NULL}, /* El */
124 {mdoc_it_pre, NULL}, /* It */
125 {mdoc_ad_pre, NULL}, /* Ad */
126 {mdoc_an_pre, NULL}, /* An */
127 {mdoc_ar_pre, NULL}, /* Ar */
128 {mdoc_cd_pre, NULL}, /* Cd */
129 {mdoc_fl_pre, NULL}, /* Cm */
130 {mdoc_dv_pre, NULL}, /* Dv */
131 {mdoc_er_pre, NULL}, /* Er */
132 {mdoc_ev_pre, NULL}, /* Ev */
133 {mdoc_ex_pre, NULL}, /* Ex */
134 {mdoc_fa_pre, NULL}, /* Fa */
135 {mdoc_fd_pre, NULL}, /* Fd */
136 {mdoc_fl_pre, NULL}, /* Fl */
137 {mdoc_fn_pre, NULL}, /* Fn */
138 {mdoc_ft_pre, NULL}, /* Ft */
139 {NULL, NULL}, /* Ic */
140 {NULL, NULL}, /* In */
141 {NULL, NULL}, /* Li */
142 {mdoc_nd_pre, NULL}, /* Nd */
143 {mdoc_nm_pre, NULL}, /* Nm */
144 {mdoc_op_pre, mdoc_op_post}, /* Op */
145 {NULL, NULL}, /* Ot */
146 {mdoc_pa_pre, NULL}, /* Pa */
147 {NULL, NULL}, /* Rv */
148 {NULL, NULL}, /* St */
149 {NULL, NULL}, /* Va */
150 {mdoc_vt_pre, NULL}, /* Vt */
151 {mdoc_xr_pre, NULL}, /* Xr */
152 {NULL, NULL}, /* %A */
153 {NULL, NULL}, /* %B */
154 {NULL, NULL}, /* %D */
155 {NULL, NULL}, /* %I */
156 {NULL, NULL}, /* %J */
157 {NULL, NULL}, /* %N */
158 {NULL, NULL}, /* %O */
159 {NULL, NULL}, /* %P */
160 {NULL, NULL}, /* %R */
161 {NULL, NULL}, /* %T */
162 {NULL, NULL}, /* %V */
163 {NULL, NULL}, /* Ac */
164 {mdoc_aq_pre, mdoc_aq_post}, /* Ao */
165 {mdoc_aq_pre, mdoc_aq_post}, /* Aq */
166 {NULL, NULL}, /* At */
167 {NULL, NULL}, /* Bc */
168 {NULL, NULL}, /* Bf */
169 {NULL, NULL}, /* Bo */
170 {NULL, NULL}, /* Bq */
171 {mdoc_xx_pre, NULL}, /* Bsx */
172 {NULL, NULL}, /* Bx */
173 {NULL, NULL}, /* Db */
174 {NULL, NULL}, /* Dc */
175 {NULL, NULL}, /* Do */
176 {mdoc_dq_pre, mdoc_dq_post}, /* Dq */
177 {NULL, NULL}, /* Ec */
178 {NULL, NULL}, /* Ef */
179 {mdoc_em_pre, NULL}, /* Em */
180 {NULL, NULL}, /* Eo */
181 {mdoc_xx_pre, NULL}, /* Fx */
182 {NULL, NULL}, /* Ms */
183 {NULL, NULL}, /* No */
184 {mdoc_ns_pre, NULL}, /* Ns */
185 {mdoc_xx_pre, NULL}, /* Nx */
186 {mdoc_xx_pre, NULL}, /* Ox */
187 {NULL, NULL}, /* Pc */
188 {NULL, NULL}, /* Pf */
189 {mdoc_pq_pre, mdoc_pq_post}, /* Po */
190 {mdoc_pq_pre, mdoc_pq_post}, /* Pq */
191 {NULL, NULL}, /* Qc */
192 {NULL, NULL}, /* Ql */
193 {mdoc_qq_pre, mdoc_qq_post}, /* Qo */
194 {mdoc_qq_pre, mdoc_qq_post}, /* Qq */
195 {NULL, NULL}, /* Re */
196 {NULL, NULL}, /* Rs */
197 {NULL, NULL}, /* Sc */
198 {mdoc_sq_pre, mdoc_sq_post}, /* So */
199 {mdoc_sq_pre, mdoc_sq_post}, /* Sq */
200 {NULL, NULL}, /* Sm */
201 {mdoc_sx_pre, NULL}, /* Sx */
202 {NULL, NULL}, /* Sy */
203 {NULL, NULL}, /* Tn */
204 {mdoc_xx_pre, NULL}, /* Ux */
205 {NULL, NULL}, /* Xc */
206 {NULL, NULL}, /* Xo */
207 {NULL, NULL}, /* Fo */
208 {NULL, NULL}, /* Fc */
209 {NULL, NULL}, /* Oo */
210 {NULL, NULL}, /* Oc */
211 {NULL, NULL}, /* Bk */
212 {NULL, NULL}, /* Ek */
213 {NULL, NULL}, /* Bt */
214 {NULL, NULL}, /* Hf */
215 {NULL, NULL}, /* Fr */
216 {NULL, NULL}, /* Ud */
217 {NULL, NULL}, /* Lb */
218 {mdoc_sp_pre, NULL}, /* Lp */
219 {NULL, NULL}, /* Lk */
220 {NULL, NULL}, /* Mt */
221 {NULL, NULL}, /* Brq */
222 {NULL, NULL}, /* Bro */
223 {NULL, NULL}, /* Brc */
224 {NULL, NULL}, /* %C */
225 {NULL, NULL}, /* Es */
226 {NULL, NULL}, /* En */
227 {mdoc_xx_pre, NULL}, /* Dx */
228 {NULL, NULL}, /* %Q */
229 {mdoc_sp_pre, NULL}, /* br */
230 {mdoc_sp_pre, NULL}, /* sp */
231 };
232
233 static char buf[BUFSIZ]; /* XXX */
234
235 #define bufcat(x) (void)strlcat(buf, (x), BUFSIZ)
236 #define bufinit() buf[0] = 0
237 #define buffmt(...) (void)snprintf(buf, BUFSIZ - 1, __VA_ARGS__)
238
239 void
240 html_mdoc(void *arg, const struct mdoc *m)
241 {
242 struct html *h;
243 struct tag *t;
244
245 h = (struct html *)arg;
246
247 print_gen_doctype(h);
248 t = print_otag(h, TAG_HTML, 0, NULL);
249 print_mdoc(mdoc_meta(m), mdoc_node(m), h);
250 print_tagq(h, t);
251
252 printf("\n");
253 }
254
255
256 static int
257 a2list(const struct mdoc_node *n)
258 {
259 int i;
260
261 assert(MDOC_BLOCK == n->type && MDOC_Bl == n->tok);
262 assert(n->args);
263
264 for (i = 0; i < (int)n->args->argc; i++)
265 switch (n->args->argv[i].arg) {
266 case (MDOC_Enum):
267 /* FALLTHROUGH */
268 case (MDOC_Dash):
269 /* FALLTHROUGH */
270 case (MDOC_Hyphen):
271 /* FALLTHROUGH */
272 case (MDOC_Bullet):
273 /* FALLTHROUGH */
274 case (MDOC_Tag):
275 /* FALLTHROUGH */
276 case (MDOC_Hang):
277 /* FALLTHROUGH */
278 case (MDOC_Inset):
279 /* FALLTHROUGH */
280 case (MDOC_Diag):
281 /* FALLTHROUGH */
282 case (MDOC_Item):
283 /* FALLTHROUGH */
284 case (MDOC_Column):
285 /* FALLTHROUGH */
286 case (MDOC_Ohang):
287 return(n->args->argv[i].arg);
288 default:
289 break;
290 }
291
292 abort();
293 /* NOTREACHED */
294 }
295
296
297 static int
298 a2width(const char *p)
299 {
300 int i, len;
301
302 if (0 == (len = (int)strlen(p)))
303 return(0);
304 for (i = 0; i < len - 1; i++)
305 if ( ! isdigit((u_char)p[i]))
306 break;
307
308 if (i == len - 1)
309 if ('n' == p[len - 1] || 'm' == p[len - 1])
310 return(atoi(p) + 2);
311
312 return(len + 2);
313 }
314
315
316 static int
317 a2offs(const char *p)
318 {
319 int len, i;
320
321 if (0 == strcmp(p, "left"))
322 return(0);
323 if (0 == strcmp(p, "indent"))
324 return(INDENT + 1);
325 if (0 == strcmp(p, "indent-two"))
326 return((INDENT + 1) * 2);
327
328 if (0 == (len = (int)strlen(p)))
329 return(0);
330
331 for (i = 0; i < len - 1; i++)
332 if ( ! isdigit((u_char)p[i]))
333 break;
334
335 if (i == len - 1)
336 if ('n' == p[len - 1] || 'm' == p[len - 1])
337 return(atoi(p));
338
339 return(len);
340 }
341
342
343 static void
344 print_mdoc(MDOC_ARGS)
345 {
346 struct tag *t;
347 struct htmlpair tag;
348
349 t = print_otag(h, TAG_HEAD, 0, NULL);
350 print_mdoc_head(m, n, h);
351 print_tagq(h, t);
352
353 t = print_otag(h, TAG_BODY, 0, NULL);
354
355 tag.key = ATTR_CLASS;
356 tag.val = "body";
357 print_otag(h, TAG_DIV, 1, &tag);
358
359 print_mdoc_nodelist(m, n, h);
360 print_tagq(h, t);
361 }
362
363
364 /* ARGSUSED */
365 static void
366 print_mdoc_head(MDOC_ARGS)
367 {
368 char b[BUFSIZ];
369
370 print_gen_head(h);
371
372 (void)snprintf(b, BUFSIZ - 1,
373 "%s(%d)", m->title, m->msec);
374
375 if (m->arch) {
376 (void)strlcat(b, " (", BUFSIZ);
377 (void)strlcat(b, m->arch, BUFSIZ);
378 (void)strlcat(b, ")", BUFSIZ);
379 }
380
381 print_otag(h, TAG_TITLE, 0, NULL);
382 print_text(h, b);
383 }
384
385
386 static void
387 print_mdoc_nodelist(MDOC_ARGS)
388 {
389
390 print_mdoc_node(m, n, h);
391 if (n->next)
392 print_mdoc_nodelist(m, n->next, h);
393 }
394
395
396 static void
397 print_mdoc_node(MDOC_ARGS)
398 {
399 int child;
400 struct tag *t;
401
402 child = 1;
403 t = SLIST_FIRST(&h->tags);
404
405 bufinit();
406
407 switch (n->type) {
408 case (MDOC_ROOT):
409 child = mdoc_root_pre(m, n, h);
410 break;
411 case (MDOC_TEXT):
412 print_text(h, n->string);
413 break;
414 default:
415 if (mdocs[n->tok].pre)
416 child = (*mdocs[n->tok].pre)(m, n, h);
417 break;
418 }
419
420 if (child && n->child)
421 print_mdoc_nodelist(m, n->child, h);
422
423 print_stagq(h, t);
424
425 bufinit();
426
427 switch (n->type) {
428 case (MDOC_ROOT):
429 mdoc_root_post(m, n, h);
430 break;
431 case (MDOC_TEXT):
432 break;
433 default:
434 if (mdocs[n->tok].post)
435 (*mdocs[n->tok].post)(m, n, h);
436 break;
437 }
438 }
439
440
441 /* ARGSUSED */
442 static void
443 mdoc_root_post(MDOC_ARGS)
444 {
445 struct tm tm;
446 struct htmlpair tag[2];
447 struct tag *t, *tt;
448 char b[BUFSIZ];
449
450 (void)localtime_r(&m->date, &tm);
451
452 if (0 == strftime(b, BUFSIZ - 1, "%B %e, %Y", &tm))
453 err(EXIT_FAILURE, "strftime");
454
455 tag[0].key = ATTR_CLASS;
456 tag[0].val = "footer";
457 tag[1].key = ATTR_STYLE;
458 tag[1].val = "width: 100%;";
459 t = print_otag(h, TAG_TABLE, 2, tag);
460 tt = print_otag(h, TAG_TR, 0, NULL);
461
462 tag[0].key = ATTR_STYLE;
463 tag[0].val = "width: 50%;";
464 print_otag(h, TAG_TD, 1, tag);
465 print_text(h, b);
466 print_stagq(h, tt);
467
468 tag[0].key = ATTR_STYLE;
469 tag[0].val = "width: 50%; text-align: right;";
470 print_otag(h, TAG_TD, 1, tag);
471 print_text(h, m->os);
472 print_tagq(h, t);
473 }
474
475
476 /* ARGSUSED */
477 static int
478 mdoc_root_pre(MDOC_ARGS)
479 {
480 struct htmlpair tag[2];
481 struct tag *t, *tt;
482 char b[BUFSIZ], title[BUFSIZ];
483
484 (void)strlcpy(b, m->vol, BUFSIZ);
485
486 if (m->arch) {
487 (void)strlcat(b, " (", BUFSIZ);
488 (void)strlcat(b, m->arch, BUFSIZ);
489 (void)strlcat(b, ")", BUFSIZ);
490 }
491
492 (void)snprintf(title, BUFSIZ - 1,
493 "%s(%d)", m->title, m->msec);
494
495 tag[0].key = ATTR_CLASS;
496 tag[0].val = "header";
497 tag[1].key = ATTR_STYLE;
498 tag[1].val = "width: 100%;";
499 t = print_otag(h, TAG_TABLE, 2, tag);
500 tt = print_otag(h, TAG_TR, 0, NULL);
501
502 tag[0].key = ATTR_STYLE;
503 tag[0].val = "width: 33%;";
504 print_otag(h, TAG_TD, 1, tag);
505 print_text(h, b);
506 print_stagq(h, tt);
507
508 tag[0].key = ATTR_STYLE;
509 tag[0].val = "width: 33%; text-align: center;";
510 print_otag(h, TAG_TD, 1, tag);
511 print_text(h, title);
512 print_stagq(h, tt);
513
514 tag[0].key = ATTR_STYLE;
515 tag[0].val = "width: 33%; text-align: right;";
516 print_otag(h, TAG_TD, 1, tag);
517 print_text(h, b);
518 print_tagq(h, t);
519
520 return(1);
521 }
522
523
524 /* ARGSUSED */
525 static int
526 mdoc_sh_pre(MDOC_ARGS)
527 {
528 struct htmlpair tag[2];
529 const struct mdoc_node *nn;
530
531 if (MDOC_HEAD == n->type) {
532 tag[0].key = ATTR_CLASS;
533 tag[0].val = "sec-head";
534 print_otag(h, TAG_DIV, 1, tag);
535 print_otag(h, TAG_SPAN, 1, tag);
536
537 for (nn = n->child; nn; nn = nn->next) {
538 bufcat(nn->string);
539 if (nn->next)
540 bufcat(" ");
541 }
542 tag[0].key = ATTR_NAME;
543 tag[0].val = buf;
544 print_otag(h, TAG_A, 1, tag);
545 return(1);
546 } else if (MDOC_BLOCK == n->type) {
547 tag[0].key = ATTR_CLASS;
548 tag[0].val = "sec-block";
549
550 if (n->prev && NULL == n->prev->body->child) {
551 print_otag(h, TAG_DIV, 1, tag);
552 return(1);
553 }
554
555 bufcat("margin-top: 1em;");
556 if (NULL == n->next)
557 bufcat("margin-bottom: 1em;");
558
559 tag[1].key = ATTR_STYLE;
560 tag[1].val = buf;
561
562 print_otag(h, TAG_DIV, 2, tag);
563 return(1);
564 }
565
566 buffmt("margin-left: %dem;", INDENT);
567
568 tag[0].key = ATTR_CLASS;
569 tag[0].val = "sec-body";
570 tag[1].key = ATTR_STYLE;
571 tag[1].val = buf;
572
573 print_otag(h, TAG_DIV, 2, tag);
574 return(1);
575 }
576
577
578 /* ARGSUSED */
579 static int
580 mdoc_ss_pre(MDOC_ARGS)
581 {
582 struct htmlpair tag[2];
583 int i;
584 const struct mdoc_node *nn;
585
586 i = 0;
587
588 if (MDOC_BODY == n->type) {
589 tag[i].key = ATTR_CLASS;
590 tag[i++].val = "ssec-body";
591 if (n->parent->next && n->child) {
592 bufcat("margin-bottom: 1em;");
593 tag[i].key = ATTR_STYLE;
594 tag[i++].val = buf;
595 }
596 print_otag(h, TAG_DIV, i, tag);
597 return(1);
598 } else if (MDOC_BLOCK == n->type) {
599 tag[i].key = ATTR_CLASS;
600 tag[i++].val = "ssec-block";
601 if (n->prev) {
602 bufcat("margin-top: 1em;");
603 tag[i].key = ATTR_STYLE;
604 tag[i++].val = buf;
605 }
606 print_otag(h, TAG_DIV, i, tag);
607 return(1);
608 }
609
610 buffmt("margin-left: -%dem;", INDENT - HALFINDENT);
611
612 tag[0].key = ATTR_CLASS;
613 tag[0].val = "ssec-head";
614 tag[1].key = ATTR_STYLE;
615 tag[1].val = buf;
616
617 print_otag(h, TAG_DIV, 2, tag);
618 print_otag(h, TAG_SPAN, 1, tag);
619
620 bufinit();
621 for (nn = n->child; nn; nn = nn->next) {
622 bufcat(nn->string);
623 if (nn->next)
624 bufcat(" ");
625 }
626 tag[0].key = ATTR_NAME;
627 tag[0].val = buf;
628 print_otag(h, TAG_A, 1, tag);
629
630 return(1);
631 }
632
633
634 /* ARGSUSED */
635 static int
636 mdoc_fl_pre(MDOC_ARGS)
637 {
638 struct htmlpair tag;
639
640 tag.key = ATTR_CLASS;
641 tag.val = "flag";
642
643 print_otag(h, TAG_SPAN, 1, &tag);
644 if (MDOC_Fl == n->tok) {
645 print_text(h, "\\-");
646 h->flags |= HTML_NOSPACE;
647 }
648 return(1);
649 }
650
651
652 /* ARGSUSED */
653 static int
654 mdoc_nd_pre(MDOC_ARGS)
655 {
656 struct htmlpair tag;
657
658 if (MDOC_BODY != n->type)
659 return(1);
660
661 /* XXX - this can contain block elements! */
662 print_text(h, "\\(em");
663 tag.key = ATTR_CLASS;
664 tag.val = "desc-body";
665 print_otag(h, TAG_SPAN, 1, &tag);
666 return(1);
667 }
668
669
670 /* ARGSUSED */
671 static int
672 mdoc_op_pre(MDOC_ARGS)
673 {
674 struct htmlpair tag;
675
676 if (MDOC_BODY != n->type)
677 return(1);
678
679 /* XXX - this can contain block elements! */
680 print_text(h, "\\(lB");
681 h->flags |= HTML_NOSPACE;
682 tag.key = ATTR_CLASS;
683 tag.val = "opt";
684 print_otag(h, TAG_SPAN, 1, &tag);
685 return(1);
686 }
687
688
689 /* ARGSUSED */
690 static void
691 mdoc_op_post(MDOC_ARGS)
692 {
693
694 if (MDOC_BODY != n->type)
695 return;
696 h->flags |= HTML_NOSPACE;
697 print_text(h, "\\(rB");
698 }
699
700
701 static int
702 mdoc_nm_pre(MDOC_ARGS)
703 {
704 struct htmlpair tag;
705
706 if ( ! (HTML_NEWLINE & h->flags))
707 if (SEC_SYNOPSIS == n->sec) {
708 tag.key = ATTR_STYLE;
709 tag.val = "clear: both;";
710 print_otag(h, TAG_BR, 1, &tag);
711 }
712
713 tag.key = ATTR_CLASS;
714 tag.val = "name";
715
716 print_otag(h, TAG_SPAN, 1, &tag);
717 if (NULL == n->child)
718 print_text(h, m->name);
719
720 return(1);
721 }
722
723
724 /* ARGSUSED */
725 static int
726 mdoc_xr_pre(MDOC_ARGS)
727 {
728 struct htmlpair tag[2];
729 const char *name, *sec;
730 const struct mdoc_node *nn;
731
732 nn = n->child;
733 name = nn && nn->string ? nn->string : "";
734 nn = nn ? nn->next : NULL;
735 sec = nn && nn->string ? nn->string : "";
736
737 buffmt("%s%s%s.html", name, name && sec ? "." : "", sec);
738
739 tag[0].key = ATTR_CLASS;
740 tag[0].val = "link-man";
741 tag[1].key = ATTR_HREF;
742 tag[1].val = buf;
743 print_otag(h, TAG_A, 2, tag);
744
745 nn = n->child;
746 print_text(h, nn->string);
747 if (NULL == (nn = nn->next))
748 return(0);
749
750 h->flags |= HTML_NOSPACE;
751 print_text(h, "(");
752 h->flags |= HTML_NOSPACE;
753 print_text(h, nn->string);
754 h->flags |= HTML_NOSPACE;
755 print_text(h, ")");
756
757 return(0);
758 }
759
760
761 /* ARGSUSED */
762 static int
763 mdoc_ns_pre(MDOC_ARGS)
764 {
765
766 h->flags |= HTML_NOSPACE;
767 return(1);
768 }
769
770
771 /* ARGSUSED */
772 static int
773 mdoc_ar_pre(MDOC_ARGS)
774 {
775 struct htmlpair tag;
776
777 tag.key = ATTR_CLASS;
778 tag.val = "arg";
779
780 print_otag(h, TAG_SPAN, 1, &tag);
781 return(1);
782 }
783
784
785 /* ARGSUSED */
786 static int
787 mdoc_xx_pre(MDOC_ARGS)
788 {
789 const char *pp;
790 struct htmlpair tag;
791
792 switch (n->tok) {
793 case (MDOC_Bsx):
794 pp = "BSDI BSD/OS";
795 break;
796 case (MDOC_Dx):
797 pp = "DragonFlyBSD";
798 break;
799 case (MDOC_Fx):
800 pp = "FreeBSD";
801 break;
802 case (MDOC_Nx):
803 pp = "NetBSD";
804 break;
805 case (MDOC_Ox):
806 pp = "OpenBSD";
807 break;
808 case (MDOC_Ux):
809 pp = "UNIX";
810 break;
811 default:
812 return(1);
813 }
814
815 tag.key = ATTR_CLASS;
816 tag.val = "unix";
817
818 print_otag(h, TAG_SPAN, 1, &tag);
819 print_text(h, pp);
820 return(1);
821 }
822
823
824 /* ARGSUSED */
825 static int
826 mdoc_tbl_block_pre(MDOC_ARGS, int t, int w, int o, int c)
827 {
828 struct htmlpair tag;
829
830 switch (t) {
831 case (MDOC_Column):
832 /* FALLTHROUGH */
833 case (MDOC_Item):
834 /* FALLTHROUGH */
835 case (MDOC_Ohang):
836 buffmt("margin-left: %dem; clear: both;", o);
837 break;
838 default:
839 buffmt("margin-left: %dem; clear: both;", w + o);
840 break;
841 }
842
843 if ( ! c && MDOC_Column != t) {
844 if (n->prev && n->prev->body->child)
845 bufcat("padding-top: 1em;");
846 else if (NULL == n->prev)
847 bufcat("padding-top: 1em;");
848 }
849
850 tag.key = ATTR_STYLE;
851 tag.val = buf;
852 print_otag(h, TAG_DIV, 1, &tag);
853 return(1);
854 }
855
856
857 /* ARGSUSED */
858 static int
859 mdoc_tbl_body_pre(MDOC_ARGS, int t, int w)
860 {
861
862 print_otag(h, TAG_DIV, 0, NULL);
863 return(1);
864 }
865
866
867 /* ARGSUSED */
868 static int
869 mdoc_tbl_head_pre(MDOC_ARGS, int t, int w)
870 {
871 struct htmlpair tag;
872 struct ord *ord;
873 char nbuf[BUFSIZ];
874
875 switch (t) {
876 case (MDOC_Item):
877 /* FALLTHROUGH */
878 case (MDOC_Ohang):
879 print_otag(h, TAG_DIV, 0, NULL);
880 break;
881 case (MDOC_Column):
882 buffmt("min-width: %dem;", w);
883 bufcat("clear: none;");
884 if (n->next && MDOC_HEAD == n->next->type)
885 bufcat("float: left;");
886 tag.key = ATTR_STYLE;
887 tag.val = buf;
888 print_otag(h, TAG_DIV, 1, &tag);
889 break;
890 default:
891 buffmt("margin-left: -%dem;", w);
892 bufcat("clear: left;");
893 bufcat("float: left;");
894 bufcat("padding-right: 1em;");
895 tag.key = ATTR_STYLE;
896 tag.val = buf;
897 print_otag(h, TAG_DIV, 1, &tag);
898 break;
899 }
900
901 switch (t) {
902 case (MDOC_Diag):
903 tag.key = ATTR_CLASS;
904 tag.val = "diag";
905 print_otag(h, TAG_SPAN, 1, &tag);
906 break;
907 case (MDOC_Enum):
908 ord = SLIST_FIRST(&h->ords);
909 assert(ord);
910 nbuf[BUFSIZ - 1] = 0;
911 (void)snprintf(nbuf, BUFSIZ - 1, "%d.", ord->pos++);
912 print_text(h, nbuf);
913 return(0);
914 case (MDOC_Dash):
915 print_text(h, "\\(en");
916 return(0);
917 case (MDOC_Hyphen):
918 print_text(h, "\\-");
919 return(0);
920 case (MDOC_Bullet):
921 print_text(h, "\\(bu");
922 return(0);
923 default:
924 break;
925 }
926
927 return(1);
928 }
929
930
931 static int
932 mdoc_tbl_pre(MDOC_ARGS, int type)
933 {
934 int i, w, o, c, wp;
935 const struct mdoc_node *bl, *nn;
936
937 bl = n->parent->parent;
938 if (MDOC_BLOCK != n->type)
939 bl = bl->parent;
940
941 /* FIXME: fmt_vspace() equivalent. */
942
943 assert(bl->args);
944
945 w = o = c = 0;
946 wp = -1;
947
948 for (i = 0; i < (int)bl->args->argc; i++)
949 if (MDOC_Width == bl->args->argv[i].arg) {
950 assert(bl->args->argv[i].sz);
951 wp = i;
952 w = a2width(bl->args->argv[i].value[0]);
953 } else if (MDOC_Offset == bl->args->argv[i].arg) {
954 assert(bl->args->argv[i].sz);
955 o = a2offs(bl->args->argv[i].value[0]);
956 } else if (MDOC_Compact == bl->args->argv[i].arg)
957 c = 1;
958
959 if (MDOC_HEAD == n->type && MDOC_Column == type) {
960 nn = n->parent->child;
961 assert(nn && MDOC_HEAD == nn->type);
962 for (i = 0; nn && nn != n; nn = nn->next, i++)
963 /* Counter... */ ;
964 assert(nn);
965 if (wp >= 0 && i < (int)bl->args[wp].argv->sz)
966 w = a2width(bl->args->argv[wp].value[i]);
967 }
968
969 switch (type) {
970 case (MDOC_Enum):
971 /* FALLTHROUGH */
972 case (MDOC_Dash):
973 /* FALLTHROUGH */
974 case (MDOC_Hyphen):
975 /* FALLTHROUGH */
976 case (MDOC_Bullet):
977 if (w < 4)
978 w = 4;
979 break;
980 case (MDOC_Inset):
981 /* FALLTHROUGH */
982 case (MDOC_Diag):
983 w = 1;
984 break;
985 default:
986 if (0 == w)
987 w = 10;
988 break;
989 }
990
991 switch (n->type) {
992 case (MDOC_BLOCK):
993 break;
994 case (MDOC_HEAD):
995 return(mdoc_tbl_head_pre(m, n, h, type, w));
996 case (MDOC_BODY):
997 return(mdoc_tbl_body_pre(m, n, h, type, w));
998 default:
999 abort();
1000 /* NOTREACHED */
1001 }
1002
1003 return(mdoc_tbl_block_pre(m, n, h, type, w, o, c));
1004 }
1005
1006
1007 /* ARGSUSED */
1008 static int
1009 mdoc_bl_pre(MDOC_ARGS)
1010 {
1011 struct ord *ord;
1012
1013 if (MDOC_BLOCK != n->type)
1014 return(1);
1015 if (MDOC_Enum != a2list(n))
1016 return(1);
1017
1018 ord = malloc(sizeof(struct ord));
1019 if (NULL == ord)
1020 err(EXIT_FAILURE, "malloc");
1021 ord->cookie = n;
1022 ord->pos = 1;
1023 SLIST_INSERT_HEAD(&h->ords, ord, entry);
1024
1025 return(1);
1026 }
1027
1028
1029 /* ARGSUSED */
1030 static void
1031 mdoc_bl_post(MDOC_ARGS)
1032 {
1033 struct ord *ord;
1034
1035 if (MDOC_BLOCK != n->type)
1036 return;
1037 if (MDOC_Enum != a2list(n))
1038 return;
1039
1040 ord = SLIST_FIRST(&h->ords);
1041 assert(ord);
1042 SLIST_REMOVE_HEAD(&h->ords, entry);
1043 free(ord);
1044 }
1045
1046
1047 static int
1048 mdoc_it_pre(MDOC_ARGS)
1049 {
1050 int type;
1051
1052 if (MDOC_BLOCK == n->type)
1053 type = a2list(n->parent->parent);
1054 else
1055 type = a2list(n->parent->parent->parent);
1056
1057 return(mdoc_tbl_pre(m, n, h, type));
1058 }
1059
1060
1061 /* ARGSUSED */
1062 static int
1063 mdoc_ex_pre(MDOC_ARGS)
1064 {
1065 const struct mdoc_node *nn;
1066 struct tag *t;
1067 struct htmlpair tag;
1068
1069 print_text(h, "The");
1070
1071 tag.key = ATTR_CLASS;
1072 tag.val = "utility";
1073
1074 for (nn = n->child; nn; nn = nn->next) {
1075 t = print_otag(h, TAG_SPAN, 1, &tag);
1076 print_text(h, nn->string);
1077 print_tagq(h, t);
1078
1079 h->flags |= HTML_NOSPACE;
1080
1081 if (nn->next && NULL == nn->next->next)
1082 print_text(h, ", and");
1083 else if (nn->next)
1084 print_text(h, ",");
1085 else
1086 h->flags &= ~HTML_NOSPACE;
1087 }
1088
1089 if (n->child->next)
1090 print_text(h, "utilities exit");
1091 else
1092 print_text(h, "utility exits");
1093
1094 print_text(h, "0 on success, and >0 if an error occurs.");
1095 return(0);
1096 }
1097
1098
1099 /* ARGSUSED */
1100 static int
1101 mdoc_dq_pre(MDOC_ARGS)
1102 {
1103
1104 if (MDOC_BODY != n->type)
1105 return(1);
1106 print_text(h, "\\(lq");
1107 h->flags |= HTML_NOSPACE;
1108 return(1);
1109 }
1110
1111
1112 /* ARGSUSED */
1113 static void
1114 mdoc_dq_post(MDOC_ARGS)
1115 {
1116
1117 if (MDOC_BODY != n->type)
1118 return;
1119 h->flags |= HTML_NOSPACE;
1120 print_text(h, "\\(rq");
1121 }
1122
1123
1124 /* ARGSUSED */
1125 static int
1126 mdoc_pq_pre(MDOC_ARGS)
1127 {
1128
1129 if (MDOC_BODY != n->type)
1130 return(1);
1131 print_text(h, "\\&(");
1132 h->flags |= HTML_NOSPACE;
1133 return(1);
1134 }
1135
1136
1137 /* ARGSUSED */
1138 static void
1139 mdoc_pq_post(MDOC_ARGS)
1140 {
1141
1142 if (MDOC_BODY != n->type)
1143 return;
1144 print_text(h, ")");
1145 }
1146
1147
1148 /* ARGSUSED */
1149 static int
1150 mdoc_sq_pre(MDOC_ARGS)
1151 {
1152
1153 if (MDOC_BODY != n->type)
1154 return(1);
1155 print_text(h, "\\(oq");
1156 h->flags |= HTML_NOSPACE;
1157 return(1);
1158 }
1159
1160
1161 /* ARGSUSED */
1162 static void
1163 mdoc_sq_post(MDOC_ARGS)
1164 {
1165
1166 if (MDOC_BODY != n->type)
1167 return;
1168 h->flags |= HTML_NOSPACE;
1169 print_text(h, "\\(aq");
1170 }
1171
1172
1173 /* ARGSUSED */
1174 static int
1175 mdoc_em_pre(MDOC_ARGS)
1176 {
1177 struct htmlpair tag;
1178
1179 tag.key = ATTR_CLASS;
1180 tag.val = "emph";
1181
1182 print_otag(h, TAG_SPAN, 1, &tag);
1183 return(1);
1184 }
1185
1186
1187 /* ARGSUSED */
1188 static int
1189 mdoc_d1_pre(MDOC_ARGS)
1190 {
1191 struct htmlpair tag[2];
1192
1193 if (MDOC_BLOCK != n->type)
1194 return(1);
1195
1196 buffmt("margin-left: %dem;", INDENT);
1197
1198 tag[0].key = ATTR_CLASS;
1199 tag[0].val = "lit-block";
1200 tag[1].key = ATTR_STYLE;
1201 tag[1].val = buf;
1202
1203 print_otag(h, TAG_DIV, 2, tag);
1204 return(1);
1205 }
1206
1207
1208 /* ARGSUSED */
1209 static int
1210 mdoc_sx_pre(MDOC_ARGS)
1211 {
1212 struct htmlpair tag[2];
1213 const struct mdoc_node *nn;
1214
1215 bufcat("#");
1216 for (nn = n->child; nn; nn = nn->next) {
1217 bufcat(nn->string);
1218 if (nn->next)
1219 bufcat(" ");
1220 }
1221
1222 tag[0].key = ATTR_HREF;
1223 tag[0].val = buf;
1224 tag[1].key = ATTR_CLASS;
1225 tag[1].val = "link-sec";
1226
1227 print_otag(h, TAG_A, 2, tag);
1228 return(1);
1229 }
1230
1231
1232 /* ARGSUSED */
1233 static int
1234 mdoc_aq_pre(MDOC_ARGS)
1235 {
1236
1237 if (MDOC_BODY != n->type)
1238 return(1);
1239 print_text(h, "\\(la");
1240 h->flags |= HTML_NOSPACE;
1241 return(1);
1242 }
1243
1244
1245 /* ARGSUSED */
1246 static void
1247 mdoc_aq_post(MDOC_ARGS)
1248 {
1249
1250 if (MDOC_BODY != n->type)
1251 return;
1252 h->flags |= HTML_NOSPACE;
1253 print_text(h, "\\(ra");
1254 }
1255
1256
1257 /* ARGSUSED */
1258 static int
1259 mdoc_bd_pre(MDOC_ARGS)
1260 {
1261 struct htmlpair tag[2];
1262 int t, c, o, i;
1263 const struct mdoc_node *bl;
1264
1265 /* FIXME: fmt_vspace() shit. */
1266
1267 if (MDOC_BLOCK == n->type)
1268 bl = n;
1269 else if (MDOC_HEAD == n->type)
1270 return(0);
1271 else
1272 bl = n->parent;
1273
1274 t = o = c = 0;
1275
1276 for (i = 0; i < (int)bl->args->argc; i++)
1277 switch (bl->args->argv[i].arg) {
1278 case (MDOC_Offset):
1279 assert(bl->args->argv[i].sz);
1280 o = a2offs (bl->args->argv[i].value[0]);
1281 break;
1282 case (MDOC_Compact):
1283 c = 1;
1284 break;
1285 case (MDOC_Ragged):
1286 /* FALLTHROUGH */
1287 case (MDOC_Filled):
1288 /* FALLTHROUGH */
1289 case (MDOC_Unfilled):
1290 /* FALLTHROUGH */
1291 case (MDOC_Literal):
1292 t = bl->args->argv[i].arg;
1293 break;
1294 }
1295
1296 if (MDOC_BLOCK == n->type) {
1297 if (o)
1298 buffmt("margin-left: %dem;", o);
1299 bufcat("margin-top: 1em;");
1300 tag[0].key = ATTR_STYLE;
1301 tag[0].val = buf;
1302 print_otag(h, TAG_DIV, 1, tag);
1303 return(1);
1304 }
1305
1306 switch (t) {
1307 case (MDOC_Unfilled):
1308 case (MDOC_Literal):
1309 break;
1310 default:
1311 return(1);
1312 }
1313
1314 bufcat("white-space: pre;");
1315 tag[0].key = ATTR_STYLE;
1316 tag[0].val = buf;
1317 tag[1].key = ATTR_CLASS;
1318 tag[1].val = "lit-block";
1319
1320 print_otag(h, TAG_DIV, 2, tag);
1321
1322 for (n = n->child; n; n = n->next) {
1323 h->flags |= HTML_NOSPACE;
1324 print_mdoc_node(m, n, h);
1325 if (n->next)
1326 print_text(h, "\n");
1327 }
1328
1329 return(0);
1330 }
1331
1332
1333 /* ARGSUSED */
1334 static int
1335 mdoc_pa_pre(MDOC_ARGS)
1336 {
1337 struct htmlpair tag;
1338
1339 tag.key = ATTR_CLASS;
1340 tag.val = "file";
1341
1342 print_otag(h, TAG_SPAN, 1, &tag);
1343 return(1);
1344 }
1345
1346
1347 /* ARGSUSED */
1348 static int
1349 mdoc_qq_pre(MDOC_ARGS)
1350 {
1351
1352 if (MDOC_BODY != n->type)
1353 return(1);
1354 print_text(h, "\\*q");
1355 h->flags |= HTML_NOSPACE;
1356 return(1);
1357 }
1358
1359
1360 /* ARGSUSED */
1361 static void
1362 mdoc_qq_post(MDOC_ARGS)
1363 {
1364
1365 if (MDOC_BODY != n->type)
1366 return;
1367 h->flags |= HTML_NOSPACE;
1368 print_text(h, "\\*q");
1369 }
1370
1371
1372 /* ARGSUSED */
1373 static int
1374 mdoc_ad_pre(MDOC_ARGS)
1375 {
1376 struct htmlpair tag;
1377
1378 tag.key = ATTR_CLASS;
1379 tag.val = "addr";
1380 print_otag(h, TAG_SPAN, 1, &tag);
1381 return(1);
1382 }
1383
1384
1385 /* ARGSUSED */
1386 static int
1387 mdoc_an_pre(MDOC_ARGS)
1388 {
1389 struct htmlpair tag;
1390
1391 tag.key = ATTR_CLASS;
1392 tag.val = "author";
1393 print_otag(h, TAG_SPAN, 1, &tag);
1394 return(1);
1395 }
1396
1397
1398 /* ARGSUSED */
1399 static int
1400 mdoc_cd_pre(MDOC_ARGS)
1401 {
1402 struct htmlpair tag;
1403
1404 tag.key = ATTR_CLASS;
1405 tag.val = "config";
1406 print_otag(h, TAG_SPAN, 1, &tag);
1407 return(1);
1408 }
1409
1410
1411 /* ARGSUSED */
1412 static int
1413 mdoc_dv_pre(MDOC_ARGS)
1414 {
1415 struct htmlpair tag;
1416
1417 tag.key = ATTR_CLASS;
1418 tag.val = "define";
1419 print_otag(h, TAG_SPAN, 1, &tag);
1420 return(1);
1421 }
1422
1423
1424 /* ARGSUSED */
1425 static int
1426 mdoc_ev_pre(MDOC_ARGS)
1427 {
1428 struct htmlpair tag;
1429
1430 tag.key = ATTR_CLASS;
1431 tag.val = "env";
1432 print_otag(h, TAG_SPAN, 1, &tag);
1433 return(1);
1434 }
1435
1436
1437 /* ARGSUSED */
1438 static int
1439 mdoc_er_pre(MDOC_ARGS)
1440 {
1441 struct htmlpair tag;
1442
1443 tag.key = ATTR_CLASS;
1444 tag.val = "errno";
1445 print_otag(h, TAG_SPAN, 1, &tag);
1446 return(1);
1447 }
1448
1449
1450 /* ARGSUSED */
1451 static int
1452 mdoc_fa_pre(MDOC_ARGS)
1453 {
1454 const struct mdoc_node *nn;
1455 struct htmlpair tag;
1456 struct tag *t;
1457
1458 tag.key = ATTR_CLASS;
1459 tag.val = "farg";
1460
1461 if (n->parent->tok != MDOC_Fo) {
1462 print_otag(h, TAG_SPAN, 1, &tag);
1463 return(1);
1464 }
1465
1466 for (nn = n->child; nn; nn = nn->next) {
1467 t = print_otag(h, TAG_SPAN, 1, &tag);
1468 print_text(h, nn->string);
1469 print_tagq(h, t);
1470 if (nn->next)
1471 print_text(h, ",");
1472 }
1473
1474 if (n->child && n->next && n->next->tok == MDOC_Fa)
1475 print_text(h, ",");
1476
1477 return(0);
1478 }
1479
1480
1481 /* ARGSUSED */
1482 static int
1483 mdoc_fd_pre(MDOC_ARGS)
1484 {
1485 struct htmlpair tag;
1486
1487 if (SEC_SYNOPSIS == n->sec) {
1488 if (n->next && MDOC_Fd != n->next->tok) {
1489 tag.key = ATTR_STYLE;
1490 tag.val = "margin-bottom: 1em;";
1491 print_otag(h, TAG_DIV, 1, &tag);
1492 } else
1493 print_otag(h, TAG_DIV, 0, NULL);
1494 }
1495
1496 tag.key = ATTR_CLASS;
1497 tag.val = "macro";
1498 print_otag(h, TAG_SPAN, 1, &tag);
1499 return(1);
1500 }
1501
1502
1503 /* ARGSUSED */
1504 static int
1505 mdoc_vt_pre(MDOC_ARGS)
1506 {
1507 struct htmlpair tag;
1508
1509 if (SEC_SYNOPSIS == n->sec) {
1510 if (n->next && MDOC_Vt != n->next->tok) {
1511 tag.key = ATTR_STYLE;
1512 tag.val = "margin-bottom: 1em;";
1513 print_otag(h, TAG_DIV, 1, &tag);
1514 } else
1515 print_otag(h, TAG_DIV, 0, NULL);
1516 }
1517
1518 tag.key = ATTR_CLASS;
1519 tag.val = "type";
1520 print_otag(h, TAG_SPAN, 1, &tag);
1521 return(1);
1522 }
1523
1524 /* ARGSUSED */
1525 static int
1526 mdoc_ft_pre(MDOC_ARGS)
1527 {
1528 struct htmlpair tag;
1529
1530 if (SEC_SYNOPSIS == n->sec) {
1531 if (n->prev && MDOC_Fo == n->prev->tok) {
1532 tag.key = ATTR_STYLE;
1533 tag.val = "magin-bottom: 1em;";
1534 print_otag(h, TAG_DIV, 1, &tag);
1535 } else
1536 print_otag(h, TAG_DIV, 0, NULL);
1537 }
1538
1539 tag.key = ATTR_CLASS;
1540 tag.val = "type";
1541 print_otag(h, TAG_SPAN, 1, &tag);
1542 return(1);
1543 }
1544
1545
1546 /* ARGSUSED */
1547 static int
1548 mdoc_fn_pre(MDOC_ARGS)
1549 {
1550 struct tag *t;
1551 struct htmlpair tag;
1552 const struct mdoc_node *nn;
1553
1554 if (SEC_SYNOPSIS == n->sec) {
1555 if (n->next) {
1556 tag.key = ATTR_STYLE;
1557 tag.val = "margin-bottom: 1em";
1558 print_otag(h, TAG_DIV, 1, &tag);
1559 } else
1560 print_otag(h, TAG_DIV, 0, NULL);
1561 }
1562
1563 tag.key = ATTR_CLASS;
1564 tag.val = "type";
1565
1566 t = print_otag(h, TAG_SPAN, 1, &tag);
1567 print_text(h, n->child->string);
1568 print_tagq(h, t);
1569
1570 h->flags |= HTML_NOSPACE;
1571 print_text(h, "(");
1572
1573 for (nn = n->child->next; nn; nn = nn->next) {
1574 tag.key = ATTR_CLASS;
1575 tag.val = "farg";
1576 t = print_otag(h, TAG_SPAN, 1, &tag);
1577 print_text(h, nn->string);
1578 print_tagq(h, t);
1579 if (nn->next)
1580 print_text(h, ",");
1581 }
1582
1583 print_text(h, ")");
1584
1585 if (SEC_SYNOPSIS == n->sec)
1586 print_text(h, ";");
1587
1588 return(0);
1589 }
1590
1591
1592 /* ARGSUSED */
1593 static int
1594 mdoc_sp_pre(MDOC_ARGS)
1595 {
1596 int len;
1597 struct htmlpair tag;
1598
1599 switch (n->tok) {
1600 case (MDOC_sp):
1601 len = n->child ? atoi(n->child->string) : 1;
1602 break;
1603 case (MDOC_br):
1604 len = 0;
1605 break;
1606 default:
1607 len = 1;
1608 break;
1609 }
1610
1611 buffmt("height: %dem", len);
1612 tag.key = ATTR_STYLE;
1613 tag.val = buf;
1614 print_otag(h, TAG_DIV, 1, &tag);
1615 return(1);
1616
1617 }