/************************************************************************
 *	TITLE:			JAZIO.C					*
 *	PROJECT:		JAGUAR/JAZ				*
 *	FUNCTION:		JAZ FILE I/O MODULE			*
 *	PROGRAMMER:		Hans-Martin Krober			*
 *	DATE:			4/94					*
 *									*
 *              COPYRIGHT 1993,1994 Atari U.S. Corporation              *
 *          UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION,         *
 *          PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR          *
 *        THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED.       *
 *                            ALL RIGHTS RESERVED.                      *
 *									*
 ************************************************************************/

#include "portab.h"
#include "dos.h"
#include "glib.h"
#include "gemlib.h"
#include "slibc.h"
#include "alloc.h"

/*
 *	EXTERNALS
 */
EXTERN WORD scrn_w, scrn_h;
EXTERN BYTE jaz_prf_file[];
EXTERN LONG sclock;

VOID	xbios(WORD, WORD, WORD, BYTE *);
WORD 	sprintf(BYTE *, ...);

/*
 *	RDB COMMANDS
 */

#define DOS_PWD	 "!pwd >_jaz712.tmp; read _jaz712.tmp ._pathbuf; g"
#define DOS_DIR	 "!ls -tF %s >_jaz712.tmp; read _jaz712.tmp ._dirbuf; g"
#define DOS_MSDIR "!ls -A1 %s >_jaz712.tmp; read _jaz712.tmp ._dirbuf; g"
#define DOS_READ "read %s ._filebuf; g"
#define DOS_BUFREAD "read %s %lx; g"
#define DOS_WRITE "write %s ._filebuf[%lx]; g"
#define DOS_FSIZE "!fsize %s >_jaz712.tmp; read _jaz712.tmp .fsizebuf; g"
#define DOS_SMPCNVT "!smpcnvt %s %s; g"
#define DOS_ECHO "echo \"%s\"; g"


/*
 *	Buffers for patch and directory
 */
#define FSIZE_SIZE	32
#define PATH_SIZE	256
#define DOS_SIZE	256
#define DIR_SIZE	16000

BYTE	pathbuf[PATH_SIZE];
BYTE	currdir[PATH_SIZE];
BYTE	fsizebuf[FSIZE_SIZE];
BYTE	dirbuf[DIR_SIZE];
BYTE	dosbuf[DOS_SIZE];

BYTE	*dirlist[512];

BYTE	SLASH;
BYTE	PARENTDIR[4];

/*
 *	File I/O Buffer
 */
#define	FILE_SIZE	64000
BYTE	filebuf[FILE_SIZE];

VOID	clear_filebuf(VOID);

/*
 *	DOS CALLS
 */
 	VOID
dos_pwd(VOID)
{
	REG BYTE *s = pathbuf;

	xbios(11, 5, 0xf100, DOS_PWD);

	for (; *s != 13; s++) ;
	*s = '\0';

	strcpy(currdir, pathbuf);
}

	LONG
dos_fsize(fname)
	BYTE *fname;
{
	LONG	fsize;

	sprintf(dosbuf, DOS_FSIZE, fname);

	xbios(11, 5, 0xf100, dosbuf);

	sscanf(fsizebuf, "%ld", &fsize);

	return fsize;
}

	VOID
dos_smpcnvt(opt, fname)
	BYTE *opt;
	BYTE *fname;
{
	sprintf(dosbuf, DOS_SMPCNVT, opt, fname);

	xbios(11, 5, 0xf100, dosbuf);

}

	VOID
dos_getloop(beg, end)
	ULONG *beg, *end;
{
	MFILE	*fp;
	BYTE 	*s, buf[256];
	WORD	n;
	ULONG	temp;

	clear_filebuf();
	sprintf(dosbuf, DOS_READ, "_smploop.tmp");
	xbios(11, 5, 0xf100, dosbuf);

	if ((fp = mfopen(filebuf, "ra")) == NULL) {
		*end = *beg = -1L;
	}
	while (mfgets(buf, 256, fp) != NULL) {
		s = buf;
		for (; *s && (*s == '	') && (*s == '\t');)
			s++;
		if (!*s)
			continue;

		if (*s == '#' || *s == ';' || *s == '*')
			continue;
		n = sscanf(s, "beg loop=$%lx", &temp);
		if (n == 1)
			*beg = temp;
		n = sscanf(s, "end loop=$%lx", &temp);
		if (n == 1)
			*end = temp;
	}
	mfclose(fp);

}

	VOID
dos_dir(dir)
	BYTE *dir;
{
	REG WORD i;
	REG UBYTE *s = dirbuf;

	for (i = 0; i < DIR_SIZE; i++)		/* clear dirbuf so we find end */
		*s++ = (UBYTE) 0xff;

	if (SLASH == '\\')
		sprintf(dosbuf, DOS_MSDIR, dir);	/* DOS version */
	else	
		sprintf(dosbuf, DOS_DIR, dir);		/* TT version */
	xbios(11, 5, 0xf100, dosbuf);
}

	VOID
dos_read(fname)
	BYTE *fname;
{
	clear_filebuf();
	sprintf(dosbuf, DOS_READ, fname);
	xbios(11, 5, 0xf100, dosbuf);
	/*video_on();*/
}


	VOID
