diff options
Diffstat (limited to '')
-rw-r--r-- | contrib/replxx/src/util.cxx | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/contrib/replxx/src/util.cxx b/contrib/replxx/src/util.cxx new file mode 100644 index 0000000..719d707 --- /dev/null +++ b/contrib/replxx/src/util.cxx @@ -0,0 +1,158 @@ +#include <chrono> +#include <cstdlib> +#include <cstring> +#include <ctime> +#include <wctype.h> + +#include "util.hxx" + +namespace replxx { + +int mk_wcwidth( char32_t ); + +/** + * Calculate a new screen position given a starting position, screen width and + * character count + * @param x - initial x position (zero-based) + * @param y - initial y position (zero-based) + * @param screenColumns - screen column count + * @param charCount - character positions to advance + * @param xOut - returned x position (zero-based) + * @param yOut - returned y position (zero-based) + */ +void calculate_screen_position( + int x, int y, int screenColumns, + int charCount, int& xOut, int& yOut +) { + xOut = x; + yOut = y; + int charsRemaining = charCount; + while ( charsRemaining > 0 ) { + int charsThisRow = ( ( x + charsRemaining ) < screenColumns ) + ? charsRemaining + : screenColumns - x; + xOut = x + charsThisRow; + yOut = y; + charsRemaining -= charsThisRow; + x = 0; + ++ y; + } + if ( xOut == screenColumns ) { // we have to special-case line wrap + xOut = 0; + ++ yOut; + } +} + +/** + * Calculate a column width using mk_wcswidth() + * @param buf32 - text to calculate + * @param len - length of text to calculate + */ +int calculate_displayed_length( char32_t const* buf32_, int size_ ) { + int len( 0 ); + for ( int i( 0 ); i < size_; ++ i ) { + char32_t c( buf32_[i] ); + if ( c == '\033' ) { + int escStart( i ); + ++ i; + if ( ( i < size_ ) && ( buf32_[i] != '[' ) ) { + i = escStart; + ++ len; + continue; + } + ++ i; + for ( ; i < size_; ++ i ) { + c = buf32_[i]; + if ( ( c != ';' ) && ( ( c < '0' ) || ( c > '9' ) ) ) { + break; + } + } + if ( ( i < size_ ) && ( buf32_[i] == 'm' ) ) { + continue; + } + i = escStart; + len += 2; + } else if ( is_control_code( c ) ) { + len += 2; + } else { + int wcw( mk_wcwidth( c ) ); + if ( wcw < 0 ) { + len = -1; + break; + } + len += wcw; + } + } + return ( len ); +} + +char const* ansi_color( Replxx::Color color_ ) { + static char const reset[] = "\033[0m"; + static char const black[] = "\033[0;22;30m"; + static char const red[] = "\033[0;22;31m"; + static char const green[] = "\033[0;22;32m"; + static char const brown[] = "\033[0;22;33m"; + static char const blue[] = "\033[0;22;34m"; + static char const magenta[] = "\033[0;22;35m"; + static char const cyan[] = "\033[0;22;36m"; + static char const lightgray[] = "\033[0;22;37m"; + +#ifdef _WIN32 + static bool const has256colorDefault( true ); +#else + static bool const has256colorDefault( false ); +#endif + static char const* TERM( getenv( "TERM" ) ); + static bool const has256color( TERM ? ( strstr( TERM, "256" ) != nullptr ) : has256colorDefault ); + static char const* gray = has256color ? "\033[0;1;90m" : "\033[0;1;30m"; + static char const* brightred = has256color ? "\033[0;1;91m" : "\033[0;1;31m"; + static char const* brightgreen = has256color ? "\033[0;1;92m" : "\033[0;1;32m"; + static char const* yellow = has256color ? "\033[0;1;93m" : "\033[0;1;33m"; + static char const* brightblue = has256color ? "\033[0;1;94m" : "\033[0;1;34m"; + static char const* brightmagenta = has256color ? "\033[0;1;95m" : "\033[0;1;35m"; + static char const* brightcyan = has256color ? "\033[0;1;96m" : "\033[0;1;36m"; + static char const* white = has256color ? "\033[0;1;97m" : "\033[0;1;37m"; + static char const error[] = "\033[101;1;33m"; + + char const* code( reset ); + switch ( color_ ) { + case Replxx::Color::BLACK: code = black; break; + case Replxx::Color::RED: code = red; break; + case Replxx::Color::GREEN: code = green; break; + case Replxx::Color::BROWN: code = brown; break; + case Replxx::Color::BLUE: code = blue; break; + case Replxx::Color::MAGENTA: code = magenta; break; + case Replxx::Color::CYAN: code = cyan; break; + case Replxx::Color::LIGHTGRAY: code = lightgray; break; + case Replxx::Color::GRAY: code = gray; break; + case Replxx::Color::BRIGHTRED: code = brightred; break; + case Replxx::Color::BRIGHTGREEN: code = brightgreen; break; + case Replxx::Color::YELLOW: code = yellow; break; + case Replxx::Color::BRIGHTBLUE: code = brightblue; break; + case Replxx::Color::BRIGHTMAGENTA: code = brightmagenta; break; + case Replxx::Color::BRIGHTCYAN: code = brightcyan; break; + case Replxx::Color::WHITE: code = white; break; + case Replxx::Color::ERROR: code = error; break; + case Replxx::Color::DEFAULT: code = reset; break; + } + return ( code ); +} + +std::string now_ms_str( void ) { + std::chrono::milliseconds ms( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ) ); + time_t t( ms.count() / 1000 ); + tm broken; +#ifdef _WIN32 +#define localtime_r( t, b ) localtime_s( ( b ), ( t ) ) +#endif + localtime_r( &t, &broken ); +#undef localtime_r + static int const BUFF_SIZE( 32 ); + char str[BUFF_SIZE]; + strftime( str, BUFF_SIZE, "%Y-%m-%d %H:%M:%S.", &broken ); + snprintf( str + sizeof ( "YYYY-mm-dd HH:MM:SS" ), 5, "%03d", static_cast<int>( ms.count() % 1000 ) ); + return ( str ); +} + +} + |