/*	kb.c of gulam+ue -- key to function bindings 

	copyright (c) 1987, pm@Case
*/

#include "ue.h"
#include "keynames.h"

/* Function names: These are generated by kbgen.tos from data in
kbin.000.  Unless you really know, do not change these defines by
hand.  These are indices into the fpfs[] of function.c.  */

#define	Fnoop		0
#define	Fescctrld	1
#define	Fescesc		2
#define	Fminiterm	3
#define	Ffilename	4
#define	Fgxpand		5
#define	Ftogulambuf	6
#define	Fexecbuf	7
#define	Ffileread	8
#define	Fshowkbdmacro	9
#define	Ftemul		10
#define	Fmvupwind	11
#define	Fmvdnwind	12
#define	Fquickexit	13
#define	Ftempexit	14
#define	Fgforwline	15
#define	Fgulam		16
#define	Ftab		17
#define	Fquit		18
#define	Fctrlg		19
#define	Fhelp		20
#define	Fctlxlp		21
#define	Fctlxrp		22
#define	Fctlxe		23
#define	Fsetfillcol	24
#define	Frefresh	25
#define	Fbackchar	26
#define	Fforwchar	27
#define	Fbackdel	28
#define	Fforwdel	29
#define	Fgotobol	30
#define	Fgotoeol	31
#define	Fkill		32
#define	Fforwline	33
#define	Fopenline	34
#define	Fbackline	35
#define	Fnewline	36
#define	Findent		37
#define	Fgotoline	38
#define	Fspawn		39
#define	Fkilltobln	40
#define	Ffillpara	41
#define	Fsearchagain	42
#define	Fbacksearch	43
#define	Fforwsearch	44
#define	Fbackisearch	45
#define	Fforwisearch	46
#define	Fqueryrepl	47
#define	Fsetmark	48
#define	Fselfinsert	49
#define	Freposition	50
#define	Fquote		51
#define	Ftwiddle	52
#define	Fcopyregion	53
#define	Fkillregion	54
#define	Fkbreset	55
#define Fsemireset	56
#define	Fprefixregion	57
#define	Fsetprefix	58
#define	Fyank		59
#define	Ffileinsert	60
#define	Ffilevisit	61
#define	Ffilesave	62
#define	Ffilewrite	63
#define	Fpoptofile	64
#define	Fdeblank	65
#define	Fswapmark	66
#define	Fshowcpos	67
#define	Fnextwind	68
#define	Fprevwind	69
#define	Fshrinkwind	70
#define	Fenlargewind	71
#define	Fdelwind	72
#define	Fonlywind	73
#define	Fsplitwind	74
#define	Fctlx4hack	75
#define	Fnotmodified	76
#define	Fbufferinsert	77
#define	Fusebuffer	78
#define	Fpoptobuffer	79
#define	Flistbuffers	80
#define	Fkillbuffer	81
#define	Fsavebuffers	82
#define	Fpagenext	83
#define	Fgotoeob	84
#define	Fgotobob	85
#define	Fgotobop	86
#define	Fgotoeop	87
#define	Fkillpara	88
#define	Fdelwhite	89
#define	Fbackword	90
#define	Fcapword	91
#define	Fdelbword	92
#define	Fdelfword	93
#define	Fforwword	94
#define	Flowerword	95
#define	Fupperword	96
#define	Fforwpage	97
#define	Fbackpage	98
#define	Fgxpshow	99
#define	Fevalexpr	100
#define	Fevalbuffer	101
#define	Fevalfile	102
#define	Fbsmapmode	103
#define	Fflowmode	104
#define	Findentmode	105
#define	Fblinkparen	106
#define	Fshowmatch	107
#define	Funsetkey	108
#define	Fbindtokey	109
#define	Fdesckey	110
#define	Fwallchart	111
#define	Fgetarg		112
#define	Fmetanext	113
#define	Fctlxnext	114
#define	Ftenewline	115
#define	Ftotebuf	116
#define	Ftesendtext	117
#define	Ftotal		117

