/******************************************

	Dic Search & Display

*******************************************/
#include    "defs.h"
#include    "dic.h"

#ifdef	UNIX
#define	POINT_MAX	1000
#else
#define	POINT_MAX	400		/* 4+2 * 400 = 2400 */
#endif

static	int	serch_flg = FALSE;
static	POINT	point_tab[POINT_MAX];

char	*idx_name(INDEX *ip)
{
    static struct {
	uchar		id;
	char		*ttl;
    } index_name[] = {
	{ MK_HONMON,	"本文データ" },
	{ MK_MENU,	"メニュー表示データ" },
	{ MK_COPR,	"著作権表示データ" },
	{ TI_TANGO,	"単語検索用見出しデータ" },
	{ TI_ZKANA,	"前方一致かな検索用見出しデータ" },
	{ TI_ZHYOKI,	"前方一致表記検索用見出しデータ" },
	{ TI_KKANA,	"後方一致かな検索用見出しデータ" },
	{ TI_KHYOKI,	"後方一致表記検索用見出しデータ" },
	{ TI_ZALPHA,	"前方一致英字検索用見出しデータ" },
	{ TI_KALPHA,	"後方一致英字検索用見出しデータ" },
	{ TI_CROSS,	"見出し条件，クロス検索用見出しデータ" },
	{ TI_NUMBER,	"数字検索用見出しデータ" },
	{ MK_MENU2,	"メニュー表示用データ２" },
	{ MK_COPR2,	"著作権表示データ２" },
	{ MK_COPR3,	"著作権表示データ３" },
	{ MK_SOUND,	"音データ用見出しデータ" },
	{ MK_ZUHAN,	"図版データ" },
	{ MK_IRO,	"色表示用データ" },
	{ MK_ANSHO,	"暗証データ" },
	{ MK_KANA,	"かな検索用インデックス" },
	{ MK_ALPHA,	"英字検索用インデックス" },
	{ MK_KANJI,	"漢字検索用インデックス" },
	{ MK_HYOKI,	"表記形検索用インデックス" },
	{ MK_KKANA,	"後方一致かな検索用インデックス" },
	{ MK_KHYOKI,	"後方一致表記形検索用インデックス" },
	{ MK_KALPHA,	"後方一致英字検索用インデックス" },
	{ MK_TANGO,	"単語検索用インデックス" },
	{ MK_CROSS,	"見出し条件・クロス検索用インデックス" },
	{ MK_ZKANA,	"前方一致かな検索用インデックス" },
	{ MK_ZHYOKI,	"前方一致表記形検索用インデックス" },
	{ MK_ZALPHA,	"前方一致英字検索用インデックス" },
	{ MK_NUMBER,	"項目番号（数字）インデックス" },
	{ MK_PAGE,	"ペ−ジ検索用インデックス" },
	{ MK_SOUKAKU,	"漢字総画数インデックス" },
	{ MK_BUSYUKAKU,	"漢字部首数インデックス" },
	{ MK_FUKUGO,	"複合インデックステ−ブル" },
	{ 0,		NULL }
    };
    static char *index_sub_name[] = {
	"デ−タ",		"デ−タ",		"デ−タ",
	"階層化インデックス",	"階層化インデックス",	"階層化インデックス",
	"階層化インデックス",	"階層化インデックス",	"階層化インデックス",
	"階層化インデックス",	"階層化インデックス",
	"非階層化インデックス",	"非階層化インデックス",
	"図版デ−タ",
	"その他",		"その他",
    };
    int     n;
    static char tmp[32];

    for ( n = 0 ; index_name[n].ttl != NULL ; n++ ) {
	if ( ip->id == index_name[n].id )
	    return index_name[n].ttl;
    }
    n = (ip->id >> 4) & 0x0F;
    sprintf(tmp, "%02x %s", ip->id, index_sub_name[n]);
    return tmp;
}
/******************************************

	Multi Dic Search

*******************************************/
static	int	point_search(POINT *pos, int bs, int mx)
{
    int    n, c;

    while ( bs <= mx ) {
	n = (bs + mx) / 2;
	if ( (c = point_tab[n].block  - pos->block) == 0 &&
	     (c = point_tab[n].offset - pos->offset) == 0 )
	    return n;
	else if ( c < 0 )
	    bs = n + 1;
	else
	    mx = n - 1;
    }
    return (-1);
}
static	int	point_cmp(POINT *sp, POINT *dp)
{
    int     c;

    if ( (c = sp->block - dp->block) != 0 )
	return c;
    return (sp->offset - dp->offset);
}
static	int	point_multi(char *str, int mx, int *rx)
{
    int     n;
    int     bs = 0;

    *rx = 0;

    if ( init_serch(str) )
	return 0;

    qsort((char *)point_tab, mx, sizeof(POINT), point_cmp);

    while ( dic_serch() == FALSE ) {
	if ( (n = point_search(&honbun, bs, mx)) >= 0 ) {
	    for ( ; n > 0 ; n-- )
		point_tab[n] = point_tab[n - 1];
	    bs++;
	    point_tab[0] = honbun;
	}
	*rx += 1;
    }

    return bs;
}
static	int	stand_kensaku(char *str)
{
    int     n, mx;
    POINT   old;

    if ( init_serch(str) )
	return 0;

    old.block = 0L;
    mx = 0;
    serch_flg = FALSE;

    while ( mx < POINT_MAX && (n = dic_serch()) == FALSE ) {
	if ( old.block == honbun.block && old.offset == honbun.offset )
	    continue;
	point_tab[mx].block  = old.block  = honbun.block;
	point_tab[mx].offset = old.offset = honbun.offset;
	mx++;
    }

    if ( mx == 0 && index_ptr != NULL && index_ptr->id == MK_ALPHA &&
		gobi_init(str) ) {
	while ( (str = gobi_conv()) != NULL ) {
	    if ( !init_serch(str) ) {
		while ( mx < POINT_MAX && (n = dic_serch()) == FALSE ) {
		    if ( old.block == honbun.block &&
			 old.offset == honbun.offset )
			continue;
		    point_tab[mx].block  = old.block  = honbun.block;
		    point_tab[mx].offset = old.offset = honbun.offset;
		    mx++;
		}
	    }
	}
    }

    if ( mx == 0 && n != ERR ) {
	point_tab[mx].block  = honbun.block;
	point_tab[mx].offset = honbun.offset;
	mx++;
	serch_flg = TRUE;
    }

    return mx;
}
int	dic_kensaku(uchar *str)
{
    int     mx, bs, rx;
    static uchar tmp[COLS_MAX + 2];
    static uchar one[COLS_MAX + 2];

    str = str_jis(tmp, str);
    str = str_word(one, str);

    mx = stand_kensaku(one);
    if ( *str == '\0' )
	return mx;

    put_jis(one, COLS_MAX);
    if ( serch_flg )
	printf("\t曖昧な検索です\n");
    else
	printf("\t%d 項目\n", mx);

    while ( mx > 0 && *str != '\0' ) {
	str = str_word(one, str);
	bs = point_multi(one, mx, &rx);
	put_jis(one, COLS_MAX);
	printf("\t%d/%d:%d 項目\n", rx, mx, bs);
	mx = bs;
    }

    return mx;
}
void	dic_print(int mx)
{
    if ( src_index_disp && index_ptr != NULL )
	printf("Search Index is %s\n", idx_name(index_ptr));

    if ( mx == 0 ) {
	printf("<<< 見当たりません >>\n");
    } else if ( mx >= POINT_MAX ) {
	printf("<<< たくさんあります >>\n");
    } else if ( serch_flg ) {
	printf("<<< 曖昧な検索です >>\n");
    } else if ( mx > 1 ) {
	printf("<<< %d項目 >>\n", mx);
    }

    if ( extdisp_flag )
	pager(point_tab, mx, FALSE);
    else
	more(point_tab, mx);
}
void	dic_index_print()
{
    if ( IDX_KANA != NULL || IDX_KKANA != NULL || IDX_ZKANA != NULL )
	printf("%s%s%sかな検索\n",
		IDX_ZKANA != NULL ? "前方":"",
		IDX_KKANA != NULL ? "後方":"",
		IDX_KANA  != NULL ? "完全":"");

    if ( IDX_ALPHA != NULL || IDX_KALPHA != NULL || IDX_ZALPHA != NULL )
	printf("%s%s%s英字検索\n",
		IDX_ZALPHA != NULL ? "前方":"",
		IDX_KALPHA != NULL ? "後方":"",
		IDX_ALPHA  != NULL ? "完全":"");

    if ( IDX_HYOKI != NULL || IDX_KHYOKI != NULL || IDX_ZHYOKI != NULL )
	printf("%s%s%s表記検索\n",
		IDX_ZHYOKI != NULL ? "前方":"",
		IDX_KHYOKI != NULL ? "後方":"",
		IDX_HYOKI  != NULL ? "完全":"");

    if ( IDX_KANJI != NULL || IDX_TANGO != NULL || IDX_CROSS != NULL ||
	 IDX_NUMBER != NULL || IDX_MENU != NULL )
	printf("%s%s%s%s%s",
		IDX_KANJI != NULL ? "漢字検索\n":"",
		IDX_TANGO != NULL ? "単語検索\n":"",
		IDX_CROSS != NULL ? "見出し検索\n":"",
		IDX_NUMBER!= NULL ? "数字検索\n":"",
		IDX_MENU  != NULL ? "メニュ−検索\n":"");
}
void	dic_index_list()
{
    int      n = 0;
    MULTI    *mul;
    MULPTR   *mp;
    int      bs, mx;

    bs = index_tab_base;
    mx = index_tab_max;

    index_tab_init(0, index_max);
    if ( (mul = multi_top) != NULL )
	printf("−− 00:Standard Index −−\n");
    dic_index_print();

    while ( mul != NULL ) {
	mp = mul->mul_list;
	while ( mp != NULL ) {
	    index_tab_init(mp->bs, mp->mx);
	    printf("−− %02d:%s −−\n", ++n, mp->mul_ttl);
	    dic_index_print();
	    mp = mp->next;
	}
	mul = mul->next;
    }

    index_tab_init(bs, mx);
}
void	multi_index_print(MULPTR *mp)
{
    int     n;

    if ( mp == NULL )
	return;

    multi_index_print(mp->next);

    printf("%s\n", mp->mul_ttl);
    for ( n = mp->bs ; n < mp->mx ; n++ )
	printf("\t%s\n", idx_name(&(index_buf[n])));
}
void	multi_dic_print(MULTI *mul)
{
    if ( mul == NULL )
	return;
    multi_dic_print(mul->next);
    multi_index_print(mul->mul_list);
}
int	multi_select(int no)
{
    int     n;
    MULTI   *mu;
    MULPTR  *mi;

    if ( no == 0 ) {
	if ( src_index_disp )
	    printf("−− 00:Standard Index −−\n");
	index_tab_init(0, index_max);
	return FALSE;
    }

    if ( (mu = multi_top) == NULL )
	return ERR;

    n = 0;
    while ( mu != NULL ) {
	mi = mu->mul_list;
	while ( mi != NULL ) {
	    if ( ++n == no ) {
		if ( src_index_disp )
		    printf("−− %02d:%s −−\n", n, mi->mul_ttl);
		index_tab_init(mi->bs, mi->mx);
		return FALSE;
	    }
	    mi = mi->next;
	}
	mu = mu->next;
    }
    return ERR;
}
