|
|
1.1 root 1: /*
2: * output.c
3: * troff
4: * Back end to output device-dependent bits for troff.
5: * Writes either PCL escape sequences for the Hewlett-Packard LaserJet
6: * or (if pflag) PostScript.
7: */
8:
9: #include <ctype.h>
10: #include "roff.h"
11:
12: extern char *fontname();
13: extern char *ndiv10();
14:
15: /* HP LaserJet PCL. */
16: #define HPLJEJECT "\033&l0H" /* page eject */
17:
18: /* PostScript. */
19: #define PSLINIT "90 rotate\n0 -612 translate\n"
20: #define PSEJECT "\nshowpage\n"
21: #if ZKLUDGE
22: #define PSSAVE1 "/state1 save def\n"
23: #define PSREST1 "state1 restore\n"
24: #endif
25:
26: /*
27: * Device parameters.
28: */
29: int ntroff = TROFF; /* Programme is TROFF type */
30:
31: long semmul = 1; /* Multiplier for em space */
32: long semdiv = 1; /* Divisor for em space */
33:
34: long senmul = 1; /* Multiplier for en space */
35: long sendiv = 2; /* Divisor for en space */
36:
37: long shrmul = 12; /* Horizontal resolution (mul) */
38: long shrdiv = 5; /* Horizontal resolution (div) */
39:
40: long sinmul = 720; /* Multiplier for inch */
41: long sindiv = 1; /* Divisor for inch */
42:
43: long snrmul = 1; /* Narrow space (mul) */
44: long snrdiv = 6; /* Narrow space (div) */
45:
46: long svrmul = 12; /* Vertical resolution (mul) */
47: long svrdiv = 5; /* Vertical resolution (div) */
48:
49: /*
50: * Local variables for output writer.
51: */
52: static int hposd; /* device horizontal postition */
53: static int vposd; /* device vertical position */
54: static int inword; /* in word flag for PostScript */
55: static int lastfont = -1; /* current output font */
56:
57: #if ZKLUDGE
58: static int npages; /* Output page count */
59: #endif
60:
61: /*
62: * Initialize the device.
63: */
64: dev_init()
65: {
66: #if ZKLUDGE
67: if (Zflag)
68: printf(PSSAVE1);
69: #endif
70: }
71:
72: #if ZKLUDGE
73: /*
74: * Close the device.
75: */
76: dev_close()
77: {
78: if (Zflag != 0)
79: printf(PSREST1);
80: }
81: #endif
82:
83: /*
84: * Compute the scaled width of a character:
85: * width(c) == unit(swdmul*fonwidt[c]*psz, swddiv).
86: */
87: int
88: width(c) register int c;
89: {
90: register long l;
91:
92: /* Watch out for sign-extension of argument! */
93: l = swdmul * fonwidt[c & 0xFF] * psz;
94: return (swddiv == 1) ? (int)l : (int)(l/swddiv);
95: }
96:
97: /*
98: * Given a font number, change to the given font.
99: */
100: dev_font(n) register int n;
101: {
102: register FWTAB *fp;
103:
104: #if 0
105: fprintf(stderr, "dev_font(%d)\n", n);
106: #endif
107: if (n >= nfonts)
108: panic("bad font %d at dev_font, nfonts=%d", n, nfonts);
109: curfont = n;
110: addidir(DFONT, n);
111: fp = fwptab[n];
112: csz = fcsz[n];
113: swdmul = (long)fp->f_num;
114: swddiv = (long)fp->f_den;
115: fonwidt = fp->f_width;
116: varsp = fp->f_spacing;
117: dev_ps(fpsz[n]);
118: }
119:
120: /*
121: * Change to the given pointsize.
122: * There are several different notions of pointsize:
123: * global psz (and oldpsz) in the environment,
124: * fpsz for each font in the environment,
125: * fp->f_psz for each font, and
126: * wpsz in flushl() (see comment below).
127: * The font fp->f_psz is used to initialize fpsz in the environment
128: * but is subsequently unused.
129: * The environment fpsz[n] gives the current pointsize for each font.
130: * The environment psz is the pointsize of the current input font,
131: * wpsz is the pointsize of the current output font.
132: * Changing pointsize with a .ps directive or \s escape
133: * changes fpsz[] for each font.
134: */
135: dev_ps(n) register int n;
136: {
137: if (n <= 0) {
138: printe("illegal pointsize %d, ignored", n/10);
139: return;
140: }
141: oldpsz = psz;
142: psz = n;
143: addidir(DPSZE, n);
144:
145: /* Scale space width for pointsize change. */
146: if (psz != oldpsz && sszdiv != 0)
147: ssz = (int)((long)sszmul * psz / sszdiv);
148: }
149:
150: /*
151: * Set a fixed pointsize for a font.
152: */
153: dev_fz(font, size) char *font, size;
154: {
155: char name[2];
156: register int n;
157:
158: argname(font, name);
159: if ((n = font_number(name, ".fz: ")) < 0)
160: return;
161: fwptab[n]->f_flags |= F_FIXED;
162: fpsz[n] = number(size, SMPOIN, SDPOIN, fpsz[n], 0, fpsz[n]);
163: if (n == curfont)
164: dev_ps(fpsz[n]);
165: }
166:
167: /*
168: * Specify a constant size font.
169: */
170: dev_cs(n, size) register int n, size;
171: {
172: fcsz[n] = size;
173: if (n == curfont)
174: csz = size;
175: }
176:
177: /*
178: * Change all non-fixed font pointsizes to the given pointsize,
179: * then change the current pointsize.
180: */
181: newpsze(n) register int n;
182: {
183: register int i;
184:
185: if (n <= 0) {
186: printe("illegal pointsize %d, ignored", n/10);
187: return;
188: }
189: for (i = 0; i < nfonts; i++)
190: if (((fwptab[i]->f_flags) & F_FIXED) == 0) {
191: fwptab[i]->f_flags &= ~F_USED;
192: fpsz[i] = n;
193: }
194: dev_ps(n);
195: }
196:
197: /*
198: * Given a pointer to a buffer containing stream directives
199: * and a pointer to the end of the buffer,
200: * print the buffer.
201: * The output writer maintains its own notion of current font and pointsize
202: * because [nt]roff buffers output and then flushes at the end of a line;
203: * the environment "curfont" is the current font for input stream processing,
204: * the output writer "font" is the current output stream font.
205: * The font change is implicit until a character is written in the new font.
206: */
207: flushl(buffer, bufend) CODE *buffer, *bufend;
208: {
209: register CODE *cp;
210: register int code;
211: int i;
212: char *tp;
213: static FWTAB *fp; /* current font table entry */
214: static int newpage = 1; /* new page flag */
215: static int hpost; /* troff horizontal pos (u's) */
216: static int vpost; /* troff vertical pos (u's) */
217: static int font = -1; /* current font */
218: static unsigned char *wtab; /* current font width table */
219: static long wnum; /* current width numerator */
220: static long wden; /* current width denominator */
221: static int wpsz; /* current pointsize */
222:
223: for (cp = buffer; cp < bufend; cp++) {
224: code = cp->l_arg.c_code;
225: i = cp->l_arg.c_iarg;
226: if (pflag && is_dir(code))
227: endword();
228: #if 0
229: fprintf(stderr, "output: code=%d arg=%d\n", code, i);
230: #endif
231: switch (code) {
232: case DNULL: /* null code */
233: case DHYPH: /* place to hyphenate */
234: continue;
235: case DHMOV: /* move horizontally */
236: case DPADC: /* paddable character */
237: hpost += i;
238: if (hpost < 0)
239: hpost = 0;
240: continue;
241: case DVMOV: /* move vertically */
242: vpost += i;
243: if (vpost < 0)
244: vpost = 0;
245: continue;
246: case DFPOS: /* fix position */
247: move();
248: continue;
249: case DFONT: /* change font */
250: if (i == font)
251: continue; /* unchanged */
252: if ((unsigned)i >= nfonts)
253: panic("bad font %d, nfonts=%d", i, nfonts);
254: font = i;
255: fp = fwptab[font];
256: wtab = fp->f_width;
257: wpsz = fpsz[font];
258: wnum = (long)fp->f_num * wpsz;
259: wden = (long)fp->f_den;
260: continue;
261: case DTRAB: /* transparent line */
262: tp = cp->b_arg.c_bufp;
263: while (*tp)
264: putchar(*tp++);
265: free(cp->b_arg.c_bufp);
266: continue;
267: case DPSZE: /* change pointsize */
268: if (wpsz != i) {
269: wpsz = i;
270: wnum = (long)fp->f_num * wpsz;
271: if (pflag) {
272: /* Mask off used bit to force rescaling */
273: lastfont = -1;
274: fp->f_flags &= ~F_USED;
275: } else {
276: printf("\033(s%sV", ndiv10(wpsz));
277: }
278: }
279: continue;
280: case DSPAR: /* space down and return */
281: hposd = hpost = 0;
282: vpost += i;
283: if (vpost < 0)
284: vpost = 0;
285: else if (vpost >= pgl) {
286: /* New page. */
287: endpage();
288: vpost %= pgl;
289: vposd = vpost;
290: newpage = 1;
291: }
292: continue;
293: case DHLIN:
294: case DVLIN:
295: if (code == DHLIN && i < 0) {
296: hpost += i;
297: i = -i;
298: }
299: hposd = hpost;
300: vposd = vpost;
301: move();
302: if (code == DHLIN) {
303: printf("\n%s 0 L", ndiv10(i));
304: hpost += i;
305: } else {
306: printf("\n0 %s L", ndiv10(-i));
307: vpost += i;
308: }
309: continue;
310: default: /* print something */
311: /* Start a new page. */
312: if (newpage) {
313: if (lflag && pflag)
314: printf(PSLINIT);
315: hposd = hpost;
316: vposd = vpost;
317: move();
318: newpage = 0;
319: }
320: /*
321: * Check whether we are on a new page.
322: * Note, the laser goes to funny places when it
323: * crosses a page boundary.
324: */
325: if (vpost >= pgl) {
326: /* New page. */
327: endpage();
328: vpost %= pgl;
329: vposd = vpost;
330: hposd = hpost;
331: newpage = 1;
332: }
333: /* Output move to new position if appropriate. */
334: if (hpost != hposd || vpost != vposd) {
335: hposd = hpost;
336: vposd = vpost;
337: move();
338: }
339: /* Change to different font. */
340: if (lastfont != font)
341: selectfont(lastfont=font, wpsz);
342: if (code == DHYPC)
343: code = '-';
344: if (code < 0 || code >= NWIDTH)
345: panic("bad directive %d", code);
346: hpost += cp->c_arg.c_move;
347: hposd += unit(wnum*wtab[code], wden);
348: i = code;
349: if (pflag && !inword)
350: startword();
351: outchar(code);
352: if (enb != 0) { /* dag's enbolden... */
353: hposd -= unit(wnum*wtab[i], wden);
354: vposd -= enb;
355: move();
356: putchar(code);
357: hposd -= enb;
358: move();
359: putchar(code);
360: vposd += enb;
361: putchar(code);
362: hposd += (unit(wnum*wtab[i], wden) + enb);
363: move();
364: }
365: }
366: }
367: }
368:
369: /*
370: * Move horizontally and/or vertically.
371: * This used to shift PCL output right to avoid printing at left border;
372: * that responsibility is now left to the user.
373: */
374: move()
375: {
376: static int vold = -1;
377:
378: if (pflag) {
379: /* PostScript. */
380: if (inword)
381: endword();
382: printf("\n%s", ndiv10(hposd+pof));
383: printf(" %s M", ndiv10(pgl - vposd));
384: } else {
385: /* PCL. */
386: if (vposd == vold)
387: printf("\033&a%dH", hposd+pof);
388: else
389: printf("\033&a%dh%dV", hposd+pof, vposd);
390: }
391: vold = vposd;
392: }
393:
394: /*
395: * Select a font.
396: */
397: selectfont(font, ptsize) int font, ptsize;
398: {
399: register FWTAB *fp;
400: register char *s;
401:
402: fp = fwptab[font];
403: if (!pflag) {
404: /* Select font via PCL. */
405: printf("\033(%d%c", fp->f_symset/32, fp->f_symset%32+64); /* symbol set */
406: printf("\033(s%dp", fp->f_spacing); /* spacing */
407: /* fp->f_pitch is in quarterdots/char, convert to chars/inch. */
408: if (fp->f_pitch != 0)
409: printf("%sh", ndiv10(12000/fp->f_pitch)); /* pitch */
410: printf("%sv", ndiv10(fpsz[font])); /* point size */
411: printf("%ds", fp->f_style); /* style */
412: printf("%db", fp->f_weight); /* stroke weight */
413: printf("%dT", fp->f_face); /* typeface */
414: return;
415: }
416: /* Select font via PostScript. */
417: if ((s = fontname(font)) == NULL)
418: panic("botch: fontname(%d)", font);
419: endword();
420: if ((fp->f_flags & F_USED) == 0) {
421: fp->f_flags |= F_USED;
422: printf("\n"
423: "/font%s /%s findfont %d.%d scalefont def\n"
424: "/f%s { font%s setfont } bind def\n",
425: s, fp->f_PSname,
426: ptsize / 10, ptsize % 10,
427: s, s);
428: }
429: printf(" f%s", s);
430: }
431:
432: /*
433: * Convert e.g. 123 to "12.3" without using floating point output.
434: * Return a pointer to statically allocated buffer.
435: */
436: char *
437: ndiv10(n) register int n;
438: {
439: static char buf[10];
440: register char *cp;
441:
442: cp = buf;
443: if (n < 0) {
444: n = -n;
445: *cp++ = '-';
446: }
447: if ((n % 10) == 0)
448: sprintf(cp, "%d", n/10);
449: else
450: sprintf(cp, "%d.%d", n/10, n%10);
451: return buf;
452: }
453:
454: /*
455: * Output a character.
456: * If writing PostScript output, watch out for "()\\"
457: * and expand high-bit characters to octal escapes.
458: */
459: outchar(n) register int n;
460: {
461: if (pflag) {
462: if (n >= 128) {
463: printf("\\%03o", n);
464: return;
465: } else if (n == '(' || n == ')' || n == '\\')
466: putchar('\\');
467: }
468: putchar(n);
469: }
470:
471: startword()
472: {
473: putchar(' ');
474: putchar('(');
475: inword = 1;
476: }
477:
478: endword()
479: {
480: if (inword) {
481: printf(") S");
482: inword = 0;
483: }
484: }
485:
486: endpage()
487: {
488: if (pflag)
489: endword();
490: printf((pflag) ? PSEJECT : HPLJEJECT);
491: #if ZKLUDGE
492: if (Zflag && ++npages % Zflag == 0) {
493: register int i;
494:
495: printf(PSREST1);
496: printf(PSSAVE1);
497: for (i = 0; i < nfonts; i++)
498: fwptab[i]->f_flags &= ~F_USED;
499: lastfont = -1;
500: dev_font(curfont);
501: }
502: #endif
503: }
504:
505: /* end of output.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.