/***   [dropdm.c]
*
*	ドロップダウンメニュー 関連		(C)ささがわ
*
*	For GNU C Compiler (GCC)   Version 1.39
*
***/

#include <stdio.h>
#include <string.h>
#include "dropdm.h"
#include "graph.h"
#include "mos.h"
#include "others.h"

extern int	PAL_Black, PAL_Button;
static int	Title, nTitle, nMenu, Shadow;
static int	Yt1, Yt2, Xm1, Xm2, Ym1, Ym2;
static struct menu_t	*Menu;

static int	DRPDM_sub(int *);
static void	Rev_sub(int);
static void	Open(void);
static void	Close(void);
static int	Where(int, int, int *);
static int	Where_title(int, int);

/**
*	ﾄﾞﾛｯﾌﾟﾀﾞｳﾝﾒﾆｭｰ 関数
*		入力:	x, y 呼び出し直前のﾏｳｽ座標, dp ﾊﾟﾗﾒｰﾀ
*		出力:	戻り値が真の場合 ﾒﾆｭｰが選択されたことを示す
*				x ﾀｲﾄﾙ番号, y ﾒﾆｭｰ番号 (戻り値が偽の場合は不定)
**/

int DRPDM_main(int *x, int *y, struct dropdm_t *dp) {
	int		t, p, mx, my;
	char	mb;
	
	nTitle = dp->ntitle;	Yt1 = dp->yt1;
	Yt2 = dp->yt2;	Ym1 = dp->ym;
	Menu = dp->m;	Shadow = dp->shadow;
	
	if ((t = Where_title(*x, *y)) < 0)
		return 0;
	
	do	p = t;	while (!DRPDM_sub(&t));
	while (MOS_rdpos(&mb, &mx, &my), mb & 1);
	*x = p;	*y = t;
	
	return (t < 0 ? 0 : 1);
}

/*	入力:	t ﾀｲﾄﾙ番号
	出力:	戻り値が正の場合 ﾒﾆｭｰが選択され t にその番号が返される
			  〃    零の場合 ﾀｲﾄﾙが選択され t に    〃
			  〃    負の場合 上記以外が選択されたことを示す t は負
*/

static int DRPDM_sub(int *t) {
	int		flag = -1, lop = 1;
	int		mx, my, rel, fwh, wh;
	char	mb;
	
	Title = *t;
	for (nMenu = 0; Menu[Title].name[nMenu] != NULL; nMenu++);
	Xm1 = Menu[Title].xm;
	Xm2 = Xm1 + Menu[Title].wm * 8 - 1;
	Ym2 = Ym1 + nMenu * 20 - 1;
	
	Open();
	MOS_rdpos(&mb, &mx, &my);
	rel = mb & 1 ? 0 : 1;
	do {
		int		a;
		
		do {
			CLOCK(0);
			MOS_rdpos(&mb, &mx, &my);
		} while (!(mb & 1) && rel);
		
		fwh = Where(mx, my, &wh);
		a = fwh > 0 && wh >= 0 ? wh : -1;
		if (flag != a) {
			Rev_sub(flag);	Rev_sub(a);
			flag = a;
		}
		
		if (mb & 1) {
			if (rel && fwh < 0 || !fwh)
				lop = 0;
			
			rel = 0;
		} else {
			if (fwh <= 0 || wh >= 0)	/* !(fwh > 0 && wh < 0) */
				lop = 0;
			
			rel = 1;
		}
	} while (lop);
	Close();
	
	*t = !fwh ? wh : flag;
	return fwh;
}

static void Rev_sub(int i) {
	int		a;
	
	if (i < 0)
		return;
	
	a = Ym1 + 20 * i;
	EGB_rev(1, Xm1, a, Xm2, a + 19);
}

static void Open(void) {
	int		i;
	struct menu_t	*p = Menu + Title;
	
	MOS_disp(0);
	EGB_rev(0, p->xt, Yt1, p->xt + p->wt - 1, Yt2);
	EGB_mycopy(EGB_readactPage(), Xm1 - 1, Ym1 - 1, Xm2 + 3, Ym2 + 3, 0, 650, 0);
	if (Shadow) {
		EGB_boxf(Xm2 + 2, Ym1 + 1, Xm2 + 3, Ym2 + 3, PAL_Black, PAL_Black);
		EGB_boxf(Xm1 + 1, Ym2 + 2, Xm2 + 3, Ym2 + 3, PAL_Black, PAL_Black);
	}
	EGB_boxf(Xm1 - 1, Ym1 - 1, Xm2 + 1, Ym2 + 1, PAL_Black, 15);
	for (i = 0; i < nMenu; i++)
		EGB_str2(p->name[i], Xm1, Ym1 + i * 20 + 17, p->mask[i] ? PAL_Button : PAL_Black);
	MOS_disp(1);
}

static void Close(void) {
	MOS_disp(0);
	EGB_mycopy(0, 650, 0, 650 + Xm2 - Xm1 + 4, Ym2 - Ym1 + 4, EGB_readactPage(), Xm1 - 1, Ym1 - 1);
	EGB_rev(0, Menu[Title].xt, Yt1, Menu[Title].xt + Menu[Title].wt - 1, Yt2);
	MOS_disp(1);
}

static int Where(int x, int y, int *wh) {
	int		i, ret = -1;
	
	if (Xm1 <= x && x <= Xm2 && Ym1 <= y && y <= Ym2) {
		struct menu_t	*p;
		
		*wh = (y - Ym1) / 20;
		p = Menu + Title;
		if (!strncmp(p->name[*wh] + 1, "─", 2) || p->mask[*wh]) *wh = -1;
		ret = 1;
	} else if ((i = Where_title(x, y)) >= 0) {
		if (i == Title) {
			*wh = -1;	ret = 1;
		} else {
			*wh = i;	ret = 0;
		}
	}
	
	return ret;
}

static int Where_title(int x, int y) {
	int		i, ret = -1;
	struct menu_t	*p;
	
	for (i = 0, p = Menu; i < nTitle; i++, p++) {
		if (p->xt <= x && x <= p->xt + p->wt - 1 && Yt1 <= y && y <= Yt2) {
			ret = i;
			break;
		}
	}
	
	return ret;
}
