]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/troff/n9.c
fix filetype detecton by suffix so that multiple dots dont confuse it. (thanks kvik)
[plan9front.git] / sys / src / cmd / troff / n9.c
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) == ROOTEN)
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
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 != '\n'; k++) {
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 <= brabuf + NC - 4) {
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 Konijnenburg, */
203                         v = VERT;       /* hvlpb!evkonij, ATT NSI Hilversum, Holland */
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 function */
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 be) */
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 from there */
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 end */
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] : (NMOT | -dx[k]));
297                         drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k]));
298                 }
299                 if (type == DRAWELLIPSE) {
300                         drawbuf[5] = drawbuf[4] | NMOT; /* so the net vertical is zero */
301                         j = 6;
302                 } else if (type == DRAWBUILD) {
303                         drawbuf[4] = drawbuf[3] | NMOT; /* net horizontal motion is zero */
304                         drawbuf[2] &= ~ZBIT;            /* width taken from drawing char */
305                         j = 5;
306                 }
307                 drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks end for ptout */
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         if (x == tabch) 
345                 rchar = tabc | chbits;
346         else if (x ==  ldrch) 
347                 rchar = dotc | chbits;
348         temp = npad = ws = 0;
349         savfc = fc;
350         savtc = tabch;
351         savlc = ldrch;
352         tabch = ldrch = fc = IMP;
353         savepos = numtabp[HP].val;
354         gchtab[tabch] &= ~TABBIT;
355         gchtab[ldrch] &= ~LDRBIT;
356         gchtab[fc] &= ~FCBIT;
357         gchtab[IMP] |= TABBIT|LDRBIT|FCBIT;
358         for (j = 0; ; j++) {
359                 if ((tabtab[j] & TABMASK) == 0) {
360                         if (x == savfc)
361                                 ERROR "zero field width." WARN;
362                         jj = 0;
363                         goto rtn;
364                 }
365                 if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val)) > 0 )
366                         break;
367         }
368         type = tabtab[j] & ~TABMASK;
369         fp = fbuf;
370         pp = padptr;
371         if (x == savfc) {
372                 while (1) {
373                         j = cbits(ii = getch());
374                         jj = width(ii);
375                         widthp = jj;
376                         numtabp[HP].val += jj;
377                         if (j == padc) {
378                                 npad++;
379                                 *pp++ = fp;
380                                 if (pp > padptr + NPP - 1)
381                                         break;
382                                 goto s1;
383                         } else if (j == savfc) 
384                                 break;
385                         else if (j == '\n') {
386                                 temp = j;
387                                 if (nlflg && ip == 0) {
388                                         numtabp[CD].val--;
389                                         nlflg = 0;
390                                 }
391                                 break;
392                         }
393                         ws += jj;
394 s1:
395                         *fp++ = ii;
396                         if (fp > fbuf + FBUFSZ - 3)
397                                 break;
398                 }
399                 if (ws)
400                         *fp++ = WORDSP;
401                 if (!npad) {
402                         npad++;
403                         *pp++ = fp;
404                         *fp++ = 0;
405                 }
406                 *fp++ = temp;
407                 *fp = 0;
408                 temp = i = (j = length - ws) / npad;
409                 i = (i / HOR) * HOR;
410                 if ((j -= i * npad) < 0)
411                         j = -j;
412                 ii = makem(i);
413                 if (temp < 0)
414                         ii |= NMOT;
415                 for (; npad > 0; npad--) {
416                         *(*--pp) = ii;
417                         if (j) {
418                                 j -= HOR;
419                                 (*(*pp)) += HOR;
420                         }
421                 }
422                 pushback(fbuf);
423                 jj = 0;
424         } else if (type == 0) {
425                 /*plain tab or leader*/
426                 if ((j = width(rchar)) > 0) {
427                         int nchar = length / j;
428                         while (nchar-->0 && pbp < &pbbuf[NC-3]) {
429                                 numtabp[HP].val += j;
430                                 widthp = j;
431                                 *pbp++ = rchar;
432                         }
433                         length %= j;
434                 }
435                 if (length)
436                         jj = length | MOT;
437                 else 
438                         jj = getch0();
439                 if (savepos > 0)
440                         pushback(wbuf);
441         } else {
442                 /*center tab*/
443                 /*right tab*/
444                 while ((j = cbits(ii = getch())) != savtc && j != '\n' && j != savlc) {
445                         jj = width(ii);
446                         ws += jj;
447                         numtabp[HP].val += jj;
448                         widthp = jj;
449                         *fp++ = ii;
450                         if (fp > fbuf + FBUFSZ - 3) 
451                                 break;
452                 }
453                 *fp++ = ii;
454                 *fp = 0;
455                 if (type == RTAB)
456                         length -= ws;
457                 else 
458                         length -= ws / 2; /*CTAB*/
459                 pushback(fbuf);
460                 if ((j = width(rchar)) != 0 && length > 0) {
461                         int nchar = length / j;
462                         while (nchar-- > 0 && pbp < &pbbuf[NC-3])
463                                 *pbp++ = rchar;
464                         length %= j;
465                 }
466                 if (savepos > 0)
467                         pushback(wbuf);
468                 length = (length / HOR) * HOR;
469                 jj = makem(length);
470                 if (nlflg) {
471                         if (ip == 0)
472                                 numtabp[CD].val--;
473                         nlflg = 0;
474                 }
475         }
476 rtn:
477         gchtab[fc] &= ~FCBIT;
478         gchtab[tabch] &= ~TABBIT;
479         gchtab[ldrch] &= ~LDRBIT;
480         fc = savfc;
481         tabch = savtc;
482         ldrch = savlc;
483         gchtab[fc] |= FCBIT;
484         gchtab[tabch] = TABBIT;
485         gchtab[ldrch] |= LDRBIT;
486         numtabp[HP].val = savepos;
487         return(jj);
488 }