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>
2012-01-14 02:42:17 -08:00
# include <assert.h>
2005-09-20 23:26:39 +10:00
# 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_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
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"
2012-02-07 23:15:32 -08:00
# include <vector>
2007-09-26 02:14:47 +10:00
/**
Struct representing a keybinding . Returned by input_get_mappings .
*/
2011-12-31 15:57:30 -08:00
struct input_mapping_t
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08:00
wcstring seq ; /**< Character sequence which generates this event */
wcstring command ; /**< command that should be evaluated by this mapping */
2012-11-18 11:23:22 +01:00
2011-12-31 15:57:30 -08:00
input_mapping_t ( const wcstring & s , const wcstring & c ) : seq ( s ) , command ( c ) { }
} ;
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
*/
2012-02-07 23:15:32 -08:00
struct terminfo_mapping_t
2007-09-26 02:14:47 +10:00
{
2012-11-18 16:30:30 -08:00
const wchar_t * name ; /**< Name of key */
const char * seq ; /**< Character sequence generated on keypress. Constant string. */
2012-11-18 11:23:22 +01:00
2012-02-07 23:15:32 -08:00
} ;
2007-09-26 02:14:47 +10:00
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
*/
2012-11-07 19:59:20 -08:00
static const wchar_t * const name_arr [ ] =
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08: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 " ,
2012-12-20 17:58:09 -08:00
L " backward-kill-path-component " ,
2012-11-18 16:30:30 -08:00
L " dump-functions " ,
L " history-token-search-backward " ,
L " history-token-search-forward " ,
L " self-insert " ,
2013-05-20 21:42:34 +02:00
L " transpose-chars " ,
2013-05-27 23:25:55 +02:00
L " transpose-words " ,
2013-09-09 18:46:16 +02:00
L " upcase-word " ,
L " downcase-word " ,
L " capitalize-word " ,
2012-11-18 16:30:30 -08:00
L " null " ,
L " eof " ,
L " vi-arg-digit " ,
L " execute " ,
L " beginning-of-buffer " ,
L " end-of-buffer " ,
L " repaint " ,
L " up-line " ,
L " down-line " ,
L " suppress-autosuggestion " ,
L " accept-autosuggestion "
2005-09-20 23:26:39 +10:00
}
2012-11-18 16:30:30 -08:00
;
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
{
2012-11-18 11:23:22 +01: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 key bindings " ,
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 " ,
L " Do nothing " ,
L " End of file " ,
L " Repeat command "
2005-09-20 23:26:39 +10:00
}
2012-11-18 11:23:22 +01: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
*/
2012-11-18 11:23:22 +01:00
static const wchar_t code_arr [ ] =
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08: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 ,
2012-12-20 17:58:09 -08:00
R_BACKWARD_KILL_PATH_COMPONENT ,
2012-11-18 16:30:30 -08:00
R_DUMP_FUNCTIONS ,
R_HISTORY_TOKEN_SEARCH_BACKWARD ,
R_HISTORY_TOKEN_SEARCH_FORWARD ,
R_SELF_INSERT ,
2013-05-20 21:42:34 +02:00
R_TRANSPOSE_CHARS ,
2013-05-27 23:25:55 +02:00
R_TRANSPOSE_WORDS ,
2013-09-09 18:46:16 +02:00
R_UPCASE_WORD ,
R_DOWNCASE_WORD ,
R_CAPITALIZE_WORD ,
2012-11-18 16:30:30 -08:00
R_NULL ,
R_EOF ,
R_VI_ARG_DIGIT ,
R_EXECUTE ,
R_BEGINNING_OF_BUFFER ,
R_END_OF_BUFFER ,
R_REPAINT ,
R_UP_LINE ,
R_DOWN_LINE ,
R_SUPPRESS_AUTOSUGGESTION ,
R_ACCEPT_AUTOSUGGESTION
2005-09-20 23:26:39 +10:00
}
2012-11-18 16:30:30 -08:00
;
2005-09-20 23:26:39 +10:00
2012-02-07 23:15:32 -08:00
/** Mappings for the current input mode */
static std : : vector < input_mapping_t > mapping_list ;
/* Terminfo map list */
static std : : vector < terminfo_mapping_t > terminfo_mappings ;
2012-07-17 12:47:01 -07:00
# define TERMINFO_ADD(key) { (L ## #key) + 4, key }
2012-02-07 23:15:32 -08:00
2005-09-20 23:26:39 +10:00
2008-01-14 02:47:47 +10:00
/**
List of all terminfo mappings
*/
2012-02-07 23:15:32 -08:00
static std : : vector < terminfo_mapping_t > mappings ;
2005-09-20 23:26:39 +10:00
2006-06-20 10:50:10 +10:00
/**
2012-11-18 11:23:22 +01:00
Set to one when the input subsytem has been initialized .
2006-06-20 10:50:10 +10:00
*/
2013-02-15 14:00:25 -08:00
static bool is_init = false ;
2006-03-10 23:38:09 +10:00
2008-01-14 02:47:47 +10:00
/**
Initialize terminfo .
*/
2007-09-26 02:14:47 +10:00
static void input_terminfo_init ( ) ;
2012-02-07 23:15:32 -08:00
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 .
*/
2013-04-15 13:07:17 -07:00
void input_mapping_add ( const wchar_t * sequence , const wchar_t * command )
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08:00
CHECK ( sequence , ) ;
CHECK ( command , ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
// debug( 0, L"Add mapping from %ls to %ls", escape(sequence, 1), escape(command, 1 ) );
2012-11-18 11:23:22 +01:00
2013-04-15 13:07:17 -07:00
for ( size_t i = 0 ; i < mapping_list . size ( ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
input_mapping_t & m = mapping_list . at ( i ) ;
if ( m . seq = = sequence )
{
m . command = command ;
return ;
}
2012-11-18 11:23:22 +01:00
}
mapping_list . push_back ( input_mapping_t ( sequence , command ) ) ;
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
{
2012-11-18 11:23:22 +01:00
/*
2012-11-18 16:30:30 -08:00
Fire any pending events
*/
event_fire ( NULL ) ;
/*
Reap stray processes , including printing exit status messages
2012-11-18 11:23:22 +01:00
*/
2012-11-18 16:30:30 -08:00
if ( job_reap ( 1 ) )
reader_repaint_needed ( ) ;
/*
Tell the reader an event occured
*/
2013-01-22 11:00:02 +01:00
if ( reader_reading_interrupted ( ) )
2012-11-18 16:30:30 -08:00
{
/*
Return 3 , i . e . the character read by a Control - C .
*/
return 3 ;
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
return R_NULL ;
2007-09-26 02:14:47 +10:00
}
2005-09-20 23:26:39 +10:00
2012-03-05 14:18:16 -08:00
void update_fish_term256 ( void )
{
2012-03-06 14:32:00 -08:00
/* Infer term256 support. If fish_term256 is set, we respect it; otherwise try to detect it from the TERM variable */
2012-03-05 14:18:16 -08:00
env_var_t fish_term256 = env_get_string ( L " fish_term256 " ) ;
bool support_term256 ;
2012-11-18 16:30:30 -08:00
if ( ! fish_term256 . missing_or_empty ( ) )
{
2012-03-05 14:18:16 -08:00
support_term256 = from_string < bool > ( fish_term256 ) ;
2012-11-18 16:30:30 -08:00
}
else
{
2012-03-05 14:18:16 -08:00
env_var_t term = env_get_string ( L " TERM " ) ;
2012-11-18 16:30:30 -08:00
if ( term . missing ( ) )
{
2012-04-01 00:53:47 -07:00
support_term256 = false ;
2012-11-18 16:30:30 -08:00
}
else if ( term . find ( L " 256color " ) ! = wcstring : : npos )
{
2012-06-05 02:06:33 -07:00
/* Explicitly supported */
support_term256 = true ;
2012-11-18 16:30:30 -08:00
}
else if ( term . find ( L " xterm " ) ! = wcstring : : npos )
{
2012-06-05 02:06:33 -07:00
// assume that all xterms are 256, except for OS X SnowLeopard
env_var_t prog = env_get_string ( L " TERM_PROGRAM " ) ;
support_term256 = ( prog ! = L " Apple_Terminal " ) ;
2012-11-18 16:30:30 -08:00
}
else
{
2012-06-05 02:06:33 -07:00
// Don't know, default to false
support_term256 = false ;
2012-04-01 00:53:47 -07:00
}
2012-03-05 14:18:16 -08:00
}
output_set_supports_term256 ( support_term256 ) ;
}
2007-09-26 02:14:47 +10:00
int input_init ( )
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08:00
if ( is_init )
return 1 ;
2012-11-18 11:23:22 +01:00
2013-02-15 14:00:25 -08:00
is_init = true ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
input_common_init ( & interrupt_handler ) ;
2012-11-18 11:23:22 +01:00
2013-05-13 01:41:50 -07:00
int errret ;
if ( setupterm ( 0 , STDOUT_FILENO , & errret ) = = ERR )
2012-11-18 16:30:30 -08:00
{
debug ( 0 , _ ( L " Could not set up terminal " ) ) ;
exit_without_destructors ( 1 ) ;
}
const env_var_t term = env_get_string ( L " TERM " ) ;
2012-01-14 02:42:17 -08:00
assert ( ! term . missing ( ) ) ;
2012-12-19 13:31:06 -08:00
output_set_term ( term ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
input_terminfo_init ( ) ;
2012-11-18 11:23:22 +01:00
2012-03-05 14:18:16 -08:00
update_fish_term256 ( ) ;
2012-03-05 10:44:08 -08:00
2012-11-18 16:30:30 -08:00
/* If we have no keybindings, add a few simple defaults */
if ( mapping_list . empty ( ) )
{
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 " ) ;
}
return 1 ;
2007-09-26 02:14:47 +10:00
}
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
{
2012-11-18 16:30:30 -08:00
if ( ! is_init )
return ;
2012-11-18 11:23:22 +01:00
2013-02-15 14:00:25 -08:00
is_init = false ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
input_common_destroy ( ) ;
2012-11-18 11:23:22 +01:00
2013-02-26 18:31:08 -08:00
if ( fish_del_curterm ( cur_term ) = = ERR )
2012-11-18 16:30:30 -08:00
{
debug ( 0 , _ ( L " Error while closing terminfo " ) ) ;
}
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
*/
2012-11-18 16:30:30 -08:00
static wint_t input_exec_binding ( const input_mapping_t & m , const wcstring & seq )
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08:00
wchar_t code = input_function_get_code ( m . command ) ;
2013-05-23 21:11:10 +03:00
if ( code ! = ( wchar_t ) - 1 )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
switch ( code )
{
2012-11-18 11:23:22 +01:00
2012-11-19 00:31:03 -08:00
case R_SELF_INSERT :
{
return seq [ 0 ] ;
}
default :
{
return code ;
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
else
{
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
This key sequence is bound to a command , which
is sent to the parser for evaluation .
*/
int last_status = proc_get_last_status ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
parser_t : : principal_parser ( ) . eval ( m . command . c_str ( ) , io_chain_t ( ) , TOP ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
proc_set_last_status ( last_status ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
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 .
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
Bindings that produce output should emit a R_REPAINT
function by calling ' commandline - f repaint ' to tell
fish that a repaint is in order .
*/
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
return R_NULL ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
/**
Try reading the specified function mapping
*/
2012-11-18 16:30:30 -08:00
static wint_t input_try_mapping ( const input_mapping_t & m )
2007-09-26 02:14:47 +10:00
{
2012-11-18 16:30:30 -08:00
wint_t c = 0 ;
int j ;
/*
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 ) )
{
return input_exec_binding ( m , m . seq ) ;
}
input_unreadch ( c ) ;
2007-09-26 02:14:47 +10:00
2011-12-31 15:57:30 -08:00
const wchar_t * str = m . seq . c_str ( ) ;
2012-06-02 15:43:18 -07:00
for ( j = 0 ; str [ j ] ! = L ' \0 ' ; j + + )
{
bool timed = ( j > 0 ) ;
c = input_common_readch ( timed ) ;
if ( str [ j ] ! = c )
break ;
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( str [ j ] = = L ' \0 ' )
2011-12-31 15:57:30 -08:00
{
2012-06-02 15:43:18 -07:00
/* We matched the entire sequence */
2012-11-18 16:30:30 -08:00
return input_exec_binding ( m , m . seq ) ;
2011-12-31 15:57:30 -08:00
}
else
{
2012-06-02 15:43:18 -07:00
int k ;
2011-12-31 15:57:30 -08:00
/*
Return the read characters
*/
input_unreadch ( c ) ;
2012-11-18 16:30:30 -08:00
for ( k = j - 1 ; k > = 0 ; k - - )
2011-12-31 15:57:30 -08:00
{
2012-11-18 16:30:30 -08:00
input_unreadch ( m . seq [ k ] ) ;
2011-12-31 15:57:30 -08:00
}
}
2012-11-18 16:30:30 -08:00
return 0 ;
2012-11-18 11:23:22 +01:00
2007-09-26 02:14:47 +10:00
}
2005-09-20 23:26:39 +10:00
2012-11-18 16:30:30 -08:00
void input_unreadch ( wint_t ch )
2007-09-26 02:14:47 +10:00
{
2012-11-18 16:30:30 -08:00
input_common_unreadch ( ch ) ;
2007-09-26 02:14:47 +10:00
}
2005-09-20 23:26:39 +10:00
2007-09-26 02:14:47 +10:00
wint_t input_readch ( )
{
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
size_t i ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
CHECK_BLOCK ( R_NULL ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
Clear the interrupted flag
*/
2013-01-20 22:23:27 +01:00
reader_reset_interrupted ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
Search for sequence in mapping tables
*/
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
while ( 1 )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
const input_mapping_t * generic = 0 ;
for ( i = 0 ; i < mapping_list . size ( ) ; i + + )
{
const input_mapping_t & m = mapping_list . at ( i ) ;
wint_t res = input_try_mapping ( m ) ;
if ( res )
return res ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( m . seq . length ( ) = = 0 )
{
generic = & m ;
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
No matching exact mapping , try to find generic mapping .
*/
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
if ( generic )
{
wchar_t arr [ 2 ] =
2012-07-06 16:25:10 -07:00
{
2012-11-18 11:23:22 +01:00
0 ,
2012-07-06 16:25:10 -07:00
0
}
2012-11-18 16:30:30 -08:00
;
arr [ 0 ] = input_common_readch ( 0 ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
return input_exec_binding ( * generic , arr ) ;
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
/*
No action to take on specified character , ignore it
and move to next one .
*/
wchar_t c = input_common_readch ( 0 ) ;
2012-11-18 11:23:22 +01:00
2012-07-06 16:25:10 -07:00
/* If it's closed, then just return */
if ( c = = R_EOF )
{
return WEOF ;
}
2012-11-18 11:23:22 +01:00
}
2007-09-26 02:14:47 +10:00
}
2012-11-18 16:30:30 -08:00
void input_mapping_get_names ( wcstring_list_t & lst )
2007-09-26 02:14:47 +10:00
{
2012-11-18 16:30:30 -08:00
size_t i ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( i = 0 ; i < mapping_list . size ( ) ; i + + )
{
const input_mapping_t & m = mapping_list . at ( i ) ;
2011-12-31 15:57:30 -08:00
lst . push_back ( wcstring ( m . seq ) ) ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
2012-11-18 16:30:30 -08:00
bool input_mapping_erase ( const wchar_t * sequence )
2005-09-20 23:26:39 +10:00
{
2011-12-31 15:57:30 -08:00
ASSERT_IS_MAIN_THREAD ( ) ;
2012-11-18 16:30:30 -08:00
bool result = false ;
size_t i , sz = mapping_list . size ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( i = 0 ; i < sz ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
const input_mapping_t & m = mapping_list . at ( i ) ;
if ( sequence = = m . seq )
{
if ( i ! = ( sz - 1 ) )
{
2011-12-31 15:57:30 -08:00
mapping_list [ i ] = mapping_list [ sz - 1 ] ;
2012-11-18 16:30:30 -08:00
}
2011-12-31 15:57:30 -08:00
mapping_list . pop_back ( ) ;
2012-11-18 16:30:30 -08:00
result = true ;
break ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
return result ;
2005-09-20 23:26:39 +10:00
}
2012-11-18 16:30:30 -08:00
bool input_mapping_get ( const wcstring & sequence , wcstring & cmd )
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08:00
size_t i , sz = mapping_list . size ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( i = 0 ; i < sz ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
const input_mapping_t & m = mapping_list . at ( i ) ;
if ( sequence = = m . seq )
{
cmd = m . command ;
2011-12-31 15:57:30 -08:00
return true ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
return false ;
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
{
2012-11-18 16:30:30 -08:00
const terminfo_mapping_t tinfos [ ] =
{
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 ) ,
/*
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 .
*/
/*
TERMINFO_ADD ( key_f21 ) ,
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 )
2012-07-17 12:47:01 -07:00
} ;
const size_t count = sizeof tinfos / sizeof * tinfos ;
terminfo_mappings . reserve ( terminfo_mappings . size ( ) + count ) ;
terminfo_mappings . insert ( terminfo_mappings . end ( ) , tinfos , tinfos + count ) ;
2005-09-20 23:26:39 +10:00
}
2013-04-15 13:07:17 -07:00
bool input_terminfo_get_sequence ( const wchar_t * name , wcstring * out_seq )
2005-09-20 23:26:39 +10:00
{
2012-02-07 23:17:20 -08:00
ASSERT_IS_MAIN_THREAD ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
const char * res = 0 ;
int err = ENOENT ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
CHECK ( name , 0 ) ;
input_init ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( size_t i = 0 ; i < terminfo_mappings . size ( ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
const terminfo_mapping_t & m = terminfo_mappings . at ( i ) ;
if ( ! wcscmp ( name , m . name ) )
{
res = m . seq ;
err = EILSEQ ;
break ;
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
if ( ! res )
{
errno = err ;
2013-04-15 13:07:17 -07:00
return false ;
2013-05-05 02:33:17 -07:00
}
2013-04-15 13:07:17 -07:00
* out_seq = format_string ( L " %s " , res ) ;
return true ;
2012-11-18 11:23:22 +01:00
2005-09-20 23:26:39 +10:00
}
2012-11-18 16:30:30 -08:00
bool input_terminfo_get_name ( const wcstring & seq , wcstring & name )
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08:00
input_init ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( size_t i = 0 ; i < terminfo_mappings . size ( ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
terminfo_mapping_t & m = terminfo_mappings . at ( i ) ;
if ( ! m . seq )
{
continue ;
}
2012-11-18 11:23:22 +01:00
2012-02-07 23:15:32 -08:00
const wcstring map_buf = format_string ( L " %s " , m . seq ) ;
2012-11-18 16:30:30 -08:00
if ( map_buf = = seq )
{
2012-02-07 23:15:32 -08:00
name = m . name ;
2011-12-31 15:57:30 -08:00
return true ;
}
}
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
return false ;
2005-09-20 23:26:39 +10:00
}
2012-11-18 16:30:30 -08:00
wcstring_list_t input_terminfo_get_names ( bool skip_null )
2005-09-20 23:26:39 +10:00
{
2012-02-07 17:06:45 -08:00
wcstring_list_t result ;
2012-02-07 23:15:32 -08:00
result . reserve ( terminfo_mappings . size ( ) ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
input_init ( ) ;
2012-11-18 11:23:22 +01:00
2012-11-18 16:30:30 -08:00
for ( size_t i = 0 ; i < terminfo_mappings . size ( ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
terminfo_mapping_t & m = terminfo_mappings . at ( i ) ;
if ( skip_null & & ! m . seq )
{
continue ;
}
2012-02-07 23:15:32 -08:00
result . push_back ( wcstring ( m . name ) ) ;
2012-11-18 16:30:30 -08:00
}
2012-02-07 17:06:45 -08:00
return result ;
2005-09-20 23:26:39 +10:00
}
2012-11-18 16:30:30 -08:00
wcstring_list_t input_function_get_names ( void )
2005-09-20 23:26:39 +10:00
{
2012-01-23 20:48:47 -08:00
size_t count = sizeof name_arr / sizeof * name_arr ;
return wcstring_list_t ( name_arr , name_arr + count ) ;
2007-09-26 02:14:47 +10:00
}
2005-09-20 23:26:39 +10:00
2012-11-18 16:30:30 -08:00
wchar_t input_function_get_code ( const wcstring & name )
2005-09-20 23:26:39 +10:00
{
2006-11-19 07:15:31 +10:00
2012-11-18 16:30:30 -08:00
size_t i ;
for ( i = 0 ; i < ( sizeof ( code_arr ) / sizeof ( wchar_t ) ) ; i + + )
2012-11-18 11:23:22 +01:00
{
2012-11-18 16:30:30 -08:00
if ( name = = name_arr [ i ] )
{
return code_arr [ i ] ;
}
2012-11-18 11:23:22 +01:00
}
2012-11-18 16:30:30 -08:00
return - 1 ;
2005-09-20 23:26:39 +10:00
}