]> git.lyx.org Git - lyx.git/blob - src/Color.cpp
* src/LyXRC.{cpp,h}:
[lyx.git] / src / Color.cpp
1 /**
2  * \file Color.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author Lars Gullik Bjønnes
8  * \author Matthias Ettrich
9  * \author Jean-Marc Lasgouttes
10  * \author John Levon
11  * \author André Pönitz
12  * \author Martin Vermeer
13  *
14  * Full author contact details are available in file CREDITS.
15  */
16
17 #include <config.h>
18
19 #include "debug.h"
20 #include "gettext.h"
21 #include "Color.h"
22
23 #include "support/lstrings.h"
24
25 #include <map>
26 #include <cmath>
27 #include <sstream>
28 #include <iomanip>
29
30
31 #ifndef CXX_GLOBAL_CSTD
32 using std::floor;
33 #endif
34
35 using std::max;
36 using std::min;
37 using std::setw;
38
39 using std::istringstream;
40 using std::ostringstream;
41 using std::string;
42 using std::endl;
43
44 namespace lyx {
45
46 using support::compare_ascii_no_case;
47 using support::ascii_lowercase;
48
49 namespace {
50
51 struct ColorEntry {
52         ColorCode lcolor;
53         char const * guiname;
54         char const * latexname;
55         char const * x11name;
56         char const * lyxname;
57 };
58
59 int const nohue = -1;
60
61 int hexstrToInt(string const & str)
62 {
63         int val = 0;
64         istringstream is(str);
65         is >> std::setbase(16) >> val;
66         return val;
67 }
68
69 } // namespace anon
70
71
72 /////////////////////////////////////////////////////////////////////
73 //
74 // RGBColor
75 //
76 /////////////////////////////////////////////////////////////////////
77
78
79 string const X11hexname(RGBColor const & col)
80 {
81         ostringstream ostr;
82
83         ostr << '#' << std::setbase(16) << std::setfill('0')
84              << setw(2) << col.r
85              << setw(2) << col.g
86              << setw(2) << col.b;
87
88         return ostr.str();
89 }
90
91
92 RGBColor::RGBColor(string const & x11hexname)
93         : r(0), g(0), b(0)
94 {
95         BOOST_ASSERT(x11hexname.size() == 7 && x11hexname[0] == '#');
96         r = hexstrToInt(x11hexname.substr(1,2));
97         g = hexstrToInt(x11hexname.substr(3,2));
98         b = hexstrToInt(x11hexname.substr(5,2));
99 }
100
101
102 /////////////////////////////////////////////////////////////////////
103 //
104 // Color::Pimpl
105 //
106 /////////////////////////////////////////////////////////////////////
107
108 class Color::Pimpl {
109 public:
110         ///
111         class information {
112         public:
113                 /// the name as it appears in the GUI
114                 string guiname;
115                 /// the name used in LaTeX
116                 string latexname;
117                 /// the name for X11
118                 string x11name;
119                 /// the name for LyX
120                 string lyxname;
121         };
122
123         /// initialise a color entry
124         void fill(ColorEntry const & entry)
125         {
126                 information in;
127                 in.lyxname   = entry.lyxname;
128                 in.latexname = entry.latexname;
129                 in.x11name   = entry.x11name;
130                 in.guiname   = entry.guiname;
131                 infotab[entry.lcolor] = in;
132                 lyxcolors[entry.lyxname] = entry.lcolor;
133                 latexcolors[entry.latexname] = entry.lcolor;
134         }
135
136         ///
137         typedef std::map<ColorCode, information> InfoTab;
138         /// the table of color information
139         InfoTab infotab;
140
141         typedef std::map<string, ColorCode> Transform;
142         /// the transform between LyX color name string and integer code.
143         Transform lyxcolors;
144         /// the transform between LaTeX color name string and integer code.
145         Transform latexcolors;
146
147 };
148
149
150 Color::Color()
151         : pimpl_(new Pimpl)
152 {
153         //  ColorCode, gui, latex, x11, lyx
154         static ColorEntry const items[] = {
155         { Color_none, N_("none"), "none", "black", "none" },
156         { Color_black, N_("black"), "black", "black", "black" },
157         { Color_white, N_("white"), "white", "white", "white" },
158         { Color_red, N_("red"), "red", "red", "red" },
159         { Color_green, N_("green"), "green", "green", "green" },
160         { Color_blue, N_("blue"), "blue", "blue", "blue" },
161         { Color_cyan, N_("cyan"), "cyan", "cyan", "cyan" },
162         { Color_magenta, N_("magenta"), "magenta", "magenta", "magenta" },
163         { Color_yellow, N_("yellow"), "yellow", "yellow", "yellow" },
164         { Color_cursor, N_("cursor"), "cursor", "black", "cursor" },
165         { Color_background, N_("background"), "background", "linen", "background" },
166         { Color_foreground, N_("text"), "foreground", "black", "foreground" },
167         { Color_selection, N_("selection"), "selection", "LightBlue", "selection" },
168         { Color_latex, N_("LaTeX text"), "latex", "DarkRed", "latex" },
169         { Color_preview, N_("previewed snippet"), "preview", "black", "preview" },
170         { Color_note, N_("note"), "note", "blue", "note" },
171         { Color_notebg, N_("note background"), "notebg", "yellow", "notebg" },
172         { Color_comment, N_("comment"), "comment", "magenta", "comment" },
173         { Color_commentbg, N_("comment background"), "commentbg", "linen", "commentbg" },
174         { Color_greyedout, N_("greyedout inset"), "greyedout", "red", "greyedout" },
175         { Color_greyedoutbg, N_("greyedout inset background"), "greyedoutbg", "linen", "greyedoutbg" },
176         { Color_shadedbg, N_("shaded box"), "shaded", "#ff0000", "shaded" },
177         { Color_depthbar, N_("depth bar"), "depthbar", "IndianRed", "depthbar" },
178         { Color_language, N_("language"), "language", "Blue", "language" },
179         { Color_command, N_("command inset"), "command", "black", "command" },
180         { Color_commandbg, N_("command inset background"), "commandbg", "azure", "commandbg" },
181         { Color_commandframe, N_("command inset frame"), "commandframe", "black", "commandframe" },
182         { Color_special, N_("special character"), "special", "RoyalBlue", "special" },
183         { Color_math, N_("math"), "math", "DarkBlue", "math" },
184         { Color_mathbg, N_("math background"), "mathbg", "linen", "mathbg" },
185         { Color_graphicsbg, N_("graphics background"), "graphicsbg", "linen", "graphicsbg" },
186         { Color_mathmacrobg, N_("Math macro background"), "mathmacrobg", "linen", "mathmacrobg" },
187         { Color_mathframe, N_("math frame"), "mathframe", "Magenta", "mathframe" },
188         { Color_mathcorners, N_("math corners"), "mathcorners", "linen", "mathcorners" },
189         { Color_mathline, N_("math line"), "mathline", "Blue", "mathline" },
190         { Color_mathmacrobg, N_("Math macro background"), "mathmacrobg", "#ede2d8", "mathmacrobg" },
191         { Color_mathmacrohoverbg, N_("Math macro hovered background"), "mathmacrohoverbg", "#cdc3b8", "mathmacrohoverbg" },
192         { Color_mathmacrolabel, N_("Math macro label"), "mathmacrolabel", "#a19992", "mathmacrolabel" },
193         { Color_mathmacroframe, N_("Math macro frame"), "mathmacroframe", "#ede2d8", "mathmacroframe" },
194         { Color_mathmacroblend, N_("Math macro blended out"), "mathmacroblend", "#000000", "mathmacroblend" },
195         { Color_captionframe, N_("caption frame"), "captionframe", "DarkRed", "captionframe" },
196         { Color_collapsable, N_("collapsable inset text"), "collapsable", "DarkRed", "collapsable" },
197         { Color_collapsableframe, N_("collapsable inset frame"), "collapsableframe", "IndianRed", "collapsableframe" },
198         { Color_insetbg, N_("inset background"), "insetbg", "grey80", "insetbg" },
199         { Color_insetframe, N_("inset frame"), "insetframe", "IndianRed", "insetframe" },
200         { Color_error, N_("LaTeX error"), "error", "Red", "error" },
201         { Color_eolmarker, N_("end-of-line marker"), "eolmarker", "Brown", "eolmarker" },
202         { Color_appendix, N_("appendix marker"), "appendix", "Brown", "appendix" },
203         { Color_changebar, N_("change bar"), "changebar", "Blue", "changebar" },
204         { Color_deletedtext, N_("Deleted text"), "deletedtext", "#ff0000", "deletedtext" },
205         { Color_addedtext, N_("Added text"), "addedtext", "#0000ff", "addedtext" },
206         { Color_added_space, N_("added space markers"), "added_space", "Brown", "added_space" },
207         { Color_topline, N_("top/bottom line"), "topline", "Brown", "topline" },
208         { Color_tabularline, N_("table line"), "tabularline", "black", "tabularline" },
209         { Color_tabularonoffline, N_("table on/off line"), "tabularonoffline",
210              "LightSteelBlue", "tabularonoffline" },
211         { Color_bottomarea, N_("bottom area"), "bottomarea", "grey40", "bottomarea" },
212         { Color_pagebreak, N_("page break"), "pagebreak", "RoyalBlue", "pagebreak" },
213         { Color_buttonframe, N_("frame of button"), "buttonframe", "#dcd2c8", "buttonframe" },
214         { Color_buttonbg, N_("button background"), "buttonbg", "#dcd2c8", "buttonbg" },
215         { Color_buttonhoverbg, N_("button background under focus"), "buttonhoverbg", "#C7C7CA", "buttonhoverbg" },
216         { Color_inherit, N_("inherit"), "inherit", "black", "inherit" },
217         { Color_ignore, N_("ignore"), "ignore", "black", "ignore" },
218         { Color_ignore, 0, 0, 0, 0 }
219         };
220
221         for (int i = 0; items[i].guiname; ++i)
222                 pimpl_->fill(items[i]);
223 }
224
225
226 Color::Color(Color const & c)
227         : pimpl_(new Pimpl(*c.pimpl_))
228 {}
229
230
231 Color::~Color()
232 {}
233
234
235 Color & Color::operator=(Color tmp)
236 {
237         boost::swap(pimpl_, tmp.pimpl_);
238         return *this;
239 }
240
241
242 docstring const Color::getGUIName(ColorCode c) const
243 {
244         Pimpl::InfoTab::const_iterator it = pimpl_->infotab.find(c);
245         if (it != pimpl_->infotab.end())
246                 return _(it->second.guiname);
247         return from_ascii("none");
248 }
249
250
251 string const Color::getX11Name(ColorCode c) const
252 {
253         Pimpl::InfoTab::const_iterator it = pimpl_->infotab.find(c);
254         if (it != pimpl_->infotab.end())
255                 return it->second.x11name;
256
257         lyxerr << "LyX internal error: Missing color"
258                   " entry in Color.cpp for " << c << '\n'
259                << "Using black." << endl;
260         return "black";
261 }
262
263
264 string const Color::getLaTeXName(ColorCode c) const
265 {
266         Pimpl::InfoTab::const_iterator it = pimpl_->infotab.find(c);
267         if (it != pimpl_->infotab.end())
268                 return it->second.latexname;
269         return "black";
270 }
271
272
273 string const Color::getLyXName(ColorCode c) const
274 {
275         Pimpl::InfoTab::const_iterator it = pimpl_->infotab.find(c);
276         if (it != pimpl_->infotab.end())
277                 return it->second.lyxname;
278         return "black";
279 }
280
281
282 bool Color::setColor(ColorCode col, string const & x11name)
283 {
284         Pimpl::InfoTab::iterator it = pimpl_->infotab.find(col);
285         if (it == pimpl_->infotab.end()) {
286                 lyxerr << "Color " << col << " not found in database."
287                        << std::endl;
288                 return false;
289         }
290
291         // "inherit" is returned for colors not in the database
292         // (and anyway should not be redefined)
293         if (col == Color_none || col == Color_inherit || col == Color_ignore) {
294                 lyxerr << "Color " << getLyXName(col)
295                        << " may not be redefined" << endl;
296                 return false;
297         }
298
299         it->second.x11name = x11name;
300         return true;
301 }
302
303
304 bool Color::setColor(string const & lyxname, string const &x11name)
305 {
306         string const lcname = ascii_lowercase(lyxname);
307         if (pimpl_->lyxcolors.find(lcname) == pimpl_->lyxcolors.end()) {
308                 LYXERR(Debug::GUI)
309                         << "Color::setColor: Unknown color \""
310                        << lyxname << '"' << endl;
311                 addColor(static_cast<ColorCode>(pimpl_->infotab.size()), lcname);
312         }
313
314         return setColor(pimpl_->lyxcolors[lcname], x11name);
315 }
316
317
318 void Color::addColor(ColorCode c, string const & lyxname) const
319 {
320         ColorEntry ce = { c, "", "", "", lyxname.c_str() };
321         pimpl_->fill(ce);
322 }
323
324
325 ColorCode Color::getFromLyXName(string const & lyxname) const
326 {
327         string const lcname = ascii_lowercase(lyxname);
328         if (pimpl_->lyxcolors.find(lcname) == pimpl_->lyxcolors.end()) {
329                 lyxerr << "Color::getFromLyXName: Unknown color \""
330                        << lyxname << '"' << endl;
331                 return Color_none;
332         }
333
334         return pimpl_->lyxcolors[lcname];
335 }
336
337
338 ColorCode Color::getFromLaTeXName(string const & latexname) const
339 {
340         if (pimpl_->latexcolors.find(latexname) == pimpl_->latexcolors.end()) {
341                 lyxerr << "Color::getFromLaTeXName: Unknown color \""
342                        << latexname << '"' << endl;
343                 return Color_none;
344         }
345
346         return pimpl_->latexcolors[latexname];
347 }
348
349
350 // The evil global Color instance
351 Color lcolor;
352 // An equally evil global system Color instance
353 Color system_lcolor;
354
355
356 } // namespace lyx