/****************************************

    Shell like Message Wind

    1990.9.25 make by ken

******************************************/
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <ctype.h>
#include    <time.h>
#include    <mos.h>
#include    "event.h"
#include    "graphic.h"
#include    "defs.h"
#include    "coldef.h"

#define FUNC_MAX    	(32*1024)

#define	HASH_MAX	16			/* 4,8,16,32... */
#define	HASH(p)	    	hash_calc(p)

#define	MSG_MAX		128
#define	BUF_MAX		256

#define	MSG_LEN		50
#define	MSG_X1		112
#define	MSG_Y1		120
#define	MSG_XSIZ	(MSG_LEN*8+16)
#define	MSG_YSIZ	(11*18+16)
#define	MSG_X2		(MSG_X1+MSG_XSIZ-1)
#define	MSG_Y2		(MSG_Y1+MSG_YSIZ-1)

#define	YES_X		(MSG_X1+17*8)
#define	YES_Y		(MSG_Y1+10*18+12)
#define	NO_X		(MSG_X1+25*8)
#define	NO_Y		(MSG_Y1+10*18+12)

void	CHK_snd(void);
void	CHK_eup(void);
void	DSP_xline();
int	MSG_run();
int	iskan(char *p);
int	kan_pos(char *str,int pos);
void	key_in(void);
void	key_out(void);
int	kbhit(void);
int	getkey(unsigned *ec);
int	getch(void);
int	keyword(char *file,int sw);
void	getdir(char *dir);
int	MSG_cfg_load(char *file);
char	*secret_file(char *file);
void	EDIT_KEY_set(int code,char *func);
void	TERM_KEY_set(int code,char *func);
void	KAN_KAN_open(void);
void	KAN_close(void);
void	CON_open(int no);
void	CON_close();
char	*CON_input(int ch);
int	CON_redisp(int ofs);

typedef struct _MAC {
    struct _MAC	*next;
    char	*mac;
    char	*str;
} MACRO;

static int	msg_event=ERR;
static int	msg_col=15,msg_bak=9,msg_lin=7,msg_lin2=8;
static int	msg_len=0,msg_ox=0,msg_x=0,msg_y=0;
static int	msg_sts=FALSE;
static int	msg_open_flg=FALSE;
static BLOCK	*msg_save=NULL;
       int	msg_tab=8;
static char	msg_buf[BUF_MAX];
       char	func_buf[FUNC_MAX];
       char     *func_ptr=func_buf;
static MACRO	*topmac[HASH_MAX]={
	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL };
static MACRO	*topprc[HASH_MAX]={
	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
	NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL };

