/*
 * BDF ファイルからフォントデータを生成する
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char wbuffer[200];
char *params[50];

/*
 *  グループ・テーブルの各エントリには、最初のグリフと最後のグリフの
 *  コード番号を保持する。
 */
struct ftab_ent {
    unsigned short first;
    unsigned short last;
};

#define	MAX_GROUPS	200

struct ftab_ent gtable[MAX_GROUPS];

char **linesprit(char *line)
{
    int narg, c;

    narg = 0;

    while (*line != '\n') {
        params[narg++] = line;
        while (*line != ' ' && *line != '\n') line++;
	c = *line;
        *line++ = '\0';
	if (c == '\n') break;
        while (*line == ' ') line++;
    }
    params[narg] = NULL;
    return params;
}

unsigned short jis_to_sjis(unsigned short jis)
{
    unsigned char c1, c2;

    c1 = jis >> 8;
    c2 = jis & 0xff;
    if (c1 % 2) {
	c1 = ((c1 + 1)/2) + 0x70;
	c2 = c2 + 0x1f;
    } else {
	c1 = (c1 / 2) + 0x70;
	c2 = c2 + 0x7d;
    }
    if (c1 >= 0xa0) { c1 = c1 + 0x40; };
    if (c2 >= 0x7f) { c2 = c2 + 1; };
    return (c1 << 8) | c2;
}

void fontgen(FILE *fp, char *fname, char *ftype)
{
    int nb;
    int nparams;
    char **parg, *cp;
    int gwidth, gheight, wbytes;
    int defchar, jis;
    int gnumber, gfirst, glast;
    int ntable, nchars, i;
    int dump_flag;

    /* 1st pass. Collect font table info. */
 
    defchar = ntable = 0;
    gfirst = -10;
    while (fgets(wbuffer, sizeof(wbuffer), fp)) {
        parg = linesprit(wbuffer);
	if (strcmp(parg[0], "FONTBOUNDINGBOX") == 0) {
	    gwidth = atoi(parg[1]);
	    gheight = atoi(parg[2]);
	    wbytes = gwidth / 8;
	    if (gwidth % 8) wbytes++;
#ifdef DEBUG
	    printf("%d,%d\n", gwidth, gheight);
#endif
	} else if (strcmp(parg[0], "DEFAULT_CHAR") == 0) {
	    defchar = atoi(parg[1]);
	    if (defchar > 255) defchar = jis_to_sjis(defchar);
	} else if (strcmp(parg[0], "SPACING") == 0) {
	    if (strcmp(parg[1], "\"C\"")) {
		fprintf(stderr, "Not a constant width font set.\n");
		exit(1);
	    }
	} else if (strcmp(parg[0], "CHARS") == 0) {
	    nchars = atoi(parg[1]);
	} else if (strcmp(parg[0], "ENCODING") == 0) {
	    gnumber = jis = atoi(parg[1]);
            if (jis > 255) gnumber = jis_to_sjis(jis);
#ifdef DEBUG
	    printf("gnumber = %d --> %x\n", jis, gnumber);
#endif
	    if (gnumber != glast + 1) {
		if (gfirst >= 0) {
		    gtable[ntable].first = gfirst;
		    gtable[ntable].last = glast;
		    ntable++;
		    if (ntable == MAX_GROUPS) {
			fprintf(stderr, "Too many groups!!\n");
			exit(1);
		    }
		}
		gfirst = gnumber;
	    }
	    glast = gnumber;
	}
    }
    gtable[ntable].first = gfirst;
    gtable[ntable].last = glast;
    ntable++;
#ifdef DEBUG
    printf("Group %d --> %d\n", gfirst, glast);
    printf("ntable = %d\n", ntable);
#endif

    printf("const struct codetab %s_tab[%d] = {\n", fname, ntable);
    for (i = 0; i < ntable; i++) {
	printf("  { 0x%x, 0x%x },\n", gtable[i].first, gtable[i].last);
    }
    printf("};\n");
    fseek(fp, 0L, SEEK_SET);

    /* 2nd pass. Dump Glyph image data */
    printf("const unsigned char %s_glyph_data[] = {\n", fname);
    dump_flag = 0;
    while (fgets(wbuffer, sizeof(wbuffer), fp)) {
        parg = linesprit(wbuffer);
	if (strcmp(parg[0], "BITMAP") == 0) {
	    dump_flag = 1;
	} else if (strcmp(parg[0], "ENDCHAR") == 0) {
	    printf("\n");
	    dump_flag = 0;
	} else {
	    if (dump_flag) {
		cp = parg[0];
		while (*cp) {
		    printf(" 0x%c%c,", cp[0], cp[1]);
		    cp += 2;
		}
	    }
	}
    }
    printf("};\n");

    printf("const struct font_info finfo_%s = {\n", ftype);
    printf("  %d, %d, %d, %d, %d,\n", gwidth, gheight, wbytes, ntable, defchar);
    printf("  %s_tab,\n", fname);
    printf("  %s_glyph_data,\n", fname);
    printf("};\n");
}

main(int argc, char **argv)
{
    FILE *fp1, *fp2;
    char *afont, *kfont, *cp;

    if (argc < 3) {
	fprintf(stderr, "Usage: %s ascii.bdf kanji.bdf\n", argv[0]);
	exit(1);
    }
    afont = argv[1];
    kfont = argv[2];
    fp1 = fopen(afont, "r");
    if (fp1 == NULL) {
	fprintf(stderr, "can't open %s\n", afont);
	exit(1);
    }
    cp = strrchr(afont, '/');
    if (cp) afont = ++cp;
    for (cp = afont; *cp; cp++) {
        if (*cp == '.') {
	    *cp = '\0';
	    break;
	}
    }
    fp2 = fopen(kfont, "r");
    if (fp2 == NULL) {
	fprintf(stderr, "can't open %s\n", kfont);
	exit(1);
    }
    cp = strrchr(kfont, '/');
    if (cp) kfont = ++cp;
    for (cp = kfont; *cp; cp++) {
        if (*cp == '.') {
	    *cp = '\0';
	    break;
	}
    }
    fontgen(fp1, afont, "ascii");
    fontgen(fp2, kfont, "kanji");
    return 0;
}

