1 /*
2 * $Id: key.c,v 1.8 2001/02/13 23:38:06 danny Exp $
3 *
4 * Copyright � 1993, 2001 Free Software Foundation, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this software; see the file COPYING. If not, write to
18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #ifdef WITH_DMALLOC
25 #include <dmalloc.h>
26 #endif
27
28 #include <ctype.h>
29
30 #include "key.h"
31 #include "cmd.h"
32 #include "io-abstract.h"
33 #include "io-generic.h"
34 #include "io-utils.h"
35 #include "io-term.h"
36
37 struct keymap **the_maps;
38 char **map_names;
39 char **map_prompts;
40 int num_maps;
41 struct cmd_func **the_funcs;
42 int num_funcs;
43
44
45 int
search_map_for_cmd(struct line * line,int map,int vec,int code)46 search_map_for_cmd (struct line * line, int map, int vec, int code)
47 {
48 int len = strlen (line->buf);
49 struct keymap * this_map;
50 int x;
51 char used[OLEO_NUM_KEYS];
52 int try_prefix;
53
54 for (try_prefix = 0; try_prefix < 2; ++try_prefix)
55 {
56 bzero (used, sizeof (used));
57
58 for (this_map = the_maps[map]; this_map; this_map = this_map->map_next)
59 {
60 for (x = 128; x >= 0; --x)
61 if (!used[x])
62 {
63 int found_it = ((this_map->keys[x].vector == vec)
64 && this_map->keys[x].code == code);
65 int prefix_key = ((this_map->keys[x].vector == -1)
66 && (this_map->keys[x].code != -1));
67 if (!( (this_map->keys[x].vector == -1)
68 && (this_map->keys[x].code == -1)))
69 used[x] = 1;
70 if (found_it || (try_prefix && prefix_key))
71 {
72 char * c = char_to_string (x);
73 catn_line (line, " ", 1);
74 catn_line (line, c, strlen (c));
75 if (found_it
76 || (try_prefix
77 && search_map_for_cmd (line,
78 this_map->keys[x].code,
79 vec, code)))
80 return 1;
81 line->buf[len] = 0;
82 }
83 }
84 }
85 }
86 return 0;
87 }
88
89 static void
do_bind_key(struct keymap * m,int key,int vector,int code)90 do_bind_key (struct keymap *m, int key, int vector, int code)
91 {
92 m->keys[key].vector = (short)vector;
93 m->keys[key].code = (short)code;
94 }
95
96
97 void
bind_key(char * keymap,char * function,int ch)98 bind_key (char * keymap, char * function, int ch)
99 {
100 struct cmd_func * tmpfunc;
101 int map = map_id (keymap);
102 int vec;
103 int code;
104 struct rng rng;
105 struct cmd_func * cmd;
106
107 if (map < 0)
108 {
109 io_error_msg ("bind_key: bad keymap.");
110 return;
111 }
112
113 if (!find_func (&vec, &cmd, function))
114 {
115 code = (cmd - the_funcs[vec]);
116 goto fini;
117 }
118
119 for (code = 0; code < num_maps; code++)
120 {
121 if (!strcmp (function, map_names[code]))
122 {
123 vec = -1;
124 goto fini;
125 }
126 }
127 if (get_abs_rng (&function, &rng))
128 {
129 io_error_msg ("Unknown command '%s'", function);
130 return;
131 }
132
133 for (code = 0; code < n_bound_macros; code++)
134 {
135 if (!bcmp (&bound_macros[code], &rng, sizeof (struct rng)))
136 goto fini;
137 }
138
139 function = range_name (&rng);
140 if (!bound_macro_vec)
141 {
142 bound_macros = ck_malloc (sizeof (struct rng));
143 n_bound_macros = 1;
144 tmpfunc = (struct cmd_func *)ck_malloc (2 * sizeof (struct cmd_func));
145 bzero (tmpfunc + 1, sizeof (*tmpfunc));
146 bound_macro_vec = add_usr_cmds (tmpfunc);
147 }
148 else
149 {
150 n_bound_macros++;
151 bound_macros = ck_realloc (bound_macros,
152 n_bound_macros * sizeof (struct rng));
153 the_funcs[bound_macro_vec]
154 = ck_realloc (the_funcs[bound_macro_vec],
155 (1 + n_bound_macros) * sizeof (struct cmd_func));
156 tmpfunc = &the_funcs[bound_macro_vec][n_bound_macros - 1];
157 bzero (tmpfunc + 1, sizeof (*tmpfunc));
158 }
159 vec = bound_macro_vec;
160 bound_macros[n_bound_macros - 1] = rng;
161 tmpfunc->func_args = (char **)ck_malloc (2 * sizeof (char *));
162 tmpfunc->func_args[0] = mk_sprintf ("#%d", n_bound_macros - 1);
163 tmpfunc->func_args[1] = 0;
164 tmpfunc->init_code = 0;
165 tmpfunc->func_doc = 0;
166 tmpfunc->func_name = ck_savestr (function);
167 tmpfunc->func_func = bound_macro;
168 fini:
169 do_bind_key (the_maps[map], ch, vec, code);
170 }
171
172 void
unbind_key(char * keymap,int ch)173 unbind_key (char * keymap, int ch)
174 {
175 int map = map_id (keymap);
176 struct keymap *m;
177 m = the_maps[map];
178 m->keys[ch].vector = -1;
179 m->keys[ch].code = -1;
180 }
181
182 void
bind_or_unbind_set(char * keymap,char * command,char * keyset)183 bind_or_unbind_set (char * keymap, char * command, char * keyset)
184 {
185 int first;
186 int last;
187 first = string_to_char (&keyset);
188 if (first < 0)
189 {
190 io_error_msg ("Invalid character set.");
191 return;
192 }
193 while (isspace (*keyset))
194 ++keyset;
195 if (*keyset == '-')
196 {
197 ++keyset;
198 last = string_to_char (&keyset);
199 if (last < 0)
200 {
201 io_error_msg ("Unterminated character set.");
202 return;
203 }
204 }
205 else if (*keyset)
206 {
207 io_error_msg ("Extra characters in keyset: `%s'.",
208 keyset);
209 return;
210 }
211 else
212 last = first;
213
214 while (first <= last)
215 {
216 if (command != "0")
217 bind_key (keymap, command, first);
218 else
219 unbind_key (keymap, first);
220 ++first;
221 }
222 }
223
unbind_set(char * keymap,char * keyset)224 void unbind_set (char *keymap, char *keyset)
225 {
226 char *command = "0";
227 bind_or_unbind_set (keymap, command, keyset);
228 }
229
230 void
bind_all_keys(char * keymap,char * function)231 bind_all_keys (char * keymap, char * function)
232 {
233 struct cmd_func * tmpfunc;
234 int map = map_id (keymap);
235 int vec;
236 int code;
237 struct rng rng;
238 struct cmd_func * cmd;
239
240 if (map < 0)
241 {
242 io_error_msg ("bind_key: bad keymap.");
243 return;
244 }
245
246 if (!find_func (&vec, &cmd, function))
247 {
248 code = (cmd - the_funcs[vec]);
249 goto fini;
250 }
251
252 for (code = 0; code < num_maps; code++)
253 {
254 if (!strcmp (function, map_names[code]))
255 {
256 vec = -1;
257 goto fini;
258 }
259 }
260 if (get_abs_rng (&function, &rng))
261 {
262 io_error_msg ("Unknown command '%s'", function);
263 return;
264 }
265
266 vec = bound_macro_vec;
267 for (code = 0; code < n_bound_macros; code++)
268 {
269 if (!bcmp (&bound_macros[code], &rng, sizeof (struct rng)))
270 goto fini;
271 }
272
273 function = range_name (&rng);
274 if (!bound_macro_vec)
275 {
276 bound_macros = ck_malloc (sizeof (struct rng));
277 n_bound_macros = 1;
278 tmpfunc = (struct cmd_func *)ck_malloc (2 * sizeof (struct cmd_func));
279 bzero (tmpfunc + 1, sizeof (*tmpfunc));
280 bound_macro_vec = add_usr_cmds (tmpfunc);
281 }
282 else
283 {
284 n_bound_macros++;
285 bound_macros = ck_realloc (bound_macros,
286 n_bound_macros * sizeof (struct rng));
287 the_funcs[bound_macro_vec]
288 = ck_realloc (the_funcs[bound_macro_vec],
289 (1 + n_bound_macros) * sizeof (struct cmd_func));
290 tmpfunc = &the_funcs[bound_macro_vec][n_bound_macros - 1];
291 bzero (tmpfunc + 1, sizeof (*tmpfunc));
292 }
293 bound_macros[n_bound_macros - 1] = rng;
294 tmpfunc->func_args = (char **)ck_malloc (2 * sizeof (char *));
295 tmpfunc->func_args[0] = mk_sprintf ("#%d", n_bound_macros - 1);
296 tmpfunc->func_args[1] = 0;
297 tmpfunc->func_doc = 0;
298 tmpfunc->func_name = ck_savestr (function);
299 tmpfunc->func_func = bound_macro;
300 fini:
301 {
302 int ch;
303 for (ch = 0; ch < OLEO_NUM_KEYS; ++ch)
304 do_bind_key (the_maps[map], ch, vec, code);
305 }
306 }
307
308
309 void
write_keys_cmd(FILE * fp)310 write_keys_cmd (FILE *fp)
311 {
312 struct keymap *map;
313 int n;
314 int key;
315 int vec;
316 int code;
317
318 for (n = 0; n < num_maps; n++)
319 {
320 char *def;
321 map = the_maps[n];
322 def = 0;
323 if (map && map->map_next)
324 {
325 for (key = 0; key < num_maps; key++)
326 if (the_maps[key] == map->map_next)
327 {
328 def = map_names[key];
329 break;
330 }
331 }
332 if (def)
333 fprintf (fp, "create-keymap %s %s\n", map_names[n], def);
334 else
335 fprintf (fp, "create-keymap %s\n", map_names[n]);
336 }
337 for (n = 0; n < num_maps; n++)
338 {
339 map = the_maps[n];
340 for (key = 0; key < OLEO_NUM_KEYS; key++)
341 {
342 vec = map->keys[key].vector;
343 code = map->keys[key].code;
344 if (vec < 0 && code >= 0)
345 fprintf (fp, "bind-key %s %s %s\n",
346 map_names[n],
347 map_names[code],
348 char_to_string (key));
349 else if (vec >= 0)
350 fprintf (fp, "bind-key %s %s %s\n",
351 map_names[n],
352 the_funcs[vec][code].func_name,
353 char_to_string (key));
354 }
355 }
356 }
357
358
359
360 void
clear_keymap(struct keymap * m)361 clear_keymap (struct keymap *m)
362 {
363 int n;
364 for (n = 0; n < OLEO_NUM_KEYS; n++)
365 {
366 m->keys[n].vector = -1;
367 m->keys[n].code = -1;
368 }
369 }
370
371 int
map_idn(const char * name,int n)372 map_idn (const char *name, int n)
373 {
374 int x;
375 for (x = 0; x < num_maps; ++x)
376 if (!strincmp (name, map_names[x], n))
377 return x;
378 return -1;
379 }
380
381 int
map_id(const char * name)382 map_id(const char *name)
383 {
384 return map_idn(name, strlen(name));
385 }
386
387 void
create_keymap(char * mapname,char * parentname)388 create_keymap (char * mapname, char * parentname)
389 {
390 int map = map_id (mapname);
391 int parent = parentname ? map_id (parentname) : -1;
392
393 if (map >= 0)
394 {
395 io_info_msg ("Map %s already exists.", mapname);
396 return;
397 }
398 if (parentname && (parent < 0))
399 {
400 io_error_msg ("Map %s does not exist.", parentname);
401 return;
402 }
403 the_maps = ck_realloc (the_maps, (num_maps + 1) * sizeof (struct keymap *));
404 the_maps[num_maps] = ck_malloc (sizeof (struct keymap));
405 the_maps[num_maps]->id = num_maps;
406 the_maps[num_maps]->map_next = ((parent >= 0)
407 ? the_maps[parent]
408 : 0);
409 {
410 int c;
411 for (c = 0; c < OLEO_NUM_KEYS; ++c)
412 {
413 the_maps[num_maps]->keys[c].vector = -1;
414 the_maps[num_maps]->keys[c].code = -1;
415 }
416 }
417 map_names = ck_realloc (map_names, (num_maps + 1) * sizeof (char *));
418 map_prompts = ck_realloc (map_prompts, (num_maps + 1) * sizeof (char *));
419 map_names[num_maps] = ck_savestr (mapname);
420 map_prompts[num_maps] = 0;
421 num_maps++;
422 }
423
424
425 void
set_map_prompt(char * map,char * str)426 set_map_prompt (char * map, char * str)
427 {
428 int id = map_id (map);
429 if (id < 0)
430 io_error_msg ("No such keymap as %s.", map); /* No return. */
431 if (map_prompts[id])
432 free (map_prompts [id]);
433 map_prompts[id] = ck_savestr (str);
434 }
435