/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
 *
 *	Name .....: TermXEM.c
 *	Created ..: Saturday 03-Nov-91 11:17
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	03-Nov-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

#include "termGlobal.h"

	/* Local terminal emulation data. */

STATIC	struct sharedvars	 sv;
STATIC	struct hostfuncs	 hf;
STATIC	BPTR			 EmulatorSegment;
STATIC	struct MsgPort		*EmulatorPort;
STATIC	UWORD			 ScreenDepth;

	/* Two less important dummy functions. */

STATIC BOOL __saveds
TrueDummy()
{
	return(TRUE);
}

STATIC VOID __saveds
VoidDummy()
{
}

	/* xem_sbreak():
	 *
	 *	Send a break signal across the serial line.
	 */

STATIC BOOL __saveds
xem_sbreak()
{
	if(!WriteRequest)
		return(-1);

	WriteRequest -> IOSer . io_Command = SDCMD_BREAK;

	return((LONG)DoIO(WriteRequest));
}

	/* xem_swrite(UBYTE *Buffer,ULONG Size):
	 *
	 *	Write a few bytes to the serial line.
	 */

STATIC BOOL __saveds
xem_swrite(UBYTE *Buffer,ULONG Size)
{
	return((BOOL)xpr_swrite(Buffer,Size));
}

	/* xem_sread(UBYTE *Buffer,ULONG Size,LONG Timeout):
	 *
	 *	Read a few bytes fro the serial line.
	 */

STATIC LONG __saveds
xem_sread(UBYTE *Buffer,ULONG Size,LONG Timeout)
{
	return((LONG)xpr_sread(Buffer,Size,Timeout));
}

	/* xem_tgets(UBYTE *Prompt,UBYTE *Buffer,ULONG Size):
	 *
	 *	Get a string from the user.
	 */

STATIC BOOL __saveds
xem_tgets(UBYTE *Prompt,UBYTE *Buffer,ULONG Size)
{
	return((BOOL)xpr_gets(Prompt,Buffer));
}

	/* xem_tbeep(ULONG Times,ULONG Delay):
	 *
	 *	Beep the terminal display.
	 */

STATIC VOID __saveds
xem_tbeep(ULONG Times,ULONG Delay)
{
	WORD i;

	for(i = 0 ; i < Times ; i++)
		RealBeep();
}

	/* LoadEmulator(struct sharedvars *sv,UBYTE *Name):
	 *
	 *	Load emulator code and start it.
	 */

