|
|
1.1 root 1: /*
2: * t6.c
3: *
4: * width functions, sizes and fonts
5: */
6:
7: #include "tdef.h"
8: #include "dev.h"
9: #include <ctype.h>
10: #include "ext.h"
11:
12: /*
13: fitab[f][c] is 0 if c is not on font f
14: if it's non-zero, c is in fontab[f] at position fitab[f][c].
15: */
16: extern struct Font *fontbase[NFONT+1];
17: extern char *codetab[NFONT+1];
18: extern int nchtab;
19:
20: int fontlab[NFONT+1];
21: short *pstab;
22: int cstab[NFONT+1];
23: int ccstab[NFONT+1];
24: int bdtab[NFONT+1];
25: int sbold = 0;
26:
27: width(j)
28: register tchar j;
29: {
30: register i, k;
31:
32: if (j & (ZBIT|MOT)) {
33: if (iszbit(j))
34: return(0);
35: if (isvmot(j))
36: return(0);
37: k = absmot(j);
38: if (isnmot(j))
39: k = -k;
40: return(k);
41: }
42: i = cbits(j);
43: if (i < 32) {
44: if (i == '\b')
45: return(-widthp);
46: if (i == PRESC)
47: i = eschar;
48: else if (iscontrol(i))
49: return(0);
50: }
51: if (i == ohc)
52: return(0);
53: i = trtab[i] - 32; /* fails for \N */
54: if (i < 0)
55: return(0);
56: if (sfbits(j) == oldbits) {
57: xfont = pfont;
58: xpts = ppts;
59: } else
60: xbits(j, 0);
61: if (i < nchtab + 128-32 && widcache[i].fontpts == (xfont<<8) + xpts && !setwdf)
62: k = widcache[i].width;
63: else {
64: k = getcw(i);
65: if (bd)
66: k += (bd - 1) * HOR;
67: if (cs)
68: k = cs;
69: }
70: widthp = k;
71: return(k);
72: }
73:
74: /*
75: * clear width cache-- s means just space
76: */
77: zapwcache(s)
78: {
79: register i;
80:
81: if (s) {
82: widcache[0].fontpts = 0;
83: return;
84: }
85: for (i=0; i<NWIDCACHE; i++)
86: widcache[i].fontpts = 0;
87: }
88:
89: getcw(i)
90: register int i;
91: {
92: register int k;
93: register char *p;
94: register int x, j;
95: int nocache = 0;
96:
97: bd = 0;
98: if (i >= nchtab + 128-32) {
99: j = abscw(i + 32 - (nchtab+128));
100: goto g0;
101: }
102: if (i == 0) { /* a blank */
103: k = (fontab[xfont][0] * spacesz + 6) / 12;
104: /* this nonsense because .ss cmd uses 1/36 em as its units */
105: /* and default is 12 */
106: goto g1;
107: }
108: if ((j = fitab[xfont][i] & BYTEMASK) == 0) { /* it's not on current font */
109: /* search through search list of xfont
110: /* to see what font it ought to be on.
111: /* searches S, then remaining fonts in wraparound order.
112: */
113: nocache = 1;
114: if (smnt) {
115: int ii, jj;
116: for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) {
117: j = fitab[ii][i] & BYTEMASK;
118: if (j != 0) {
119: p = fontab[ii];
120: k = *(p + j);
121: if (xfont == sbold)
122: bd = bdtab[ii];
123: if (setwdf)
124: numtab[CT].val |= kerntab[ii][j];
125: goto g1;
126: }
127: }
128: }
129: k = fontab[xfont][0]; /* leave a space-size space */
130: goto g1;
131: }
132: g0:
133: p = fontab[xfont];
134: if (setwdf)
135: numtab[CT].val |= kerntab[xfont][j];
136: k = *(p + j);
137: g1:
138: if (!bd)
139: bd = bdtab[xfont];
140: if (cs = cstab[xfont]) {
141: nocache = 1;
142: if (ccs = ccstab[xfont])
143: x = ccs;
144: else
145: x = xpts;
146: cs = (cs * EMPTS(x)) / 36;
147: }
148: k = ((k&BYTEMASK) * xpts + (Unitwidth / 2)) / Unitwidth;
149: if (nocache|bd)
150: widcache[i].fontpts = 0;
151: else {
152: widcache[i].fontpts = (xfont<<8) + xpts;
153: widcache[i].width = k;
154: }
155: return(k);
156: /* Unitwidth is Units/Point, where
157: /* Units is the fundamental digitization
158: /* of the character set widths, and
159: /* Point is the number of goobies in a point
160: /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6
161: /* In effect, it's the size at which the widths
162: /* translate directly into units.
163: */
164: }
165:
166: abscw(n) /* return index of abs char n in fontab[], etc. */
167: { register int i, ncf;
168:
169: ncf = fontbase[xfont]->nwfont & BYTEMASK;
170: for (i = 0; i < ncf; i++)
171: if (codetab[xfont][i] == n)
172: return i;
173: return 0;
174: }
175:
176: xbits(i, bitf)
177: register tchar i;
178: {
179: register k;
180:
181: xfont = fbits(i);
182: k = sbits(i);
183: if (k) {
184: xpts = pstab[--k];
185: oldbits = sfbits(i);
186: pfont = xfont;
187: ppts = xpts;
188: return;
189: }
190: switch (bitf) {
191: case 0:
192: xfont = font;
193: xpts = pts;
194: break;
195: case 1:
196: xfont = pfont;
197: xpts = ppts;
198: break;
199: case 2:
200: xfont = mfont;
201: xpts = mpts;
202: }
203: }
204:
205:
206: tchar setch(c)
207: {
208: register j;
209: char temp[50];
210: register char *s;
211: extern char *chname;
212: extern short *chtab;
213:
214: s = temp;
215: if (c == '(') { /* \(xx */
216: if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0)
217: return(0);
218: } else { /* \C'...' */
219: c = getach();
220: while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1)
221: s++;
222: }
223: *s = '\0';
224: for (j = 0; j < nchtab; j++)
225: if (strcmp(&chname[chtab[j]], temp) == 0)
226: return(j + 128 | chbits);
227: return(0);
228: }
229:
230: tchar setabs() /* set absolute char from \N'...' */
231: {
232: int n;
233:
234: getch();
235: n = 0;
236: n = inumb(&n);
237: getch();
238: if (nonumb)
239: return 0;
240: if (n > (fontbase[xfont]->nwfont & BYTEMASK)) {
241: errprint("\\N'%d' toooo large", n);
242: return 0;
243: }
244: return n + nchtab + 128 | chbits;
245: }
246:
247:
248: findft(i)
249: register int i;
250: {
251: register int k, c0, c1;
252:
253: c0 = i & BYTEMASK; /* unPAIR: allows for 2-digit font numbers */
254: c1 = (i >> BYTE) & BYTEMASK;
255: if (isdigit(c0)) {
256: if (c1 == 0)
257: k = c0 - '0';
258: else if (isdigit(c1))
259: k = 10 * (c0 - '0') + c1 - '0';
260: else
261: k = -1;
262: if (k >= 0 && k <= nfonts && k < smnt)
263: return(k);
264: }
265: for (k = 0; fontlab[k] != i; k++)
266: if (k > nfonts)
267: return(-1);
268: return(k);
269: }
270:
271:
272: caseps()
273: {
274: register i;
275:
276: if (skip())
277: i = apts1;
278: else {
279: noscale++;
280: i = inumb(&apts); /* this is a disaster for fractional point sizes */
281: noscale = 0;
282: if (nonumb)
283: return;
284: }
285: casps1(i);
286: }
287:
288:
289: casps1(i)
290: register int i;
291: {
292:
293: /*
294: * in olden times, it used to ignore changes to 0 or negative.
295: * this is meant to allow the requested size to be anything,
296: * in particular so eqn can generate lots of \s-3's and still
297: * get back by matching \s+3's.
298:
299: if (i <= 0)
300: return;
301: */
302: apts1 = apts;
303: apts = i;
304: pts1 = pts;
305: pts = findps(i);
306: mchbits();
307: }
308:
309:
310: findps(i)
311: register int i;
312: {
313: register j, k;
314:
315: for (j=k=0 ; pstab[j] != 0 ; j++)
316: if (abs(pstab[j]-i) < abs(pstab[k]-i))
317: k = j;
318:
319: return(pstab[k]);
320: }
321:
322:
323: mchbits()
324: {
325: register i, j, k;
326:
327: i = pts;
328: for (j = 0; i > (k = pstab[j]); j++)
329: if (!k) {
330: j--;
331: break;
332: }
333: chbits = 0;
334: setsbits(chbits, ++j);
335: setfbits(chbits, font);
336: sps = width(' ' | chbits);
337: zapwcache(1);
338: }
339:
340: setps()
341: {
342: register int i, j;
343:
344: i = cbits(getch());
345: if (isdigit(i)) { /* \sd or \sdd */
346: i -= '0';
347: if (i == 0) /* \s0 */
348: j = apts1;
349: else if (i <= 3 && isdigit(j = cbits(ch=getch()))) { /* \sdd */
350: j = 10 * i + j - '0';
351: ch = 0;
352: } else /* \sd */
353: j = i;
354: } else if (i == '(') { /* \s(dd */
355: j = cbits(getch()) - '0';
356: j = 10 * j + cbits(getch()) - '0';
357: if (j == 0) /* \s(00 */
358: j = apts1;
359: } else if (i == '+' || i == '-') { /* \s+, \s- */
360: j = cbits(getch());
361: if (isdigit(j)) { /* \s+d, \s-d */
362: j -= '0';
363: } else if (j == '(') { /* \s+(dd, \s-(dd */
364: j = cbits(getch()) - '0';
365: j = 10 * j + cbits(getch()) - '0';
366: }
367: if (i == '-')
368: j = -j;
369: j += apts;
370: }
371: casps1(j);
372: }
373:
374:
375: tchar setht() /* set character height from \H'...' */
376: {
377: int n;
378: tchar c;
379:
380: getch();
381: n = inumb(&apts);
382: getch();
383: if (n == 0 || nonumb)
384: n = apts; /* does this work? */
385: c = CHARHT;
386: c |= ZBIT;
387: setsbits(c, n);
388: return(c);
389: }
390:
391: tchar setslant() /* set slant from \S'...' */
392: {
393: int n;
394: tchar c;
395:
396: getch();
397: n = 0;
398: n = inumb(&n);
399: getch();
400: if (nonumb)
401: n = 0;
402: c = SLANT;
403: c |= ZBIT;
404: setsfbits(c, n+180);
405: return(c);
406: }
407:
408:
409: caseft()
410: {
411: skip();
412: setfont(1);
413: }
414:
415:
416: setfont(a)
417: int a;
418: {
419: register i, j;
420:
421: if (a)
422: i = getrq();
423: else
424: i = getsn();
425: if (!i || i == 'P') {
426: j = font1;
427: goto s0;
428: }
429: if (i == 'S' || i == '0')
430: return;
431: if ((j = findft(i)) == -1)
432: if ((j = setfp(0, i, (char*)0)) == -1) /* try to put it in position 0 */
433: return;
434: s0:
435: font1 = font;
436: font = j;
437: mchbits();
438: }
439:
440:
441: setwd()
442: {
443: register base, wid;
444: register tchar i;
445: int delim, emsz, k;
446: int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1;
447:
448: base = numtab[ST].val = numtab[ST].val = wid = numtab[CT].val = 0;
449: if (ismot(i = getch()))
450: return;
451: delim = cbits(i);
452: savhp = numtab[HP].val;
453: numtab[HP].val = 0;
454: savapts = apts;
455: savapts1 = apts1;
456: savfont = font;
457: savfont1 = font1;
458: savpts = pts;
459: savpts1 = pts1;
460: setwdf++;
461: while (cbits(i = getch()) != delim && !nlflg) {
462: k = width(i);
463: wid += k;
464: numtab[HP].val += k;
465: if (!ismot(i)) {
466: emsz = POINT * xpts;
467: } else if (isvmot(i)) {
468: k = absmot(i);
469: if (isnmot(i))
470: k = -k;
471: base -= k;
472: emsz = 0;
473: } else
474: continue;
475: if (base < numtab[SB].val)
476: numtab[SB].val = base;
477: if ((k = base + emsz) > numtab[ST].val)
478: numtab[ST].val = k;
479: }
480: setn1(wid, 0, (tchar) 0);
481: numtab[HP].val = savhp;
482: apts = savapts;
483: apts1 = savapts1;
484: font = savfont;
485: font1 = savfont1;
486: pts = savpts;
487: pts1 = savpts1;
488: mchbits();
489: setwdf = 0;
490: }
491:
492:
493: tchar vmot()
494: {
495: dfact = lss;
496: vflag++;
497: return(mot());
498: }
499:
500:
501: tchar hmot()
502: {
503: dfact = EM;
504: return(mot());
505: }
506:
507:
508: tchar mot()
509: {
510: register int j, n;
511: register tchar i;
512:
513: j = HOR;
514: getch(); /*eat delim*/
515: if (n = atoi()) {
516: if (vflag)
517: j = VERT;
518: i = makem(quant(n, j));
519: } else
520: i = 0;
521: getch();
522: vflag = 0;
523: dfact = 1;
524: return(i);
525: }
526:
527:
528: tchar sethl(k)
529: int k;
530: {
531: register j;
532: tchar i;
533:
534: j = EM / 2;
535: if (k == 'u')
536: j = -j;
537: else if (k == 'r')
538: j = -2 * j;
539: vflag++;
540: i = makem(j);
541: vflag = 0;
542: return(i);
543: }
544:
545:
546: tchar makem(i)
547: register int i;
548: {
549: register tchar j;
550:
551: if ((j = i) < 0)
552: j = -j;
553: j |= MOT;
554: if (i < 0)
555: j |= NMOT;
556: if (vflag)
557: j |= VMOT;
558: return(j);
559: }
560:
561:
562: tchar getlg(i)
563: tchar i;
564: {
565: tchar j, k;
566: register int lf;
567:
568: if ((lf = fontbase[fbits(i)]->ligfont) == 0) /* font lacks ligatures */
569: return(i);
570: j = getch0();
571: if (cbits(j) == 'i' && (lf & LFI))
572: j = LIG_FI;
573: else if (cbits(j) == 'l' && (lf & LFL))
574: j = LIG_FL;
575: else if (cbits(j) == 'f' && (lf & LFF)) {
576: if ((lf & (LFFI|LFFL)) && lg != 2) {
577: k = getch0();
578: if (cbits(k)=='i' && (lf&LFFI))
579: j = LIG_FFI;
580: else if (cbits(k)=='l' && (lf&LFFL))
581: j = LIG_FFL;
582: else {
583: *pbp++ = k;
584: j = LIG_FF;
585: }
586: } else
587: j = LIG_FF;
588: } else {
589: *pbp++ = j;
590: j = i;
591: }
592: return(i & SFMASK | j);
593: }
594:
595:
596: caselg()
597: {
598:
599: lg = 1;
600: if (skip())
601: return;
602: lg = atoi();
603: }
604:
605:
606: casefp()
607: {
608: register int i, j;
609:
610: skip();
611: i = cbits(getch());
612: if (isdigit(i)) {
613: i -= '0';
614: j = cbits(getch());
615: if (isdigit(j))
616: i = 10 * i + j - '0';
617: }
618: if (i <= 0 || i > nfonts)
619: errprint("fp: bad font position %d", i);
620: else if (skip() || !(j = getrq()))
621: errprint("fp: no font name");
622: else if (skip() || !getname())
623: setfp(i, j, (char*)0);
624: else /* 3rd argument = filename */
625: setfp(i, j, nextf);
626: }
627:
628: setfp(pos, f, truename) /* mount font f at position pos[0...nfonts] */
629: int pos, f;
630: char *truename;
631: {
632: register k;
633: int onw, nw;
634: char longname[NS], shortname[NS];
635:
636: zapwcache(0);
637: if (truename) {
638: strcpy(shortname, truename);
639: } else {
640: shortname[0] = f & BYTEMASK;
641: shortname[1] = f >> BYTE;
642: shortname[2] = '\0';
643: }
1.1.1.2 ! root 644: if (truename && truename[0] == '/') /* full pathname -- use verbatim.out */
1.1 root 645: sprintf(longname, "%s.out", truename);
646: else
647: sprintf(longname, "%s/dev%s/%s.out", fontdir, devname, shortname);
648: if ((k = open(longname, 0)) < 0) {
649: errprint("Can't open %s", longname);
650: return(-1);
651: }
652: onw = fontbase[pos]->nwfont & BYTEMASK;
653: read(k, (char *) fontbase[pos], 3*onw + nchtab + 128-32 + sizeof(struct Font));
654: nw = fontbase[pos]->nwfont & BYTEMASK;
655: kerntab[pos] = (char *) fontab[pos] + nw;
656: codetab[pos] = (char *) fontab[pos] + 2 * nw;
657: /* have to reset the fitab pointer because the width may be different */
658: fitab[pos] = (char *) fontab[pos] + 3 * nw;
659: if (nw > onw) {
660: errprint("Font %s too big for position %d", shortname, pos);
661: fontbase[pos]->nwfont = onw;
662: return(-1);
663: }
664: fontbase[pos]->nwfont = onw; /* so can load a larger one again later */
665: close(k);
666: if (pos == smnt) {
667: smnt = 0;
668: sbold = 0;
669: }
670: if ((fontlab[pos] = f) == 'S')
671: smnt = pos;
672: bdtab[pos] = cstab[pos] = ccstab[pos] = 0;
673: /* if there is a directory, no place to store its name. */
674: /* if position isn't zero, no place to store its value. */
675: /* only time a FONTPOS is pushed back is if it's a */
676: /* standard font on position 0 (i.e., mounted implicitly. */
677: /* there's a bug here: if there are several input lines */
678: /* that look like .ft XX in short successtion, the output */
679: /* will all be in the last one because the "x font ..." */
680: /* comes out too soon. pushing back FONTPOS doesn't work */
681: /* with .ft commands because input is flushed after .xx cmds */
682: ptfpcmd(pos, shortname);
683: if (pos == 0)
684: ch = (tchar) FONTPOS | (tchar) f << 16;
685: return(pos);
686: }
687:
688:
689: casecs()
690: {
691: register i, j;
692:
693: noscale++;
694: skip();
695: if (!(i = getrq()) || (i = findft(i)) < 0)
696: goto rtn;
697: skip();
698: cstab[i] = atoi();
699: skip();
700: j = atoi();
701: if (nonumb)
702: ccstab[i] = 0;
703: else
704: ccstab[i] = findps(j);
705: rtn:
706: zapwcache(0);
707: noscale = 0;
708: }
709:
710:
711: casebd()
712: {
713: register i, j, k;
714:
715: zapwcache(0);
716: k = 0;
717: bd0:
718: if (skip() || !(i = getrq()) || (j = findft(i)) == -1) {
719: if (k)
720: goto bd1;
721: else
722: return;
723: }
724: if (j == smnt) {
725: k = smnt;
726: goto bd0;
727: }
728: if (k) {
729: sbold = j;
730: j = k;
731: }
732: bd1:
733: skip();
734: noscale++;
735: bdtab[j] = atoi();
736: noscale = 0;
737: }
738:
739:
740: casevs()
741: {
742: register i;
743:
744: skip();
745: vflag++;
746: dfact = INCH; /* default scaling is points! */
747: dfactd = 72;
748: res = VERT;
749: i = inumb(&lss);
750: if (nonumb)
751: i = lss1;
752: if (i < VERT)
753: i = VERT;
754: lss1 = lss;
755: lss = i;
756: }
757:
758:
759: casess()
760: {
761: register i;
762:
763: noscale++;
764: skip();
765: if (i = atoi()) {
766: spacesz = i & 0177;
767: zapwcache(0);
768: sps = width(' ' | chbits);
769: }
770: noscale = 0;
771: }
772:
773:
774: tchar xlss()
775: {
776: /* stores \x'...' into
777: /* two successive tchars.
778: /* the first contains HX, the second the value,
779: /* encoded as a vertical motion.
780: /* decoding is done in n2.c by pchar().
781: */
782: int i;
783:
784: getch();
785: dfact = lss;
786: i = quant(atoi(), VERT);
787: dfact = 1;
788: getch();
789: if (i >= 0)
790: *pbp++ = MOT | VMOT | i;
791: else
792: *pbp++ = MOT | VMOT | NMOT | -i;
793: return(HX);
794: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.