/*
 * Name:	MicroEMACS
 * 		Amiga virtual terminal keyboard, default console keymap.
 * Version:	31
 * Last edit:	20-Apr-86
 * Created:	19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 *			Supports all the default console device
 *			(RAW:) input codes for the Amiga keyboard.
 * Modified:	20-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 *		[UT-14A] Added processing for GR_to_META, so
 *			characters in the alternate character set
 *			can automatically map to META characters.
 *			This is a rather nice thing to have...
 */
#include	"def.h"

#define	ESC	0x1B			/* Escape, arrows et al.	*/
#define	CSI	0x9B			/* Amiga CSI			*/

/*
 * The function keys on the Amiga send back
 * escape sequences of the form <ESC>[code~, where code
 * is a one or two-character code for the key.  To make
 * it easier to decode, we place the internal key values
 * for these codes in this table.
 */

short	consolemap[] = {
	KF1,		KF2,		KF3,		KF4,
	KF5,		KF6,		KF7,		KF8,
	KF9,		KF10,		KSF1,		KSF2,
	KSF3,		KSF4,		KSF5,		KSF6,
	KSF7,		KSF8,		KSF9,		KSF10
};
#define	NFUNCKEYS ((sizeof consolemap)/(sizeof consolemap[0]))

/*
 * Names for the keys with basic keycode
 * between KFIRST and KLAST (inclusive). This is used by
 * the key name routine in "kbd.c".  KFIRST is KRANDOM, which
 * we don't bind anything useful to.
 */
char	*keystrings[] = {
	NULL,		"F1",		"F2",		"F3",
	"F4",		"F5",		"F6",		"F7",
	"F8",		"F9",		"F10",		"Shift-F1",
	"Shift-F2",	"Shift-F3",	"Shift-F4",	"Shift-F5",
	"Shift-F6",	"Shift-F7",	"Shift-F8",	"Shift-F9",
	"Shift-F10",	"Up",		"Shift-Up",	"Down",
	"Shift-Down",	"Left",		"Shift-Left",	"Right",
	"Shift-Right",	"Help",		NULL,		NULL
};

/*
 * Read in a key, doing the low level mapping
 * of ASCII code to 11 bit code. This level deals with
 * mapping the special keys into their spots in the C1
 * control area. The C0 controls go right through, and
 * get remapped by "getkey".
 *
 * If GR_to_META is TRUE, characters in the Amiga alternate
 * character set get mapped to META characters.  If FALSE,
 * they get sent straight through.
 */

#ifdef AS_DISTRIBUTED
extern	int	GR_to_META;	/* defined in "kbd.c" */
#else
int	GR_to_META = TRUE;	/* not in *MY* "kbd.c"; Fred Fish */
#endif

getkbd()
{
	register int	c;
	register int	n;
loop:
	c = ttgetc();
	if (c == CSI) {
		c = ttgetc();
		/* Unshifted arrow keys */
		if (c == 'A')
			return (KUP);
		if (c == 'B')
			return (KDOWN);
		if (c == 'C')
			return (KRIGHT);
		if (c == 'D')
			return (KLEFT);
		if (c == 'T')
			return (KSUP);
		if (c == 'S')
			return (KSDOWN);
		if (c == '?') {
			ttgetc();		/* discard '~' */
			return (KHELP);
		}

		/* Shifted left, right */
		if (c == ' ') {
			c = ttgetc();
			if (c == 'A' || c == '@')
				return (c == 'A') ? (KSLEFT) : (KSRIGHT);
			goto loop;		/* try again, sucker */
		}

		/* Function keys	*/
		if (c >= '0' && c <= '9') {
			n = 0;
			do {
				n = 10*n + c - '0';
				c = ttgetc();
			} while (c>='0' && c<='9');
			if (c == '~' && n < NFUNCKEYS) {
				c = consolemap[n];
				if (c != KRANDOM)
					return (c);
				goto loop;
			}
			else 
				goto loop;	/* Try again */
		}
		goto loop;		/* Try again */
	}

	/* Meta keys -- also check for high bit set */
	if ((c == ESC) || (GR_to_META && (c & 0x80))) {
		if (c == ESC)
			c = ttgetc();
		c &= 0x7F;			/* Strip high bit	*/
		if (ISLOWER(c) != FALSE)	/* Copy the standard	*/
			c = TOUPPER(c);		/* META code.		*/
		if (c>=0x00 && c<=0x1F)
			c = KCTRL | (c+'@');
		return (KMETA | c);
	}
	return (c);
}

/*
 * Terminal specific keymap initialization.
 * Attach the special keys to the appropriate built
 * in functions. Bind all of the assigned graphics in the
 * Amiga alternate character set to self-insert.
 * As is the case of all the keymap routines, errors
 * are very fatal.
 */
ttykeymapinit()
{
	register SYMBOL	*sp;
	register int	i;

	keydup(KUP,	"back-line");
	keydup(KDOWN,	"forw-line");
	keydup(KRIGHT,	"forw-char");
	keydup(KLEFT,	"back-char");
	keydup(KHELP,	"help");

	keydup(KSUP,	"goto-bob");
	keydup(KSDOWN,	"goto-eob");
#ifdef AS_DISTRIBUTED
	keydup(KSRIGHT,	"goto-eop");
	keydup(KSLEFT,	"goto-bop");
#endif

	keydup(KF1,	"down-window");
	keydup(KF2,	"forw-page");
	keydup(KF3,	"enlarge-window");
	keydup(KF4,	"forw-window");
	keydup(KF5,	"split-window");
	keydup(KF6,	"file-visit");
	keydup(KF7,	"file-save");
	keydup(KF8,	"start-macro");
	keydup(KF9,	"bind-to-key");
	keydup(KF10,	"display-version");

	keydup(KSF1,	"up-window");
	keydup(KSF2,	"back-page");
	keydup(KSF3,	"shrink-window");
	keydup(KSF4,	"back-window");
	keydup(KSF5,	"only-window");
	keydup(KSF6,	"file-read");
	keydup(KSF7,	"file-write");
	keydup(KSF8,	"end-macro");
	keydup(KSF9,	"display-bindings");
	keydup(KSF10,	"quit");

	/*
	 * Bind all positions that correspond
	 * to characters in the Amiga alternate
	 * character set to "ins-self". These characters may
	 * be used just like any other character.
	 */

	if ((sp=symlookup("ins-self")) == NULL)
		abort();
	for (i=0xA0; i<0xFF; ++i) {
		if (binding[i] != NULL)
			abort();
		binding[i] = sp;
		++sp->s_nkey;
	}
}