/* key-to-function-index table.  This table is searched linearly.  So,
the most frequent cmds should appear before the others.  Other than
this, the order is unimportant.  */


local KB  regkeybind[] = {
	{F1,			Fdelbword},
	{F2,			Fdelfword},
	{F3,			Fkill},
	{F4,			Fcopyregion},
	{F5,			Fkillbuffer},
	{F6,     		Flistbuffers},
	{F7,			Fusebuffer},
	{F8,			Ffilewrite},
	{F9,			Ffilevisit},
	{F10,    		Ffilesave},

	{HELP,			Fhelp},
	{UNDO,   		Fquickexit},
	{INSERT,		Fbackpage},
	{HOME,			Fforwpage},
	{UPARRO, 		Fbackline},
	{DNARRO,		Fgforwline},
	{LTARRO,		Fbackchar},
	{RTARRO,		Fforwchar},

	{CTRL|'[',		Fmetanext},
	{CTRL|'X',		Fctlxnext},
        {CTRL|'@',		Fsetmark},
        {CTRL|'A',		Fgotobol},
        {CTRL|'B',		Fbackchar},
	{CTRL|'C',		Ftogulambuf},
        {CTRL|'D',		Fforwdel},
        {CTRL|'E',		Fgotoeol},
        {CTRL|'F',		Fforwchar},
        {CTRL|'G',		Fctrlg},
        {CTRL|'H',		Fbackdel},
        {CTRL|'I',		Ftab},
        {CTRL|'J',		Findent},
        {CTRL|'K',		Fkill},
        {CTRL|'L',		Frefresh},
        {CTRL|'M',		Fnewline},
        {CTRL|'N',		Fgforwline},
        {CTRL|'O',		Fopenline},
        {CTRL|'P',		Fbackline},
        {CTRL|'Q',		Fquote},
        {CTRL|'R',		Fbacksearch},
        {CTRL|'S',		Fforwsearch},
        {CTRL|'T',		Ftwiddle},
        {CTRL|'U',		Fgetarg},
        {CTRL|'V',		Fforwpage},
        {CTRL|'W',		Fkillregion},
        {CTRL|'Y',		Fyank},
        {CTRL|'Z',		Ftempexit},
	{CTRL|'_',		Fhelp},

	{')',			Fshowmatch},
	{'}',			Fshowmatch},
	{']',			Fshowmatch},

/*
keypad keys
-----------		*/
	{KLP,			Fmvdnwind},
	{KRP,			Fmvupwind},
	{KSLASH,		Fsplitwind},
	{KSTAR,			Fonlywind},
	{KMINUS,		Fprevwind},
	{KPLUS,			Fnextwind},
	{KENTER,		Fctlxe},
	{KDOT,			Fgotoline},
	{K0,			Ftemul},


	{K7,			Fgotobob},
	{K8,			Freposition},
	{K9,			Fgotoeob},
	{K4,			Fbackword},
	{K5,			Fbackline},
	{K6,			Fforwword},
	{K1,			Fgotobol},
	{K2,			Fgforwline},
	{K3,			Fgotoeol},
	{CTLX|CTRL|'A',		Fshowkbdmacro},
        {CTLX|CTRL|'B',		Flistbuffers},
        {CTLX|CTRL|'C',		Fquit},
        {CTLX|CTRL|'F',		Ffilevisit},
        {CTLX|CTRL|'I',		Fbufferinsert},
        {CTLX|CTRL|'O',		Fdeblank},
        {CTLX|CTRL|'N',		Fmvdnwind},
        {CTLX|CTRL|'P',		Fmvupwind},
        {CTLX|CTRL|'R',		Ffileread},
        {CTLX|CTRL|'S',		Ffilesave},
        {CTLX|CTRL|'V',		Ffilevisit},
        {CTLX|CTRL|'W',		Ffilewrite},
        {CTLX|CTRL|'X',		Fswapmark},
        {CTLX|CTRL|'Z',		Fshrinkwind},
	{CTLX|'!',		Fspawn},
        {CTLX|'!',		Fexecbuf},
        {CTLX|'=',		Fshowcpos},
        {CTLX|'(',		Fctlxlp},
        {CTLX|')',		Fctlxrp},
        {CTLX|'1',		Fonlywind},
        {CTLX|'2',		Fsplitwind},
        {CTLX|'B',		Fusebuffer},
	{CTLX|'E',		Fctlxe},
        {CTLX|'F',		Fsetfillcol},
        {CTLX|'I',		Ffileinsert},
        {CTLX|'K',		Fkillbuffer},
        {CTLX|'N',		Fnextwind},
        {CTLX|'O',		Fnextwind},
        {CTLX|'P',		Fprevwind},
	{CTLX|'S',		Fsavebuffers},
        {CTLX|'Z',		Fenlargewind},
        {META|CTRL|'H',		Fdelbword},
        {META|'!',		Fexecbuf},
	{META|'.',		Fsetmark},
        {META|'>',		Fgotoeob},
        {META|'<',		Fgotobob},
	{META|'[',		Fgotobop},
	{META|']',		Fgotoeop},
	{META|'%',		Fqueryrepl},
	{META|' ',		Fdelwhite},
        {META|'B',		Fbackword},
        {META|'C',		Fcapword},
        {META|'D',		Fdelfword},
        {META|'F',		Fforwword},
        {META|'G',		Ftogulambuf},
        {META|'L',		Flowerword},
	{META|'Q',		Ffillpara},
	{META|'R',		Fbacksearch},
	{META|'S',		Fforwsearch},
        {META|'U',		Fupperword},
        {META|'V',		Fbackpage},
        {META|'W',		Fcopyregion},
 	{META|0x7F,		Fdelbword},
        {META|CTRL|'[',		Fgxpand},
        {META|CTRL|'D',		Fgxpshow},
        {META|CTRL|'F',		Ffilename},
        {0x7F,			Fbackdel},
	{HELP+SHIFTED,		Fkbreset},
				/* room for new key bindings */
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{KEOTBL,		Fnoop}
};


