/****************************************************************************
 *                                                                          *
 *                              File Requester                              *
 *                                                                          *
 *                   (c) Copyright 1989 Jonathan Potter                     *
 *                                                                          *
 * This program is freely redistributable, although all rights to it remain *
 * with the author. It may be used freely in any program as long as this    *
 * notice remains intact, however, if you do this, please mention the       *
 * author in the program. If you wish to use this in a commercial program   *
 * of any kind, you must register with a $15 donation.                      *
 * Please send donations, bug reports, comments and suggestions to :        *
 *                                                                          *
 *                              Jonathan Potter                             *
 *                              3 William Street                            *
 *                              Clarence Park 5034                          *
 *                              South Australia                             *
 *                              Australia                                   *
 *                                                                          *
 *                         Ph : (08) 2932788  home                          *
 *                                                                          *
 ****************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuitionbase.h>
#include <libraries/dosextens.h>
#include <graphics/gfxbase.h>
#include "filereq.h"

#define FILEBASE 1
#define DEVICEBASE 6
#define DRAWERBASE 11
#define FILENAME 16
#define DRAWERNAME 17
#define DEVICENAME 18
#define FILENAMEUP 19
#define DRAWERUP 20
#define DEVICEUP 21
#define FILENAMEDOWN 22
#define DRAWERDOWN 23
#define DEVICEDOWN 24
#define FILENAMEPOS 25
#define DRAWERPOS 26
#define DEVICEPOS 27
#define OKAY 28
#define CANCEL 29
#define RENAME 30
#define DELETE 31
#define MAKEDIR 32
#define PARENT 33
#define SUPEROKAY 34

/* Image-Ed Sprite generation */

/* Start of Sprite Data */
static USHORT BusySpriteData[]={
	0x0000, 0x0000,
	0x3c00, 0x3c00,
	0x7e00, 0x4200,
	0x7e00, 0x4200,
	0x7e00, 0x4200,
	0x7e00, 0x4200,
	0x7e00, 0x7e00,
	0xff00, 0x8100,
	0xef00, 0x9100,
	0xef00, 0x9100,
	0xe300, 0x9d00,
	0xff00, 0x8100,
	0xff00, 0x8100,
	0x7e00, 0x7e00,
	0x7e00, 0x4200,
	0x7e00, 0x4200,
	0x7eee, 0x42ee,
	0x7eaa, 0x42ee,
	0x3cee, 0x3cee,
	0xffff, 0xffff
};
/* End of Sprite Data */

/* End of Image-Ed Sprite generation */

/* Image-Ed Image generation */

/* Start of Image data */
static USHORT UpArrow1ImageData[]={
	/* Plane 0 */
	0x0040, 0x0000, 0x01f0, 0x0000, 0x07fc, 0x0000, 0x1fff, 0x0000, 
	0x7fff, 0xc000, 0xffff, 0xe000, 0x03f8, 0x0000, 0x03f8, 0x0000, 
	0x03f8, 0x0000, 0x03f8, 0x0000, 
	/* Plane 1 */
	0x0030, 0x0000, 0x000c, 0x0000, 0x0003, 0x0000, 0x0000, 0xc000, 
	0x0000, 0x3000, 0x0000, 0x1800, 0x0006, 0x0000, 0x0006, 0x0000, 
	0x0006, 0x0000, 0x0006, 0x0000
};
/* End of Image data */

static struct Image UpArrow1Image={
	0,0, /* LeftEdge, TopEdge */
	21,10,2, /* Width, Height, Depth */
	&UpArrow1ImageData[0], /* ImageData */
	0x3,0x0, /* PlanePick, PlaneOnOff */
	NULL /* Next Image */
};

/* Start of Image data */
static USHORT UpArrow2ImageData[]={
	/* Plane 0 */
	0x0010, 0x0000, 0x007c, 0x0000, 0x01ff, 0x0000, 0x07ff, 0xc000, 
	0x1fff, 0xf000, 0x3fff, 0xf800, 0x00fe, 0x0000, 0x00fe, 0x0000, 
	0x00fe, 0x0000, 0x00fe, 0x0000, 
	/* Plane 1 */
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000
};
/* End of Image data */

static struct Image UpArrow2Image={
	0,0, /* LeftEdge, TopEdge */
	21,10,2, /* Width, Height, Depth */
	&UpArrow2ImageData[0], /* ImageData */
	0x3,0x0, /* PlanePick, PlaneOnOff */
	NULL /* Next Image */
};

/* Start of Image data */
static USHORT DownArrow1ImageData[]={
	/* Plane 0 */
	0x03f8, 0x0000, 0x03f8, 0x0000, 0x03f8, 0x0000, 0x03f8, 0x0000, 
	0xffff, 0xe000, 0x7fff, 0xc000, 0x1fff, 0x0000, 0x07fc, 0x0000, 
	0x01f0, 0x0000, 0x0040, 0x0000, 
	/* Plane 1 */
	0x0006, 0x0000, 0x0006, 0x0000, 0x0006, 0x0000, 0x0006, 0x0000, 
	0x0000, 0x1800, 0x0000, 0x3000, 0x0000, 0xc000, 0x0003, 0x0000, 
	0x000c, 0x0000, 0x0030, 0x0000
};
/* End of Image data */

static struct Image DownArrow1Image={
	0,0, /* LeftEdge, TopEdge */
	21,10,2, /* Width, Height, Depth */
	&DownArrow1ImageData[0], /* ImageData */
	0x3,0x0, /* PlanePick, PlaneOnOff */
	NULL /* Next Image */
};

/* Start of Image data */
static USHORT DownArrow2ImageData[]={
	/* Plane 0 */
	0x00fe, 0x0000, 0x00fe, 0x0000, 0x00fe, 0x0000, 0x00fe, 0x0000, 
	0x3fff, 0xf800, 0x1fff, 0xf000, 0x07ff, 0xc000, 0x01ff, 0x0000, 
	0x007c, 0x0000, 0x0010, 0x0000, 
	/* Plane 1 */
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000
};
/* End of Image data */

static struct Image DownArrow2Image={
	0,0, /* LeftEdge, TopEdge */
	21,10,2, /* Width, Height, Depth */
	&DownArrow2ImageData[0], /* ImageData */
	0x3,0x0, /* PlanePick, PlaneOnOff */
	NULL /* Next Image */
};

