/*
    input subroutine
		key_in  :  key board input (encode mode)
					up, down, right, left key & ESC key
		mouse_in:  mouse input
					left, right bottan
		pad_in  :  pad input
					A, B trigger, up, down, right, left key & RUN, SEL trigger
		menuread:  menu display and select
					panel display, panel read call

                      1993.6.27 v1.0
                      copyright Y.Ouchi

*/

#include	<string.h>
#include	<register.h>
#include	"mos.h"
#include	"snd.h"
#include	"egb.h"
#include	"bb.h"

extern	char	moswork[];
extern	char	egbwork[1536];

	/* 関数プロトタイプ宣言 */
int		intreal(int, union REGS *, union REGS *, struct SREGS *);

extern	void	box(int, int, int, int, int, int);
extern	void	linedsp(int, int, char *);
extern	void	linedspv(int, int, char *, int, unsigned int, unsigned int);

static	char	*menutable[16]={"先頭テキスト",
							"最終テキスト",
							"会議室一覧",
							"タイトル一覧",
							"終了",
							"モード変更",
							"別ファイル",
							"ログ更新",
							"コンソール",
							"","","","",""};
/*
static	char	*menutable[16]={"NEXT TITLE",
							"PREVIOUS TITLE",
							"TOP TEXT",
							"LAST TEXT",
							"LOG UPDATE & QUIT",
							"QUIT",
							"TITLE MODE",
							"NEW FILE",
							"MODE CHANGE",
							"CONSOLE",
							"COMF TITLE","","","","",""};
*/
#define	MENU_NO			8
#define	MENU_DEFLT		4

/*
    key input (real interupt) .. encode mode
        return code 0 : no input
                    1 : ESC key
                    2 : down key
                    3 : up key
                    4 : right key
                    5 : left key
                    6 : CR key
                    7 : 取消 key
*/
int	key_in(void)
{
union	REGS	in;
struct	SREGS	seg;

		int		endcode;
		char	code;

					/* key board status check */
	in.h.ah = 0x09;
	in.h.al = 0x01;
	intreal(0x90, &in, &in, &seg);
	if (in.h.dh == 0xff)	code = 0x00;
	else	code = in.h.dl;

	switch ( code ){
		case 0 :
			endcode=0;
			break;
		case 0x1c :			/* righy arrow */
			endcode=4;
			break;
		case 0x1d :			/* left  arrow */
			endcode=5;
			break;
		case 0x1e :			/* up    arrow */
			endcode=3;
			break;
		case 0x1f :			/* down  arrow */
			endcode=2;
			break;
		case 0x1b :			/* ESC key */
			endcode=1;
			break;
		case 0x0d :			/* CR key (実行 key on cosole) */
			endcode=6;
			break;
		case 0x12 :			/* 実行 key (TOWNS OS) */
			endcode=6;
			break;
		case 0x11 :			/* 取消 key  (TOWNS OS) */
			endcode=7;
			break;
		case 0x18 :			/* 取消 key  (console) */
			endcode=7;
			break;
		default :
			endcode=0;
			break;
	}
	return ( endcode );
}



/*
    mouse input
        return code 0 : no action
                    1 : right bottan
                    2 : left bottan
                    3 : both bottan
                    &x: x posision
                    &y: y posision
*/
int	mouse_in(int *xpos, int *ypos)
{
		char	para[20];
		int		x,y;
		int		i,endcode=0;
		int		botan_state;
static	int		old_botan_state=0;

					/* mouse status check */
	MOS_rdpos(&botan_state,&x,&y);
	if ( botan_state != old_botan_state ) {
		for (i=0;i<CLICK_TIMING;i++) {
			WORD(para+0)=0;
			EGB_palette(egbwork,1,para);
		}
		MOS_rdpos(&botan_state,&x,&y);
		switch ( botan_state ){
			case 3 :		/* both bottan push */
				endcode=3;
				break;
			case 1 :		/* left bottan push */
				endcode=2;
				break;
			case 2 :		/* right bottan push */
				endcode=1;
				break;
		}
		old_botan_state=botan_state;
	}
	else endcode=0;
	*xpos=x;
	*ypos=y;

	return ( endcode ) ;
}