dos_echo(str)
	BYTE *str;
{
	sprintf(dosbuf, DOS_ECHO, str);
	xbios(11, 5, 0xf100, dosbuf);
}


	VOID
dos_bufread(fname, bufp)
	BYTE *fname;
	BYTE *bufp;
{
	sprintf(dosbuf, DOS_BUFREAD, fname, bufp);
	xbios(11, 5, 0xf100, dosbuf);
	/*video_on();*/
}

	VOID
dos_write(fname, size)
	BYTE *fname;
	LONG size;
{
	sprintf(dosbuf, DOS_WRITE, fname, size);
	xbios(11, 5, 0xf100, dosbuf);
}

	VOID
clear_filebuf()
{
	REG WORD i, l;
	REG LONG *p;

	l = FILE_SIZE / 4;
	p = (LONG *) filebuf;
	for (i = 0; i < l; i++)
		*p++ = 0xffffffffL;
}

/*	--------------------------------------------------------------
 *	File Selector
 */

#define FSEL_BOX	0
#define FSEL_TITLE	1
#define FSEL_DIRBOX	2
#define FSEL_UPDBAR	3
#define FSEL_UPDATE	4
#define FSEL_DRIVE	5
#define FSEL_EXT	6
#define FSEL_SELECTION	7
#define FSEL_BAR	8
#define FSEL_OK		9
#define FSEL_CANCEL	10

#define STR_SELECTION	"SELECTION"
#define STR_DRIVE	"DRIVE"
#define STR_UPDATE	"UPDATE"
#define STR_EXT		"EXT"
#define STR_OK		"OK"
#define STR_CANCEL	"Cancel"

OBJECT	fseltree[20];		/* File Selector Dialog Box */
BYTE	extbuf[6];
BYTE	*ext;

VOID	dirlst_handler(OBJECT *, WORD, LISTINFO *);
VOID	dirlst_scrolled(OBJECT *, WORD, LISTINFO *);
LONG	dirext_handler(OBJECT *, WORD, POPUPINFO *);
LONG	dirdrv_handler(OBJECT *, WORD, POPUPINFO *);
WORD	dircmp(BYTE **, BYTE**);
VOID	update_dir(WORD);
VOID	build_dir(BYTE *);
LONG	fselbttn_handler(OBJECT *, WORD, WORD, WORD, ULONG);
LONG	fselupdate_handler(OBJECT *, WORD, WORD, WORD, ULONG);

BYTE	fnametab[] = "abcdefghijklmnopqrstuvwxyz1234567890_ ";
#if 0
BYTE	*devdrivetab[] = {
	"a:", "b:", "c:", "d:", "e:", "f:", 
	"g:", "h:", "i:", "j:", "k:", "l:", 
	"m:", "n:", "o:", "p:"
};
#define NR_DFTDRIVES	16
#else
BYTE	devdrivetab[] = { " a: | b: | c: | d: | e: | f: | g: " };
#define NR_DFTDRIVES	7
#endif

BYTE	drivetab[128];
BYTE	drivetab_strs[32][4]; 

WORD	 nr_drives;


#define DRIVETAB_WID	2	

#if 0
BYTE	*rom_exttab[] = {
	"*.pmp", "*.*  ", NULL
};

BYTE exttab_str[4][6];

BYTE	*exttab[4] = {
	exttab_str[0],
	exttab_str[1],
	exttab_str[2],
	exttab_str[3]
};


#define NR_EXTS		2
#define EXTTAB_WID	5	

#else
#define NR_EXTS		1

BYTE	rom_exttab[] = { " *.* " };
BYTE 	exttab[128];

#endif

WORD	fsel_button;		/* exit button index */


/*
 * Directory cache
 */
typedef struct _dirinfo {
	BYTE	categ[48];
	BYTE	ext[64];
	WORD	ext_index;
	BYTE	path[256];
	BYTE	*dirbuf;
	LONG	dirsize;
	BYTE	mainstr[12];
	BYTE	extstr[6];
	WORD	loaded;
	WORD	used;
	LONG	time;
} DIRINFO;

#define N_DIRS 8
DIRINFO dirs[N_DIRS];
DIRINFO *curr_dir;
LONG fsel_time;