/* End of Image-Ed Image generation */

static struct TextAttr TopazText={
	(STRPTR)"topaz.font",8,0,0};

static char filenamebuffer[32], drawernamebuffer[236], devicenamebuffer[32];
static char filetextbuffer[5][16], drawertextbuffer[5][16], devicetextbuffer[5][16];

static short border1_xy[]={
	-1,-1,120,-1,120,40,-1,40,-1,-1};
static struct Border border1={
	0,0,2,0,JAM1,5,border1_xy,NULL};
static short border2_xy[]={
 	-1,-1,120,-1,120,8,-1,8,-1,-1};
static struct Border border2={
	0,0,2,0,JAM1,5,border2_xy,NULL};

static struct PropInfo
	filenameprop={AUTOKNOB|FREEVERT,0,0,0,0x1000},
	drawerprop={AUTOKNOB|FREEVERT,0,0,0,0x1000},
	deviceprop={AUTOKNOB|FREEVERT,0,0,0,0x1000};

static struct Image filenameimage, drawerimage, deviceimage;

static struct StringInfo
	filenamesinfo={(STRPTR)filenamebuffer,NULL,0,32,0},
	drawernamesinfo={(STRPTR)drawernamebuffer,NULL,0,236,0},
	devicenamesinfo={(STRPTR)devicenamebuffer,NULL,0,32,0};

static struct IntuiText
	filetext[5]={
	{1,0,JAM2,0,0,&TopazText,(STRPTR)filetextbuffer[0],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)filetextbuffer[1],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)filetextbuffer[2],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)filetextbuffer[3],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)filetextbuffer[4],NULL}},
	drawertext[5]={
	{1,0,JAM2,0,0,&TopazText,(STRPTR)drawertextbuffer[0],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)drawertextbuffer[1],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)drawertextbuffer[2],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)drawertextbuffer[3],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)drawertextbuffer[4],NULL}},
	devicetext[5]={
	{1,0,JAM2,0,0,&TopazText,(STRPTR)devicetextbuffer[0],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)devicetextbuffer[1],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)devicetextbuffer[2],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)devicetextbuffer[3],NULL},
	{1,0,JAM2,0,0,&TopazText,(STRPTR)devicetextbuffer[4],NULL}},
	filenametext={
		3,1,JAM2,44,-54,&TopazText,(UBYTE *)"File",NULL},
	drawernametext={
		3,1,JAM2,36,-54,&TopazText,(UBYTE *)"Drawer",NULL},
	devicenametext={
		3,1,JAM2,36,-54,&TopazText,(UBYTE *)"Volume",NULL},
	parenttext={
		3,2,JAM2,0,0,&TopazText,(UBYTE *)"    PARENT     ",NULL},
	okaytext={
		3,2,JAM2,0,0,&TopazText,(UBYTE *)"     OKAY      ",NULL},
	canceltext={
		3,2,JAM2,0,0,&TopazText,(UBYTE *)"    CANCEL     ",NULL},
	renametext={
		3,2,JAM2,0,0,&TopazText,(UBYTE *)"    RENAME     ",NULL},
	deletetext={
		3,2,JAM2,0,0,&TopazText,(UBYTE *)"    DELETE     ",NULL},
	makedirtext={
		3,2,JAM2,0,0,&TopazText,(UBYTE *)"   MAKE DIR    ",NULL};