int	hash_calc(register char *p)
{
    register int hs=0;

    while ( *p != '\0' )
	hs = hs * 31 + *(p++);
    return(hs & (HASH_MAX-1));
}
char	*strdup(char *str)
{
    register char *p;

    if ( (p = (char *)malloc(strlen(str)+1)) != NULL )
	strcpy(p,str);
    return p;
}
int	htoi(char *p)
{
    int     i=0;

    while ( isxdigit(*p) ) {
	if ( isdigit(*p) )
	    i = i * 16 + (*p - '0');
	else
	    i = i * 16 + (toupper(*p) - 'A' + 10);
	p++;
    }
    return i;
}
void	tsleep(int sec)
{
    clock_t t;

    t = clock() + CLK_TCK * sec;
    while ( t > clock() ) {
	CHK_snd();
	CHK_eup();
    }
}
char    *get_word(char *buf,char *str)
{
    while ( *str != '\0' && (isalnum(*str) || *str == '_') )
	*(buf++) = *(str++);
    *buf = '\0';
    return str;
}
char    *prcget(char *prc)
{
    register MACRO *mp;

    for ( mp = topprc[HASH(prc)] ; mp != NULL ; mp = mp->next ) {
	if ( strcmp(mp->mac,prc) == 0 )
	    return mp->str;
    }
    return "";
}
void	prcset(char *prc,char *str)
{
    int    hs;
    register MACRO *mp;

    hs = HASH(prc);
    for ( mp = topprc[hs] ; mp != NULL ; mp = mp->next ) {
	if ( strcmp(mp->mac,prc) == 0 ) {
	    free(mp->str);
	    mp->str = strdup(str);
	    return;
	}
    }
    if ( (mp = (MACRO *)malloc(sizeof(MACRO))) != NULL ) {
	mp->next = topprc[hs];
	topprc[hs] = mp;
	mp->mac = strdup(prc);
	mp->str = strdup(str);
    }
}
char    *macget(char *mac)
{
    register MACRO *mp;

    for ( mp = topmac[HASH(mac)] ; mp != NULL ; mp = mp->next ) {
	if ( strcmp(mp->mac,mac) == 0 )
	    return mp->str;
    }
    return "";
}
void    macset(char *mac,char *str)
{
    int     hs;
    register MACRO *mp;

    hs = HASH(mac);
    for ( mp = topmac[hs] ; mp != NULL ; mp = mp->next ) {
	if ( strcmp(mp->mac,mac) == 0 ) {
	    free(mp->str);
	    mp->str = strdup(str);
	    return;
	}
    }
    if ( (mp = (MACRO *)malloc(sizeof(MACRO))) != NULL ) {
	mp->next = topmac[hs];
	topmac[hs] = mp;
	mp->mac = strdup(mac);
	mp->str = strdup(str);
    }
}
void	macvalset(char *mac,int val)
{
    char    tmp[16];

    sprintf(tmp,"%d",val);
    macset(mac,tmp);
}
int	macval(char *mac)
{
    return atoi(macget(mac));
}
char	*cutpara(char *arg,char *str)
{
    int     n=0,len=0;

    *arg = '\0';
    if ( *str != '(' )
	return str;
    while ( len < (BUFSIZ - 2) && *(++str) != '\0' ) {
	if ( iskan(str) ) {
	    *(arg++) = *(str++);
	    *(arg++) = *str;
	    len += 2;
	} else if ( *str == '(' ) {
	    *(arg++) = *str;
	    n++;
	    len++;
	} else if ( *str == ')' && --n < 0 ) {
	    str++;
	    break;
	} else {
	    *(arg++) = *str;
	    len++;
	}
    }
    *arg = '\0';
    return str;
}
char	*cutcmds(char *str)
{
    int     n;

    if ( *(str++) != '{' )
	return NULL;
    for ( n = 0 ; *str != '\0' ; str++ ) {
	if ( iskan(str) )
	    str++;
	else if ( *str == '{' )
	    n++;
	else if ( *str == '}' && --n < 0 )
	    return str;
    }
    return NULL;
}
char	*get_str(char *buf,char *str)
{
    int     n,len=0;
    char    *p;
    char    dmy[BUFSIZ];

    while ( len < (BUFSIZ - 2) && *str != '\0' ) {
	if ( *str == '\\' ) {
	    str++;
	    switch(*(str++)) {
	    case 'n':
		*(buf++) = 0x0D;
		*(buf++) = 0x0A;
		len += 2;
		break;

	    case 'r':
		*(buf++) = 0x0D;
		len++;
		break;

	    case 't':
		*(buf++) = 0x09;
		len++;
		break;

	    case 'b':
		*(buf++) = 0x08;
		len++;
		break;

	    case 'c':
		*(buf++) = 0x0C;
		len++;
		break;

	    case 'x':
		n = 0;
		while ( *str != '\0' ) {
		    if ( isdigit(*str) )
			n = n * 16 + (*str - '0');
		    else if ( *str >= 'A' && *str <= 'F' )
			n = n * 16 + (*str - 'A') + 10;
		    else if ( *str >= 'a' && *str <= 'f' )
			n = n * 16 + (*str - 'a') + 10;
		    else
			break;
		    str++;
		}
		*(buf++) = n;
		len++;
		break;

	    case '(':
		for ( p = dmy ; *str != '\0' ; ) {
		    if ( *str == ')' ) {
			str++;
			break;
		    }
		    *(p++) = *(str++);
		}
		*p = '\0';
		p = macget(dmy);
		while ( len < (BUFSIZ - 2) && *p != '\0' ) {
		    *(buf++) = *(p++);
		    len++;
		}
		break;

	    default:
		if ( *(str-1) == '0' ) {
		    n = 0;
		    while ( *str >= '0' && *str <= '7' )
			n = n * 8 + (*(str++) - '0');
		    *(buf++) = n;
		} else if ( isdigit(*(str-1)) ) {
		    n = 0; str--;
		    while ( isdigit(*str) )
			n = n * 10 + (*(str++) - '0');
		    *(buf++) = n;
		} else
		    *(buf++) = *(str-1);
		len++;
		break;
	    }
	} else if ( *str == '"' ) {
	    str++;
	    break;

	} else if ( iskan(str) ) {
	    *(buf++) = *(str++);
	    *(buf++) = *(str++);
	    len += 2;

	} else {
	    *(buf++) = *(str++);
	    len++;
	}
    }
    *buf = '\0';
    return str;
}
char	*get_para(int *mode,int *no,char *tmp,char *str)
{
    int     n;

    *tmp = '\0';
    *mode = (-1);

    if ( *str == '"' ) {
	str = get_str(tmp,++str);
	*mode = 0;

    } else if ( *str == '0' ) {
	n = 0;
	if ( *(++str) == 'x' ) {
	    str++;
	    while ( *str != '\0' ) {
		if ( isdigit(*str) )
		    n = n * 16 + (*str - '0');
		else if ( *str >= 'A' && *str <= 'F' )
		    n = n * 16 + (*str - 'A') + 10;
		else if ( *str >= 'a' && *str <= 'f' )
		    n = n * 16 + (*str - 'a') + 10;
		else
		    break;
		str++;
	    }

	} else {
	    while ( *str >= '0' && *str <= '7' )
		n = n * 8 + (*(str++) - '0');
	}
	*mode = 1;

    } else if ( isdigit(*str) ) {
	n = 0;
	do {
	    n = n * 10 + (*(str++) - '0');
	} while ( isdigit(*str) );
	*mode = 1;
	
    } else {
	str = get_word(tmp,str);
	*mode = 2;
    }

    *no = n;

    return str;
}
char	*get_string(char *tmp,char *str)
{
    int     n;

    *tmp = '\0';

    if ( *str == '"' ) {
	str = get_str(tmp,++str);

    } else if ( *str == '0' ) {
	n = 0;
	if ( *(++str) == 'x' ) {
	    str++;
	    while ( *str != '\0' ) {
		if ( isdigit(*str) )
		    n = n * 16 + (*str - '0');
		else if ( *str >= 'A' && *str <= 'F' )
		    n = n * 16 + (*str - 'A') + 10;
		else if ( *str >= 'a' && *str <= 'f' )
		    n = n * 16 + (*str - 'a') + 10;
		else
		    break;
		str++;
	    }

	} else {
	    while ( *str >= '0' && *str <= '7' )
		n = n * 8 + (*(str++) - '0');
	}
	sprintf(tmp,"%d",n);

    } else if ( isdigit(*str) ) {
	n = 0;
	do {
	    n = n * 10 + (*(str++) - '0');
	} while ( isdigit(*str) );
	sprintf(tmp,"%d",n);

    } else {
	str = get_word(tmp,str);
	strcpy(tmp,macget(tmp));
    }

    return str;
}
int     cmp_func(char *str)
{
    int     ch,cd;
    int     no1,no2;
    int     md1,md2;
    char    para1[BUFSIZ];
    char    para2[BUFSIZ];

    md1 = md2 = (-1);

    str = get_para(&md1,&no1,para1,str);
    if ( (ch = *str) != '\0' )
	str = get_para(&md2,&no2,para2,++str);

    switch(md1) {
    case (-1):
	cd = ERR;
	break;
    case 0:
	switch(md2) {
	case (-1): cd = strlen(para1); break;
	case 0:    cd = strcmp(para1,para2); break;
	case 1:    cd = atoi(para1) - no2; break;
	case 2:    cd = strcmp(para1,macget(para2)); break;
	}
	break;
    case 1:
	switch(md2) {
	case (-1): cd = no1; break;
	case 0:    cd = no1 - atoi(para2); break;
	case 1:    cd = no1 - no2; break;
	case 2:    cd = no1 - atoi(macget(para2)); break;
	}
	break;
    case 2:
	switch(md2) {
	case (-1): cd = strlen(macget(para1)); break;
	case 0:    cd = strcmp(macget(para1),para2); break;
	case 1:    cd = atoi(macget(para1)) - no2; break;
	case 2:    cd = strcmp(macget(para1),macget(para2)); break;
	}
	break;
    }

    switch(ch) {
    case '=': case '\0':
	return (cd == 0);
    case '!':
	return (cd != 0);
    case '<':
	return (cd < 0);
    case '>':
	return (cd > 0);
    }
    return FALSE;
}
void	MSG_event(EVENT *ep)
{
    switch(ep->now) {

    case EVT_CLIP_MOS:
	EVT_clip_on(ep);
    case EVT_ON_MOS:
	DSP_mos(1);
	break;

    case EVT_SELECT_MOS:
	msg_event = ep->no;
    case EVT_DOLACK_MOS:
	ep->now = EVT_NON;
    case EVT_MOVE_MOS:
	EVT_clip_off(ep);
    case EVT_OFF_MOS:
	DSP_mos(0);
	break;
    }
}
void	MOS_push(int x1,int y1,int x2,int y2)
{
    static int sw,x,y;

    if ( x1 != ERR ) {
	MOS_rdpos(&sw,&x,&y);
	MOS_horizon(x1,x2-8);
	MOS_vertical(y1,y2-8);
    } else {
	MOS_horizon(0,632);
	MOS_vertical(0,470);
	MOS_setpos(x,y);
    }
}
int	MSG_pause(int fg)
{
    unsigned ec;

    EVT_sw(YES_X,YES_Y," Y E S ",COL_CHR,msg_bak,500,MSG_event,TRUE);
    if ( fg != FALSE )
	EVT_sw(NO_X,NO_Y,"  N O  ",COL_CHR,msg_bak,500,MSG_event,FALSE);

    MOS_disp(TRUE);

    if ( fg != FALSE ) {
	MOS_push(YES_X,YES_Y,NO_X+48,YES_Y+8);
	MOS_setpos(NO_X-8,YES_Y+2);
    } else {
	MOS_push(YES_X,YES_Y,YES_X+48,YES_Y+8);
	MOS_setpos(YES_X+28,YES_Y+2);
    }

    key_in();		/* key buffer clear */
    key_out();

    for ( msg_event = ERR ; msg_event == ERR ; ) {
	EVT_loop(500);
	if ( kbhit() != FALSE ) {
	    getkey(&ec); ec &= 0xFF00;
	    if ( ec == 0x7300 )
		msg_event = TRUE;
	    else if ( ec == 0x7200 )
		msg_event = FALSE;
	}
    }
    EVT_level_free(500);

    MOS_disp(FALSE);
    MOS_push(ERR,ERR,ERR,ERR);
    DSP_xline(YES_X,YES_Y,NO_X+60,NO_Y+12,msg_bak,0);

    return msg_event;
}
int	MENU_tate(int x,int y,int col,char *argv[])
{
    int    i,n,max;
    BLOCK  *save;

    for ( max = 0 ; argv[max] != NULL ; max++ );

    i = x+strlen(argv[0])*8+8;
    n = y+max*22;

    MOS_disp(FALSE);
    MOS_push(x,y,i,n);
    MOS_setpos((x+i)/2,(y+n)/2);
    save = DSP_push_vram(x,y,i,n);
    DSP_box(x,y,i,n,COL_LINE,col);

    for ( i = 0 ; i < max ; i++ )
	EVT_big_sw(x+2,y+i*22+2,argv[i],COL_CHR,col,500,MSG_event,i);

    MOS_disp(TRUE);
    msg_event = ERR;

    while ( msg_event == ERR )
	EVT_loop(500);

    EVT_level_free(500);
    MOS_disp(FALSE);
    MOS_push(ERR,ERR,ERR,ERR);
    DSP_pop_vram(save);

    return msg_event;
}
int	MENU_state(int x,int y,int col,char *argv[])
{
    int    i,n,max;
    BLOCK  *save;

    for ( max = 0 ; argv[max] != NULL ; max++ );

    i = x+strlen(argv[0])*8+8;
    n = y+max*14+1;

    MOS_disp(FALSE);
    MOS_push(x,y,i,n);
    MOS_setpos((x+i)/2,(y+n)/2);
    save = DSP_push_vram(x,y,i,n);
    DSP_box(x,y,i,n,COL_LINE,col);

    for ( i = 0 ; i < max ; i++ )
	EVT_sw(x+2,y+i*14+2,argv[i],COL_CHR,col,500,MSG_event,i);

    MOS_disp(TRUE);
    msg_event = ERR;

    while ( msg_event == ERR )
	EVT_loop(500);

    EVT_level_free(500);
    MOS_disp(FALSE);
    MOS_push(ERR,ERR,ERR,ERR);
    DSP_pop_vram(save);

    return msg_event;
}
int	MENU_syoko(int x,int y,int col,char *argv[])
{
    int    i,n,max,len;
    BLOCK  *save;

    for ( max = 0 ; argv[max] != NULL ; max++ );

    len = strlen(argv[0]);
    i = x+(len*8+6)*max+3;
    n = y+15;

    MOS_disp(FALSE);
    MOS_push(x,y,i,n);
    MOS_setpos((x+i)/2,(y+n)/2);
    save = DSP_push_vram(x,y,x+(len*8+6)*max+3,y+15);
    DSP_box(x,y,x+(len*8+6)*max+3,y+15,COL_LINE,col);

    for ( i = 0 ; i < max ; i++ )
	EVT_sw(x+(len*8+6)*i+2,y+2,argv[i],COL_CHR,col,500,MSG_event,i);

    MOS_disp(TRUE);
    msg_event = ERR;

    while ( msg_event == ERR )
	EVT_loop(500);

    EVT_level_free(500);
    MOS_disp(FALSE);
    MOS_push(ERR,ERR,ERR,ERR);
    DSP_pop_vram(save);

    return msg_event;
}
char	*MSG_getstr(int x,int y,int col,int bak,char *str,int max)
{
    int     i,n,ch,fg;
    int     ofs=0,len=0,pos=0;
    BLOCK   *save;
    char    *p;
    char    dmy[84];
    static char tmp[84];

    cur_x = x;
    cur_y = y;
    key_in();
    fg = macval("NOECHO");

    if ( str != NULL ) {
	strcpy(tmp,str);
	if ( (pos = len = strlen(str)) > 80 )
	    pos = len = 80;
    }

    for ( ch = 0 ; ; ) {

	tmp[len] = '\0';

	ofs = 0;
	n = pos;
	while ( n >= (max - 4) ) {
	    ofs += (max / 2);
	    ofs = kan_pos(tmp,ofs);
	    n = pos - ofs;
	}

	if ( (i = len - ofs) >= max )
	    i = kan_pos(tmp,ofs+max) - ofs;

	if ( fg == FALSE )
	    strncpy(dmy,&(tmp[ofs]),i);
	else
	    memset(dmy,'*',i);

	dmy[i] = '\0';

        save = DSP_push_vram(x,y,x+(i+3)*8,y+15);
        wrtstr(dmy,page_ofs,x/2+y*512,
		col_cnv[col],col_cnv[bak],16);
	DSP_xline(x+n*8,y+14,x+n*8+7,y+15,15,4);

	cur_x = x + n * 8;

	while ( (ch = getch()) == 0xFFFF );

	do {

	    if ( ch == 0x08 && pos > 0 ) {
		pos = kan_pos(tmp,pos-1);
		p = &(tmp[pos]);
		n = (iskan(p) ? 2:1);
		strcpy(p,p+n);
		len -= n;

	    } else if ( ch == 0x7F ) {
		if ( pos < len ) {
		    p = &(tmp[pos]);
		    n = (iskan(p) ? 2:1);
		    strcpy(p,p+n);
		    len -= n;
		}

	    } else if ( ch == 0x1C ) {
		if ( pos < len )
		    pos += (iskan(&(tmp[pos])) ? 2:1);

	    } else if ( ch == 0x1D ) {
		if ( pos > 0 )
		    pos = kan_pos(tmp,pos-1);

	    } else if ( ch >= ' ' && len < 80 ) {
		if ( pos < len ) {
		    p = &(tmp[len]);
		    for ( i = len - pos ; i > 0 ; i--,p-- )
			*p = *(p-1);
		}
		tmp[pos++] = ch;
		len++;

	    } else if ( ch == 0x0D ) {
		msg_sts = FALSE;
		goto ENDOF;
	    } else if ( ch == 0x1B ) {
		msg_sts = ERR;
		goto ENDOF;
	    }

	} while ( (ch = getch()) != 0xFFFF );

        DSP_pop_vram(save);
    }

ENDOF:
    DSP_pop_vram(save);
    tmp[len] = '\0';
    key_out();
    return tmp;
}
int	MSG_open_wind(void)
{
    if ( msg_open_flg == FALSE ) {
	msg_save = DSP_push_vram(MSG_X1,MSG_Y1,MSG_X2,MSG_Y2);
	DSP_rbox(MSG_X1,MSG_Y1,MSG_X2,MSG_Y2,msg_lin,msg_lin2,msg_bak);
	msg_open_flg = TRUE;
    }
    return TRUE;
}
int	MSG_close_wind(void)
{
    if ( msg_open_flg != FALSE )
	DSP_pop_vram(msg_save);
    msg_open_flg = FALSE;
    msg_len = msg_ox = msg_x = msg_y = 0;
    return FALSE;
}
void	MSG_flush(void)
{
    if ( msg_x == msg_ox )
	return;

    MSG_open_wind();

    msg_buf[msg_x] = '\0';
    wrtstr(&msg_buf[msg_ox],
	page_ofs,(MSG_X1+msg_ox*8+8)/2+(MSG_Y1+msg_y*18+8)*512,
	col_cnv[msg_col],col_cnv[msg_bak],16);
    msg_ox = msg_x;
}
void	MSG_putc(char ch)
{
    msg_buf[msg_x++] = ch;
    if ( msg_x >= MSG_LEN ) {
	MSG_flush();
	msg_ox = msg_x = 0;
	msg_y++;
    }
}
void	MSG_puts(char *str)
{
    int     n;

    while ( *str != '\0' ) {
	switch(*str) {
	case 0x0D:
	    MSG_flush();
	    msg_ox = msg_x = 0;
	    break;

	case 0x0A:
	    MSG_flush();
	    msg_y++;
	    break;

	case 0x08:
	    MSG_flush();
	    msg_ox = msg_x = msg_x - 1;
	    break;

	case 0x09:
	    n = msg_tab - (msg_x % msg_tab);
	    while ( n-- > 0 )
	        MSG_putc(' ');
	    break;	

	case 0x0C:
	    if ( msg_open_flg != FALSE )
		DSP_rbox(MSG_X1,MSG_Y1,MSG_X2,MSG_Y2,msg_lin,msg_lin2,msg_bak);
	    msg_ox = msg_x = msg_y = 0;
	    break;	

	default:
	    MSG_putc(*str);
	    break;
	}
	str++;
    }
    MSG_flush();
}
int	MSG_echo(char *argv[])
{
    while ( *argv != NULL )
	MSG_puts(*(argv++));
    return FALSE;
}
int	MSG_input(char *argv[])
{
    char    *p;

    while ( *argv != NULL ) {
	p = MSG_getstr(MSG_X1+msg_ox*8+8,MSG_Y1+msg_y*18+8,
			msg_col,msg_bak,macget(*argv),MSG_LEN-msg_ox);
	macset(*(argv++),p);
    }
    return msg_sts;
}
int	MSG_yes(char *argv[])
{
    int     cd;

    cd = MSG_pause(FALSE);
    while ( *argv != NULL )
        macvalset(*(argv++),cd);
    return cd;
}
int	MSG_yesno(char *argv[])
{
    int     cd;

    cd = MSG_pause(TRUE);
    while ( *argv != NULL )
        macvalset(*(argv++),cd);
    return cd;
}
int	MSG_color(char *argv[])
{
    int     n;

    if ( (n = atoi(*argv)) != 0 )
	msg_col = n;
    return n;
}
int	MSG_bakcol(char *argv[])
{
    int     n;

    if ( (n = atoi(*argv)) != 0 )
	msg_bak = n;
    return n;
}
int	MSG_lincol(char *argv[])
{
    int     n;

    if ( (n = atoi(*argv)) != 0 ) {
	msg_lin = n | 8;
	msg_lin2 = n;
    }
    return n;
}
int	TAB_set(char *argv[])
{
    msg_tab = atoi(argv[0]);
    return msg_tab;
}
int	MSG_ext_cfg(char *argv[])
{
    return MSG_cfg_load(*argv);
}
int	MSG_menu_tate(char *argv[])
{
    return MENU_tate(atoi(argv[0]),atoi(argv[1]),atoi(argv[2]),&(argv[3]));
}
int	MSG_menu_state(char *argv[])
{
    return MENU_state(atoi(argv[0]),atoi(argv[1]),atoi(argv[2]),&(argv[3]));
}
int	MSG_menu_syoko(char *argv[])
{
    return MENU_syoko(atoi(argv[0]),atoi(argv[1]),atoi(argv[2]),&(argv[3]));
}
int	MSG_system(char *argv[])
{
    int    rc;
    BLOCK  *save;

    save = DSP_push_vram(0,0,639,479);
    KAN_close();
    CON_open(999);
    rc = system(*argv);
    CON_close();
    DSP_reinit();
    DSP_pop_vram(save);
    KAN_KAN_open();
    return rc;
}
int	equl(char *ptn,char *str)
{
    while ( *ptn != '\0' ) {
	if ( *ptn != toupper(*str) )
	    return FALSE;
	ptn++;
	str++;
    }
    return (*str == '\0' ? TRUE:FALSE);
}
int	MSG_command(char *argv[])
{
    int    ch,ofs=0;
    unsigned ec;
    BLOCK  *save;
    char   *p;
    char   tmp[BUFSIZ];

    save = DSP_push_vram(0,0,639,479);
    CON_open(atoi(argv[0]));
    key_in();

    getdir(tmp);
    if ( (p = strrchr(tmp,'\\')) != NULL ) *p = '\0';
    printf("%s> ",tmp);
    for ( ; ; ) {
	while ( kbhit() == 0 );

	ch = getkey(&ec);
	ec &= 0xFF14;
	if ( ec == 0x6E00 ) {
	    ofs += 5;
	    ofs = CON_redisp(ofs);

	} else if ( ec == 0x7000 ) {
	    if ( ofs > 0 ) {
		ofs -= 5;
	        ofs = CON_redisp(ofs);
	    }

	} else if ( ch != 0xFFFF ) {
	    if ( ofs > 0 ) {
		ofs = 0;
		CON_redisp(ofs);
	    }
	    if ( (p = CON_input(ch)) != NULL ) {
		if ( *p == '\x1B' || equl("EXIT",p) ) {
		    printf("\n");
		    goto ENDOF;
		} else if ( *p != '\0' ) {
		    system(p);
		    printf("\n");
		}
		getdir(tmp);
		if ( (p = strrchr(tmp,'\\')) != NULL ) *p = '\0';
		printf("%s> ",tmp);
	    }
	}
    }

ENDOF:
    key_out();
    CON_close();
    DSP_pop_vram(save);
    return FALSE;
}
int	MSG_wind(char *str)
{
    int     cd;

    str = prcget(str);

    if ( str == NULL || *str == '\0' )
	return ERR;

    MOS_disp(FALSE);
    mos_lock = TRUE;
    msg_open_flg = FALSE;

    msg_ox = msg_x = msg_y = 0;
    msg_lin = 7;
    msg_lin2 = 8;
    msg_col = 15;
    msg_event = ERR;

    cd = MSG_run(str);

    MSG_close_wind();

    MOS_disp(TRUE);
    mos_lock = FALSE;

    return cd;
}
int	MSG_cfg_load(char *file)
{
    int     n,nest=0;
    int     fun_flg = FALSE;
    FILE    *fp;
    char    *p,*s,*t;
    char    tmp[BUFSIZ];
    char    dmy[BUFSIZ];

    if ( (fp = fopen(file,"r")) == NULL )
	return ERR;

    while ( (p = fgets(tmp,BUFSIZ,fp)) != NULL ) {

	if ( (t = strrchr(p,'\n')) != NULL )
	    *t = '\0';
LOOP:
	while ( isspace(*p) ) p++;

	if ( *p == '#' || *p == '\0' )
	    continue;

	if ( fun_flg == FALSE ) {

	    if ( *p == '.' ) {			/* edit key defs */
		n = htoi(p+1);
		if ( (p = strchr(p,'=')) == NULL )
		    continue;
		for ( p++ ; isspace(*p) ; p++ );
		p = get_word(dmy,p);
		EDIT_KEY_set(n,dmy);
		continue;

	    } else if ( *p == '^' ) {		/* term key defs */
		n = htoi(p+1);
		if ( (p = strchr(p,'=')) == NULL )
		    continue;
		for ( p++ ; isspace(*p) ; p++ );
		p = get_word(dmy,p);
		TERM_KEY_set(n,dmy);
		continue;
	    }

	    p = get_word(dmy,p);

	    if ( dmy[0] == '\0' )
		continue;

	    while ( isspace(*p) ) p++;

	    if ( *p == '=' ) {
		p++;
		while ( isspace(*p) ) p++;
		macset(dmy,p);
		continue;

	    } else if ( *p == '{' ) {
		p++;
		while ( isspace(*p) ) p++;
		s = func_ptr;
		nest = 0;
		fun_flg = TRUE;

	    } else
		continue;
	}

	while ( *p != '\0' ) {
	    if ( *p == '#' )
		break;
	    else if ( *p == '{' )
		nest++;
	    else if ( *p == '}' && nest-- <= 0 ) {
		*s = '\0';
		prcset(dmy,func_ptr);
		fun_flg = FALSE;
		goto LOOP;

	    } else if ( *p == '"' ) {
		do {
		    if ( iskan(p) ) {
			if ( s < &func_buf[FUNC_MAX-2] )
			    *(s++) = *p;
			p++;
		    }
		    if ( s < &func_buf[FUNC_MAX-2] )
			*(s++) = *p;
		    p++;
		} while ( *p != '\0' && *p != '"' );

	    } else if ( iskan(p) ) {
		if ( s < &func_buf[FUNC_MAX-2] )
		    *(s++) = *p;
		p++;
	    }

	    if ( s < &func_buf[FUNC_MAX-2] )
		*(s++) = *p;
	    p++;

	    while ( isspace(*p) ) p++;
	}
    }

    fclose(fp);
    return FALSE;
}
int	MSG_init(char *file,char *user)
{
    time_t  t;
    struct tm *tp;
    char    *p;
    char    tmp[80];

    time(&t);
    tp = localtime(&t);
    sprintf(msg_buf,"%02d/%02d/%02d",tp->tm_year,tp->tm_mon+1,tp->tm_mday);
    macset("DATE",msg_buf);
    sprintf(msg_buf,"%02d/%02d",tp->tm_mon+1,tp->tm_mday);
    macset("TODAY",msg_buf);
    sprintf(msg_buf,"%02d:%02d:%02d",tp->tm_hour,tp->tm_min,tp->tm_sec);
    macset("TIME",msg_buf);

    if ( file == NULL )
	getdir(tmp);
    else {
	strcpy(tmp,file);
	strcat(tmp,"\\");
    }

    macset("HOME",tmp);
    sprintf(msg_buf,"%sWHISPER.CFG",tmp);
    macset("SYSCFG",msg_buf);
    sprintf(msg_buf,"%s%s.USR",tmp,(user == NULL ? "NONAME":user));
    macset("USRCFG",msg_buf);

    if ( MSG_cfg_load(macget("SYSCFG")) != FALSE )
	return ERR;

    macset("KEYWORD","WHISPER");
    if ( (p = secret_file(macget("USRCFG"))) != NULL ) {
	MSG_cfg_load(p);
	remove(p);
    }
    macset("KEYWORD","");
    return FALSE;
}
void	MSG_end(void)
{
    int     i;
    char    *file;
    FILE    *fp;
    MACRO   *mp;

    file = macget("USRCFG");
    if ( (fp = fopen(file,"w")) == NULL )
	return;

    fprintf(fp,"NAME = %s\n",macget("NAME"));
    fprintf(fp,"BASDAY = %s\n",macget("BASDAY"));
    fprintf(fp,"LEVEL = %s\n",macget("LEVEL"));
    fprintf(fp,"ACOUNT = %s\n",macget("ACOUNT"));
    fprintf(fp,"FDATE = %s\n",macget("FDATE"));
    fprintf(fp,"LDATE = %s\n",macget("DATE"));
    fprintf(fp,"\n");

    for ( i = 0 ; i < HASH_MAX ; i++ ) {
	for ( mp = topmac[i] ; mp != NULL ; mp = mp->next ) {
	    if ( *(mp->mac) == '_' )
		fprintf(fp,"%s = %s\n",mp->mac,mp->str);
	}
    }

    fclose(fp);
    macset("KEYWORD","WHISPER");
    keyword(file,0);
}
