/****************************************************************************/
/* Mini TEXT MENU SYSTEM for X68000 V1.0 Copyright (C) 1994,95 by AIG-SOFT  */
/****************************************************************************/

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

static	unsint	Cno[9],Csep[9],Cmn[9]; /* 色コードバッファー */

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

static int key_play(int ky,int n,int *sp)
/* return : 0 = nothing happen (not use key)
   	    1 = nothing happen (operation disable)
	    2 = point move
*/
{
	switch (ky) {
	    case SKdown: /* cursor down */
		if (*sp==n) return(1); /* cursor at end */
		(*sp)++;
		return(2); /* point move */
	
	    case SKup: /* cursor up */
		if (*sp==1) return(1); /* cursor at top */
		(*sp)--;
		return(2); /* point move */
	
	    case SKhome: /* top */
		*sp=1;
		return(2);
	
	    case SKdel: /* end */
		*sp=n;
		return(2);
	}
	return(0); /* not use key */
}

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

static int jump_key(int ky,int n,int *sp,int matr[],_MENU_DATA *md)
/* リターン値はkey_play()と同じ */
{
int i;
	ky=toupper(ky&0xff);
	
	if (md->direct) { /* ダイレクトキージャンプモード */
		for (i=1;i<=n;i++) {
			if ((matr[i]&0xff)==ky) {
				*sp=i;
				return(2);
			}
		}
		return(0); /* not use key */
	}
	
	switch (md->num) {
		case 1: /* A-Z mode */
			if (!isupper(ky)) return(1); /* 'A'-'Z'以外 */
			ky-=('A'-1);
			break;
		case 2: /* 1-9/A-Z */
			if (!isalnum(ky)) return(0); /* '0'-'9','A'-'Z'以外 */
			if (isdigit(ky)) ky-='0'; /* '0'-'9' */
			else ky-=('A'-10); /* 'A'-'Z' */
			if (ky==0) return(1); /* 0が押された */
		default: /* それ以外の番号モードの時 */
			return(0);
	}
	if (ky>n) return(1); /* この番号はない */
	*sp=ky;
	return(2);
}

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

static void set1(x,y,sp,ms,matr,mlen,md,cl,sel)
/* メニュー項目：１行表示 */
int x,y,sp,matr[],mlen,sel; /* x,y = in active window */
unchar *ms[];
_MENU_DATA *md;
MCOLORS *cl;
{
int l,atr;
unchar a[DISPX+1];
	B_LOCATE(x,y);
	atr=((md->direct||md->md_spcol||md->md_non)? matr[sp]:0);
	
	/* sel */
	/* 入力：0=normal , 1=select , 2=決定 */
	/* 内部：3=特殊色１ , 4=特殊色２ , 5=特殊色２select , 6=特殊色２決定 */
	/*	 7=non select normal , 8=non select select */
	
	if ((md->md_non)&&(atr&BIT8)) { /* non select */
		sel+=7;
	} else {
		if (md->md_spcol) { /* 特殊色有効モード */
			if (atr&BIT10) sel+=4;
			if ((atr&BIT9) && sel==0) sel=3;
		}
	}
	if (md->md_scnc) sel=0; /* select color -> normal color */
	
	if (md->num) { /* 番号あり */
		a[1]=0;
		if (md->direct) { /* ダイレクトキージャンプモード */
			a[0]=toupper(atr&0xff);
			if (a[0]<' ') a[0]+=('a'-1); /* CTRL-key */
		} else { /* 通常番号モード */
			switch (md->num) {
			    case 1: /* A-Z */
				a[0]='A'-1+sp;
				break;
			    case 2: /* 1-9/A-Z */
				if (sp>=0 && sp<=9) a[0]='0'+sp;
				else a[0]='A'-10+sp;
				break;
			}
		}
		B_COLOR(Cno[sel]); /* 番号色選択 */
		B_PRINT(a);
	}
	
	if (md->sep[0]) { /* ":" */
		B_COLOR(Csep[sel]); /* ":"色選択 */
		B_PRINT(md->sep);
	}
	
	/* メニュー項目 */
	B_COLOR(Cmn[sel]);
	B_PRINT(ms[sp]);
	
	/* メッセージ長がmlenに満たないときの処理 */
	l=mlen-klen2(ms[sp]); /* 見た目の長さの差 */
	if (l>0) { /* 後ろにスペースを表示する */
		string(a,' ',l);
		if (md->md_revlen==0) B_COLOR(cl->back);
		B_PRINT(a);
	}
}

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

