/* $Revision Header built by Ueli Kaufmann ********** (please edit) **********
**
** © Copyright by Ueli `Lonely Rider' Kaufmann
**
** File             : xemhex.library
** Created on       : Sonntag 23-Mai-93  15:17:12
** Created by       : U. Kaufmann (Ueli_Kaufmann@augs1.adsp.sub.org)
** Current revision : V4.5
**
**
** Purpose
** -------
**     HEX Emulator ala XEm
**
**
** Revision V4.5
** -------------
**   - first release
**
*********************************************************************************/

#include "ownincs/HEXConsole.h"



/* allowed globals.. */
struct	ExecBase			*SysBase;
struct	DosLibrary		*DOSBase;
struct	GfxBase			*GfxBase;
struct	IntuitionBase	*IntuitionBase;
struct	Library			*DiskfontBase;
struct	Library			*KeymapBase;
struct	Library			*UtilityBase;


/* utils.a */
VOID *GetSucc(VOID *);
VOID *GetHead(VOID *);
VOID *GetTail(VOID *);
VOID *GetPred(VOID *);
VOID BZero(VOID *, LONG);
VOID BSet(VOID *, LONG, LONG);

STATIC VOID HEX_internalsettings(struct HEXConsole *con);
STATIC BOOL HEX_parseoptions(struct HEXConsole *con, STRPTR optionsBuffer);


VOID __saveds __asm __UserLibCleanup(register __a6 struct Library *libBase)
{
	if(DiskfontBase != NULL)
	{
		CloseLibrary(DiskfontBase);
		DiskfontBase = NULL;
	}

	if(KeymapBase != NULL)
	{
		CloseLibrary(KeymapBase);
		KeymapBase = NULL;
	}

	if(UtilityBase != NULL)
	{
		CloseLibrary(UtilityBase);
		UtilityBase = NULL;
	}

	if(IntuitionBase != NULL)
	{
		CloseLibrary((struct Library *)IntuitionBase);
		IntuitionBase = NULL;
	}

	if(GfxBase != NULL)
	{
		CloseLibrary((struct Library *)GfxBase);
		GfxBase = NULL;
	}

	if(DOSBase != NULL)
	{
		CloseLibrary((struct Library *)DOSBase);
		DOSBase = NULL;
	}
}


int __saveds __asm __UserLibInit(register __a6 struct Library *libBase)
{
	SysBase = *(struct ExecBase **)4;

	if((DOSBase			= (struct DosLibrary *)OpenLibrary("dos.library", 37)) == NULL)
		return(1);

	if((IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37)) == NULL)
		return(1);

	if((GfxBase			= (struct GfxBase *)OpenLibrary("graphics.library", 37)) == NULL)
		return(1);

	if((UtilityBase	= OpenLibrary("utility.library", 37)) == NULL)
		return(1);

	if((KeymapBase		= OpenLibrary("keymap.library", 37)) == NULL)
		return(1);

	if((DiskfontBase	= OpenLibrary("diskfont.library", 33)) == NULL)
		return(1);


	return(0);
}


VOID ProcessData(struct HEXConsole *con, UBYTE *buffer, ULONG length)
{
	con->wcon->io_Length	= length;
	con->wcon->io_Data	= (APTR)buffer;
	con->wcon->io_Command= CMD_WRITE;
	DoIO((struct IORequest *)con->wcon);
}


BOOL __saveds __asm XEmulatorSetup(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con;
	
	io->xem_console = NULL;

	if(con = AllocVec(sizeof(struct HEXConsole), MEMF_ANY | MEMF_CLEAR))
	{
		con->io = io;			/* for easier passing..(-; */
		io->xem_console = con;

		if(con->wconport = CreatePort(NULL, 0))
		{
			if(con->wcon = CreateStdIO(con->wconport))
			{
				STATIC struct TextAttr topazAttr8 = { "topaz.font", 8, FS_NORMAL, FPF_ROMFONT };

				if(con->topazFont8 = OpenFont(&topazAttr8))
				{
					STATIC struct TextAttr topazAttr11 = { "topaz.font", 11, FS_NORMAL, FPF_DISKFONT };

					if((con->topazFont11 = OpenFont(&topazAttr11)) == NULL)
						con->topazFont11 = OpenDiskFont(&topazAttr11);

					return(TRUE);
				}
			}
		}
	}

	return(FALSE);
}


VOID __saveds __asm XEmulatorCleanup(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	if(con != NULL)
	{
		*con->io->xem_signal = 0;

		if(con->wcon->io_Device != NULL)
			CloseDevice((struct IORequest *)con->wcon);

		if(con->wcon != NULL)
			DeleteStdIO(con->wcon);

		if(con->wconport != NULL)
			DeletePort(con->wconport);

		if(con->topazFont8 != NULL)
			CloseFont(con->topazFont8);

		if(con->topazFont11 != NULL)
			CloseFont(con->topazFont11);

		FreeVec(con);
	}
}