/*
    pad input
        return code 0 : no action
                    1 : A trigger
                    2 : B trigger
                    3 : down key
                    4 : up key
                    5 : right key
                    6 : left key
                    7 : RUN key
                    8 : SELECT key
*/
int	pad_in(void)
{
		int		padstate,pad0out,pad1out;
		int		endcode=0;
static	int		padold=0x3f;
static	int		repeat_count=200;

					/* joy pad status check */
	SND_joy_out(0x13, &pad0out, &pad1out);
	padstate=pad0out & 0x3f;

	if ( padstate != 0x3f ){
		if (padstate!=padold){
			padold=padstate;
			switch ( padstate ^ 0x3f ){
				case 0x10:		/* pad A key  */
					endcode=1;
					break;
				case 0x20:		/* pad B key */
					endcode=2;
					break;
				case 0x02:		/* down key  */
					endcode=3;
					break;
				case 0x01:		/* up key    */
					endcode=4;
					break;
				case 0x08:		/* right key */
					endcode=5;
					break;
				case 0x04:		/* left key  */
					endcode=6;
					break;
				case 0x0c:		/* run key   */
					endcode=7;
					break;
				case 0x03:		/* select key */
					endcode=8;
					break;
			}
		}
		else{
			endcode=0;
			if (--repeat_count==0){
				padold=0x3f;
				repeat_count=200;
			}
		}
	}
	else{
		padold=0x3f;
		endcode=0;
	}

	return ( endcode ) ;
}



/*
    直線の描画
*/
void line(int x1, int y1, int x2, int y2, int col)
{
    char para[12];

    EGB_color(egbwork, 0, col);
    WORD(para + 0) = 2;
    WORD(para + 2) = x1;
    WORD(para + 4) = y1;
    WORD(para + 6) = x2;
    WORD(para + 8) = y2;
    EGB_connect(egbwork, para);
}

/*
    ボタンの描画
*/
void bottan(int sx, int sy, int ex, int ey)
{
    box(sx, sy, ex, ey, BOTAN_COL,1);
    line(sx, sy, sx, ey, HILIGHT);
/*    line(sx + 1, sy + 1, sx + 1, ey - 1, HILIGHT);*/
    line(sx, sy, ex, sy, HILIGHT);
/*    line(sx + 1, sy + 1, ex - 1, sy + 1, HILIGHT);*/
    line(sx, ey, ex, ey, SHADOW);
/*    line(sx + 1, ey - 1, ex - 1, ey - 1, SHADOW);*/
    line(ex, sy, ex, ey, SHADOW);
/*    line(ex - 1, sy + 1, ex - 1, ey - 1, SHADOW);*/
/*    line(sx, sy, sx + 1, sy + 1, SHADOW);*/
    line(sx, sy, sx, sy, SHADOW);
/*    line(ex, ey, ex - 1, ey - 1, HILIGHT);*/
    line(ex, ey, ex, ey, HILIGHT);
}

/*
    ボタン押下の描画
*/
void bpush(int sx, int sy, int ex, int ey)
{
    line(sx, sy, sx, ey, SHADOW);
/*    line(sx + 1, sy + 1, sx + 1, ey - 1, SHADOW);*/
    line(sx, sy, ex, sy, SHADOW);
/*    line(sx + 1, sy + 1, ex - 1, sy + 1, SHADOW);*/
    line(sx, ey, ex, ey, HILIGHT);
/*    line(sx + 1, ey - 1, ex - 1, ey - 1, HILIGHT);*/
    line(ex, sy, ex, ey, HILIGHT);
/*    line(ex - 1, sy + 1, ex - 1, ey - 1, HILIGHT);*/
/*    line(sx, sy, sx + 1, sy + 1, HILIGHT);*/
/*    line(ex, ey, ex - 1, ey - 1, SHADOW);*/
    line(sx, sy, sx, sy, HILIGHT);
    line(ex, ey, ex, ey, SHADOW);
}

