/****************************************************************************/
/* TEXT Title MENU SYSTEM for X68000 V1.7 Copyright (C) 1991-94 by AIG-SOFT*/
/****************************************************************************/
/* '94/02/21 V1.70 操作キー設定機能削除 */
/* '94/07/18 V1.71 細部修正 */

#include <stdio.h>
#include <stdlib.h>
#include "defines.h"
#include "menu.h"
#include "aigtext.h"
#include "ascreen.h"
#include "akey.h"
#include "skey.h"

static	unint	k2,k8;	/* テンキー移動モード */
static	unsint	Cno[9],Csep[9],Cmn[9];	/* 色コードバッファー */

/****************************************************************************/

static int key_play(int ky,int all,int *sp,_MENU_DATA *md)
/* return : 0 = nothing happen (not use key)
   	    1 = nothing happen (operation disable)
	    2 = point move in active window
*/
{
	/* テンキーオペレーション */
	if (ky==k2) ky=SKdown; /* cursor down */
	if (ky==k8) ky=SKup; /* cursor up */
	
	switch (ky) {
	    case SKdown: /* cursor down */
		if (*sp+1>all) return(1); /* 移動不可 */
		(*sp)++;
		return(2); /* point move */
	
	    case SKup: /* cursor up */
		if (*sp==1) return(1); /* 移動不可 */
		(*sp)--;
		return(2); /* point move */
	
	    case SKhome: /* active window top */
		*sp=1;
		return(2);
	
	    case SKdel: /* active window end */
		*sp=all;
		return(2);
	}
	return(0); /* not use key */
}

/****************************************************************************/

static int jump_key(ky,all,sp,msatr,fdirect,num)
int ky,all,*sp,msatr[],fdirect,num;
/* リターン値はkey_play()と同じ */
{
int i;
	ky=toupper(ky&0xff);
	
	if (fdirect) { /* ダイレクトキージャンプモード */
		for(i=1;i<=all;i++) {
			if ((msatr[i]&0xff)==ky) {
				*sp=i;
				return(2);
			}
		}
		return(0); /* not use key */
	}
	
	switch (num) {
		default: /* それ以外の番号モードの時 */
			return(0);
		case 1: /* A-I mode */
			if (ky<'A'||ky>'I') return(1); /* 'A'-'I'以外 */
			ky-=('A'-1);
			break;
		case 2: /* 1-9 */
			if (ky<'1'||ky>'9') return(1); /* '1'-'9'以外 */
			ky-='0';
	}
	if (ky>all) return(1); /* この番号はない */
	*sp=ky;
	return(2);
}

/****************************************************************************/
/* 項目表示ルーチン */

