/***   [fswind_n.c]
*
*	ファイルセレクタウィンドウ 関連 (標準)		(C)ささがわ
*
*	For GNU C Compiler (GCC)   Version 1.39
*
***/

#include <string.h>
#include <jctype.h>
#include <dos.h>
#include <direct.h>
#include "window.h"
#include "graph.h"
#include "mos.h"
#include "keyin.h"
#include "fswind.h"
#include "icn.h"
#include "beep.h"
#include "others.h"

extern int	PAL_Black;
static struct cvars_t	*cv;
static int	filehd, diroff, ERROR;
static get_f	gf;

static void	Draw_window(void);			/* ｶｰｿﾙ */
static int	Where(int, int);
static int	Where_drive(int, int);
static int	SUB_drive(int, int);		/* ｶｰｿﾙ */
static int	Where_path(int, int);
static int	SUB_path(int, int);			/* ｶｰｿﾙ */
static int	Where_file(int, int);
static int	SUB_file(int, int);			/* ｶｰｿﾙ */
static void	SUB_scupdw(int);			/* ｶｰｿﾙ */
static int	SUB_scupdw_sub(int);
static void	SUB_scdr(int);				/* ｶｰｿﾙ */
static void	SUB_move(int, int, struct keyin_t *);	/* ｶｰｿﾙ */
static int	Where_kyb(int, int);
static void	SUB_kyb(int, int);			/* ｶｰｿﾙ */
static void	allcls(void);				/* ｶｰｿﾙ */
static void	errord(void);				/* ｶｰｿﾙ */

int WIND_file_n(char *path, struct cvars_t *cvars) {
	int		ret = 0, ret2 = 0;
	struct keyin_t	kt;
	
	ICN_mos(0);
	ERROR = 0;
	cv = cvars;
	
	kt.x = cv->wx + 276;
	kt.y = cv->wy + 227 + 20 * cv->drw;
	kt.keta = 14;
	kt.foreC = PAL_Black;
	kt.backC = 7;
	kt.curC = 10;
	kt.buf = path;
	kt.bufn = 80;
	Draw_window();
	Keyin_init(&kt);
	
	ICN_mos(1);
	if (FSW_Draw_path(0, &diroff)) {
		errord();
	} else if (FSW_Draw_diskfree(0)) {
		errord();
	} else {
		filehd = 0;
		if (FSW_Draw_file(0, filehd, &gf))
			return -1;
		FSW_Draw_scrollB(filehd, gf.nfiles);
	}
	ICN_mos(0);
	
	while (!ret && ret2 != 1) {
		char	mb;
		int		wh, mx, my;
		
		if ((ret2 = Keyin()) == -1)
			Keyin_init(&kt);
		
		CLOCK(0);
		if (MOS_rdpos(&mb, &mx, &my), !(mb & 1))
			continue;
		
		if (wh = Where(mx, my), wh == WH_PATH || wh == WH_SCUP || wh == WH_SCDW || wh == WH_SCDR || wh == WH_FILE) {
			if (!ERROR) {
				switch (wh) {
					int		sc;
					
					case WH_PATH:
						if (SUB_path(mx, my))
							ret = -1;
						break;
					case WH_SCUP:
						SUB_scupdw(1);
						break;
					case WH_SCDW:
						SUB_scupdw(0);
						break;
					case WH_SCDR:
						SUB_scdr(my);
						break;
					case WH_FILE:
						if ((sc = SUB_file(mx, my)) == -2) {
							ret = -1;
						} else if (sc >= 0) {
							strlow(1, (gf.pbuf[filehd + sc])->name);
							strcpy(path, cv->dirbuf);
							if (strchr(path, '\0')[-1] != '\\')
								strcat(path, "\\");
							strcat(path, (char *)(gf.pbuf[filehd + sc])->name);
							ret = 1;
						}
						break;
				}
			}
		} else {
			switch (wh) {
				case WH_END:
					if (FSW_end())
						ret = 2;
					break;
				case WH_TITLE:
					SUB_move(mx, my, &kt);
					break;
				case WH_OPT1:
					if (FSW_opt1())
						ret = 3;
					break;
				case WH_OPT2:
					if (FSW_opt2(&mx, &my)) {
						cv->sort = my;
						if (!ERROR) {
							filehd = 0;
							FSW_Draw_file(2, filehd, &gf);
							FSW_Draw_scrollB(filehd, gf.nfiles);
						}
					}
					break;
				case WH_DRIVE:
					if (SUB_drive(mx, my))
						ret = -1;
					break;
				case WH_KYB:
					SUB_kyb(mx, my);
					break;
				default:
					do {
						MOS_rdpos(&mb, &mx, &my);
					} while (mb & 1);
					break;
			}
		}
	}
	
	Gf_bufrel();
	if (ret == -1)
		return -1;
	else if (ret == 2)
		return 0;
	else if (ret == 3)
		return 2;
	else
		return 1;
}

