|
|
1.1 root 1: /*
2: * t6.c
3: *
4: * width functions, sizes and fonts
5: */
6:
7: #include "tdef.h"
8: #include "fns.h"
9: #include "ext.h"
10:
11: int fontlab[MAXFONTS+1];
12: int cstab[MAXFONTS+1];
13: int ccstab[MAXFONTS+1];
14: int bdtab[MAXFONTS+1];
15: int sbold = 0;
16:
17: t_width(Tchar j)
18: {
19: int i, k;
20:
21: if (iszbit(j))
22: return 0;
23: if (ismot(j)) {
24: if (isvmot(j))
25: return(0);
26: k = absmot(j);
27: if (isnmot(j))
28: k = -k;
29: return(k);
30: }
31: i = cbits(j);
32: if (i < ' ') {
33: if (i == '\b')
34: return(-widthp);
35: if (i == PRESC)
36: i = eschar;
37: else if (i == HX)
38: return(0);
39: }
40: if (i == ohc)
41: return(0);
42: i = trtab[i];
43: if (i < ' ')
44: return(0);
45: if (sfbits(j) == oldbits) {
46: xfont = pfont;
47: xpts = ppts;
48: } else
49: xbits(j, 0);
50: if (i < nchnames + ALPHABET && widcache[i].fontpts == (xfont<<8) + xpts && !setwdf)
51: k = widcache[i].width;
52: else {
53: k = getcw(i);
54: if (bd)
55: k += (bd - 1) * HOR;
56: if (cs)
57: k = cs;
58: }
59: widthp = k;
60: return(k);
61: }
62:
63: /*
64: * clear width cache-- s means just space
65: */
66: void zapwcache(int s)
67: {
68: int i;
69:
70: if (s) {
71: widcache[' '].fontpts = 0;
72: return;
73: }
74: for (i=0; i<NWIDCACHE; i++)
75: widcache[i].fontpts = 0;
76: }
77:
78: onfont(int n, int f) /* is char n on font f? */
79: {
80: int i;
81: Font *fp = &fonts[f];
82: Chwid *cp, *ep;
83: char *np;
84:
85: if (n < ALPHABET) {
86: if (fp->wp[n].num == n) /* ascii at front */
87: return n;
88: else
89: return -1;
90: }
91: cp = &fp->wp[ALPHABET];
92: ep = &fp->wp[fp->nchars];
93: for ( ; cp < ep; cp++) /* search others */
94: if (cp->num == n)
95: return cp - &fp->wp[0];
96: /* maybe it was a \N... */
97: np = chname(n);
98: if (*np == '#') {
99: i = atoi(np+1); /* sscanf(np+1, "%d", &i); */
100: cp = &fp->wp[0];
101: ep = &fp->wp[fp->nchars];
102: for ( ; cp < ep; cp++) { /* search others */
103: if (cp->code == i)
104: return cp - &fp->wp[0];
105: }
106: return -2; /* a \N that doesn't have an entry */
107: }
108: return -1; /* vanilla not found */
109: }
110:
111: getcw(int i)
112: {
113: int k, n, x;
114: Font *fp;
115: int nocache = 0;
116:
117: if (i < ' ')
118: return 0;
119: bd = 0;
120: fp = &fonts[xfont];
121: if (i == ' ') { /* a blank */
122: k = (fp->spacewidth * spacesz + 6) / 12;
123: /* this nonsense because .ss cmd uses 1/36 em as its units */
124: /* and default is 12 */
125: } else if ((n = onfont(i, xfont)) >= 0) { /* on this font at n */
126: k = fp->wp[n].wid;
127: if (setwdf)
128: numtab[CT].val |= fp->wp[n].kern;
129: } else if (n == -2) { /* \N with default width */
130: k = fp->defaultwidth;
131: } else { /* not on current font */
132: nocache = 1;
133: k = fp->defaultwidth; /* default-size space */
134: if (smnt) {
135: int ii, jj;
136: for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) {
137: if ((n = onfont(i, ii)) >= 0) {
138: k = fonts[ii].wp[n].wid;
139: if (xfont == sbold)
140: bd = bdtab[ii];
141: if (setwdf)
142: numtab[CT].val |= fonts[ii].wp[n].kern;
143: break;
144: }
145: }
146: }
147: }
148: if (!bd)
149: bd = bdtab[xfont];
150: if (cs = cstab[xfont]) {
151: nocache = 1;
152: if (ccs = ccstab[xfont])
153: x = ccs;
154: else
155: x = xpts;
156: cs = (cs * EMPTS(x)) / 36;
157: }
158: /* was (k & BYTEMASK); since .wid is unsigned, should never happen */
159: if (k < 0)
160: ERROR "can't happen: negative width %d in getcw %d\n", k, i WARN;
161: k = (k * xpts + (Unitwidth / 2)) / Unitwidth;
162: if (nocache|bd)
163: widcache[i].fontpts = 0;
164: else {
165: widcache[i].fontpts = (xfont<<8) + xpts;
166: widcache[i].width = k;
167: }
168: return(k);
169: /* Unitwidth is Units/Point, where
170: /* Units is the fundamental digitization
171: /* of the character set widths, and
172: /* Point is the number of goobies in a point
173: /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6
174: /* In effect, it's the size at which the widths
175: /* translate directly into units.
176: */
177: }
178:
179: void xbits(Tchar i, int bitf)
180: {
181: int k;
182:
183: if(TROFF) {
184: xfont = fbits(i);
185: k = sbits(i);
186: if(k) {
187: xpts = pstab[k-1];
188: oldbits = sfbits(i);
189: pfont = xfont;
190: ppts = xpts;
191: return;
192: }
193: switch(bitf) {
194: case 0:
195: xfont = font;
196: xpts = pts;
197: break;
198: case 1:
199: xfont = pfont;
200: xpts = ppts;
201: break;
202: case 2:
203: xfont = mfont;
204: xpts = mpts;
205: }
206: }
207: }
208:
209:
210: /* these next two functions ought to be the same in troff and nroff, */
211: /* but the data structures they search are different. */
212: /* silly historical problem. */
213:
214:
215: Tchar t_setch(int c)
216: {
217: int j;
218: char temp[50];
219: char *s;
220:
221: s = temp;
222: if (c == '(') { /* \(xx */
223: if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0)
224: return(0);
225: } else { /* \C'...' */
226: c = getach();
227: while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1)
228: s++;
229: }
230: *s = '\0';
231: if ((j = chindex(temp)) == -1)
232: return chadd(temp) | chbits; /* add name even if haven't seen it */
233: /* "return 0" -> discard unknown char */
234: else
235: return(j | chbits);
236: }
237:
238: Tchar t_setabs(void) /* set absolute char from \N'...' */
239: {
240: int n;
241: char temp[10];
242:
243: getch(); /* delim */
244: n = 0;
245: n = inumb(&n);
246: getch(); /* delim */
247: if (nonumb)
248: return 0;
249: sprintf(temp, "#%d", n); /* convert into "#n" */
250: if ((n = chindex(temp)) == -1) /* look for that name */
251: n = chadd(temp);
252: return n | chbits;
253: }
254:
255:
256: /*
257: * fontlab[] is a cache that contains font information
258: * for each font.
259: * fontlab[] contains the 1- or 2-character name of the
260: * font current associated with that font.
261: * fonts 1..nfonts correspond to the mounted fonts;
262: * the last of these are the special fonts.
263: * If we don't use the (named) font in one of the
264: * standard positions, we install the name in the next
265: * free slot of fontlab[] and font[].
266: * Whenever we need info about the font, we
267: * read in the data into the next free slot with getfont.
268: * The ptfont() (t10.c) routine will tell
269: * the device filter to put the font always at position
270: * zero if xfont > nfonts, so no need to change these filters.
271: * Yes, this is a bit kludgy.
272: *
273: * This gives the new specs of findft:
274: * find the font name i, where i also can be a number.
275: * Installs the font(name) i when not present
276: * returns -1 on error
277: */
278:
279:
280: t_findft(int i)
281: {
282: int k;
283: char *p;
284:
285: p = unpair(i);
286:
287: if (isdigit(p[0])) { /* first look for numbers */
288: k = p[0] - '0';
289: if (p[1] > 0 && isdigit(p[1]))
290: k = 10 * k + p[1] - '0';
291: if (k > 0 && k <= nfonts && k < smnt)
292: return(k); /* mounted font: .ft 3 */
293: if (fontlab[k] && k <= MAXFONTS) { /* translate */
294: return(k); /*number to a name */
295: } else {
296: fprintf(stderr, "troff: no font at position %d\n", k);
297: return(-1); /* wild number */
298: }
299: }
300:
301: /*
302: * Now we look for font names
303: */
304: for (k = 1; fontlab[k] != i; k++) {
305: if (k > MAXFONTS)
306: return(-1); /* running out of fontlab space */
307: if (fontlab[k] == 0) { /* passed all existing names */
308: if (setfp(k, i, (char *) 0, 1) == -1)
309: return(-1);
310: else {
311: fontlab[k] = i; /* install the name */
312: return(k);
313: }
314: }
315: }
316: return(k); /* was one of the existing names */
317: }
318:
319:
320: void caseps(void)
321: {
322: int i;
323:
324: if (TROFF) {
325: if(skip())
326: i = apts1;
327: else {
328: noscale++;
329: i = inumb(&apts); /* this is a disaster for fractional point sizes */
330: noscale = 0;
331: if(nonumb)
332: return;
333: }
334: casps1(i);
335: }
336: }
337:
338:
339: void casps1(int i)
340: {
341:
342: /*
343: * in olden times, it used to ignore changes to 0 or negative.
344: * this is meant to allow the requested size to be anything,
345: * in particular so eqn can generate lots of \s-3's and still
346: * get back by matching \s+3's.
347:
348: if (i <= 0)
349: return;
350: */
351: apts1 = apts;
352: apts = i;
353: pts1 = pts;
354: pts = findps(i);
355: mchbits();
356: }
357:
358:
359: findps(int i)
360: {
361: int j, k;
362:
363: for (j=k=0 ; pstab[j] != 0 ; j++)
364: if (abs(pstab[j]-i) < abs(pstab[k]-i))
365: k = j;
366:
367: return(pstab[k]);
368: }
369:
370:
371: void t_mchbits(void)
372: {
373: int i, j, k;
374:
375: i = pts;
376: for (j = 0; i > (k = pstab[j]); j++)
377: if (!k) {
378: j--;
379: break;
380: }
381: chbits = 0;
382: setsbits(chbits, ++j);
383: setfbits(chbits, font);
384: sps = width(' ' | chbits);
385: zapwcache(1);
386: }
387:
388: void t_setps(void)
389: {
390: int i, j;
391:
392: i = cbits(getch());
393: if (isdigit(i)) { /* \sd or \sdd */
394: i -= '0';
395: if (i == 0) /* \s0 */
396: j = apts1;
397: else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch))) { /* \sdd */
398: j = 10 * i + j - '0';
399: ch = 0;
400: } else /* \sd */
401: j = i;
402: } else if (i == '(') { /* \s(dd */
403: j = cbits(getch()) - '0';
404: j = 10 * j + cbits(getch()) - '0';
405: if (j == 0) /* \s(00 */
406: j = apts1;
407: } else if (i == '+' || i == '-') { /* \s+, \s- */
408: j = cbits(getch());
409: if (isdigit(j)) { /* \s+d, \s-d */
410: j -= '0';
411: } else if (j == '(') { /* \s+(dd, \s-(dd */
412: j = cbits(getch()) - '0';
413: j = 10 * j + cbits(getch()) - '0';
414: }
415: if (i == '-')
416: j = -j;
417: j += apts;
418: }
419: casps1(j);
420: }
421:
422:
423: Tchar t_setht(void) /* set character height from \H'...' */
424: {
425: int n;
426: Tchar c;
427:
428: getch();
429: n = inumb(&apts);
430: getch();
431: if (n == 0 || nonumb)
432: n = apts; /* does this work? */
433: c = CHARHT;
434: c |= ZBIT;
435: setsbits(c, n);
436: return(c);
437: }
438:
439: Tchar t_setslant(void) /* set slant from \S'...' */
440: {
441: int n;
442: Tchar c;
443:
444: getch();
445: n = 0;
446: n = inumb(&n);
447: getch();
448: if (nonumb)
449: n = 0;
450: c = SLANT;
451: c |= ZBIT;
452: setsfbits(c, n+180);
453: return(c);
454: }
455:
456:
457: void caseft(void)
458: {
459: if (!TROFF) {
460: n_caseft();
461: return;
462: }
463: skip();
464: setfont(1);
465: }
466:
467:
468: void t_setfont(int a)
469: {
470: int i, j;
471:
472: if (a)
473: i = getrq();
474: else
475: i = getsn();
476: if (!i || i == 'P') {
477: j = font1;
478: goto s0;
479: }
480: if (/* i == 'S' || */ i == '0') /* an experiment -- why can't we change to it? */
481: return;
482: if ((j = findft(i)) == -1)
483: if ((j = setfp(0, i, (char*) 0, 1)) == -1) /* try to put it in position 0 */
484: return;
485: s0:
486: font1 = font;
487: font = j;
488: mchbits();
489: }
490:
491:
492: void t_setwd(void)
493: {
494: int base, wid;
495: Tchar i;
496: int delim, emsz, k;
497: int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1;
498:
499: base = numtab[ST].val = numtab[SB].val = wid = numtab[CT].val = 0;
500: if (ismot(i = getch()))
501: return;
502: delim = cbits(i);
503: savhp = numtab[HP].val;
504: numtab[HP].val = 0;
505: savapts = apts;
506: savapts1 = apts1;
507: savfont = font;
508: savfont1 = font1;
509: savpts = pts;
510: savpts1 = pts1;
511: setwdf++;
512: while (cbits(i = getch()) != delim && !nlflg) {
513: k = width(i);
514: wid += k;
515: numtab[HP].val += k;
516: if (!ismot(i)) {
517: emsz = (INCH/72) * xpts;
518: } else if (isvmot(i)) {
519: k = absmot(i);
520: if (isnmot(i))
521: k = -k;
522: base -= k;
523: emsz = 0;
524: } else
525: continue;
526: if (base < numtab[SB].val)
527: numtab[SB].val = base;
528: if ((k = base + emsz) > numtab[ST].val)
529: numtab[ST].val = k;
530: }
531: setn1(wid, 0, (Tchar) 0);
532: numtab[HP].val = savhp;
533: apts = savapts;
534: apts1 = savapts1;
535: font = savfont;
536: font1 = savfont1;
537: pts = savpts;
538: pts1 = savpts1;
539: mchbits();
540: setwdf = 0;
541: }
542:
543:
544: Tchar t_vmot(void)
545: {
546: dfact = lss;
547: vflag++;
548: return t_mot();
549: }
550:
551:
552: Tchar t_hmot(void)
553: {
554: dfact = EM;
555: return t_mot();
556: }
557:
558:
559: Tchar t_mot(void)
560: {
561: int j, n;
562: Tchar i;
563:
564: j = HOR;
565: getch(); /*eat delim*/
566: if (n = atoi0()) {
567: if (vflag)
568: j = VERT;
569: i = makem(quant(n, j));
570: } else
571: i = 0;
572: getch();
573: vflag = 0;
574: dfact = 1;
575: return(i);
576: }
577:
578:
579: Tchar t_sethl(int k)
580: {
581: int j;
582: Tchar i;
583:
584: j = EM / 2;
585: if (k == 'u')
586: j = -j;
587: else if (k == 'r')
588: j = -2 * j;
589: vflag++;
590: i = makem(j);
591: vflag = 0;
592: return(i);
593: }
594:
595:
596: Tchar t_makem(int i)
597: {
598: Tchar j;
599:
600: if (i >= 0)
601: j = i;
602: else
603: j = -i;
604: if (Hor > 1 && !vflag)
605: j = (j + Hor/2)/Hor * Hor;
606: j |= MOT;
607: if (i < 0)
608: j |= NMOT;
609: if (vflag)
610: j |= VMOT;
611: return(j);
612: }
613:
614:
615: Tchar getlg(Tchar i)
616: {
617: Tchar j, k;
618: int lf;
619:
620: if (!TROFF)
621: return i;
622: if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures */
623: return(i);
624: j = getch0();
625: if (cbits(j) == 'i' && (lf & LFI))
626: j = LIG_FI;
627: else if (cbits(j) == 'l' && (lf & LFL))
628: j = LIG_FL;
629: else if (cbits(j) == 'f' && (lf & LFF)) {
630: if ((lf & (LFFI|LFFL)) && lg != 2) {
631: k = getch0();
632: if (cbits(k)=='i' && (lf&LFFI))
633: j = LIG_FFI;
634: else if (cbits(k)=='l' && (lf&LFFL))
635: j = LIG_FFL;
636: else {
637: *pbp++ = k;
638: j = LIG_FF;
639: }
640: } else
641: j = LIG_FF;
642: } else {
643: *pbp++ = j;
644: j = i;
645: }
646: return(i & SFMASK | j);
647: }
648:
649:
650: void caselg(void)
651: {
652:
653: if(TROFF) {
654: lg = 1;
655: if(skip())
656: return;
657: lg = atoi0();
658: }
659: }
660:
661: void casefp(void)
662: {
663: int i, j;
664:
665: if (!TROFF) {
666: n_casefp();
667: return;
668: }
669: skip();
670: i = cbits(getch());
671: if (isdigit(i)) {
672: i -= '0';
673: j = cbits(getch());
674: if (isdigit(j))
675: i = 10 * i + j - '0';
676: }
677: if (i <= 0 || i > nfonts)
678: ERROR "fp: bad font position %d", i WARN;
679: else if (skip() || !(j = getrq()))
680: ERROR "fp: no font name" WARN;
681: else if (skip() || !getname())
682: setfp(i, j, (char*) 0, 1);
683: else /* 3rd argument = filename */
684: setfp(i, j, nextf, 1);
685: }
686:
687: char *strdup(char *s) /* make a copy of s */
688: {
689: char *t;
690:
691: t = (char *) malloc(strlen(s) + 1);
692: if (t == NULL)
693: ERROR "out of space in strdup(%s)", s FATAL;
694: strcpy(t, s);
695: return t;
696: }
697:
698: setfp(int pos, int f, char *truename, int print) /* mount font f at position pos[0...nfonts] */
699: {
700: char pathname[NS], shortname[NS], *sl;
701:
702: zapwcache(0);
703: if (truename)
704: strcpy(shortname, truename);
705: else
706: strcpy(shortname, unpair(f));
707: if (truename && strrchr(truename, '/')) { /* .fp 1 R dir/file: use verbatim */
708: sprintf(pathname, "%s", truename);
709: if (fonts[pos].truename)
710: free(fonts[pos].truename);
711: fonts[pos].truename = strdup(truename);
712: } else if (truename) { /* synonym: .fp 1 R Avant */
713: sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truename);
714: truename = 0; /* so doesn't get repeated by ptfpcmd */
715: } else /* vanilla: .fp 5 XX */
716: sprintf(pathname, "%s/dev%s/%s", fontdir, devname, shortname);
717: if (truename == 0 && fonts[pos].truename != 0) {
718: free(fonts[pos].truename);
719: fonts[pos].truename = 0;
720: }
721: if (getfont(pathname, pos) < 0) {
722: ERROR "Can't open font file %s", pathname WARN;
723: return -1;
724: }
725: if (print && !ascii) {
726: ptfpcmd(pos, fonts[pos].longname, truename);
727: ptfont();
728: }
729: if (pos == smnt) {
730: smnt = 0;
731: sbold = 0;
732: }
733: fontlab[pos] = f;
734: if (smnt == 0 && fonts[pos].specfont)
735: smnt = pos;
736: bdtab[pos] = cstab[pos] = ccstab[pos] = 0;
737: return pos;
738: }
739:
740:
741: void casecs(void)
742: {
743: int i, j;
744:
745: if (TROFF) {
746: noscale++;
747: skip();
748: if (!(i = getrq()) || (i = findft(i)) < 0)
749: goto rtn;
750: skip();
751: cstab[i] = atoi0();
752: skip();
753: j = atoi0();
754: if(nonumb)
755: ccstab[i] = 0;
756: else
757: ccstab[i] = findps(j);
758: rtn:
759: zapwcache(0);
760: noscale = 0;
761: }
762: }
763:
764:
765: void casebd(void)
766: {
767: int i, j, k;
768:
769: if (!TROFF) {
770: n_casebd();
771: return;
772: }
773: zapwcache(0);
774: k = 0;
775: bd0:
776: if (skip() || !(i = getrq()) || (j = findft(i)) == -1) {
777: if (k)
778: goto bd1;
779: else
780: return;
781: }
782: if (j == smnt) {
783: k = smnt;
784: goto bd0;
785: }
786: if (k) {
787: sbold = j;
788: j = k;
789: }
790: bd1:
791: skip();
792: noscale++;
793: bdtab[j] = atoi0();
794: noscale = 0;
795: }
796:
797:
798: void casevs(void)
799: {
800: int i;
801:
802: if (!TROFF) {
803: n_casevs();
804: return;
805: }
806: skip();
807: vflag++;
808: dfact = INCH; /* default scaling is points! */
809: dfactd = 72;
810: res = VERT;
811: i = inumb(&lss);
812: if (nonumb)
813: i = lss1;
814: if (i < VERT)
815: i = VERT;
816: lss1 = lss;
817: lss = i;
818: }
819:
820:
821: void casess(void)
822: {
823: int i;
824:
825: if(TROFF) {
826: noscale++;
827: skip();
828: if(i = atoi0()) {
829: spacesz = i & 0177;
830: zapwcache(0);
831: sps = width(' ' | chbits);
832: }
833: noscale = 0;
834: }
835: }
836:
837:
838: Tchar t_xlss(void)
839: {
840: /* stores \x'...' into two successive Tchars.
841: /* the first contains HX, the second the value,
842: /* encoded as a vertical motion.
843: /* decoding is done in n2.c by pchar().
844: */
845: int i;
846:
847: getch();
848: dfact = lss;
849: i = quant(atoi0(), VERT);
850: dfact = 1;
851: getch();
852: if (i >= 0)
853: *pbp++ = MOT | VMOT | i;
854: else
855: *pbp++ = MOT | VMOT | NMOT | -i;
856: return(HX);
857: }
858:
859: char *unpair(int i)
860: {
861: static char name[3];
862:
863: name[0] = i & BYTEMASK;
864: name[1] = (i >> BYTE) & BYTEMASK;
865: name[2] = 0;
866: return (name);
867: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.