static struct Gadget
	filegadget[5]={
	{&filegadget[1],10,23,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border1,NULL,
	&filetext[0],NULL,NULL,FILEBASE,NULL},
	{&filegadget[2],10,31,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&filetext[1],NULL,NULL,FILEBASE+1,NULL},
	{&filegadget[3],10,39,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&filetext[2],NULL,NULL,FILEBASE+2,NULL},
	{&filegadget[4],10,47,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&filetext[3],NULL,NULL,FILEBASE+3,NULL},
	{NULL,10,55,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&filetext[4],NULL,NULL,FILEBASE+4,NULL}},
	devicegadget[5]={
	{&devicegadget[1],10,90,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border1,NULL,
	&devicetext[0],NULL,NULL,DEVICEBASE,NULL},
	{&devicegadget[2],10,98,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&devicetext[1],NULL,NULL,DEVICEBASE+1,NULL},
	{&devicegadget[3],10,106,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&devicetext[2],NULL,NULL,DEVICEBASE+2,NULL},
	{&devicegadget[4],10,114,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&devicetext[3],NULL,NULL,DEVICEBASE+3,NULL},
	{&filegadget[0],10,122,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&devicetext[4],NULL,NULL,DEVICEBASE+4,NULL}},
	drawergadget[5]={
	{&drawergadget[1],159,23,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border1,NULL,
	&drawertext[0],NULL,NULL,DRAWERBASE,NULL},
	{&drawergadget[2],159,31,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&drawertext[1],NULL,NULL,DRAWERBASE+1,NULL},
	{&drawergadget[3],159,39,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&drawertext[2],NULL,NULL,DRAWERBASE+2,NULL},
	{&drawergadget[4],159,47,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&drawertext[3],NULL,NULL,DRAWERBASE+3,NULL},
	{&devicegadget[0],159,55,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,NULL,NULL,
	&drawertext[4],NULL,NULL,DRAWERBASE+4,NULL}},
	filenamegadget={
		&drawergadget[0],10,67,120,8,GADGHCOMP,RELVERIFY|TOGGLESELECT,STRGADGET,
		(APTR)&border2,NULL,&filenametext,NULL,(APTR)&filenamesinfo,FILENAME,NULL},
	drawernamegadget={
		&filenamegadget,159,67,120,8,GADGHCOMP,RELVERIFY|TOGGLESELECT,STRGADGET,
		(APTR)&border2,NULL,&drawernametext,NULL,(APTR)&drawernamesinfo,DRAWERNAME,NULL},
	devicenamegadget={
		&drawernamegadget,10,134,120,8,GADGHCOMP,RELVERIFY|TOGGLESELECT,STRGADGET,
		(APTR)&border2,NULL,&devicenametext,NULL,(APTR)&devicenamesinfo,DEVICENAME,NULL},
	filenameupgadget={
		&devicenamegadget,134,23,21,10,GADGHIMAGE|GADGIMAGE,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
		(APTR)&UpArrow1Image,(APTR)&UpArrow2Image,NULL,NULL,NULL,FILENAMEUP,NULL},
	drawerupgadget={
		&filenameupgadget,283,23,21,10,GADGHIMAGE|GADGIMAGE,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
		(APTR)&UpArrow1Image,(APTR)&UpArrow2Image,NULL,NULL,NULL,DRAWERUP,NULL},
	deviceupgadget={
		&drawerupgadget,134,90,21,10,GADGHIMAGE|GADGIMAGE,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
		(APTR)&UpArrow1Image,(APTR)&UpArrow2Image,NULL,NULL,NULL,DEVICEUP,NULL},
	filedowngadget={
		&deviceupgadget,134,65,21,10,GADGHIMAGE|GADGIMAGE,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
		(APTR)&DownArrow1Image,(APTR)&DownArrow2Image,NULL,NULL,NULL,FILENAMEDOWN,NULL},
	drawerdowngadget={
		&filedowngadget,283,65,21,10,GADGHIMAGE|GADGIMAGE,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
		(APTR)&DownArrow1Image,(APTR)&DownArrow2Image,NULL,NULL,NULL,DRAWERDOWN,NULL},
	devicedowngadget={
		&drawerdowngadget,134,132,21,10,GADGHIMAGE|GADGIMAGE,GADGIMMEDIATE|RELVERIFY,BOOLGADGET,
		(APTR)&DownArrow1Image,(APTR)&DownArrow2Image,NULL,NULL,NULL,DEVICEDOWN,NULL},
	filenamepropgadget={
		&devicedowngadget,134,34,21,30,GADGHCOMP,GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY,PROPGADGET,
		(APTR)&filenameimage,NULL,NULL,NULL,(APTR)&filenameprop,FILENAMEPOS,NULL},
	drawerpropgadget={
		&filenamepropgadget,283,34,21,30,GADGHCOMP,GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY,PROPGADGET,
		(APTR)&drawerimage,NULL,NULL,NULL,(APTR)&drawerprop,DRAWERPOS,NULL},
	devicepropgadget={
		&drawerpropgadget,134,101,21,30,GADGHCOMP,GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY,PROPGADGET,
		(APTR)&deviceimage,NULL,NULL,NULL,(APTR)&deviceprop,DEVICEPOS,NULL},
	parentgadget={
		&devicepropgadget,159,79,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border2,NULL,
		&parenttext,NULL,NULL,PARENT,NULL},
	okaygadget={
		&parentgadget,159,90,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border2,NULL,
		&okaytext,NULL,NULL,OKAY,NULL},
	cancelgadget={
		&okaygadget,159,101,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border2,NULL,
		&canceltext,NULL,NULL,CANCEL,NULL},
	renamegadget={
		&cancelgadget,159,112,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border2,NULL,
		&renametext,NULL,NULL,RENAME,NULL},
	deletegadget={
		&renamegadget,159,123,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border2,NULL,
		&deletetext,NULL,NULL,DELETE,NULL},
	makedirgadget={
		&deletegadget,159,134,120,8,GADGHCOMP,RELVERIFY,BOOLGADGET,(APTR)&border2,NULL,
		&makedirtext,NULL,NULL,MAKEDIR,NULL};

static struct NewWindow fr_window={
	8,25,311,147,1,3,
	GADGETUP|GADGETDOWN|MOUSEMOVE|MOUSEBUTTONS|DISKINSERTED|DISKREMOVED,
	SMART_REFRESH|NOCAREREFRESH|ACTIVATE|RMBTRAP,
	NULL,NULL,(STRPTR)"File request",NULL,NULL,0,0,0,0,CUSTOMSCREEN};

static struct Window *fr_Window;
static struct IntuiMessage *fr_Msg;
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct DosLibrary *DosBase;

static struct direntry {
	struct direntry *next;
	char name[35];
};
static struct direntry 
	*FirstFileEntry, *FileEntry,
	*FirstDrawerEntry, *DrawerEntry,
	*FirstDeviceEntry, *DeviceEntry;

static int deviceentries=0, fileentries=0, drawerentries=0;
static int deviceoffset=0, fileoffset=0, draweroffset=0;
static int olddeviceoffset=-1, oldfileoffset=-1, olddraweroffset=-1;
static char *nullstring="               ";

static BOOL SortOn;

file_request(dest_scr,hail,x,y,device,directory,filename,so)
struct Screen *dest_scr;
char *hail;
int x,y;
char *device, *directory, *filename;
BOOL so;
{
	int Class, Code, GadgetID, i;
	SortOn=so;
	if (!IntuitionBase) return(NO_INTUITION);
	if (!GfxBase) return(NO_GRAPHICS);
	if (!DosBase) return(NO_DOS);
	if (!directory) return(NO_DIRECTORY);
	if (!filename) return(NO_FILENAME);
	if (!device) return(NO_DEVICE);
	if (!dest_scr) fr_window.Type=WBENCHSCREEN;
	else fr_window.Screen=dest_scr;
	if (x>-1 && fr_window.Screen->Width>=x+fr_window.Width) fr_window.LeftEdge=x;
	if (y>-1 && fr_window.Screen->Height>=y+fr_window.Height) fr_window.TopEdge=y;
	if (hail) fr_window.Title=hail;
	strncpy(filenamebuffer,filename,32);
	strncpy(drawernamebuffer,directory,236);
	strncpy(devicenamebuffer,device,32);
	if (strlen(devicenamebuffer)==0) strcpy(devicenamebuffer,":");
	fr_Window=(struct Window *) OpenWindow(&fr_window);
	if (!fr_Window) return(OPENWINDOW_FAILED);
	SetAPen(fr_Window->RPort,1);
	RectFill(fr_Window->RPort,3,11,307,144);
	SetAPen(fr_Window->RPort,0);
	RectFill(fr_Window->RPort,10,90,129,129);
	RectFill(fr_Window->RPort,10,23,129,62);
	RectFill(fr_Window->RPort,159,23,278,62);
	AddGList(fr_Window,&makedirgadget,-1,-1,35,NULL);
	RefreshGList(&makedirgadget,fr_Window,NULL,-1);
	SetAPen(fr_Window->RPort,1);
	ActivateGadget(&filenamegadget,fr_Window,NULL);
	i=get_devicenames();
	if (i==CANCEL) {
		close_req();
		goto quit_req;
	}
	if (i==OKAY || i==SUPEROKAY) {
		close_req();
		goto do_okay;
	}
	i=get_filenames();
	if (i==CANCEL) {
		close_req();
		goto quit_req;
	}
	if (i==OKAY || i==SUPEROKAY) {
		close_req();
		goto do_okay;
	}
	FOREVER {
		Wait(1<<fr_Window->UserPort->mp_SigBit);
		while (fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort)) {
			Class=fr_Msg->Class; Code=fr_Msg->Code;
			if (Class==GADGETDOWN || Class==GADGETUP)
				GadgetID=((struct Gadget *) fr_Msg->IAddress)->GadgetID;
			ReplyMsg((struct Message *) fr_Msg);
			i=do_idcmp(Class,Code,GadgetID);
			if (i==CANCEL) {
				close_req();
				goto quit_req;
				break;
			}
			if (i==OKAY || i==SUPEROKAY) {
				close_req();
				goto do_okay;
			}
		}
	}
	quit_req:
	return(FALSE);
	do_okay:
	strcpy(device,devicenamebuffer);
	strcpy(directory,drawernamebuffer);
	strcpy(filename,filenamebuffer);
	return(TRUE);
}