init_fsel()
{
	REG WORD	j;
	LISTINFO	*list;
	REG BYTE	**s;

	if (nr_drives == 0) { 
#if 0
		for (j = 0; j < NR_DFTDRIVES; j++) {
			drivetab[j] = devdrivetab[j];
		}	
#else
		strcpy(drivetab, devdrivetab);
#endif
		nr_drives = NR_DFTDRIVES;
	}
	for (j = 0; j < N_DIRS; j++) {
		dirs[j].used     = 0;
		dirs[j].loaded   = 0;
		dirs[j].categ[0] = 0;
		dirs[j].path[0]  = 0;
		dirs[j].ext[0]   = 0;
		dirs[j].time     = 0L;
		dirs[j].dirbuf   = NULL;

	}
	fsel_time = 0L;

	objc_xadd(fseltree, NIL, FSEL_BOX, 
		G_BOX, -1, -1, 
		30, 30, 320, 152,
		IS3DOBJ|NONE, NORMAL,
		0);	
		objc_xadd(fseltree, FSEL_BOX, FSEL_TITLE, 
			G_XBOXTEXT, -1, -1, 
			0, 0, 
			0, 14, 
			IS3DOBJ|NONE, NORMAL,
			T_OB_LATTACH, FSEL_BOX, 6,		
			T_OB_RATTACH, FSEL_BOX, 6,		
			T_OB_UATTACH, FSEL_BOX, 2,
			T_BX_TEXT, " ",
			T_BX_FONTID, FNT_MEDIUM,
			T_BX_ALIGN, TE_CNTR,
			0);
		objc_xadd(fseltree, FSEL_BOX, FSEL_DIRBOX, 
			G_XLIST, -1, -1, 
			0, 0, 140, 100,
			JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
			T_OB_UATTACH, FSEL_TITLE, 8,
			T_OB_LATTACH, FSEL_BOX, 6,
			T_OB_LEFT, FSEL_SELECTION,
			T_OB_RIGHT, FSEL_SELECTION,
			T_OB_DOWN, FSEL_UPDBAR,
			T_OB_UP, FSEL_UPDBAR,
			T_LST_NAME, "DIRECTORY",
			T_LST_TITLES, "      *.      ",
			T_LST_FONTID, FNT_MEDIUM,
			T_LST_CALLBK, dirlst_handler,
			T_LST_SCROLLED, dirlst_scrolled,
			0);
		objc_xadd(fseltree, FSEL_BOX, FSEL_UPDBAR, 
			G_XBAR, -1, -1, 
			4, 0, 140, 13,
			IS3DOBJ|JOYPAD|SELECTABLE, NORMAL,
			T_OB_DOWN, FSEL_DIRBOX,
			T_OB_UP, FSEL_DIRBOX,
			T_OB_UATTACH, FSEL_DIRBOX, 2,
			T_OB_LATTACH, FSEL_BOX, 6,
			T_BA_NUM, 1,
			T_BA_FIRST, 1,
			0);
			objc_xadd(fseltree, FSEL_UPDBAR, FSEL_UPDATE, 
				G_XBUTTON, -1, -1, 
				0, 2, 60, 10,
				ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
				T_OB_LATTACH, FSEL_UPDBAR, 30,
				T_OB_RATTACH, FSEL_UPDBAR, 30,
				T_OB_UATTACH, FSEL_UPDBAR, 0,
				T_BT_TEXT, STR_UPDATE,
				T_BT_BGCOLOR, 0,
				T_BT_TXTCOLOR, 1,
				T_BT_FONTID, 0,
				T_BT_SMCHAR, '1',
				T_BT_CALLBK, fselupdate_handler,
				0);
#if 0
		objc_xadd(fseltree, FSEL_BOX, FSEL_DRIVE,
			G_XTXTSLIDER, -1, -1,
			0, 0, 49, 24,
			JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
			T_OB_LATTACH, FSEL_DIRBOX, 6,
			T_OB_UATTACH, FSEL_TITLE, 8,
			T_OB_LEFT, FSEL_DIRBOX,
			T_OB_RIGHT, FSEL_EXT,
			T_OB_UP, FSEL_BAR,
			T_OB_DOWN, FSEL_SELECTION,
			T_TXT_SLNAME, STR_DRIVE,
			T_TXT_FONTID, FNT_MEDIUM,
			T_TXT_TABLE, drivetab,
			T_TXT_MAXITEMS, nr_drives,
			T_TXT_MAXLEN, DRIVETAB_WID,
			T_TXT_CALLBK, dirdrv_handler,
			0);
#endif
		objc_xadd(fseltree, FSEL_BOX, FSEL_DRIVE,
			G_XPOPUP, -1, -1,
			0, 0, 49, 24,
			JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
			T_OB_LATTACH, FSEL_DIRBOX, 18,
			T_OB_UATTACH, FSEL_TITLE, 8,
			T_OB_LEFT, FSEL_DIRBOX,
			T_OB_RIGHT, FSEL_EXT,
			T_OB_UP, FSEL_BAR,
			T_OB_DOWN, FSEL_SELECTION,
			T_POP_SLNAME, STR_DRIVE,
			T_POP_FONTID, FNT_MEDIUM,
			T_POP_DATA, drivetab,
			T_POP_CALLBK, dirdrv_handler,
			0);
#if 0
		for (s = rom_exttab, j = 0; *s != NULL; s++, j++) {
			strcpy(exttab[j], *s);
		}

		objc_xadd(fseltree, FSEL_BOX, FSEL_EXT,
			G_XTXTSLIDER, -1, -1,
			0, 0, 49, 24,
			JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
			T_OB_LATTACH, FSEL_DRIVE, 6,
			T_OB_UATTACH, FSEL_TITLE, 8,
			T_OB_LEFT, FSEL_DRIVE,
			T_OB_RIGHT, FSEL_DIRBOX,
			T_OB_UP, FSEL_BAR,
			T_OB_DOWN, FSEL_SELECTION,
			T_TXT_SLNAME, STR_EXT,
			T_TXT_FONTID, FNT_MEDIUM,
			T_TXT_TABLE, exttab,
			T_TXT_MAXITEMS, NR_EXTS,
			T_TXT_MAXLEN, EXTTAB_WID,
			T_TXT_CALLBK, dirext_handler,
			0);
#endif
		strcpy(exttab, rom_exttab);
		
		objc_xadd(fseltree, FSEL_BOX, FSEL_EXT,
			G_XPOPUP, -1, -1,
			0, 0, 60, 24,
			JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
			T_OB_LATTACH, FSEL_DRIVE, 14,
			T_OB_UATTACH, FSEL_TITLE, 8,
			T_OB_LEFT, FSEL_DRIVE,
			T_OB_RIGHT, FSEL_DIRBOX,
			T_OB_UP, FSEL_BAR,
			T_OB_DOWN, FSEL_SELECTION,
			T_POP_SLNAME, STR_EXT,
			T_POP_FONTID, FNT_MEDIUM,
			T_POP_DATA, exttab,
			T_POP_CALLBK, dirext_handler,
			0);


		objc_xadd(fseltree, FSEL_BOX, FSEL_SELECTION,
			G_XALPHSLIDER, -1, -1,
			0, 0, 49, 24,
			JOYPAD|IS3DOBJ|SELECTABLE, NORMAL,
			T_OB_LATTACH, FSEL_DIRBOX, 18,
			T_OB_UATTACH, FSEL_DRIVE, 8,
			T_OB_LEFT, FSEL_DIRBOX,
			T_OB_RIGHT, FSEL_DIRBOX,
			T_OB_UP, FSEL_DRIVE,
			T_OB_DOWN, FSEL_BAR,
			T_ALPH_SLNAME, STR_SELECTION,
			T_ALPH_FONTID, FNT_MEDIUM,
			T_ALPH_MAINSPACES, 8,
			T_ALPH_EXTSPACES, 3,
			T_ALPH_MAINSTR, "new     ", 
			T_ALPH_EXTSTR, "   ",
			T_ALPH_TABLE, fnametab,
			T_ALPH_EXTFLAG, 1,
			0);
		objc_xadd(fseltree, FSEL_BOX, FSEL_BAR, 
			G_XBAR, -1, -1, 
			4, 0, 372, 18,
			IS3DOBJ|JOYPAD|SELECTABLE, NORMAL,
			T_OB_DOWN, FSEL_DRIVE,
			T_OB_UP, FSEL_SELECTION,
			T_OB_LEFT, FSEL_DIRBOX,
			T_OB_RIGHT, FSEL_DIRBOX,
			T_OB_DATTACH, FSEL_BOX, 0,
			T_OB_LATTACH, FSEL_DIRBOX, 6,
			T_OB_RATTACH, FSEL_BOX, 6,
			T_BA_NUM, 2,
			T_BA_FIRST, 1,
			0);
			objc_xadd(fseltree, FSEL_BAR, FSEL_OK, 
				G_XBUTTON, -1, -1, 
				0, 2, 60, 12,
				ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
				T_BT_TEXT, STR_OK,
				T_BT_BGCOLOR, 0,
				T_BT_TXTCOLOR, 1,
				T_BT_FONTID, 1,
				T_BT_SMCHAR, '1',
				T_BT_CALLBK, fselbttn_handler,
				T_OB_LATTACH, FSEL_BAR, 4,
				T_OB_UATTACH, FSEL_BAR, 1,
				0);
			objc_xadd(fseltree, FSEL_BAR, FSEL_CANCEL, 
				G_XBUTTON, -1, -1, 
				0, 2, 60, 12,
				ABUTTON|IS3DOBJ|SELECTABLE, NORMAL,
				T_BT_TEXT, STR_CANCEL,
				T_BT_BGCOLOR, 0,
				T_BT_TXTCOLOR, 1,
				T_BT_FONTID, 1,
				T_BT_SMCHAR, '2',
				T_BT_CALLBK, fselbttn_handler,
				T_OB_RATTACH, FSEL_BAR, 4,
				T_OB_UATTACH, FSEL_BAR, 1,
				0);

		list = fseltree[FSEL_DIRBOX].ob_spec.list;
		list->data = (VOID*) &dirlist;
		list->index = 0;

}

