xref: /openbsd/usr.bin/mandoc/term_ascii.c (revision 84dd50f0)
1*84dd50f0Sschwarze /*	$Id: term_ascii.c,v 1.9 2011/12/05 00:28:12 schwarze Exp $ */
2f95d589eSschwarze /*
3a5e11edeSschwarze  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4f95d589eSschwarze  *
5f95d589eSschwarze  * Permission to use, copy, modify, and distribute this software for any
6f95d589eSschwarze  * purpose with or without fee is hereby granted, provided that the above
7f95d589eSschwarze  * copyright notice and this permission notice appear in all copies.
8f95d589eSschwarze  *
9f95d589eSschwarze  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10f95d589eSschwarze  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11f95d589eSschwarze  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12f95d589eSschwarze  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13f95d589eSschwarze  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14f95d589eSschwarze  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15f95d589eSschwarze  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16f95d589eSschwarze  */
17f95d589eSschwarze #include <sys/types.h>
18f95d589eSschwarze 
19f95d589eSschwarze #include <assert.h>
20a5e11edeSschwarze #include <locale.h>
21f95d589eSschwarze #include <stdint.h>
22f95d589eSschwarze #include <stdio.h>
23f95d589eSschwarze #include <stdlib.h>
24f95d589eSschwarze #include <unistd.h>
25a5e11edeSschwarze #include <wchar.h>
26f95d589eSschwarze 
272791bd1cSschwarze #include "mandoc.h"
28f95d589eSschwarze #include "out.h"
29f95d589eSschwarze #include "term.h"
30f95d589eSschwarze #include "main.h"
31f95d589eSschwarze 
32a5e11edeSschwarze static	struct termp	 *ascii_init(enum termenc, char *);
33769ee804Sschwarze static	double		  ascii_hspan(const struct termp *,
34769ee804Sschwarze 				const struct roffsu *);
35a5e11edeSschwarze static	size_t		  ascii_width(const struct termp *, int);
36769ee804Sschwarze static	void		  ascii_advance(struct termp *, size_t);
37769ee804Sschwarze static	void		  ascii_begin(struct termp *);
38769ee804Sschwarze static	void		  ascii_end(struct termp *);
39f95d589eSschwarze static	void		  ascii_endline(struct termp *);
40a5e11edeSschwarze static	void		  ascii_letter(struct termp *, int);
41f95d589eSschwarze 
42a5e11edeSschwarze static	void		  locale_advance(struct termp *, size_t);
43a5e11edeSschwarze static	void		  locale_endline(struct termp *);
44a5e11edeSschwarze static	void		  locale_letter(struct termp *, int);
45a5e11edeSschwarze static	size_t		  locale_width(const struct termp *, int);
46f95d589eSschwarze 
47a5e11edeSschwarze static struct termp *
48a5e11edeSschwarze ascii_init(enum termenc enc, char *outopts)
49f95d589eSschwarze {
50b6695f6fSschwarze 	const char	*toks[4];
51f95d589eSschwarze 	char		*v;
52a5e11edeSschwarze 	struct termp	*p;
53f95d589eSschwarze 
54a5e11edeSschwarze 	p = mandoc_calloc(1, sizeof(struct termp));
55a5e11edeSschwarze 	p->enc = enc;
56f95d589eSschwarze 
573ebeb861Sschwarze 	p->tabwidth = 5;
583ebeb861Sschwarze 	p->defrmargin = 78;
593ebeb861Sschwarze 
60f95d589eSschwarze 	p->begin = ascii_begin;
61f95d589eSschwarze 	p->end = ascii_end;
62769ee804Sschwarze 	p->hspan = ascii_hspan;
63769ee804Sschwarze 	p->type = TERMTYPE_CHAR;
64a5e11edeSschwarze 
65a5e11edeSschwarze 	p->enc = TERMENC_ASCII;
66a5e11edeSschwarze 	p->advance = ascii_advance;
67a5e11edeSschwarze 	p->endline = ascii_endline;
68a5e11edeSschwarze 	p->letter = ascii_letter;
693ebeb861Sschwarze 	p->width = ascii_width;
70f95d589eSschwarze 
71a5e11edeSschwarze 	if (TERMENC_ASCII != enc) {
72a5e11edeSschwarze 		v = TERMENC_LOCALE == enc ?
73a5e11edeSschwarze 			setlocale(LC_ALL, "") :
74a5e11edeSschwarze 			setlocale(LC_CTYPE, "UTF-8");
75a5e11edeSschwarze 		if (NULL != v && MB_CUR_MAX > 1) {
76a5e11edeSschwarze 			p->enc = enc;
77a5e11edeSschwarze 			p->advance = locale_advance;
78a5e11edeSschwarze 			p->endline = locale_endline;
79a5e11edeSschwarze 			p->letter = locale_letter;
80a5e11edeSschwarze 			p->width = locale_width;
81a5e11edeSschwarze 		}
82a5e11edeSschwarze 	}
83a5e11edeSschwarze 
84e12fe158Sschwarze 	toks[0] = "indent";
85e12fe158Sschwarze 	toks[1] = "width";
86b6695f6fSschwarze 	toks[2] = "mdoc";
87b6695f6fSschwarze 	toks[3] = NULL;
88f95d589eSschwarze 
89f95d589eSschwarze 	while (outopts && *outopts)
90f95d589eSschwarze 		switch (getsubopt(&outopts, UNCONST(toks), &v)) {
91f95d589eSschwarze 		case (0):
92e12fe158Sschwarze 			p->defindent = (size_t)atoi(v);
93e12fe158Sschwarze 			break;
94e12fe158Sschwarze 		case (1):
95f95d589eSschwarze 			p->defrmargin = (size_t)atoi(v);
96f95d589eSschwarze 			break;
97b6695f6fSschwarze 		case (2):
98*84dd50f0Sschwarze 			/*
99*84dd50f0Sschwarze 			 * Temporary, undocumented mode
100*84dd50f0Sschwarze 			 * to imitate mdoc(7) output style.
101*84dd50f0Sschwarze 			 */
102b6695f6fSschwarze 			p->mdocstyle = 1;
103b6695f6fSschwarze 			p->defindent = 5;
104b6695f6fSschwarze 			break;
105f95d589eSschwarze 		default:
106f95d589eSschwarze 			break;
107f95d589eSschwarze 		}
108f95d589eSschwarze 
109f95d589eSschwarze 	/* Enforce a lower boundary. */
110f95d589eSschwarze 	if (p->defrmargin < 58)
111f95d589eSschwarze 		p->defrmargin = 58;
112f95d589eSschwarze 
113f95d589eSschwarze 	return(p);
114f95d589eSschwarze }
115f95d589eSschwarze 
116a5e11edeSschwarze void *
117a5e11edeSschwarze ascii_alloc(char *outopts)
118a5e11edeSschwarze {
119a5e11edeSschwarze 
120a5e11edeSschwarze 	return(ascii_init(TERMENC_ASCII, outopts));
121a5e11edeSschwarze }
122a5e11edeSschwarze 
123a5e11edeSschwarze void *
124a5e11edeSschwarze utf8_alloc(char *outopts)
125a5e11edeSschwarze {
126a5e11edeSschwarze 
127a5e11edeSschwarze 	return(ascii_init(TERMENC_UTF8, outopts));
128a5e11edeSschwarze }
129a5e11edeSschwarze 
130a5e11edeSschwarze 
131a5e11edeSschwarze void *
132a5e11edeSschwarze locale_alloc(char *outopts)
133a5e11edeSschwarze {
134a5e11edeSschwarze 
135a5e11edeSschwarze 	return(ascii_init(TERMENC_LOCALE, outopts));
136a5e11edeSschwarze }
137f95d589eSschwarze 
138769ee804Sschwarze /* ARGSUSED */
1393ebeb861Sschwarze static size_t
140a5e11edeSschwarze ascii_width(const struct termp *p, int c)
1413ebeb861Sschwarze {
1423ebeb861Sschwarze 
1433ebeb861Sschwarze 	return(1);
1443ebeb861Sschwarze }
1453ebeb861Sschwarze 
146f95d589eSschwarze void
147f95d589eSschwarze ascii_free(void *arg)
148f95d589eSschwarze {
149f95d589eSschwarze 
150f95d589eSschwarze 	term_free((struct termp *)arg);
151f95d589eSschwarze }
152f95d589eSschwarze 
153f95d589eSschwarze /* ARGSUSED */
154f95d589eSschwarze static void
155a5e11edeSschwarze ascii_letter(struct termp *p, int c)
156f95d589eSschwarze {
157f95d589eSschwarze 
158f95d589eSschwarze 	putchar(c);
159f95d589eSschwarze }
160f95d589eSschwarze 
161f95d589eSschwarze static void
162f95d589eSschwarze ascii_begin(struct termp *p)
163f95d589eSschwarze {
164f95d589eSschwarze 
165f95d589eSschwarze 	(*p->headf)(p, p->argf);
166f95d589eSschwarze }
167f95d589eSschwarze 
168f95d589eSschwarze static void
169f95d589eSschwarze ascii_end(struct termp *p)
170f95d589eSschwarze {
171f95d589eSschwarze 
172f95d589eSschwarze 	(*p->footf)(p, p->argf);
173f95d589eSschwarze }
174f95d589eSschwarze 
175f95d589eSschwarze /* ARGSUSED */
176f95d589eSschwarze static void
177f95d589eSschwarze ascii_endline(struct termp *p)
178f95d589eSschwarze {
179f95d589eSschwarze 
180f95d589eSschwarze 	putchar('\n');
181f95d589eSschwarze }
182f95d589eSschwarze 
183f95d589eSschwarze /* ARGSUSED */
184f95d589eSschwarze static void
185f95d589eSschwarze ascii_advance(struct termp *p, size_t len)
186f95d589eSschwarze {
187f95d589eSschwarze 	size_t	 	i;
188f95d589eSschwarze 
189f95d589eSschwarze 	for (i = 0; i < len; i++)
190f95d589eSschwarze 		putchar(' ');
191f95d589eSschwarze }
192769ee804Sschwarze 
193769ee804Sschwarze /* ARGSUSED */
194769ee804Sschwarze static double
195769ee804Sschwarze ascii_hspan(const struct termp *p, const struct roffsu *su)
196769ee804Sschwarze {
197769ee804Sschwarze 	double		 r;
198769ee804Sschwarze 
199769ee804Sschwarze 	/*
200769ee804Sschwarze 	 * Approximate based on character width.  These are generated
201769ee804Sschwarze 	 * entirely by eyeballing the screen, but appear to be correct.
202769ee804Sschwarze 	 */
203769ee804Sschwarze 
204769ee804Sschwarze 	switch (su->unit) {
205769ee804Sschwarze 	case (SCALE_CM):
206769ee804Sschwarze 		r = 4 * su->scale;
207769ee804Sschwarze 		break;
208769ee804Sschwarze 	case (SCALE_IN):
209769ee804Sschwarze 		r = 10 * su->scale;
210769ee804Sschwarze 		break;
211769ee804Sschwarze 	case (SCALE_PC):
212769ee804Sschwarze 		r = (10 * su->scale) / 6;
213769ee804Sschwarze 		break;
214769ee804Sschwarze 	case (SCALE_PT):
215769ee804Sschwarze 		r = (10 * su->scale) / 72;
216769ee804Sschwarze 		break;
217769ee804Sschwarze 	case (SCALE_MM):
218769ee804Sschwarze 		r = su->scale / 1000;
219769ee804Sschwarze 		break;
220769ee804Sschwarze 	case (SCALE_VS):
221769ee804Sschwarze 		r = su->scale * 2 - 1;
222769ee804Sschwarze 		break;
223769ee804Sschwarze 	default:
224769ee804Sschwarze 		r = su->scale;
225769ee804Sschwarze 		break;
226769ee804Sschwarze 	}
227769ee804Sschwarze 
228769ee804Sschwarze 	return(r);
229769ee804Sschwarze }
230769ee804Sschwarze 
231a5e11edeSschwarze /* ARGSUSED */
232a5e11edeSschwarze static size_t
233a5e11edeSschwarze locale_width(const struct termp *p, int c)
234a5e11edeSschwarze {
235a5e11edeSschwarze 	int		rc;
236a5e11edeSschwarze 
237a5e11edeSschwarze 	return((rc = wcwidth(c)) < 0 ? 0 : rc);
238a5e11edeSschwarze }
239a5e11edeSschwarze 
240a5e11edeSschwarze /* ARGSUSED */
241a5e11edeSschwarze static void
242a5e11edeSschwarze locale_advance(struct termp *p, size_t len)
243a5e11edeSschwarze {
244a5e11edeSschwarze 	size_t	 	i;
245a5e11edeSschwarze 
246a5e11edeSschwarze 	for (i = 0; i < len; i++)
247a5e11edeSschwarze 		putwchar(L' ');
248a5e11edeSschwarze }
249a5e11edeSschwarze 
250a5e11edeSschwarze /* ARGSUSED */
251a5e11edeSschwarze static void
252a5e11edeSschwarze locale_endline(struct termp *p)
253a5e11edeSschwarze {
254a5e11edeSschwarze 
255a5e11edeSschwarze 	putwchar(L'\n');
256a5e11edeSschwarze }
257a5e11edeSschwarze 
258a5e11edeSschwarze /* ARGSUSED */
259a5e11edeSschwarze static void
260a5e11edeSschwarze locale_letter(struct termp *p, int c)
261a5e11edeSschwarze {
262a5e11edeSschwarze 
263a5e11edeSschwarze 	putwchar(c);
264a5e11edeSschwarze }
265