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