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