Update list of wide characters
[centerim5.git] / cppconsui / ColorScheme.cpp
blob62c6dc01026840bdb214b4117b1e86c4f099962a
1 // Copyright (C) 2008 Mark Pustjens <pustjens@dds.nl>
2 // Copyright (C) 2010-2015 Petr Pavlu <setup@dagobah.cz>
3 //
4 // This file is part of CenterIM.
5 //
6 // CenterIM 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 2 of the License, or
9 // (at your option) any later version.
11 // CenterIM 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.
16 // You should have received a copy of the GNU General Public License
17 // along with CenterIM. If not, see <http://www.gnu.org/licenses/>.
19 /// @file
20 /// ColorScheme class implementation.
21 ///
22 /// @ingroup cppconsui
24 #include "ColorScheme.h"
26 #include "CoreManager.h"
28 #include "gettext.h"
29 #include <cassert>
30 #include <cctype>
31 #include <cerrno>
32 #include <cstdlib>
33 #include <cstring>
35 namespace CppConsUI {
37 int ColorScheme::getAttributes(
38 int scheme, int property, int subproperty, int *out_attrs, Error &error)
40 assert(out_attrs != nullptr);
42 PropertyPair property_pair(property, subproperty);
43 Schemes::const_iterator i;
44 Properties::const_iterator j;
45 if ((i = schemes_.find(scheme)) != schemes_.end() &&
46 (j = i->second.find(property_pair)) != i->second.end()) {
47 Color c = j->second;
48 if (getColorPair(c, out_attrs, error) != 0)
49 return error.getCode();
50 *out_attrs |= c.attrs;
51 #ifdef SAVE_COLOR_PAIRS
52 // Save updated color in case it got inverted.
53 schemes_[scheme][property_pair] = c;
54 #endif // SAVE_COLOR_PAIRS
55 return 0;
58 *out_attrs = 0;
59 return 0;
62 #ifdef SAVE_COLOR_PAIRS
63 int ColorScheme::getColorPair(Color &c, int *out_attrs, Error &error)
64 #else
65 int ColorScheme::getColorPair(const Color &c, int *out_attrs, Error &error)
66 #endif // SAVE_COLOR_PAIRS
68 assert(out_attrs != nullptr);
70 ColorPairs::const_iterator i;
71 int fg = c.foreground;
72 int bg = c.background;
73 ColorPair color_pair(fg, bg);
75 // Check if the pair already exists.
76 if ((i = pairs_.find(color_pair)) != pairs_.end()) {
77 *out_attrs = i->second;
78 return 0;
81 #ifdef SAVE_COLOR_PAIRS
82 // Check if the inverse pairs exists.
83 if ((i = pairs_.find(color_pair)) != pairs_.end()) {
84 // If the inverse pair exists, use that one and flip the REVERSE bit.
85 c.foreground = bg;
86 c.background = fg;
87 c.out_attrs ^= Curses::Attr::REVERSE;
88 *out_attrs = i->second;
89 return 0;
91 #endif // SAVE_COLOR_PAIRS
93 // Add a new color pair to the palette.
94 if (Curses::initColorPair(pairs_.size() + 1, fg, bg, out_attrs, error) != 0)
95 return error.getCode();
97 pairs_[color_pair] = *out_attrs;
98 return 0;
101 bool ColorScheme::setAttributes(int scheme, int property, int foreground,
102 int background, int attrs, bool overwrite)
104 return setAttributesExt(
105 scheme, property, 0, foreground, background, attrs, overwrite);
108 bool ColorScheme::setAttributesExt(int scheme, int property, int subproperty,
109 int foreground, int background, int attrs, bool overwrite)
111 PropertyPair property_pair(property, subproperty);
112 Schemes::const_iterator i;
113 if (!overwrite && (i = schemes_.find(scheme)) != schemes_.end() &&
114 i->second.find(property_pair) != i->second.end())
115 return false;
117 schemes_[scheme][property_pair] = Color(foreground, background, attrs);
118 return true;
121 void ColorScheme::freeScheme(int scheme)
123 Schemes::const_iterator i = schemes_.find(scheme);
124 if (i == schemes_.end())
125 return;
127 schemes_.erase(scheme);
130 void ColorScheme::clear()
132 schemes_.clear();
133 pairs_.clear();
136 const char *ColorScheme::propertyToWidgetName(int property)
138 switch (static_cast<Property>(property)) {
139 case PROPERTY_BUTTON_FOCUS:
140 case PROPERTY_BUTTON_NORMAL:
141 return "button";
142 case PROPERTY_CHECKBOX_FOCUS:
143 case PROPERTY_CHECKBOX_NORMAL:
144 return "checkbox";
145 case PROPERTY_CONTAINER_BACKGROUND:
146 return "container";
147 case PROPERTY_HORIZONTALLINE_LINE:
148 return "horizontalline";
149 case PROPERTY_LABEL_TEXT:
150 return "label";
151 case PROPERTY_PANEL_LINE:
152 case PROPERTY_PANEL_TITLE:
153 return "panel";
154 case PROPERTY_TEXTEDIT_TEXT:
155 return "textedit";
156 case PROPERTY_TEXTVIEW_TEXT:
157 case PROPERTY_TEXTVIEW_SCROLLBAR:
158 return "textview";
159 case PROPERTY_VERTICALLINE_LINE:
160 return "verticalline";
161 case PROPERTY_TREEVIEW_LINE:
162 return "treeview";
164 return nullptr;
167 const char *ColorScheme::propertyToPropertyName(int property)
169 switch (static_cast<Property>(property)) {
170 case PROPERTY_BUTTON_FOCUS:
171 case PROPERTY_CHECKBOX_FOCUS:
172 return "focus";
173 case PROPERTY_BUTTON_NORMAL:
174 case PROPERTY_CHECKBOX_NORMAL:
175 return "normal";
176 case PROPERTY_CONTAINER_BACKGROUND:
177 return "background";
178 case PROPERTY_HORIZONTALLINE_LINE:
179 case PROPERTY_PANEL_LINE:
180 case PROPERTY_VERTICALLINE_LINE:
181 case PROPERTY_TREEVIEW_LINE:
182 return "line";
183 case PROPERTY_LABEL_TEXT:
184 case PROPERTY_TEXTEDIT_TEXT:
185 case PROPERTY_TEXTVIEW_TEXT:
186 return "text";
187 case PROPERTY_PANEL_TITLE:
188 return "title";
189 case PROPERTY_TEXTVIEW_SCROLLBAR:
190 return "scrollbar";
192 return nullptr;
195 ColorScheme::PropertyConversionResult ColorScheme::stringPairToPropertyPair(
196 const char *widget, const char *property, int *out_property,
197 int *out_subproperty)
199 assert(out_property != nullptr);
200 assert(out_subproperty != nullptr);
202 *out_subproperty = 0;
204 if (std::strcmp(widget, "button") == 0) {
205 if (std::strcmp(property, "focus") == 0) {
206 *out_property = PROPERTY_BUTTON_FOCUS;
207 return CONVERSION_SUCCESS;
209 if (std::strcmp(property, "normal") == 0) {
210 *out_property = PROPERTY_BUTTON_NORMAL;
211 return CONVERSION_SUCCESS;
213 return CONVERSION_ERROR_PROPERTY;
215 else if (std::strcmp(widget, "checkbox") == 0) {
216 if (std::strcmp(property, "focus") == 0) {
217 *out_property = PROPERTY_CHECKBOX_FOCUS;
218 return CONVERSION_SUCCESS;
220 if (std::strcmp(property, "normal") == 0) {
221 *out_property = PROPERTY_CHECKBOX_NORMAL;
222 return CONVERSION_SUCCESS;
224 return CONVERSION_ERROR_PROPERTY;
226 else if (std::strcmp(widget, "container") == 0) {
227 if (std::strcmp(property, "background") == 0) {
228 *out_property = PROPERTY_CONTAINER_BACKGROUND;
229 return CONVERSION_SUCCESS;
231 return CONVERSION_ERROR_PROPERTY;
233 else if (std::strcmp(widget, "horizontalline") == 0) {
234 if (std::strcmp(property, "line") == 0) {
235 *out_property = PROPERTY_HORIZONTALLINE_LINE;
236 return CONVERSION_SUCCESS;
238 return CONVERSION_ERROR_PROPERTY;
240 else if (std::strcmp(widget, "label") == 0) {
241 if (std::strcmp(property, "text") == 0) {
242 *out_property = PROPERTY_LABEL_TEXT;
243 return CONVERSION_SUCCESS;
245 return CONVERSION_ERROR_PROPERTY;
247 else if (std::strcmp(widget, "panel") == 0) {
248 if (std::strcmp(property, "line") == 0) {
249 *out_property = PROPERTY_PANEL_LINE;
250 return CONVERSION_SUCCESS;
252 if (std::strcmp(property, "title") == 0) {
253 *out_property = PROPERTY_PANEL_TITLE;
254 return CONVERSION_SUCCESS;
256 return CONVERSION_ERROR_PROPERTY;
258 else if (std::strcmp(widget, "textedit") == 0) {
259 if (std::strcmp(property, "text") == 0) {
260 *out_property = PROPERTY_TEXTEDIT_TEXT;
261 return CONVERSION_SUCCESS;
263 return CONVERSION_ERROR_PROPERTY;
265 else if (std::strcmp(widget, "textview") == 0) {
266 if (std::strcmp(property, "text") == 0) {
267 *out_property = PROPERTY_TEXTVIEW_TEXT;
268 return CONVERSION_SUCCESS;
270 if (std::strcmp(property, "scrollbar") == 0) {
271 *out_property = PROPERTY_TEXTVIEW_SCROLLBAR;
272 return CONVERSION_SUCCESS;
275 // Handle text_<number> and color<number> properties. The latter one is
276 // recognized only for backward compatibility.
277 if (std::strncmp(property, "text_", 5) != 0 &&
278 std::strncmp(property, "color", 5) != 0)
279 return CONVERSION_ERROR_PROPERTY;
280 property += 5;
282 if (!std::isdigit((unsigned char)*property))
283 return CONVERSION_ERROR_PROPERTY;
285 char *endptr;
286 errno = 0;
287 long i = std::strtol(property, &endptr, 10);
288 assert(i >= 0);
289 if (*endptr != '\0' || errno == ERANGE || i > INT_MAX)
290 return CONVERSION_ERROR_PROPERTY;
292 *out_property = PROPERTY_TEXTVIEW_TEXT;
293 *out_subproperty = i;
294 return CONVERSION_SUCCESS;
296 else if (std::strcmp(widget, "verticalline") == 0) {
297 if (std::strcmp(property, "line") == 0) {
298 *out_property = PROPERTY_VERTICALLINE_LINE;
299 return CONVERSION_SUCCESS;
302 else if (std::strcmp(widget, "treeview") == 0) {
303 if (std::strcmp(property, "line") == 0) {
304 *out_property = PROPERTY_TREEVIEW_LINE;
305 return CONVERSION_SUCCESS;
309 return CONVERSION_ERROR_WIDGET;
312 } // namespace CppConsUI
314 // vim: set tabstop=2 shiftwidth=2 textwidth=80 expandtab: