]>
git.cameronkatri.com Git - mandoc.git/blob - man_term.c
58fcee0d22358560d7bd10eed7e076fef01ee36f
1 /* $Id: man_term.c,v 1.4 2009/03/26 16:23:22 kristaps Exp $ */
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
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
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.
29 extern size_t strlcpy(char *, const char *, size_t);
30 extern size_t strlcat(char *, const char *, size_t);
33 #define DECL_ARGS struct termp *p, \
34 const struct man_node *n, \
35 const struct man_meta *m
38 int (*pre
)(DECL_ARGS
);
39 void (*post
)(DECL_ARGS
);
42 static int pre_B(DECL_ARGS
);
43 static int pre_BI(DECL_ARGS
);
44 static int pre_BR(DECL_ARGS
);
45 static int pre_I(DECL_ARGS
);
46 static int pre_IB(DECL_ARGS
);
47 static int pre_IP(DECL_ARGS
);
48 static int pre_IR(DECL_ARGS
);
49 static int pre_PP(DECL_ARGS
);
50 static int pre_RB(DECL_ARGS
);
51 static int pre_RI(DECL_ARGS
);
52 static int pre_SH(DECL_ARGS
);
53 static int pre_SS(DECL_ARGS
);
54 static int pre_TP(DECL_ARGS
);
56 static void post_B(DECL_ARGS
);
57 static void post_I(DECL_ARGS
);
58 static void post_SH(DECL_ARGS
);
59 static void post_SS(DECL_ARGS
);
61 static const struct termact termacts
[MAN_MAX
] = {
62 { NULL
, NULL
}, /* __ */
63 { NULL
, NULL
}, /* TH */
64 { pre_SH
, post_SH
}, /* SH */
65 { pre_SS
, post_SS
}, /* SS */
66 { pre_TP
, NULL
}, /* TP */
67 { pre_PP
, NULL
}, /* LP */
68 { pre_PP
, NULL
}, /* PP */
69 { pre_PP
, NULL
}, /* P */
70 { pre_IP
, NULL
}, /* IP */
71 { pre_PP
, NULL
}, /* HP */ /* FIXME */
72 { NULL
, NULL
}, /* SM */
73 { pre_B
, post_B
}, /* SB */
74 { pre_BI
, NULL
}, /* BI */
75 { pre_IB
, NULL
}, /* IB */
76 { pre_BR
, NULL
}, /* BR */
77 { pre_RB
, NULL
}, /* RB */
78 { NULL
, NULL
}, /* R */
79 { pre_B
, post_B
}, /* B */
80 { pre_I
, post_I
}, /* I */
81 { pre_IR
, NULL
}, /* IR */
82 { pre_RI
, NULL
}, /* RI */
85 static void print_head(struct termp
*,
86 const struct man_meta
*);
87 static void print_body(DECL_ARGS
);
88 static void print_node(DECL_ARGS
);
89 static void print_foot(struct termp
*,
90 const struct man_meta
*);
94 man_run(struct termp
*p
, const struct man
*m
)
97 print_head(p
, man_meta(m
));
98 p
->flags
|= TERMP_NOSPACE
;
99 print_body(p
, man_node(m
), man_meta(m
));
100 print_foot(p
, man_meta(m
));
111 p
->flags
|= TERMP_UNDER
;
121 p
->flags
&= ~TERMP_UNDER
;
129 const struct man_node
*nn
;
132 for (i
= 0, nn
= n
->child
; nn
; nn
= nn
->next
, i
++) {
134 p
->flags
|= TERMP_UNDER
;
136 p
->flags
|= TERMP_NOSPACE
;
137 print_node(p
, nn
, m
);
139 p
->flags
&= ~TERMP_UNDER
;
149 const struct man_node
*nn
;
152 for (i
= 0, nn
= n
->child
; nn
; nn
= nn
->next
, i
++) {
153 p
->flags
|= i
% 2 ? TERMP_BOLD
: TERMP_UNDER
;
155 p
->flags
|= TERMP_NOSPACE
;
156 print_node(p
, nn
, m
);
157 p
->flags
&= i
% 2 ? ~TERMP_BOLD
: ~TERMP_UNDER
;
167 const struct man_node
*nn
;
170 for (i
= 0, nn
= n
->child
; nn
; nn
= nn
->next
, i
++) {
172 p
->flags
|= TERMP_BOLD
;
174 p
->flags
|= TERMP_NOSPACE
;
175 print_node(p
, nn
, m
);
177 p
->flags
&= ~TERMP_BOLD
;
187 const struct man_node
*nn
;
190 for (i
= 0, nn
= n
->child
; nn
; nn
= nn
->next
, i
++) {
192 p
->flags
|= TERMP_UNDER
;
194 p
->flags
|= TERMP_NOSPACE
;
195 print_node(p
, nn
, m
);
197 p
->flags
&= ~TERMP_UNDER
;
207 const struct man_node
*nn
;
210 for (i
= 0, nn
= n
->child
; nn
; nn
= nn
->next
, i
++) {
212 p
->flags
|= TERMP_BOLD
;
214 p
->flags
|= TERMP_NOSPACE
;
215 print_node(p
, nn
, m
);
217 p
->flags
&= ~TERMP_BOLD
;
227 const struct man_node
*nn
;
230 for (i
= 0, nn
= n
->child
; nn
; nn
= nn
->next
, i
++) {
231 p
->flags
|= i
% 2 ? TERMP_UNDER
: TERMP_BOLD
;
233 p
->flags
|= TERMP_NOSPACE
;
234 print_node(p
, nn
, m
);
235 p
->flags
&= i
% 2 ? ~TERMP_UNDER
: ~TERMP_BOLD
;
246 p
->flags
|= TERMP_BOLD
;
256 p
->flags
&= ~TERMP_BOLD
;
275 const struct man_node
*nn
;
281 if (NULL
== (nn
= n
->child
))
284 /* FIXME - ignore the designator. */
287 if (MAN_TEXT
!= nn
->type
)
288 errx(1, "expected text line argument");
290 offs
= (size_t)atoi(nn
->string
);
293 p
->flags
|= TERMP_NOSPACE
;
303 const struct man_node
*nn
;
309 if (NULL
== (nn
= n
->child
))
312 if (nn
->line
== n
->line
) {
313 if (MAN_TEXT
!= nn
->type
)
314 errx(1, "expected text line argument");
315 offs
= (size_t)atoi(nn
->string
);
320 for ( ; nn
; nn
= nn
->next
)
321 print_node(p
, nn
, m
);
324 p
->flags
|= TERMP_NOSPACE
;
336 p
->flags
|= TERMP_BOLD
;
347 p
->flags
&= ~TERMP_BOLD
;
348 p
->flags
|= TERMP_NOSPACE
;
359 p
->flags
|= TERMP_BOLD
;
371 p
->flags
&= ~TERMP_BOLD
;
372 p
->flags
|= TERMP_NOSPACE
;
377 print_node(DECL_ARGS
)
385 if (termacts
[n
->tok
].pre
)
386 c
= (*termacts
[n
->tok
].pre
)(p
, n
, m
);
389 if (0 == *n
->string
) {
394 * Note! This is hacky. Here, we recognise the `\c'
395 * escape embedded in so many -man pages. It's supposed
396 * to remove the subsequent space, so we mark NOSPACE if
397 * it's encountered in the string.
399 sz
= (int)strlen(n
->string
);
400 term_word(p
, n
->string
);
401 if (sz
>= 2 && n
->string
[sz
- 1] == 'c' &&
402 n
->string
[sz
- 2] == '\\')
403 p
->flags
|= TERMP_NOSPACE
;
410 print_body(p
, n
->child
, m
);
414 if (termacts
[n
->tok
].post
)
415 (*termacts
[n
->tok
].post
)(p
, n
, m
);
424 print_body(DECL_ARGS
)
429 print_body(p
, n
->next
, m
);
434 print_foot(struct termp
*p
, const struct man_meta
*meta
)
439 if (NULL
== (buf
= malloc(p
->rmargin
)))
442 tm
= localtime(&meta
->date
);
445 if (NULL
== strftime(buf
, p
->rmargin
, "%B %d, %Y", tm
))
447 if (0 == strftime(buf
, p
->rmargin
, "%B %d, %Y", tm
))
453 p
->flags
|= TERMP_NOSPACE
| TERMP_NOBREAK
;
454 p
->rmargin
= p
->maxrmargin
- strlen(buf
);
458 term_word(p
, meta
->source
);
463 p
->flags
|= TERMP_NOLPAD
| TERMP_NOSPACE
;
464 p
->offset
= p
->rmargin
;
465 p
->rmargin
= p
->maxrmargin
;
466 p
->flags
&= ~TERMP_NOBREAK
;
476 print_head(struct termp
*p
, const struct man_meta
*meta
)
480 p
->rmargin
= p
->maxrmargin
;
483 if (NULL
== (buf
= malloc(p
->rmargin
)))
485 if (NULL
== (title
= malloc(p
->rmargin
)))
489 (void)strlcpy(buf
, meta
->vol
, p
->rmargin
);
493 (void)snprintf(title
, p
->rmargin
, "%s(%d)",
494 meta
->title
, meta
->msec
);
497 p
->rmargin
= (p
->maxrmargin
- strlen(buf
)) / 2;
498 p
->flags
|= TERMP_NOBREAK
| TERMP_NOSPACE
;
503 p
->flags
|= TERMP_NOLPAD
| TERMP_NOSPACE
;
504 p
->offset
= p
->rmargin
;
505 p
->rmargin
= p
->maxrmargin
- strlen(title
);
510 p
->offset
= p
->rmargin
;
511 p
->rmargin
= p
->maxrmargin
;
512 p
->flags
&= ~TERMP_NOBREAK
;
513 p
->flags
|= TERMP_NOLPAD
| TERMP_NOSPACE
;
518 p
->rmargin
= p
->maxrmargin
;
520 p
->flags
&= ~TERMP_NOSPACE
;