xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/ui-style.h (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
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