STATIC BYTE __regargs
LoadEmulator(struct sharedvars *sv,UBYTE *Name)
{
		/* Reload emulator code if none present. */

	if(!EmulatorSegment)
		EmulatorSegment = LoadSeg(Name);

	if(EmulatorSegment)
	{
		struct MsgPort *ReplyPort;

			/* Create a reply port. */

		if(ReplyPort = (struct MsgPort *)CreateMsgPort())
		{
				/* Create the emulator process. */

			if(EmulatorPort = (struct MsgPort *)CreateProc(FilePart(Name),0,EmulatorSegment,4000))
			{
				struct EmuMsg	msg;
				BYTE		GotIt = FALSE;
				ULONG		SignalSet;

					/* Set up handshake message. */

				memset(&msg,0,sizeof(struct EmuMsg));

				msg . em_msg . mn_Node . ln_Name	= EMULATOR_CURRENT_VERSION;
				msg . em_arg				= (APTR)sv;
				msg . em_msg . mn_ReplyPort		= ReplyPort;
				msg . em_msg . mn_Length		= sizeof(struct EmuMsg);

					/* Set up for timeout. */

				TimeRequest -> tr_node . io_Command	= TR_ADDREQUEST;
				TimeRequest -> tr_time . tv_secs	= 3;
				TimeRequest -> tr_time . tv_micro	= 0;

				SendIO(TimeRequest);

					/* Transfer handshake message. */

				PutMsg(EmulatorPort,(struct Message *)&msg);

					/* Wait for handshake. */

				while(!GotIt)
				{
					SignalSet = Wait(SIG_TIMER | (1 << ReplyPort -> mp_SigBit));

						/* Got a reply? */

					if(SignalSet & (1 << ReplyPort -> mp_SigBit))
					{
						GetMsg(ReplyPort);

						GotIt = TRUE;

						if(!(SignalSet & SIG_TIMER))
							AbortIO(TimeRequest);

						break;
					}

						/* Hit by timeout? */

					if(SignalSet & SIG_TIMER)
						break;
				}

					/* Wait for timer request to return. */

				WaitIO(TimeRequest);

					/* Successful initialization? */

				if(GotIt)
				{
						/* Does the module respond to our version number? */

					if(!strcmp(msg . em_msg . mn_Node . ln_Name,CURRENT_VERSION_ACCEPTED))
					{
							/* Extract callback structure. */

						if(Console = (struct confuncs *)msg . em_arg)
						{
								/* Allocate resources. */

							if(Console -> alloc_resources((APTR)Console))
							{
									/* Open the console. */

								if(!(Console -> open_console((APTR)Console)))
								{
									Console -> close_console((APTR)Console);

									Console -> free_resources((APTR)Console);

									Console = NULL;

									EmulationSetupError = EM_CONSOLE;
								}
								else
								{
									EmulationSetupError = 0;

									return(TRUE);
								}
							}
							else
							{
								Console -> free_resources((APTR)Console);

								Console = NULL;

								EmulationSetupError = EM_RESOURCES;
							}
						}
						else
							EmulationSetupError = EM_DATA;
					}
					else
						EmulationSetupError = EM_VERSION;
				}
				else
					EmulationSetupError = EM_TIMEOUT;
			}
			else
				EmulationSetupError = EM_NOPROC;

			RemTask(EmulatorPort -> mp_SigTask);

			EmulatorPort = NULL;
		}
		else
			EmulationSetupError = EM_NOPORT;

		UnLoadSeg(EmulatorSegment);

		EmulatorSegment = NULL;
	}
	else
		EmulationSetupError = EM_LOADFAILED;

	return(FALSE);
}

	/* DeleteEmulator(BYTE UnloadIt):
	 *
	 *	Disable or unload the current terminal emulation.
	 */

VOID
DeleteEmulator(BYTE UnloadIt)
{
	if(Console)
	{
		Console -> close_console((APTR)Console);

		Console -> free_resources((APTR)Console);

		Console = NULL;
	}

	if(EmulatorPort)
	{
		RemTask(EmulatorPort -> mp_SigTask);

		EmulatorPort = NULL;
	}

	if(EmulatorSegment && UnloadIt)
	{
		UnLoadSeg(EmulatorSegment);

		EmulatorSegment = NULL;
	}
}

	/* CreateEmulator(UBYTE *Name,BYTE ForceNew):
	 *
	 *	Set up or reload the external terminal emulator.
	 */

BYTE
CreateEmulator(UBYTE *Name,BYTE ForceNew)
{
	DeleteEmulator(ForceNew);

	hf . xem_swrite		= (APTR)xem_swrite;
	hf . xem_sread		= (APTR)xem_sread;
	hf . xem_sbreak		= (APTR)xem_sbreak;
	hf . xem_sstart		= (APTR)VoidDummy;
	hf . xem_sstop		= (APTR)TrueDummy;
	hf . xem_tgets		= (APTR)xem_tgets;
	hf . xem_tbeep		= (APTR)xem_tbeep;
	hf . xpr_options	= (APTR)xpr_options;
	hf . xpr_sflush		= (APTR)xpr_sflush;

	ScreenDepth = Screen -> RastPort . BitMap -> Depth;

	sv . hf			= &hf;
	sv . scr		= &Screen;
	sv . win		= &Window;
	sv . rp			= &RPort;
	sv . extsig		= &ExtSigs;
	sv . depth		= &ScreenDepth;
	sv . SysBase		= SysBase;
	sv . DOSBase		= DOSBase;
	sv . GfxBase		= GfxBase;
	sv . IntuitionBase	= IntuitionBase;
	sv . DiskFontBase	= DiskfontBase;
	sv . KeymapBase		= KeymapBase;
	sv . RexxSysBase	= RexxSysBase;

	return(LoadEmulator(&sv,Name));
}
