1/*
2 This file is part of Konsole, KDE's terminal.
3
4 Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
5 Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
21*/
22
23#ifndef CHARACTERCOLOR_H
24#define CHARACTERCOLOR_H
25
26// Qt
27#include <QColor>
28
29//#include <kdemacros.h>
30#define KDE_NO_EXPORT
31
32namespace Konsole
33{
34
35/**
36 * An entry in a terminal display's color palette.
37 *
38 * A color palette is an array of 16 ColorEntry instances which map
39 * system color indexes (from 0 to 15) into actual colors.
40 *
41 * Each entry can be set as bold, in which case any text
42 * drawn using the color should be drawn in bold.
43 *
44 * Each entry can also be transparent, in which case the terminal
45 * display should avoid drawing the background for any characters
46 * using the entry as a background.
47 */
48class ColorEntry
49{
50public:
51 /** Specifies the weight to use when drawing text with this color. */
52 enum FontWeight
53 {
54 /** Always draw text in this color with a bold weight. */
55 Bold,
56 /** Always draw text in this color with a normal weight. */
57 Normal,
58 /**
59 * Use the current font weight set by the terminal application.
60 * This is the default behavior.
61 */
62 UseCurrentFormat
63 };
64
65 /**
66 * Constructs a new color palette entry.
67 *
68 * @param c The color value for this entry.
69 * @param tr Specifies that the color should be transparent when used as a background color.
70 * @param weight Specifies the font weight to use when drawing text with this color.
71 */
72 ColorEntry(QColor c, bool tr, FontWeight weight = UseCurrentFormat)
73 : color(c), transparent(tr), fontWeight(weight) {}
74
75 /**
76 * Constructs a new color palette entry with an undefined color, and
77 * with the transparent and bold flags set to false.
78 */
79 ColorEntry() : transparent(false), fontWeight(UseCurrentFormat) {}
80
81 /**
82 * Sets the color, transparency and boldness of this color to those of @p rhs.
83 */
84 void operator=(const ColorEntry& rhs)
85 {
86 color = rhs.color;
87 transparent = rhs.transparent;
88 fontWeight = rhs.fontWeight;
89 }
90
91 /** The color value of this entry for display. */
92 QColor color;
93
94 /**
95 * If true character backgrounds using this color should be transparent.
96 * This is not applicable when the color is used to render text.
97 */
98 bool transparent;
99 /**
100 * Specifies the font weight to use when drawing text with this color.
101 * This is not applicable when the color is used to draw a character's background.
102 */
103 FontWeight fontWeight;
104};
105
106
107// Attributed Character Representations ///////////////////////////////
108
109// Colors
110
111#define BASE_COLORS (2+8)
112#define INTENSITIES 2
113#define TABLE_COLORS (INTENSITIES*BASE_COLORS)
114
115#define DEFAULT_FORE_COLOR 0
116#define DEFAULT_BACK_COLOR 1
117
118//a standard set of colors using black text on a white background.
119//defined in TerminalDisplay.cpp
120
121extern const ColorEntry base_color_table[TABLE_COLORS] KDE_NO_EXPORT;
122
123/* CharacterColor is a union of the various color spaces.
124
125 Assignment is as follows:
126
127 Type - Space - Values
128
129 0 - Undefined - u: 0, v:0 w:0
130 1 - Default - u: 0..1 v:intense w:0
131 2 - System - u: 0..7 v:intense w:0
132 3 - Index(256) - u: 16..255 v:0 w:0
133 4 - RGB - u: 0..255 v:0..256 w:0..256
134
135 Default colour space has two separate colours, namely
136 default foreground and default background colour.
137*/
138
139#define COLOR_SPACE_UNDEFINED 0
140#define COLOR_SPACE_DEFAULT 1
141#define COLOR_SPACE_SYSTEM 2
142#define COLOR_SPACE_256 3
143#define COLOR_SPACE_RGB 4
144
145/**
146 * Describes the color of a single character in the terminal.
147 */
148class CharacterColor
149{
150 friend class Character;
151
152public:
153 /** Constructs a new CharacterColor whoose color and color space are undefined. */
154 CharacterColor()
155 : _colorSpace(COLOR_SPACE_UNDEFINED),
156 _u(0),
157 _v(0),
158 _w(0)
159 {}
160
161 /**
162 * Constructs a new CharacterColor using the specified @p colorSpace and with
163 * color value @p co
164 *
165 * The meaning of @p co depends on the @p colorSpace used.
166 *
167 * TODO : Document how @p co relates to @p colorSpace
168 *
169 * TODO : Add documentation about available color spaces.
170 */
171 CharacterColor(quint8 colorSpace, int co)
172 : _colorSpace(colorSpace),
173 _u(0),
174 _v(0),
175 _w(0)
176 {
177 switch (colorSpace)
178 {
179 case COLOR_SPACE_DEFAULT:
180 _u = co & 1;
181 break;
182 case COLOR_SPACE_SYSTEM:
183 _u = co & 7;
184 _v = (co >> 3) & 1;
185 break;
186 case COLOR_SPACE_256:
187 _u = co & 255;
188 break;
189 case COLOR_SPACE_RGB:
190 _u = co >> 16;
191 _v = co >> 8;
192 _w = co;
193 break;
194 default:
195 _colorSpace = COLOR_SPACE_UNDEFINED;
196 }
197 }
198
199 /**
200 * Returns true if this character color entry is valid.
201 */
202 bool isValid() const
203 {
204 return _colorSpace != COLOR_SPACE_UNDEFINED;
205 }
206
207 /**
208 * Set the value of this color from a normal system color to the corresponding intensive
209 * system color if it's not already an intensive system color.
210 *
211 * This is only applicable if the color is using the COLOR_SPACE_DEFAULT or COLOR_SPACE_SYSTEM
212 * color spaces.
213 */
214 void setIntensive();
215
216 /**
217 * Returns the color within the specified color @p palette
218 *
219 * The @p palette is only used if this color is one of the 16 system colors, otherwise
220 * it is ignored.
221 */
222 QColor color(const ColorEntry* palette) const;
223
224 /**
225 * Compares two colors and returns true if they represent the same color value and
226 * use the same color space.
227 */
228 friend bool operator == (const CharacterColor& a, const CharacterColor& b);
229 /**
230 * Compares two colors and returns true if they represent different color values
231 * or use different color spaces.
232 */
233 friend bool operator != (const CharacterColor& a, const CharacterColor& b);
234
235private:
236 quint8 _colorSpace;
237
238 // bytes storing the character color
239 quint8 _u;
240 quint8 _v;
241 quint8 _w;
242};
243
244inline bool operator == (const CharacterColor& a, const CharacterColor& b)
245{
246 return a._colorSpace == b._colorSpace &&
247 a._u == b._u &&
248 a._v == b._v &&
249 a._w == b._w;
250}
251inline bool operator != (const CharacterColor& a, const CharacterColor& b)
252{
253 return !operator==(a,b);
254}
255
256inline const QColor color256(quint8 u, const ColorEntry* base)
257{
258 // 0.. 16: system colors
259 if (u < 8) return base[u+2 ].color;
260 u -= 8;
261 if (u < 8) return base[u+2+BASE_COLORS].color;
262 u -= 8;
263
264 // 16..231: 6x6x6 rgb color cube
265 if (u < 216) return QColor(((u/36)%6) ? (40*((u/36)%6)+55) : 0,
266 ((u/ 6)%6) ? (40*((u/ 6)%6)+55) : 0,
267 ((u/ 1)%6) ? (40*((u/ 1)%6)+55) : 0);
268 u -= 216;
269
270 // 232..255: gray, leaving out black and white
271 int gray = u*10+8; return QColor(gray,gray,gray);
272}
273
274inline QColor CharacterColor::color(const ColorEntry* base) const
275{
276 switch (_colorSpace)
277 {
278 case COLOR_SPACE_DEFAULT: return base[_u+0+(_v?BASE_COLORS:0)].color;
279 case COLOR_SPACE_SYSTEM: return base[_u+2+(_v?BASE_COLORS:0)].color;
280 case COLOR_SPACE_256: return color256(_u,base);
281 case COLOR_SPACE_RGB: return QColor(_u,_v,_w);
282 case COLOR_SPACE_UNDEFINED: return QColor();
283 }
284
285 Q_ASSERT(false); // invalid color space
286
287 return QColor();
288}
289
290inline void CharacterColor::setIntensive()
291{
292 if (_colorSpace == COLOR_SPACE_SYSTEM || _colorSpace == COLOR_SPACE_DEFAULT)
293 {
294 _v = 1;
295 }
296}
297
298
299}
300
301#endif // CHARACTERCOLOR_H
302
303