BOOL __saveds __asm XEmulatorOpenConsole(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	if(con != NULL)
	{
		struct RastPort *rp=con->io->xem_window->RPort;

		if(con->io->xem_font->tf_XSize != 8)
		{
			if(con->io->xem_font->tf_YSize > 8  &&  con->topazFont11 != NULL) 
				SetFont(rp, con->topazFont11);
			else
				SetFont(rp, con->topazFont8);
		}
		else
			SetFont(rp, con->io->xem_font);

		con->wcon->io_Data	= (APTR)con->io->xem_window;
		con->wcon->io_Length	= sizeof(struct Window);
		if(!OpenDevice("console.device", 0, (struct IORequest *)con->wcon, 0))
			return(TRUE);	
		else
			con->wcon->io_Device = NULL;
	}

	return(FALSE);	
}


VOID __saveds __asm XEmulatorCloseConsole(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	if(con)
	{
		if(con->wcon->io_Device)
		{
			CloseDevice((struct IORequest *)con->wcon);
			con->wcon->io_Device = NULL;
		}
	}
}


#include <devices/conunit.h>

VOID __saveds __asm XEmulatorWrite(register __a0 struct XEM_IO *io, register __a1 UBYTE *buf, register __d0 ULONG buflen)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;
	struct ConUnit	*unit = (struct ConUnit *)con->wcon->io_Unit;

	UBYTE	dummyBuffer[40], c;
	LONG	fit, spaces, current;

	buflen = (((LONG)buflen) == -1) ? strlen(buf) : buflen;

	fit		= (unit->cu_XMax + 1) / 4;
	current	= unit->cu_XCCP / 3;

	if(current >= fit  ||  (unit->cu_XCCP % 3))
	{
		ProcessData(con, "\r\n", 2);
		current	= 0;
	}

	while(buflen-- > 0)
	{
		c = *buf++;

		spaces = (fit - current) * 3 + current - 3;

		if((c > ' '  &&  c < 127)  ||  c > 160)
			sprintf(dummyBuffer,"%02lx \33[%ldC%lc\33[%ldD", c, spaces, c, spaces + 1);
		else
			sprintf(dummyBuffer,"%02lx \33[%ldC.\33[%ldD", c, spaces, spaces + 1);

		ProcessData(con, dummyBuffer, strlen(dummyBuffer));

		if(current++ == (fit-1))
		{
			current = 0;
			ProcessData(con, "\r\n", 2);
		}
	}
}


BOOL __saveds __asm XEmulatorSignal(register __a0 struct XEM_IO *io, register __d0 ULONG sig)
{
	return(TRUE);
}


STATIC BOOL HandleMacroKeys(struct HEXConsole *con, struct IntuiMessage *imsg, UBYTE chr)
{
	if(con->macrokeys  &&  con->io->xem_process_macrokeys)
	{
		struct XEmulatorMacroKey *key;
		BOOL shift, alt, ctrl;
		UWORD qual;

		shift	= imsg->Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT);
		ctrl	= imsg->Qualifier &  IEQUALIFIER_CONTROL;
		alt	= imsg->Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT);

		if(shift)
			qual = XMKQ_SHIFT;
		else
		{
			if(alt)
				qual = XMKQ_ALTERNATE;
			else
			{
				if(ctrl)
					qual = XMKQ_CONTROL;
				else
					qual = XMKQ_NONE;
			}
		}

		if(key = GetHead(con->macrokeys))
		{
			do
			{
				if(key->xmk_Qualifier == qual)
				{
					BOOL match=FALSE;

					if(key->xmk_Type == XMKT_RAWKEY)
					{
						if(key->xmk_Code == imsg->Code)
							match = TRUE;
					}

					if(key->xmk_Type == XMKT_COOKED)
					{
						if(key->xmk_Code == chr)
							match = TRUE;
					}

					if(match != FALSE)
					{
						con->io->xem_process_macrokeys(key);
						return(TRUE);
					}
				}
			}
			while(key = GetSucc(key));
		}
	}
	return(FALSE);
}


