|
|
1.1 ! root 1: /* ! 2: * dcan ! 3: * driver for impress/imagen canon laser printer ! 4: */ ! 5: ! 6: /* ! 7: output language from troff: ! 8: all numbers are character strings ! 9: ! 10: sn size in points ! 11: fn font as number from 1-n ! 12: cx ascii character x ! 13: Cxyz funny char xyz. terminated by white space ! 14: Hn go to absolute horizontal position n ! 15: Vn go to absolute vertical position n (down is positive) ! 16: hn go n units horizontally (relative) ! 17: vn ditto vertically ! 18: nnc move right nn, then print c (exactly 2 digits!) ! 19: (this wart is an optimization that shrinks output file size ! 20: about 35% and run-time about 15% while preserving ascii-ness) ! 21: Dt ...\n draw operation 't': ! 22: Dl x y line from here by x,y ! 23: Dc d circle of diameter d with left side here ! 24: De x y ellipse of axes x,y with left side here ! 25: Da x y r arc counter-clockwise by x,y of radius r ! 26: D~ x y x y ... wiggly line by x,y then x,y ... ! 27: nb a end of line (information only -- no action needed) ! 28: b = space before line, a = after ! 29: p new page begins -- set v to 0 ! 30: #...\n comment ! 31: x ...\n device control functions: ! 32: x i init ! 33: x T s name of device is s ! 34: x r n h v resolution is n/inch ! 35: h = min horizontal motion, v = min vert ! 36: x p pause (can restart) ! 37: x s stop -- done for ever ! 38: x t generate trailer ! 39: x f n s font position n contains font s ! 40: x H n set character height to n ! 41: x S n set slant to N ! 42: ! 43: Subcommands like "i" are often spelled out like "init". ! 44: */ ! 45: ! 46: #include <stdio.h> ! 47: #include <signal.h> ! 48: #include <math.h> ! 49: #include <ctype.h> ! 50: #include "dev.h" ! 51: #include "/usr/bwk/imagen/src/imPcodes.h" ! 52: #include "glyph.h" ! 53: ! 54: #define abs(n) ((n) >= 0 ? (n) : -(n)) ! 55: ! 56: #define NFONT 10 ! 57: ! 58: int xx, yy; ! 59: int xoffset = 0; /* shift output right by this amount */ ! 60: int yoffset = -120; /* shift down (!) by this amount */ ! 61: /* -120 is 1/2 inch on canon */ ! 62: /* allows for 10 inch page -- */ ! 63: /* toss away 1/2 inch on top and bottom */ ! 64: float xfac = 1.0; /* scaling factor for x */ ! 65: float yfac = 1.0; /* scaling factor for y */ ! 66: int inputarea = 3; /* input area = 3 * 8k bytes */ ! 67: int rotate = 0; /* 0 => portrait, 1 => landscape */ ! 68: int output = 0; /* do we do output at all? */ ! 69: int pageno = -1; /* output page number */ ! 70: int nolist = 0; /* output page list if > 0 */ ! 71: int olist[20]; /* pairs of page numbers */ ! 72: ! 73: int erase = 1; ! 74: float aspect = 1; /* default aspect ratio */ ! 75: ! 76: struct dev dev; ! 77: struct font *fontbase[NFONT+1]; ! 78: short *pstab; ! 79: int nsizes = 1; ! 80: int nfonts; ! 81: int smnt; /* index of first special font */ ! 82: int nchtab; ! 83: char *chname; ! 84: short *chtab; ! 85: char *fitab[NFONT+1]; ! 86: char *widthtab[NFONT+1]; /* widtab would be a better name */ ! 87: char *codetab[NFONT+1]; /* device codes */ ! 88: ! 89: #define FATAL 1 ! 90: #define BMASK 0377 ! 91: int dbg = 0; ! 92: long lineno = 0; ! 93: int res = 972; /* input assumed computed according to this resolution */ ! 94: /* initial value to avoid 0 divide */ ! 95: FILE *tf = NULL; /* output file pointer */ ! 96: char *tempfile; ! 97: char *fontdir = "/usr/lib/font"; ! 98: char *bitdir = "/usr/lib/font/devcan"; ! 99: char *acctfile = "/usr/adm/dcanacct"; ! 100: int acctpages = 0; ! 101: int copies = 1; ! 102: char *username = "???"; ! 103: char *getlogin(); ! 104: extern char devname[]; ! 105: ! 106: FILE *fp = stdin; /* input file pointer */ ! 107: ! 108: main(argc, argv) ! 109: char *argv[]; ! 110: { ! 111: char buf[BUFSIZ]; ! 112: char *mktemp(); ! 113: int done(); ! 114: extern int DX, DY; ! 115: ! 116: username = getlogin(); ! 117: while (argc > 1 && argv[1][0] == '-') { ! 118: switch (argv[1][1]) { ! 119: case 'c': ! 120: copies = atoi(&argv[1][2]); ! 121: break; ! 122: case 'r': ! 123: rotate = !rotate; ! 124: break; ! 125: case 't': ! 126: tf = stdout; ! 127: break; ! 128: case 'x': ! 129: xoffset = atoi(&argv[1][2]); ! 130: break; ! 131: case 'y': ! 132: yoffset = atoi(&argv[1][2]); ! 133: break; ! 134: case 'f': ! 135: bitdir = argv[2]; ! 136: argv++; ! 137: argc--; ! 138: break; ! 139: case 'a': ! 140: aspect = atof(&argv[1][2]); ! 141: break; ! 142: case 'e': ! 143: erase = 0; ! 144: break; ! 145: case 'o': ! 146: outlist(&argv[1][2]); ! 147: break; ! 148: case 'i': /* set input area parameter */ ! 149: inputarea = atoi(&argv[1][2]); ! 150: if (inputarea < 1) ! 151: inputarea = 1; ! 152: else if (inputarea > 5) ! 153: inputarea = 5; ! 154: break; ! 155: case 'p': /* pixels of resolution */ ! 156: DX = DY = atoi(&argv[1][2]); ! 157: if (DX == 0) ! 158: DX = DY = 1; ! 159: break; ! 160: case 'd': ! 161: dbg = atoi(&argv[1][2]); ! 162: if (dbg == 0) dbg = 1; ! 163: tf = stdout; ! 164: break; ! 165: } ! 166: argc--; ! 167: argv++; ! 168: } ! 169: ! 170: signal(SIGINT, done); ! 171: signal(SIGHUP, done); ! 172: signal(SIGQUIT, done); ! 173: ! 174: tempfile = mktemp("/tmp/dcanXXXXX"); ! 175: if (tf != stdout) ! 176: if ((tf = fopen(tempfile, "w")) == NULL) ! 177: error(FATAL, "can't open temporary file %s", tempfile); ! 178: ! 179: if (argc <= 1) ! 180: conv(stdin); ! 181: else ! 182: while (--argc > 0) { ! 183: if (strcmp(*++argv, "-") == 0) ! 184: fp = stdin; ! 185: else if ((fp = fopen(*argv, "r")) == NULL) ! 186: error(FATAL, "can't open %s", *argv); ! 187: conv(fp); ! 188: fclose(fp); ! 189: } ! 190: fclose(tf); ! 191: sprintf(buf, "ipr -p %d -c %d %s", acctpages, copies, tempfile); ! 192: if(dbg){fprintf(stderr, "executing %s\n", buf); done();} ! 193: if (tf != stdout) { ! 194: system(buf); ! 195: account(); ! 196: } ! 197: done(); ! 198: } ! 199: ! 200: outlist(s) /* process list of page numbers to be printed */ ! 201: char *s; ! 202: { ! 203: int n1, n2, i; ! 204: ! 205: nolist = 0; ! 206: while (*s) { ! 207: n1 = 0; ! 208: if (isdigit(*s)) ! 209: do ! 210: n1 = 10 * n1 + *s++ - '0'; ! 211: while (isdigit(*s)); ! 212: else ! 213: n1 = -9999; ! 214: n2 = n1; ! 215: if (*s == '-') { ! 216: s++; ! 217: n2 = 0; ! 218: if (isdigit(*s)) ! 219: do ! 220: n2 = 10 * n2 + *s++ - '0'; ! 221: while (isdigit(*s)); ! 222: else ! 223: n2 = 9999; ! 224: } ! 225: olist[nolist++] = n1; ! 226: olist[nolist++] = n2; ! 227: if (*s != '\0') ! 228: s++; ! 229: } ! 230: olist[nolist] = 0; ! 231: if (dbg) ! 232: for (i=0; i<nolist; i += 2) ! 233: printf("%3d %3d\n", olist[i], olist[i+1]); ! 234: } ! 235: ! 236: in_olist(n) /* is n in olist? */ ! 237: int n; ! 238: { ! 239: int i; ! 240: ! 241: if (nolist == 0) ! 242: return(1); /* everything is included */ ! 243: for (i = 0; i < nolist; i += 2) ! 244: if (n >= olist[i] && n <= olist[i+1]) ! 245: return(1); ! 246: return(0); ! 247: } ! 248: ! 249: conv(fp) ! 250: register FILE *fp; ! 251: { ! 252: register int c, k; ! 253: int m, n, i, n1, m1; ! 254: char str[100], buf[300]; ! 255: ! 256: while ((c = getc(fp)) != EOF) { ! 257: switch (c) { ! 258: case '\n': /* when input is text */ ! 259: case ' ': ! 260: case 0: /* occasional noise creeps in */ ! 261: break; ! 262: case '0': case '1': case '2': case '3': case '4': ! 263: case '5': case '6': case '7': case '8': case '9': ! 264: /* two motion digits plus a character */ ! 265: hmot((c-'0')*10 + getc(fp)-'0'); ! 266: put1(getc(fp)); ! 267: break; ! 268: case 'c': /* single ascii character */ ! 269: put1(getc(fp)); ! 270: break; ! 271: case 'C': ! 272: fscanf(fp, "%s", str); ! 273: put1s(str); ! 274: break; ! 275: case 'D': /* draw function */ ! 276: fgets(buf, sizeof(buf), fp); ! 277: switch (buf[0]) { ! 278: case 'l': /* draw a line */ ! 279: sscanf(buf+1, "%d %d", &n, &m); ! 280: drawline(n, m, "."); ! 281: break; ! 282: case 'c': /* circle */ ! 283: sscanf(buf+1, "%d", &n); ! 284: drawcirc(n); ! 285: break; ! 286: case 'e': /* ellipse */ ! 287: sscanf(buf+1, "%d %d", &m, &n); ! 288: drawellip(m, n); ! 289: break; ! 290: case 'a': /* arc */ ! 291: sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); ! 292: drawarc(n, m, n1, m1); ! 293: break; ! 294: case '~': /* wiggly line */ ! 295: drawwig(buf+1); ! 296: break; ! 297: default: ! 298: error(FATAL, "unknown drawing function %s\n", buf); ! 299: break; ! 300: } ! 301: break; ! 302: case 's': ! 303: fscanf(fp, "%d", &n); /* ignore fractional sizes */ ! 304: setsize(t_size(n)); ! 305: break; ! 306: case 'f': ! 307: fscanf(fp, "%s", str); ! 308: setfont(t_font(str)); ! 309: break; ! 310: case 'H': /* absolute horizontal motion */ ! 311: /* fscanf(fp, "%d", &n); */ ! 312: while ((c = getc(fp)) == ' ') ! 313: ; ! 314: k = 0; ! 315: do { ! 316: k = 10 * k + c - '0'; ! 317: } while (isdigit(c = getc(fp))); ! 318: ungetc(c, fp); ! 319: hgoto(k); ! 320: break; ! 321: case 'h': /* relative horizontal motion */ ! 322: /* fscanf(fp, "%d", &n); */ ! 323: while ((c = getc(fp)) == ' ') ! 324: ; ! 325: k = 0; ! 326: do { ! 327: k = 10 * k + c - '0'; ! 328: } while (isdigit(c = getc(fp))); ! 329: ungetc(c, fp); ! 330: hmot(k); ! 331: break; ! 332: case 'w': /* word space */ ! 333: break; ! 334: case 'V': ! 335: fscanf(fp, "%d", &n); ! 336: vgoto(n); ! 337: break; ! 338: case 'v': ! 339: fscanf(fp, "%d", &n); ! 340: vmot(n); ! 341: break; ! 342: case 'p': /* new page */ ! 343: fscanf(fp, "%d", &n); ! 344: t_page(n); ! 345: break; ! 346: case 'n': /* end of line */ ! 347: while (getc(fp) != '\n') ! 348: ; ! 349: t_newline(); ! 350: break; ! 351: case '#': /* comment */ ! 352: while (getc(fp) != '\n') ! 353: ; ! 354: break; ! 355: case 'x': /* device control */ ! 356: devcntrl(fp); ! 357: break; ! 358: default: ! 359: error(!FATAL, "unknown input character %o %c\n", c, c); ! 360: done(); ! 361: } ! 362: } ! 363: } ! 364: ! 365: devcntrl(fp) /* interpret device control functions */ ! 366: FILE *fp; ! 367: { ! 368: char str[20], str1[50], buf[50]; ! 369: int c, n; ! 370: ! 371: fscanf(fp, "%s", str); ! 372: switch (str[0]) { /* crude for now */ ! 373: case 'i': /* initialize */ ! 374: fileinit(); ! 375: t_init(0); ! 376: break; ! 377: case 'T': /* device name */ ! 378: fscanf(fp, "%s", devname); ! 379: break; ! 380: case 't': /* trailer */ ! 381: t_trailer(); ! 382: break; ! 383: case 'p': /* pause -- can restart */ ! 384: t_reset('p'); ! 385: break; ! 386: case 's': /* stop */ ! 387: t_reset('s'); ! 388: break; ! 389: case 'r': /* resolution assumed when prepared */ ! 390: fscanf(fp, "%d", &res); ! 391: break; ! 392: case 'f': /* font used */ ! 393: fscanf(fp, "%d %s", &n, str); ! 394: fgets(buf, sizeof buf, fp); /* in case there's a filename */ ! 395: ungetc('\n', fp); /* fgets goes too far */ ! 396: str1[0] = 0; /* in case there's nothing to come in */ ! 397: sscanf(buf, "%s", str1); ! 398: loadfont(n, str, str1); ! 399: break; ! 400: /* these don't belong here... */ ! 401: case 'H': /* char height */ ! 402: fscanf(fp, "%d", &n); ! 403: t_charht(n); ! 404: break; ! 405: case 'S': /* slant */ ! 406: fscanf(fp, "%d", &n); ! 407: t_slant(n); ! 408: break; ! 409: } ! 410: while ((c = getc(fp)) != '\n') /* skip rest of input line */ ! 411: if (c == EOF) ! 412: break; ! 413: } ! 414: ! 415: fileinit() /* read in font and code files, etc. */ ! 416: { ! 417: int i, fin, nw; ! 418: char *malloc(), *filebase, *p; ! 419: char temp[60]; ! 420: ! 421: /* open table for device, ! 422: /* read in resolution, size info, font info, etc. ! 423: /* and set params ! 424: */ ! 425: strcpy(devname, "202"); /* this is the only char set we have */ ! 426: /* the resolution, etc., is already in */ ! 427: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname); ! 428: if ((fin = open(temp, 0)) < 0) ! 429: error(FATAL, "can't open tables for %s\n", temp); ! 430: read(fin, &dev, sizeof(struct dev)); ! 431: nfonts = dev.nfonts; ! 432: nsizes = dev.nsizes; ! 433: nchtab = dev.nchtab; ! 434: filebase = malloc(dev.filesize); /* enough room for whole file */ ! 435: read(fin, filebase, dev.filesize); /* all at once */ ! 436: pstab = (short *) filebase; ! 437: chtab = pstab + nsizes + 1; ! 438: chname = (char *) (chtab + dev.nchtab); ! 439: p = chname + dev.lchname; ! 440: for (i = 0; i <= nfonts; i++) { ! 441: fontbase[i] = NULL; ! 442: widthtab[i] = codetab[i] = fitab[i] = NULL; ! 443: } ! 444: close(fin); ! 445: } ! 446: ! 447: fontprint(i) /* debugging print of font i (0,...) */ ! 448: { ! 449: int j, k, n; ! 450: char *p; ! 451: ! 452: printf("font %d:\n", i); ! 453: p = (char *) fontbase[i]; ! 454: n = fontbase[i]->nwfont & BMASK; ! 455: printf("base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n", ! 456: p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]); ! 457: printf("widths:\n"); ! 458: for (j=0; j <= n; j++) { ! 459: printf(" %2d", widthtab[i][j] & BMASK); ! 460: if (j % 20 == 19) printf("\n"); ! 461: } ! 462: printf("\ncodetab:\n"); ! 463: for (j=0; j <= n; j++) { ! 464: printf(" %2d", codetab[i][j] & BMASK); ! 465: if (j % 20 == 19) printf("\n"); ! 466: } ! 467: printf("\nfitab:\n"); ! 468: for (j=0; j <= dev.nchtab + 128-32; j++) { ! 469: printf(" %2d", fitab[i][j] & BMASK); ! 470: if (j % 20 == 19) printf("\n"); ! 471: } ! 472: printf("\n"); ! 473: } ! 474: ! 475: loadfont(n, s, s1) /* load font info for font s on position n (0...) */ ! 476: int n; ! 477: char *s, *s1; ! 478: { ! 479: char temp[60]; ! 480: int fin, nw, norig; ! 481: ! 482: if (n < 0 || n > NFONT) ! 483: error(FATAL, "illegal fp command %d %s", n, s); ! 484: if (fontbase[n] != NULL && strcmp(s, fontbase[n]->namefont) == 0) ! 485: return; ! 486: if (s1 == NULL || s1[0] == '\0') ! 487: sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s); ! 488: else ! 489: sprintf(temp, "%s/%s.out", s1, s); ! 490: if ((fin = open(temp, 0)) < 0) { ! 491: error(!FATAL, "can't open font table %s", temp); ! 492: return; ! 493: } ! 494: if (fontbase[n] != NULL) ! 495: free(fontbase[n]); ! 496: fontbase[n] = (struct font *) malloc(3*255 + dev.nchtab + ! 497: (128-32) + sizeof(struct font)); ! 498: if (fontbase[n] == NULL) ! 499: error(FATAL, "Out of space in loadfont %s\n", s); ! 500: read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct font)); ! 501: close(fin); ! 502: if (smnt == 0 && fontbase[n]->specfont == 1) ! 503: smnt = n; ! 504: nw = fontbase[n]->nwfont & BMASK; ! 505: widthtab[n] = (char *) fontbase[n] + sizeof(struct font); ! 506: codetab[n] = (char *) widthtab[n] + 2 * nw; ! 507: fitab[n] = (char *) widthtab[n] + 3 * nw; ! 508: t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); ! 509: if (dbg > 1) fontprint(n); ! 510: } ! 511: ! 512: ! 513: error(f, s, a1, a2, a3, a4, a5, a6, a7) { ! 514: fprintf(stderr, "dcan: "); ! 515: fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); ! 516: fprintf(stderr, " near line %ld\n", lineno); ! 517: if (f) ! 518: done(); ! 519: } ! 520: ! 521: ! 522: /* ! 523: Here beginneth all the stuff that really depends ! 524: on the canon (we hope). ! 525: */ ! 526: ! 527: #define RES 240 /* resolution of canon */ ! 528: #define MAXX (8*RES + RES/2) /* 8-1/2 inches? */ ! 529: #define MAXY (11 * RES) ! 530: #define WIDTH 8 ! 531: #define LOGWID 3 ! 532: #define K * 1024 /* clever, so watch out */ ! 533: ! 534: char devname[20] = "can"; ! 535: ! 536: int nglyph = 0; /* number of glyphs loaded */ ! 537: int totglyph = 0; /* total space used by glyphs sent down */ ! 538: int maxglyph = 16 K; /* maximum space for glyphs */ ! 539: ! 540: #define oput(c) if (output) xychar(c); else; ! 541: ! 542: /* input coordinate system: */ ! 543: ! 544: int size = 1; ! 545: int font = 1; /* current font */ ! 546: int hpos; /* horizontal position where we are supposed to be next (left = 0) */ ! 547: int vpos; /* current vertical position (down positive) */ ! 548: int DX = 10; /* step size in x for drawing */ ! 549: int DY = 10; /* step size in y for drawing */ ! 550: ! 551: /* canon coordinate system: */ ! 552: ! 553: int lastsize = -1; ! 554: int lastfont = -1; ! 555: int lastx = -1; ! 556: int lasty = -1; ! 557: int lastfam = -1; ! 558: ! 559: int drawdot = '.'; /* draw with this character */ ! 560: int drawsize = 1; /* shrink by this factor when drawing */ ! 561: ! 562: t_init(reinit) /* initialize device */ ! 563: int reinit; ! 564: { ! 565: int i; ! 566: ! 567: if (! reinit) { ! 568: for (i = 0; i < nchtab; i++) ! 569: if (strcmp(&chname[chtab[i]], "l.") == 0) ! 570: break; ! 571: if (i < nchtab) { ! 572: drawdot = i + 128; ! 573: drawsize = 1; ! 574: } else { ! 575: drawdot = '.'; ! 576: drawsize = 2; /* half size */ ! 577: } ! 578: ! 579: /* some Imagen-specific junk: */ ! 580: fprintf(tf, "%1d", inputarea); /* their kludge for setting */ ! 581: /* input area to x * 8k */ ! 582: maxglyph = 52 K - inputarea K - 4 K; ! 583: /* glyph area = 52K - input */ ! 584: fprintf(tf, " %s\n", username); ! 585: putc(0, tf); /* terminate this [so they say] */ ! 586: fprintf(tf, "%8.8s", "dcan1/24"); /* padding 8 bytes */ ! 587: /* ignored but needed */ ! 588: xfac = (float) RES / res * aspect; ! 589: yfac = (float) RES / res; ! 590: } ! 591: fflush(tf); ! 592: hpos = vpos = 0; ! 593: setsize(t_size(10)); /* start somewhere */ ! 594: } ! 595: ! 596: t_page(pg) /* do whatever new page functions */ ! 597: { ! 598: register int i, j, n; ! 599: register unsigned char *p; ! 600: static int firstpage = 1; ! 601: ! 602: pageno = pg; ! 603: if(dbg)fprintf(stderr, "t_page %d, output=%d\n", pg, output); ! 604: if (output != 0) { ! 605: /* beginning of first page, or */ ! 606: /* have just printed something, and seen p<n> for next one */ ! 607: /* ought to read in entire page, select needed glyphs */ ! 608: putc(AEND, tf); ! 609: firstpage = 0; ! 610: fflush(tf); ! 611: } ! 612: output = in_olist(pg); ! 613: if (output) { ! 614: if (totglyph >= maxglyph) { ! 615: clearglyphs(); ! 616: totglyph = 0; ! 617: } ! 618: putc(APAGE, tf); ! 619: acctpages++; ! 620: } ! 621: lastx = lasty = -1; ! 622: t_init(1); ! 623: } ! 624: ! 625: t_newline() /* do whatever for the end of a line */ ! 626: { ! 627: hpos = 0; ! 628: } ! 629: ! 630: t_size(n) /* convert integer to internal size number*/ ! 631: int n; ! 632: { ! 633: int i; ! 634: ! 635: if (n <= pstab[0]) ! 636: return(1); ! 637: else if (n >= pstab[nsizes-1]) ! 638: return(nsizes); ! 639: for (i = 0; n > pstab[i]; i++) ! 640: ; ! 641: return(i+1); ! 642: } ! 643: ! 644: t_charht(n) /* set character height to n */ ! 645: int n; ! 646: { ! 647: /* punt for now */ ! 648: } ! 649: ! 650: t_slant(n) /* set slant to n */ ! 651: int n; ! 652: { ! 653: /* punt for now */ ! 654: } ! 655: ! 656: t_font(s) /* convert string to internal font number */ ! 657: char *s; ! 658: { ! 659: int n; ! 660: ! 661: n = atoi(s); ! 662: if (n < 1 || n > nfonts) ! 663: n = 1; ! 664: return(n); ! 665: } ! 666: ! 667: t_reset(c) ! 668: { ! 669: int n; ! 670: ! 671: if (output) ! 672: acctpages++; ! 673: if (c == 's') { ! 674: putc(AEND, tf); ! 675: putc(AEOF, tf); ! 676: } ! 677: } ! 678: ! 679: account() /* record paper use */ ! 680: { ! 681: FILE *f = NULL; ! 682: ! 683: if (tf == stdout) ! 684: return; ! 685: f = fopen(acctfile, "a"); ! 686: if (f != NULL) { ! 687: if (username == NULL) ! 688: username = "???"; ! 689: fprintf(f, "%4d %s\n", acctpages, username); ! 690: } ! 691: } ! 692: ! 693: ! 694: t_trailer() ! 695: { ! 696: } ! 697: ! 698: hgoto(n) ! 699: { ! 700: hpos = n; /* this is where we want to be */ ! 701: /* before printing a character, */ ! 702: /* have to make sure it's true */ ! 703: } ! 704: ! 705: hmot(n) /* generate n units of horizontal motion */ ! 706: int n; ! 707: { ! 708: hpos += n; ! 709: } ! 710: ! 711: vgoto(n) ! 712: { ! 713: vpos = n; ! 714: } ! 715: ! 716: vmot(n) /* generate n units of vertical motion */ ! 717: int n; ! 718: { ! 719: vgoto(vpos + n); /* ignores rounding */ ! 720: } ! 721: ! 722: put1s(s) /* s is a funny char name */ ! 723: register char *s; ! 724: { ! 725: static int i = 0; ! 726: ! 727: if (!output) ! 728: return; ! 729: if (dbg) printf("%s ", s); ! 730: if (strcmp(s, &chname[chtab[i]]) != 0) ! 731: for (i = 0; i < nchtab; i++) ! 732: if (strcmp(&chname[chtab[i]], s) == 0) ! 733: break; ! 734: if (i < nchtab) ! 735: put1(i + 128); ! 736: else ! 737: i = 0; ! 738: } ! 739: ! 740: put1(c) /* output char c */ ! 741: register int c; ! 742: { ! 743: char *pw; ! 744: register char *p; ! 745: register int i, j, k; ! 746: int ofont, code, w; ! 747: ! 748: if (!output) ! 749: return; ! 750: c -= 32; ! 751: if (c <= 0) { ! 752: if (dbg) printf("non-exist 0%o\n", c+32); ! 753: return; ! 754: } ! 755: k = ofont = font; ! 756: i = fitab[font][c] & BMASK; ! 757: if (i != 0) { /* it's on this font */ ! 758: p = codetab[font]; ! 759: pw = widthtab[font]; ! 760: } else if (smnt > 0) { /* on special (we hope) */ ! 761: for (k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1)) ! 762: if ((i = fitab[k][c] & BMASK) != 0) { ! 763: p = codetab[k]; ! 764: pw = widthtab[k]; ! 765: setfont(k); ! 766: break; ! 767: } ! 768: } ! 769: if (i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts) { ! 770: if (dbg) printf("not found 0%o\n", c+32); ! 771: return; ! 772: } ! 773: if (dbg) { ! 774: if (isprint(c+32)) ! 775: printf("%c %d\n", c+32, code); ! 776: else ! 777: printf("%03o %d\n", c+32, code); ! 778: } else ! 779: oput(code); ! 780: if (font != ofont) ! 781: setfont(ofont); ! 782: } ! 783: ! 784: setsize(n) /* set point size to n (internal) */ ! 785: int n; ! 786: { ! 787: size = n; ! 788: } ! 789: ! 790: /* font position info: */ ! 791: ! 792: struct { ! 793: char *name; ! 794: int number; ! 795: } fontname[NFONT+1]; ! 796: ! 797: t_fp(n, s, si) /* font position n now contains font s, intname si */ ! 798: int n; ! 799: char *s, *si; ! 800: { ! 801: fontname[n].name = s; ! 802: fontname[n].number = atoi(si); ! 803: } ! 804: ! 805: setfont(n) /* set font to n */ ! 806: int n; ! 807: { ! 808: if (!output) ! 809: return; ! 810: if (n < 0 || n > NFONT) ! 811: error(FATAL, "illegal font %d\n", n); ! 812: font = n; ! 813: } ! 814: ! 815: done() ! 816: { ! 817: exit(0); ! 818: } ! 819: ! 820: /* ! 821: The following things manage raster font information. ! 822: The big problem is mapping desired font + size into ! 823: available font + size. For now, a file RASTERLIST ! 824: contains entries like ! 825: R 6 8 10 14 999 ! 826: I 8 10 12 999 ! 827: ... ! 828: This data is used to create an array "fontdata" that ! 829: describes legal fonts and sizes, and pointers to any ! 830: data from files that has actually been loaded. ! 831: */ ! 832: ! 833: struct fontdata { ! 834: char name[4]; /* e.g., "R" or "PA" */ ! 835: int size[10]; /* e.g., 6 8 10 14 0 */ ! 836: struct fontset *fsp[10]; /* either NULL or block of data */ ! 837: }; ! 838: ! 839: #define MAXFONT 20 /* no more than this many fonts forever */ ! 840: ! 841: struct fontdata fontdata[MAXFONT]; ! 842: int maxfonts = 0; /* how many actually used; set in initfontdata() */ ! 843: ! 844: struct Fontheader fh; ! 845: struct fontset { ! 846: int size; ! 847: int family; ! 848: struct Charparam *chp; ! 849: unsigned char *cdp; /* char data pointer */ ! 850: unsigned char *chused; /* bit-indexed; 1 if char downloaded */ ! 851: }; ! 852: ! 853: /* A global variable for the current font+size */ ! 854: struct fontset *fs; ! 855: int nfamily = 0; /* number of "families" (font+size) */ ! 856: ! 857: initfontdata() /* read RASTERLIST information */ ! 858: { ! 859: char name[100]; ! 860: FILE *fp; ! 861: int i, j, n; ! 862: ! 863: sprintf(name, "%s/RASTERLIST", bitdir); ! 864: if ((fp = fopen(name, "r")) == NULL) ! 865: error(FATAL, "can't open %s\n", name); ! 866: maxfonts = 0; ! 867: while (fscanf(fp, "%s", fontdata[maxfonts].name) != EOF) { ! 868: i = 0; ! 869: while (fscanf(fp, "%d", &n) != EOF && n < 100) { ! 870: fontdata[maxfonts].size[i] = n; ! 871: fontdata[maxfonts].fsp[i] = NULL; ! 872: i++; ! 873: } ! 874: fontdata[maxfonts].size[i] = 999; ! 875: if (++maxfonts > MAXFONT) ! 876: error(FATAL, "Too many fonts in RASTERLIST"); ! 877: } ! 878: fclose(fp); ! 879: if (dbg) { ! 880: fprintf(stderr, "initfontdata(): maxfonts=%d\n", maxfonts); ! 881: for (i = 0; i < maxfonts; i++) { ! 882: fprintf(stderr, "%.4s ", fontdata[i].name); ! 883: for (j = 0; fontdata[i].size[j] < 100; j++) ! 884: fprintf(stderr, " %3d", fontdata[i].size[j]); ! 885: fprintf(stderr, "\n"); ! 886: } ! 887: } ! 888: } ! 889: ! 890: getfontdata(f, s) /* causes loading of font information if needed */ ! 891: char *f; ! 892: int s; ! 893: { ! 894: int fd, n, i, j; ! 895: char name[100]; ! 896: static int first = 1; ! 897: ! 898: if (first) { ! 899: initfontdata(); ! 900: first = 0; ! 901: } ! 902: ! 903: for (i = 0; i < maxfonts; i++) ! 904: if (strcmp(f, fontdata[i].name) == 0) ! 905: break; ! 906: if (i >= maxfonts) /* the requested font wasn't there */ ! 907: i = 0; /* use the first one (probably R) */ ! 908: ! 909: /* find the best approximation to size s */ ! 910: for (j = 1; s >= fontdata[i].size[j]; j++) ! 911: ; ! 912: j--; ! 913: ! 914: /* open file if necessary */ ! 915: if (fontdata[i].fsp[j] == NULL) { ! 916: fs = (struct fontset *) malloc(sizeof(struct fontset)); ! 917: fontdata[i].fsp[j] = fs; ! 918: fs->chp = (struct Charparam *) malloc(256*sizeof(struct Charparam)); ! 919: sprintf(name, "%s/%s.%d%s", bitdir, ! 920: f, fontdata[i].size[j], rotate? "r" : ""); ! 921: fd = open(name, 0); ! 922: if (fd == -1) ! 923: error(FATAL, "can't open %s\n", name); ! 924: read(fd, &fh, sizeof(struct Fontheader)); ! 925: read(fd, fs->chp, 256*sizeof(struct Charparam)); ! 926: fs->size = fontdata[i].size[j]; ! 927: fs->family = nfamily; ! 928: nfamily += 2; /* even-odd leaves room for big fonts */ ! 929: fs->cdp = (unsigned char *) malloc(fh.f_size); ! 930: fs->chused = (unsigned char *) malloc(256/8); ! 931: read(fd, fs->cdp, fh.f_size); ! 932: close(fd); ! 933: } ! 934: fs = fontdata[i].fsp[j]; ! 935: } ! 936: ! 937: xychar(c) ! 938: register int c; ! 939: { ! 940: register unsigned char *p; ! 941: register struct Charparam *par; ! 942: register int x, y; ! 943: int i, n, rwid, ht, fam; ! 944: ! 945: x = hpos * xfac + 0.5; ! 946: x += xoffset; ! 947: y = vpos * yfac + 0.5; ! 948: y += yoffset; ! 949: ! 950: if (font != lastfont || size != lastsize) { ! 951: getfontdata(fontname[font].name, pstab[size-1]); ! 952: lastsize = size; ! 953: lastfont = font; ! 954: } ! 955: par = fs->chp + c; ! 956: p = fs->cdp + par->c_addr; ! 957: ! 958: fam = fs->family; ! 959: if (c > 127) ! 960: fam++; ! 961: if (fam != lastfam) { ! 962: putc(AF, tf); ! 963: putc(lastfam = fam, tf); ! 964: } ! 965: ! 966: /* first cut: ship each glyph as needed. */ ! 967: /* ignore memory use, efficiency, etc. */ ! 968: ! 969: if ( !bit(fs->chused, c) ) { /* 1st use of this character */ ! 970: nglyph++; ! 971: totglyph += glspace(par); ! 972: setbit(fs->chused, c); ! 973: putc(ASGLY, tf); ! 974: putint((fam << 7) | c, tf); ! 975: /* putc(par->c_width, tf); /* character width */ ! 976: putc(0, tf); /* zap nominal width because it's wrong */ ! 977: putc(par->c_left + par->c_right + 1, tf); ! 978: putc(par->c_left, tf); ! 979: /* this nonsense fixes a bug in output produced by rec.c: */ ! 980: /* when up is < 0 (and = 0?) size is one too big */ ! 981: rwid = (1 + par->c_left + par->c_right + WIDTH-1) / WIDTH; ! 982: ht = par->c_size / rwid; ! 983: par->c_down = ht - par->c_up; ! 984: putc(par->c_down + par->c_up, tf); ! 985: putc(par->c_up, tf); ! 986: for (i = par->c_size; i--; ) ! 987: putc(*p++, tf); ! 988: } ! 989: ! 990: if (y != lasty) { ! 991: putc(AV, tf); ! 992: putint(y<<1, tf); ! 993: lasty = y; ! 994: } ! 995: if (x != lastx) { ! 996: if (abs(x-lastx) > 127) { ! 997: putc(AH, tf); ! 998: putint(x<<1, tf); ! 999: } else { ! 1000: putc(AM, tf); ! 1001: putc(x-lastx, tf); ! 1002: putc(AM, tf); ! 1003: } ! 1004: } ! 1005: ! 1006: if (c <= 127) ! 1007: putc(c, tf); /* fails if c > 127, probably disastrously */ ! 1008: else ! 1009: putc(c-128, tf); ! 1010: /* lastx = x + par->c_width; */ ! 1011: lastx = x; ! 1012: } ! 1013: ! 1014: glspace(par) ! 1015: struct Charparam *par; ! 1016: { ! 1017: int n; ! 1018: ! 1019: /* works only for small glyphs right now */ ! 1020: ! 1021: n = 12 ! 1022: + ((par->c_left+par->c_right+1+15)/16 ) * (par->c_up+par->c_down) ! 1023: + 2; ! 1024: return n; ! 1025: } ! 1026: ! 1027: clearglyphs() /* remove "used" bits from all glyphs */ ! 1028: /* delete all families */ ! 1029: /* very conservative policy */ ! 1030: { ! 1031: int i, j, k; ! 1032: struct fontset *f; ! 1033: ! 1034: if (tf == stdout) fprintf(stderr, "clear %d glyphs (%d/%d) on page %d\n", ! 1035: nglyph, totglyph, maxglyph, pageno); ! 1036: for (i = 0; i < maxfonts; i++) ! 1037: for (j = 0; fontdata[i].size[j] < 999; j++) { ! 1038: f = fontdata[i].fsp[j]; ! 1039: if (f != NULL) { ! 1040: putc(ADELF, tf); ! 1041: putc(f->family, tf); ! 1042: for (k = 0; k < 256/8; k++) ! 1043: f->chused[k] = 0; ! 1044: } ! 1045: } ! 1046: } ! 1047: ! 1048: bit(p, n) /* return n-th bit of p[] */ ! 1049: char *p; ! 1050: int n; ! 1051: { ! 1052: return (p[n/8] >> (7 - n%8)) & 01; ! 1053: } ! 1054: ! 1055: setbit(p, n) /* set bit n of p[] */ ! 1056: char *p; ! 1057: int n; ! 1058: { ! 1059: p[n/8] |= 01 << (7 - n%8); ! 1060: } ! 1061: ! 1062: putint(n, f) ! 1063: int n; ! 1064: FILE *f; ! 1065: { ! 1066: putc(n >> 8, f); ! 1067: putc(n & 0377, f); ! 1068: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.