/*************************************************************

	CD辞書検索プログラム

**************************************************************/
#include    "defs.h"
#include    "getopt.h"

#define	VERSION	"%s version 0.24 1994.05.16 Nanno-NET(Ken)\n"

	char	*program_name = "dic";

	int	all_index_disp = FALSE;
	int	src_index_disp = FALSE;

	int	lines_max = DEF_LINE_MAX;
	int	cols_max = DEF_COLS_MAX;

	int	towns_flg = TRUE;	/* Towns CD_mode_set call */
	char	*dict_file_name = NULL;
	FILE	*dev_fp = NULL;
	char	*config_file_name = NULL;

#ifdef	STDFILE
	char	*dev_unit_name = CD_ROM;
#endif

#ifdef	MSCDEX
	int	dev_unit_no = 0;	/* MSCDEX CD Device No. */
	char	*dev_unit_name = NULL;
#endif

#ifdef	FMRBIOS
	int	dev_unit_no = 0xC0;	/* Towns CD Device No. */
	char	*dev_unit_name = "C0";
#endif

	char	*select_dic_str = NULL;
	int	now_dic_mode = DIC_DEVICE_MODE;
	int	now_dev_id = (-1);
	MENU	*dic_menu = NULL;
	MENU	*now_dic_menu = NULL;
	int	dic_count = 0;

	FILE	*ext_out_fp = NULL;
	char	ext_out_file[128];

	int	pause_flg = FALSE;
	int	prompt_flg = TRUE;
	int	zenkou_flag = FALSE;
	int	cutof_flag = FALSE;
	int	gaiji_flag = FALSE;
	int	color_flag = FALSE;
	int	bitmap_flag = FALSE;
	int	extdisp_flag = FALSE;
	int	extinput_flag = FALSE;
	int	copr_disp_flg = FALSE;
	int	menu_disp_flg = FALSE;
	int	catalog_disp_flag = FALSE;
	int	tex_out_flag = FALSE;

static	struct option opt_tab[] = {
	{ 'A',	0,	"catalog" },
	{ 'B',  0,	"bitmap" },
	{ 'C',	0,	"copr" },
	{ 'D',	1,	"dictionary" },
	{ 'L',  1,	"log" },
	{ 'M',  1,	"map" },
	{ 'N',	0,	"non" },
	{ 'P',  0,	"noprompt" },
	{ 'S',  0,	"noseparate" },
	{ 'V',  0,	"version" },
#ifdef	MAKDIC
	{ 'W',	1,	"makdic" },
#endif
	{ 'X',  0,	"pager" },
	{ 'a',	0,	"all_index" },
	{ 'c',	1,	"cols" },
	{ 'd',	1,	"device" },
	{ 'f',	1,	"file" },
	{ 'g',  0,	"gaiji" },
#ifdef	HISTORY
	{ 'h',  0,	"history" },
#endif
	{ 'l',	1,	"line" },
	{ 'm',	0,	"menu" },
	{ 'n',	0,	"no_towns" },
	{ 'p',	0,	"pause" },
	{ 'q',	1,	"config" },
	{ 's',	0,	"serach_index" },
	{ 'x',  0,	"extcolor" },
	{ 't',	0,	"tex" },
	{ 0,	0,	NULL } };

