/***   [fswind.c]
*
*	ファイルセレクタウィンドウ 関連		(C)ささがわ
*
*	For GNU C Compiler (GCC)   Version 1.39
*
***/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <jctype.h>
#include "graph.h"
#include "dos.h"
#include "icn.h"
#include "window.h"
#include "mos.h"
#include "dropdm.h"
#include "fswind.h"
#include "others.h"
#include "optparse.h"

extern int	PAL_Black;
extern unsigned char	RIN_dataBuf[303];
static char	wmode;
static char	(*flinf)[45];
static struct cvars_t	cv;

static int	Getdrinfo(void);
static int	mygetcd(char *);
static void	FSW_Setfiles(get_f *);

void WIND_filesel_init(void) {
	OPT_filew(&wmode, &cv.cap, &cv.sort);
}

/***
*	ファイル・セレクタ関数
*		入力：	path   ﾌｧｲﾙ名格納用ﾊﾞｯﾌｧ (85ﾊﾞｲﾄ必要)
*				mode   0以外の時のときワイド型
*				capital   0以外のとき大文字
*				dirsort   0:ｿｰﾄなし   1:種類別   2:名前順   3:作成日時順
*		戻り値：	0:ｷｬﾝｾﾙ   1:入力あり   -1:ｴﾗｰ
***/
int WIND_filesel(const char *title, char *path) {
	int		ret;
	struct RECT	af1 = {
		319, 259, 320, 260
	};
	
	cv.title = title;
	if (Getdrinfo()) {
		WIND_error(1, NULL);
		return -1;
	}
	wmode = !wmode;
	do {
		struct RECT	af2;
		
		MOS_disp(0);
		EGB_cls(0);
		MOS_disp(1);
		if (wmode = !wmode) {
			cv.drw = (cv.drinfo[0] + 10) / 11;
			cv.wx = 0;
			cv.wy = 40 + (424 - (356 + 20 * cv.drw)) / 2;
			
			af2.x1 = cv.wx;
			af2.y1 = cv.wy;
			af2.x2 = af2.x1 + 639;
			af2.y2 = af2.y1 + 355 + 20 * cv.drw;
			afterImage(&af1, &af2);
			
			ret = WIND_file_w(path, &cv);
			
			af1.x1 = cv.wx;
			af1.y1 = cv.wy;
			af1.x2 = af1.x1 + 639;
			af1.y2 = af1.y1 + 355 + 20 * cv.drw;
		} else {
			cv.drw = (cv.drinfo[0] + 6) / 7;
			cv.wx = (640 - 396) / 2;
			cv.wy = 40 + (424 - (236 + 20 * cv.drw)) / 2;
			
			af2.x1 = cv.wx;
			af2.y1 = cv.wy;
			af2.x2 = af2.x1 + 395;
			af2.y2 = af2.y1 + 235 + 20 * cv.drw;
			afterImage(&af1, &af2);
			
			ret = WIND_file_n(path, &cv);
			
			af1.x1 = cv.wx;
			af1.y1 = cv.wy;
			af1.x2 = af1.x1 + 395;
			af1.y2 = af1.y1 + 235 + 20 * cv.drw;
		}
	} while (ret == 2);
	free(flinf);
	flinf = NULL;
	
	if (ret == -1)	WIND_error(1, NULL);
	
	return ret;
}

/* ﾄﾞﾗｲﾌﾞ接続情報 格納 */
static int Getdrinfo(void) {
	int				i, ii = 0;
	int				ncd, scd;
	union REGS		regs;
	struct SREGS	sregs;
	
	regs.h.ah = 0x00;
	if (nativetoreal(RIN_dataBuf, 200, &sregs.ds, &regs.x.di))
		return -1;
	int86x(0x8e, &regs, &regs, &sregs);
	
	for (i = 0; i < 16; i++) {
		unsigned char	d;
		
		if ((d = RIN_dataBuf[0x30 + i * 2]) != 0xff) {
			switch (d) {
				case 2:	d = 1;	break;
				case 3:	d = 3;	break;
				default:	d = 0;	break;
			}
			cv.drinfo[ii * 2 + 1] = 'A' + i;
			cv.drinfo[ii++ * 2 + 2] = d;
		}
	}
	
	Get_cdexinf(&ncd, &scd);
	for (i = 0; i < ncd; i++) {
		cv.drinfo[ii * 2 + 1] = scd + 'A' + i;
		cv.drinfo[ii * 2 + 2] = 2;
		ii++;
	}
	
	cv.drinfo[0] = ii;
	return 0;
}

