/* TeX driver */ /* $Log: df.c.backup,v $ Revision 1.2 88/02/03 08:52:23 simpson added tpic support Revision 1.1 88/01/15 13:03:27 simpson initial release Revision 0.2 87/12/18 11:39:36 simpson added void for lint Revision 0.1 87/12/11 18:30:46 simpson beta test */ #ifndef lint static char *rcs = "$Header: df.c.backup,v 1.2 88/02/03 08:52:23 simpson Exp $"; #endif #include #include #include #include #include #include #include #include #include "dvi.h" #include "constants.h" #include "fontinfo.h" #include "fontnode.h" /* Cast for accessing LocalInfo */ #define LI(p) ((struct LocalInfo *)p->localinfo) struct Stack { long h, v, w, x, y, z; }; struct DviNode { long dvinumber; struct DviNode *next; }; struct LocalInfo { long widths[256]; /* RSUs. Font but ! file mag in account */ short mapsize[2][256];/* Width & height of each char bitmap */ int qmsheight; /* Height to give QMS printer */ int qmsbaseline; /* Baseline height to give QMS printer */ struct DviNode *dvifontnumbers; /* List of #s DVI file uses */ char pathname[81]; /* Full pathname in file system */ }; double ConvInches; /* RSU->inches. File mag not taken into account */ char *Whoami; /* argv[0] */ char Orientation = 'P'; /* P=Portrait, L=Landscape */ char *Model; /* Model of printer being used */ char PKName[101]; /* Only used by pkeofsocleanup() */ char *Xxxstring; /* String found in XXX? command */ char *Pxxxstring; /* And a pointer used by lexical analyzer */ char PKDir[101]; /* Location of PK font files */ int Magnification; /* Magnification file was TeXed at (x1000) */ int MaxBlocks; /* # of free blocks w/out ram or rom fonts, ovls */ int CurRamBlocks; /* # of blocks used by ram fonts */ int CurRomBlocks; /* # of blocks used by rom fonts */ int DownLoadFNum; /* Number of font currently being downloaded */ int UserFontCount = 30001; /* User fonts start getting #s from here */ int Origin[2]; /* Origin of a postprocessor graph in pixels */ long Numerator, Denominator; /* From .dvi preamble */ FILE *ReadLine; /* Debugger port tty */ struct sigvec SigStruct; struct FontNode *FontList; /* List containing all fnts & their attributes */ extern char *Host, *User; extern FILE *Accting; extern Boolean Accounting; extern int NumPages; main(argc, argv) int argc; char *argv[]; { extern char *optarg; extern int optind; void qmsfntfree(), cleanup(), dvieofsoexit(), readpreamble(), seteoffunction(), dvieofsocleanup(), process(); Boolean found, loadnametable(), setnewid(); int c; int *intptr, *tempintptr; int simplyexit(), callcleanup(); int romlist[41]; /* List of rom font #s */ char *strcpy(); #ifdef DEBUG char *malloc(), orien; int i, fontno, size; struct fontnode *fn; FILE *f; #endif PROFILE_VALUE *v, *getbindingvalue(); struct qmsram *raminfo; struct qmsfnt *fntinfo; struct FontNode *createfontlist(); struct fontnode *p; Whoami = argv[0]; while ((c = getopt(argc, argv, "x:y:n:h:w:l:i:")) != EOF) switch (c) { case 'x': if (atoi(optarg) > 2550) Orientation = 'L'; break; case 'h': Host = optarg; break; case 'n': User = optarg; break; case 'y': case 'w': case 'l': case 'i': break; default: exit(2); } SigStruct.sv_handler = simplyexit; SigStruct.sv_mask = 0; SigStruct.sv_onstack = 0; (void)sigvec(SIGINT, &SigStruct, (struct sigvec *)NULL); if (optind < argc) { Accounting = TRUE; if (!(Accting = fopen(argv[optind], "a"))) { fprintf(stderr, "%s: cannot open accounting file %s\n", Whoami, argv[optind]); Accounting = FALSE; } } if (!(v = getbindingvalue("model")) || v->class != PROFILE_STRING && v->class != PROFILE_OTHER) { fprintf(stderr, "%s: model binding missing or invalid in configuration file\n", Whoami); exit(2); } Model = v->value.s; fputs(QUICON, stdout); printf("%s^Z%s%s", CLEAROVERLAY, CLEARAOVERLAY, ENDCMD); fputs(QUICOFF, stdout); (void)fflush(stdout); if (!(v = getbindingvalue("readline")) || v->class != PROFILE_STRING && v->class != PROFILE_OTHER) { fprintf(stderr, "%s: readline binding missing or invalid in configuration file\n", Whoami); exit(2); } if (!(ReadLine = fopen(v->value.s, "r"))) { fprintf(stderr, "%s: could not open %s for reading\n", Whoami, v->value.s); exit(2); } #ifdef DEBUG raminfo = (struct qmsram *)malloc((unsigned)sizeof(struct qmsram)); raminfo->TR = 401; raminfo->AR = 387; raminfo->FR = 13; raminfo->OR = 0; #else qmsopen(fileno(stdout), fileno(ReadLine)); if (!(raminfo = qmsram())) { fprintf(stderr, "%s: could not get printer ram info\n", Whoami); exit(2); } #endif MaxBlocks = raminfo->AR + raminfo->FR; /* Save 5 blocks for filling with tpic */ MaxBlocks -= 5; #ifdef DEBUG fntinfo = (struct qmsfnt *)malloc((unsigned)sizeof(struct qmsfnt)); fntinfo->ram = fntinfo->rom = NULL; for (i = 0; i < 13; i++) { switch (i) { case 0: fontno = 521; orien = 'L'; break; case 1: fontno = 522; orien = 'L'; break; case 2: fontno = 523; orien = 'L'; break; case 3: fontno = 524; orien = 'L'; break; case 4: fontno = 1100; orien = 'P'; break; case 5: fontno = 1103; orien = 'P'; break; case 6: fontno = 1200; orien = 'P'; break; case 7: fontno = 1204; orien = 'P'; break; case 8: fontno = 1217; orien = 'L'; case 9: fontno = 7009; orien = 'P'; break; case 10: fontno = 7010; orien = 'P'; break; case 11: fontno = 7036; orien = 'P'; break; case 12: fontno = 7037; orien = 'P'; break; } fn = (struct fontnode *)malloc((unsigned)sizeof(struct fontnode)); fn->next = fntinfo->rom, fntinfo->rom = fn; fn->orientation = orien; fn->number = fontno; fn->bytes = 1024; /* Rom fonts occupy one block */ fn->version = '0'; fn->class = '1'; } /* For testing, ramfonts contains the already loaded fonts. It should * consist of lines containing two numbers and a letter, the first being * the font number, the second being the font size, and the third letter * is an orientation. The orientation should be the character immediately * after the size of the font. */ if (f = fopen("ramfonts", "r")) { /* File is optional for testing */ while (fscanf(f, "%d%d%c", &fontno, &size, &orien) == 3) { fn = (struct fontnode *)malloc((unsigned)sizeof(struct fontnode)); fn->next = fntinfo->ram, fntinfo->ram = fn; fn->orientation = orien; fn->number = fontno; fn->bytes = size; fn->version = '0'; fn->class = '1'; raminfo->AR -= CEILING(size / 1024.0); raminfo->FR += CEILING(size / 1024.0); } fclose(f); } #else if (!(fntinfo = qmsfnt())) { fprintf(stderr, "%s: could not get printer font info\n", Whoami); exit(2); } #endif for (CurRomBlocks = 0, p = fntinfo->rom; p; p = p->next) CurRomBlocks += CEILING(p->bytes / (double)1024); CurRamBlocks = raminfo->FR - CurRomBlocks; /* Make an array of rom font #s */ for (p = fntinfo->rom, intptr = romlist; p; p = p->next) { for (tempintptr = romlist, found = FALSE; tempintptr < intptr; tempintptr++) if (*tempintptr == p->number) found = TRUE; if (!found) *intptr++ = p->number; } *intptr = 0; if (EQ(Model, "QMS800")) (void)strcpy(PKDir, "--PKDIR1--"); else (void)strcpy(PKDir, "--PKDIR2--"); if (!loadnametable(PKDir, romlist, 1)) { fprintf(stderr, "%s: could not open font directory %s\n", Whoami, PKDir); exit(2); } FontList = createfontlist(fntinfo); qmsfntfree(fntinfo); if (!setnewid(Host, User)) { fprintf(stderr, "%s: could not change user id to %s\n", Whoami, User); exit(2); /* This is fatal, bud. */ } seteoffunction(dvieofsoexit); readpreamble(); SigStruct.sv_handler = callcleanup; (void)sigvec(SIGINT, &SigStruct, (struct sigvec *)NULL); fputs(QUICON, stdout); if (Orientation == 'P') fputs(PORTRAIT, stdout); else fputs(LANDSCAPE, stdout); printf("%s%c%c", TEXTPROC, '0', '0'); printf("%s00000%05d", INITMARGVERT, Orientation == 'P' ? 11 * 1000 : (int)(8.5 * 1000)); printf("%s00000%05d", INITMARGHORZ, Orientation == 'P' ? (int)(8.5 * 1000) : 11 * 1000); printf("%s0000", CHARSPACING); fputs(FREEOFF, stdout); seteoffunction(dvieofsocleanup); process(); cleanup(FontList, SUCCEED); } /* Reads the info in the DVI preamble */ void readpreamble() { int i, k; long integer(); unsigned long uinteger(); if (cgetchar() != PRE) { fprintf(stderr, "%s: input file is not a DVI file\n", Whoami); exit(2); } if (cgetchar() != DVIID) { fprintf(stderr, "%s: wrong version of DVI file \n", Whoami); exit(2); } Numerator = uinteger(stdin, 4); Denominator = uinteger(stdin, 4); Magnification = integer(stdin, 4); k = cgetchar(); /* Ignore comment */ for (i = 0; i < k; i++) (void)cgetchar(); ConvInches = 1 / 100000.0 / 2.54; /* RSU 1m 100cm 1inch n inches */ /* x --------- x ----- x ------ = */ /* 10^7 RSUs 1m 2.54cm */ } /* Main routine that interprets the DVI file */ void process() { unsigned long uinteger(), ulk, uli; struct FontNode *curfontnode = NULL, *getdvifontnode(), *tempcurfontnode; struct Stack *tempstack; Boolean download(), makeroom(), fontselected = FALSE; int ch, ldirectory, lfontname, i; long dvifontnum, dvichecksum, scalefactor, designsize, curfontnum, integer(), a, b; char directory[256], fontname[256], *push(), *pop(), *malloc(); void fonttolist(), adjust(), endoflist(); long h, v, w, x, y, z; /* In RSUs. Mag not taken in account */ long realhpxl, realvpxl; /* Real h & v in printer in pixels */ long virthpxl, virtvpxl; /* Virtual h & v current point in */ /* pixels. Mag is taken in account */ for (ch = cgetchar(); ch != BOP; ch = cgetchar()) switch (ch) { case NOP: break; case FNTDEF1: case FNTDEF2: case FNTDEF3: case FNTDEF4: dvifontnum = integer(stdin, ch - FNTDEF1 + 1); dvichecksum = integer(stdin, 4); scalefactor = integer(stdin, 4); designsize = integer(stdin, 4); ldirectory = cgetchar(); lfontname = cgetchar(); for (i = 0; i < ldirectory; i++) directory[i] = cgetchar(); directory[i] = '\0'; for (i = 0; i < lfontname; i++) fontname[i] = cgetchar(); fontname[i] = '\0'; fonttolist(dvifontnum, dvichecksum, scalefactor, designsize, directory, fontname); break; default: #ifndef lint assert(FALSE); #else ; #endif cleanup(FontList, 2); } while (ch == BOP) { for (i = 0; i < 10; i++) (void)integer(stdin, 4); (void)uinteger(stdin, 4); /* Pointer to previous page */ virthpxl = virtvpxl = realhpxl = realvpxl = h = v = w = x = y = z = 0; for (ch = cgetchar(); ch != EOP; ch = cgetchar()) { virthpxl = ROUND(h*ConvInches*RESOLUTION*(Magnification/1000.0)); virtvpxl = ROUND(v*ConvInches*RESOLUTION*(Magnification/1000.0)); if (SETCHAR0 <= ch && ch < 128) { /* The following statement will only be true if the first * font in the dvi file was not found at any magnification. * In this case, skip this character since we don't know * how to increment the virtual or real pixel locations! * The true coordinates will probably be reset when TeX * pops the stack at the beginning of a line. */ if (!curfontnode || !curfontnode->localinfo) continue; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); if (!(curfontnode->flags & LOADED)) { if (!makeroom(FontList, MaxBlocks, &CurRamBlocks, CurRomBlocks, curfontnode->blocksize)) { fprintf(stderr, "%s: could not free %d blocks for font %s\n", Whoami, curfontnode->blocksize, LI(curfontnode)->pathname); goto trytocontinue1; } if (!download(curfontnode)) goto trytocontinue1; realhpxl = realvpxl = 0; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); } if (!fontselected) { printf("%s%d%s", DEFFONT, curfontnode->qmsnumber, ENDCMD); fontselected = TRUE; } /* SliTeX fonts have width but no bitmap. Unfortunately the * QMS will not print (or download) a character with width and * no bitmap so we must not print characters that are not in * the font. If you do, you will get the lowest character in * the font. */ trytocontinue1: if (LI(curfontnode)->mapsize[0][ch] != 0 && LI(curfontnode)->mapsize[1][ch] != 0) { if (ch == '^' || ch <= 32 || ch >= 127) printf("%s%02X", SPECIAL, ch); else (void)putchar(ch); realhpxl += ROUND(LI(curfontnode)->widths[ch] * (Magnification / 1000.0) * ConvInches * RESOLUTION); } h += LI(curfontnode)->widths[ch]; } else if (FNTNUM0 <= ch && ch < FNT1) { curfontnum = ch - FNTNUM0; if (!(tempcurfontnode = getdvifontnode(FontList, curfontnum, Orientation))) continue; /* Font file was not found during FNTDEF */ curfontnode = tempcurfontnode; endoflist(&FontList, curfontnode); fontselected = FALSE; putchar('\r'); /* Ends the pass */ printf("%s00000%s", TAB, ENDCMD); printf("%s00000%s", JUSTIFYMARGIN, ENDCMD); realhpxl = realvpxl = 0; } else switch (ch) { case SET1: case SET2: case SET3: case SET4: ch = uinteger(stdin, ch - SET1 + 1); assert(0 <= ch && ch <= 255); if (!curfontnode || !curfontnode->localinfo) continue; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); if (!(curfontnode->flags & LOADED)) { if (!makeroom(FontList, MaxBlocks, &CurRamBlocks, CurRomBlocks, curfontnode->blocksize)) { fprintf(stderr, "%s: could not free %d blocks for font %s\n", Whoami, curfontnode->blocksize, LI(curfontnode)->pathname); goto trytocontinue2; } if (!download(curfontnode)) goto trytocontinue2; realhpxl = realvpxl = 0; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); } if (!fontselected) { printf("%s%d%s", DEFFONT, curfontnode->qmsnumber, ENDCMD); fontselected = TRUE; } trytocontinue2: if (LI(curfontnode)->mapsize[0][ch] != 0 && LI(curfontnode)->mapsize[1][ch] != 0) { if (ch == '^' || ch <= 32 || ch >= 127) printf("%s%02X", SPECIAL, ch); else (void)putchar(ch); realhpxl += ROUND(LI(curfontnode)->widths[ch] * (Magnification / 1000.0) * ConvInches * RESOLUTION); } h += LI(curfontnode)->widths[ch]; break; case SETRULE: adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); a = integer(stdin, 4); b = integer(stdin, 4); if (a > 0 && b > 0) { printf("%s-%05d", JUSTIFYRELATIVE, ROUND(a / (double)SPOINT / PPI * (double)Magnification)); printf("%s%05d%05d", LINE, ROUND(b/(double)SPOINT/PPI*(double)Magnification), ROUND(a/(double)SPOINT/PPI*(double)Magnification)); printf("%s+%05d", JUSTIFYRELATIVE, ROUND(a / (double)SPOINT / PPI * (double)Magnification)); realhpxl += ROUND(b / (double)SPOINT / PPI * RESOLUTION * (Magnification / 1000.0)); } h += ROUND(b * (Numerator / (double)Denominator)); break; case PUT1: case PUT2: case PUT3: case PUT4: ch = uinteger(stdin, ch - PUT1 + 1); assert(0 <= ch && ch <= 255); if (!curfontnode || !curfontnode->localinfo) continue; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); if (!(curfontnode->flags & LOADED)) { if (!makeroom(FontList, MaxBlocks, &CurRamBlocks, CurRomBlocks, curfontnode->blocksize)) { fprintf(stderr, "%s: could not free %d blocks for font %s\n", Whoami, curfontnode->blocksize, LI(curfontnode)->pathname); goto trytocontinue3; } if (!download(curfontnode)) goto trytocontinue3; realhpxl = realvpxl = 0; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); } if (!fontselected) { printf("%s%d%s", DEFFONT, curfontnode->qmsnumber, ENDCMD); fontselected = TRUE; } trytocontinue3: if (LI(curfontnode)->mapsize[0][ch] != 0 && LI(curfontnode)->mapsize[1][ch] != 0) { if (ch == '^' || ch <= 32 || ch >= 127) printf("%s%02X", SPECIAL, ch); else (void)putchar(ch); realhpxl += ROUND(LI(curfontnode)->widths[ch] * (Magnification / 1000.0) * ConvInches * RESOLUTION); } break; case PUTRULE: adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); a = integer(stdin, 4); b = integer(stdin, 4); if (a > 0 && b > 0) { printf("%s-%05d", JUSTIFYRELATIVE, ROUND(a / (double)SPOINT / PPI * (double)Magnification)); printf("%s%05d%05d", LINE, ROUND(b/(double)SPOINT/PPI*(double)Magnification), ROUND(a/(double)SPOINT/PPI*(double)Magnification)); printf("%s+%05d", JUSTIFYRELATIVE, ROUND(a / (double)SPOINT / PPI * (double)Magnification)); realhpxl += ROUND(b / (double)SPOINT / PPI * RESOLUTION * (Magnification / 1000.0)); } break; case NOP: break; case PUSH: tempstack = (struct Stack *)malloc((unsigned)sizeof( struct Stack)); tempstack->h = h, tempstack->v = v, tempstack->w = w, tempstack->x = x, tempstack->y = y, tempstack->z = z; (void)push((char *)tempstack); break; case POP: tempstack = (struct Stack *)pop(); assert(tempstack); h = tempstack->h, v = tempstack->v, w = tempstack->w, x = tempstack->x, y = tempstack->y, z = tempstack->z; free((char *)tempstack); break; case RIGHT1: case RIGHT2: case RIGHT3: case RIGHT4: h += integer(stdin, ch - RIGHT1 + 1) * (Numerator / (double)Denominator); break; case W0: horw: h += w; break; case W1: case W2: case W3: case W4: w = integer(stdin, ch - W1 + 1) * (Numerator / (double)Denominator); goto horw; case X0: horx: h += x; break; case X1: case X2: case X3: case X4: x = integer(stdin, ch - X1 + 1) * (Numerator / (double)Denominator); goto horx; case DOWN1: case DOWN2: case DOWN3: case DOWN4: v += integer(stdin, ch - DOWN1 + 1) * (Numerator / (double)Denominator); break; case Y0: very: v += y; break; case Y1: case Y2: case Y3: case Y4: y = integer(stdin, ch - Y1 + 1) * (Numerator / (double)Denominator); goto very; case Z0: verz: v += z; break; case Z1: case Z2: case Z3: case Z4: z = integer(stdin, ch - Z1 + 1) * (Numerator / (double)Denominator); goto verz; case FNT1: case FNT2: case FNT3: case FNT4: curfontnum = uinteger(stdin, ch - FNT1 + 1); if (!(tempcurfontnode = getdvifontnode(FontList, curfontnum, Orientation))) continue; curfontnode = tempcurfontnode; endoflist(&FontList, curfontnode); fontselected = FALSE; putchar('\r'); /* Ends the pass */ printf("%s00000%s", TAB, ENDCMD); printf("%s00000%s", JUSTIFYMARGIN, ENDCMD); realhpxl = realvpxl = 0; break; case XXX1: case XXX2: case XXX3: case XXX4: ulk = uinteger(stdin, ch - XXX1 + 1); Pxxxstring = Xxxstring = malloc((unsigned)(ulk + 1)); for (uli = 0; uli < ulk; uli++) Xxxstring[uli] = cgetchar(); Xxxstring[uli] = '\0'; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); Origin[0] = virthpxl + RESOLUTION, Origin[1] = virtvpxl + RESOLUTION; (void)yyparse(); free(Xxxstring); fputs(QUICON, stdout); if (Orientation == 'P') fputs(PORTRAIT, stdout); else fputs(LANDSCAPE, stdout); printf("%s%c%c", TEXTPROC, '0', '0'); printf("%s00000%05d", INITMARGVERT, Orientation == 'P' ? 11 * 1000 : (int)(8.5 * 1000)); printf("%s00000%05d", INITMARGHORZ, Orientation == 'P' ? (int)(8.5 * 1000) : 11 * 1000); printf("%s0000", CHARSPACING); realhpxl = realvpxl = 0; break; case FNTDEF1: case FNTDEF2: case FNTDEF3: case FNTDEF4: dvifontnum = integer(stdin, ch - FNTDEF1 + 1); dvichecksum = integer(stdin, 4); scalefactor = integer(stdin, 4); designsize = integer(stdin, 4); ldirectory = cgetchar(); lfontname = cgetchar(); for (i = 0; i < ldirectory; i++) directory[i] = cgetchar(); directory[i] = '\0'; for (i = 0; i < lfontname; i++) fontname[i] = cgetchar(); fontname[i] = '\0'; fonttolist(dvifontnum, dvichecksum, scalefactor, designsize, directory, fontname); break; default: /* Bad DVI command */ #ifndef lint assert(FALSE); #else ; #endif cleanup(FontList, 2); } } NumPages++; printf("%s", FORMFEED); for (ch = cgetchar(); ch != BOP && ch != POST; ch = cgetchar()) switch (ch) { case NOP: break; case FNTDEF1: case FNTDEF2: case FNTDEF3: case FNTDEF4: dvifontnum = integer(stdin, ch - FNTDEF1 + 1); dvichecksum = integer(stdin, 4); scalefactor = integer(stdin, 4); designsize = integer(stdin, 4); ldirectory = cgetchar(); lfontname = cgetchar(); for (i = 0; i < ldirectory; i++) directory[i] = cgetchar(); directory[i] = '\0'; for (i = 0; i < lfontname; i++) fontname[i] = cgetchar(); fontname[i] = '\0'; fonttolist(dvifontnum, dvichecksum, scalefactor, designsize, directory, fontname); break; default: #ifndef lint assert(FALSE); #else ; #endif cleanup(FontList, 2); } } while (getchar() != EOF) ; } /* Returns the full pathname of the pk file found or NULL if not found. * The algorithm is as follows: * Create a new path, say TEXFONTS*, which is equal to $TEXFONTS:PKDir * if there is a directory name in the DVI file { * look in that directory for the font at any magnification * if found { * select this font * return it * } * } * look in TEXFONTS* directories consecutively for font with closest * magnification * if no font matches, return NULL */ char *findpkfont(directory, fontname, designsize, scalefactor) char *directory; char *fontname; long designsize, scalefactor; { int closestnumber = MAX_INTEGER; int desiredmagnification = ROUND(RESOLUTION * ((double)scalefactor / designsize) * (Magnification / 1000.0)); int dirdsize, dirmag; Boolean extractinfo(); static char returnvalue[101]; char dirfname[81], dirsfname[81], hostname[81], component[81]; char fontpaths[201], *strcpy(), *nextcomponent(); char *p, *comp, *fgetenv(), *expandtilde(), *expandhome(); DIR *dirp; struct direct *direntry; returnvalue[0] = '\0'; (void)gethostname(hostname, 80); if (!EQ(hostname, Host) || !(p = fgetenv("TEXFONTS", User))) (void)strcpy(fontpaths, PKDir); else (void)sprintf(fontpaths, "%s:%s", p, PKDir); if (directory && strlen(directory) > 0) { if (dirp = opendir(directory)) { for (direntry = readdir(dirp); direntry; direntry = readdir(dirp)) { if (direntry->d_namlen < 5 || !extractinfo(direntry->d_name, dirfname, dirsfname, &dirdsize, &dirmag) || !EQ(dirfname, fontname)) continue; if (ABS(dirmag - desiredmagnification) < closestnumber) { closestnumber = ABS(dirmag - desiredmagnification); (void)sprintf(returnvalue, "%s%s", directory, direntry->d_name); } } closedir(dirp); if (strlen(returnvalue) > 0) return returnvalue; } } for (p = &fontpaths[0]; comp = nextcomponent(&p); ) { (void)strcpy(component, comp); (void)expandtilde(component); (void)expandhome(component); if (dirp = opendir(component)) { for (direntry = readdir(dirp); direntry; direntry = readdir(dirp)) { if (direntry->d_namlen < 5 || !extractinfo(direntry->d_name, dirfname, dirsfname, &dirdsize, &dirmag) || !EQ(dirfname, fontname)) continue; if (ABS(dirmag - desiredmagnification) < closestnumber) { closestnumber = ABS(dirmag - desiredmagnification); (void)sprintf(returnvalue, "%s/%s", component, direntry->d_name); } } closedir(dirp); } } if (strlen(returnvalue) > 0) return returnvalue; return NULL; } /* Adjusts the real current position to the virtual current position */ void adjust(realh, realv, virth, virtv, h, v) long *realh, *realv; long virth, virtv; long h, v; { if (*realh != virth + RESOLUTION) { printf("%s%05d%s", TAB, ROUND(h * ConvInches * Magnification) + 1000, ENDCMD); /* Add 1000 since the origin is (1in,1in) */ *realh = virth + RESOLUTION; } if (*realv != virtv + RESOLUTION) { printf("%s%05d%s", JUSTIFYMARGIN, ROUND(v * ConvInches * Magnification) + 1000, ENDCMD); *realv = virtv + RESOLUTION; } } /* Adds a new font to the font list. The width info, mapsize, qmsheight, * qmsbaseline, pathname, blocksize and dvifontnumber in the FontNode * structure and LocalInfo structure are filled in also. If the font is * loaded on startup, the blocksize is left as is; otherwise, the blocksize * is estimated. */ void fonttolist(fontnumber, dvichecksum, scalefactor, designsize, directory, fontname) long fontnumber; long dvichecksum; long scalefactor, designsize; char *directory, *fontname; { struct DviNode *d; struct FontInfo *fi, *getfontinfo(); struct FontNode *fn, *getfontnode(); char *fullfontpath, *findpkfont(), *tail(); void cleanup(), pkeofsocleanup(), seteoffunction(), dvieofsocleanup(); int qmsfontnum, i; Boolean found; if (!(fullfontpath = findpkfont(directory, fontname, designsize, scalefactor))) { fprintf(stderr, "%s: could not find font %s anywhere\n", Whoami, fontname); return; /* Try to continue */ } if (EQN(PKDir, fullfontpath, strlen(PKDir)) && fullfontpath[strlen(PKDir)] == '/' && EQ(&fullfontpath[strlen(PKDir)+1], tail(fullfontpath))) qmsfontnum = getnumfromtable(tail(fullfontpath)); else /*tail(fullfontpath) ! necessarily == fontname if exact size !found*/ qmsfontnum = UserFontCount++; assert(qmsfontnum > 0); if (!(fn = getfontnode(FontList, qmsfontnum, Orientation))) { bzero((char *)(fn = (struct FontNode *)malloc((unsigned)sizeof(struct FontNode))), sizeof(struct FontNode)); fn->next = FontList, FontList = fn; } if (!fn->localinfo) bzero(fn->localinfo = malloc((unsigned)sizeof(struct LocalInfo)), sizeof(struct LocalInfo)); fn->flags |= RAM; if (Orientation == 'P') fn->flags |= PORT; fn->qmsnumber = qmsfontnum; (void)strcpy(LI(fn)->pathname, fullfontpath); for (d = LI(fn)->dvifontnumbers, found = FALSE; d && !found; d = d->next) if (d->dvinumber == fontnumber) found = TRUE; if (!found) { d = (struct DviNode *)malloc(sizeof(struct DviNode)); d->next = LI(fn)->dvifontnumbers, LI(fn)->dvifontnumbers = d; d->dvinumber = fontnumber; } (void)strcpy(PKName, fullfontpath); seteoffunction(pkeofsocleanup); if (!(fi = getfontinfo(fullfontpath, (EQ(Model, "QMS800") || EQ(Model, "QMS1500")) && Orientation == 'P' || (!EQ(Model, "QMS800") && !EQ(Model, "QMS1500")) && Orientation == 'L' ? 'X' : 'Y'))) { fprintf(stderr, "%s: cannot open or invalid font file %s\n", Whoami, fullfontpath); fn->flags |= LOADED; /* Try to continue */ fn->blocksize = 0; return; } seteoffunction(dvieofsocleanup); LI(fn)->qmsheight = fi->qmsheight; LI(fn)->qmsbaseline = fi->qmsbaseline; if (!(fn->flags & PRELOADED)) fn->blocksize = fi->blocksize; for (i = 0; i < 256; i++) { LI(fn)->widths[i] = ROUND(fi->chararray[i].tfm * ((fi->ds / (double)FIX) / FIX) * (2.54 / PPI * 100000) * ((fi->hppp / (double)SPOINT * PPI / RESOLUTION) / (Magnification / 1000.0))); LI(fn)->mapsize[0][i] = fi->chararray[i].w; LI(fn)->mapsize[1][i] = fi->chararray[i].h; } /* fi->chararray[i].tfm is in units of FIXes/designsize. fi->hppp is in units * of scaled points times pixels/point. Convert the width into RSUs with only * font magnification taken into account by the following formulas: * * tfm designsize * x ---------- = width in points * FIX * * width 1inch 2.54cm 1m 10^7RSUs * in x -------- x ------ x ----- x -------- = width in RSUs * points 72.27pts 1inch 100cm 1m * * hppp PPI * ------ x = Resolution designed for (the number before "pk" in the * SPOINT file name) * * Multiplying the width in RSUs by the number before the "pk" in the file * name yields the width in RSUs with font and file magnification taken into * account. Dividing by the file magnification yields the width with only * the font magnification taken into account. */ if (dvichecksum != 0 && fi->cs != 0) if (dvichecksum != fi->cs) fprintf(stderr, "%s: DVI checksum (O%lo) != PK checksum (O%lo) in %s\n", Whoami, dvichecksum, fi->cs, LI(fn)->pathname); } /* Downloads a font */ Boolean download(fn) struct FontNode *fn; { struct CharInfo *ci; char *tail(), *strcpy(); void resetpkfile(), seteoffunction(), downloadpkeofsocleanup(), dvieofsocleanup(); int downloadinterrupt(), callcleanup(); int downloadtype, result, i, truebyteswide, bytestooutput, row, bytes; if (!fn || fn->flags & LOADED || !(fn->flags & RAM) || (fn->flags & PORT ? 'P' : 'L') != Orientation) return FALSE; resetpkfile(); downloadtype = ((EQ(Model, "QMS800") || EQ(Model, "QMS1500")) && Orientation == 'P' || (!EQ(Model, "QMS800") && !EQ(Model, "QMS1500")) && Orientation == 'L' ? 'X' : 'Y'); DownLoadFNum = fn->qmsnumber; (void)sigblock(SIGINT); /* Temporarily block interrupts */ SigStruct.sv_handler = downloadinterrupt; (void)sigvec(SIGINT, &SigStruct, (struct sigvec *)NULL); (void)strcpy(PKName, LI(fn)->pathname); seteoffunction(downloadpkeofsocleanup); /* #defining ASCIILOAD causes ASCII characters to be used for the download * sequence. Twice as many characters must be sent but it is useful for * looking at the output when debugging. Also, you can actually see the * bitmaps in the output. ASCII loading must be used when you can't get * hardware flow control to work. Far out. */ #ifdef ASCIILOAD fputs(FREEFORM, stdout); #else fputs(EIGHTBITON, stdout); #endif printf("%s%05d%c0%-4.4s%03d%03dT", DOWNLOAD, fn->qmsnumber, Orientation, tail(LI(fn)->pathname), LI(fn)->qmsheight, LI(fn)->qmsbaseline); (void)sigsetmask(sigblock(0) & ~SIGINT); /* Unblock interrupts */ while ((result = getnextcharinfo(LI(fn)->pathname, downloadtype, &ci)) != 1) switch (result) { case 2: fprintf(stderr, "%s: could not open %s\n", Whoami, LI(fn)->pathname); return FALSE; case 3: fprintf(stderr, "%s: %s is not a PK file\n", Whoami, LI(fn)->pathname); return FALSE; case 4: fprintf(stderr, "%s: %s PK version is incorrect\n", Whoami, LI(fn)->pathname); return FALSE; case 0: /* Ok. Got a bitmap */ if (ci->h == 0 || ci->w == 0) continue; putchar(','); printf("%02X%03d", ci->cc, ROUND(LI(fn)->widths[ci->cc] * (Magnification / 1000.0) * ConvInches * RESOLUTION)); if (downloadtype == 'X') { printf("%03d%03d", ci->h, ci->w); printf("%c%03d", LI(fn)->qmsbaseline - ci->voff >= 0 ? '+' : '-', ABS(LI(fn)->qmsbaseline - ci->voff)); printf("%c%03d", -ci->hoff >= 0 ? '+' : '-', ABS(-ci->hoff)); } else { printf("%03d%03d", ci->w, ci->h); printf("%c%03d", -ci->hoff >= 0 ? '+' : '-', ABS(ci->hoff)); printf("%c%03d", (LI(fn)->qmsheight - LI(fn)->qmsbaseline) - (ci->h - ci->voff) >= 0 ? '+' : '-', ABS((LI(fn)->qmsheight - LI(fn)->qmsbaseline) - (ci->h - ci->voff))); i = ci->w, ci->w = ci->h, ci->h = i; /* Swaparoo! */ } truebyteswide = ci->w + 7 >> 3; /* >> divides by 8 */ bytestooutput = (ci->w + 15 >> 4) * 2; /* >> divides by 16 */ #ifdef ASCIILOAD for (row = 0; row < ci->h; row++) { #else for (row = 0; row < ci->h; row++) #endif for (bytes = 0; bytes < bytestooutput; bytes++) { if (bytes == truebyteswide - 1) *(ci->bitmap + row * truebyteswide + bytes) &= 0xFF<<7-(ci->w+7)%8; if (bytes < truebyteswide) { i = *(ci->bitmap + row * truebyteswide + bytes) & 0xFF; #ifdef ASCIILOAD printf("%c%c", "0123456789ABCDEF"[i >> 4], "0123456789ABCDEF"[i & 0xF]); #else if (i == '^') printf("^^"); else (void)putchar(i); #endif } else #ifdef ASCIILOAD printf("00"); #else (void)putchar(0); #endif } #ifdef ASCIILOAD putchar('\n'); } #endif break; } /* End switch */ #ifdef ASCIILOAD printf("%s%s", ENDCMD, FREEOFF); #else printf("%s%s", ENDCMD, EIGHTBITOFF); #endif putchar('\r'); /* Ends the pass */ (void)sigblock(SIGINT); printf("%s00000%s", TAB, ENDCMD); printf("%s00000%s", JUSTIFYMARGIN, ENDCMD); SigStruct.sv_handler = callcleanup; (void)sigvec(SIGINT, &SigStruct, (struct sigvec *)NULL); seteoffunction(dvieofsocleanup); CurRamBlocks += fn->blocksize; fn->flags |= LOADED; (void)sigsetmask(sigblock(0) & ~SIGINT); return TRUE; } /* Returns a pointer to a font on the font list using the DVI number; NULL * if not found. */ struct FontNode *getdvifontnode(head, dvinumber, orientation) struct FontNode *head; long dvinumber; int orientation; { struct FontNode *p; struct DviNode *d; for (p = head; p; p = p->next) if (p->flags & RAM && (p->flags & PORT ? 'P' : 'L') == orientation && p->localinfo && LI(p)->dvifontnumbers) for (d = LI(p)->dvifontnumbers; d; d = d->next) if (d->dvinumber == dvinumber) return p; return NULL; } /* The following are routines called when a SIGINT is received or EOF is * unexpectedly encountered when reading a file. */ simplyexit() { exit(SUCCEED); } callcleanup() { void cleanup(); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, SUCCEED); /* Interrupting a program is not an error */ } void dvieofsoexit() { fprintf(stderr, "%s: unexpected EOF when reading DVI file\n", Whoami); exit(2); } void dvieofsocleanup() { fprintf(stderr, "%s: unexpected EOF when reading DVI file\n", Whoami); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } void pkeofsocleanup() { fprintf(stderr, "%s: unexpected EOF in PK file %s\n", Whoami, PKName); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } void downloadpkeofsocleanup() { fputs(ENDCMD, stdout); #ifdef ASCIILOAD fputs(FREEOFF, stdout); #else fputs(EIGHTBITOFF, stdout); #endif printf("%s%05d%c%s", DOWNLOAD, DownLoadFNum, Orientation, ENDCMD); pkeofsocleanup(); } downloadinterrupt() { fputs(ENDCMD, stdout); #ifdef ASCIILOAD fputs(FREEOFF, stdout); #else fputs(EIGHTBITOFF, stdout); #endif printf("%s%05d%c%s", DOWNLOAD, DownLoadFNum, Orientation, ENDCMD); callcleanup(); } /* Lex and Yacc routines to parse \special command string */ #include "xxx.c"