/*
    ボタン開放の描画
*/
void bopen(int sx, int sy, int ex, int ey)
{
    line(sx, sy, sx, ey, HILIGHT);
/*    line(sx + 1, sy + 1, sx + 1, ey - 1, HILIGHT);*/
    line(sx, sy, ex, sy, HILIGHT);
/*    line(sx + 1, sy + 1, ex - 1, sy + 1, HILIGHT);*/
    line(sx, ey, ex, ey, SHADOW);
/*    line(sx + 1, ey - 1, ex - 1, ey - 1, SHADOW);*/
    line(ex, sy, ex, ey, SHADOW);
/*    line(ex - 1, sy + 1, ex - 1, ey - 1, SHADOW);*/
/*    line(sx, sy, sx + 1, sy + 1, SHADOW);*/
/*    line(ex, ey, ex - 1, ey - 1, HILIGHT);*/
    line(sx, sy, sx, sy, SHADOW);
    line(ex, ey, ex, ey, HILIGHT);
}

/*
    initial panel set
*/
void panelinit(int no, struct panel p[], char *s[], int cent)
{
	int i,j,k,n,sx,sy;

	for (n=0;n<no;n++){
		box (p[n].xpos,p[n].ypos,
				p[n].xpos+p[n].xsize-1,p[n].ypos+p[n].ysize-1,BOTAN_COL,1);
		i=j=k=0;
		for (i=0;i<p[n].ysize/p[n].ybtnsize;i++){
			for (j=0;j<p[n].xsize/p[n].xbtnsize;j++){
				sx=p[n].xpos+j*p[n].xbtnsize;
				sy=p[n].ypos+i*p[n].ybtnsize;
				bottan(sx,sy,sx+p[n].xbtnsize-1,sy+p[n].ybtnsize-1);
				EGB_color(egbwork, 0, BOTAN_TITLE_COL);
				if (cent==1){
					linedspv(sx+((p[n].xbtnsize-strlen(s[k])*8)/2),sy+18,s[k],
												0,BOTAN_TITLE_COL,BOTAN_COL);
				}
				else{
					linedspv(sx+2,sy+18,s[k],0,BOTAN_TITLE_COL,BOTAN_COL);
				}
				k++;
			}
		}
	}
}

/*
	menu panel posision check
*/
int		poscheck(int menuno, struct panel p[], int x, int y)
{
	int		digit;

	if (x>=p[menuno].xpos && x<p[menuno].xpos+p[menuno].xsize 
				&& y>=p[menuno].ypos && y<p[menuno].ypos+p[menuno].ysize){
		digit=(x-p[menuno].xpos)/p[menuno].xbtnsize
			+((y-p[menuno].ypos)/p[menuno].ybtnsize)
				*(p[menuno].xsize/p[menuno].xbtnsize) + p[menuno].ini_digit;
	}
	else digit=-1;
	return (digit);
}

/*
	which menu mouse cursol on check
*/
int		whichmenu(int no, struct panel p[], int x, int y)
{
	int		j;

	for ( j=0;j<no;j++ ){
		if (x>=p[j].xpos && x<p[j].xpos+p[j].xsize 
					&& y>=p[j].ypos && y<p[j].ypos+p[j].ysize){
			break;
		}
	}
	if ( j!=no ) return (j);
	else return (-1);
}



