/*
 * Key Map Editor ver 1.0
 *
 * By: Tim Friest
 * on: December 31, 1988
 *
 * Editor for standard Amiga Key Maps.  Allows custom key definitions.
 * Produces files compatible with AmigaDOS SetMap command.
 */

unsigned long	ResourceFlags = 0;
unsigned long	StatusFlags = 0;

#include "KME_Includes.h"
#include "KME_Protos.h"
#include "KME_Defs.h"
#include "KME_Menus.h"
#include "KME_Gadgets.h"
#include "KME_Window.h"

int	ReturnCode	= 0;
struct	GfxBase	*GfxBase;
struct	IntuitionBase	*IntuitionBase;
struct	timerequest	*Timer;
ULONG	Timer_sf	= 0;
struct	TextAttr	Topaz8TextAttr = {
	"topaz.font",	/* name */
	8,		/* size */
	FS_NORMAL,	/* style */
	FPF_ROMFONT	/* flags */
};
struct	TextFont	*TopazFont;
struct	Window	*KeyMapEdWindow;
struct	Window	*FileReqWindow;
struct	Window	*KeyReqWindow;
BPTR	DirLock;
BPTR	KeyMapSegment;
struct	KeyMapNode	*KeyMapNode;
struct	FileNode	*FileList = NULL;
int	FileListLength	= 0;
char	*filename = NULL;

unsigned long	Wind_sf = 0;

struct Gadget	*FromKeyGad = NULL;

extern	struct StringInfo	NameStrGadSInfo;
extern	UBYTE FileNameBuff[30];

extern int main(int, char **);
/*
 * Key Map Editor Main procedure
 *
 * reads keymap filename from command line if supplied
 */
int main(argc, argv)
int argc;
char **argv;
{
	struct IntuiMessage *Message;
	unsigned long	Class;
	unsigned short	Code;
	APTR	Address;
	struct MenuItem *Item;
	struct Gadget *Gad;
	BPTR	OldDirLock, templock;

/*
 * Get the Key Map Filename
 */
	if (argc > 1) {
		if (strcmp(argv[1], "?") == 0) {
			Write(Output(), "KeyMapEd ver 1.0 1-Jan-89\n", 26);
			Write(Output(), "         by Tim Friest\n", 23);
			Write(Output(), "Usage: KeyMapEd keymap\n", 23);
			goto CleanUp;
		}
		filename = argv[1];
	}

/*
 * Change directory to devs:keymaps
 */
	if ((DirLock = Lock("devs:keymaps", SHARED_LOCK)) == NULL) {
		ReturnCode = IoErr();
		Write(Output(), "Unable to place lock on devs:keymaps\n", 37);
		goto CleanUp;
	}
	FlagResource(RF_DirLock);
	if ((OldDirLock = CurrentDir(DirLock)) == NULL) {
		ReturnCode = IoErr();
		Write(Output(), "Unable to CD to devs:keymaps\n", 29);
		goto CleanUp;
	}
	FlagResource(RF_CurrentDir);

/*
 * Open necessary libraries
 */
	if ((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0))
	     == NULL) {
		Write(Output(), "Unable to open Graphics Library\n", 32);
		goto CleanUp;
	}
	FlagResource(RF_Graphics);

	if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary(
	     "intuition.library", 0)) == NULL) {
		Write(Output(), "Unable to open Intuition Library\n", 33);
		goto CleanUp;
	}
	FlagResource(RF_Intuition);

/*
 * Open necessary devices
 */
	if ((Timer = (struct timerequest *)CreateExtIO(CreatePort("Timer", 0), sizeof(struct timerequest))) == NULL) {
		Write(Output(), "Unable to create timer ExtIO block\n", 35);
		goto CleanUp;
	}
	if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)Timer, NULL)) {
		Write(Output(), "Unable to open timer device\n", 28);
		goto CleanUp;
	}
	Timer_sf = (1<<Timer->tr_node.io_Message.mn_ReplyPort->mp_SigBit);
	FlagResource(RF_Timer);

/*
 * Read in the Key Map
 */
	if (filename != NULL) {
		strcpy(FileNameBuff, filename);
		NameStrGadSInfo.BufferPos = strlen(filename);
		if (ReadKeyMap(FileNameBuff))
			UpdateDisplay(GadgetList, KeyMapNode, TRUE);
		else
			KeyMapIO(FileNameBuff, LOAD);
	}
	else
		KeyMapIO(filename, LOAD);
	if (!CheckResource(RF_KeyMap))
		goto CleanUp;

