#include <stdio.h>
#include <string.h>
#include <dir.h>
#include <sys/extender.h>
#include <register.h>
#include <libio.h>
#include <egb.h>
#include "sort.h"
#include "symbol.h"
#include "fsdat.c"

#define ERR		1
#define NOERR	0

#define A_RAF	0x00
#define A_ROF	0x01
#define A_HND	0x02
#define A_SYS	0x04
#define A_SUB	0x10

#define	ON		1
#define	OFF		0

typedef struct
{
	char	fullname[16];
	char	outname[16];
	char	attrib;
} FILEINF ;


extern int	FS_fileSelect( char *, char *, char * );
extern int	FS_locate( int, int );
static int	FS_x = 0;
static int	FS_y = 0;
static char	c_dir[256];
static char	drv[2];
static char *egbwork;
static int	diskch( int d );

static int	diskch( int d )
{
	struct	SREGS	seg;
	union	REGS	creg,rreg;

	int		s,o;
	char	buf[512];

	nativetoreal( buf, 1, &s, &o );
	segread( &seg );
	creg.h.al = d;
	creg.x.bx = o;
	seg.ss = s;
	creg.x.cx = 0;
	creg.x.dx = 0;
	intreal( 0x25, &creg, &rreg, &seg );

	return ( rreg.x.cflag & 1 );
}

int		FS_locate( int x, int y )
{
	if( x<0 || x>511 || y<0 || y>263 )
		return ERR;

	FS_x = x;
	FS_y = y;

	return NOERR;
}

static void	FS_end( char *grp_buf )
{
	MOS_disp( 0 );
	EGB_writeMode( egbwork, 0 );
	EGB_putRect( egbwork, 0, grp_buf, FS_x, FS_y, 127+FS_x, 215+FS_y );
	return;
}

static int	upButton( int cx, int cy )
{
	static int	UB_flg = OFF;

	if( cx<108+FS_x || cy<49+FS_y || cx>122+FS_x || cy>63+FS_y )
	{
		if( UB_flg == ON )
		{
			UB_flg = OFF;
			MOS_disp( 0 );
			EGB_writeMode( egbwork, 4 );
			EGB_paintMode( egbwork, 0x22 );
			EGB_foreColor( egbwork, 15 );
			EGB_paintColor( egbwork, 15 );
			EGB_box( egbwork, 108+FS_x, 49+FS_y, 122+FS_x, 63+FS_y );
			MOS_disp( 1 );
		}
		return 0;
	}

	if( UB_flg != ON )
	{
		UB_flg = ON;
		MOS_disp( 0 );
		EGB_writeMode( egbwork, 4 );
		EGB_paintMode( egbwork, 0x22 );
		EGB_foreColor( egbwork, 15 );
		EGB_paintColor( egbwork, 15 );
		EGB_box( egbwork, 108+FS_x, 49+FS_y, 122+FS_x, 63+FS_y );
		MOS_disp( 1 );
	}

	return 1;
}

static int	downButton( int cx, int cy )
{
	static int	DB_flg = OFF;

	if( cx<108+FS_x || cy<196+FS_y || cx>122+FS_x || cy>210+FS_y )
	{
		if( DB_flg == ON )
		{
			DB_flg = OFF;
			MOS_disp( 0 );
			EGB_writeMode( egbwork, 4 );
			EGB_paintMode( egbwork, 0x22 );
			EGB_foreColor( egbwork, 15 );
			EGB_paintColor( egbwork, 15 );
			EGB_box( egbwork, 108+FS_x, 196+FS_y, 122+FS_x, 210+FS_y );
			MOS_disp( 1 );
		}
		return 0;
	}

	if( DB_flg != ON )
	{
		DB_flg = ON;
		MOS_disp( 0 );
		EGB_writeMode( egbwork, 4 );
		EGB_paintMode( egbwork, 0x22 );
		EGB_foreColor( egbwork, 15 );
		EGB_paintColor( egbwork, 15 );
		EGB_box( egbwork, 108+FS_x, 196+FS_y, 122+FS_x, 210+FS_y );
		MOS_disp( 1 );
	}

	return 1;
}

static int	incDriveNum( int cx, int cy )
{
	static int	ID_flg = OFF;

	if( cx<39+FS_x || cy<27+FS_y || cx>55+FS_x || cy>44+FS_y )
	{
		if( ID_flg == ON )
		{
			ID_flg = OFF;
			MOS_disp( 0 );
			EGB_writeMode( egbwork, 4 );
			EGB_paintMode( egbwork, 0x22 );
			EGB_foreColor( egbwork, 15 );
			EGB_paintColor( egbwork, 15 );
			EGB_box( egbwork, 39+FS_x, 27+FS_y, 55+FS_x, 44+FS_y );
			MOS_disp( 1 );
		}
		return 0;
	}

	if( ID_flg != ON )
	{
		ID_flg = ON;
		MOS_disp( 0 );
		EGB_writeMode( egbwork, 4 );
		EGB_paintMode( egbwork, 0x22 );
		EGB_foreColor( egbwork, 15 );
		EGB_paintColor( egbwork, 15 );
		EGB_box( egbwork, 39+FS_x, 27+FS_y, 55+FS_x, 44+FS_y );
		MOS_disp( 1 );
	}

	return 1;

}