static close_req()
{
	if (fr_Window) CloseWindow(fr_Window);
	deallocate_entries(7);
	return(0);
}

static DOSDisk(device)
struct DeviceList *device;
{
	struct MsgPort *port;
	BOOL result;
	struct InfoData *info;
	struct StandardPacket *packet;

	result=FALSE;
	info=(struct InfoData *) AllocMem(sizeof(struct InfoData),MEMF_CLEAR);
	packet=(struct StandardPacket *) AllocMem(sizeof(struct StandardPacket),MEMF_CLEAR);
	port=(struct MsgPort *) CreatePort(NULL,0);
	if (port&&info&&packet) {
		packet->sp_Msg.mn_Node.ln_Type=NT_MESSAGE;
		packet->sp_Msg.mn_Node.ln_Name=(char *)&packet->sp_Pkt;
		packet->sp_Msg.mn_ReplyPort=port;
		packet->sp_Pkt.dp_Link=&packet->sp_Msg;
		packet->sp_Pkt.dp_Type=ACTION_DISK_INFO;
		packet->sp_Pkt.dp_Arg1=((LONG)info>>2);
		packet->sp_Pkt.dp_Port=port;
		PutMsg(device->dl_Task,&packet->sp_Msg);
		WaitPort(port);
		if (info->id_DiskType==ID_DOS_DISK) result=TRUE;
	}
	if (port) DeletePort(port);
	if (info) FreeMem(info, sizeof(struct InfoData));
	if (packet) FreeMem(packet, sizeof(struct StandardPacket));
	return(result);
}

static get_devicenames()
{
	struct RootNode *rootnode;
	struct DosInfo *dosinfo;
	struct DeviceList *devlist;
	struct FileLock *lock;
	struct InfoData *data;
	struct FileInfoBlock *finfo;
	UBYTE devname[32];
	int Class, Code, GadgetID;
	int ret=0;

	FirstDeviceEntry=NULL; DeviceEntry=NULL;
	data=(struct InfoData *)AllocMem(sizeof(struct InfoData),MEMF_CLEAR);
	finfo=(struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR);
	rootnode=(struct RootNode *) DosBase->dl_Root;
	dosinfo=(struct DosInfo *) BADDR(rootnode->rn_Info);

	Forbid();
	busy();
	devlist=(struct DeviceList *) BADDR(dosinfo->di_DevInfo);
	while (devlist) {
		while (fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort)) {
			Class=fr_Msg->Class; Code=fr_Msg->Code;
			if (Class==GADGETDOWN || Class==GADGETUP)
				GadgetID=((struct Gadget *) fr_Msg->IAddress)->GadgetID;
			ReplyMsg((struct Message *) fr_Msg);
			if (Class==GADGETUP && do_idtype(GadgetID)) goto defin;
			unbusy();
			ret=do_idcmp(Class,Code,GadgetID);
			busy();
			if (ret==SUPEROKAY) goto fin;
		}
		if (devlist->dl_Type!=DLT_DEVICE || !devlist->dl_Task) {
			devlist=(struct DeviceList *) BADDR(devlist->dl_Next);
			continue;
		}
		if (!DOSDisk(devlist)) {
			devlist=(struct DeviceList *) BADDR(devlist->dl_Next);
			continue;
		}
		conbstr((BPTR)devlist->dl_Name,devname);
		strcat(devname,":");
		lock=(struct FileLock *) Lock(devname,ACCESS_READ);
		if (lock==NULL) goto fin;
		Info(lock,data);
		Examine(lock,finfo);
		if (FirstDeviceEntry==NULL) {
			FirstDeviceEntry=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
			strncpy(FirstDeviceEntry->name,finfo->fib_FileName,32);
			strcat(FirstDeviceEntry->name,":");
			DeviceEntry=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
			FirstDeviceEntry->next=DeviceEntry;
			strncpy(DeviceEntry->name,devname,32);
			deviceentries+=2;
		}
		else {
			DeviceEntry->next=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
			DeviceEntry=DeviceEntry->next;
			strncpy(DeviceEntry->name,finfo->fib_FileName,32);
			strcat(DeviceEntry->name,":");
			DeviceEntry->next=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
			DeviceEntry=DeviceEntry->next;
			strncpy(DeviceEntry->name,devname,32);
			deviceentries+=2;
		}
		UnLock(lock);
		devlist=(struct DeviceList *) BADDR(devlist->dl_Next);
		DeviceEntry->next=NULL;
		DisplayDevices(FALSE);
	}
	goto fin;
	defin:
	unbusy();
	ret=do_idcmp(Class,Code,GadgetID);
	fin:
	Permit();
	if (data) FreeMem(data,sizeof(struct InfoData));
	if (finfo) FreeMem(finfo,sizeof(struct FileInfoBlock));
	if (deviceentries && SortOn) Sort(FirstDeviceEntry,deviceentries);
	olddeviceoffset=-1;
	DisplayDevices(TRUE);
	unbusy();
	return(ret);
}

