split global key binding list into mode specific and global lists

added commands local-unset-key and global-unset-key
This commit is contained in:
Charlie Gordon 2008-04-18 14:39:07 +00:00
commit 24d4fda0aa
3 changed files with 158 additions and 111 deletions

View file

@ -22,6 +22,7 @@
#include "qe.h"
#include "qfribidi.h"
#include "variables.h"
void do_compare_windows(EditState *s, int argval)
{
@ -344,6 +345,39 @@ static void do_transpose(EditState *s, int cmd)
eb_write(s->b, offset0, buf, size0 + size1 + size2);
}
/* remove a key binding from mode or globally */
static int qe_unregister_binding1(unsigned int *keys, int nb_keys, ModeDef *m)
{
QEmacsState *qs = &qe_state;
KeyDef **lp, *p;
lp = m ? &m->first_key : &qs->first_key;
while (*lp) {
if ((*lp)->nb_keys == nb_keys
&& !memcmp((*lp)->keys, keys, nb_keys * sizeof(*keys)))
{
p = *lp;
*lp = (*lp)->next;
qe_free(p);
return 1;
}
lp = &(*lp)->next;
}
return 0;
}
static void do_unset_key(EditState *s, const char *keystr, int local)
{
unsigned int keys[MAX_KEYS];
int nb_keys;
nb_keys = strtokeys(keystr, keys, MAX_KEYS);
if (!nb_keys)
return;
qe_unregister_binding1(keys, nb_keys, local ? s->mode : NULL);
}
static CmdDef extra_commands[] = {
CMD_( KEY_META('='), KEY_NONE,
"compare-windows", do_compare_windows, ESi, "ui" )
@ -371,6 +405,15 @@ static CmdDef extra_commands[] = {
CMDV( KEY_META('t'), KEY_NONE,
"transpose-words", do_transpose, ESi, CMD_TRANSPOSE_WORDS, "*v")
CMDV( KEY_NONE, KEY_NONE,
"global-unset-key", do_unset_key, ESsi, 0,
"s{Unset key globally: }[key]"
"v")
CMDV( KEY_NONE, KEY_NONE,
"local-unset-key", do_unset_key, ESsi, 1,
"s{Unset key locally: }[key]"
"v")
CMD_DEF_END,
};
@ -379,8 +422,9 @@ static int extras_init(void)
int key;
qe_register_cmd_table(extra_commands, NULL);
for (key = KEY_META('0'); key <= KEY_META('9'); key++)
for (key = KEY_META('0'); key <= KEY_META('9'); key++) {
qe_register_binding(key, "universal-argument", NULL);
}
return 0;
}

216
qe.c
View file

