X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=lib%2FTinyCon%2FConsole.cxx;fp=lib%2FTinyCon%2FConsole.cxx;h=ab05cd82248e0f362aec983e1f20bb54ff9db6bf;hb=2e142df11d6f312a2a2b5097b8da73571ed523e8;hp=0000000000000000000000000000000000000000;hpb=61b3659afe961ed248f30e26f9ca8f28fcfafddc;p=cpPlugins.git diff --git a/lib/TinyCon/Console.cxx b/lib/TinyCon/Console.cxx new file mode 100644 index 0000000..ab05cd8 --- /dev/null +++ b/lib/TinyCon/Console.cxx @@ -0,0 +1,417 @@ +// ========================================================================= +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ========================================================================= + +#include +#include + +// ------------------------------------------------------------------------- +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) +# include +# include +const char TinyCon::Console::KEY_CTRL1 = -32; +const char TinyCon::Console::BACKSPACE = 8; +const char TinyCon::Console::UP_ARROW = 72; +const char TinyCon::Console::DOWN_ARROW = 80; +const char TinyCon::Console::RIGHT_ARROW = 77; +const char TinyCon::Console::LEFT_ARROW = 75; +const char TinyCon::Console::NEWLINE = '\r'; + +#else +# include +# include +const char TinyCon::Console::KEY_CTRL1 = 17; +const char TinyCon::Console::BACKSPACE = 127; +const char TinyCon::Console::UP_ARROW = 65; +const char TinyCon::Console::DOWN_ARROW = 66; +const char TinyCon::Console::RIGHT_ARROW = 67; +const char TinyCon::Console::LEFT_ARROW = 68; +const char TinyCon::Console::NEWLINE = '\n'; + +int getch( ) +{ + struct termios oldt, newt; + int ch; + tcgetattr( STDIN_FILENO, &oldt ); + newt = oldt; + newt.c_lflag &= ~( ICANON | ECHO ); + tcsetattr( STDIN_FILENO, TCSANOW, &newt ); + + ch = getchar( ); + if( ch == TinyCon::Console::ESC ) + { + ch = getchar( ); + if( ch == 91 ) + ch = TinyCon::Console::KEY_CTRL1; + } + tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); + return( ch ); +} +#endif // defined(WIN32) || defined(_WIN32) || defined(__WIN32) + +// ------------------------------------------------------------------------- +const unsigned long TinyCon::Console::MAX_HISTORY = 500; +const char TinyCon::Console::TAB = 9; +const char TinyCon::Console::ESC = 27; +const char TinyCon::Console::DEL = 51; +const short TinyCon::Console::M_LINE = 0; +const short TinyCon::Console::M_PASSWORD = 1; + +// ------------------------------------------------------------------------- +TinyCon::Console:: +Console( ) +{ + this->m_MaxHistory = Self::MAX_HISTORY; + this->m_Quit = false; + this->m_Pos = -1; + this->m_LinePos = 0; + this->m_SkipOut = false; +} + +// ------------------------------------------------------------------------- +TinyCon::Console:: +Console( const std::string& prompt ) +{ + this->m_MaxHistory = Self::MAX_HISTORY; + this->m_Quit = false; + this->m_Prompt = prompt; + this->m_Pos = -1; + this->m_LinePos = 0; + this->m_SkipOut = false; +} + +// ------------------------------------------------------------------------- +TinyCon::Console:: +~Console( ) +{ +} + +// ------------------------------------------------------------------------- +void TinyCon::Console:: +run( ) +{ + std::cout << this->m_Prompt; + + bool ok = true; + while( ok ) + { + this->m_Char = getch( ); + if( this->hotkeys( this->m_Char ) == 0 ) + { + switch( this->m_Char ) + { + case Self::ESC: + { + } // end case + break; + case Self::KEY_CTRL1: + { + char c = getch( ); + switch( c ) + { + case Self::UP_ARROW: + { + if( this->m_History.size( ) > 0 ) + { + if( this->m_Pos == -1 ) + { + // store current command + this->m_Unused = ""; + this->m_Unused.assign( + this->m_Buffer.begin( ), this->m_Buffer.end( ) + ); + } // end if + + // clear line + for( int i = 0; i < this->m_LinePos; ++i ) + std::cout << "\b \b"; + + // clean buffer + this->m_Buffer.clear( ); + + this->m_Pos++; + if( this->m_Pos > ( this->m_History.size( ) - 1 ) ) + this->m_Pos = this->m_History.size( ) - 1; + + // store in buffer + for( int i = 0; i < this->m_History[ this->m_Pos ].size( ); ++i ) + this->m_Buffer.push_back( this->m_History[ this->m_Pos ][ i ] ); + this->m_LinePos = this->m_Buffer.size( ); + std::cout << this->m_History[ this->m_Pos ]; + } // end if + } // end case + break; + case Self::DOWN_ARROW: + { + if( this->m_History.size( ) > 0 ) + { + // clear line + for( int i = 0; i < this->m_LinePos; ++i ) + std::cout << "\b \b"; + + // clean buffer + this->m_Buffer.clear( ); + + this->m_Pos--; + if( this->m_Pos < -1 ) + this->m_Pos = -1; + if( this->m_Pos >= 0 ) + { + std::cout << this->m_History[ this->m_Pos ]; + // store in buffer + for( int i = 0; i < this->m_History[ this->m_Pos ].size( ); ++i ) + this->m_Buffer.push_back( + this->m_History[ this->m_Pos ][ i ] + ); + } + else + { + if( this->m_Buffer.size( ) > 0 ) + { + std::cout << this->m_Unused; + + // store in buffer + for( int i = 0; i < this->m_Unused.size( ); ++i ) + this->m_Buffer.push_back( this->m_Unused[ i ] ); + } // end if + } // end if + this->m_LinePos = this->m_Buffer.size( ); + } // end if + } // end case + break; + case Self::LEFT_ARROW: + { + // if there are characters to move left over, do so + if( this->m_LinePos > 0 ) + { + std::cout << "\b"; + this->m_LinePos--; + } // end if + } // end case + break; + case Self::RIGHT_ARROW: + { + // if there are characters to move right over, do so + if( this->m_LinePos < this->m_Buffer.size( ) ) + { + std::cout << this->m_Buffer[ this->m_LinePos ]; + this->m_LinePos++; + } // end if + } // end case + break; + case Self::DEL: + { + if( this->m_LinePos < this->m_Buffer.size( ) ) + { + this->m_SkipOut = true; + this->m_Buffer.erase( this->m_Buffer.begin( ) + this->m_LinePos ); + // update screen after current position + for( int i = this->m_LinePos; i < this->m_Buffer.size( ); ++i ) + std::cout << this->m_Buffer[ i ]; + // erase last char + std::cout << " "; + for( int i = this->m_LinePos; i < this->m_Buffer.size( ); ++i ) + std::cout << "\b"; + // make-up for erase position + std::cout << "\b"; + } // end if + } // end case + break; + default: + { + this->m_SkipOut = true; + } // end case + break; + } // end switch + } // end case + break; + case Self::BACKSPACE: + { + if( this->m_LinePos > 0 ) + { + // move cursor back, blank char, and move cursor back again + std::cout << "\b \b"; + // don't forget to clean the buffer and update line position + if( this->m_LinePos == this->m_Buffer.size( ) ) + { + this->m_Buffer.pop_back( ); + this->m_LinePos--; + } + else + { + this->m_LinePos--; + this->m_Buffer.erase( this->m_Buffer.begin( ) + this->m_LinePos ); + // update screen after current position + for( int i = this->m_LinePos; i < this->m_Buffer.size( ); ++i ) + std::cout << this->m_Buffer[ i ]; + // erase last char + std::cout << " "; + for( int i = this->m_LinePos + 1; i < this->m_Buffer.size( ); ++i ) + std::cout << "\b"; + // make-up for erase position and go to new position + std::cout << "\b\b"; + } // end if + } // end if + } // end case + break; + case Self::TAB: + { + } // end case + break; + case Self::NEWLINE: + { + // store in string + this->m_String.assign( + this->m_Buffer.begin( ), this->m_Buffer.end( ) + ); + + // save command to history + // trimming of command should be done in callback function + if( this->m_String.length( ) > 0 ) + this->m_History.push_front( this->m_String ); + + // run command + std::cout << std::endl; + this->trigger( this->m_String ); + + // check for exit command + ok = !( this->m_Quit ); + if( ok ) + { + if( this->m_History.size( ) > this->m_MaxHistory ) + this->m_History.pop_back( ); + + // clean buffer + this->m_Buffer.clear( ); + + // print prompt. new line should be added from callback function + std::cout << this->m_Prompt; + + // reset position + this->m_Pos = -1; + this->m_LinePos = 0; + } // end if + } // end case + break; + default: + { + if( !( this->m_SkipOut ) ) + { + std::cout << this->m_Char; + if( this->m_LinePos != this->m_Buffer.size( ) ) + { + // line position is not at end. Insert new char + this->m_Buffer.insert( + this->m_Buffer.begin( ) + this->m_LinePos, this->m_Char + ); + // update screen after current position + for( int i = this->m_LinePos + 1; i < this->m_Buffer.size( ); ++i ) + std::cout << this->m_Buffer[ i ]; + for( int i = this->m_LinePos + 1; i < this->m_Buffer.size( ); ++i ) + std::cout << "\b"; + } + else + this->m_Buffer.push_back( this->m_Char ); + this->m_LinePos++; + } + else + this->m_SkipOut = false; + } // end case + break; + } // end switch + } // end if + } // end while +} + +// ------------------------------------------------------------------------- +void TinyCon::Console:: +setPrompt( const std::string& prompt ) +{ + this->m_Prompt = prompt; +} + +// ------------------------------------------------------------------------- +int TinyCon::Console:: +trigger( const std::string& cmd ) +{ + return( ( this->m_Quit )? 1: 0 ); +} + +// ------------------------------------------------------------------------- +int TinyCon::Console:: +hotkeys( char c ) +{ + return( 0 ); +} + +// ------------------------------------------------------------------------- +void TinyCon::Console:: +pause( ) +{ + getch( ); +} + +// ------------------------------------------------------------------------- +void TinyCon::Console:: +quit( ) +{ + this->m_Quit = true; +} + +// ------------------------------------------------------------------------- +std::string TinyCon::Console:: +getLine( ) +{ + return( this->getLine( Self::M_LINE, "" ) ); +} + +// ------------------------------------------------------------------------- +std::string TinyCon::Console:: +getLine( int mode, const std::string& delimiter ) +{ + std::string line; + char c; + bool ok = true; + while( ok ) + { + c = getch( ); + if( c == Self::NEWLINE ) + { + std::cout << std::endl; + ok = false; + } + else if( c == Self::BACKSPACE ) + { + if( line.length( ) > 0 ) + { + line = line.substr( 0,line.size( ) - 1 ); + if( mode != Self::M_PASSWORD ) + std::cout << "\b \b"; + } // end if + } + else + { + line += c; + if( mode != Self::M_PASSWORD ) + std::cout << c; + } // end if + } // end while + return( line ); +} + +// ------------------------------------------------------------------------- +void TinyCon::Console:: +setMaxHistory( int count ) +{ + this->m_MaxHistory = count; +} + +// ------------------------------------------------------------------------- +void TinyCon::Console:: +setBuffer( const std::string& buffer ) +{ + this->m_Buffer.assign( buffer.begin( ), buffer.end( ) ); + this->m_LinePos = this->m_Buffer.size( ); +} + +// eof - $RCSfile$