/*
    panel input read
		input	int no	:panel kind no
				struct panel[]	:panel format
				on		:cursol on response lag
		output	int		-1		: not on menu or cancel
						0..999	: on menu left bottan
					1000..1999	: on menu right bottan
					2000..2999	: on menu both bottan
*/
int  panelread(int no, struct panel p[], int on )
{
	int		i,j,var,x,y;
	int		sx,sy,digit,olddigit,flag;
	int		contflag;
	int		menuno;
	int		defbtnsize=20;

	flag = 1 ;
	while ( flag != 0 ){
		MOS_rdpos(&var,&x,&y);
		flag=var;
	}
	digit=olddigit=-1;

	contflag=1;
	while ( contflag ) {
		MOS_rdpos(&var,&x,&y);
		menuno=whichmenu(no,p,x,y);
		if ( on==1 ){
			if (menuno==-1) digit=-1;
			else digit=poscheck(menuno,p,x,y);
			if (digit!=olddigit){
				olddigit=digit;

				for (j=0;j<no;j++){
					if ( j==menuno ){
						for (i=0;i<((p[j].xsize/p[j].xbtnsize)
								*(p[j].ysize/p[j].ybtnsize));i++){
							if ((p[j].xpos+p[j].xbtnsize
										*(i%(p[j].xsize/p[j].xbtnsize)))<=x 
									&& (p[j].xpos+p[j].xbtnsize
										*(i%(p[j].xsize/p[j].xbtnsize))
										+p[j].xbtnsize)>x 
									&& (p[j].ypos+p[j].ybtnsize
										*(i/(p[j].xsize/p[j].xbtnsize)))<=y 
									&& (p[j].ypos+p[j].ybtnsize
										*(i/(p[j].xsize/p[j].xbtnsize))
										+p[j].ybtnsize)>y ){
								sx=p[j].xpos+(i%(p[j].xsize/p[j].xbtnsize))
											*p[j].xbtnsize;
								sy=p[j].ypos+(i/(p[j].xsize/p[j].xbtnsize))
											*p[j].ybtnsize;
								if ( p[j].ful==1 ){
									bpush(sx,sy,sx+p[j].xbtnsize-1,
												sy+p[j].ybtnsize-1);
								}
								else{
									box(sx,sy,sx+p[j].xbtnsize-1,
										sy+p[j].ybtnsize-1,BOTAN_FRAME_COL,0);
								}
							}
							else{
								sx=p[j].xpos+(i%(p[j].xsize/p[j].xbtnsize))
											*p[j].xbtnsize;
								sy=p[j].ypos+(i/(p[j].xsize/p[j].xbtnsize))
											*p[j].ybtnsize;
								if ( p[j].ful==1 ){
									bopen(sx,sy,sx+p[j].xbtnsize-1,
												sy+p[j].ybtnsize-1);
								}
								else{
									box(sx,sy,sx+p[j].xbtnsize-1,
										sy+p[j].ybtnsize-1,BACK_COL,0);
								}
							}
						}
					}
					else{
						for (i=0;i<((p[j].xsize/p[j].xbtnsize)
								*(p[j].ysize/p[j].ybtnsize));i++){
							sx=p[j].xpos+(i%(p[j].xsize/p[j].xbtnsize))
										*p[j].xbtnsize;
							sy=p[j].ypos+(i/(p[j].xsize/p[j].xbtnsize))
										*p[j].ybtnsize;
							if ( p[j].ful==1 ){
								bopen(sx,sy,sx+p[j].xbtnsize-1,
											sy+p[j].ybtnsize-1);
							}
							else{
								box(sx,sy,sx+p[j].xbtnsize-1,
									sy+p[j].ybtnsize-1,BACK_COL,0);
							}
						}
					}
				}
			}
		}

		if (menuno!=-1){
					/* mouse status check */
			switch (mouse_in(&x,&y)){
				case 1 :			/* right bottan */
					digit=poscheck(menuno,p,x,y);
					digit=digit+1000;
					contflag=0;
					break;
				case 2 :			/* left bottan  */
					digit=poscheck(menuno,p,x,y);
					contflag=0;
					break;
				case 3 :			/* both bottan  */
					digit=poscheck(menuno,p,x,y);
					digit=digit+2000;
					contflag=0;
					break;
				default : break;
			}

					/* key board status check */
			switch (key_in()){
				case 0 : break;		/* no input */
				case 1 :			/* ESC key  */
					digit=-1;
					contflag=0;
					break;
				case 2 :			/* down key */
					if ((j=whichmenu(no,p,x,y))!=-1) y=y+p[j].ybtnsize;
					else y=y+defbtnsize;
					MOS_setpos( x, y );
					break;
				case 3 :			/* up key   */
					if ((j=whichmenu(no,p,x,y))!=-1) y=y-p[j].ybtnsize;
					else y=y-defbtnsize;
					MOS_setpos( x, y );
					break;
				case 4 :			/* right key */
					if ((j=whichmenu(no,p,x,y))!=-1) x=x+p[j].xbtnsize;
					else x=x+defbtnsize;
					MOS_setpos( x, y );
					break;
				case 5 :			/* left key  */
					if ((j=whichmenu(no,p,x,y))!=-1) x=x-p[j].xbtnsize;
					else x=x-defbtnsize;
					MOS_setpos( x, y );
					break;
				case 6 :			/* CR/実行 key  */
					digit=poscheck(menuno,p,x,y);
					contflag=0;
					break;
				case 7 :			/* 取消 key  */
					digit=poscheck(menuno,p,x,y);
					digit=digit+1000;
					contflag=0;
					break;
				default : break;
			}

					/* joy pad status check */
			switch (pad_in()){
				case 0 : break;		/* no input  */
				case 1 :			/* A trigger */
					digit=poscheck(menuno,p,x,y);
					contflag=0;
					break;
				case 2 :			/* B trigger */
					digit=poscheck(menuno,p,x,y);
					digit=digit+1000;
					contflag=0;
					break;
				case 3 :			/* down key  */
					if ((j=whichmenu(no,p,x,y))!=-1) y=y+p[j].ybtnsize;
					else y=y+defbtnsize;
					MOS_setpos( x, y );
					break;
				case 4 :			/* up key    */
					if ((j=whichmenu(no,p,x,y))!=-1) y=y-p[j].ybtnsize;
					else y=y-defbtnsize;
					MOS_setpos( x, y );
					break;
				case 5 :			/* right key */
					if ((j=whichmenu(no,p,x,y))!=-1) x=x+p[j].xbtnsize;
					else x=x+defbtnsize;
					MOS_setpos( x, y );
					break;
				case 6 :			/* left key   */
					if ((j=whichmenu(no,p,x,y))!=-1) x=x-p[j].xbtnsize;
					else x=x-defbtnsize;
					MOS_setpos( x, y );
					break;
				case 7 :			/* RUN key   */
					digit=poscheck(menuno,p,x,y);
					digit=digit+2000;
					contflag=0;
					break;
				case 8 :			/* SELECT key   */
					digit=poscheck(menuno,p,x,y);
					digit=digit+2000;
					contflag=0;
					break;
				default : break;
			}
		}
	}
	return ( digit );
}