/* ﾄﾞﾗｲﾌﾞ描画 */
void FSW_Draw_drive(void) {
	int		i = 0, xn;
	int		x, y, xx, yy;
	
	xn = wmode ? 11 : 7;
	yy = cv.wy + 29;
	
	for (y = 0; y < cv.drw; y++) {
		xx = cv.wx + (wmode ? 12 : 14);
		for (x = 0; x < xn; x++) {
			char	buf[5] = " :";
			
			if (i >= cv.drinfo[0])
				break;
			
			buf[0] = cv.drinfo[i * 2 + 1];
			if (!cv.cap)
				buf[0] = tolower(buf[0]);
			EGB_str2(buf, xx, yy + 15, PAL_Black);
			DrawButton(1, xx + 16, yy, xx + 44, yy + 15);
			ICN_drive(cv.drinfo[i * 2 + 2], xx + 18, yy + 2);
			
			i++;
			xx += wmode ? 57 : 53;
		}
		yy += 20;
	}
}

/* modeが0のときは, ｶﾚﾝﾄ･ﾃﾞｨﾚｸﾄﾘを読み込んで描画, それ以外のときは単に描画 */
/* diroffはmode==0のときCont_pathと同じ */
int FSW_Draw_path(int mode, int *diroff) {
	int		xx, yy;
	
	xx = cv.wx + (wmode ? 250 : 6);
	yy = cv.wy + 28 + 20 * cv.drw;
	
	MOS_disp(0);
	EGB_boxf(xx, yy, xx + 383, yy + 19, 7, 7);
	MOS_disp(1);
	
	if (mode == 0) {
		if (mygetcd(cv.dirbuf))
			return -1;
		*diroff = Cont_path(cv.dirbuf, 46, cv.dirbuf2);
	}
	
	MOS_disp(0);
	EGB_str2(cv.dirbuf2, xx + 8, yy + 17, PAL_Black);
	MOS_disp(1);
	
	return 0;
}

/* ｶﾚﾝﾄﾄﾞﾗｲﾌﾞとﾃﾞｨﾚｸﾄﾘをbufへ格納 戻り値はｴﾗｰの場合-1 */
static int mygetcd(char *buf) {
	int		ret;
	
	FSW_getdrive(buf);
	strcat(buf, "\\");
	if (Get_curdir(0, buf + 3)) {
		buf[2] = 0;
		ret = -1;
	} else {
		ret = 0;
	}
	if (!cv.cap)
		strlow(0, (unsigned char *)buf);
	
	return ret;
}

/* ﾌｧｲﾙ名を描画 mode 0:読み込んで描画   1:単に描画   2:ｿｰﾄしなおして描画 */
/*    filehd:先頭のﾌｧｲﾙ番号   gf:ﾌｧｲﾙ情報   戻り値:ｴﾗｰのとき-1           */
int FSW_Draw_file(int mode, int filehd, get_f *gf) {
	int		i, xx, yy, g;
	
	xx = cv.wx + (wmode ? 250 : 6);
	yy = cv.wy + 49 + 20 * cv.drw;
	g = wmode ? 14 : 8;
	
	MOS_disp(0);
	EGB_boxf(xx, yy, xx + 367, yy + g * 20 - 1, 7, 7);
	MOS_disp(1);
	if (mode == 0) {
		int		i;
		
		if (Getfiles(cv.sort, gf, 0))
			return -1;
		if (!cv.cap) {
			for (i = 0; i < gf->nfiles; i++)
				strlow(0, (gf->pbuf[filehd + i])->name);
		}
		free(flinf);
		if ((flinf = malloc(45 * gf->nfiles)) == NULL)
			return -1;
		FSW_Setfiles(gf);
	} else if (mode == 2) {
		Getfiles(cv.sort, gf, 1);
		FSW_Setfiles(gf);
	}
	
	MOS_disp(0);
	for (i = 0; i + filehd < gf->nfiles && i < g; i++)
		FSW_Draw_file_sub(i, filehd, gf);
	MOS_disp(1);
	
	return 0;
}

