+update_modkey(unsigned int mod)
+{
+ int i;
+
+ mod_key = mod;
+ for (i = 0; i < keys_length; i++)
+ if (keys[i].mod & ShiftMask)
+ keys[i].mod = mod | ShiftMask;
+ else
+ keys[i].mod = mod;
+
+ for (i = 0; i < LENGTH(buttons); i++)
+ if (buttons[i].mask & ShiftMask)
+ buttons[i].mask = mod | ShiftMask;
+ else
+ buttons[i].mask = mod;
+}
+
+#define SWM_MODNAME_SIZE 32
+#define SWM_KEY_WS "\n+ \t"
+int
+parsekeys(char *keystr, unsigned int currmod, unsigned int *mod, KeySym *ks)
+{
+ char *cp, *name;
+ KeySym uks;
+ if (mod == NULL || ks == NULL)
+ return (0);
+ cp = keystr;
+ *mod = 0;
+ while ((name = strsep(&cp, SWM_KEY_WS)) != NULL) {
+ if (cp)
+ cp += (long)strspn(cp, SWM_KEY_WS);
+ if (strncasecmp(name, "MOD", SWM_MODNAME_SIZE) == 0)
+ *mod |= currmod;
+ else if (!strncasecmp(name, "Mod1", SWM_MODNAME_SIZE))
+ *mod |= Mod1Mask;
+ else if (!strncasecmp(name, "Mod2", SWM_MODNAME_SIZE))
+ *mod += Mod2Mask;
+ else if (!strncmp(name, "Mod3", SWM_MODNAME_SIZE))
+ *mod |= Mod3Mask;
+ else if (!strncmp(name, "Mod4", SWM_MODNAME_SIZE))
+ *mod |= Mod4Mask;
+ else if (strncasecmp(name, "SHIFT", SWM_MODNAME_SIZE) == 0)
+ *mod |= ShiftMask;
+ else if (strncasecmp(name, "CONTROL", SWM_MODNAME_SIZE) == 0)
+ *mod |= ControlMask;
+ else {
+ *ks = XStringToKeysym(name);
+ XConvertCase(*ks, ks, &uks);
+ if (ks == NoSymbol) {
+ DNPRINTF(SWM_D_KEY,
+ "parsekeys: invalid key %s\n",
+ name);
+ return (0);
+ }
+ }
+ }
+ return (1);
+}
+void
+setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid)
+{
+ int i, j;
+ /* find existing */
+ for (i = 0; i < keys_length; i++) {
+ if (keys[i].mod == mod && keys[i].keysym == ks) {
+ if (kfid == kf_invalid) {
+ /* found: delete */
+ DNPRINTF(SWM_D_KEY,
+ "setkeybinding: delete #%d %s\n",
+ i, keyfuncs[keys[i].funcid].name);
+ j = keys_length - 1;
+ if (i < j)
+ keys[i] = keys[j];
+ keys_length--;
+ return;
+ } else {
+ /* found: replace */
+ DNPRINTF(SWM_D_KEY,
+ "setkeybinding: replace #%d %s\n",
+ i, keyfuncs[keys[i].funcid].name);
+ keys[i].mod = mod;
+ keys[i].keysym = ks;
+ keys[i].funcid = kfid;
+ return;
+ }
+ }
+ }
+ if (kfid == kf_invalid) {
+ fprintf(stderr,
+ "error: setkeybinding: cannot find mod/key combination");
+ return;
+ }
+ /* not found: add */
+ if (keys_size == 0 || keys == NULL) {
+ keys_size = 4;
+ DNPRINTF(SWM_D_KEY, "setkeybinding: init list %d\n", keys_size);
+ keys = malloc((size_t)keys_size * sizeof(struct key));
+ if (!keys) {
+ fprintf(stderr, "malloc failed\n");
+ perror(" failed");
+ quit(NULL, NULL);
+ }
+ } else if (keys_length == keys_size) {
+ keys_size *= 2;
+ DNPRINTF(SWM_D_KEY, "setkeybinding: grow list %d\n", keys_size);
+ keys = realloc(keys, (size_t)keys_size * sizeof(struct key));
+ if (!keys) {
+ fprintf(stderr, "realloc failed\n");
+ perror(" failed");
+ quit(NULL, NULL);
+ }
+ }
+ if (keys_length < keys_size) {
+ DNPRINTF(SWM_D_KEY, "setkeybinding: add %d\n", keys_length);
+ j = keys_length++;
+ keys[j].mod = mod;
+ keys[j].keysym = ks;
+ keys[j].funcid = kfid;
+ } else {
+ fprintf(stderr, "keys array problem?\n");
+ if (!keys) {
+ fprintf(stderr, "keys array problem\n");
+ quit(NULL, NULL);
+ }
+ }
+}
+int
+setconfbinding(char *selector, char *value, int flags)
+{
+ enum keyfuncid kfid;
+ unsigned int mod;
+ KeySym ks;
+ for (kfid = 0; kfid < kf_invalid; (kfid)++) {
+ if (strncasecmp(selector, keyfuncs[kfid].name,
+ SWM_FUNCNAME_LEN) == 0) {
+ if (parsekeys(value, mod_key, &mod, &ks))
+ setkeybinding(mod, ks, kfid);
+ else
+ return (0);
+ }
+
+ }
+ return (1);
+}
+void
+setup_keys(void)
+{
+ setkeybinding(MODKEY, XK_space, kf_cycle_layout);
+ setkeybinding(MODKEY|ShiftMask, XK_space, kf_stack_reset);
+ setkeybinding(MODKEY, XK_h, kf_master_shrink);
+ setkeybinding(MODKEY, XK_l, kf_master_grow);
+ setkeybinding(MODKEY, XK_comma, kf_master_add);
+ setkeybinding(MODKEY, XK_period, kf_master_del);
+ setkeybinding(MODKEY|ShiftMask, XK_comma, kf_stack_inc);
+ setkeybinding(MODKEY|ShiftMask, XK_period, kf_stack_dec);
+ setkeybinding(MODKEY, XK_Return, kf_swap_main);
+ setkeybinding(MODKEY, XK_j, kf_focus_next);
+ setkeybinding(MODKEY, XK_k, kf_focus_prev);
+ setkeybinding(MODKEY|ShiftMask, XK_j, kf_swap_next);
+ setkeybinding(MODKEY|ShiftMask, XK_k, kf_swap_prev);
+ setkeybinding(MODKEY|ShiftMask, XK_Return, kf_spawn_term);
+ setkeybinding(MODKEY, XK_p, kf_spawn_menu);
+ setkeybinding(MODKEY|ShiftMask, XK_q, kf_quit);
+ setkeybinding(MODKEY, XK_q, kf_restart);
+ setkeybinding(MODKEY, XK_m, kf_focus_main);
+ setkeybinding(MODKEY, XK_1, kf_ws_1);
+ setkeybinding(MODKEY, XK_2, kf_ws_2);
+ setkeybinding(MODKEY, XK_3, kf_ws_3);
+ setkeybinding(MODKEY, XK_4, kf_ws_4);
+ setkeybinding(MODKEY, XK_5, kf_ws_5);
+ setkeybinding(MODKEY, XK_6, kf_ws_6);
+ setkeybinding(MODKEY, XK_7, kf_ws_7);
+ setkeybinding(MODKEY, XK_8, kf_ws_8);
+ setkeybinding(MODKEY, XK_9, kf_ws_9);
+ setkeybinding(MODKEY, XK_0, kf_ws_10);
+ setkeybinding(MODKEY, XK_Right, kf_ws_next);
+ setkeybinding(MODKEY, XK_Left, kf_ws_prev);
+ setkeybinding(MODKEY|ShiftMask, XK_Right, kf_screen_next);
+ setkeybinding(MODKEY|ShiftMask, XK_Left, kf_screen_prev);
+ setkeybinding(MODKEY|ShiftMask, XK_1, kf_mvws_1);
+ setkeybinding(MODKEY|ShiftMask, XK_2, kf_mvws_2);
+ setkeybinding(MODKEY|ShiftMask, XK_3, kf_mvws_3);
+ setkeybinding(MODKEY|ShiftMask, XK_4, kf_mvws_4);
+ setkeybinding(MODKEY|ShiftMask, XK_5, kf_mvws_5);
+ setkeybinding(MODKEY|ShiftMask, XK_6, kf_mvws_6);
+ setkeybinding(MODKEY|ShiftMask, XK_7, kf_mvws_7);
+ setkeybinding(MODKEY|ShiftMask, XK_8, kf_mvws_8);
+ setkeybinding(MODKEY|ShiftMask, XK_9, kf_mvws_9);
+ setkeybinding(MODKEY|ShiftMask, XK_0, kf_mvws_10);
+ setkeybinding(MODKEY, XK_b, kf_bar_toggle);
+ setkeybinding(MODKEY, XK_Tab, kf_focus_next);
+ setkeybinding(MODKEY|ShiftMask, XK_Tab, kf_focus_prev);
+ setkeybinding(MODKEY|ShiftMask, XK_x, kf_wind_kill);
+ setkeybinding(MODKEY, XK_x, kf_wind_del);
+ setkeybinding(MODKEY, XK_s, kf_screenshot_all);
+ setkeybinding(MODKEY|ShiftMask, XK_s, kf_screenshot_wind);
+ setkeybinding(MODKEY, XK_t, kf_float_toggle);
+ setkeybinding(MODKEY|ShiftMask, XK_v, kf_version);
+ setkeybinding(MODKEY|ShiftMask, XK_Delete, kf_spawn_lock);
+ setkeybinding(MODKEY|ShiftMask, XK_i, kf_spawn_initscr);
+}
+void