Mercurial > pidgin.yaz
annotate finch/libgnt/gntkeys.c @ 21304:add12afc3140
Fix size calculation when shadow is enabled.
Also, when the terminal is resized, the SIGWINCH callback needs to refresh
after endwin to get the correct new size of the terminal.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 10 Nov 2007 23:48:57 +0000 |
parents | 44b4e8bd759b |
children | 02b6569d99e9 e145f37cb2e2 |
rev | line source |
---|---|
18049
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
1 /** |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
2 * GNT - The GLib Ncurses Toolkit |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
3 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
4 * GNT is the legal property of its developers, whose names are too numerous |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
5 * to list here. Please refer to the COPYRIGHT file distributed with this |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
6 * source distribution. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
7 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
8 * This library is free software; you can redistribute it and/or modify |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
11 * (at your option) any later version. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
12 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
13 * This program is distributed in the hope that it will be useful, |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
16 * GNU General Public License for more details. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
17 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
18 * You should have received a copy of the GNU General Public License |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
19 * along with this program; if not, write to the Free Software |
19680
44b4e8bd759b
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
18423
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
18049
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
21 */ |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
22 |
15818 | 23 #include "gntkeys.h" |
24 | |
25 #include <glib.h> | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
28 | |
29 char *gnt_key_cup; | |
30 char *gnt_key_cdown; | |
31 char *gnt_key_cleft; | |
32 char *gnt_key_cright; | |
33 | |
34 static const char *term; | |
35 static GHashTable *specials; | |
36 | |
37 void gnt_init_keys() | |
38 { | |
39 const char *controls[] = {"", "c-", "ctrl-", "ctr-", "ctl-", NULL}; | |
40 const char *alts[] = {"", "alt-", "a-", "m-", "meta-", NULL}; | |
41 int c, a, ch; | |
42 char key[32]; | |
43 | |
44 if (term == NULL) { | |
45 term = getenv("TERM"); | |
46 if (!term) | |
47 term = ""; /* Just in case */ | |
48 } | |
49 | |
50 if (strcmp(term, "xterm") == 0 || strcmp(term, "rxvt") == 0) { | |
51 gnt_key_cup = "\033" "[1;5A"; | |
52 gnt_key_cdown = "\033" "[1;5B"; | |
53 gnt_key_cright = "\033" "[1;5C"; | |
54 gnt_key_cleft = "\033" "[1;5D"; | |
55 } else if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0) { | |
56 gnt_key_cup = "\033" "Oa"; | |
57 gnt_key_cdown = "\033" "Ob"; | |
58 gnt_key_cright = "\033" "Oc"; | |
59 gnt_key_cleft = "\033" "Od"; | |
60 } | |
61 | |
62 specials = g_hash_table_new(g_str_hash, g_str_equal); | |
63 | |
64 #define INSERT_KEY(k, code) do { \ | |
65 g_hash_table_insert(specials, g_strdup(k), g_strdup(code)); \ | |
66 gnt_keys_add_combination(code); \ | |
67 } while (0) | |
68 | |
69 INSERT_KEY("home", GNT_KEY_HOME); | |
70 INSERT_KEY("end", GNT_KEY_END); | |
71 INSERT_KEY("pageup", GNT_KEY_PGUP); | |
72 INSERT_KEY("pagedown", GNT_KEY_PGDOWN); | |
73 INSERT_KEY("insert", GNT_KEY_INS); | |
74 INSERT_KEY("delete", GNT_KEY_DEL); | |
18000
05d7fe2320a9
(16:39:44) rekkanoryo: i have a feature request
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
16044
diff
changeset
|
75 INSERT_KEY("back_tab", GNT_KEY_BACK_TAB); |
15818 | 76 |
77 INSERT_KEY("left", GNT_KEY_LEFT); | |
78 INSERT_KEY("right", GNT_KEY_RIGHT); | |
79 INSERT_KEY("up", GNT_KEY_UP); | |
80 INSERT_KEY("down", GNT_KEY_DOWN); | |
81 | |
82 INSERT_KEY("tab", "\t"); | |
83 INSERT_KEY("menu", GNT_KEY_POPUP); | |
84 | |
85 INSERT_KEY("f1", GNT_KEY_F1); | |
86 INSERT_KEY("f2", GNT_KEY_F2); | |
87 INSERT_KEY("f3", GNT_KEY_F3); | |
88 INSERT_KEY("f4", GNT_KEY_F4); | |
89 INSERT_KEY("f5", GNT_KEY_F5); | |
90 INSERT_KEY("f6", GNT_KEY_F6); | |
91 INSERT_KEY("f7", GNT_KEY_F7); | |
92 INSERT_KEY("f8", GNT_KEY_F8); | |
93 INSERT_KEY("f9", GNT_KEY_F9); | |
94 INSERT_KEY("f10", GNT_KEY_F10); | |
95 INSERT_KEY("f11", GNT_KEY_F11); | |
96 INSERT_KEY("f12", GNT_KEY_F12); | |
97 | |
98 #define REM_LENGTH (sizeof(key) - (cur - key)) | |
99 #define INSERT_COMB(k, code) do { \ | |
100 snprintf(key, sizeof(key), "%s%s%s", controls[c], alts[a], k); \ | |
101 INSERT_KEY(key, code); \ | |
102 } while (0); | |
103 | |
104 /* Lower-case alphabets */ | |
105 for (a = 0, c = 0; controls[c]; c++, a = 0) { | |
106 if (c) { | |
107 INSERT_COMB("up", gnt_key_cup); | |
108 INSERT_COMB("down", gnt_key_cdown); | |
109 INSERT_COMB("left", gnt_key_cleft); | |
110 INSERT_COMB("right", gnt_key_cright); | |
111 } | |
112 | |
113 for (a = 0; alts[a]; a++) { | |
114 for (ch = 0; ch < 26; ch++) { | |
115 char str[2] = {'a' + ch, 0}, code[4] = "\0\0\0\0"; | |
116 int ind = 0; | |
117 if (a) | |
118 code[ind++] = '\033'; | |
119 code[ind] = (c ? 1 : 'a') + ch; | |
120 INSERT_COMB(str, code); | |
121 } | |
122 } | |
123 } | |
124 c = 0; | |
125 for (a = 0; alts[a]; a++) { | |
126 /* Upper-case alphabets */ | |
127 for (ch = 0; ch < 26; ch++) { | |
128 char str[2] = {'A' + ch, 0}, code[] = {'\033', 'A' + ch, 0}; | |
129 INSERT_COMB(str, code); | |
130 } | |
131 /* Digits */ | |
132 for (ch = 0; ch < 10; ch++) { | |
133 char str[2] = {'0' + ch, 0}, code[] = {'\033', '0' + ch, 0}; | |
134 INSERT_COMB(str, code); | |
135 } | |
136 } | |
137 } | |
138 | |
139 void gnt_keys_refine(char *text) | |
140 { | |
141 if (*text == 27 && *(text + 1) == '[' && | |
142 (*(text + 2) >= 'A' && *(text + 2) <= 'D')) { | |
143 /* Apparently this is necessary for urxvt and screen and xterm */ | |
144 if (strcmp(term, "screen") == 0 || strcmp(term, "rxvt-unicode") == 0 || | |
145 strcmp(term, "xterm") == 0) | |
146 *(text + 1) = 'O'; | |
147 } else if (*(unsigned char*)text == 195) { | |
148 if (*(text + 2) == 0 && strcmp(term, "xterm") == 0) { | |
149 *(text) = 27; | |
150 *(text + 1) -= 64; /* Say wha? */ | |
151 } | |
152 } | |
153 } | |
154 | |
155 const char *gnt_key_translate(const char *name) | |
156 { | |
18423
48067a8f6a32
Do not crash on NULL checks.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18057
diff
changeset
|
157 return name ? g_hash_table_lookup(specials, name) : NULL; |
15818 | 158 } |
159 | |
15979
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
160 typedef struct { |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
161 const char *name; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
162 const char *key; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
163 } gntkey; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
164 |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
165 static void |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
166 get_key_name(gpointer key, gpointer value, gpointer data) |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
167 { |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
168 gntkey *k = data; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
169 if (k->name) |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
170 return; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
171 if (g_utf8_collate(value, k->key) == 0) |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
172 k->name = key; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
173 } |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
174 |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
175 const char *gnt_key_lookup(const char *key) |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
176 { |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
177 gntkey k = {NULL, key}; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
178 g_hash_table_foreach(specials, get_key_name, &k); |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
179 return k.name; |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
180 } |
2c81ebc7bf0b
Add a way to get a list of bindings for a widget. This can be used by, eg, a window-manager to show helpful messages to the user.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
181 |
15818 | 182 /** |
183 * The key-bindings will be saved in a tree. When a keystroke happens, GNT will | |
184 * find the sequence that matches a binding and return the length. | |
185 * A sequence should not be a prefix of another sequence. If it is, then only | |
186 * the shortest one will be processed. If we want to change that, we will need | |
187 * to allow getting the k-th prefix that matches the input, and pay attention | |
188 * to the return value of gnt_wm_process_input in gntmain.c. | |
189 */ | |
190 #define SIZE 256 | |
191 | |
192 #define IS_END 1 << 0 | |
193 struct _node | |
194 { | |
195 struct _node *next[SIZE]; | |
196 int ref; | |
197 int flags; | |
198 }; | |
199 | |
200 static struct _node root = {.ref = 1, .flags = 0}; | |
201 | |
202 static void add_path(struct _node *node, const char *path) | |
203 { | |
204 struct _node *n = NULL; | |
205 if (!path || !*path) { | |
206 node->flags |= IS_END; | |
207 return; | |
208 } | |
18057
23b03396e71e
Eliminate warnings about array subscripts being char. They can be signed,
Richard Laager <rlaager@wiktel.com>
parents:
18049
diff
changeset
|
209 while (*path && node->next[(unsigned char)*path]) { |
23b03396e71e
Eliminate warnings about array subscripts being char. They can be signed,
Richard Laager <rlaager@wiktel.com>
parents:
18049
diff
changeset
|
210 node = node->next[(unsigned char)*path]; |
15818 | 211 node->ref++; |
212 path++; | |
213 } | |
214 if (!*path) | |
215 return; | |
216 n = g_new0(struct _node, 1); | |
217 n->ref = 1; | |
18057
23b03396e71e
Eliminate warnings about array subscripts being char. They can be signed,
Richard Laager <rlaager@wiktel.com>
parents:
18049
diff
changeset
|
218 node->next[(unsigned char)*path++] = n; |
15818 | 219 add_path(n, path); |
220 } | |
221 | |
222 void gnt_keys_add_combination(const char *path) | |
223 { | |
224 add_path(&root, path); | |
225 } | |
226 | |
227 static void del_path(struct _node *node, const char *path) | |
228 { | |
229 struct _node *next = NULL; | |
230 | |
231 if (!*path) | |
232 return; | |
18057
23b03396e71e
Eliminate warnings about array subscripts being char. They can be signed,
Richard Laager <rlaager@wiktel.com>
parents:
18049
diff
changeset
|
233 next = node->next[(unsigned char)*path]; |
15818 | 234 if (!next) |
235 return; | |
236 del_path(next, path + 1); | |
237 next->ref--; | |
238 if (next->ref == 0) { | |
18057
23b03396e71e
Eliminate warnings about array subscripts being char. They can be signed,
Richard Laager <rlaager@wiktel.com>
parents:
18049
diff
changeset
|
239 node->next[(unsigned char)*path] = NULL; |
15818 | 240 g_free(next); |
241 } | |
242 } | |
243 | |
244 void gnt_keys_del_combination(const char *path) | |
245 { | |
246 del_path(&root, path); | |
247 } | |
248 | |
249 int gnt_keys_find_combination(const char *path) | |
250 { | |
251 int depth = 0; | |
252 struct _node *n = &root; | |
253 | |
254 root.flags &= ~IS_END; | |
18057
23b03396e71e
Eliminate warnings about array subscripts being char. They can be signed,
Richard Laager <rlaager@wiktel.com>
parents:
18049
diff
changeset
|
255 while (*path && n->next[(unsigned char)*path] && !(n->flags & IS_END)) { |
16044
ca463cecd432
Only ascii keys can be bound, fixes a crash when inputting non-ascii chars
Richard Nelson <wabz@pidgin.im>
parents:
15979
diff
changeset
|
256 if (!g_ascii_isspace(*path) && |
ca463cecd432
Only ascii keys can be bound, fixes a crash when inputting non-ascii chars
Richard Nelson <wabz@pidgin.im>
parents:
15979
diff
changeset
|
257 !g_ascii_iscntrl(*path) && |
ca463cecd432
Only ascii keys can be bound, fixes a crash when inputting non-ascii chars
Richard Nelson <wabz@pidgin.im>
parents:
15979
diff
changeset
|
258 !g_ascii_isgraph(*path)) |
15818 | 259 return 0; |
18057
23b03396e71e
Eliminate warnings about array subscripts being char. They can be signed,
Richard Laager <rlaager@wiktel.com>
parents:
18049
diff
changeset
|
260 n = n->next[(unsigned char)*path++]; |
15818 | 261 depth++; |
262 } | |
263 | |
264 if (!(n->flags & IS_END)) | |
265 depth = 0; | |
266 return depth; | |
267 } | |
268 | |
269 static void | |
270 print_path(struct _node *node, int depth) | |
271 { | |
272 int i; | |
273 for (i = 0; i < SIZE; i++) { | |
274 if (node->next[i]) { | |
275 g_printerr("%*c (%d:%d)\n", depth * 4, i, node->next[i]->ref, | |
276 node->next[i]->flags); | |
277 print_path(node->next[i], depth + 1); | |
278 } | |
279 } | |
280 } | |
281 | |
282 /* this is purely for debugging purposes. */ | |
283 void gnt_keys_print_combinations(void); | |
284 void gnt_keys_print_combinations() | |
285 { | |
286 g_printerr("--------\n"); | |
287 print_path(&root, 1); | |
288 g_printerr("--------\n"); | |
289 } | |
290 |