/*
 *	still to do:	fill path + fname
 *			copy ext to exttab
 *			build selection filename + ext
 */



	WORD
fsel_input(categ, title, dir, name, extp, path, fname)
	BYTE *title;
	BYTE *categ;
	BYTE *dir;
	BYTE *name;
	BYTE *extp; 
	BYTE *path;
	BYTE *fname;
{
	REG BYTE *s, *t;
	REG WORD i, j;
	WORD	 space;
	BYTE	 fstr[32];
	BYTE	 estr[22];
	WORD	 err = 0, r;
	BYTE	 *sstr[9];

	fsel_time++;

	/*
	 * read the directory
	 */
	curr_dir = NULL;
	for (i = 0; i < N_DIRS; i++) {
		if (dirs[i].used && (strcmp(categ, dirs[i].categ) == 0)) {
			if (dirs[i].loaded) {
				dirs[i].time = fsel_time;
				curr_dir = &dirs[i];
				dir = curr_dir->path;				
				extp = curr_dir->ext;
				strcpy(pathbuf, dir);
				if (strlen(name) > 0)
					strcpy(dirs[i].mainstr, name);
				break;
			}
		}
	}
	if (i == N_DIRS) {
		BYTE	cdir[256];

		for (i = 0; i < N_DIRS; i++) {
			if (!dirs[i].used) {
				dirs[i].used = 1;
				dirs[i].loaded = 0;
				dirs[i].ext_index = 0;
				dirs[i].time = fsel_time;
				strcpy(dirs[i].categ, categ);
				strcpy(dirs[i].path, path);
				strcpy(dirs[i].ext, extp);
				if (strlen(name) > 0)
					strcpy(dirs[i].mainstr, name);
				else
					strcpy(dirs[i].mainstr, "new     ");
				strcpy(dirs[i].extstr, "   ");
				curr_dir = &dirs[i];
				break;
			}
		}
		if (i == N_DIRS) {
			LONG min_time;
			WORD min_ix;

			min_time = 0x7fffffffL;
			min_ix = 0;
			for (i = 0; i < N_DIRS; i++) {
				if (min_time > dirs[i].time) {
					min_time = dirs[i].time;
					min_ix = i;
				}
			}
			i = min_ix;
			dirs[i].used = 1;
			dirs[i].loaded = 0;
			dirs[i].time = fsel_time;
			dirs[i].ext_index = 0;
			strcpy(dirs[i].categ, categ);
			strcpy(dirs[i].path, path);
			strcpy(dirs[i].ext, extbuf);
			if (strlen(name) > 0)
				strcpy(dirs[i].mainstr, name);
			else
				strcpy(dirs[i].mainstr, "new     ");
			strcpy(dirs[i].extstr, "   ");

		}
		if (strcmp(dir, ".") == 0) {
			strcpy(cdir, currdir);
		} else {
			strcpy(cdir, dir);
		}
		for (j = 0; j < N_DIRS; j++) {
			if (j == i)
				continue;
			if (dirs[j].used && (strcmp(cdir, dirs[j].path) == 0)
			&& dirs[j].loaded) {
				if ((dirs[i].dirbuf = alloc(dirs[j].dirsize))
				== NULL)
					break;
				memcpy(dirs[i].dirbuf, dirs[j].dirbuf,
					dirs[j].dirsize);
				dirs[i].loaded = 1;
				dirs[i].dirsize = dirs[j].dirsize;
				strcpy(dirs[i].path, cdir);

				curr_dir = &dirs[i];
				dir = curr_dir->path;				
				extp = curr_dir->ext;
				strcpy(pathbuf, dir);
				break;
			}
		}
	}

	/*
	 * check extention
	 */
	fseltree[FSEL_EXT].ob_spec.popup->index = 0;
	if (strcmp(extp, " *.*") == 0) {
		ext = NULL;
		strcpy(extbuf, " *.*");
		fseltree[FSEL_EXT].ob_spec.popup->data = extbuf;
	} else {
		REG WORD c;
		REG BYTE *p;
		
		c=1;
		p = extp;
		while (*p)
			if (*p++=='|') c++;	

		fseltree[FSEL_EXT].ob_spec.popup->data = extp;
		fseltree[FSEL_EXT].ob_spec.popup->entries = c;
		if (curr_dir)
			c = curr_dir->ext_index;
		else
			c = 0;
		GetPopItem(fseltree[FSEL_EXT].ob_spec.popup->data, c, extbuf);
		fseltree[FSEL_EXT].ob_spec.popup->index = c;
		if (strcmp(extbuf, " *.*") == 0) {
			ext = NULL;
			if (fseltree[FSEL_EXT].ob_spec.popup->entries == 1)
				strcpy(curr_dir->extstr, "   ");
			else {
				BYTE temp[8];

				c = (c == 0) ? 1 : 0;
				GetPopItem(fseltree[FSEL_EXT].ob_spec.popup->data, 
					c, temp);
				strcpy(curr_dir->extstr, &temp[3]);
			}

		} else {
			ext = &extbuf[2];
			strcpy(curr_dir->extstr, &extbuf[3]);
		}
		
	}
	if (curr_dir) {
		strcpy((fseltree[FSEL_SELECTION].ob_spec.alphaslider)->extstr, 
			curr_dir->extstr);
		strcpy((fseltree[FSEL_SELECTION].ob_spec.alphaslider)->mainstr, 
			curr_dir->mainstr);
	} else {
		if (strlen(name) > 0)
		 strcpy((fseltree[FSEL_SELECTION].ob_spec.alphaslider)->mainstr, 
			name);
		else
		 strcpy((fseltree[FSEL_SELECTION].ob_spec.alphaslider)->mainstr, 
			"new     ");
		if (strcmp(extbuf, " *.*") == 0) {
			if (fseltree[FSEL_EXT].ob_spec.popup->entries == 1)
				strcpy(
				 (fseltree[FSEL_SELECTION].ob_spec.alphaslider)->extstr, 
				  "   ");
			else {
				WORD c;
				BYTE temp[8];

				c = (c == 0) ? 1 : 0;
				GetPopItem(fseltree[FSEL_EXT].ob_spec.popup->data, 
					c, temp);
				strcpy(
				 (fseltree[FSEL_SELECTION].ob_spec.alphaslider)->extstr, 
				  &temp[3]);
			}
		}

	}

	/*
	 * read directory
	 */			
	build_dir(dir);


	/*
	 * do fsel dialog box
	 */
fsel_handle:
	objc_xupdate(fseltree, FSEL_TITLE, T_BX_TEXT, title, 0);
	objc_draw(fseltree, 0, MAXDEPTH, 0, 0, scrn_w, scrn_h);
	form_xdo(fseltree, FSEL_DIRBOX);

	/*
	 * build path + fname
	 */
	strcpy(path, pathbuf);
	strcpy(fstr, (fseltree[FSEL_SELECTION].ob_spec.alphaslider)->mainstr);
	strcpy(estr, (fseltree[FSEL_SELECTION].ob_spec.alphaslider)->extstr);
	if (curr_dir)
		strcpy(curr_dir->path, pathbuf);
	/*
	 * check for valid fname
	 */
	if (fsel_button == FSEL_OK) {
		for (s = fstr, space = 0; *s; ) {
			if (*s == ' ') {
				sstr[space++] = s;
				for (; *s && (*s == ' '); s++);
				if (!*s)
					space--;
				if (space) {
					err = 1;
				} 	
			} else
				s++;
		}
		if (err == 1) {
			r = form_alert(FRM_ALERT, 
				"[The file name contains|spaces inbetween|characters. Do you want|to replace them|with '_'?][ Yes | No ]");
			if (r == 1) {
				for (i = 0; i < space; i++) {
					for (s = sstr[i]; *s == ' '; )
						*s++ = '_';
				}
			} else {
				goto fsel_handle;
			}
		}
		for (t = fname, s = fstr; *s && (*s != ' '); )
			*t++ = *s++;
		if (*estr) {
			*t++ = '.';
			for (s = estr; *s && (*s != ' '); )
				*t++ = *s++;
			*t = '\0';
		}			 		
	}
	return (fsel_button == FSEL_OK) ? 1 : 0;
}

	VOID
