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>
2014-02-12 21:08:12 -08:00
# include <algorithm>
2007-09-26 02:14:47 +10:00
2013-11-26 11:39:54 +08:00
# define DEFAULT_TERM L"ansi"
2014-01-22 10:00:44 +01:00
# define MAX_INPUT_FUNCTION_ARGS 20
2007-09-26 02:14:47 +10:00
/**
Struct representing a keybinding . Returned by input_get_mappings .
*/
2014-01-01 00:11:32 +01:00
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 */
2014-03-30 13:13:35 -07:00
wcstring_list_t commands ; /**< commands that should be evaluated by this mapping */
2014-03-31 10:01:39 -07:00
2014-02-12 12:49:32 -08:00
/* We wish to preserve the user-specified order. This is just an incrementing value. */
unsigned int specification_order ;
2014-03-31 10:01:39 -07:00
2013-12-31 01:52:41 +01:00
wcstring mode ; /**< mode in which this command should be evaluated */
2014-01-15 11:39:19 +01:00
wcstring sets_mode ; /** new mode that should be switched to after command evaluation */
2014-03-31 10:01:39 -07:00
2014-01-01 00:11:32 +01:00
input_mapping_t ( const wcstring & s , const std : : vector < wcstring > & c ,
2013-12-31 01:52:41 +01:00
const wcstring & m = DEFAULT_BIND_MODE ,
2014-03-29 14:19:45 -07:00
const wcstring & sm = DEFAULT_BIND_MODE ) : seq ( s ) , commands ( c ) , mode ( m ) , sets_mode ( sm )
2014-02-12 12:49:32 -08:00
{
static unsigned int s_last_input_mapping_specification_order = 0 ;
specification_order = + + s_last_input_mapping_specification_order ;
2014-03-31 10:01:39 -07:00
2014-02-12 12:49:32 -08:00
}
2011-12-31 15:57:30 -08:00
} ;
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-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 " ,
2014-01-27 00:56:13 -08:00
L " complete-and-search " ,
2012-11-18 16:30:30 -08:00
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 " 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 " vi-arg-digit " ,
2014-01-21 16:08:35 -08:00
L " vi-delete-to " ,
2012-11-18 16:30:30 -08:00
L " execute " ,
L " beginning-of-buffer " ,
L " end-of-buffer " ,
L " repaint " ,
2013-12-31 14:53:29 +01:00
L " force-repaint " ,
2012-11-18 16:30:30 -08:00
L " up-line " ,
L " down-line " ,
L " suppress-autosuggestion " ,
2014-01-15 15:07:22 +01:00
L " accept-autosuggestion " ,
L " begin-selection " ,
L " end-selection " ,
2014-01-22 10:00:44 +01:00
L " kill-selection " ,
L " forward-jump " ,
2014-01-23 10:23:04 +01:00
L " backward-jump " ,
2014-03-29 14:19:45 -07:00
L " and " ,
2014-01-27 02:17:31 -08:00
L " cancel "
2014-01-21 16:08:35 -08:00
} ;
2014-02-12 12:49:32 -08:00
wcstring describe_char ( wint_t c )
2014-01-21 16:08:35 -08:00
{
2014-04-27 17:23:19 -07:00
wint_t initial_cmd_char = R_BEGINNING_OF_LINE ;
2014-01-21 16:08:35 -08:00
size_t name_count = sizeof name_arr / sizeof * name_arr ;
if ( c > = initial_cmd_char & & c < initial_cmd_char + name_count )
{
return format_string ( L " %02x (%ls) " , c, name_arr[c - initial_cmd_char]) ;
}
return format_string ( L " %02x " , c ) ;
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 ,
2014-01-27 00:56:13 -08:00
R_COMPLETE_AND_SEARCH ,
2012-11-18 16:30:30 -08:00
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_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_VI_ARG_DIGIT ,
2014-01-21 16:08:35 -08:00
R_VI_DELETE_TO ,
2012-11-18 16:30:30 -08:00
R_EXECUTE ,
R_BEGINNING_OF_BUFFER ,
R_END_OF_BUFFER ,
R_REPAINT ,
2013-12-31 14:53:29 +01:00
R_FORCE_REPAINT ,
2012-11-18 16:30:30 -08:00
R_UP_LINE ,
R_DOWN_LINE ,
R_SUPPRESS_AUTOSUGGESTION ,
2014-01-15 15:07:22 +01:00
R_ACCEPT_AUTOSUGGESTION ,
R_BEGIN_SELECTION ,
2014-01-18 10:18:29 +01:00
R_END_SELECTION ,
2014-01-22 10:00:44 +01:00
R_KILL_SELECTION ,
R_FORWARD_JUMP ,
2014-01-23 10:23:04 +01:00
R_BACKWARD_JUMP ,
2014-03-29 14:19:45 -07:00
R_AND ,
2014-01-27 02:17:31 -08:00
R_CANCEL
2014-01-21 16:08:35 -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
2014-03-30 13:13:35 -07:00
static wchar_t input_function_args [ MAX_INPUT_FUNCTION_ARGS ] ;
static bool input_function_status ;
static int input_function_args_index = 0 ;
2014-01-22 10:00:44 +01:00
2013-12-31 01:52:41 +01:00
/**
Return the current bind mode
*/
2014-03-30 13:13:35 -07:00
wcstring input_get_bind_mode ( )
2013-12-31 01:52:41 +01:00
{
2014-03-30 13:13:35 -07:00
env_var_t mode = env_get_string ( FISH_BIND_MODE_VAR ) ;
return mode . missing ( ) ? DEFAULT_BIND_MODE : mode ;
2013-12-31 01:52:41 +01:00
}
/**
Set the current bind mode
*/
2014-03-30 13:13:35 -07:00
void input_set_bind_mode ( const wcstring & bm )
2013-12-31 01:52:41 +01:00
{
2014-03-30 13:13:35 -07:00
env_set ( FISH_BIND_MODE_VAR , bm . c_str ( ) , ENV_GLOBAL ) ;
2013-12-31 01:52:41 +01:00
}
2006-07-24 06:52:03 +10:00
2014-01-22 10:00:44 +01:00
2014-03-31 10:01:39 -07:00
/**
2014-01-22 10:00:44 +01:00
Returns the arity of a given input function
*/
int input_function_arity ( int function )
{
2014-03-31 10:01:39 -07:00
switch ( function )
2014-01-22 10:00:44 +01:00
{
case R_FORWARD_JUMP :
case R_BACKWARD_JUMP :
2014-03-30 13:13:35 -07:00
return 1 ;
2014-01-22 10:00:44 +01:00
default :
2014-03-30 13:13:35 -07:00
return 0 ;
2014-01-22 10:00:44 +01:00
}
}
2014-03-31 10:01:39 -07:00
/**
2014-01-23 10:23:04 +01:00
Sets the return status of the most recently executed input function
*/
void input_function_set_status ( bool status )
{
input_function_status = status ;
}
2014-01-22 10:00:44 +01:00
/**
Returns the nth argument for a given input function
*/
wchar_t input_function_get_arg ( int index )
{
return input_function_args [ index ] ;
}
2014-02-12 12:49:32 -08:00
/* Helper function to compare the lengths of sequences */
static bool length_is_greater_than ( const input_mapping_t & m1 , const input_mapping_t & m2 )
{
return m1 . seq . size ( ) > m2 . seq . size ( ) ;
}
2005-09-20 23:26:39 +10:00
2014-02-12 12:49:32 -08:00
static bool specification_order_is_less_than ( const input_mapping_t & m1 , const input_mapping_t & m2 )
{
return m1 . specification_order < m2 . specification_order ;
}
2006-07-24 06:52:03 +10:00
2014-02-12 12:49:32 -08:00
/* Inserts an input mapping at the correct position. We sort them in descending order by length, so that we test longer sequences first. */
static void input_mapping_insert_sorted ( const input_mapping_t & new_mapping )
{
std : : vector < input_mapping_t > : : iterator loc = std : : lower_bound ( mapping_list . begin ( ) , mapping_list . end ( ) , new_mapping , length_is_greater_than ) ;
mapping_list . insert ( loc , new_mapping ) ;
}
/* Adds an input mapping */
2014-01-01 00:11:32 +01:00
void input_mapping_add ( const wchar_t * sequence , const wchar_t * * commands , size_t commands_len ,
2014-01-15 11:39:19 +01:00
const wchar_t * mode , const wchar_t * sets_mode )
2005-09-20 23:26:39 +10:00
{
2012-11-18 16:30:30 -08:00
CHECK ( sequence , ) ;
2014-01-01 00:11:32 +01:00
CHECK ( commands , ) ;
2013-12-31 01:52:41 +01:00
CHECK ( mode , ) ;
2014-01-15 11:39:19 +01:00
CHECK ( sets_mode , ) ;
2012-11-18 11:23:22 +01:00
2013-12-31 14:53:29 +01:00
// debug( 0, L"Add mapping from %ls to %ls in mode %ls", escape(sequence, 1), escape(command, 1 ), mode);
2012-11-18 11:23:22 +01:00
2014-02-12 12:49:32 -08:00
// remove existing mappings with this sequence
2014-03-30 13:13:35 -07:00
const wcstring_list_t commands_vector ( commands , commands + commands_len ) ;
2014-01-01 00:11:32 +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 ) ;
2013-12-31 01:52:41 +01:00
if ( m . seq = = sequence & & m . mode = = mode )
2012-11-18 16:30:30 -08:00
{
2014-01-01 00:11:32 +01:00
m . commands = commands_vector ;
2014-01-15 11:39:19 +01:00
m . sets_mode = sets_mode ;
2012-11-18 16:30:30 -08:00
return ;
}
2012-11-18 11:23:22 +01:00
}
2014-03-31 10:01:39 -07:00
2014-03-30 13:13:35 -07:00
// add a new mapping, using the next order
const input_mapping_t new_mapping = input_mapping_t ( sequence , commands_vector , mode , sets_mode ) ;
input_mapping_insert_sorted ( new_mapping ) ;
2014-01-01 00:11:32 +01:00
}
void input_mapping_add ( const wchar_t * sequence , const wchar_t * command ,
2014-01-15 11:39:19 +01:00
const wchar_t * mode , const wchar_t * sets_mode )
2014-01-01 00:11:32 +01:00
{
2014-01-15 11:39:19 +01:00
input_mapping_add ( sequence , & command , 1 , mode , sets_mode ) ;
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-11-25 00:10:41 +08:00
const env_var_t term = env_get_string ( L " TERM " ) ;
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 " ) ) ;
2013-11-25 00:10:41 +08:00
if ( errret = = 0 )
{
debug ( 0 , _ ( L " Check that your terminal type, '%ls', is supported on this system " ) ,
term . c_str ( ) ) ;
2013-11-26 11:39:54 +08:00
debug ( 0 , _ ( L " Attempting to use '%ls' instead " ) , DEFAULT_TERM ) ;
env_set ( L " TERM " , DEFAULT_TERM , ENV_GLOBAL | ENV_EXPORT ) ;
const std : : string default_term = wcs2string ( DEFAULT_TERM ) ;
2013-11-26 10:56:43 -08:00
if ( setupterm ( const_cast < char * > ( default_term . c_str ( ) ) , STDOUT_FILENO , & errret ) = = ERR )
2013-11-26 11:39:54 +08:00
{
debug ( 0 , _ ( L " Could not set up terminal " ) ) ;
exit_without_destructors ( 1 ) ;
}
}
else
{
exit_without_destructors ( 1 ) ;
2013-11-25 00:10:41 +08:00
}
2012-11-18 16:30:30 -08:00
}
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
}
2014-01-22 10:00:44 +01:00
void input_function_push_arg ( wchar_t arg )
{
input_function_args [ input_function_args_index + + ] = arg ;
}
2014-01-01 00:11:32 +01:00
2014-01-22 10:00:44 +01:00
wchar_t input_function_pop_arg ( )
{
return input_function_args [ - - input_function_args_index ] ;
}
void input_function_push_args ( int code )
{
int arity = input_function_arity ( code ) ;
2014-03-31 10:01:39 -07:00
for ( int i = 0 ; i < arity ; i + + )
2014-01-22 10:00:44 +01:00
{
2014-03-31 10:01:39 -07:00
input_function_push_arg ( input_common_readch ( 0 ) ) ;
2014-01-22 10:00:44 +01:00
}
}
2014-01-01 00:11:32 +01: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
*/
2014-01-01 00:11:32 +01:00
static void input_mapping_execute ( const input_mapping_t & m )
2005-09-20 23:26:39 +10:00
{
2014-01-23 10:23:04 +01:00
/* By default input functions always succeed */
input_function_status = true ;
2014-03-31 10:01:39 -07:00
2014-03-30 13:13:35 -07:00
size_t idx = m . commands . size ( ) ;
while ( idx - - )
2014-01-22 10:00:44 +01:00
{
2014-03-30 13:13:35 -07:00
wcstring command = m . commands . at ( idx ) ;
wchar_t code = input_function_get_code ( command ) ;
if ( code ! = ( wchar_t ) - 1 )
{
input_function_push_args ( code ) ;
}
2014-01-22 10:00:44 +01:00
}
2014-03-31 10:01:39 -07:00
2014-03-30 13:13:35 -07:00
idx = m . commands . size ( ) ;
while ( idx - - )
2012-11-18 11:23:22 +01:00
{
2014-03-30 13:13:35 -07:00
wcstring command = m . commands . at ( idx ) ;
wchar_t code = input_function_get_code ( command ) ;
if ( code ! = ( wchar_t ) - 1 )
{
input_unreadch ( code ) ;
}
else
{
/*
This key sequence is bound to a command , which
is sent to the parser for evaluation .
*/
int last_status = proc_get_last_status ( ) ;
parser_t : : principal_parser ( ) . eval ( command . c_str ( ) , io_chain_t ( ) , TOP ) ;
2014-03-31 10:01:39 -07:00
2014-03-30 13:13:35 -07:00
proc_set_last_status ( last_status ) ;
2014-03-31 10:01:39 -07:00
2014-03-30 13:13:35 -07:00
input_unreadch ( R_NULL ) ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2014-03-31 10:01:39 -07:00
2014-01-15 11:39:19 +01:00
input_set_bind_mode ( m . sets_mode . c_str ( ) ) ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
/**
Try reading the specified function mapping
*/
2014-01-01 00:11:32 +01:00
static bool input_mapping_is_match ( const input_mapping_t & m )
2007-09-26 02:14:47 +10:00
{
2014-01-01 00:11:32 +01:00
wint_t c = 0 ;
2012-11-18 16:30:30 -08:00
int j ;
2014-01-01 00:11:32 +01:00
//debug(0, L"trying mapping %ls\n", escape(m.seq.c_str(), 1));
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 + + )
{
2013-12-31 16:16:28 +01:00
bool timed = ( j > 0 & & iswcntrl ( str [ 0 ] ) ) ;
2013-12-31 14:53:29 +01:00
2012-06-02 15:43:18 -07:00
c = input_common_readch ( timed ) ;
if ( str [ j ] ! = c )
2013-12-31 14:53:29 +01:00
{
2012-06-02 15:43:18 -07:00
break ;
2013-12-31 14:53:29 +01:00
}
2012-06-02 15:43:18 -07:00
}
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
{
2013-12-31 16:16:28 +01:00
//debug(0, L"matched mapping %ls (%ls)\n", escape(m.seq.c_str(), 1), m.command.c_str());
2012-06-02 15:43:18 -07:00
/* We matched the entire sequence */
2014-01-01 00:11:32 +01:00
return true ;
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
}
}
2013-12-31 16:16:28 +01:00
2014-01-01 00:11:32 +01:00
return false ;
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
2014-01-01 00:11:32 +01:00
static void input_mapping_execute_matching_or_generic ( )
{
const input_mapping_t * generic = NULL ;
2014-03-30 13:13:35 -07:00
const wcstring bind_mode = input_get_bind_mode ( ) ;
2014-01-15 12:04:52 +01:00
2014-01-01 00:11:32 +01:00
for ( int i = 0 ; i < mapping_list . size ( ) ; i + + )
{
const input_mapping_t & m = mapping_list . at ( i ) ;
//debug(0, L"trying mapping (%ls,%ls,%ls)\n", escape(m.seq.c_str(), 1),
2014-01-15 11:39:19 +01:00
// m.mode.c_str(), m.sets_mode.c_str());
2014-03-31 10:01:39 -07:00
2014-03-30 13:13:35 -07:00
if ( m . mode ! = bind_mode )
2014-01-01 00:11:32 +01:00
{
//debug(0, L"skipping mapping because mode %ls != %ls\n", m.mode.c_str(), input_get_bind_mode());
continue ;
}
if ( m . seq . length ( ) = = 0 )
{
generic = & m ;
}
2014-03-31 10:01:39 -07:00
else if ( input_mapping_is_match ( m ) )
2014-01-01 00:11:32 +01:00
{
input_mapping_execute ( m ) ;
return ;
}
}
if ( generic )
{
input_mapping_execute ( * generic ) ;
}
else
{
//debug(0, L"no generic found, ignoring...");
wchar_t c = input_common_readch ( 0 ) ;
if ( c = = R_EOF )
input_common_unreadch ( c ) ;
}
}
2007-09-26 02:14:47 +10:00
wint_t input_readch ( )
{
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
2014-01-23 10:23:04 +01:00
*/
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
2014-01-23 10:23:04 +01:00
*/
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
{
2014-01-01 00:11:32 +01:00
wchar_t c = input_common_readch ( 0 ) ;
2012-11-18 11:23:22 +01:00
2014-01-01 00:11:32 +01:00
if ( c > = R_MIN & & c < = R_MAX )
2012-11-18 16:30:30 -08:00
{
2014-03-31 10:01:39 -07:00
switch ( c )
{
case R_EOF : /* If it's closed, then just return */
{
2014-05-25 15:22:21 -07:00
return R_EOF ;
2014-03-31 10:01:39 -07:00
}
case R_SELF_INSERT :
{
return input_common_readch ( 0 ) ;
}
case R_AND :
{
if ( input_function_status )
{
return input_readch ( ) ;
}
else
{
while ( ( c = input_common_readch ( 0 ) ) & & c > = R_MIN & & c < = R_MAX ) ;
input_unreadch ( c ) ;
return input_readch ( ) ;
}
}
default :
{
return c ;
}
}
2012-11-18 16:30:30 -08:00
}
2014-01-01 00:11:32 +01:00
else
2012-07-06 16:25:10 -07:00
{
2014-03-31 10:01:39 -07:00
input_unreadch ( c ) ;
input_mapping_execute_matching_or_generic ( ) ;
2012-07-06 16:25:10 -07:00
}
2012-11-18 11:23:22 +01:00
}
2007-09-26 02:14:47 +10:00
}
2014-03-30 13:13:35 -07:00
wcstring_list_t input_mapping_get_names ( )
2007-09-26 02:14:47 +10:00
{
2014-02-12 12:49:32 -08:00
// Sort the mappings by the user specification order, so we can return them in the same order that the user specified them in
std : : vector < input_mapping_t > local_list = mapping_list ;
std : : sort ( local_list . begin ( ) , local_list . end ( ) , specification_order_is_less_than ) ;
2014-03-30 13:13:35 -07:00
wcstring_list_t result ;
result . reserve ( local_list . size ( ) ) ;
2012-11-18 11:23:22 +01:00
2014-02-12 12:49:32 -08:00
for ( size_t i = 0 ; i < local_list . size ( ) ; i + + )
2012-11-18 16:30:30 -08:00
{
2014-02-12 12:49:32 -08:00
const input_mapping_t & m = local_list . at ( i ) ;
2014-03-30 13:13:35 -07:00
result . push_back ( m . seq ) ;
2012-11-18 16:30:30 -08:00
}
2014-03-30 13:13:35 -07:00
return result ;
2005-09-20 23:26:39 +10:00
}
2007-09-26 02:14:47 +10:00
2013-12-31 01:52:41 +01:00
bool input_mapping_erase ( const wchar_t * sequence , const wchar_t * mode )
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 ) ;
2013-12-31 14:53:29 +01:00
if ( sequence = = m . seq & & ( mode = = NULL | | mode = = m . mode ) )
2012-11-18 16:30:30 -08:00
{
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
}
2014-03-30 13:13:35 -07:00
bool input_mapping_get ( const wcstring & sequence , wcstring_list_t * out_cmds , wcstring * out_mode , wcstring * out_sets_mode )
2005-09-20 23:26:39 +10:00
{
2014-03-30 13:13:35 -07:00
bool result = false ;
size_t sz = mapping_list . size ( ) ;
for ( size_t 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 )
{
2014-03-30 13:13:35 -07:00
* out_cmds = m . commands ;
* out_mode = m . mode ;
* out_sets_mode = m . sets_mode ;
result = true ;
break ;
2012-11-18 16:30:30 -08:00
}
2012-11-18 11:23:22 +01:00
}
2014-03-30 13:13:35 -07:00
return result ;
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
}
2014-07-07 10:45:26 -07:00
bool input_terminfo_get_name ( const wcstring & seq , wcstring * out_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 )
{
2014-07-07 10:45:26 -07:00
out_name - > assign ( 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
}