#include    <stdio.h>
#include    <stdlib.h>
#include    <ctype.h>
#include    <strings.h>
#include    <msdos.cf>
/* ------------------ Debug  91.08.28 Pumpkin --------------- */
#include    <dos.h>
/* ---------------------------------------------------------- */

#define SHORT   short int
#define LONG    long int
#define ULONG   unsigned long int
#define BOOL    int

#define TRUE    1
#define FALSE   0
#define ERR     (-1)

#define	MAXWCP	300

typedef struct {
    SHORT   wb_dsp;
    SHORT   wb_att;
    SHORT   wb_time,wb_date;
    ULONG   wb_size;
    char    wb_name[14];
} WCBUF;

extern void	wrtstr();
extern void	Dmy_form();
extern int	getch();
extern void	Dsp_vram_flash();

static int	wcmax=0;
static WCBUF	*topwcp=NULL;
static char	dir[80];
static char     wild[80];

char    *endname(char *name)
{
    char    *p;

    for ( p=name ; *p != '\0' ; p++ );
    for ( ; p != name && *p != '\\' && *p != ':' ; p-- );
    if ( p != name )
        p++;
    return p;
}
char	*subname(char *name)
{
    static char tmp[14];
    int	    i;
    char    *p;

    if ( *name == '.' ) {
	for ( i = 0,p = tmp ; i < 9 ; i++ ) {
	    if ( *name == '\0' )
		*(p++) = ' ';
	    else
		*(p++) = *(name++);
	}
    } else {
	for ( i = 0,p = tmp ; i < 9 ; i++ ) {
	    if ( *name == '.' || *name == '\0' )
		*(p++) = ' ';
	    else
		*(p++) = *(name++);
	}
	if ( *name == '.' ) name++;
    }
    for ( ; i < 12 ; i++ ) {
	if ( *name == '\0' )
	    *(p++) = ' ';
	else
	    *(p++) = *(name++);
    }
    *p = '\0';
    return tmp;	
}
int	cmpname(char *arg,char *str)
{
    int     i;
    char    *p,tmp[14];

    strcpy(tmp,subname(arg));
    p = subname(str);
    if ( (i = strcmp(tmp + 9,p + 9)) != 0 )
	return i;
    tmp[9] = p[9] = '\0';
    return strcmp(tmp,p);
}
void	sort(int bs,int mx)
{
    int     i,j;
    WCBUF   x,w;

    i=bs;
    j=mx;
    memcpy(&x,&(topwcp[bs + (mx - bs) / 2]),sizeof(WCBUF));
    do {
        while ( cmpname(topwcp[i].wb_name, x.wb_name) < 0 )
            i++;
        while ( cmpname(topwcp[j].wb_name, x.wb_name) > 0 )
            j--;
        if ( i <= j ) {
            memcpy(&w,&(topwcp[i]),sizeof(WCBUF));
            memcpy(&(topwcp[i]),&(topwcp[j]),sizeof(WCBUF));
            memcpy(&(topwcp[j]),&w,sizeof(WCBUF));
            i++; j--;
        }
    } while ( i <= j );
    if ( bs < j )
        sort(bs,j);
    if ( i < mx )
        sort(i,mx);
}
BOOL	subwc(char *arg,int mode,WCBUF *wcp)
{
    static BOOL opflg=FALSE;
    static struct {
        char    dd_dmy[22];
        SHORT   dd_time,dd_date;
        LONG    dd_size;
        char    dd_name[13];
    } dma;

    if ( opflg == FALSE ) {
        Registers.AX.R = 0x1A00;
        Registers.DX.R = (int)&dma;
        Registers.DS.R = getds();
        calldos(); 
        Registers.AX.R = 0x4E00;
        Registers.CX.R = mode;
        Registers.DX.R = (int)arg;
        Registers.DS.R = getds();
        opflg = TRUE;
    }
    else
        Registers.AX.R = 0x4F00;

    calldos();
    if ( (Registers.Flags & 0x0001) != 0 ) {
        opflg = FALSE;
	return FALSE;
    }

    wcp->wb_dsp = 0;
    wcp->wb_att = dma.dd_dmy[21];
    wcp->wb_date = dma.dd_date;
    wcp->wb_time = dma.dd_time;
    wcp->wb_size = dma.dd_size;
    strcpy(wcp->wb_name,dma.dd_name);
    return TRUE;
}
void	chdir(char *name)
{
    char tmp[129],i;
    strcpy(tmp,name); i = strlen(tmp);
    if (i > 3 && tmp[i-1] == '\\') tmp[i-1] = 0;

    Registers.AX.R = 0x3B00;
    Registers.DX.R = (int)name;
    Registers.DS.R = getds();
    calldos();
    if ( name[1] == ':' ) {
	Registers.AX.R = 0x0E00;
	Registers.DX.R = (*name & 0xDF) - 'A';
	calldos();
    }
}
/* ------------------ Debug  92.02.07 Pumpkin --------------- */
int	diskReady(int drive)
{
    Registers.AX.R = 0x3600;
    Registers.DX.R = drive;
    calldos();
    if (Registers.AX.R == 0xffff) return ERR;
    return FALSE;
}
/* ---------------------------------------------------------- */
int	retdir(char *name)
{
/* ------------------ Debug  92.02.07 Pumpkin --------------- */
    if (diskReady(0) == ERR) {
	*(long *)name = 0;
	return ERR;
    }
/* ---------------------------------------------------------- */

    Registers.AX.R = 0x4700;
    Registers.DX.R = 0x0000;
    Registers.SI.R = (int)name+3;
    Registers.DS.R = getds();
    calldos();

    Registers.AX.R = 0x1900;
    calldos();

    *(name++) = 'A' + (Registers.AX.R & 0xFF);
    *(name++) = ':';
    *(name++) = '\\';
    if ( *name != '\0' )
	strcat(name,"\\");
    return (Registers.AX.R & 0xFF);
}
int	WC_open(char *file)
{
    int     i;
    char    *p,*s;

    if ( (s = endname(file)) != file ) {
	for ( p = dir ; file != s ; )
	    *(p++) = *(file++);
    /* ------------------ Debug  91.08.28 Pumpkin --------------- */
	if (*(p-2) != ':'  && *(p-1) == '\\' ) p--;
/****
	if ( *(p-1) == '\\' ) p--;
****/
    /* ---------------------------------------------------------- */
	*p = '\0';
	chdir(dir);
    }
    strcpy(wild,s);

    if ( topwcp == NULL &&
	(topwcp = (WCBUF *)malloc(sizeof(WCBUF)*MAXWCP)) == NULL )
	return 0;
    wcmax = 0;
    while ( wcmax < MAXWCP && subwc("*.*",0x10,&topwcp[wcmax]) != FALSE ) {
	if ( (topwcp[wcmax].wb_att & 0x10) != 0 )
	    wcmax++;
    }
    if ( wcmax > 1 ) sort(0,wcmax - 1);
    i = wcmax;
    while ( wcmax < MAXWCP && subwc(wild,0x21,&topwcp[wcmax]) != FALSE )
	wcmax++;
    if ( (wcmax - 1) > i ) sort(i,wcmax - 1);

    retdir(dir);
    return wcmax;
}
void	File_dsp(off,no)
int	off,no;
{
    int     i,c;
    char    *p;

    for ( i = 0 ; i < 30 ; i++ ) {
	c = 0x05;
	if ( (i+off) >= wcmax )
	    p = "            ";
	else {
	    p = subname(topwcp[i+off].wb_name);
	    if ( (topwcp[i+off].wb_att & 0x10) != 0 )
	        c = 0x0D;
	    if ( (i+off) == no )
		c |= 0x10;
	}
	wrtstr(p,17+(i%3)*14,11+(i/3),c);
    }
}
int	File_sel(char *file)
{
    int     i,no,off,fg,ch;
    int	    no_s,off_s;
    char    tmp[160];
    char    *p;
    char    bkdir[80];


    /* ------------------ Debug  91.08.28 Pumpkin --------------- */
    unsigned int att;

    if ( *file == '\0' ) {
	strcpy(file,"*.*");
    } else {
    	p = file + strlen(file) - 1;
    	if ( *p == ':' || *p == '\\' ) {
		strcat(file,"*.*");
	} else {
		if ((_dos_getfileattr(file,&att) == 0) && ((att & 16) == 16)) 
			strcat(file,"\\*.*");
	}
    }
    if (strcmp(file,"\\*.*") == 0) {
	retdir(bkdir);
	strncpy(tmp,bkdir,2);
	strcat(tmp,file);
	strcpy(file,tmp);
    }

/*****
    if ( *file == '\0' )
	strcpy(file,"*.*");
*****/
    /* ---------------------------------------------------------- */

    for ( p = file ; *p != '*' && *p != '?' && *p != '\0' ; p++ );
    if ( *p == '\0' )
	return FALSE;

    retdir(bkdir);


    /* ------------------ New file  91.10.12 Pumpkin ------------ */
    if ( WC_open(file) == 0 )
	return 2;
/*****
    if ( WC_open(file) == 0 )
	return FALSE;
*****/
    /* ---------------------------------------------------------- */


    Dmy_form(tmp,44,0x98,0x95,0x99); 
    wrtstr(tmp,15,8,0x05);

    Dmy_form(tmp,44,0x96,0x20,0x96); 
    for ( i = 0 ; i < 12 ; i++ )
        wrtstr(tmp,15,9+i,0x05);

    Dmy_form(tmp,44,0x9A,0x95,0x9B); 
    wrtstr(tmp,15,21,0x05);

    Dmy_form(tmp,44,0x93,0x95,0x92); 
    wrtstr(tmp,15,10,0x05);

    Dmy_form(tmp,44,0x96,0x20,0x96); 
    wrtstr(dir,17,9,0x05);

    for ( no_s = off_s = 1,no = off = 0,fg = FALSE ; fg == FALSE ; ) { 
	if ( no != no_s || off != off_s ) {
            File_dsp(off,no);
	    no_s = no; off_s = off;
	}
	ch = getch();
	if ( ch == '\x0D' ) {
	    if ( (topwcp[no].wb_att & 0x10) != 0 ) {
		strcat(dir,topwcp[no].wb_name);
		strcat(dir,"\\");
		strcat(dir,wild);
		WC_open(dir);
                wrtstr(tmp,15,9,0x05);
                wrtstr(dir,17,9,0x05);
		no_s = off_s = 1;
		no = off = 0;
	    } else {
		fg = TRUE;
	    }
	} else if ( ch == '\x1B' ) {
	    fg = ERR;
	} else if ( ch == '\x1C' && no < (wcmax-1) ) {
	    no++;
	} else if ( ch == '\x1D' && no > 0 ) {
	    no--;
	} else if ( ch == '\x1F' && (no + 3) < wcmax ) {
	    no += 3;
	} else if ( ch == '\x1E' && no >= 3 ) {
	    no -= 3;
	}
	while ( no < off ) off -= 3;
	while ( no >= (off+30) ) off += 3;
    }
    Dsp_vram_flash();
    if ( fg == TRUE ) {
	strcat(dir,topwcp[no].wb_name);
	strcpy(file,dir);
	fg = FALSE;
    }
    free(topwcp);
    topwcp = NULL;

    if ( bkdir[3] != '\0' )
	bkdir[strlen(bkdir)-1] = '\0';
    chdir(bkdir);

    return fg;
}
