123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881 |
- /*
- * 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;
- }
|