Subject: GB code and bitmap (display GB code on a terminal)

From: YLu <[email-masked]>
Date: Sun, 19 May 91 21:18:47 BST

#     #         #         #             #
   ##   ###        ##  ########      ########         ####
   ##   ##         ##       ##  #   # ##  ##         ##  ##
  ##   ##    #    ##       ##   ########  ##        ##    ##
  #    ########   ## #    #     ## ## ##  ##         #    ##
 ###  ## #  ##  #######   ##    ## ## ##  ##             ##
 ### #   ## #     ## ##   ## #  ## ## ##  ## #          ##
# ##   # ##       ## ########## ## ## #########        ##
  ##   #####     ## ##    ##    ## ## #     ##         #
  ##  ##### #    ## ##    ##    ## ##       ##         #
  ##  ## ## ##    ###     ##    ## ##     # ##         #
  ## ##  ##  ##    ###    ##    ##############
  ###    ##  #    ## ##   ##    #  #        ##        ##
  ##     ##      ##  ## # ##                ##       ####
  ##   ####      #   #   ###              ###         ##
  #      #      #         #                #

The following is the C program I modified from the ahkcus.org 'readnews.c'
program with help from Mark Leisher of NMSU. It can be used to display
GB code on a dumb terminal with the BYX 16x16 bitmap file 'ziku'.

The program is successfully compiled under HP-UX 7.0 and Turbo C 2.01.
--------------------------------------------------------------------------
/*
 * readnews.c
 * Copyright (C) July 1990
 * Democracy Propaganda News System
 * version 1.00
 *
 */

/*
 * Program to display Chinese GuoBiao code on an ASCII terminal.
 * The bitmap file 'ziku' (distributed with BYX 1.1) is required.
 *
 * The original 'readnews.c' program is obtained from ahkcus.org
 * and can display Big5 code on an ASCII terminal with the
 * bitmap file 'chinese.16'.
 *
 * Modified Sun May 19 21:02:52 BST 1991 by YLu with help from
 * Mark Leisher ([email-masked])
 *
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#ifndef ZITAPE
#define	ZITAPE	"ziku"
#endif

#define HEIGHT	16

#define GBstart		0xA1A1
#define GBend		0xFEFE
#define ChWord(hi, lo)	((((hi) & 0xFF) << 8) | ((lo) & 0xFF))
#define isFirstByte(c)	(((c) & 0xFF) >= 0xA1)
#define inGBrange(x)	(((x) >= GBstart) && ((x) <= GBend))

FILE *fp, *bitmap;
char dictname[100] = ZITAPE;
char buffer[HEIGHT][200];
char inbuf[512];
int charinline = 5;

char chdot = '#', space = ' ';
char *program;

int order(), map();
void getbitmap(), putbitmap(), putline();

main(argc, argv)
int argc;
char **argv;
{
    int cc;
    int ch, charcnt, ch1, ch2;

#ifdef __MSDOS__
    char dir_delim = '\\';
#else
    char dir_delim = '/';
#endif

    /* get program name */
    if ((program = strrchr(argv[0], dir_delim)) == NULL)
	program = argv[0];
    else
	program++;

    /* process command arguments */
    while (--argc > 0 && (*++argv)[0] == '-')
	switch ((*argv)[1]) {
	case 'w':
	    charinline = atoi(*argv + 2);
	    break;
	case 'd':
	    strcpy(dictname, *argv + 2);
	    break;
	case 'c':
	    if ((cc = (*argv)[2]) != '\0' && isgraph(cc))
		chdot = cc;
	    break;
	default:
	    fprintf(stderr, "Usage: %s [-wWIDTH] [-dBITMAP] [-cCHAR] [file]\n",
 program);
	    exit(1);
	    break;
	}

    if (argc == 0)
	fp = stdin;
    else if ((fp = fopen(argv[0], "rb")) == NULL) {
	/* process the first file only */
	fprintf(stderr, "cannot open Big5 file: %s\n", argv[0]);
	exit(1);
    }
#ifdef __MSDOS__
    if ((bitmap = fopen(dictname, "rb")) == NULL) {
	fprintf(stderr, "cannot open bitmap file: %s\n", dictname);
	exit(1);
    }
#else
    if ((bitmap = fopen(dictname, "r")) == NULL) {
	fprintf(stderr, "cannot open bitmap file: %s\n", dictname);
	exit(1);
    }
#endif

    charcnt = 0;
    while ((ch = fgetc(fp)) != EOF) {
	ch1 = ch;
	if (ch1 == '\n' || ch1 == 26) {
	    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 = ch;
	    if (!inGBrange(ChWord(ch1, ch2))) {
		fputs("error: invalid character code\n", stderr);
		exit(1);
	    }
	    getbitmap(order(ch1, ch2));
	    putbitmap(charcnt);
	    charcnt++;
	} else if (map(ch, &ch1, &ch2) == 0) {
	    getbitmap(order(ch1, ch2));
	    putbitmap(charcnt);
	    charcnt++;
	}
	if (charcnt == charinline) {
	    putline(charinline);
	    charcnt = 0;
	}
    }
    fclose(bitmap);
}

int order(fontid, glyphid)
int fontid, glyphid;
{
    int charno;

    charno = (fontid - 0xA1) * 94 + (glyphid - 0xA1);
    if (fontid > 0xAA)
	charno -= 752;
    return (charno);
}

void getbitmap(bmindex)
int bmindex;
{
    long absaddr;
    int i;

    absaddr = ((long) bmindex) * 32;

    fseek(bitmap, absaddr, SEEK_SET);
    for (i = 0; i < 32; i++)
	fscanf(bitmap, "%c", &inbuf[i]);
}