/*
 * Open the Key Map Editor window
 */
	if ((KeyMapEdWindow = OpenWindow(&NewKMEWindow)) == NULL) {
		Write(Output(), "Unable to open window\n", 22);
		goto CleanUp;
	}
	FlagResource(RF_Window);
	Wind_sf = (1<<KeyMapEdWindow->UserPort->mp_SigBit);

/*
 * Set font to Topaz 8 (so everything looks right)
 */
	if ((TopazFont = OpenFont(&Topaz8TextAttr)) != NULL) {
		if (!SetFont(KeyMapEdWindow->RPort, TopazFont))
			Write(Output(), "Unable to set font in Key Map Ed window\n", 40);
		FlagResource(RF_Font);
	}
	else
		Write(Output(), "Unable to open Topaz 8 font\n", 28);

/* Add menu to Window */

	SetMenuStrip(KeyMapEdWindow, MenuList);
	FlagResource(RF_Menu);
	SetFlag(SF_Define);

/*
 * Process Inputs
 */
	while (Wait(Wind_sf) == Wind_sf) {
		while ((Message = (struct IntuiMessage *)GetMsg(KeyMapEdWindow->UserPort)) != NULL) {
			Class = Message->Class;
			Code = Message->Code;
			Address = Message->IAddress;
			ReplyMsg((struct Message *)Message);
			switch (Class) {
				case CLOSEWINDOW: /* CloseWindow gadget was hit */
					if (CheckFlag(SF_Modified)) {
						if (VerifyReq())
							goto CleanUp;
					}
					else
						goto CleanUp;
					break;
				case MENUPICK:	/* Menu Item was selected */
					while (Code != MENUNULL) {
						Item = ItemAddress(MenuList, Code);
						if (!ProcMenu(Code))
							goto CleanUp;
						Code = Item->NextSelect;
					}
					break;
				case GADGETUP:	/* Gadget was selected */
					Gad = (struct Gadget *)Address;
					ProcGadget(Gad);
					break;
			} /* switch */
		} /* while */
	} /* while */

CleanUp:
	if (CheckFlag(SF_Pointer))
		ChangePointer(0);
	if (CheckResource(RF_Timer)) {
		CloseDevice((struct IORequest *)Timer);
		DeletePort(Timer->tr_node.io_Message.mn_ReplyPort);
		DeleteExtIO((struct IORequest *)Timer);
		ClearResource(RF_Timer);
	}
	if (CheckResource(RF_FileList)) {
		struct FileNode *temp;

		while (FileList != NULL) {
			temp = FileList;
			FileList = FileList->NextFile;
			if (temp->FileName != NULL)
				FreeMem(temp->FileName, strlen(temp->FileName)+1);
			FreeMem(temp, sizeof(struct FileNode));
		}
		ClearResource(RF_FileList);
	}
	if (CheckResource(RF_KeyMap))
		FreeKeyMap(KeyMapNode);
	if (CheckResource(RF_Menu)) {
		ClearMenuStrip(KeyMapEdWindow);
		ClearResource(RF_Menu);
	}
	if (CheckResource(RF_GadgetText)) {
		Gad = GadgetList;
		do
			if (Gad->GadgetText != NULL) {
				if (Gad->GadgetText->IText != NULL)
					FreeMem(Gad->GadgetText->IText, strlen(Gad->GadgetText->IText)+1);
				FreeMem(Gad->GadgetText, sizeof(struct IntuiText));
				Gad->GadgetText = NULL;
			}
		while ((Gad = Gad->NextGadget) != NULL);
		ClearResource(RF_GadgetText);
	}
	if (CheckResource(RF_Font)) {
		CloseFont(TopazFont);
		ClearResource(RF_Font);
	}
	if (CheckResource(RF_Window)) {
		CloseWindow(KeyMapEdWindow);
		ClearResource(RF_Window);
	}
	if (CheckResource(RF_Intuition)) {
		CloseLibrary((struct Library *)IntuitionBase);
		ClearResource(RF_Intuition);
	}
	if (CheckResource(RF_Graphics)) {
		CloseLibrary((struct Library *)GfxBase);
		ClearResource(RF_Graphics);
	}
	if (CheckResource(RF_CurrentDir)) {
		templock = CurrentDir(OldDirLock);
		ClearResource(RF_CurrentDir);
	}
	if (CheckResource(RF_DirLock)) {
		UnLock(DirLock);
		ClearResource(RF_DirLock);
	}
	return(ReturnCode);
}
