/*************************************************

	File Selecter Program

*************************************************/
#include	<stdio.h>
#include	<stdlib.h>
#include	<strings.h>
#include	<mos.h>

#define	SHORT	short int
#define	ULONG	unsigned long int

#define	TRUE	0
#define	FALSE	1
#define	ERR		(-1)

#define	M_PSET		0
#define	M_PRESET	1
#define	M_OR		2
#define	M_AND		3
#define	M_XOR		4
#define	M_NOT		5
#define	M_MATTE		6
#define	M_PASTEL	7

#define C_HWHITE     15
#define C_HYELLOW    14
#define C_HLIGHTBLUE 13
#define C_HGREEN     12
#define C_HPURPLE    11
#define C_HRED       10
#define C_HBLUE       9
#define C_HBLACK      8
#define C_WHITE       7
#define C_YELLOW      6
#define C_LIGHTBLUE   5
#define C_GREEN       4
#define C_PURPLE      3
#define C_RED         2
#define C_BLUE        1
#define C_BLACK       0

#define	FORCOL		15
#define	BAKCOL		8

typedef struct {
	SHORT	wb_dsp;
    SHORT   wb_att;
    SHORT   wb_time,wb_date;
    ULONG   wb_size;
    char    wb_name[14];
} WCBUF;

typedef struct wdtmp {
	SHORT	wd_mode;
	SHORT	wd_lx, wd_ly;
	SHORT	wd_rx, wd_ry;
	char	*wd_img;
	struct	wdtmp *wd_forwfp;
	struct	wdtmp *wd_nxtwfp;
} WINDFP;

extern void grainit(void);
extern void graend(void);
extern void	line(int x1,int y1,int x2,int y2,int col,int mode);
extern void	box(int x1,int y1,int x2,int y2,int col,int mode);
extern void	fbox(int x1,int y1,int x2,int y2,int col,int bcol,int mode);
extern void	wrtptn(char *ptn,int x,int y,int sx,int sy,int col,int bak);
extern void	wrtstr(char *str,int x,int y,int font,int ccol,int bcol);
extern void	wrtmos(int sw);
extern int	mosclip(int sw,int x,int y);
extern int  WC_open(char *dir,char *wild);
extern char *subname(char *name);
extern int  retdir(char *dir);
extern int  drvsts(int no);

extern int		wcmax;
extern WCBUF	*topwcp;
extern char		diskptn[];
extern char		exitptn[];
extern char		subptn[];
extern char		lftptn[];
extern char		ritptn[];
extern char		*work;

int		ofx=0,ofy=0,dspoff=0;
int		wd=1,lx=10,ly=5,rx=630,ry=475;

static SHORT	maxdrv=0;
static SHORT	rdydrv[20],dspdrv[20];
static int		fs_x1=0,fs_y1=0,fs_x2=0,fs_y2=0;
static int		fs_dx=0,fs_dy=0,fs_ds;
static int		fs_drv=0;
static int		fs_off=0;
static char		fs_dir[80];
static WINDFP	*fsfp;	

