]> git.cameronkatri.com Git - mandoc.git/blob - term_ascii.c
5b2ee847aca070d405092ad4ba3e6a53eed3b291
[mandoc.git] / term_ascii.c
1 /* $Id: term_ascii.c,v 1.14 2011/05/17 14:38:34 kristaps Exp $ */
2 /*
3 * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
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 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <sys/types.h>
22
23 #include <assert.h>
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28
29 #include "mandoc.h"
30 #include "out.h"
31 #include "term.h"
32 #include "main.h"
33
34 static struct termp *ascii_init(enum termenc, char *);
35 static double ascii_hspan(const struct termp *,
36 const struct roffsu *);
37 static size_t ascii_width(const struct termp *, int);
38 static void ascii_advance(struct termp *, size_t);
39 static void ascii_begin(struct termp *);
40 static void ascii_end(struct termp *);
41 static void ascii_endline(struct termp *);
42 static void ascii_letter(struct termp *, int);
43
44 static struct termp *
45 ascii_init(enum termenc enc, char *outopts)
46 {
47 const char *toks[2];
48 char *v;
49 struct termp *p;
50
51 p = mandoc_calloc(1, sizeof(struct termp));
52 p->enc = enc;
53
54 p->tabwidth = 5;
55 p->defrmargin = 78;
56
57 p->advance = ascii_advance;
58 p->begin = ascii_begin;
59 p->end = ascii_end;
60 p->endline = ascii_endline;
61 p->hspan = ascii_hspan;
62 p->letter = ascii_letter;
63 p->type = TERMTYPE_CHAR;
64 p->width = ascii_width;
65
66 toks[0] = "width";
67 toks[1] = NULL;
68
69 while (outopts && *outopts)
70 switch (getsubopt(&outopts, UNCONST(toks), &v)) {
71 case (0):
72 p->defrmargin = (size_t)atoi(v);
73 break;
74 default:
75 break;
76 }
77
78 /* Enforce a lower boundary. */
79 if (p->defrmargin < 58)
80 p->defrmargin = 58;
81
82 return(p);
83 }
84
85 void *
86 ascii_alloc(char *outopts)
87 {
88
89 return(ascii_init(TERMENC_ASCII, outopts));
90 }
91
92 void *
93 locale_alloc(char *outopts)
94 {
95
96 return(ascii_init(TERMENC_LOCALE, outopts));
97 }
98
99 /* ARGSUSED */
100 static size_t
101 ascii_width(const struct termp *p, int c)
102 {
103
104 return(1);
105 }
106
107
108 void
109 ascii_free(void *arg)
110 {
111
112 term_free((struct termp *)arg);
113 }
114
115
116 /* ARGSUSED */
117 static void
118 ascii_letter(struct termp *p, int c)
119 {
120
121 /* LINTED */
122 putchar(c);
123 }
124
125
126 static void
127 ascii_begin(struct termp *p)
128 {
129
130 (*p->headf)(p, p->argf);
131 }
132
133
134 static void
135 ascii_end(struct termp *p)
136 {
137
138 (*p->footf)(p, p->argf);
139 }
140
141
142 /* ARGSUSED */
143 static void
144 ascii_endline(struct termp *p)
145 {
146
147 putchar('\n');
148 }
149
150
151 /* ARGSUSED */
152 static void
153 ascii_advance(struct termp *p, size_t len)
154 {
155 size_t i;
156
157 /* Just print whitespace on the terminal. */
158 for (i = 0; i < len; i++)
159 putchar(' ');
160 }
161
162
163 /* ARGSUSED */
164 static double
165 ascii_hspan(const struct termp *p, const struct roffsu *su)
166 {
167 double r;
168
169 /*
170 * Approximate based on character width. These are generated
171 * entirely by eyeballing the screen, but appear to be correct.
172 */
173
174 switch (su->unit) {
175 case (SCALE_CM):
176 r = 4 * su->scale;
177 break;
178 case (SCALE_IN):
179 r = 10 * su->scale;
180 break;
181 case (SCALE_PC):
182 r = (10 * su->scale) / 6;
183 break;
184 case (SCALE_PT):
185 r = (10 * su->scale) / 72;
186 break;
187 case (SCALE_MM):
188 r = su->scale / 1000;
189 break;
190 case (SCALE_VS):
191 r = su->scale * 2 - 1;
192 break;
193 default:
194 r = su->scale;
195 break;
196 }
197
198 return(r);
199 }
200