/* ﾌｧｲﾙ名を描画 (1行だけ)                               */
/*    line:行番号   filehd:先頭のﾌｧｲﾙ番号   gf:ﾌｧｲﾙ情報 */
void FSW_Draw_file_sub(int line, int filehd, get_f *gf) {
	int		x, y;
	
	x = cv.wx + (wmode ? 258 : 14);
	y = cv.wy + 66 + 20 * cv.drw + line * 20;
	
	ICN_file(flinf[filehd + line][0], x, y - 15);
	EGB_str3(flinf[filehd + line] + 1, x + 32, y, PAL_Black, 7);
}

static void FSW_Setfiles(get_f *gf) {
	int		line, i, yy, mm, dd;
	char	buf_base[10], buf_ext[5];
	files	**ptr;
	
	#define F(x)	(flinf[line] + (x) + 1)
	for (line = 0; line < gf->nfiles; line++) {
		ptr = gf->pbuf + line;
		
		flinf[line][0] = Split_fname((char *)(*ptr)->name, (*ptr)->attr, buf_base, buf_ext);
		if ((*ptr)->attr & _A_SUBDIR) {
			char	*p;
			
			sprintf(F(0), "<%s%s>", buf_base, buf_ext);
			p = strchr(F(0), '\0');
			for (i = 22 - strlen(F(0)); i > 0; i--)
				*(p++) = ' ';
		} else {
			sprintf(F(0), "%-8s%-4s  ", buf_base, buf_ext);
			if ((*ptr)->sz <= 999999)
				sprintf(F(14), "%6d  ", (*ptr)->sz);
			else
				sprintf(F(14), "FFFFFF  ");
		}
		
		yy = (*ptr)->dt >> 9;
		mm = (*ptr)->dt >> 5 & 0x0f;
		dd = (*ptr)->dt & 0x1f;
		sprintf(F(22), "%2d-%2d-%2d.%2s  ", 80 + yy, mm, dd, Getyoubi(yy, mm, dd));
		sprintf(F(35), "%2d:%2d", (*ptr)->tm >> 11, (*ptr)->tm >> 5 & 0x3f);
	}
	#undef F(x)
}

/* ｽｸﾛｰﾙ･ﾊﾞｰ描画   filehd:先頭ﾌｧｲﾙ番号   nfile:ﾌｧｲﾙ数 */
void FSW_Draw_scrollB(int filehd, int nfile) {
	int		xx, yy, u, l, bar;
	struct sb_t	sb;
	
	xx = cv.wx + (wmode ? 619 : 375);
	yy = cv.wy + 65 + 20 * cv.drw;
	
	bar = wmode ? 248 : 128;
	sb.tl = nfile;	sb.lpp = (wmode ? 14 : 8);
	sb.blen = bar;	sb.bml = 15;
	SCRB_page(&sb, filehd, &u, &l);
	
	MOS_disp(0);
	if (u > 0)
		EGB_boxf(xx, yy, xx + 14, yy + u - 1, 6, 6);
	DrawButton(0, xx, yy + u, xx + 14, yy + l);
	if (l < bar - 1)
		EGB_boxf(xx, yy + l + 1, xx + 14, yy + bar - 1, 6, 6);
	MOS_disp(1);
}