static DisplayDevices(clear)
BOOL clear;
{
	struct direntry *work;
	int a,b;
	if (deviceoffset==olddeviceoffset && clear) return(0);
	olddeviceoffset=deviceoffset;
	if (clear) {
		SetAPen(fr_Window->RPort,0);
		RectFill(fr_Window->RPort,10,90,129,129);
		SetAPen(fr_Window->RPort,1);
	}
	work=FirstDeviceEntry;
	for (a=0;a<deviceoffset;a++) {
		work=work->next;
		if (!work) return(0);
	}
	for (b=0;b<5;b++) {
		strncpy(devicetextbuffer[b],work->name,15);
		if (!work) strncpy(devicetextbuffer[b],nullstring,15);
		work=work->next;
	}
	RefreshGList(&devicegadget[0],fr_Window,NULL,5);
}

static conbstr(in,out)
BSTR in;
char *out;
{
	register UBYTE *ch;
	register int len,i;
	ch=(UBYTE *) BADDR(in);
	len=(int) *(ch++);
	len=(len>20)?20:len;
	for (i=0;i<len;i++) out[i]=*(ch++);
	out[i]='\0';
	return(0);
}

static get_filenames()
{
	struct FileLock *lock;
	struct FileInfoBlock *finfo;
	int Class, Code, GadgetID;
	int ret;
	char directory[400];

	strcpy(directory,devicenamebuffer);
	strcat(directory,drawernamebuffer);

	FirstFileEntry=NULL; FirstDrawerEntry=NULL;
	FileEntry=NULL; DrawerEntry=NULL;
	finfo=(struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR);
	busy();
	Forbid();
	lock=(struct FileLock *) Lock(directory,ACCESS_READ);
	if (lock==NULL) goto fin;
	Examine(lock,finfo);
	while (ExNext(lock,finfo)) {
		while (fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort)) {
			Class=fr_Msg->Class; Code=fr_Msg->Code;
			if (Class==GADGETDOWN || Class==GADGETUP)
				GadgetID=((struct Gadget *) fr_Msg->IAddress)->GadgetID;
			ReplyMsg((struct Message *) fr_Msg);
			if (Class==GADGETUP && do_idtype(GadgetID)) goto defin;
			unbusy();
			ret=do_idcmp(Class,Code,GadgetID);
			busy();
			if (ret==SUPEROKAY) goto fin;
		}
		if (finfo->fib_DirEntryType>0) {
			if (FirstDrawerEntry==NULL) {
				FirstDrawerEntry=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
				strncpy(FirstDrawerEntry->name,finfo->fib_FileName,32);
				DrawerEntry=FirstDrawerEntry;
				++drawerentries;
			}
			else {
				DrawerEntry->next=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
				DrawerEntry=DrawerEntry->next;
				strncpy(DrawerEntry->name,finfo->fib_FileName,32);
				++drawerentries;
			}
			DrawerEntry->next=NULL;
			DisplayDrawers(FALSE);
		}
		else {
			if (FirstFileEntry==NULL) {
				FirstFileEntry=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
				strncpy(FirstFileEntry->name,finfo->fib_FileName,32);
				FileEntry=FirstFileEntry;
				++fileentries;
			}
			else {
				FileEntry->next=(struct direntry *) AllocMem((sizeof(struct direntry)),MEMF_CLEAR);
				FileEntry=FileEntry->next;
				strncpy(FileEntry->name,finfo->fib_FileName,32);
				++fileentries;
			}
			FileEntry->next=NULL;
			DisplayFiles(FALSE);
		}
	}
	defin:
	unbusy();
	ret=do_idcmp(Class,Code,GadgetID);
	busy();
	fin:
	if (lock) UnLock(lock);
	Permit();
	if (finfo) FreeMem(finfo,sizeof(struct FileInfoBlock));
	if (drawerentries && SortOn) Sort(FirstDrawerEntry,drawerentries);
	if (fileentries && SortOn) Sort(FirstFileEntry,fileentries);
	olddraweroffset=-1; oldfileoffset=-1;
	DisplayDrawers(TRUE); DisplayFiles(TRUE);
	unbusy();
	return(ret);
}

static DisplayFiles(clear)
BOOL clear;
{
	struct direntry *work;
	int a,b;
	if (fileoffset==oldfileoffset && clear) return(0);
	oldfileoffset=fileoffset;
	if (clear) {
		SetAPen(fr_Window->RPort,0);
		RectFill(fr_Window->RPort,10,23,129,62);
		SetAPen(fr_Window->RPort,1);
	}
	work=FirstFileEntry;
	for (a=0;a<fileoffset;a++) {
		work=work->next;
		if (!work) return(0);
	}
	for (b=0;b<5;b++) {
		strncpy(filetextbuffer[b],work->name,15);
		if (!work) strncpy(filetextbuffer[b],nullstring,15);
		work=work->next;
	}
	RefreshGList(&filegadget[0],fr_Window,NULL,5);
}

static DisplayDrawers(clear)
BOOL clear;
{
	struct direntry *work;
	int a,b;
	if (draweroffset==olddraweroffset && clear) return(0);
	olddraweroffset=draweroffset;
	if (clear) {
		SetAPen(fr_Window->RPort,0);
		RectFill(fr_Window->RPort,159,23,278,62);
		SetAPen(fr_Window->RPort,1);
	}
	work=FirstDrawerEntry;
	for (a=0;a<draweroffset;a++) {
		work=work->next;
		if (!work) return(0);
	}
	for (b=0;b<5;b++) {
		strncpy(drawertextbuffer[b],work->name,15);
		if (!work) strncpy(drawertextbuffer[b],nullstring,15);
		work=work->next;
	}
	RefreshGList(&drawergadget[0],fr_Window,NULL,5);
}

