#include #include #include #include #include #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::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( ms.count() % 1000 ) ); return ( str ); } }