static void Draw_window(void) {
	int		a;
	struct opnwin_t	opw;
	static const int	optw[] = {
		2, 2
	};
	
	a = 20 * cv->drw;
	opw.title = cv->title;
	opw.x1 = cv->wx;
	opw.y1 = cv->wy;
	opw.x2 = opw.x1 + 395;
	opw.y2 = opw.y1 + 235 + a;
	opw.canb = 1;
	opw.nopt = 2;
	opw.wopt = optw;
	opw.expb = 0;
	opw.shdw = 1;
	opw.ord = 0;
	MOS_disp(0);
	drawWindow(&opw);
	
	EGB_line(cv->wx + 5, cv->wy + 27 + a, cv->wx + 390, cv->wy + 27 + a, PAL_Black);
	EGB_line(cv->wx + 5, cv->wy + 48 + a, cv->wx + 390, cv->wy + 48 + a, PAL_Black);
	EGB_line(cv->wx + 5, cv->wy + 209 + a, cv->wx + 390, cv->wy + 209 + a, PAL_Black);
	EGB_line(cv->wx + 273, cv->wy + 209 + a, cv->wx + 273, cv->wy + 230 + a, PAL_Black);
	
	DrawScrollbar(0, cv->wx + 374, cv->wy + 48 + a, 162);
	ICN_opt(0, cv->wx + 372, cv->wy + 8);
	EGB_str2("★", cv->wx + 351, cv->wy + 23, PAL_Black);
	FSW_Draw_drive();
	MOS_disp(1);
}

static int Where_drive(int x, int y) {
	int		i = 0, xx, yy;
	
	x -= cv->wx;
	y -= cv->wy;
	for (yy = 0; yy < cv->drw; yy++) {
		for (xx = 0; xx < 7; xx++) {
			if (i >= cv->drinfo[0])
				return -1;
			else if (xx * 53 + 30 < x && x < xx * 53 + 58 && yy * 20 + 29 < y && y < yy * 20 + 44)
				return i;
			else
				i++;
		}
	}
	
	return -1;
}

static int SUB_drive(int x, int y) {
	int		psc;
	
	if ((psc = Where_drive(x, y)) == -1) {
		char	mb;
		
		do {
			int		mx, my;
			
			MOS_rdpos(&mb, &mx, &my);
		} while (mb & 1);
		return 0;
	}
	
	x = psc % 7;
	y = psc / 7;
	x = cv->wx + x * 53 + 31;
	y = cv->wy + y * 20 + 30;
	if (Button(x, y, x + 26, y + 13)) {
		unsigned	dr;
		
		EGB_rev(1, x, y, x + 26, y + 13);
		ICN_mos(1);
		allcls();
		_dos_setdrive(cv->drinfo[psc * 2 + 1] - 'A' + 1, &dr);
		if (FSW_Draw_path(0, &diroff)) {
			errord();
		} else if (FSW_Draw_diskfree(0)) {
			errord();
		} else {
			ERROR = 0;
			filehd = 0;
			if (FSW_Draw_file(0, filehd, &gf))
				return -1;
			FSW_Draw_scrollB(filehd, gf.nfiles);
		}
		ICN_mos(0);
	}
	
	return 0;
}