ULONG __saveds __asm XEmulatorUserMon(register __a0 struct XEM_IO *io, register __a1 UBYTE *retstr, register __d0 ULONG maxlen, register __a2 struct IntuiMessage *imsg)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;
	struct InputEvent ie;
	ULONG length=0;
	UBYTE *p;


	if(imsg->Code & IECODE_UP_PREFIX)
		return(0);

	p = retstr;
	*p = '\0';

   ie.ie_Class			= IECLASS_RAWKEY;
   ie.ie_SubClass		= 0;
	ie.ie_Code			= imsg->Code;
	ie.ie_Qualifier	= imsg->Qualifier;
	ie.ie_position.ie_addr = *((APTR *)imsg->IAddress);

	if((length = MapRawKey(&ie, retstr, maxlen, NULL)) <= 0)
		return(0);

	*(p+length) = '\0';			/* Null terminate the value */

	if(HandleMacroKeys(con, imsg, p[0]))
		length = 0;

	return(length);
}


ULONG __saveds __asm XEmulatorHostMon(register __a0 struct XEM_IO *io, register __a1 struct XEmulatorHostData *hd, register __d0 ULONG actual)
{
	if(hd->Destination != NULL)
	{
		ULONG cnt;
		UBYTE *read, *write;
		REGISTER UBYTE c;

		read	= hd->Source;
		write = hd->Destination;
		for(cnt=0; cnt < actual; cnt++)
		{
			c = *read++;

			if(c == '\x18'  ||  c == '\x1A')	/* CAN  ||  SUB */
			{
				hd->InESC = FALSE;
				hd->InCSI = FALSE;
				continue;
			}

			if(hd->InESC)		/* Escape - Befehl ? */
			{
				if(c == '[')	/* ist's ein verkappter CSI ? */
				{
					hd->InCSI = TRUE;
					hd->InESC = FALSE;
				}
				else
				{
					if(c >= '0')
						hd->InESC = FALSE;
				}
				continue;
			}

			if(hd->InCSI)		/* CSI - Befehl ? */
			{
				if(c >= '@')
					hd->InCSI = FALSE;
				continue;
			}


			if(c == '\033')
			{
				hd->InESC = TRUE;
				hd->InCSI = FALSE;
				continue;
			}

			if(c == '\233')
			{
				hd->InESC = FALSE;
				hd->InCSI = TRUE;
				continue;
			}

			*write++ = c;
		}

		return((ULONG)(write - hd->Destination));
	}
	else
		return(0);
}


BOOL __saveds __asm XEmulatorClearConsole(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	ProcessData(con, "\014", 1);
	return(TRUE);
}


BOOL __saveds __asm XEmulatorResetConsole(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	ProcessData(con, "\033c", 2);
	return(TRUE);
}


BOOL __saveds __asm XEmulatorResetTextStyles(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	ProcessData(con, "\033[m", -1);
	return(TRUE);
}


BOOL __saveds __asm XEmulatorResetCharset(register __a0 struct XEM_IO *io)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	ProcessData(con, "\017", 1);
	return(TRUE);
}


BOOL __saveds __asm XEmulatorOptions(register __a0 struct XEM_IO *io)
{
	return(TRUE);
}


ULONG __saveds __asm XEmulatorGetFreeMacroKeys(register __a0 struct XEM_IO *io)
{
	return(512 + 256 + 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1);
}


BOOL __saveds __asm XEmulatorMacroKeyFilter(register __a0 struct XEM_IO *io, register __a1 struct XEmulatorMacroKey *macrokeys)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;

	if(con != NULL  &&  con->io->xem_process_macrokeys)
	{
		con->macrokeys = macrokeys;
		return(TRUE);
	}

	return(FALSE);
}


#include <devices/conunit.h>

LONG __saveds __asm XEmulatorInfo(register __a0 struct XEM_IO *io, register __d0 ULONG type)
{
	struct HEXConsole *con = (struct HEXConsole *)io->xem_console;
	LONG result = -1;

	if(con != NULL)
	{
		struct ConUnit	*unit = (struct ConUnit *)con->wcon->io_Unit;

		switch(type)
		{
			case XEMI_CURSOR_POSITION:
				result = XEMI_CREATE_POSITION(unit->cu_YCCP+1, unit->cu_XCCP+1);
			break;

			case XEMI_CONSOLE_DIMENSIONS:
				result = XEMI_CREATE_DIMENSIONS(unit->cu_XMax+1, unit->cu_YMax+1);
			break;

		}
	}

	return(result);
}


BOOL __saveds __asm XEmulatorPreferences(register __a0 struct XEM_IO *io, register __a1 STRPTR filename, register __d0 ULONG mode)
{
	return(TRUE);
}


STATIC VOID HEX_internalsettings(struct HEXConsole *con)
{
}


STATIC BOOL HEX_parseoptions(struct HEXConsole *con, STRPTR optionsBuffer)
{
	return(TRUE);
}


VOID __saveds __asm XEmulatorNewSize(register __a0 struct XEM_IO *io, register __a1 struct IBox *frame)
{
}


/* end of source-code */