char	*progname(char *prog)
{
    char    *p;

    if ( (p = strrchr(prog, '\\')) != NULL )
	prog = p + 1;
    if ( (p = strrchr(prog, '/')) != NULL )
	prog = p + 1;
    for ( p = prog ; *p != '\0' ; p++ )
	*p = tolower(*p);
    if ( (p = strrchr(prog, '.')) != NULL && strcmp(p, ".exe") == 0 )
	*p = '\0';
    return prog;
}
void	usage(char *prog)
{
    int     n;
    static char *help[] = {
"Usage : %s [-adfghmnpqsxABCLMPSVX] [-D dic] <KeyWord...>\n",
"\t[-a] [--all_index]  [-c] [--cols]    [-d] [--device] [-f] [--file]\n",
"\t[-g] [--gaiji]      [-h] [--history] [-l] [--line]   [-m] [--menu]\n",
"\t[-n] [--no_towns]   [-p] [--pause]   [-s] [--serach_index]\n",
"\t[-x] [--extcolor]   [-B] [--bitmap]  [-C] [--copr] [-A] [--catalog]\n",
"\t[-D] [--dictionary] [-L] [--log]     [-M] [--map]  [-P] [--noprompt]\n",
"\t[-S] [--noseparate] [-X] [--pager]   [-V] [--version]\n",
NULL };

    for ( n = 0 ; help[n] != NULL ; n++ )
	fprintf(stderr, help[n], prog);
}
int	main_device_open(int mode, char *file)
{
    int     n;
    char    tmp[8];

    if ( Cache_flush(name_to_id(file)) )
	return FALSE;

    if ( dev_fp != NULL ) {
	fclose(dev_fp);
	dev_fp = NULL;
    }

    now_dic_mode = mode;
    file_start_block = 0L;
    file_end_block = 0xFFFFFFFFL;
    comp_dic_mode = FALSE;

    if ( now_dic_mode == DIC_FILE_MODE ) {
#ifndef	UNIX
	if ( (dev_fp = fopen(file, "rb")) == NULL )
#else
	if ( (dev_fp = fopen(file, "r")) == NULL )
#endif
	    return ERR;
	if ( fread(tmp, 1, 4, dev_fp) == 4 && strncmp(tmp, "EDIC", 4) == 0 )
	    comp_dic_mode = TRUE;
	return FALSE;
    }

#ifdef	STDFILE
    if ( (dev_fp = fopen(file, "r")) == NULL )
	return ERR;
    if ( fread(tmp, 1, 4, dev_fp) == 4 && strncmp(tmp, "EDIC", 4) == 0 )
	comp_dic_mode = TRUE;
#else
    dev_unit_no = htoi(file);
#endif

    for ( n = 0 ; n < 3 ; n++ ) {
	if ( !CD_file_init() )
	    break;
    }

    if ( n >= 3 )
	return ERR;

    return FALSE;
}
int	main_dic_open(MENU *mp)
{
    if ( main_device_open(mp->mode, mp->file) ) {
	fprintf(stderr,"Can't open Device %s\n", mp->file);
	return ERR;
    }

    if ( mp->mode == DIC_DEVICE_MODE && CD_file_open(mp->no) ) {
	fprintf(stderr,"Can't open Dictionary %s\n", mp->ttl);
	return ERR;
    }

    if ( dic_open() ) {
	fprintf(stderr,"Dictionary Init Error %s\n", mp->ttl);
	return ERR;
    }

    if ( gaiji_flag || bitmap_flag )
	Gaiji_init(mp->gaz, mp->gah);
    else
	Gaiji_close();

    return FALSE;
}
int	main_menu_set(int mode, char *file,
		char *ttl, int no, int gah, int gaz)
{
    MENU    *tp, *mp;

    if ( (mp = (MENU *)malloc(sizeof(MENU))) == NULL )
	return ERR;

    mp->next = NULL;
    mp->mode = mode;
    mp->file = strdup(file);
    mp->ttl  = strdup(ttl == NULL ? file:ttl);
    mp->no   = no;
    mp->gah  = gah;
    mp->gaz  = gaz;

    if ( dic_menu == NULL )
	dic_menu = mp;
    else {
	tp = dic_menu;
	while ( tp->next != NULL )
	    tp = tp->next;
	tp->next = mp;
    }
    dic_count++;

    return FALSE;
}
int	main_catalog_set(char *file, int no)
{
    CATALOG    *tp, *cp;

    if ( main_device_open(DIC_DEVICE_MODE, file) )
	return ERR;

    if ( (tp = catalog_load("CATALOG1")) == NULL &&
	 (tp = catalog_load("CATALOG2")) == NULL )
	return ERR;

    if ( no == ERR ) {
	for ( cp = tp ; cp != NULL ; cp = cp->next ) {
	    if ( main_menu_set(DIC_DEVICE_MODE, file,
			cp->ttl, cp->no, cp->gah, cp->gaz) )
	        return ERR;
	}
    } else {
	cp = tp;
	while ( --no > 0 && cp != NULL )
	    cp = cp->next;
	if ( cp == NULL ||
	     main_menu_set(DIC_DEVICE_MODE, file,
			cp->ttl, cp->no, cp->gah, cp->gaz) )
	    return ERR;
    }

    catalog_free(tp);
    return FALSE;
}
int	main_dic_list()
{
    int     n = 0;
    MENU    *mp;

    mp = dic_menu;
    while ( mp != NULL ) {
	printf("%2d:%s\n", ++n, mp->ttl);
	mp = mp->next;
    }
    return n;
}