local KB  gukeybind[] = {
	{F1,			Fdelbword},
	{F2,			Fdelfword},
	{F3,			Fkill},
	{F4,			Fcopyregion},
	{F5,			Fkillbuffer},
	{F6,     		Flistbuffers},
	{F7,			Fusebuffer},
	{F8,			Ffilewrite},
	{F9,			Ffilevisit},
	{F10,    		Ffilesave},

	{HELP,			Fhelp},
	{UNDO,   		Fquickexit},
	{INSERT,		Fbackpage},
	{HOME,			Fforwpage},
	{UPARRO, 		Fbackline},
	{DNARRO,		Fgforwline},
	{LTARRO,		Fbackchar},
	{RTARRO,		Fforwchar},

	{CTRL|'[',		Fmetanext},
	{CTRL|'X',		Fctlxnext},
        {CTRL|'@',		Fsetmark},
        {CTRL|'A',		Fgotobol},
        {CTRL|'B',		Fbackchar},
	{CTRL|'C',		Ftogulambuf},
        {CTRL|'D',		Fforwdel},
        {CTRL|'E',		Fgotoeol},
        {CTRL|'F',		Fforwchar},
        {CTRL|'G',		Fctrlg},
        {CTRL|'H',		Fbackdel},
        {CTRL|'I',		Ftab},
        {CTRL|'J',		Findent},
        {CTRL|'K',		Fkill},
        {CTRL|'L',		Frefresh},
        {CTRL|'M',		Fgulam},
        {CTRL|'N',		Fgforwline},
        {CTRL|'O',		Fopenline},
        {CTRL|'P',		Fbackline},
        {CTRL|'Q',		Fquote},
        {CTRL|'R',		Fbacksearch},
        {CTRL|'S',		Fforwsearch},
        {CTRL|'T',		Ftwiddle},
        {CTRL|'U',		Fgetarg},
        {CTRL|'V',		Fforwpage},
        {CTRL|'W',		Fkillregion},
        {CTRL|'Y',		Fyank},
        {CTRL|'Z',		Ftempexit},
	{CTRL|'_',		Fhelp},

	{')',			Fshowmatch},
	{'}',			Fshowmatch},
	{']',			Fshowmatch},

/*
keypad keys
-----------		*/
	{KLP,			Fmvdnwind},
	{KRP,			Fmvupwind},
	{KSLASH,		Fsplitwind},
	{KSTAR,			Fonlywind},
	{KMINUS,		Fprevwind},
	{KPLUS,			Fnextwind},
	{KENTER,		Fctlxe},
	{KDOT,			Fgotoline},
	{K0,			Ftemul},


	{K7,			Fgotobob},
	{K8,			Freposition},
	{K9,			Fgotoeob},
	{K4,			Fbackword},
	{K5,			Fbackline},
	{K6,			Fforwword},
	{K1,			Fgotobol},
	{K2,			Fgforwline},
	{K3,			Fgotoeol},
	{CTLX|CTRL|'A',		Fshowkbdmacro},
        {CTLX|CTRL|'B',		Flistbuffers},
        {CTLX|CTRL|'C',		Fquit},
        {CTLX|CTRL|'F',		Ffilevisit},
        {CTLX|CTRL|'I',		Fbufferinsert},
        {CTLX|CTRL|'O',		Fdeblank},
        {CTLX|CTRL|'N',		Fmvdnwind},
        {CTLX|CTRL|'P',		Fmvupwind},
        {CTLX|CTRL|'R',		Ffileread},
        {CTLX|CTRL|'S',		Ffilesave},
        {CTLX|CTRL|'V',		Ffilevisit},
        {CTLX|CTRL|'W',		Ffilewrite},
        {CTLX|CTRL|'X',		Fswapmark},
        {CTLX|CTRL|'Z',		Fshrinkwind},
	{CTLX|'!',		Fspawn},
        {CTLX|'!',		Fexecbuf},
        {CTLX|'=',		Fshowcpos},
        {CTLX|'(',		Fctlxlp},
        {CTLX|')',		Fctlxrp},
        {CTLX|'1',		Fonlywind},
        {CTLX|'2',		Fsplitwind},
        {CTLX|'B',		Fusebuffer},
	{CTLX|'E',		Fctlxe},
        {CTLX|'F',		Fsetfillcol},
        {CTLX|'I',		Ffileinsert},
        {CTLX|'K',		Fkillbuffer},
        {CTLX|'N',		Fnextwind},
        {CTLX|'O',		Fnextwind},
        {CTLX|'P',		Fprevwind},
	{CTLX|'S',		Fsavebuffers},
        {CTLX|'Z',		Fenlargewind},
        {META|CTRL|'H',		Fdelbword},
        {META|'!',		Fexecbuf},
	{META|'.',		Fsetmark},
        {META|'>',		Fgotoeob},
        {META|'<',		Fgotobob},
	{META|'[',		Fgotobop},
	{META|']',		Fgotoeop},
	{META|'%',		Fqueryrepl},
	{META|' ',		Fdelwhite},
        {META|'B',		Fbackword},
        {META|'C',		Fcapword},
        {META|'D',		Fdelfword},
        {META|'F',		Fforwword},
        {META|'G',		Ftogulambuf},
        {META|'L',		Flowerword},
	{META|'Q',		Ffillpara},
	{META|'R',		Fbacksearch},
	{META|'S',		Fforwsearch},
        {META|'U',		Fupperword},
        {META|'V',		Fbackpage},
        {META|'W',		Fcopyregion},
 	{META|0x7F,		Fdelbword},
        {META|CTRL|'[',		Fgxpand},
        {META|CTRL|'D',		Fgxpshow},
        {META|CTRL|'F',		Ffilename},
        {0x7F,			Fbackdel},
	{HELP+SHIFTED,		Fkbreset},
				/* room for new key bindings */
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{KEOTBL,		Fnoop}
};

