home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
text
/
jed
/
src
/
jed.lha
/
keys.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-05
|
10KB
|
438 lines
/*
* KEYS.C
* (c) 1992-3 J.Harper
*/
#include "jed.h"
#include "jed_protos.h"
Prototype VALUE * cmd_bind (LONG, VALUE *);
Prototype VALUE * cmd_unbind (LONG, VALUE *);
Prototype VOID killbindings (VOID);
Local STRPTR evalbinding (UBYTE, UWORD);
Prototype VOID usekey (struct IntuiMessage *);
Local ULONG descrtoraw (STRPTR);
Local BOOL cmpquals (UWORD, UWORD);
#define HARDCODE_CURSOR
#define UNPAIREDQUALS (IEQUALIFIER_CONTROL | IEQUALIFIER_NUMERICPAD | \
IEQUALIFIER_MIDBUTTON | IEQUALIFIER_RBUTTON | IEQUALIFIER_LEFTBUTTON)
#define SHIFTQUALS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
#define ALTQUALS (IEQUALIFIER_LALT | IEQUALIFIER_RALT)
#define CMDQUALS (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)
typedef struct KEY
{
struct KEY *ky_Next;
UWORD ky_Qual;
STRPTR ky_Cmd;
} KEY;
Local KEY *KeyHash[128];
typedef struct KEYDESC
{
STRPTR kd_Name;
BOOL kd_IsCode;
UWORD kd_Value;
} KEYDESC;
Local const KEYDESC KeyDescr[] =
{
"SHIFT", FALSE, SHIFTQUALS,
"ALT", FALSE, ALTQUALS,
"COMMAND", FALSE, CMDQUALS,
"AMIGA", FALSE, CMDQUALS,
"CONTROL", FALSE, IEQUALIFIER_CONTROL,
"CTRL", FALSE, IEQUALIFIER_CONTROL,
"NUMERICPAD", FALSE, IEQUALIFIER_NUMERICPAD,
"LMB", FALSE, IEQUALIFIER_LEFTBUTTON,
"MMB", FALSE, IEQUALIFIER_MIDBUTTON,
"RMB", FALSE, IEQUALIFIER_RBUTTON,
"SPACE", TRUE, 0x40,
"BACKSPACE", TRUE, 0x41,
"TAB", TRUE, 0x42,
"ENTER", TRUE, 0x43,
"RETURN", TRUE, 0x44,
"ESC", TRUE, 0x45,
"ESCAPE", TRUE, 0x45,
"DEL", TRUE, 0x46,
"DELETE", TRUE, 0x46,
"HELP", TRUE, 0x5f,
"UP", TRUE, 0x4c,
"DOWN", TRUE, 0x4d,
"RIGHT", TRUE, 0x4e,
"LEFT", TRUE, 0x4f,
"F1", TRUE, 0x50,
"F2", TRUE, 0x51,
"F3", TRUE, 0x52,
"F4", TRUE, 0x53,
"F5", TRUE, 0x54,
"F6", TRUE, 0x55,
"F7", TRUE, 0x56,
"F8", TRUE, 0x57,
"F9", TRUE, 0x58,
"F10", TRUE, 0x59,
NULL, 0, 0
};
/*
* Structure to fix problems with binding to numeric pad keys.
* actually this may not work properly on some weird keymaps.
*/
typedef struct NUMDESC
{
STRPTR nd_Name; /* char to map */
UBYTE nd_TypewriterKey; /* rawkey for typewriter */
UBYTE nd_TypewriterQual;
UBYTE nd_NumericKey; /* rawkey for numeric */
} NUMDESC;
Local const NUMDESC NumDescr[] =
{
"(", 0x09, SHIFTQUALS, 0x5c,
")", 0x0a, SHIFTQUALS, 0x5b,
"/", 0x3a, 0, 0x5c,
"*", 0x08, SHIFTQUALS, 0x5d,
"7", 0x07, 0, 0x3d,
"8", 0x08, 0, 0x3e,
"9", 0x09, 0, 0x3f,
"-", 0x0b, 0, 0x4a,
"4", 0x04, 0, 0x2d,
"5", 0x05, 0, 0x2e,
"6", 0x06, 0, 0x2f,
"+", 0x0c, SHIFTQUALS, 0x5e,
"1", 0x01, 0, 0x1d,
"2", 0x02, 0, 0x1e,
"3", 0x03, 0, 0x1f,
"0", 0x0a, 0, 0x0f,
".", 0x39, 0, 0x3c,
0, 0, 0, 0
};
/*
* (bind {`keyDescr' `command'})
*/
VALUE *
cmd_bind(LONG argc, VALUE *argv)
{
VALUE *res = &RES;
BOOL rc = TRUE;
while(rc && (argc >= 2))
{
if(TPLATE2(VTF_STRING, VTF_STRING))
{
KEY *newkey;
LONG keyqual;
if(newkey = AllocVec(sizeof(KEY), MEMF_CLEAR))
{
if(((keyqual = descrtoraw(ARG1.val_Value.String)) != -1) && ((UBYTE)keyqual < IECODE_UP_PREFIX))
{
newkey->ky_Qual = (WORD)(keyqual >> 16);
if(newkey->ky_Cmd = savestring(ARG2.val_Value.String))
{
newkey->ky_Next = KeyHash[(UBYTE)keyqual];
KeyHash[(UBYTE)keyqual] = newkey;
}
else
{
settitle(NoMemMsg);
FreeVec(newkey);
rc = FALSE;
}
}
else
{
FreeVec(newkey);
rc = FALSE;
}
}
else
{
settitle(NoMemMsg);
rc = FALSE;
}
}
else
goto abort;
argc -= 2;
argv += 2;
}
res->val_Type = VTF_NUMBER;
res->val_Value.Number = rc;
abort:
return(res);
}
/*
* (unbind {`keyDescr'})
*/
VALUE *
cmd_unbind(LONG argc, VALUE *argv)
{
VALUE *res = &RES;
BOOL rc = TRUE;
while(rc && (argc >= 1))
{
if(TPLATE1(VTF_STRING))
{
LONG keyqual;
if(keyqual = descrtoraw(ARG1.val_Value.String))
{
KEY *thiskey, *prevkey = NULL;
UBYTE index = (UBYTE)keyqual;
if(thiskey = KeyHash[index])
{
while(thiskey)
{
if(thiskey->ky_Qual == (WORD)(keyqual >> 16))
break;
prevkey = thiskey;
thiskey = thiskey->ky_Next;
}
if(thiskey)
{
if(prevkey)
prevkey->ky_Next = thiskey->ky_Next;
else
KeyHash[index] = thiskey->ky_Next;
freestring(thiskey->ky_Cmd);
FreeVec(thiskey);
}
}
else
{
settitle("error: key not bound to anything");
rc = FALSE;
}
}
}
else
goto abort;
argc--;
argv++;
}
res->val_Type = VTF_NUMBER;
res->val_Value.Number = rc;
abort:
return(res);
}
VOID
killbindings(VOID)
{
LONG i;
for(i = 0; i < 128; i++)
{
KEY *thiskey;
thiskey = KeyHash[i];
while(thiskey)
{
KEY *nextkey = thiskey->ky_Next;
freestring(thiskey->ky_Cmd);
FreeVec(thiskey);
thiskey = nextkey;
}
KeyHash[i] = NULL;
}
}
Local STRPTR
evalbinding(UBYTE key, UWORD qual)
{
if(key < IECODE_UP_PREFIX)
{
KEY *thiskey;
if(thiskey = KeyHash[key])
{
while(thiskey)
{
if(cmpquals(thiskey->ky_Qual, qual))
break;
thiskey = thiskey->ky_Next;
}
if(thiskey)
return(thiskey->ky_Cmd);
}
}
return(FALSE);
}
VOID
usekey(struct IntuiMessage *im)
{
UWORD key = im->Code;
UWORD qual = im->Qualifier;
STRPTR cmd;
qual &= ~(IEQUALIFIER_REPEAT | IEQUALIFIER_INTERRUPT | IEQUALIFIER_MULTIBROADCAST | IEQUALIFIER_RELATIVEMOUSE);
resettitle();
cursor(OFF);
if(cmd = evalbinding(key, qual))
{
VALUE result;
execstr(cmd, &result, FALSE, 0, NULL);
releasevalue(&result);
}
else
{
#ifdef HARDCODE_CURSOR
switch(key)
{
case 0x4c:
if(!(qual & ~IEQUALIFIER_CAPSLOCK))
moveuplines(1);
else if(qual & SHIFTQUALS)
moveuppages(1);
else if(qual & IEQUALIFIER_CONTROL)
movesof();
break;
case 0x4d:
if(!(qual & ~IEQUALIFIER_CAPSLOCK))
movedownlines(1);
else if(qual & SHIFTQUALS)
movedownpages(1);
else if(qual & IEQUALIFIER_CONTROL)
moveeof();
break;
case 0x4e:
if(!(qual & ~IEQUALIFIER_CAPSLOCK))
moveright(1);
else if(qual & SHIFTQUALS)
moveeol();
else if(qual & IEQUALIFIER_CONTROL)
movenextword(1);
break;
case 0x4f:
if(!(qual & ~IEQUALIFIER_CAPSLOCK))
moveleft(1);
else if(qual & SHIFTQUALS)
movesol();
else if(qual & IEQUALIFIER_CONTROL)
moveprevword(1);
break;
default:
#endif
UBYTE buff[256];
LONG len;
struct InputEvent ie;
ie.ie_Class = IECLASS_RAWKEY;
ie.ie_SubClass = 0;
ie.ie_Code = key;
ie.ie_Qualifier = qual;
ie.ie_EventAddress = *((APTR *)im->IAddress);
if((len = MapRawKey(&ie, buff, 255, NULL)) > 0)
{
VW *vw = CurrVW;
setrefresh(RFF_LINEFROM, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line);
buff[len] = 0;
padcursor();
if((vw->vw_Prefs.prf_WordWrap) && ((vw->vw_CursorPos.pos_Col + len) > vw->vw_Prefs.prf_RightMargin))
wrapline();
insertstrn(buff, len);
resyncxy();
vw->vw_Tx->tx_Changes++;
}
else if(len < 0)
settitle("error: key buffer screwup");
#ifdef HARDCODE_CURSOR
break;
}
#endif
refresh();
}
cursor(ON);
}
/*
* Gets a packed set of rawkey and qualifier from an input description.
* Qualifier is high 16 bits, rawkey is low 16. Returns -1 if an error.
*/
Local ULONG
descrtoraw(STRPTR desc)
{
STRPTR str = desc;
UWORD qual = 0;
for(;;)
{
UBYTE buff[100];
KEYDESC *kd = KeyDescr;
str = stpblk(cpynotspc(buff, str));
while(kd->kd_Name)
{
if(!stricmp(kd->kd_Name, buff))
{
if(!kd->kd_IsCode)
{
qual |= kd->kd_Value;
break;
}
else
return(((ULONG)qual << 16) | ((ULONG)kd->kd_Value));
}
kd++;
}
if(!kd->kd_Name)
{
NUMDESC *nd = NumDescr;
UBYTE coded[2];
while(nd->nd_Name)
{
if(!strcmp(nd->nd_Name, buff))
{
if(qual & IEQUALIFIER_NUMERICPAD)
return(((ULONG)qual << 16) | ((ULONG)nd->nd_NumericKey));
else
{
qual |= nd->nd_TypewriterQual;
return(((ULONG)qual << 16) | ((ULONG)nd->nd_TypewriterKey));
}
}
nd++;
}
if(MapANSI(buff, strlen(buff), coded, 1, NULL) == 1)
{
qual |= (UWORD)coded[1];
return(((ULONG)qual << 16) | ((ULONG)coded[0]));
}
settitlefmt("error: invalid key description %s", (LONG)desc);
return(-1);
}
}
}
/*
* I'm sure there's an easier way to compare qualifiers (treating the paired
* keys (eg lshift and rshift) as equivalent), however, I can't think of it.
*/
Local BOOL
cmpquals(UWORD qual1, UWORD qual2)
{
if((qual1 & UNPAIREDQUALS) == (qual2 & UNPAIREDQUALS))
{
UWORD res1, res2;
res1 = qual1 & SHIFTQUALS;
res2 = qual2 & SHIFTQUALS;
if((!res1 && !res2) || (res1 && res2))
{
res1 = qual1 & ALTQUALS;
res2 = qual2 & ALTQUALS;
if((!res1 && !res2) || (res1 && res2))
{
res1 = qual1 & CMDQUALS;
res2 = qual2 & CMDQUALS;
if((!res1 && !res2) || (res1 && res2))
return(TRUE);
}
}
}
return(FALSE);
}