diff options
Diffstat (limited to 'src/cmd/troff/n10.c')
-rw-r--r-- | src/cmd/troff/n10.c | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/src/cmd/troff/n10.c b/src/cmd/troff/n10.c new file mode 100644 index 00000000..0183cadc --- /dev/null +++ b/src/cmd/troff/n10.c @@ -0,0 +1,549 @@ +/* +n10.c + +Device interfaces +*/ + +#include "tdef.h" +#include "ext.h" +#include "fns.h" +#include <ctype.h> + +Term t; /* terminal characteristics */ + +int dtab; +int plotmode; +int esct; + +enum { Notype = 0, Type = 1 }; + +static char *parse(char *s, int typeit) /* convert \0, etc to nroff driving table format */ +{ /* typeit => add a type id to the front for later use */ + static char buf[100], *t, *obuf; + int quote = 0; + wchar_t wc; + + obuf = typeit == Type ? buf : buf+1; +#ifdef UNICODE + if (mbtowc(&wc, s, strlen(s)) > 1) { /* it's multibyte, */ + buf[0] = MBchar; + strcpy(buf+1, s); + return obuf; + } /* so just hand it back */ +#endif /*UNICODE*/ + buf[0] = Troffchar; + t = buf + 1; + if (*s == '"') { + s++; + quote = 1; + } + for (;;) { + if (quote && *s == '"') { + s++; + break; + } + if (!quote && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\0')) + break; + if (*s != '\\') + *t++ = *s++; + else { + s++; /* skip \\ */ + if (isdigit(s[0]) && isdigit(s[1]) && isdigit(s[2])) { + *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0'; + s += 2; + } else if (isdigit(s[0])) { + *t++ = *s - '0'; + } else if (*s == 'b') { + *t++ = '\b'; + } else if (*s == 'n') { + *t++ = '\n'; + } else if (*s == 'r') { + *t++ = '\r'; + } else if (*s == 't') { + *t++ = '\t'; + } else { + *t++ = *s; + } + s++; + } + } + *t = '\0'; + return obuf; +} + + +static int getnrfont(FILE *fp) /* read the nroff description file */ +{ + FILE *fin; + Chwid chtemp[NCHARS]; + static Chwid chinit; + int i, nw, n, wid, code, type; + char buf[100], ch[100], s1[100], s2[100], cmd[300]; + wchar_t wc; + + + chinit.wid = 1; + chinit.str = ""; + for (i = 0; i < ALPHABET; i++) { + chtemp[i] = chinit; /* zero out to begin with */ + chtemp[i].num = chtemp[i].code = i; /* every alphabetic character is itself */ + chtemp[i].wid = 1; /* default ascii widths */ + } + skipline(fp); + nw = ALPHABET; + while (fgets(buf, sizeof buf, fp) != NULL) { + sscanf(buf, "%s %s %[^\n]", ch, s1, s2); + if (!eq(s1, "\"")) { /* genuine new character */ + sscanf(s1, "%d", &wid); + } /* else it's a synonym for prev character, */ + /* so leave previous values intact */ + + /* decide what kind of alphabet it might come from */ + + if (strlen(ch) == 1) { /* it's ascii */ + n = ch[0]; /* origin includes non-graphics */ + chtemp[n].num = ch[0]; + } else if (ch[0] == '\\' && ch[1] == '0') { + n = strtol(ch+1, 0, 0); /* \0octal or \0xhex */ + chtemp[n].num = n; +#ifdef UNICODE + } else if (mbtowc(&wc, ch, strlen(ch)) > 1) { + chtemp[nw].num = chadd(ch, MBchar, Install); + n = nw; + nw++; +#endif /*UNICODE*/ + } else { + if (strcmp(ch, "---") == 0) { /* no name */ + sprintf(ch, "%d", code); + type = Number; + } else + type = Troffchar; +/* BUG in here somewhere when same character occurs twice in table */ + chtemp[nw].num = chadd(ch, type, Install); + n = nw; + nw++; + } + chtemp[n].wid = wid; + chtemp[n].str = strdupl(parse(s2, Type)); + } + t.tfont.nchars = nw; + t.tfont.wp = (Chwid *) malloc(nw * sizeof(Chwid)); + if (t.tfont.wp == NULL) + return -1; + for (i = 0; i < nw; i++) + t.tfont.wp[i] = chtemp[i]; + return 1; +} + + +void n_ptinit(void) +{ + int i; + char *p, *cp; + char opt[50], cmd[100]; + FILE *fp; + + hmot = n_hmot; + makem = n_makem; + setabs = n_setabs; + setch = n_setch; + sethl = n_sethl; + setht = n_setht; + setslant = n_setslant; + vmot = n_vmot; + xlss = n_xlss; + findft = n_findft; + width = n_width; + mchbits = n_mchbits; + ptlead = n_ptlead; + ptout = n_ptout; + ptpause = n_ptpause; + setfont = n_setfont; + setps = n_setps; + setwd = n_setwd; + + if ((p = getenv("NROFFTERM")) != 0) + strcpy(devname, p); + if (termtab[0] == 0) + strcpy(termtab,DWBntermdir); + if (fontdir[0] == 0) + strcpy(fontdir, ""); + if (devname[0] == 0) + strcpy(devname, NDEVNAME); + pl = 11*INCH; + po = PO; + hyf = 0; + ascii = 1; + lg = 0; + fontlab[1] = 'R'; + fontlab[2] = 'I'; + fontlab[3] = 'B'; + fontlab[4] = PAIR('B','I'); + fontlab[5] = 'D'; + bdtab[3] = 3; + bdtab[4] = 3; + + /* hyphalg = 0; /* for testing */ + + strcat(termtab, devname); + if ((fp = fopen(unsharp(termtab), "r")) == NULL) { + ERROR "cannot open %s", termtab WARN; + exit(-1); + } + + +/* this loop isn't robust about input format errors. */ +/* it assumes name, name-value pairs..., charset */ +/* god help us if we get out of sync. */ + + fscanf(fp, "%s", cmd); /* should be device name... */ + if (!is(devname) && trace) + ERROR "wrong terminal name: saw %s, wanted %s", cmd, devname WARN; + for (;;) { + fscanf(fp, "%s", cmd); + if (is("charset")) + break; + fscanf(fp, " %[^\n]", opt); + if (is("bset")) t.bset = atoi(opt); + else if (is("breset")) t.breset = atoi(opt); + else if (is("Hor")) t.Hor = atoi(opt); + else if (is("Vert")) t.Vert = atoi(opt); + else if (is("Newline")) t.Newline = atoi(opt); + else if (is("Char")) t.Char = atoi(opt); + else if (is("Em")) t.Em = atoi(opt); + else if (is("Halfline")) t.Halfline = atoi(opt); + else if (is("Adj")) t.Adj = atoi(opt); + else if (is("twinit")) t.twinit = strdupl(parse(opt, Notype)); + else if (is("twrest")) t.twrest = strdupl(parse(opt, Notype)); + else if (is("twnl")) t.twnl = strdupl(parse(opt, Notype)); + else if (is("hlr")) t.hlr = strdupl(parse(opt, Notype)); + else if (is("hlf")) t.hlf = strdupl(parse(opt, Notype)); + else if (is("flr")) t.flr = strdupl(parse(opt, Notype)); + else if (is("bdon")) t.bdon = strdupl(parse(opt, Notype)); + else if (is("bdoff")) t.bdoff = strdupl(parse(opt, Notype)); + else if (is("iton")) t.iton = strdupl(parse(opt, Notype)); + else if (is("itoff")) t.itoff = strdupl(parse(opt, Notype)); + else if (is("ploton")) t.ploton = strdupl(parse(opt, Notype)); + else if (is("plotoff")) t.plotoff = strdupl(parse(opt, Notype)); + else if (is("up")) t.up = strdupl(parse(opt, Notype)); + else if (is("down")) t.down = strdupl(parse(opt, Notype)); + else if (is("right")) t.right = strdupl(parse(opt, Notype)); + else if (is("left")) t.left = strdupl(parse(opt, Notype)); + else + ERROR "bad tab.%s file, %s %s", devname, cmd, opt WARN; + } + + getnrfont(fp); + fclose(fp); + + sps = EM; + ics = EM * 2; + dtab = 8 * t.Em; + for (i = 0; i < 16; i++) + tabtab[i] = dtab * (i + 1); + pl = 11 * INCH; + po = PO; + spacesz = SS; + lss = lss1 = VS; + ll = ll1 = lt = lt1 = LL; + smnt = nfonts = 5; /* R I B BI S */ + n_specnames(); /* install names like "hyphen", etc. */ + if (eqflg) + t.Adj = t.Hor; +} + + +void n_specnames(void) +{ + + int i; + + for (i = 0; spnames[i].n; i++) + *spnames[i].n = chadd(spnames[i].v, Troffchar, Install); + if (c_isalnum == 0) + c_isalnum = NROFFCHARS; +} + +void twdone(void) +{ + if (!TROFF && t.twrest) { + obufp = obuf; + oputs(t.twrest); + flusho(); + if (pipeflg) { + pclose(ptid); + } + restore_tty(); + } +} + + +void n_ptout(Tchar i) +{ + *olinep++ = i; + if (olinep >= &oline[LNSIZE]) + olinep--; + if (cbits(i) != '\n') + return; + olinep--; + lead += dip->blss + lss - t.Newline; + dip->blss = 0; + esct = esc = 0; + if (olinep > oline) { + move(); + ptout1(); + oputs(t.twnl); + } else { + lead += t.Newline; + move(); + } + lead += dip->alss; + dip->alss = 0; + olinep = oline; +} + + +void ptout1(void) +{ + int k; + char *codep; + int w, j, phyw; + Tchar *q, i; + static int oxfont = FT; /* start off in roman */ + + for (q = oline; q < olinep; q++) { + i = *q; + if (ismot(i)) { + j = absmot(i); + if (isnmot(i)) + j = -j; + if (isvmot(i)) + lead += j; + else + esc += j; + continue; + } + if ((k = cbits(i)) <= ' ') { + switch (k) { + case ' ': /*space*/ + esc += t.Char; + break; + case '\033': + case '\007': + case '\016': + case '\017': + oput(k); + break; + } + continue; + } + phyw = w = t.Char * t.tfont.wp[k].wid; + if (iszbit(i)) + w = 0; + if (esc || lead) + move(); + esct += w; + xfont = fbits(i); + if (xfont != oxfont) { + switch (oxfont) { + case ULFONT: oputs(t.itoff); break; + case BDFONT: oputs(t.bdoff); break; + case BIFONT: oputs(t.itoff); oputs(t.bdoff); break; + } + switch (xfont) { + case ULFONT: + if (*t.iton & 0377) oputs(t.iton); break; + case BDFONT: + if (*t.bdon & 0377) oputs(t.bdon); break; + case BIFONT: + if (*t.bdon & 0377) oputs(t.bdon); + if (*t.iton & 0377) oputs(t.iton); + break; + } + oxfont = xfont; + } + if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) { + for (j = w / t.Char; j > 0; j--) + oput('_'); + for (j = w / t.Char; j > 0; j--) + oput('\b'); + } + if (!(*t.bdon & 0377) && ((j = bdtab[xfont]) || xfont == BDFONT || xfont == BIFONT)) + j++; + else + j = 1; /* number of overstrikes for bold */ + if (k < ALPHABET) { /* ordinary ascii */ + oput(k); + while (--j > 0) { + oput('\b'); + oput(k); + } + } else if (k >= t.tfont.nchars) { /* BUG -- not really understood */ +/* fprintf(stderr, "big char %d, name %s\n", k, chname(k)); /* */ + oputs(chname(k)+1); /* BUG: should separate Troffchar and MBchar... */ + } else if (t.tfont.wp[k].str == 0) { +/* fprintf(stderr, "nostr char %d, name %s\n", k, chname(k)); /* */ + oputs(chname(k)+1); /* BUG: should separate Troffchar and MBchar... */ + } else if (t.tfont.wp[k].str[0] == MBchar) { /* parse() puts this on */ +/* fprintf(stderr, "MBstr char %d, name %s\n", k, chname(k)); /* */ + oputs(t.tfont.wp[k].str+1); + } else { + int oj = j; +/* fprintf(stderr, "str char %d, name %s\n", k, chname(k)); /* */ + codep = t.tfont.wp[k].str+1; /* Troffchar by default */ + while (*codep != 0) { + if (*codep & 0200) { + codep = plot(codep); + oput(' '); + } else { + if (*codep == '%') /* escape */ + codep++; + oput(*codep); + if (*codep == '\033') + oput(*++codep); + else if (*codep != '\b') + for (j = oj; --j > 0; ) { + oput('\b'); + oput(*codep); + } + codep++; + } + } + } + if (!w) + for (j = phyw / t.Char; j > 0; j--) + oput('\b'); + } +} + + +char *plot(char *x) +{ + int i; + char *j, *k; + + oputs(t.ploton); + k = x; + if ((*k & 0377) == 0200) + k++; + for (; *k; k++) { + if (*k == '%') { /* quote char within plot mode */ + oput(*++k); + } else if (*k & 0200) { + if (*k & 0100) { + if (*k & 040) + j = t.up; + else + j = t.down; + } else { + if (*k & 040) + j = t.left; + else + j = t.right; + } + if ((i = *k & 037) == 0) { /* 2nd 0200 turns it off */ + ++k; + break; + } + while (i--) + oputs(j); + } else + oput(*k); + } + oputs(t.plotoff); + return(k); +} + + +void move(void) +{ + int k; + char *i, *j; + char *p, *q; + int iesct, dt; + + iesct = esct; + if (esct += esc) + i = "\0"; + else + i = "\n\0"; + j = t.hlf; + p = t.right; + q = t.down; + if (lead) { + if (lead < 0) { + lead = -lead; + i = t.flr; + /* if(!esct)i = t.flr; else i = "\0";*/ + j = t.hlr; + q = t.up; + } + if (*i & 0377) { + k = lead / t.Newline; + lead = lead % t.Newline; + while (k--) + oputs(i); + } + if (*j & 0377) { + k = lead / t.Halfline; + lead = lead % t.Halfline; + while (k--) + oputs(j); + } else { /* no half-line forward, not at line begining */ + k = lead / t.Newline; + lead = lead % t.Newline; + if (k > 0) + esc = esct; + i = "\n"; + while (k--) + oputs(i); + } + } + if (esc) { + if (esc < 0) { + esc = -esc; + j = "\b"; + p = t.left; + } else { + j = " "; + if (hflg) + while ((dt = dtab - (iesct % dtab)) <= esc) { + if (dt % t.Em) + break; + oput(TAB); + esc -= dt; + iesct += dt; + } + } + k = esc / t.Em; + esc = esc % t.Em; + while (k--) + oputs(j); + } + if ((*t.ploton & 0377) && (esc || lead)) { + oputs(t.ploton); + esc /= t.Hor; + lead /= t.Vert; + while (esc--) + oputs(p); + while (lead--) + oputs(q); + oputs(t.plotoff); + } + esc = lead = 0; +} + + +void n_ptlead(void) +{ + move(); +} + + +void n_ptpause(void ) +{ + char junk; + + flusho(); + read(2, &junk, 1); +} |