#include "kanjiif.h"

#define	MAXOPEN		64
kaninfo kanjiinfo[MAXOPEN];
static int (*in_ln_tab[])() = {
    in_ln_ascii,
    in_ln_jis,
    in_ln_jis,
    in_ln_jis,
    in_ln_jis,
    in_ln_jis,
    in_ln_jis,
    0,
    0,
    0,
    in_ln_sjis,
    0, 0, 0, 0, 0, 0, 0, 0, 0,
    in_ln_jis
};
static int (*out_ch_tab[])() = {
    out_ch_ascii,
    out_ch_jis,
    out_ch_jis,
    out_ch_jis,
    out_ch_jis,
    out_ch_jis,
    out_ch_jis,
    0,
    0,
    0,
    out_ch_sjis,
    0, 0, 0, 0, 0, 0, 0, 0, 0,
    out_ch_euc
};
struct {
    char esc_in, esc_out;
} jis_esc_tab[] = {
    {'\0', '\0'}, /* dummy */
    {'@', 'J'},
    {'@', 'H'},
    {'@', 'B'},
    {'B', 'J'},
    {'B', 'H'},
    {'B', 'B'}
};

int in_ln_ascii(f, ki)
register FILE *f;
kaninfo *ki;
{
    register int i;

    while (last < bufsize && ((i = getc(f)) != EOF) && i != '\n')
	if (is_eightbit(i)) {
	    buffer[last++] = ext_eightbit;
	    buffer[last++] = de_eightbit(i);
	} else
	    buffer[last++] = i;
    return (i);
}

int in_ln_jis(f, ki)
FILE *f;
kaninfo *ki;
{
    return (in_ln_gen(f, ki, check_euc_kanji, euc2TeXkanji));
}

int in_ln_sjis(f, ki)
FILE *f;
kaninfo *ki;
{
    return (in_ln_gen(f, ki, check_sj_kanji, sj2TeXkanji));
}

check_euc_kanji(c, ki)
textchar c;
kaninfo *ki;
{
    if (c&0x80) {
	ki->kpend = c;
	ki->kstat = KAN_ASCII_KAN;
    } else
	buffer[last++] = c;
}

check_sj_kanji(c, ki)
textchar c;
kaninfo *ki;
{
    if (c >= 0xe0 || c >= 0x80 && c < 0xa0) {
	ki->kpend = c;
	ki->kstat = KAN_ASCII_KAN;
    } else if (c < 0x80)
	buffer[last++] = c;
    else {
	/* Web procedure should be called for a better error handling. */
	/*fprintf(stderr, "\n1-byte kana (shift-jis) ignored.\n");*/
	buffer[last++] = '?';
    }
}

int in_ln_gen(f, ki, checkkanji, makekanji)
register FILE *f;
register kaninfo *ki;
int (*checkkanji)(), (*makekanji)();
{
    register int i;
    textchar c1, c2;

    while (last < bufsize && ((i = getc(f)) != EOF) && i != '\n') {
	if (ki->kstat == KAN_ASCII) {
	    if (i == ESC) {
		if ((i = getc(f)) == '$') {
		    getc(f);
		    ki->kstat = KAN_JIS_SECOND;
		} else if (i == '(') {
		    getc(f);
		    /* ki->kstat = KAN_ASCII; */
		} else {
		    /* Web procedure should be called for a better error handling. */
		    fprintf(stderr,"\nText line contains an invalid escape sequence\n");
		    exit(1);
		}
	    } else
		(*checkkanji)(i, ki);
	} else if (ki->kstat == KAN_JIS_FIRST) {
	    if (last >= bufsize-1)
		return(i);
	    jis2TeXkanji(ki->kpend, i, &c1, &c2);
	    buffer[last++] = make_ext_kanji(c1);
	    buffer[last++] = c2;
	    ki->kstat = KAN_JIS_SECOND;
	} else if (ki->kstat == KAN_JIS_SECOND) {
	    if (i == ESC) {
		if ((i = getc(f)) == '$') {
		    getc(f);
		    /* ki->kstat = KAN_JIS_SECOND; */
		} else if (i == '(') {
		    getc(f);
		    ki->kstat = KAN_ASCII;
		} else {
		    /* Web procedure should be called for a better error handling. */
		    fprintf(stderr,"\nText line contains an invalid escape sequence\n");
		    exit(1);
		}
	    } else if (i < ' ') {
		buffer[last++] = i;
	    } else {
		ki->kpend = i;
		ki->kstat = KAN_JIS_FIRST;
	    }
	} else /*if (ki->kstat == KAN_ASCII_KAN)*/ {
	    if (last >= bufsize-1)
		return(i);
	    (*makekanji)(ki->kpend, i, &c1, &c2);
	    buffer[last++] = make_ext_kanji(c1);
	    buffer[last++] = c2;
	    ki->kstat = KAN_ASCII;
	}
    }
    return (i);
}

Fputc(c, f)
textchar c;
FILE *f;
{
    register kaninfo *ki;

    ki = &kanjiinfo[fileno(f)];
    (*(ki->out_ch))(c, f, ki);
}

Fputs(f, s)
register FILE *f;
register textchar *s;
{
    register kaninfo *ki;

    ki = &kanjiinfo[fileno(f)];
    for (; *s; s++)
	(*(ki->out_ch))(*s, f, ki);
}

out_ch_ascii(c, f, ki)
textchar c;
FILE *f;
kaninfo *ki;
{
    if (ki->kstat == KAN_EIGHT) {
	putc(make_eightbit(c), f);
	ki->kstat = KAN_ASCII;
    } else if (is_ext_eightbit(c)) {
	ki->kstat = KAN_EIGHT;
    } else
	putc(c, f);
}

