xref: /plan9/sys/src/cmd/htmlroff/t2.c (revision 426d2b71458df9b491ba6c167f699b3f1f7b0428)
1 #include "a.h"
2 
3 /*
4  * Section 2 - Font and character size control.
5  */
6 
7 /* 2.1 - Character set */
8 /* XXX
9  *
10  * \C'name' - character named name
11  * \N'n' - character number
12  * \(xx - two-letter character
13  * \-
14  * \`
15  * \'
16  * `
17  * '
18  * -
19  */
20 
21 Rune*
getqarg(void)22 getqarg(void)
23 {
24 	static Rune buf[MaxLine];
25 	int c;
26 	Rune *p, *e;
27 
28 	p = buf;
29 	e = p+sizeof buf-1;
30 
31 	if(getrune() != '\'')
32 		return nil;
33 	while(p < e){
34 		c = getrune();
35 		if(c < 0)
36 			return nil;
37 		if(c == '\'')
38 			break;
39 		*p++ = c;
40 	}
41 	*p = 0;
42 	return buf;
43 }
44 
45 int
e_N(void)46 e_N(void)
47 {
48 	Rune *a;
49 	if((a = getqarg()) == nil)
50 		goto error;
51 	return eval(a);
52 
53 error:
54 	warn("malformed %CN'...'", backslash);
55 	return 0;
56 }
57 
58 int
e_paren(void)59 e_paren(void)
60 {
61 	int c, cc;
62 	Rune buf[2], r;
63 
64 	if((c = getrune()) < 0 || c == '\n')
65 		goto error;
66 	if((cc = getrune()) < 0 || cc == '\n')
67 		goto error;
68 	buf[0] = c;
69 	buf[1] = cc;
70 	r = troff2rune(buf);
71  	if(r == Runeerror)
72 		warn("unknown char %C(%C%C", backslash, c, cc);
73 	return r;
74 
75 error:
76 	warn("malformed %C(xx", backslash);
77 	return 0;
78 }
79 
80 /* 2.2 - Fonts */
81 Rune fonttab[10][100];
82 
83 /*
84  * \fx \f(xx \fN - font change
85  * number register .f - current font
86  * \f0 previous font (undocumented?)
87  */
88 /* change to font f.  also \fx, \f(xx, \fN */
89 /* .ft LongName is okay - temporarily at fp 0 */
90 void
ft(Rune * f)91 ft(Rune *f)
92 {
93 	int i;
94 	int fn;
95 
96 	if(f && runestrcmp(f, L("P")) == 0)
97 		f = nil;
98 	if(f == nil)
99 		fn = 0;
100 	else if(isdigit(f[0]))
101 		fn = eval(f);
102 	else{
103 		for(i=0; i<nelem(fonttab); i++){
104 			if(runestrcmp(fonttab[i], f) == 0){
105 				fn = i;
106 				goto have;
107 			}
108 		}
109 		warn("unknown font %S", f);
110 		fn = 1;
111 	}
112 have:
113 	if(fn < 0 || fn >= nelem(fonttab)){
114 		warn("unknown font %d", fn);
115 		fn = 1;
116 	}
117 	if(fn == 0)
118 		fn = getnr(L(".f0"));
119 	nr(L(".f0"), getnr(L(".f")));
120 	nr(L(".f"), fn);
121 	runmacro1(L("font"));
122 }
123 
124 /* mount font named f on physical position N */
125 void
fp(int i,Rune * f)126 fp(int i, Rune *f)
127 {
128 	if(i <= 0 || i >= nelem(fonttab)){
129 		warn("bad font position %d", i);
130 		return;
131 	}
132 	runestrecpy(fonttab[i], fonttab[i]+sizeof fonttab[i], f);
133 }
134 
135 int
e_f(void)136 e_f(void)
137 {
138 	ft(getname());
139 	return 0;
140 }
141 
142 void
r_ft(int argc,Rune ** argv)143 r_ft(int argc, Rune **argv)
144 {
145 	if(argc == 1)
146 		ft(nil);
147 	else
148 		ft(argv[1]);
149 }
150 
151 void
r_fp(int argc,Rune ** argv)152 r_fp(int argc, Rune **argv)
153 {
154 	if(argc < 3){
155 		warn("missing arguments to %Cfp", dot);
156 		return;
157 	}
158 	fp(eval(argv[1]), argv[2]);
159 }
160 
161 /* 2.3 - Character size */
162 
163 /* \H'±N' sets height */
164 
165 void
ps(int s)166 ps(int s)
167 {
168 	if(s == 0)
169 		s = getnr(L(".s0"));
170 	nr(L(".s0"), getnr(L(".s")));
171 	nr(L(".s"), s);
172 	runmacro1(L("font"));
173 }
174 
175 /* set point size */
176 void
r_ps(int argc,Rune ** argv)177 r_ps(int argc, Rune **argv)
178 {
179 	Rune *p;
180 
181 	if(argc == 1 || argv[1][0] == 0)
182 		ps(0);
183 	else{
184 		p = argv[1];
185 		if(p[0] == '-')
186 			ps(getnr(L(".s"))-eval(p+1));
187 		else if(p[0] == '+')
188 			ps(getnr(L(".s"))+eval(p+1));
189 		else
190 			ps(eval(p));
191 	}
192 }
193 
194 int
e_s(void)195 e_s(void)
196 {
197 	int c, cc, ccc, n, twodigit;
198 
199 	c = getnext();
200 	if(c < 0)
201 		return 0;
202 	if(c == '+' || c == '-'){
203 		cc = getnext();
204 		if(cc == '('){
205 			cc = getnext();
206 			ccc = getnext();
207 			if(cc < '0' || cc > '9' || ccc < '0' || ccc > '9'){
208 				warn("bad size %Cs%C(%C%C", backslash, c, cc, ccc);
209 				return 0;
210 			}
211 			n = (cc-'0')*10+ccc-'0';
212 		}else{
213 			if(cc < '0' || cc > '9'){
214 				warn("bad size %Cs%C%C", backslash, c, cc);
215 				return 0;
216 			}
217 			n = cc-'0';
218 		}
219 		if(c == '+')
220 			ps(getnr(L(".s"))+n);
221 		else
222 			ps(getnr(L(".s"))-n);
223 		return 0;
224 	}
225 	twodigit = 0;
226 	if(c == '('){
227 		twodigit = 1;
228 		c = getnext();
229 		if(c < 0)
230 			return 0;
231 	}
232 	if(c < '0' || c > '9'){
233 		warn("bad size %Cs%C", backslash, c);
234 		ungetnext(c);
235 		return 0;
236 	}
237 	if(twodigit || (c < '4' && c != '0')){
238 		cc = getnext();
239 		if(c < 0)
240 			return 0;
241 		n = (c-'0')*10+cc-'0';
242 	}else
243 		n = c-'0';
244 	ps(n);
245 	return 0;
246 }
247 
248 void
t2init(void)249 t2init(void)
250 {
251 	fp(1, L("R"));
252 	fp(2, L("I"));
253 	fp(3, L("B"));
254 	fp(4, L("BI"));
255 	fp(5, L("CW"));
256 
257 	nr(L(".s"), 10);
258 	nr(L(".s0"), 10);
259 
260 	addreq(L("ft"), r_ft, -1);
261 	addreq(L("fp"), r_fp, -1);
262 	addreq(L("ps"), r_ps, -1);
263 	addreq(L("ss"), r_warn, -1);
264 	addreq(L("cs"), r_warn, -1);
265 	addreq(L("bd"), r_warn, -1);
266 
267 	addesc('f', e_f, 0);
268 	addesc('s', e_s, 0);
269 	addesc('(', e_paren, 0);	/* ) */
270 	addesc('C', e_warn, 0);
271 	addesc('N', e_N, 0);
272 	/* \- \' \` are handled in html.c */
273 }
274 
275