/*
elmo - ELectronic Mail Operator
Copyright (C) 2003, 2004 rzyjontko
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; version 2.
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 program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
----------------------------------------------------------------------
*/
/****************************************************************************
* IMPLEMENTATION HEADERS
****************************************************************************/
#include "keymap.h"
#include "xmalloc.h"
#include "error.h"
#include "exec.h"
/****************************************************************************
* IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS
****************************************************************************/
#define FIRST_ALLOC 10
/****************************************************************************
* IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES
****************************************************************************/
/****************************************************************************
* IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES
****************************************************************************/
/****************************************************************************
* IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID)
****************************************************************************/
/****************************************************************************
* IMPLEMENTATION PRIVATE DATA
****************************************************************************/
static int no_default = 0;
/****************************************************************************
* INTERFACE DATA
****************************************************************************/
keymap_t keymap_default;
/****************************************************************************
* IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES
****************************************************************************/
/****************************************************************************
* IMPLEMENTATION PRIVATE FUNCTIONS
****************************************************************************/
static void
reallocate (keymap_t *km)
{
if (km->k_size == km->k_count){
km->k_size = (km->k_size + 1) * 2;
km->keys = xrealloc (km->keys,
km->k_size * sizeof (struct key));
}
if (km->m_size == km->m_count){
km->m_size = (km->m_size + 1) * 2;
km->meta = xrealloc (km->meta,
km->m_size * sizeof (struct key));
}
}
static void
execute (struct key *k)
{
exec_run (k->exec);
}
/****************************************************************************
* INTERFACE FUNCTIONS
****************************************************************************/
void
keymap_init (keymap_t *km)
{
km->k_size = FIRST_ALLOC;
km->k_count = 0;
km->keys = xmalloc (km->k_size * sizeof (struct key));
km->m_size = FIRST_ALLOC;
km->m_count = 0;
km->meta = xmalloc (km->m_size * sizeof (struct key));
}
void
keymap_destroy (keymap_t *km)
{
if (km->keys)
xfree (km->keys);
if (km->meta)
xfree (km->meta);
}
struct key *
keymap_lookup (keymap_t *km, int key, int no_default)
{
int i;
for (i = 0; i < km->k_count; i++){
if (km->keys[i].key == key)
return km->keys + i;
}
if (no_default)
return NULL;
for (i = 0; i < keymap_default.k_count; i++){
if (keymap_default.keys[i].key == key)
return keymap_default.keys + i;
}
return NULL;
}
struct key *
keymap_meta_lookup (keymap_t *km, int key, int no_default)
{
int i;
for (i = 0; i < km->m_count; i++){
if (km->meta[i].key == key)
return km->meta + i;
}
if (no_default)
return NULL;
for (i = 0; i < keymap_default.m_count; i++){
if (keymap_default.meta[i].key == key)
return keymap_default.meta + i;
}
return NULL;
}
struct key *
keymap_lookup_fun (keymap_t *km, void (*fun)(void))
{
int i;
exec_t *exec = exec_lookup_fun (fun);
if (exec == NULL)
return NULL;
for (i = 0; i < km->k_count; i++){
if (km->keys[i].exec == exec)
return km->keys + i;
}
if (no_default)
return NULL;
for (i = 0; i < keymap_default.k_count; i++){
if (keymap_default.keys[i].exec == exec){
if (keymap_lookup (km, keymap_default.keys[i].key, 1))
return NULL;
return keymap_default.keys + i;
}
}
return NULL;
}
void
keymap_add (keymap_t *km, int key, int meta, void (*fun)(void))
{
struct key *k;
exec_t *exec = exec_lookup_fun (fun);
if (meta)
k = keymap_meta_lookup (km, key, 1);
else
k = keymap_lookup (km, key, 1);
if (k){
k->exec = exec;
return;
}
reallocate (km);
if (! meta){
km->keys[km->k_count].key = key;
km->keys[km->k_count].exec = exec;
km->k_count++;
}
else {
km->meta[km->m_count].key = key;
km->meta[km->m_count].exec = exec;
km->m_count++;
}
}
int
keymap_action (keymap_t *km, int key, int meta)
{
struct key *k;
if (meta)
k = keymap_meta_lookup (km, key, no_default);
else
k = keymap_lookup (km, key, no_default);
if (k){
execute (k);
return 0;
}
return 1;
}
void
keymap_disable_default (void)
{
no_default = 1;
}
void
keymap_enable_default (void)
{
no_default = 0;
}
/****************************************************************************
* INTERFACE CLASS BODIES
****************************************************************************/
/****************************************************************************
*
* END MODULE keymap.c
*
****************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1