/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1990 by Olaf 'Olsen' Barthel & MXM
 *
 *	Name .....: ParseCode.c
 *	Created ..: Monday 21-Jan-91 20:12
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	21-Jan-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

#include "TermGlobal.h"

	/* A couple of internally referenced variables. */

STATIC BYTE	CharsInBuffer = 0;
STATIC UBYTE	SaveBuffer[30];
STATIC BYTE	ScanStep = 0;

	/* External comparison routines. */

extern BYTE Num1(WORD Char);
extern BYTE Num2(WORD Char);
extern BYTE Num3(WORD Char);
extern BYTE Num4(WORD Char);

	/* This structure describes an ANSI control sequence. */

struct ControlCode
{
	UBYTE	 FirstChar;
	BYTE	(*Match)(WORD Char);
	UBYTE	 LastChar;

	BYTE	 ExactSize;
	UBYTE *	(*Func)(UBYTE *Buffer);
};

	/* At present 55 different control sequences are supported/trapped. */

#define NUM_CODES 55

	/* This follows the control code information. */

struct ControlCode ANSICode[NUM_CODES] =
{
	/* Single Character Sequences. */

	'D',	NULL,	 0 ,	1,	(APTR)CursorScrollDown,
	'M',	NULL,	 0 ,	1,	(APTR)CursorScrollUp,
	'E',	NULL,	 0 ,	1,	(APTR)NextLine,
	'7',	NULL,	 0 ,	1,	(APTR)SaveCursor,
	'8',	NULL,	 0 ,	1,	(APTR)LoadCursor,
	'=',	NULL,	 0 ,	1,	(APTR)NumericAppMode,
	'>',	NULL,	 0 ,	1,	(APTR)NumericAppMode,
	'N',	NULL,	 0 ,	1,	(APTR)Ignore,
	'O',	NULL,	 0 ,	1,	(APTR)Ignore,
	'H',	NULL,	 0 ,	1,	(APTR)SetTab,
	'Z',	NULL,	 0 ,	1,	(APTR)RequestTerminal,
	'c',	NULL,	 0 ,	1,	(APTR)Reset,
	'<',	NULL,	 0 ,	1,	(APTR)Ignore,
	'~',	NULL,	 0 ,	1,	(APTR)Ignore,
	'n',	NULL,	 0 ,	1,	(APTR)Ignore,
	'}',	NULL,	 0 ,	1,	(APTR)Ignore,
	'o',	NULL,	 0 ,	1,	(APTR)Ignore,
	'|',	NULL,	 0 ,	1,	(APTR)Ignore,

	/* Double Character Sequences. */

	'[',	NULL,	's',	2,	(APTR)SaveCursor,
	'[',	NULL,	'u',	2,	(APTR)LoadCursor,
	'(',	NULL,	'A',	2,	(APTR)FontStuff,
	'(',	NULL,	'B',	2,	(APTR)FontStuff,
	'(',	NULL,	'0',	2,	(APTR)Ignore,	/* was FontStuff, */
	')',	NULL,	'A',	2,	(APTR)FontStuff,
	')',	NULL,	'B',	2,	(APTR)FontStuff,
	')',	NULL,	'0',	2,	(APTR)Ignore,	/* was FontStuff, */
	'#',	NULL,	'3',	2,	(APTR)ScaleFont,
	'#',	NULL,	'4',	2,	(APTR)ScaleFont,
	'#',	NULL,	'5',	2,	(APTR)ScaleFont,
	'#',	NULL,	'6',	2,	(APTR)ScaleFont,
	'#',	NULL,	'8',	2,	(APTR)Ignore,
	' ',	NULL,	'F',	2,	(APTR)Ignore,
	' ',	NULL,	'G',	2,	(APTR)Ignore,

	/* Multiple Character Sequence. */

	'[',	Num3,	'i',	0,	(APTR)Ignore,
	'[',	Num3,	'n',	0,	(APTR)RequestInformation,
	'[',	Num3,	'c',	0,	(APTR)RequestTerminal,
	'[',	Num3,	'h',	0,	(APTR)SetSomething,
	'[',	Num3,	'l',	0,	(APTR)SetSomething,

	'[',	Num4,	'h',	0,	(APTR)Ignore,

	'[',	Num1,	'A',	0,	(APTR)MoveCursor,
	'[',	Num1,	'B',	0,	(APTR)MoveCursor,
	'[',	Num1,	'C',	0,	(APTR)MoveCursor,
	'[',	Num1,	'D',	0,	(APTR)MoveCursor,
	'[',	Num1,	'K',	0,	(APTR)EraseLine,
	'[',	Num1,	'J',	0,	(APTR)EraseScreen,
	'[',	Num1,	'P',	0,	(APTR)EraseCharacters,
	'[',	Num1,	'L',	0,	(APTR)InsertLine,
	'[',	Num1,	'M',	0,	(APTR)ClearLine,
	'[',	Num1,	'g',	0,	(APTR)SetTabs,
	'[',	Num1,	'q',	0,	(APTR)Ignore,