static int	decDriveNum( int cx, int cy )
{
	static int	DD_flg = OFF;

	if( cx<9+FS_x || cy<27+FS_y || cx>25+FS_x || cy>44+FS_y )
	{
		if( DD_flg == ON )
		{
			DD_flg = OFF;
			MOS_disp( 0 );
			EGB_writeMode( egbwork, 4 );
			EGB_paintMode( egbwork, 0x22 );
			EGB_foreColor( egbwork, 15 );
			EGB_paintColor( egbwork, 15 );
			EGB_box( egbwork, 9+FS_x, 27+FS_y, 25+FS_x, 44+FS_y );
			MOS_disp( 1 );
		}
		return 0;
	}

	if( DD_flg != ON )
	{
		DD_flg = ON;
		MOS_disp( 0 );
		EGB_writeMode( egbwork, 4 );
		EGB_paintMode( egbwork, 0x22 );
		EGB_foreColor( egbwork, 15 );
		EGB_paintColor( egbwork, 15 );
		EGB_box( egbwork, 9+FS_x, 27+FS_y, 25+FS_x, 44+FS_y );
		MOS_disp( 1 );
	}

	return 1;
}

static int	fileNameCheck( int cx, int cy )
{
	static int	s = 0;

	if( cx<10+FS_x || cy<50+FS_y || cx>105+FS_x || cy>209+FS_y )
	{
		if( s > 0 )
		{
			s = 0;
		}
		return 0;
	}

	if( s != (cy-FS_y-50)/16 + 1 )
	{
		s = (cy-FS_y-50)/16 + 1;
	}

	return s;
}

