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 1989 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 /* from OpenSolaris "t10.c 1.11 05/06/08 SMI" */
32
33 /*
34 * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
35 *
36 * Sccsid @(#)t10.c 1.98 (gritter) 8/19/08
37 */
38
39 /*
40 * Changes Copyright (c) 2014 Carsten Kunze (carsten.kunze at arcor.de)
41 */
42
43 /*
44 * University Copyright- Copyright (c) 1982, 1986, 1988
45 * The Regents of the University of California
46 * All Rights Reserved
47 *
48 * University Acknowledgment- Portions of this document are derived from
49 * software developed by the University of California, Berkeley, and its
50 * contributors.
51 */
52
53 #include <stdlib.h>
54 #include "tdef.h"
55 #include <ctype.h>
56 #include <fcntl.h>
57 #include <unistd.h>
58 #include <string.h>
59 #ifdef EUC
60 #include <locale.h>
61 #endif
62 #include "ext.h"
63 #include "dev.h"
64 #include "afm.h"
65 #include "pt.h"
66 #include "troff.h"
67 #include "unimap.h"
68 #include "fontmap.h"
69 /*
70 * troff10.c
71 *
72 * typesetter interface
73 */
74
75 int vpos = 0; /* absolute vertical position on page */
76 int hpos = 0; /* ditto horizontal */
77
78 int initbdtab[NFONT+1];
79
80 short *chtab;
81 char *chname;
82 int **fontab;
83 char **kerntab;
84 unsigned short **fitab;
85 unsigned short **codetab;
86
87 int Inch;
88 int Hor;
89 int Vert;
90 int Unitwidth;
91 int nfonts;
92 int nsizes;
93 int nchtab;
94 int lettrack;
95 float horscale;
96
97 static float mzoom;
98 static int mtrack;
99 static float mhorscale;
100
101 /* these characters are used as various signals or values
102 * in miscellaneous places.
103 * values are set in specnames in t10.c
104 */
105
106 int c_hyphen;
107 int c_emdash;
108 int c_endash;
109 int c_rule;
110 int c_minus;
111 int c_fi;
112 int c_fl;
113 int c_ff;
114 int c_ffi;
115 int c_ffl;
116 int c_acute;
117 int c_grave;
118 int c_under;
119 int c_rooten;
120 int c_boxrule;
121 int c_lefthand;
122 int c_dagger;
123
124 struct dev dev;
125 struct Font **fontbase;
126
127 int Nfont;
128
129 static int okern(tchar *, tchar *, int);
130 static void pthorscale(int);
131 static void pttrack(int);
132 static void ptanchor(int);
133 static void ptlink(int);
134 static void ptulink(int);
135 static void ptyon(int);
136 static void ptchar(int, int);
137 static void pnc(int, struct afmtab *);
138
139 void
growfonts(int n)140 growfonts(int n)
141 {
142 int i, j;
143
144 fontbase = realloc(fontbase, n * sizeof *fontbase);
145 memset(&fontbase[Nfont], 0, (n - Nfont) * sizeof *fontbase);
146 fontab = realloc(fontab, n * sizeof *fontab);
147 memset(&fontab[Nfont], 0, (n - Nfont) * sizeof *fontab);
148 kerntab = realloc(kerntab, n * sizeof *kerntab);
149 memset(&kerntab[Nfont], 0, (n - Nfont) * sizeof *kerntab);
150 codetab = realloc(codetab, n * sizeof *codetab);
151 memset(&codetab[Nfont], 0, (n - Nfont) * sizeof *codetab);
152 fitab = realloc(fitab, n * sizeof *fitab);
153 memset(&fitab[Nfont], 0, (n - Nfont) * sizeof *fitab);
154 fontlab = realloc(fontlab, n * sizeof *fontlab);
155 memset(&fontlab[Nfont], 0, (n - Nfont) * sizeof *fontlab);
156 cstab = realloc(cstab, n * sizeof *cstab);
157 memset(&cstab[Nfont], 0, (n - Nfont) * sizeof *cstab);
158 ccstab = realloc(ccstab, n * sizeof *ccstab);
159 memset(&ccstab[Nfont], 0, (n - Nfont) * sizeof *ccstab);
160 bdtab = realloc(bdtab, n * sizeof *bdtab);
161 memset(&bdtab[Nfont], 0, (n - Nfont) * sizeof *bdtab);
162 tracktab = realloc(tracktab, n * sizeof *tracktab);
163 memset(&tracktab[Nfont], 0, (n - Nfont) * sizeof *tracktab);
164 fallbacktab = realloc(fallbacktab, n * sizeof *fallbacktab);
165 memset(&fallbacktab[Nfont], 0, (n - Nfont) * sizeof *fallbacktab);
166 zoomtab = realloc(zoomtab, n * sizeof *zoomtab);
167 memset(&zoomtab[Nfont], 0, (n - Nfont) * sizeof *zoomtab);
168 lhangtab = realloc(lhangtab, n * sizeof *lhangtab);
169 memset(&lhangtab[Nfont], 0, (n - Nfont) * sizeof *lhangtab);
170 rhangtab = realloc(rhangtab, n * sizeof *rhangtab);
171 memset(&rhangtab[Nfont], 0, (n - Nfont) * sizeof *rhangtab);
172 kernafter = realloc(kernafter, n * sizeof *kernafter);
173 memset(&kernafter[Nfont], 0, (n - Nfont) * sizeof *kernafter);
174 kernbefore = realloc(kernbefore, n * sizeof *kernbefore);
175 memset(&kernbefore[Nfont], 0, (n - Nfont) * sizeof *kernbefore);
176 ftrtab = realloc(ftrtab, n * sizeof *ftrtab);
177 for (i = Nfont; i < n; i++) {
178 ftrtab[i] = malloc(NCHARS * sizeof **ftrtab);
179 for (j = 0; j < NCHARS; j++)
180 ftrtab[i][j] = j;
181 }
182 lgtab = realloc(lgtab, n * sizeof *lgtab);
183 memset(&lgtab[Nfont], 0, (n - Nfont) * sizeof *lgtab);
184 lgrevtab = realloc(lgrevtab, n * sizeof *lgrevtab);
185 memset(&lgrevtab[Nfont], 0, (n - Nfont) * sizeof *lgrevtab);
186 Nfont = n;
187 }
188
189 void
ptinit(void)190 ptinit(void)
191 {
192 int i, nw;
193 char *filebase, *p, *ap, *descp;
194 char *p2;
195 size_t l;
196 size_t l2;
197
198 if (!strcmp(devname, "html")) html = 1;
199 growfonts(NFONT+1);
200 memcpy(bdtab, initbdtab,
201 max((NFONT+1) * sizeof *bdtab, sizeof initbdtab));
202 uninit();
203 /* open table for device,
204 * read in resolution, size info, font info, etc.
205 * and set params
206 */
207 l = strlen(termtab) + strlen(devname) + 10;
208 l2 = l + 3;
209 p = malloc(l);
210 p2 = malloc(l2);
211 n_strcpy(p, termtab, l);
212 termtab = p;
213 n_strcat(termtab, "/dev", l);
214 n_strcat(termtab, devname, l);
215 n_strcpy(p2, termtab, l2);
216 n_strcat(p2, "/FONTMAP", l2);
217 rdftmap(p2);
218 free(p2);
219 n_strcat(termtab, "/DESC", l); /* makes "..../devXXX/DESC" */
220 if ((descp = readdesc(termtab)) == NULL)
221 done3(1);
222 memcpy(&dev, descp, sizeof dev);
223 Inch = dev.res;
224 Hor = dev.hor;
225 Vert = dev.vert;
226 Unitwidth = dev.unitwidth;
227 nfonts = dev.nfonts;
228 nsizes = dev.nsizes;
229 nchtab = dev.nchtab;
230 if (nchtab >= NCHARS - 128) {
231 errprint("too many special characters in file %s",
232 termtab);
233 done3(1);
234 }
235 filebase = malloc(dev.filesize + 3*EXTRAFONT); /* enough room for whole file */
236 memcpy(filebase, &descp[sizeof dev], dev.filesize); /* all at once */
237 free(descp);
238 pstab = (int *) filebase;
239 for (i = 0; pstab[i]; i++)
240 pstab[i] = pts2u(pstab[i]);
241 chtab = (short *)(pstab + nsizes + 1);
242 chname = (char *) (chtab + dev.nchtab);
243 p = chname + dev.lchname;
244 specnames(); /* install names like "hyphen", etc. */
245 for (i = 1; i <= nfonts; i++) {
246 fontbase[i] = (struct Font *) p;
247 nw = *p & BYTEMASK; /* 1st thing is width count */
248 fontlab[i] = PAIR(fontbase[i]->namefont[0], fontbase[i]->namefont[1]);
249 /* for now, still 2 char names */
250 if (smnt == 0 && fontbase[i]->specfont == 1)
251 smnt = i; /* first special font */
252 p += sizeof(struct Font); /* that's what's on the beginning */
253 if ((ap = strstr(fontbase[i]->namefont, ".afm")) != NULL) {
254 *ap = 0;
255 if (ap == &fontbase[i]->namefont[1])
256 fontlab[i] &= BYTEMASK;
257 loadafm(i, fontlab[i], fontbase[i]->namefont, NULL,
258 1, SPEC_NONE);
259 } else {
260 makefont(i, p, p + nw, p + 2 * nw, p + 3 * nw, nw);
261 }
262 p += 3 * nw + dev.nchtab + 128 - 32;
263 }
264 fontbase[0] = (struct Font *) p; /* the last shall be first */
265 memset(fontbase[0], 0, sizeof *fontbase[0]);
266 nw = EXTRAFONT - dev.nchtab - (128-32) - sizeof (struct Font);
267 fontbase[0]->nwfont = nw;
268 makefont(0, p, p + nw, p + 2 * nw, p + 3 * nw, nw);
269 /* there are a lot of things that used to be constant
270 * that now require code to be executed.
271 */
272 sps = SPS;
273 ses = SES;
274 for (i = 0; i < 16; i++)
275 tabtab[i] = DTAB * (i + 1);
276 pl = 11 * INCH;
277 po = PO;
278 spacesz = SS;
279 sesspsz = SSS;
280 lss = lss1 = VS;
281 ll = ll1 = lt = lt1 = LL;
282 apts = pts2u(apts);
283 apts1 = pts2u(apts1);
284 pts = pts2u(pts);
285 pts1 = pts2u(pts1);
286 ics = ICS;
287 for (i = 0; i <= nfonts; i++)
288 setlig(i, fontbase[i]->ligfont);
289 kern = xflag;
290 if (ascii)
291 return;
292 fdprintf(ptid, "x T %s\n", devname);
293 fdprintf(ptid, "x res %d %d %d\n", Inch, Hor, Vert);
294 fdprintf(ptid, "x init\n"); /* do initialization for particular device */
295 /*
296 for (i = 1; i <= nfonts; i++)
297 fdprintf(ptid, "x font %d %s\n", i, fontbase[i]->namefont);
298 fdprintf(ptid, "x xxx fonts=%d sizes=%d unit=%d\n", nfonts, nsizes, Unitwidth);
299 fdprintf(ptid, "x xxx nchtab=%d lchname=%d nfitab=%d\n",
300 dev.nchtab, dev.lchname, dev.nchtab+128-32);
301 fdprintf(ptid, "x xxx sizes:\nx xxx ");
302 for (i = 0; i < nsizes; i++)
303 fdprintf(ptid, " %d", pstab[i]);
304 fdprintf(ptid, "\nx xxx chars:\nx xxx ");
305 for (i = 0; i < dev.nchtab; i++)
306 fdprintf(ptid, " %s", &chname[chtab[i]]);
307 fdprintf(ptid, "\nx xxx\n");
308 */
309 #ifdef EUC
310 ptlocale(setlocale(LC_CTYPE, NULL));
311 #endif /* EUC */
312 free(termtab);
313 }
314
315 void
specnames(void)316 specnames(void)
317 {
318 static struct {
319 int *n;
320 char *v;
321 } spnames[] = {
322 { &c_hyphen , "hy" },
323 { &c_emdash , "em" },
324 { &c_endash , "en" },
325 { &c_rule , "ru" },
326 { &c_minus , "\\-"},
327 { &c_fi , "fi" },
328 { &c_fl , "fl" },
329 { &c_ff , "ff" },
330 { &c_ffi , "Fi" },
331 { &c_ffl , "Fl" },
332 { &c_acute , "aa" },
333 { &c_grave , "ga" },
334 { &c_under , "ul" },
335 { &c_rooten , "rn" },
336 { &c_boxrule , "br" },
337 { &c_lefthand, "lh" },
338 { &c_dagger , "dg" },
339 { 0 , 0 }
340 };
341 static int twice;
342 int i;
343
344 if (twice++)
345 return;
346 for (i = 0; spnames[i].n; i++)
347 *spnames[i].n = findch(spnames[i].v);
348 }
349
350 int
findch(register char * s)351 findch(register char *s) /* find char s in chname */
352 {
353 register int i;
354
355 for (i = 0; i < nchtab; i++)
356 if (strcmp(s, &chname[chtab[i]]) == 0)
357 return(i + 128);
358 return(0);
359 }
360
361 void
ptout(register tchar i)362 ptout(register tchar i)
363 {
364 register int dv;
365 register tchar *k;
366 int temp, a, b;
367
368 if (isadjspc(i))
369 return;
370 if (olinep >= &oline[olinesz]) {
371 olinesz += 100;
372 k = realloc(oline, olinesz * sizeof *oline);
373 olinep = (tchar *)((char *)olinep + ((char *)k-(char *)oline));
374 oline = k;
375 }
376 if (cbits(i) != '\n') {
377 *olinep++ = i;
378 return;
379 }
380 if (olinep == oline) {
381 lead += lss;
382 return;
383 }
384
385 hpos = po; /* ??? */
386 esc = 0; /* ??? */
387 ptesc(); /* the problem is to get back to the left end of the line */
388 dv = 0;
389 for (k = oline; k < olinep; k++) {
390 if (ismot(*k) && isvmot(*k)) {
391 temp = absmot(*k);
392 if (isnmot(*k))
393 temp = -temp;
394 dv += temp;
395 }
396 }
397 if (dv) {
398 vflag++;
399 *olinep++ = makem(-dv);
400 vflag = 0;
401 }
402
403 b = dip->blss + lss;
404 lead += dip->blss + lss;
405 dip->blss = 0;
406 if (linkout)
407 linkhp = hpos;
408 for (k = oline; k < olinep; )
409 k = ptout0(k, olinep); /* now passing a pointer! */
410 olinep = oline;
411 lead += dip->alss;
412 a = dip->alss;
413 dip->alss = 0;
414 if (linkout)
415 ptlink(linkout);
416 /*
417 fdprintf(ptid, "x xxx end of line: hpos=%d, vpos=%d\n", hpos, vpos);
418 */
419 fdprintf(ptid, "n%d %d\n", b, a); /* be nice to chuck */
420 }
421
422 tchar *
ptout0(tchar * pi,tchar * pend)423 ptout0(tchar *pi, tchar *pend)
424 {
425 struct afmtab *a;
426 register int j;
427 register int k, w = 0;
428 int z, dx, dy, dx2, dy2, n, c;
429 register tchar i;
430 int outsize; /* size of object being printed */
431 double f;
432 int tfont;
433
434 outsize = 1; /* default */
435 i = *pi;
436 k = cbits(i);
437 if (k == FILLER)
438 return(pi+outsize);
439 if (ismot(i)) {
440 j = absmot(i);
441 if (isnmot(i))
442 j = -j;
443 if (isvmot(i))
444 lead += j;
445 else
446 esc += j;
447 return(pi+outsize);
448 }
449 if (k == XON) {
450 if (xfont != mfont)
451 ptfont();
452 if (xpts != mpts || zoomtab[xfont] != mzoom)
453 ptps();
454 if (lead)
455 ptlead();
456 if (esc)
457 ptesc();
458 fdprintf(ptid, "x X ");
459 /*
460 * not guaranteed of finding a XOFF if a word overflow
461 * error occured, so also bound this loop by olinep
462 */
463 pi++;
464 while( cbits(*pi) != XOFF && pi < olinep )
465 outascii(*pi++);
466 oput('\n');
467 if ( cbits(*pi) == XOFF )
468 pi++;
469 return pi;
470 }
471 ;
472 if (k == CHARHT) {
473 if (xflag) {
474 xfont = fbits(i);
475 if (xfont != mfont)
476 ptfont();
477 }
478 if (xpts != mpts || zoomtab[xfont] != mzoom)
479 ptps();
480 j = f = u2pts(sbits(i));
481 if (j != f && xflag && dev.anysize)
482 fdprintf(ptid, "x H -23 %g\n", f);
483 else
484 fdprintf(ptid, "x H %d\n", j);
485 return(pi+outsize);
486 }
487 if (k == SLANT) {
488 if (xflag) {
489 xfont = fbits(i);
490 if (xfont != mfont)
491 ptfont();
492 }
493 fdprintf(ptid, "x S %d\n", (int)sbits(i)-180);
494 return(pi+outsize);
495 }
496 if (k == WORDSP) {
497 oput('w');
498 return(pi+outsize);
499 }
500 if (k == FONTPOS) {
501 n = i >> 22;
502 ptfpcmd(0, macname(n), NULL, 0);
503 return(pi+outsize);
504 }
505 if (k == XFUNC) {
506 switch (fbits(i)) {
507 case ANCHOR:
508 ptanchor(sbits(i));
509 return(pi+outsize);
510 case LINKON:
511 linkout = sbits(i);
512 linkhp = hpos + esc;
513 if (html) ptlink(sbits(i));
514 return(pi+outsize);
515 case LINKOFF:
516 ptlink(html ? 0 : sbits(i));
517 linkout = 0;
518 return(pi+outsize);
519 case ULINKON:
520 linkout = sbits(i);
521 linkhp = hpos + esc;
522 if (html) ptulink(sbits(i));
523 return(pi+outsize);
524 case ULINKOFF:
525 ptulink(html ? 0 : sbits(i));
526 linkout = 0;
527 return(pi+outsize);
528 case INDENT:
529 if (linkout)
530 linkhp += sbits(i);
531 return(pi+outsize);
532 case LETSP:
533 lettrack = sbits(i);
534 return(pi+outsize);
535 case NLETSP:
536 lettrack = -sbits(i);
537 return(pi+outsize);
538 case LETSH:
539 horscale = 1 + (double)sbits(i) / LAFACT;
540 return(pi+outsize);
541 case NLETSH:
542 horscale = 1 - (double)sbits(i) / LAFACT;
543 return(pi+outsize);
544 case YON:
545 if (&pi[outsize] >= pend)
546 return(pi+outsize);
547 ptyon(fetchrq(&pi[outsize]));
548 return(pi+outsize+1);
549 case CHAR:
550 ptchar(sbits(i), iszbit(i) != 0);
551 if (!iszbit(i))
552 esc += okern(pi, pend, outsize);
553 return(pi+outsize);
554 default:
555 return(pi+outsize);
556 }
557 }
558 if (sfbits(i) == oldbits) {
559 xfont = pfont;
560 xpts = ppts;
561 } else
562 xbits(i, 2);
563 if (k < 040 && k != DRAWFCN)
564 return(pi+outsize);
565 if (k >= 32) {
566 if (html && k >= NCHARS)
567 w = getcw(0);
568 else
569 if (widcache[k-32].fontpts == xfont + (xpts<<8) && !setwdf &&
570 kern == 0 && horscale == 0) {
571 w = widcache[k-32].width;
572 lasttrack = widcache[k-32].track;
573 bd = 0;
574 cs = 0;
575 } else {
576 tfont = xfont;
577 w = getcw(k-32);
578 if (tfont != xfont)
579 k = ftrans(xfont, k);
580 }
581 }
582 if (xfont != mfont)
583 ptfont();
584 if (xpts != mpts || zoomtab[xfont] != mzoom)
585 ptps();
586 if (lead)
587 ptlead();
588 if (lettrack || lasttrack || mtrack)
589 pttrack(0);
590 if (horscale || mhorscale)
591 pthorscale(0);
592 w += okern(pi, pend, outsize);
593 if (afmtab && (j = (fontbase[xfont]->afmpos) - 1) >= 0)
594 a = afmtab[j];
595 else
596 a = NULL;
597 j = z = 0;
598 if (k != DRAWFCN) {
599 if (cs && !fmtchar) {
600 if (bd)
601 w += (bd - 1) * HOR;
602 j = (cs - w) / 2;
603 w = cs - j;
604 if (bd)
605 w -= (bd - 1) * HOR;
606 }
607 if (iszbit(i)) {
608 if (cs && !fmtchar)
609 w = -j;
610 else
611 w = 0;
612 z = 1;
613 }
614 }
615 esc += j;
616 /* put out the real character here */
617 if (k == DRAWFCN) {
618 if (esc)
619 ptesc();
620 dx = absmot(pi[3]);
621 if (isnmot(pi[3]))
622 dx = -dx;
623 dy = absmot(pi[4]);
624 if (isnmot(pi[4]))
625 dy = -dy;
626 switch ((c=cbits(pi[1]))) {
627 case DRAWCIRCLE: /* circle */
628 case DRAWCIRCLEFI:
629 fdprintf(ptid, "D%c %d\n", c, dx); /* dx is diameter */
630 w = 0;
631 hpos += dx;
632 break;
633 case DRAWELLIPSE:
634 case DRAWELLIPSEFI:
635 fdprintf(ptid, "D%c %d %d\n", c, dx, dy);
636 w = 0;
637 hpos += dx;
638 break;
639 case DRAWLINE: /* line */
640 k = cbits(pi[2]);
641 fdprintf(ptid, "D%c %d %d ", DRAWLINE, dx, dy);
642 if (k < 128)
643 fdprintf(ptid, "%c\n", k);
644 else
645 fdprintf(ptid, "%s\n", &chname[chtab[k - 128]]);
646 w = 0;
647 hpos += dx;
648 vpos += dy;
649 break;
650 case DRAWARC: /* arc */
651 dx2 = absmot(pi[5]);
652 if (isnmot(pi[5]))
653 dx2 = -dx2;
654 dy2 = absmot(pi[6]);
655 if (isnmot(pi[6]))
656 dy2 = -dy2;
657 fdprintf(ptid, "D%c %d %d %d %d\n", DRAWARC,
658 dx, dy, dx2, dy2);
659 w = 0;
660 hpos += dx + dx2;
661 vpos += dy + dy2;
662 break;
663 case DRAWSPLINE: /* spline */
664 default: /* something else; copy it like spline */
665 fdprintf(ptid, "D%c %d %d", (int)cbits(pi[1]), dx, dy);
666 w = 0;
667 hpos += dx;
668 vpos += dy;
669 if (cbits(pi[3]) == DRAWFCN || cbits(pi[4]) == DRAWFCN) {
670 /* it was somehow defective */
671 fdprintf(ptid, "\n");
672 break;
673 }
674 for (n = 5; cbits(pi[n]) != DRAWFCN; n += 2) {
675 dx = absmot(pi[n]);
676 if (isnmot(pi[n]))
677 dx = -dx;
678 dy = absmot(pi[n+1]);
679 if (isnmot(pi[n+1]))
680 dy = -dy;
681 fdprintf(ptid, " %d %d", dx, dy);
682 hpos += dx;
683 vpos += dy;
684 }
685 fdprintf(ptid, "\n");
686 break;
687 }
688 for (n = 3; cbits(pi[n]) != DRAWFCN; n++)
689 ;
690 outsize = n + 1;
691 } else if (k < 128) {
692 /* try to go faster and compress output */
693 /* by printing nnc for small positive motion followed by c */
694 /* kludgery; have to make sure set all the vars too */
695 if (esc > 0 && esc < 100) {
696 oput(esc / 10 + '0');
697 oput(esc % 10 + '0');
698 oput(k);
699 hpos += esc;
700 esc = 0;
701 } else {
702 if (esc)
703 ptesc();
704 oput('c');
705 oput(k);
706 oput('\n');
707 }
708 } else {
709 if (esc)
710 ptesc();
711 pnc(k, a);
712 }
713 if (bd && !fmtchar) {
714 bd -= HOR;
715 if (esc += bd)
716 ptesc();
717 if (k < 128) {
718 fdprintf(ptid, "c%c\n", k);
719 } else
720 pnc(k, a);
721 if (z)
722 esc -= bd;
723 }
724 esc += w;
725 lettrack = 0;
726 horscale = 0;
727 return(pi+outsize);
728 }
729
730 static void
pnc(int k,struct afmtab * a)731 pnc(int k, struct afmtab *a) {
732 int j;
733
734 if (k >= nchtab + 128) {
735 if (a && (j = a->fitab[k-nchtab-128-32]) < a->nchars &&
736 a->nametab[j] != NULL) {
737 fdprintf(ptid, "CPS%s\n", a->nametab[j]);
738 } else {
739 fdprintf(ptid, "N%d\n",
740 k - (html ? 0 : (nchtab + 128)) );
741 }
742 } else {
743 fdprintf(ptid, "C%s\n", &chname[chtab[k - 128]]);
744 }
745 }
746
747 static int
okern(tchar * pi,tchar * pend,int outsize)748 okern(tchar *pi, tchar *pend, int outsize)
749 {
750 int j;
751
752 for (j = outsize; &pi[j] < pend; j++)
753 if (cbits(pi[j]) != XFUNC || (fbits(pi[j]) != LETSP &&
754 fbits(pi[j]) != NLETSP &&
755 fbits(pi[j]) != LETSH &&
756 fbits(pi[j]) != NLETSH))
757 break;
758 if (&pi[j] < pend)
759 return getkw(pi[0], pi[j]);
760 else
761 return 0;
762 }
763
764 static void
pthorscale(int always)765 pthorscale(int always)
766 {
767 if (horscale || mhorscale) {
768 if (always || mhorscale != horscale)
769 fdprintf(ptid, "x X HorScale %g\n",
770 horscale ? horscale : 1.0);
771 mhorscale = horscale;
772 } else
773 mhorscale = 0;
774 }
775
776 static void
pttrack(int always)777 pttrack(int always)
778 {
779 if (xflag && (lasttrack || lettrack || mtrack)) {
780 if (always || mtrack != (lasttrack + lettrack))
781 fdprintf(ptid, "x X Track %d\n", lasttrack + lettrack);
782 mtrack = lasttrack + lettrack;
783 } else
784 mtrack = 0;
785 }
786
787 void
ptps(void)788 ptps(void)
789 {
790 register int i, j, k;
791 double s, z;
792 int found;
793
794 i = xpts;
795 for (j = 0; i > (k = pstab[j]); j++)
796 if (!k) {
797 k = pstab[--j];
798 break;
799 }
800 found = k == i;
801 if (dev.anysize && xflag)
802 k = i;
803 s = u2pts(k);
804 if ((z = zoomtab[xfont]) != 0 && dev.anysize && xflag)
805 s *= z;
806 if (dev.anysize && xflag && (!found || (z != 0 && z != 1)))
807 fdprintf(ptid, "s-23 %g\n", s);
808 else
809 fdprintf(ptid, "s%d\n", (int)s); /* really should put out string rep of size */
810 mpts = i;
811 mzoom = z;
812 pttrack(0);
813 pthorscale(0);
814 }
815
816 void
ptfont(void)817 ptfont(void)
818 {
819 mfont = xfont;
820 fdprintf(ptid, "f%d\n", xfont);
821 mtrack = 0;
822 pttrack(1);
823 pthorscale(1);
824 }
825
826 void
ptfpcmd(int f,char * s,char * path,int flags)827 ptfpcmd(int f, char *s, char *path, int flags)
828 {
829 if (ascii)
830 return;
831 fdprintf(ptid, "x font %d %s", f, s);
832 if (path) {
833 fdprintf(ptid, " %s", path);
834 if (flags)
835 fdprintf(ptid, " %d", flags);
836 }
837 fdprintf(ptid, "\n");
838 ptfont(); /* make sure that it gets noticed */
839 }
840
841 void
ptlead(void)842 ptlead(void)
843 {
844 vpos += lead;
845 if (!ascii)
846 fdprintf(ptid, "V%d\n", vpos);
847 lead = 0;
848 }
849
850 void
ptesc(void)851 ptesc(void)
852 {
853 hpos += esc;
854 if (esc > 0) {
855 oput('h');
856 if (esc>=10 && esc<100) {
857 oput(esc/10 + '0');
858 oput(esc%10 + '0');
859 } else
860 fdprintf(ptid, "%d", esc);
861 } else
862 fdprintf(ptid, "H%d\n", hpos);
863 esc = 0;
864 }
865
866 void
ptsupplyfont(char * fontname,char * file)867 ptsupplyfont(char *fontname, char *file)
868 {
869 if (ascii)
870 return;
871 fdprintf(ptid, "x X SupplyFont %s %s\n", fontname, file);
872 }
873
874 void
ptpapersize(void)875 ptpapersize(void)
876 {
877 if (ascii || mediasize.flag == 0)
878 return;
879 fdprintf(ptid, "x X PaperSize %d %d %d\n",
880 mediasize.val[2], mediasize.val[3],
881 mediasize.flag&2?1:0);
882 }
883
884 static void
cut1(const char * name,struct box * bp)885 cut1(const char *name, struct box *bp)
886 {
887 if (bp->flag)
888 fdprintf(ptid, "x X %s %d %d %d %d\n", name,
889 bp->val[0], bp->val[1], bp->val[2], bp->val[3]);
890 }
891
892 void
ptcut(void)893 ptcut(void)
894 {
895 if (ascii)
896 return;
897 cut1("TrimAt", &trimat);
898 cut1("BleedAt", &bleedat);
899 cut1("CropAt", &cropat);
900 }
901
902 void
ptlocale(const char * cp)903 ptlocale(const char *cp)
904 {
905 static char *lp;
906
907 if (cp != NULL) {
908 size_t l;
909 free(lp);
910 l = strlen(cp) + 1;
911 lp = malloc(l);
912 n_strcpy(lp, cp, l);
913 }
914 if (ascii || realpage == 0 || lp == NULL || dev.lc_ctype == 0)
915 return;
916 fdprintf(ptid, "x X LC_CTYPE %s\n", lp);
917 }
918
919 static void
ptanchor(int n)920 ptanchor(int n)
921 {
922 struct ref *rp;
923
924 if (ascii)
925 return;
926 for (rp = anchors; rp; rp = rp->next)
927 if (rp->cnt == n) {
928 if (html) {
929 fdprintf(ptid, "x X Anchor %s\n", rp->name);
930 } else {
931 fdprintf(ptid, "x X Anchor %d,%d %s\n",
932 vpos + lead - lss, hpos + esc, rp->name);
933 }
934 break;
935 }
936 }
937
938 static void
_ptlink(int n,struct ref * rstart,const char * type)939 _ptlink(int n, struct ref *rstart, const char *type)
940 {
941 struct ref *rp;
942
943 if (ascii)
944 return;
945 if (html && !n) {
946 fdprintf(ptid, "x X %s\n", type);
947 return;
948 }
949 for (rp = rstart; rp; rp = rp->next)
950 if (rp->cnt == n) {
951 if (html)
952 fdprintf(ptid, "x X %s %s\n", type, rp->name);
953 else
954 fdprintf(ptid, "x X %s %d,%d,%d,%d %s\n",
955 type,
956 linkhp, vpos + pts2u(1),
957 hpos + esc, vpos - pts * 8 / 10,
958 rp->name);
959 break;
960 }
961 }
962
963 static void
ptlink(int n)964 ptlink(int n)
965 {
966 _ptlink(n, links, "Link");
967 }
968
969 static void
ptulink(int n)970 ptulink(int n)
971 {
972 _ptlink(n, ulinks, "ULink");
973 }
974
975 static void
ptyon(int i)976 ptyon(int i)
977 {
978 struct contab *cp;
979 tchar c;
980 int k, nl;
981 filep savip;
982
983 if ((cp = findmx(i)) == NULL || !cp->mx) {
984 nosuch(i);
985 return;
986 }
987 if (xfont != mfont)
988 ptfont();
989 if (xpts != mpts || zoomtab[xfont] != mzoom)
990 ptps();
991 if (lead)
992 ptlead();
993 if (esc)
994 ptesc();
995 fdprintf(ptid, "x X ");
996 savip = ip;
997 ip = (filep)cp->mx;
998 app = 1;
999 k = -1;
1000 nl = 0;
1001 while ((c = rbf()) != 0) {
1002 if ((k = cbits(c)) != '\n') {
1003 while (nl--)
1004 oputs("\n+");
1005 nl = 0;
1006 outascii(c);
1007 } else
1008 nl++;
1009 }
1010 while (nl-- > 1)
1011 oputs("\n+");
1012 oput('\n');
1013 app = 0;
1014 ip = savip;
1015 }
1016
1017 static void
ptchar1(struct charout * cp,int z)1018 ptchar1(struct charout *cp, int z)
1019 {
1020 filep savip;
1021 tchar i, *k, *savoline, *savolinep;
1022 size_t savolinesz;
1023 int savhpos, savvpos, savlettrack;
1024
1025 savoline = oline;
1026 savolinep = olinep;
1027 savolinesz = olinesz;
1028 olinep = oline = NULL;
1029 olinesz = 0;
1030 savlettrack = lettrack;
1031 lettrack = 0;
1032 savhpos = hpos + esc;
1033 savvpos = vpos + lead;
1034 savip = ip;
1035 ip = cp->op;
1036 app++;
1037 fmtchar++;
1038 while ((i = rbf()) != 0 && cbits(i) != '\n' && cbits(i) != FLSS)
1039 pchar(i);
1040 for (k = oline; k < olinep; )
1041 k = ptout0(k, olinep);
1042 fmtchar--;
1043 app--;
1044 ip = savip;
1045 free(oline);
1046 oline = savoline;
1047 olinep = savolinep;
1048 olinesz = savolinesz;
1049 lettrack = savlettrack;
1050 esc = savhpos - hpos;
1051 if (!z)
1052 esc += cs ? cs : cp->width + lettrack;
1053 lead = savvpos - vpos;
1054 }
1055
1056 static void
ptchar(int n,int z)1057 ptchar(int n, int z)
1058 {
1059 struct charout *cp = &charout[n];
1060 int savbd;
1061
1062 ptchar1(cp, z);
1063 if (bd) {
1064 bd -= HOR;
1065 if (esc += bd)
1066 ptesc();
1067 savbd = bd;
1068 bd = 0;
1069 ptchar1(cp, z);
1070 bd = savbd;
1071 if (iszbit(cp->ch))
1072 esc -= bd;
1073 }
1074 lettrack = 0;
1075 }
1076
1077 void
newpage(int n)1078 newpage(int n) /* called at end of each output page (we hope) */
1079 {
1080 int i;
1081
1082 realpage++;
1083 ptlead();
1084 vpos = 0;
1085 if (ascii)
1086 return;
1087 fdprintf(ptid, "p%d\n", n); /* new page */
1088 for (i = 0; i <= nfonts; i++) {
1089 if (fontbase[i] == NULL)
1090 continue;
1091 if (afmtab && fontbase[i]->afmpos) {
1092 struct afmtab *a = afmtab[(fontbase[i]->afmpos)-1];
1093 if (a->encpath == NULL)
1094 a->encpath = afmencodepath(a->path);
1095 fdprintf(ptid, "x font %d %s %s %d\n", i,
1096 macname(fontlab[i]),
1097 a->encpath, (int)a->spec);
1098 if (a->supply)
1099 ptsupplyfont(a->fontname, a->supply);
1100 } else if (fontbase[i]->namefont[0])
1101 fdprintf(ptid, "x font %d %s\n", i, macname(fontlab[i]));
1102 }
1103 ptps();
1104 ptfont();
1105 ptpapersize();
1106 ptcut();
1107 ptlocale(NULL);
1108 }
1109
1110 void
pttrailer(void)1111 pttrailer(void)
1112 {
1113 fdprintf(ptid, "x trailer\n");
1114 }
1115
1116 void
ptstop(void)1117 ptstop(void)
1118 {
1119 fdprintf(ptid, "x stop\n");
1120 }
1121
1122 void
dostop(void)1123 dostop(void)
1124 {
1125 if (ascii)
1126 return;
1127 ptlead();
1128 vpos = 0;
1129 /* fdprintf(ptid, "x xxx end of page\n");*/
1130 if (!nofeed)
1131 pttrailer();
1132 ptlead();
1133 fdprintf(ptid, "x pause\n");
1134 flusho();
1135 mpts = mfont = 0;
1136 ptesc();
1137 esc = po;
1138 hpos = vpos = 0; /* probably in wrong place */
1139 }
1140