/*
 * Key Map Editor ver 1.0
 * Process File Requester
 *
 * parameter: 	Option - "Load" or "Save" strings to place in gadget
 * returns: 	Filename - Filename of file to load or save
 *
 * by: Tim Friest
 * on: January 7, 1989
 */

#include "KME_Includes.h"
#include "KME_Protos.h"
#include "KME_Defs.h"
#include "KME_FileReq.h"
#include "KME_Globals.h"

extern int InsertFileNode(struct FileNode *);
extern void GetFileList(void);
extern struct FileNode *UpdateFileDisplay(struct FileNode *, int *, int);

USHORT	PotIncrement;

char *ProcFileReq(Option)
char *Option;
{
	struct FileNode *DisplayFile;
	int	CurrentDisplayFile = 0;
	static SHORT FileReqWindx = FRWLEFTEDGE;
	static SHORT FileReqWindy = FRWTOPEDGE;
	ULONG	FileWind_sf = 0;
	struct IntuiMessage	*Message;
	ULONG	Class;
	USHORT	Code;
	struct Gadget *Gad;
	struct StringInfo *StrInfo;
	char	*filename = NULL;
	int	Done = FALSE;
	ULONG	signal;
	int	Move;
	
	if (!(CheckResource(RF_FileList)))
		GetFileList();
	NewFileReqWindow.LeftEdge = FileReqWindx;
	NewFileReqWindow.TopEdge = FileReqWindy;
	if ((FileReqWindow = OpenWindow(&NewFileReqWindow)) == NULL)
		return(NULL);
	FileWind_sf = (1<<FileReqWindow->UserPort->mp_SigBit);
	if (CheckResource(RF_Font))
		SetFont(FileReqWindow->RPort, TopazFont);
	ContinueGadget.GadgetText->IText = Option;
	if (NameGadgetListLen < FileListLength) {
		SliderGadPInfo.VertBody = MAXBODY / FileListLength * NameGadgetListLen;
		PotIncrement = MAXPOT/(FileListLength-NameGadgetListLen);
	}
	else {
		SliderGadPInfo.VertBody = -1;
		PotIncrement = -1;
	}
	if (!Request(&FileRequester, FileReqWindow))
		Done = TRUE;
	while (!Done) {
		while ((signal = Wait(FileWind_sf|Wind_sf)) == Wind_sf) {
			while ((Message = (struct IntuiMessage *)GetMsg(KeyMapEdWindow->UserPort)) != NULL)
				ReplyMsg((struct Message *)Message);
			DisplayBeep(FileReqWindow->WScreen);
		} /* while */
		if (signal == Timer_sf) {
			WaitIO((struct IORequest *)Timer);
			ClearFlag(SF_Timer);
		}
		while ((!Done) && ((Message = (struct IntuiMessage *)GetMsg(FileReqWindow->UserPort)) != NULL)) {
			Class = Message->Class;
			Code = Message->Code;
			Gad = (struct Gadget *)Message->IAddress;
			ReplyMsg((struct Message *)Message);
			switch (Class) {
				case REQSET:
					DisplayFile = UpdateFileDisplay(FileList, &CurrentDisplayFile, 0);
					if (!ActivateGadget(&NameStrGadget, FileReqWindow, &FileRequester)) {
						EndRequest(&FileRequester, FileReqWindow);
						Done = TRUE;
					}
					break;
				case GADGETDOWN:
					if (CheckFlag(SF_Timer)) {
						if (CheckIO((struct IORequest *)Timer))
							WaitIO((struct IORequest *)Timer);
						else
							AbortIO((struct IORequest *)Timer);
						ClearFlag(SF_Timer);
					}
					switch (Gad->GadgetID) {
						case 0x03: /* slider down gad */
							do {
								DisplayFile = UpdateFileDisplay(DisplayFile, &CurrentDisplayFile, 1);
								Timer->tr_node.io_Command = TR_ADDREQUEST;
								Timer->tr_time.tv_secs = 0;
								Timer->tr_time.tv_micro = 50000;
								SendIO((struct IORequest *)Timer);
								if ((signal = Wait(FileWind_sf|Timer_sf)) == Timer_sf)
									WaitIO((struct IORequest *)Timer);
							} while ((signal == Timer_sf) && (Gad->Flags & SELECTED));
							if (signal != Timer_sf)
								AbortIO((struct IORequest *)Timer);
							if ((Message = (struct IntuiMessage *)GetMsg(FileReqWindow->UserPort)) != NULL)
								ReplyMsg((struct Message *)Message);
							break;
						case 0x04: /* slider up gad */
							do {
								DisplayFile = UpdateFileDisplay(DisplayFile, &CurrentDisplayFile, -1);
								Timer->tr_node.io_Command = TR_ADDREQUEST;
								Timer->tr_time.tv_secs = 0;
								Timer->tr_time.tv_micro = 50000;
								SendIO((struct IORequest *)Timer);
								if ((signal = Wait(FileWind_sf|Timer_sf)) == Timer_sf)
									WaitIO((struct IORequest *)Timer);
							} while ((signal == Timer_sf) && (Gad->Flags & SELECTED));
							if (signal != Timer_sf)
								AbortIO((struct IORequest *)Timer);
							if ((Message = (struct IntuiMessage *)GetMsg(FileReqWindow->UserPort)) != NULL)
								ReplyMsg((struct Message *)Message);
					} /* switch */
					break;
				case GADGETUP:
					switch (Gad->GadgetID) {
						case 0x00: /* Abort Gadget Selected */
							EndRequest(&FileRequester, FileReqWindow);
							filename = NULL;
							Done = TRUE;
							break;
						case 0x01: /* Continue Gadget Selected */ 
						case 0x05: /* String Gadget Selected */
							EndRequest(&FileRequester, FileReqWindow);
							StrInfo = (struct StringInfo *)NameStrGadget.SpecialInfo;
							filename = StrInfo->Buffer;
							Done = TRUE;
							break;
						case 0x02: /* Slider Gadget Selected */
							Move = (SliderGadPInfo.VertPot/PotIncrement) - CurrentDisplayFile;
							if (Move != 0)
								DisplayFile = UpdateFileDisplay(DisplayFile, &CurrentDisplayFile, Move);
							break;
						case 0x10: /* Name GadgetID-$10 Selected */
						case 0x11:
						case 0x12:
						case 0x13:
						case 0x14:
						case 0x15:
						case 0x16:
							if (CheckFlag(SF_Timer)) {
								if (CheckIO((struct IORequest *)Timer)) {
									WaitIO((struct IORequest *)Timer);
									ClearFlag(SF_Timer);
								}
								else {
									AbortIO((struct IORequest *)Timer);
									ClearFlag(SF_Timer);
									if (strcmp(filename, Gad->GadgetText->IText) == 0) {
										EndRequest(&FileRequester, FileReqWindow);
										Done = TRUE;
										break;
									}
								}
							}
							strcpy(FileNameBuff, Gad->GadgetText->IText);
							filename = FileNameBuff;
							NameStrGadSInfo.BufferPos = strlen(filename);
							RefreshGList(&NameStrGadget, FileReqWindow, &FileRequester, 1);
							if (!ActivateGadget(&NameStrGadget, FileReqWindow, &FileRequester)) {
								EndRequest(&FileRequester, FileReqWindow);
								Done = TRUE;
							}
							Timer->tr_node.io_Command = TR_ADDREQUEST;
							Timer->tr_time.tv_secs = 0;
							Timer->tr_time.tv_micro = 250000;
							SendIO((struct IORequest *)Timer);
							SetFlag(SF_Timer);
					} /* switch */
			} /* switch */
		} /* while */
	} /* while */
	FileReqWindx = FileReqWindow->LeftEdge;
	FileReqWindy = FileReqWindow->TopEdge;
	CloseWindow(FileReqWindow);
	if (CheckFlag(SF_Timer)) {
		if (CheckIO((struct IORequest *)Timer))
			WaitIO((struct IORequest *)Timer);
		else
			AbortIO((struct IORequest *)Timer);
		ClearFlag(SF_Timer);
	}
	if (stricmp(Option, "Save") == 0) {
		int len;
		struct FileNode *temp;

		len = strlen(filename)+1;
		if ((temp = (struct FileNode *)AllocMem(sizeof(struct FileNode), 0)) != 0)
			if ((temp->FileName = (char *)AllocMem(len, MEMF_CLEAR)) != NULL) {
				strcpy(temp->FileName, filename);
				if (!InsertFileNode(temp)) {
					FreeMem(temp->FileName, len);
					FreeMem(temp, sizeof(struct FileNode));
				}
			}
			else
				FreeMem(temp, sizeof(struct FileNode));
	}
	return(filename);
}

