diff options
Diffstat (limited to 'src/cmd/troff/t6.c')
-rw-r--r-- | src/cmd/troff/t6.c | 881 |
1 files changed, 881 insertions, 0 deletions
diff --git a/src/cmd/troff/t6.c b/src/cmd/troff/t6.c new file mode 100644 index 00000000..b778916c --- /dev/null +++ b/src/cmd/troff/t6.c @@ -0,0 +1,881 @@ +/* + * t6.c + * + * width functions, sizes and fonts + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +int fontlab[MAXFONTS+1]; +int cstab[MAXFONTS+1]; +int ccstab[MAXFONTS+1]; +int bdtab[MAXFONTS+1]; +int sbold = 0; + +t_width(Tchar j) +{ + int i, k; + + if (iszbit(j)) + return 0; + if (ismot(j)) { + if (isvmot(j)) + return(0); + k = absmot(j); + if (isnmot(j)) + k = -k; + return(k); + } + i = cbits(j); + if (i < ' ') { + if (i == '\b') + return(-widthp); + if (i == PRESC) + i = eschar; + else if (i == HX) + return(0); + } + if (i == ohc) + return(0); + i = trtab[i]; + if (i < ' ') + return(0); + if (sfbits(j) == oldbits) { + xfont = pfont; + xpts = ppts; + } else + xbits(j, 0); + if (i < nchnames + ALPHABET && widcache[i].fontpts == (xfont<<8) + xpts && !setwdf) + k = widcache[i].width; + else { + k = getcw(i); + if (bd) + k += (bd - 1) * HOR; + if (cs) + k = cs; + } + widthp = k; + return(k); +} + +/* + * clear width cache-- s means just space + */ +void zapwcache(int s) +{ + int i; + + if (s) { + widcache[' '].fontpts = 0; + return; + } + for (i=0; i<NWIDCACHE; i++) + widcache[i].fontpts = 0; +} + +onfont(int n, int f) /* is char n on font f? */ +{ + int i; + Font *fp = &fonts[f]; + Chwid *cp, *ep; + char *np; + + if (n < ALPHABET) { + if (fp->wp[n].num == n) /* ascii at front */ + return n; + else + return -1; + } + cp = &fp->wp[ALPHABET]; + ep = &fp->wp[fp->nchars]; + for ( ; cp < ep; cp++) /* search others */ + if (cp->num == n) + return cp - &fp->wp[0]; + /* maybe it was a \N... */ + np = chname(n); + if (*np == Number) { + i = atoi(np+1); /* sscanf(np+1, "%d", &i); */ + cp = &fp->wp[0]; + ep = &fp->wp[fp->nchars]; + for ( ; cp < ep; cp++) { /* search others */ + if (cp->code == i) + return cp - &fp->wp[0]; + } + return -2; /* a \N that doesn't have an entry */ + } + return -1; /* vanilla not found */ +} + +getcw(int i) +{ + int k, n, x; + Font *fp; + int nocache = 0; + if (i < ' ') + return 0; + bd = 0; + fp = &fonts[xfont]; + if (i == ' ') { /* a blank */ + k = (fp->spacewidth * spacesz + 6) / 12; + /* this nonsense because .ss cmd uses 1/36 em as its units */ + /* and default is 12 */ + } else if ((n = onfont(i, xfont)) >= 0) { /* on this font at n */ + k = fp->wp[n].wid; + if (setwdf) + numtabp[CT].val |= fp->wp[n].kern; + } else if (n == -2) { /* \N with default width */ + + k = fp->defaultwidth; + } else { /* not on current font */ + nocache = 1; + k = fp->defaultwidth; /* default-size space */ + if (smnt) { + int ii, jj; + for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) { + if ((n = onfont(i, ii)) >= 0) { + k = fonts[ii].wp[n].wid; + if (xfont == sbold) + bd = bdtab[ii]; + if (setwdf) + numtabp[CT].val |= fonts[ii].wp[n].kern; + break; + } + } + } + } + if (!bd) + bd = bdtab[xfont]; + if (cs = cstab[xfont]) { + nocache = 1; + if (ccs = ccstab[xfont]) + x = ccs; + else + x = xpts; + cs = (cs * EMPTS(x)) / 36; + } + /* was (k & BYTEMASK); since .wid is unsigned, should never happen */ + if (k < 0) + ERROR "can't happen: negative width %d in getcw %d\n", k, i WARN; + k = (k * xpts + (Unitwidth / 2)) / Unitwidth; + if (nocache|bd) + widcache[i].fontpts = 0; + else { + widcache[i].fontpts = (xfont<<8) + xpts; + widcache[i].width = k; + } + return(k); + /* Unitwidth is Units/Point, where + /* Units is the fundamental digitization + /* of the character set widths, and + /* Point is the number of goobies in a point + /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6 + /* In effect, it's the size at which the widths + /* translate directly into units. + */ +} + +void xbits(Tchar i, int bitf) +{ + int k; + + if(TROFF) { + xfont = fbits(i); + k = sbits(i); + if(k) { + xpts = pstab[k-1]; + oldbits = sfbits(i); + pfont = xfont; + ppts = xpts; + return; + } + switch(bitf) { + case 0: + xfont = font; + xpts = pts; + break; + case 1: + xfont = pfont; + xpts = ppts; + break; + case 2: + xfont = mfont; + xpts = mpts; + } + } +} + + +/* these next two functions ought to be the same in troff and nroff, */ +/* but the data structures they search are different. */ +/* silly historical problem. */ + + +Tchar t_setch(int c) +{ + int j; + char temp[50]; + char *s; + + s = temp; + if (c == '(') { /* \(xx */ + if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0) + return(0); + } else { /* \C'...' */ + c = getach(); + while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1) + s++; + } + *s = '\0'; +#ifdef UNICODE + return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ +#else + if (NROFF) { + j = chadd(temp, Troffchar, Lookup); + if ( j == -1) + return 0; + else + return j | chbits; + } else + return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ + +#endif /*UNICODE*/ +} + +Tchar t_setabs(void) /* set absolute char from \N'...' */ +{ + int n; + char temp[10]; + + getch(); /* delim */ + n = 0; + n = inumb(&n); + getch(); /* delim */ + if (nonumb) + return 0; + sprintf(temp, "%d", n); /* convert into "#n" */ + n = chadd(temp, Number, Install); + return n | chbits; +} + + +/* + * fontlab[] is a cache that contains font information + * for each font. + * fontlab[] contains the 1- or 2-character name of the + * font current associated with that font. + * fonts 1..nfonts correspond to the mounted fonts; + * the last of these are the special fonts. + * If we don't use the (named) font in one of the + * standard positions, we install the name in the next + * free slot of fontlab[] and font[]. + * Whenever we need info about the font, we + * read in the data into the next free slot with getfont. + * The ptfont() (t10.c) routine will tell + * the device filter to put the font always at position + * zero if xfont > nfonts, so no need to change these filters. + * Yes, this is a bit kludgy. + * + * This gives the new specs of findft: + * find the font name i, where i also can be a number. + * Installs the font(name) i when not present + * returns -1 on error + */ + + +t_findft(int i) +{ + int k; + Uchar *p; + + p = unpair(i); + + if (isdigit(p[0])) { /* first look for numbers */ + k = p[0] - '0'; + if (p[1] > 0 && isdigit(p[1])) + k = 10 * k + p[1] - '0'; + if (k > 0 && k <= nfonts && k < smnt) + return(k); /* mounted font: .ft 3 */ + if (fontlab[k] && k <= MAXFONTS) { /* translate */ + return(k); /*number to a name */ + } else { + fprintf(stderr, "troff: no font at position %d\n", k); + return(-1); /* wild number */ + } + } + + /* + * Now we look for font names + */ + for (k = 1; fontlab[k] != i; k++) { + if (k > MAXFONTS) + return(-1); /* running out of fontlab space */ + if (fontlab[k] == 0) { /* passed all existing names */ + if (setfp(k, i, (char *) 0, 1) == -1) + return(-1); + else { + fontlab[k] = i; /* install the name */ + return(k); + } + } + } + return(k); /* was one of the existing names */ +} + + +void caseps(void) +{ + int i; + + if (TROFF) { + if(skip()) + i = apts1; + else { + noscale++; + i = inumb(&apts); /* this is a disaster for fractional point sizes */ + noscale = 0; + if(nonumb) + i = apts1; + } + casps1(i); + } +} + + +void casps1(int i) +{ + +/* + * in olden times, it used to ignore changes to 0 or negative. + * this is meant to allow the requested size to be anything, + * in particular so eqn can generate lots of \s-3's and still + * get back by matching \s+3's. + + if (i <= 0) + return; +*/ + apts1 = apts; + apts = i; + pts1 = pts; + pts = findps(i); + mchbits(); +} + + +findps(int i) +{ + int j, k; + + for (j=k=0 ; pstab[j] != 0 ; j++) + if (abs(pstab[j]-i) < abs(pstab[k]-i)) + k = j; + + return(pstab[k]); +} + + +void t_mchbits(void) +{ + int i, j, k; + + i = pts; + for (j = 0; i > (k = pstab[j]); j++) + if (!k) { + j--; + break; + } + chbits = 0; + setsbits(chbits, ++j); + setfbits(chbits, font); + sps = width(' ' | chbits); + zapwcache(1); +} + +void t_setps(void) +{ + int i, j; + + i = cbits(getch()); + if (isdigit(i)) { /* \sd or \sdd */ + i -= '0'; + if (i == 0) /* \s0 */ + j = apts1; + else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch))) { /* \sdd */ + j = 10 * i + j - '0'; + ch = 0; + } else /* \sd */ + j = i; + } else if (i == '(') { /* \s(dd */ + j = cbits(getch()) - '0'; + j = 10 * j + cbits(getch()) - '0'; + if (j == 0) /* \s(00 */ + j = apts1; + } else if (i == '+' || i == '-') { /* \s+, \s- */ + j = cbits(getch()); + if (isdigit(j)) { /* \s+d, \s-d */ + j -= '0'; + } else if (j == '(') { /* \s+(dd, \s-(dd */ + j = cbits(getch()) - '0'; + j = 10 * j + cbits(getch()) - '0'; + } + if (i == '-') + j = -j; + j += apts; + } + casps1(j); +} + + +Tchar t_setht(void) /* set character height from \H'...' */ +{ + int n; + Tchar c; + + getch(); + n = inumb(&apts); + getch(); + if (n == 0 || nonumb) + n = apts; /* does this work? */ + c = CHARHT; + c |= ZBIT; + setsbits(c, n); + setfbits(c, pts); /* sneaky, CHARHT font bits are size bits */ + return(c); +} + +Tchar t_setslant(void) /* set slant from \S'...' */ +{ + int n; + Tchar c; + + getch(); + n = 0; + n = inumb(&n); + getch(); + if (nonumb) + n = 0; + c = SLANT; + c |= ZBIT; + setsfbits(c, n+180); + return(c); +} + + +void caseft(void) +{ + if (!TROFF) { + n_caseft(); + return; + } + skip(); + setfont(1); +} + + +void t_setfont(int a) +{ + int i, j; + + if (a) + i = getrq(); + else + i = getsn(); + if (!i || i == 'P') { + j = font1; + goto s0; + } + if (/* i == 'S' || */ i == '0') /* an experiment -- why can't we change to it? */ + return; + if ((j = findft(i)) == -1) + if ((j = setfp(0, i, (char*) 0, 1)) == -1) /* try to put it in position 0 */ + return; +s0: + font1 = font; + font = j; + mchbits(); +} + + +void t_setwd(void) +{ + int base, wid; + Tchar i; + int delim, emsz, k; + int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; + + base = numtabp[ST].val = numtabp[SB].val = wid = numtabp[CT].val = 0; + if (ismot(i = getch())) + return; + delim = cbits(i); + savhp = numtabp[HP].val; + numtabp[HP].val = 0; + savapts = apts; + savapts1 = apts1; + savfont = font; + savfont1 = font1; + savpts = pts; + savpts1 = pts1; + setwdf++; + while (cbits(i = getch()) != delim && !nlflg) { + k = width(i); + wid += k; + numtabp[HP].val += k; + if (!ismot(i)) { + emsz = (INCH/72) * xpts; + } else if (isvmot(i)) { + k = absmot(i); + if (isnmot(i)) + k = -k; + base -= k; + emsz = 0; + } else + continue; + if (base < numtabp[SB].val) + numtabp[SB].val = base; + if ((k = base + emsz) > numtabp[ST].val) + numtabp[ST].val = k; + } + setn1(wid, 0, (Tchar) 0); + numtabp[HP].val = savhp; + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + setwdf = 0; +} + + +Tchar t_vmot(void) +{ + dfact = lss; + vflag++; + return t_mot(); +} + + +Tchar t_hmot(void) +{ + dfact = EM; + return t_mot(); +} + + +Tchar t_mot(void) +{ + int j, n; + Tchar i; + + j = HOR; + getch(); /*eat delim*/ + if (n = atoi0()) { + if (vflag) + j = VERT; + i = makem(quant(n, j)); + } else + i = 0; + getch(); + vflag = 0; + dfact = 1; + return(i); +} + + +Tchar t_sethl(int k) +{ + int j; + Tchar i; + + j = EM / 2; + if (k == 'u') + j = -j; + else if (k == 'r') + j = -2 * j; + vflag++; + i = makem(j); + vflag = 0; + return(i); +} + + +Tchar t_makem(int i) +{ + Tchar j; + + if (i >= 0) + j = i; + else + j = -i; + if (Hor > 1 && !vflag) + j = (j + Hor/2)/Hor * Hor; + j |= MOT; + if (i < 0) + j |= NMOT; + if (vflag) + j |= VMOT; + return(j); +} + + +Tchar getlg(Tchar i) +{ + Tchar j, k; + int lf; + + if (!TROFF) + return i; + if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures */ + return(i); + j = getch0(); + if (cbits(j) == 'i' && (lf & LFI)) + j = LIG_FI; + else if (cbits(j) == 'l' && (lf & LFL)) + j = LIG_FL; + else if (cbits(j) == 'f' && (lf & LFF)) { + if ((lf & (LFFI|LFFL)) && lg != 2) { + k = getch0(); + if (cbits(k)=='i' && (lf&LFFI)) + j = LIG_FFI; + else if (cbits(k)=='l' && (lf&LFFL)) + j = LIG_FFL; + else { + *pbp++ = k; + j = LIG_FF; + } + } else + j = LIG_FF; + } else { + *pbp++ = j; + j = i; + } + return(i & SFMASK | j); +} + + +void caselg(void) +{ + + if(TROFF) { + skip(); + lg = atoi0(); + if (nonumb) + lg = 1; + } +} + +void casefp(void) +{ + int i, j; + + if (!TROFF) { + n_casefp(); + return; + } + skip(); + i = cbits(getch()); + if (isdigit(i)) { + i -= '0'; + j = cbits(getch()); + if (isdigit(j)) + i = 10 * i + j - '0'; + } + if (i <= 0 || i > nfonts) + ERROR "fp: bad font position %d", i WARN; + else if (skip() || !(j = getrq())) + ERROR "fp: no font name" WARN; + else if (skip() || !getname()) + setfp(i, j, (char*) 0, 1); + else /* 3rd argument = filename */ + setfp(i, j, nextf, 1); +} + +char *strdupl(const char *s) /* make a copy of s */ +{ + char *t; + + t = (char *) malloc(strlen(s) + 1); + if (t == NULL) + ERROR "out of space in strdupl(%s)", s FATAL; + strcpy(t, s); + return t; +} + +setfp(int pos, int f, char *truename, int print) /* mount font f at position pos[0...nfonts] */ +{ + char pathname[NS], shortname[NS], *sl; + + zapwcache(0); + if (truename) + strcpy(shortname, truename); + else + strcpy(shortname, (char *) unpair(f)); + if (truename && strrchr(truename, '/')) { /* .fp 1 R dir/file: use verbatim */ + sprintf(pathname, "%s", truename); + if (fonts[pos].truename) + free(fonts[pos].truename); + fonts[pos].truename = strdupl(truename); + } else if (truename) { /* synonym: .fp 1 R Avant */ + sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truename); + truename = 0; /* so doesn't get repeated by ptfpcmd */ + } else /* vanilla: .fp 5 XX */ + sprintf(pathname, "%s/dev%s/%s", fontdir, devname, shortname); + if (truename == 0 && fonts[pos].truename != 0) { + free(fonts[pos].truename); + fonts[pos].truename = 0; + } + if (getfont(pathname, pos) < 0) { + ERROR "Can't open font file %s", pathname WARN; + return -1; + } + if (print && !ascii) { + ptfpcmd(pos, fonts[pos].longname, truename); + ptfont(); + } + if (pos == smnt) { + smnt = 0; + sbold = 0; + } + fontlab[pos] = f; + if (smnt == 0 && fonts[pos].specfont) + smnt = pos; + bdtab[pos] = cstab[pos] = ccstab[pos] = 0; + return pos; +} + +/* + * .cs request; don't check legality of optional arguments + */ +void casecs(void) +{ + int i, j; + + if (TROFF) { + int savtr = trace; + + trace = 0; + noscale++; + skip(); + if (!(i = getrq()) || (i = findft(i)) < 0) + goto rtn; + skip(); + cstab[i] = atoi0(); + skip(); + j = atoi0(); + if(nonumb) + ccstab[i] = 0; + else + ccstab[i] = findps(j); + rtn: + zapwcache(0); + noscale = 0; + trace = savtr; + } +} + + +void casebd(void) +{ + int i, j, k; + + if (!TROFF) { + n_casebd(); + return; + } + zapwcache(0); + k = 0; +bd0: + if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { + if (k) + goto bd1; + else + return; + } + if (j == smnt) { + k = smnt; + goto bd0; + } + if (k) { + sbold = j; + j = k; + } +bd1: + skip(); + noscale++; + bdtab[j] = atoi0(); + noscale = 0; +} + + +void casevs(void) +{ + int i; + + if (!TROFF) { + n_casevs(); + return; + } + skip(); + vflag++; + dfact = INCH; /* default scaling is points! */ + dfactd = 72; + res = VERT; + i = inumb(&lss); + if (nonumb) + i = lss1; + if (i < VERT) + i = VERT; + lss1 = lss; + lss = i; +} + + +void casess(void) +{ + int i; + + if(TROFF) { + noscale++; + skip(); + if(i = atoi0()) { + spacesz = i & 0177; + zapwcache(0); + sps = width(' ' | chbits); + } + noscale = 0; + } +} + + +Tchar t_xlss(void) +{ + /* stores \x'...' into two successive Tchars. + /* the first contains HX, the second the value, + /* encoded as a vertical motion. + /* decoding is done in n2.c by pchar(). + */ + int i; + + getch(); + dfact = lss; + i = quant(atoi0(), VERT); + dfact = 1; + getch(); + if (i >= 0) + *pbp++ = MOT | VMOT | i; + else + *pbp++ = MOT | VMOT | NMOT | -i; + return(HX); +} + +Uchar *unpair(int i) +{ + static Uchar name[3]; + + name[0] = i & SHORTMASK; + name[1] = (i >> SHORT) & SHORTMASK; + name[2] = 0; + return name; +} |