#include #include #include #include #include "KeyMacro.h" char *CLI_Template = "STARTUP/K,QUIT/S,INFO/S"; char *CLI_Help = "\nUsage: \33[1mKeyMacro\33[0m [STARTUP ] [QUIT] [INFO]\n"; #define ARG_STARTUP 1 #define ARG_QUIT 2 #define ARG_INFO 3 #define ARG_UPDATE 4 #define From_CLI (ThatsMe -> pr_CLI) struct MXMBase *MXMBase; struct MSeg *MSeg; struct MacroKey *KeyList; struct KeyAlias KeyTab[22] = { {"TAB", 0x42}, {"ESC", 0x45}, {"SPACE", 0x40}, {"RETURN", 0x44}, {"ENTER", 0x43}, {"DEL", 0x46}, {"BACKSPACE", 0x41}, {"HELP", 0x5F}, {"LEFT", 0x4F}, {"RIGHT", 0x4E}, {"UP", 0x4C}, {"DOWN", 0x4D}, {"F1", 0x50}, {"F2", 0x51}, {"F3", 0x52}, {"F4", 0x53}, {"F5", 0x54}, {"F6", 0x55}, {"F7", 0x56}, {"F8", 0x57}, {"F9", 0x58}, {"F10", 0x59} }; struct KeyAlias QualifierTab[9] = { {"NONE", 0}, {"CTRL", IEQUALIFIER_CONTROL}, {"NUMPAD", IEQUALIFIER_NUMERICPAD}, {"LSHIFT", IEQUALIFIER_LSHIFT}, {"RSHIFT", IEQUALIFIER_RSHIFT}, {"LALT", IEQUALIFIER_LALT}, {"RALT", IEQUALIFIER_RALT}, {"LAMIGA", IEQUALIFIER_LCOMMAND}, {"RAMIGA", IEQUALIFIER_RCOMMAND} }; #asm _LVORawDoFmt EQU $FFFFFDF6 StuffChar: MOVE.B D0,(A3)+ RTS XDEF _Format _Format: MOVE.L 4(SP),D1 MOVE.L 8(SP),D0 LEA 12(SP),A1 MOVEM.L A0-A3,-(SP) MOVE.L D1,A3 MOVE.L D0,A0 LEA StuffChar(PC),A2 MOVE.L 4,A6 JSR _LVORawDoFmt(A6) MOVEM.L (SP)+,A0-A3 CLR.L D0 RTS #endasm void * SendCustomMsg(scm_Msg) struct MacroMessage *scm_Msg; { struct MacroMessage *scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR); if(scm_TempMsg) { 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(&MSeg -> Port,scm_TempMsg); } return((void *)scm_TempMsg); } UBYTE * GetToken(s,start) UBYTE *s; long *start; { static UBYTE buffer[256]; long i,j,end = 0,quote = FALSE,maxlen = strlen(s); char t; if(maxlen > 255) maxlen = 255; if(*start > strlen(s) - 1 || !strlen(s) || !s) return(NULL); for(i = *start ; i <= maxlen ; i++) { if(!end && (s[i] == ' ' || s[i] == '\t')) { while((s[i] == ' ' || s[i] == '\t') && i < maxlen) { i++; (*start)++; } } t = s[i]; if(!end && t == '+') { (*start)++; continue; } if(!end && t == '=') { strcpy(buffer,"="); (*start)++; return(buffer); } if(s[i] == '\\' && s[i + 1] == '\"') { i += 2; end = i - *start + 1; t = s[i]; } if(t == '\"' && !quote) { quote = TRUE; (*start)++; end++; continue; } if((t == '+' || t == '=' || t == ' ' || t == '\t' || t == ';') && quote) { end++; continue; } if((t == '+' || t == '\n' || t == '=' || t == ' ' || t == 0) || (t == '\"' && quote) || (t == ';' && !quote)) { if(t == ';' && !end) return(NULL); if(t == '\"') { strncpy(buffer,s + *start,end - 1); buffer[end - 1] = 0; } else { strncpy(buffer,s + *start,end); buffer[end] = 0; } (*start) += end; return(buffer); } end++; } return(NULL); } struct MacroKey * AddMacroKey(MacroKey) struct MacroKey *MacroKey; { struct MacroKey *TheKey = NULL; long i; for(i = 0 ; i < MSeg -> NumMacros ; i++) { if(KeyList[i] . mk_Type == MK_UNUSED) { TheKey = &KeyList[i]; break; } } if(!TheKey) return(NULL); CopyMem(MacroKey,TheKey,sizeof(struct MacroKey)); return(TheKey); } BOOL Interprete(String,Line) UBYTE *String; long Line; { ULONG Qualifier = 0; ULONG Code = -1; struct InputEvent FakeEvent; struct MacroKey NewKey; long Start = 0,Key = FALSE,QuitLoop = FALSE,i,KeyCount = 0; UBYTE *Token,*CommandString,*WindowName = NULL,Recognized = FALSE; UBYTE MessBuff[256],KeyBuff1[40],KeyBuff2[40]; if(String[strlen(String) - 1] == '\n') String[strlen(String) - 1] = 0; if(Token = GetToken(String,&Start)) { if(!UStrCmp("KEY",Token)) Key = TRUE; if(UStrCmp("COMMAND",Token) && !Key) { Format(MessBuff,"Line %ld: Unknown keyword:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } } else return(TRUE); FOREVER { if(Token = GetToken(String,&Start)) { QuitLoop = TRUE; for(i = 0 ; i < 9 ; i++) { if(!UStrCmp(QualifierTab[i] . ka_Name,Token)) { Recognized = TRUE; QuitLoop = FALSE; Qualifier |= QualifierTab[i] . ka_Key; } } } else break; if(QuitLoop) break; } if(!Recognized) { Format(MessBuff,"Line %ld: Didn't recognize qualifier:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } if(Token) goto JumpIn; if(Token = GetToken(String,&Start)) { JumpIn: for(i = 0 ; i < 22 ; i++) { if(!UStrCmp(KeyTab[i] . ka_Name,Token)) { Code = KeyTab[i] . ka_Key; goto Next; } } if(InvertKey(Token[0],&FakeEvent,IK_USEIKM,NULL)) Code = FakeEvent . ie_Code; } if(Code == -1) { Format(MessBuff,"Line %ld: Didn't recognize key:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } Next: FOREVER { if(Token = GetToken(String,&Start)) { if(!UStrCmp("=",Token)) break; } else { Format(MessBuff,"Line %ld: Statement '=' missing:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } } if(Token = GetToken(String,&Start)) strcpy(KeyBuff1,Token); else { Format(MessBuff,"Line %ld: Didn't find macro:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } if(Key) goto AddIt; if(!(Token = GetToken(String,&Start))) goto AddIt; if(UStrCmp("WINDOW",Token)) { Format(MessBuff,"Line %ld: Didn't recognize 'WINDOW' statement:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } if(!(Token = GetToken(String,&Start))) { Format(MessBuff,"Line %ld: Didn't find window title:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } if(!(WindowName = (UBYTE *)AllocRem(strlen(Token) + 1,MEMF_PUBLIC))) { PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL); return(FALSE); } strcpy(WindowName,Token); AddIt: for(i = 0 ; i < strlen(KeyBuff1) ; i++) { UBYTE c; if(KeyBuff1[i] != '\\') { KeyBuff2[KeyCount++] = KeyBuff1[i]; continue; } if(i == strlen(KeyBuff1) - 1) break; i++; c = 0; switch(ToUpper(KeyBuff1[i])) { case 'U': c = KC_CURSORUP; break; case 'D': c = KC_CURSORDOWN; break; case 'L': c = KC_CURSORLEFT; break; case 'R': c = KC_CURSORRIGHT; break; case 'H': c = KC_HELP; break; case 'B': c = 8; break; case 'E': c = 127; break; case 'F': if(i == strlen(KeyBuff1) - 1) break; i++; if(!isdigit(KeyBuff1[i])) break; if(!KeyBuff1[i] == '1') { c = KC_FKEY1 + KeyBuff1[i] - '1'; break; } if(i == strlen(KeyBuff1) - 1) break; i++; if(!isdigit(KeyBuff1[i])) { c = KC_FKEY1; break; } if(KeyBuff1[i] != '0') break; c = KC_FKEY10; break; case 'N': c = '\n'; break; case '\\': c = '\\'; break; default: c = KeyBuff1[i]; break; } if(c) KeyBuff2[KeyCount++] = c; } KeyBuff2[KeyCount] = 0; if(!(CommandString = (UBYTE *)AllocRem(strlen(KeyBuff2) + 1,MEMF_PUBLIC))) { PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL); FreeRem(WindowName); return(FALSE); } strcpy(CommandString,KeyBuff2); setmem(&NewKey,sizeof(struct MacroKey),0); NewKey . mk_CommandKey = Code; NewKey . mk_CommandQualifier = Qualifier; NewKey . mk_String = CommandString; NewKey . mk_Window = WindowName; if(Key) NewKey . mk_Type = MK_WORD; else NewKey . mk_Type = MK_COMMAND; if(AddMacroKey(&NewKey)) return(TRUE); Format(MessBuff,"Line %ld: Key macro table full.",Line); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE,NULL); return(FALSE); } BOOL UpdateList(Name) char *Name; { char LineBuff[256]; long LineNum = 1; FILE *ConfigFile; if(!Name) Name = "S:KeyMacro.config"; if(!(KeyList = (struct MacroKey *)AllocRem(sizeof(struct MacroKey) * MAXMACROS,MEMF_PUBLIC | MEMF_CLEAR))) { PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE,NULL); return(FALSE); } MSeg -> NumMacros = MAXMACROS; if(ConfigFile = fopen(Name,"r")) { while(fgets(LineBuff,256,ConfigFile)) { if(!Interprete(LineBuff,LineNum++)) { fclose(ConfigFile); FreeRem(KeyList); return(FALSE); } } fclose(ConfigFile); } else { PopRequest(NULL,"KeyMacro Problem:","Couldn't open configuration file!",NULL,"Continue?",FALSE,NULL); return(FALSE); } return(TRUE); } Chk_Abort() { return(0); } void main(argc,argv) long argc; char *argv[]; { struct Process *ThatsMe = (struct Process *)FindTask(NULL); BOOL Created = FALSE; char *FileName = argv[ARG_STARTUP]; long i; if(!From_CLI) FileName = NULL; if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",0))) { if(From_CLI) Puts("\33[1mKeyMacro:\33[0m You need the \33[1mmxm.library\33[0m to run this program."); exit(5); } MSeg = (struct MSeg *)FindPort(PORTNAME); if(argv[ARG_INFO]) { Printf("\n\33[1m\33[33mKeyMacro\33[31m\33[0m the Amiga macro key handler.\n\n"); Printf(" This program may be non-commercially\n"); Printf(" re-distributed!\n\n"); Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel of MXM\n"); Printf(" Brabeckstrasse 35\n"); Printf(" D-3000 Hannover 71\n\n"); Printf(" Federal Republic of Germany.\n\n"); CloseLibrary(MXMBase); exit(0); } if(argv[ARG_QUIT]) { Printf("Removing \33[1m\33[33mKeyMacro\33[31m\33[0m, "); if(!MSeg) { Printf("failed!\7\n"); CloseLibrary(MXMBase); exit(0); } MSeg -> Father = (struct Task *)FindTask(NULL); if(MSeg -> Child) { Signal(MSeg -> Child,SIG_CLOSE); Wait(SIG_CLOSE); } RemPort(&MSeg -> Port); FreeRem(MSeg -> Port . mp_Node . ln_Name); if(MSeg -> Segment) UnLoadSeg(MSeg -> Segment); if(MSeg -> MacroList) { for(i = 0 ; i < MSeg -> NumMacros ; i++) { if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED) continue; if(MSeg -> MacroList[i] . mk_String) FreeRem(MSeg -> MacroList[i] . mk_String); if(MSeg -> MacroList[i] . mk_Window) FreeRem(MSeg -> MacroList[i] . mk_Window); } FreeRem(MSeg -> MacroList); } FreeRem(MSeg); Printf("OK.\n"); CloseLibrary(MXMBase); exit(0); } if(!MSeg) { if(MSeg = (struct MSeg *)AllocRem(sizeof(struct MSeg),MEMF_PUBLIC | MEMF_CLEAR)) { MSeg -> Port . mp_Flags = PA_IGNORE; MSeg -> Port . mp_Node . ln_Pri = 0; MSeg -> Port . mp_Node . ln_Type= NT_MSGPORT; MSeg -> Port . mp_Node . ln_Name= AllocRem(sizeof(PORTNAME),MEMF_PUBLIC); MSeg -> Child = NULL; MSeg -> Father = (struct Task *)FindTask(NULL); MSeg -> SegSize = sizeof(struct MSeg); MSeg -> RingBack = SIGBREAKF_CTRL_C; MSeg -> Revision = REVISION; NewList(&MSeg -> Port . mp_MsgList); if(From_CLI) { Printf("\33[1m\33[33mKeyMacro v1.%ld \33[31m\33[0m(C) Copyright 1989, 1990 by \33[4mMXM\33[0m.\n",REVISION); Printf("Installing \33[33m\33[1mKeyMacro\33[0m\33[31m, "); } if(MSeg -> Port . mp_Node . ln_Name) strcpy(MSeg -> Port . mp_Node . ln_Name,PORTNAME); else { if(From_CLI) Printf("failed!\n"); CloseLibrary(MXMBase); exit(20); } MSeg -> Segment = (BPTR)LoadSeg("KeyMacro-Handler"); if(!MSeg -> Segment) MSeg -> Segment = (BPTR)LoadSeg("L:KeyMacro-Handler"); if(!MSeg -> Segment) { if(From_CLI) Printf("unable to find \33[33mL:KeyMacro-Handler\33[31m\7!\n"); FreeRem(MSeg -> Port . mp_Node . ln_Name); FreeRem(MSeg); } else { AddPort(&MSeg -> Port); CreateProc("KeyMacro-Handler",10,MSeg -> Segment,4096); Wait(SIGBREAKF_CTRL_C); if(!MSeg -> Child) { if(From_CLI) Printf("\33[33mFAILED!\33[31m (care to retry?)\n"); RemPort(&MSeg -> Port); FreeRem(MSeg -> Port . mp_Node . ln_Name); if(MSeg -> Segment) UnLoadSeg(MSeg -> Segment); FreeRem(MSeg); CloseLibrary(MXMBase); exit(20); } else { if(From_CLI) Printf("initializing, "); InvertKey(NULL,NULL,IK_USEIKM | IK_BUILDLIST,NULL); if(From_CLI) Puts("Okay."); else PopRequest(NULL,"KeyMacro Info:","\33[1mKeyMacro\33[0m installed.",NULL,"Continue?",FALSE,NULL); Created = TRUE; } } } } if(UpdateList(FileName)) { if(Created) { MSeg -> NumMacros = MAXMACROS; MSeg -> MacroList = KeyList; } else { struct MacroMessage UpdateMsg; UpdateMsg . mm_Type = MM_UPDATE; UpdateMsg . mm_NumMacros= MAXMACROS; UpdateMsg . mm_MacroList= KeyList; SendCustomMsg(&UpdateMsg); if(From_CLI) Printf("\33[1mKeyMacro:\33[0m Updating macro keys...\n"); } } else { CloseLibrary(MXMBase); exit(10); } CloseLibrary(MXMBase); }