static int SUB_path(int mx, int my) {
	int		sc, psc = -1;
	int		xx, yy;
	char	mb;
	
	ICN_mos(2);
	sc = Where_path(mx, my);
	
	xx = cv->wx + 14;
	yy = cv->wy + 30 + 20 * cv->drw;
	do {
		if (sc != -1) {
			if (diroff == 0 && sc <= 2) {
				sc = 2;
			} else {
				do {
					sc++;
				} while (sc < strlen(cv->dirbuf2) && cv->dirbuf2[sc] != '\\');
				sc--;
			}
		}
		if (sc == -1 && psc != sc)
			EGB_rev(1, xx, yy, xx + (psc + 1) * 8 - 1, yy + 15);
		else if (sc > psc)
			EGB_rev(1, xx + (psc + 1) * 8, yy, xx + (sc + 1) * 8 - 1, yy + 15);
		else if (sc < psc)
			EGB_rev(1, xx + (sc + 1) * 8, yy, xx + (psc + 1) * 8 - 1, yy + 15);
		psc = sc;
		
		MOS_rdpos(&mb, &mx, &my);
		sc = Where_path(mx, my);
	} while (mb & 1);
	ICN_mos(0);
	
	if (psc != -1) {
		if (diroff != 0)
			cv->dirbuf[diroff + psc - 4] = '\0';
		else
			cv->dirbuf[diroff + psc + 1] = '\0';
		if (strlen(cv->dirbuf) < 3)
			strcpy(cv->dirbuf + 2, "\\");
		ICN_mos(1);
		if (chdir(cv->dirbuf)) {
			errord();
		} else if (FSW_Draw_path(0, &diroff)) {
			errord();
		} else {
			filehd = 0;
			if (FSW_Draw_file(0, filehd, &gf))
				return -1;
			FSW_Draw_scrollB(filehd, gf.nfiles);
		}
		ICN_mos(0);
	}
	
	return 0;
}

static int Where_path(int x, int y) {
	int		sc, ret;
	
	x -= cv->wx;
	y -= cv->wy;
	if (x < 14 || 382 < x || y < 30 + 20 * cv->drw || 45 + 20 * cv->drw < y) {
		ret = -1;
	} else {
		sc = (x - 14) / 8;
		if (strlen(cv->dirbuf2) > sc)
			ret = sc;
		else
			ret = -1;
	}
	
	return ret;
}

static void SUB_scupdw(int w) {
	int		mx, my, xx, yy, fllast, flpush = 1;
	char	mb;
	
	if (w) {
		xx = cv->wx + 375;
		yy = cv->wy + 49 + 20 * cv->drw;
	} else {
		xx = cv->wx + 375;
		yy = cv->wy + 194 + 20 * cv->drw;
	}
	
	EGB_rev(1, xx, yy, xx + 14, yy + 14);
	fllast = SUB_scupdw_sub(w);
	TIMER_set(20);
	
	while (MOS_rdpos(&mb, &mx, &my), mb & 1) {
		int		whres;
		
		whres = Where(mx, my) == (w ? WH_SCUP : WH_SCDW);
		if (!whres && flpush || whres && !flpush) {
			EGB_rev(1, xx, yy, xx + 14, yy + 14);
			flpush = !flpush;
		}
		
		if (flpush && TIMER() && !fllast)
			fllast = SUB_scupdw_sub(w);
	}
	
	if (flpush)
		EGB_rev(1, xx, yy, xx + 14, yy + 14);
}

static int SUB_scupdw_sub(int w) {
	if (!(w && filehd > 0 || !w && filehd + 8 < gf.nfiles))
		return 1;
	
	w ? filehd-- : filehd++;
	FSW_Draw_scrollB(filehd, gf.nfiles);
	EGB_color(EGB_work, EGB_COL_BACK, 7);
	MOS_disp(0);
	EGB_scrl(1, cv->wx + 14, cv->wy + 49 + 20 * cv->drw, cv->wx + 365, cv->wy + 208 + 20 * cv->drw, 0, w ? 20 : -20);
	FSW_Draw_file_sub(w ? 0 : 7, filehd, &gf);
	MOS_disp(1);
	
	return 0;
}

