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