2005-09-20 13:26:39 +00:00
|
|
|
/** \file input.c
|
2007-09-21 14:07:52 +00:00
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
Functions for reading a character of input from stdin, using the
|
|
|
|
inputrc information for key bindings.
|
|
|
|
|
|
|
|
The inputrc file format was invented for the readline library. The
|
|
|
|
implementation in fish is as of yet incomplete.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2006-08-09 22:53:38 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TERMIOS_H
|
|
|
|
#include <sys/termios.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_IOCTL_H
|
2005-09-20 13:26:39 +00:00
|
|
|
#include <sys/ioctl.h>
|
2006-08-09 22:53:38 +00:00
|
|
|
#endif
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <wchar.h>
|
|
|
|
|
|
|
|
#if HAVE_NCURSES_H
|
|
|
|
#include <ncurses.h>
|
|
|
|
#else
|
|
|
|
#include <curses.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_TERMIO_H
|
|
|
|
#include <termio.h>
|
|
|
|
#endif
|
|
|
|
|
2006-01-19 12:22:07 +00:00
|
|
|
#if HAVE_TERM_H
|
2005-09-20 13:26:39 +00:00
|
|
|
#include <term.h>
|
2006-01-19 12:22:07 +00:00
|
|
|
#elif HAVE_NCURSES_TERM_H
|
|
|
|
#include <ncurses/term.h>
|
|
|
|
#endif
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
#include <signal.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <wctype.h>
|
|
|
|
|
|
|
|
|
2006-02-28 13:17:16 +00:00
|
|
|
|
|
|
|
#include "fallback.h"
|
2005-09-20 13:26:39 +00:00
|
|
|
#include "util.h"
|
2006-02-28 13:17:16 +00:00
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
#include "wutil.h"
|
|
|
|
#include "reader.h"
|
|
|
|
#include "proc.h"
|
|
|
|
#include "common.h"
|
|
|
|
#include "sanity.h"
|
|
|
|
#include "input_common.h"
|
|
|
|
#include "input.h"
|
|
|
|
#include "parser.h"
|
|
|
|
#include "env.h"
|
|
|
|
#include "expand.h"
|
2005-11-25 14:18:26 +00:00
|
|
|
#include "event.h"
|
2006-02-09 15:50:20 +00:00
|
|
|
#include "signal.h"
|
2006-07-19 22:55:49 +00:00
|
|
|
|
2006-02-16 13:40:25 +00:00
|
|
|
#include "output.h"
|
2006-06-21 14:03:44 +00:00
|
|
|
#include "intern.h"
|
2007-09-25 16:14:47 +00:00
|
|
|
#include "halloc.h"
|
|
|
|
#include "halloc_util.h"
|
2005-09-20 13:26:39 +00:00
|
|
|
|
|
|
|
/**
|
2007-09-25 16:14:47 +00:00
|
|
|
Add a new terminfo mapping
|
2005-09-20 13:26:39 +00:00
|
|
|
*/
|
2007-09-25 16:14:47 +00:00
|
|
|
#define TERMINFO_ADD(key) \
|
|
|
|
{ \
|
|
|
|
terminfo_mapping_t *m = halloc( terminfo_mappings, sizeof( terminfo_mapping_t ) ); \
|
|
|
|
m->name = halloc_wcsdup( terminfo_mappings, (L ## #key)+4 ); \
|
|
|
|
m->seq = key; \
|
|
|
|
al_push( terminfo_mappings, m ); \
|
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
Struct representing a keybinding. Returned by input_get_mappings.
|
|
|
|
*/
|
2005-09-20 13:26:39 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
2006-06-21 14:03:44 +00:00
|
|
|
const wchar_t *seq; /**< Character sequence which generates this event */
|
|
|
|
const wchar_t *command; /**< command that should be evaluated by this mapping */
|
2005-09-20 13:26:39 +00:00
|
|
|
|
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
input_mapping_t;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2005-10-02 13:40:46 +00:00
|
|
|
/**
|
2007-09-25 16:14:47 +00:00
|
|
|
A struct representing the mapping from a terminfo key name to a terminfo character sequence
|
|
|
|
*/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
const wchar_t *name; /**< Name of key */
|
|
|
|
const char *seq; /**< Character sequence generated on keypress */
|
|
|
|
|
|
|
|
}
|
|
|
|
terminfo_mapping_t;
|
|
|
|
|
2005-10-02 13:40:46 +00:00
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
/**
|
|
|
|
Names of all the readline functions supported
|
|
|
|
*/
|
2006-06-13 17:23:37 +00:00
|
|
|
static const wchar_t *name_arr[] =
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
|
|
|
L"beginning-of-line",
|
|
|
|
L"end-of-line",
|
|
|
|
L"forward-char",
|
|
|
|
L"backward-char",
|
|
|
|
L"forward-word",
|
|
|
|
L"backward-word",
|
|
|
|
L"history-search-backward",
|
|
|
|
L"history-search-forward",
|
|
|
|
L"delete-char",
|
|
|
|
L"backward-delete-char",
|
|
|
|
L"kill-line",
|
|
|
|
L"yank",
|
|
|
|
L"yank-pop",
|
|
|
|
L"complete",
|
|
|
|
L"beginning-of-history",
|
|
|
|
L"end-of-history",
|
|
|
|
L"delete-line",
|
|
|
|
L"backward-kill-line",
|
|
|
|
L"kill-whole-line",
|
|
|
|
L"kill-word",
|
|
|
|
L"backward-kill-word",
|
|
|
|
L"dump-functions",
|
2006-10-04 21:45:02 +00:00
|
|
|
L"winch",
|
2005-09-20 13:26:39 +00:00
|
|
|
L"exit",
|
|
|
|
L"history-token-search-backward",
|
|
|
|
L"history-token-search-forward",
|
|
|
|
L"self-insert",
|
2006-05-14 10:16:23 +00:00
|
|
|
L"null",
|
2006-07-23 20:52:03 +00:00
|
|
|
L"eof",
|
2006-10-09 01:15:29 +00:00
|
|
|
L"vi-arg-digit",
|
2006-10-31 22:01:49 +00:00
|
|
|
L"execute",
|
|
|
|
L"beginning-of-buffer",
|
2006-12-12 10:13:48 +00:00
|
|
|
L"end-of-buffer",
|
2007-09-21 14:05:49 +00:00
|
|
|
L"repaint",
|
|
|
|
L"up-line",
|
|
|
|
L"down-line"
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
/**
|
|
|
|
Description of each supported readline function
|
|
|
|
*/
|
2006-06-13 17:23:37 +00:00
|
|
|
/*
|
|
|
|
static const wchar_t *desc_arr[] =
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
|
|
|
L"Move to beginning of line",
|
|
|
|
L"Move to end of line",
|
|
|
|
L"Move forward one character",
|
|
|
|
L"Move backward one character",
|
|
|
|
L"Move forward one word",
|
|
|
|
L"Move backward one word",
|
|
|
|
L"Search backward through list of previous commands",
|
|
|
|
L"Search forward through list of previous commands",
|
|
|
|
L"Delete one character forward",
|
|
|
|
L"Delete one character backward",
|
|
|
|
L"Move contents from cursor to end of line to killring",
|
|
|
|
L"Paste contents of killring",
|
|
|
|
L"Rotate to previous killring entry",
|
|
|
|
L"Guess the rest of the next input token",
|
|
|
|
L"Move to first item of history",
|
|
|
|
L"Move to last item of history",
|
|
|
|
L"Clear current line",
|
|
|
|
L"Move contents from beginning of line to cursor to killring",
|
|
|
|
L"Move entire line to killring",
|
|
|
|
L"Move next word to killring",
|
|
|
|
L"Move previous word to killring",
|
|
|
|
L"Write out keybindings",
|
|
|
|
L"Clear entire screen",
|
|
|
|
L"Quit the running program",
|
|
|
|
L"Search backward through list of previous commands for matching token",
|
|
|
|
L"Search forward through list of previous commands for matching token",
|
|
|
|
L"Insert the pressed key",
|
2006-05-14 10:16:23 +00:00
|
|
|
L"Do nothing",
|
2006-07-23 20:52:03 +00:00
|
|
|
L"End of file",
|
|
|
|
L"Repeat command"
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
;
|
2006-06-13 17:23:37 +00:00
|
|
|
*/
|
2007-09-25 16:14:47 +00:00
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
/**
|
|
|
|
Internal code for each supported readline function
|
|
|
|
*/
|
2006-06-13 17:23:37 +00:00
|
|
|
static const wchar_t code_arr[] =
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
|
|
|
R_BEGINNING_OF_LINE,
|
|
|
|
R_END_OF_LINE,
|
|
|
|
R_FORWARD_CHAR,
|
|
|
|
R_BACKWARD_CHAR,
|
|
|
|
R_FORWARD_WORD,
|
|
|
|
R_BACKWARD_WORD,
|
|
|
|
R_HISTORY_SEARCH_BACKWARD,
|
|
|
|
R_HISTORY_SEARCH_FORWARD,
|
|
|
|
R_DELETE_CHAR,
|
|
|
|
R_BACKWARD_DELETE_CHAR,
|
|
|
|
R_KILL_LINE,
|
|
|
|
R_YANK,
|
|
|
|
R_YANK_POP,
|
|
|
|
R_COMPLETE,
|
|
|
|
R_BEGINNING_OF_HISTORY,
|
|
|
|
R_END_OF_HISTORY,
|
|
|
|
R_DELETE_LINE,
|
|
|
|
R_BACKWARD_KILL_LINE,
|
|
|
|
R_KILL_WHOLE_LINE,
|
|
|
|
R_KILL_WORD,
|
|
|
|
R_BACKWARD_KILL_WORD,
|
|
|
|
R_DUMP_FUNCTIONS,
|
2006-10-04 21:45:02 +00:00
|
|
|
R_WINCH,
|
2005-09-20 13:26:39 +00:00
|
|
|
R_EXIT,
|
|
|
|
R_HISTORY_TOKEN_SEARCH_BACKWARD,
|
|
|
|
R_HISTORY_TOKEN_SEARCH_FORWARD,
|
|
|
|
R_SELF_INSERT,
|
2006-05-14 10:16:23 +00:00
|
|
|
R_NULL,
|
2006-07-23 20:52:03 +00:00
|
|
|
R_EOF,
|
2006-10-09 01:15:29 +00:00
|
|
|
R_VI_ARG_DIGIT,
|
2006-10-31 22:01:49 +00:00
|
|
|
R_EXECUTE,
|
|
|
|
R_BEGINNING_OF_BUFFER,
|
|
|
|
R_END_OF_BUFFER,
|
2007-09-21 14:05:49 +00:00
|
|
|
R_REPAINT,
|
|
|
|
R_UP_LINE,
|
|
|
|
R_DOWN_LINE
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
;
|
|
|
|
|
|
|
|
|
2006-01-23 20:40:14 +00:00
|
|
|
/**
|
|
|
|
Mappings for the current input mode
|
|
|
|
*/
|
2007-09-25 16:14:47 +00:00
|
|
|
static array_list_t mappings = {0,0,0};
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
static array_list_t *terminfo_mappings = 0;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
|
|
|
|
2006-06-20 00:50:10 +00:00
|
|
|
/**
|
|
|
|
Set to one when the input subsytem has been initialized.
|
|
|
|
*/
|
2006-03-10 13:38:09 +00:00
|
|
|
static int is_init = 0;
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
static void input_terminfo_init();
|
|
|
|
static void input_terminfo_destroy();
|
2006-07-23 20:52:03 +00:00
|
|
|
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Returns the function name for the given function code.
|
|
|
|
*/
|
2006-08-11 09:30:51 +00:00
|
|
|
/*
|
2005-09-20 13:26:39 +00:00
|
|
|
static const wchar_t *input_get_name( wchar_t c )
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for( i = 0; i<(sizeof( code_arr )/sizeof(wchar_t)) ; i++ )
|
|
|
|
{
|
|
|
|
if( c == code_arr[i] )
|
|
|
|
{
|
|
|
|
return name_arr[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2006-08-11 09:30:51 +00:00
|
|
|
*/
|
2005-09-20 13:26:39 +00:00
|
|
|
/**
|
|
|
|
Returns the function description for the given function code.
|
|
|
|
*/
|
2006-01-16 13:42:44 +00:00
|
|
|
/*
|
2005-09-20 13:26:39 +00:00
|
|
|
static const wchar_t *input_get_desc( wchar_t c )
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for( i = 0; i<(sizeof( code_arr )/sizeof(wchar_t)) ; i++ )
|
|
|
|
{
|
|
|
|
if( c == code_arr[i] )
|
|
|
|
{
|
|
|
|
return desc_arr[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2006-01-16 13:42:44 +00:00
|
|
|
*/
|
2005-09-20 13:26:39 +00:00
|
|
|
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
void input_mapping_add( const wchar_t *sequence,
|
|
|
|
const wchar_t *command )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
CHECK( sequence, );
|
|
|
|
CHECK( command, );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
// debug( 0, L"Add mapping from %ls to %ls", escape(sequence, 1), escape(command, 1 ) );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
|
|
|
|
for( i=0; i<al_get_count( &mappings); i++ )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
input_mapping_t *m = (input_mapping_t *)al_get( &mappings, i );
|
|
|
|
if( wcscmp( m->seq, sequence ) == 0 )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
m->command = intern(command);
|
2005-09-20 13:26:39 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
input_mapping_t *m = malloc( sizeof( input_mapping_t ) );
|
|
|
|
m->seq = intern( sequence );
|
|
|
|
m->command = intern(command);
|
|
|
|
al_push( &mappings, m );
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2007-09-25 16:14:47 +00:00
|
|
|
Handle interruptions to key reading by reaping finshed jobs and
|
|
|
|
propagating the interrupt to the reader.
|
2005-09-20 13:26:39 +00:00
|
|
|
*/
|
2007-09-25 16:14:47 +00:00
|
|
|
static int interrupt_handler()
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
/*
|
|
|
|
Fire any pending events
|
|
|
|
*/
|
|
|
|
event_fire( 0 );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
/*
|
|
|
|
Reap stray processes, including printing exit status messages
|
|
|
|
*/
|
|
|
|
if( job_reap( 1 ) )
|
|
|
|
repaint();
|
|
|
|
|
|
|
|
/*
|
|
|
|
Check if we should exit
|
|
|
|
*/
|
|
|
|
if( exit_status() )
|
|
|
|
{
|
|
|
|
return R_EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Tell the reader an event occured
|
|
|
|
*/
|
|
|
|
if( reader_interrupted() )
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Return 3, i.e. the character read by a Control-C.
|
|
|
|
*/
|
|
|
|
return 3;
|
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
return R_WINCH;
|
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
int input_init()
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
if( is_init )
|
|
|
|
return 1;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
is_init = 1;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
input_common_init( &interrupt_handler );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
|
|
|
|
{
|
|
|
|
debug( 0, _( L"Could not set up terminal" ) );
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
output_set_term( env_get( L"TERM" ) );
|
|
|
|
|
|
|
|
input_terminfo_init();
|
|
|
|
|
2005-10-02 13:40:46 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2005-10-02 13:40:46 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
void input_destroy()
|
2005-10-02 13:40:46 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
if( !is_init )
|
|
|
|
return;
|
2005-10-02 13:40:46 +00:00
|
|
|
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
is_init=0;
|
|
|
|
|
|
|
|
al_foreach( &mappings, &free );
|
|
|
|
al_destroy( &mappings );
|
2005-10-02 13:40:46 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
input_common_destroy();
|
2005-10-02 13:40:46 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( del_curterm( cur_term ) == ERR )
|
2005-10-02 13:40:46 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
debug( 0, _(L"Error while closing terminfo") );
|
2005-10-02 13:40:46 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
|
|
|
|
input_terminfo_destroy();
|
2005-10-02 13:40:46 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
/**
|
2007-09-25 16:14:47 +00:00
|
|
|
Perform the action of the specified binding
|
2005-09-20 13:26:39 +00:00
|
|
|
*/
|
2007-09-25 16:14:47 +00:00
|
|
|
static wint_t input_exec_binding( input_mapping_t *m, const wchar_t *seq )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
wchar_t code = input_function_get_code( m->command );
|
|
|
|
if( code != -1 )
|
|
|
|
{
|
|
|
|
switch( code )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2005-09-25 22:39:48 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
case R_SELF_INSERT:
|
|
|
|
{
|
|
|
|
return seq[0];
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
default:
|
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
return code;
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
This key sequence is bound to a command, which
|
|
|
|
is sent to the parser for evaluation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
eval( m->command, 0, TOP );
|
|
|
|
|
|
|
|
/*
|
|
|
|
We still need to return something to the caller, R_NULL
|
|
|
|
tells the reader that no key press needs to be handled,
|
|
|
|
and no repaint is needed.
|
|
|
|
|
|
|
|
Bindings that produce output should emit a R_REPAINT
|
|
|
|
function by calling 'commandline -f repaint' to tell
|
|
|
|
fish that a repaint is in order.
|
|
|
|
*/
|
|
|
|
|
|
|
|
return R_NULL;
|
2005-09-25 22:39:48 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
/**
|
|
|
|
Try reading the specified function mapping
|
|
|
|
*/
|
|
|
|
static wint_t input_try_mapping( input_mapping_t *m)
|
|
|
|
{
|
|
|
|
int j, k;
|
|
|
|
wint_t c=0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Check if the actual function code of this mapping is on the stack
|
|
|
|
*/
|
|
|
|
c = input_common_readch( 0 );
|
|
|
|
if( c == input_function_get_code( m->command ) )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
return input_exec_binding( m, m->seq );
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
input_unreadch( c );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( m->seq != 0 )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
|
|
|
|
for( j=0; m->seq[j] != L'\0' &&
|
|
|
|
m->seq[j] == (c=input_common_readch( j>0 )); j++ )
|
|
|
|
;
|
|
|
|
|
|
|
|
if( m->seq[j] == L'\0' )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
return input_exec_binding( m, m->seq );
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
/*
|
|
|
|
Return the read characters
|
|
|
|
*/
|
|
|
|
input_unreadch(c);
|
|
|
|
for( k=j-1; k>=0; k-- )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
input_unreadch( m->seq[k] );
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
return 0;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
void input_unreadch( wint_t ch )
|
|
|
|
{
|
|
|
|
input_common_unreadch( ch );
|
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
wint_t input_readch()
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
CHECK_BLOCK( R_NULL );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Clear the interrupted flag
|
|
|
|
*/
|
|
|
|
reader_interrupted();
|
|
|
|
|
|
|
|
/*
|
|
|
|
Search for sequence in various mapping tables
|
|
|
|
*/
|
|
|
|
|
|
|
|
while( 1 )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
for( i=0; i<al_get_count( &mappings); i++ )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
wint_t res = input_try_mapping( (input_mapping_t *)al_get( &mappings, i ));
|
|
|
|
if( res )
|
|
|
|
return res;
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2005-10-02 13:40:46 +00:00
|
|
|
/*
|
2007-09-25 16:14:47 +00:00
|
|
|
No matching exact mapping, try to find generic mapping.
|
2005-10-02 13:40:46 +00:00
|
|
|
*/
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
for( i=0; i<al_get_count( &mappings); i++ )
|
2005-10-02 13:40:46 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
input_mapping_t *m = (input_mapping_t *)al_get( &mappings, i );
|
|
|
|
if( wcslen( m->seq) == 0 )
|
|
|
|
{
|
|
|
|
wchar_t arr[2]=
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
}
|
|
|
|
;
|
|
|
|
arr[0] = input_common_readch(0);
|
|
|
|
|
|
|
|
return input_exec_binding( m, arr );
|
|
|
|
}
|
2005-10-02 13:40:46 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
/*
|
|
|
|
No action to take on specified character, ignoer it
|
|
|
|
and move to next one.
|
|
|
|
*/
|
|
|
|
input_common_readch( 0 );
|
2005-10-02 13:40:46 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void input_mapping_get_names( array_list_t *list )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for( i=0; i<al_get_count( &mappings ); i++ )
|
|
|
|
{
|
|
|
|
input_mapping_t *m = (input_mapping_t *)al_get( &mappings, i );
|
|
|
|
al_push( list, m->seq );
|
2005-10-02 13:40:46 +00:00
|
|
|
}
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
|
|
|
|
int input_mapping_erase( const wchar_t *sequence )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
int ok = 0;
|
|
|
|
int i;
|
|
|
|
size_t sz = al_get_count( &mappings );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
for( i=0; i<sz; i++ )
|
|
|
|
{
|
|
|
|
input_mapping_t *m = (input_mapping_t *)al_get( &mappings, i );
|
|
|
|
if( !wcscmp( sequence, m->seq ) )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
if( i != (sz-1 ) )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
al_set( &mappings, i, al_get( &mappings, sz -1 ) );
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
al_truncate( &mappings, sz-1 );
|
|
|
|
ok = 1;
|
|
|
|
|
|
|
|
free( m );
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
|
|
|
|
return ok;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
const wchar_t *input_mapping_get( const wchar_t *sequence )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
int i;
|
|
|
|
size_t sz = al_get_count( &mappings );
|
|
|
|
|
|
|
|
for( i=0; i<sz; i++ )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
input_mapping_t *m = (input_mapping_t *)al_get( &mappings, i );
|
|
|
|
if( !wcscmp( sequence, m->seq ) )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
return m->command;
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
return 0;
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-28 21:32:27 +00:00
|
|
|
|
2005-10-24 15:26:25 +00:00
|
|
|
/**
|
2007-09-25 16:14:47 +00:00
|
|
|
Add all terminfo mappings
|
|
|
|
*/
|
|
|
|
static void input_terminfo_init()
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
terminfo_mappings = al_halloc( 0 );
|
|
|
|
|
|
|
|
TERMINFO_ADD( key_down );
|
|
|
|
TERMINFO_ADD( key_up );
|
|
|
|
TERMINFO_ADD( key_left );
|
|
|
|
TERMINFO_ADD( key_right );
|
|
|
|
TERMINFO_ADD( key_dc );
|
|
|
|
TERMINFO_ADD( key_backspace );
|
|
|
|
TERMINFO_ADD( key_home );
|
|
|
|
TERMINFO_ADD( key_end );
|
|
|
|
TERMINFO_ADD( key_ppage );
|
|
|
|
TERMINFO_ADD( key_npage );
|
|
|
|
TERMINFO_ADD( key_clear );
|
|
|
|
TERMINFO_ADD( key_close );
|
|
|
|
TERMINFO_ADD( key_command );
|
|
|
|
TERMINFO_ADD( key_copy );
|
|
|
|
TERMINFO_ADD( key_create );
|
|
|
|
TERMINFO_ADD( key_dl );
|
|
|
|
TERMINFO_ADD( key_enter );
|
|
|
|
TERMINFO_ADD( key_undo );
|
|
|
|
TERMINFO_ADD( key_suspend );
|
|
|
|
TERMINFO_ADD( key_cancel );
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
static void input_terminfo_destroy()
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( terminfo_mappings )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
halloc_free( terminfo_mappings );
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
const wchar_t *input_terminfo_get_sequence( const wchar_t *name )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
const char *res = 0;
|
|
|
|
int i;
|
|
|
|
static string_buffer_t *buff = 0;
|
|
|
|
int err = ENOENT;
|
2006-01-18 12:42:48 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
CHECK( name, 0 );
|
|
|
|
input_init();
|
2006-01-18 12:42:48 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
for( i=0; i<al_get_count( terminfo_mappings ); i++ )
|
2006-01-18 12:42:48 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
terminfo_mapping_t *m = (terminfo_mapping_t *)al_get( terminfo_mappings, i );
|
|
|
|
|
|
|
|
if( !wcscmp( name, m->name ) )
|
|
|
|
{
|
|
|
|
res = m->seq;
|
|
|
|
err = EILSEQ;
|
|
|
|
break;
|
|
|
|
}
|
2006-01-18 12:42:48 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( !res )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
errno = err;
|
|
|
|
return 0;
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2006-03-10 13:38:09 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( !buff )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
buff = sb_halloc( global_context );
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
sb_clear( buff );
|
|
|
|
sb_printf( buff, L"%s", res );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
return (wchar_t *)buff->buff;
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
const wchar_t *input_terminfo_get_name( const wchar_t *seq )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
int i;
|
|
|
|
static string_buffer_t *buff = 0;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
CHECK( seq, 0 );
|
|
|
|
input_init();
|
|
|
|
|
|
|
|
if( !buff )
|
2006-08-13 23:05:02 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
buff = sb_halloc( global_context );
|
2006-08-13 23:05:02 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
for( i=0; i<al_get_count( terminfo_mappings ); i++ )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
terminfo_mapping_t *m = (terminfo_mapping_t *)al_get( terminfo_mappings, i );
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( !m->seq )
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2006-12-01 16:30:09 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
sb_clear( buff );
|
|
|
|
sb_printf( buff, L"%s", m->seq );
|
|
|
|
|
|
|
|
if( !wcscmp( seq, (wchar_t *)buff->buff ) )
|
|
|
|
{
|
|
|
|
return m->name;
|
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
return 0;
|
|
|
|
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
void input_terminfo_get_names( array_list_t *lst, int skip_null )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
int i;
|
2006-07-23 20:52:03 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
CHECK( lst, );
|
|
|
|
input_init();
|
|
|
|
|
|
|
|
for( i=0; i<al_get_count( terminfo_mappings ); i++ )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
terminfo_mapping_t *m = (terminfo_mapping_t *)al_get( terminfo_mappings, i );
|
2005-09-25 22:39:48 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
if( skip_null && !m->seq )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
continue;
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
al_push( lst, m->name );
|
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
void input_function_get_names( array_list_t *lst )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
int i;
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
CHECK( lst, );
|
|
|
|
|
|
|
|
for( i=0; i<(sizeof(name_arr)/sizeof(wchar_t *)); i++ )
|
|
|
|
{
|
|
|
|
al_push( lst, name_arr[i] );
|
|
|
|
}
|
|
|
|
}
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
wchar_t input_function_get_code( const wchar_t *name )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2006-11-18 21:15:31 +00:00
|
|
|
|
2007-09-25 16:14:47 +00:00
|
|
|
int i;
|
|
|
|
for( i = 0; i<(sizeof( code_arr )/sizeof(wchar_t)) ; i++ )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
if( wcscmp( name, name_arr[i] ) == 0 )
|
2005-09-20 13:26:39 +00:00
|
|
|
{
|
2007-09-25 16:14:47 +00:00
|
|
|
return code_arr[i];
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
}
|
|
|
|
return -1;
|
2005-09-20 13:26:39 +00:00
|
|
|
}
|
2007-09-25 16:14:47 +00:00
|
|
|
|