Annotation of src/usr.bin/mandoc/term_ascii.c, Revision 1.9
1.9 ! schwarze 1: /* $Id: term_ascii.c,v 1.8 2011/11/13 13:30:42 schwarze Exp $ */
1.1 schwarze 2: /*
1.6 schwarze 3: * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.1 schwarze 4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: #include <sys/types.h>
18:
19: #include <assert.h>
1.6 schwarze 20: #include <locale.h>
1.1 schwarze 21: #include <stdint.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <unistd.h>
1.6 schwarze 25: #include <wchar.h>
1.1 schwarze 26:
1.4 schwarze 27: #include "mandoc.h"
1.1 schwarze 28: #include "out.h"
29: #include "term.h"
30: #include "main.h"
31:
1.6 schwarze 32: static struct termp *ascii_init(enum termenc, char *);
1.3 schwarze 33: static double ascii_hspan(const struct termp *,
34: const struct roffsu *);
1.6 schwarze 35: static size_t ascii_width(const struct termp *, int);
1.3 schwarze 36: static void ascii_advance(struct termp *, size_t);
37: static void ascii_begin(struct termp *);
38: static void ascii_end(struct termp *);
1.1 schwarze 39: static void ascii_endline(struct termp *);
1.6 schwarze 40: static void ascii_letter(struct termp *, int);
1.1 schwarze 41:
1.6 schwarze 42: static void locale_advance(struct termp *, size_t);
43: static void locale_endline(struct termp *);
44: static void locale_letter(struct termp *, int);
45: static size_t locale_width(const struct termp *, int);
1.1 schwarze 46:
1.6 schwarze 47: static struct termp *
48: ascii_init(enum termenc enc, char *outopts)
1.1 schwarze 49: {
1.8 schwarze 50: const char *toks[4];
1.1 schwarze 51: char *v;
1.6 schwarze 52: struct termp *p;
1.1 schwarze 53:
1.6 schwarze 54: p = mandoc_calloc(1, sizeof(struct termp));
55: p->enc = enc;
1.1 schwarze 56:
1.2 schwarze 57: p->tabwidth = 5;
58: p->defrmargin = 78;
59:
1.1 schwarze 60: p->begin = ascii_begin;
61: p->end = ascii_end;
1.6 schwarze 62: p->hspan = ascii_hspan;
63: p->type = TERMTYPE_CHAR;
64:
65: p->enc = TERMENC_ASCII;
66: p->advance = ascii_advance;
1.1 schwarze 67: p->endline = ascii_endline;
1.3 schwarze 68: p->letter = ascii_letter;
1.2 schwarze 69: p->width = ascii_width;
1.1 schwarze 70:
1.6 schwarze 71: if (TERMENC_ASCII != enc) {
72: v = TERMENC_LOCALE == enc ?
73: setlocale(LC_ALL, "") :
74: setlocale(LC_CTYPE, "UTF-8");
75: if (NULL != v && MB_CUR_MAX > 1) {
76: p->enc = enc;
77: p->advance = locale_advance;
78: p->endline = locale_endline;
79: p->letter = locale_letter;
80: p->width = locale_width;
81: }
82: }
83:
1.7 schwarze 84: toks[0] = "indent";
85: toks[1] = "width";
1.8 schwarze 86: toks[2] = "mdoc";
87: toks[3] = NULL;
1.1 schwarze 88:
89: while (outopts && *outopts)
90: switch (getsubopt(&outopts, UNCONST(toks), &v)) {
91: case (0):
1.7 schwarze 92: p->defindent = (size_t)atoi(v);
93: break;
94: case (1):
1.1 schwarze 95: p->defrmargin = (size_t)atoi(v);
1.8 schwarze 96: break;
97: case (2):
1.9 ! schwarze 98: /*
! 99: * Temporary, undocumented mode
! 100: * to imitate mdoc(7) output style.
! 101: */
1.8 schwarze 102: p->mdocstyle = 1;
103: p->defindent = 5;
1.1 schwarze 104: break;
105: default:
106: break;
107: }
108:
109: /* Enforce a lower boundary. */
110: if (p->defrmargin < 58)
111: p->defrmargin = 58;
112:
113: return(p);
1.2 schwarze 114: }
115:
1.6 schwarze 116: void *
117: ascii_alloc(char *outopts)
118: {
119:
120: return(ascii_init(TERMENC_ASCII, outopts));
121: }
122:
123: void *
124: utf8_alloc(char *outopts)
125: {
126:
127: return(ascii_init(TERMENC_UTF8, outopts));
128: }
129:
130:
131: void *
132: locale_alloc(char *outopts)
133: {
134:
135: return(ascii_init(TERMENC_LOCALE, outopts));
136: }
1.2 schwarze 137:
1.3 schwarze 138: /* ARGSUSED */
1.2 schwarze 139: static size_t
1.6 schwarze 140: ascii_width(const struct termp *p, int c)
1.2 schwarze 141: {
142:
143: return(1);
1.1 schwarze 144: }
145:
146: void
147: ascii_free(void *arg)
148: {
149:
150: term_free((struct termp *)arg);
151: }
152:
153: /* ARGSUSED */
154: static void
1.6 schwarze 155: ascii_letter(struct termp *p, int c)
1.1 schwarze 156: {
157:
158: putchar(c);
159: }
160:
161: static void
162: ascii_begin(struct termp *p)
163: {
164:
165: (*p->headf)(p, p->argf);
166: }
167:
168: static void
169: ascii_end(struct termp *p)
170: {
171:
172: (*p->footf)(p, p->argf);
173: }
174:
175: /* ARGSUSED */
176: static void
177: ascii_endline(struct termp *p)
178: {
179:
180: putchar('\n');
181: }
182:
183: /* ARGSUSED */
184: static void
185: ascii_advance(struct termp *p, size_t len)
186: {
187: size_t i;
188:
189: for (i = 0; i < len; i++)
190: putchar(' ');
191: }
1.3 schwarze 192:
193: /* ARGSUSED */
194: static double
195: ascii_hspan(const struct termp *p, const struct roffsu *su)
196: {
197: double r;
198:
199: /*
200: * Approximate based on character width. These are generated
201: * entirely by eyeballing the screen, but appear to be correct.
202: */
203:
204: switch (su->unit) {
205: case (SCALE_CM):
206: r = 4 * su->scale;
207: break;
208: case (SCALE_IN):
209: r = 10 * su->scale;
210: break;
211: case (SCALE_PC):
212: r = (10 * su->scale) / 6;
213: break;
214: case (SCALE_PT):
215: r = (10 * su->scale) / 72;
216: break;
217: case (SCALE_MM):
218: r = su->scale / 1000;
219: break;
220: case (SCALE_VS):
221: r = su->scale * 2 - 1;
222: break;
223: default:
224: r = su->scale;
225: break;
226: }
227:
228: return(r);
229: }
230:
1.6 schwarze 231: /* ARGSUSED */
232: static size_t
233: locale_width(const struct termp *p, int c)
234: {
235: int rc;
236:
237: return((rc = wcwidth(c)) < 0 ? 0 : rc);
238: }
239:
240: /* ARGSUSED */
241: static void
242: locale_advance(struct termp *p, size_t len)
243: {
244: size_t i;
245:
246: for (i = 0; i < len; i++)
247: putwchar(L' ');
248: }
249:
250: /* ARGSUSED */
251: static void
252: locale_endline(struct termp *p)
253: {
254:
255: putwchar(L'\n');
256: }
257:
258: /* ARGSUSED */
259: static void
260: locale_letter(struct termp *p, int c)
261: {
262:
263: putwchar(c);
264: }