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