xref: /openbsd/usr.bin/mandoc/term_ascii.c (revision 4f4f7972)
1*4f4f7972Sschwarze /*	$Id: term_ascii.c,v 1.11 2014/03/21 22:17:01 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 
19a5e11edeSschwarze #include <locale.h>
20f95d589eSschwarze #include <stdint.h>
21f95d589eSschwarze #include <stdio.h>
22f95d589eSschwarze #include <stdlib.h>
23f95d589eSschwarze #include <unistd.h>
24a5e11edeSschwarze #include <wchar.h>
25f95d589eSschwarze 
262791bd1cSschwarze #include "mandoc.h"
27*4f4f7972Sschwarze #include "mandoc_aux.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));
55f95d589eSschwarze 
563ebeb861Sschwarze 	p->tabwidth = 5;
573ebeb861Sschwarze 	p->defrmargin = 78;
583ebeb861Sschwarze 
59f95d589eSschwarze 	p->begin = ascii_begin;
60f95d589eSschwarze 	p->end = ascii_end;
61769ee804Sschwarze 	p->hspan = ascii_hspan;
62769ee804Sschwarze 	p->type = TERMTYPE_CHAR;
63a5e11edeSschwarze 
64a5e11edeSschwarze 	p->enc = TERMENC_ASCII;
65a5e11edeSschwarze 	p->advance = ascii_advance;
66a5e11edeSschwarze 	p->endline = ascii_endline;
67a5e11edeSschwarze 	p->letter = ascii_letter;
683ebeb861Sschwarze 	p->width = ascii_width;
69f95d589eSschwarze 
70a5e11edeSschwarze 	if (TERMENC_ASCII != enc) {
71a5e11edeSschwarze 		v = TERMENC_LOCALE == enc ?
72a5e11edeSschwarze 			setlocale(LC_ALL, "") :
7367b9506bSschwarze 			setlocale(LC_CTYPE, "en_US.UTF-8");
74a5e11edeSschwarze 		if (NULL != v && MB_CUR_MAX > 1) {
75a5e11edeSschwarze 			p->enc = enc;
76a5e11edeSschwarze 			p->advance = locale_advance;
77a5e11edeSschwarze 			p->endline = locale_endline;
78a5e11edeSschwarze 			p->letter = locale_letter;
79a5e11edeSschwarze 			p->width = locale_width;
80a5e11edeSschwarze 		}
81a5e11edeSschwarze 	}
82a5e11edeSschwarze 
83e12fe158Sschwarze 	toks[0] = "indent";
84e12fe158Sschwarze 	toks[1] = "width";
85b6695f6fSschwarze 	toks[2] = "mdoc";
86b6695f6fSschwarze 	toks[3] = NULL;
87f95d589eSschwarze 
88f95d589eSschwarze 	while (outopts && *outopts)
89f95d589eSschwarze 		switch (getsubopt(&outopts, UNCONST(toks), &v)) {
90f95d589eSschwarze 		case (0):
91e12fe158Sschwarze 			p->defindent = (size_t)atoi(v);
92e12fe158Sschwarze 			break;
93e12fe158Sschwarze 		case (1):
94f95d589eSschwarze 			p->defrmargin = (size_t)atoi(v);
95f95d589eSschwarze 			break;
96b6695f6fSschwarze 		case (2):
9784dd50f0Sschwarze 			/*
9884dd50f0Sschwarze 			 * Temporary, undocumented mode
9984dd50f0Sschwarze 			 * to imitate mdoc(7) output style.
10084dd50f0Sschwarze 			 */
101b6695f6fSschwarze 			p->mdocstyle = 1;
102b6695f6fSschwarze 			p->defindent = 5;
103b6695f6fSschwarze 			break;
104f95d589eSschwarze 		default:
105f95d589eSschwarze 			break;
106f95d589eSschwarze 		}
107f95d589eSschwarze 
108f95d589eSschwarze 	/* Enforce a lower boundary. */
109f95d589eSschwarze 	if (p->defrmargin < 58)
110f95d589eSschwarze 		p->defrmargin = 58;
111f95d589eSschwarze 
112f95d589eSschwarze 	return(p);
113f95d589eSschwarze }
114f95d589eSschwarze 
115a5e11edeSschwarze void *
116a5e11edeSschwarze ascii_alloc(char *outopts)
117a5e11edeSschwarze {
118a5e11edeSschwarze 
119a5e11edeSschwarze 	return(ascii_init(TERMENC_ASCII, outopts));
120a5e11edeSschwarze }
121a5e11edeSschwarze 
122a5e11edeSschwarze void *
123a5e11edeSschwarze utf8_alloc(char *outopts)
124a5e11edeSschwarze {
125a5e11edeSschwarze 
126a5e11edeSschwarze 	return(ascii_init(TERMENC_UTF8, outopts));
127a5e11edeSschwarze }
128a5e11edeSschwarze 
129a5e11edeSschwarze 
130a5e11edeSschwarze void *
131a5e11edeSschwarze locale_alloc(char *outopts)
132a5e11edeSschwarze {
133a5e11edeSschwarze 
134a5e11edeSschwarze 	return(ascii_init(TERMENC_LOCALE, outopts));
135a5e11edeSschwarze }
136f95d589eSschwarze 
137769ee804Sschwarze /* ARGSUSED */
1383ebeb861Sschwarze static size_t
139a5e11edeSschwarze ascii_width(const struct termp *p, int c)
1403ebeb861Sschwarze {
1413ebeb861Sschwarze 
1423ebeb861Sschwarze 	return(1);
1433ebeb861Sschwarze }
1443ebeb861Sschwarze 
145f95d589eSschwarze void
146f95d589eSschwarze ascii_free(void *arg)
147f95d589eSschwarze {
148f95d589eSschwarze 
149f95d589eSschwarze 	term_free((struct termp *)arg);
150f95d589eSschwarze }
151f95d589eSschwarze 
152f95d589eSschwarze /* ARGSUSED */
153f95d589eSschwarze static void
154a5e11edeSschwarze ascii_letter(struct termp *p, int c)
155f95d589eSschwarze {
156f95d589eSschwarze 
157f95d589eSschwarze 	putchar(c);
158f95d589eSschwarze }
159f95d589eSschwarze 
160f95d589eSschwarze static void
161f95d589eSschwarze ascii_begin(struct termp *p)
162f95d589eSschwarze {
163f95d589eSschwarze 
164f95d589eSschwarze 	(*p->headf)(p, p->argf);
165f95d589eSschwarze }
166f95d589eSschwarze 
167f95d589eSschwarze static void
168f95d589eSschwarze ascii_end(struct termp *p)
169f95d589eSschwarze {
170f95d589eSschwarze 
171f95d589eSschwarze 	(*p->footf)(p, p->argf);
172f95d589eSschwarze }
173f95d589eSschwarze 
174f95d589eSschwarze /* ARGSUSED */
175f95d589eSschwarze static void
176f95d589eSschwarze ascii_endline(struct termp *p)
177f95d589eSschwarze {
178f95d589eSschwarze 
179f95d589eSschwarze 	putchar('\n');
180f95d589eSschwarze }
181f95d589eSschwarze 
182f95d589eSschwarze /* ARGSUSED */
183f95d589eSschwarze static void
184f95d589eSschwarze ascii_advance(struct termp *p, size_t len)
185f95d589eSschwarze {
186f95d589eSschwarze 	size_t	 	i;
187f95d589eSschwarze 
188f95d589eSschwarze 	for (i = 0; i < len; i++)
189f95d589eSschwarze 		putchar(' ');
190f95d589eSschwarze }
191769ee804Sschwarze 
192769ee804Sschwarze /* ARGSUSED */
193769ee804Sschwarze static double
194769ee804Sschwarze ascii_hspan(const struct termp *p, const struct roffsu *su)
195769ee804Sschwarze {
196769ee804Sschwarze 	double		 r;
197769ee804Sschwarze 
198769ee804Sschwarze 	/*
199769ee804Sschwarze 	 * Approximate based on character width.  These are generated
200769ee804Sschwarze 	 * entirely by eyeballing the screen, but appear to be correct.
201769ee804Sschwarze 	 */
202769ee804Sschwarze 
203769ee804Sschwarze 	switch (su->unit) {
204769ee804Sschwarze 	case (SCALE_CM):
205769ee804Sschwarze 		r = 4 * su->scale;
206769ee804Sschwarze 		break;
207769ee804Sschwarze 	case (SCALE_IN):
208769ee804Sschwarze 		r = 10 * su->scale;
209769ee804Sschwarze 		break;
210769ee804Sschwarze 	case (SCALE_PC):
211769ee804Sschwarze 		r = (10 * su->scale) / 6;
212769ee804Sschwarze 		break;
213769ee804Sschwarze 	case (SCALE_PT):
214769ee804Sschwarze 		r = (10 * su->scale) / 72;
215769ee804Sschwarze 		break;
216769ee804Sschwarze 	case (SCALE_MM):
217769ee804Sschwarze 		r = su->scale / 1000;
218769ee804Sschwarze 		break;
219769ee804Sschwarze 	case (SCALE_VS):
220769ee804Sschwarze 		r = su->scale * 2 - 1;
221769ee804Sschwarze 		break;
222769ee804Sschwarze 	default:
223769ee804Sschwarze 		r = su->scale;
224769ee804Sschwarze 		break;
225769ee804Sschwarze 	}
226769ee804Sschwarze 
227769ee804Sschwarze 	return(r);
228769ee804Sschwarze }
229769ee804Sschwarze 
230a5e11edeSschwarze /* ARGSUSED */
231a5e11edeSschwarze static size_t
232a5e11edeSschwarze locale_width(const struct termp *p, int c)
233a5e11edeSschwarze {
234a5e11edeSschwarze 	int		rc;
235a5e11edeSschwarze 
236a5e11edeSschwarze 	return((rc = wcwidth(c)) < 0 ? 0 : rc);
237a5e11edeSschwarze }
238a5e11edeSschwarze 
239a5e11edeSschwarze /* ARGSUSED */
240a5e11edeSschwarze static void
241a5e11edeSschwarze locale_advance(struct termp *p, size_t len)
242a5e11edeSschwarze {
243a5e11edeSschwarze 	size_t	 	i;
244a5e11edeSschwarze 
245a5e11edeSschwarze 	for (i = 0; i < len; i++)
246a5e11edeSschwarze 		putwchar(L' ');
247a5e11edeSschwarze }
248a5e11edeSschwarze 
249a5e11edeSschwarze /* ARGSUSED */
250a5e11edeSschwarze static void
251a5e11edeSschwarze locale_endline(struct termp *p)
252a5e11edeSschwarze {
253a5e11edeSschwarze 
254a5e11edeSschwarze 	putwchar(L'\n');
255a5e11edeSschwarze }
256a5e11edeSschwarze 
257a5e11edeSschwarze /* ARGSUSED */
258a5e11edeSschwarze static void
259a5e11edeSschwarze locale_letter(struct termp *p, int c)
260a5e11edeSschwarze {
261a5e11edeSschwarze 
262a5e11edeSschwarze 	putwchar(c);
263a5e11edeSschwarze }
264