int mini_menu(sx,sy,sp,n,ms,matr,md,cl,rcode,inkeys)
int sx,sy,sp,n,matr[],rcode[MRCODE],(*inkeys)();
unchar *ms[];
_MENU_DATA *md;
MCOLORS *cl;
{
int ex,ey,mlen,nmlen,fkey=0,fcur=1,ssp;
int asx,asy,aex,aey;
int code[12];
int btn=0,lx,ly,cur,ret,i,ky,c,msc,mcx,mcy,fmouse;
unchar *title;
	/* 設定 */
	c=B_COLOR(-1);
	cur=curmode(md->cursor);
	cursor(&lx,&ly); /* cursor save */
	
	/* メモリー節約のため */
	fmouse=md->mouse&~BIT7; /* BIT7を消しておく */
	
	/* 色コード記録 */
	Cno[0]=cl->no;		Cno[1]=cl->sel_no;	Cno[2]=cl->cr_no;
	Cno[3]=cl->no1;		Cno[4]=cl->no2;		Cno[5]=cl->sel_no2;
	Cno[6]=cl->cr_no2;	Cno[7]=cl->non_no;	Cno[8]=cl->nsl_no;
	
	Csep[0]=cl->sep;	Csep[1]=cl->sel_sep;	Csep[2]=cl->cr_sep;
	Csep[3]=cl->sep1;	Csep[4]=cl->sep2;	Csep[5]=cl->sel_sep2;
	Csep[6]=cl->cr_sep2;	Csep[7]=cl->non_sep;	Csep[8]=cl->nsl_sep;
	
	Cmn[0]=cl->menues;	Cmn[1]=cl->sel_menues;	Cmn[2]=cl->cr_menues;
	Cmn[3]=cl->menues1;	Cmn[4]=cl->menues2;	Cmn[5]=cl->sel_menues2;
	Cmn[6]=cl->cr_menues2;	Cmn[7]=cl->non_menues;	Cmn[8]=cl->nsl_menues;
	
	/* タイトル置き換え */
	if (ms[0][0]!=0) md->title=ms[0];
	title=md->title;
	
	/* メニュー情報GET */
	mlen=mini_menu_width(sx,sy,n,ms,md,code);
	ex  =code[4];	ey  =code[5];
	asx =code[6];	asy =code[7];
	aex =code[8];	aey =code[9];
	n   =code[10];	nmlen=code[11]+mlen;
	
	/* セレクトポイント修正 */
	if (sp==0) sp=1;
	if (sp<0) {sp=-sp; fkey=rcode[0];}
	
	if (md->remake==0) { /* make menu */
		/* 枠描画 */
		make_waku(sx,sy,ex,ey,md,cl);
		/* マウス前回座標初期化 */
		if (fmouse) rcode[7]=rcode[8]=-1;
	}
	
	/* 項目表示 */
	if (md->remake!=1) { /* 最初または項目再表示モードの時のみ */
		for (i=1;i<=n;i++) {
			set1(asx,asy+i-1,i,ms,matr,mlen,md,cl,i==sp);
		}
		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=(asx+(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,sp,ms,matr,mlen,md,cl,1);
		if (fcur==2) fkey=SKcr; /* セレクト＆リターン */
		fcur=0;
		
		/* キー入力 */
		if (fkey) {ky=fkey; fkey=0;} /* 第１入力キー */
		else {
		    do {
			if (fmouse) { /* マウス */
				btn=mson();
				if ((ky=inkeys(1,btn))) break;
				ky=mini_menu_mouse(btn,&sp,sx,sy,ex,ey
						,nmlen,md,&rcode[7]);
				if (ky==2) goto OPERATION;
				/* ESC/CRも帰って来る */
			} else 	ky=inkeys(1,0);
		    } while (ky==0);
		}
		
		/* キーごとの処理 */
		for (i=0;i<md->exits;i++) { /* 緊急脱出キー */
			if (keycmp(ky,md->exit[i])) {
				ret=-sp; /* リターン値 */
				goto WEND;
			}
		}
		if ((ky&0xff)==CR) { /* 決定 */
			if (md->md_non && (matr[sp]&BIT8)) {
				/* non select menu */
				beep();
				continue;
			}
			/* 決定色に変える */
			set1(asx,asy+ssp-1,sp,ms,matr,mlen,md,cl,2);
			ret=sp; /* リターン値 */
			break;
		}
		if ((ky&0xff)==ESC||ky==SKbrk) { /* ESC/BREAK */
			ret=0; /* リターン値 */
			break;
		}
		
		/* cursor key move */
		ret=key_play(ky,n,&sp);
		if (ret==0) {
			/* direct key move */
			ret=jump_key(ky,n,&sp,matr,md);
			if (ret && md->direct==2) fcur=2; /* select&ret.*/
		}
		if (ret==2) { /* point move */
		    OPERATION:;
			/* 元のところをselect中でないにする */
			set1(asx,asy+ssp-1,ssp,ms,matr,mlen,md,cl,0);
			if (fcur==0) fcur=1;
		}
	}
    WEND: /* リターン */
	/* 後処理 */
	if (fmouse==1) ms_reset(msc,mcx,mcy); /* マウス後処理 */
    WEND2:;
	/* status */
	rcode[0]=ky;
	rcode[1]=ex;	rcode[2]=ey;
	rcode[4]=sp;
    WEND3:;
	md->title=title;
	B_COLOR(c);
	B_LOCATE(lx,ly);
	curmode(cur);
	return(ret);
}

/****************************************************************************/
/*	x,y	: メニュー左上座標（テキスト）
	sp 	: 初期セレクトポイント：何行目か（１〜ｎ）
	   	  sp<0のときは-sp=ポイント、rcode[0]=第一入力キー
	n	: 全項目数
 	ms[]	: メニュー項目
		  ms[0]="" : タイトルはmd.title
		  ms[0]<>"": ms[0]がタイトル
	matr[]	: メニュー項目属性
		  bit0-7 : ダイレクトセレクトキー
		  bit8   : non select
		  bit9   : 特殊色１を使う
		  bit10  : 特殊色２を使う
	md	: メニューデータ
	cl	: 色情報
	rcode[MRCODE]: リターン時のメニュー状態情報
		  [0]=return key , [1]=ex , [2]=ey , [4]=sp
		  [7]=mouse-x , [8]=mouse-y
		  またsp<0のときは[0]は第一入力キーコードになる
*/
/****************************************************************************/