static void set1(x,y,no,sel,ms,msatr,mlen,md,col)
int x,y,no,sel,msatr[],mlen;
unchar *ms[];
_MENU_DATA *md;
MCOLORS *col;
{
int c,l,l2;
unchar a[DISPX+1];
	
	c=(md->md_mes&BIT1? 2:1)+md->wy;
	y+=(c*(no-1));
	B_LOCATE(x,y); /* for 16dot display */
	x*=8;	/* グラフィック座標 for 24dot display */
	y*=16;
	
	/* sel */
	/* 入力 */
	/* 0=normal , 1=select , 2=決定 */
	
	/* 内部変換 */
	/* 3=特殊色１ , 4=特殊色２ , 5=特殊色２select , 6=特殊色２決定 */
	/* 7=non select normal , 8=non select select */
	
	c=(md->direct||md->md_spcol)? msatr[no]:0;
	
	if ((md->md_non)&&(c&BIT8)) { /* non select */
		sel+=7;
	} else {
		if (md->md_spcol) { /* 特殊色有効モード */
			if (c&BIT10) sel+=4;
			if ((c&BIT9) && sel==0) sel=3;
		}
	}
	if (md->md_scnc) sel=0; /* select color -> normal color */
	
	if (md->num) { /* 番号あり */
		if (md->direct) { /* ダイレクトキージャンプモード */
			a[0]=toupper(c&0xff);
			if (a[0]<' ') a[0]+=('a'-1); /* CTRL-key */
		} else { /* 通常番号モード */
			switch (md->num) {
				case 1: /* A-I */
					a[0]=(md->nums? 'a':'A')+no-1;
					break;
				case 2: /* 1-9 */
					a[0]='0'+no;
					break;
			}
		}
		a[1]=0;
		EX_COLOR(Cno[sel]); /* 番号色選択 */
		if (md->md_mes&BIT1) x=print12(x,y,a);
		else EX_PRINT2(8,a);
	}
	if (md->sep[0]!=0) {	/* ":" */
		EX_COLOR(Csep[sel]); /* ":"色選択 */
		if (md->md_mes&BIT1) x=print12(x,y,md->sep);
		else EX_PRINT2(8,md->sep);
	}
	
	/* メニュー項目 */
	c=Cmn[sel]; /* 項目色選択 */
	
	l=mlen-klen2(ms[no]); /* 見た目の長さの差 */
	if (md->md_mes&BIT0) { /* center */
		l2=l;
		l/=2;
		l2-=l;
		/* メッセージ長がmlenに満たないときの処理 */
		if (l>0) { /* 前にスペースを表示する */
			string(a,' ',l);
			EX_COLOR(md->md_revlen==0? col->back:c);
			if (md->md_mes&BIT1) x=print12(x,y,a);
			else EX_PRINT2(8,a);
		}
		l=l2;
	} /* leftの時は何もしない */
	
	EX_COLOR(c);
	if (md->md_mes&BIT1) x=print12(x,y,ms[no]);
	else EX_PRINT2(8,ms[no]);
	
	/* メッセージ長がmlenに満たないときの処理 */
	if (l>0) { /* 後ろにスペースを表示する */
		string(a,' ',l);
		if (md->md_revlen==0) EX_COLOR(col->back);
		if (md->md_mes&BIT1) print12(x,y,a);
		else EX_PRINT2(8,a);
	}
}

/****************************************************************************/
/*	x,y	: メニュー左上座標（テキスト）
	sp 	: 初期セレクトポイント：何行目か（１〜ｎ）
	   	  sp<0のときは-sp=ポイント、rcode[0]=第一入力キー
	all	: 全項目数
 	ms[]	: メニュー項目
		  ms[0]="" : タイトルはmd.title
		  ms[0]<>"": ms[0]がタイトル
	msatr[]	: メニュー項目属性
		  bit0-7 : ダイレクトセレクトキー
		  bit8   : non select
		  bit9   : 特殊色１を使う
		  bit10  : 特殊色２を使う
	md	: メニューデータ
	col	: 色情報
	wget	: メニューの下のﾃｷｽﾄ画面を待避するﾜｰｸｴﾘｱ変数のｱﾄﾞﾚｽ
	rcode[MRCODE]: リターン時のメニュー状態情報
		  [0]=return key , [1]=ex , [2]=ey , [4]=sp , [7]=mouse-x , [8]=mouse-y
		  またsp<0のときは[0]は第一入力キーコードになる
		  選択番号=sp
*/
/****************************************************************************/

