source: keybinding.c @ b470451

release-1.10release-1.8release-1.9
Last change on this file since b470451 was d427f08, checked in by Nelson Elhage <nelhage@mit.edu>, 13 years ago
Use G_GNUC_WARN_UNUSED_RESULT Have gcc warn us when we ignore the result of a function that requires the caller to free the result, or an initilization function that can fail. This might help (slightly) with preventing leaks and segfaults. Additionally changed some functions that should never fail to not return values. (The owl_list_* functions changed only fail if list->size < 0, which we assume is not the case elsewhere.)
  • Property mode set to 100644
File size: 3.6 KB
Line 
1#include <ctype.h>
2#include <string.h>
3#include "owl.h"
4
5/*
6 * TODO: Idea for allowing functions to be user-specified ---
7 *      Have function have a context bitmask that says where it
8 *      can be used, and have keymaps also have one, and compare
9 *      the two when setting.
10 *     
11 */
12
13static int owl_keybinding_make_keys(owl_keybinding *kb, const char *keyseq);
14
15/* sets up a new keybinding for a command */
16G_GNUC_WARN_UNUSED_RESULT owl_keybinding *owl_keybinding_new(const char *keyseq, const char *command, void (*function_fn)(void), const char *desc)
17{
18  owl_keybinding *kb = g_new(owl_keybinding, 1);
19
20  owl_function_debugmsg("owl_keybinding_init: creating binding for <%s> with desc: <%s>", keyseq, desc);
21  if (command && function_fn) {
22    g_free(kb);
23    return NULL;
24  } else if (command && !function_fn) {
25    kb->type = OWL_KEYBINDING_COMMAND;
26  } else if (!command && function_fn) {
27    kb->type = OWL_KEYBINDING_FUNCTION;
28  } else {
29    kb->type = OWL_KEYBINDING_NOOP;
30  }
31
32  if (owl_keybinding_make_keys(kb, keyseq) != 0) {
33    g_free(kb);
34    return NULL;
35  }
36
37  kb->command = g_strdup(command);
38  kb->function_fn = function_fn;
39  kb->desc = g_strdup(desc);
40  return kb;
41}
42
43static int owl_keybinding_make_keys(owl_keybinding *kb, const char *keyseq)
44{
45  char **ktokens;
46  int    nktokens, i;
47
48  ktokens = g_strsplit_set(keyseq, " ", 0);
49  nktokens = g_strv_length(ktokens);
50  if (nktokens < 1 || nktokens > OWL_KEYMAP_MAXSTACK) {
51    g_strfreev(ktokens);
52    return(-1);
53  }
54  kb->keys = g_new(int, nktokens);
55  for (i=0; i<nktokens; i++) {
56    kb->keys[i] = owl_keypress_fromstring(ktokens[i]);
57    if (kb->keys[i] == ERR) {
58      g_strfreev(ktokens);
59      g_free(kb->keys);
60      return(-1);
61    }
62  }
63  kb->len = nktokens;
64  g_strfreev(ktokens);
65  return(0);
66}
67
68/* Releases data associated with a keybinding, and the kb itself */
69void owl_keybinding_delete(owl_keybinding *kb)
70{
71  g_free(kb->keys);
72  g_free(kb->desc);
73  g_free(kb->command);
74  g_free(kb);
75}
76
77/* executes a keybinding */
78void owl_keybinding_execute(const owl_keybinding *kb, int j)
79{
80  if (kb->type == OWL_KEYBINDING_COMMAND && kb->command) {
81    owl_function_command_norv(kb->command);
82  } else if (kb->type == OWL_KEYBINDING_FUNCTION && kb->function_fn) {
83    kb->function_fn();
84  }
85}
86
87G_GNUC_WARN_UNUSED_RESULT char *owl_keybinding_stack_tostring(int *j, int len)
88{
89  GString *string;
90  int  i;
91
92  string = g_string_new("");
93  for (i = 0; i < len; i++) {
94    char *keypress = owl_keypress_tostring(j[i], 0);
95    g_string_append(string, keypress ? keypress : "INVALID");
96    g_free(keypress);
97    if (i < len - 1) g_string_append_c(string, ' ');
98  }
99  return g_string_free(string, false);
100}
101
102G_GNUC_WARN_UNUSED_RESULT char *owl_keybinding_tostring(const owl_keybinding *kb)
103{
104  return owl_keybinding_stack_tostring(kb->keys, kb->len);
105}
106
107const char *owl_keybinding_get_desc(const owl_keybinding *kb)
108{
109  return kb->desc;
110}
111
112/* returns 0 on no match, 1 on subset match, and 2 on complete match */
113int owl_keybinding_match(const owl_keybinding *kb, const owl_keyhandler *kh)
114{
115  int i;
116  for(i = 0; i <= kh->kpstackpos && i < kb->len; i++) {
117    if(kb->keys[i] != kh->kpstack[i])
118      return 0;
119  }
120
121  /* If we've made it to this point, then they match as far as they are. */
122  if(kb->len == kh->kpstackpos + 1) {
123    /* Equal length */
124    return 2;
125  } else if(kb->len > kh->kpstackpos + 1) {
126    return 1;
127  }
128
129  return 0;
130}
131
132/* returns 1 if keypress sequence is the same */
133int owl_keybinding_equal(const owl_keybinding *kb1, const owl_keybinding *kb2)
134{
135  int i;
136
137  if(kb1->len != kb2->len) return 0;
138
139  for(i = 0; i < kb1->len; i++) {
140    if(kb1->keys[i] != kb2->keys[i])
141      return 0;
142  }
143
144  return 1;
145}
Note: See TracBrowser for help on using the repository browser.