/*
* $Id: key.c,v 1.8 2001/02/13 23:38:06 danny Exp $
*
* Copyright © 1993, 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef WITH_DMALLOC
#include <dstdlib.h>
#endif
#include <ctype.h>
#include "key.h"
#include "cmd.h"
#include "io-abstract.h"
#include "io-generic.h"
#include "io-utils.h"
#include "io-term.h"
struct keymap **the_maps;
char **map_names;
char **map_prompts;
int num_maps;
struct cmd_func **the_funcs;
int num_funcs;
int
search_map_for_cmd (struct line * line, int map, int vec, int code)
{
int len = strlen (line->buf);
struct keymap * this_map;
int x;
char used[OLEO_NUM_KEYS];
int try_prefix;
for (try_prefix = 0; try_prefix < 2; ++try_prefix)
{
bzero (used, sizeof (used));
for (this_map = the_maps[map]; this_map; this_map = this_map->map_next)
{
for (x = 128; x >= 0; --x)
if (!used[x])
{
int found_it = ((this_map->keys[x].vector == vec)
&& this_map->keys[x].code == code);
int prefix_key = ((this_map->keys[x].vector == -1)
&& (this_map->keys[x].code != -1));
if (!( (this_map->keys[x].vector == -1)
&& (this_map->keys[x].code == -1)))
used[x] = 1;
if (found_it || (try_prefix && prefix_key))
{
char * c = char_to_string (x);
catn_line (line, " ", 1);
catn_line (line, c, strlen (c));
if (found_it
|| (try_prefix
&& search_map_for_cmd (line,
this_map->keys[x].code,
vec, code)))
return 1;
line->buf[len] = 0;
}
}
}
}
return 0;
}
static void
do_bind_key (struct keymap *m, int key, int vector, int code)
{
m->keys[key].vector = (short)vector;
m->keys[key].code = (short)code;
}
void
bind_key (char * keymap, char * function, int ch)
{
struct cmd_func * tmpfunc;
int map = map_id (keymap);
int vec;
int code;
struct rng rng;
struct cmd_func * cmd;
if (map < 0)
{
io_error_msg ("bind_key: bad keymap.");
return;
}
if (!find_func (&vec, &cmd, function))
{
code = (cmd - the_funcs[vec]);
goto fini;
}
for (code = 0; code < num_maps; code++)
{
if (!strcmp (function, map_names[code]))
{
vec = -1;
goto fini;
}
}
if (get_abs_rng (&function, &rng))
{
io_error_msg ("Unknown command '%s'", function);
return;
}
for (code = 0; code < n_bound_macros; code++)
{
if (!bcmp (&bound_macros[code], &rng, sizeof (struct rng)))
goto fini;
}
function = range_name (&rng);
if (!bound_macro_vec)
{
bound_macros = ck_malloc (sizeof (struct rng));
n_bound_macros = 1;
tmpfunc = (struct cmd_func *)ck_malloc (2 * sizeof (struct cmd_func));
bzero (tmpfunc + 1, sizeof (*tmpfunc));
bound_macro_vec = add_usr_cmds (tmpfunc);
}
else
{
n_bound_macros++;
bound_macros = ck_realloc (bound_macros,
n_bound_macros * sizeof (struct rng));
the_funcs[bound_macro_vec]
= ck_realloc (the_funcs[bound_macro_vec],
(1 + n_bound_macros) * sizeof (struct cmd_func));
tmpfunc = &the_funcs[bound_macro_vec][n_bound_macros - 1];
bzero (tmpfunc + 1, sizeof (*tmpfunc));
}
vec = bound_macro_vec;
bound_macros[n_bound_macros - 1] = rng;
tmpfunc->func_args = (char **)ck_malloc (2 * sizeof (char *));
tmpfunc->func_args[0] = mk_sprintf ("#%d", n_bound_macros - 1);
tmpfunc->func_args[1] = 0;
tmpfunc->init_code = 0;
tmpfunc->func_doc = 0;
tmpfunc->func_name = ck_savestr (function);
tmpfunc->func_func = bound_macro;
fini:
do_bind_key (the_maps[map], ch, vec, code);
}
void
unbind_key (char * keymap, int ch)
{
int map = map_id (keymap);
struct keymap *m;
m = the_maps[map];
m->keys[ch].vector = -1;
m->keys[ch].code = -1;
}
void
bind_or_unbind_set (char * keymap, char * command, char * keyset)
{
int first;
int last;
first = string_to_char (&keyset);
if (first < 0)
{
io_error_msg ("Invalid character set.");
return;
}
while (isspace (*keyset))
++keyset;
if (*keyset == '-')
{
++keyset;
last = string_to_char (&keyset);
if (last < 0)
{
io_error_msg ("Unterminated character set.");
return;
}
}
else if (*keyset)
{
io_error_msg ("Extra characters in keyset: `%s'.",
keyset);
return;
}
else
last = first;
while (first <= last)
{
if (command != "0")
bind_key (keymap, command, first);
else
unbind_key (keymap, first);
++first;
}
}
void unbind_set (char *keymap, char *keyset)
{
char *command = "0";
bind_or_unbind_set (keymap, command, keyset);
}
void
bind_all_keys (char * keymap, char * function)
{
struct cmd_func * tmpfunc;
int map = map_id (keymap);
int vec;
int code;
struct rng rng;
struct cmd_func * cmd;
if (map < 0)
{
io_error_msg ("bind_key: bad keymap.");
return;
}
if (!find_func (&vec, &cmd, function))
{
code = (cmd - the_funcs[vec]);
goto fini;
}
for (code = 0; code < num_maps; code++)
{
if (!strcmp (function, map_names[code]))
{
vec = -1;
goto fini;
}
}
if (get_abs_rng (&function, &rng))
{
io_error_msg ("Unknown command '%s'", function);
return;
}
vec = bound_macro_vec;
for (code = 0; code < n_bound_macros; code++)
{
if (!bcmp (&bound_macros[code], &rng, sizeof (struct rng)))
goto fini;
}
function = range_name (&rng);
if (!bound_macro_vec)
{
bound_macros = ck_malloc (sizeof (struct rng));
n_bound_macros = 1;
tmpfunc = (struct cmd_func *)ck_malloc (2 * sizeof (struct cmd_func));
bzero (tmpfunc + 1, sizeof (*tmpfunc));
bound_macro_vec = add_usr_cmds (tmpfunc);
}
else
{
n_bound_macros++;
bound_macros = ck_realloc (bound_macros,
n_bound_macros * sizeof (struct rng));
the_funcs[bound_macro_vec]
= ck_realloc (the_funcs[bound_macro_vec],
(1 + n_bound_macros) * sizeof (struct cmd_func));
tmpfunc = &the_funcs[bound_macro_vec][n_bound_macros - 1];
bzero (tmpfunc + 1, sizeof (*tmpfunc));
}
bound_macros[n_bound_macros - 1] = rng;
tmpfunc->func_args = (char **)ck_malloc (2 * sizeof (char *));
tmpfunc->func_args[0] = mk_sprintf ("#%d", n_bound_macros - 1);
tmpfunc->func_args[1] = 0;
tmpfunc->func_doc = 0;
tmpfunc->func_name = ck_savestr (function);
tmpfunc->func_func = bound_macro;
fini:
{
int ch;
for (ch = 0; ch < OLEO_NUM_KEYS; ++ch)
do_bind_key (the_maps[map], ch, vec, code);
}
}
void
write_keys_cmd (FILE *fp)
{
struct keymap *map;
int n;
int key;
int vec;
int code;
for (n = 0; n < num_maps; n++)
{
char *def;
map = the_maps[n];
def = 0;
if (map && map->map_next)
{
for (key = 0; key < num_maps; key++)
if (the_maps[key] == map->map_next)
{
def = map_names[key];
break;
}
}
if (def)
fprintf (fp, "create-keymap %s %s\n", map_names[n], def);
else
fprintf (fp, "create-keymap %s\n", map_names[n]);
}
for (n = 0; n < num_maps; n++)
{
map = the_maps[n];
for (key = 0; key < OLEO_NUM_KEYS; key++)
{
vec = map->keys[key].vector;
code = map->keys[key].code;
if (vec < 0 && code >= 0)
fprintf (fp, "bind-key %s %s %s\n",
map_names[n],
map_names[code],
char_to_string (key));
else if (vec >= 0)
fprintf (fp, "bind-key %s %s %s\n",
map_names[n],
the_funcs[vec][code].func_name,
char_to_string (key));
}
}
}
void
clear_keymap (struct keymap *m)
{
int n;
for (n = 0; n < OLEO_NUM_KEYS; n++)
{
m->keys[n].vector = -1;
m->keys[n].code = -1;
}
}
int
map_idn (const char *name, int n)
{
int x;
for (x = 0; x < num_maps; ++x)
if (!strincmp (name, map_names[x], n))
return x;
return -1;
}
int
map_id(const char *name)
{
return map_idn(name, strlen(name));
}
void
create_keymap (char * mapname, char * parentname)
{
int map = map_id (mapname);
int parent = parentname ? map_id (parentname) : -1;
if (map >= 0)
{
io_info_msg ("Map %s already exists.", mapname);
return;
}
if (parentname && (parent < 0))
{
io_error_msg ("Map %s does not exist.", parentname);
return;
}
the_maps = ck_realloc (the_maps, (num_maps + 1) * sizeof (struct keymap *));
the_maps[num_maps] = ck_malloc (sizeof (struct keymap));
the_maps[num_maps]->id = num_maps;
the_maps[num_maps]->map_next = ((parent >= 0)
? the_maps[parent]
: 0);
{
int c;
for (c = 0; c < OLEO_NUM_KEYS; ++c)
{
the_maps[num_maps]->keys[c].vector = -1;
the_maps[num_maps]->keys[c].code = -1;
}
}
map_names = ck_realloc (map_names, (num_maps + 1) * sizeof (char *));
map_prompts = ck_realloc (map_prompts, (num_maps + 1) * sizeof (char *));
map_names[num_maps] = ck_savestr (mapname);
map_prompts[num_maps] = 0;
num_maps++;
}
void
set_map_prompt (char * map, char * str)
{
int id = map_id (map);
if (id < 0)
io_error_msg ("No such keymap as %s.", map); /* No return. */
if (map_prompts[id])
free (map_prompts [id]);
map_prompts[id] = ck_savestr (str);
}
syntax highlighted by Code2HTML, v. 0.9.1