int tmenu(x,y,sp,all,ms,msatr,md,col,wget,rcode)
int *x,*y,sp,all,msatr[],rcode[MRCODE];
unchar *ms[],*(*wget);
_MENU_DATA *md;
MCOLORS *col;
{
int sx,sy,ex,ey,xx,mlen,fkey=0,fcur=1,ssp;
int asx,asy;
int code[15];
int lx,ly,cur,ret,i,ky,c,msc,mcx,mcy,fmouse;
int osx,osy,oex,oey,btn=0;
unchar *title;
	/* 設定 */
	c=EX_COLOR(-1);
	cur=curmode(0); /* 常にカーソルoff */
	fmouse=md->mouse&(~BIT7); /* BIT7を消しておく */
	
	/* 色コード記録 */
	Cno[0]=col->no;		Cno[1]=col->sel_no;	Cno[2]=col->cr_no;
	Cno[3]=col->no1;	Cno[4]=col->no2;	Cno[5]=col->sel_no2;
	Cno[6]=col->cr_no2;	Cno[7]=col->non_no;	Cno[8]=col->nsl_no;
	
	Csep[0]=col->sep;	Csep[1]=col->sel_sep;	Csep[2]=col->cr_sep;
	Csep[3]=col->sep1;	Csep[4]=col->sep2;	Csep[5]=col->sel_sep2;
	Csep[6]=col->cr_sep2;	Csep[7]=col->non_sep;	Csep[8]=col->nsl_sep;
	
	Cmn[0]=col->menues;	Cmn[1]=col->sel_menues;	Cmn[2]=col->cr_menues;
	Cmn[3]=col->menues1;	Cmn[4]=col->menues2;	Cmn[5]=col->sel_menues2;
	Cmn[6]=col->cr_menues2;	Cmn[7]=col->non_menues;	Cmn[8]=col->nsl_menues;
	
	/* cursor save */
	cursor(&lx,&ly);
	
	/* タイトル置き換え */
	if (ms[0][0]!=0) md->title=ms[0];
	title=md->title;
	
	/* メニュー情報GET */
	mlen=tmenu_width(*x,*y,all,ms,md,code);
	if (mlen<0) { /* parameter error */
		ret=mlen-10000; /* -10001/-10002/-10003 */
		goto TEND2;
	}
	sx =code[0]; sy =code[1];
	ex =code[2]; ey =code[3];
	asx=code[7]; asy=code[9];
	all=code[13];
	
	/* テンキー移動モード */
	k2=SKt2;
	k8=SKt8;
	if (md->num==2) { /* 番号が１〜９でないときはテンキーで操作可能 */
		k2=k8=0;
	}
	
	/* セレクトポイント修正 */
	if (sp==0) sp=1;
	if (sp<0) {sp=-sp; fkey=rcode[0];}
	
	if (md->remake==0) { /* make menu */
		/* ウインドウ用ワークエリア確保 */
		*wget=gettext2(sx,sy,ex,ey);
		if (*wget==NULL) { /* memory can't get error */
			ret=-10003;
			goto TEND;
		}
		
		/* 枠内クリア */
		fill_area(sx*8,sy*16,(ex-sx+1)*8,(ey-sy+1)*16,col->back);
		
		/* タイトル表示 */
		EX_COLOR(col->title);
		if (md->ti_mode&BIT1) print12(code[11]*8,sy*16,md->title);
		else {
			B_LOCATE(code[11],sy);
			EX_PRINT2(8,md->title);
		}
		
		/* テイル表示 */
		i=ey-1-(md->ta_mode&BIT1? 1:0);
		EX_COLOR(col->tale);
		if (md->ta_mode&BIT1) print12(code[12]*8,i*16,md->tale);
		else {
			B_LOCATE(code[12],i);
			EX_PRINT2(8,md->tale);
		}
		
		if (fmouse) { /* マウス前回座標初期化 */
			rcode[7]=rcode[8]=-1;
		}
	}
	
	/* 項目表示 */
	if (md->remake!=1) { /* 最初または項目再表示モードの時のみ */
		for (i=1;i<=all;i++) set1(asx,asy,i,i==sp,ms,msatr,mlen,md,col);
		kflush(); /* キーボードバッファークリア */
	}
	
	if (fmouse) { /* マウス初期化 */
		if (fmouse==3) { /* マウスカーソル初期設定なし */
		    mcx=MS_CURGT();
		    mcy=mcx&0xffff;
		    mcx>>=16;
		    msc=MS_STAT();
		} else {
		  int cx,cy;
		    if (md->remake==0) {
			cx=(sx+1)*8+4;
			cy=(sy+1)*16+8;
		    } else {
			cx=(sx+(rcode[7]>>16))*8+4;
			cy=(asy+rcode[8])*16+8;
		    }
		    msc=ms_set(&mcx,&mcy,cx,cy,1);
		}
	}
	
	/* メイン */
	while (1) { /* 項目選択 */
		ssp=sp;
		
		/* 選択中項目反転表示 */
		if (fcur) set1(asx,asy,sp,1,ms,msatr,mlen,md,col);
		if (fcur==2) fkey=SKcr; /* セレクト＆リターン */
		fcur=0;
		
		/* キー入力 */
		if (fkey) {ky=fkey; fkey=0;} /* 第１入力キー */
		else {
			do {
				if (fmouse) btn=mson();
				ky=inkey2(1,btn);
				if (ky==0 && fmouse) { /* マウス */
					ky=tmenu_mouse(btn,&sp,code,md,&rcode[7]);
					switch (ky) { /* 特殊操作 */
						case -1: /* move */
							goto TM_MOVE;
						case 2: /* point move */
							goto OPERATION;
					}
					/* ESC/CRも帰って来る */
				}
			} while (ky==0);
		}
		
		/* キーごとの処理 */
		for (i=0;i<md->exits;i++) { /* 緊急脱出キー */
			if (keycmp(ky,md->exit[i])) {
				ret=-sp; /* リターン値 */
				goto TRETURN;
			}
		}
		
		if ((ky&0xff)==ESC || ky==SKbrk) { /* ESC/BREAK */
			ret=0; /* リターン値 */
			break;
		}
		
		if ((ky&0xff)==CR) { /* 決定 */
			ret=sp; /* リターン値 */
			if (md->md_non&&(msatr[ret]&BIT8)) {
				/* non select menu */
				beep();
				continue;
			}
			/* 決定色に変える */
			set1(asx,asy,ssp,2,ms,msatr,mlen,md,col);
			break;
		}
		
		if (ky==SKtou && CheckMESXY()) { /* 登録：メニュー移動 */
		    TM_MOVE:;
			osx=asx-sx;	osy=asy-sy;
			code[7]-=sx;	code[8]-=sx;
			code[11]-=sx;	code[12]-=sx;
			code[14]-=sx;
			code[9]-=sy;	code[10]-=sy;
			ky=move_area(&sx,&sy,&ex,&ey
				,wget,fmouse
				,md->startx,md->starty,md->endx,md->endy);
			if (ky!=-1) { /* move ok => active window area */
				asx=sx+osx;	asy=sy+osy;
				code[0]=sx;	code[1]=sy;
				code[2]=ex;	code[3]=ey;
				/* 実座標化 */
				code[7]+=sx;	code[8]+=sx;
				code[11]+=sx;	code[12]+=sx;
				code[14]+=sx;
				code[9]+=sy;	code[10]+=sy;
			} else beep(); /* can't move */
			continue;
		}
		
		/* cursor key move */
		ret=key_play(ky,all,&sp,md);
		
		if (ret==0) {
			/* direct key move */
			ret=jump_key(ky,all,&sp,msatr,md->direct,md->num);
			if (ret && md->direct==2) fcur=2; /* direct select & return */
		}
		
		if (ret==2) { /* point move in active window */
		    OPERATION:;
			/* 元のところをselect中でないにする */
			set1(asx,asy,ssp,0,ms,msatr,mlen,md,col);
			if (fcur==0) fcur=1;
		}
	}
	
    TRETURN:; /* リターン */
	/* 後処理 */
	if (fmouse==1) ms_reset(msc,mcx,mcy); /* マウス後処理 */
	
    TEND:; /* リターン */
	/* 座標渡し */
	*x=sx;	*y=sy;
	/* status */
	rcode[0]=ky;
	rcode[1]=ex;	rcode[2]=ey;
	rcode[4]=sp;
    TEND2:;
	md->title=title;
	EX_COLOR(c);
	B_LOCATE(lx,ly);
	curmode(cur);
	return(ret);
}

/****************************************************************************/
