mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-26 10:43:47 +08:00
221 lines
3.6 KiB
C
221 lines
3.6 KiB
C
|
/** \file input_common.h
|
||
|
|
||
|
Implementation file for the low level input library
|
||
|
|
||
|
*/
|
||
|
#include "config.h"
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
#include <unistd.h>
|
||
|
#include <wchar.h>
|
||
|
|
||
|
#include "util.h"
|
||
|
#include "common.h"
|
||
|
#include "wutil.h"
|
||
|
#include "input_common.h"
|
||
|
#include "env_universal.h"
|
||
|
|
||
|
/**
|
||
|
Time in milliseconds to wait for another byte to be available for
|
||
|
reading after \e is read before assuming that escape key was
|
||
|
pressed, and not an escape sequence.
|
||
|
*/
|
||
|
#define WAIT_ON_ESCAPE 10
|
||
|
|
||
|
/**
|
||
|
Characters that have been read and returned by the sequence matching code
|
||
|
*/
|
||
|
static wint_t lookahead_arr[32];
|
||
|
|
||
|
/**
|
||
|
Number of entries in lookahead_arr
|
||
|
*/
|
||
|
static int lookahead_count = 0;
|
||
|
|
||
|
/**
|
||
|
Callback function for handling interrupts on reading
|
||
|
*/
|
||
|
static int (*interrupt_handler)();
|
||
|
|
||
|
void input_common_init( int (*ih)() )
|
||
|
{
|
||
|
interrupt_handler = ih;
|
||
|
}
|
||
|
|
||
|
void input_common_destroy()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Internal function used by input_common_readch to read one byte from fd 1. This function should only be called by
|
||
|
input_common_readch().
|
||
|
*/
|
||
|
static wint_t readb()
|
||
|
{
|
||
|
char arr[1];
|
||
|
int do_loop = 0;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
fd_set fd;
|
||
|
int fd_max=1;
|
||
|
int res;
|
||
|
|
||
|
FD_ZERO( &fd );
|
||
|
FD_SET( 0, &fd );
|
||
|
if( env_universal_server.fd > 0 )
|
||
|
{
|
||
|
FD_SET( env_universal_server.fd, &fd );
|
||
|
fd_max = env_universal_server.fd+1;
|
||
|
}
|
||
|
|
||
|
do_loop = 0;
|
||
|
|
||
|
res = select( fd_max, &fd, 0, 0, 0 );
|
||
|
if( res==-1 )
|
||
|
{
|
||
|
switch( errno )
|
||
|
{
|
||
|
case EINTR:
|
||
|
case EAGAIN:
|
||
|
{
|
||
|
// wperror( L"select" );
|
||
|
if( interrupt_handler )
|
||
|
{
|
||
|
int res = interrupt_handler();
|
||
|
|
||
|
/* debug( 0,
|
||
|
L"interrupt, %d is %ls",
|
||
|
res,
|
||
|
(res==R_NULL?L"good": L"Bad") );
|
||
|
*/
|
||
|
if( res )
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
do_loop = 1;
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
debug( 0, L"Error while reading input from keyboard, shutting down" );
|
||
|
wperror(L"read");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( env_universal_server.fd > 0 )
|
||
|
{
|
||
|
if( FD_ISSET( env_universal_server.fd, &fd ) )
|
||
|
{
|
||
|
debug( 3, L"Wake up on universal variable event" );
|
||
|
env_universal_read_all();
|
||
|
return R_NULL;
|
||
|
}
|
||
|
}
|
||
|
if( FD_ISSET( 0, &fd ) )
|
||
|
{
|
||
|
if( read_blocked( 0, arr, 1 ) == -1 )
|
||
|
{
|
||
|
debug( 0, L"Error while reading input from keyboard, shutting down" );
|
||
|
wperror(L"read");
|
||
|
exit(1);
|
||
|
}
|
||
|
do_loop = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while( do_loop );
|
||
|
|
||
|
return arr[0];
|
||
|
}
|
||
|
|
||
|
wchar_t input_common_readch( int timed )
|
||
|
{
|
||
|
if( lookahead_count == 0 )
|
||
|
{
|
||
|
if( timed )
|
||
|
{
|
||
|
int count;
|
||
|
fd_set fds;
|
||
|
struct timeval tm=
|
||
|
{
|
||
|
0,
|
||
|
1000 * WAIT_ON_ESCAPE
|
||
|
}
|
||
|
;
|
||
|
|
||
|
FD_ZERO( &fds );
|
||
|
FD_SET( 0, &fds );
|
||
|
count = select(1, &fds, 0, 0, &tm);
|
||
|
|
||
|
switch( count )
|
||
|
{
|
||
|
case 0:
|
||
|
return WEOF;
|
||
|
|
||
|
case -1:
|
||
|
return WEOF;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
wchar_t res;
|
||
|
static mbstate_t state;
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
wint_t b = readb();
|
||
|
int sz;
|
||
|
|
||
|
if( b == R_NULL )
|
||
|
return R_NULL;
|
||
|
|
||
|
sz = mbrtowc( &res, &b, 1, &state );
|
||
|
|
||
|
switch( sz )
|
||
|
{
|
||
|
case -1:
|
||
|
memset (&state, '\0', sizeof (state));
|
||
|
debug( 2, L"Illegal input" );
|
||
|
return R_NULL;
|
||
|
case -2:
|
||
|
break;
|
||
|
case 0:
|
||
|
return 0;
|
||
|
default:
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( !timed )
|
||
|
{
|
||
|
while( (lookahead_count >= 0) && (lookahead_arr[lookahead_count-1] == WEOF) )
|
||
|
lookahead_count--;
|
||
|
if( lookahead_count == 0 )
|
||
|
return input_common_readch(0);
|
||
|
}
|
||
|
|
||
|
return lookahead_arr[--lookahead_count];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void input_common_unreadch( wint_t ch )
|
||
|
{
|
||
|
lookahead_arr[lookahead_count++] = ch;
|
||
|
}
|
||
|
|