xref: /minix3/external/bsd/mdocml/dist/term_ascii.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	Id: term_ascii.c,v 1.21 2013/06/01 14:27:20 schwarze Exp  */
2d65f6f70SBen Gras /*
392395e9cSLionel Sambuc  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4d65f6f70SBen Gras  *
5d65f6f70SBen Gras  * Permission to use, copy, modify, and distribute this software for any
6d65f6f70SBen Gras  * purpose with or without fee is hereby granted, provided that the above
7d65f6f70SBen Gras  * copyright notice and this permission notice appear in all copies.
8d65f6f70SBen Gras  *
9d65f6f70SBen Gras  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10d65f6f70SBen Gras  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11d65f6f70SBen Gras  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12d65f6f70SBen Gras  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13d65f6f70SBen Gras  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14d65f6f70SBen Gras  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15d65f6f70SBen Gras  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16d65f6f70SBen Gras  */
17d65f6f70SBen Gras #ifdef HAVE_CONFIG_H
18d65f6f70SBen Gras #include "config.h"
19d65f6f70SBen Gras #endif
20d65f6f70SBen Gras 
21d65f6f70SBen Gras #include <sys/types.h>
22d65f6f70SBen Gras 
23d65f6f70SBen Gras #include <assert.h>
2492395e9cSLionel Sambuc #ifdef USE_WCHAR
2592395e9cSLionel Sambuc # include <locale.h>
2692395e9cSLionel Sambuc #endif
27d65f6f70SBen Gras #include <stdint.h>
28d65f6f70SBen Gras #include <stdio.h>
29d65f6f70SBen Gras #include <stdlib.h>
30d65f6f70SBen Gras #include <unistd.h>
3192395e9cSLionel Sambuc #ifdef USE_WCHAR
3292395e9cSLionel Sambuc # include <wchar.h>
3392395e9cSLionel Sambuc #endif
34d65f6f70SBen Gras 
35d65f6f70SBen Gras #include "mandoc.h"
36d65f6f70SBen Gras #include "out.h"
37d65f6f70SBen Gras #include "term.h"
38d65f6f70SBen Gras #include "main.h"
39d65f6f70SBen Gras 
4092395e9cSLionel Sambuc /*
4192395e9cSLionel Sambuc  * Sadly, this doesn't seem to be defined on systems even when they
4292395e9cSLionel Sambuc  * support it.  For the time being, remove it and let those compiling
4392395e9cSLionel Sambuc  * the software decide for themselves what to use.
4492395e9cSLionel Sambuc  */
4592395e9cSLionel Sambuc #if 0
4692395e9cSLionel Sambuc #if ! defined(__STDC_ISO_10646__)
4792395e9cSLionel Sambuc # undef USE_WCHAR
4892395e9cSLionel Sambuc #endif
4992395e9cSLionel Sambuc #endif
5092395e9cSLionel Sambuc 
5192395e9cSLionel Sambuc static	struct termp	 *ascii_init(enum termenc, char *);
52d65f6f70SBen Gras static	double		  ascii_hspan(const struct termp *,
53d65f6f70SBen Gras 				const struct roffsu *);
5492395e9cSLionel Sambuc static	size_t		  ascii_width(const struct termp *, int);
55d65f6f70SBen Gras static	void		  ascii_advance(struct termp *, size_t);
56d65f6f70SBen Gras static	void		  ascii_begin(struct termp *);
57d65f6f70SBen Gras static	void		  ascii_end(struct termp *);
58d65f6f70SBen Gras static	void		  ascii_endline(struct termp *);
5992395e9cSLionel Sambuc static	void		  ascii_letter(struct termp *, int);
60d65f6f70SBen Gras 
6192395e9cSLionel Sambuc #ifdef	USE_WCHAR
6292395e9cSLionel Sambuc static	void		  locale_advance(struct termp *, size_t);
6392395e9cSLionel Sambuc static	void		  locale_endline(struct termp *);
6492395e9cSLionel Sambuc static	void		  locale_letter(struct termp *, int);
6592395e9cSLionel Sambuc static	size_t		  locale_width(const struct termp *, int);
6692395e9cSLionel Sambuc #endif
67d65f6f70SBen Gras 
6892395e9cSLionel Sambuc static struct termp *
ascii_init(enum termenc enc,char * outopts)6992395e9cSLionel Sambuc ascii_init(enum termenc enc, char *outopts)
70d65f6f70SBen Gras {
7192395e9cSLionel Sambuc 	const char	*toks[4];
72d65f6f70SBen Gras 	char		*v;
7392395e9cSLionel Sambuc 	struct termp	*p;
74d65f6f70SBen Gras 
7592395e9cSLionel Sambuc 	p = mandoc_calloc(1, sizeof(struct termp));
76d65f6f70SBen Gras 
77d65f6f70SBen Gras 	p->tabwidth = 5;
78d65f6f70SBen Gras 	p->defrmargin = 78;
79d65f6f70SBen Gras 
80d65f6f70SBen Gras 	p->begin = ascii_begin;
81d65f6f70SBen Gras 	p->end = ascii_end;
82d65f6f70SBen Gras 	p->hspan = ascii_hspan;
83d65f6f70SBen Gras 	p->type = TERMTYPE_CHAR;
8492395e9cSLionel Sambuc 
8592395e9cSLionel Sambuc 	p->enc = TERMENC_ASCII;
8692395e9cSLionel Sambuc 	p->advance = ascii_advance;
8792395e9cSLionel Sambuc 	p->endline = ascii_endline;
8892395e9cSLionel Sambuc 	p->letter = ascii_letter;
89d65f6f70SBen Gras 	p->width = ascii_width;
90d65f6f70SBen Gras 
9192395e9cSLionel Sambuc #ifdef	USE_WCHAR
9292395e9cSLionel Sambuc 	if (TERMENC_ASCII != enc) {
9392395e9cSLionel Sambuc 		v = TERMENC_LOCALE == enc ?
9492395e9cSLionel Sambuc 			setlocale(LC_ALL, "") :
95*0a6a1f1dSLionel Sambuc 			setlocale(LC_CTYPE, "en_US.UTF-8");
9692395e9cSLionel Sambuc 		if (NULL != v && MB_CUR_MAX > 1) {
9792395e9cSLionel Sambuc 			p->enc = enc;
9892395e9cSLionel Sambuc 			p->advance = locale_advance;
9992395e9cSLionel Sambuc 			p->endline = locale_endline;
10092395e9cSLionel Sambuc 			p->letter = locale_letter;
10192395e9cSLionel Sambuc 			p->width = locale_width;
10292395e9cSLionel Sambuc 		}
10392395e9cSLionel Sambuc 	}
10492395e9cSLionel Sambuc #endif
10592395e9cSLionel Sambuc 
10692395e9cSLionel Sambuc 	toks[0] = "indent";
10792395e9cSLionel Sambuc 	toks[1] = "width";
10892395e9cSLionel Sambuc 	toks[2] = "mdoc";
10992395e9cSLionel Sambuc 	toks[3] = NULL;
110d65f6f70SBen Gras 
111d65f6f70SBen Gras 	while (outopts && *outopts)
112d65f6f70SBen Gras 		switch (getsubopt(&outopts, UNCONST(toks), &v)) {
113d65f6f70SBen Gras 		case (0):
11492395e9cSLionel Sambuc 			p->defindent = (size_t)atoi(v);
11592395e9cSLionel Sambuc 			break;
11692395e9cSLionel Sambuc 		case (1):
117d65f6f70SBen Gras 			p->defrmargin = (size_t)atoi(v);
118d65f6f70SBen Gras 			break;
11992395e9cSLionel Sambuc 		case (2):
12092395e9cSLionel Sambuc 			/*
12192395e9cSLionel Sambuc 			 * Temporary, undocumented mode
12292395e9cSLionel Sambuc 			 * to imitate mdoc(7) output style.
12392395e9cSLionel Sambuc 			 */
12492395e9cSLionel Sambuc 			p->mdocstyle = 1;
12592395e9cSLionel Sambuc 			p->defindent = 5;
12692395e9cSLionel Sambuc 			break;
127d65f6f70SBen Gras 		default:
128d65f6f70SBen Gras 			break;
129d65f6f70SBen Gras 		}
130d65f6f70SBen Gras 
131d65f6f70SBen Gras 	/* Enforce a lower boundary. */
132d65f6f70SBen Gras 	if (p->defrmargin < 58)
133d65f6f70SBen Gras 		p->defrmargin = 58;
134d65f6f70SBen Gras 
135d65f6f70SBen Gras 	return(p);
136d65f6f70SBen Gras }
137d65f6f70SBen Gras 
13892395e9cSLionel Sambuc void *
ascii_alloc(char * outopts)13992395e9cSLionel Sambuc ascii_alloc(char *outopts)
14092395e9cSLionel Sambuc {
14192395e9cSLionel Sambuc 
14292395e9cSLionel Sambuc 	return(ascii_init(TERMENC_ASCII, outopts));
14392395e9cSLionel Sambuc }
14492395e9cSLionel Sambuc 
14592395e9cSLionel Sambuc void *
utf8_alloc(char * outopts)14692395e9cSLionel Sambuc utf8_alloc(char *outopts)
14792395e9cSLionel Sambuc {
14892395e9cSLionel Sambuc 
14992395e9cSLionel Sambuc 	return(ascii_init(TERMENC_UTF8, outopts));
15092395e9cSLionel Sambuc }
15192395e9cSLionel Sambuc 
15292395e9cSLionel Sambuc 
15392395e9cSLionel Sambuc void *
locale_alloc(char * outopts)15492395e9cSLionel Sambuc locale_alloc(char *outopts)
15592395e9cSLionel Sambuc {
15692395e9cSLionel Sambuc 
15792395e9cSLionel Sambuc 	return(ascii_init(TERMENC_LOCALE, outopts));
15892395e9cSLionel Sambuc }
159d65f6f70SBen Gras 
160d65f6f70SBen Gras /* ARGSUSED */
161d65f6f70SBen Gras static size_t
ascii_width(const struct termp * p,int c)16292395e9cSLionel Sambuc ascii_width(const struct termp *p, int c)
163d65f6f70SBen Gras {
164d65f6f70SBen Gras 
165d65f6f70SBen Gras 	return(1);
166d65f6f70SBen Gras }
167d65f6f70SBen Gras 
168d65f6f70SBen Gras void
ascii_free(void * arg)169d65f6f70SBen Gras ascii_free(void *arg)
170d65f6f70SBen Gras {
171d65f6f70SBen Gras 
172d65f6f70SBen Gras 	term_free((struct termp *)arg);
173d65f6f70SBen Gras }
174d65f6f70SBen Gras 
175d65f6f70SBen Gras /* ARGSUSED */
176d65f6f70SBen Gras static void
ascii_letter(struct termp * p,int c)17792395e9cSLionel Sambuc ascii_letter(struct termp *p, int c)
178d65f6f70SBen Gras {
179d65f6f70SBen Gras 
180d65f6f70SBen Gras 	putchar(c);
181d65f6f70SBen Gras }
182d65f6f70SBen Gras 
183d65f6f70SBen Gras static void
ascii_begin(struct termp * p)184d65f6f70SBen Gras ascii_begin(struct termp *p)
185d65f6f70SBen Gras {
186d65f6f70SBen Gras 
187d65f6f70SBen Gras 	(*p->headf)(p, p->argf);
188d65f6f70SBen Gras }
189d65f6f70SBen Gras 
190d65f6f70SBen Gras static void
ascii_end(struct termp * p)191d65f6f70SBen Gras ascii_end(struct termp *p)
192d65f6f70SBen Gras {
193d65f6f70SBen Gras 
194d65f6f70SBen Gras 	(*p->footf)(p, p->argf);
195d65f6f70SBen Gras }
196d65f6f70SBen Gras 
197d65f6f70SBen Gras /* ARGSUSED */
198d65f6f70SBen Gras static void
ascii_endline(struct termp * p)199d65f6f70SBen Gras ascii_endline(struct termp *p)
200d65f6f70SBen Gras {
201d65f6f70SBen Gras 
202d65f6f70SBen Gras 	putchar('\n');
203d65f6f70SBen Gras }
204d65f6f70SBen Gras 
205d65f6f70SBen Gras /* ARGSUSED */
206d65f6f70SBen Gras static void
ascii_advance(struct termp * p,size_t len)207d65f6f70SBen Gras ascii_advance(struct termp *p, size_t len)
208d65f6f70SBen Gras {
209d65f6f70SBen Gras 	size_t	 	i;
210d65f6f70SBen Gras 
211d65f6f70SBen Gras 	for (i = 0; i < len; i++)
212d65f6f70SBen Gras 		putchar(' ');
213d65f6f70SBen Gras }
214d65f6f70SBen Gras 
215d65f6f70SBen Gras /* ARGSUSED */
216d65f6f70SBen Gras static double
ascii_hspan(const struct termp * p,const struct roffsu * su)217d65f6f70SBen Gras ascii_hspan(const struct termp *p, const struct roffsu *su)
218d65f6f70SBen Gras {
219d65f6f70SBen Gras 	double		 r;
220d65f6f70SBen Gras 
221d65f6f70SBen Gras 	/*
222d65f6f70SBen Gras 	 * Approximate based on character width.  These are generated
223d65f6f70SBen Gras 	 * entirely by eyeballing the screen, but appear to be correct.
224d65f6f70SBen Gras 	 */
225d65f6f70SBen Gras 
226d65f6f70SBen Gras 	switch (su->unit) {
227d65f6f70SBen Gras 	case (SCALE_CM):
228d65f6f70SBen Gras 		r = 4 * su->scale;
229d65f6f70SBen Gras 		break;
230d65f6f70SBen Gras 	case (SCALE_IN):
231d65f6f70SBen Gras 		r = 10 * su->scale;
232d65f6f70SBen Gras 		break;
233d65f6f70SBen Gras 	case (SCALE_PC):
234d65f6f70SBen Gras 		r = (10 * su->scale) / 6;
235d65f6f70SBen Gras 		break;
236d65f6f70SBen Gras 	case (SCALE_PT):
237d65f6f70SBen Gras 		r = (10 * su->scale) / 72;
238d65f6f70SBen Gras 		break;
239d65f6f70SBen Gras 	case (SCALE_MM):
240d65f6f70SBen Gras 		r = su->scale / 1000;
241d65f6f70SBen Gras 		break;
242d65f6f70SBen Gras 	case (SCALE_VS):
243d65f6f70SBen Gras 		r = su->scale * 2 - 1;
244d65f6f70SBen Gras 		break;
245d65f6f70SBen Gras 	default:
246d65f6f70SBen Gras 		r = su->scale;
247d65f6f70SBen Gras 		break;
248d65f6f70SBen Gras 	}
249d65f6f70SBen Gras 
250d65f6f70SBen Gras 	return(r);
251d65f6f70SBen Gras }
252d65f6f70SBen Gras 
25392395e9cSLionel Sambuc #ifdef USE_WCHAR
25492395e9cSLionel Sambuc /* ARGSUSED */
25592395e9cSLionel Sambuc static size_t
locale_width(const struct termp * p,int c)25692395e9cSLionel Sambuc locale_width(const struct termp *p, int c)
25792395e9cSLionel Sambuc {
25892395e9cSLionel Sambuc 	int		rc;
25992395e9cSLionel Sambuc 
26092395e9cSLionel Sambuc 	return((rc = wcwidth(c)) < 0 ? 0 : rc);
26192395e9cSLionel Sambuc }
26292395e9cSLionel Sambuc 
26392395e9cSLionel Sambuc /* ARGSUSED */
26492395e9cSLionel Sambuc static void
locale_advance(struct termp * p,size_t len)26592395e9cSLionel Sambuc locale_advance(struct termp *p, size_t len)
26692395e9cSLionel Sambuc {
26792395e9cSLionel Sambuc 	size_t	 	i;
26892395e9cSLionel Sambuc 
26992395e9cSLionel Sambuc 	for (i = 0; i < len; i++)
27092395e9cSLionel Sambuc 		putwchar(L' ');
27192395e9cSLionel Sambuc }
27292395e9cSLionel Sambuc 
27392395e9cSLionel Sambuc /* ARGSUSED */
27492395e9cSLionel Sambuc static void
locale_endline(struct termp * p)27592395e9cSLionel Sambuc locale_endline(struct termp *p)
27692395e9cSLionel Sambuc {
27792395e9cSLionel Sambuc 
27892395e9cSLionel Sambuc 	putwchar(L'\n');
27992395e9cSLionel Sambuc }
28092395e9cSLionel Sambuc 
28192395e9cSLionel Sambuc /* ARGSUSED */
28292395e9cSLionel Sambuc static void
locale_letter(struct termp * p,int c)28392395e9cSLionel Sambuc locale_letter(struct termp *p, int c)
28492395e9cSLionel Sambuc {
28592395e9cSLionel Sambuc 
28692395e9cSLionel Sambuc 	putwchar(c);
28792395e9cSLionel Sambuc }
28892395e9cSLionel Sambuc #endif
289