/*
 * utilities for japanese
 */

#include	"defs.h"
#include	"global.h"

/* jsubfont */
#include	"jsub.h"

char *jsf_names[] = {
    "",
    "jsy",
    "jroma",
    "jhira",
    "jkata",
    "jgreek",
    "jrussian",
    "jkeisen",
    "jka",
    "jkb",
    "jkc",
    "jkd",
    "jke",
    "jkf",
    "jkg",
    "jkh",
    "jki",
    "jkj",
    "jkk",
    "jkl",
    "jkm",
    "jkn",
    "jko",
    "jkp",
    "jkq",
    "jkr",
    "jks",
    "jkt",
    "jku",
    "jkv",
    "jkw",
    "jkx",
    "jky",
    "jkz",
    NULL
};

getjsubfont(n, subend)
char *n;
char **subend;
{
    int f;

    for (f = 1; f <= NJSUBS; f++)
	if (!strncmp(n, jsf_names[f], strlen(jsf_names[f]))) {
	    *subend = n + strlen(jsf_names[f])-1;
	    return f;
	}
    return 0;
}

#define	hex(c)	(c>='a' ? c-'a'+10 : c-'0')

getdcode(n, subend)
char *n;
char **subend;
{
    if (*n == CSUB_SEP && *(n+3) == CSUB_SEP) {
	*subend = n+3;
	return (hex(*(n+1))*16+hex(*(n+2)));
    }
    return 0;
}

#define	kushift(c)	(c+0x20)
#define	tenshift(c)	(c+0x20)

void
jsub_to_jis(f, c, ku, ten)
short f, c;
unsigned short *ku, *ten;
{
    int n;

    if (f <= 7) {
	if (f == 1) {
	    if (c >= 100) {
		*ku = kushift(2);
		*ten = tenshift(c-100);
	    } else {
		*ku = kushift(1);
		*ten = tenshift(c);
	    }
	} else if (f == 2) {
	    *ku = kushift(3);
	    *ten = tenshift(c-32);
	} else {
	    *ku = kushift(f+1);
	    *ten = tenshift(c);
	}
    } else if (f <= 19) {	/* Daiichi Suijun */
	n = (f-8)*256+c;
	*ku = kushift((n/94)+16);
	*ten = tenshift((n%94)+1);
    } else {			/* Daini Suijun */
	n = (f-20)*256+c;
	*ku = kushift((n/94)+48);
	*ten = tenshift((n%94)+1);
    }
}

void
jis_to_jsub(ku, ten, f, c)
short ku, ten;
unsigned short *f, *c;
{
    int n;

    ku -= 0x20;
    ten -= 0x20;
    *f = 1;
    *c = 1;
    if (ku <= 0 || (9 <= ku && ku <= 15) || ku > 84) {
	Warning("invalid ku in jis (%x, %x)", ku+0x20, ten+0x20);
	return;
    }
    if (ten < 1 || ten > 94) {
	Warning("invalid ten in jis (%x, %x)", ku+0x20, ten+0x20);
	return;
    }
    if (ku <= 8) {
	if (ku == 1) {
	    *f = 1;
	    *c = ten;
	} else if (ku == 2) {
	    *f = 1;
	    *c = ten+100;
	} else if (ku == 3) {
	    *f = 2;
	    *c = ten+32;
	} else {
	    *f = ku-1;
	    *c = ten;
	}
    } else if (ku <= 47) {	/* Daiich Suijun */
	n = (ku-16)*94+ten-1;
	*f = (n/256)+8;
	*c = n%256;
    } else {			/* Daini Suijun */
	n = (ku-48)*94+ten-1;
	*f = (n/256)+20;
	*c = n%256;
    }
}

void
code_to_jis(s, c, ku, ten)
unsigned short s, c;
unsigned short *ku, *ten;
{
    if (c >= 128) {
	*ku = s+1;
	*ten = c-128;
    } else {
	*ku = s;
	*ten = c;
    }
}

#if 0
void
dcode_to_jis(f, c, ku, ten)
unsigned short f, c;
unsigned short *ku, *ten;
{
    if (c >= 128) {
	*ku = f*2+0x20;
	*ten = c-128;
    } else {
	*ku = f*2+0x1f;
	*ten = c;
    }
}
#endif

void
jis_to_dcode(ku, ten, f, c)
unsigned short ku, ten;
unsigned short *f, *c;
{
    *f = (unsigned short)(ku-0x21)/2 + 1;
    *c = (ku%2 == 1) ? ten : ten+128;
}

int foundjsubf;

/* fname is obtained by substituting subfont of sname.
 * if ini, initial match, otherwise strict match.
 * sb and se points subfont part of fname.
 */
match_subf(sname, fname, ini, sb, se)
char *sname, *fname;
BOOLEAN ini;
char **sb, **se;
{
    *sb = NULL;
    for (; *sname != '\0'; sname++, fname++) {
	if (*sname == '%') {
	    if (*++sname == 'j') {
		if ((foundjsubf = getjsubfont(fname, se)) == 0)
		    return FALSE;
	    } else if (*sname == 'c') {
		if (*fname == CSUB_SEP && *(fname+3) == CSUB_SEP) {
		    *se = fname+3;
		} else
		    return FALSE;
	    } else
		return FALSE;
	    *sb = fname;
	    fname = *se;
	} else if (*sname != *fname)
	    return FALSE;
    }
    if (*fname == '\0')
	return TRUE;
    else
	return ini;
}

void
subst_subf(fname, sname, sb, se)
char *fname, *sname;
char *sb, *se;
{
    char *s;

    for (; *sname != '\0'; sname++) {
	if (*sname == '%') {
	    sname++;
	    for (s = sb; s <= se; s++, fname++)
		*fname = *s;
	} else
	    *fname++ = *sname;
    }
    *fname = '\0';
}

/* converts jis code to 94*94 code intex,
 * but if jis is out of range, return -1
 */
jis_to_idx94(jis)
unsigned int jis;
{
    int kanji, c1, c2;

    if ((kanji = jis - 0x2121) < 0)
	return -1;
    c1 = (kanji>>8)&0xff;
    if (c1 >= 94)
	return -1;
    c2 = kanji&0xff;
    if (c2 >= 94)
	return -1;
    return (c1*94 + c2);
}

#ifdef UNDEF
idx94_to_std(idx)
int idx;
{
    return ((idx/94)*256 + (idx%94) + 0x2121);
}

jsub_to_idx94(f, c)
short f, c;
{
    unsigned short ku, ten;

    jsub_to_jis(f, c, &ku, &ten);
    return jis_to_idx94(ku*256+ten);
}

idx94_to_sjis(idx)
int idx;
{
    int i1, i2, c1, c2;

    i1 = idx/94;
    i2 = idx%94;
    if ((i1 & 1) == 0) {
	if (i1 < 0x3e) c1 = i1/2 + 0x81;
	else c1 = i1/2 + 0xc1;
	if (i2 >= 0x3f) c2 = i2 + 0x41;
	else c2 = i2 + 0x40;
    } else {
	if (i1 < 0x3e) c1 = i1/2 + 0x81;
	else  c1 = i1/2 + 0xc0;
	c2 = i2 + 0x9f;
    }
    return (c1*256 + c2);
}
#endif
