/* invert.c -- string-to-inputevents	*/

#include "sysall.h"
#include "cx/cxusr.h"

#define D(x)	;

extern struct Library	*CxBase;

struct InputEvent	*
InvertString(str, km)
UBYTE	*str;
CPTR	*km;		/* keymap	*/
{
	/* bugs:
		can't escape '>'
		puts '\0' on closing angles
	 */
	/* allocate input event for each character in string	*/

	struct InputEvent	*chain = NULL;
	struct InputEvent	*tail;
	struct InputEvent	*ie;
	int					abort = 0;
	UBYTE				cc;

	BYTE doesc();

	if (!str || !*str) return (NULL);

	tail = (struct InputEvent *) &chain;	/* jvudu	*/

	do {	/* have checked that str is not null 	*/
		/* allocate the next ie and link it in	*/
		if (!(ie = 
			AllocMem((LONG) sizeof (struct InputEvent), (LONG) MEMF_CLEAR)))
		{
			abort = 1;
			goto DONE;
		}
		tail->ie_NextEvent = ie;	/* link in */
		tail = ie;

		/* now fill in the input event	*/
		switch (cc = *str)
		{
		case	'<':
			++str;
			if (!doangle(&str, ie)) 
			{
				D( printf("doangle failed.  abort\n") );
				abort = 1;
				goto DONE;
			}
			break;

		case	'\\':
			D( printf("is: doesc\n"); )
			if ((cc = doesc( *(++str) )) == -1)	/* get escaped character	*/
			{
				abort = 1;
				goto DONE;
			}
			/* fall through	*/
		default:
			InvertKeyMap((ULONG) cc, ie, km);
		}


	} while (*(++str));

DONE:
	if (abort)
	{
		FreeIEvents(ie);
		return (NULL);
	}
	return (chain);
}

BYTE
doesc(cc)
BYTE	cc;
{
	switch(cc)
	{
	case	'n':	/* \n means "return"	*/
	case	'r':
		return ('\r');
		break;
	case	't':
		return ('\t');
		break;
	case	'0':
		return ('\0');
		break;

	case	'\\':
	case	'\"':
	case	'\'':
	case	'<':
		break;
	default:
		cc = -1;
	}

	return (cc);
}

/* return 0 if problem	*/
doangle(strp, ie)
char				**strp;
struct InputEvent	*ie;
{
	IX	ix;
	char	*cp = NULL;
	ULONG	retval;

	/* find closing angle '>', put a null there	*/
	for (cp = *strp; *cp; ++cp)
	{
		if (*cp == '>')
		{
			D( printf("found >") );
			*cp = '\0';
			break;
		}
		D( printf("> look past %c\n", *cp) );
	}

	retval = ParseIX(*strp, &ix);

	D( printf("> parseix back\n") );

	if (cp)
	{
		*cp = '>';	/* fix it	*/
		*strp = cp;	/* point to char following '>'	*/
	}
	else
	{
		*strp = cp - 1;	/* ++will point to terminating null	*/
	}

	if (retval) 	/* error */
	{
		return (0);
	}

	/* use IX to describe a suitable InputEvent	*/
	ie->ie_Class		= ix.ix_Class;
	ie->ie_Code			= ix.ix_Code;
	ie->ie_Qualifier	= ix.ix_Qualifier;

	return (1);
}