@ -160,6 +160,21 @@ CmdDef *qe_find_cmd(const char *cmd_name)
return NULL;
}
void command_completion(CompleteState *cp)
{
QEmacsState *qs = cp->s->qe_state;
CmdDef *d;
d = qs->first_cmd;
while (d != NULL) {
while (d->name != NULL) {
complete_test(cp, d->name);
d++;
}
d = d->action.next;
}
}
static int qe_register_binding1(unsigned int *keys, int nb_keys,
CmdDef *d, ModeDef *m)
{
@ -175,19 +190,16 @@ static int qe_register_binding1(unsigned int *keys, int nb_keys,
if (!p)
return -1;
p->cmd = d;
p->mode = m;
p->nb_keys = nb_keys;
for (i = 0; i < nb_keys; i++) {
p->keys[i] = keys[i];
}
/* find position: mode keys should be before generic keys, but
* bindings must be prepended to override previous bindings
*/
lp = &qs->first_key;
if (m == NULL) {
while (*lp != NULL && (*lp)->mode != NULL)
lp = &(*lp)->next;
}
lp = m ? &m->first_key : &qs->first_key;
/* Bindings must be prepended to override previous bindings */
#if 0
while (*lp != NULL && (*lp)->mode != NULL)
lp = &(*lp)->next;
#endif
p->next = *lp;
*lp = p;
return 0;
@ -203,11 +215,13 @@ static int qe_register_binding2(int key, CmdDef *d, ModeDef *m)
if (key >= KEY_CTRLX(0) && key <= KEY_CTRLX(0xff)) {
keys[nb_keys++] = KEY_CTRL('x');
keys[nb_keys++] = key & 0xff;
} else if (key >= KEY_CTRLXRET(0) && key <= KEY_CTRLXRET(0xff)) {
} else
if (key >= KEY_CTRLXRET(0) && key <= KEY_CTRLXRET(0xff)) {
keys[nb_keys++] = KEY_CTRL('x');
keys[nb_keys++] = KEY_RET;
keys[nb_keys++] = key & 0xff;
} else if (key >= KEY_CTRLH(0) && key <= KEY_CTRLH(0xff)) {
} else
if (key >= KEY_CTRLH(0) && key <= KEY_CTRLH(0xff)) {
keys[nb_keys++] = KEY_CTRL('h');
keys[nb_keys++] = key & 0xff;
} else {
@ -216,28 +230,6 @@ static int qe_register_binding2(int key, CmdDef *d, ModeDef *m)
return qe_register_binding1(keys, nb_keys, d, m);
}
#if 0
/* remove a key binding from mode or globally */
/* should take key sequence */
int qe_unregister_binding1(int key, ModeDef *m)
{
QEmacsState *qs = &qe_state;
KeyDef **lp, *p;
lp = (m) ? &m->first_key : &qs->first_key;
while (*lp) {
if ((*lp)->key == key) {
p = *lp;
*lp = (*lp)->next;
free(p);
break;
}
lp = &(*lp)->next;
}
return 0;
}
#endif
/* if mode is non NULL, the defined keys are only active in this mode */
void qe_register_cmd_table(CmdDef *cmds, ModeDef *m)
{
@ -287,23 +279,6 @@ int qe_register_binding(int key, const char *cmd_name, ModeDef *m)
return qe_register_binding2(key, qe_find_cmd(cmd_name), m);
}
void command_completion(CompleteState *cp)
{
QEmacsState *qs = cp->s->qe_state;
CmdDef *d;
d = qs->first_cmd;
while (d != NULL) {
while (d->name != NULL) {
complete_test(cp, d->name);
d++;
}
d = d->action.next;
}
}
#define MAX_KEYS 10
void do_set_key(EditState *s, const char *keystr,
const char *cmd_name, int local)
{
@ -323,31 +298,14 @@ void do_set_key(EditState *s, const char *keystr,
qe_register_binding1(keys, nb_keys, d, local ? s->mode : NULL);
}
#if 0
void do_unset_key(EditState *s, const char *keystr, int local)
{
int key;
if (!keystr) {
edit_display(s->qe_state);
put_status(s, "Unset key %s: ", local ? "locally" : "globally");
dpy_flush(s->screen);
key = get_key(s->screen);
} else {
key = strtokey(&keystr);
}
qe_unregister_binding1(key, local ? s->mode : NULL);
do_describe_key(s, NULL, key);
}
#endif
void do_toggle_control_h(EditState *s, int set)
{
/* Achtung Minen! do_toggle_control_h can be called from tty_init
* with a NULL EditState.
*/
QEmacsState *qs = s ? s->qe_state : &qe_state;
KeyDef *p;
ModeDef *m;
KeyDef *kd;
int i;
if (set)
@ -360,22 +318,29 @@ void do_toggle_control_h(EditState *s, int set)
qs->backspace_is_control_h = set;
for (p = qs->first_key; p; p = p->next) {
for (i = 0; i < p->nb_keys; i++) {
switch (p->keys[i]) {
case KEY_CTRL('h'):
p->keys[i] = set ? KEY_META('h') : 127;
break;
case 127:
if (set)
p->keys[i] = KEY_CTRL('h');
break;
case KEY_META('h'):
if (!set)
p->keys[i] = KEY_CTRL('h');
break;
/* CG: This hack in incompatible with support for multiple
* concurrent input consoles.
*/
for (m = qs->first_mode;; m = m->next) {
for (kd = m ? m->first_key : qs->first_key; kd; kd = kd->next) {
for (i = 0; i < kd->nb_keys; i++) {
switch (kd->keys[i]) {
case KEY_CTRL('h'):
kd->keys[i] = set ? KEY_META('h') : 127;
break;
case 127:
if (set)
kd->keys[i] = KEY_CTRL('h');
break;
case KEY_META('h'):
if (!set)
kd->keys[i] = KEY_CTRL('h');
break;
}
}
}
if (!m)
break;
}
}
@ -4119,6 +4084,43 @@ static void qe_key_init(QEKeyContext *c)
c->buf[0] = '\0';
}
static KeyDef *find_binding(unsigned int *keys, int nb_keys, int nroots, ...)
{
KeyDef *kd = NULL;
va_list ap;
va_start(ap, nroots);
while (nroots--) {
for (kd = va_arg(ap, KeyDef *); kd != NULL; kd = kd->next) {
if (kd->nb_keys >= nb_keys
&& !memcmp(kd->keys, keys, nb_keys * sizeof(keys[0])))
{
goto found;
}
}
}
found:
va_end(ap);
return kd;
}
static KeyDef *find_binding1(unsigned int key, int nroots, ...)
{
KeyDef *kd = NULL;
va_list ap;
va_start(ap, nroots);
while (nroots--) {
for (kd = va_arg(ap, KeyDef *); kd != NULL; kd = kd->next) {
if (kd->nb_keys == 1 && kd->keys[0] == key)
goto found;
}
}
found:
va_end(ap);
return kd;
}
static void qe_key_process(int key)
{
QEmacsState *qs = &qe_state;
@ -4171,16 +4173,9 @@ static void qe_key_process(int key)
}
/* see if one command is found */
for (kd = qs->first_key; kd != NULL; kd = kd->next) {
if (kd->nb_keys >= c->nb_keys) {
if (!memcmp(kd->keys, c->keys,
c->nb_keys * sizeof(c->keys[0])) &&
(kd->mode == NULL || kd->mode == s->mode)) {
break;
}
}
}
if (!kd) {
if (!(kd = find_binding(c->keys, c->nb_keys, 2,
s->mode->first_key, qs->first_key)))
{
/* no key found */
if (c->nb_keys == 1) {
if (!KEY_SPECIAL(key)) {
@ -4198,16 +4193,12 @@ static void qe_key_process(int key)
goto next;
}
}
for (kd = qs->first_key; kd != NULL; kd = kd->next) {
if (kd->nb_keys == 1 &&
kd->keys[0] == KEY_DEFAULT &&
(kd->mode == NULL || kd->mode == s->mode)) {
break;
}
}
kd = find_binding1(KEY_DEFAULT, 2,
s->mode->first_key, qs->first_key);
if (kd) {
/* horrible kludge to pass key as intrinsic argument */
/* CG: should have an argument type for key */
/* CG: should be no longer necessary */
kd->cmd->val = key;
goto exec_cmd;
}
@ -6481,29 +6472,40 @@ static void print_bindings(EditBuffer *b, const char *title,
__unused__ int type, ModeDef *mode)
{
CmdDef *d;
KeyDef *k;
KeyDef *kd;
char buf[64];
int found, gfound;
int found, gfound, pos;
d = qe_state.first_cmd;
gfound = 0;
while (d != NULL) {
while (d->name != NULL) {
/* find each key mapping pointing to this command */
found = 0;
for (k = qe_state.first_key; k != NULL; k = k->next) {
if (k->cmd == d && k->mode == mode) {
found = pos = 0;
kd = mode ? mode->first_key : qe_state.first_key;
for (; kd != NULL; kd = kd->next) {
if (kd->cmd == d) {
if (!gfound)
eb_printf(b, "%s:\n\n", title);
if (found)
eb_printf(b, ",");
eb_printf(b, " %s", keys_to_str(buf, sizeof(buf), k->keys, k->nb_keys));
pos += eb_printf(b, ",");
if (pos > 50) {
eb_printf(b, "\n");
pos = 0;
}
pos += eb_printf(b, " %s",
keys_to_str(buf, sizeof(buf),
kd->keys, kd->nb_keys));
found = 1;
gfound = 1;
}
}
if (found) {
/* print associated command name */
if (pos > 25) {
eb_printf(b, "\n");
pos = 0;
}
eb_line_pad(b, 25);
eb_printf(b, ": %s\n", d->name);
}

7
qe.h
View file

@ -1079,7 +1079,7 @@ typedef struct ModeDef {
int (*get_mode_line)(EditState *s, char *buf, int buf_size); /* return mode line */
/* mode specific key bindings */
//struct KeyDef *first_key;
struct KeyDef *first_key;
struct ModeDef *next;
} ModeDef;
@ -1222,10 +1222,11 @@ extern QEmacsState qe_state;
/* dynamic key binding storage */
#define MAX_KEYS 10
typedef struct KeyDef {
struct CmdDef *cmd;
struct KeyDef *next;
ModeDef *mode; /* if non NULL, key is only active in this mode */
struct CmdDef *cmd;
int nb_keys;
unsigned int keys[1];
} KeyDef;