Annotation of src/usr.bin/mandoc/term_ascii.c, Revision 1.8
1.8 ! schwarze 1: /* $Id: term_ascii.c,v 1.7 2011/11/13 13:05:23 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):
! 98: p->mdocstyle = 1;
! 99: p->defindent = 5;
1.1 schwarze 100: break;
101: default:
102: break;
103: }
104:
105: /* Enforce a lower boundary. */
106: if (p->defrmargin < 58)
107: p->defrmargin = 58;
108:
109: return(p);
1.2 schwarze 110: }
111:
1.6 schwarze 112: void *
113: ascii_alloc(char *outopts)
114: {
115:
116: return(ascii_init(TERMENC_ASCII, outopts));
117: }
118:
119: void *
120: utf8_alloc(char *outopts)
121: {
122:
123: return(ascii_init(TERMENC_UTF8, outopts));
124: }
125:
126:
127: void *
128: locale_alloc(char *outopts)
129: {
130:
131: return(ascii_init(TERMENC_LOCALE, outopts));
132: }
1.2 schwarze 133:
1.3 schwarze 134: /* ARGSUSED */
1.2 schwarze 135: static size_t
1.6 schwarze 136: ascii_width(const struct termp *p, int c)
1.2 schwarze 137: {
138:
139: return(1);
1.1 schwarze 140: }
141:
142: void
143: ascii_free(void *arg)
144: {
145:
146: term_free((struct termp *)arg);
147: }
148:
149: /* ARGSUSED */
150: static void
1.6 schwarze 151: ascii_letter(struct termp *p, int c)
1.1 schwarze 152: {
153:
154: putchar(c);
155: }
156:
157: static void
158: ascii_begin(struct termp *p)
159: {
160:
161: (*p->headf)(p, p->argf);
162: }
163:
164: static void
165: ascii_end(struct termp *p)
166: {
167:
168: (*p->footf)(p, p->argf);
169: }
170:
171: /* ARGSUSED */
172: static void
173: ascii_endline(struct termp *p)
174: {
175:
176: putchar('\n');
177: }
178:
179: /* ARGSUSED */
180: static void
181: ascii_advance(struct termp *p, size_t len)
182: {
183: size_t i;
184:
185: for (i = 0; i < len; i++)
186: putchar(' ');
187: }
1.3 schwarze 188:
189: /* ARGSUSED */
190: static double
191: ascii_hspan(const struct termp *p, const struct roffsu *su)
192: {
193: double r;
194:
195: /*
196: * Approximate based on character width. These are generated
197: * entirely by eyeballing the screen, but appear to be correct.
198: */
199:
200: switch (su->unit) {
201: case (SCALE_CM):
202: r = 4 * su->scale;
203: break;
204: case (SCALE_IN):
205: r = 10 * su->scale;
206: break;
207: case (SCALE_PC):
208: r = (10 * su->scale) / 6;
209: break;
210: case (SCALE_PT):
211: r = (10 * su->scale) / 72;
212: break;
213: case (SCALE_MM):
214: r = su->scale / 1000;
215: break;
216: case (SCALE_VS):
217: r = su->scale * 2 - 1;
218: break;
219: default:
220: r = su->scale;
221: break;
222: }
223:
224: return(r);
225: }
226:
1.6 schwarze 227: /* ARGSUSED */
228: static size_t
229: locale_width(const struct termp *p, int c)
230: {
231: int rc;
232:
233: return((rc = wcwidth(c)) < 0 ? 0 : rc);
234: }
235:
236: /* ARGSUSED */
237: static void
238: locale_advance(struct termp *p, size_t len)
239: {
240: size_t i;
241:
242: for (i = 0; i < len; i++)
243: putwchar(L' ');
244: }
245:
246: /* ARGSUSED */
247: static void
248: locale_endline(struct termp *p)
249: {
250:
251: putwchar(L'\n');
252: }
253:
254: /* ARGSUSED */
255: static void
256: locale_letter(struct termp *p, int c)
257: {
258:
259: putwchar(c);
260: }