local KB  minikeybind[] = {
	{F1,			Fdelbword},
	{F2,			Fdelfword},
	{F3,			Fkill},
	{F4,			Fcopyregion},

	{HELP,			Fhelp},
	{UNDO,   		Fsemireset},
	{INSERT,		Fescesc},
	{HOME,			Fescctrld},
	{UPARRO, 		Fbackline},
	{DNARRO,		Fgforwline},
	{LTARRO,		Fbackchar},
	{RTARRO,		Fforwchar},

	{CTRL|'[',		Fescesc},
	{CTRL|'X',		Fctlxnext},
        {CTRL|'@',		Fsetmark},
        {CTRL|'A',		Fgotobol},
        {CTRL|'B',		Fbackchar},
	{CTRL|'C',		Fkilltobln},
        {CTRL|'D',		Fforwdel},
        {CTRL|'E',		Fgotoeol},
        {CTRL|'F',		Fforwchar},
	{CTRL|'G',		Fminiterm},
        {CTRL|'H',		Fbackdel},
        {CTRL|'I',		Fescesc},
	{CTRL|'J',		Fminiterm},
        {CTRL|'K',		Fkill},
 	{CTRL|'L',		Frefresh},
        {CTRL|'M',		Fminiterm},
        {CTRL|'N',		Fgforwline},
        {CTRL|'O',		Fopenline},
        {CTRL|'P',		Fbackline},
        {CTRL|'Q',		Fquote},
	{CTRL|'R',		Fminiterm},
        {CTRL|'S',		Fminiterm},
        {CTRL|'T',		Ftwiddle},
	{CTRL|'U',		Fkilltobln},
        {CTRL|'V',		Fforwpage},
	{CTRL|'W',		Fkillregion},
        {CTRL|'Y',		Fyank},
        {CTRL|'Z',		Ftempexit},

/*
keypad keys
-----------		*/
	{KENTER,		Fctlxe},
	{KDOT,			Fswapmark},
	{K0,			Ftemul},

	{K7,			Fgotobob},
	{K8,			Freposition},
	{K9,			Fgotoeob},
	{K4,			Fbackword},
	{K5,			Fbackline},
	{K6,			Fforwword},
	{K1,			Fgotobol},
	{K2,			Fgforwline},
	{K3,			Fgotoeol},

        {CTLX|CTRL|'O',		Fdeblank},
        {CTLX|CTRL|'X',		Fswapmark},
        {CTLX|'E',		Fctlxe},
        {CTLX|'(',		Fctlxlp},
	{CTLX|')',		Fctlxrp},

        {META|CTRL|'D',		Fminiterm},
        {META|CTRL|'H',		Fdelbword},
        {META|'!',		Freposition},
        {META|'.',		Fsetmark},
	{META|'>',		Fgotoeob},
        {META|'<',		Fgotobob},
        {META|'B',		Fbackword},
        {META|'C',		Fcapword},
        {META|'D',		Fdelfword},
        {META|'F',		Fforwword},
        {META|'L',		Flowerword},
        {META|'U',		Fupperword},
        {META|'V',		Fbackpage},
        {META|'W',		Fcopyregion},
        {META|0x7F,		Fdelbword},
        {META|CTRL|'[',		Fescesc},
        {0x7F,			Fbackdel},
	{HELP+SHIFTED,		Fkbreset},
				/* room for new key bindings */
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{0,			Fnoop},
	{KEOTBL,		Fnoop}
};

