n7.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
       ---
       n7.c (12546B)
       ---
            1 #define _BSD_SOURCE 1        /* isascii */
            2 #include "tdef.h"
            3 #include "fns.h"
            4 #include "ext.h"
            5 
            6 #ifdef STRICT
            7         /* not in ANSI or POSIX */
            8 #define        isascii(a) ((a) >= 0 && (a) <= 127)
            9 #endif
           10 
           11 #define GETCH gettch
           12 Tchar        gettch(void);
           13 
           14 
           15 /*
           16  * troff7.c
           17  * 
           18  * text
           19  */
           20 
           21 int        brflg;
           22 
           23 void tbreak(void)
           24 {
           25         int pad, k;
           26         Tchar *i, j;
           27         int resol;
           28         int un0 = un;
           29 
           30         trap = 0;
           31         if (nb)
           32                 return;
           33         if (dip == d && numtabp[NL].val == -1) {
           34                 newline(1);
           35                 return;
           36         }
           37         if (!nc) {
           38                 setnel();
           39                 if (!wch)
           40                         return;
           41                 if (pendw)
           42                         getword(1);
           43                 movword();
           44         } else if (pendw && !brflg) {
           45                 getword(1);
           46                 movword();
           47         }
           48         *linep = dip->nls = 0;
           49         if (NROFF && dip == d)
           50                 horiz(po);
           51         if (lnmod)
           52                 donum();
           53         lastl = ne;
           54         if (brflg != 1) {
           55                 totout = 0;
           56         } else if (ad) {
           57                 if ((lastl = ll - un) < ne)
           58                         lastl = ne;
           59         }
           60         if (admod && ad && (brflg != 2)) {
           61                 lastl = ne;
           62                 adsp = adrem = 0;
           63                 if (admod == 1)
           64                         un +=  quant(nel / 2, HOR);
           65                 else if (admod == 2)
           66                         un += nel;
           67         }
           68         totout++;
           69         brflg = 0;
           70         if (lastl + un > dip->maxl)
           71                 dip->maxl = lastl + un;
           72         horiz(un);
           73         if (NROFF) {
           74                 if (adrem % t.Adj)
           75                         resol = t.Hor; 
           76                 else 
           77                         resol = t.Adj;
           78         } else
           79                 resol = HOR;
           80 
           81         lastl = ne + (nwd-1) * adsp + adrem;
           82         for (i = line; nc > 0; ) {
           83                 if ((cbits(j = *i++)) == ' ') {
           84                         pad = 0;
           85                         do {
           86                                 pad += width(j);
           87                                 nc--;
           88                         } while ((cbits(j = *i++)) == ' ');
           89                         i--;
           90                         pad += adsp;
           91                         --nwd;
           92                         if (adrem) {
           93                                 if (adrem < 0) {
           94                                         pad -= resol;
           95                                         adrem += resol;
           96                                 } else if ((totout & 01) || adrem / resol >= nwd) {
           97                                         pad += resol;
           98                                         adrem -= resol;
           99                                 }
          100                         }
          101                         pchar((Tchar) WORDSP);
          102                         horiz(pad);
          103                 } else {
          104                         pchar(j);
          105                         nc--;
          106                 }
          107         }
          108         if (ic) {
          109                 if ((k = ll - un0 - lastl + ics) > 0)
          110                         horiz(k);
          111                 pchar(ic);
          112         }
          113         if (icf)
          114                 icf++;
          115         else 
          116                 ic = 0;
          117         ne = nwd = 0;
          118         un = in;
          119         setnel();
          120         newline(0);
          121         if (dip != d) {
          122                 if (dip->dnl > dip->hnl)
          123                         dip->hnl = dip->dnl;
          124         } else {
          125                 if (numtabp[NL].val > dip->hnl)
          126                         dip->hnl = numtabp[NL].val;
          127         }
          128         for (k = ls - 1; k > 0 && !trap; k--)
          129                 newline(0);
          130         spread = 0;
          131 }
          132 
          133 void donum(void)
          134 {
          135         int i, nw;
          136         int lnv = numtabp[LN].val;
          137 
          138         nrbits = nmbits;
          139         nw = width('1' | nrbits);
          140         if (nn) {
          141                 nn--;
          142                 goto d1;
          143         }
          144         if (lnv % ndf) {
          145                 numtabp[LN].val++;
          146 d1:
          147                 un += nw * (nmwid + nms + ni);
          148                 return;
          149         }
          150         i = 0;
          151         do {                /* count digits in numtabp[LN].val */
          152                 i++;
          153         } while ((lnv /= 10) > 0);
          154         horiz(nw * (ni + max(nmwid-i, 0)));
          155         nform = 0;
          156         fnumb(numtabp[LN].val, pchar);
          157         un += nw * nms;
          158         numtabp[LN].val++;
          159 }
          160 
          161 
          162 void text(void)
          163 {
          164         Tchar i;
          165         static int spcnt;
          166 
          167         nflush++;
          168         numtabp[HP].val = 0;
          169         if ((dip == d) && (numtabp[NL].val == -1)) {
          170                 newline(1); 
          171                 return;
          172         }
          173         setnel();
          174         if (ce || !fi) {
          175                 nofill();
          176                 return;
          177         }
          178         if (pendw)
          179                 goto t4;
          180         if (pendt)
          181                 if (spcnt)
          182                         goto t2; 
          183                 else 
          184                         goto t3;
          185         pendt++;
          186         if (spcnt)
          187                 goto t2;
          188         while ((cbits(i = GETCH())) == ' ') {
          189                 spcnt++;
          190                 numtabp[HP].val += sps;
          191                 widthp = sps;
          192         }
          193         if (nlflg) {
          194 t1:
          195                 nflush = pendt = ch = spcnt = 0;
          196                 callsp();
          197                 return;
          198         }
          199         ch = i;
          200         if (spcnt) {
          201 t2:
          202                 tbreak();
          203                 if (nc || wch)
          204                         goto rtn;
          205                 un += spcnt * sps;
          206                 spcnt = 0;
          207                 setnel();
          208                 if (trap)
          209                         goto rtn;
          210                 if (nlflg)
          211                         goto t1;
          212         }
          213 t3:
          214         if (spread)
          215                 goto t5;
          216         if (pendw || !wch)
          217 t4:
          218                 if (getword(0))
          219                         goto t6;
          220         if (!movword())
          221                 goto t3;
          222 t5:
          223         if (nlflg)
          224                 pendt = 0;
          225         adsp = adrem = 0;
          226         if (ad) {
          227                 if (nwd == 1)
          228                         adsp = nel; 
          229                 else 
          230                         adsp = nel / (nwd - 1);
          231                 adsp = (adsp / HOR) * HOR;
          232                 adrem = nel - adsp*(nwd-1);
          233         }
          234         brflg = 1;
          235         tbreak();
          236         spread = 0;
          237         if (!trap)
          238                 goto t3;
          239         if (!nlflg)
          240                 goto rtn;
          241 t6:
          242         pendt = 0;
          243         ckul();
          244 rtn:
          245         nflush = 0;
          246 }
          247 
          248 
          249 void nofill(void)
          250 {
          251         int j;
          252         Tchar i;
          253 
          254         if (!pendnf) {
          255                 over = 0;
          256                 tbreak();
          257                 if (trap)
          258                         goto rtn;
          259                 if (nlflg) {
          260                         ch = nflush = 0;
          261                         callsp();
          262                         return;
          263                 }
          264                 adsp = adrem = 0;
          265                 nwd = 10000;
          266         }
          267         while ((j = (cbits(i = GETCH()))) != '\n') {
          268                 if (j == ohc)
          269                         continue;
          270                 if (j == CONT) {
          271                         pendnf++;
          272                         nflush = 0;
          273                         flushi();
          274                         ckul();
          275                         return;
          276                 }
          277                 j = width(i);
          278                 widthp = j;
          279                 numtabp[HP].val += j;
          280                 storeline(i, j);
          281         }
          282         if (ce) {
          283                 ce--;
          284                 if ((i = quant(nel / 2, HOR)) > 0)
          285                         un += i;
          286         }
          287         if (!nc)
          288                 storeline((Tchar)FILLER, 0);
          289         brflg = 2;
          290         tbreak();
          291         ckul();
          292 rtn:
          293         pendnf = nflush = 0;
          294 }
          295 
          296 
          297 void callsp(void)
          298 {
          299         int i;
          300 
          301         if (flss)
          302                 i = flss; 
          303         else 
          304                 i = lss;
          305         flss = 0;
          306         casesp1(i);
          307 }
          308 
          309 
          310 void ckul(void)
          311 {
          312         if (ul && (--ul == 0)) {
          313                 cu = 0;
          314                 font = sfont;
          315                 mchbits();
          316         }
          317         if (it && --it == 0 && itmac)
          318                 control(itmac, 0);
          319 }
          320 
          321 
          322 void storeline(Tchar c, int w)
          323 {
          324         int diff;
          325 
          326         if (linep >= line + lnsize - 2) {
          327                 lnsize += LNSIZE;
          328                 diff = linep - line;
          329                 if (( line = (Tchar *)realloc((char *)line, lnsize * sizeof(Tchar))) != NULL) {
          330                         if (linep && diff)
          331                                 linep = line + diff;
          332                 } else {
          333                         if (over) {
          334                                 return;
          335                         } else {
          336                                 flusho();
          337                                 ERROR "Line overflow." WARN;
          338                                 over++;
          339                                 *linep++ = LEFTHAND;
          340                                 w = width(LEFTHAND);
          341                                 nc++;
          342                                 c = '\n';
          343                         }
          344                 }
          345         }
          346         *linep++ = c;
          347         ne += w;
          348         nel -= w;
          349         nc++;
          350 }
          351 
          352 
          353 void newline(int a)
          354 {
          355         int i, j, nlss;
          356         int opn;
          357 
          358         nlss = 0;
          359         if (a)
          360                 goto nl1;
          361         if (dip != d) {
          362                 j = lss;
          363                 pchar1((Tchar)FLSS);
          364                 if (flss)
          365                         lss = flss;
          366                 i = lss + dip->blss;
          367                 dip->dnl += i;
          368                 pchar1((Tchar)i);
          369                 pchar1((Tchar)'\n');
          370                 lss = j;
          371                 dip->blss = flss = 0;
          372                 if (dip->alss) {
          373                         pchar1((Tchar)FLSS);
          374                         pchar1((Tchar)dip->alss);
          375                         pchar1((Tchar)'\n');
          376                         dip->dnl += dip->alss;
          377                         dip->alss = 0;
          378                 }
          379                 if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac)
          380                         if (control(dip->dimac, 0)) {
          381                                 trap++; 
          382                                 dip->ditf++;
          383                         }
          384                 return;
          385         }
          386         j = lss;
          387         if (flss)
          388                 lss = flss;
          389         nlss = dip->alss + dip->blss + lss;
          390         numtabp[NL].val += nlss;
          391         if (TROFF && ascii) {
          392                 dip->alss = dip->blss = 0;
          393         }
          394         pchar1((Tchar)'\n');
          395         flss = 0;
          396         lss = j;
          397         if (numtabp[NL].val < pl)
          398                 goto nl2;
          399 nl1:
          400         ejf = dip->hnl = numtabp[NL].val = 0;
          401         ejl = frame;
          402         if (donef) {
          403                 if ((!nc && !wch) || ndone)
          404                         done1(0);
          405                 ndone++;
          406                 donef = 0;
          407                 if (frame == stk)
          408                         nflush++;
          409         }
          410         opn = numtabp[PN].val;
          411         numtabp[PN].val++;
          412         if (npnflg) {
          413                 numtabp[PN].val = npn;
          414                 npn = npnflg = 0;
          415         }
          416 nlpn:
          417         if (numtabp[PN].val == pfrom) {
          418                 print++;
          419                 pfrom = -1;
          420         } else if (opn == pto) {
          421                 print = 0;
          422                 opn = -1;
          423                 chkpn();
          424                 goto nlpn;
          425         }
          426         if (print)
          427                 ptpage(numtabp[PN].val);        /* supposedly in a clean state so can pause */
          428         if (stop && print) {
          429                 dpn++;
          430                 if (dpn >= stop) {
          431                         dpn = 0;
          432                         ptpause();
          433                 }
          434         }
          435 nl2:
          436         trap = 0;
          437         if (numtabp[NL].val == 0) {
          438                 if ((j = findn(0)) != NTRAP)
          439                         trap = control(mlist[j], 0);
          440         } else if ((i = findt(numtabp[NL].val - nlss)) <= nlss) {
          441                 if ((j = findn1(numtabp[NL].val - nlss + i)) == NTRAP) {
          442                         flusho();
          443                         ERROR "Trap botch." WARN;
          444                         done2(-5);
          445                 }
          446                 trap = control(mlist[j], 0);
          447         }
          448 }
          449 
          450 int
          451 findn1(int a)
          452 {
          453         int i, j;
          454 
          455         for (i = 0; i < NTRAP; i++) {
          456                 if (mlist[i]) {
          457                         if ((j = nlist[i]) < 0)
          458                                 j += pl;
          459                         if (j == a)
          460                                 break;
          461                 }
          462         }
          463         return(i);
          464 }
          465 
          466 
          467 void chkpn(void)
          468 {
          469         pto = *(pnp++);
          470         pfrom = pto>=0 ? pto : -pto;
          471         if (pto == -INT_MAX) {
          472                 flusho();
          473                 done1(0);
          474         }
          475         if (pto < 0) {
          476                 pto = -pto;
          477                 print++;
          478                 pfrom = 0;
          479         }
          480 }
          481 
          482 int
          483 findt(int a)
          484 {
          485         int i, j, k;
          486 
          487         k = INT_MAX;
          488         if (dip != d) {
          489                 if (dip->dimac && (i = dip->ditrap - a) > 0)
          490                         k = i;
          491                 return(k);
          492         }
          493         for (i = 0; i < NTRAP; i++) {
          494                 if (mlist[i]) {
          495                         if ((j = nlist[i]) < 0)
          496                                 j += pl;
          497                         if ((j -= a) <= 0)
          498                                 continue;
          499                         if (j < k)
          500                                 k = j;
          501                 }
          502         }
          503         i = pl - a;
          504         if (k > i)
          505                 k = i;
          506         return(k);
          507 }
          508 
          509 int
          510 findt1(void)
          511 {
          512         int i;
          513 
          514         if (dip != d)
          515                 i = dip->dnl;
          516         else 
          517                 i = numtabp[NL].val;
          518         return(findt(i));
          519 }
          520 
          521 
          522 void eject(Stack *a)
          523 {
          524         int savlss;
          525 
          526         if (dip != d)
          527                 return;
          528         ejf++;
          529         if (a)
          530                 ejl = a;
          531         else 
          532                 ejl = frame;
          533         if (trap)
          534                 return;
          535 e1:
          536         savlss = lss;
          537         lss = findt(numtabp[NL].val);
          538         newline(0);
          539         lss = savlss;
          540         if (numtabp[NL].val && !trap)
          541                 goto e1;
          542 }
          543 
          544 int
          545 movword(void)
          546 {
          547         int w;
          548         Tchar i, *wp;
          549         int savwch, hys;
          550 
          551         over = 0;
          552         wp = wordp;
          553         if (!nwd) {
          554                 while (cbits(*wp++) == ' ') {
          555                         wch--;
          556                         wne -= sps;
          557                 }
          558                 wp--;
          559         }
          560         if (wne > nel && !hyoff && hyf && (!nwd || nel > 3 * sps) &&
          561            (!(hyf & 02) || (findt1() > lss)))
          562                 hyphen(wp);
          563         savwch = wch;
          564         hyp = hyptr;
          565         nhyp = 0;
          566         while (*hyp && *hyp <= wp)
          567                 hyp++;
          568         while (wch) {
          569                 if (hyoff != 1 && *hyp == wp) {
          570                         hyp++;
          571                         if (!wdstart || (wp > wdstart + 1 && wp < wdend &&
          572                            (!(hyf & 04) || wp < wdend - 1) &&                /* 04 => last 2 */
          573                            (!(hyf & 010) || wp > wdstart + 2))) {        /* 010 => 1st 2 */
          574                                 nhyp++;
          575                                 storeline((Tchar)IMP, 0);
          576                         }
          577                 }
          578                 i = *wp++;
          579                 w = width(i);
          580                 wne -= w;
          581                 wch--;
          582                 storeline(i, w);
          583         }
          584         if (nel >= 0) {
          585                 nwd++;
          586                 return(0);        /* line didn't fill up */
          587         }
          588         if (TROFF)
          589                 xbits((Tchar)HYPHEN, 1);
          590         hys = width((Tchar)HYPHEN);
          591 m1:
          592         if (!nhyp) {
          593                 if (!nwd)
          594                         goto m3;
          595                 if (wch == savwch)
          596                         goto m4;
          597         }
          598         if (*--linep != IMP)
          599                 goto m5;
          600         if (!(--nhyp))
          601                 if (!nwd)
          602                         goto m2;
          603         if (nel < hys) {
          604                 nc--;
          605                 goto m1;
          606         }
          607 m2:
          608         if ((i = cbits(*(linep - 1))) != '-' && i != EMDASH) {
          609                 *linep = (*(linep - 1) & SFMASK) | HYPHEN;
          610                 w = width(*linep);
          611                 nel -= w;
          612                 ne += w;
          613                 linep++;
          614         }
          615 m3:
          616         nwd++;
          617 m4:
          618         wordp = wp;
          619         return(1);        /* line filled up */
          620 m5:
          621         nc--;
          622         w = width(*linep);
          623         ne -= w;
          624         nel += w;
          625         wne += w;
          626         wch++;
          627         wp--;
          628         goto m1;
          629 }
          630 
          631 
          632 void horiz(int i)
          633 {
          634         vflag = 0;
          635         if (i)
          636                 pchar(makem(i));
          637 }
          638 
          639 
          640 void setnel(void)
          641 {
          642         if (!nc) {
          643                 linep = line;
          644                 if (un1 >= 0) {
          645                         un = un1;
          646                         un1 = -1;
          647                 }
          648                 nel = ll - un;
          649                 ne = adsp = adrem = 0;
          650         }
          651 }
          652 
          653 int
          654 getword(int x)
          655 {
          656         int j, k;
          657         Tchar i, *wp;
          658         int noword;
          659         int obits;
          660 
          661         j = 0;
          662         noword = 0;
          663         if (x)
          664                 if (pendw) {
          665                         *pendw = 0;
          666                         goto rtn;
          667                 }
          668         if (wordp = pendw)
          669                 goto g1;
          670         hyp = hyptr;
          671         wordp = word;
          672         over = wne = wch = 0;
          673         hyoff = 0;
          674         obits = chbits;
          675         while (1) {        /* picks up 1st char of word */
          676                 j = cbits(i = GETCH());
          677                 if (j == '\n') {
          678                         wne = wch = 0;
          679                         noword = 1;
          680                         goto rtn;
          681                 }
          682                 if (j == ohc) {
          683                         hyoff = 1;        /* 1 => don't hyphenate */
          684                         continue;
          685                 }
          686                 if (j == ' ') {
          687                         numtabp[HP].val += sps;
          688                         widthp = sps;
          689                         storeword(i, sps);
          690                         continue;
          691                 }
          692                 break;
          693         }
          694         storeword(' ' | obits, sps);
          695         if (spflg) {
          696                 storeword(' ' | obits, sps);
          697                 spflg = 0;
          698         }
          699 g0:
          700         if (j == CONT) {
          701                 pendw = wordp;
          702                 nflush = 0;
          703                 flushi();
          704                 return(1);
          705         }
          706         if (hyoff != 1) {
          707                 if (j == ohc) {
          708                         hyoff = 2;
          709                         *hyp++ = wordp;
          710                         if (hyp > hyptr + NHYP - 1)
          711                                 hyp = hyptr + NHYP - 1;
          712                         goto g1;
          713                 }
          714                 if (((j == '-' || j == EMDASH)) && !(i & ZBIT))        /* zbit avoids \X */
          715                         if (wordp > word + 1) {
          716                                 hyoff = 2;
          717                                 *hyp++ = wordp + 1;
          718                                 if (hyp > hyptr + NHYP - 1)
          719                                         hyp = hyptr + NHYP - 1;
          720                         }
          721         }
          722         j = width(i);
          723         numtabp[HP].val += j;
          724         storeword(i, j);
          725 g1:
          726         j = cbits(i = GETCH());
          727         if (j != ' ') {
          728                 static char *sentchar = ".?!";        /* sentence terminators */
          729                 if (j != '\n')
          730                         goto g0;
          731                 wp = wordp-1;        /* handle extra space at end of sentence */
          732                 while (wp >= word) {
          733                         j = cbits(*wp--);
          734                         if (j=='"' || j=='\'' || j==')' || j==']' || j=='*' || j==DAGGER)
          735                                 continue;
          736                         for (k = 0; sentchar[k]; k++)
          737                                 if (j == sentchar[k]) {
          738                                         spflg++;
          739                                         break;
          740                                 }
          741                         break;
          742                 }
          743         }
          744         *wordp = 0;
          745         numtabp[HP].val += sps;
          746 rtn:
          747         for (wp = word; *wp; wp++) {
          748                 if (ismot(j))
          749                         break;        /* drechsler */
          750                 j = cbits(*wp);
          751                 if (j == ' ')
          752                         continue;
          753                 if (!(isascii(j) && isdigit(j)) && j != '-')
          754                         break;
          755         }
          756         if (*wp == 0)        /* all numbers, so don't hyphenate */
          757                 hyoff = 1;
          758         wdstart = 0;
          759         wordp = word;
          760         pendw = 0;
          761         *hyp++ = 0;
          762         setnel();
          763         return(noword);
          764 }
          765 
          766 
          767 void storeword(Tchar c, int w)
          768 {
          769         Tchar *savp;
          770         int i;
          771 
          772         if (wordp >= word + wdsize - 2) {
          773                 wdsize += WDSIZE;
          774                 savp = word;
          775                 if (( word = (Tchar *)realloc((char *)word, wdsize * sizeof(Tchar))) != NULL) {
          776                         if (wordp)
          777                                 wordp = word + (wordp - savp);
          778                         if (pendw)
          779                                 pendw = word + (pendw - savp);
          780                         if (wdstart)
          781                                 wdstart = word + (wdstart - savp);
          782                         if (wdend)
          783                                 wdend = word + (wdend - savp);
          784                         for (i = 0; i < NHYP; i++)
          785                                 if (hyptr[i])
          786                                         hyptr[i] = word + (hyptr[i] - savp);
          787                 } else {
          788                         if (over) {
          789                                 return;
          790                         } else {
          791                                 flusho();
          792                                 ERROR "Word overflow." WARN;
          793                                 over++;
          794                                 c = LEFTHAND;
          795                                 w = width(LEFTHAND);
          796                         }
          797                 }
          798         }
          799         widthp = w;
          800         wne += w;
          801         *wordp++ = c;
          802         wch++;
          803 }
          804 
          805 
          806 Tchar gettch(void)
          807 {
          808         extern int c_isalnum;
          809         Tchar i;
          810         int j;
          811 
          812         if (TROFF)
          813                 return getch();
          814 
          815         i = getch();
          816         j = cbits(i);
          817         if (ismot(i) || fbits(i) != ulfont)
          818                 return(i);
          819         if (cu) {
          820                 if (trtab[j] == ' ') {
          821                         setcbits(i, '_');
          822                         setfbits(i, FT);        /* default */
          823                 }
          824                 return(i);
          825         }
          826         /* should test here for characters that ought to be underlined */
          827         /* in the old nroff, that was the 200 bit on the width! */
          828         /* for now, just do letters, digits and certain special chars */
          829         if (j <= 127) {
          830                 if (!isalnum(j))
          831                         setfbits(i, FT);
          832         } else {
          833                 if (j < c_isalnum)
          834                         setfbits(i, FT);
          835         }
          836         return(i);
          837 }