n9.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
n9.c (9091B) | |
--- | |
1 #include "tdef.h" | |
2 #include "ext.h" | |
3 #include "fns.h" | |
4 | |
5 /* | |
6 * troff9.c | |
7 * | |
8 * misc functions | |
9 */ | |
10 | |
11 Tchar setz(void) | |
12 { | |
13 Tchar i; | |
14 | |
15 if (!ismot(i = getch())) | |
16 i |= ZBIT; | |
17 return(i); | |
18 } | |
19 | |
20 void setline(void) | |
21 { | |
22 Tchar *i; | |
23 Tchar c; | |
24 int length; | |
25 int j, w, cnt, delim, rem, temp; | |
26 Tchar linebuf[NC]; | |
27 | |
28 if (ismot(c = getch())) | |
29 return; | |
30 delim = cbits(c); | |
31 vflag = 0; | |
32 dfact = EM; | |
33 length = quant(atoi0(), HOR); | |
34 dfact = 1; | |
35 if (!length) { | |
36 eat(delim); | |
37 return; | |
38 } | |
39 s0: | |
40 if ((j = cbits(c = getch())) == delim || j == '\n') { | |
41 ch = c; | |
42 c = RULE | chbits; | |
43 } else if (cbits(c) == FILLER) | |
44 goto s0; | |
45 w = width(c); | |
46 if (w <= 0) { | |
47 ERROR "zero-width underline character ignored" WARN; | |
48 c = RULE | chbits; | |
49 w = width(c); | |
50 } | |
51 i = linebuf; | |
52 if (length < 0) { | |
53 *i++ = makem(length); | |
54 length = -length; | |
55 } | |
56 if (!(cnt = length / w)) { | |
57 *i++ = makem(-(temp = ((w - length) / 2))); | |
58 *i++ = c; | |
59 *i++ = makem(-(w - length - temp)); | |
60 goto s1; | |
61 } | |
62 if (rem = length % w) { | |
63 if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c… | |
64 *i++ = c | ZBIT; | |
65 *i++ = makem(rem); | |
66 } | |
67 if (cnt) { | |
68 *i++ = RPT; | |
69 *i++ = cnt; | |
70 *i++ = c; | |
71 } | |
72 s1: | |
73 *i = 0; | |
74 eat(delim); | |
75 pushback(linebuf); | |
76 } | |
77 | |
78 int | |
79 eat(int c) | |
80 { | |
81 int i; | |
82 | |
83 while ((i = cbits(getch())) != c && i != '\n') | |
84 ; | |
85 return(i); | |
86 } | |
87 | |
88 | |
89 void setov(void) | |
90 { | |
91 int j, k; | |
92 Tchar i, o[NOV+1]; | |
93 int delim, w[NOV+1]; | |
94 | |
95 if (ismot(i = getch())) | |
96 return; | |
97 delim = cbits(i); | |
98 for (k = 0; k < NOV && (j = cbits(i = getch())) != delim && j !=… | |
99 o[k] = i; | |
100 w[k] = width(i); | |
101 } | |
102 o[k] = w[k] = 0; | |
103 if (o[0]) | |
104 for (j = 1; j; ) { | |
105 j = 0; | |
106 for (k = 1; o[k] ; k++) { | |
107 if (w[k-1] < w[k]) { | |
108 j++; | |
109 i = w[k]; | |
110 w[k] = w[k-1]; | |
111 w[k-1] = i; | |
112 i = o[k]; | |
113 o[k] = o[k-1]; | |
114 o[k-1] = i; | |
115 } | |
116 } | |
117 } | |
118 else | |
119 return; | |
120 *pbp++ = makem(w[0] / 2); | |
121 for (k = 0; o[k]; k++) | |
122 ; | |
123 while (k>0) { | |
124 k--; | |
125 *pbp++ = makem(-((w[k] + w[k+1]) / 2)); | |
126 *pbp++ = o[k]; | |
127 } | |
128 } | |
129 | |
130 | |
131 void setbra(void) | |
132 { | |
133 int k; | |
134 Tchar i, *j, dwn; | |
135 int cnt, delim; | |
136 Tchar brabuf[NC]; | |
137 | |
138 if (ismot(i = getch())) | |
139 return; | |
140 delim = cbits(i); | |
141 j = brabuf + 1; | |
142 cnt = 0; | |
143 if (NROFF) | |
144 dwn = (2 * t.Halfline) | MOT | VMOT; | |
145 else | |
146 dwn = EM | MOT | VMOT; | |
147 while ((k = cbits(i = getch())) != delim && k != '\n' && j <= br… | |
148 *j++ = i | ZBIT; | |
149 *j++ = dwn; | |
150 cnt++; | |
151 } | |
152 if (--cnt < 0) | |
153 return; | |
154 else if (!cnt) { | |
155 ch = *(j - 2); | |
156 return; | |
157 } | |
158 *j = 0; | |
159 if (NROFF) | |
160 *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT; | |
161 else | |
162 *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT; | |
163 *--j &= ~ZBIT; | |
164 pushback(brabuf); | |
165 } | |
166 | |
167 | |
168 void setvline(void) | |
169 { | |
170 int i; | |
171 Tchar c, rem, ver, neg; | |
172 int cnt, delim, v; | |
173 Tchar vlbuf[NC]; | |
174 Tchar *vlp; | |
175 | |
176 if (ismot(c = getch())) | |
177 return; | |
178 delim = cbits(c); | |
179 dfact = lss; | |
180 vflag++; | |
181 i = quant(atoi0(), VERT); | |
182 dfact = 1; | |
183 if (!i) { | |
184 eat(delim); | |
185 vflag = 0; | |
186 return; | |
187 } | |
188 if ((cbits(c = getch())) == delim) { | |
189 c = BOXRULE | chbits; /*default box rule*/ | |
190 } else | |
191 getch(); | |
192 c |= ZBIT; | |
193 neg = 0; | |
194 if (i < 0) { | |
195 i = -i; | |
196 neg = NMOT; | |
197 } | |
198 if (NROFF) | |
199 v = 2 * t.Halfline; | |
200 else { | |
201 v = EM; | |
202 if (v < VERT) /* ATT EVK hack: Erik van K… | |
203 v = VERT; /* hvlpb!evkonij, ATT NSI Hilve… | |
204 } | |
205 | |
206 cnt = i / v; | |
207 rem = makem(i % v) | neg; | |
208 ver = makem(v) | neg; | |
209 vlp = vlbuf; | |
210 if (!neg) | |
211 *vlp++ = ver; | |
212 if (absmot(rem) != 0) { | |
213 *vlp++ = c; | |
214 *vlp++ = rem; | |
215 } | |
216 while (vlp < vlbuf + NC - 3 && cnt--) { | |
217 *vlp++ = c; | |
218 *vlp++ = ver; | |
219 } | |
220 *(vlp - 2) &= ~ZBIT; | |
221 if (!neg) | |
222 vlp--; | |
223 *vlp = 0; | |
224 pushback(vlbuf); | |
225 vflag = 0; | |
226 } | |
227 | |
228 #define NPAIR (NC/2-6) /* max pairs in spline, etc.… | |
229 | |
230 void setdraw(void) /* generate internal cookies for a drawing fun… | |
231 { | |
232 int i, j, k, dx[NPAIR], dy[NPAIR], delim, type; | |
233 Tchar c, drawbuf[NC]; | |
234 int drawch = '.'; /* character to draw with */ | |
235 | |
236 /* input is \D'f dx dy dx dy ... c' (or at least it had better b… | |
237 /* this does drawing function f with character c and the */ | |
238 /* specified dx,dy pairs interpreted as appropriate */ | |
239 /* pairs are deltas from last point, except for radii */ | |
240 | |
241 /* l dx dy: line from here by dx,dy */ | |
242 /* c x: circle of diameter x, left side here */ | |
243 /* e x y: ellipse of diameters x,y, left side here */ | |
244 /* a dx1 dy1 dx2 dy2: | |
245 ccw arc: ctr at dx1,dy1, then end at dx2,dy2 fro… | |
246 /* ~ dx1 dy1 dx2 dy2...: | |
247 spline to dx1,dy1 to dx2,dy2 ... */ | |
248 /* b x c: | |
249 built-up character of type c, ht x */ | |
250 /* f dx dy ...: f is any other char: like spline */ | |
251 | |
252 if (ismot(c = getch())) | |
253 return; | |
254 delim = cbits(c); | |
255 numerr.escarg = type = cbits(getch()); | |
256 if (type == '~') /* head off the .tr ~ problem */ | |
257 type = 's'; | |
258 for (i = 0; i < NPAIR ; i++) { | |
259 skip(); | |
260 vflag = 0; | |
261 dfact = EM; | |
262 dx[i] = quant(atoi0(), HOR); | |
263 if (dx[i] > MAXMOT) | |
264 dx[i] = MAXMOT; | |
265 else if (dx[i] < -MAXMOT) | |
266 dx[i] = -MAXMOT; | |
267 skip(); | |
268 if (type == 'c') { | |
269 dy[i] = 0; | |
270 goto eat; | |
271 } | |
272 vflag = 1; | |
273 dfact = lss; | |
274 dy[i] = quant(atoi0(), VERT); | |
275 if (dy[i] > MAXMOT) | |
276 dy[i] = MAXMOT; | |
277 else if (dy[i] < -MAXMOT) | |
278 dy[i] = -MAXMOT; | |
279 eat: | |
280 if (cbits(c = getch()) != ' ') { /* must be the e… | |
281 if (cbits(c) != delim) { | |
282 drawch = cbits(c); | |
283 getch(); | |
284 } | |
285 i++; | |
286 break; | |
287 } | |
288 } | |
289 dfact = 1; | |
290 vflag = 0; | |
291 if (TROFF) { | |
292 drawbuf[0] = DRAWFCN | chbits | ZBIT; | |
293 drawbuf[1] = type | chbits | ZBIT; | |
294 drawbuf[2] = drawch | chbits | ZBIT; | |
295 for (k = 0, j = 3; k < i; k++) { | |
296 drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NM… | |
297 drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k… | |
298 } | |
299 if (type == DRAWELLIPSE) { | |
300 drawbuf[5] = drawbuf[4] | NMOT; /* so the… | |
301 j = 6; | |
302 } else if (type == DRAWBUILD) { | |
303 drawbuf[4] = drawbuf[3] | NMOT; /* net ho… | |
304 drawbuf[2] &= ~ZBIT; /* width tak… | |
305 j = 5; | |
306 } | |
307 drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks … | |
308 drawbuf[j] = 0; | |
309 pushback(drawbuf); | |
310 } | |
311 } | |
312 | |
313 | |
314 void casefc(void) | |
315 { | |
316 int i; | |
317 Tchar j; | |
318 | |
319 gchtab[fc] &= ~FCBIT; | |
320 fc = IMP; | |
321 padc = ' '; | |
322 if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n') | |
323 return; | |
324 fc = i; | |
325 gchtab[fc] |= FCBIT; | |
326 if (skip() || ismot(ch) || (ch = cbits(ch)) == fc) | |
327 return; | |
328 padc = ch; | |
329 } | |
330 | |
331 | |
332 Tchar setfield(int x) | |
333 { | |
334 Tchar ii, jj, *fp; | |
335 int i, j; | |
336 int length, ws, npad, temp, type; | |
337 Tchar **pp, *padptr[NPP]; | |
338 Tchar fbuf[FBUFSZ]; | |
339 int savfc, savtc, savlc; | |
340 Tchar rchar; | |
341 int savepos; | |
342 static Tchar wbuf[] = { WORDSP, 0}; | |
343 | |
344 rchar = 0; | |
345 if (x == tabch) | |
346 rchar = tabc | chbits; | |
347 else if (x == ldrch) | |
348 rchar = dotc | chbits; | |
349 temp = npad = ws = 0; | |
350 savfc = fc; | |
351 savtc = tabch; | |
352 savlc = ldrch; | |
353 tabch = ldrch = fc = IMP; | |
354 savepos = numtabp[HP].val; | |
355 gchtab[tabch] &= ~TABBIT; | |
356 gchtab[ldrch] &= ~LDRBIT; | |
357 gchtab[fc] &= ~FCBIT; | |
358 gchtab[IMP] |= TABBIT|LDRBIT|FCBIT; | |
359 for (j = 0; ; j++) { | |
360 if ((tabtab[j] & TABMASK) == 0) { | |
361 if (x == savfc) | |
362 ERROR "zero field width." WARN; | |
363 jj = 0; | |
364 goto rtn; | |
365 } | |
366 if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val))… | |
367 break; | |
368 } | |
369 type = tabtab[j] & ~TABMASK; | |
370 fp = fbuf; | |
371 pp = padptr; | |
372 if (x == savfc) { | |
373 while (1) { | |
374 j = cbits(ii = getch()); | |
375 jj = width(ii); | |
376 widthp = jj; | |
377 numtabp[HP].val += jj; | |
378 if (j == padc) { | |
379 npad++; | |
380 *pp++ = fp; | |
381 if (pp > padptr + NPP - 1) | |
382 break; | |
383 goto s1; | |
384 } else if (j == savfc) | |
385 break; | |
386 else if (j == '\n') { | |
387 temp = j; | |
388 if (nlflg && ip == 0) { | |
389 numtabp[CD].val--; | |
390 nlflg = 0; | |
391 } | |
392 break; | |
393 } | |
394 ws += jj; | |
395 s1: | |
396 *fp++ = ii; | |
397 if (fp > fbuf + FBUFSZ - 3) | |
398 break; | |
399 } | |
400 if (ws) | |
401 *fp++ = WORDSP; | |
402 if (!npad) { | |
403 npad++; | |
404 *pp++ = fp; | |
405 *fp++ = 0; | |
406 } | |
407 *fp++ = temp; | |
408 *fp = 0; | |
409 temp = i = (j = length - ws) / npad; | |
410 i = (i / HOR) * HOR; | |
411 if ((j -= i * npad) < 0) | |
412 j = -j; | |
413 ii = makem(i); | |
414 if (temp < 0) | |
415 ii |= NMOT; | |
416 for (; npad > 0; npad--) { | |
417 *(*--pp) = ii; | |
418 if (j) { | |
419 j -= HOR; | |
420 (*(*pp)) += HOR; | |
421 } | |
422 } | |
423 pushback(fbuf); | |
424 jj = 0; | |
425 } else if (type == 0) { | |
426 /*plain tab or leader*/ | |
427 if ((j = width(rchar)) > 0) { | |
428 int nchar = length / j; | |
429 while (nchar-->0 && pbp < &pbbuf[NC-3]) { | |
430 numtabp[HP].val += j; | |
431 widthp = j; | |
432 *pbp++ = rchar; | |
433 } | |
434 length %= j; | |
435 } | |
436 if (length) | |
437 jj = length | MOT; | |
438 else | |
439 jj = getch0(); | |
440 if (savepos > 0) | |
441 pushback(wbuf); | |
442 } else { | |
443 /*center tab*/ | |
444 /*right tab*/ | |
445 while ((j = cbits(ii = getch())) != savtc && j != '\n' &… | |
446 jj = width(ii); | |
447 ws += jj; | |
448 numtabp[HP].val += jj; | |
449 widthp = jj; | |
450 *fp++ = ii; | |
451 if (fp > fbuf + FBUFSZ - 3) | |
452 break; | |
453 } | |
454 *fp++ = ii; | |
455 *fp = 0; | |
456 if (type == RTAB) | |
457 length -= ws; | |
458 else | |
459 length -= ws / 2; /*CTAB*/ | |
460 pushback(fbuf); | |
461 if ((j = width(rchar)) != 0 && length > 0) { | |
462 int nchar = length / j; | |
463 while (nchar-- > 0 && pbp < &pbbuf[NC-3]) | |
464 *pbp++ = rchar; | |
465 length %= j; | |
466 } | |
467 if (savepos > 0) | |
468 pushback(wbuf); | |
469 length = (length / HOR) * HOR; | |
470 jj = makem(length); | |
471 if (nlflg) { | |
472 if (ip == 0) | |
473 numtabp[CD].val--; | |
474 nlflg = 0; | |
475 } | |
476 } | |
477 rtn: | |
478 gchtab[fc] &= ~FCBIT; | |
479 gchtab[tabch] &= ~TABBIT; | |
480 gchtab[ldrch] &= ~LDRBIT; | |
481 fc = savfc; | |
482 tabch = savtc; | |
483 ldrch = savlc; | |
484 gchtab[fc] |= FCBIT; | |
485 gchtab[tabch] = TABBIT; | |
486 gchtab[ldrch] |= LDRBIT; | |
487 numtabp[HP].val = savepos; | |
488 return(jj); | |
489 } |