1 /* Styling for ui_file 2 Copyright (C) 2018-2023 Free Software Foundation, Inc. 3 4 This file is part of GDB. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 #ifndef UI_STYLE_H 20 #define UI_STYLE_H 21 22 /* Styles that can be applied to a ui_file. */ 23 struct ui_file_style 24 { 25 /* One of the basic colors that can be handled by ANSI 26 terminals. */ 27 enum basic_color 28 { 29 NONE = -1, 30 BLACK, 31 RED, 32 GREEN, 33 YELLOW, 34 BLUE, 35 MAGENTA, 36 CYAN, 37 WHITE 38 }; 39 40 /* Representation of a terminal color. */ 41 class color 42 { 43 public: 44 45 color (basic_color c) 46 : m_simple (true), 47 m_value (c) 48 { 49 } 50 51 color (int c) 52 : m_simple (true), 53 m_value (c) 54 { 55 gdb_assert (c >= -1 && c <= 255); 56 } 57 58 color (uint8_t r, uint8_t g, uint8_t b) 59 : m_simple (false), 60 m_red (r), 61 m_green (g), 62 m_blue (b) 63 { 64 } 65 66 bool operator== (const color &other) const 67 { 68 if (m_simple != other.m_simple) 69 return false; 70 if (m_simple) 71 return m_value == other.m_value; 72 return (m_red == other.m_red && m_green == other.m_green 73 && m_blue == other.m_blue); 74 } 75 76 bool operator< (const color &other) const 77 { 78 if (m_simple != other.m_simple) 79 return m_simple < other.m_simple; 80 if (m_simple) 81 return m_value < other.m_value; 82 if (m_red < other.m_red) 83 return true; 84 if (m_red == other.m_red) 85 { 86 if (m_green < other.m_green) 87 return true; 88 if (m_green == other.m_green) 89 return m_blue < other.m_blue; 90 } 91 return false; 92 } 93 94 /* Return true if this is the "NONE" color, false otherwise. */ 95 bool is_none () const 96 { 97 return m_simple && m_value == NONE; 98 } 99 100 /* Return true if this is one of the basic colors, false 101 otherwise. */ 102 bool is_basic () const 103 { 104 return m_simple && m_value >= BLACK && m_value <= WHITE; 105 } 106 107 /* Return the value of a basic color. */ 108 int get_value () const 109 { 110 gdb_assert (is_basic ()); 111 return m_value; 112 } 113 114 /* Fill in RGB with the red/green/blue values for this color. 115 This may not be called for basic colors or for the "NONE" 116 color. */ 117 void get_rgb (uint8_t *rgb) const; 118 119 /* Append the ANSI terminal escape sequence for this color to STR. 120 IS_FG indicates whether this is a foreground or background 121 color. Returns true if any characters were written; returns 122 false otherwise (which can only happen for the "NONE" 123 color). */ 124 bool append_ansi (bool is_fg, std::string *str) const; 125 126 private: 127 128 bool m_simple; 129 union 130 { 131 int m_value; 132 struct 133 { 134 uint8_t m_red, m_green, m_blue; 135 }; 136 }; 137 }; 138 139 /* Intensity settings that are available. */ 140 enum intensity 141 { 142 NORMAL = 0, 143 BOLD, 144 DIM 145 }; 146 147 ui_file_style () = default; 148 149 ui_file_style (color f, color b, intensity i = NORMAL) 150 : m_foreground (f), 151 m_background (b), 152 m_intensity (i) 153 { 154 } 155 156 bool operator== (const ui_file_style &other) const 157 { 158 return (m_foreground == other.m_foreground 159 && m_background == other.m_background 160 && m_intensity == other.m_intensity 161 && m_reverse == other.m_reverse); 162 } 163 164 bool operator!= (const ui_file_style &other) const 165 { 166 return !(*this == other); 167 } 168 169 /* Return the ANSI escape sequence for this style. */ 170 std::string to_ansi () const; 171 172 /* Return true if this style is the default style; false 173 otherwise. */ 174 bool is_default () const 175 { 176 return (m_foreground == NONE 177 && m_background == NONE 178 && m_intensity == NORMAL 179 && !m_reverse); 180 } 181 182 /* Return true if this style specified reverse display; false 183 otherwise. */ 184 bool is_reverse () const 185 { 186 return m_reverse; 187 } 188 189 /* Set/clear the reverse display flag. */ 190 void set_reverse (bool reverse) 191 { 192 m_reverse = reverse; 193 } 194 195 /* Return the foreground color of this style. */ 196 const color &get_foreground () const 197 { 198 return m_foreground; 199 } 200 201 /* Set the foreground color of this style. */ 202 void set_fg (color c) 203 { 204 m_foreground = c; 205 } 206 207 /* Return the background color of this style. */ 208 const color &get_background () const 209 { 210 return m_background; 211 } 212 213 /* Set the background color of this style. */ 214 void set_bg (color c) 215 { 216 m_background = c; 217 } 218 219 /* Return the intensity of this style. */ 220 intensity get_intensity () const 221 { 222 return m_intensity; 223 } 224 225 /* Parse an ANSI escape sequence in BUF, modifying this style. BUF 226 must begin with an ESC character. Return true if an escape 227 sequence was successfully parsed; false otherwise. In either 228 case, N_READ is updated to reflect the number of chars read from 229 BUF. */ 230 bool parse (const char *buf, size_t *n_read); 231 232 /* We need this because we can't pass a reference via va_args. */ 233 const ui_file_style *ptr () const 234 { 235 return this; 236 } 237 238 private: 239 240 color m_foreground = NONE; 241 color m_background = NONE; 242 intensity m_intensity = NORMAL; 243 bool m_reverse = false; 244 }; 245 246 /* Skip an ANSI escape sequence in BUF. BUF must begin with an ESC 247 character. Return true if an escape sequence was successfully 248 skipped; false otherwise. If an escape sequence was skipped, 249 N_READ is updated to reflect the number of chars read from BUF. */ 250 251 extern bool skip_ansi_escape (const char *buf, int *n_read); 252 253 #endif /* UI_STYLE_H */ 254