dirlst_scrolled(tree, obj, info)
	OBJECT	 	*tree;
	WORD	 	obj;
	REG LISTINFO 	*info;
{
	REG BYTE *curr, *s, *t;
	REG WORD i;
	WORD l;
	BYTE buf[128];
	SLALPHINFO *slinfo;

	curr = (BYTE *) dirlist[info->index];
	l = strlen(curr) - 1;

	if (strcmp(curr, PARENTDIR) == 0) {
		return;
	} else if (curr[l] == SLASH) {
		return;
	} else {
		slinfo = fseltree[FSEL_SELECTION].ob_spec.alphaslider;
		s = curr;
		t = slinfo->mainstr;
		for (i = 0; *s && (*s != '.') && (i < 8); i++) {
			*t++ = *s++;
		}
		for (; i < 8; i++) {
			*t++ = ' ';
		}
		if (*s) {
			s++;		/* skip '.' */
		}
		t = slinfo->extstr;
		for (i = 0; *s && (i < 3); i++)
			*t++ = *s++;
		for (; i < 3; i++)
			*t++ = ' ';
		objc_draw(fseltree, FSEL_SELECTION, MAXDEPTH, 
			0, 0, scrn_w, scrn_h);
	}
}

	VOID
dirlst_handler(tree, obj, info)
	OBJECT	 	*tree;
	WORD	 	obj;
	REG LISTINFO 	*info;
{
	REG BYTE *curr, *s, *t;
	REG WORD i;
	WORD l;
	BYTE buf[128];
	SLALPHINFO *slinfo;

	curr = (BYTE *) dirlist[info->index];
	l = strlen(curr) - 1;

	if (strcmp(curr, PARENTDIR) == 0) {
		if ((s = strrchr(pathbuf, SLASH)) != NULL) {
			if ((s - pathbuf) <= 3L)
				*(s + 1) = '\0';
			else
				*s = '\0';

			update_dir(TRUE);
		}
	} else if (curr[l] == SLASH) {
		if (strlen(pathbuf) <= 3) {
			strcpy(&buf[0], curr);
			buf[l] = '\0';
		} else {
			buf[0] = SLASH;
			strcpy(&buf[1], curr);
			buf[l+1] = '\0';
		}
		buf[l+1] = '\0';
		strcat(pathbuf, buf);

		update_dir(TRUE);
	} else {
		slinfo = fseltree[FSEL_SELECTION].ob_spec.alphaslider;
		s = curr;
		t = slinfo->mainstr;
		for (i = 0; *s && (*s != '.') && (i < 8); i++) {
			*t++ = *s++;
		}
		for (; i < 8; i++) {
			*t++ = ' ';
		}
		if (*s) {
			s++;		/* skip '.' */
		}
		t = slinfo->extstr;
		for (i = 0; *s && (i < 3); i++)
			*t++ = *s++;
		for (; i < 3; i++)
			*t++ = ' ';
		objc_draw(fseltree, FSEL_SELECTION, MAXDEPTH, 
			0, 0, scrn_w, scrn_h);
	}
}

	VOID
