#include #include #include #include #include #include #include "fvwm.h" #include "menus.h" #include "misc.h" #include "parse.h" #include "screen.h" #include "module.h" struct charstring { char key; int value; }; /* The keys must be in lower case! */ struct charstring win_contexts[]= { {'w',C_WINDOW}, {'t',C_TITLE}, {'i',C_ICON}, {'r',C_ROOT}, {'f',C_FRAME}, {'s',C_SIDEBAR}, {'1',C_L1}, {'2',C_R1}, {'3',C_L2}, {'4',C_R2}, {'5',C_L3}, {'6',C_R3}, {'7',C_L4}, {'8',C_R4}, {'9',C_L5}, {'0',C_R5}, {'a',C_WINDOW|C_TITLE|C_ICON|C_ROOT|C_FRAME|C_SIDEBAR| C_L1|C_L2|C_L3|C_L4|C_L5|C_R1|C_R2|C_R3|C_R4|C_R5}, {0,0} }; /* The keys musat be in lower case! */ struct charstring key_modifiers[]= { {'s',ShiftMask}, {'c',ControlMask}, {'m',Mod1Mask}, {'1',Mod1Mask}, {'2',Mod2Mask}, {'3',Mod3Mask}, {'4',Mod4Mask}, {'5',Mod5Mask}, {'a',AnyModifier}, {'n',0}, {0,0} }; void find_context(char *string, int *output, struct charstring *table, char *tline); /**************************************************************************** * * to remove a binding from the global list (probably needs more processing * for mouse binding lines though, like when context is a title bar button). * ****************************************************************************/ void remove_binding(int contexts, int mods, int button, KeySym keysym, int mouse_binding) { Binding *temp = Scr.AllBindings, *temp2, *prev = NULL; KeyCode keycode; if (!mouse_binding) keycode = XKeysymToKeycode(dpy, keysym); while (temp) { temp2 = temp->NextBinding; if (temp->IsMouse == mouse_binding) { if ((temp->Button_Key == ((mouse_binding)?(button):(keycode))) && (temp->Context == contexts) && (temp->Modifier == mods)) { /* we found it, remove it from list */ if (prev) /* middle of list */ prev->NextBinding = temp2; else /* must have been first one, set new start */ Scr.AllBindings = temp2; free(temp); temp = NULL; } } if (temp) prev = temp; temp = temp2; } } /**************************************************************************** * * Parses a mouse binding - probably should combine w/ ParseKeyEntry to save * some more memory (CKH) * ****************************************************************************/ void ParseMouseEntry(XEvent *eventp,Window w,FvwmWindow *tmp_win, unsigned long junk, char *tline,int* Module) { char context[20],modifiers[20],*ptr,*action,*token; Binding *temp; int button,i,j; int n1=0,n2=0,n3=0; int contexts; int mods; /* tline points after the key word "Mouse" */ ptr = tline; ptr = GetNextToken(ptr,&token); if(token != NULL) { n1 = sscanf(token,"%d",&button); free(token); } ptr = GetNextToken(ptr,&token); if(token != NULL) { n2 = sscanf(token,"%19s",context); free(token); } action = GetNextToken(ptr,&token); if(token != NULL) { n3 = sscanf(token,"%19s",modifiers); free(token); } if((n1 != 1)||(n2 != 1)||(n3 != 1)) { fvwm_msg(ERR,"ParseMouseEntry","Mouse binding: Syntax error in line %s", tline); return; } find_context(context, &contexts, win_contexts, tline); find_context(modifiers, &mods, key_modifiers, tline); /* strip leading whitespace from action if necessary */ while (*action && (*action == ' ' || *action == '\t')) action++; /* is this an unbind request? */ if (!action || action[0] == '-') { remove_binding(contexts, mods, button, 0, 1); return; } if((contexts != C_ALL) && (contexts & C_LALL)) { /* check for nr_left_buttons */ i=0; j=(contexts &C_LALL)/C_L1; while(j>0) { i++; j=j>>1; } if (Scr.nr_left_buttons < i) Scr.nr_left_buttons = i; } if((contexts != C_ALL) && (contexts & C_RALL)) { /* check for nr_right_buttons */ i=0; j=(contexts&C_RALL)/C_R1; while(j>0) { i++; j=j>>1; } if(Scr.nr_right_buttons < i) Scr.nr_right_buttons = i; } if((mods & AnyModifier)&&(mods&(~AnyModifier))) { fvwm_msg(WARN,"ParseMouseEntry", "Binding specified AnyModifier and other modifers too. Excess modifiers will be ignored."); } if((contexts & C_WINDOW)&&(((mods==0)||mods == AnyModifier))) { Scr.buttons2grab &= ~(1<<(button-1)); } temp = Scr.AllBindings; Scr.AllBindings = (Binding *)safemalloc(sizeof(Binding)); Scr.AllBindings->IsMouse = 1; Scr.AllBindings->Button_Key = button; Scr.AllBindings->key_name = NULL; Scr.AllBindings->Context = contexts; Scr.AllBindings->Modifier = mods; Scr.AllBindings->Action = stripcpy(action); Scr.AllBindings->NextBinding = temp; return; } /**************************************************************************** * * Processes a line with a key binding * ****************************************************************************/ void ParseKeyEntry(XEvent *eventp,Window w,FvwmWindow *tmp_win, unsigned long junk, char *tline,int* Module) { char *action,context[20],modifiers[20],key[20],*ptr, *token; Binding *temp; int i,min,max; int n1=0,n2=0,n3=0; KeySym keysym; int contexts; int mods; /* tline points after the key word "key" */ ptr = tline; ptr = GetNextToken(ptr,&token); if(token != NULL) { n1 = sscanf(token,"%19s",key); free(token); } ptr = GetNextToken(ptr,&token); if(token != NULL) { n2 = sscanf(token,"%19s",context); free(token); } action = GetNextToken(ptr,&token); if(token != NULL) { n3 = sscanf(token,"%19s",modifiers); free(token); } if((n1 != 1)||(n2 != 1)||(n3 != 1)) { fvwm_msg(ERR,"ParseKeyEntry","Syntax error in line %s",tline); return; } find_context(context,&contexts,win_contexts,tline); find_context(modifiers,&mods,key_modifiers,tline); /* * Don't let a 0 keycode go through, since that means AnyKey to the * XGrabKey call in GrabKeys(). */ if ((keysym = XStringToKeysym(key)) == NoSymbol || (XKeysymToKeycode(dpy, keysym)) == 0) return; /* strip leading whitespace from action if necessary */ while (*action && (*action == ' ' || *action == '\t')) action++; /* is this an unbind request? */ if (!action || action[0] == '-') { remove_binding(contexts,mods,0,keysym,0); return; } if((mods & AnyModifier)&&(mods&(~AnyModifier))) { fvwm_msg(WARN,"ParseKeyEntry", "Binding specified AnyModifier and other modifers too. Excess modifiers will be ignored."); } /* why wasn't XKeysymToKeycode used instead of this for loop? */ XDisplayKeycodes(dpy, &min, &max); for (i=min; i<=max; i++) if (XKeycodeToKeysym(dpy, i, 0) == keysym) { temp = Scr.AllBindings; Scr.AllBindings = (Binding *)safemalloc(sizeof(Binding)); Scr.AllBindings->IsMouse = 0; Scr.AllBindings->Button_Key = i; Scr.AllBindings->key_name = stripcpy(key);; Scr.AllBindings->Context = contexts; Scr.AllBindings->Modifier = mods; Scr.AllBindings->Action = stripcpy(action); Scr.AllBindings->NextBinding = temp; } return; } /**************************************************************************** * * Turns a string context of context or modifier values into an array of * true/false values (bits) * ****************************************************************************/ void find_context(char *string, int *output, struct charstring *table, char *tline) { int i=0,j=0; Bool matched; char tmp1; *output=0; i=0; while(i