/**************************************************************************** * * 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); } /* PackQualifiers(): * * Pack a couple of qualifiers indicated by a keymap * qualifier tag (sortof). */ STATIC UWORD PackQualifiers(BYTE Bits) { UWORD Qualifier = 0; if(Bits & KCF_SHIFT) Qualifier |= IEQUALIFIER_LSHIFT; if(Bits & KCF_ALT) Qualifier |= IEQUALIFIER_LALT; if(Bits & KCF_CONTROL) Qualifier |= IEQUALIFIER_CONTROL; return(Qualifier); } /* ScanKeyMap(): * * Scan a given part of the keymap area and handle the * necessary Ansi<->InputEvent conversion. */ BYTE ScanKeyMap(UBYTE Hi,UBYTE Offset,UBYTE *KeyTable,UBYTE *KeyTypes,UBYTE AnsiKey,struct InputEvent *Event) { /* This table contains the qualifiers associated with * the various KeyType flag bits. */ STATIC struct { UBYTE QualBits; UWORD Qualifiers[4]; } QualType[8] = { KC_NOQUAL, 0, 0, 0, 0, KCF_SHIFT, 0, 0, IEQUALIFIER_LSHIFT, 0, KCF_ALT, 0, 0, IEQUALIFIER_LALT, 0, KCF_CONTROL, 0, 0, IEQUALIFIER_CONTROL, 0, KCF_ALT|KCF_SHIFT, IEQUALIFIER_LSHIFT|IEQUALIFIER_LALT, IEQUALIFIER_LALT, IEQUALIFIER_LSHIFT, 0, KCF_CONTROL|KCF_ALT, IEQUALIFIER_CONTROL|IEQUALIFIER_LALT, IEQUALIFIER_CONTROL, IEQUALIFIER_LALT, 0, KCF_CONTROL|KCF_SHIFT, IEQUALIFIER_CONTROL|IEQUALIFIER_LSHIFT, IEQUALIFIER_CONTROL, IEQUALIFIER_LSHIFT, 0, KC_VANILLA, IEQUALIFIER_LSHIFT|IEQUALIFIER_LALT, IEQUALIFIER_LALT, IEQUALIFIER_LSHIFT, 0 }; BYTE *String; SHORT i,j,k; /* Scan the area. */ for(i = 0 ; i < Hi ; i++) { /* This one's a dead key or dead-key-modifiable. */ if(KeyTypes[i] & KCF_DEAD) { String = (BYTE *)(((ULONG *)KeyTable)[i]); /* There a eight two-byte-pairs. The first * byte indicates the type of the dead * key. */ for(j = 0 ; j < 8 ; j++) { switch(String[2 * j]) { /* Vanilla key. */ case 0: if((UBYTE)String[2 * j + 1] == AnsiKey) { Event -> ie_Qualifier = PackQualifiers(j); Event -> ie_Code = Offset + i; return(TRUE); } break; /* Dead key modifiable, let's hope * that the first character in * the table indicates our ansi key. */ case DPF_MOD: if((UBYTE)String[String[2 * j + 1]] == AnsiKey) { Event -> ie_Qualifier = PackQualifiers(j); Event -> ie_Code = Offset + i; return(TRUE); } break; /* Ignore the rest. */ default: break; } } } /* Is a string mapped to this key? */ if(KeyTypes[i] & KCF_STRING) { String = (BYTE *)(((ULONG *)KeyTable)[i]); /* We need only 1 character strings. */ if(String[0] == 1) { if((UBYTE)String[String[1]] == AnsiKey) { for(k = 0 ; k < 8 ; k++) { if(QualType[k] . QualBits == (KeyTypes[i] & KC_VANILLA)) { Event -> ie_Qualifier = QualType[k] . Qualifiers[j]; Event -> ie_Code = Offset + i; return(TRUE); } } } } /* Find the approriate qualifier. */ for(j = 0 ; j < 3 ; j++) { if(KeyTypes[i] & (1 << j)) { if(String[2 + (2 * j)] == 1) { if((UBYTE)String[String[3 + (2 * j)]] == AnsiKey) { for(k = 0 ; k < 8 ; k++) { if(QualType[k] . QualBits == (KeyTypes[i] & KC_VANILLA)) { Event -> ie_Qualifier = QualType[k] . Qualifiers[j]; Event -> ie_Code = Offset + i; return(TRUE); } } } } } } } else { /* It's a fair vanilla key. */ for(j = 0 ; j < 4 ; j++) { if(AnsiKey == KeyTable[4 * i + j]) { for(k = 0 ; k < 8 ; k++) { if(QualType[k] . QualBits == KeyTypes[i]) { Event -> ie_Qualifier = QualType[k] . Qualifiers[j]; Event -> ie_Code = Offset + i; return(TRUE); } } } } } } return(FALSE); } STATIC VOID PutKey(struct InputEvent *Event,UBYTE RawKey) { Event -> ie_Qualifier = 0; Event -> ie_Code = RawKey; } /* KeyInvert(): * * Find the qualifier & code which generate the Ansi * character passed to this routine. */ BYTE KeyInvert(UBYTE AnsiKey,struct InputEvent *Event,struct KeyMap *KeyMap) { /* Careful: if this is actually a control character * (return, escape, etc.) we will check the * high keymap table first, else the low * keymap table. */ switch(AnsiKey) { case ' ': PutKey(Event,0x40); return(TRUE); case '\b': PutKey(Event,0x41); return(TRUE); case '\t': PutKey(Event,0x42); return(TRUE); case '\n': case '\r': PutKey(Event,0x44); return(TRUE); case '\33': PutKey(Event,0x45); return(TRUE); case '\177': PutKey(Event,0x46); return(TRUE); /* This does - strange enough - not work correctly. Can you discover why? case ' ': case '\b': case '\t': case '\n': case '\r': case '\33': case '\177': if(!ScanKeyMap(0x28,0x40,KeyMap -> km_HiKeyMap,KeyMap -> km_HiKeyMapTypes,AnsiKey,Event)) return(ScanKeyMap(0x40,0x00,KeyMap -> km_LoKeyMap,KeyMap -> km_LoKeyMapTypes,AnsiKey,Event)); else return(TRUE); */ /* Check the low keymap table first. */ default: if(!ScanKeyMap(0x40,0x00,KeyMap -> km_LoKeyMap,KeyMap -> km_LoKeyMapTypes,AnsiKey,Event)) return(ScanKeyMap(0x28,0x40,KeyMap -> km_HiKeyMap,KeyMap -> km_HiKeyMapTypes,AnsiKey,Event)); else return(TRUE); } }