/**************************************************************************** * * KeyMacro.c ------------ KeyMacro main process. * * 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. * ****************************************************************************/ /* Buffered IO include. */ #include "MRArpFile.h" /* Function prototypes. */ VOID CalcDimensions(UBYTE *cd_String,LONG *cd_Width,LONG *cd_Height,LONG cd_MaxWidth); LONG MovePointer(struct Screen *mp_Screen,LONG mp_Button,LONG mp_X,LONG mp_Y); LONG WriteConsole(struct Window *wc_Window,UBYTE *wc_String); VOID EraseGadget(struct RastPort *RPort,struct Gadget *Gadget,LONG Colour); BYTE PopRequest(struct Window *pr_ParentWindow,UBYTE *pr_TitleText,UBYTE *pr_BodyText,UBYTE *pr_PosText,UBYTE *pr_NegText,LONG pr_Default); UBYTE * GetToken(UBYTE *s,LONG *start); struct MacroKey * AddMacroKey(struct MacroKey *MacroKey); BYTE Interprete(UBYTE *String,LONG Line); BYTE UpdateList(char *Name); BYTE GetDefaultKeyMap(VOID); BYTE UStrCmp(UBYTE *a,UBYTE *b); VOID * SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port); VOID * AllocRem(LONG ByteSize,LONG Requirements); VOID * FreeRem(LONG *MemoryBlock); ULONG InvertKeyMap(ULONG ansicode,struct InputEvent *ie,struct KeyMap *km); VOID main(int argc,char **argv); /* The Arp CLI-Interface data. */ char *CLI_Template = "Startup,Q=Quit/s,I=Info/s"; char *CLI_Help = "\nUsage: \33[1mKeyMacro\33[0m [Quit] [Info]\n"; #define ARG_STARTUP 1 #define ARG_QUIT 2 #define ARG_INFO 3 #define ARG_UPDATE 4 /* Easy macro. */ #define From_CLI (ThatsMe -> pr_CLI) /* Global and shared data structures. */ extern struct ExecBase *SysBase; extern struct IntuitionBase *IntuitionBase; struct MSeg *MSeg; struct MacroKey *KeyList; /* We use this list to identify the non-ascii keys. */ 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} }; /* These are the qualifiers. */ 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} }; /* Our current version tag. */ const char *VersionTag = "$VER: KeyMacro 1.6 (09 Sep 1990)\n\r"; /* UStrCmp(): * * strcmp function which ignores case. */ BYTE UStrCmp(UBYTE *a,UBYTE *b) { for( ; ToUpper(*a) == ToUpper(*b) ; a++, b++) { if(!(*a)) return(0); } return(1); } /* CalcDimensions(): * * Calculate width and height for text string. */ VOID CalcDimensions(UBYTE *cd_String,LONG *cd_Width,LONG *cd_Height,LONG cd_MaxWidth) { LONG i,cd_InLine = 0,cd_NumLines = 0; *cd_Width = *cd_Height = 0; for(i = 0 ; i < strlen(cd_String) ; i++) { if(cd_String[i] == '\n' || cd_InLine == cd_MaxWidth) { if(cd_InLine > *cd_Width) *cd_Width = cd_InLine; cd_NumLines++; cd_InLine = 0; continue; } if(cd_String[i] == '\33') { while(cd_String[i] != 'm' && cd_String[i] != 'w' && i < strlen(cd_String)) i++; if(i >= strlen(cd_String)) i = strlen(cd_String) - 1; continue; } if(cd_String[i] < ' ') continue; cd_InLine++; } *cd_Height = cd_NumLines; if(cd_InLine > *cd_Width) *cd_Width = cd_InLine; } /* MovePointer(): * * Move the mouse pointer to a given position on a * screen. */ LONG MovePointer(struct Screen *mp_Screen,LONG mp_Button,LONG mp_X,LONG mp_Y) { STATIC struct InputEvent mp_StaticEvent = { NULL, IECLASS_POINTERPOS, 0, IECODE_NOBUTTON, 0,0,0,0 }; struct MsgPort *mp_InputPort; struct IOStdReq *mp_InputRequest; struct InputEvent *mp_FakeEvent; LONG mp_Success = FALSE; if(mp_InputPort = (struct MsgPort *)CreatePort(NULL,0)) { if(mp_InputRequest = (struct IOStdReq *)CreateStdIO(mp_InputPort)) { if(!OpenDevice("input.device",0,mp_InputRequest,0)) { if(mp_FakeEvent = (struct InputEvent *)AllocPub(sizeof(struct InputEvent))) { CopyMem(&mp_StaticEvent,mp_FakeEvent,sizeof(struct InputEvent)); mp_InputRequest -> io_Command = IND_WRITEEVENT; mp_InputRequest -> io_Flags = 0; mp_InputRequest -> io_Length = sizeof(struct InputEvent); mp_InputRequest -> io_Data = (APTR)mp_FakeEvent; mp_FakeEvent -> ie_X = mp_X; mp_FakeEvent -> ie_Y = mp_Y; if(!(mp_Screen -> ViewPort . Modes & HIRES)) mp_FakeEvent -> ie_X *= 2; if(!(mp_Screen -> ViewPort . Modes & LACE)) mp_FakeEvent -> ie_Y *= 2; mp_FakeEvent -> ie_Y += (2 * mp_Screen -> TopEdge); if(mp_Button) mp_FakeEvent -> ie_Code = IECODE_LBUTTON; DoIO(mp_InputRequest); if(mp_Button) { mp_FakeEvent -> ie_Code = IECODE_LBUTTON | IECODE_UP_PREFIX; DoIO(mp_InputRequest); } mp_Success = TRUE; FreeRem(mp_FakeEvent); } CloseDevice(mp_InputRequest); } DeleteStdIO(mp_InputRequest); } DeletePort(mp_InputPort); } return(mp_Success); } /* WriteConsole(): * * Write a string to a window using the console.device. */ LONG WriteConsole(struct Window *wc_Window,UBYTE *wc_String) { struct IOStdReq *wc_ConWrite; struct MsgPort *wc_ConPort; LONG wc_Success = FALSE; if(wc_ConPort = (struct MsgPort *)CreatePort(NULL,0)) { if(wc_ConWrite = (struct IOStdReq *)CreateStdIO(wc_ConPort)) { wc_ConWrite -> io_Data = (APTR)wc_Window; wc_ConWrite -> io_Length = sizeof(struct Window); if(!OpenDevice("console.device",0,wc_ConWrite,0)) { wc_ConWrite -> io_Command = CMD_WRITE; wc_ConWrite -> io_Data = (APTR)"\2330 p"; wc_ConWrite -> io_Length = -1; DoIO(wc_ConWrite); wc_ConWrite -> io_Data = (APTR)wc_String; wc_ConWrite -> io_Length = -1; DoIO(wc_ConWrite); wc_Success = TRUE; CloseDevice(wc_ConWrite); } DeleteStdIO(wc_ConWrite); } DeletePort(wc_ConPort); } return(wc_Success); } /* EraseGadget(): * * Erase the background of a gadget. */ VOID EraseGadget(struct RastPort *RPort,struct Gadget *Gadget,LONG Colour) { BYTE FgPen = RPort -> FgPen; SetAPen(RPort,Colour); RectFill(RPort,Gadget -> LeftEdge,Gadget -> TopEdge,Gadget -> LeftEdge + Gadget -> Width - 1,Gadget -> TopEdge + Gadget -> Height - 1); SetAPen(RPort,FgPen); } /* PopRequest(): * * Display a pop-up requester. */ BYTE PopRequest(struct Window *pr_ParentWindow,UBYTE *pr_TitleText,UBYTE *pr_BodyText,UBYTE *pr_PosText,UBYTE *pr_NegText,LONG pr_Default) { STATIC struct NewWindow pr_StaticNewWindow = { 0,0, 0,1, 0,1, VANILLAKEY | MOUSEBUTTONS | GADGETUP | CLOSEWINDOW, RMBTRAP | WINDOWDRAG | WINDOWDEPTH, (struct Gadget *)NULL, (struct Image *)NULL, (STRPTR)NULL, (struct Screen *)NULL, (struct BitMap *)NULL, 0,0, 0,0, WBENCHSCREEN }; STATIC struct Gadget pr_StaticGadget = { (struct Gadget *)NULL, 0,0, 0,0, GADGHBOX, RELVERIFY | GADGIMMEDIATE, BOOLGADGET, (APTR)NULL, (APTR)NULL, (struct IntuiText *)NULL, NULL, (APTR)NULL, 0, (APTR)NULL }; STATIC struct TextAttr pr_TextAttr = { (UBYTE *)"topaz.font", 8, FS_NORMAL, FPF_ROMFONT }; struct NewWindow *pr_NewWindow; struct Window *pr_Window; struct IntuiMessage *pr_IMsg; struct Gadget *pr_PosGadget = NULL,*pr_NegGadget = NULL,*pr_TempGadget; struct Screen pr_Screen,*pr_FrontScreen; struct TextFont *pr_TextFont; LONG pr_Width,pr_Height; LONG pr_Result = FALSE; LONG pr_TickCount = 0; ULONG pr_IntuiLock; if(!pr_BodyText) return(pr_Result); if(!(pr_NewWindow = (struct NewWindow *)AllocRem(sizeof(struct NewWindow),MEMF_PUBLIC))) return(pr_Result); CopyMem(&pr_StaticNewWindow,pr_NewWindow,sizeof(struct NewWindow)); pr_IntuiLock = LockIBase(NULL); pr_FrontScreen = IntuitionBase -> FirstScreen; UnlockIBase(pr_IntuiLock); if(pr_ParentWindow) { pr_NewWindow -> Type = CUSTOMSCREEN; pr_NewWindow -> Screen = pr_ParentWindow -> WScreen; } else OpenWorkBench(); if(!GetScreenData(&pr_Screen,sizeof(struct Screen),pr_NewWindow -> Type,pr_NewWindow -> Screen)) { FreeRem(pr_NewWindow); return(pr_Result); } CalcDimensions(pr_BodyText,&pr_Width,&pr_Height,(pr_Screen . Width - 6) / 8); if(pr_Height > (pr_Screen . Height - 15 - 13) / 8) { FreeRem(pr_NewWindow); return(pr_Result); } pr_NewWindow -> Width = pr_Width * 8 + 6 + 4; pr_NewWindow -> Height = pr_Height * 8 + 15 + 19 + 2; if(pr_TitleText) pr_NewWindow -> Title = pr_TitleText; else pr_NewWindow -> Title = (UBYTE *)"System Request"; if(!pr_PosText && !pr_NegText) pr_NegText = (UBYTE *)"Okay"; if(pr_PosText) { if(!(pr_PosGadget = (struct Gadget *)AllocRem(sizeof(struct Gadget),MEMF_PUBLIC))) { FreeRem(pr_NewWindow); return(pr_Result); } CopyMem(&pr_StaticGadget,pr_PosGadget,sizeof(struct Gadget)); pr_PosGadget -> Width = 8 * strlen(pr_PosText) + 4; pr_PosGadget -> Height = 8 + 2; pr_PosGadget -> LeftEdge= 3 + 2 + 3; pr_PosGadget -> TopEdge = pr_NewWindow -> Height - 13 - 1; } if(pr_NegText) { if(!(pr_NegGadget = (struct Gadget *)AllocRem(sizeof(struct Gadget),MEMF_PUBLIC))) { FreeRem(pr_NewWindow); if(pr_PosGadget) FreeRem(pr_PosGadget); return(pr_Result); } CopyMem(&pr_StaticGadget,pr_NegGadget,sizeof(struct Gadget)); pr_NegGadget -> Width = 8 * strlen(pr_NegText) + 4; pr_NegGadget -> Height = 8 + 2; pr_Width = pr_NegGadget -> Width + 6 + 4 + 6; if(pr_PosGadget) pr_Width += (pr_PosGadget -> Width + 12); if(pr_NewWindow -> Width < pr_Width) pr_NewWindow -> Width = pr_Width; pr_NegGadget -> LeftEdge= pr_NewWindow -> Width - pr_NegGadget -> Width - 3 - 2 - 3; pr_NegGadget -> TopEdge = pr_NewWindow -> Height - 13 - 1; pr_NegGadget -> GadgetID= 1; } if(!pr_NegGadget && pr_NewWindow -> Width < pr_PosGadget -> Width + 6 + 4 + 6) pr_NewWindow -> Width = pr_PosGadget -> Width + 6 + 4 + 6; if(pr_Default && !pr_PosGadget) pr_Default = FALSE; if(!pr_Default && !pr_NegGadget) pr_Default = TRUE; if(pr_Default) pr_TempGadget = pr_PosGadget; else pr_TempGadget = pr_NegGadget; pr_NewWindow -> LeftEdge= pr_Screen . MouseX - (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2); pr_NewWindow -> TopEdge = pr_Screen . MouseY - (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2); while(pr_NewWindow -> LeftEdge < 0) pr_NewWindow -> LeftEdge++; while(pr_NewWindow -> TopEdge < 0) pr_NewWindow -> TopEdge++; while(pr_NewWindow -> LeftEdge + pr_NewWindow -> Width >= pr_Screen . Width) pr_NewWindow -> LeftEdge--; while(pr_NewWindow -> TopEdge + pr_NewWindow -> Height >= pr_Screen . Height) pr_NewWindow -> TopEdge--; if(!(pr_TextFont = (struct TextFont *)OpenFont(&pr_TextAttr))) { if(pr_PosGadget) FreeRem(pr_PosGadget); if(pr_NegGadget) FreeRem(pr_NegGadget); FreeRem(pr_NewWindow); return(pr_Result); } if(!(pr_Window = (struct Window *)OpenWindow(pr_NewWindow))) { CloseFont(pr_TextFont); if(pr_PosGadget) FreeRem(pr_PosGadget); if(pr_NegGadget) FreeRem(pr_NegGadget); FreeRem(pr_NewWindow); return(pr_Result); } SetFont(pr_Window -> RPort,pr_TextFont); WriteConsole(pr_Window,pr_BodyText); if(pr_PosGadget) { AddGadget(pr_Window,pr_PosGadget,1); EraseGadget(pr_Window -> RPort,pr_PosGadget,2); Move(pr_Window -> RPort,pr_PosGadget -> LeftEdge + 2,pr_PosGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline); Text(pr_Window -> RPort,pr_PosText,strlen(pr_PosText)); } if(pr_NegGadget) { AddGadget(pr_Window,pr_NegGadget,1); EraseGadget(pr_Window -> RPort,pr_NegGadget,2); Move(pr_Window -> RPort,pr_NegGadget -> LeftEdge + 2,pr_NegGadget -> TopEdge + 1 + pr_TextFont -> tf_Baseline); Text(pr_Window -> RPort,pr_NegText,strlen(pr_NegText)); } MoveScreen(pr_Window -> WScreen,0,- pr_Window -> WScreen -> TopEdge); ScreenToFront(pr_Window -> WScreen); ActivateWindow(pr_Window); MovePointer(pr_Window -> WScreen,FALSE, pr_Window -> LeftEdge + (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2), pr_Window -> TopEdge + (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2)); Skip1: FOREVER { ULONG pr_Class,pr_Code; struct Gadget *pr_Gadget; WaitPort(pr_Window -> UserPort); if(pr_IMsg = (struct IntuiMessage *)GetMsg(pr_Window -> UserPort)) { pr_Class = pr_IMsg -> Class; pr_Code = pr_IMsg -> Code; pr_Gadget = (struct Gadget *)pr_IMsg -> IAddress; if(pr_Class == VANILLAKEY) pr_Code = ToUpper(pr_Code); ReplyMsg(pr_IMsg); if(pr_Class == INTUITICKS) { if(pr_TickCount) pr_TickCount--; else { pr_Result = pr_Default; break; } continue; } if(pr_Class == INACTIVEWINDOW) { MoveScreen(pr_Window -> WScreen,0,- pr_Window -> WScreen -> TopEdge); ScreenToFront(pr_Window -> WScreen); ActivateWindow(pr_Window); continue; } if(pr_Class == GADGETUP) { if(pr_Gadget -> GadgetID == 0) pr_Result = TRUE; break; } if(pr_Class == CLOSEWINDOW) break; if(pr_Class == VANILLAKEY) { pr_Code = ToUpper(pr_Code); if((pr_Code == 'Y' || pr_Code == 'J' || pr_Code == 'V' || pr_Code == 'C' || pr_Code == 'R' || pr_Code == '\r') && pr_PosText) { pr_Result = TRUE; break; } if((pr_Code == 'N' || pr_Code == 'Q' || pr_Code == 'B' || pr_Code == '\33') && pr_NegText) break; continue; } if(pr_Class == MOUSEBUTTONS && pr_Code == MENUDOWN) { MovePointer(pr_Window -> WScreen,FALSE, pr_Window -> LeftEdge+ (pr_TempGadget -> LeftEdge + pr_TempGadget -> Width / 2), pr_Window -> TopEdge + (pr_TempGadget -> TopEdge + pr_TempGadget -> Height / 2)); } } } CloseFont(pr_TextFont); if(pr_PosGadget) { RemoveGadget(pr_Window,pr_PosGadget); FreeRem(pr_PosGadget); } if(pr_NegGadget) { RemoveGadget(pr_Window,pr_NegGadget); FreeRem(pr_NegGadget); } FreeRem(pr_NewWindow); pr_IntuiLock = LockIBase(NULL); if(pr_FrontScreen == IntuitionBase -> FirstScreen) pr_FrontScreen = NULL; UnlockIBase(pr_IntuiLock); if(pr_FrontScreen) ScreenToFront(pr_FrontScreen); CloseWindow(pr_Window); return(pr_Result); } /* GetToken(s,start): * * Parse a string and split it into single tokens. */ UBYTE * GetToken(UBYTE *s,LONG *start) { static UBYTE buffer[256]; LONG i,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); } /* AddMacroKey(MacroKey): * * Add a macro key to the big list. */ struct MacroKey * AddMacroKey(struct MacroKey *MacroKey) { struct MacroKey *TheKey = NULL; LONG i; for(i = 0 ; i < MAXMACROS ; i++) { if(KeyList[i] . mk_Type == MK_UNUSED) { TheKey = &KeyList[i]; break; } } if(!TheKey) return(NULL); CopyMem(MacroKey,TheKey,sizeof(struct MacroKey)); return(TheKey); } /* Interprete(String,Line): * * Interprete a command line from the config file. */ BYTE Interprete(UBYTE *String,LONG Line) { ULONG Qualifier = 0; ULONG Code = -1; struct InputEvent FakeEvent; struct MacroKey NewKey; LONG Start = 0,Key = FALSE,i,KeyCount = 0; volatile LONG QuitLoop; 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) { SPrintf(MessBuff,"Line %ld: Unknown keyword:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); 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) { SPrintf(MessBuff,"Line %ld: Didn't recognize qualifier:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); 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(InvertKeyMap(Token[0],&FakeEvent,MSeg -> DefaultKeyMap)) Code = FakeEvent . ie_Code; } if(Code == -1) { SPrintf(MessBuff,"Line %ld: Didn't recognize key:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); return(FALSE); } Next: FOREVER { if(Token = GetToken(String,&Start)) { if(!UStrCmp("=",Token)) break; } else { SPrintf(MessBuff,"Line %ld: Statement '=' missing:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); return(FALSE); } } if(Token = GetToken(String,&Start)) strcpy(KeyBuff1,Token); else { SPrintf(MessBuff,"Line %ld: Didn't find macro:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); return(FALSE); } if(Key) goto AddIt; if(!(Token = GetToken(String,&Start))) goto AddIt; if(UStrCmp("WINDOW",Token)) { SPrintf(MessBuff,"Line %ld: Didn't recognize 'WINDOW' statement:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); return(FALSE); } if(!(Token = GetToken(String,&Start))) { SPrintf(MessBuff,"Line %ld: Didn't find window title:\n\n'%s'",Line,String); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); return(FALSE); } if(!(WindowName = (UBYTE *)AllocRem(strlen(Token) + 1,MEMF_PUBLIC))) { PopRequest(NULL,"KeyMacro Problem:","Can't allocate memory chunk!",NULL,"Continue?",FALSE); 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); FreeRem(WindowName); return(FALSE); } strcpy(CommandString,KeyBuff2); memset(&NewKey,0,sizeof(struct MacroKey)); 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); SPrintf(MessBuff,"Line %ld: Key macro table full.",Line); PopRequest(NULL,"KeyMacro Problem:",MessBuff,NULL,"Continue?",FALSE); return(FALSE); } /* UpdateList(Name): * * Update the big macro key list. */ BYTE UpdateList(char *Name) { char LineBuff[257]; LONG LineNum = 1; ARPFileHandle *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); return(FALSE); } GetDefaultKeyMap(); if(ConfigFile = OpenARPFile(Name,MODE_OLDFILE,976)) { while(FGetsARP(LineBuff,256,ConfigFile)) { if(!Interprete(LineBuff,LineNum++)) { CloseARPFile(ConfigFile); FreeRem(KeyList); return(FALSE); } } CloseARPFile(ConfigFile); } else { PopRequest(NULL,"KeyMacro Problem:","Couldn't open configuration file!",NULL,"Continue?",FALSE); FreeRem(KeyList); return(FALSE); } return(TRUE); } BYTE GetDefaultKeyMap() { struct IOStdReq *ConsoleRequest; struct MsgPort *ConsolePort; BYTE Result = FALSE; if(ConsolePort = CreatePort(NULL,0)) { if(ConsoleRequest = CreateStdIO(ConsolePort)) { if(!OpenDevice("console.device",CONU_STANDARD,ConsoleRequest,0)) { ConsoleRequest -> io_Command = CD_ASKDEFAULTKEYMAP; ConsoleRequest -> io_Length = sizeof(struct KeyMap); ConsoleRequest -> io_Data = (APTR)MSeg -> DefaultKeyMap; ConsoleRequest -> io_Flags = IOF_QUICK; if(!DoIO(ConsoleRequest)) Result = TRUE; CloseDevice(ConsoleRequest); } DeleteStdIO(ConsoleRequest); } DeletePort(ConsolePort); } return(Result); } /* main(argc,argv): * * The entry point to this program. */ VOID main(int argc,char **argv) { struct Process *ThatsMe = (struct Process *)SysBase -> ThisTask; char *FileName = argv[ARG_STARTUP]; LONG Created = FALSE; LONG i; /* No ^C trapping, please. */ Enable_Abort = FALSE; /* Started from Workbench? */ if(!From_CLI) FileName = NULL; /* Look if handler process is already running. */ MSeg = (struct MSeg *)FindPort(PORTNAME); /* Short info? */ 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(" redistributed!\n\n"); Printf("\33[1m\33[33mAuthor\33[31m\33[0m - Olaf Barthel, MXM\n"); Printf(" Brabeckstrasse 35\n"); Printf(" D-3000 Hannover 71\n\n"); Printf(" Federal Republic of Germany.\n\n"); exit(RETURN_OK); } /* Remove the handler? */ if(argv[ARG_QUIT]) { Printf("Removing \33[1m\33[33mKeyMacro\33[31m\33[0m, "); if(!MSeg) { Printf("failed!\a\n"); exit(RETURN_OK); } MSeg -> Father = (struct Task *)SysBase -> ThisTask; if(MSeg -> Child) { Signal(MSeg -> Child,SIG_CLOSE); Wait(SIG_CLOSE); } RemPort(&MSeg -> Port); FreeMem(MSeg -> Port . mp_Node . ln_Name,sizeof(PORTNAME)); if(MSeg -> Segment) UnLoadPrg(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 -> DefaultKeyMap); FreeRem(MSeg); Printf("OK.\n"); exit(RETURN_OK); } /* Allocate the handler data. */ 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 = AllocMem(sizeof(PORTNAME),MEMF_PUBLIC); MSeg -> Child = NULL; MSeg -> Father = (struct Task *)SysBase -> ThisTask; 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© Copyright 1989, 1990 by \33[4mMXM\33[0m, All rights reserved.\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 { Failed: FreeRem(MSeg); if(From_CLI) Printf("failed!\a\n"); exit(RETURN_FAIL); } if(!(MSeg -> DefaultKeyMap = (struct KeyMap *)AllocPub(sizeof(struct KeyMap)))) goto Failed; if(!(MSeg -> Segment = LoadPrg("KeyMacro-Handler"))) MSeg -> Segment = LoadPrg("L:KeyMacro-Handler"); if(!MSeg -> Segment) { if(From_CLI) Printf("unable to find \33[33mL:KeyMacro-Handler\33[31m\a!\n"); FreeRem(MSeg -> DefaultKeyMap); FreeRem(MSeg -> Port . mp_Node . ln_Name); FreeRem(MSeg); } else { AddPort(&MSeg -> Port); if(!CreateProc("KeyMacro-Handler",10,MSeg -> Segment,4096)) goto NoMem; Wait(SIGBREAKF_CTRL_C); if(!MSeg -> Child) { NoMem: if(From_CLI) Printf("\33[33mFAILED!\33[31m (care to retry?)\n"); RemPort(&MSeg -> Port); FreeRem(MSeg -> DefaultKeyMap); FreeRem(MSeg -> Port . mp_Node . ln_Name); if(MSeg -> Segment) UnLoadPrg(MSeg -> Segment); FreeRem(MSeg); exit(RETURN_FAIL); } else { if(From_CLI) Printf("initializing, "); GetDefaultKeyMap(); if(From_CLI) Puts("Okay."); else PopRequest(NULL,"KeyMacro Info:","\33[1mKeyMacro\33[0m installed.",NULL,"Continue?",FALSE); Created = TRUE; } } } } /* Update the macro key list. */ 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; SendMacroMsg(&UpdateMsg,&MSeg -> Port); if(From_CLI) Printf("\33[1mKeyMacro:\33[0m Updating macro keys...\n"); } } else exit(RETURN_ERROR); exit(RETURN_OK); }