/*
elmo - ELectronic Mail Operator
Copyright (C) 2002, 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.
----------------------------------------------------------------------
handles command loop
*/
/****************************************************************************
* IMPLEMENTATION HEADERS
****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <ctype.h>
#include "ecurses.h"
#include "cmd.h"
#include "status.h"
#include "folder.h"
#include "mailreader.h"
#include "error.h"
#include "elmo.h"
#include "box_selection.h"
#include "xmalloc.h"
#include "fetch.h"
#include "confread.h"
#include "compose.h"
#include "sender.h"
#include "attach.h"
#include "abook.h"
#include "read.h"
#include "exec.h"
#include "keymap.h"
#include "hook.h"
#include "choose.h"
#include "ask.h"
#include "bayes.h"
#include "gettext.h"
#include "help.h"
#include "color.h"
#include "interface.h"
#include "debug.h"
#include "smtp.h"
#include "pgp.h"
#include "select.h"
/****************************************************************************
* IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS
****************************************************************************/
#define STACK_SIZE 10
#ifndef DEBUG
# define DEBUG 0
#endif
/****************************************************************************
* IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES
****************************************************************************/
/****************************************************************************
* IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES
****************************************************************************/
struct fd_handler {
struct fd_handler *next;
int fd;
void (*handler)(int);
};
/****************************************************************************
* IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID)
****************************************************************************/
/****************************************************************************
* IMPLEMENTATION PRIVATE DATA
****************************************************************************/
/* Each keymap is bound to a particular state. Opening a window usually
pushes new state on the stack, and closing - pops the state from the top
of the stack. Switching between windows works in the same manner.
Elmo determines action by watching at a keymap bound to the state on the
top of the stack. */
static cmd_state_t state_stack[STACK_SIZE];
static cmd_state_t *state_top;
/* Colors used to display messages in echo area. */
static chtype text_color;
static chtype error_color;
/* Lists of handlers for read, and write descriptors used in select call. */
static struct fd_handler *readfd_list = NULL;
static struct fd_handler *writefd_list = NULL;
/* List of functions to execute on timeout. */
static struct fd_handler *timeout_list = NULL;
/* This is the last character - input from user. */
static int last_char = 0;
/* We use digits as prefix arguments to functions. */
static int prefix_arg = 0;
/****************************************************************************
* INTERFACE DATA
****************************************************************************/
/* Echo area window. It is not static because error.c uses this window
to display error messages, and read.c uses this window to read the
input string. */
WINDOW *cmd_win = NULL;
/* These are keymaps, and hooks bindings. The array is indexed with state
number. */
keymap_t keymaps[CMD_STATE_COUNT];
/****************************************************************************
* IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES
****************************************************************************/
static void destroy_keymaps (void);
static void destroy_list (struct fd_handler *list);
/****************************************************************************
* IMPLEMENTATION PRIVATE FUNCTIONS
****************************************************************************/
static void
quit (void)
{
destroy_keymaps ();
destroy_list (readfd_list);
destroy_list (writefd_list);
destroy_list (timeout_list);
readfd_list = NULL;
writefd_list = NULL;
timeout_list = NULL;
elmo_finish (0);
exit (EXIT_SUCCESS);
}
static void
init_keymaps (void)
{
int i;
for (i = 0; i < CMD_STATE_COUNT; i++)
keymap_init (keymaps + i);
keymap_init (&keymap_default);
for (i = '0'; i < '9'; i++)
keymap_add (& keymap_default, i, 1, interface_num_window);
keymap_add (&keymap_default, 12, 0, interface_redraw);
keymap_add (&keymap_default, '\t', 0, interface_next_window);
keymap_add (&keymap_default, 'q', 0, cmd_quit);
keymap_add (&keymap_default, '?', 0, help_open);
keymap_add (&keymap_default, 'h', 0, help_open);
keymap_add (&keymap_default, KEY_F (1), 0, help_open);
keymap_add (&keymap_default, 6, 0, pgp_forget_passphrase);
keymap_add (keymaps + CMD_LIST, KEY_PPAGE, 0, folder_page_prev);
keymap_add (keymaps + CMD_LIST, KEY_NPAGE, 0, folder_page_next);
keymap_add (keymaps + CMD_LIST, KEY_HOME, 0, folder_bar_first);
keymap_add (keymaps + CMD_LIST, KEY_END, 0, folder_bar_last);
keymap_add (keymaps + CMD_LIST, KEY_UP, 0, folder_bar_prev);
keymap_add (keymaps + CMD_LIST, KEY_DOWN, 0, folder_bar_next);
keymap_add (keymaps + CMD_LIST, KEY_DC, 0, folder_delete_mail);
keymap_add (keymaps + CMD_LIST, 'K', 0, folder_kill_mail);
keymap_add (keymaps + CMD_LIST, 'd', 0, folder_sort_date);
keymap_add (keymaps + CMD_LIST, 't', 0, folder_sort_threads);
keymap_add (keymaps + CMD_LIST, 'A', 0, folder_sort_from);
keymap_add (keymaps + CMD_LIST, 's', 0, folder_sort_subject);
keymap_add (keymaps + CMD_LIST, 'a', 0, abook_show);
keymap_add (keymaps + CMD_LIST, '\r', 0, mailreader_show);
keymap_add (keymaps + CMD_LIST, 'F', 0, fetch_open);
keymap_add (keymaps + CMD_LIST, 'm', 0, sender_open_new);
keymap_add (keymaps + CMD_LIST, 'r', 0, sender_open_reply);
keymap_add (keymaps + CMD_LIST, 'R', 0, sender_open_reply_all);
keymap_add (keymaps + CMD_LIST, 'f', 0, sender_open_fwd);
keymap_add (keymaps + CMD_LIST, 'e', 0, sender_open_edit);
keymap_add (keymaps + CMD_LIST, '$', 0, folder_flush);
keymap_add (keymaps + CMD_LIST, ' ', 0, folder_toggle_flag);
keymap_add (keymaps + CMD_LIST, '*', 0, folder_flag_invert);
keymap_add (keymaps + CMD_LIST, '+', 0, folder_flag_all);
keymap_add (keymaps + CMD_LIST, '-', 0, folder_unflag_all);
keymap_add (keymaps + CMD_LIST, '=', 0, folder_flag_duplicates);
keymap_add (keymaps + CMD_LIST, 'N', 0, folder_scroll_down);
keymap_add (keymaps + CMD_LIST, 'P', 0, folder_scroll_up);
keymap_add (keymaps + CMD_LIST, 'c', 0, folder_recenter);
keymap_add (keymaps + CMD_LIST, 'M', 0, folder_move_mail);
keymap_add (keymaps + CMD_LIST, 'n', 0, folder_next_unread);
keymap_add (keymaps + CMD_LIST, 'p', 0, folder_prev_unread);
keymap_add (keymaps + CMD_LIST, 'S', 0, smtp_flush_outbox);
keymap_add (keymaps + CMD_LIST, 18, 0, folder_search_backward);
keymap_add (keymaps + CMD_LIST, 19, 0, folder_search_forward);
keymap_add (keymaps + CMD_SELECT_BOX, KEY_PPAGE, 0, box_selection_prev_page);
keymap_add (keymaps + CMD_SELECT_BOX, KEY_NPAGE, 0, box_selection_next_page);
keymap_add (keymaps + CMD_SELECT_BOX, KEY_HOME, 0, box_selection_first);
keymap_add (keymaps + CMD_SELECT_BOX, KEY_END, 0, box_selection_last);
keymap_add (keymaps + CMD_SELECT_BOX, KEY_UP, 0, box_selection_prev);
keymap_add (keymaps + CMD_SELECT_BOX, KEY_DOWN, 0, box_selection_next);
keymap_add (keymaps + CMD_SELECT_BOX, '\r', 0, box_selection_hit);
keymap_add (keymaps + CMD_SELECT_BOX, 18, 0, box_selection_search_backward);
keymap_add (keymaps + CMD_SELECT_BOX, 19, 0, box_selection_search_forward);
keymap_add (keymaps + CMD_ABOOK, KEY_PPAGE, 0, abook_prev_page);
keymap_add (keymaps + CMD_ABOOK, KEY_NPAGE, 0, abook_next_page);
keymap_add (keymaps + CMD_ABOOK, KEY_HOME, 0, abook_first);
keymap_add (keymaps + CMD_ABOOK, KEY_END, 0, abook_last);
keymap_add (keymaps + CMD_ABOOK, KEY_DOWN, 0, abook_next);
keymap_add (keymaps + CMD_ABOOK, KEY_UP, 0, abook_prev);
keymap_add (keymaps + CMD_ABOOK, KEY_DC, 0, abook_remove);
keymap_add (keymaps + CMD_ABOOK, 'n', 0, abook_change_name);
keymap_add (keymaps + CMD_ABOOK, 'e', 0, abook_change_email);
keymap_add (keymaps + CMD_ABOOK, 'g', 0, abook_change_groups);
keymap_add (keymaps + CMD_ABOOK, 's', 0, abook_change_sex);
keymap_add (keymaps + CMD_ABOOK, 'o', 0, abook_change_official);
keymap_add (keymaps + CMD_ABOOK, 'f', 0, abook_change_foreign);
keymap_add (keymaps + CMD_ABOOK, 'a', 0, abook_insert);
keymap_add (keymaps + CMD_ABOOK, 'q', 0, abook_hide);
keymap_add (keymaps + CMD_ABOOK, ' ', 0, abook_hit);
keymap_add (keymaps + CMD_ABOOK, '*', 0, abook_hit_all);
keymap_add (keymaps + CMD_ABOOK, '+', 0, abook_set_all);
keymap_add (keymaps + CMD_ABOOK, '-', 0, abook_unset_all);
keymap_add (keymaps + CMD_ABOOK, 'm', 0, abook_compose);
keymap_add (keymaps + CMD_ABOOK, 18, 0, abook_search_backward);
keymap_add (keymaps + CMD_ABOOK, 19, 0, abook_search_forward);
keymap_add (keymaps + CMD_READ_MAIL, 'q', 0, mailreader_close);
keymap_add (keymaps + CMD_READ_MAIL, KEY_PPAGE, 0, mailreader_page_up);
keymap_add (keymaps + CMD_READ_MAIL, KEY_NPAGE, 0, mailreader_page_down);
keymap_add (keymaps + CMD_READ_MAIL, KEY_HOME, 0, mailreader_top);
keymap_add (keymaps + CMD_READ_MAIL, KEY_END, 0, mailreader_bottom);
keymap_add (keymaps + CMD_READ_MAIL, KEY_DOWN, 0, mailreader_line_down);
keymap_add (keymaps + CMD_READ_MAIL, KEY_UP, 0, mailreader_line_up);
keymap_add (keymaps + CMD_READ_MAIL, 18, 0, mailreader_search_backward);
keymap_add (keymaps + CMD_READ_MAIL, 19, 0, mailreader_search_forward);
keymap_add (keymaps + CMD_READ_MAIL, 'h', 0, mailreader_header_switch);
keymap_add (keymaps + CMD_READ_MAIL, 'b', 0, abook_add_show);
keymap_add (keymaps + CMD_READ_MAIL, 'a', 0, attach_show);
keymap_add (keymaps + CMD_READ_MAIL, 'r', 0, sender_open_reply);
keymap_add (keymaps + CMD_READ_MAIL, 'R', 0, sender_open_reply_all);
keymap_add (keymaps + CMD_READ_MAIL, 'f', 0, sender_open_fwd);
keymap_add (keymaps + CMD_FETCH, KEY_PPAGE, 0, fetch_prev_page);
keymap_add (keymaps + CMD_FETCH, KEY_NPAGE, 0, fetch_next_page);
keymap_add (keymaps + CMD_FETCH, KEY_HOME, 0, fetch_first);
keymap_add (keymaps + CMD_FETCH, KEY_END, 0, fetch_last);
keymap_add (keymaps + CMD_FETCH, KEY_DOWN, 0, fetch_next);
keymap_add (keymaps + CMD_FETCH, KEY_UP, 0, fetch_prev);
keymap_add (keymaps + CMD_FETCH, 'q', 0, fetch_close);
keymap_add (keymaps + CMD_FETCH, 'f', 0, fetch_get_mail);
keymap_add (keymaps + CMD_FETCH, 'd', 0, fetch_del_mail);
keymap_add (keymaps + CMD_FETCH, 'r', 0, fetch_rset);
keymap_add (keymaps + CMD_ATTACH, KEY_PPAGE, 0, attach_prev_page);
keymap_add (keymaps + CMD_ATTACH, KEY_NPAGE, 0, attach_next_page);
keymap_add (keymaps + CMD_ATTACH, KEY_HOME, 0, attach_first);
keymap_add (keymaps + CMD_ATTACH, KEY_END, 0, attach_last);
keymap_add (keymaps + CMD_ATTACH, KEY_DOWN, 0, attach_next);
keymap_add (keymaps + CMD_ATTACH, KEY_UP, 0, attach_prev);
keymap_add (keymaps + CMD_ATTACH, 's', 0, attach_save);
keymap_add (keymaps + CMD_ATTACH, 'S', 0, attach_save_all);
keymap_add (keymaps + CMD_ATTACH, '\r', 0, attach_hit);
keymap_add (keymaps + CMD_ATTACH, 'q', 0, attach_hide);
keymap_add (keymaps + CMD_ABOOK_ADD, KEY_PPAGE, 0, abook_add_prev_page);
keymap_add (keymaps + CMD_ABOOK_ADD, KEY_NPAGE, 0, abook_add_next_page);
keymap_add (keymaps + CMD_ABOOK_ADD, KEY_HOME, 0, abook_add_first);
keymap_add (keymaps + CMD_ABOOK_ADD, KEY_END, 0, abook_add_last);
keymap_add (keymaps + CMD_ABOOK_ADD, KEY_DOWN, 0, abook_add_next);
keymap_add (keymaps + CMD_ABOOK_ADD, KEY_UP, 0, abook_add_prev);
keymap_add (keymaps + CMD_ABOOK_ADD, 'q', 0, abook_add_hide);
keymap_add (keymaps + CMD_ABOOK_ADD, '\r', 0, abook_add_hit);
keymap_add (keymaps + CMD_SENDER, KEY_PPAGE, 0, sender_prev_page);
keymap_add (keymaps + CMD_SENDER, KEY_NPAGE, 0, sender_next_page);
keymap_add (keymaps + CMD_SENDER, KEY_HOME, 0, sender_first);
keymap_add (keymaps + CMD_SENDER, KEY_END, 0, sender_last);
keymap_add (keymaps + CMD_SENDER, KEY_DOWN, 0, sender_next);
keymap_add (keymaps + CMD_SENDER, KEY_UP, 0, sender_prev);
keymap_add (keymaps + CMD_SENDER, 'q', 0, sender_close);
keymap_add (keymaps + CMD_SENDER, 'y', 0, sender_go);
keymap_add (keymaps + CMD_SENDER, 'S', 0, sender_change_smtp);
keymap_add (keymaps + CMD_SENDER, 'f', 0, sender_change_from);
keymap_add (keymaps + CMD_SENDER, 'r', 0, sender_change_reply_to);
keymap_add (keymaps + CMD_SENDER, 't', 0, sender_change_to);
keymap_add (keymaps + CMD_SENDER, 'c', 0, sender_change_cc);
keymap_add (keymaps + CMD_SENDER, 'b', 0, sender_change_bcc);
keymap_add (keymaps + CMD_SENDER, 's', 0, sender_change_subject);
keymap_add (keymaps + CMD_SENDER, 'a', 0, sender_add_attachment);
keymap_add (keymaps + CMD_SENDER, KEY_DC, 0, sender_delete_attachment);
keymap_add (keymaps + CMD_SENDER, 'T', 0, sender_change_type);
keymap_add (keymaps + CMD_ASK, KEY_HOME, 0, choose_first);
keymap_add (keymaps + CMD_ASK, KEY_END, 0, choose_last);
keymap_add (keymaps + CMD_ASK, KEY_DOWN, 0, choose_next);
keymap_add (keymaps + CMD_ASK, KEY_RIGHT, 0, choose_next);
keymap_add (keymaps + CMD_ASK, KEY_UP, 0, choose_prev);
keymap_add (keymaps + CMD_ASK, KEY_LEFT, 0, choose_prev);
keymap_add (keymaps + CMD_HELP, KEY_HOME, 0, help_beg);
keymap_add (keymaps + CMD_HELP, KEY_END, 0, help_end);
keymap_add (keymaps + CMD_HELP, KEY_DOWN, 0, help_scroll_down);
keymap_add (keymaps + CMD_HELP, KEY_UP, 0, help_scroll_up);
keymap_add (keymaps + CMD_HELP, KEY_NPAGE, 0, help_next_page);
keymap_add (keymaps + CMD_HELP, KEY_PPAGE, 0, help_prev_page);
keymap_add (keymaps + CMD_HELP, 'q', 0, help_close);
keymap_add (keymaps + CMD_HELP, 27, 0, help_close);
keymap_add (keymaps + CMD_HELP, 7, 0, help_close);
keymap_add (keymaps + CMD_HELP, '?', 0, cmd_nothing);
keymap_add (keymaps + CMD_READ, 7, 0, read_abort);
keymap_add (keymaps + CMD_READ, '\r', 0, read_accept);
keymap_add (keymaps + CMD_READ, KEY_HOME, 0, read_begin);
keymap_add (keymaps + CMD_READ, 1, 0, read_begin);
keymap_add (keymaps + CMD_READ, KEY_END, 0, read_end);
keymap_add (keymaps + CMD_READ, 5, 0, read_end);
keymap_add (keymaps + CMD_READ, KEY_LEFT, 0, read_backward_char);
keymap_add (keymaps + CMD_READ, 2, 0, read_backward_char);
keymap_add (keymaps + CMD_READ, KEY_RIGHT, 0, read_forward_char);
keymap_add (keymaps + CMD_READ, 6, 0, read_forward_char);
keymap_add (keymaps + CMD_READ, 'b', 1, read_backward_word);
keymap_add (keymaps + CMD_READ, 'f', 1, read_forward_word);
keymap_add (keymaps + CMD_READ, 4, 0, read_del_char_fwd);
keymap_add (keymaps + CMD_READ, KEY_DC, 0, read_del_char_fwd);
keymap_add (keymaps + CMD_READ, KEY_BACKSPACE, 0, read_del_char_back);
keymap_add (keymaps + CMD_READ, '\b', 0, read_del_char_back);
keymap_add (keymaps + CMD_READ, 127, 0, read_del_char_back);
keymap_add (keymaps + CMD_READ, 'd', 1, read_del_word_fwd);
keymap_add (keymaps + CMD_READ, KEY_BACKSPACE, 1, read_del_word_back);
keymap_add (keymaps + CMD_READ, '\b', 1, read_del_word_back);
keymap_add (keymaps + CMD_READ, 127, 1, read_del_word_back);
keymap_add (keymaps + CMD_READ, 11, 0, read_kill_line);
keymap_add (keymaps + CMD_READ, '\t', 0, read_complete);
keymap_add (keymaps + CMD_READ, 14, 0, read_choose_next);
keymap_add (keymaps + CMD_READ, KEY_DOWN, 0, read_choose_next);
keymap_add (keymaps + CMD_READ, 16, 0, read_choose_prev);
keymap_add (keymaps + CMD_READ, KEY_UP, 0, read_choose_prev);
keymap_add (keymaps + CMD_SEARCH, 18, 0, select_search_backward);
keymap_add (keymaps + CMD_SEARCH, 19, 0, select_search_forward);
keymap_add (keymaps + CMD_SEARCH, '\b', 0, select_search_backspace);
keymap_add (keymaps + CMD_SEARCH, 127, 0, select_search_backspace);
keymap_add (keymaps + CMD_SEARCH, KEY_BACKSPACE, 0, select_search_backspace);
#if DEBUG
keymap_add (keymaps + CMD_DEBUG, KEY_HOME, 0, debug_first);
keymap_add (keymaps + CMD_DEBUG, KEY_END, 0, debug_last);
keymap_add (keymaps + CMD_DEBUG, KEY_UP, 0, debug_prev);
keymap_add (keymaps + CMD_DEBUG, KEY_DOWN, 0, debug_next);
keymap_add (keymaps + CMD_DEBUG, KEY_PPAGE, 0, debug_prev_page);
keymap_add (keymaps + CMD_DEBUG, KEY_NPAGE, 0, debug_next_page);
keymap_add (keymaps + CMD_DEBUG, ' ', 0, debug_show);
#endif
}
static void
destroy_keymaps (void)
{
int i;
for (i = 0; i < CMD_STATE_COUNT; i++){
keymap_destroy (keymaps + i);
}
keymap_destroy (&keymap_default);
}
static void
destroy_list (struct fd_handler *list)
{
if (list == NULL)
return;
destroy_list (list->next);
xfree (list);
}
static void
key_action (int nothing)
{
int meta;
int c;
char *arg;
meta = 0;
c = wgetch (cmd_win);
if (c == 27){
meta = 1;
c = wgetch (cmd_win);
}
last_char = c;
if (c == ':'){
arg = read_argument (": ", NULL, COMPLETE_FUNS, HIDE_NO);
if (arg)
exec_run_name (arg);
return;
}
if (! meta && isdigit (c)){
prefix_arg = c - '0';
return;
}
if (keymap_action (keymaps + *state_top, c, meta))
fprintf (stderr, "%c", '\a');
prefix_arg = 0;
}
/* This file is generated by interface.pl script from interface.desc,
and inc.in. */
static WINDOW *interface_init (void);
#include "cmd.inc"
static void
init (void)
{
cmd_win = interface_init ();
keypad (cmd_win, TRUE);
meta (cmd_win, TRUE);
init_keymaps ();
state_top = state_stack;
*state_top = CMD_LIST;
cmd_add_readfd_handler (0, key_action);
}
static void
put_fds (fd_set *set, struct fd_handler *list)
{
if (list == NULL)
return;
FD_SET (list->fd, set);
put_fds (set, list->next);
}
/* The reversed order of taking actions is *very* important. The action
may change the list by removing or adding new elements. */
static void
take_actions (fd_set *set, struct fd_handler *list)
{
if (list == NULL)
return;
take_actions (set, list->next);
if (set == NULL || FD_ISSET (list->fd, set))
list->handler (list->fd);
}
static struct fd_handler *
list_rem (struct fd_handler *list, int fd)
{
struct fd_handler *result;
if (list == NULL)
return NULL;
if (list->fd != fd){
list->next = list_rem (list->next, fd);
return list;
}
result = list->next;
xfree (list);
return result;
}
/****************************************************************************
* INTERFACE FUNCTIONS
****************************************************************************/
void
cmd_text_color (void)
{
wattrset (cmd_win, text_color);
}
void
cmd_error_color (void)
{
wattrset (cmd_win, error_color);
}
void
cmd_init (void)
{
init ();
}
void
cmd_quit (void)
{
exec_t *exec;
exec = exec_lookup_fun (cmd_quit);
hook_execute (exec->hook);
quit ();
}
void
cmd_nothing (void)
{
}
void
cmd_state_push (cmd_state_t requested_state)
{
if (state_top == state_stack + STACK_SIZE){
error_ (0, _("state stack overflow, please send bug report"));
}
state_top++;
*state_top = requested_state;
}
int
cmd_state_pop (void)
{
if (state_top == state_stack){
error_ (0, _("state stack underflow, "
"please send bug report"));
}
state_top--;
return 0;
}
cmd_state_t
cmd_state_get (int from_top)
{
return *(state_top - from_top);
}
void
cmd_add_writefd_handler (int fd, void (*handler)(int))
{
struct fd_handler *elem = xmalloc (sizeof (struct fd_handler));
elem->fd = fd;
elem->handler = handler;
elem->next = writefd_list;
writefd_list = elem;
}
void
cmd_add_readfd_handler (int fd, void (*handler)(int))
{
struct fd_handler *elem = xmalloc (sizeof (struct fd_handler));
elem->fd = fd;
elem->handler = handler;
elem->next = readfd_list;
readfd_list = elem;
}
void
cmd_add_timeout_handler (void (*handler)(int))
{
struct fd_handler *elem = xmalloc (sizeof (struct fd_handler));
elem->fd = 0;
elem->handler = handler;
elem->next = timeout_list;
timeout_list = elem;
}
void
cmd_del_writefd_handler (int fd)
{
writefd_list = list_rem (writefd_list, fd);
}
void
cmd_del_readfd_handler (int fd)
{
readfd_list = list_rem (readfd_list, fd);
}
void
cmd_read_loop (void)
{
struct timeval tv;
fd_set readfds;
fd_set writefds;
int ret;
interface_redraw ();
cmd_after_startup ();
while (1){
doupdate ();
tv.tv_sec = 0;
tv.tv_usec = 3000;
FD_ZERO (& readfds);
FD_ZERO (& writefds);
put_fds (& readfds, readfd_list);
put_fds (& writefds, writefd_list);
ret = select (FD_SETSIZE, & readfds, & writefds, NULL, & tv);
if (ret > 0){
take_actions (& readfds, readfd_list);
take_actions (& writefds, writefd_list);
}
else if (ret == 0){
take_actions (NULL, timeout_list);
}
else {
error_critical (EXIT_FAILURE, errno, "select");
}
}
}
void
cmd_choose (void)
{
int meta;
int c;
while (1){
doupdate ();
meta = 0;
c = wgetch (cmd_win);
if (c == 27){
meta = 1;
c = wgetch (cmd_win);
}
if (c == '\r'){
break;
}
if (c == 7){
choose_cancel ();
break;
}
keymap_action (keymaps + CMD_ASK, c, meta);
}
interface_redraw ();
}
int
cmd_last_char (void)
{
return last_char;
}
int
cmd_prefix_arg (void)
{
return prefix_arg;
}
void
cmd_after_startup (void)
{
exec_t *exec;
exec = exec_lookup_fun (cmd_after_startup);
hook_execute (exec->hook);
}
/****************************************************************************
* INTERFACE CLASS BODIES
****************************************************************************/
/****************************************************************************
*
* END MODULE cmd.c
*
****************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1