static void SUB_scdr(int my) {
	int		mx, y;
	char	mb;	
	struct sb_t	sb;
	
	ICN_mos(3);
	y = cv->wy + 65 + 20 * cv->drw;
	sb.tl = gf.nfiles;	sb.lpp = 8;
	sb.blen = 128;		sb.bml = 15;
	SCRB_bar(&sb, my - y, &filehd);
	
	FSW_Draw_scrollB(filehd, gf.nfiles);
	FSW_Draw_file(1, filehd, &gf);
	
	while (MOS_rdpos(&mb, &mx, &my), mb & 1) {
		int		a, f;
		
		if (Where(mx, my) != WH_SCDR)
			continue;
		if (SCRB_bar(&sb, my - y, &a), a == filehd)
			continue;
		
		f = a < filehd;
		filehd += f ? -1 : 1;
		FSW_Draw_scrollB(filehd, gf.nfiles);
		EGB_color(EGB_work, EGB_COL_BACK, 7);
		MOS_disp(0);
		EGB_scrl(1, cv->wx + 14, cv->wy + 49 + 20 * cv->drw, cv->wx + 365, cv->wy + 208 + 20 * cv->drw, 0, f ? 20 : -20);
		FSW_Draw_file_sub(f ? 0 : 7, filehd, &gf);
		MOS_disp(1);
	}
	ICN_mos(0);
}

static int SUB_file(int mx, int my) {
	int		ret, sc, xx, yy, psc = -1;
	char	mb;
	
	xx = cv->wx + 6;
	yy = cv->wy + 49 + 20 * cv->drw;
	sc = Where_file(mx, my);
	do {
		if (psc != sc) {
			if (psc != -1)
				EGB_rev(1, xx, yy + psc * 20, xx + 367, yy + (psc + 1) * 20 - 1);
			if (sc != -1)
				EGB_rev(1, xx, yy + sc * 20, xx + 367, yy + (sc + 1) * 20 - 1);
		}
		psc = sc;
		
		MOS_rdpos(&mb, &mx, &my);
		sc = Where_file(mx, my);
	} while (mb & 1);
	
	if (psc == -1) {
		ret = -1;
	} else if ((gf.pbuf[filehd + sc])->attr & _A_SUBDIR) {
		ICN_mos(1);
		if (chdir((char *)(gf.pbuf[filehd + sc])->name)) {
			errord();
		} else if (FSW_Draw_path(0, &diroff)) {
			errord();
		} else {
			filehd = 0;
			if (FSW_Draw_file(0, filehd, &gf))
				return -2;
			FSW_Draw_scrollB(filehd, gf.nfiles);
		}
		ICN_mos(0);
		
		ret = -1;
	} else {
		int	i;
		
		for (i = 0; i < 4; i++) {
			for (TIMER_set(5); !TIMER(); );
			EGB_rev(1, xx, yy + psc * 20, xx + 367, yy + (psc + 1) * 20 - 1);
		}
		ret = sc;
	}
	
	return ret;
}

static int Where_file(int mx, int my) {
	int		ret;
	
	mx -= cv->wx;
	my -= cv->wy;
	if (mx < 6 || 373 < mx || my < 49 + 20 * cv->drw || 208 + 20 * cv->drw < my) {
		ret = -1;
	} else {
		int		sc;
		
		sc = (my - (49 + 20 * cv->drw)) / 20;
		if (filehd + sc < gf.nfiles)
			ret = sc;
		else
			ret = -1;
	}
	
	return ret;
}

