2 // "$Id: Fl_get_system_colors.cxx 7903 2010-11-28 21:06:39Z matt $"
4 // System color support for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 #include <FL/fl_draw.H>
32 #include <FL/fl_utf8.h>
36 #include <FL/Fl_Pixmap.H>
37 #include <FL/Fl_Tiled_Image.H>
40 #if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
41 // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs
42 // on Windows, which is supposed to be POSIX compliant...
43 # define putenv _putenv
44 #endif // WIN32 && !__CYGWIN__
46 static char fl_bg_set
= 0;
47 static char fl_bg2_set
= 0;
48 static char fl_fg_set
= 0;
51 Changes fl_color(FL_BACKGROUND_COLOR) to the given color,
52 and changes the gray ramp from 32 to 56 to black to white. These are
53 the colors used as backgrounds by almost all widgets and used to draw
54 the edges of all the boxtypes.
56 void Fl::background(uchar r
, uchar g
, uchar b
) {
59 // replace the gray ramp so that FL_GRAY is this color
60 if (!r
) r
= 1; else if (r
==255) r
= 254;
61 double powr
= log(r
/255.0)/log((FL_GRAY
-FL_GRAY_RAMP
)/(FL_NUM_GRAY
-1.0));
62 if (!g
) g
= 1; else if (g
==255) g
= 254;
63 double powg
= log(g
/255.0)/log((FL_GRAY
-FL_GRAY_RAMP
)/(FL_NUM_GRAY
-1.0));
64 if (!b
) b
= 1; else if (b
==255) b
= 254;
65 double powb
= log(b
/255.0)/log((FL_GRAY
-FL_GRAY_RAMP
)/(FL_NUM_GRAY
-1.0));
66 for (int i
= 0; i
< FL_NUM_GRAY
; i
++) {
67 double gray
= i
/(FL_NUM_GRAY
-1.0);
68 Fl::set_color(fl_gray_ramp(i
),
69 uchar(pow(gray
,powr
)*255+.5),
70 uchar(pow(gray
,powg
)*255+.5),
71 uchar(pow(gray
,powb
)*255+.5));
74 /** Changes fl_color(FL_FOREGROUND_COLOR). */
75 void Fl::foreground(uchar r
, uchar g
, uchar b
) {
78 Fl::set_color(FL_FOREGROUND_COLOR
,r
,g
,b
);
82 Changes the alternative background color. This color is used as a
83 background by Fl_Input and other text widgets.
84 <P>This call may change fl_color(FL_FOREGROUND_COLOR) if it
85 does not provide sufficient contrast to FL_BACKGROUND2_COLOR.
87 void Fl::background2(uchar r
, uchar g
, uchar b
) {
90 Fl::set_color(FL_BACKGROUND2_COLOR
,r
,g
,b
);
91 Fl::set_color(FL_FOREGROUND_COLOR
,
92 get_color(fl_contrast(FL_FOREGROUND_COLOR
,FL_BACKGROUND2_COLOR
)));
95 // these are set by Fl::args() and override any system colors:
96 const char *fl_fg
= NULL
;
97 const char *fl_bg
= NULL
;
98 const char *fl_bg2
= NULL
;
100 static void set_selection_color(uchar r
, uchar g
, uchar b
) {
101 Fl::set_color(FL_SELECTION_COLOR
,r
,g
,b
);
104 #if defined(WIN32) || defined(__APPLE__)
107 // simulation of XParseColor:
108 int fl_parse_color(const char* p
, uchar
& r
, uchar
& g
, uchar
& b
) {
112 const char *pattern
= 0;
114 case 1: pattern
= "%1x%1x%1x"; break;
115 case 2: pattern
= "%2x%2x%2x"; break;
116 case 3: pattern
= "%3x%3x%3x"; break;
117 case 4: pattern
= "%4x%4x%4x"; break;
120 int R
,G
,B
; if (sscanf(p
,pattern
,&R
,&G
,&B
) != 3) return 0;
122 case 1: R
*= 0x11; G
*= 0x11; B
*= 0x11; break;
123 case 3: R
>>= 4; G
>>= 4; B
>>= 4; break;
124 case 4: R
>>= 8; G
>>= 8; B
>>= 8; break;
126 r
= (uchar
)R
; g
= (uchar
)G
; b
= (uchar
)B
;
130 // Wrapper around XParseColor...
131 int fl_parse_color(const char* p
, uchar
& r
, uchar
& g
, uchar
& b
) {
133 if (!fl_display
) fl_open_display();
134 if (XParseColor(fl_display
, fl_colormap
, p
, &x
)) {
135 r
= (uchar
)(x
.red
>>8);
136 g
= (uchar
)(x
.green
>>8);
137 b
= (uchar
)(x
.blue
>>8);
141 #endif // WIN32 || __APPLE__
142 /** \fn Fl::get_system_colors()
143 Read the user preference colors from the system and use them to call
144 Fl::foreground(), Fl::background(), and
145 Fl::background2(). This is done by
146 Fl_Window::show(argc,argv) before applying the -fg and -bg
149 <P>On X this reads some common values from the Xdefaults database.
150 KDE users can set these values by running the "krdb" program, and
151 newer versions of KDE set this automatically if you check the "apply
152 style to other X programs" switch in their control panel.
156 getsyscolor(int what
, const char* arg
, void (*func
)(uchar
,uchar
,uchar
))
160 if (!fl_parse_color(arg
, r
,g
,b
))
161 Fl::error("Unknown color: %s", arg
);
165 DWORD x
= GetSysColor(what
);
166 func(uchar(x
&255), uchar(x
>>8), uchar(x
>>16));
170 void Fl::get_system_colors() {
171 if (!fl_bg2_set
) getsyscolor(COLOR_WINDOW
, fl_bg2
,Fl::background2
);
172 if (!fl_fg_set
) getsyscolor(COLOR_WINDOWTEXT
, fl_fg
, Fl::foreground
);
173 if (!fl_bg_set
) getsyscolor(COLOR_BTNFACE
, fl_bg
, Fl::background
);
174 getsyscolor(COLOR_HIGHLIGHT
, 0, set_selection_color
);
177 #elif defined(__APPLE__)
178 // MacOS X currently supports two color schemes - Blue and Graphite.
179 // Since we aren't emulating the Aqua interface (even if Apple would
180 // let us), we use some defaults that are similar to both. The
181 // Fl::scheme("plastic") color/box scheme provides a usable Aqua-like
183 void Fl::get_system_colors()
187 if (!fl_bg2_set
) background2(0xff, 0xff, 0xff);
188 if (!fl_fg_set
) foreground(0, 0, 0);
189 if (!fl_bg_set
) background(0xd8, 0xd8, 0xd8);
192 // this would be the correct code, but it does not run on all versions
193 // of OS X. Also, setting a bright selection color would require
194 // some updates in Fl_Adjuster and Fl_Help_Browser
197 err
= GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor
, 24, true, &c
);
199 set_selection_color(0x00, 0x00, 0x80);
201 set_selection_color(c
.red
, c
.green
, c
.blue
);
203 set_selection_color(0x00, 0x00, 0x80);
208 // Read colors that KDE writes to the xrdb database.
210 // XGetDefault does not do the expected thing: it does not like
211 // periods in either word. Therefore it cannot match class.Text.background.
212 // However *.Text.background is matched by pretending the program is "Text".
213 // But this will also match *.background if there is no *.Text.background
214 // entry, requiring users to put in both (unless they want the text fields
215 // the same color as the windows).
218 getsyscolor(const char *key1
, const char* key2
, const char *arg
, const char *defarg
, void (*func
)(uchar
,uchar
,uchar
))
221 arg
= XGetDefault(fl_display
, key1
, key2
);
222 if (!arg
) arg
= defarg
;
225 if (!XParseColor(fl_display
, fl_colormap
, arg
, &x
))
226 Fl::error("Unknown color: %s", arg
);
228 func(x
.red
>>8, x
.green
>>8, x
.blue
>>8);
231 void Fl::get_system_colors()
234 const char* key1
= 0;
235 if (Fl::first_window()) key1
= Fl::first_window()->xclass();
236 if (!key1
) key1
= "fltk";
237 if (!fl_bg2_set
) getsyscolor("Text","background", fl_bg2
, "#ffffff", Fl::background2
);
238 if (!fl_fg_set
) getsyscolor(key1
, "foreground", fl_fg
, "#000000", Fl::foreground
);
239 if (!fl_bg_set
) getsyscolor(key1
, "background", fl_bg
, "#c0c0c0", Fl::background
);
240 getsyscolor("Text", "selectBackground", 0, "#000080", set_selection_color
);
246 //// Simple implementation of 2.0 Fl::scheme() interface...
247 #define D1 BORDER_WIDTH
248 #define D2 (BORDER_WIDTH+BORDER_WIDTH)
250 extern void fl_up_box(int, int, int, int, Fl_Color
);
251 extern void fl_down_box(int, int, int, int, Fl_Color
);
252 extern void fl_thin_up_box(int, int, int, int, Fl_Color
);
253 extern void fl_thin_down_box(int, int, int, int, Fl_Color
);
254 extern void fl_round_up_box(int, int, int, int, Fl_Color
);
255 extern void fl_round_down_box(int, int, int, int, Fl_Color
);
257 extern void fl_up_frame(int, int, int, int, Fl_Color
);
258 extern void fl_down_frame(int, int, int, int, Fl_Color
);
259 extern void fl_thin_up_frame(int, int, int, int, Fl_Color
);
260 extern void fl_thin_down_frame(int, int, int, int, Fl_Color
);
263 const char *Fl::scheme_
= (const char *)0; // current scheme
264 Fl_Image
*Fl::scheme_bg_
= (Fl_Image
*)0; // current background image for the scheme
267 static Fl_Pixmap
tile(tile_xpm
);
269 int Fl::scheme(const char *s
) {
271 printf( "Setting Fl::scheme() is obsolete" );
272 // Load the scheme...
273 return reload_scheme();
276 int Fl::reload_scheme() {
279 set_boxtype(FL_UP_FRAME
, fl_up_frame
, D1
, D1
, D2
, D2
);
280 set_boxtype(FL_DOWN_FRAME
, fl_down_frame
, D1
, D1
, D2
, D2
);
281 set_boxtype(FL_THIN_UP_FRAME
, fl_thin_up_frame
, 1, 1, 2, 2);
282 set_boxtype(FL_THIN_DOWN_FRAME
, fl_thin_down_frame
, 1, 1, 2, 2);
284 set_boxtype(FL_UP_BOX
, fl_up_box
, D1
, D1
, D2
, D2
);
285 set_boxtype(FL_DOWN_BOX
, fl_down_box
, D1
, D1
, D2
, D2
);
286 set_boxtype(FL_THIN_UP_BOX
, fl_thin_up_box
, 1, 1, 2, 2);
287 set_boxtype(FL_THIN_DOWN_BOX
, fl_thin_down_box
, 1, 1, 2, 2);
288 set_boxtype(_FL_ROUND_UP_BOX
, fl_round_up_box
, 3, 3, 6, 6);
289 set_boxtype(_FL_ROUND_DOWN_BOX
, fl_round_down_box
, 3, 3, 6, 6);
291 // Use standard size scrollbars...
292 Fl::scrollbar_size(16);
294 // Set (or clear) the background tile for all windows...
295 for (win
= first_window(); win
; win
= next_window(win
)) {
296 // win->labeltype(scheme_bg_ ? FL_NORMAL_LABEL : FL_NO_LABEL);
297 // win->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP | FL_ALIGN_IMAGE_BACKDROP );
298 win
->align( FL_ALIGN_IMAGE_BACKDROP
);
299 win
->image(scheme_bg_
);
308 // End of "$Id: Fl_get_system_colors.cxx 7903 2010-11-28 21:06:39Z matt $".