void FSW_Draw_volid(int mode) {
	static char		volid[30];
	
	if (mode == 0) {
		struct find_t	ft;
		
		sprintf(volid, "ボリュームラベルは");
		if (_dos_findfirst("\\*.*", _A_VOLID, &ft)) {
			strcat(volid, "ありません");
		} else {
			strcat(volid, " ");
			if (strlen(ft.name) > 8) {
				strncat(volid, ft.name, 8);
				strcat(volid, ft.name + 9);
			} else {
				strcat(volid, ft.name);
			}
		}
		if (!cv.cap)
			strlow(0, (unsigned char *)volid);
	}
	MOS_disp(0);
	EGB_boxf(cv.wx + 9, cv.wy + 332 + 20 * cv.drw, cv.wx + 256, cv.wy + 347 + 20 * cv.drw, 7, 7);
	EGB_str2(volid, cv.wx + 9, cv.wy + 347 + 20 * cv.drw, PAL_Black);
	MOS_disp(1);
}

/* ﾃﾞｨｽｸ･ｽﾍﾟｰｽ描画   mode 0:読み込んで描画   1:単に描画 */
int FSW_Draw_diskfree(int mode) {
	int		xx, yy;
	char	buf[40];
	struct diskfree_t	diskf;
	static unsigned long	bytes;
	
	xx = cv.wx + (wmode ? 257 : 11);
	yy = cv.wy + (wmode ? 347 : 227) + 20 * cv.drw;
	
	MOS_disp(0);
	EGB_boxf(xx, yy - 15, xx + 255, yy, 7, 7);
	MOS_disp(1);
	if (mode == 0) {
		if (_dos_getdiskfree(0, &diskf))
			return -1;
		bytes = diskf.avail_clusters * diskf.sectors_per_cluster * diskf.bytes_per_sector;
	}
	
	if (bytes <= 999999999)
		Konma(bytes, buf);
	else
		sprintf(buf, "FFFFFFFFFFF");
	strcpy(buf + 11, " バイトが使用可能です");
	MOS_disp(0);
	EGB_str2(buf, xx, yy, PAL_Black);
	MOS_disp(1);
	
	return 0;
}

/* ｿｰﾄ･ｵﾌﾟｼｮﾝ用関数  戻り値が0以外の時, *yへ結果代入 */
int FSW_opt2(int *x, int *y) {
	int		i;
	struct dropdm_t	dp;
	struct menu_t	m[1];
	const char	*n[5];
	static char	nstr[][20] = {
		"   ソートなし ",
		"   種  類  別 ",
		"   名  前  順 ",
		"   作成日時順 "
	};
	char	mask[] = {
		0, 0, 0, 0
	};
	
	m[0].xt = cv.wx + (wmode ? 593 : 349);
	m[0].wt = 20;
	m[0].xm = cv.wx + (wmode ? 547 : 303);
	m[0].wm = 14;
	if (m[0].xm + m[0].wm * 8 > 639)
		m[0].xm = 639 - m[0].wm * 8;
	
	for (i = 0; i < 4; i++) {
		strncpy(nstr[i] + 1, i == cv.sort ? "※" : "  ", 2);
		n[i] = nstr[i];
	}
	n[4] = NULL;
	m[0].name = n;
	m[0].mask = mask;
	
	dp.ntitle = 1;
	dp.yt1 = cv.wy + 6;
	dp.yt2 = dp.yt1 + 19;
	dp.ym = dp.yt1 + 26;
	dp.m = m;
	dp.shadow = 0;
	
	return DRPDM_main(x, y, &dp);
}

/* 終了ﾎﾞﾀﾝ 関数   戻り値:ﾎﾞﾀﾝが押された場合1 */
int FSW_end(void) {
	return Button(cv.wx + 6, cv.wy + 6, cv.wx + 25, cv.wy + 25);
}

/* ｳｲﾝﾄﾞｳ切り換えﾎﾞﾀﾝ 関数   戻り値:ﾎﾞﾀﾝが押された場合1 */
int FSW_opt1(void) {
	int		xx;
	
	xx = cv.wx + (wmode ? 614 : 370);
	
	return Button(xx, cv.wy + 6, xx + 19, cv.wy + 25);
}