static deallocate_entries(which)
int which;
{
	struct direntry *work;
	if (which&1) {
		work=FirstDeviceEntry;
		while (work) {
			DeviceEntry=work->next;
			if (work) FreeMem(work,(sizeof(struct direntry)));
			work=DeviceEntry;
		}
		FirstDeviceEntry=NULL; DeviceEntry=NULL;
		deviceentries=0; deviceoffset=0; olddeviceoffset=-1;
	}
	if (which&2) {
		work=FirstDrawerEntry;
		while (work) {
			DrawerEntry=work->next;
			if (work) FreeMem(work,(sizeof(struct direntry)));
			work=DrawerEntry;
		}
		FirstDrawerEntry=NULL; DrawerEntry=NULL;
		drawerentries=0; draweroffset=0; olddraweroffset=-1;
	}
	if (which&4) {
		work=FirstFileEntry;
		while (work) {
			FileEntry=work->next;
			if (work) FreeMem(work,(sizeof(struct direntry)));
			work=FileEntry;
		}
		FirstFileEntry=NULL; FileEntry=NULL;
		fileentries=0; fileoffset=0; oldfileoffset=-1;
	}
	return(0);
}

static doposprop(vertpot,wp)
long vertpot;
int wp;
{
	register int i,a;
	if (wp==0) a=deviceentries;
	else if (wp==1) a=drawerentries;
	else a=fileentries;
	i=(a-5)*vertpot/0xffff;
	if (i>(a-5)) i=a-5;
	if (i<0) i=0;
	if (wp==0) {
		deviceoffset=i;
		DisplayDevices(TRUE);
	}
	else if (wp==1) {
		draweroffset=i;
		DisplayDrawers(TRUE);
	}
	else {
		fileoffset=i;
		DisplayFiles(TRUE);
	}
	return(0);
}

static getnewdevice()
{
	if (strlen(devicenamebuffer)==0) {
		strcpy(devicenamebuffer,":");
		RefreshGList(&devicenamegadget,fr_Window,NULL,1);
	}
	if (strlen(devicenamebuffer)>0) {
		if (devicenamebuffer[(strlen(devicenamebuffer)-1)]!=':') {
			strcat(devicenamebuffer,":");
			RefreshGList(&devicenamegadget,fr_Window,NULL,1);
		}
	}
	deallocate_entries(6);
	drawernamebuffer[0]='\0';
	RefreshGList(&drawernamegadget,fr_Window,NULL,1);
	DisplayDrawers(TRUE);
	DisplayFiles(TRUE);
	return(get_filenames());
}

static getnewdrawer()
{
	if (strlen(drawernamebuffer)>0) {
		if (drawernamebuffer[(strlen(drawernamebuffer)-1)]!='/') {
			strcat(drawernamebuffer,"/");
			RefreshGList(&drawernamegadget,fr_Window,NULL,1);
		}
	}
	ActivateGadget(&filenamegadget,fr_Window,NULL);
	deallocate_entries(6);
	DisplayFiles(TRUE);
	DisplayDrawers(TRUE);
	return(get_filenames());
}

static do_parent()
{
	int i,b;
	if (strlen(drawernamebuffer)==0) return(0);
	i=strlen(drawernamebuffer)-1;
	if (drawernamebuffer[i]=='/') --i;
	for (b=i;b>-1;b--) if (drawernamebuffer[b]=='/') break;
	if (b<0) b=0;
	drawernamebuffer[b]='\0';
	RefreshGList(&drawernamegadget,fr_Window,NULL,1);
	return(getnewdrawer());
}

static getnew_drawer(which)
int which;
{
	int i,b;
	struct direntry *work;
	i=draweroffset+which;
	work=FirstDrawerEntry;
	if (!work) return(FALSE);
	for (b=0;b<i;b++) work=work->next;
	if (!work) return(FALSE);
	if (strlen(drawernamebuffer)+strlen(work->name)>236) return(FALSE);
	strcat(drawernamebuffer,work->name);
	RefreshGList(&drawernamegadget,fr_Window,NULL,1);
	return(getnewdrawer());
}

static getnew_device(which)
int which;
{
	int i,b;
	struct direntry *work;
	i=deviceoffset+which;
	work=FirstDeviceEntry;
	if (!work) return(FALSE);
	for (b=0;b<i;b++) work=work->next;
	if (!work) return(FALSE);
	strcpy(devicenamebuffer,work->name);
	RefreshGList(&devicenamegadget,fr_Window,NULL,1);
	return(getnewdevice());
}

static getnew_file(which)
int which;
{
	int i,b;
	struct direntry *work;
	i=fileoffset+which;
	work=FirstFileEntry;
	if (!work) return(FALSE);
	for (b=0;b<i;b++) work=work->next;
	if (!work) return(FALSE);
	if ((strcmp(filenamebuffer,work->name))==0) return(SUPEROKAY);
	strcpy(filenamebuffer,work->name);
	RefreshGList(&filenamegadget,fr_Window,NULL,1);
	return(FALSE);
}

static do_idtype(GadgetID)
int GadgetID;
{
	switch (GadgetID) {
		case CANCEL:
		case OKAY:
		case FILENAME:
		case DRAWERNAME:
		case DEVICENAME:
		case DRAWERBASE:
		case DRAWERBASE+1:
		case DRAWERBASE+2:
		case DRAWERBASE+3:
		case DRAWERBASE+4:
		case DEVICEBASE:
		case DEVICEBASE+1:
		case DEVICEBASE+2:
		case DEVICEBASE+3:
		case DEVICEBASE+4:
		case RENAME:
		case DELETE:
		case MAKEDIR:
		case PARENT:
			return(TRUE);
		default:
			return(FALSE);
	}
}