extern	KB	tekeybind[];

KB	*kba[]	= {regkeybind, gukeybind, minikeybind, tekeybind};

/** int	nminikeybind	= (sizeof(minikeybind)/sizeof(minikeybind[0])); **/

extern	long	atoir();


/* This function modifies the keyboard binding table.  It is invoked
from Gulam's do.c.  Arg n is the index into kba[], and both codes are
given as hex strings.  */

bindkey(n, keycode, cmdcode)
uchar	*keycode, *cmdcode;
{	register int	kc, fx, cc;
        register KB *ktp;

	kc = (int) atoir(keycode, 16);
	fx = (int) atoir(cmdcode, 16);  if (kc == 0 || fx > Ftotal) return;
	for (ktp  = kba[n]; (cc = ktp->k_code) != KEOTBL; ktp++)
	{	if (cc == 0 || cc == kc)
		{	ktp->k_code = kc;
			ktp->k_fx   = fx;
			return;
        }	}
	mlwrite("sorry, no room for new key binding...");
}

static	char	buf[64];
static	char	bl[16] = "               ";	/* 15 blanks */

	static
setupkf(kc, fx)
register int	kc, fx;
{
	register long	xx;
	extern	uchar	*findname();

	/* 0x1000 is added because itoar() does not give leading 0s */
	xx = 0x1000L + (long) kc;
	strcpy(buf, itoar(xx, 16)); buf[0]= ' ';
	xx = 0x100L + (long) fx;
	strcpy(buf+4, itoar(xx, 16)); buf[4]=buf[7]=buf[8]= ' ';
	strcpy(buf+9,  findname(0, kc));  strcat(buf+9, bl);
	strcpy(buf+24, findname(1, fx));  /* Add function name.	*/
}

