]>
git.cameronkatri.com Git - mandoc.git/blob - man_term.c
d5d95edc94530856da3d95b2c139b3efee2660fa
1 /* $Id: man_term.c,v 1.1 2009/03/26 14:38:11 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.
28 #define DECL_ARGS struct termp *p, \
29 const struct man_node *n, \
30 const struct man_meta *m
33 int (*pre
)(DECL_ARGS
);
34 void (*post
)(DECL_ARGS
);
37 static int pre_B(DECL_ARGS
);
38 static int pre_I(DECL_ARGS
);
39 static int pre_PP(DECL_ARGS
);
40 static int pre_SH(DECL_ARGS
);
41 static int pre_SS(DECL_ARGS
);
42 static int pre_TP(DECL_ARGS
);
44 static void post_B(DECL_ARGS
);
45 static void post_I(DECL_ARGS
);
46 static void post_SH(DECL_ARGS
);
47 static void post_SS(DECL_ARGS
);
49 static const struct termact termacts
[MAN_MAX
] = {
50 { NULL
, NULL
}, /* __ */
51 { NULL
, NULL
}, /* TH */
52 { pre_SH
, post_SH
}, /* SH */
53 { pre_SS
, post_SS
}, /* SS */
54 { pre_TP
, NULL
}, /* TP */
55 { pre_PP
, NULL
}, /* LP */
56 { pre_PP
, NULL
}, /* PP */
57 { pre_PP
, NULL
}, /* P */
58 { NULL
, NULL
}, /* IP */
59 { pre_PP
, NULL
}, /* HP */ /* XXX */
60 { NULL
, NULL
}, /* SM */
61 { pre_B
, post_B
}, /* SB */
62 { NULL
, NULL
}, /* BI */
63 { NULL
, NULL
}, /* IB */
64 { NULL
, NULL
}, /* BR */
65 { NULL
, NULL
}, /* RB */
66 { NULL
, NULL
}, /* R */
67 { pre_B
, post_B
}, /* B */
68 { pre_I
, post_I
}, /* I */
69 { NULL
, NULL
}, /* IR */
70 { NULL
, NULL
}, /* RI */
73 static void print_head(struct termp
*,
74 const struct man_meta
*);
75 static void print_body(DECL_ARGS
);
76 static void print_node(DECL_ARGS
);
77 static void print_foot(struct termp
*,
78 const struct man_meta
*);
82 man_run(struct termp
*p
, const struct man
*m
)
85 print_head(p
, man_meta(m
));
86 p
->flags
|= TERMP_NOSPACE
;
87 print_body(p
, man_node(m
), man_meta(m
));
88 print_foot(p
, man_meta(m
));
98 p
->flags
|= TERMP_UNDER
;
107 p
->flags
&= ~TERMP_UNDER
;
115 p
->flags
|= TERMP_BOLD
;
124 p
->flags
&= ~TERMP_BOLD
;
141 const struct man_node
*nn
;
147 if (NULL
== (nn
= n
->child
))
150 if (nn
->line
== n
->line
) {
151 if (MAN_TEXT
!= nn
->type
)
152 errx(1, "expected text line argument");
153 offs
= atoi(nn
->string
);
158 for ( ; nn
; nn
= nn
->next
)
159 print_node(p
, nn
, m
);
162 p
->flags
|= TERMP_NOSPACE
;
173 p
->flags
|= TERMP_BOLD
;
183 p
->flags
&= ~TERMP_BOLD
;
184 p
->flags
|= TERMP_NOSPACE
;
194 p
->flags
|= TERMP_BOLD
;
205 p
->flags
&= ~TERMP_BOLD
;
206 p
->flags
|= TERMP_NOSPACE
;
211 print_node(DECL_ARGS
)
219 if (termacts
[n
->tok
].pre
)
220 c
= (*termacts
[n
->tok
].pre
)(p
, n
, m
);
224 term_word(p
, n
->string
);
234 print_body(p
, n
->child
, m
);
238 if (termacts
[n
->tok
].post
)
239 (*termacts
[n
->tok
].post
)(p
, n
, m
);
248 print_body(DECL_ARGS
)
253 print_body(p
, n
->next
, m
);
258 print_foot(struct termp
*p
, const struct man_meta
*meta
)
263 if (NULL
== (buf
= malloc(p
->rmargin
)))
266 tm
= localtime(&meta
->date
);
269 if (NULL
== strftime(buf
, p
->rmargin
, "%B %d, %Y", tm
))
271 if (0 == strftime(buf
, p
->rmargin
, "%B %d, %Y", tm
))
276 * This is /slightly/ different from regular groff output
277 * because we don't have page numbers. Print the following:
284 p
->flags
|= TERMP_NOSPACE
| TERMP_NOBREAK
;
285 p
->rmargin
= p
->maxrmargin
- strlen(buf
);
289 term_word(p
, meta
->source
);
294 p
->flags
|= TERMP_NOLPAD
| TERMP_NOSPACE
;
295 p
->offset
= p
->rmargin
;
296 p
->rmargin
= p
->maxrmargin
;
297 p
->flags
&= ~TERMP_NOBREAK
;
307 print_head(struct termp
*p
, const struct man_meta
*meta
)
311 p
->rmargin
= p
->maxrmargin
;
314 if (NULL
== (buf
= malloc(p
->rmargin
)))
316 if (NULL
== (title
= malloc(p
->rmargin
)))
320 * The header is strange. It has three components, which are
321 * really two with the first duplicated. It goes like this:
323 * IDENTIFIER TITLE IDENTIFIER
325 * The IDENTIFIER is NAME(SECTION), which is the command-name
326 * (if given, or "unknown" if not) followed by the manual page
327 * section. These are given in `Dt'. The TITLE is a free-form
328 * string depending on the manual volume. If not specified, it
329 * switches on the manual section.
333 (void)strlcpy(buf
, meta
->vol
, p
->rmargin
);
337 (void)snprintf(title
, p
->rmargin
, "%s(%d)",
338 meta
->title
, meta
->msec
);
341 p
->rmargin
= (p
->maxrmargin
- strlen(buf
)) / 2;
342 p
->flags
|= TERMP_NOBREAK
| TERMP_NOSPACE
;
347 p
->flags
|= TERMP_NOLPAD
| TERMP_NOSPACE
;
348 p
->offset
= p
->rmargin
;
349 p
->rmargin
= p
->maxrmargin
- strlen(title
);
354 p
->offset
= p
->rmargin
;
355 p
->rmargin
= p
->maxrmargin
;
356 p
->flags
&= ~TERMP_NOBREAK
;
357 p
->flags
|= TERMP_NOLPAD
| TERMP_NOSPACE
;
362 p
->rmargin
= p
->maxrmargin
;
364 p
->flags
&= ~TERMP_NOSPACE
;