int		FS_fileSelect( char *w, char *wild, char *path )
{
	struct ffblk	fb;
	int		attrib = 0x17;
	char	wildcard[60];
	FILEINF	f_inf[128];
	int		fnum,ptop,i,j,sw,cx,cy,sel,loop_f;
	char	*fname;
	char	buf1[64];
	char	testname[256];
	char	grp_buf[13824];
	char	*s,*t,buf2[8];
	char	*sortbuf[128];
	int		sortlank[128];

	egbwork = w;
	drv[0] = 'A' + _dos_get_default_disk_number();
	drv[1] = 0;
/*	getcwd( c_dir, 60 );*/
	_dos_get_current_directory( drv[0] - 'A' + 1, buf1 );
	strcpy( c_dir, "\\" );
	strcat( c_dir, buf1 );

	EGB_writeMode( egbwork, 0 );
	EGB_getRect( egbwork, grp_buf, FS_x, FS_y, 127+FS_x, 215+FS_y );
	EGB_putRect( egbwork, 0, FS_grp_data, FS_x, FS_y, 127+FS_x, 215+FS_y );

START:
	MOS_disp( 0 );

	strcpy( wildcard, drv );
	strcat( wildcard, ":" );
	strcat( wildcard, c_dir );
	if( *(c_dir+1) )
		strcat( wildcard, "\\" );
	strcat( wildcard, wild );

	fnum = 0;
	if( findfirst( wildcard, &fb, attrib ) == 0 )
	{
		strcpy( f_inf[fnum].fullname, fb.ff_name );
		s = buf1;
		t = fb.ff_name;
		while( *t != 0 && *t != '.' )
		{
			*s++ = *t++;
		}
		*s = 0;

		if( *t == 0 )
			*buf2 = 0;
		else
		{
			++t;
			strcpy( buf2, t );
		}
		if( (f_inf[fnum].attrib = fb.ff_attrib) & A_SUB )
		{
			strcpy( f_inf[fnum].outname, "<" );
			strcat( f_inf[fnum].outname, fb.ff_name );
			while( strlen( f_inf[fnum].outname ) < 11 )
				strcat( f_inf[fnum].outname, " " );
			strcat( f_inf[fnum].outname, ">" );
		}
		else
		{
			strcpy( f_inf[fnum].outname, buf1 );
			while( strlen( f_inf[fnum].outname ) < 8 )
				strcat( f_inf[fnum].outname, " " );
			strcat( f_inf[fnum].outname, "." );
			strcat( f_inf[fnum].outname, buf2 );
		}
		++fnum;

		while( findnext( &fb ) == 0 )
		{
			strcpy( f_inf[fnum].fullname, fb.ff_name );
			s = buf1;
			t = fb.ff_name;
			while( *t != 0 && *t != '.' )
			{
				*s++ = *t++;
			}
			*s = 0;

			if( *t == 0 )
				*buf2 = 0;
			else
			{
				++t;
				strcpy( buf2, t );
			}
			if( (f_inf[fnum].attrib = fb.ff_attrib) & A_SUB )
			{
				strcpy( f_inf[fnum].outname, "<" );
				strcat( f_inf[fnum].outname, fb.ff_name );
				while( strlen( f_inf[fnum].outname ) < 11 )
					strcat( f_inf[fnum].outname, " " );
				strcat( f_inf[fnum].outname, ">" );
			}
			else
			{
				strcpy( f_inf[fnum].outname, buf1 );
				while( strlen( f_inf[fnum].outname ) < 8 )
					strcat( f_inf[fnum].outname, " " );
				strcat( f_inf[fnum].outname, "." );
				strcat( f_inf[fnum].outname, buf2 );
			}
			++fnum;
		}
	}

	for( i=0; i<fnum; i++ )
		sortbuf[i] = f_inf[i].outname;
	sort( SORT_SHELL, SORT_STR, sortbuf, fnum, sortlank );

	EGB_writeMode( egbwork, 0 );
	EGB_paintMode( egbwork, 0x22 );
	EGB_foreColor( egbwork, 0 );
	EGB_paintColor( egbwork, 0 );
	EGB_box( egbwork, 10+FS_x, 8+FS_y, 105+FS_x, 23+FS_y );
	EGB_box( egbwork, 58+FS_x, 28+FS_y, 105+FS_x, 43+FS_y );
	EGB_box( egbwork, 28+FS_x, 28+FS_y, 36+FS_x, 43+FS_y );

	EGB_foreColor( egbwork, 15 );
	strcpy( buf1, c_dir );
	buf1[12] = 0;
	symbol( egbwork, 10+FS_x, 23+FS_y, buf1 );
	symbol( egbwork, 58+FS_x, 43+FS_y, wild );
	symbol( egbwork, 28+FS_x, 43+FS_y, drv );

	do
	{
		MOS_rdpos( &sw, &cx, &cy );
	}
	while( sw );

	loop_f = 1;
	ptop = 0;
	while( loop_f )
	{
		EGB_writeMode( egbwork, 0 );
		EGB_paintMode( egbwork, 0x22 );
		EGB_foreColor( egbwork, 0 );
		EGB_paintColor( egbwork, 0 );
		EGB_box( egbwork, 10+FS_x, 50+FS_y, 105+FS_x, 209+FS_y );

		EGB_foreColor( egbwork, 15 );
		for( j=0; j<10; j++ )
		{
			if( ptop+j < fnum )
				symbol( egbwork, 10+FS_x, j*16+65+FS_y, f_inf[sortlank[ptop+j]].outname );
		}

		MOS_disp( 1 );

		sw = 0;
		while( (sw & 2) == 0 )
		{
			MOS_rdpos( &sw, &cx, &cy );

			if( incDriveNum( cx, cy ) && (sw & 1) )
			{
				i = 0;
				while(1)
				{
					drv[0] = ( drv[0] == 'Z' )? 'A':++(drv[0]);
					if( diskch( drv[0] - 'A' ) == 0 )
						break;
				}
				_dos_get_current_directory( drv[0] - 'A' + 1, buf1 );
				strcpy( c_dir, "\\" );
				strcat( c_dir, buf1 );
				loop_f = 0;
				sw = 5;
				break;
			}
			if( decDriveNum( cx, cy ) && (sw & 1) )
			{
				i = 0;
				while(1)
				{
					drv[0] = ( drv[0] == 'A' )? 'Z':--(drv[0]);
					if( diskch( drv[0] - 'A' ) == 0 )
						break;
				}
				_dos_get_current_directory( drv[0] - 'A' + 1, buf1 );
				strcpy( c_dir, "\\" );
				strcat( c_dir, buf1 );
				loop_f = 0;
				sw = 5;
				break;
			}

			if( upButton( cx, cy ) && (sw & 1) && ptop>0 )
			{
				--ptop;
				break;
			}
			if( downButton( cx, cy ) && (sw & 1) && ptop+10<fnum )
			{
				++ptop;
				break;
			}
			if( ( sel = fileNameCheck( cx, cy ) ) && (sw & 1) )
			{
				if( ptop+sel-1 < fnum )
				{
					loop_f = 0;
					break;
				}
			}
		}
		if( sw & 2 )
		{
			FS_end( grp_buf );
			return ERR;
		}
	}

	if( sw == 5 )
		goto START;

	if( f_inf[sortlank[ptop+sel-1]].attrib & A_SUB )
	{
		if( strcmp( f_inf[sortlank[ptop+sel-1]].fullname, "." ) == 0 )
		{
			goto START;
		}
		if( strcmp( f_inf[sortlank[ptop+sel-1]].fullname, ".." ) == 0 )
		{
			char	*s;
			s = c_dir;

			while( *s )
				++s;

			while( *s != '\\' )
				--s;

			if( s == c_dir )
				*(c_dir+1) = 0;
			else
				*s = 0;

			goto START;
		}

		if( *(c_dir+1) )
			strcat( c_dir, "\\" );
		strcat( c_dir, f_inf[sortlank[ptop+sel-1]].fullname );
		goto START;
	}

	strcpy( path, drv );
	strcat( path, ":" );
	strcat( path, c_dir );
	if( *(c_dir+1) )
		strcat( path, "\\" );
	strcat( path, f_inf[sortlank[ptop+sel-1]].fullname );

	FS_end( grp_buf );
	return NOERR;
}