update_dir(flag)
	WORD flag;
{
	if (curr_dir && flag) {
		strcpy(curr_dir->path, pathbuf);
		curr_dir->loaded = FALSE;
	}
	build_dir(pathbuf);

	objc_draw(fseltree, FSEL_DIRBOX, MAXDEPTH, 0, 0, scrn_w, scrn_h);
}


	WORD
dircmp(a, b)
	BYTE **a, **b;
{
	WORD dira, dirb;

	dira = ((*a)[strlen(*a)-1] == SLASH) ? 1 : 0;
	dirb = ((*b)[strlen(*b)-1] == SLASH) ? 1 : 0;

	if ((dira && dirb) || (!dira && !dirb))
		return strcmp(*a, *b);
	else if (dira)
		return -1;
	else
		return 1;
}

	VOID
build_dir(dir)
	BYTE	*dir;
{
	WORD		root = FALSE;
	REG UBYTE	*s, **t, *u;	
	UBYTE		*v;
	REG WORD	i, k;
	LISTINFO	*list;
	BYTE		drive;
	POPUPINFO	*slinfo;
	BYTE		temp[8];
	BYTE		*dirp;

	form_alert(FRM_MSGSHOW, "[Loading directory...][]");

	/* get directory */

	/* check for root */


	if (strcmp(dir, ".") == 0) {
		dos_pwd();
		if (strlen(pathbuf) <= 3)
			root = TRUE;
	}


	/*
	 *	Update the drive txt box
	 */
	slinfo = fseltree[FSEL_DRIVE].ob_spec.popup;
	
	drive = pathbuf[0];
	for (i = 0; i < nr_drives; i++) {
		GetPopItem(slinfo->data, i, temp);
		if (drive == temp[1])
			break;
	}
	if (i == nr_drives)
		slinfo->index = 0;
	else
		slinfo->index = i;


	/*
	 * Read the directory
	 */
	if (!curr_dir) {
		dos_dir(pathbuf);
		dirp = dirbuf;
	} else if (!curr_dir->loaded) {
		for (i = 0; i < N_DIRS; i++) {
			if (dirs[i].used && (strcmp(pathbuf, dirs[i].path) == 0) &&
			dirs[i].loaded) {					
				if (curr_dir->dirbuf)
					free(curr_dir->dirbuf);
				if ((curr_dir->dirbuf = alloc(dirs[i].dirsize))
				 == NULL) {
					curr_dir = NULL;
					i = N_DIRS;
					break;
				}
				memcpy(curr_dir->dirbuf, dirs[i].dirbuf,
					dirs[i].dirsize);
				curr_dir->dirsize = dirs[i].dirsize;
				curr_dir->loaded = 1;
				dirp = curr_dir->dirbuf;
				strcpy(curr_dir->path, pathbuf);
				break;	
			}
		}
		if (i == N_DIRS) {
			dos_dir(pathbuf);
			dirp = dirbuf;
		}
	} else {
		dirp = curr_dir->dirbuf;
	}	

	if (strlen(pathbuf) <= 3)
		root = TRUE;
	
	/* 
	 * Build file list 
	 */
	i = 0;
	if ((UBYTE)dirp[0] != (UBYTE) 0xff) {
		s = dirp;
		if (root)
			t = (BYTE *) dirlist;
		else {
			i = 1;
			dirlist[0] = &PARENTDIR;
			t = (BYTE *) &dirlist[1];
		}
		u = s;
		while (*s != (UBYTE) 0xff) {
			if ((*s == (UBYTE)0x0d) || (*s == '\0')) {
				*s = '\0';
				v = strchr(u, '.');
				if (ext && ((*(s-1) == SLASH) || (v &&
				(strcmp(v, ext) == 0)))) {
					*t++ = u; i++;
				} else if (ext == NULL) {
					*t++ = u; i++;
				}
				s += 2;
				u = s;
			} else
				s++;
		}
	}
	if (curr_dir && !curr_dir->loaded) {
		LONG l;

		if (curr_dir->dirbuf)
			free(curr_dir->dirbuf);
		if ((curr_dir->dirbuf = (DIRINFO*)alloc(l = (LONG) ((LONG)s - (LONG)dirbuf + 1L))) != NULL) {
			memcpy(curr_dir->dirbuf, dirbuf, l);
			curr_dir->loaded = TRUE;
			curr_dir->dirsize = l;
		} else
			curr_dir = NULL;
	}


	qsort((BYTE*) &dirlist, i, (WORD) sizeof(BYTE *), &dircmp);
	list = fseltree[FSEL_DIRBOX].ob_spec.list;
	list->data = (VOID*) &dirlist;
	list->index = 0;
	list->maxitems = i;

	if (strlen(pathbuf) > 13) {
		if ((s = strrchr(pathbuf, SLASH)) != NULL) {
			strcpy(&list->name[3], s);

			list->name[0] = '.';	
			list->name[1] = '.';	
			list->name[2] = '.';	

		} else
			/*strrncpy(list->name, pathbuf, 10);*/
			strcpy(list->name, "PATH"); 
	} else
		strcpy(list->name, pathbuf);
	k = strlen(extbuf);
	s = &list->titles[0][8];
	u = &extbuf[3];
	for (i = 1; i < k; i++) {
		*s++ = *u++;
	}
	for (; i < k+4; i++)
		*s++ = ' ';
	*s = '\0';
	form_alert(FRM_MSGCLOSE, NULL);	
}

