/* A program in the C Language for compiling on Unix-like systems. * * Converts a pattern font file to the code required to load the font * into a Wyse60 terminal or Wyse99GT in native emulation (personality * per Wyse jargon). * * Copyright (c) by David S. Lawyer, July 1990 and may be freely used, * copied, and modified by anyone provided that any modifications * of major significance be also made freely available. If sold, the * purchaser must be clearly informed (by larger than fine print) prior * to the sale that this is free software. * This copyright notice must not be removed. * * Thanks to Victor Poon for his Wyse60 font programs which provided * some of the ideas used in this program. *Version: 1.1 * Input is a pattern file containing character patterns, 8 to a row. It is * either std. input [use -s flag] or is given as an argument. Each such * pattern should be similar to the large "A" character shown on the next page. * Output goes to stdout and thus all messages must go to stderr. To run this * program (after you compile it) create a pattern file named say my_patterns * by using any convenient editor. Then put my_patterns thru this program (as * a filter) thereby obtaining the font code in your output file named say * my_font. To download this font you could just copy it to the terminal but * in most cases you will want to use a shell script. This script will set up * the terminal correctly and then activate the appropriate font bank, etc. * See the Wyse Programmers's Guide p.8-6 to 8-10 for how to generate * characters and p.7-4 to 7-5 on how to assign font banks. The * secondary bank (bank 1 by defualt) seems to display as meta characters * (8th bit set). * * Many terminals can't download font at 9600 baud. There are 3 types of * fixes for this problem: 1. Lower the baud rate. 2. Enable Xon/Xoff * flow control (Doesn't always solve the problem on some inferior * terminals). 3. Add null padding to your my_font file by using a flag * such as -p 80 when generating the softfont. On a Wyse 99Gt terminals * it was necessary to use 80 nulls per line of my_font. */ #include /* For some C compliers you should: #include */ /*--------------------external variables--------------------------------------*/ extern char *optarg; extern int optind; /*--------------------global variables---------------------------------------*/ int nchars_coded = 0, Bank = 1, /* Bank of Wyse terminal to load font into. Command line opt.*/ Cell_height, /* = cell_height++ since index-origin = 0. Read from header.*/ Cell_width, /* = cell_width++ since index-origin = 0. Read from header.*/ First_char = 0x20, /* Hex no. of first character. Command line option */ Pad_level = 0; /* How many nulls to pad each line with. Command line option.*/ char junk[100]; /* For reading junk characters from file (comments etc.) */ FILE *fp; /* Pointer to input file */ /*--------------------forward declarations-----------------------------------*/ int encode_band(); /* Encodes 8 large-chars in band */ void usage(); /* Usage help & error message */ void scan_err(int nscanned, int row); /* error message */ void char_read_err( char ch,int nchars_coded, int char_no, int row, int col, char line[][]); /* error message*/ /*--------------------start of main------------------------------------------*/ void main(int argc, char **argv) { char header_line1[100], /* For storing 1st header line */ header_line2[100], /* For storing 2nd header line */ ch; /* For reading first char of header*/ /*-------------------parse command line--------------------------------------*/ if ( argc == 1 ) usage(); while (( ch = getopt(argc, argv, "b:f:p:s") ) != EOF) { switch (ch) { case 'b': Bank = atoi(optarg); fprintf(stderr, "Bank = %d \n", Bank); break; case 'f': First_char = (int) strtol (optarg, (char **)NULL, 16); fprintf(stderr, "First_char = %X hex. \n", First_char); break; case 'p': Pad_level = atoi(optarg); fprintf(stderr, "Pad_level = %d nulls/line. \n", Pad_level); break; case 's': fp = stdin; fprintf(stderr, "Using standard input \n"); break; case '?': usage(); } } if (fp != stdin) { if ( (fp = fopen( argv[optind], "r")) == NULL) { fprintf(stderr, "Can't open output file: %s\n", argv[optind]); usage(); } } /*------------------parse header lines--------------------------------------*/ while( '#' == (ch = getc(fp) ) ) /* Discard comment lines (seek) */ fgets(junk, sizeof(junk), fp); /* Seek to end of line. fscanf broken */ ungetc( ch, fp); /* Put back non-# ch on input file. */ fprintf (stderr,"Start of encoding font. Following are header lines from your\ input file:\n"); /* The first line of the source file must look something like: 12x7 pattern. */ fgets( header_line1, sizeof(header_line1), fp); /* Read first line */ fputs( header_line1, stderr); /* Echo it to your terminal */ sscanf( header_line1, "%ix%i",&Cell_height, &Cell_width ); /* Extract vars. from it */ /* The second line of the source file is just a brief description of the * font which will be echoed to the terminal each time the font is loaded. */ fgets( header_line2, sizeof(header_line2), fp); /* Read second line */ fputs( header_line2, stderr); /* Echo it to your terminal */ /*----------------------call encode_band-------------------------------------*/ while (encode_band() != NULL); /* Encodes 8 chars until EOF */ fputs(header_line1, stdout); /* Header line at end of output file */ fputs(header_line2, stdout); /* Header line at end of output file */ fprintf( stdout,"Bank = %d ", Bank); fprintf( stdout,"First_char = %x hex ", First_char ); fprintf( stdout,"Pad_level = %d nulls/line \n", Pad_level); fprintf (stderr,"Finished. Encoded %d characters for a Wyse (native) terminal.\n", nchars_coded); } /*---------------------end of main-------------------------------------------*/ /* EXAMPLE OF A 12x7 PATTERN: * It is also called a 7x12 pattern and it might be displayed within a * larger 10x13 (or 13x10) cell on a Wyse terminal. This 12x7 pattern * is also said to fit into a 12x7 "cell" which in turn will go * into a larger cell on the physical terminal screen. * * The character matrix (or pattern) has character (either . or *) pixels. * Eight such matrices in a row form a "band" of 8 character matrices. * (0,0).......(0,6) * ...*... Note index origin = 0. * ..*.*.. * .*...*. <--------- Band[0][3] = 01000100 = 88 hex. * *.....* [0] is the 0th character matrix * ******* in the band of 8 chars (0-7) * *.....* Col. 8 is absent (but assumed all dots) * *.....* 88 hex is stored as one ascii char. * *.....* * *.....* band [char_no][row] * *.....* Use last 2 rows for descenders. * ....... Cell_height = 12 * (11,0).......(11,6) cell_height = Cell_height - 1 = 11 * Cell_width = 7 * cell_width = Cell_width - 1 = 6 * The 1st letter has bits (0,0)-(0,6) (0,0) is the low-order bit. * The 2nd letter has bits (1,0)-(1,6) * The 3rd letter has bits (2,0)-(2,6) * ......... * The letter(Cell_height) has bits (cell_height,0)-(cell_height,cell_width) ** * INPUT FILE FORMAT: Look at a sample file (named ...pat) before * reading this. The file begins with optional comment lines each * starting with #. The next two lines are file-header lines for the * entire file. The first gives the size of the character cells in the * pattern file. For example: 12x7 cells. "10x8 patterns" would also be * an acceptable line (don't type in the quotes). The second line should * be an important comment which will be displayed on the crt each time you * download the font. Then comes thick-rows of Character matrices * (patterns). Each such thick-row is called a "band" and must be * preceded by a horizontal separator-header line. The horizontal * separator-header lines should contain the character numbers etc. but * may contain anything (including a blank line). Each character matrix * is separated from the adjacent one to its right (or left) by vertical * "columns" of white space. Each such "column" may be wider than one * space if desired. There must be exactly 8 character matrices * (patterns) in each band (= thick-row). */ /**************************encode_band()***************************************/ int encode_band() { /* Parameters passed vis global vars. */ int row, col, /* Loop index counter. */ i, /* loop index counter used in padding loop*/ cell_height = Cell_height - 1, cell_width = Cell_width - 1, bit_value, /* increment letter with this */ char_no, /* =0 to 7; sequence no. of pattern-char */ nscanned; /* No. of strings scanned by fscanf. Should be 1.*/ char ch, /* char read from pattern == * or . */ header[100], /* used for storage of a header line */ line[8][Cell_width + 1]; /* for reading a line of input pat. file */ unsigned char letter, /* letter encoded from a row of a pattern matrix */ band[8][Cell_height]; /* A band of 8 pattern_chars. See drawing above. * band array: band [char_no] [row] * Element is the ascii char encoding for a row */ /*--------------------------------start---------------------------------------*/ /* A band of 8 large_characters is read from the input file pointed to by fp * and is put into the band array. */ if ( fgets(header, sizeof(header), fp) == NULL) /* Get header line */ return 0; /* probably EOF */ fputs(header, stderr); /* echo header line of band */ for (row = 0; row <= cell_height; row ++) { /*-------------------------------read a line----------------------------------*/ for (char_no = 0; char_no <= 7; char_no ++) { nscanned = fscanf(fp, "%[^ \t\n]%*[ \t]", line[char_no]); if (nscanned != 1) scan_err(nscanned, row); /* print error message. No exit */ } fgets(junk, sizeof(junk), fp); /* seek to end of line */ /*-------------------------encode line into band------------------------------*/ for (char_no = 0 ; char_no <= 7 ; char_no ++) { bit_value = 128; letter = 0; /* initialize */ for (col = 0 ; col <= cell_width ; col ++) { ch = line [char_no] [col]; if (ch == '*') letter += bit_value; else if (ch != '.') char_read_err(ch, nchars_coded, char_no, row, col, line); bit_value >>= 1; /* halve bit_value */ } /* end for on cols. Have a letter for a row*/ band [char_no] [row] = letter; } /* end for on char_no. Have encoded row crossing 8 chars */ } /* end for on row. Have encoded all rows (and completed band)*/ /*-----------------------write band to stdout---------------------------------*/ for (char_no = 0 ; char_no <= 7 ; char_no ++) { printf("\033cA%1d%02X", Bank, nchars_coded + First_char); for (row = 0; row <= cell_height; row ++) printf("%02X", band [char_no] [row]); putchar('\031'); /* ^Y for Wyse 60 terminals. */ /* Not needed for Wyse 99GT */ /*--------------------------add padding?--------------------------------------*/ for (i = 1; i <= Pad_level; i++) /* Append padding nulls to char */ putchar('\0'); /*-------------------------finish up------------------------------------------*/ putchar('\n'); /* End of large_char encoding (EOL) */ nchars_coded ++; } /* end 2nd for on char_no. 8 Pattern-chars done. */ return nchars_coded; /* Must return a non-zero value */ } /*----------------------end encode_band()-------------------------------------*/ /***********************char_read_err******************************************/ void char_read_err( char ch, int nchars_coded, int char_no, int row, int col, char line[][Cell_width + 1]) { fprintf(stderr, "ERROR in reading pattern file. Found an illegal char: %c\ (= Hex %X)\nin band %d the %d th character", ch, ch, nchars_coded / 8, char_no); fprintf(stderr, ", located at row %d col %d of character matrix.\n", row, col); fprintf(stderr, " This error is within the last header line shown above.\n"); fprintf(stderr, "The offending line (white space becomes a single space) is:\ \n%s %s %s %s %s %s %s %s \n", line[0], line[1], line[2], line[3], line[4], line[5], line[6], line[7]); if (ch == '\0' ) fprintf(stderr, "The null character found is likely not really in your source file but is a null (Hex 0) terminator for a string which is generated because there is a white-space character where a . or * should be.\n"); exit (-1); } /*****************************scan_err()***************************************/ void scan_err(int nscanned, int row) { fprintf(stderr, "***ERROR*** fscanf returned %d instead of 1. If 0 it failed to find a char.\ \nBefore scanning this band you encoded %d characters. Error is in\ \n row %d of current band (see last header line above) \n\n", nscanned, nchars_coded, row + 1); /* Should exit w/char_read_err */ } /*********************************usage()**************************************/ void usage() { fprintf(stderr, "Usage: gfontv [-p 80] -s | input_file \ \n-b 2 => Bank 2 will get font (default = 1).\ \n-f 0 => first character is 0 hex in the character code chart. Default\ \n is 20 hex (=40 octal, = 16 decimal, = the character in ascii)\ \n-p 80 => append 80 (or whatever) padding nulls to each line of output.\ \n-s use standard input.\n"); exit (-1); }