static do_idcmp(Class,Code,GadgetID)
int Class, Code, GadgetID;
{
	int ret;
	fr_Msg=NULL;
	switch (Class) {
		case GADGETDOWN:
		case MOUSEMOVE:
			switch (GadgetID) {
				case FILENAMEPOS:
					doposprop((filenameprop.VertPot),2);
					break;
				case DRAWERPOS:
					doposprop((drawerprop.VertPot),1);
					break;
				case DEVICEPOS:
					doposprop((deviceprop.VertPot),0);
					break;
				case FILENAMEUP:
					while (!(fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort))) {
						if (fileoffset==0) break;
						--fileoffset;
						DisplayFiles(TRUE);
						doprops(&filenamepropgadget,fileentries,fileoffset);
					}
					if (fr_Msg) ReplyMsg((struct Message *) fr_Msg);
					break;
				case FILENAMEDOWN:
					while (!(fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort))) {
						if (fileoffset>=fileentries-5) break;
						++fileoffset;
						DisplayFiles(TRUE);
						doprops(&filenamepropgadget,fileentries,fileoffset);
					}
					if (fr_Msg) ReplyMsg((struct Message *) fr_Msg);
					break;
				case DRAWERUP:
					while (!(fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort))) {
						if (draweroffset==0) break;
						--draweroffset;
						DisplayDrawers(TRUE);
						doprops(&drawerpropgadget,drawerentries,draweroffset);
					}
					if (fr_Msg) ReplyMsg((struct Message *) fr_Msg);
					break;
				case DRAWERDOWN:
					while (!(fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort))) {
						if (draweroffset>=drawerentries-5) break;
						++draweroffset;
						DisplayDrawers(TRUE);
						doprops(&drawerpropgadget,drawerentries,draweroffset);
					}
					if (fr_Msg) ReplyMsg((struct Message *) fr_Msg);
					break;
				case DEVICEUP:
					while (!(fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort))) {
						if (deviceoffset==0) break;
						--deviceoffset;
						DisplayDevices(TRUE);
						doprops(&devicepropgadget,deviceentries,deviceoffset);
					}
					if (fr_Msg) ReplyMsg((struct Message *) fr_Msg);
					break;
				case DEVICEDOWN:
					while (!(fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort))) {
						if (deviceoffset>=deviceentries-5) break;
						++deviceoffset;
						DisplayDevices(TRUE);
						doprops(&devicepropgadget,deviceentries,deviceoffset);
					}
					if (fr_Msg) ReplyMsg((struct Message *) fr_Msg);
					break;
			}
			if (GadgetID!=FILENAMEPOS && GadgetID!=DRAWERPOS && GadgetID!=DEVICEPOS)
				ActivateGadget(&filenamegadget,fr_Window,NULL);
			break;
		case GADGETUP:
			switch (GadgetID) {
				case CANCEL:
					ret=CANCEL;
					break;
				case OKAY:
					ret=OKAY;
					break;
				case DRAWERNAME:
					ret=getnewdrawer();
					break;
				case DEVICENAME:
					ActivateGadget(&drawernamegadget,fr_Window,NULL);
					ret=getnewdevice();
					break;
				case FILENAME:
					ret=OKAY;
					break;
				case DRAWERBASE:
				case DRAWERBASE+1:
				case DRAWERBASE+2:
				case DRAWERBASE+3:
				case DRAWERBASE+4:
					ret=getnew_drawer((GadgetID-DRAWERBASE));
					break;
				case DEVICEBASE:
				case DEVICEBASE+1:
				case DEVICEBASE+2:
				case DEVICEBASE+3:
				case DEVICEBASE+4:
					ActivateGadget(&drawernamegadget,fr_Window,NULL);
					ret=getnew_device((GadgetID-DEVICEBASE));
					break;
				case FILEBASE:
				case FILEBASE+1:
				case FILEBASE+2:
				case FILEBASE+3:
				case FILEBASE+4:
					ret=getnew_file((GadgetID-FILEBASE));
					break;
				case PARENT:
					do_parent();
					ret=PARENT;
					break;
				case DELETE:
					do_delete();
					ret=DELETE;
					break;
				case RENAME:
					do_rename();
					ret=RENAME;
					break;
				case MAKEDIR:
					do_makedir();
					ret=MAKEDIR;
					break;
			}
			switch (GadgetID) {
				case DEVICENAME:
				case DEVICEBASE:
				case DEVICEBASE+1:
				case DEVICEBASE+2:
				case DEVICEBASE+3:
				case DEVICEBASE+4:
					ActivateGadget(&drawernamegadget,fr_Window,NULL);
					break;
				default:
				ActivateGadget(&filenamegadget,fr_Window,NULL);
			}
			return(ret);
			break;
		case DISKINSERTED:
		case DISKREMOVED:
			deallocate_entries(1);
			olddeviceoffset=-1;
			DisplayDevices(TRUE);
			get_devicenames();
			break;
		default:
			if (!GadgetID) ActivateGadget(&filenamegadget,fr_Window,NULL);
			break;
	}
	return(GadgetID);
}

static Sort(which,count)
struct direntry *which;
int count;
{
	register int gap,i,j;
	register struct direntry *file1, *file2;
	char *hail;
	hail=fr_Window->Title;
	SetWindowTitles(fr_Window,"Please wait... Sorting...",-1);
	busy();
	for (gap=count/2;gap>0;gap/=2)
		for (i=gap;i<count;i++)
			for (j=i-gap;j>=0;j-=gap) {
				file1=(struct direntry *) getentry(j,which);
				file2=(struct direntry *) getentry((j+gap),which);
				if (mystrcmp(file1->name,file2->name)<=0) break;
#ifdef LATTICE
				swmem(file1->name,file2->name,32);
#else
				swapmem(file1->name,file2->name,32);
#endif
			}
	SetWindowTitles(fr_Window,hail,-1);
	unbusy();
	return(0);
}

static getentry(h,which)
int h;
struct direntry *which;
{
	struct direntry *work;
	register int a;
	work=which;
	for (a=0;a<h;a++) work=work->next;
	return(work);
}

static mystrcmp(s,t)
char s[], t[];
{
	register int i;
	i=0;
	while (toupper(s[i])==toupper(t[i]))
		if (s[i++]=='\0') return(0);
	return(toupper(s[i])-toupper(t[i]));
}

static doprops(gadget,entries,offset)
struct Gadget *gadget;
register int entries;
register int offset;
{
	register long vertpot;
	struct PropInfo *pinfo;
	if (entries<=5) return(0);
	vertpot=(offset*0xffff)/(entries-5);
	pinfo=(struct PropInfo *)&(gadget->SpecialInfo);
	if (vertpot==pinfo->VertPot) return(0);
	NewModifyProp(gadget,fr_Window,NULL,AUTOKNOB|FREEVERT,0,vertpot,0,0x1000,1);
}

