Handle user input through terminal
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp
|
source = parse.cpp parserstate.cpp parser.cpp templates.cpp terminal.cpp termemu.cpp parseraction.cpp terminalfunctions.cpp swrite.cpp terminalframebuffer.cpp terminaldispatcher.cpp terminaluserinput.cpp
|
||||||
objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o
|
objects = parserstate.o parser.o templates.o terminal.o parseraction.o terminalfunctions.o swrite.o terminalframebuffer.o terminaldispatcher.o terminaluserinput.o
|
||||||
repos = templates.rpo
|
repos = templates.rpo
|
||||||
executables = parse termemu
|
executables = parse termemu
|
||||||
|
|
||||||
|
|||||||
@@ -65,3 +65,8 @@ void OSC_End::act_on_terminal( Terminal::Emulator *emu )
|
|||||||
{
|
{
|
||||||
emu->OSC_end( this );
|
emu->OSC_end( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UserByte::act_on_terminal( Terminal::Emulator *emu )
|
||||||
|
{
|
||||||
|
emu->dispatch.terminal_to_host.append( emu->user.input( this ) );
|
||||||
|
}
|
||||||
|
|||||||
@@ -87,6 +87,17 @@ namespace Parser {
|
|||||||
std::string name( void ) { return std::string( "OSC_End" ); }
|
std::string name( void ) { return std::string( "OSC_End" ); }
|
||||||
void act_on_terminal( Terminal::Emulator *emu );
|
void act_on_terminal( Terminal::Emulator *emu );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class UserByte : public Action {
|
||||||
|
/* user keystroke -- not part of the host-source state machine*/
|
||||||
|
public:
|
||||||
|
char c; /* The user-source byte. We don't try to interpret the charset */
|
||||||
|
|
||||||
|
std::string name( void ) { return std::string( "UserByte" ); }
|
||||||
|
void act_on_terminal( Terminal::Emulator *emu );
|
||||||
|
|
||||||
|
UserByte( int s_c ) : c( s_c ) {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+31
-28
@@ -24,8 +24,9 @@ const size_t buf_size = 1024;
|
|||||||
|
|
||||||
void emulate_terminal( int fd, int debug_fd );
|
void emulate_terminal( int fd, int debug_fd );
|
||||||
int copy( int src, int dest );
|
int copy( int src, int dest );
|
||||||
int termemu( int fd, Parser::UTF8Parser *parser,
|
int termemu( int host_fd, int src_fd, bool user, int debug_fd,
|
||||||
Terminal::Emulator *terminal, int debug_fd );
|
Parser::UTF8Parser *parser,
|
||||||
|
Terminal::Emulator *terminal );
|
||||||
|
|
||||||
int main( int argc,
|
int main( int argc,
|
||||||
char *argv[],
|
char *argv[],
|
||||||
@@ -134,11 +135,11 @@ void emulate_terminal( int fd, int debug_fd )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( pollfds[ 0 ].revents & POLLIN ) {
|
if ( pollfds[ 0 ].revents & POLLIN ) {
|
||||||
if ( copy( STDIN_FILENO, fd ) < 0 ) {
|
if ( termemu( fd, STDIN_FILENO, true, debug_fd, &parser, &terminal ) < 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if ( pollfds[ 1 ].revents & POLLIN ) {
|
} else if ( pollfds[ 1 ].revents & POLLIN ) {
|
||||||
if ( termemu( fd, &parser, &terminal, debug_fd ) < 0 ) {
|
if ( termemu( fd, fd, false, debug_fd, &parser, &terminal ) < 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
} else if ( (pollfds[ 0 ].revents | pollfds[ 1 ].revents)
|
||||||
@@ -150,28 +151,14 @@ void emulate_terminal( int fd, int debug_fd )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int copy( int src, int dest )
|
int termemu( int host_fd, int src_fd, bool user, int debug_fd,
|
||||||
{
|
Parser::UTF8Parser *parser,
|
||||||
char buf[ buf_size ];
|
Terminal::Emulator *terminal )
|
||||||
|
|
||||||
ssize_t bytes_read = read( src, buf, buf_size );
|
|
||||||
if ( bytes_read == 0 ) { /* EOF */
|
|
||||||
return -1;
|
|
||||||
} else if ( bytes_read < 0 ) {
|
|
||||||
perror( "read" );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return swrite( dest, buf, bytes_read );
|
|
||||||
}
|
|
||||||
|
|
||||||
int termemu( int fd, Parser::UTF8Parser *parser,
|
|
||||||
Terminal::Emulator *terminal, int debug_fd )
|
|
||||||
{
|
{
|
||||||
char buf[ buf_size ];
|
char buf[ buf_size ];
|
||||||
|
|
||||||
/* fill buffer if possible */
|
/* fill buffer if possible */
|
||||||
ssize_t bytes_read = read( fd, buf, buf_size );
|
ssize_t bytes_read = read( src_fd, buf, buf_size );
|
||||||
if ( bytes_read == 0 ) { /* EOF */
|
if ( bytes_read == 0 ) { /* EOF */
|
||||||
return -1;
|
return -1;
|
||||||
} else if ( bytes_read < 0 ) {
|
} else if ( bytes_read < 0 ) {
|
||||||
@@ -179,21 +166,37 @@ int termemu( int fd, Parser::UTF8Parser *parser,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* feed bytes to parser, and actions to terminal */
|
|
||||||
for ( int i = 0; i < bytes_read; i++ ) {
|
for ( int i = 0; i < bytes_read; i++ ) {
|
||||||
std::list<Parser::Action *> actions = parser->input( buf[ i ] );
|
/* feed bytes to parser */
|
||||||
|
std::list<Parser::Action *> actions;
|
||||||
|
if ( user ) {
|
||||||
|
actions.push_back( new Parser::UserByte( buf[ i ] ) );
|
||||||
|
} else {
|
||||||
|
actions = parser->input( buf[ i ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* apply actions to terminal */
|
||||||
for ( std::list<Parser::Action *>::iterator i = actions.begin();
|
for ( std::list<Parser::Action *>::iterator i = actions.begin();
|
||||||
i != actions.end();
|
i != actions.end();
|
||||||
i++ ) {
|
i++ ) {
|
||||||
(*i)->act_on_terminal( terminal );
|
Parser::Action *act = *i;
|
||||||
|
/* apply action to terminal */
|
||||||
|
act->act_on_terminal( terminal );
|
||||||
|
|
||||||
|
/* print out action for debugging */
|
||||||
|
if ( (debug_fd > 0) ) {
|
||||||
|
char actsum[ 64 ];
|
||||||
|
snprintf( actsum, 64, "%s ", act->str().c_str() );
|
||||||
|
swrite( debug_fd, actsum );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete *i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal->debug_printout( STDOUT_FILENO );
|
terminal->debug_printout( STDOUT_FILENO );
|
||||||
|
|
||||||
debug_fd = debug_fd;
|
|
||||||
|
|
||||||
/* write writeback */
|
/* write writeback */
|
||||||
std::string terminal_to_host = terminal->read_octets_to_host();
|
std::string terminal_to_host = terminal->read_octets_to_host();
|
||||||
return swrite( fd, terminal_to_host.c_str(), terminal_to_host.length() );
|
return swrite( host_fd, terminal_to_host.c_str(), terminal_to_host.length() );
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
using namespace Terminal;
|
using namespace Terminal;
|
||||||
|
|
||||||
Emulator::Emulator( size_t s_width, size_t s_height )
|
Emulator::Emulator( size_t s_width, size_t s_height )
|
||||||
: fb( s_width, s_height ), dispatch()
|
: fb( s_width, s_height ), dispatch(), user()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string Emulator::read_octets_to_host( void )
|
std::string Emulator::read_octets_to_host( void )
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "parseraction.hpp"
|
#include "parseraction.hpp"
|
||||||
#include "terminalframebuffer.hpp"
|
#include "terminalframebuffer.hpp"
|
||||||
#include "terminaldispatcher.hpp"
|
#include "terminaldispatcher.hpp"
|
||||||
|
#include "terminaluserinput.hpp"
|
||||||
|
|
||||||
namespace Terminal {
|
namespace Terminal {
|
||||||
class Emulator {
|
class Emulator {
|
||||||
@@ -22,10 +23,12 @@ namespace Terminal {
|
|||||||
friend void Parser::OSC_Start::act_on_terminal( Emulator * );
|
friend void Parser::OSC_Start::act_on_terminal( Emulator * );
|
||||||
friend void Parser::OSC_Put::act_on_terminal( Emulator * );
|
friend void Parser::OSC_Put::act_on_terminal( Emulator * );
|
||||||
friend void Parser::OSC_End::act_on_terminal( Emulator * );
|
friend void Parser::OSC_End::act_on_terminal( Emulator * );
|
||||||
|
friend void Parser::UserByte::act_on_terminal( Emulator * );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Framebuffer fb;
|
Framebuffer fb;
|
||||||
Dispatcher dispatch;
|
Dispatcher dispatch;
|
||||||
|
UserInput user;
|
||||||
|
|
||||||
/* action methods */
|
/* action methods */
|
||||||
void print( Parser::Print *act );
|
void print( Parser::Print *act );
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#include "terminaluserinput.hpp"
|
||||||
|
|
||||||
|
using namespace Terminal;
|
||||||
|
|
||||||
|
std::string UserInput::input( Parser::UserByte *act )
|
||||||
|
{
|
||||||
|
char translated_str[ 2 ] = { act->c, 0 };
|
||||||
|
|
||||||
|
/* The user will always be in application mode. If rtm is not in
|
||||||
|
application mode, convert user's cursor control function to an
|
||||||
|
ANSI cursor control sequence */
|
||||||
|
|
||||||
|
/* We don't need lookahead to do this for 7-bit. */
|
||||||
|
|
||||||
|
if ( (!application_mode_cursor)
|
||||||
|
&& (last_byte == 0x1b) /* ESC */
|
||||||
|
&& (act->c == 'O') ) { /* ESC O = 7-bit SS3 = application mode */
|
||||||
|
translated_str[ 0 ] = '[';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This doesn't handle the 8-bit SS3 C1 control, which would be
|
||||||
|
two octets in UTF-8. Fortunately nobody seems to send this. */
|
||||||
|
|
||||||
|
return std::string( translated_str );
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef TERMINALUSERINPUT_HPP
|
||||||
|
#define TERMINALUSERINPUT_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "parseraction.hpp"
|
||||||
|
|
||||||
|
namespace Terminal {
|
||||||
|
class UserInput {
|
||||||
|
private:
|
||||||
|
bool last_byte;
|
||||||
|
bool application_mode_cursor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UserInput()
|
||||||
|
: last_byte( 0 ),
|
||||||
|
application_mode_cursor( false )
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string input( Parser::UserByte *act );
|
||||||
|
void set_cursor_application_mode( bool mode ) { application_mode_cursor = mode; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user