/*
 * Insert File Node
 */
int InsertFileNode(Node)
struct FileNode *Node;
{
	struct FileNode *temp, *prev = NULL;
	int result = 1;

	temp = FileList;
	while ((temp != NULL) && ((result = stricmp(Node->FileName, temp->FileName)) > 0)) {
		prev = temp;
		temp = temp->NextFile;
	} /* while */
	if (result != 0) {
		Node->NextFile = temp;
		if (temp != NULL)
			temp->PrevFile = Node;
		Node->PrevFile = prev;
		if (prev != NULL)
			prev->NextFile = Node;
		else
			FileList = Node;
		FileListLength += 1;
	}
	return(result);
}

/*
 * Get File List
 */
void GetFileList()
{
	struct FileInfoBlock *FileInfo;
	struct FileNode *temp;
	int len;

	if ((FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock), MEMF_CLEAR)) != NULL) {
		if (Examine(DirLock, FileInfo)) {
			temp = (struct FileNode *)AllocMem(sizeof(struct FileNode), 0);
			while ((temp != NULL) && (ExNext(DirLock, FileInfo))) {
				len = strlen(FileInfo->fib_FileName)+1;
				if ((temp->FileName = (char *)AllocMem(len, MEMF_CLEAR)) != NULL) {
					strcpy(temp->FileName, FileInfo->fib_FileName);
					if (InsertFileNode(temp))
						temp = (struct FileNode *)AllocMem(sizeof(struct FileNode), 0);
					else
						FreeMem(temp->FileName, sizeof(temp->FileName)+1);
				}
				else {
					FreeMem(temp, sizeof(struct FileNode));
					temp = NULL;
				}
			} /* while */
		}
		if (temp != NULL)
			FreeMem(temp, sizeof(struct FileNode));
		FreeMem(FileInfo, sizeof(struct FileInfoBlock));
		if (FileList != NULL)
			FlagResource(RF_FileList);
	}
}