static do_delete()
{
	int Class, Code, GadgetID, i;
	char file[400];
	struct direntry *work, *work1;
	char *hail;
	if (strlen(filenamebuffer)==0) return(0);
	hail=fr_Window->Title;
	SetWindowTitles(fr_Window,"OKAY to confirm, or CANCEL to cancel",-1);
	FOREVER {
		Wait(1<<fr_Window->UserPort->mp_SigBit);
		while (fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort)) {
			Class=fr_Msg->Class; Code=fr_Msg->Code;
			if (Class==GADGETUP) GadgetID=((struct Gadget *) fr_Msg->IAddress)->GadgetID;
			ReplyMsg((struct Message *) fr_Msg);
			if (Class!=GADGETUP) break;
			if (GadgetID!=OKAY && GadgetID!=CANCEL) break;
			if (GadgetID==CANCEL) {
				SetWindowTitles(fr_Window,hail,-1);
				return(FALSE);
			}
			busy();
			SetWindowTitles(fr_Window,"Please wait...",-1);
			strcpy(file,devicenamebuffer);
			strcat(file,drawernamebuffer);
			strcat(file,filenamebuffer);
			i=DeleteFile(file);
			if (!i) {
				SetWindowTitles(fr_Window,"Delete failed.",-1);
				DisplayBeep(NULL);
				Delay(50);
			}
			if (i) {
				work=FirstFileEntry;
				strcpy(file,filenamebuffer);
				strcpy(filenamebuffer,"");
				RefreshGList(&filenamegadget,fr_Window,NULL,1);
				--fileentries;
				while ((strcmp(work->name,file)!=0)) {
					work1=work;
					work=work->next;
					if (!work) break;
				}
				if (work->next) {
					if (work1) work1->next=work->next;
					if (work==FirstFileEntry) FirstFileEntry=work->next;
				}
				else {
					if (work1) work1->next=NULL;
					if (work==FirstFileEntry) FirstFileEntry=NULL;
				}
				if (work) FreeMem(work,(sizeof(struct direntry)));
				oldfileoffset=-1;
				if (fileoffset>0) --fileoffset;
				DisplayFiles(TRUE);
				doprops(&filenamepropgadget,fileentries,fileoffset);
			}
			SetWindowTitles(fr_Window,hail,-1);
			unbusy();
			return(i);
		}
	}
}

static do_rename()
{
	int Class, Code, GadgetID, i;
	char file1[400], file2[400], file[32];
	struct direntry *work, *work1;
	char *hail;
	if (strlen(filenamebuffer)==0) return(0);
	hail=fr_Window->Title;
	SetWindowTitles(fr_Window,"Enter new name and choose OKAY",-1);
	strcpy(file,filenamebuffer);
	strcpy(file1,devicenamebuffer);
	strcat(file1,drawernamebuffer);
	strcat(file1,filenamebuffer);
	ActivateGadget(&filenamegadget,fr_Window,NULL);
	FOREVER {
		Wait(1<<fr_Window->UserPort->mp_SigBit);
		while (fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort)) {
			Class=fr_Msg->Class; Code=fr_Msg->Code;
			if (Class==GADGETUP) GadgetID=((struct Gadget *) fr_Msg->IAddress)->GadgetID;
			ReplyMsg((struct Message *) fr_Msg);
			if (Class!=GADGETUP) break;
			if (GadgetID!=OKAY) break;
			busy();
			SetWindowTitles(fr_Window,"Please wait...",-1);
			strcpy(file2,devicenamebuffer);
			strcat(file2,drawernamebuffer);
			strcat(file2,filenamebuffer);
			i=Rename(file1,file2);
			if (!i) {
				SetWindowTitles(fr_Window,"Rename failed.",-1);
				DisplayBeep(NULL);
				Delay(50);
				strcpy(filenamebuffer,file);
				RefreshGList(&filenamegadget,fr_Window,NULL,1);
			}
			if (i) {
				work=FirstFileEntry;
				while ((strcmp(work->name,file)!=0)) {
					work1=work;
					work=work->next;
					if (!work) break;
				}
				strcpy(work->name,filenamebuffer);
				oldfileoffset=-1;
				if (SortOn) Sort(FirstFileEntry,fileentries);
				DisplayFiles(TRUE);
				doprops(&filenamepropgadget,fileentries,fileoffset);
			}
			SetWindowTitles(fr_Window,hail,-1);
			unbusy();
			return(i);
		}
	}
}

static do_makedir()
{
	int Class, Code, GadgetID;
	char file1[400], file2[400];
	struct FileLock *i;
	char *hail;
	hail=fr_Window->Title;
	SetWindowTitles(fr_Window,"Enter new dir. name, OKAY or CANCEL",-1);
	strcpy(file1,drawernamebuffer);
	ActivateGadget(&drawernamegadget,fr_Window,NULL);
	FOREVER {
		Wait(1<<fr_Window->UserPort->mp_SigBit);
		while (fr_Msg=(struct IntuiMessage *) GetMsg(fr_Window->UserPort)) {
			Class=fr_Msg->Class; Code=fr_Msg->Code;
			if (Class==GADGETUP) GadgetID=((struct Gadget *) fr_Msg->IAddress)->GadgetID;
			ReplyMsg((struct Message *) fr_Msg);
			if (Class!=GADGETUP) break;
			if (GadgetID!=OKAY && GadgetID!=CANCEL) break;
			if (GadgetID==CANCEL) {
				strcpy(drawernamebuffer,file1);
				RefreshGList(&drawernamegadget,fr_Window,NULL,1);
				SetWindowTitles(fr_Window,hail,-1);
				return(FALSE);
			}
			busy();
			SetWindowTitles(fr_Window,"Please wait...",-1);
			strcpy(file2,devicenamebuffer);
			strcat(file2,drawernamebuffer);
			i=(struct FileLock *) CreateDir(file2);
			if (!i) {
				SetWindowTitles(fr_Window,"Make Dir failed.",-1);
				DisplayBeep(NULL);
				Delay(50);
				strcpy(drawernamebuffer,file1);
				RefreshGList(&drawernamegadget,fr_Window,NULL,1);
			}
			if (i) {
				UnLock(i);
				getnewdrawer();
			}
			SetWindowTitles(fr_Window,hail,-1);
			unbusy();
			return(TRUE);
		}
	}
}

static busy()
{
	SetPointer(fr_Window,&BusySpriteData[0],18,16,0,0);
	return(0);
}

static unbusy()
{
	ClearPointer(fr_Window);
	return(0);
}