void	MOS_getpos(sw,x,y)
int		*sw,*x,*y;
{
	int		cgx=0,cgy=0;

	MOS_rdpos(sw,x,y);
	if ( *x > (ofx + 640) )
		ofx = *x - 640;
	else if ( *x < ofx )
		ofx = *x;
	else
		cgx = 1;

	if ( *y > (ofy + 480) )
		ofy = *y - 480;
	else if ( *y < ofy )
		ofy = *y;
	else
		cgy = 1;

	if ( cgx != 0 || cgy != 0 ) {
		EGB_writePage(work,1);
		EGB_displayStart(work,1,ofx,(ofy + dspoff) & (512 - 1));
		EGB_writePage(work,0);
		EGB_displayStart(work,1,ofx,ofy);
	}
}
void	drvset(void)
{
	int		i;

	for ( i = maxdrv = 0 ; i < 20 ; i++ ) {
		if ( drvsts(i) == 0 ) {
			dspdrv[i] = maxdrv;
			rdydrv[maxdrv++] = i;
		}
	}
}
void	FS_dspdrv(int drv,int mode)
{
	int		n,x,y,fcol,bcol;

	n = dspdrv[drv];
	if ( mode == 0 ) {
		fcol = FORCOL; bcol = BAKCOL;
	} else {
		bcol = FORCOL; fcol = BAKCOL;
	}
	x = fs_dx + (n % 5) * 64;
	y = fs_y1 + 26 + (n / 5) * 16;
	wrtstrf(x,y,0,fcol,bcol,"%c:",'A'+drv);
	wrtptn(diskptn,x+16,y,32,16,fcol,bcol);	
}
void	FS_dspfile(int no)
{
	int		i,fcol,bcol;

	if ( no >= wcmax || no < fs_off || no >= (fs_off + 27) )
		return;

	if ( topwcp[no].wb_dsp == 0 ) {
		fcol = FORCOL; bcol = BAKCOL;
	} else {
		bcol = FORCOL; fcol = BAKCOL;
	}		

	i = no - fs_off;
	wrtstr(subname(topwcp[no].wb_name),
		   fs_dx + (i / 9) * 106, fs_dy + 32 + (i % 9) * 16,
		   (topwcp[no].wb_att & 0x10) != 0 ? 1 : 0,
		   fcol,bcol);
}
void	FS_alldsp(int off)
{
	int		i,j,k;

	fbox(fs_dx, fs_dy + 32, fs_x2 - 4, fs_y2 - 22,
		 BAKCOL,BAKCOL,M_PSET);
	fs_off = off;
	for ( i = 0 ; i < 27 ; i++ )
		FS_dspfile(off + i);

	if ( wcmax == 0 ) {
		j = 0; k = 285;
	} else {
		i = (285 * 9) / wcmax;
		j = (fs_off / 9) * i;
		if ( (k = j + 3 * i) > 285 )
			k = 285;
	}
	fbox(fs_x1+19,fs_y2-18,fs_x1+308,fs_y2-3,FORCOL,BAKCOL,M_PSET);
	box(fs_x1+21+j,fs_y2-16,fs_x1+21+k,fs_y2-5,FORCOL,M_PSET);
}
void	FS_cngdrv(char *dir,char *wild)
{
	int		x,y;
	char	tmp[80];

	wrtmos(1);
	x = fs_dx + (dspdrv[fs_drv] % 5) * 64 + 21;
	y = fs_y1 + (dspdrv[fs_drv] / 5) * 16 + 36;
	box(x,y,x+1,y+1,C_HRED,M_PSET);
	sprintf(tmp,"%c:%s",'A'+fs_drv,dir);
	WC_open(tmp,wild);
	fs_drv = retdir(fs_dir);
	fbox(fs_dx,fs_dy+8,fs_x2 - 8,fs_dy+24,BAKCOL,BAKCOL,M_PSET);
	wrtstr(fs_dir,fs_dx,fs_dy+8,0,FORCOL,BAKCOL);
	FS_alldsp(0);
	box(x,y,x+1,y+1,BAKCOL,M_PSET);
	wrtmos(0);
}
void	FS_open(int dx, int dy)
{
	int		i;

	if ( maxdrv == 0 )
		drvset();
	fs_ds = ((maxdrv + 4) / 5) * 16;
	fs_x1 = dx & 0xfffe; 
	fs_y1 = dy & 0xfffe;
	fs_x2 = fs_x1 + 328;
	fs_y2 = fs_y1 + 224 + fs_ds;

	fs_dx = fs_x1 + 8;
	fs_dy = fs_y1 + 26 + fs_ds;

	fbox(fs_x1,fs_y1,fs_x2,fs_y2,FORCOL,BAKCOL,M_PSET);
	fbox(fs_x1+2,fs_y1+2,fs_x2-2,fs_y1+20,FORCOL,FORCOL,M_PSET);
	wrtstr("FILE SELECTER",fs_x1+112,fs_y1+3,1,BAKCOL,FORCOL);
	wrtptn(subptn,fs_x2-20,fs_y1+3,16,16,BAKCOL,FORCOL);
	wrtptn(exitptn,fs_dx,fs_y1+3,16,16,BAKCOL,FORCOL);
	line(fs_x1,fs_dy+4,fs_x2,fs_dy+4,FORCOL,M_PSET);
	line(fs_x1,fs_dy+28,fs_x2,fs_dy+28,FORCOL,M_PSET);
	wrtptn(lftptn,fs_x1+2,fs_y2-18,16,16,FORCOL,BAKCOL);
	wrtptn(ritptn,fs_x2-18,fs_y2-18,16,16,FORCOL,BAKCOL);
	fsfp = (WINDFP *)WIN_dmyopen(fs_x1,fs_y1,fs_x2,fs_y2);

	fs_drv = retdir(fs_dir);
	for ( i = 0 ; i < maxdrv ; i++ )
		FS_dspdrv(rdydrv[i],(rdydrv[i] == fs_drv ? 1 : 0));
	FS_cngdrv("","*.*");
}
void	FS_drvsel(void)
{
	int		old,i,b,x,y;

	old = dspdrv[fs_drv];
	do {
		MOS_rdpos(&b,&x,&y);
		i = (x - fs_dx) / 64 + ((y - fs_y1 - 26) / 16) * 5;
		if ( i >= 0 && i < maxdrv ) {
			if ( old != i ) {
				FS_dspdrv(rdydrv[old],0);
				FS_dspdrv(rdydrv[i],1);
				old = i;
			}
		}
	} while ( b != 0 );
	if ( old != fs_drv ) {
		fs_drv = rdydrv[old];
		FS_cngdrv("","*.*");
	}
}
void	FS_dspdir(int len)
{
	char	tmp[80];

	if ( len > 0 ) {
		strcpy(tmp,fs_dir);
		tmp[len] = '\0';
		wrtstr(tmp,fs_dx,fs_dy+8,0,BAKCOL,FORCOL);
	}
	wrtstr(fs_dir+len,fs_dx + len * 8,fs_dy+8,0,FORCOL,BAKCOL);
}
void	FS_dirsel(void)
{
	int		len,old,i,b,x,y;

	len = strlen(fs_dir);
	i = old = 0;
	do {
		MOS_rdpos(&b,&x,&y);
		if ( y >= (fs_dy + 8) && y <= (fs_dy + 24) &&
			 x >= fs_dx && x <= (fs_dx + len * 8) ) {
			i = (x - fs_dx) / 8;
			while ( fs_dir[i] != '\0' && fs_dir[i] != '\\' )
				i++;
			if ( fs_dir[i] == '\\' ) i++;
		} else
			i = 0;
		if ( i != old ) {
			FS_dspdir(i);
			old = i;
		}
	} while ( b != 0 );
	if ( old > 2 ) {
		if ( old > 3 && fs_dir[old] != '\0' )
			old--;
		fs_dir[old] = '\0';
		FS_cngdrv(fs_dir+2,"*.*");
	}
}
void	FS_newwind(int no)
{
	int		i,b,x,y;
	int		x1,y1,x2,y2;
	int		sx1,sy1,sx2,sy2;

	wrtmos(2);
	i = no - fs_off;
	x1 = fs_dx + (i / 9) * 106; y1 = fs_dy + 32 + (i % 9) * 16;
	x2 = x1 + 96; y2 = y1 + 15;

	MOS_getpos(&b,&x,&y);
	sx1 = x - x1; sy1 = y - y1;
	do {
		box(x1,y1,x2,y2,15,M_XOR);
		MOS_getpos(&b,&x,&y);
		box(x1,y1,x2,y2,15,M_XOR);
		x -= sx1; y -= sy1;
		if ( x >= 0 ) x1 = x; else x1 = 0;
		if ( y >= 0 ) y1 = y; else y1 = 0;
		x2 = x1 + 96; y2 = y1 + 15;
		if ( x2 >= 1024 ) { x1 = 926; x2 = 1023; }
		if ( y2 >= 512 ) { y1 = 496; y2 = 511; }
	} while ( b == 0 );

	if ( (b & 2) != 0 ) goto ABORT;
	if ( (lx = x1 - 102) < 0 ) lx = 0;
	if ( (ly = y1 - 50 ) < 0 ) ly = 0;
	if ( (rx = lx + 300) >= 1024 ) { lx = 723; rx = 1023; }
	if ( (ry = ly + 200) >= 512 ) { ly = 311; ry = 511; }

	sx1 = (lx - x1) / 10; sy1 = (ly - y1) / 10;
	sx2 = (rx - x2) / 10; sy2 = (ry - y2) / 10;

	for ( i = 10 ; i > 0 ; i-- ) {
		box(x1,y1,x2,y2,15,M_XOR);
		box(x1,y1,x2,y2,15,M_XOR);
		x1 += sx1; y1 += sy1;
		x2 += sx2; y2 += sy2;
	}
	wrtmos(1);
	if ( WIN_open(topwcp[no].wb_name,topwcp[no].wb_name,
				  topwcp[no].wb_size,0,lx,ly,rx,ry,
				  C_HWHITE, C_HBLACK, C_HWHITE) == 0 )
		MSG_disp("Can't open Text Wind...",C_HRED);
ABORT:
	wrtmos(0);
}
void	FS_filesel(void)
{
	int		old,i,b,x,y;
	char	*p;

	old = wcmax;
	do {
		MOS_rdpos(&b,&x,&y);		
		i = ((x - fs_dx) / 106) * 9 + (y - fs_dy - 32) /16;
		if ( y >= (fs_dy + 32 ) && y <= (fs_dy + 176) &&
			 i >= 0 && i < (wcmax - fs_off) ) {
			i += fs_off;
			if ( old != i ) {
				if ( old < wcmax ) {
					topwcp[old].wb_dsp = 0;
					FS_dspfile(old);
				}
				if ( topwcp[i].wb_dsp != 0 )
					topwcp[i].wb_dsp = 0;
				else
					topwcp[i].wb_dsp = 1;
				FS_dspfile(i);
				old = i;
			}
		} else if ( old < wcmax ) {
			topwcp[old].wb_dsp = 0;
			FS_dspfile(old);
			old = wcmax;
		}
	} while ( b != 0 );

	if ( old < wcmax ) {
		topwcp[old].wb_dsp = 0;
		FS_dspfile(old);
		if ( (topwcp[old].wb_att & 0x10) != 0 )
			FS_cngdrv(topwcp[old].wb_name,"*.*");
		else {
			p = subname(topwcp[old].wb_name);
			if ( strcmp(p+9,"SND") == 0 )
				runsnd(topwcp[old].wb_name);
			else if ( strcmp(p+9,"EUP") == 0 )
				runeup(topwcp[old].wb_name);
			else
				FS_newwind(old);
		}
	}
}
void	FS_dspmov(int old,int fra,int bak)
{
	if ( old > fs_off )
		wrtptn(lftptn,fs_x1+2,fs_y2-18,16,16,fra,bak);
	else
		wrtptn(ritptn,fs_x2-18,fs_y2-18,16,16,fra,bak);
}
void	FS_movesel()
{
	int		old,b,x,y;

	old = fs_off;
	MOS_rdpos(&b,&x,&y);		
	if ( x >= fs_x1 && x <= fs_x2 && 
		 y >= (fs_y2 - 20) && y <= (fs_y2 - 4) ) {
		if ( x <= (fs_x1 + 24) && fs_off > 0 )
			fs_off -= 9;
		else if ( x >= (fs_x2 - 24) && (fs_off + 27) <= wcmax )
			fs_off += 9;
		if ( old != fs_off ) {
			FS_dspmov(old,BAKCOL,FORCOL);
			FS_alldsp(fs_off);
			FS_dspmov(old,FORCOL,BAKCOL);
			old = fs_off;
		}
	}
}
void	FS_resize(void)
{
	fs_x1 = fsfp->wd_lx;
	fs_y1 = fsfp->wd_ly;
	fs_x2 = fs_x1 + 328;
	fs_y2 = fs_y1 + 224 + fs_ds;
	fs_dx = fs_x1 + 8;
	fs_dy = fs_y1 + 26 + fs_ds;
}
int		FS_finis(void)
{
	static char *menu[]={ "CLOSE ALL WIND","END OF LOOKING",NULL };
	int		i;

/*	wrtptn(exitptn,fs_dx,fs_y1+3,16,16,FORCOL,BAKCOL); */
	i = MENU_select(menu);
/*	wrtptn(exitptn,fs_dx,fs_y1+3,16,16,BAKCOL,FORCOL); */
	if ( i == 1 )
		return (-1);
	else if ( i == 0 )
		WIN_allclose(fsfp);
	return 0;
}
void	FS_fremem(void)
{
	int		mx,sz,fm;
	char	*dmy[128];
	char	tmp[80];

	for ( sz = 0x10000,fm = mx = 0 ; mx < 128 ; mx++ ) {
		while ( (dmy[mx] = malloc(sz)) == NULL ) {
			if ( (sz /= 2) < 0x1000 )
				break;
		}
		if ( dmy[mx] == NULL )
			break;
		fm += sz;
	}
	while ( mx > 0 )
		free(dmy[--mx]);
	sprintf(tmp,"%dK Byte Free Memory",fm / 1000);
	MSG_disp(tmp,C_HGREEN);
}
void	FS_sub(void)
{
	static char *menu[]={ "FREE MEMORY","WILD CARD",NULL };
	static char *wmenu[]={ "*.*",  "TEXT","SUND","GRPH",NULL };
	static char *wildt[]={ "*.*",  "*.DOC","*.HLP","*.BAT",
						   "*.C",  "*.ASM","*.LST","*.TXT",NULL };
	static char *wilds[]={ "*.EUP","*.SND","*.FMB","*.PMB",NULL };
	static char *wildg[]={ "*.TIF","*.GRP","*.GIF","*.GED","*.FIG",
					       "*.PIC","*.P16","*.P25","*.P32",NULL };
	int		i;
	char	*p;

/*	wrtptn(subptn,fs_x2-20,fs_y1+3,16,16,FORCOL,BAKCOL); */
	i = MENU_select(menu);
	if ( i == 0 )
		FS_fremem();
	else if ( i == 1 && (i = MENU_select(wmenu)) >= 0 ) {
		switch(i) {
			case 0: p = wmenu[0]; break;
			case 1:
				if ( (i = MENU_select(wildt)) >= 0 ) 
					p = wildt[i];
				break;
			case 2:
				if ( (i = MENU_select(wilds)) >= 0 )
					p = wilds[i];
				break;
			case 3:
				if ( (i = MENU_select(wildg)) >= 0 )
					p = wildg[i];
				break;
		}
		if ( i >= 0 )
			FS_cngdrv("",p);
	}
/*	wrtptn(subptn,fs_x2-20,fs_y1+3,16,16,BAKCOL,FORCOL); */
}
int		FS_select(void)
{
	int		b,x,y;

	MOS_rdpos(&b,&x,&y);
	if ( b != 0 && x >= fs_x1 && x <= fs_x2 && 
				   y >= fs_y1 && y <= fs_y2 ) {
		if ( y >= (fs_y1 + 26) && y <= fs_dy )
			FS_drvsel();
		else if ( y >= (fs_dy + 8) && y <= (fs_dy + 24) )
			FS_dirsel();
		else if ( y >= (fs_dy + 32) && y <= (fs_dy + 176) )
			FS_filesel();
		else if ( y >= (fs_y2 - 20) && y <= (fs_y2 - 4) )
			FS_movesel();
		else if ( x <= (fs_x1 + 20) && y <= (fs_y1 + 20) )
			return FS_finis();
		else if ( x >= (fs_x2 - 20) && y <= (fs_y1 + 20) )
			FS_sub();
		else if ( y <= (fs_y1 + 20) ) {
			WIN_move(fsfp);
			FS_resize();
		} else
			return 1;
	}
	return 0;
}
/***********************************************************/
/***********************************************************/
void	main(int argc,char *argv[])
{
	int		i,b,x,y,ev;
	WINDFP	*dmy;

	grainit();
	if ( argc > 1 ) {
		y = 470 / (argc - 1);
		while ( --argc > 0 ) {
			argv++;
			WIN_open(argv[0],argv[0],16384,0,lx,ly,rx,ly+y,
					 C_HWHITE, C_HBLACK, C_HWHITE);
		}
		WIN_allselect();
	} else {
		FS_open(10,180);
		for ( ; ; ) {
			MOS_getpos(&b,&x,&y);
			if ( (dmy = (WINDFP *)WIN_allevent(&ev)) != NULL ) {
				if ( ev == (-1) )
					MSG_disp("Memory Full Error !!",C_HRED);
				else if ( dmy == fsfp ) {
					if ( FS_select() == (-1) )
						break;
				} else
					WIN_select(dmy,ev);
			}
		}
	}
	fbox(220,190,440,290,C_LIGHTBLUE,C_HBLACK,M_PSET);
	wrtstr("ＬＯＯＫを終了しました",244,220,0,C_LIGHTBLUE,C_HBLACK);
	wrtstr("しばらくお待ちください｡",244,250,0,C_LIGHTBLUE,C_HBLACK);
	graend();
}
