home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
keyboard
/
keymacro_398
/
keysupport.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-01
|
7KB
|
341 lines
/****************************************************************************
*
* KeySupport.c ---------- Keymacro support routines.
*
* Author ---------------- Olaf Barthel, MXM
* Brabeckstrasse 35
* D-3000 Hannover 71
*
* KeyMacro © Copyright 1990 by MXM; Executable program,
* documentation and source code are shareware. If you like
* this program a small donation will entitle you to receive
* updates and new programs from MXM.
*
****************************************************************************/
/* AllocRem():
*
* Allocate public memory and keep track of its size.
*/
VOID *
AllocRem(LONG ByteSize,LONG Requirements)
{
LONG *MemoryBlock = NULL;
LONG RemSize = ByteSize + sizeof(LONG);
if(ByteSize > 0)
MemoryBlock = (LONG *)AllocMem(RemSize,Requirements);
if(MemoryBlock)
*MemoryBlock++ = RemSize;
return((VOID *)MemoryBlock);
}
/* FreeRem():
*
* Free a tracked portion of memory.
*/
VOID *
FreeRem(LONG *MemoryBlock)
{
if(MemoryBlock--)
FreeMem(MemoryBlock,*MemoryBlock);
return(NULL);
}
/* SendMacroMsg(scm_Msg,scm_Port):
*
* Post a cloned macro message to a MsgPort.
*/
VOID *
SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port)
{
struct MacroMessage *scm_TempMsg;
if(scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR))
{
CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
scm_TempMsg -> mm_Message . mn_Node . ln_Name = (char *)scm_TempMsg;
scm_TempMsg -> mm_Message . mn_ReplyPort = NULL;
scm_TempMsg -> mm_Message . mn_Length = sizeof(struct MacroMessage);
PutMsg(scm_Port,(struct Message *)scm_TempMsg);
}
return((VOID *)scm_TempMsg);
}
/* The following piece of code was written by Jim Mackraz;
* I do not claim any publishing rights for it, the code
* is still his property. I will try to remove it as soon
* as Kick 2.x has left the beta phase (read the docs,
* there will probably be no further KeyMacro revisions
* for pre-2.x systems).
*/
#define CONTROLBITS ( (1 << 5) | (1 << 6) )
STATIC BYTE
CheckNormal(four_bytesp, val, type, qualp)
LONG four_bytesp;
UBYTE val;
UWORD type;
UWORD *qualp;
{
UBYTE *p = (UBYTE *)four_bytesp; /* codes held in long word */
long position;
/* start with last of four bytes, "more vanilla" */
p += 3;
for(position = 3 ; position >= 0 ; --position, --p)
{
if(*p == val)
{
switch(type)
{
case KC_NOQUAL: if(position != 3)
goto NOT_THIS;
break;
case KCF_SHIFT: if(!(position & 2))
goto NOT_THIS;
if(position == 2)
*qualp |= IEQUALIFIER_LSHIFT;
break;
case KCF_ALT: if(!(position & 2))
goto NOT_THIS;
if(position == 2)
*qualp |= IEQUALIFIER_LALT;
break;
case KCF_CONTROL:
if(!(position & 2))
goto NOT_THIS;
if(position == 2)
*qualp |= IEQUALIFIER_CONTROL;
break;
case KCF_ALT | KCF_CONTROL:
if(!(position & 1))
*qualp |= IEQUALIFIER_LALT;
if(!(position & 2))
*qualp |= IEQUALIFIER_CONTROL;
break;
case KCF_SHIFT | KCF_CONTROL:
if(!(position & 1))
*qualp |= IEQUALIFIER_LSHIFT;
if(!(position & 2))
*qualp |= IEQUALIFIER_CONTROL;
break;
case KCF_SHIFT | KCF_ALT:
if(!(position & 1))
*qualp |= IEQUALIFIER_LSHIFT;
if(!(position & 2))
*qualp |= IEQUALIFIER_LALT;
break;
default: break;
}
return(TRUE);
}
NOT_THIS: ;
}
return(FALSE);
}
STATIC BYTE
CheckVanilla(p,val,qualp)
UBYTE *p; /* note: byte pointer */
UBYTE val;
UWORD *qualp;
{
int i;
/* only one way to match a vanilla control key */
if(!(val & CONTROLBITS))
{
/* is a control code */
if((p[3] & ~CONTROLBITS) == val)
{
*qualp |= IEQUALIFIER_CONTROL;
return(TRUE);
}
}
else
{
/* not a control */
for(i = 3 ; i >= 0 ; --i)
{
if(p[i] == val)
{
if(!(i & 1))
*qualp |= IEQUALIFIER_LSHIFT;
if(!(i & 2))
*qualp |= IEQUALIFIER_LALT;
return(TRUE);
}
}
}
return(FALSE);
}
#define KEYMAPSIZE 64
/* LowKeyInvert returns good code else <0 if no find
*
* regarding keymap as many-to-one mapping:
* -entries for a given key are scanned so that
* the minimum number of qualifiers are associated
* with the keystroke.
* -passing a character value of zero corresponds, in
* the default keymap, to CTRL-`, which is probably a bug.
* -numerals are matched with numeric pad keystrokes (no
* qualifiers) on standard keymap. The way to specify
* a key on the number row is via its shifted value;
* specify explicitly that the qualifier is to be unshifted,
* or a "don't care."
*/
STATIC UWORD
LowKeyInvert(value,km,codep,qualp,indexp)
UBYTE value; /* translation value from low keymap */
struct KeyMap *km;
UWORD *codep; /* pointers where answers are to be put */
UWORD *qualp;
ULONG *indexp; /* dead-key index information (put into ie?) */
{
UWORD code = KEYMAPSIZE - 1; /* last entry */
unsigned int type;
LONG *p; /* points to four-byte lokeymap entry */
int found_it = 0;
*indexp = *qualp = 0;
p = (LONG *)km -> km_LoKeyMap + code;
do
{
/* determine type of key */
if((type = km -> km_LoKeyMapTypes[code]) == KC_VANILLA)
found_it = CheckVanilla(p,value,qualp);
else
if(!(type & KCF_NOP))
found_it = CheckNormal(p,value,type,qualp);
--p;
}
while(!found_it && code--);
*codep = code;
return(code);
}
ULONG
InvertKeyMap(ULONG ansicode,struct InputEvent *ie,struct KeyMap *km)
{
LONG kindex;
UBYTE code = 0;
ie -> ie_Class = IECLASS_RAWKEY;
ie -> ie_EventAddress = 0;
/* check for codes in (default) high map first */
switch(ansicode)
{
case ' ': code = 0x40; /* space */
break;
case 0x08: code = 0x41; /* backspace */
break;
case '\t': code = 0x42; /* tab */
break;
case 0x0A:
case 0x0D: code = 0x44; /* return */
break;
case 0x1B: code = 0x45; /* esc */
break;
case 0x7F: code = 0x46; /* del */
break;
case '0': code = 0x0a;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': code = ansicode - '0';
break;
}
if(ansicode >= '1' && ansicode <= '0')
code =
ie -> ie_Code = 0;
ie -> ie_Qualifier = 0;
if(code)
{
ie -> ie_Code = code;
ie -> ie_Qualifier = 0;
return(TRUE);
}
LowKeyInvert((UBYTE)ansicode,km,&ie -> ie_Code,&ie -> ie_Qualifier,(ULONG *)&kindex);
if(!ie -> ie_Code && !ie -> ie_Qualifier)
return(FALSE);
return(TRUE);
}