/* From: YLu Date: Mon, 25 Jan 93 17:48:45 GMT usage example: readgb -d/home/ftp/software/fonts/cclib.16 -f16 < gb_file | cless readgb -d/home/ftp/software/fonts/cclibk.24 -f24 -e0 < gb_file | cless */ /*************************************************************************** Program to display Chinese GuoBiao code on an ASCII terminal. The 16x16 bitmap 'ziku' (BYX 1.1) or 'cclib.16' is required. ** Chinese GuoBiao coding The 2-byte 8-bit GB code (with high bit set) is in the range 0xA1A1 to 0xF7FE. The second byte (WEI) has values from 0xA1 to 0xFE, thus forming 0xFE - 0xA1 + 1 = 0x5E (94) GB ideograms. The first byte (QU) is from 0xA1 to 0xF7, therefore there can be a total of (0xF7 - 0xA1 + 1)*94 = 8178 valid GB codes. In the GB table, from 0xA1A1 to 0xAFFE are allocated for symbols. HanZi starts from 0xB0A1, the possible total HanZi is therefore (0xF7 - 0xB0 + 1)*94 = 6768. The HanZi code between 0xB0A1 and 0xF7FE is divided into two parts, the first part between 0xB0A1 and 0xD7F9 with a total of 3755 is the most frequently used and is in PinYin order, while the second part between 0xD8A1 and 0xF7FE has a total of 3008 and is in stroke (BuShou) order. There are five blank spaces from 0xD7FA to 0xD7FE. The total HanZi accommodated in the GB table is therefore 6768 - 5 = 6763. ** Calculations for getting bitmaps from GB fonts: word_index = (first_byte - 0xA1)*94 + (second_byte - 0xA1); byte_index = word_index * num_bytes; where num_bytes is the number of bytes needed for one bitmap. num_bytes = font_height * font_width/8; For a square Chinese Hanzi, font_height = font_width = fontsize; A 16x16 font requires 32 bytes for each bitmap, and a 24x24 font requires 72 bytes for each bitmap. byte_index gives the starting point of the bitmap in the font file. ** Special considerations for the available bitmap libray: In the 16x16 BYX ziku and cclib.16, the range from 0xA8A1 to 0xAFFE is undefined. This gives (0xAF - 0xA8 + 1)*94 = 752 empty spaces. Therefore, we have: word_index = (first_byte - 0xA1)*94 + (second_byte - 0xA1); if (first_byte > 0xAF) word_index -= 752; byte_index = word_index * num_bytes; The 16x16 font is stored in row order and scanned from left to right, top to bottom. The MSB of the first byte is the upper left bit, the LSB of the last byte is the lower right bit. The 24x24 BYX font is stored in column order and scanned from top to bottom, left to right. The MSB of the first byte is the upper left bit, the LSB of the last byte is the lower right bit. The 24x24 cclib.24 font is stored in row order and has all the legal codes defined. ***************************************************************************/ #include #include #include #include #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef GBTAPE #define GBTAPE "ziku" #endif #ifndef FONTSIZE #define FONTSIZE 16 #endif #ifndef NCOLUMNS #define NCOLUMNS 132 #endif #ifndef EMPTYSP #define EMPTYSP 752 #endif #define BYTE8(c) ((c) & 0xFF) #define isFirstByte(c) (((c) >= 0xA1) && ((c) <= 0xF7)) #define isSecondByte(c) (((c) >= 0xA1) && ((c) <= 0xFE)) #define isGBcode(hi,lo) (isFirstByte(hi) && isSecondByte(lo)) FILE *fp, *bitmap; char dictname[100] = GBTAPE; char **buffer; char inbuf[BUFSIZ]; #ifdef __MSDOS__ #define RMODE "rb" #define DIR_DELIM '\\' #else /* unix */ #define RMODE "r" #define DIR_DELIM '/' #endif char chdot = '#', space = ' '; char *program; int fontsize = FONTSIZE; int height, column, num_bytes; int row_row = 1; /* row by row order */ int row_mul, col_mul; /* fontsize/8 */ int row_loop, col_loop; /* 8 */ int charinline = 4; int width_flag = 0; int empty_sp = EMPTYSP; int order(), map(); void getbitmap(), putbitmap(), putline(); void usage(), load_bitmap(), display_gb(); void gb_font(); main(argc, argv) int argc; char **argv; { int cc; /* get program name */ if ((program = strrchr(argv[0], DIR_DELIM)) == NULL) program = argv[0]; else program++; /* process command arguments */ /* better to use getopt() */ while (--argc > 0 && (*++argv)[0] == '-') switch ((*argv)[1]) { case 'w': charinline = atoi(*argv + 2); width_flag = 1; break; case 'e': empty_sp = atoi(*argv + 2); break; case 'k': row_row = 0; /* column order */ break; case 'f': fontsize = atoi(*argv + 2); break; case 'd': strcpy(dictname, *argv + 2); break; case 'c': if ((cc = (*argv)[2]) != '\0' && isgraph(cc)) chdot = cc; break; default: usage(); break; } if (argc == 0) fp = stdin; else if ((fp = fopen(argv[0], RMODE)) == NULL) { /* process the first file for fun only */ fprintf(stderr, "cannot open GB file: %s\n", argv[0]); exit(1); } gb_font(); load_bitmap(); display_gb(); fclose(bitmap); if (fp != stdin) fclose(fp); } void usage() { fprintf(stderr, "Usage:\t%s [-wLINE] [-fSIZE] [-dBITMAP] [-cGLYPH] [-eSIZE] [-k] [file]\n\n", program); fprintf(stderr, "\tDisplay Guo Biao code on terminal\n"); fprintf(stderr, "\t-w width of line (number of ideographs across)\n"); fprintf(stderr, "\t-f font size if not %dx%d\n", FONTSIZE, FONTSIZE); fprintf(stderr, "\t-d follow with bitmap path\n"); fprintf(stderr, "\t-c if unsatisfied with [%c]\n", chdot); fprintf(stderr, "\t-e empty space undefined in bitmap\n"); fprintf(stderr, "\t-k column order if image mirrored\n"); fprintf(stderr, "\t-h help\n"); exit(1); } void gb_font() { int i; if ((fontsize % 8 != 0) || (fontsize == 0)) { fprintf(stderr, "invalid GB font: %dx%d\n", fontsize, fontsize); exit(1); } if (row_row) { height = fontsize; column = fontsize / 8; row_mul = column; col_mul = 1; } else { height = fontsize / 8; column = fontsize; row_mul = 1; col_mul = height; } num_bytes = height * column; row_loop = fontsize / height; /* row_loop * col_loop == 8 */ col_loop = fontsize / column; if (!width_flag || (charinline == 0)) charinline = 79 / fontsize; /* for 80 column screen */ if ((buffer = (char **) malloc(height * sizeof(char *))) == NULL) { fputs("not enough memory for buffer!\n", stderr); exit(1); } for (i = 0; i < height; i++) { if ((buffer[i] = (char *) malloc(NCOLUMNS * sizeof(char))) == NULL) { fputs("not enough memory!\n", stderr); exit(1); } } } void load_bitmap() { if ((bitmap = fopen(dictname, RMODE)) == NULL) { fprintf(stderr, "cannot open bitmap file: %s\n", dictname); exit(1); } } void display_gb() { int ch, ch1, ch2; int lastch, nextch; int charcnt = 0; while ((ch = fgetc(fp)) != EOF) { ch1 = lastch = BYTE8(ch); if (ch1 == '\r' || ch1 == 26) continue; if (ch1 == '\n') { if (charcnt > 0) { putline(charcnt); charcnt = 0; } } else if (isFirstByte(ch1)) { if ((ch = fgetc(fp)) == EOF) { fputs("error: reading input data\n", stderr); exit(1); } ch2 = BYTE8(ch); if (!isGBcode(ch1, ch2)) { fputs("error: invalid character code\n", stderr); exit(1); } getbitmap(order(ch1, ch2)); putbitmap(charcnt); charcnt++; } else if ((lastch == ' ') || (lastch == '\t')) { /* squeeze extra spaces or tabs */ while ((nextch = fgetc(fp)) != EOF) { if ((nextch == ' ') || (nextch == '\t')) continue; else { ungetc(nextch, fp); break; } } ch1 = 0xA1; ch2 = 0xA1; getbitmap(order(ch1, ch2)); putbitmap(charcnt); charcnt++; } else if (map(lastch, &ch1, &ch2) == 0) { getbitmap(order(ch1, ch2)); putbitmap(charcnt); charcnt++; } if (charcnt == charinline) { putline(charinline); charcnt = 0; } } if (charcnt > 0) putline(charcnt); /* characters left */ } int order(fontid, glyphid) int fontid, glyphid; { int charno; charno = (fontid - 0xA1) * 94 + (glyphid - 0xA1); if (fontid > 0xAA) charno -= empty_sp; return (charno); } void getbitmap(bmindex) int bmindex; { long absaddr; int i; absaddr = ((long) bmindex) * num_bytes; fseek(bitmap, absaddr, SEEK_SET); for (i = 0; i < num_bytes; i++) fscanf(bitmap, "%c", &inbuf[i]); } void putbitmap(charpos) int charpos; { int i, j, k; k = charpos * column; for (i = 0; i < height; i++) { for (j = 0; j < column; j++) { buffer[i][k + j] = inbuf[i * row_mul + j * col_mul]; } } } void putline(noofchar) int noofchar; { char i, j, r, k, cij, crk, ch; for (i = 0; i < height; i++) { for (r = 0; r < row_loop; r++) { for (j = 0; j < noofchar * column; j++) { cij = buffer[i][j]; crk = cij << r; for (k = 0; k < col_loop; k++) { ch = crk << k; /* is high bit set? */ if (ch & 0x80) putchar(chdot); else putchar(space); } } putchar('\n'); } } putchar('\n'); } /********************************************************************* Mapping printable standard ASCII to GuoBiao code. In the GB table, the 94 printable ASCII characters (excluding space) are in the 0xA3 Qu. By an offset of 0x80, the GB ASCII characters correspond to the standard ASCII character set. There are two exceptions in the cclib.16 library: the dollar $ sign becomes a Y and the tilde ~ sign becomes a bar. *********************************************************************/ int map(inchar, qu, wei) int inchar; int *qu, *wei; { if (isgraph(inchar)) { *qu = 0xA3; *wei = inchar + 0x80; return (0); } else return (-1); }