static int Where(int x, int y) {
	int		a, i, ret = WH_OTHER;
	static const short	table[12][7] = {
		{5, 26, 5, 26, 0, 0, WH_END},	{26, 348, 5, 26, 0, 0, WH_TITLE},
		{369, 390, 5, 26, 0, 0, WH_OPT1},	{348, 369, 5, 26, 0, 0, WH_OPT2},
		{5, 390, 26, 27, 0, 1, WH_DRIVE},	{5, 390, 27, 48, 1, 1, WH_PATH},
		{5, 374, 48, 209, 1, 1, WH_FILE},	{374, 390, 48, 64, 1, 1, WH_SCUP},
		{374, 390, 64, 193, 1, 1, WH_SCDR},	{374, 390, 193, 209, 1, 1, WH_SCDW},
		{5, 273, 209, 230, 1, 1, WH_FREE},	{273, 390, 209, 230, 1, 1, WH_KYB}
	};
	
	x -= cv->wx;
	y -= cv->wy;
	a = 20 * cv->drw;
	for (i = 0; i < 12; i++) {
		const short	*p;
		
		p = table[i];
		if (p[0] < x && x < p[1] && p[2] + (p[4] ? a : 0) < y && y < p[3] + (p[5] ? a : 0)) {
			ret = p[6];
			break;
		}
	}
	
	return ret;
}

static void SUB_move(int x, int y, struct keyin_t *kt) {
	struct RECT	s, w;
	
	w.x1 = cv->wx;	w.y1 = cv->wy;
	w.x2 = cv->wx + 395;	w.y2 = cv->wy + 235 + 20 * cv->drw;
	s.x1 = 0;	s.y1 = 40;	s.x2 = 639;	s.y2 = 463;
	if (dragWindow(x, y, &w, &s, 0, 0)) {
		cv->wx = w.x1;	cv->wy = w.y1;
		MOS_disp(0);
		EGB_cls(0);
		MOS_disp(1);
		kt->x = cv->wx + 276;
		kt->y = cv->wy + 227 + 20 * cv->drw;
		Draw_window();
		Keyin_redisp();
		if (ERROR) {
			errord();
		} else {
			FSW_Draw_diskfree(1);
			FSW_Draw_path(1, &diroff);
			FSW_Draw_file(1, filehd, &gf);
			FSW_Draw_scrollB(filehd, gf.nfiles);
		}
	}
}

static void SUB_kyb(int mx, int my) {
	int		sc;
	char	mb;
	
	ICN_mos(2);
	sc = Where_kyb(mx, my);
	do {
		Keyin_cur(sc);
		MOS_rdpos(&mb, &mx, &my);
		sc = Where_kyb(mx, my);
	} while (mb & 1);
	ICN_mos(0);
}

static int Where_kyb(int x, int y) {
	int		ret;
	
	x -= cv->wx;
	y -= cv->wy;
	if (x < 276 || 387 < x || y < 212 + 20 * cv->drw || 227 + 20 * cv->drw < y)
		ret = -1;
	else
		ret = (x - 276) / 8;
	
	return ret;
}

static void allcls(void) {
	int		a;
	
	a = 20 * cv->drw;
	MOS_disp(0);
	EGB_boxf(cv->wx + 5, cv->wy + 27 + a, cv->wx + 390, cv->wy + 48 + a, PAL_Black, 7);
	EGB_boxf(cv->wx + 5, cv->wy + 48 + a, cv->wx + 374, cv->wy + 209 + a, PAL_Black, 7);
	EGB_boxf(cv->wx + 374, cv->wy + 64 + a, cv->wx + 390, cv->wy + 193 + a, PAL_Black, 6);
	EGB_boxf(cv->wx + 5, cv->wy + 209 + a, cv->wx + 273, cv->wy + 230 + a, PAL_Black, 7);
	MOS_disp(1);
}

static void errord(void) {
	int		x, y;
	char	buf[5];
	
	allcls();
	FSW_getdrive(buf);
	MOS_disp(0);
	EGB_str2(buf, cv->wx + 14, cv->wy + 45 + 20 * cv->drw, PAL_Black);
	x = cv->wx + 46;
	y = cv->wy + 48 + 20 * cv->drw;
	EGB_str2("ディスクの有無を確認して", x, y + 70, PAL_Black);
	EGB_str2("  ドライブを選択しなおしてください", x, y + 90, PAL_Black);
	MOS_disp(1);
	BEP_on();
	ERROR = 1;
}
