/*
 * Copyright (C) 1994	Edward Der-Hua Liu, Hsin-Chu, Taiwan
 */

#include "big5con.h"

static int     *idx;		/* sorted index pointing to the phrase */
static u_char  *ph;		/* key string, phrase string  : C style */
static u_short  kmap[128];	/* hash,  point to idx array  */
/* 0xffff if the key is undefined */
/* 65535 phrases can be defined */
static int      phn = 0;
extern char    *tabfname[];

static 
qcmp_voc(int *a, int *b)
{
    return strcmp(&ph[*a], &ph[*b]);
}

void 
InitVocBox(int usenow)
{
    FILE           *fp;
    char            tt[1024];
    int             i, j;
    int             mfree;
    int             phsize;
    int             len;
    char           *p, *q;
    char           *vocbox_fname = tabfname[11];

    if (ph) {
	gotox(0);
	xprintf(" ¡iµü®w¡j");
	return;
    }
    if ((fp = fopen(vocbox_fname, "r")) == NULL) {
	error("Cannot open voxbox file %s\n", vocbox_fname);
	return;
    }
    while (!feof(fp)) {
	fgets(tt, sizeof(tt), fp);
	phn++;
    }
    phn++;

    if (!(idx = (int *)malloc(phn * sizeof(u_char *)))) {
	error("phrase.c: malloc error");
	return;
    }
    if (!(ph = (u_char *) malloc(phsize = 1024))) {
	error("phrase.c: malloc error");
	return;
    }
    mfree = phn = 0;
    fseek(fp, 0, 0);
    while (!feof(fp)) {
	fgets(tt, sizeof(tt), fp);
	p = tt;
	len = strlen(tt);
	if (len && tt[len - 1] == '\n')
	    tt[len - 1] = 0;
	if (tt[0] == '#')
	    continue;
	while (*p == 9 || *p == ' ')
	    p++;
	if (!*p)
	    continue;
	q = p;
	while (*q != 9 && *q != ' ' && *q)
	    q++;
	if (!*q)
	    continue;
	len = q - p + 1;	/* must include \000 */
	if (len >= phsize - mfree) {
	    phsize += 1024;
	    if ((ph = (char *)realloc(ph, phsize)) == NULL) {
		error("phrase.c: realloc err");
		return;
	    }
	}
	*(q++) = 0;
	strcpy(&ph[mfree], p);
	idx[phn++] = mfree;
	mfree += len;
	while (*q == 9 || *q == ' ')
	    q++;
	if (*q == '\n')
	    *q = 0;
	len = strlen(q);
	if (*q && *(q + len - 1) == 13) {
	    len--;
	    *(q + len) = 0;
	}
	if (len >= phsize - mfree) {
	    phsize += 1024;
	    if ((ph = (char *)realloc(ph, phsize)) == NULL) {
		error("phrase.c: realloc err");
		return;
	    }
	}
	strcpy(&ph[mfree], q);
	mfree += len + 1;
    }

    qsort(idx, phn, sizeof(idx[0]), qcmp_voc);

    fclose(fp);
    {
	char            d[128];
	bzero(d, sizeof(d));
	for (i = 0; i < 128; i++)
	    kmap[i] = 0xffff;
	for (i = 0; i < phn; i++) {	/* simple hash */
	    j = ph[idx[i]];
#if	0
	    printf("%s  %s\n", &ph[idx[i]], &ph[idx[i]] + strlen(&ph[idx[i]]) + 1);
#endif	/* 0 */
	    if (!d[j]) {
		kmap[j] = i;
		d[j] = 1;
	    }
	}
	kmap[127] = phn;
	for (i = 126; i >= 0; i--)
	    if (kmap[i] == 0xffff)
		kmap[i] = kmap[i + 1];

    }

    if (usenow) {
	gotox(0);
	xprintf("¡iµü®w¡j");
    }
}				/* InitPhrase */


static u_char   inch[40];
static int      cin;
static int      pg_idx, mic;

void 
ClrInArea()
{
    int             i;
    gotox(InAreaX);
    for (i = 0; i < cin + 1; i++)
	xprintf("  ");
    mic = cin = 0;
}

void 
DispInputArea()
{
    int             f, i;
    extern char     fullchar[];
    gotox(InAreaX);
    for (i = 0; i < cin; i++) {
	f = (int)(inch[i] - ' ') << 1;
	xprintf("%c%c", fullchar[f], fullchar[f + 1]);
    }
    xprintf("  ");

}

feedkey_vocbox(int key)
{
    int             i, j;
    extern int      cursor_x;

    switch (key) {
    case VK_Escape:
	if (cin) {
	    ClrSelArea();
	    ClrInArea();
	    return 1;
	} else
	    return 0;
    case VK_BackSpace:
    case VK_Delete:
	mic = 0;
	if (cin > 0) {
	    cin--;
	    break;
	} else
	    return 0;
    case ' ':
	if (cin > 0) {
	    int             s_h, e_h, cou, ic, xw;
	    char           *ss, *tt, vv[512];

	    pg_idx = 0;
	    inch[cin] = 0;
	    s_h = kmap[inch[0]];
	    e_h = kmap[inch[0] + 1];
	    for (i = s_h; i < e_h; i++)
		if (!strcmp(&ph[idx[i]], inch))
		    break;
	    if (i == e_h) {
		bell();
		return 1;
	    }
	    if (i == phn - 1 || strcmp(&ph[idx[i + 1]], inch)) {
		putstr(&ph[idx[i]] + strlen(&ph[idx[i]]) + 1);
		ClrInArea();
		cin = 0;
		return 1;
	    }
	    ic = 0;
	    pg_idx = i;
	    gotox(SelAreaX + 1);
	    while (i < e_h && cursor_x < 40 + SelAreaX && ic < 9 &&
		   !strcmp(ss = &ph[idx[i]], inch)) {
		tt = ss + strlen(ss) + 1;
		strcpy(vv, tt);
		vv[6] = 0;
		i++;
		ic++;
		xprintf("%d%s ", ic, vv);
	    }
	    mic = ic;
	    return 1;
	}
	return 0;
    default:
	if (key < ' ' || key > 0x7e)
	    return 0;
	if (mic) {
	    i = key - '1';
	    if (i < 0 || i >= mic)
		return 0;
	    putstr(&ph[idx[pg_idx + i]] +
		   strlen(&ph[idx[pg_idx + i]]) + 1);
	    mic = 0;
	    ClrSelArea();
	    ClrInArea();
	    return 1;
	}
	if (cin < 14)
	    inch[cin++] = key;
    }

    DispInputArea();
    return 1;
}
