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