2005-09-20 23:26:39 +10:00
/** \file input.c
2007-09-22 00:07:52 +10:00
2007-10-02 19:28:38 +10:00
Functions for reading a character of input from stdin .
2005-09-20 23:26:39 +10:00
*/
# 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-10 08:53:38 +10:00
# ifdef HAVE_SYS_TERMIOS_H
# include <sys/termios.h>
# endif
# ifdef HAVE_SYS_IOCTL_H
2005-09-20 23:26:39 +10:00
# include <sys/ioctl.h>
2006-08-10 08:53:38 +10:00
# endif
2005-09-20 23:26:39 +10: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 22:22:07 +10:00
# if HAVE_TERM_H
2005-09-20 23:26:39 +10:00
# include <term.h>
2006-01-19 22:22:07 +10:00
# elif HAVE_NCURSES_TERM_H
# include <ncurses/term.h>
# endif
2005-09-20 23:26:39 +10:00
# include <signal.h>
# include <dirent.h>
# include <wctype.h>
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-09-20 23:26:39 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10: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-26 00:18:26 +10:00
# include "event.h"
2006-02-10 01:50:20 +10:00
# include "signal.h"
2006-07-20 08:55:49 +10:00
2006-02-16 23:40:25 +10:00
# include "output.h"
2006-06-22 00:03:44 +10:00
# include "intern.h"
2007-09-26 02:14:47 +10:00
# include "halloc.h"
# include "halloc_util.h"
2005-09-20 23:26:39 +10:00
/**
2007-09-26 02:14:47 +10:00
Add a new terminfo mapping
2005-09-20 23:26:39 +10:00
*/
2007-09-26 02:14:47 +10:00
# define TERMINFO_ADD(key) \
{ \
2011-12-26 19:18:46 -08:00
terminfo_mapping_t * m = ( terminfo_mapping_t * ) halloc ( terminfo_mappings , sizeof ( terminfo_mapping_t ) ) ; \
2007-09-26 02:14:47 +10:00
m - > name = halloc_wcsdup ( terminfo_mappings , ( L # # # key ) + 4 ) ; \
m - > seq = key ; \
al_push ( terminfo_mappings , m ) ; \
}
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
/**
Struct representing a keybinding . Returned by input_get_mappings .
*/
2005-09-20 23:26:39 +10:00
typedef struct
{
2006-06-22 00:03:44 +10:00
const wchar_t * seq ; /**< Character sequence which generates this event */
const wchar_t * command ; /**< command that should be evaluated by this mapping */
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
input_mapping_t ;
2005-09-20 23:26:39 +10:00
2005-10-02 23:40:46 +10:00
/**
2007-09-26 02:14:47 +10: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 */
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
}
terminfo_mapping_t ;
2005-10-02 23:40:46 +10:00
2005-09-20 23:26:39 +10:00
/**
2007-10-02 19:28:38 +10:00
Names of all the input functions supported
2005-09-20 23:26:39 +10:00
*/
2011-12-26 19:18:46 -08:00
static const wchar_t * name_arr [ ] =
2005-09-20 23:26:39 +10: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 " backward-kill-line " ,
L " kill-whole-line " ,
L " kill-word " ,
L " backward-kill-word " ,
L " dump-functions " ,
L " history-token-search-backward " ,
L " history-token-search-forward " ,
L " self-insert " ,
2006-05-14 20:16:23 +10:00
L " null " ,
2006-07-24 06:52:03 +10:00
L " eof " ,
2006-10-09 11:15:29 +10:00
L " vi-arg-digit " ,
2006-11-01 08:01:49 +10:00
L " execute " ,
L " beginning-of-buffer " ,
2006-12-12 20:13:48 +10:00
L " end-of-buffer " ,
2007-09-22 00:05:49 +10:00
L " repaint " ,
L " up-line " ,
L " down-line "
2005-09-20 23:26:39 +10:00
}
;
/**
2007-10-02 19:28:38 +10:00
Description of each supported input function
2005-09-20 23:26:39 +10:00
*/
2006-06-14 03:23:37 +10:00
/*
static const wchar_t * desc_arr [ ] =
2005-09-20 23:26:39 +10: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 20:16:23 +10:00
L " Do nothing " ,
2006-07-24 06:52:03 +10:00
L " End of file " ,
L " Repeat command "
2005-09-20 23:26:39 +10:00
}
;
2006-06-14 03:23:37 +10:00
*/
2007-09-26 02:14:47 +10:00
2005-09-20 23:26:39 +10:00
/**
2007-10-02 19:28:38 +10:00
Internal code for each supported input function
2005-09-20 23:26:39 +10:00
*/
2011-12-26 19:18:46 -08:00
static const wchar_t code_arr [ ] =
2005-09-20 23:26:39 +10: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_BACKWARD_KILL_LINE ,
R_KILL_WHOLE_LINE ,
R_KILL_WORD ,
R_BACKWARD_KILL_WORD ,
R_DUMP_FUNCTIONS ,
R_HISTORY_TOKEN_SEARCH_BACKWARD ,
R_HISTORY_TOKEN_SEARCH_FORWARD ,
R_SELF_INSERT ,
2006-05-14 20:16:23 +10:00
R_NULL ,
2006-07-24 06:52:03 +10:00
R_EOF ,
2006-10-09 11:15:29 +10:00
R_VI_ARG_DIGIT ,
2006-11-01 08:01:49 +10:00
R_EXECUTE ,
R_BEGINNING_OF_BUFFER ,
R_END_OF_BUFFER ,
2007-09-22 00:05:49 +10:00
R_REPAINT ,
R_UP_LINE ,
R_DOWN_LINE
2005-09-20 23:26:39 +10:00
}
;
2006-01-24 06:40:14 +10:00
/**
Mappings for the current input mode
*/
2011-12-26 19:18:46 -08:00
static array_list_t mappings = { 0 , 0 , 0 } ;
2005-09-20 23:26:39 +10:00
2008-01-14 02:47:47 +10:00
/**
List of all terminfo mappings
*/
2007-09-26 02:14:47 +10:00
static array_list_t * terminfo_mappings = 0 ;
2005-09-20 23:26:39 +10:00
2006-06-20 10:50:10 +10:00
/**
2011-12-26 19:18:46 -08:00
Set to one when the input subsytem has been initialized .
2006-06-20 10:50:10 +10:00
*/
2006-03-10 23:38:09 +10:00
static int is_init = 0 ;
2008-01-14 02:47:47 +10:00
/**
Initialize terminfo .
*/
2007-09-26 02:14:47 +10:00
static void input_terminfo_init ( ) ;
2008-01-14 02:47:47 +10:00
/**
Deallocate memory used by terminfo . Or at least try to . Terminfo leaks .
*/
2007-09-26 02:14:47 +10:00
static void input_terminfo_destroy ( ) ;
2006-07-24 06:52:03 +10:00
2005-09-20 23:26:39 +10:00
/**
Returns the function description for the given function code .
*/
2007-09-26 02:14:47 +10:00
void input_mapping_add ( const wchar_t * sequence ,
const wchar_t * command )
2005-09-20 23:26:39 +10:00
{
int i ;
2007-09-26 02:14:47 +10:00
CHECK ( sequence , ) ;
CHECK ( command , ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
// debug( 0, L"Add mapping from %ls to %ls", escape(sequence, 1), escape(command, 1 ) );
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
for ( i = 0 ; i < al_get_count ( & mappings ) ; i + + )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
input_mapping_t * m = ( input_mapping_t * ) al_get ( & mappings , i ) ;
if ( wcscmp ( m - > seq , sequence ) = = 0 )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
m - > command = intern ( command ) ;
2005-09-20 23:26:39 +10:00
return ;
}
}
2011-12-26 19:18:46 -08:00
input_mapping_t * m = ( input_mapping_t * ) malloc ( sizeof ( input_mapping_t ) ) ;
2007-09-26 02:14:47 +10:00
m - > seq = intern ( sequence ) ;
m - > command = intern ( command ) ;
2011-12-26 19:18:46 -08:00
al_push ( & mappings , m ) ;
2005-09-20 23:26:39 +10:00
}
/**
2007-09-26 02:14:47 +10:00
Handle interruptions to key reading by reaping finshed jobs and
propagating the interrupt to the reader .
2005-09-20 23:26:39 +10:00
*/
2007-09-26 02:14:47 +10:00
static int interrupt_handler ( )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
/*
Fire any pending events
*/
2010-09-18 21:30:02 +08:00
event_fire ( NULL ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
/*
Reap stray processes , including printing exit status messages
*/
if ( job_reap ( 1 ) )
2007-10-06 00:59:19 +10:00
reader_repaint_needed ( ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
/*
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 23:26:39 +10:00
2011-12-26 19:18:46 -08:00
return R_NULL ;
2007-09-26 02:14:47 +10:00
}
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
int input_init ( )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
if ( is_init )
return 1 ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
is_init = 1 ;
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
input_common_init ( & interrupt_handler ) ;
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10: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 " ) ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
input_terminfo_init ( ) ;
2007-10-15 18:51:30 +10:00
/*
If we have no keybindings , add a few simple defaults
*/
if ( ! al_get_count ( & mappings ) )
{
input_mapping_add ( L " " , L " self-insert " ) ;
input_mapping_add ( L " \n " , L " execute " ) ;
input_mapping_add ( L " \t " , L " complete " ) ;
input_mapping_add ( L " \ x3 " , L " commandline \" \" " ) ;
input_mapping_add ( L " \ x4 " , L " exit " ) ;
input_mapping_add ( L " \ x5 " , L " bind " ) ;
}
2005-10-02 23:40:46 +10:00
2007-09-26 02:14:47 +10:00
return 1 ;
}
2005-10-02 23:40:46 +10:00
2007-09-26 02:14:47 +10:00
void input_destroy ( )
2005-10-02 23:40:46 +10:00
{
2007-09-26 02:14:47 +10:00
if ( ! is_init )
return ;
2011-12-26 19:18:46 -08:00
2005-10-02 23:40:46 +10:00
2007-09-26 02:14:47 +10:00
is_init = 0 ;
2011-12-26 19:18:46 -08:00
al_foreach ( & mappings , & free ) ;
2007-09-26 02:14:47 +10:00
al_destroy ( & mappings ) ;
2005-10-02 23:40:46 +10:00
2007-09-26 02:14:47 +10:00
input_common_destroy ( ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( del_curterm ( cur_term ) = = ERR )
2005-10-02 23:40:46 +10:00
{
2007-09-26 02:14:47 +10:00
debug ( 0 , _ ( L " Error while closing terminfo " ) ) ;
2005-10-02 23:40:46 +10:00
}
2007-09-26 02:14:47 +10:00
input_terminfo_destroy ( ) ;
2011-12-26 19:18:46 -08:00
2005-10-02 23:40:46 +10:00
}
2005-09-20 23:26:39 +10:00
/**
2007-09-26 02:14:47 +10:00
Perform the action of the specified binding
2005-09-20 23:26:39 +10:00
*/
2007-09-26 02:14:47 +10:00
static wint_t input_exec_binding ( input_mapping_t * m , const wchar_t * seq )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
wchar_t code = input_function_get_code ( m - > command ) ;
if ( code ! = - 1 )
2011-12-26 19:18:46 -08:00
{
2007-09-26 02:14:47 +10:00
switch ( code )
2005-09-20 23:26:39 +10:00
{
2005-09-26 08:39:48 +10:00
2007-09-26 02:14:47 +10:00
case R_SELF_INSERT :
{
return seq [ 0 ] ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
default :
{
2007-09-26 02:14:47 +10:00
return code ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
}
else
{
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
/*
This key sequence is bound to a command , which
is sent to the parser for evaluation .
*/
2008-01-09 05:31:45 +10:00
int last_status = proc_get_last_status ( ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
eval ( m - > command , 0 , TOP ) ;
2011-12-26 19:18:46 -08:00
2008-01-09 05:31:45 +10:00
proc_set_last_status ( last_status ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
/*
We still need to return something to the caller , R_NULL
2011-12-26 19:18:46 -08:00
tells the reader that no key press needs to be handled ,
2007-09-26 02:14:47 +10:00
and no repaint is needed .
Bindings that produce output should emit a R_REPAINT
function by calling ' commandline - f repaint ' to tell
2011-12-26 19:18:46 -08:00
fish that a repaint is in order .
2007-09-26 02:14:47 +10:00
*/
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
return R_NULL ;
2005-09-26 08:39:48 +10:00
2007-09-26 02:14:47 +10:00
}
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10: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 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
return input_exec_binding ( m , m - > seq ) ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
input_unreadch ( c ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( m - > seq ! = 0 )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
2011-12-26 19:18:46 -08:00
for ( j = 0 ; m - > seq [ j ] ! = L ' \0 ' & &
2007-09-26 02:14:47 +10:00
m - > seq [ j ] = = ( c = input_common_readch ( j > 0 ) ) ; j + + )
;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( m - > seq [ j ] = = L ' \0 ' )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
return input_exec_binding ( m , m - > seq ) ;
2005-09-20 23:26:39 +10:00
}
else
{
2007-09-26 02:14:47 +10:00
/*
Return the read characters
*/
input_unreadch ( c ) ;
for ( k = j - 1 ; k > = 0 ; k - - )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
input_unreadch ( m - > seq [ k ] ) ;
2005-09-20 23:26:39 +10:00
}
}
}
2007-09-26 02:14:47 +10:00
return 0 ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
}
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
void input_unreadch ( wint_t ch )
{
input_common_unreadch ( ch ) ;
}
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
wint_t input_readch ( )
{
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
int i ;
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
CHECK_BLOCK ( R_NULL ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
/*
Clear the interrupted flag
*/
reader_interrupted ( ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
/*
2007-10-02 19:28:38 +10:00
Search for sequence in mapping tables
2007-09-26 02:14:47 +10:00
*/
2007-10-15 18:51:30 +10:00
2007-09-26 02:14:47 +10:00
while ( 1 )
2005-09-20 23:26:39 +10:00
{
2007-10-02 19:28:38 +10:00
input_mapping_t * generic = 0 ;
2007-09-26 02:14:47 +10:00
for ( i = 0 ; i < al_get_count ( & mappings ) ; i + + )
2005-09-20 23:26:39 +10:00
{
2007-10-02 19:28:38 +10:00
input_mapping_t * m = ( input_mapping_t * ) al_get ( & mappings , i ) ;
2011-12-26 19:18:46 -08:00
wint_t res = input_try_mapping ( m ) ;
2007-09-26 02:14:47 +10:00
if ( res )
2007-10-02 19:28:38 +10:00
return res ;
2011-12-26 19:18:46 -08:00
2007-10-02 19:28:38 +10:00
if ( wcslen ( m - > seq ) = = 0 )
{
generic = m ;
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-10-02 23:40:46 +10:00
/*
2007-09-26 02:14:47 +10:00
No matching exact mapping , try to find generic mapping .
2005-10-02 23:40:46 +10:00
*/
2007-10-02 19:28:38 +10:00
if ( generic )
2011-12-26 19:18:46 -08:00
{
2007-10-02 19:28:38 +10:00
wchar_t arr [ 2 ] =
{
2011-12-26 19:18:46 -08:00
0 ,
2007-10-02 19:28:38 +10:00
0
}
;
arr [ 0 ] = input_common_readch ( 0 ) ;
2011-12-26 19:18:46 -08:00
return input_exec_binding ( generic , arr ) ;
2005-10-02 23:40:46 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
/*
2007-10-02 19:28:38 +10:00
No action to take on specified character , ignore it
2007-09-26 02:14:47 +10:00
and move to next one .
2007-10-15 18:51:30 +10:00
*/
2011-12-26 19:18:46 -08:00
input_common_readch ( 0 ) ; }
2007-09-26 02:14:47 +10:00
}
void input_mapping_get_names ( array_list_t * list )
{
int i ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
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 23:40:46 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
int input_mapping_erase ( const wchar_t * sequence )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
int ok = 0 ;
int i ;
size_t sz = al_get_count ( & mappings ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10: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 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
if ( i ! = ( sz - 1 ) )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
al_set ( & mappings , i , al_get ( & mappings , sz - 1 ) ) ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
al_truncate ( & mappings , sz - 1 ) ;
ok = 1 ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
free ( m ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
break ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
return ok ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
const wchar_t * input_mapping_get ( const wchar_t * sequence )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
int i ;
size_t sz = al_get_count ( & mappings ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
for ( i = 0 ; i < sz ; i + + )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
input_mapping_t * m = ( input_mapping_t * ) al_get ( & mappings , i ) ;
if ( ! wcscmp ( sequence , m - > seq ) )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
return m - > command ;
2005-09-20 23:26:39 +10:00
}
}
2007-09-26 02:14:47 +10:00
return 0 ;
2005-09-20 23:26:39 +10:00
}
2007-09-29 07:32:27 +10:00
2005-10-25 01:26:25 +10:00
/**
2007-09-26 02:14:47 +10:00
Add all terminfo mappings
*/
static void input_terminfo_init ( )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
terminfo_mappings = al_halloc ( 0 ) ;
2011-12-26 19:18:46 -08:00
2007-09-29 07:36:16 +10:00
TERMINFO_ADD ( key_a1 ) ;
TERMINFO_ADD ( key_a3 ) ;
TERMINFO_ADD ( key_b2 ) ;
TERMINFO_ADD ( key_backspace ) ;
TERMINFO_ADD ( key_beg ) ;
TERMINFO_ADD ( key_btab ) ;
TERMINFO_ADD ( key_c1 ) ;
TERMINFO_ADD ( key_c3 ) ;
TERMINFO_ADD ( key_cancel ) ;
TERMINFO_ADD ( key_catab ) ;
TERMINFO_ADD ( key_clear ) ;
TERMINFO_ADD ( key_close ) ;
TERMINFO_ADD ( key_command ) ;
TERMINFO_ADD ( key_copy ) ;
TERMINFO_ADD ( key_create ) ;
TERMINFO_ADD ( key_ctab ) ;
TERMINFO_ADD ( key_dc ) ;
TERMINFO_ADD ( key_dl ) ;
TERMINFO_ADD ( key_down ) ;
TERMINFO_ADD ( key_eic ) ;
TERMINFO_ADD ( key_end ) ;
TERMINFO_ADD ( key_enter ) ;
TERMINFO_ADD ( key_eol ) ;
TERMINFO_ADD ( key_eos ) ;
TERMINFO_ADD ( key_exit ) ;
TERMINFO_ADD ( key_f0 ) ;
TERMINFO_ADD ( key_f1 ) ;
TERMINFO_ADD ( key_f2 ) ;
TERMINFO_ADD ( key_f3 ) ;
TERMINFO_ADD ( key_f4 ) ;
TERMINFO_ADD ( key_f5 ) ;
TERMINFO_ADD ( key_f6 ) ;
TERMINFO_ADD ( key_f7 ) ;
TERMINFO_ADD ( key_f8 ) ;
TERMINFO_ADD ( key_f9 ) ;
TERMINFO_ADD ( key_f10 ) ;
TERMINFO_ADD ( key_f11 ) ;
TERMINFO_ADD ( key_f12 ) ;
TERMINFO_ADD ( key_f13 ) ;
TERMINFO_ADD ( key_f14 ) ;
TERMINFO_ADD ( key_f15 ) ;
TERMINFO_ADD ( key_f16 ) ;
TERMINFO_ADD ( key_f17 ) ;
TERMINFO_ADD ( key_f18 ) ;
TERMINFO_ADD ( key_f19 ) ;
TERMINFO_ADD ( key_f20 ) ;
2007-10-02 19:28:38 +10:00
/*
2007-10-02 20:09:37 +10:00
I know of no keyboard with more than 20 function keys , so
adding the rest here makes very little sense , since it will
take up a lot of room in any listings ( like tab completions ) ,
but with no benefit .
2007-10-02 19:28:38 +10:00
*/
/*
TERMINFO_ADD ( key_f21 ) ;
2007-09-29 07:36:16 +10:00
TERMINFO_ADD ( key_f22 ) ;
TERMINFO_ADD ( key_f23 ) ;
TERMINFO_ADD ( key_f24 ) ;
TERMINFO_ADD ( key_f25 ) ;
TERMINFO_ADD ( key_f26 ) ;
TERMINFO_ADD ( key_f27 ) ;
TERMINFO_ADD ( key_f28 ) ;
TERMINFO_ADD ( key_f29 ) ;
TERMINFO_ADD ( key_f30 ) ;
TERMINFO_ADD ( key_f31 ) ;
TERMINFO_ADD ( key_f32 ) ;
TERMINFO_ADD ( key_f33 ) ;
TERMINFO_ADD ( key_f34 ) ;
TERMINFO_ADD ( key_f35 ) ;
TERMINFO_ADD ( key_f36 ) ;
TERMINFO_ADD ( key_f37 ) ;
TERMINFO_ADD ( key_f38 ) ;
TERMINFO_ADD ( key_f39 ) ;
TERMINFO_ADD ( key_f40 ) ;
TERMINFO_ADD ( key_f41 ) ;
TERMINFO_ADD ( key_f42 ) ;
TERMINFO_ADD ( key_f43 ) ;
TERMINFO_ADD ( key_f44 ) ;
TERMINFO_ADD ( key_f45 ) ;
TERMINFO_ADD ( key_f46 ) ;
TERMINFO_ADD ( key_f47 ) ;
TERMINFO_ADD ( key_f48 ) ;
TERMINFO_ADD ( key_f49 ) ;
TERMINFO_ADD ( key_f50 ) ;
TERMINFO_ADD ( key_f51 ) ;
TERMINFO_ADD ( key_f52 ) ;
TERMINFO_ADD ( key_f53 ) ;
TERMINFO_ADD ( key_f54 ) ;
TERMINFO_ADD ( key_f55 ) ;
TERMINFO_ADD ( key_f56 ) ;
TERMINFO_ADD ( key_f57 ) ;
TERMINFO_ADD ( key_f58 ) ;
TERMINFO_ADD ( key_f59 ) ;
TERMINFO_ADD ( key_f60 ) ;
TERMINFO_ADD ( key_f61 ) ;
TERMINFO_ADD ( key_f62 ) ;
TERMINFO_ADD ( key_f63 ) ; */
TERMINFO_ADD ( key_find ) ;
TERMINFO_ADD ( key_help ) ;
TERMINFO_ADD ( key_home ) ;
TERMINFO_ADD ( key_ic ) ;
TERMINFO_ADD ( key_il ) ;
TERMINFO_ADD ( key_left ) ;
TERMINFO_ADD ( key_ll ) ;
TERMINFO_ADD ( key_mark ) ;
TERMINFO_ADD ( key_message ) ;
TERMINFO_ADD ( key_move ) ;
TERMINFO_ADD ( key_next ) ;
TERMINFO_ADD ( key_npage ) ;
TERMINFO_ADD ( key_open ) ;
TERMINFO_ADD ( key_options ) ;
TERMINFO_ADD ( key_ppage ) ;
TERMINFO_ADD ( key_previous ) ;
TERMINFO_ADD ( key_print ) ;
TERMINFO_ADD ( key_redo ) ;
TERMINFO_ADD ( key_reference ) ;
TERMINFO_ADD ( key_refresh ) ;
TERMINFO_ADD ( key_replace ) ;
TERMINFO_ADD ( key_restart ) ;
TERMINFO_ADD ( key_resume ) ;
TERMINFO_ADD ( key_right ) ;
TERMINFO_ADD ( key_save ) ;
TERMINFO_ADD ( key_sbeg ) ;
TERMINFO_ADD ( key_scancel ) ;
TERMINFO_ADD ( key_scommand ) ;
TERMINFO_ADD ( key_scopy ) ;
TERMINFO_ADD ( key_screate ) ;
TERMINFO_ADD ( key_sdc ) ;
TERMINFO_ADD ( key_sdl ) ;
TERMINFO_ADD ( key_select ) ;
TERMINFO_ADD ( key_send ) ;
TERMINFO_ADD ( key_seol ) ;
TERMINFO_ADD ( key_sexit ) ;
TERMINFO_ADD ( key_sf ) ;
TERMINFO_ADD ( key_sfind ) ;
TERMINFO_ADD ( key_shelp ) ;
TERMINFO_ADD ( key_shome ) ;
TERMINFO_ADD ( key_sic ) ;
TERMINFO_ADD ( key_sleft ) ;
TERMINFO_ADD ( key_smessage ) ;
TERMINFO_ADD ( key_smove ) ;
TERMINFO_ADD ( key_snext ) ;
TERMINFO_ADD ( key_soptions ) ;
TERMINFO_ADD ( key_sprevious ) ;
TERMINFO_ADD ( key_sprint ) ;
TERMINFO_ADD ( key_sr ) ;
TERMINFO_ADD ( key_sredo ) ;
TERMINFO_ADD ( key_sreplace ) ;
TERMINFO_ADD ( key_sright ) ;
TERMINFO_ADD ( key_srsume ) ;
TERMINFO_ADD ( key_ssave ) ;
TERMINFO_ADD ( key_ssuspend ) ;
TERMINFO_ADD ( key_stab ) ;
TERMINFO_ADD ( key_sundo ) ;
TERMINFO_ADD ( key_suspend ) ;
TERMINFO_ADD ( key_undo ) ;
TERMINFO_ADD ( key_up ) ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
static void input_terminfo_destroy ( )
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( terminfo_mappings )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
halloc_free ( terminfo_mappings ) ;
2005-09-20 23:26:39 +10:00
}
}
2007-09-26 02:14:47 +10:00
const wchar_t * input_terminfo_get_sequence ( const wchar_t * name )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
const char * res = 0 ;
2011-12-26 19:18:46 -08:00
int i ;
2007-09-26 02:14:47 +10:00
static string_buffer_t * buff = 0 ;
int err = ENOENT ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
CHECK ( name , 0 ) ;
input_init ( ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
for ( i = 0 ; i < al_get_count ( terminfo_mappings ) ; i + + )
2006-01-18 22:42:48 +10:00
{
2007-09-26 02:14:47 +10:00
terminfo_mapping_t * m = ( terminfo_mapping_t * ) al_get ( terminfo_mappings , i ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( ! wcscmp ( name , m - > name ) )
{
res = m - > seq ;
err = EILSEQ ;
break ;
}
2006-01-18 22:42:48 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( ! res )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
errno = err ;
return 0 ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( ! buff )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
buff = sb_halloc ( global_context ) ;
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
sb_clear ( buff ) ;
sb_printf ( buff , L " %s " , res ) ;
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
return ( wchar_t * ) buff - > buff ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
const wchar_t * input_terminfo_get_name ( const wchar_t * seq )
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
int i ;
2007-09-26 02:14:47 +10:00
static string_buffer_t * buff = 0 ;
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
CHECK ( seq , 0 ) ;
input_init ( ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( ! buff )
2006-08-14 09:05:02 +10:00
{
2007-09-26 02:14:47 +10:00
buff = sb_halloc ( global_context ) ;
2006-08-14 09:05:02 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
for ( i = 0 ; i < al_get_count ( terminfo_mappings ) ; i + + )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
terminfo_mapping_t * m = ( terminfo_mapping_t * ) al_get ( terminfo_mappings , i ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( ! m - > seq )
{
continue ;
}
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
sb_clear ( buff ) ;
sb_printf ( buff , L " %s " , m - > seq ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( ! wcscmp ( seq , ( wchar_t * ) buff - > buff ) )
{
return m - > name ;
}
2005-09-20 23:26:39 +10:00
}
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
return 0 ;
2011-12-26 19:18:46 -08:00
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
void input_terminfo_get_names ( array_list_t * lst , int skip_null )
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
int i ;
2006-07-24 06:52:03 +10:00
2007-09-26 02:14:47 +10:00
CHECK ( lst , ) ;
input_init ( ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
for ( i = 0 ; i < al_get_count ( terminfo_mappings ) ; i + + )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
terminfo_mapping_t * m = ( terminfo_mapping_t * ) al_get ( terminfo_mappings , i ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
if ( skip_null & & ! m - > seq )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
continue ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
al_push ( lst , m - > name ) ;
}
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
void input_function_get_names ( array_list_t * lst )
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
int i ;
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
CHECK ( lst , ) ;
2011-12-26 19:18:46 -08:00
2007-09-26 02:14:47 +10:00
for ( i = 0 ; i < ( sizeof ( name_arr ) / sizeof ( wchar_t * ) ) ; i + + )
{
al_push ( lst , name_arr [ i ] ) ;
}
}
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
wchar_t input_function_get_code ( const wchar_t * name )
2005-09-20 23:26:39 +10:00
{
2006-11-19 07:15:31 +10:00
2007-09-26 02:14:47 +10:00
int i ;
for ( i = 0 ; i < ( sizeof ( code_arr ) / sizeof ( wchar_t ) ) ; i + + )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
if ( wcscmp ( name , name_arr [ i ] ) = = 0 )
2005-09-20 23:26:39 +10:00
{
2007-09-26 02:14:47 +10:00
return code_arr [ i ] ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
}
2011-12-26 19:18:46 -08:00
return - 1 ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00