void FSW_Draw_tree(int treehd, int col, struct dirtree_t *dt, int cd) {
	int		y;
	
	MOS_disp(0);
	EGB_boxf(cv.wx + 7, cv.wy + 30 + 20 * cv.drw, cv.wx + 230, cv.wy + 309 + 20 * cv.drw, 7, 7);
	MOS_disp(1);
	FSW_Draw_trscrlB(0, treehd, dt->numd, col, dt->numc);
	FSW_Draw_trscrlB(1, treehd, dt->numd, col, dt->numc);
	MOS_disp(0);
	for (y = 0; y + treehd < dt->numd && y < 14; y++)
		FSW_Draw_tree_line(treehd, col, y, dt, cd);
	MOS_disp(1);
}

void FSW_Draw_tree_line(int treehd, int col, int line, struct dirtree_t *dt, int cd) {
	int		x, xx, yy, i;
	unsigned char	branch[40];
	
	EGB_view(cv.wx + 7, cv.wy + 30 + 20 * cv.drw, cv.wx + 230, cv.wy + 309 + 20 * cv.drw);
	x = cv.wx + 7 - 32 * col;
	
	TR_branch(1, branch, dt->tr[treehd + line].branch);
	for (i = 0; i < dt->tr[treehd + line].nest - 1; i++) {
		if (branch[i])
			EGB_line(x + 24 + 32 * i, cv.wy + 30 + (line + cv.drw) * 20, x + 24 + 32 * i, cv.wy + 49 + (line + cv.drw) * 20, PAL_Black);
	}
	xx = x + 32 * dt->tr[treehd + line].nest;
	yy = cv.wy + 47 + (line + cv.drw) * 20;
	if (treehd + line != 0) {
		if (dt->tr[treehd + line].dirn == 0xffff)
			EGB_line(xx - 8, yy - 17, xx - 8, yy - 7, PAL_Black);
		else
			EGB_line(xx - 8, yy - 17, xx - 8, yy + 2, PAL_Black);
		EGB_line(xx - 8, yy - 7, xx - 1, yy - 7, PAL_Black);
	}
	ICN_file(1, xx, yy - 15);
	EGB_str3(dt->tr[treehd + line].name, xx + 32, yy, PAL_Black, 7);
	if (treehd + line == cd)
		EGB_rev(0, xx, yy - 17, xx + (4 + strlen(dt->tr[cd].name)) * 8 - 1, yy + 2);
	EGB_view(0, 0, 1023, 511);
}

void FSW_getdrive(char *buf) {
	unsigned	dr;
	
	strcpy(buf, "A:");
	_dos_getdrive(&dr);
	buf[0] += dr - 1;
	if (!cv.cap)
		strlow(0, (unsigned char *)buf);
}

/* ﾂﾘｰ･ｽｸﾛｰﾙ･ﾊﾞｰ描画 */
void FSW_Draw_trscrlB(int hv, int trhd, int numd, int col, int numc) {
	int		xx, yy, u, l;
	struct sb_t	sb;
	
	MOS_disp(0);
	if (hv) {
		sb.tl = numd;	sb.lpp = 14;
		sb.blen = 253;	sb.bml = 15;
		SCRB_page(&sb, trhd, &u, &l);
		
		xx = cv.wx + 234;
		yy = cv.wy + 44 + 20 * cv.drw;
		if (u > 0)
			EGB_boxf(xx, yy, xx + 14, yy + u - 1, 6, 6);
		DrawButton(0, xx, yy + u, xx + 14, yy + l);
		if (l < 252)
			EGB_boxf(xx, yy + l + 1, xx + 14, yy + 252, 6, 6);
	} else {
		sb.tl = numc + 3;	sb.lpp = 7;
		sb.blen = 195;		sb.bml = 15;
		SCRB_page(&sb, col, &u, &l);
		
		xx = cv.wx + 22;
		yy = cv.wy + 314 + 20 * cv.drw;
		if (u > 0)
			EGB_boxf(xx, yy, xx + u - 1, yy + 14, 6, 6);
		DrawButton(0, xx + u, yy, xx + l, yy + 14);
		if (l < 194)
			EGB_boxf(xx + l + 1, yy, xx + 194, yy + 14, 6, 6);
	}
	MOS_disp(1);
}
