From 1f8f19b4d50f59624e84a3c932b639670e0d8b27 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 29 Jan 2014 18:34:22 +0000 Subject: [PATCH 1/5] Check command name/path for truncation and provide user feedback during config parse (and use conf_cmd_add to populate defaults); based on a discussion with Tiago Cunha. While this looks ugly, there are likely some other changes here to come. --- calmwm.h | 2 +- conf.c | 36 +++++++++++++++++++++++------------- parse.y | 7 ++++++- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/calmwm.h b/calmwm.h index 4ea482e..389c269 100644 --- a/calmwm.h +++ b/calmwm.h @@ -522,7 +522,7 @@ int conf_bind_mouse(struct conf *, const char *, const char *); void conf_clear(struct conf *); void conf_client(struct client_ctx *); -void conf_cmd_add(struct conf *, const char *, +int conf_cmd_add(struct conf *, const char *, const char *); void conf_cursor(struct conf *); void conf_grab_kbd(Window); diff --git a/conf.c b/conf.c index 9ecf1b4..8f067d0 100644 --- a/conf.c +++ b/conf.c @@ -35,21 +35,32 @@ static const char *conf_bind_getmask(const char *, unsigned int *); static void conf_unbind_kbd(struct conf *, struct keybinding *); static void conf_unbind_mouse(struct conf *, struct mousebinding *); -/* Add an command menu entry to the end of the menu */ -void +int conf_cmd_add(struct conf *c, const char *name, const char *path) { + struct cmd *cmd; + /* "term" and "lock" have special meanings. */ - if (strcmp(name, "term") == 0) - (void)strlcpy(c->termpath, path, sizeof(c->termpath)); - else if (strcmp(name, "lock") == 0) - (void)strlcpy(c->lockpath, path, sizeof(c->lockpath)); - else { - struct cmd *cmd = xmalloc(sizeof(*cmd)); - (void)strlcpy(cmd->name, name, sizeof(cmd->name)); - (void)strlcpy(cmd->path, path, sizeof(cmd->path)); + if (strcmp(name, "term") == 0) { + if (strlcpy(c->termpath, path, sizeof(c->termpath)) >= + sizeof(c->termpath)) + return (0); + } else if (strcmp(name, "lock") == 0) { + if (strlcpy(c->lockpath, path, sizeof(c->lockpath)) >= + sizeof(c->lockpath)) + return (0); + } else { + cmd = xmalloc(sizeof(*cmd)); + + if (strlcpy(cmd->name, name, sizeof(cmd->name)) >= + sizeof(cmd->name)) + return (0); + if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= + sizeof(cmd->path)) + return (0); TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry); } + return (1); } void @@ -249,9 +260,8 @@ conf_init(struct conf *c) for (i = 0; i < nitems(color_binds); i++) c->color[i] = xstrdup(color_binds[i]); - /* Default term/lock */ - (void)strlcpy(c->termpath, "xterm", sizeof(c->termpath)); - (void)strlcpy(c->lockpath, "xlock", sizeof(c->lockpath)); + conf_cmd_add(c, "lock", "xlock"); + conf_cmd_add(c, "term", "xterm"); (void)snprintf(c->known_hosts, sizeof(c->known_hosts), "%s/%s", homedir, ".ssh/known_hosts"); diff --git a/parse.y b/parse.y index 672a896..fb8c01e 100644 --- a/parse.y +++ b/parse.y @@ -137,7 +137,12 @@ main : FONTNAME STRING { conf->snapdist = $2; } | COMMAND STRING string { - conf_cmd_add(conf, $2, $3); + if (!conf_cmd_add(conf, $2, $3)) { + yyerror("command name/path too long"); + free($2); + free($3); + YYERROR; + } free($2); free($3); } From 4438970b649d8c6b0d662576bc37fc577b8de1b6 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 29 Jan 2014 18:43:27 +0000 Subject: [PATCH 2/5] Much like we do for keyboard and mouse bindings, remove duplicates for command name - last match. --- conf.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/conf.c b/conf.c index 8f067d0..9d4c079 100644 --- a/conf.c +++ b/conf.c @@ -32,6 +32,7 @@ #include "calmwm.h" static const char *conf_bind_getmask(const char *, unsigned int *); +static void conf_cmd_remove(struct conf *, const char *); static void conf_unbind_kbd(struct conf *, struct keybinding *); static void conf_unbind_mouse(struct conf *, struct mousebinding *); @@ -52,6 +53,8 @@ conf_cmd_add(struct conf *c, const char *name, const char *path) } else { cmd = xmalloc(sizeof(*cmd)); + conf_cmd_remove(c, name); + if (strlcpy(cmd->name, name, sizeof(cmd->name)) >= sizeof(cmd->name)) return (0); @@ -63,6 +66,18 @@ conf_cmd_add(struct conf *c, const char *name, const char *path) return (1); } +static void +conf_cmd_remove(struct conf *c, const char *name) +{ + struct cmd *cmd = NULL, *cmdnxt; + + TAILQ_FOREACH_SAFE(cmd, &c->cmdq, entry, cmdnxt) { + if (strcmp(cmd->name, name) == 0) { + TAILQ_REMOVE(&c->cmdq, cmd, entry); + free(cmd); + } + } +} void conf_autogroup(struct conf *c, int no, const char *val) { From db0b2fde5cb55a8867d9781dd0acb7c0ef92bcd2 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 29 Jan 2014 21:13:52 +0000 Subject: [PATCH 3/5] Merge keybinding and mousebinding queues into using the same merged struct, binding; they were essentially the same accept for what was 'pressed', keysym or button. --- calmwm.h | 26 +++++++++++--------------- conf.c | 45 ++++++++++++++++++++++----------------------- xevents.c | 10 +++++----- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/calmwm.h b/calmwm.h index 389c269..14ffcf2 100644 --- a/calmwm.h +++ b/calmwm.h @@ -94,6 +94,11 @@ union arg { int i; }; +union press { + KeySym keysym; + unsigned int button; +}; + enum cursor_font { CF_DEFAULT, CF_MOVE, @@ -247,26 +252,17 @@ struct screen_ctx { }; TAILQ_HEAD(screen_ctx_q, screen_ctx); -struct keybinding { - TAILQ_ENTRY(keybinding) entry; +struct binding { + TAILQ_ENTRY(binding) entry; void (*callback)(struct client_ctx *, union arg *); union arg argument; unsigned int modmask; - KeySym keysym; + union press press; int flags; int argtype; }; -TAILQ_HEAD(keybinding_q, keybinding); - -struct mousebinding { - TAILQ_ENTRY(mousebinding) entry; - void (*callback)(struct client_ctx *, union arg *); - union arg argument; - unsigned int modmask; - unsigned int button; - int flags; -}; -TAILQ_HEAD(mousebinding_q, mousebinding); +TAILQ_HEAD(keybinding_q, binding); +TAILQ_HEAD(mousebinding_q, binding); struct cmd { TAILQ_ENTRY(cmd) entry; @@ -290,10 +286,10 @@ TAILQ_HEAD(menu_q, menu); struct conf { struct keybinding_q keybindingq; + struct mousebinding_q mousebindingq; struct autogroupwin_q autogroupq; struct winmatch_q ignoreq; struct cmd_q cmdq; - struct mousebinding_q mousebindingq; #define CONF_STICKY_GROUPS 0x0001 int flags; #define CONF_BWIDTH 1 diff --git a/conf.c b/conf.c index 9d4c079..7f0c659 100644 --- a/conf.c +++ b/conf.c @@ -33,8 +33,8 @@ static const char *conf_bind_getmask(const char *, unsigned int *); static void conf_cmd_remove(struct conf *, const char *); -static void conf_unbind_kbd(struct conf *, struct keybinding *); -static void conf_unbind_mouse(struct conf *, struct mousebinding *); +static void conf_unbind_kbd(struct conf *, struct binding *); +static void conf_unbind_mouse(struct conf *, struct binding *); int conf_cmd_add(struct conf *c, const char *name, const char *path) @@ -288,10 +288,9 @@ void conf_clear(struct conf *c) { struct autogroupwin *ag; - struct keybinding *kb; + struct binding *kb, *mb; struct winmatch *wm; struct cmd *cmd; - struct mousebinding *mb; int i; while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) { @@ -491,16 +490,16 @@ conf_bind_getmask(const char *name, unsigned int *mask) int conf_bind_kbd(struct conf *c, const char *bind, const char *cmd) { - struct keybinding *kb; - const char *key; - unsigned int i, mask; + struct binding *kb; + const char *key; + unsigned int i, mask; kb = xcalloc(1, sizeof(*kb)); key = conf_bind_getmask(bind, &mask); kb->modmask |= mask; - kb->keysym = XStringToKeysym(key); - if (kb->keysym == NoSymbol) { + kb->press.keysym = XStringToKeysym(key); + if (kb->press.keysym == NoSymbol) { warnx("unknown symbol: %s", key); free(kb); return (0); @@ -535,15 +534,15 @@ conf_bind_kbd(struct conf *c, const char *bind, const char *cmd) } static void -conf_unbind_kbd(struct conf *c, struct keybinding *unbind) +conf_unbind_kbd(struct conf *c, struct binding *unbind) { - struct keybinding *key = NULL, *keynxt; + struct binding *key = NULL, *keynxt; TAILQ_FOREACH_SAFE(key, &c->keybindingq, entry, keynxt) { if (key->modmask != unbind->modmask) continue; - if (key->keysym == unbind->keysym) { + if (key->press.keysym == unbind->press.keysym) { TAILQ_REMOVE(&c->keybindingq, key, entry); if (key->argtype & ARG_CHAR) free(key->argument.c); @@ -574,15 +573,15 @@ static const struct { int conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) { - struct mousebinding *mb; - const char *button, *errstr; - unsigned int i, mask; + struct binding *mb; + const char *button, *errstr; + unsigned int i, mask; mb = xcalloc(1, sizeof(*mb)); button = conf_bind_getmask(bind, &mask); mb->modmask |= mask; - mb->button = strtonum(button, Button1, Button5, &errstr); + mb->press.button = strtonum(button, Button1, Button5, &errstr); if (errstr) { warnx("button number is %s: %s", errstr, button); free(mb); @@ -612,15 +611,15 @@ conf_bind_mouse(struct conf *c, const char *bind, const char *cmd) } static void -conf_unbind_mouse(struct conf *c, struct mousebinding *unbind) +conf_unbind_mouse(struct conf *c, struct binding *unbind) { - struct mousebinding *mb = NULL, *mbnxt; + struct binding *mb = NULL, *mbnxt; TAILQ_FOREACH_SAFE(mb, &c->mousebindingq, entry, mbnxt) { if (mb->modmask != unbind->modmask) continue; - if (mb->button == unbind->button) { + if (mb->press.button == unbind->press.button) { TAILQ_REMOVE(&c->mousebindingq, mb, entry); free(mb); } @@ -647,25 +646,25 @@ conf_cursor(struct conf *c) void conf_grab_mouse(Window win) { - struct mousebinding *mb; + struct binding *mb; xu_btn_ungrab(win); TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) { if (mb->flags & CWM_WIN) - xu_btn_grab(win, mb->modmask, mb->button); + xu_btn_grab(win, mb->modmask, mb->press.button); } } void conf_grab_kbd(Window win) { - struct keybinding *kb; + struct binding *kb; xu_key_ungrab(win); TAILQ_FOREACH(kb, &Conf.keybindingq, entry) - xu_key_grab(win, kb->modmask, kb->keysym); + xu_key_grab(win, kb->modmask, kb->press.keysym); } static char *cwmhints[] = { diff --git a/xevents.c b/xevents.c index b321acb..987d4fa 100644 --- a/xevents.c +++ b/xevents.c @@ -224,12 +224,12 @@ xev_handle_buttonpress(XEvent *ee) { XButtonEvent *e = &ee->xbutton; struct client_ctx *cc, fakecc; - struct mousebinding *mb; + struct binding *mb; e->state &= ~IGNOREMODMASK; TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) { - if (e->button == mb->button && e->state == mb->modmask) + if (e->button == mb->press.button && e->state == mb->modmask) break; } @@ -263,7 +263,7 @@ xev_handle_keypress(XEvent *ee) { XKeyEvent *e = &ee->xkey; struct client_ctx *cc = NULL, fakecc; - struct keybinding *kb; + struct binding *kb; KeySym keysym, skeysym; unsigned int modshift; @@ -273,7 +273,7 @@ xev_handle_keypress(XEvent *ee) e->state &= ~IGNOREMODMASK; TAILQ_FOREACH(kb, &Conf.keybindingq, entry) { - if (keysym != kb->keysym && skeysym == kb->keysym) + if (keysym != kb->press.keysym && skeysym == kb->press.keysym) modshift = ShiftMask; else modshift = 0; @@ -281,7 +281,7 @@ xev_handle_keypress(XEvent *ee) if ((kb->modmask | modshift) != e->state) continue; - if (kb->keysym == (modshift == 0 ? keysym : skeysym)) + if (kb->press.keysym == (modshift == 0 ? keysym : skeysym)) break; } From 59fe14bd2f2876beb16497f950ce589ccab4beb6 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 29 Jan 2014 21:17:33 +0000 Subject: [PATCH 4/5] keybinding -> key binding --- cwmrc.5 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cwmrc.5 b/cwmrc.5 index 0b28ed5..bc6e9c2 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: December 13 2013 $ +.Dd $Mdocdate: December 16 2013 $ .Dt CWMRC 5 .Os .Sh NAME @@ -64,8 +64,8 @@ are both set in the WM_CLASS property and may be obtained using .Xr xprop 1 . .Pp .It Ic bind Ar keys command -Cause the creation of a keybinding, or replacement of a default -keybinding. +Cause the creation of a key binding, or replacement of a default +key binding. The modifier keys come first, followed by a .Sq - . .Pp @@ -96,7 +96,7 @@ A special .Ar command keyword .Dq unmap -can be used to remove the named keybinding. +can be used to remove the named key binding. This can be used to remove a binding which conflicts with an application. .Pp @@ -148,7 +148,7 @@ and .Nm lock have a special meaning. They point to the terminal and screen locking programs specified by -keybindings. +key bindings. The defaults are .Xr xterm 1 and @@ -258,7 +258,7 @@ ignore xwi ignore xapm ignore xclock -# Keybindings +# Key bindings bind CM-r label bind CS-Return "xterm -e top" bind 4-o unmap @@ -273,7 +273,7 @@ bind MS-1 movetogroup1 bind MS-2 movetogroup2 bind MS-3 movetogroup3 -# Mousebindings +# Mouse bindings mousebind M-2 window_lower mousebind M-3 window_resize .Ed From 2be890489b8542b12f77133fbba404210c1b5f54 Mon Sep 17 00:00:00 2001 From: okan Date: Wed, 29 Jan 2014 22:30:00 +0000 Subject: [PATCH 5/5] Minimize trivial differences between a few kb and mb functions. --- calmwm.h | 2 +- conf.c | 2 +- kbfunc.c | 2 +- mousefunc.c | 13 ++++++------- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/calmwm.h b/calmwm.h index 14ffcf2..f71426d 100644 --- a/calmwm.h +++ b/calmwm.h @@ -477,7 +477,7 @@ void kbfunc_cmdexec(struct client_ctx *, union arg *); void kbfunc_cwm_status(struct client_ctx *, union arg *); void kbfunc_exec(struct client_ctx *, union arg *); void kbfunc_lock(struct client_ctx *, union arg *); -void kbfunc_menu_search(struct client_ctx *, union arg *); +void kbfunc_menu_cmd(struct client_ctx *, union arg *); void kbfunc_ssh(struct client_ctx *, union arg *); void kbfunc_term(struct client_ctx *, union arg *); void kbfunc_tile(struct client_ctx *, union arg *); diff --git a/conf.c b/conf.c index 7f0c659..e4b4dbb 100644 --- a/conf.c +++ b/conf.c @@ -353,7 +353,7 @@ static const struct { { "lower", kbfunc_client_lower, CWM_WIN, {0} }, { "raise", kbfunc_client_raise, CWM_WIN, {0} }, { "search", kbfunc_client_search, 0, {0} }, - { "menusearch", kbfunc_menu_search, 0, {0} }, + { "menusearch", kbfunc_menu_cmd, 0, {0} }, { "hide", kbfunc_client_hide, CWM_WIN, {0} }, { "cycle", kbfunc_client_cycle, 0, {.i = CWM_CYCLE} }, { "rcycle", kbfunc_client_cycle, 0, {.i = CWM_RCYCLE} }, diff --git a/kbfunc.c b/kbfunc.c index d44f63b..705baef 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -167,7 +167,7 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg) } void -kbfunc_menu_search(struct client_ctx *cc, union arg *arg) +kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg) { struct screen_ctx *sc = cc->sc; struct cmd *cmd; diff --git a/mousefunc.c b/mousefunc.c index 72953b2..73c3449 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -221,7 +221,6 @@ mousefunc_menu_unhide(struct client_ctx *cc, union arg *arg) old_cc = client_current(); TAILQ_INIT(&menuq); - TAILQ_FOREACH(cc, &Clientq, entry) if (cc->flags & CLIENT_HIDDEN) { wname = (cc->label) ? cc->label : cc->name; @@ -235,8 +234,8 @@ mousefunc_menu_unhide(struct client_ctx *cc, union arg *arg) if (TAILQ_EMPTY(&menuq)) return; - mi = menu_filter(sc, &menuq, NULL, NULL, 0, NULL, NULL); - if (mi != NULL) { + if ((mi = menu_filter(sc, &menuq, NULL, NULL, 0, + NULL, NULL)) != NULL) { cc = (struct client_ctx *)mi->ctx; client_unhide(cc); @@ -252,19 +251,19 @@ void mousefunc_menu_cmd(struct client_ctx *cc, union arg *arg) { struct screen_ctx *sc = cc->sc; + struct cmd *cmd; struct menu *mi; struct menu_q menuq; - struct cmd *cmd; TAILQ_INIT(&menuq); - TAILQ_FOREACH(cmd, &Conf.cmdq, entry) menuq_add(&menuq, cmd, "%s", cmd->name); + if (TAILQ_EMPTY(&menuq)) return; - mi = menu_filter(sc, &menuq, NULL, NULL, 0, NULL, NULL); - if (mi != NULL) + if ((mi = menu_filter(sc, &menuq, NULL, NULL, 0, + NULL, NULL)) != NULL) u_spawn(((struct cmd *)mi->ctx)->path); menuq_clear(&menuq);