#define	FUKUSU_MAX	10

static	int	fukusu_dic = 1;
static	int	fukusu_tab[FUKUSU_MAX];

int	main_dic_select(int no, char *str)
{
    int     n, i;
    MENU    *mp;
    char    tmp[COLS_MAX + 2];
    char    *av[FUKUSU_MAX];

    if ( no <= 0 && dic_count > 1 ) {
	for ( ; ; ) {
	    if ( str == NULL ) {
		main_dic_list();
	        printf("Dic No. ? ");
	        fflush(stdout);
	        if ( gets(tmp) == NULL )
	            return ERR;
	    } else {
		strcpy(tmp, str);
		str = NULL;
	    }

	    n = strcut(FUKUSU_MAX, av, tmp);
	    if ( n == 1 ) {
	        if ( (no = atoi(av[0])) > 0 && no <= dic_count ) {
		    fukusu_dic = 1;
		    break;
		}
		fprintf(stderr, "dic: dic select 1-%d\n", dic_count);

	    } else if ( n > 1 ) {
		for ( i = 0 ; i < n ; i++ ) {
		    if ( (no = atoi(av[i])) <= 0 || no > dic_count ) {
			fprintf(stderr, "dic: dic select 1-%d\n", dic_count);
			break;
		    }
		    fukusu_tab[i] = no;
		}
		if ( i == n ) {
		    fukusu_dic = i;
		    no = fukusu_tab[0];
		    break;
		}
	    }
	}
    }

    mp = dic_menu;
    for ( n = 1 ; n < no && mp != NULL ; n++ )
	mp = mp->next;

    if ( mp == NULL || main_dic_open(mp) )
	return ERR;

    now_dic_menu = mp;
    return FALSE;
}
void	main_dic_kensaku(char *str)
{
    int     n;

    if ( fukusu_dic > 1 ) {
	for ( n = 0 ; n < fukusu_dic ; n++ ) {
	    if ( !main_dic_select(fukusu_tab[n], NULL) ) {
		printf("%2d:%s\n", fukusu_tab[n], now_dic_menu->ttl);
	 	dic_print(dic_kensaku(str));
	    }
	}
	if ( main_dic_select(fukusu_tab[0], NULL) )
	    exit(1);
    } else
        dic_print(dic_kensaku(str));
}
int	main(int ac, char *av[])
{
    int     n;
    int     mx = 1;
    int     non_flag = FALSE;
    char    *p;
    char    tmp[COLS_MAX + 2];
#ifdef	MAKDIC
    char    *comp_dic = NULL;
#endif

#ifdef	MSDOS
    static char iobuffer[BUFSIZ];

    setbuf(stdout, iobuffer);
#endif

#ifdef	HAVE_LICO
    cols_lines_get(&cols_max, &lines_max);
#endif

    insert_opt(&ac, &av, 1, getenv("DICOPT"));
    program_name = progname(av[0]);

#ifdef	MSCDEX
    if ( CD_mscdex_init() ) {
	fprintf(stderr, "MSCDEX get Drive Error\n");
	exit(1);
    }
#endif

    for ( ; ; ) {
	while ( (n = getopt_long(ac, av, opt_tab)) != EOF ) {
	    switch(n) {
	    case 'a': all_index_disp = TRUE; break;
	    case 's': src_index_disp = TRUE; break;
	    case 'p': pause_flg = TRUE; break;
	    case 'd': dev_unit_name = optarg; break;
	    case 'D': select_dic_str = optarg; break;
	    case 'l': lines_max = atoi(optarg); break;
	    case 'c': cols_max = atoi(optarg); break;
	    case 'n': towns_flg = FALSE; break;
	    case 'C': copr_disp_flg = TRUE; break;
	    case 'm': menu_disp_flg = TRUE; break;
	    case 'f': dict_file_name = optarg; break;
	    case 'L':
		if ( (ext_out_fp = fopen(optarg, "a")) == NULL &&
		     (ext_out_fp = fopen(optarg, "w")) == NULL ) {
		    fprintf(stderr, "%s: Can't open %s\n",
			program_name, optarg);
		    exit(1);
		}
		strcpy(ext_out_file, optarg);
		break;
	    case 'P': prompt_flg = FALSE; break;
	    case 'S': cutof_flag = TRUE; break;
	    case 'g': gaiji_flag = TRUE; break;
	    case 'x': color_flag = TRUE; break;
	    case 'B': bitmap_flag = TRUE; break;
	    case 'M': Gaiji_config(optarg); break;
	    case 'X': extdisp_flag = TRUE; break;
	    case 'h': extinput_flag = TRUE; break;
	    case 'N': non_flag = TRUE; break;
	    case 'A': catalog_disp_flag = TRUE; break;
	    case 'V': fprintf(stderr, VERSION, program_name); exit(0);
	    case 'q': config_file_name = optarg; break;
	    case 't': tex_out_flag = TRUE; break;
#ifdef	MAKDIC
	    case 'W': comp_dic = optarg; break;
#endif
	    default: usage(program_name); exit(1);
	    }
	}
	if ( optind >= ac )
	    break;
	av[mx++] = av[optind++];
    }

    Cache_init();
    Gaiji_tab_init();

    if ( !isatty(0) || !isatty(1) ) {
	prompt_flg = FALSE;
	pause_flg = FALSE;
	extdisp_flag = FALSE;
	extinput_flag = FALSE;
    }

    if ( config_file_name != NULL ) {
	if ( device_config(config_file_name) )
	    exit(1);

    } else if ( dict_file_name != NULL ) {
	if ( main_menu_set(DIC_FILE_MODE, dict_file_name, NULL, 0, 0, 0) )
	    exit(1);

    } else if ( main_catalog_set(dev_unit_name, ERR) ) {
	fprintf(stderr, "dic: catalog load error\n");
	exit(1);
    }

    if ( catalog_disp_flag ) {
	main_dic_list();
	if ( mx == 1 && copr_disp_flg == FALSE &&
			menu_disp_flg == FALSE &&
			bitmap_flag   == FALSE &&
			all_index_disp == FALSE )
	    exit(0);
    }

    if ( main_dic_select(ERR, select_dic_str) ) {
	fprintf(stderr, "dic: dic select error\n");
	exit(1);
    }

#ifdef	MAKDIC
    if ( comp_dic != NULL ) {
	if ( compress(TRUE, comp_dic) )
	    fprintf(stderr, "dic: makdic error %s\n", comp_dic);
	exit(1);
    }
#endif

    if ( bitmap_flag ) {
	Gaiji_zenkaku_bitmap();
	Gaiji_hankaku_bitmap();
    }

    if ( all_index_disp ) {
	for ( n = 0 ; n < index_max ; n++ )
	    printf("\t%s\n", idx_name(&(index_buf[n])));
	multi_dic_print(multi_top);
    }

    if ( copr_disp_flg && IDX_COPR != NULL ) {
	dic_display(IDX_COPR->start_block, 0);
	if ( mx == 1 && menu_disp_flg == FALSE )
	    exit(0);
    }

    if ( menu_disp_flg && IDX_MENU != NULL ) {
	dic_display(IDX_MENU->start_block, 0);
	if ( mx == 1 )
	    exit(0);
    }

    if ( mx > 1 ) {
	while ( --mx > 0 )
	    main_dic_kensaku(*(++av));

    } else if ( non_flag == FALSE ) {
	for ( ; ; ) {
	    if ( prompt_flg )
		printf(">");

	    fflush(stdout);

#ifdef	HISTORY
	    if ( extinput_flag )
		input(tmp, cols_max - 2);
	    else if ( gets(tmp) == NULL )
		break;
#else
	    if ( gets(tmp) == NULL )
		break;
#endif

	    if ( (p = strchr(tmp, '\n')) != NULL )
	        *p = '\0';

	    if ( tmp[0] == '/' ) {
		if ( command(tmp) )
		    break;

	    } else if ( tmp[0] != '\0' )
		main_dic_kensaku(tmp);
	}
    }

    exit(0);
}
