n9.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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) == 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 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 != '\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         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)) > 0 )
          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' && j != savlc) {
          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 }