|  | /* Styling for ui_file | 
|  | Copyright (C) 2018-2025 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GDB. | 
|  |  | 
|  | This program is free software; you can redistribute it and/or modify | 
|  | it under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3 of the License, or | 
|  | (at your option) any later version. | 
|  |  | 
|  | This program is distributed in the hope that it will be useful, | 
|  | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | GNU General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #ifndef GDB_UI_STYLE_H | 
|  | #define GDB_UI_STYLE_H | 
|  |  | 
|  | /* One of the color spaces that usually supported by terminals.  */ | 
|  | enum class color_space | 
|  | { | 
|  | /* one default terminal color  */ | 
|  | MONOCHROME, | 
|  |  | 
|  | /* foreground colors \e[30m ... \e[37m, | 
|  | background colors \e[40m ... \e[47m  */ | 
|  | ANSI_8COLOR, | 
|  |  | 
|  | /* foreground colors \e[30m ... \e[37m, \e[90m ... \e[97m | 
|  | background colors \e[40m ... \e[47m, \e[100m ... \e107m  */ | 
|  | AIXTERM_16COLOR, | 
|  |  | 
|  | /* foreground colors \e[38;5;0m ... \e[38;5;255m | 
|  | background colors \e[48;5;0m ... \e[48;5;255m  */ | 
|  | XTERM_256COLOR, | 
|  |  | 
|  | /* foreground colors \e[38;2;0;0;0m ... \e[38;2;255;255;255m | 
|  | background colors \e[48;2;0;0;0m ... \e[48;2;255;255;255m  */ | 
|  | RGB_24BIT | 
|  | }; | 
|  |  | 
|  | /* Color spaces supported by terminal.  */ | 
|  | extern const std::vector<color_space> & colorsupport (); | 
|  |  | 
|  | /* Textual representation of C.  */ | 
|  | extern const char * color_space_name (color_space c); | 
|  |  | 
|  | /* Cast C to RESULT and return true if it's value is valid; false otherwise.  */ | 
|  | extern bool color_space_safe_cast (color_space *result, long c); | 
|  |  | 
|  | /* Styles that can be applied to a ui_file.  */ | 
|  | struct ui_file_style | 
|  | { | 
|  | /* One of the basic colors that can be handled by ANSI | 
|  | terminals.  */ | 
|  | enum basic_color | 
|  | { | 
|  | NONE = -1, | 
|  | BLACK, | 
|  | RED, | 
|  | GREEN, | 
|  | YELLOW, | 
|  | BLUE, | 
|  | MAGENTA, | 
|  | CYAN, | 
|  | WHITE | 
|  | }; | 
|  |  | 
|  | /* Representation of a terminal color.  */ | 
|  | class color | 
|  | { | 
|  | public: | 
|  |  | 
|  | color (basic_color c) | 
|  | : m_color_space (c == NONE ? color_space::MONOCHROME | 
|  | : color_space::ANSI_8COLOR), | 
|  | m_value (c) | 
|  | { | 
|  | } | 
|  |  | 
|  | color (int c) | 
|  | : m_value (c) | 
|  | { | 
|  | if (c < -1 || c > 255) | 
|  | error (_("Palette color index %d is out of range."), c); | 
|  | if (c == -1) | 
|  | m_color_space = color_space::MONOCHROME; | 
|  | else if (c <= 7) | 
|  | m_color_space = color_space::ANSI_8COLOR; | 
|  | else if (c <= 15) | 
|  | m_color_space = color_space::AIXTERM_16COLOR; | 
|  | else | 
|  | m_color_space = color_space::XTERM_256COLOR; | 
|  | } | 
|  |  | 
|  | color (color_space cs, int c) | 
|  | : m_color_space (cs), | 
|  | m_value (c) | 
|  | { | 
|  | if (c < -1 || c > 255) | 
|  | error (_("Palette color index %d is out of range."), c); | 
|  |  | 
|  | std::pair<int, int> range; | 
|  | switch (cs) | 
|  | { | 
|  | case color_space::MONOCHROME: | 
|  | range = {-1, -1}; | 
|  | break; | 
|  | case color_space::ANSI_8COLOR: | 
|  | range = {0, 7}; | 
|  | break; | 
|  | case color_space::AIXTERM_16COLOR: | 
|  | range = {0, 15}; | 
|  | break; | 
|  | case color_space::XTERM_256COLOR: | 
|  | range = {0, 255}; | 
|  | break; | 
|  | default: | 
|  | error (_("Color space %d is incompatible with indexed colors."), | 
|  | static_cast<int> (cs)); | 
|  | } | 
|  |  | 
|  | if (c < range.first || c > range.second) | 
|  | error (_("Color %d is out of range [%d, %d] of color space %d."), | 
|  | c, range.first, range.second, static_cast<int> (cs)); | 
|  | } | 
|  |  | 
|  | color (uint8_t r, uint8_t g, uint8_t b) | 
|  | : m_color_space (color_space::RGB_24BIT), | 
|  | m_red (r), | 
|  | m_green (g), | 
|  | m_blue (b) | 
|  | { | 
|  | } | 
|  |  | 
|  | bool operator== (const color &other) const | 
|  | { | 
|  | if (m_color_space != other.m_color_space) | 
|  | return false; | 
|  | if (is_simple ()) | 
|  | return m_value == other.m_value; | 
|  | return (m_red == other.m_red && m_green == other.m_green | 
|  | && m_blue == other.m_blue); | 
|  | } | 
|  |  | 
|  | bool operator!= (const color &other) const | 
|  | { | 
|  | return ! (*this == other); | 
|  | } | 
|  |  | 
|  | /* Compute a simple hash code for this object.  */ | 
|  | size_t hash () const | 
|  | { | 
|  | if (is_simple ()) | 
|  | return m_value; | 
|  | return (m_red << 16) + (m_green << 8) + m_red; | 
|  | } | 
|  |  | 
|  | color_space colorspace () const | 
|  | { | 
|  | return m_color_space; | 
|  | } | 
|  |  | 
|  | /* Return true if this is the "NONE" color, false otherwise.  */ | 
|  | bool is_none () const | 
|  | { | 
|  | return m_color_space == color_space::MONOCHROME && m_value == NONE; | 
|  | } | 
|  |  | 
|  | /* Return true if this is one of the basic colors, false | 
|  | otherwise.  */ | 
|  | bool is_basic () const | 
|  | { | 
|  | if (m_color_space == color_space::ANSI_8COLOR | 
|  | || m_color_space == color_space::AIXTERM_16COLOR) | 
|  | return BLACK <= m_value && m_value <= WHITE; | 
|  | else | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /* Return true if this is one of the colors, stored as int, false | 
|  | otherwise.  */ | 
|  | bool is_simple () const | 
|  | { | 
|  | return m_color_space != color_space::RGB_24BIT; | 
|  | } | 
|  |  | 
|  | /* Return true if this is one of the indexed colors, false | 
|  | otherwise.  */ | 
|  | bool is_indexed () const | 
|  | { | 
|  | return m_color_space != color_space::RGB_24BIT | 
|  | && m_color_space != color_space::MONOCHROME; | 
|  | } | 
|  |  | 
|  | /* Return true if this is one of the direct colors (RGB, CMY, CMYK), false | 
|  | otherwise.  */ | 
|  | bool is_direct () const | 
|  | { | 
|  | return m_color_space == color_space::RGB_24BIT; | 
|  | } | 
|  |  | 
|  | /* Return the value of a simple color.  */ | 
|  | int get_value () const | 
|  | { | 
|  | gdb_assert (is_simple ()); | 
|  | return m_value; | 
|  | } | 
|  |  | 
|  | /* Fill in RGB with the red/green/blue values for this color. | 
|  | This may not be called for basic colors or for the "NONE" | 
|  | color.  */ | 
|  | void get_rgb (uint8_t *rgb) const; | 
|  |  | 
|  | /* Append the ANSI terminal escape sequence for this color to STR. | 
|  | IS_FG indicates whether this is a foreground or background | 
|  | color.  */ | 
|  | void append_ansi (bool is_fg, std::string *str) const; | 
|  |  | 
|  | /* Return the ANSI escape sequence for this color. | 
|  | IS_FG indicates whether this is a foreground or background color.  */ | 
|  | std::string to_ansi (bool is_fg) const; | 
|  |  | 
|  | /* Returns text representation of this object. | 
|  | It is "none", name of a basic color, number or a #RRGGBB hex triplet.  */ | 
|  | std::string to_string () const; | 
|  |  | 
|  | /* Approximates THIS color by closest one from SPACES.  */ | 
|  | color approximate (const std::vector<color_space> &spaces) const; | 
|  |  | 
|  | private: | 
|  |  | 
|  | color_space m_color_space; | 
|  | union | 
|  | { | 
|  | int m_value; | 
|  | struct | 
|  | { | 
|  | uint8_t m_red, m_green, m_blue; | 
|  | }; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | /* Intensity settings that are available.  */ | 
|  | enum intensity | 
|  | { | 
|  | NORMAL = 0, | 
|  | BOLD, | 
|  | DIM | 
|  | }; | 
|  |  | 
|  | ui_file_style () = default; | 
|  |  | 
|  | ui_file_style (color f, color b, intensity i = NORMAL) | 
|  | : m_foreground (f), | 
|  | m_background (b), | 
|  | m_intensity (i) | 
|  | { | 
|  | } | 
|  |  | 
|  | bool operator== (const ui_file_style &other) const | 
|  | { | 
|  | return (m_foreground == other.m_foreground | 
|  | && m_background == other.m_background | 
|  | && m_intensity == other.m_intensity | 
|  | && m_reverse == other.m_reverse); | 
|  | } | 
|  |  | 
|  | bool operator!= (const ui_file_style &other) const | 
|  | { | 
|  | return !(*this == other); | 
|  | } | 
|  |  | 
|  | /* Return the ANSI escape sequence for this style.  */ | 
|  | std::string to_ansi () const; | 
|  |  | 
|  | /* Return true if this style is the default style; false | 
|  | otherwise.  */ | 
|  | bool is_default () const | 
|  | { | 
|  | return (m_foreground == NONE | 
|  | && m_background == NONE | 
|  | && m_intensity == NORMAL | 
|  | && !m_reverse); | 
|  | } | 
|  |  | 
|  | /* Return true if this style specified reverse display; false | 
|  | otherwise.  */ | 
|  | bool is_reverse () const | 
|  | { | 
|  | return m_reverse; | 
|  | } | 
|  |  | 
|  | /* Set/clear the reverse display flag.  */ | 
|  | void set_reverse (bool reverse) | 
|  | { | 
|  | m_reverse = reverse; | 
|  | } | 
|  |  | 
|  | /* Return the foreground color of this style.  */ | 
|  | const color &get_foreground () const | 
|  | { | 
|  | return m_foreground; | 
|  | } | 
|  |  | 
|  | /* Set the foreground color of this style.  */ | 
|  | void set_fg (color c) | 
|  | { | 
|  | m_foreground = c; | 
|  | } | 
|  |  | 
|  | /* Return the background color of this style.  */ | 
|  | const color &get_background () const | 
|  | { | 
|  | return m_background; | 
|  | } | 
|  |  | 
|  | /* Set the background color of this style.  */ | 
|  | void set_bg (color c) | 
|  | { | 
|  | m_background = c; | 
|  | } | 
|  |  | 
|  | /* Return the intensity of this style.  */ | 
|  | intensity get_intensity () const | 
|  | { | 
|  | return m_intensity; | 
|  | } | 
|  |  | 
|  | /* Parse an ANSI escape sequence in BUF, modifying this style.  BUF | 
|  | must begin with an ESC character.  Return true if an escape | 
|  | sequence was successfully parsed; false otherwise.  In either | 
|  | case, N_READ is updated to reflect the number of chars read from | 
|  | BUF.  */ | 
|  | bool parse (const char *buf, size_t *n_read); | 
|  |  | 
|  | /* We need this because we can't pass a reference via va_args.  */ | 
|  | const ui_file_style *ptr () const | 
|  | { | 
|  | return this; | 
|  | } | 
|  |  | 
|  | /* nullptr-terminated list of names corresponding to enum basic_color.  */ | 
|  | static const std::vector<const char *> basic_color_enums; | 
|  |  | 
|  | private: | 
|  |  | 
|  | color m_foreground = NONE; | 
|  | color m_background = NONE; | 
|  | intensity m_intensity = NORMAL; | 
|  | bool m_reverse = false; | 
|  | }; | 
|  |  | 
|  | /* Skip an ANSI escape sequence in BUF.  BUF must begin with an ESC | 
|  | character.  Return true if an escape sequence was successfully | 
|  | skipped; false otherwise.  If an escape sequence was skipped, | 
|  | N_READ is updated to reflect the number of chars read from BUF.  */ | 
|  |  | 
|  | extern bool skip_ansi_escape (const char *buf, int *n_read); | 
|  |  | 
|  | #endif /* GDB_UI_STYLE_H */ |