/* Create a table, listing all of the command keys and their current
bindings, and stores the table in the standard pop-op buffer.  This
lets MicroEMACS produce it's own wall chart.  The bindings to
"ins-self" are only displayed if there is an argument.  */

local	uchar	*wcname[3] = {
#ifdef	AtariST
	"\257wall chart r\256",
	"\257wall chart g\256",
	"\257wall chart m\256"
#else
	">wall chart r<",
	">wall chart g<",
	">wall chart m<"
#endif
};

wallchart()
{	register BUFFER *bp;
	register KB	*ktp;
	register int	cc, n;

	mlwrite("wall chart for Regular buffer, Minibuf, or Gulam? [r m or g] ");
	cc = getkey();
	n = (cc == 'm'? 2 : (cc == 'g'? 1 : 0));
        bp = bfind(wcname[n], TRUE, BFTEMP, REGKB, BMCTMP);
	if (bp==NULL || bclear(bp)!=TRUE) return FALSE;
	for (ktp = kba[n]; (cc = ktp->k_code) != KEOTBL; ktp++)
	{	setupkf(cc, ktp->k_fx);
		if (addline(bp, buf) == FALSE)	return FALSE;
	}
	return popbuf(bp) != NULL;
}

/* Read a key from the keyboard, and look it up in the binding table.
Display the name of the function currently bound to the key.  */

desckey()
{	register int    fx;
	register KEY	c, kc, c2, n;
        register KB	*ktp;

	mlwrite("Briefly describe key: ");
	c = getkey();
	mlwrite("in Regular buffer, Minibuf, or Gulam? [r m or g] ");
	c2 = getkey();
	n = (c2 == 'm'? 2 : (c2 == 'g'? 1 : 0));
	for (fx = 0, ktp = kba[n]; (kc = ktp->k_code) != KEOTBL; ktp++)
		if (kc == c) {fx = ktp->k_fx; break;}
        if (fx == 0 && ((c>=0x20 && c<=0x7E) ||  (c>=0xA0 && c<=0xFE)))
		/* Self inserting.  these too are ok on ST */
		fx = Fselfinsert;
	setupkf(c, fx); buf[7] = buf[23] = '\000';
	mlwrite("(key-code fn-code %s) %s runs %s", buf, buf+8, buf+24);
	return TRUE;
}

/* -eof- */