void putbitmap(charpos)
int charpos;
{
    int i, k;

    k = charpos * 2;
    for (i = 0; i < HEIGHT; i++) {
	buffer[i][k] = inbuf[i * 2];
	buffer[i][k + 1] = inbuf[i * 2 + 1];
    }
}

void putline(noofchar)
int noofchar;
{
    char i, j, k, ch;

    for (i = 0; i < HEIGHT; i++) {
	for (j = 0; j < noofchar * 2; j++) {
	    ch = buffer[i][j];
	    k = 1;
	    if (j == 0) {
		ch <<= 1;
		k = 2;
	    }
	    for (; k <= 8; k++) {
		/* is high bit set? */
		if (ch & 0x80)
		    putchar(chdot);
		else
		    putchar(space);
		ch <<= 1;
	    }
	}
	putchar('\n');
    }
}

/* mapping printable ASCII to GB code */
int map(inchar, fontcode, charcode)
int inchar;
int *fontcode, *charcode;
{
    *fontcode = 0xA1;
    *charcode = 0xA1;		/* space */
    if (inchar == '\t')
	return (0);
    if (inchar < 0x20)		/* control characters */
	return (-1);
    switch (inchar) {
    case 'A':
    case 'B':
    case 'C':
    case 'D':
    case 'E':
    case 'F':
    case 'G':
    case 'H':
    case 'I':
    case 'J':
    case 'K':
    case 'L':
    case 'M':
    case 'N':
    case 'O':
    case 'P':
    case 'Q':
    case 'R':
    case 'S':
    case 'T':
    case 'U':
    case 'V':
    case 'W':
    case 'X':
    case 'Y':
    case 'Z':
	*fontcode = 0xA3;
	*charcode = 0xC1 + inchar - 'A';
	break;
    case 'a':
    case 'b':
    case 'c':
    case 'd':
    case 'e':
    case 'f':
    case 'g':
    case 'h':
    case 'i':
    case 'j':
    case 'k':
    case 'l':
    case 'm':
    case 'n':
    case 'o':
    case 'p':
    case 'q':
    case 'r':
    case 's':
    case 't':
    case 'u':
    case 'v':
    case 'w':
    case 'x':
    case 'y':
    case 'z':
	*fontcode = 0xA3;
	*charcode = 0xE1 + inchar - 'a';
	break;
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
	*fontcode = 0xA3;
	*charcode = 0xB0 + inchar - '0';
	break;
    case '!':
	*fontcode = 0xA3;
	*charcode = 0xA1;
	break;
    case '@':
	*fontcode = 0xA3;
	*charcode = 0xC0;
	break;
    case '#':
	*fontcode = 0xA3;
	*charcode = 0xA3;
	break;
    case '$':
	*fontcode = 0xA3;
	*charcode = 0xA4;
	break;
    case '%':
	*fontcode = 0xA3;
	*charcode = 0xA5;
	break;
    case '':
	*fontcode = 0xA3;
	*charcode = 0xDE;
	break;
    case '&':
	*fontcode = 0xA3;
	*charcode = 0xA6;
	break;
    case '*':
	*fontcode = 0xA3;
	*charcode = 0xAA;
	break;
    case '(':
	*fontcode = 0xA3;
	*charcode = 0xA8;
	break;
    case ')':
	*fontcode = 0xA3;
	*charcode = 0xA9;
	break;
    case ',':
	*fontcode = 0xA3;
	*charcode = 0xAC;
	break;
    case '.':
	*fontcode = 0xA3;
	*charcode = 0xAE;
	break;
    case ';':
	*fontcode = 0xA3;
	*charcode = 0xBB;
	break;
    case ':':
	*fontcode = 0xA3;
	*charcode = 0xBA;
	break;
    case '?':
	*fontcode = 0xA3;
	*charcode = 0xBF;
	break;
    case '|':
	*fontcode = 0xA3;
	*charcode = 0xFC;
	break;
    case '{':
	*fontcode = 0xA3;
	*charcode = 0xFB;
	break;
    case '}':
	*fontcode = 0xA3;
	*charcode = 0xFD;
	break;
    case '[':
	*fontcode = 0xA3;
	*charcode = 0xDB;
	break;
    case ']':
	*fontcode = 0xA3;
	*charcode = 0xDD;
	break;
    case '<':
	*fontcode = 0xA3;
	*charcode = 0xBC;
	break;
    case '>':
	*fontcode = 0xA3;
	*charcode = 0xBE;
	break;
    case '\"':
	*fontcode = 0xA3;
	*charcode = 0xA2;
	break;
    case '`':
	*fontcode = 0xA3;
	*charcode = 0xE0;
	break;
    case '\'':
	*fontcode = 0xA3;
	*charcode = 0xA7;
	break;
    case '_':
	*fontcode = 0xA3;
	*charcode = 0xDF;
	break;
    case '+':
	*fontcode = 0xA3;
	*charcode = 0xAB;
	break;
    case '-':
	*fontcode = 0xA3;
	*charcode = 0xAD;
	break;
    case '=':
	*fontcode = 0xA3;
	*charcode = 0xBD;
	break;
    case '^':
	*fontcode = 0xA1;
	*charcode = 0xAB;
	break;
    case '/':
	*fontcode = 0xA3;
	*charcode = 0xAF;
	break;
    case '\\':
	*fontcode = 0xA3;
	*charcode = 0xDC;
	break;
    }
    return (0);
}