|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 27455 (0x6b3f)
Types: TextFile
Names: »tf.c.backup«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./DVIware/laser-setters/quicspool/src/tf.c.backup«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
└─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z«
└─⟦ca79c7339⟧
└─⟦this⟧ »DVIware/laser-setters/quicspool/src/tf.c.backup«
/* 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 <stdio.h>
#include <signal.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <local/standard.h>
#include <local/qms.h>
#include <local/profile.h>
#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();
}