	'[',	Num2,	'H',	0,	(APTR)SetPosition,
	'[',	Num2,	'f',	0,	(APTR)SetPosition,
	'[',	Num2,	'm',	0,	(APTR)SetAttributes,
	'[',	Num2,	'y',	0,	(APTR)Ignore,
	'[',	Num2,	'r',	0,	(APTR)SetRegion,
};

	/* DoCancel():
	 *
	 *	Cancel any currently scanned sequence.
	 */

VOID
DoCancel()
{
	InSequence = FALSE;
	CharsInBuffer = ScanStep = 0;
}

	/* CSIFake():
	 *
	 *	This routine was added to support 8-bit control
	 *	sequences introduced by a CSI character.
	 */

VOID
CSIFake()
{
		/* Reset scanner */

	DoCancel();

		/* Perform as if ESC [ had been transmitted. */

	InSequence = ParseCode('[');
}

	/* ParseCode(UBYTE c):
	 *
	 *	Input:	A character to be passed through the ANSI code
	 *		parser.
	 *
	 *	Output:	FALSE if input characters did form a valid ANSI
	 *		control sequence or if input characters did not
	 *		form an ANSI control sequence at all.
	 *
	 *		TRUE if input characters did possibly introduce
	 *		a valid ANSI control sequence.
	 */

BYTE
ParseCode(UBYTE c)
{
	SHORT i;

		/* ScanStep = 0:	This is the first character
		 *			to introduce a control sequence.
		 */

	if(!ScanStep)
	{
			/* Scan all available codes and try to find
			 * a match.
			 */

		for(i = 0 ; i < NUM_CODES ; i++)
		{
				/* This character may introduce a
				 * control sequence.
				 */

			if(ANSICode[i] . FirstChar == c)
			{
					/* If this is a single
					 * character control sequence
					 * call the approriate function
					 * and exit immediately.
					 */

				if(ANSICode[i] . ExactSize == 1)
				{
					SaveBuffer[CharsInBuffer++] = c;
					SaveBuffer[CharsInBuffer] = 0;

					if(Config . Emulation != EMULATION_ATOMIC || Escape)
					{
						UBYTE *SomeString = ANSICode[i] . Func(&SaveBuffer[0]);

						if(SomeString)
							SerWrite(SomeString,strlen(SomeString));
					}

					CharsInBuffer = ScanStep = 0;

					return(FALSE);
				}

					/* The length of this control
					 * sequence is greater than
					 * a single character. Save
					 * the input character and
					 * return.
					 */

				ScanStep = i;

				SaveBuffer[CharsInBuffer++] = c;

				return(TRUE);
			}
		}

			/* No control sequence introducing character
			 * was found.
			 */

		/* No Match */

		CharsInBuffer = ScanStep = 0;

		return(FALSE);
	}
	else
	{
			/* Length of the control sequence
			 * overrides the boundary, exit
			 * immediately!
			 */

		if(CharsInBuffer == 21)
		{
			/* No Match */

			CharsInBuffer = ScanStep = 0;

			return(FALSE);
		}

			/* Scan the remaining codes for a match. */

		for(i = ScanStep ; i < NUM_CODES ; i++)
		{
				/* This sequence begins with the
				 * same character the parser was
				 * initialized with, so let's take
				 * a look at it.
				 */

			if(ANSICode[i] . FirstChar == SaveBuffer[0])
			{
					/* This character is supposed to
					 * terminate the sequence. So let's
					 * exit.
					 */

				if(ANSICode[i] . LastChar == c)
				{
					SaveBuffer[CharsInBuffer++] = c;
					SaveBuffer[CharsInBuffer] = 0;

					if(Config . Emulation != EMULATION_ATOMIC || Escape)
					{
						UBYTE *SomeString = ANSICode[i] . Func(&SaveBuffer[0]);

						if(SomeString)
							SerWrite(SomeString,strlen(SomeString));
					}

					CharsInBuffer = ScanStep = 0;

					return(FALSE);
				}
				else
				{
					if(ANSICode[i] . Match)
					{
							/* This character is part of
							 * a legal sequence. Store it
							 * and return.
							 */

						if(ANSICode[i] . Match(c))
						{
							ScanStep = i;

							SaveBuffer[CharsInBuffer++] = c;

							return(TRUE);
						}
					}
				}
			}
		}

			/* This character is not part of a valid
			 * ANSI control sequence, so exit.
			 */

		/* No Match */

		CharsInBuffer = ScanStep = 0;

		return(FALSE);
	}
}
