=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/key-bindings.c,v retrieving revision 1.44 retrieving revision 1.45 diff -u -r1.44 -r1.45 --- src/usr.bin/tmux/key-bindings.c 2015/04/19 21:34:21 1.44 +++ src/usr.bin/tmux/key-bindings.c 2015/04/20 15:34:56 1.45 @@ -1,4 +1,4 @@ -/* $OpenBSD: key-bindings.c,v 1.44 2015/04/19 21:34:21 nicm Exp $ */ +/* $OpenBSD: key-bindings.c,v 1.45 2015/04/20 15:34:56 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -25,63 +25,123 @@ #include "tmux.h" RB_GENERATE(key_bindings, key_binding, entry, key_bindings_cmp); +RB_GENERATE(key_tables, key_table, entry, key_table_cmp); +struct key_tables key_tables = RB_INITIALIZER(&key_tables); -struct key_bindings key_bindings; +int +key_table_cmp(struct key_table *e1, struct key_table *e2) +{ + return (strcmp(e1->name, e2->name)); +} int key_bindings_cmp(struct key_binding *bd1, struct key_binding *bd2) { - int key1, key2; + return (bd1->key - bd2->key); +} - key1 = bd1->key & ~KEYC_PREFIX; - key2 = bd2->key & ~KEYC_PREFIX; - if (key1 != key2) - return (key1 - key2); +struct key_table * +key_bindings_get_table(const char *name, int create) +{ + struct key_table table_find, *table; - if (bd1->key & KEYC_PREFIX && !(bd2->key & KEYC_PREFIX)) - return (-1); - if (bd2->key & KEYC_PREFIX && !(bd1->key & KEYC_PREFIX)) - return (1); - return (0); + table_find.name = name; + table = RB_FIND(key_tables, &key_tables, &table_find); + if (table != NULL || !create) + return (table); + + table = xmalloc(sizeof *table); + table->name = xstrdup(name); + RB_INIT(&table->key_bindings); + + table->references = 1; /* one reference in key_tables */ + RB_INSERT(key_tables, &key_tables, table); + + return (table); } -struct key_binding * -key_bindings_lookup(int key) +void +key_bindings_unref_table(struct key_table *table) { - struct key_binding bd; + struct key_binding *bd; - bd.key = key; - return (RB_FIND(key_bindings, &key_bindings, &bd)); + if (--table->references != 0) + return; + + while (!RB_EMPTY(&table->key_bindings)) { + bd = RB_ROOT(&table->key_bindings); + RB_REMOVE(key_bindings, &table->key_bindings, bd); + cmd_list_free(bd->cmdlist); + free(bd); + } + + free((void *)table->name); + free(table); } void -key_bindings_add(int key, int can_repeat, struct cmd_list *cmdlist) +key_bindings_add(const char *name, int key, int can_repeat, + struct cmd_list *cmdlist) { - struct key_binding *bd; + struct key_table *table; + struct key_binding bd_find, *bd; - key_bindings_remove(key); + table = key_bindings_get_table(name, 1); + bd_find.key = key; + bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find); + if (bd != NULL) { + RB_REMOVE(key_bindings, &table->key_bindings, bd); + cmd_list_free(bd->cmdlist); + free(bd); + } + bd = xmalloc(sizeof *bd); bd->key = key; - RB_INSERT(key_bindings, &key_bindings, bd); + RB_INSERT(key_bindings, &table->key_bindings, bd); bd->can_repeat = can_repeat; bd->cmdlist = cmdlist; } void -key_bindings_remove(int key) +key_bindings_remove(const char *name, int key) { - struct key_binding *bd; + struct key_table *table; + struct key_binding bd_find, *bd; - if ((bd = key_bindings_lookup(key)) == NULL) + table = key_bindings_get_table(name, 0); + if (table == NULL) return; - RB_REMOVE(key_bindings, &key_bindings, bd); + + bd_find.key = key; + bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find); + if (bd == NULL) + return; + + RB_REMOVE(key_bindings, &table->key_bindings, bd); cmd_list_free(bd->cmdlist); free(bd); + + if (RB_EMPTY(&table->key_bindings)) { + RB_REMOVE(key_tables, &key_tables, table); + key_bindings_unref_table(table); + } } void +key_bindings_remove_table(const char *name) +{ + struct key_table *table; + + table = key_bindings_get_table(name, 0); + if (table != NULL) { + RB_REMOVE(key_tables, &key_tables, table); + key_bindings_unref_table(table); + } +} + +void key_bindings_init(void) { static const char* defaults[] = { @@ -168,8 +228,6 @@ char* cause; int error; struct cmd_q *cmdq; - - RB_INIT(&key_bindings); cmdq = cmdq_new(NULL); for (i = 0; i < nitems(defaults); i++) {