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