/*
 * Update File Display
 */
struct FileNode *UpdateFileDisplay(DisplayFile, CurrentDisplayFile, Move)
struct FileNode *DisplayFile;
int *CurrentDisplayFile;
int Move;
{
	struct FileNode *temp;
	struct Gadget *Gad;

	temp = DisplayFile;
	if (Move > 0) {
		*CurrentDisplayFile += Move;
		for (;((temp->NextFile != NULL) && (Move > 0)); Move--)
			temp = temp->NextFile;
		*CurrentDisplayFile -= Move;
		DisplayFile = temp;
		for (Move = 1; ((temp->NextFile != NULL) && (Move < NameGadgetListLen)); Move++)
			temp = temp->NextFile;
		Move = Move - NameGadgetListLen;
		temp = DisplayFile;
	}
	if (Move < 0) {
		*CurrentDisplayFile += Move;
		for (;((temp->PrevFile != NULL) && (Move < 0)); Move++)
			temp = temp->PrevFile;
		*CurrentDisplayFile -= Move;
		DisplayFile = temp;
	}
	Gad = NameGadgetList;
	while (Gad != NULL) {
		if (temp != NULL) {
			Gad->GadgetText->IText = temp->FileName;
			temp = temp->NextFile;
		}
		else
			Gad->GadgetText->IText = NULL;
		Gad = Gad->NextGadget;
	} /* while */
	ModifyProp(&SliderGadget, FileReqWindow, &FileRequester, SliderGadPInfo.Flags,
		SliderGadPInfo.HorizPot, (PotIncrement * (*CurrentDisplayFile)),
		SliderGadPInfo.HorizBody, SliderGadPInfo.VertBody);
	RefreshGList(NameGadgetList, FileReqWindow, &FileRequester, NameGadgetListLen);
	return(DisplayFile);
}