/*
 * Callback for ext text slider
 */

	LONG
dirext_handler(tree, obj, slinfo)
	OBJECT	*tree;
	WORD	obj;
	POPUPINFO *slinfo;
{
	REG BYTE *s;

	if (curr_dir)
		curr_dir->ext_index = slinfo->index;

	GetPopItem(slinfo->data, slinfo->index, extbuf);
#if 0
	for (s = extbuf; *s; s++)
		if (*s == ' ') {
			*s = '\0';
			break;
		}
#endif
	if (strcmp(extbuf, " *.*") == 0)
		ext = NULL;
	else
		ext = &extbuf[2];

	update_dir(FALSE);
	return 0L;
}

/*
 * Callback for drive text slider
 */

	LONG
dirdrv_handler(tree, obj, slinfo)
	OBJECT	*tree;
	WORD	obj;
	POPUPINFO *slinfo;
{
	REG BYTE *s;
	BYTE	 temp[8];
	BYTE	 drive;

	GetPopItem(slinfo->data, slinfo->index, temp);
	drive = temp[1];
	if (pathbuf[0] == drive)
		return 0L;

	pathbuf[0] = drive;
	pathbuf[1] = ':';
	pathbuf[2] = SLASH;
	pathbuf[3] = '\0';

	update_dir(TRUE);
	return 0L;
}

	LONG	
