/* Old troff driver */ #ifndef lint static char *rcs = "$Header: tf.c.backup,v 1.2 88/02/03 08:52:30 simpson Exp $"; #endif /* $Log: tf.c.backup,v $ Revision 1.2 88/02/03 08:52:30 simpson added tpic support Revision 1.1 88/01/15 13:05:39 simpson initial release Revision 0.2 87/12/18 11:38:39 simpson added void for lint Revision 0.1 87/12/11 18:31:22 simpson beta test */ #include #include #include #include #include #include #include #include #include "fontnode.h" #include "fontinfo.h" #include "constants.h" #define FONTDIR "--FONTDIR--" /* Cast for accessing LocalInfo */ #define LI(p) ((struct LocalInfo *)p->localinfo) #define TILT 1 /* 1 == down */ #define RAIL 2 /* 1 == upper */ #define MAGAZINE 4 /* 1 == upper */ #define UPPERHALF 8 /* 1 == upper font half */ #define ESCFORWARD 16 #define LEADFORWARD 32 struct LocalInfo { char name[21]; /* Name of font */ int pointsize; int qmsheight; /* Height to give QMS printer */ int qmsbaseline; /* Baseline height to give QMS printer */ char pathname[81]; /* Full pathname in file system */ short bitmapsize[2][256]; /* Width & height of each char bitmap */ int widths[256]; /* Width in HORCATRESes */ }; /* Old dumb troff only uses 4 fonts */ char *Fonts[4] = {"R", "I", "B", "S"}; char flags; /* ESCFORWARD,LEADFORWARD,UPPER,RAIL,MAGAZINE,TILT */ char EOFName[101]; /* Used by pkeofsocleanup() */ char *Whoami; /* argv[0] */ char *Model; /* Model of printer being used */ char Orientation = 'P'; char PKDir[101]; /* Directory location of PK files */ int MaxBlocks; /* # of free blocks w/out ram or rom fonts */ int CurRamBlocks; /* # of blocks used by ram fonts */ int CurRomBlocks; /* # of blocks used by rom fonts */ int DownLoadFNum; /* Number of font currently being downloaded */ FILE *ReadLine; /* Debugger port tty */ struct sigvec SigStruct; struct FontNode *FontList; /* Contains all fonts and their attributes */ extern char *Host, *User; extern FILE *Accting; extern Boolean Accounting; extern int NumPages; main(argc, argv) int argc; char *argv[]; { Boolean found, loadnametable(); extern int optind; extern char *optarg; int *intptr, *tempintptr; int c; int romlist[41]; /* List of rom font #s */ int simplyexit(), callcleanup(); void qmsfntfree(), cleanup(), seteoffunction(), process(), troffeofsocleanup(), adjust(); PROFILE_VALUE *v, *getbindingvalue(); struct qmsram *raminfo; struct qmsfnt *fntinfo; struct fontnode *p; struct FontNode *createfontlist(); #ifdef DEBUG char *malloc(), orien; int i, fontno, size; FILE *f; struct fontnode *fn; #endif 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); } (void)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)sprintf(PKDir, "%s/wbfonts", FONTDIR); else (void)sprintf(PKDir, "%s/wwfonts", FONTDIR); if (!loadnametable(PKDir, romlist, 10001)) { fprintf(stderr, "%s: could not open font directory %s\n", Whoami, PKDir); exit(2); } FontList = createfontlist(fntinfo); qmsfntfree(fntinfo); 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(troffeofsocleanup); process(); cleanup(FontList, SUCCEED); } /* Main routine that interprets the troff file */ void process() { struct FontNode *curnode= NULL; /* Current font troff has selected */ struct FontNode *fonttolist(); int curfont = 0; /* Current font selected in Fonts */ int curptsize = 10; /* Current pt size selected */ int c, d; int realhpxl, realvpxl; /* Real pixel locations */ int virthpxl, virtvpxl; /* Virtual pixel locations */ int h; /* In HORCATRES */ int v; /* In VERCATRES */ Boolean single = TRUE; /* Doubler lens */ Boolean fontselected = FALSE, download(), makeroom(); /* The first escape and lead are skipped since this sets up the machine */ Boolean skipesc = TRUE, skiplead = TRUE; /* Keep track of whether we have printed on the page because the C/A/T */ /* does a lot of leads at the end of a job. */ Boolean printedonpage = FALSE; int blankpagecount = 0; extern char RegularToAscii[], SpecialToAscii[]; void endoflist(); h = v = realhpxl = realvpxl = virthpxl = virtvpxl = 0; while (TRUE) { /* A non-returning function is called to exit. */ c = cgetchar(); if (c == 0) /* Ignore nulls */ continue; if (c == 0xFF) { /* Alls 1s is an error */ fprintf(stderr, "%s: invalid troff command 0xFF\n", Whoami); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } virthpxl = ROUND(h / (double)HORCATRES * RESOLUTION); virtvpxl = ROUND(v / (double)VERCATRES * RESOLUTION); if (c & 0x80) { /* Escape code */ if (skipesc) skipesc = FALSE; else { d = (c ^ 0x7F) & 0x7F; if (flags & ESCFORWARD) h += d; else h -= d; } continue; } if (c & 0x40) { /* Control code */ if (c & 0x20) { /* Lead code */ if (skiplead) skiplead = FALSE; else { d = (c ^ 0x1F) & 0x1F; if (flags & LEADFORWARD) v += d; else v -= d; /* The C/A/T formfeeds by running off the page! Well, the * the C/A/T uses (used?) continuous roll paper so this is * not as crazy as it sounds. */ if (v > ROUND((Orientation == 'P' ? 11 : 8.5) * VERCATRES)) { v -= ROUND((Orientation == 'P' ? 11 : 8.5) * VERCATRES ); if (printedonpage) { realhpxl = realvpxl = 0; fputs(FORMFEED, stdout), NumPages++; printedonpage = FALSE; } else blankpagecount++; /* Ignore at end of job but */ } /* not in between */ } continue; } if (c & 0x10) { /* Size change */ switch (c & 0xF) { case 0: if (!single) h += 55; single = TRUE; curptsize = 7; break; case 1: if (!single) h += 55; single = TRUE; curptsize = 8; break; case 2: if (!single) h += 55; single = TRUE; curptsize = 10; break; case 3: if (!single) h += 55; single = TRUE; curptsize = 11; break; case 4: if (!single) h += 55; single = TRUE; curptsize = 12; break; case 5: if (!single) h += 55; single = TRUE; curptsize = 14; break; case 6: if (!single) h += 55; single = TRUE; curptsize = 18; break; case 7: if (!single) h += 55; single = TRUE; curptsize = 9; break; case 8: if (!single) h += 55; single = TRUE; curptsize = 6; break; case 9: if (single) h -= 55; single = FALSE; curptsize = 16; break; case 10: if (single) h -= 55; single = FALSE; curptsize = 20; break; case 11: if (single) h -= 55; single = FALSE; curptsize = 22; break; case 12: if (single) h -= 55; single = FALSE; curptsize = 24; break; case 13: if (single) h -= 55; single = FALSE; curptsize = 28; break; case 14: if (single) h -= 55; single = FALSE; curptsize = 36; break; case 15: fprintf(stderr, "%s: invalid otroff size change 0x5F\n", Whoami); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } curnode = fonttolist(Fonts[curfont], curptsize); endoflist(&FontList, curnode); fontselected = FALSE; putchar('\r'); /* Ends the pass */ printf("%s00000%s", TAB, ENDCMD); printf("%s00000%s", JUSTIFYMARGIN, ENDCMD); realhpxl = realvpxl = 0; continue; } switch (c & 0xF) { /* Control code command */ case 0x0: /* Initialize */ flags |= ESCFORWARD | LEADFORWARD | TILT; flags &= ~(MAGAZINE | RAIL | UPPERHALF); break; case 0x9: /* Stop */ while (getchar() != EOF) ; /* Consume rest of input */ if (printedonpage) fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, SUCCEED); case 0x2: /* Upper rail */ flags |= RAIL; goto reloadfont; case 0x1: /* Lower rail */ flags &= ~RAIL; goto reloadfont; case 0x3: /* Upper magazine */ flags |= MAGAZINE; goto reloadfont; case 0x4: /* Lower magazine */ flags &= ~MAGAZINE; reloadfont: curfont = flags >> 1 & 0x3; /* Ignore tilt */ curnode = fonttolist(Fonts[curfont], curptsize); endoflist(&FontList, curnode); fontselected = FALSE; putchar('\r'); /* Ends the pass */ printf("%s00000%s", TAB, ENDCMD); printf("%s00000%s", JUSTIFYMARGIN, ENDCMD); realhpxl = realvpxl = 0; break; case 0xE: /* Tilt up */ break; /* No op */ case 0xF: /* Tilt down */ break; /* No op */ case 0x6: /* Upper font half */ flags |= UPPERHALF; break; case 0x5: /* Lower font half */ flags &= ~UPPERHALF; break; case 0x7: flags |= ESCFORWARD; /* Escape forward */ break; case 0x8: flags &= ~ESCFORWARD; /* Escape backward */ break; case 0xA: /* Lead forward */ flags |= LEADFORWARD; break; case 0xC: /* Lead backward */ flags &= ~LEADFORWARD; break; case 0xB: /* Extension */ switch (c = cgetchar()) { case 1: /* Big lead */ if (flags & LEADFORWARD) v += 64 * cgetchar(); else v -= 64 * cgetchar(); break; case 2: /* Big escape */ if (flags & ESCFORWARD) h += 128 * cgetchar(); else h -= 128 * cgetchar(); break; case 3: /* Formfeed */ fputs(FORMFEED, stdout), NumPages++; realhpxl = realvpxl = 0; printedonpage = FALSE; break; } break; case 0xD: /* Error! */ fprintf(stderr, "%s: illegal otroff command 0x4D\n", Whoami); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } continue; } d = c & 0x3F; /* Flash code */ printedonpage = TRUE; if (blankpagecount > 0) { for (c = 0; c < blankpagecount; c++) fputs(FORMFEED, stdout), NumPages++; blankpagecount = 0; } if (d > 45 && flags & UPPERHALF) { fprintf(stderr, "%s: illegal otroff flash code %d\n", Whoami, d); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } if (flags & UPPERHALF) d += 64; d = (curfont == 3 ? SpecialToAscii[d] : RegularToAscii[d]); if (d == 0) /* Character not used */ continue; /* If we couldn't find the font, don't anything since we don't know * how to increment the real pixel locations. */ if (!curnode || !curnode->localinfo) continue; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); if (!(curnode->flags & LOADED)) { if (!makeroom(FontList, MaxBlocks, &CurRamBlocks, CurRomBlocks, curnode->blocksize)) { fprintf(stderr, "%s: could not free %d blocks for font %s\n", Whoami, curnode->blocksize, LI(curnode)->pathname); goto trytocontinue; } if (!download(curnode)) goto trytocontinue; realhpxl = realvpxl = 0; adjust(&realhpxl, &realvpxl, virthpxl, virtvpxl, h, v); } if (!fontselected) { printf("%s%d%s", DEFFONT, curnode->qmsnumber, ENDCMD); fontselected = TRUE; } /* For fonts with width but no bitmap, check the size of the * raster. The QMS will 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. */ trytocontinue: if (LI(curnode)->bitmapsize[0][d] != 0 && LI(curnode)->bitmapsize[1][d] != 0) { if (d == '^' || d <= 32 || d >= 127) printf("%s%02X", SPECIAL, d); else (void)putchar(d); realhpxl += ROUND(LI(curnode)->widths[d] / (double)HORCATRES * RESOLUTION); } } } /* Adjusts printer coordinates so they correspond to otroff's coordinates. It * adjusts the real coordinates if necessary. */ void adjust(realh, realv, virth, virtv, h, v) int *realh, *realv, virth, virtv, h, v; { if (*realh != virth) { printf("%s%05d%s", TAB, ROUND(h / (double)HORCATRES * 1000.0), ENDCMD); *realh = virth; } if (*realv != virtv) { printf("%s%05d%s", JUSTIFYMARGIN, ROUND(v / (double)VERCATRES * 1000.0), ENDCMD); *realv = virtv; } } /* Returns a pointer to a node on the FontList with the matching name, * pointsize and orientation or NULL if not found. */ struct FontNode *getnodebyname(head, name, ptsize, or) struct FontNode *head; char *name; int ptsize; int or; { struct FontNode *p; for (p = head; p; p = p->next) if (p->localinfo && LI(p)->pointsize == ptsize && (p->flags & PORT ? 'P' : 'L') == or && EQ(LI(p)->name, name)) return p; return NULL; } /* Returns the full pathname of the font whose size most closely matches that * passed as a parameter. Returns NULL if it can't open the directory or it * cannot find the font at any magnification. The return value is static and * overwritten with each call. */ char *findpkfont(fontname, pointsize) char *fontname; int pointsize; { int closestnumber = MAX_INTEGER; int desiredmagnification = ROUND(RESOLUTION * pointsize/10.0); static char returnvalue[101]; DIR *dirp; struct direct *direntry; char dirfname[81], dirsfname[81]; Boolean extractinfo(); int dirdsize, dirmag; returnvalue[0] = '\0'; if (dirp = opendir(PKDir)) { 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", PKDir, direntry->d_name); } } closedir(dirp); } if (strlen(returnvalue) > 0) return returnvalue; return NULL; } /* Adds a new font to the font list. All the fields in the LocalInfo * structure are filled in. If the font is loaded on startup, the blocksize * is left as is; otherwise, the blocksize is estimated. */ struct FontNode *fonttolist(font, pointsize) char *font; int pointsize; { int qmsfontnum, mag, ds, i; char *fullfontpath, fontname[21], sfontname[21], *tail(), *malloc(), *findpkfont(), *strcpy(); Boolean extractinfo(); void seteoffunction(), pkeofsocleanup(), desceofsocleanup(), troffeofsocleanup(); struct FontNode *fn, *getfontnode(); struct FontInfo *fi, *getfontinfo(); if (strlen(font) == 0 || pointsize == 0) /* One of the two has not */ return NULL; /* been filled in yet. */ /* If this works, we don't need to search the font directory */ if (fn = getnodebyname(FontList, font, pointsize, Orientation)) return fn; if (!(fullfontpath = findpkfont(font, pointsize))) return NULL; /* Try to continue */ qmsfontnum = getnumfromtable(tail(fullfontpath)); 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) /* This font is already on the list */ return fn; else 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)->name, font); (void)strcpy(LI(fn)->pathname, fullfontpath); (void)extractinfo(tail(LI(fn)->pathname), fontname, sfontname, &ds, &mag); LI(fn)->pointsize = ROUND(mag / (double)RESOLUTION * 10); (void)strcpy(EOFName, 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'))) { FontList = FontList->next; /* Bad PK file or not readable */ fprintf(stderr, "%s: could not open or bad PK file %s\n", Whoami, fullfontpath); free(fn->localinfo), free((char *)fn); return NULL; } if (!(fn->flags & PRELOADED)) fn->blocksize = fi->blocksize; seteoffunction(troffeofsocleanup); LI(fn)->qmsheight = fi->qmsheight; LI(fn)->qmsbaseline = fi->qmsbaseline; for (i = 0; i < 256; i++) { LI(fn)->widths[i] = ROUND(fi->chararray[i].tfm * ((fi->ds / (double)FIX) / FIX) / PPI * HORCATRES * (LI(fn)->pointsize / 10.0)); LI(fn)->bitmapsize[0][i] = fi->chararray[i].w; LI(fn)->bitmapsize[1][i] = fi->chararray[i].h; } return fn; } /* Downloads a font */ Boolean download(fn) struct FontNode *fn; { struct CharInfo *ci; char *tail(), *strcpy(); void resetpkfile(), seteoffunction(), downloadpkeofsocleanup(), troffeofsocleanup(); 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(EOFName, 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] / (double)HORCATRES * 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(troffeofsocleanup); CurRamBlocks += fn->blocksize; fn->flags |= LOADED; (void)sigsetmask(sigblock(0) & ~SIGINT); return TRUE; } /* The following routines are 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 troffeofsocleanup() { fprintf(stderr, "%s: unexpected EOF when reading otroff file\n", Whoami); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } void pkeofsocleanup() { fprintf(stderr, "%s: unexpected EOF when reading PK file %s\n", Whoami, EOFName); fputs(FORMFEED, stdout), NumPages++; cleanup(FontList, 2); } downloadinterrupt() { fputs(ENDCMD, stdout); #ifdef ASCIILOAD fputs(FREEOFF, stdout); #else fputs(EIGHTBITOFF, stdout); #endif printf("%s%05d%c%s", DOWNLOAD, DownLoadFNum, Orientation, ENDCMD); callcleanup(); } 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(); }