REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestStringOutput.cxx
1 #include "TRestStringOutput.h"
2 
3 #include "TRestStringHelper.h"
4 
5 using namespace std;
6 
7 #ifdef WIN32
8 #include <Windows.h>
9 #include <conio.h>
10 #endif // WIN32
11 
12 int Console::GetWidth() {
13 #ifdef WIN32
14  CONSOLE_SCREEN_BUFFER_INFO csbi;
15  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
16  return csbi.srWindow.Right - csbi.srWindow.Left + 1;
17 #else
18  if (isatty(fileno(stdout))) {
19  struct winsize w;
20  ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
21  return w.ws_col;
22  }
23  return -1;
24 #endif // WIN32
25 }
26 
27 int Console::GetHeight() {
28 #ifdef WIN32
29  CONSOLE_SCREEN_BUFFER_INFO csbi;
30  GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
31  return csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
32 #else
33  if (isatty(fileno(stdout))) {
34  struct winsize w;
35  ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
36  return w.ws_row;
37  }
38  return -1;
39 #endif // WIN32
40 }
41 
42 bool Console::kbhit() {
43 #ifdef WIN32
44  return _kbhit();
45 #else
46  struct termios oldt, newt;
47  int ch;
48  int oldf;
49  tcgetattr(STDIN_FILENO, &oldt);
50  newt = oldt;
51  newt.c_lflag &= ~(ICANON | ECHO);
52  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
53  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
54  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
55  ch = getchar();
56  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
57  fcntl(STDIN_FILENO, F_SETFL, oldf);
58  if (ch != EOF) {
59  ungetc(ch, stdin);
60  return true;
61  }
62  return false;
63 
64 // int byteswaiting;
65 // ioctl(0, FIONREAD, &byteswaiting);
66 // return byteswaiting > 0;
67 #endif
68 }
69 
70 int Console::Read() { return getchar(); }
71 
72 int Console::ReadKey() {
73 #ifdef WIN32
74  return _getch();
75 #else
76  struct termios tm, tm_old;
77  int fd = 0, ch;
78 
79  if (tcgetattr(fd, &tm) < 0) {
80  return -1;
81  }
82 
83  tm_old = tm;
84  cfmakeraw(&tm);
85  if (tcsetattr(fd, TCSANOW, &tm) < 0) {
86  return -1;
87  }
88 
89  ch = getchar();
90  if (tcsetattr(fd, TCSANOW, &tm_old) < 0) {
91  return -1;
92  }
93 
94  return ch;
95 #endif
96 }
97 
98 string Console::ReadLine() {
99  char a[500];
100  cin.getline(a, 500);
101  return string(a);
102 }
103 
104 void Console::WriteLine(string content) {
105  printf("%s", content.c_str());
106  fflush(stdout);
107 }
108 
109 void Console::CursorUp(int n) {
110  printf("\033[%dA", n);
111  fflush(stdout);
112 }
113 
114 void Console::CursorDown(int n) {
115  printf("\033[%dB", n);
116  fflush(stdout);
117 }
118 
119 void Console::CursorRight(int n) {
120  printf("\033[%dC", n);
121  fflush(stdout);
122 }
123 
124 void Console::CursorLeft(int n) {
125  printf("\033[%dD", n);
126  fflush(stdout);
127 }
128 
129 void Console::CursorToXY(int x, int y) {
130  printf("\033[%d%dH", x, y);
131  fflush(stdout);
132 }
133 
134 void Console::ClearScreen() {
135  printf("\033[2J");
136  fflush(stdout);
137 }
138 
139 void Console::ClearCurrentLine() {
140 #ifdef WIN32
141  printf("\r");
142  fflush(stdout);
143 #else
144  printf("\033[K");
145  fflush(stdout);
146 #endif // WIN32
147 }
148 
149 void Console::ClearLinesAfterCursor() {
150  printf("\033[s");
151  for (int i = 0; i < 50; i++) {
152  printf("\033[K");
153  CursorDown(1);
154  }
155  printf("\033[u");
156  fflush(stdout);
157 }
158 
159 char mirrorchar(char c) {
160  switch (c) {
161  default:
162  return c;
163  case '<':
164  return '>';
165  case '>':
166  return '<';
167  case '[':
168  return ']';
169  case ']':
170  return '[';
171  case '{':
172  return '}';
173  case '}':
174  return '{';
175  case '(':
176  return ')';
177  case ')':
178  return '(';
179  case '\\':
180  return '/';
181  case '/':
182  return '\\';
183  case 'd':
184  return 'b';
185  case 'b':
186  return 'd';
187  case 'q':
188  return 'p';
189  case 'p':
190  return 'q';
191  }
192 }
193 
194 #define TRestStringOutput_BestLength 100
195 TRestStringOutput::TRestStringOutput(COLORCODE_TYPE _color, string formatter,
196  REST_Display_Orientation _orientation) {
197  iserror = false;
198  color = _color;
199  orientation = _orientation;
200  // check if is border expression
201  useborder = true;
202  if (formatter.size() < 2) {
203  useborder = false;
204  }
205  for (unsigned int i = 0; i < formatter.size() / 2; i++) {
206  if (mirrorchar(formatter[i]) != formatter[formatter.size() - i - 1]) {
207  useborder = false;
208  break;
209  }
210  }
211  if (formatter[formatter.size() / 2] != ' ') {
212  useborder = false;
213  }
214 
215  if (useborder) {
216  formatstring = formatter.substr(0, formatter.size() / 2);
217  formatstring = Replace(formatstring, " ", "");
218  } else {
219  formatstring = formatter;
220  }
221 
222  setlength(TRestStringOutput_BestLength);
223  resetstring();
224  if (length > 500 || length < 20) // unsupported console, we will fall back to compatibility modes
225  {
226  length = -1;
227  REST_Display_CompatibilityMode = true;
228  }
229 
230  verbose = REST_Verbose_Level::REST_Essential;
231 }
232 
233 void TRestStringOutput::resetstring() {
234  buf.clear();
235  buf.str("");
236 }
237 
238 string TRestStringOutput::FormattingPrintString(string input) {
239  if (input == "") return "";
240 
241  // input: "=abc=", output "=============abc============="(length)
242  if (input[0] == input[input.size() - 1] &&
243  (input[0] == '=' || input[0] == '-' || input[0] == '*' || input[0] == '+')) {
244  return string(length, input[0]);
245  }
246 
247  if (useborder) {
248  string output(length, ' ');
249 
250  int Lstr = input.size();
251  int Lfmt = formatstring.size();
252 
253  int startblank;
254  if (useborder || orientation == TRestStringOutput::REST_Display_Orientation::kMiddle) {
255  startblank = (length - Lstr) / 2;
256  } else {
257  startblank = Lfmt;
258  }
259  if (startblank < 0) {
260  startblank = 0;
261  }
262 
263  string& border = formatstring;
264  for (int i = 0; i < Lfmt && i < length; i++) {
265  output[i] = border[i];
266  output[length - i - 1] = mirrorchar(border[i]);
267  }
268 
269  for (int i = 0; i < Lstr; i++) {
270  if (startblank + i > length - 1) {
271  output[length - 3] = '.';
272  output[length - 2] = '.';
273  output[length - 1] = '.';
274  return output;
275  }
276  output[startblank + i] = input[i];
277  }
278 
279  return output;
280  } else {
281  return formatstring + input;
282  }
283 }
284 
285 void TRestStringOutput::setlength(int n) {
286  if (!REST_Display_CompatibilityMode) {
287  if (n >= Console::GetWidth() - 2) {
288  length = Console::GetWidth() - 2;
289  } else if (n <= 0) {
290  length = Console::GetWidth() - 2;
291  } else {
292  length = n;
293  }
294  } else {
295  length = n;
296  }
297 }
298 
299 #ifdef WIN32
300 // use >> 4 << 4 to extract first 4 bytes from COLOR_RESET, which means the background color
301 #define SET_COLOR(color) \
302  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), (COLOR_RESET >> 4 << 4) + color);
303 #define RESET_COLOR() SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), COLOR_RESET);
304 #else
305 #define SET_COLOR(color) std::cout << color;
306 #define RESET_COLOR() std::cout << COLOR_RESET;
307 #endif // WIN32
308 
309 void TRestStringOutput::flushstring() {
310  if (REST_Display_CompatibilityMode) // this means we are using condor
311  {
312  std::cout << buf.str() << std::endl;
313  } else {
314  Console::ClearCurrentLine();
315  if (orientation == TRestStringOutput::REST_Display_Orientation::kMiddle) {
316  // we always reset the length of TRestStringOutput in case the console is resized
317  setlength(TRestStringOutput_BestLength);
318  int blankwidth = (Console::GetWidth() - 2 - length) / 2;
319 
320  SET_COLOR(color);
321  std::cout << string(blankwidth, ' ') << FormattingPrintString(buf.str())
322  << string(blankwidth, ' ');
323  RESET_COLOR()
324  std::cout << std::endl;
325  } else {
326  SET_COLOR(color);
327  std::cout << FormattingPrintString(buf.str());
328  RESET_COLOR()
329  std::cout << std::endl;
330  }
331  }
332  resetstring();
333 }
334 
335 TRestStringOutput& TRestStringOutput::operator<<(void (*pfunc)(TRestStringOutput&)) {
336  if (gVerbose >= verbose) {
337  ((*pfunc)(*this));
338  }
339  return *this;
340 }
std::string Replace(std::string in, std::string thisString, std::string byThisString, size_t fromPosition=0, Int_t N=0)
Replace any occurences of thisSring by byThisString inside string in.