out_ch_jis(c, f, ki)
textchar c;
FILE *f;
register kaninfo *ki;
{
    textchar c1, c2;

    if (ki->kstat == KAN_FIRST) {
	TeXkanji2jis(ki->kpend, c, &c1, &c2);
	putc(c1, f); putc(c2, f);
	ki->kstat = KAN_SECOND;
    } else if (ki->kstat == KAN_EIGHT) {
	putc(make_eightbit(c), f);
	ki->kstat = KAN_ASCII;
    } else if (is_ext_kanji(c)) {
	if (ki->kstat == KAN_ASCII) {
	    putc(ESC, f); putc('$', f);
	    putc(jis_esc_tab[ki->ktype].esc_in, f);
	}
	ki->kpend = de_ext_kanji(c);
	ki->kstat = KAN_FIRST;
    } else {
	if (ki->kstat == KAN_SECOND) {
	    putc(ESC, f); putc('(', f);
	    putc(jis_esc_tab[ki->ktype].esc_out, f);
	}
	if (is_ext_eightbit(c)) {
	    ki->kstat = KAN_EIGHT;
	} else {
	    putc(c, f);
	    ki->kstat = KAN_ASCII;
	}
    }
}

out_ch_euc(c, f, ki)
textchar c;
FILE *f;
kaninfo *ki;
{
    textchar c1, c2;

    if (ki->kstat == KAN_FIRST) {
	TeXkanji2euc(ki->kpend, c, &c1, &c2);
	putc(c1, f); putc(c2, f);
	ki->kstat = KAN_SECOND;
    } else if (is_ext_kanji(c)) {
	ki->kpend = de_ext_kanji(c);
	ki->kstat = KAN_FIRST;
    } else {
	putc(c, f);
	ki->kstat = KAN_ASCII;
    }
}

out_ch_sjis(c, f, ki)
textchar c;
FILE *f;
register kaninfo *ki;
{
    textchar c1, c2;

    if (ki->kstat == KAN_FIRST) {
	TeXkanji2sj(ki->kpend, c, &c1, &c2);
	putc(c1, f); putc(c2, f);
	ki->kstat = KAN_SECOND;
    } else if (is_ext_kanji(c)) {
	ki->kpend = de_ext_kanji(c);
	ki->kstat = KAN_FIRST;
    } else {
	putc(c, f);
	ki->kstat = KAN_ASCII;
    }
}

/*
 * Kanji conversion functions
 */
jis2TeXkanji(i1, i2, c1, c2)
textchar i1, i2, *c1, *c2;
{
    *c1 = i1;
    *c2 = i2;
    fix_kanji_range(c1, c2);
#ifndef	TeX
    *c2 = i2|0x80;
#endif
}

TeXkanji2jis(i1, i2, c1, c2)
textchar i1, i2, *c1, *c2;
{
    *c1 = i1;
#ifdef	TeX
    *c2 = i2;
#else
    *c2 = i2&0x7f;
#endif
}

euc2TeXkanji(i1, i2, c1, c2)
textchar i1, i2, *c1, *c2;
{
    *c1 = i1&0x7f;
    *c2 = i2&0x7f;
    fix_kanji_range(c1, c2);
#ifndef	TeX
    *c2 = i2|0x80;
#endif
}

TeXkanji2euc(i1, i2, c1, c2)
textchar i1, i2, *c1, *c2;
{
    *c1 = i1|0x80;
    *c2 = i2|0x80;
}

sj2TeXkanji(i1, i2, c1, c2)
textchar i1, i2, *c1, *c2;
{
    if (i2 >= 0x9f) {
	if (i1 >= 0xe0) *c1 = (i1 - 0xb0) * 2;
	else *c1 = (i1 - 0x70) * 2;
	*c2 = i2 - 0x7e;
    } else {
	if (i1 >= 0xe0) *c1 = (i1 - 0xb0) * 2 - 1;
	else *c1 = (i1 - 0x70) * 2 - 1;
	if (i2 >= 0x7f) *c2 = i2 - 0x20;
	else *c2 = i2 -  0x1f;
    }
    fix_kanji_range(c1, c2);
#ifndef	TeX
    *c2 = i2|0x80;
#endif
}

TeXkanji2sj(i1, i2, c1, c2)
textchar i1, i2, *c1, *c2;
{
#ifndef	TeX
    i2 &= 0x7f;
#endif
    if (i1 & 1) {
	if (i1 < 0x5f) *c1 = i1/2 + 0x71;
	else *c1 = i1/2 + 0xb1;
	if (i2 >= 0x60) *c2 = i2 + 0x20;
	else *c2 = i2 + 0x1f;
    } else {
	if (i1 < 0x5f) *c1 = i1/2 + 0x70;
	else  *c1 = i1/2 + 0xb0;
	*c2 = i2 + 0x7e;
    }
}

fix_kanji_range(c1, c2)
textchar *c1, *c2;
{
    if (*c1 < 0x21 || (*c1 >= 0x29 && *c1 <= 0x2f) || *c1 >= 0x75) {
	*c1 = 0x22;
	*c2 = 0x23;
    }
}

setinkanjitype(f, ktype)
FILE *f;
int ktype;
{
    kanjiinfo[fileno(f)].ktype = ktype;
    kanjiinfo[fileno(f)].kstat = KAN_ASCII;
    kanjiinfo[fileno(f)].in_ln = in_ln_tab[ktype];
}

setoutkanjitype(f, ktype)
FILE *f;
int ktype;
{
    kanjiinfo[fileno(f)].ktype = ktype;
    kanjiinfo[fileno(f)].kstat = KAN_ASCII;
    kanjiinfo[fileno(f)].out_ch = out_ch_tab[ktype];
}
