|
|
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.