fselbttn_handler(tree, curr, found, n, k)
	OBJECT *tree;
	WORD	curr;
	WORD	found;
	WORD	n;
	ULONG	k;
{
	fsel_button = found;
	if (curr_dir) {
		strncpy(curr_dir->extstr,
		  (fseltree[FSEL_SELECTION].ob_spec.alphaslider)->extstr, 3);
		strncpy(curr_dir->mainstr,
		 (fseltree[FSEL_SELECTION].ob_spec.alphaslider)->mainstr, 8);
	}

	return -1L;
}


	LONG	
fselupdate_handler(tree, curr, found, n, k)
	OBJECT *tree;
	WORD	curr;
	WORD	found;
	WORD	n;
	ULONG	k;
{
	update_dir(TRUE);

	return 0L;
}

/*	--------------------------------------------------------------	    */

WORD	read_jazcnf(VOID);
VOID	parse_cnf(BYTE *);

/*
 *	Read JAZ CNF File
 */

	WORD
read_cnf()
{
	REG BYTE *s, *t;

	nr_drives = 0;

	SLASH = '\\';
	strcpy(PARENTDIR, "..\\");

	clear_filebuf();

	dos_read("JAZ.CNF");
	if ((UBYTE) filebuf[0] == (UBYTE) 0xff)
		return -1;
	
	t = s = filebuf;
	for (; (UBYTE) *s != (UBYTE) 0xff; s++) {
		if (*s == 0x0d) {
			*s++ = '\0';
			parse_cnf(t);
			t = ++s;
		}
	}
	return 0;
}


/*
 *	parse a line in the jaz.cnf file
 */

	VOID
parse_cnf(line)
	BYTE *line;
{
	REG WORD i = 0, j;
	WORD	 x;
	REG BYTE *s, *t;
	BYTE	 drivemap[32];
	LONG	 atol(BYTE *);

	/*
	 * ignore comments
	 */
	if ((s[0] == '#') || (s[0] == ';') || (s[0] == '*'))
		return;
	for (; *s; s++) {
		if ((*s == '#') || (*s == ';') || (*s == '*')) {
			*s = '\0';
			break;
		}
	}
	s = line;
	for (; (*s == ' ') || (*s == '\t'); )	/* skip tabs and spaces */
		s++;

	/*
	 *	look for drive map
	 */

	if ((t = strstr(s, "drives")) != NULL) {
		s = t;
		for (; (*s != '\0') && (*s != '='); s++) ;
		if (*s) {
			for (i = 0; *s; s++) {
				if ((*s == '#') || (*s == ';') || (*s == '*'))
					break;
				if (*s >= 65 && *s <= 90)
					drivemap[i++] = *s + 32;
				else if (*s >= 97 && *s <= 122)	
					drivemap[i++] = *s;
			}
			if (i > 0) {
				for (j = 0, x = 0; j < i; j++) {
#if 0
					drivetab_strs[j][0] = drivemap[j];
					drivetab_strs[j][1] = ':';
					drivetab_strs[j][2] = '\0';
					drivetab[j] = drivetab_strs[j];
#else					
					drivetab[x++] = ' ';
					drivetab[x++] = drivemap[j];
					drivetab[x++] = ':';
					drivetab[x++] = ' ';
					drivetab[x++] = '|';
#endif
				}
				drivetab[--x] = '\0';
				nr_drives = i;
			} 

		}
		return;
	}

	if ((t = strstr(s, "slash")) != NULL) {
		s = t;
		for (; (*s != '\0') && (*s != '='); s++) ;
		if (*s) {
			if (strstr(s, "unix") != NULL) {
				SLASH = '/';	
			} else {
				SLASH = '\\';	
			}
			PARENTDIR[2] = SLASH;			
		}

	}

	if ((t = strstr(s, "prf")) != NULL) {
		s = t;
		for (; (*s != '\0') && (*s != '='); s++) ;
		if (*s) {
			s++;
			strcpy(jaz_prf_file, s);
		}

	}
	if ((t = strstr(s, "sclock")) != NULL) {
		s = t;
		for (; (*s != '\0') && (*s != '='); s++) ;
		if (*s) {
			s++;
			sclock = atol(s);
		}

	}

}

