/* * ***************** * * L F N T . C * * ***************** * * This program loads character patterns into the P/OS * terminal subsystem's character generator area in * main memory. It reads the pixel patterns from a * standard ASCII file which contains the patterns in an * editable form (more on this later). The replacement * characters are loaded into the area normally occupied * by the "supplemental graphics" characters (a.k.a. * "European" characters). * * With release 2, this program also supports a binary font * format for faster loading and smaller disk usage. The * format of the binary file is R.VAR with no carriage control. * The 1st record is the font header, and each succeeding * record is the data for a character. Character data consists * of 3 words of character header info, followed by 10 bytes or * 10 words (132 or 80 col. format, respectively) of pixel * row data. * * By: * Robert B. Denny * Alisa Systems, Inc. * Mezzanine Floor * 234 E. Colorado Blvd. * Pasadena, CA 91101 * * Edits: * * X1.1 06-Dec-83 RBD Add 132-column support - new PXL file format * Y1.2 10-Dec-83 RBD Add help text on startup per M. Otte * Y1.3 16-Dec-83 RBD Fencepost error -- RH column not being loaded. * Add help text for 132-column fonts. * Y1.4 20-Dec-83 RBD Change font file locations to [ZZSYS]. Add * conditional code for DCS test version which * will not support direct user interface, just * spawning from CT*OS, and has no licensing. * Y1.5 22-Dec-83 TTC Display loading font message. * Y2.0 11-Jan-83 RBD Major changes. Use RMS, remove serial number * checking, add binary font file capability, * make silent version for CT*OS, spawn-only, * requires password on command line. Make * non-silent version use P/OS menu's etc. * MUST be built using LFNTGEN now, as the * PAB files are different, etc. Automatically * loads both 80 and 132 column fonts if the * font name doesn't contain those strings. * If one of the two don't exist, the non-SILENT * one issues a warning. The interactive version * keeps its files in [FONTS]. * Y2.1 12-Jan-83 RBD Removed CT*OS proprietary stuff prior to releasing * to M. Minow & friends at Digital. */ /* * ************* * ** N O T E ** * ************* * * Use the LFNTGEN.CMD file to generate this program * in either the interactive or quiet version. */ #define DEBUGoff #define TESTINGoff #include #include #include #include #include "lfcnd.h" /* * The following definition establishes the location * on the P/OS system of the font files. */ #ifdef INTERACTIVE #define FONT_LOC "LB:[FONTS]" #else #define FONT_LOC "LB:[ZZSYS]" #endif int $$narg = 1; /* Supress the startup prompt */ /* * Data structures for PLAS access to the VDFNTS partition. * * NOTE: * Addresses within VDFNTS are APR4-relative, and the following * code assumes that we map through APR4 as well. If you * make this program too big, it'll bump into APR4's VA's * and you'll have to make it even bigger, translating VA's * to APR6-relative (or whatever). */ static struct rdb vrdb = /* Define the VDFNTS partition as a region */ { 0, 0, 0105046, 055263, 026226, 0, RS_RED | RS_WRT, 0 }; static struct wdb vwdb = /* Set up an address window at 100000 VA */ { 0, 4, 0, 0, 0, 0, 0, WS_MAP|WS_64B|WS_WRT, 0 }; /* * Data structures which map the contents of the VDFNTS * partition. The actual structure is variable, driven * by descriptive information also contained within the * partition. Hence the looseness of definition. */ /* * Partition header - points to index and map areas for * each of the fonts resident in the partition. There * are currently 3 separate fonts in VDFNTS. The first * contains the 80-column characters for ALL 3 CHARACTER * SETS (ASCII, Special Graphics and Supplemental Graphics). * The second font appears to contain the 132-column char- * acters for the same sets of characters. I don't (yet) * know what is in the third font (may belong to $GIDIS). * * The Indexing arrays contain bitmap indexes which identify * the character bitmaps for each of the 96 characters in * each of the three character sets. These are used to * translate the character code into an address of a * character bitmap. The bitmaps are packed end-to-end * and can be viewed as an array of character cell maps * of whatever size. The "index" is the index of the cell * array to use. For example, if an octal 111 is received, * then the 112th (octal) index is used to locate the char- * acter cell. If this index is 29, then the 29th cell map * is used to display the character. * * The important thing to note is that the mapping index * correspond to the three 96-character "sets", and refer * to a single FONT. Normally, the first font is in use, * and the values in all three mapping indexes refer to * cell maps in the first font. When the system is * switched to 132-column mode, the indexes all refer to * the second font ... Nuff said? */ struct fnt_hdr { word xx; word n_fnts; /* Number of fonts */ address bitmap[8]; /* APR-4 based VA's of font bitmaps */ word n_indx; /* Number of indexing arrays */ address index[8]; /* APR-4 based VA's of index arrays */ }; static int bin_fmt; /* TRUE if font file is binary */ #ifdef INTERACTIVE /* * Menu data */ static int stat[8]; /* Used everywhere */ static char action[8]; static char *msg1 = ""; static char *msg2 = ""; static char *clrseq = "\033[1;1H\033[J"; static char *wrgkey = "You pressed the wrong function key"; static char *unsup = "Not supported yet"; static char m1buf[80]; #endif extern int $dsw; extern int $$ferr; main(argc, argv) int argc; char *argv[]; { register address pxlp; register char *cp; word chcode, charset, idxval, i, j; struct fnt_hdr *hdr; word fntnum, nbpr, nbpc, nbits, bits; char buf[64]; char filename[64]; FILE *ffp; char *np; word *wp; byte *bp; char *aflavor; char *bflavor; int pass; /* * Get the name of the font file to load */ #ifdef INTERACTIVE #ifdef TESTING /* * The following 2 POSRES calls may be eliminated when the * program is run via an application installation file. */ if(p$mfile("LFNT.MNU", stat) != 1) my_err("Failed to open LFNT.MNU"); if(p$hfile("LFNT.HLP", "LFMAIN", stat) != 1) my_err("Failed to open LFNT.HLP"); #endif np = NULL; while(np == NULL) { display("LFMAIN"); switch(stat[0]) { case 1: /* DO key */ switch(stat[1]) /*** HACK -- use action string!! ***/ { case 1: np = "ASCII"; break; case 2: np = "SPCGRF"; break; case 3: np = "SUPGRF"; break; case 4: np = "GRKMTH"; break; case 5: np = "USER1"; break; case 6: np = "USER2"; break; case 7: np = "USER3"; break; case 8: np = "USER4"; break; default: msg1 = unsup; } break; case -14: /* Function key */ switch(stat[1]) { case 10: /* Exit */ case 9: /* Main Screen */ printf("%s", clrseq); fflush(stdout); p$hclose(stat); p$mclose(stat); exits(1); default: msg1 = wrgkey; } break; default: my_error("MENU error"); } } #else if(argc < 3) /* Bad command line */ exits(1); /* Silently exit */ else np = argv[1]; /* OK, font name is first arg */ #endif #ifdef DEBUG printf("Font name \"%s\"\n", np); #endif /* * Map to the VDFNTS partition via APR4 */ if(atrg(&vrdb) != IS_SUC) my_err("Attach failed. Status = %d", $dsw); vwdb.w_nsiz = vrdb.r_gsiz; vwdb.w_nrid = vrdb.r_gid; if(craw(&vwdb) != IS_SUC) my_err("Map failed. Status = %d", $dsw); hdr = (struct fnt_hdr *)vwdb.w_nbas; /* Point to header */ fntnum = -1; /* Font header not yet seen */ #ifdef DEBUG printf("VDFNTS partition mapped at %06o with size %06o\n", hdr, vwdb.w_nsiz * 64); printf("There are %d fonts at %06o, %06o and %06o\n", hdr->n_fnts, hdr->bitmap[0], hdr->bitmap[1], hdr->bitmap[2]); printf(" and %d character sets at %06o, %06o and %06o\n", hdr->n_indx, hdr->index[0], hdr->index[1], hdr->index[2]); #endif /* * Determine the font file(s) to open, and whether they * are binary or ASCII format. */ bflavor = "80.DAT"; /* Do 80-col first */ aflavor = "80.FNT"; pass = 1; nxtflavor: /* Branch-back */ concat(filename, FONT_LOC, np, bflavor, 0); /* Make a binary name */ if((ffp = fopen(filename, "run")) == NULL) /* Try for binary */ { concat(filename, FONT_LOC, np, aflavor, 0); /* Make ASCII name */ if((ffp = fopen(filename, "r")) == NULL) /* Try for ASCII */ my_err("Missing font file", $$ferr); else bin_fmt = FALSE; } else bin_fmt = TRUE; /* * Load the font/character set. THERE IS NO ERROR CHECKING, THE * FILE'd BETTER DAMN WELL BE CORRECT!! */ while(!feof(ffp)) /* Read till EOF */ { if(fget(buf, 64, ffp) == EOF) /* Quit if EOF encountered here */ break; if(bin_fmt) /* BINARY FLAVOR */ { wp = (word *)buf; /* Make a word pointer */ if(fntnum == -1) /* First record */ { /* (font header) */ fntnum = *wp++; /* Font number, */ nbpr = *wp++; /* # bytes per row */ nbpc = *wp; /* # bytes/char */ continue; /* Go back & read next rec */ } else /* Character definition rec */ { /* so get its index info */ charset = *wp++; /* Character set */ chcode = *wp++; /* Character code for index */ idxval = *wp++; /* Offset in index to bash */ bp = (char *)wp; /* bp & wp --> 1st bitmap */ } } else /* ASCII FLAVOR */ { if(buf[0] == '[') /* If is font header line */ { sscanf(buf, "[%d %d %d", &fntnum, &nbpr, &nbpc); /* Get info */ continue; } if(buf[0] != '<') /* Read lines till start-cell */ continue; if(fntnum == -1) /* NO FONT HEADER??? */ my_err("Missing font header", 0); sscanf(buf, "<%d %d %d", &charset, &chcode, &idxval); } #ifdef DEBUG printf("Code %d Character set %d Index %d\n", chcode, charset, idxval); #endif if(chcode > 95 || idxval > 221) /* Check values */ { printf("Code %h Character set %d Index %h:\n", chcode, charset, idxval); my_err("Illegal cell map in PXL file", 0); } #ifdef DEBUG printf("Loading index entry %d (%06o) with %d\n", chcode, &(hdr->index[charset][chcode]), idxval); #endif hdr->index[charset][chcode] = idxval; /* Load the mapping index */ if(idxval == 0) /* If undefined character */ continue; /* Finished, ignore noise */ /* * Point to the cell map to be bashed and * read in pixel rows, bashing the cell. */ pxlp = hdr->bitmap[fntnum] + (nbpc * idxval); nbits = nbpr << 3; for(i=0; i 132 */ switch(charset) /* HACK - ASSUMES ALL SAME SET */ { case 0: i = 'B'; break; /* G0 is ASCII (default) */ case 1: i = '0'; break; /* G0 is Special Graphics */ case 2: i = '<'; /* G0 is Supplemental Graphics */ } printf("\033(%c\n\n\t", i); for(i=0; i<6; i++) { for(j=0; j<16; j++) printf("%c ", 040 + (16 * i) + j); printf("\n\t"); } if(pass == 1) printf("\033(B\nPress RETURN to see the 132-column set ..."); else printf("\033(B\nPress RETURN to exit ..."); fflush(stdout); gets(buf); if(nbpr == 1) /* 132-column -> 80 */ { printf("\033[?3l"); fflush(stdout); } #endif if(pass++ == 1) /* If we just did the 80-column */ { fclose(ffp); fntnum = -1; /* Reset to see header in bin file! */ aflavor = "132.FNT"; bflavor = "132.DAT"; goto nxtflavor; /* Go back for 132-column */ } else exits(1); } /* * MY_ERR - Handle error conditions * * Non-interactive version silently returns with severe error, * otherwise calls FATLER for application error. */ my_err(fmt, val) char *fmt; int val; { char mb[80]; sprintf(mb, fmt, val); #ifdef DEBUG printf(fmt, val); #endif #ifdef INTERACTIVE p$fatler(mb); #endif exits(EX$SEV); } #ifdef INTERACTIVE /* * DISPLAY - Load and display selected menu */ display(frame) char *frame; { if(p$mframe(frame, action, sizeof(action), stat) != 1) my_err("MFRAME error"); p$menu(action, sizeof(action), FALSE, msg1, msg2, stat); } #endif