1 #include <chrono>
2 #include <cstdlib>
3 #include <cstring>
4 #include <ctime>
5 #include <wctype.h>
6
7 #include "util.hxx"
8
9 namespace replxx {
10
11 int mk_wcwidth( char32_t );
12
13 /**
14 * Calculate a new screen position given a starting position, screen width and
15 * character count
16 * @param x - initial x position (zero-based)
17 * @param y - initial y position (zero-based)
18 * @param screenColumns - screen column count
19 * @param charCount - character positions to advance
20 * @param xOut - returned x position (zero-based)
21 * @param yOut - returned y position (zero-based)
22 */
calculate_screen_position(int x,int y,int screenColumns,int charCount,int & xOut,int & yOut)23 void calculate_screen_position(
24 int x, int y, int screenColumns,
25 int charCount, int& xOut, int& yOut
26 ) {
27 xOut = x;
28 yOut = y;
29 int charsRemaining = charCount;
30 while ( charsRemaining > 0 ) {
31 int charsThisRow = ( ( x + charsRemaining ) < screenColumns )
32 ? charsRemaining
33 : screenColumns - x;
34 xOut = x + charsThisRow;
35 yOut = y;
36 charsRemaining -= charsThisRow;
37 x = 0;
38 ++ y;
39 }
40 if ( xOut == screenColumns ) { // we have to special-case line wrap
41 xOut = 0;
42 ++ yOut;
43 }
44 }
45
46 /**
47 * Calculate a column width using mk_wcswidth()
48 * @param buf32 - text to calculate
49 * @param len - length of text to calculate
50 */
calculate_displayed_length(char32_t const * buf32_,int size_)51 int calculate_displayed_length( char32_t const* buf32_, int size_ ) {
52 int len( 0 );
53 for ( int i( 0 ); i < size_; ++ i ) {
54 char32_t c( buf32_[i] );
55 if ( c == '\033' ) {
56 int escStart( i );
57 ++ i;
58 if ( ( i < size_ ) && ( buf32_[i] != '[' ) ) {
59 i = escStart;
60 ++ len;
61 continue;
62 }
63 ++ i;
64 for ( ; i < size_; ++ i ) {
65 c = buf32_[i];
66 if ( ( c != ';' ) && ( ( c < '0' ) || ( c > '9' ) ) ) {
67 break;
68 }
69 }
70 if ( ( i < size_ ) && ( buf32_[i] == 'm' ) ) {
71 continue;
72 }
73 i = escStart;
74 len += 2;
75 } else if ( is_control_code( c ) ) {
76 len += 2;
77 } else {
78 int wcw( mk_wcwidth( c ) );
79 if ( wcw < 0 ) {
80 len = -1;
81 break;
82 }
83 len += wcw;
84 }
85 }
86 return ( len );
87 }
88
ansi_color(Replxx::Color color_)89 char const* ansi_color( Replxx::Color color_ ) {
90 static char const reset[] = "\033[0m";
91 static char const black[] = "\033[0;22;30m";
92 static char const red[] = "\033[0;22;31m";
93 static char const green[] = "\033[0;22;32m";
94 static char const brown[] = "\033[0;22;33m";
95 static char const blue[] = "\033[0;22;34m";
96 static char const magenta[] = "\033[0;22;35m";
97 static char const cyan[] = "\033[0;22;36m";
98 static char const lightgray[] = "\033[0;22;37m";
99
100 #ifdef _WIN32
101 static bool const has256colorDefault( true );
102 #else
103 static bool const has256colorDefault( false );
104 #endif
105 static char const* TERM( getenv( "TERM" ) );
106 static bool const has256color( TERM ? ( strstr( TERM, "256" ) != nullptr ) : has256colorDefault );
107 static char const* gray = has256color ? "\033[0;1;90m" : "\033[0;1;30m";
108 static char const* brightred = has256color ? "\033[0;1;91m" : "\033[0;1;31m";
109 static char const* brightgreen = has256color ? "\033[0;1;92m" : "\033[0;1;32m";
110 static char const* yellow = has256color ? "\033[0;1;93m" : "\033[0;1;33m";
111 static char const* brightblue = has256color ? "\033[0;1;94m" : "\033[0;1;34m";
112 static char const* brightmagenta = has256color ? "\033[0;1;95m" : "\033[0;1;35m";
113 static char const* brightcyan = has256color ? "\033[0;1;96m" : "\033[0;1;36m";
114 static char const* white = has256color ? "\033[0;1;97m" : "\033[0;1;37m";
115 static char const error[] = "\033[101;1;33m";
116
117 char const* code( reset );
118 switch ( color_ ) {
119 case Replxx::Color::BLACK: code = black; break;
120 case Replxx::Color::RED: code = red; break;
121 case Replxx::Color::GREEN: code = green; break;
122 case Replxx::Color::BROWN: code = brown; break;
123 case Replxx::Color::BLUE: code = blue; break;
124 case Replxx::Color::MAGENTA: code = magenta; break;
125 case Replxx::Color::CYAN: code = cyan; break;
126 case Replxx::Color::LIGHTGRAY: code = lightgray; break;
127 case Replxx::Color::GRAY: code = gray; break;
128 case Replxx::Color::BRIGHTRED: code = brightred; break;
129 case Replxx::Color::BRIGHTGREEN: code = brightgreen; break;
130 case Replxx::Color::YELLOW: code = yellow; break;
131 case Replxx::Color::BRIGHTBLUE: code = brightblue; break;
132 case Replxx::Color::BRIGHTMAGENTA: code = brightmagenta; break;
133 case Replxx::Color::BRIGHTCYAN: code = brightcyan; break;
134 case Replxx::Color::WHITE: code = white; break;
135 case Replxx::Color::ERROR: code = error; break;
136 case Replxx::Color::DEFAULT: code = reset; break;
137 }
138 return ( code );
139 }
140
now_ms_str(void)141 std::string now_ms_str( void ) {
142 std::chrono::milliseconds ms( std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now().time_since_epoch() ) );
143 time_t t( ms.count() / 1000 );
144 tm broken;
145 #ifdef _WIN32
146 #define localtime_r( t, b ) localtime_s( ( b ), ( t ) )
147 #endif
148 localtime_r( &t, &broken );
149 #undef localtime_r
150 static int const BUFF_SIZE( 32 );
151 char str[BUFF_SIZE];
152 strftime( str, BUFF_SIZE, "%Y-%m-%d %H:%M:%S.", &broken );
153 snprintf( str + sizeof ( "YYYY-mm-dd HH:MM:SS" ), 5, "%03d", static_cast<int>( ms.count() % 1000 ) );
154 return ( str );
155 }
156
157 }
158
159