libcopp  1.2.0
shell_font.cpp
Go to the documentation of this file.
1 /*
2  * shell_fonts.h
3  *
4  * Created on: 2014年3月11日
5  * Author: owent
6  *
7  * Released under the MIT license
8  */
9 
10 #include <algorithm>
11 #include <cstdlib>
12 #include <set>
13 
14 #include "cli/shell_font.h"
15 
16 #define SHELL_FONT_SET_OPT_END "\033[0m"
17 
18 namespace util {
19  namespace cli {
20 
21  namespace detail {
22  static char tolower(char c) {
23  if (c >= 'A' && c <= 'Z') {
24  return c - 'A' + 'a';
25  }
26 
27  return c;
28  }
29  } // namespace detail
30 
31  shell_font::shell_font(int iFlag) : m_iFlag(iFlag) {}
32 
34 
35  std::string shell_font::GetStyleCode(int iFlag) {
36  std::string ret;
37  ret.reserve(32);
38  ret = "\033[";
39  bool bFirst = true;
40 
41  // 第一部分,特殊样式
43  ret += std::string((!bFirst) ? ";" : "") + "1";
44  bFirst = false;
45  }
47  ret += std::string((!bFirst) ? ";" : "") + "4";
48  bFirst = false;
49  }
51  ret += std::string((!bFirst) ? ";" : "") + "5";
52  bFirst = false;
53  }
55  ret += std::string((!bFirst) ? ";" : "") + "2";
56  bFirst = false;
57  }
58 
59  // 前景色
60  iFlag >>= 8;
61  if (iFlag & 0xff) {
62  std::string base = "30";
63  int iStart = 0;
64  for (; iStart < 8 && !(iFlag & (1 << iStart)); ++iStart)
65  ;
66  if (iStart < 8) base[1] += static_cast<char>(iStart);
67  ret += std::string((!bFirst) ? ";" : "") + base;
68  bFirst = false;
69  }
70 
71  // 背景色
72  iFlag >>= 8;
73  if (iFlag & 0xff) {
74  std::string base = "40";
75  int iStart = 0;
76  for (; iStart < 8 && !(iFlag & (1 << iStart)); ++iStart)
77  ;
78  if (iStart < 8) base[1] += static_cast<char>(iStart);
79  ret += std::string((!bFirst) ? ";" : "") + base;
80  // bFirst = false; no need to set because not used later
81  }
82 
83  ret += "m";
84 
85  return ret;
86  }
87 
88  std::string shell_font::GetStyleCode() { return GetStyleCode(m_iFlag); }
89 
91 
92  static int _check_term_color_status() {
93  std::set<std::string> color_term;
94  color_term.insert("eterm");
95  color_term.insert("ansi");
96  color_term.insert("color-xterm");
97  color_term.insert("con132x25");
98  color_term.insert("con132x30");
99  color_term.insert("con132x43");
100  color_term.insert("con132x60");
101  color_term.insert("con80x25");
102  color_term.insert("con80x28");
103  color_term.insert("con80x30");
104  color_term.insert("con80x43");
105  color_term.insert("con80x50");
106  color_term.insert("con80x60");
107  color_term.insert("cons25");
108  color_term.insert("console");
109  color_term.insert("cygwin");
110  color_term.insert("dtterm");
111  color_term.insert("eterm-color");
112  color_term.insert("gnome");
113  color_term.insert("gnome-256color");
114  color_term.insert("jfbterm");
115  color_term.insert("konsole");
116  color_term.insert("kterm");
117  color_term.insert("linux");
118  color_term.insert("linux-c");
119  color_term.insert("mach-color");
120  color_term.insert("mlterm");
121  color_term.insert("putty");
122  color_term.insert("rxvt");
123  color_term.insert("rxvt-256color");
124  color_term.insert("rxvt-cygwin");
125  color_term.insert("rxvt-cygwin-native");
126  color_term.insert("rxvt-unicode");
127  color_term.insert("rxvt-unicode256");
128  color_term.insert("screen");
129  color_term.insert("screen-256color");
130  color_term.insert("screen-256color-bce");
131  color_term.insert("screen-bce");
132  color_term.insert("screen-256color-bce");
133  color_term.insert("screen-bce");
134  color_term.insert("screen-w");
135  color_term.insert("screen.linux");
136  color_term.insert("vt100");
137  color_term.insert("xterm");
138  color_term.insert("xterm-16color");
139  color_term.insert("xterm-256color");
140  color_term.insert("xterm-88color");
141  color_term.insert("xterm-color");
142  color_term.insert("xterm-debian");
143 
144  std::string my_term_name;
145 
146 #ifdef _MSC_VER
147  char * term_name = NULL;
148  size_t term_name_len = 0;
149  _dupenv_s(&term_name, &term_name_len, "TERM");
150 #else
151  char *term_name = getenv("TERM");
152 #endif
153  if (NULL != term_name) {
154 #ifdef _MSC_VER
155  my_term_name.assign(term_name, term_name_len);
156  ::free(term_name);
157 #else
158  my_term_name = term_name;
159 #endif
160  }
161 
162  std::transform(my_term_name.begin(), my_term_name.end(), my_term_name.begin(), detail::tolower);
163 
164  if (color_term.end() == color_term.find(my_term_name)) return -1;
165  return 1;
166  }
167 
168  std::string shell_font::GenerateString(const std::string &strInput, int iFlag) {
169  static int status_ = 0;
170 
171  if (0 == status_) {
172  status_ = _check_term_color_status();
173  }
174 
175  if (status_ < 0 || iFlag == 0) return strInput;
176  return GetStyleCode(iFlag) + strInput + GetStyleCloseCode();
177  }
178 
179  std::string shell_font::GenerateString(const std::string &strInput) { return GenerateString(strInput, m_iFlag); }
180 
181 
182 #ifdef SHELL_FONT_USING_WIN32_CONSOLE
183 
184  static std::map<int, WORD> &_get_flag_mapping() {
185  static std::map<int, WORD> ret;
186  if (ret.empty()) {
188  ret[shell_font_style::SHELL_FONT_SPEC_BOLD] = COMMON_LVB_LEADING_BYTE;
189  ret[shell_font_style::SHELL_FONT_SPEC_UNDERLINE] = COMMON_LVB_UNDERSCORE;
190  ret[shell_font_style::SHELL_FONT_SPEC_FLASH] = 0; // 不支持
191  ret[shell_font_style::SHELL_FONT_SPEC_DARK] = 0; // 不支持
192 
194  ret[shell_font_style::SHELL_FONT_COLOR_RED] = FOREGROUND_RED | FOREGROUND_INTENSITY;
195  ret[shell_font_style::SHELL_FONT_COLOR_GREEN] = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
196  ret[shell_font_style::SHELL_FONT_COLOR_YELLOW] = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
197  ret[shell_font_style::SHELL_FONT_COLOR_BLUE] = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
198  ret[shell_font_style::SHELL_FONT_COLOR_MAGENTA] = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
199  ret[shell_font_style::SHELL_FONT_COLOR_CYAN] = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
200  ret[shell_font_style::SHELL_FONT_COLOR_WHITE] = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
201 
205  ret[shell_font_style::SHELL_FONT_BACKGROUND_COLOR_YELLOW] = BACKGROUND_RED | BACKGROUND_GREEN;
207  ret[shell_font_style::SHELL_FONT_BACKGROUND_COLOR_MAGENTA] = BACKGROUND_RED | BACKGROUND_BLUE;
208  ret[shell_font_style::SHELL_FONT_BACKGROUND_COLOR_CYAN] = BACKGROUND_BLUE | BACKGROUND_GREEN;
209  ret[shell_font_style::SHELL_FONT_BACKGROUND_COLOR_WHITE] = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE;
210  }
211 
212  return ret;
213  }
214 
215  static WORD _get_default_color() { return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; }
216 
217 #endif
218 
219 
220  shell_stream::shell_stream(stream_t &stream) : m_pOs(&stream) {}
221 
222 
223  shell_stream::shell_stream_opr::shell_stream_opr(stream_t *os) : pOs(os), flag(shell_font_style::SHELL_FONT_SPEC_NULL) {
224 #ifdef SHELL_FONT_USING_WIN32_CONSOLE
225  if (os == &std::cout) {
226  hOsHandle = GetStdHandle(STD_OUTPUT_HANDLE);
227  } else if (os == &std::cerr) {
228  hOsHandle = GetStdHandle(STD_ERROR_HANDLE);
229  } else {
230  hOsHandle = NULL;
231  }
232 #endif
233  }
234 
236  if (NULL == pOs) {
237  return;
238  }
239 
240  reset();
241  }
242 
244 
246  pOs = other.pOs;
247 
248 #ifdef SHELL_FONT_USING_WIN32_CONSOLE
249  hOsHandle = other.hOsHandle;
250 #endif
252 
253  return (*this);
254  }
255 
258  reset();
259  return (*this);
260  }
261 
262  flag |= f;
263  return (*this);
264  }
265 
267  if (NULL == pOs) {
268  return;
269  }
270 
272  return;
273  }
274 
275 #ifdef SHELL_FONT_USING_WIN32_CONSOLE
276  if (NULL != hOsHandle) {
277 
278  std::map<int, WORD> &color_map = _get_flag_mapping();
279  WORD style = 0;
280  int left_flag = flag;
281 
282  while (left_flag) {
283  int f = left_flag & (left_flag ^ (left_flag - 1));
284  std::map<int, WORD>::iterator iter = color_map.find(f);
285  if (iter != color_map.end()) {
286  style |= iter->second;
287  }
288 
289  left_flag = left_flag & (left_flag - 1);
290  }
291 
292  SetConsoleTextAttribute(hOsHandle, style);
293  }
294 #else
295  (*pOs) << shell_font::GetStyleCode(flag);
296 #endif
297 
299  }
300 
302  if (NULL == pOs) {
303  return;
304  }
305 
306  close();
307 
308 #ifdef SHELL_FONT_USING_WIN32_CONSOLE
309  if (NULL != hOsHandle) {
310  SetConsoleTextAttribute(hOsHandle, _get_default_color());
311  }
312 #else
313 
314  (*pOs) << shell_font::GetStyleCloseCode();
315 
316 #endif
317  }
318 
319  } // namespace cli
320 } // namespace util
shell_stream(stream_t &stream=std::cout)
Definition: shell_font.cpp:220
std::string GenerateString(const std::string &strInput)
Definition: shell_font.cpp:179
shell_stream_opr(const shell_stream_opr &)
Definition: shell_font.cpp:243
const shell_stream_opr & open(int flag) const
Definition: shell_font.cpp:256
static std::string GetStyleCloseCode()
Definition: shell_font.cpp:90
static char tolower(char c)
shell_stream_opr & operator=(const shell_stream_opr &)
Definition: shell_font.cpp:245
#define SHELL_FONT_SET_OPT_END
Definition: shell_font.cpp:16
static int _check_term_color_status()
Definition: shell_font.cpp:92
shell_font(int iFlag=0)
Definition: shell_font.cpp:31
std::ostream stream_t
Definition: shell_font.h:157
std::string GetStyleCode()
Definition: shell_font.cpp:88