/*
	menu display and read
*/
int  menuread(void)
{
	int		i,endcode;
	struct	panel	n_menu[1];

	n_menu[0].xpos=PANEL_SX;
	n_menu[0].ypos=PANEL_SY;
	n_menu[0].xsize=BOTAN_X;
	n_menu[0].ysize=BOTAN_Y*MENU_NO;
	n_menu[0].xbtnsize=BOTAN_X;
	n_menu[0].ybtnsize=BOTAN_Y;
	panelinit(1,n_menu,menutable,1);
	MOS_horizon( PANEL_SX,PANEL_SX+BOTAN_X-1 );
	MOS_vertical( PANEL_SY,PANEL_SY+BOTAN_Y*MENU_NO-1 );
	MOS_setpos( PANEL_SX+BOTAN_X/2, PANEL_SY+BOTAN_Y*MENU_DEFLT+10 );
	MOS_disp( 1 );

	n_menu[0].xpos=PANEL_SX;
	n_menu[0].ypos=PANEL_SY;
	n_menu[0].xsize=BOTAN_X;
	n_menu[0].ysize=BOTAN_Y*MENU_NO;
	n_menu[0].xbtnsize=BOTAN_X;
	n_menu[0].ybtnsize=BOTAN_Y;
	n_menu[0].ful=1;
	n_menu[0].disp=1;
	n_menu[0].ini_digit=0;
	while ( (i = panelread (1, n_menu, 1)) >= 2000 );
	MOS_disp( 0 );

	if ( i<0 || i>=1000 ) endcode = -1;
	else{
		switch ( i ){
			case 0 :	/* top text */
				endcode=TOP_TEXT;
				break;
			case 1 :	/* last text */
				endcode=LAST_TEXT;
				break;
			case 2 :	/* conference title */
				endcode=CONF_TITLE;
				break;
			case 3 :	/* title mode */
				endcode=TITLE_MODE;
				break;
			case 4 :	/* quit */
				endcode=ALL_QUIT;
				break;
			case 5 :	/* mode change */
				endcode=MODE_CHG;
				break;
			case 6 :	/* new file select */
				endcode=NEW_FILE;
				break;
			case 7 :	/* log update & new file */
				endcode=SAVE_QUIT;
				break;
			case 8 :	/* console */
				endcode=CONSOLE;
				break;
			default :	/* no effect */
				endcode=-1;
				break;
		}
	}
	return (endcode);
}

