#ifdef _WIN32 #include #include #include #if _MSC_VER < 1900 && defined (_MSC_VER) #define snprintf _snprintf // Microsoft headers use underscores in some names #endif #define strcasecmp _stricmp #define strdup _strdup #define write _write #define STDIN_FILENO 0 #else /* _WIN32 */ #include #endif /* _WIN32 */ #include "prompt.hxx" #include "util.hxx" namespace replxx { Prompt::Prompt( Terminal& terminal_ ) : _extraLines( 0 ) , _lastLinePosition( 0 ) , _cursorRowOffset( 0 ) , _screenColumns( 0 ) , _terminal( terminal_ ) { } void Prompt::write() { _terminal.write32( _text.get(), _text.length() ); } void Prompt::update_screen_columns( void ) { _screenColumns = _terminal.get_screen_columns(); } void Prompt::set_text( UnicodeString const& text_ ) { _text = text_; update_state(); } void Prompt::update_state() { _cursorRowOffset -= _extraLines; _extraLines = 0; _lastLinePosition = 0; _screenColumns = 0; update_screen_columns(); // strip control characters from the prompt -- we do allow newline UnicodeString::const_iterator in( _text.begin() ); UnicodeString::iterator out( _text.begin() ); int visibleCount = 0; int x = 0; bool const strip = !tty::out; while (in != _text.end()) { char32_t c = *in; if ('\n' == c || !is_control_code(c)) { *out = c; ++out; ++in; ++visibleCount; if ('\n' == c || ++x >= _screenColumns) { x = 0; ++_extraLines; _lastLinePosition = visibleCount; } } else if (c == '\x1b') { if ( strip ) { // jump over control chars ++in; if (*in == '[') { ++in; while ( ( in != _text.end() ) && ( ( *in == ';' ) || ( ( ( *in >= '0' ) && ( *in <= '9' ) ) ) ) ) { ++in; } if (*in == 'm') { ++in; } } } else { // copy control chars *out = *in; ++out; ++in; if (*in == '[') { *out = *in; ++out; ++in; while ( ( in != _text.end() ) && ( ( *in == ';' ) || ( ( ( *in >= '0' ) && ( *in <= '9' ) ) ) ) ) { *out = *in; ++out; ++in; } if (*in == 'm') { *out = *in; ++out; ++in; } } } } else { ++in; } } _characterCount = visibleCount; int charCount( static_cast( out - _text.begin() ) ); _text.erase( charCount, _text.length() - charCount ); _cursorRowOffset += _extraLines; } int Prompt::indentation() const { return _characterCount - _lastLinePosition; } // Used with DynamicPrompt (history search) // const UnicodeString forwardSearchBasePrompt("(i-search)`"); const UnicodeString reverseSearchBasePrompt("(reverse-i-search)`"); const UnicodeString endSearchBasePrompt("': "); DynamicPrompt::DynamicPrompt( Terminal& terminal_, int initialDirection ) : Prompt( terminal_ ) , _searchText() , _direction( initialDirection ) { updateSearchPrompt(); } void DynamicPrompt::updateSearchPrompt(void) { update_screen_columns(); const UnicodeString* basePrompt = (_direction > 0) ? &forwardSearchBasePrompt : &reverseSearchBasePrompt; _text.assign( *basePrompt ).append( _searchText ).append( endSearchBasePrompt ); update_state(); } }