Mercurial > pidgin
changeset 23218:0f7aca3ed899
merge of '417f9d0217b6d3b9f2b5f2b9361ffe03efc2d634'
and '79699160e06b69f70db91eef65287f15685ec2bf'
author | John Bailey <rekkanoryo@rekkanoryo.org> |
---|---|
date | Tue, 27 May 2008 03:45:02 +0000 |
parents | 3dc1bc92b170 (current diff) 02b6569d99e9 (diff) |
children | f9ec2f2580e6 |
files | |
diffstat | 1 files changed, 155 insertions(+), 152 deletions(-) [+] |
line wrap: on
line diff
--- a/finch/libgnt/gntkeys.c Tue May 27 03:16:15 2008 +0000 +++ b/finch/libgnt/gntkeys.c Tue May 27 03:45:02 2008 +0000 @@ -34,6 +34,158 @@ static const char *term; static GHashTable *specials; +void gnt_keys_refine(char *text) +{ + if (*text == 27 && *(text + 1) == '[' && + (*(text + 2) >= 'A' && *(text + 2) <= 'D')) { + /* Apparently this is necessary for urxvt and screen and xterm */ + if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0 || + strcmp(term, "xterm") == 0) + *(text + 1) = 'O'; + } else if (*(unsigned char*)text == 195) { + if (*(text + 2) == 0 && strcmp(term, "xterm") == 0) { + *(text) = 27; + *(text + 1) -= 64; /* Say wha? */ + } + } +} + +const char *gnt_key_translate(const char *name) +{ + return name ? g_hash_table_lookup(specials, name) : NULL; +} + +typedef struct { + const char *name; + const char *key; +} gntkey; + +static void +get_key_name(gpointer key, gpointer value, gpointer data) +{ + gntkey *k = data; + if (k->name) + return; + if (g_utf8_collate(value, k->key) == 0) + k->name = key; +} + +const char *gnt_key_lookup(const char *key) +{ + gntkey k = {NULL, key}; + g_hash_table_foreach(specials, get_key_name, &k); + return k.name; +} + +/** + * The key-bindings will be saved in a tree. When a keystroke happens, GNT will + * find the sequence that matches a binding and return the length. + * A sequence should not be a prefix of another sequence. If it is, then only + * the shortest one will be processed. If we want to change that, we will need + * to allow getting the k-th prefix that matches the input, and pay attention + * to the return value of gnt_wm_process_input in gntmain.c. + */ +#define SIZE 256 + +#define IS_END 1 << 0 +struct _node +{ + struct _node *next[SIZE]; + int ref; + int flags; +}; + +struct _node root; + +static void add_path(struct _node *node, const char *path) +{ + struct _node *n = NULL; + if (!path || !*path) { + node->flags |= IS_END; + return; + } + while (*path && node->next[(unsigned char)*path]) { + node = node->next[(unsigned char)*path]; + node->ref++; + path++; + } + if (!*path) + return; + n = g_new0(struct _node, 1); + n->ref = 1; + node->next[(unsigned char)*path++] = n; + add_path(n, path); +} + +void gnt_keys_add_combination(const char *path) +{ + add_path(&root, path); +} + +static void del_path(struct _node *node, const char *path) +{ + struct _node *next = NULL; + + if (!*path) + return; + next = node->next[(unsigned char)*path]; + if (!next) + return; + del_path(next, path + 1); + next->ref--; + if (next->ref == 0) { + node->next[(unsigned char)*path] = NULL; + g_free(next); + } +} + +void gnt_keys_del_combination(const char *path) +{ + del_path(&root, path); +} + +int gnt_keys_find_combination(const char *path) +{ + int depth = 0; + struct _node *n = &root; + + root.flags &= ~IS_END; + while (*path && n->next[(unsigned char)*path] && !(n->flags & IS_END)) { + if (!g_ascii_isspace(*path) && + !g_ascii_iscntrl(*path) && + !g_ascii_isgraph(*path)) + return 0; + n = n->next[(unsigned char)*path++]; + depth++; + } + + if (!(n->flags & IS_END)) + depth = 0; + return depth; +} + +static void +print_path(struct _node *node, int depth) +{ + int i; + for (i = 0; i < SIZE; i++) { + if (node->next[i]) { + g_printerr("%*c (%d:%d)\n", depth * 4, i, node->next[i]->ref, + node->next[i]->flags); + print_path(node->next[i], depth + 1); + } + } +} + +/* this is purely for debugging purposes. */ +void gnt_keys_print_combinations(void); +void gnt_keys_print_combinations() +{ + g_printerr("--------\n"); + print_path(&root, 1); + g_printerr("--------\n"); +} + void gnt_init_keys() { const char *controls[] = {"", "c-", "ctrl-", "ctr-", "ctl-", NULL}; @@ -41,6 +193,9 @@ int c, a, ch; char key[32]; + memset(&root, 0, sizeof(root)); + root.ref = 1; + if (term == NULL) { term = getenv("TERM"); if (!term) @@ -136,155 +291,3 @@ } } -void gnt_keys_refine(char *text) -{ - if (*text == 27 && *(text + 1) == '[' && - (*(text + 2) >= 'A' && *(text + 2) <= 'D')) { - /* Apparently this is necessary for urxvt and screen and xterm */ - if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0 || - strcmp(term, "xterm") == 0) - *(text + 1) = 'O'; - } else if (*(unsigned char*)text == 195) { - if (*(text + 2) == 0 && strcmp(term, "xterm") == 0) { - *(text) = 27; - *(text + 1) -= 64; /* Say wha? */ - } - } -} - -const char *gnt_key_translate(const char *name) -{ - return name ? g_hash_table_lookup(specials, name) : NULL; -} - -typedef struct { - const char *name; - const char *key; -} gntkey; - -static void -get_key_name(gpointer key, gpointer value, gpointer data) -{ - gntkey *k = data; - if (k->name) - return; - if (g_utf8_collate(value, k->key) == 0) - k->name = key; -} - -const char *gnt_key_lookup(const char *key) -{ - gntkey k = {NULL, key}; - g_hash_table_foreach(specials, get_key_name, &k); - return k.name; -} - -/** - * The key-bindings will be saved in a tree. When a keystroke happens, GNT will - * find the sequence that matches a binding and return the length. - * A sequence should not be a prefix of another sequence. If it is, then only - * the shortest one will be processed. If we want to change that, we will need - * to allow getting the k-th prefix that matches the input, and pay attention - * to the return value of gnt_wm_process_input in gntmain.c. - */ -#define SIZE 256 - -#define IS_END 1 << 0 -struct _node -{ - struct _node *next[SIZE]; - int ref; - int flags; -}; - -static struct _node root = {.ref = 1, .flags = 0}; - -static void add_path(struct _node *node, const char *path) -{ - struct _node *n = NULL; - if (!path || !*path) { - node->flags |= IS_END; - return; - } - while (*path && node->next[(unsigned char)*path]) { - node = node->next[(unsigned char)*path]; - node->ref++; - path++; - } - if (!*path) - return; - n = g_new0(struct _node, 1); - n->ref = 1; - node->next[(unsigned char)*path++] = n; - add_path(n, path); -} - -void gnt_keys_add_combination(const char *path) -{ - add_path(&root, path); -} - -static void del_path(struct _node *node, const char *path) -{ - struct _node *next = NULL; - - if (!*path) - return; - next = node->next[(unsigned char)*path]; - if (!next) - return; - del_path(next, path + 1); - next->ref--; - if (next->ref == 0) { - node->next[(unsigned char)*path] = NULL; - g_free(next); - } -} - -void gnt_keys_del_combination(const char *path) -{ - del_path(&root, path); -} - -int gnt_keys_find_combination(const char *path) -{ - int depth = 0; - struct _node *n = &root; - - root.flags &= ~IS_END; - while (*path && n->next[(unsigned char)*path] && !(n->flags & IS_END)) { - if (!g_ascii_isspace(*path) && - !g_ascii_iscntrl(*path) && - !g_ascii_isgraph(*path)) - return 0; - n = n->next[(unsigned char)*path++]; - depth++; - } - - if (!(n->flags & IS_END)) - depth = 0; - return depth; -} - -static void -print_path(struct _node *node, int depth) -{ - int i; - for (i = 0; i < SIZE; i++) { - if (node->next[i]) { - g_printerr("%*c (%d:%d)\n", depth * 4, i, node->next[i]->ref, - node->next[i]->flags); - print_path(node->next[i], depth + 1); - } - } -} - -/* this is purely for debugging purposes. */ -void gnt_keys_print_combinations(void); -void gnt_keys_print_combinations() -{ - g_printerr("--------\n"); - print_path(&root, 1); - g_printerr("--------\n"); -} -