n10.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
       ---
       n10.c (11599B)
       ---
            1 /*
            2 n10.c
            3 
            4 Device interfaces
            5 */
            6 
            7 #include <u.h>
            8 #include "tdef.h"
            9 #include "ext.h"
           10 #include "fns.h"
           11 #include <ctype.h>
           12 
           13 Term        t;        /* terminal characteristics */
           14 
           15 int        dtab;
           16 int        plotmode;
           17 int        esct;
           18 
           19 enum        { Notype = 0, Type = 1 };
           20 
           21 static char *parse(char *s, int typeit)        /* convert \0, etc to nroff driving table format */
           22 {                /* typeit => add a type id to the front for later use */
           23         static char buf[100], *t, *obuf;
           24         int quote = 0;
           25         wchar_t wc;
           26 
           27         obuf = typeit == Type ? buf : buf+1;
           28 #ifdef UNICODE
           29         if (mbtowc(&wc, s, strlen(s)) > 1) {        /* it's multibyte, */
           30                 buf[0] = MBchar;
           31                 strcpy(buf+1, s);
           32                 return obuf;
           33         }                        /* so just hand it back */
           34 #endif        /*UNICODE*/
           35         buf[0] = Troffchar;
           36         t = buf + 1;
           37         if (*s == '"') {
           38                 s++;
           39                 quote = 1;
           40         }
           41         for (;;) {
           42                 if (quote && *s == '"') {
           43                         s++;
           44                         break;
           45                 }
           46                 if (!quote && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\0'))
           47                         break;
           48                 if (*s != '\\')
           49                         *t++ = *s++;
           50                 else {
           51                         s++;        /* skip \\ */
           52                         if (isdigit((uchar)s[0]) && isdigit((uchar)s[1]) && isdigit((uchar)s[2])) {
           53                                 *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0';
           54                                 s += 2;
           55                         } else if (isdigit((uchar)s[0])) {
           56                                 *t++ = *s - '0';
           57                         } else if (*s == 'b') {
           58                                 *t++ = '\b';
           59                         } else if (*s == 'n') {
           60                                 *t++ = '\n';
           61                         } else if (*s == 'r') {
           62                                 *t++ = '\r';
           63                         } else if (*s == 't') {
           64                                 *t++ = '\t';
           65                         } else {
           66                                 *t++ = *s;
           67                         }
           68                         s++;
           69                 }
           70         }
           71         *t = '\0';
           72         return obuf;
           73 }
           74 
           75 
           76 static int getnrfont(FILE *fp)        /* read the nroff description file */
           77 {
           78         Chwid chtemp[NCHARS];
           79         static Chwid chinit;
           80         int i, nw, n, wid, code, type;
           81         char buf[100], ch[100], s1[100], s2[100];
           82         wchar_t wc;
           83 
           84         code = 0;
           85         chinit.wid = 1;
           86         chinit.str = "";
           87         for (i = 0; i < ALPHABET; i++) {
           88                 chtemp[i] = chinit;        /* zero out to begin with */
           89                 chtemp[i].num = chtemp[i].code = i;        /* every alphabetic character is itself */
           90                 chtemp[i].wid = 1;        /* default ascii widths */
           91         }
           92         skipline(fp);
           93         nw = ALPHABET;
           94         while (fgets(buf, sizeof buf, fp) != NULL) {
           95                 sscanf(buf, "%s %s %[^\n]", ch, s1, s2);
           96                 if (!eq(s1, "\"")) {        /* genuine new character */
           97                         sscanf(s1, "%d", &wid);
           98                 } /* else it's a synonym for prev character, */
           99                         /* so leave previous values intact */
          100 
          101                 /* decide what kind of alphabet it might come from */
          102 
          103                 if (strlen(ch) == 1) {        /* it's ascii */
          104                         n = ch[0];        /* origin includes non-graphics */
          105                         chtemp[n].num = ch[0];
          106                 } else if (ch[0] == '\\' && ch[1] == '0') {
          107                         n = strtol(ch+1, 0, 0);        /* \0octal or \0xhex */
          108                         chtemp[n].num = n;
          109 #ifdef UNICODE
          110                 } else if (mbtowc(&wc, ch, strlen(ch)) > 1) {
          111                         chtemp[nw].num = chadd(ch, MBchar, Install);
          112                         n = nw;
          113                         nw++;
          114 #endif        /*UNICODE*/
          115                 } else {
          116                         if (strcmp(ch, "---") == 0) { /* no name */
          117                                 sprintf(ch, "%d", code);
          118                                 type = Number;
          119                         } else
          120                                 type = Troffchar;
          121 /* BUG in here somewhere when same character occurs twice in table */
          122                         chtemp[nw].num = chadd(ch, type, Install);
          123                         n = nw;
          124                         nw++;
          125                 }
          126                 chtemp[n].wid = wid;
          127                 chtemp[n].str = strdupl(parse(s2, Type));
          128         }
          129         t.tfont.nchars = nw;
          130         t.tfont.wp = (Chwid *) malloc(nw * sizeof(Chwid));
          131         if (t.tfont.wp == NULL)
          132                 return -1;
          133         for (i = 0; i < nw; i++)
          134                 t.tfont.wp[i] = chtemp[i];
          135         return 1;
          136 }
          137 
          138 
          139 void n_ptinit(void)
          140 {
          141         int i;
          142         char *p;
          143         char opt[50], cmd[100];
          144         FILE *fp;
          145 
          146         hmot = n_hmot;
          147         makem = n_makem;
          148         setabs = n_setabs;
          149         setch = n_setch;
          150         sethl = n_sethl;
          151         setht = n_setht;
          152         setslant = n_setslant;
          153         vmot = n_vmot;
          154         xlss = n_xlss;
          155         findft = n_findft;
          156         width = n_width;
          157         mchbits = n_mchbits;
          158         ptlead = n_ptlead;
          159         ptout = n_ptout;
          160         ptpause = n_ptpause;
          161         setfont = n_setfont;
          162         setps = n_setps;
          163         setwd = n_setwd;
          164 
          165         if ((p = getenv("NROFFTERM")) != 0)
          166                 strcpy(devname, p);
          167         if (termtab[0] == 0)
          168                 strcpy(termtab,DWBntermdir);
          169         if (fontdir[0] == 0)
          170                 strcpy(fontdir, "");
          171         if (devname[0] == 0)
          172                 strcpy(devname, NDEVNAME);
          173         pl = 11*INCH;
          174         po = PO;
          175         hyf = 0;
          176         ascii = 1;
          177         lg = 0;
          178         fontlab[1] = 'R';
          179         fontlab[2] = 'I';
          180         fontlab[3] = 'B';
          181         fontlab[4] = PAIR('B','I');
          182         fontlab[5] = 'D';
          183         bdtab[3] = 3;
          184         bdtab[4] = 3;
          185 
          186         /* hyphalg = 0;        /* for testing */
          187 
          188         strcat(termtab, devname);
          189         if ((fp = fopen(unsharp(termtab), "r")) == NULL) {
          190                 ERROR "cannot open %s", termtab WARN;
          191                 exit(-1);
          192         }
          193 
          194 
          195 /* this loop isn't robust about input format errors. */
          196 /* it assumes  name, name-value pairs..., charset */
          197 /* god help us if we get out of sync. */
          198 
          199         fscanf(fp, "%s", cmd);        /* should be device name... */
          200         if (!is(devname) && trace)
          201                 ERROR "wrong terminal name: saw %s, wanted %s", cmd, devname WARN;
          202         for (;;) {
          203                 fscanf(fp, "%s", cmd);
          204                 if (is("charset"))
          205                         break;
          206                 fscanf(fp, " %[^\n]", opt);
          207                 if (is("bset")) t.bset = atoi(opt);
          208                 else if (is("breset")) t.breset = atoi(opt);
          209                 else if (is("Hor")) t.Hor = atoi(opt);
          210                 else if (is("Vert")) t.Vert = atoi(opt);
          211                 else if (is("Newline")) t.Newline = atoi(opt);
          212                 else if (is("Char")) t.Char = atoi(opt);
          213                 else if (is("Em")) t.Em = atoi(opt);
          214                 else if (is("Halfline")) t.Halfline = atoi(opt);
          215                 else if (is("Adj")) t.Adj = atoi(opt);
          216                 else if (is("twinit")) t.twinit = strdupl(parse(opt, Notype));
          217                 else if (is("twrest")) t.twrest = strdupl(parse(opt, Notype));
          218                 else if (is("twnl")) t.twnl = strdupl(parse(opt, Notype));
          219                 else if (is("hlr")) t.hlr = strdupl(parse(opt, Notype));
          220                 else if (is("hlf")) t.hlf = strdupl(parse(opt, Notype));
          221                 else if (is("flr")) t.flr = strdupl(parse(opt, Notype));
          222                 else if (is("bdon")) t.bdon = strdupl(parse(opt, Notype));
          223                 else if (is("bdoff")) t.bdoff = strdupl(parse(opt, Notype));
          224                 else if (is("iton")) t.iton = strdupl(parse(opt, Notype));
          225                 else if (is("itoff")) t.itoff = strdupl(parse(opt, Notype));
          226                 else if (is("ploton")) t.ploton = strdupl(parse(opt, Notype));
          227                 else if (is("plotoff")) t.plotoff = strdupl(parse(opt, Notype));
          228                 else if (is("up")) t.up = strdupl(parse(opt, Notype));
          229                 else if (is("down")) t.down = strdupl(parse(opt, Notype));
          230                 else if (is("right")) t.right = strdupl(parse(opt, Notype));
          231                 else if (is("left")) t.left = strdupl(parse(opt, Notype));
          232                 else
          233                         ERROR "bad tab.%s file, %s %s", devname, cmd, opt WARN;
          234         }
          235 
          236         getnrfont(fp);
          237         fclose(fp);
          238 
          239         sps = EM;
          240         ics = EM * 2;
          241         dtab = 8 * t.Em;
          242         for (i = 0; i < 16; i++)
          243                 tabtab[i] = dtab * (i + 1);
          244         pl = 11 * INCH;
          245         po = PO;
          246         spacesz = SS;
          247         lss = lss1 = VS;
          248         ll = ll1 = lt = lt1 = LL;
          249         smnt = nfonts = 5;        /* R I B BI S */
          250         n_specnames();        /* install names like "hyphen", etc. */
          251         if (eqflg)
          252                 t.Adj = t.Hor;
          253 }
          254 
          255 
          256 void n_specnames(void)
          257 {
          258 
          259         int        i;
          260 
          261         for (i = 0; spnames[i].n; i++)
          262                 *spnames[i].n = chadd(spnames[i].v, Troffchar, Install);
          263         if (c_isalnum == 0)
          264                 c_isalnum = NROFFCHARS;
          265 }
          266 
          267 void twdone(void)
          268 {
          269         if (!TROFF && t.twrest) {
          270                 obufp = obuf;
          271                 oputs(t.twrest);
          272                 flusho();
          273                 if (pipeflg) {
          274                         pclose(ptid);
          275                 }
          276                 restore_tty();
          277         }
          278 }
          279 
          280 
          281 void n_ptout(Tchar i)
          282 {
          283         *olinep++ = i;
          284         if (olinep >= &oline[LNSIZE])
          285                 olinep--;
          286         if (cbits(i) != '\n')
          287                 return;
          288         olinep--;
          289         lead += dip->blss + lss - t.Newline;
          290         dip->blss = 0;
          291         esct = esc = 0;
          292         if (olinep > oline) {
          293                 move();
          294                 ptout1();
          295                 oputs(t.twnl);
          296         } else {
          297                 lead += t.Newline;
          298                 move();
          299         }
          300         lead += dip->alss;
          301         dip->alss = 0;
          302         olinep = oline;
          303 }
          304 
          305 
          306 void ptout1(void)
          307 {
          308         int k;
          309         char *codep;
          310         int w, j, phyw;
          311         Tchar *q, i;
          312         static int oxfont = FT;        /* start off in roman */
          313 
          314         for (q = oline; q < olinep; q++) {
          315                 i = *q;
          316                 if (ismot(i)) {
          317                         j = absmot(i);
          318                         if (isnmot(i))
          319                                 j = -j;
          320                         if (isvmot(i))
          321                                 lead += j;
          322                         else 
          323                                 esc += j;
          324                         continue;
          325                 }
          326                 if ((k = cbits(i)) <= ' ') {
          327                         switch (k) {
          328                         case ' ': /*space*/
          329                                 esc += t.Char;
          330                                 break;
          331                         case '\033':
          332                         case '\007':
          333                         case '\016':
          334                         case '\017':
          335                                 oput(k);
          336                                 break;
          337                         }
          338                         continue;
          339                 }
          340                 phyw = w = t.Char * t.tfont.wp[k].wid;
          341                 if (iszbit(i))
          342                         w = 0;
          343                 if (esc || lead)
          344                         move();
          345                 esct += w;
          346                 xfont = fbits(i);
          347                 if (xfont != oxfont) {
          348                         switch (oxfont) {
          349                         case ULFONT:        oputs(t.itoff); break;
          350                         case BDFONT:        oputs(t.bdoff); break;
          351                         case BIFONT:        oputs(t.itoff); oputs(t.bdoff); break;
          352                         }
          353                         switch (xfont) {
          354                         case ULFONT:
          355                                 if (*t.iton & 0377) oputs(t.iton); break;
          356                         case BDFONT:
          357                                 if (*t.bdon & 0377) oputs(t.bdon); break;
          358                         case BIFONT:
          359                                 if (*t.bdon & 0377) oputs(t.bdon);
          360                                 if (*t.iton & 0377) oputs(t.iton);
          361                                 break;
          362                         }
          363                         oxfont = xfont;
          364                 }
          365                 if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) {
          366                         for (j = w / t.Char; j > 0; j--)
          367                                 oput('_');
          368                         for (j = w / t.Char; j > 0; j--)
          369                                 oput('\b');
          370                 }
          371                 if (!(*t.bdon & 0377) && ((j = bdtab[xfont]) || xfont == BDFONT || xfont == BIFONT))
          372                         j++;
          373                 else
          374                         j = 1;        /* number of overstrikes for bold */
          375                 if (k < ALPHABET) {        /* ordinary ascii */
          376                         oput(k);
          377                         while (--j > 0) {
          378                                 oput('\b');
          379                                 oput(k);
          380                         }
          381                 } else if (k >= t.tfont.nchars) {        /* BUG -- not really understood */
          382 /* fprintf(stderr, "big char %d, name %s\n", k, chname(k)); /* */
          383                         oputs(chname(k)+1);        /* BUG: should separate Troffchar and MBchar... */
          384                 } else if (t.tfont.wp[k].str == 0) {
          385 /* fprintf(stderr, "nostr char %d, name %s\n", k, chname(k)); /* */
          386                         oputs(chname(k)+1);        /* BUG: should separate Troffchar and MBchar... */
          387                 } else if (t.tfont.wp[k].str[0] == MBchar) {        /* parse() puts this on */
          388 /* fprintf(stderr, "MBstr char %d, name %s\n", k, chname(k)); /* */
          389                         oputs(t.tfont.wp[k].str+1);
          390                 } else {
          391                         int oj = j;
          392 /* fprintf(stderr, "str char %d, name %s\n", k, chname(k)); /* */
          393                         codep = t.tfont.wp[k].str+1;        /* Troffchar by default */
          394                         while (*codep != 0) {
          395                                 if (*codep & 0200) {
          396                                         codep = plot(codep);
          397                                         oput(' ');
          398                                 } else {
          399                                         if (*codep == '%')        /* escape */
          400                                                 codep++;
          401                                         oput(*codep);
          402                                         if (*codep == '\033')
          403                                                 oput(*++codep);
          404                                         else if (*codep != '\b')
          405                                                 for (j = oj; --j > 0; ) {
          406                                                         oput('\b');
          407                                                         oput(*codep);
          408                                                 }
          409                                         codep++;
          410                                 }
          411                         }
          412                 }
          413                 if (!w)
          414                         for (j = phyw / t.Char; j > 0; j--)
          415                                 oput('\b');
          416         }
          417 }
          418 
          419 
          420 char *plot(char *x)
          421 {
          422         int        i;
          423         char        *j, *k;
          424 
          425         oputs(t.ploton);
          426         k = x;
          427         if ((*k & 0377) == 0200)
          428                 k++;
          429         for (; *k; k++) {
          430                 if (*k == '%') {        /* quote char within plot mode */
          431                         oput(*++k);
          432                 } else if (*k & 0200) {
          433                         if (*k & 0100) {
          434                                 if (*k & 040)
          435                                         j = t.up; 
          436                                 else 
          437                                         j = t.down;
          438                         } else {
          439                                 if (*k & 040)
          440                                         j = t.left; 
          441                                 else 
          442                                         j = t.right;
          443                         }
          444                         if ((i = *k & 037) == 0) {        /* 2nd 0200 turns it off */
          445                                 ++k;
          446                                 break;
          447                         }
          448                         while (i--)
          449                                 oputs(j);
          450                 } else 
          451                         oput(*k);
          452         }
          453         oputs(t.plotoff);
          454         return(k);
          455 }
          456 
          457 
          458 void move(void)
          459 {
          460         int k;
          461         char *i, *j;
          462         char *p, *q;
          463         int iesct, dt;
          464 
          465         iesct = esct;
          466         if (esct += esc)
          467                 i = "\0"; 
          468         else 
          469                 i = "\n\0";
          470         j = t.hlf;
          471         p = t.right;
          472         q = t.down;
          473         if (lead) {
          474                 if (lead < 0) {
          475                         lead = -lead;
          476                         i = t.flr;
          477                         /*        if(!esct)i = t.flr; else i = "\0";*/
          478                         j = t.hlr;
          479                         q = t.up;
          480                 }
          481                 if (*i & 0377) {
          482                         k = lead / t.Newline;
          483                         lead = lead % t.Newline;
          484                         while (k--)
          485                                 oputs(i);
          486                 }
          487                 if (*j & 0377) {
          488                         k = lead / t.Halfline;
          489                         lead = lead % t.Halfline;
          490                         while (k--)
          491                                 oputs(j);
          492                 } else { /* no half-line forward, not at line begining */
          493                         k = lead / t.Newline;
          494                         lead = lead % t.Newline;
          495                         if (k > 0) 
          496                                 esc = esct;
          497                         i = "\n";
          498                         while (k--) 
          499                                 oputs(i);
          500                 }
          501         }
          502         if (esc) {
          503                 if (esc < 0) {
          504                         esc = -esc;
          505                         j = "\b";
          506                         p = t.left;
          507                 } else {
          508                         j = " ";
          509                         if (hflg)
          510                                 while ((dt = dtab - (iesct % dtab)) <= esc) {
          511                                         if (dt % t.Em)
          512                                                 break;
          513                                         oput(TAB);
          514                                         esc -= dt;
          515                                         iesct += dt;
          516                                 }
          517                 }
          518                 k = esc / t.Em;
          519                 esc = esc % t.Em;
          520                 while (k--)
          521                         oputs(j);
          522         }
          523         if ((*t.ploton & 0377) && (esc || lead)) {
          524                 oputs(t.ploton);
          525                 esc /= t.Hor;
          526                 lead /= t.Vert;
          527                 while (esc--)
          528                         oputs(p);
          529                 while (lead--)
          530                         oputs(q);
          531                 oputs(t.plotoff);
          532         }
          533         esc = lead = 0;
          534 }
          535 
          536 
          537 void n_ptlead(void)
          538 {
          539         move();
          540 }
          541 
          542 
          543 void n_ptpause(void )
          544 {
          545         char        junk;
          546 
          547         flusho();
          548         read(2, &junk, 1);
          549 }