]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
new default color scheme based on the GNOME stock icon palette. (#80691,
[~andy/gtk] / gtk / gtkstyle.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "gtkgc.h"
31 #include "gtkrc.h"
32 #include "gtkspinbutton.h"
33 #include "gtkstyle.h"
34 #include "gtkwidget.h"
35 #include "gtkthemes.h"
36 #include "gtkiconfactory.h"
37 #include "gtksettings.h"        /* _gtk_settings_parse_convert() */
38
39 #define LIGHTNESS_MULT  1.3
40 #define DARKNESS_MULT   0.7
41
42 /* --- typedefs & structures --- */
43 typedef struct {
44   GType       widget_type;
45   GParamSpec *pspec;
46   GValue      value;
47 } PropertyValue;
48
49 /* --- prototypes --- */
50 static void      gtk_style_init                 (GtkStyle       *style);
51 static void      gtk_style_class_init           (GtkStyleClass  *klass);
52 static void      gtk_style_finalize             (GObject        *object);
53 static void      gtk_style_realize              (GtkStyle       *style,
54                                                  GdkColormap    *colormap);
55 static void      gtk_style_real_realize        (GtkStyle        *style);
56 static void      gtk_style_real_unrealize      (GtkStyle        *style);
57 static void      gtk_style_real_copy           (GtkStyle        *style,
58                                                 GtkStyle        *src);
59 static void      gtk_style_real_set_background (GtkStyle        *style,
60                                                 GdkWindow       *window,
61                                                 GtkStateType     state_type);
62 static GtkStyle *gtk_style_real_clone          (GtkStyle        *style);
63 static void      gtk_style_real_init_from_rc   (GtkStyle        *style,
64                                                 GtkRcStyle      *rc_style);
65 static GdkPixbuf *gtk_default_render_icon      (GtkStyle            *style,
66                                                 const GtkIconSource *source,
67                                                 GtkTextDirection     direction,
68                                                 GtkStateType         state,
69                                                 GtkIconSize          size,
70                                                 GtkWidget           *widget,
71                                                 const gchar         *detail);
72 static void gtk_default_draw_hline      (GtkStyle        *style,
73                                          GdkWindow       *window,
74                                          GtkStateType     state_type,
75                                          GdkRectangle    *area,
76                                          GtkWidget       *widget,
77                                          const gchar     *detail,
78                                          gint             x1,
79                                          gint             x2,
80                                          gint             y);
81 static void gtk_default_draw_vline      (GtkStyle        *style,
82                                          GdkWindow       *window,
83                                          GtkStateType     state_type,
84                                          GdkRectangle    *area,
85                                          GtkWidget       *widget,
86                                          const gchar     *detail,
87                                          gint             y1,
88                                          gint             y2,
89                                          gint             x);
90 static void gtk_default_draw_shadow     (GtkStyle        *style,
91                                          GdkWindow       *window,
92                                          GtkStateType     state_type,
93                                          GtkShadowType    shadow_type,
94                                          GdkRectangle    *area,
95                                          GtkWidget       *widget,
96                                          const gchar     *detail,
97                                          gint             x,
98                                          gint             y,
99                                          gint             width,
100                                          gint             height);
101 static void gtk_default_draw_polygon    (GtkStyle        *style,
102                                          GdkWindow       *window,
103                                          GtkStateType     state_type,
104                                          GtkShadowType    shadow_type,
105                                          GdkRectangle    *area,
106                                          GtkWidget       *widget,
107                                          const gchar     *detail,
108                                          GdkPoint        *points,
109                                          gint             npoints,
110                                          gboolean         fill);
111 static void gtk_default_draw_arrow      (GtkStyle        *style,
112                                          GdkWindow       *window,
113                                          GtkStateType     state_type,
114                                          GtkShadowType    shadow_type,
115                                          GdkRectangle    *area,
116                                          GtkWidget       *widget,
117                                          const gchar     *detail,
118                                          GtkArrowType     arrow_type,
119                                          gboolean         fill,
120                                          gint             x,
121                                          gint             y,
122                                          gint             width,
123                                          gint             height);
124 static void gtk_default_draw_diamond    (GtkStyle        *style,
125                                          GdkWindow       *window,
126                                          GtkStateType     state_type,
127                                          GtkShadowType    shadow_type,
128                                          GdkRectangle    *area,
129                                          GtkWidget       *widget,
130                                          const gchar     *detail,
131                                          gint             x,
132                                          gint             y,
133                                          gint             width,
134                                          gint             height);
135 static void gtk_default_draw_string     (GtkStyle        *style,
136                                          GdkWindow       *window,
137                                          GtkStateType     state_type,
138                                          GdkRectangle    *area,
139                                          GtkWidget       *widget,
140                                          const gchar     *detail,
141                                          gint             x,
142                                          gint             y,
143                                          const gchar     *string);
144 static void gtk_default_draw_box        (GtkStyle        *style,
145                                          GdkWindow       *window,
146                                          GtkStateType     state_type,
147                                          GtkShadowType    shadow_type,
148                                          GdkRectangle    *area,
149                                          GtkWidget       *widget,
150                                          const gchar     *detail,
151                                          gint             x,
152                                          gint             y,
153                                          gint             width,
154                                          gint             height);
155 static void gtk_default_draw_flat_box   (GtkStyle        *style,
156                                          GdkWindow       *window,
157                                          GtkStateType     state_type,
158                                          GtkShadowType    shadow_type,
159                                          GdkRectangle    *area,
160                                          GtkWidget       *widget,
161                                          const gchar     *detail,
162                                          gint             x,
163                                          gint             y,
164                                          gint             width,
165                                          gint             height);
166 static void gtk_default_draw_check      (GtkStyle        *style,
167                                          GdkWindow       *window,
168                                          GtkStateType     state_type,
169                                          GtkShadowType    shadow_type,
170                                          GdkRectangle    *area,
171                                          GtkWidget       *widget,
172                                          const gchar     *detail,
173                                          gint             x,
174                                          gint             y,
175                                          gint             width,
176                                          gint             height);
177 static void gtk_default_draw_option     (GtkStyle        *style,
178                                          GdkWindow       *window,
179                                          GtkStateType     state_type,
180                                          GtkShadowType    shadow_type,
181                                          GdkRectangle    *area,
182                                          GtkWidget       *widget,
183                                          const gchar     *detail,
184                                          gint             x,
185                                          gint             y,
186                                          gint             width,
187                                          gint             height);
188 static void gtk_default_draw_tab        (GtkStyle        *style,
189                                          GdkWindow       *window,
190                                          GtkStateType     state_type,
191                                          GtkShadowType    shadow_type,
192                                          GdkRectangle    *area,
193                                          GtkWidget       *widget,
194                                          const gchar     *detail,
195                                          gint             x,
196                                          gint             y,
197                                          gint             width,
198                                          gint             height);
199 static void gtk_default_draw_shadow_gap (GtkStyle        *style,
200                                          GdkWindow       *window,
201                                          GtkStateType     state_type,
202                                          GtkShadowType    shadow_type,
203                                          GdkRectangle    *area,
204                                          GtkWidget       *widget,
205                                          const gchar     *detail,
206                                          gint             x,
207                                          gint             y,
208                                          gint             width,
209                                          gint             height,
210                                          GtkPositionType  gap_side,
211                                          gint             gap_x,
212                                          gint             gap_width);
213 static void gtk_default_draw_box_gap    (GtkStyle        *style,
214                                          GdkWindow       *window,
215                                          GtkStateType     state_type,
216                                          GtkShadowType    shadow_type,
217                                          GdkRectangle    *area,
218                                          GtkWidget       *widget,
219                                          const gchar     *detail,
220                                          gint             x,
221                                          gint             y,
222                                          gint             width,
223                                          gint             height,
224                                          GtkPositionType  gap_side,
225                                          gint             gap_x,
226                                          gint             gap_width);
227 static void gtk_default_draw_extension  (GtkStyle        *style,
228                                          GdkWindow       *window,
229                                          GtkStateType     state_type,
230                                          GtkShadowType    shadow_type,
231                                          GdkRectangle    *area,
232                                          GtkWidget       *widget,
233                                          const gchar     *detail,
234                                          gint             x,
235                                          gint             y,
236                                          gint             width,
237                                          gint             height,
238                                          GtkPositionType  gap_side);
239 static void gtk_default_draw_focus      (GtkStyle        *style,
240                                          GdkWindow       *window,
241                                          GtkStateType     state_type,
242                                          GdkRectangle    *area,
243                                          GtkWidget       *widget,
244                                          const gchar     *detail,
245                                          gint             x,
246                                          gint             y,
247                                          gint             width,
248                                          gint             height);
249 static void gtk_default_draw_slider     (GtkStyle        *style,
250                                          GdkWindow       *window,
251                                          GtkStateType     state_type,
252                                          GtkShadowType    shadow_type,
253                                          GdkRectangle    *area,
254                                          GtkWidget       *widget,
255                                          const gchar     *detail,
256                                          gint             x,
257                                          gint             y,
258                                          gint             width,
259                                          gint             height,
260                                          GtkOrientation   orientation);
261 static void gtk_default_draw_handle     (GtkStyle        *style,
262                                          GdkWindow       *window,
263                                          GtkStateType     state_type,
264                                          GtkShadowType    shadow_type,
265                                          GdkRectangle    *area,
266                                          GtkWidget       *widget,
267                                          const gchar     *detail,
268                                          gint             x,
269                                          gint             y,
270                                          gint             width,
271                                          gint             height,
272                                          GtkOrientation   orientation);
273 static void gtk_default_draw_expander   (GtkStyle        *style,
274                                          GdkWindow       *window,
275                                          GtkStateType     state_type,
276                                          GdkRectangle    *area,
277                                          GtkWidget       *widget,
278                                          const gchar     *detail,
279                                          gint             x,
280                                          gint             y,
281                                          GtkExpanderStyle expander_style);
282 static void gtk_default_draw_layout     (GtkStyle        *style,
283                                          GdkWindow       *window,
284                                          GtkStateType     state_type,
285                                          gboolean         use_text,
286                                          GdkRectangle    *area,
287                                          GtkWidget       *widget,
288                                          const gchar     *detail,
289                                          gint             x,
290                                          gint             y,
291                                          PangoLayout     *layout);
292 static void gtk_default_draw_resize_grip (GtkStyle       *style,
293                                           GdkWindow      *window,
294                                           GtkStateType    state_type,
295                                           GdkRectangle   *area,
296                                           GtkWidget      *widget,
297                                           const gchar    *detail,
298                                           GdkWindowEdge   edge,
299                                           gint            x,
300                                           gint            y,
301                                           gint            width,
302                                           gint            height);
303
304 static void gtk_style_shade             (GdkColor        *a,
305                                          GdkColor        *b,
306                                          gdouble          k);
307 static void rgb_to_hls                  (gdouble         *r,
308                                          gdouble         *g,
309                                          gdouble         *b);
310 static void hls_to_rgb                  (gdouble         *h,
311                                          gdouble         *l,
312                                          gdouble         *s);
313
314 static void style_unrealize_cursor_gcs (GtkStyle *style);
315
316 static GdkFont *gtk_style_get_font_internal (GtkStyle *style);
317
318 /*
319  * Data for default check and radio buttons
320  */
321
322 static GtkRequisition default_option_indicator_size = { 7, 13 };
323 static GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
324
325 #define INDICATOR_PART_SIZE 13
326
327 typedef enum {
328   CHECK_AA,
329   CHECK_BASE,
330   CHECK_BLACK,
331   CHECK_DARK,
332   CHECK_LIGHT,
333   CHECK_MID,
334   CHECK_TEXT,
335   CHECK_INCONSISTENT_TEXT,
336   RADIO_BASE,
337   RADIO_BLACK,
338   RADIO_DARK,
339   RADIO_LIGHT,
340   RADIO_MID,
341   RADIO_TEXT,
342   RADIO_INCONSISTENT_AA,
343   RADIO_INCONSISTENT_TEXT
344 } IndicatorPart;
345
346 /*
347  * Extracted from check-13.png, width=13, height=13
348  */
349 static const guchar check_black_bits[] = {
350   0x00,0x00,0xfe,0x0f,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
351   0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00};
352 static const guchar check_dark_bits[] = {
353   0xff,0x1f,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
354   0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00};
355 static const guchar check_mid_bits[] = {
356   0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
357   0x08,0x00,0x08,0x00,0x08,0x00,0x08,0xfc,0x0f,0x00,0x00,0x00,0x00};
358 static const guchar check_light_bits[] = {
359   0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
360   0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xfe,0x1f,0x00,0x00};
361 static const guchar check_text_bits[] = {
362   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x80,0x01,0x80,0x00,0x58,
363   0x00,0x60,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
364 static const guchar check_aa_bits[] = {
365   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x58,0x00,0xa0,
366   0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
367 static const guchar check_base_bits[] = {
368   0x00,0x00,0x00,0x00,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
369   0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0x00,0x00,0x00,0x00,0x00,0x00};
370
371 /*
372  * Extracted from check-13-inconsistent.png, width=13, height=13
373  */
374 static const guchar check_inconsistent_text_bits[] = {
375   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x03,0xf8,
376   0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
377 #if 0
378 /*
379  * check_inconsistent_aa_bits is currently not used, since it is all zeros.
380  */
381 static const guchar check_inconsistent_aa_bits[] = {
382   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
383   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
384 #endif
385
386 /*
387  * Extracted from radio-13.png, width=13, height=13
388  */
389 static const guchar radio_black_bits[] = {
390   0x00,0x00,0xf0,0x01,0x0c,0x02,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
391   0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x08};
392 static const guchar radio_dark_bits[] = {
393   0xf0,0x00,0x0c,0x02,0x02,0x04,0x02,0x04,0x01,0x08,0x01,0x08,0x01,0x08,0x01,
394   0x08,0x00,0x08,0x02,0x04,0x0c,0x06,0xf0,0x01,0x00,0x00,0x00,0x00};
395 static const guchar radio_mid_bits[] = {
396   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
397   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
398 static const guchar radio_light_bits[] = {
399   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,
400   0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x06,0xe0,0x01,0x00,0x00};
401 static const guchar radio_text_bits[] = {
402   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0x01,0xf0,0x01,0xf0,
403   0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
404 #if 0
405 /*
406  * radio_aa_bits is currently not used, since it is all zeros.
407  */
408 static const guchar radio_aa_bits[] = {
409   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
410   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
411 #endif
412 static const guchar radio_base_bits[] = {
413   0x00,0x00,0x00,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
414   0x07,0xfc,0x07,0xf8,0x03,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00};
415
416 /*
417  * Extracted from radio-13.png, width=13, height=13
418  */
419 static const guchar radio_inconsistent_text_bits[] = {
420   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x03,0x00,
421   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
422 static const guchar radio_inconsistent_aa_bits[] = {
423   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x03,0x00,0x00,0xf8,
424   0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
425
426 static struct {
427   const guchar      *bits;
428   GList     *bmap_list; /* list of GdkBitmap */
429 } indicator_parts[] = {
430   { check_aa_bits, NULL },
431   { check_base_bits, NULL },
432   { check_black_bits, NULL },
433   { check_dark_bits, NULL },
434   { check_light_bits, NULL },
435   { check_mid_bits, NULL },
436   { check_text_bits, NULL },
437   { check_inconsistent_text_bits, NULL },
438   { radio_base_bits, NULL },
439   { radio_black_bits, NULL },
440   { radio_dark_bits, NULL },
441   { radio_light_bits, NULL },
442   { radio_mid_bits, NULL },
443   { radio_text_bits, NULL },
444   { radio_inconsistent_aa_bits, NULL },
445   { radio_inconsistent_text_bits, NULL },
446 };
447
448 /* --- variables --- */
449 static GdkColor gtk_default_normal_fg =      { 0,      0,      0,      0 };
450 static GdkColor gtk_default_active_fg =      { 0,      0,      0,      0 };
451 static GdkColor gtk_default_prelight_fg =    { 0,      0,      0,      0 };
452 static GdkColor gtk_default_selected_fg =    { 0, 0xffff, 0xffff, 0xffff };
453 static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 };
454
455 static GdkColor gtk_default_normal_bg =      { 0, 0xdcdc, 0xdada, 0xd5d5 };
456 static GdkColor gtk_default_active_bg =      { 0, 0xbaba, 0xb5b5, 0xabab };
457 static GdkColor gtk_default_prelight_bg =    { 0, 0xeeee, 0xebeb, 0xe7e7 };
458 static GdkColor gtk_default_selected_bg =    { 0, 0x4b4b, 0x6969, 0x8383 };
459 static GdkColor gtk_default_insensitive_bg = { 0, 0xdcdc, 0xdada, 0xd5d5 };
460 static GdkColor gtk_default_selected_base =  { 0, 0x4b4b, 0x6969, 0x8383 };
461 static GdkColor gtk_default_active_base =    { 0, 0x8080, 0x7d7d, 0x7474 };
462
463 static gpointer parent_class = NULL;
464
465
466 /* --- functions --- */
467 GType
468 gtk_style_get_type (void)
469 {
470   static GType style_type = 0;
471   
472   if (!style_type)
473     {
474       static const GTypeInfo style_info =
475       {
476         sizeof (GtkStyleClass),
477         (GBaseInitFunc) NULL,
478         (GBaseFinalizeFunc) NULL,
479         (GClassInitFunc) gtk_style_class_init,
480         NULL,           /* class_finalize */
481         NULL,           /* class_data */
482         sizeof (GtkStyle),
483         0,              /* n_preallocs */
484         (GInstanceInitFunc) gtk_style_init,
485       };
486       
487       style_type = g_type_register_static (G_TYPE_OBJECT, "GtkStyle",
488                                            &style_info, 0);
489     }
490   
491   return style_type;
492 }
493
494 /**
495  * _gtk_style_init_for_settings:
496  * @style: a #GtkStyle
497  * @settings: a #GtkSettings
498  * 
499  * Initializes the font description in @style accoridng to the default
500  * font name of @settings. This is called for gtk_style_new() with
501  * the settings for the default screen (if any); if we are creating
502  * a style for a particular screen, we then call it again in a
503  * location where we know the correct settings.
504  * The reason for this is that gtk_rc_style_create_style() doesn't
505  * take the screen for an argument.
506  **/
507 void
508 _gtk_style_init_for_settings (GtkStyle    *style,
509                               GtkSettings *settings)
510 {
511   const gchar *font_name = _gtk_rc_context_get_default_font_name (settings);
512
513   if (style->font_desc)
514     pango_font_description_free (style->font_desc);
515   
516   style->font_desc = pango_font_description_from_string (font_name);
517       
518   if (!pango_font_description_get_family (style->font_desc))
519     {
520       g_warning ("Default font does not have a family set");
521       pango_font_description_set_family (style->font_desc, "Sans");
522     }
523   if (pango_font_description_get_size (style->font_desc) <= 0)
524     {
525       g_warning ("Default font does not have a positive size");
526       pango_font_description_set_size (style->font_desc, 10 * PANGO_SCALE);
527     }
528 }
529
530 static void
531 gtk_style_init (GtkStyle *style)
532 {
533   gint i;
534   
535   GtkSettings *settings = gtk_settings_get_default ();
536   
537   if (settings)
538     _gtk_style_init_for_settings (style, settings);
539   else
540     style->font_desc = pango_font_description_from_string ("Sans 10");
541   
542   style->attach_count = 0;
543   style->colormap = NULL;
544   style->depth = -1;
545   
546   style->black.red = 0;
547   style->black.green = 0;
548   style->black.blue = 0;
549   
550   style->white.red = 65535;
551   style->white.green = 65535;
552   style->white.blue = 65535;
553   
554   style->black_gc = NULL;
555   style->white_gc = NULL;
556   
557   style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
558   style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
559   style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
560   style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
561   style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
562   
563   style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
564   style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
565   style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
566   style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
567   style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
568   
569   for (i = 0; i < 4; i++)
570     {
571       style->text[i] = style->fg[i];
572       style->base[i] = style->white;
573     }
574
575   style->base[GTK_STATE_SELECTED] = gtk_default_selected_base;
576   style->text[GTK_STATE_SELECTED] = style->white;
577   style->base[GTK_STATE_ACTIVE] = gtk_default_active_base;
578   style->text[GTK_STATE_ACTIVE] = style->white;
579   style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg;
580   style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
581   
582   for (i = 0; i < 5; i++)
583     style->bg_pixmap[i] = NULL;
584   
585   style->rc_style = NULL;
586   
587   for (i = 0; i < 5; i++)
588     {
589       style->fg_gc[i] = NULL;
590       style->bg_gc[i] = NULL;
591       style->light_gc[i] = NULL;
592       style->dark_gc[i] = NULL;
593       style->mid_gc[i] = NULL;
594       style->text_gc[i] = NULL;
595       style->base_gc[i] = NULL;
596       style->text_aa_gc[i] = NULL;
597     }
598
599   style->xthickness = 2;
600   style->ythickness = 2;
601
602   style->property_cache = NULL;
603 }
604
605 static void
606 gtk_style_class_init (GtkStyleClass *klass)
607 {
608   GObjectClass *object_class = G_OBJECT_CLASS (klass);
609   
610   parent_class = g_type_class_peek_parent (klass);
611
612   object_class->finalize = gtk_style_finalize;
613
614   klass->clone = gtk_style_real_clone;
615   klass->copy = gtk_style_real_copy;
616   klass->init_from_rc = gtk_style_real_init_from_rc;
617   klass->realize = gtk_style_real_realize;
618   klass->unrealize = gtk_style_real_unrealize;
619   klass->set_background = gtk_style_real_set_background;
620   klass->render_icon = gtk_default_render_icon;
621
622   klass->draw_hline = gtk_default_draw_hline;
623   klass->draw_vline = gtk_default_draw_vline;
624   klass->draw_shadow = gtk_default_draw_shadow;
625   klass->draw_polygon = gtk_default_draw_polygon;
626   klass->draw_arrow = gtk_default_draw_arrow;
627   klass->draw_diamond = gtk_default_draw_diamond;
628   klass->draw_string = gtk_default_draw_string;
629   klass->draw_box = gtk_default_draw_box;
630   klass->draw_flat_box = gtk_default_draw_flat_box;
631   klass->draw_check = gtk_default_draw_check;
632   klass->draw_option = gtk_default_draw_option;
633   klass->draw_tab = gtk_default_draw_tab;
634   klass->draw_shadow_gap = gtk_default_draw_shadow_gap;
635   klass->draw_box_gap = gtk_default_draw_box_gap;
636   klass->draw_extension = gtk_default_draw_extension;
637   klass->draw_focus = gtk_default_draw_focus;
638   klass->draw_slider = gtk_default_draw_slider;
639   klass->draw_handle = gtk_default_draw_handle;
640   klass->draw_expander = gtk_default_draw_expander;
641   klass->draw_layout = gtk_default_draw_layout;
642   klass->draw_resize_grip = gtk_default_draw_resize_grip;
643 }
644
645 static void
646 clear_property_cache (GtkStyle *style)
647 {
648   if (style->property_cache)
649     {
650       guint i;
651
652       for (i = 0; i < style->property_cache->len; i++)
653         {
654           PropertyValue *node = &g_array_index (style->property_cache, PropertyValue, i);
655
656           g_param_spec_unref (node->pspec);
657           g_value_unset (&node->value);
658         }
659       g_array_free (style->property_cache, TRUE);
660       style->property_cache = NULL;
661     }
662 }
663
664 static void
665 gtk_style_finalize (GObject *object)
666 {
667   GtkStyle *style = GTK_STYLE (object);
668
669   g_return_if_fail (style->attach_count == 0);
670
671   clear_property_cache (style);
672   
673   if (style->styles)
674     {
675       if (style->styles->data != style)
676         g_slist_remove (style->styles, style);
677       else
678         {
679           GSList *tmp_list = style->styles->next;
680           
681           while (tmp_list)
682             {
683               GTK_STYLE (tmp_list->data)->styles = style->styles->next;
684               tmp_list = tmp_list->next;
685             }
686           g_slist_free_1 (style->styles);
687         }
688     }
689
690   pango_font_description_free (style->font_desc);
691   
692   if (style->private_font)
693     gdk_font_unref (style->private_font);
694
695   if (style->private_font_desc)
696     pango_font_description_free (style->private_font_desc);
697   
698   if (style->rc_style)
699     gtk_rc_style_unref (style->rc_style);
700   
701   G_OBJECT_CLASS (parent_class)->finalize (object);
702 }
703
704
705 GtkStyle*
706 gtk_style_copy (GtkStyle *style)
707 {
708   GtkStyle *new_style;
709   
710   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
711   
712   new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
713   GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
714
715   return new_style;
716 }
717
718 static GtkStyle*
719 gtk_style_duplicate (GtkStyle *style)
720 {
721   GtkStyle *new_style;
722   
723   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
724   
725   new_style = gtk_style_copy (style);
726   
727   style->styles = g_slist_append (style->styles, new_style);
728   new_style->styles = style->styles;  
729   
730   return new_style;
731 }
732
733 /**
734  * gtk_style_new:
735  * @returns: a new #GtkStyle.
736  *
737  * Creates a new #GtkStyle.
738  **/
739 GtkStyle*
740 gtk_style_new (void)
741 {
742   GtkStyle *style;
743   
744   style = g_object_new (GTK_TYPE_STYLE, NULL);
745   
746   return style;
747 }
748
749 /**
750  * gtk_style_attach:
751  * @style: a #GtkStyle.
752  * @window: a #GtkWindow.
753  * @returns: Either @style, or a newly-created #GtkStyle.
754  *   If the style is newly created, the style parameter
755  *   will be dereferenced, and the new style will have
756  *   a reference count belonging to the caller.
757  *
758  * Attaches a style to a window; this process allocates the
759  * colors and creates the GC's for the style - it specializes
760  * it to a particular visual and colormap. The process may 
761  * involve the creation of a new style if the style has already 
762  * been attached to a window with a different style and colormap.
763  **/
764  /*
765  * FIXME: The sequence - 
766  *    create a style => s1
767  *    attach s1 to v1, c1 => s1
768  *    attach s1 to v2, c2 => s2
769  *    detach s1 from v1, c1
770  *    attach s1 to v2, c2 => s3
771  * results in two separate, unlinked styles s2 and s3 which
772  * are identical and could be shared. To fix this, we would
773  * want to never remove a style from the list of linked
774  * styles as long as as it has a reference count. However, the 
775  * disadvantage of doing it this way means that we would need two 
776  * passes through the linked list when attaching (one to check for 
777  * matching styles, one to look for empty unattached styles - but 
778  * it will almost never be longer than 2 elements.
779  */
780 GtkStyle*
781 gtk_style_attach (GtkStyle  *style,
782                   GdkWindow *window)
783 {
784   GSList *styles;
785   GtkStyle *new_style = NULL;
786   GdkColormap *colormap;
787   
788   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
789   g_return_val_if_fail (window != NULL, NULL);
790   
791   colormap = gdk_drawable_get_colormap (window);
792   
793   if (!style->styles)
794     style->styles = g_slist_append (NULL, style);
795   
796   styles = style->styles;
797   while (styles)
798     {
799       new_style = styles->data;
800       
801       if (new_style->attach_count == 0)
802         {
803           gtk_style_realize (new_style, colormap);
804           break;
805         }
806       else if (new_style->colormap == colormap)
807         break;
808       
809       new_style = NULL;
810       styles = styles->next;
811     }
812   
813   if (!new_style)
814     {
815       new_style = gtk_style_duplicate (style);
816       if (gdk_colormap_get_screen (style->colormap) != gdk_colormap_get_screen (colormap) &&
817           new_style->private_font)
818         {
819           gdk_font_unref (new_style->private_font);
820           new_style->private_font = NULL;
821         }
822       gtk_style_realize (new_style, colormap);
823     }
824
825   /* A style gets a refcount from being attached */
826   if (new_style->attach_count == 0)
827     g_object_ref (new_style);
828
829   /* Another refcount belongs to the parent */
830   if (style != new_style) 
831     {
832       g_object_unref (style);
833       g_object_ref (new_style);
834     }
835   
836   new_style->attach_count++;
837   
838   return new_style;
839 }
840
841 void
842 gtk_style_detach (GtkStyle *style)
843 {
844   g_return_if_fail (GTK_IS_STYLE (style));
845   
846   style->attach_count -= 1;
847   if (style->attach_count == 0)
848     {
849       GTK_STYLE_GET_CLASS (style)->unrealize (style);
850       
851       g_object_unref (style->colormap);
852       style->colormap = NULL;
853
854       if (style->private_font_desc)
855         {
856           if (style->private_font)
857             {
858               gdk_font_unref (style->private_font);
859               style->private_font = NULL;
860             }
861           
862           pango_font_description_free (style->private_font_desc);
863           style->private_font_desc = NULL;
864         }
865
866       g_object_unref (style);
867     }
868 }
869
870 /**
871  * gtk_style_ref:
872  * @style: a #GtkStyle.
873  * @returns: @style.
874  *
875  * Deprecated equivalent of g_object_ref().
876  **/
877 GtkStyle*
878 gtk_style_ref (GtkStyle *style)
879 {
880   return (GtkStyle *) g_object_ref (style);
881 }
882
883 /**
884  * gtk_style_unref:
885  * @style: a #GtkStyle.
886  *
887  * Deprecated equivalent of g_object_unref().
888  **/
889 void
890 gtk_style_unref (GtkStyle *style)
891 {
892   g_object_unref (style);
893 }
894
895 static void
896 gtk_style_realize (GtkStyle    *style,
897                    GdkColormap *colormap)
898 {
899   g_return_if_fail (GTK_IS_STYLE (style));
900   g_return_if_fail (GDK_IS_COLORMAP (colormap));
901   
902   style->colormap = g_object_ref (colormap);
903   style->depth = gdk_colormap_get_visual (colormap)->depth;
904
905   GTK_STYLE_GET_CLASS (style)->realize (style);
906 }
907
908 GtkIconSet*
909 gtk_style_lookup_icon_set (GtkStyle   *style,
910                            const char *stock_id)
911 {
912   GSList *iter;
913
914   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
915   g_return_val_if_fail (stock_id != NULL, NULL);
916   
917   iter = style->icon_factories;
918   while (iter != NULL)
919     {
920       GtkIconSet *icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
921                                                       stock_id);
922       if (icon_set)
923         return icon_set;
924       
925       iter = g_slist_next (iter);
926     }
927
928   return gtk_icon_factory_lookup_default (stock_id);
929 }
930
931 /**
932  * gtk_draw_hline:
933  * @style: a #GtkStyle
934  * @window: a #GdkWindow
935  * @state_type: a state
936  * @x1: the starting x coordinate
937  * @x2: the ending x coordinate
938  * @y: the y coordinate
939  * 
940  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
941  * using the given style and state.
942  * 
943  * This function is deprecated, use gtk_paint_hline() instead.
944  **/
945 void
946 gtk_draw_hline (GtkStyle     *style,
947                 GdkWindow    *window,
948                 GtkStateType  state_type,
949                 gint          x1,
950                 gint          x2,
951                 gint          y)
952 {
953   g_return_if_fail (GTK_IS_STYLE (style));
954   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
955   
956   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, NULL, NULL, NULL, x1, x2, y);
957 }
958
959
960 /**
961  * gtk_draw_vline:
962  * @style: a #GtkStyle
963  * @window: a #GdkWindow
964  * @state_type: a state
965  * @y1_: the starting y coordinate
966  * @y2_: the ending y coordinate
967  * @x: the x coordinate
968  * 
969  * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @window
970  * using the given style and state.
971  * 
972  * This function is deprecated, use gtk_paint_vline() instead.
973  **/
974 void
975 gtk_draw_vline (GtkStyle     *style,
976                 GdkWindow    *window,
977                 GtkStateType  state_type,
978                 gint          y1,
979                 gint          y2,
980                 gint          x)
981 {
982   g_return_if_fail (GTK_IS_STYLE (style));
983   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
984   
985   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, NULL, NULL, NULL, y1, y2, x);
986 }
987
988 /**
989  * gtk_draw_shadow:
990  * @style: a #GtkStyle
991  * @window: a #GdkWindow
992  * @state_type: a state
993  * @shadow_type: type of shadow to draw
994  * @x: x origin of the rectangle
995  * @y: y origin of the rectangle
996  * @width: width of the rectangle 
997  * @height: width of the rectangle 
998  *
999  * Draws a shadow around the given rectangle in @window 
1000  * using the given style and state and shadow type.
1001  * 
1002  * This function is deprecated, use gtk_paint_shadow() instead.
1003  */
1004 void
1005 gtk_draw_shadow (GtkStyle      *style,
1006                  GdkWindow     *window,
1007                  GtkStateType   state_type,
1008                  GtkShadowType  shadow_type,
1009                  gint           x,
1010                  gint           y,
1011                  gint           width,
1012                  gint           height)
1013 {
1014   g_return_if_fail (GTK_IS_STYLE (style));
1015   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
1016   
1017   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1018 }
1019
1020 /**
1021  * gtk_draw_polygon:
1022  * @style: a #GtkStyle
1023  * @window: a #GdkWindow
1024  * @state_type: a state
1025  * @shadow_type: type of shadow to draw
1026  * @points: an array of #GdkPoint<!-- -->s
1027  * @npoints: length of @points
1028  * @fill: %TRUE if the polygon should be filled
1029  * 
1030  * Draws a polygon on @window with the given parameters.
1031  *
1032  * This function is deprecated, use gtk_paint_polygon() instead.
1033  */ 
1034 void
1035 gtk_draw_polygon (GtkStyle      *style,
1036                   GdkWindow     *window,
1037                   GtkStateType   state_type,
1038                   GtkShadowType  shadow_type,
1039                   GdkPoint      *points,
1040                   gint           npoints,
1041                   gboolean       fill)
1042 {
1043   g_return_if_fail (GTK_IS_STYLE (style));
1044   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_polygon != NULL);
1045   
1046   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, NULL, NULL, NULL, points, npoints, fill);
1047 }
1048
1049 /**
1050  * gtk_draw_arrow:
1051  * @style: a #GtkStyle
1052  * @window: a #GdkWindow
1053  * @state_type: a state
1054  * @shadow_type: the type of shadow to draw
1055  * @arrow_type: the type of arrow to draw
1056  * @fill: %TRUE if the arrow tip should be filled
1057  * @x: x origin of the rectangle to draw the arrow in
1058  * @y: y origin of the rectangle to draw the arrow in
1059  * @width: width of the rectangle to draw the arrow in
1060  * @height: height of the rectangle to draw the arrow in
1061  * 
1062  * Draws an arrow in the given rectangle on @window using the given 
1063  * parameters. @arrow_type determines the direction of the arrow.
1064  *
1065  * This function is deprecated, use gtk_paint_arrow() instead.
1066  */
1067 void
1068 gtk_draw_arrow (GtkStyle      *style,
1069                 GdkWindow     *window,
1070                 GtkStateType   state_type,
1071                 GtkShadowType  shadow_type,
1072                 GtkArrowType   arrow_type,
1073                 gboolean       fill,
1074                 gint           x,
1075                 gint           y,
1076                 gint           width,
1077                 gint           height)
1078 {
1079   g_return_if_fail (GTK_IS_STYLE (style));
1080   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
1081   
1082   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, NULL, NULL, NULL, arrow_type, fill, x, y, width, height);
1083 }
1084
1085 /**
1086  * gtk_draw_diamond:
1087  * @style: a #GtkStyle
1088  * @window: a #GdkWindow
1089  * @state_type: a state
1090  * @shadow_type: the type of shadow to draw
1091  * @x: x origin of the rectangle to draw the diamond in
1092  * @y: y origin of the rectangle to draw the diamond in
1093  * @width: width of the rectangle to draw the diamond in
1094  * @height: height of the rectangle to draw the diamond in
1095  *
1096  * Draws a diamond in the given rectangle on @window using the given parameters.
1097  *
1098  * This function is deprecated, use gtk_paint_diamond() instead.
1099  */
1100 void
1101 gtk_draw_diamond (GtkStyle      *style,
1102                   GdkWindow     *window,
1103                   GtkStateType   state_type,
1104                   GtkShadowType  shadow_type,
1105                   gint           x,
1106                   gint           y,
1107                   gint           width,
1108                   gint           height)
1109 {
1110   g_return_if_fail (GTK_IS_STYLE (style));
1111   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
1112   
1113   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1114 }
1115
1116 /**
1117  * gtk_draw_string:
1118  * @style: a #GtkStyle
1119  * @window: a #GdkWindow
1120  * @state_type: a state
1121  * @x: x origin
1122  * @y: y origin
1123  * @string: the string to draw
1124  * 
1125  * Draws a text string on @window with the given parameters.
1126  *
1127  * This function is deprecated, use gtk_paint_layout() instead.
1128  */
1129 void
1130 gtk_draw_string (GtkStyle      *style,
1131                  GdkWindow     *window,
1132                  GtkStateType   state_type,
1133                  gint           x,
1134                  gint           y,
1135                  const gchar   *string)
1136 {
1137   g_return_if_fail (GTK_IS_STYLE (style));
1138   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
1139   
1140   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, NULL, NULL, NULL, x, y, string);
1141 }
1142
1143 /**
1144  * gtk_draw_box:
1145  * @style: a #GtkStyle
1146  * @window: a #GdkWindow
1147  * @state_type: a state
1148  * @shadow_type: the type of shadow to draw
1149  * @x: x origin of the box
1150  * @y: y origin of the box
1151  * @width: the width of the box
1152  * @height: the height of the box
1153  * 
1154  * Draws a box on @window with the given parameters.
1155  *
1156  * This function is deprecated, use gtk_paint_box() instead.
1157  */
1158 void
1159 gtk_draw_box (GtkStyle      *style,
1160               GdkWindow     *window,
1161               GtkStateType   state_type,
1162               GtkShadowType  shadow_type,
1163               gint           x,
1164               gint           y,
1165               gint           width,
1166               gint           height)
1167 {
1168   g_return_if_fail (GTK_IS_STYLE (style));
1169   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
1170   
1171   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1172 }
1173
1174 /**
1175  * gtk_draw_flat_box:
1176  * @style: a #GtkStyle
1177  * @window: a #GdkWindow
1178  * @state_type: a state
1179  * @shadow_type: the type of shadow to draw
1180  * @x: x origin of the box
1181  * @y: y origin of the box
1182  * @width: the width of the box
1183  * @height: the height of the box
1184  * 
1185  * Draws a flat box on @window with the given parameters.
1186  *
1187  * This function is deprecated, use gtk_paint_flat_box() instead.
1188  */
1189 void
1190 gtk_draw_flat_box (GtkStyle      *style,
1191                    GdkWindow     *window,
1192                    GtkStateType   state_type,
1193                    GtkShadowType  shadow_type,
1194                    gint           x,
1195                    gint           y,
1196                    gint           width,
1197                    gint           height)
1198 {
1199   g_return_if_fail (GTK_IS_STYLE (style));
1200   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
1201   
1202   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1203 }
1204
1205 /**
1206  * gtk_draw_check:
1207  * @style: a #GtkStyle
1208  * @window: a #GdkWindow
1209  * @state_type: a state
1210  * @shadow_type: the type of shadow to draw
1211  * @x: x origin of the rectangle to draw the check in
1212  * @y: y origin of the rectangle to draw the check in
1213  * @width: the width of the rectangle to draw the check in
1214  * @height: the height of the rectangle to draw the check in
1215  * 
1216  * Draws a check button indicator in the given rectangle on @window with 
1217  * the given parameters.
1218  *
1219  * This function is deprecated, use gtk_paint_check() instead.
1220  */
1221 void
1222 gtk_draw_check (GtkStyle      *style,
1223                 GdkWindow     *window,
1224                 GtkStateType   state_type,
1225                 GtkShadowType  shadow_type,
1226                 gint           x,
1227                 gint           y,
1228                 gint           width,
1229                 gint           height)
1230 {
1231   g_return_if_fail (GTK_IS_STYLE (style));
1232   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
1233   
1234   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1235 }
1236
1237 /**
1238  * gtk_draw_option:
1239  * @style: a #GtkStyle
1240  * @window: a #GdkWindow
1241  * @state_type: a state
1242  * @shadow_type: the type of shadow to draw
1243  * @x: x origin of the rectangle to draw the option in
1244  * @y: y origin of the rectangle to draw the option in
1245  * @width: the width of the rectangle to draw the option in
1246  * @height: the height of the rectangle to draw the option in
1247  *
1248  * Draws a radio button indicator in the given rectangle on @window with 
1249  * the given parameters.
1250  *
1251  * This function is deprecated, use gtk_paint_option() instead.
1252  */
1253 void
1254 gtk_draw_option (GtkStyle      *style,
1255                  GdkWindow     *window,
1256                  GtkStateType   state_type,
1257                  GtkShadowType  shadow_type,
1258                  gint           x,
1259                  gint           y,
1260                  gint           width,
1261                  gint           height)
1262 {
1263   g_return_if_fail (GTK_IS_STYLE (style));
1264   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
1265   
1266   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1267 }
1268
1269 /**
1270  * gtk_draw_tab:
1271  * @style: a #GtkStyle
1272  * @window: a #GdkWindow
1273  * @state_type: a state
1274  * @shadow_type: the type of shadow to draw
1275  * @x: x origin of the rectangle to draw the tab in
1276  * @y: y origin of the rectangle to draw the tab in
1277  * @width: the width of the rectangle to draw the tab in
1278  * @height: the height of the rectangle to draw the tab in
1279  *
1280  * Draws an option menu tab (i.e. the up and down pointing arrows)
1281  * in the given rectangle on @window using the given parameters.
1282  * 
1283  * This function is deprecated, use gtk_paint_tab() instead.
1284  */ 
1285 void
1286 gtk_draw_tab (GtkStyle      *style,
1287               GdkWindow     *window,
1288               GtkStateType   state_type,
1289               GtkShadowType  shadow_type,
1290               gint           x,
1291               gint           y,
1292               gint           width,
1293               gint           height)
1294 {
1295   g_return_if_fail (GTK_IS_STYLE (style));
1296   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
1297   
1298   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1299 }
1300
1301 void
1302 gtk_draw_shadow_gap (GtkStyle       *style,
1303                      GdkWindow      *window,
1304                      GtkStateType    state_type,
1305                      GtkShadowType   shadow_type,
1306                      gint            x,
1307                      gint            y,
1308                      gint            width,
1309                      gint            height,
1310                      GtkPositionType gap_side,
1311                      gint            gap_x,
1312                      gint            gap_width)
1313 {
1314   g_return_if_fail (GTK_IS_STYLE (style));
1315   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
1316   
1317   GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side, gap_x, gap_width);
1318 }
1319
1320 void
1321 gtk_draw_box_gap (GtkStyle       *style,
1322                   GdkWindow      *window,
1323                   GtkStateType    state_type,
1324                   GtkShadowType   shadow_type,
1325                   gint            x,
1326                   gint            y,
1327                   gint            width,
1328                   gint            height,
1329                   GtkPositionType gap_side,
1330                   gint            gap_x,
1331                   gint            gap_width)
1332 {
1333   g_return_if_fail (GTK_IS_STYLE (style));
1334   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
1335   
1336   GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side, gap_x, gap_width);
1337 }
1338
1339 void
1340 gtk_draw_extension (GtkStyle       *style,
1341                     GdkWindow      *window,
1342                     GtkStateType    state_type,
1343                     GtkShadowType   shadow_type,
1344                     gint            x,
1345                     gint            y,
1346                     gint            width,
1347                     gint            height,
1348                     GtkPositionType gap_side)
1349 {
1350   g_return_if_fail (GTK_IS_STYLE (style));
1351   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
1352   
1353   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side);
1354 }
1355
1356 /**
1357  * gtk_draw_focus:
1358  * @style: a #GtkStyle
1359  * @window: a #GdkWindow
1360  * @x: the x origin of the rectangle around which to draw a focus indicator
1361  * @y: the y origin of the rectangle around which to draw a focus indicator
1362  * @width: the width of the rectangle around which to draw a focus indicator
1363  * @height: the height of the rectangle around which to draw a focus indicator
1364  *
1365  * Draws a focus indicator around the given rectangle on @window using the
1366  * given style.
1367  * 
1368  * This function is deprecated, use gtk_paint_focus() instead.
1369  */
1370 void
1371 gtk_draw_focus (GtkStyle      *style,
1372                 GdkWindow     *window,
1373                 gint           x,
1374                 gint           y,
1375                 gint           width,
1376                 gint           height)
1377 {
1378   g_return_if_fail (GTK_IS_STYLE (style));
1379   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
1380   
1381   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, GTK_STATE_NORMAL, NULL, NULL, NULL, x, y, width, height);
1382 }
1383
1384 void 
1385 gtk_draw_slider (GtkStyle      *style,
1386                  GdkWindow     *window,
1387                  GtkStateType   state_type,
1388                  GtkShadowType  shadow_type,
1389                  gint           x,
1390                  gint           y,
1391                  gint           width,
1392                  gint           height,
1393                  GtkOrientation orientation)
1394 {
1395   g_return_if_fail (GTK_IS_STYLE (style));
1396   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
1397   
1398   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation);
1399 }
1400
1401 void 
1402 gtk_draw_handle (GtkStyle      *style,
1403                  GdkWindow     *window,
1404                  GtkStateType   state_type,
1405                  GtkShadowType  shadow_type,
1406                  gint           x,
1407                  gint           y,
1408                  gint           width,
1409                  gint           height,
1410                  GtkOrientation orientation)
1411 {
1412   g_return_if_fail (GTK_IS_STYLE (style));
1413   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
1414   
1415   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation);
1416 }
1417
1418 void
1419 gtk_draw_expander (GtkStyle        *style,
1420                    GdkWindow       *window,
1421                    GtkStateType     state_type,
1422                    gint             x,
1423                    gint             y,
1424                    GtkExpanderStyle expander_style)
1425 {
1426   g_return_if_fail (GTK_IS_STYLE (style));
1427   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
1428   
1429   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type,
1430                                               NULL, NULL, NULL,
1431                                               x, y, expander_style);
1432 }
1433
1434 void
1435 gtk_draw_layout (GtkStyle        *style,
1436                  GdkWindow       *window,
1437                  GtkStateType     state_type,
1438                  gboolean         use_text,
1439                  gint             x,
1440                  gint             y,
1441                  PangoLayout     *layout)
1442 {
1443   g_return_if_fail (GTK_IS_STYLE (style));
1444   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
1445   
1446   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text,
1447                                             NULL, NULL, NULL,
1448                                             x, y, layout);
1449 }
1450
1451 /**
1452  * gtk_draw_resize_grip:
1453  * @style: a #GtkStyle
1454  * @window: a #GdkWindow
1455  * @state_type: a state
1456  * @edge: the edge in which to draw the resize grip
1457  * @x: the x origin of the rectangle in which to draw the resize grip
1458  * @y: the y origin of the rectangle in which to draw the resize grip
1459  * @width: the width of the rectangle in which to draw the resize grip
1460  * @height: the height of the rectangle in which to draw the resize grip
1461  *
1462  * Draws a resize grip in the given rectangle on @window using the given
1463  * parameters. 
1464  * 
1465  * This function is deprecated, use gtk_paint_resize_grip() instead.
1466  */
1467 void
1468 gtk_draw_resize_grip (GtkStyle     *style,
1469                       GdkWindow    *window,
1470                       GtkStateType  state_type,
1471                       GdkWindowEdge edge,
1472                       gint          x,
1473                       gint          y,
1474                       gint          width,
1475                       gint          height)
1476 {
1477   g_return_if_fail (GTK_IS_STYLE (style));
1478   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
1479
1480   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
1481                                                  NULL, NULL, NULL,
1482                                                  edge,
1483                                                  x, y, width, height);
1484 }
1485
1486
1487 /**
1488  * gtk_style_set_background:
1489  * @style: a #GtkStyle
1490  * @window: a #GdkWindow
1491  * @state_type: a state
1492  * 
1493  * Sets the background of @window to the background color or pixmap
1494  * specified by @style for the given state.
1495  */
1496 void
1497 gtk_style_set_background (GtkStyle    *style,
1498                           GdkWindow   *window,
1499                           GtkStateType state_type)
1500 {
1501   g_return_if_fail (GTK_IS_STYLE (style));
1502   g_return_if_fail (window != NULL);
1503   
1504   GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
1505 }
1506
1507 /* Default functions */
1508 static GtkStyle *
1509 gtk_style_real_clone (GtkStyle *style)
1510 {
1511   return GTK_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
1512 }
1513
1514 static void
1515 gtk_style_real_copy (GtkStyle *style,
1516                      GtkStyle *src)
1517 {
1518   gint i;
1519   
1520   for (i = 0; i < 5; i++)
1521     {
1522       style->fg[i] = src->fg[i];
1523       style->bg[i] = src->bg[i];
1524       style->text[i] = src->text[i];
1525       style->base[i] = src->base[i];
1526       
1527       style->bg_pixmap[i] = src->bg_pixmap[i];
1528     }
1529
1530   if (style->private_font)
1531     gdk_font_unref (style->private_font);
1532   style->private_font = src->private_font;
1533   if (style->private_font)
1534     gdk_font_ref (style->private_font);
1535
1536   if (style->font_desc)
1537     pango_font_description_free (style->font_desc);
1538   if (src->font_desc)
1539     style->font_desc = pango_font_description_copy (src->font_desc);
1540   else
1541     style->font_desc = NULL;
1542   
1543   style->xthickness = src->xthickness;
1544   style->ythickness = src->ythickness;
1545
1546   if (style->rc_style)
1547     gtk_rc_style_unref (style->rc_style);
1548   style->rc_style = src->rc_style;
1549   if (src->rc_style)
1550     gtk_rc_style_ref (src->rc_style);
1551
1552   /* don't copy, just clear cache */
1553   clear_property_cache (style);
1554 }
1555
1556 static void
1557 gtk_style_real_init_from_rc (GtkStyle   *style,
1558                              GtkRcStyle *rc_style)
1559 {
1560   gint i;
1561
1562   /* cache _should_ be still empty */
1563   clear_property_cache (style);
1564
1565   if (rc_style->font_desc)
1566     pango_font_description_merge (style->font_desc, rc_style->font_desc, TRUE);
1567     
1568   for (i = 0; i < 5; i++)
1569     {
1570       if (rc_style->color_flags[i] & GTK_RC_FG)
1571         style->fg[i] = rc_style->fg[i];
1572       if (rc_style->color_flags[i] & GTK_RC_BG)
1573         style->bg[i] = rc_style->bg[i];
1574       if (rc_style->color_flags[i] & GTK_RC_TEXT)
1575         style->text[i] = rc_style->text[i];
1576       if (rc_style->color_flags[i] & GTK_RC_BASE)
1577         style->base[i] = rc_style->base[i];
1578     }
1579
1580   if (rc_style->xthickness >= 0)
1581     style->xthickness = rc_style->xthickness;
1582   if (rc_style->ythickness >= 0)
1583     style->ythickness = rc_style->ythickness;
1584
1585   if (rc_style->icon_factories)
1586     {
1587       GSList *iter;
1588
1589       style->icon_factories = g_slist_copy (rc_style->icon_factories);
1590       
1591       iter = style->icon_factories;
1592       while (iter != NULL)
1593         {
1594           g_object_ref (iter->data);
1595           iter = g_slist_next (iter);
1596         }
1597     }
1598 }
1599
1600 static gint
1601 style_property_values_cmp (gconstpointer bsearch_node1,
1602                            gconstpointer bsearch_node2)
1603 {
1604   const PropertyValue *val1 = bsearch_node1;
1605   const PropertyValue *val2 = bsearch_node2;
1606
1607   if (val1->widget_type == val2->widget_type)
1608     return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
1609   else
1610     return val1->widget_type < val2->widget_type ? -1 : 1;
1611 }
1612
1613 const GValue*
1614 _gtk_style_peek_property_value (GtkStyle           *style,
1615                                 GType               widget_type,
1616                                 GParamSpec         *pspec,
1617                                 GtkRcPropertyParser parser)
1618 {
1619   PropertyValue *pcache, key = { 0, NULL, { 0, } };
1620   const GtkRcProperty *rcprop = NULL;
1621   guint i;
1622
1623   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1624   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
1625   g_return_val_if_fail (g_type_is_a (pspec->owner_type, GTK_TYPE_WIDGET), NULL);
1626   g_return_val_if_fail (g_type_is_a (widget_type, pspec->owner_type), NULL);
1627
1628   key.widget_type = widget_type;
1629   key.pspec = pspec;
1630
1631   /* need value cache array */
1632   if (!style->property_cache)
1633     style->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
1634   else
1635     {
1636       pcache = bsearch (&key,
1637                         style->property_cache->data, style->property_cache->len,
1638                         sizeof (PropertyValue), style_property_values_cmp);
1639       if (pcache)
1640         return &pcache->value;
1641     }
1642
1643   i = 0;
1644   while (i < style->property_cache->len &&
1645          style_property_values_cmp (&key, &g_array_index (style->property_cache, PropertyValue, i)) >= 0)
1646     i++;
1647
1648   g_array_insert_val (style->property_cache, i, key);
1649   pcache = &g_array_index (style->property_cache, PropertyValue, i);
1650
1651   /* cache miss, initialize value type, then set contents */
1652   g_param_spec_ref (pcache->pspec);
1653   g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1654
1655   /* value provided by rc style? */
1656   if (style->rc_style)
1657     {
1658       GQuark prop_quark = g_quark_from_string (pspec->name);
1659
1660       do
1661         {
1662           rcprop = _gtk_rc_style_lookup_rc_property (style->rc_style,
1663                                                      g_type_qname (widget_type),
1664                                                      prop_quark);
1665           if (rcprop)
1666             break;
1667           widget_type = g_type_parent (widget_type);
1668         }
1669       while (g_type_is_a (widget_type, pspec->owner_type));
1670     }
1671
1672   /* when supplied by rc style, we need to convert */
1673   if (rcprop && !_gtk_settings_parse_convert (parser, &rcprop->value,
1674                                               pspec, &pcache->value))
1675     {
1676       gchar *contents = g_strdup_value_contents (&rcprop->value);
1677       
1678       g_message ("%s: failed to retrieve property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
1679                  rcprop->origin,
1680                  g_type_name (pspec->owner_type), pspec->name,
1681                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1682                  contents,
1683                  G_VALUE_TYPE_NAME (&rcprop->value));
1684       g_free (contents);
1685       rcprop = NULL; /* needs default */
1686     }
1687   
1688   /* not supplied by rc style (or conversion failed), revert to default */
1689   if (!rcprop)
1690     g_param_value_set_default (pspec, &pcache->value);
1691
1692   return &pcache->value;
1693 }
1694
1695 static GdkPixmap *
1696 load_bg_image (GdkColormap *colormap,
1697                GdkColor    *bg_color,
1698                const gchar *filename)
1699 {
1700   if (strcmp (filename, "<parent>") == 0)
1701     return (GdkPixmap*) GDK_PARENT_RELATIVE;
1702   else
1703     {
1704       return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
1705                                                   bg_color,
1706                                                   filename);
1707     }
1708 }
1709
1710 static void
1711 gtk_style_real_realize (GtkStyle *style)
1712 {
1713   GdkGCValues gc_values;
1714   GdkGCValuesMask gc_values_mask;
1715   
1716   gint i;
1717
1718   for (i = 0; i < 5; i++)
1719     {
1720       gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
1721       gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
1722       
1723       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1724       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
1725       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1726
1727       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1728       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
1729       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
1730     }
1731
1732   style->black.red = 0x0000;
1733   style->black.green = 0x0000;
1734   style->black.blue = 0x0000;
1735   gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
1736
1737   style->white.red = 0xffff;
1738   style->white.green = 0xffff;
1739   style->white.blue = 0xffff;
1740   gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
1741
1742   gc_values_mask = GDK_GC_FOREGROUND;
1743   
1744   gc_values.foreground = style->black;
1745   style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1746   
1747   gc_values.foreground = style->white;
1748   style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1749   
1750   for (i = 0; i < 5; i++)
1751     {
1752       if (style->rc_style && style->rc_style->bg_pixmap_name[i])
1753         style->bg_pixmap[i] = load_bg_image (style->colormap,
1754                                              &style->bg[i],
1755                                              style->rc_style->bg_pixmap_name[i]);
1756       
1757       if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
1758         g_warning ("unable to allocate color: ( %d %d %d )",
1759                    style->fg[i].red, style->fg[i].green, style->fg[i].blue);
1760       if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
1761         g_warning ("unable to allocate color: ( %d %d %d )",
1762                    style->bg[i].red, style->bg[i].green, style->bg[i].blue);
1763       if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
1764         g_warning ("unable to allocate color: ( %d %d %d )",
1765                    style->light[i].red, style->light[i].green, style->light[i].blue);
1766       if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
1767         g_warning ("unable to allocate color: ( %d %d %d )",
1768                    style->dark[i].red, style->dark[i].green, style->dark[i].blue);
1769       if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
1770         g_warning ("unable to allocate color: ( %d %d %d )",
1771                    style->mid[i].red, style->mid[i].green, style->mid[i].blue);
1772       if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
1773         g_warning ("unable to allocate color: ( %d %d %d )",
1774                    style->text[i].red, style->text[i].green, style->text[i].blue);
1775       if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
1776         g_warning ("unable to allocate color: ( %d %d %d )",
1777                    style->base[i].red, style->base[i].green, style->base[i].blue);
1778       if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
1779         g_warning ("unable to allocate color: ( %d %d %d )",
1780                    style->text_aa[i].red, style->text_aa[i].green, style->text_aa[i].blue);
1781       
1782       gc_values.foreground = style->fg[i];
1783       style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1784       
1785       gc_values.foreground = style->bg[i];
1786       style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1787       
1788       gc_values.foreground = style->light[i];
1789       style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1790       
1791       gc_values.foreground = style->dark[i];
1792       style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1793       
1794       gc_values.foreground = style->mid[i];
1795       style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1796       
1797       gc_values.foreground = style->text[i];
1798       style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1799       
1800       gc_values.foreground = style->base[i];
1801       style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1802
1803       gc_values.foreground = style->text_aa[i];
1804       style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1805     }
1806 }
1807
1808 static void
1809 gtk_style_real_unrealize (GtkStyle *style)
1810 {
1811   int i;
1812
1813   gtk_gc_release (style->black_gc);
1814   gtk_gc_release (style->white_gc);
1815       
1816   for (i = 0; i < 5; i++)
1817     {
1818       gtk_gc_release (style->fg_gc[i]);
1819       gtk_gc_release (style->bg_gc[i]);
1820       gtk_gc_release (style->light_gc[i]);
1821       gtk_gc_release (style->dark_gc[i]);
1822       gtk_gc_release (style->mid_gc[i]);
1823       gtk_gc_release (style->text_gc[i]);
1824       gtk_gc_release (style->base_gc[i]);
1825       gtk_gc_release (style->text_aa_gc[i]);
1826
1827       if (style->bg_pixmap[i] &&  style->bg_pixmap[i] != (GdkPixmap*) GDK_PARENT_RELATIVE)
1828         g_object_unref (style->bg_pixmap[i]);
1829     }
1830   
1831   gdk_colormap_free_colors (style->colormap, style->fg, 5);
1832   gdk_colormap_free_colors (style->colormap, style->bg, 5);
1833   gdk_colormap_free_colors (style->colormap, style->light, 5);
1834   gdk_colormap_free_colors (style->colormap, style->dark, 5);
1835   gdk_colormap_free_colors (style->colormap, style->mid, 5);
1836   gdk_colormap_free_colors (style->colormap, style->text, 5);
1837   gdk_colormap_free_colors (style->colormap, style->base, 5);
1838   gdk_colormap_free_colors (style->colormap, style->text_aa, 5);
1839
1840   style_unrealize_cursor_gcs (style);
1841 }
1842
1843 static void
1844 gtk_style_real_set_background (GtkStyle    *style,
1845                                GdkWindow   *window,
1846                                GtkStateType state_type)
1847 {
1848   GdkPixmap *pixmap;
1849   gint parent_relative;
1850   
1851   if (style->bg_pixmap[state_type])
1852     {
1853       if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1854         {
1855           pixmap = NULL;
1856           parent_relative = TRUE;
1857         }
1858       else
1859         {
1860           pixmap = style->bg_pixmap[state_type];
1861           parent_relative = FALSE;
1862         }
1863       
1864       gdk_window_set_back_pixmap (window, pixmap, parent_relative);
1865     }
1866   else
1867     gdk_window_set_background (window, &style->bg[state_type]);
1868 }
1869
1870 /**
1871  * gtk_style_render_icon:
1872  * @style: a #GtkStyle
1873  * @source: the #GtkIconSource specifying the icon to render
1874  * @direction: a text direction
1875  * @state: a state
1876  * @size: the size to render the icon at. A size of (GtkIconSize)-1
1877  *        means render at the size of the source and don't scale.
1878  * @widget: the widget 
1879  * @detail: a style detail
1880  * @returns: a newly-created #GdkPixbuf containing the rendered icon
1881  *
1882  * Renders the icon specified by @source at the given @size 
1883  * according to the given parameters and returns the result in a 
1884  * pixbuf.
1885  */
1886 GdkPixbuf *
1887 gtk_style_render_icon (GtkStyle            *style,
1888                        const GtkIconSource *source,
1889                        GtkTextDirection     direction,
1890                        GtkStateType         state,
1891                        GtkIconSize          size,
1892                        GtkWidget           *widget,
1893                        const gchar         *detail)
1894 {
1895   GdkPixbuf *pixbuf;
1896   
1897   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1898   g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
1899   
1900   pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
1901                                                      size, widget, detail);
1902
1903   g_return_val_if_fail (pixbuf != NULL, NULL);
1904
1905   return pixbuf;
1906 }
1907
1908 /* Default functions */
1909 void
1910 gtk_style_apply_default_background (GtkStyle     *style,
1911                                     GdkWindow    *window,
1912                                     gboolean      set_bg,
1913                                     GtkStateType  state_type, 
1914                                     GdkRectangle *area, 
1915                                     gint          x, 
1916                                     gint          y, 
1917                                     gint          width, 
1918                                     gint          height)
1919 {
1920   GdkRectangle new_rect, old_rect;
1921   
1922   if (area)
1923     {
1924       old_rect.x = x;
1925       old_rect.y = y;
1926       old_rect.width = width;
1927       old_rect.height = height;
1928       
1929       if (!gdk_rectangle_intersect (area, &old_rect, &new_rect))
1930         return;
1931     }
1932   else
1933     {
1934       new_rect.x = x;
1935       new_rect.y = y;
1936       new_rect.width = width;
1937       new_rect.height = height;
1938     }
1939   
1940   if (!style->bg_pixmap[state_type] ||
1941       GDK_IS_PIXMAP (window) ||
1942       (!set_bg && style->bg_pixmap[state_type] != (GdkPixmap*) GDK_PARENT_RELATIVE))
1943     {
1944       GdkGC *gc = style->bg_gc[state_type];
1945       
1946       if (style->bg_pixmap[state_type])
1947         {
1948           gdk_gc_set_fill (gc, GDK_TILED);
1949           gdk_gc_set_tile (gc, style->bg_pixmap[state_type]);
1950         }
1951       
1952       gdk_draw_rectangle (window, gc, TRUE, 
1953                           new_rect.x, new_rect.y, new_rect.width, new_rect.height);
1954       if (style->bg_pixmap[state_type])
1955         gdk_gc_set_fill (gc, GDK_SOLID);
1956     }
1957   else
1958     {
1959       if (set_bg)
1960         {
1961           if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1962             gdk_window_set_back_pixmap (window, NULL, TRUE);
1963           else
1964             gdk_window_set_back_pixmap (window, style->bg_pixmap[state_type], FALSE);
1965         }
1966       
1967       gdk_window_clear_area (window, 
1968                              new_rect.x, new_rect.y, 
1969                              new_rect.width, new_rect.height);
1970     }
1971 }
1972
1973 static GdkPixbuf*
1974 scale_or_ref (GdkPixbuf *src,
1975               gint width,
1976               gint height)
1977 {
1978   if (width == gdk_pixbuf_get_width (src) &&
1979       height == gdk_pixbuf_get_height (src))
1980     {
1981       return g_object_ref (src);
1982     }
1983   else
1984     {
1985       return gdk_pixbuf_scale_simple (src,
1986                                       width, height,
1987                                       GDK_INTERP_BILINEAR);
1988     }
1989 }
1990
1991 static GdkPixbuf *
1992 gtk_default_render_icon (GtkStyle            *style,
1993                          const GtkIconSource *source,
1994                          GtkTextDirection     direction,
1995                          GtkStateType         state,
1996                          GtkIconSize          size,
1997                          GtkWidget           *widget,
1998                          const gchar         *detail)
1999 {
2000   gint width = 1;
2001   gint height = 1;
2002   GdkPixbuf *scaled;
2003   GdkPixbuf *stated;
2004   GdkPixbuf *base_pixbuf;
2005   GdkScreen *screen;
2006   GtkSettings *settings;
2007
2008   /* Oddly, style can be NULL in this function, because
2009    * GtkIconSet can be used without a style and if so
2010    * it uses this function.
2011    */
2012
2013   base_pixbuf = gtk_icon_source_get_pixbuf (source);
2014
2015   g_return_val_if_fail (base_pixbuf != NULL, NULL);
2016
2017   if (widget && gtk_widget_has_screen (widget))
2018     {
2019       screen = gtk_widget_get_screen (widget);
2020       settings = gtk_settings_get_for_screen (screen);
2021     }
2022   else if (style->colormap)
2023     {
2024       screen = gdk_colormap_get_screen (style->colormap);
2025       settings = gtk_settings_get_for_screen (screen);
2026     }
2027   else
2028     {
2029       settings = gtk_settings_get_default ();
2030       GTK_NOTE (MULTIHEAD,
2031                 g_warning ("Using the default screen for gtk_default_render_icon()"));
2032     }
2033
2034   
2035   if (size != (GtkIconSize) -1 && !gtk_icon_size_lookup_for_settings (settings, size, &width, &height))
2036     {
2037       g_warning (G_STRLOC ": invalid icon size '%d'", size);
2038       return NULL;
2039     }
2040
2041   /* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
2042    * leave it alone.
2043    */
2044   if (size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded (source))
2045     scaled = scale_or_ref (base_pixbuf, width, height);
2046   else
2047     scaled = g_object_ref (base_pixbuf);
2048
2049   /* If the state was wildcarded, then generate a state. */
2050   if (gtk_icon_source_get_state_wildcarded (source))
2051     {
2052       if (state == GTK_STATE_INSENSITIVE)
2053         {
2054           stated = gdk_pixbuf_copy (scaled);      
2055           
2056           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
2057                                             0.8, TRUE);
2058           
2059           g_object_unref (scaled);
2060         }
2061       else if (state == GTK_STATE_PRELIGHT)
2062         {
2063           stated = gdk_pixbuf_copy (scaled);      
2064           
2065           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
2066                                             1.2, FALSE);
2067           
2068           g_object_unref (scaled);
2069         }
2070       else
2071         {
2072           stated = scaled;
2073         }
2074     }
2075   else
2076     stated = scaled;
2077   
2078   return stated;
2079 }
2080
2081 static void
2082 sanitize_size (GdkWindow *window,
2083                gint      *width,
2084                gint      *height)
2085 {
2086   if ((*width == -1) && (*height == -1))
2087     gdk_drawable_get_size (window, width, height);
2088   else if (*width == -1)
2089     gdk_drawable_get_size (window, width, NULL);
2090   else if (*height == -1)
2091     gdk_drawable_get_size (window, NULL, height);
2092 }
2093
2094 static GdkBitmap * 
2095 get_indicator_for_screen (GdkDrawable   *drawable,
2096                           IndicatorPart  part)
2097                           
2098 {
2099   GdkScreen *screen = gdk_drawable_get_screen (drawable);
2100   GdkBitmap *bitmap;
2101   GList *tmp_list;
2102   
2103   tmp_list = indicator_parts[part].bmap_list;
2104   while (tmp_list)
2105     {
2106       bitmap = tmp_list->data;
2107       
2108       if (gdk_drawable_get_screen (bitmap) == screen)
2109         return bitmap;
2110       
2111       tmp_list = tmp_list->next;
2112     }
2113   
2114   bitmap = gdk_bitmap_create_from_data (drawable,
2115                                         (gchar *)indicator_parts[part].bits,
2116                                         INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
2117   indicator_parts[part].bmap_list = g_list_prepend (indicator_parts[part].bmap_list, bitmap);
2118
2119   return bitmap;
2120 }
2121
2122 static void
2123 draw_part (GdkDrawable  *drawable,
2124            GdkGC        *gc,
2125            GdkRectangle *area,
2126            gint          x,
2127            gint          y,
2128            IndicatorPart part)
2129 {
2130   if (area)
2131     gdk_gc_set_clip_rectangle (gc, area);
2132   
2133   gdk_gc_set_ts_origin (gc, x, y);
2134   gdk_gc_set_stipple (gc, get_indicator_for_screen (drawable, part));
2135   gdk_gc_set_fill (gc, GDK_STIPPLED);
2136
2137   gdk_draw_rectangle (drawable, gc, TRUE, x, y, INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
2138
2139   gdk_gc_set_fill (gc, GDK_SOLID);
2140
2141   if (area)
2142     gdk_gc_set_clip_rectangle (gc, NULL);
2143 }
2144
2145 static void
2146 gtk_default_draw_hline (GtkStyle     *style,
2147                         GdkWindow    *window,
2148                         GtkStateType  state_type,
2149                         GdkRectangle  *area,
2150                         GtkWidget     *widget,
2151                         const gchar   *detail,
2152                         gint          x1,
2153                         gint          x2,
2154                         gint          y)
2155 {
2156   gint thickness_light;
2157   gint thickness_dark;
2158   gint i;
2159   
2160   g_return_if_fail (GTK_IS_STYLE (style));
2161   g_return_if_fail (window != NULL);
2162   
2163   thickness_light = style->ythickness / 2;
2164   thickness_dark = style->ythickness - thickness_light;
2165   
2166   if (area)
2167     {
2168       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2169       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2170     }
2171   
2172   if (detail && !strcmp (detail, "label"))
2173     {
2174       if (state_type == GTK_STATE_INSENSITIVE)
2175         gdk_draw_line (window, style->white_gc, x1 + 1, y + 1, x2 + 1, y + 1);   
2176       gdk_draw_line (window, style->fg_gc[state_type], x1, y, x2, y);     
2177     }
2178   else
2179     {
2180       for (i = 0; i < thickness_dark; i++)
2181         {
2182           gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i);
2183           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i);
2184         }
2185       
2186       y += thickness_dark;
2187       for (i = 0; i < thickness_light; i++)
2188         {
2189           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
2190           gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i);
2191         }
2192     }
2193   
2194   if (area)
2195     {
2196       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2197       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2198     }
2199 }
2200
2201
2202 static void
2203 gtk_default_draw_vline (GtkStyle     *style,
2204                         GdkWindow    *window,
2205                         GtkStateType  state_type,
2206                         GdkRectangle  *area,
2207                         GtkWidget     *widget,
2208                         const gchar   *detail,
2209                         gint          y1,
2210                         gint          y2,
2211                         gint          x)
2212 {
2213   gint thickness_light;
2214   gint thickness_dark;
2215   gint i;
2216   
2217   g_return_if_fail (GTK_IS_STYLE (style));
2218   g_return_if_fail (window != NULL);
2219   
2220   thickness_light = style->xthickness / 2;
2221   thickness_dark = style->xthickness - thickness_light;
2222   
2223   if (area)
2224     {
2225       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2226       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2227     }
2228   for (i = 0; i < thickness_dark; i++)
2229     {
2230       gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2);
2231       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1);
2232     }
2233   
2234   x += thickness_dark;
2235   for (i = 0; i < thickness_light; i++)
2236     {
2237       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i);
2238       gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2);
2239     }
2240   if (area)
2241     {
2242       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2243       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2244     }
2245 }
2246
2247
2248 static void
2249 draw_thin_shadow (GtkStyle      *style,
2250                   GdkWindow     *window,
2251                   GtkStateType   state,
2252                   GdkRectangle  *area,
2253                   gint           x,
2254                   gint           y,
2255                   gint           width,
2256                   gint           height)
2257 {
2258   GdkGC *gc1, *gc2;
2259
2260   sanitize_size (window, &width, &height);
2261   
2262   gc1 = style->light_gc[state];
2263   gc2 = style->dark_gc[state];
2264   
2265   if (area)
2266     {
2267       gdk_gc_set_clip_rectangle (gc1, area);
2268       gdk_gc_set_clip_rectangle (gc2, area);
2269     }
2270   
2271   gdk_draw_line (window, gc1,
2272                  x, y + height - 1, x + width - 1, y + height - 1);
2273   gdk_draw_line (window, gc1,
2274                  x + width - 1, y,  x + width - 1, y + height - 1);
2275       
2276   gdk_draw_line (window, gc2,
2277                  x, y, x + width - 2, y);
2278   gdk_draw_line (window, gc2,
2279                  x, y, x, y + height - 2);
2280
2281   if (area)
2282     {
2283       gdk_gc_set_clip_rectangle (gc1, NULL);
2284       gdk_gc_set_clip_rectangle (gc2, NULL);
2285     }
2286 }
2287
2288 static void
2289 draw_spinbutton_shadow (GtkStyle        *style,
2290                         GdkWindow       *window,
2291                         GtkStateType     state,
2292                         GtkTextDirection direction,
2293                         GdkRectangle    *area,
2294                         gint             x,
2295                         gint             y,
2296                         gint             width,
2297                         gint             height)
2298 {
2299   sanitize_size (window, &width, &height);
2300
2301   if (area)
2302     {
2303       gdk_gc_set_clip_rectangle (style->black_gc, area);
2304       gdk_gc_set_clip_rectangle (style->bg_gc[state], area);
2305       gdk_gc_set_clip_rectangle (style->dark_gc[state], area);
2306       gdk_gc_set_clip_rectangle (style->light_gc[state], area);
2307     }
2308
2309   if (direction == GTK_TEXT_DIR_LTR)
2310     {
2311       gdk_draw_line (window, style->dark_gc[state],
2312                      x, y, x + width - 1, y);
2313       gdk_draw_line (window, style->black_gc,
2314                      x, y + 1, x + width - 2, y + 1);
2315       gdk_draw_line (window, style->black_gc,
2316                      x + width - 2, y + 2, x + width - 2, y + height - 3);
2317       gdk_draw_line (window, style->light_gc[state],
2318                      x + width - 1, y + 1, x + width - 1, y + height - 2);
2319       gdk_draw_line (window, style->light_gc[state],
2320                      x, y + height - 1, x + width - 1, y + height - 1);
2321       gdk_draw_line (window, style->bg_gc[state],
2322                      x, y + height - 2, x + width - 2, y + height - 2);
2323       gdk_draw_line (window, style->black_gc,
2324                      x, y + 2, x, y + height - 3);
2325     }
2326   else
2327     {
2328       gdk_draw_line (window, style->dark_gc[state],
2329                      x, y, x + width - 1, y);
2330       gdk_draw_line (window, style->dark_gc[state],
2331                      x, y + 1, x, y + height - 1);
2332       gdk_draw_line (window, style->black_gc,
2333                      x + 1, y + 1, x + width - 1, y + 1);
2334       gdk_draw_line (window, style->black_gc,
2335                      x + 1, y + 2, x + 1, y + height - 2);
2336       gdk_draw_line (window, style->black_gc,
2337                      x + width - 1, y + 2, x + width - 1, y + height - 3);
2338       gdk_draw_line (window, style->light_gc[state],
2339                      x + 1, y + height - 1, x + width - 1, y + height - 1);
2340       gdk_draw_line (window, style->bg_gc[state],
2341                      x + 2, y + height - 2, x + width - 1, y + height - 2);
2342     }
2343   
2344   if (area)
2345     {
2346       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2347       gdk_gc_set_clip_rectangle (style->bg_gc[state], NULL);
2348       gdk_gc_set_clip_rectangle (style->dark_gc[state], NULL);
2349       gdk_gc_set_clip_rectangle (style->light_gc[state], NULL);
2350     }
2351 }
2352
2353 static void
2354 gtk_default_draw_shadow (GtkStyle      *style,
2355                          GdkWindow     *window,
2356                          GtkStateType   state_type,
2357                          GtkShadowType  shadow_type,
2358                          GdkRectangle  *area,
2359                          GtkWidget     *widget,
2360                          const gchar   *detail,
2361                          gint           x,
2362                          gint           y,
2363                          gint           width,
2364                          gint           height)
2365 {
2366   GdkGC *gc1 = NULL;
2367   GdkGC *gc2 = NULL;
2368   gint thickness_light;
2369   gint thickness_dark;
2370   gint i;
2371   
2372   g_return_if_fail (GTK_IS_STYLE (style));
2373   g_return_if_fail (window != NULL);
2374
2375   if (shadow_type == GTK_SHADOW_IN)
2376     {
2377       if (detail && (strcmp (detail, "buttondefault") == 0))
2378         {
2379           sanitize_size (window, &width, &height);
2380
2381           gdk_draw_rectangle (window, style->black_gc, FALSE,
2382                               x, y, width - 1, height - 1);
2383           
2384           return;
2385         }
2386       if (detail && strcmp (detail, "trough") == 0)
2387         {
2388           draw_thin_shadow (style, window, state_type, area,
2389                             x, y, width, height);
2390           return;
2391         }
2392       if (widget && GTK_IS_SPIN_BUTTON (widget) &&
2393          detail && strcmp (detail, "spinbutton") == 0)
2394         {
2395           draw_spinbutton_shadow (style, window, state_type,
2396                                   gtk_widget_get_direction (widget), area, x, y, width, height);
2397           
2398           return;
2399         }
2400     }
2401   
2402   sanitize_size (window, &width, &height);
2403   
2404   switch (shadow_type)
2405     {
2406     case GTK_SHADOW_NONE:
2407       return;
2408     case GTK_SHADOW_IN:
2409     case GTK_SHADOW_ETCHED_IN:
2410       gc1 = style->light_gc[state_type];
2411       gc2 = style->dark_gc[state_type];
2412       break;
2413     case GTK_SHADOW_OUT:
2414     case GTK_SHADOW_ETCHED_OUT:
2415       gc1 = style->dark_gc[state_type];
2416       gc2 = style->light_gc[state_type];
2417       break;
2418     }
2419   
2420   if (area)
2421     {
2422       gdk_gc_set_clip_rectangle (gc1, area);
2423       gdk_gc_set_clip_rectangle (gc2, area);
2424       if (shadow_type == GTK_SHADOW_IN || 
2425           shadow_type == GTK_SHADOW_OUT)
2426         {
2427           gdk_gc_set_clip_rectangle (style->black_gc, area);
2428           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2429         }
2430     }
2431   
2432   switch (shadow_type)
2433     {
2434     case GTK_SHADOW_NONE:
2435       break;
2436       
2437     case GTK_SHADOW_IN:
2438       /* Light around right and bottom edge */
2439
2440       if (style->ythickness > 0)
2441         gdk_draw_line (window, gc1,
2442                        x, y + height - 1, x + width - 1, y + height - 1);
2443       if (style->xthickness > 0)
2444         gdk_draw_line (window, gc1,
2445                        x + width - 1, y, x + width - 1, y + height - 1);
2446
2447       if (style->ythickness > 1)
2448         gdk_draw_line (window, style->bg_gc[state_type],
2449                        x + 1, y + height - 2, x + width - 2, y + height - 2);
2450       if (style->xthickness > 1)
2451         gdk_draw_line (window, style->bg_gc[state_type],
2452                        x + width - 2, y + 1, x + width - 2, y + height - 2);
2453
2454       /* Dark around left and top */
2455
2456       if (style->ythickness > 1)
2457         gdk_draw_line (window, style->black_gc,
2458                        x + 1, y + 1, x + width - 2, y + 1);
2459       if (style->xthickness > 1)
2460         gdk_draw_line (window, style->black_gc,
2461                        x + 1, y + 1, x + 1, y + height - 2);
2462
2463       if (style->ythickness > 0)
2464         gdk_draw_line (window, gc2,
2465                        x, y, x + width - 1, y);
2466       if (style->xthickness > 0)
2467         gdk_draw_line (window, gc2,
2468                        x, y, x, y + height - 1);
2469       break;
2470       
2471     case GTK_SHADOW_OUT:
2472       /* Dark around right and bottom edge */
2473
2474       if (style->ythickness > 0)
2475         {
2476           if (style->ythickness > 1)
2477             {
2478               gdk_draw_line (window, gc1,
2479                              x + 1, y + height - 2, x + width - 2, y + height - 2);
2480               gdk_draw_line (window, style->black_gc,
2481                              x, y + height - 1, x + width - 1, y + height - 1);
2482             }
2483           else
2484             {
2485               gdk_draw_line (window, gc1,
2486                              x + 1, y + height - 1, x + width - 1, y + height - 1);
2487             }
2488         }
2489
2490       if (style->xthickness > 0)
2491         {
2492           if (style->xthickness > 1)
2493             {
2494               gdk_draw_line (window, gc1,
2495                              x + width - 2, y + 1, x + width - 2, y + height - 2);
2496               
2497               gdk_draw_line (window, style->black_gc,
2498                              x + width - 1, y, x + width - 1, y + height - 1);
2499             }
2500           else
2501             {
2502               gdk_draw_line (window, gc1,
2503                              x + width - 1, y + 1, x + width - 1, y + height - 1);
2504             }
2505         }
2506       
2507       /* Light around top and left */
2508
2509       if (style->ythickness > 0)
2510         gdk_draw_line (window, gc2,
2511                        x, y, x + width - 2, y);
2512       if (style->xthickness > 0)
2513         gdk_draw_line (window, gc2,
2514                        x, y, x, y + height - 2);
2515
2516       if (style->ythickness > 1)
2517         gdk_draw_line (window, style->bg_gc[state_type],
2518                        x + 1, y + 1, x + width - 3, y + 1);
2519       if (style->xthickness > 1)
2520         gdk_draw_line (window, style->bg_gc[state_type],
2521                        x + 1, y + 1, x + 1, y + height - 3);
2522       break;
2523       
2524     case GTK_SHADOW_ETCHED_IN:
2525     case GTK_SHADOW_ETCHED_OUT:
2526       if (style->xthickness > 0)
2527         {
2528           if (style->xthickness > 1)
2529             {
2530               thickness_light = 1;
2531               thickness_dark = 1;
2532       
2533               for (i = 0; i < thickness_dark; i++)
2534                 {
2535                   gdk_draw_line (window, gc1,
2536                                  x + width - i - 1,
2537                                  y + i,
2538                                  x + width - i - 1,
2539                                  y + height - i - 1);
2540                   gdk_draw_line (window, gc2,
2541                                  x + i,
2542                                  y + i,
2543                                  x + i,
2544                                  y + height - i - 2);
2545                 }
2546       
2547               for (i = 0; i < thickness_light; i++)
2548                 {
2549                   gdk_draw_line (window, gc1,
2550                                  x + thickness_dark + i,
2551                                  y + thickness_dark + i,
2552                                  x + thickness_dark + i,
2553                                  y + height - thickness_dark - i - 1);
2554                   gdk_draw_line (window, gc2,
2555                                  x + width - thickness_light - i - 1,
2556                                  y + thickness_dark + i,
2557                                  x + width - thickness_light - i - 1,
2558                                  y + height - thickness_light - 1);
2559                 }
2560             }
2561           else
2562             {
2563               gdk_draw_line (window, 
2564                              style->dark_gc[state_type],
2565                              x, y, x, y + height);                         
2566               gdk_draw_line (window, 
2567                              style->dark_gc[state_type],
2568                              x + width, y, x + width, y + height);
2569             }
2570         }
2571
2572       if (style->ythickness > 0)
2573         {
2574           if (style->ythickness > 1)
2575             {
2576               thickness_light = 1;
2577               thickness_dark = 1;
2578       
2579               for (i = 0; i < thickness_dark; i++)
2580                 {
2581                   gdk_draw_line (window, gc1,
2582                                  x + i,
2583                                  y + height - i - 1,
2584                                  x + width - i - 1,
2585                                  y + height - i - 1);
2586           
2587                   gdk_draw_line (window, gc2,
2588                                  x + i,
2589                                  y + i,
2590                                  x + width - i - 2,
2591                                  y + i);
2592                 }
2593       
2594               for (i = 0; i < thickness_light; i++)
2595                 {
2596                   gdk_draw_line (window, gc1,
2597                                  x + thickness_dark + i,
2598                                  y + thickness_dark + i,
2599                                  x + width - thickness_dark - i - 2,
2600                                  y + thickness_dark + i);
2601           
2602                   gdk_draw_line (window, gc2,
2603                                  x + thickness_dark + i,
2604                                  y + height - thickness_light - i - 1,
2605                                  x + width - thickness_light - 1,
2606                                  y + height - thickness_light - i - 1);
2607                 }
2608             }
2609           else
2610             {
2611               gdk_draw_line (window, 
2612                              style->dark_gc[state_type],
2613                              x, y, x + width, y);
2614               gdk_draw_line (window, 
2615                              style->dark_gc[state_type],
2616                              x, y + height, x + width, y + height);
2617             }
2618         }
2619       
2620       break;
2621     }
2622
2623   if (shadow_type == GTK_SHADOW_IN &&
2624       widget && GTK_IS_SPIN_BUTTON (widget) &&
2625       detail && strcmp (detail, "entry") == 0)
2626     {
2627       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
2628         {
2629           gdk_draw_line (window,
2630                          style->base_gc[state_type],
2631                          x + width - 1, y + 2,
2632                          x + width - 1, y + height - 3);
2633           gdk_draw_line (window,
2634                          style->base_gc[state_type],
2635                          x + width - 2, y + 2,
2636                          x + width - 2, y + height - 3);
2637           gdk_draw_point (window,
2638                           style->black_gc,
2639                           x + width - 1, y + 1);
2640           gdk_draw_point (window,
2641                           style->bg_gc[state_type],
2642                           x + width - 1, y + height - 2);
2643         }
2644       else
2645         {
2646           gdk_draw_line (window,
2647                          style->base_gc[state_type],
2648                          x, y + 2,
2649                          x, y + height - 3);
2650           gdk_draw_line (window,
2651                          style->base_gc[state_type],
2652                          x + 1, y + 2,
2653                          x + 1, y + height - 3);
2654           gdk_draw_point (window,
2655                           style->black_gc,
2656                           x, y + 1);
2657           gdk_draw_line (window,
2658                          style->bg_gc[state_type],
2659                          x, y + height - 2,
2660                          x + 1, y + height - 2);
2661           gdk_draw_point (window,
2662                           style->light_gc[state_type],
2663                           x, y + height - 1);
2664         }
2665     }
2666
2667
2668   if (area)
2669     {
2670       gdk_gc_set_clip_rectangle (gc1, NULL);
2671       gdk_gc_set_clip_rectangle (gc2, NULL);
2672       if (shadow_type == GTK_SHADOW_IN || 
2673           shadow_type == GTK_SHADOW_OUT)
2674         {
2675           gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2676           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2677         }
2678     }
2679 }
2680
2681 static void
2682 gtk_default_draw_polygon (GtkStyle      *style,
2683                           GdkWindow     *window,
2684                           GtkStateType   state_type,
2685                           GtkShadowType  shadow_type,
2686                           GdkRectangle  *area,
2687                           GtkWidget     *widget,
2688                           const gchar   *detail,
2689                           GdkPoint      *points,
2690                           gint           npoints,
2691                           gboolean       fill)
2692 {
2693   static const gdouble pi_over_4 = G_PI_4;
2694   static const gdouble pi_3_over_4 = G_PI_4 * 3;
2695   GdkGC *gc1;
2696   GdkGC *gc2;
2697   GdkGC *gc3;
2698   GdkGC *gc4;
2699   gdouble angle;
2700   gint xadjust;
2701   gint yadjust;
2702   gint i;
2703   
2704   g_return_if_fail (GTK_IS_STYLE (style));
2705   g_return_if_fail (window != NULL);
2706   g_return_if_fail (points != NULL);
2707   
2708   switch (shadow_type)
2709     {
2710     case GTK_SHADOW_IN:
2711       gc1 = style->bg_gc[state_type];
2712       gc2 = style->dark_gc[state_type];
2713       gc3 = style->light_gc[state_type];
2714       gc4 = style->black_gc;
2715       break;
2716     case GTK_SHADOW_ETCHED_IN:
2717       gc1 = style->light_gc[state_type];
2718       gc2 = style->dark_gc[state_type];
2719       gc3 = style->dark_gc[state_type];
2720       gc4 = style->light_gc[state_type];
2721       break;
2722     case GTK_SHADOW_OUT:
2723       gc1 = style->dark_gc[state_type];
2724       gc2 = style->light_gc[state_type];
2725       gc3 = style->black_gc;
2726       gc4 = style->bg_gc[state_type];
2727       break;
2728     case GTK_SHADOW_ETCHED_OUT:
2729       gc1 = style->dark_gc[state_type];
2730       gc2 = style->light_gc[state_type];
2731       gc3 = style->light_gc[state_type];
2732       gc4 = style->dark_gc[state_type];
2733       break;
2734     default:
2735       return;
2736     }
2737   
2738   if (area)
2739     {
2740       gdk_gc_set_clip_rectangle (gc1, area);
2741       gdk_gc_set_clip_rectangle (gc2, area);
2742       gdk_gc_set_clip_rectangle (gc3, area);
2743       gdk_gc_set_clip_rectangle (gc4, area);
2744     }
2745   
2746   if (fill)
2747     gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints);
2748   
2749   npoints--;
2750   
2751   for (i = 0; i < npoints; i++)
2752     {
2753       if ((points[i].x == points[i+1].x) &&
2754           (points[i].y == points[i+1].y))
2755         {
2756           angle = 0;
2757         }
2758       else
2759         {
2760           angle = atan2 (points[i+1].y - points[i].y,
2761                          points[i+1].x - points[i].x);
2762         }
2763       
2764       if ((angle > -pi_3_over_4) && (angle < pi_over_4))
2765         {
2766           if (angle > -pi_over_4)
2767             {
2768               xadjust = 0;
2769               yadjust = 1;
2770             }
2771           else
2772             {
2773               xadjust = 1;
2774               yadjust = 0;
2775             }
2776           
2777           gdk_draw_line (window, gc1,
2778                          points[i].x-xadjust, points[i].y-yadjust,
2779                          points[i+1].x-xadjust, points[i+1].y-yadjust);
2780           gdk_draw_line (window, gc3,
2781                          points[i].x, points[i].y,
2782                          points[i+1].x, points[i+1].y);
2783         }
2784       else
2785         {
2786           if ((angle < -pi_3_over_4) || (angle > pi_3_over_4))
2787             {
2788               xadjust = 0;
2789               yadjust = 1;
2790             }
2791           else
2792             {
2793               xadjust = 1;
2794               yadjust = 0;
2795             }
2796           
2797           gdk_draw_line (window, gc4,
2798                          points[i].x+xadjust, points[i].y+yadjust,
2799                          points[i+1].x+xadjust, points[i+1].y+yadjust);
2800           gdk_draw_line (window, gc2,
2801                          points[i].x, points[i].y,
2802                          points[i+1].x, points[i+1].y);
2803         }
2804     }
2805
2806   if (area)
2807     {
2808       gdk_gc_set_clip_rectangle (gc1, NULL);
2809       gdk_gc_set_clip_rectangle (gc2, NULL);
2810       gdk_gc_set_clip_rectangle (gc3, NULL);
2811       gdk_gc_set_clip_rectangle (gc4, NULL);
2812     }
2813 }
2814
2815 static void
2816 draw_arrow (GdkWindow     *window,
2817             GdkGC         *gc,
2818             GdkRectangle  *area,
2819             GtkArrowType   arrow_type,
2820             gint           x,
2821             gint           y,
2822             gint           width,
2823             gint           height)
2824 {
2825   gint i, j;
2826
2827   if (area)
2828     gdk_gc_set_clip_rectangle (gc, area);
2829
2830   if (arrow_type == GTK_ARROW_DOWN)
2831     {
2832       for (i = 0, j = 0; i < height; i++, j++)
2833         gdk_draw_line (window, gc, x + j, y + i, x + width - j - 1, y + i);
2834     }
2835   else if (arrow_type == GTK_ARROW_UP)
2836     {
2837       for (i = height - 1, j = 0; i >= 0; i--, j++)
2838         gdk_draw_line (window, gc, x + j, y + i, x + width - j - 1, y + i);
2839     }
2840   else if (arrow_type == GTK_ARROW_LEFT)
2841     {
2842       for (i = width - 1, j = 0; i >= 0; i--, j++)
2843         gdk_draw_line (window, gc, x + i, y + j, x + i, y + height - j - 1);
2844     }
2845   else if (arrow_type == GTK_ARROW_RIGHT)
2846     {
2847       for (i = 0, j = 0; i < width; i++, j++)
2848         gdk_draw_line (window, gc, x + i, y + j, x + i, y + height - j - 1);
2849     }
2850
2851   if (area)
2852     gdk_gc_set_clip_rectangle (gc, NULL);
2853 }
2854
2855 static void
2856 calculate_arrow_geometry (GtkArrowType  arrow_type,
2857                           gint         *x,
2858                           gint         *y,
2859                           gint         *width,
2860                           gint         *height)
2861 {
2862   gint w = *width;
2863   gint h = *height;
2864   
2865   switch (arrow_type)
2866     {
2867     case GTK_ARROW_UP:
2868     case GTK_ARROW_DOWN:
2869       w += (w % 2) - 1;
2870       h = (w / 2 + 1);
2871       
2872       if (h > *height)
2873         {
2874           h = *height;
2875           w = 2 * h - 1;
2876         }
2877       
2878       if (arrow_type == GTK_ARROW_DOWN)
2879         {
2880           if (*height % 2 == 1 || h % 2 == 0)
2881             *height += 1;
2882         }
2883       else
2884         {
2885           if (*height % 2 == 0 || h % 2 == 0)
2886             *height -= 1;
2887         }
2888       break;
2889
2890     case GTK_ARROW_RIGHT:
2891     case GTK_ARROW_LEFT:
2892       h += (h % 2) - 1;
2893       w = (h / 2 + 1);
2894       
2895       if (w > *width)
2896         {
2897           w = *width;
2898           h = 2 * w - 1;
2899         }
2900       
2901       if (arrow_type == GTK_ARROW_RIGHT)
2902         {
2903           if (*width % 2 == 1 || w % 2 == 0)
2904             *width += 1;
2905         }
2906       else
2907         {
2908           if (*width % 2 == 0 || w % 2 == 0)
2909             *width -= 1;
2910         }
2911       break;
2912       
2913     default:
2914       /* should not be reached */
2915       break;
2916     }
2917
2918   *x += (*width - w) / 2;
2919   *y += (*height - h) / 2;
2920   *height = h;
2921   *width = w;
2922 }
2923
2924 static void
2925 gtk_default_draw_arrow (GtkStyle      *style,
2926                         GdkWindow     *window,
2927                         GtkStateType   state,
2928                         GtkShadowType  shadow,
2929                         GdkRectangle  *area,
2930                         GtkWidget     *widget,
2931                         const gchar   *detail,
2932                         GtkArrowType   arrow_type,
2933                         gboolean       fill,
2934                         gint           x,
2935                         gint           y,
2936                         gint           width,
2937                         gint           height)
2938 {
2939   gint original_width, original_x;
2940   
2941   sanitize_size (window, &width, &height);
2942
2943   original_width = width;
2944   original_x = x;
2945
2946   calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
2947
2948   if (detail && strcmp (detail, "menuitem") == 0
2949       && gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
2950     x = original_x + original_width - width;
2951
2952   if (state == GTK_STATE_INSENSITIVE)
2953     draw_arrow (window, style->white_gc, area, arrow_type,
2954                 x + 1, y + 1, width, height);
2955   draw_arrow (window, style->fg_gc[state], area, arrow_type,
2956               x, y, width, height);
2957 }
2958
2959 static void
2960 gtk_default_draw_diamond (GtkStyle      *style,
2961                           GdkWindow     *window,
2962                           GtkStateType   state_type,
2963                           GtkShadowType  shadow_type,
2964                           GdkRectangle  *area,
2965                           GtkWidget     *widget,
2966                           const gchar   *detail,
2967                           gint           x,
2968                           gint           y,
2969                           gint           width,
2970                           gint           height)
2971 {
2972   gint half_width;
2973   gint half_height;
2974   GdkGC *outer_nw = NULL;
2975   GdkGC *outer_ne = NULL;
2976   GdkGC *outer_sw = NULL;
2977   GdkGC *outer_se = NULL;
2978   GdkGC *middle_nw = NULL;
2979   GdkGC *middle_ne = NULL;
2980   GdkGC *middle_sw = NULL;
2981   GdkGC *middle_se = NULL;
2982   GdkGC *inner_nw = NULL;
2983   GdkGC *inner_ne = NULL;
2984   GdkGC *inner_sw = NULL;
2985   GdkGC *inner_se = NULL;
2986   
2987   g_return_if_fail (GTK_IS_STYLE (style));
2988   g_return_if_fail (window != NULL);
2989   
2990   sanitize_size (window, &width, &height);
2991   
2992   half_width = width / 2;
2993   half_height = height / 2;
2994   
2995   if (area)
2996     {
2997       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2998       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2999       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3000       gdk_gc_set_clip_rectangle (style->black_gc, area);
3001     }
3002   
3003   switch (shadow_type)
3004     {
3005     case GTK_SHADOW_IN:
3006       inner_sw = inner_se = style->bg_gc[state_type];
3007       middle_sw = middle_se = style->light_gc[state_type];
3008       outer_sw = outer_se = style->light_gc[state_type];
3009       inner_nw = inner_ne = style->black_gc;
3010       middle_nw = middle_ne = style->dark_gc[state_type];
3011       outer_nw = outer_ne = style->dark_gc[state_type];
3012       break;
3013           
3014     case GTK_SHADOW_OUT:
3015       inner_sw = inner_se = style->dark_gc[state_type];
3016       middle_sw = middle_se = style->dark_gc[state_type];
3017       outer_sw = outer_se = style->black_gc;
3018       inner_nw = inner_ne = style->bg_gc[state_type];
3019       middle_nw = middle_ne = style->light_gc[state_type];
3020       outer_nw = outer_ne = style->light_gc[state_type];
3021       break;
3022
3023     case GTK_SHADOW_ETCHED_IN:
3024       inner_sw = inner_se = style->bg_gc[state_type];
3025       middle_sw = middle_se = style->dark_gc[state_type];
3026       outer_sw = outer_se = style->light_gc[state_type];
3027       inner_nw = inner_ne = style->bg_gc[state_type];
3028       middle_nw = middle_ne = style->light_gc[state_type];
3029       outer_nw = outer_ne = style->dark_gc[state_type];
3030       break;
3031
3032     case GTK_SHADOW_ETCHED_OUT:
3033       inner_sw = inner_se = style->bg_gc[state_type];
3034       middle_sw = middle_se = style->light_gc[state_type];
3035       outer_sw = outer_se = style->dark_gc[state_type];
3036       inner_nw = inner_ne = style->bg_gc[state_type];
3037       middle_nw = middle_ne = style->dark_gc[state_type];
3038       outer_nw = outer_ne = style->light_gc[state_type];
3039       break;
3040       
3041     default:
3042
3043       break;
3044     }
3045
3046   if (inner_sw)
3047     {
3048       gdk_draw_line (window, inner_sw,
3049                      x + 2, y + half_height,
3050                      x + half_width, y + height - 2);
3051       gdk_draw_line (window, inner_se,
3052                      x + half_width, y + height - 2,
3053                      x + width - 2, y + half_height);
3054       gdk_draw_line (window, middle_sw,
3055                      x + 1, y + half_height,
3056                      x + half_width, y + height - 1);
3057       gdk_draw_line (window, middle_se,
3058                      x + half_width, y + height - 1,
3059                      x + width - 1, y + half_height);
3060       gdk_draw_line (window, outer_sw,
3061                      x, y + half_height,
3062                      x + half_width, y + height);
3063       gdk_draw_line (window, outer_se,
3064                      x + half_width, y + height,
3065                      x + width, y + half_height);
3066   
3067       gdk_draw_line (window, inner_nw,
3068                      x + 2, y + half_height,
3069                      x + half_width, y + 2);
3070       gdk_draw_line (window, inner_ne,
3071                      x + half_width, y + 2,
3072                      x + width - 2, y + half_height);
3073       gdk_draw_line (window, middle_nw,
3074                      x + 1, y + half_height,
3075                      x + half_width, y + 1);
3076       gdk_draw_line (window, middle_ne,
3077                      x + half_width, y + 1,
3078                      x + width - 1, y + half_height);
3079       gdk_draw_line (window, outer_nw,
3080                      x, y + half_height,
3081                      x + half_width, y);
3082       gdk_draw_line (window, outer_ne,
3083                      x + half_width, y,
3084                      x + width, y + half_height);
3085     }
3086   
3087   if (area)
3088     {
3089       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3090       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
3091       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3092       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
3093     }
3094 }
3095
3096 static void
3097 gtk_default_draw_string (GtkStyle      *style,
3098                          GdkWindow     *window,
3099                          GtkStateType   state_type,
3100                          GdkRectangle  *area,
3101                          GtkWidget     *widget,
3102                          const gchar   *detail,
3103                          gint           x,
3104                          gint           y,
3105                          const gchar   *string)
3106 {
3107   GdkDisplay *display;
3108   
3109   g_return_if_fail (GTK_IS_STYLE (style));
3110   g_return_if_fail (window != NULL);
3111   
3112   display = gdk_drawable_get_display (window);
3113   
3114   if (area)
3115     {
3116       gdk_gc_set_clip_rectangle (style->white_gc, area);
3117       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area);
3118     }
3119
3120   if (state_type == GTK_STATE_INSENSITIVE)
3121     gdk_draw_string (window,
3122                      gtk_style_get_font_internal (style),
3123                      style->white_gc, x + 1, y + 1, string);
3124
3125   gdk_draw_string (window,
3126                    gtk_style_get_font_internal (style),
3127                    style->fg_gc[state_type], x, y, string);
3128
3129   if (area)
3130     {
3131       gdk_gc_set_clip_rectangle (style->white_gc, NULL);
3132       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL);
3133     }
3134 }
3135
3136 static void
3137 option_menu_get_props (GtkWidget      *widget,
3138                        GtkRequisition *indicator_size,
3139                        GtkBorder      *indicator_spacing)
3140 {
3141   GtkRequisition *tmp_size = NULL;
3142   GtkBorder *tmp_spacing = NULL;
3143   
3144   if (widget)
3145     gtk_widget_style_get (widget, 
3146                           "indicator_size", &tmp_size,
3147                           "indicator_spacing", &tmp_spacing,
3148                           NULL);
3149
3150   if (tmp_size)
3151     {
3152       *indicator_size = *tmp_size;
3153       g_free (tmp_size);
3154     }
3155   else
3156     *indicator_size = default_option_indicator_size;
3157
3158   if (tmp_spacing)
3159     {
3160       *indicator_spacing = *tmp_spacing;
3161       g_free (tmp_spacing);
3162     }
3163   else
3164     *indicator_spacing = default_option_indicator_spacing;
3165 }
3166
3167 static void 
3168 gtk_default_draw_box (GtkStyle      *style,
3169                       GdkWindow     *window,
3170                       GtkStateType   state_type,
3171                       GtkShadowType  shadow_type,
3172                       GdkRectangle  *area,
3173                       GtkWidget     *widget,
3174                       const gchar   *detail,
3175                       gint           x,
3176                       gint           y,
3177                       gint           width,
3178                       gint           height)
3179 {
3180   gboolean is_spinbutton_box = FALSE;
3181   
3182   g_return_if_fail (GTK_IS_STYLE (style));
3183   g_return_if_fail (window != NULL);
3184   
3185   sanitize_size (window, &width, &height);
3186
3187   if (widget && GTK_IS_SPIN_BUTTON (widget) && detail)
3188     {
3189       if (strcmp (detail, "spinbutton_up") == 0)
3190         {
3191           y += 2;
3192           width -= 3;
3193           height -= 2;
3194
3195           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3196             x += 2;
3197           else
3198             x += 1;
3199
3200           is_spinbutton_box = TRUE;
3201         }
3202       else if (strcmp (detail, "spinbutton_down") == 0)
3203         {
3204           width -= 3;
3205           height -= 2;
3206
3207           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3208             x += 2;
3209           else
3210             x += 1;
3211
3212           is_spinbutton_box = TRUE;
3213         }
3214     }
3215   
3216   if (!style->bg_pixmap[state_type] || 
3217       GDK_IS_PIXMAP (window))
3218     {
3219       if (area)
3220         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
3221
3222       gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE,
3223                           x, y, width, height);
3224       if (area)
3225         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
3226     }
3227   else
3228     gtk_style_apply_default_background (style, window,
3229                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3230                                         state_type, area, x, y, width, height);
3231
3232   if (is_spinbutton_box)
3233     {
3234       GdkGC *upper_gc;
3235       GdkGC *lower_gc;
3236       
3237       lower_gc = style->dark_gc[state_type];
3238       if (shadow_type == GTK_SHADOW_OUT)
3239         upper_gc = style->light_gc[state_type];
3240       else
3241         upper_gc = style->dark_gc[state_type];
3242
3243       if (area)
3244         {
3245           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3246           gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3247         }
3248       
3249       gdk_draw_line (window, upper_gc, x, y, x + width - 1, y);
3250       gdk_draw_line (window, lower_gc, x, y + height - 1, x + width - 1, y + height - 1);
3251
3252       if (area)
3253         {
3254           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3255           gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3256         }
3257       return;
3258     }
3259
3260   gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
3261                     x, y, width, height);
3262
3263   if (detail && strcmp (detail, "optionmenu") == 0)
3264     {
3265       GtkRequisition indicator_size;
3266       GtkBorder indicator_spacing;
3267       gint vline_x;
3268
3269       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3270
3271       sanitize_size (window, &width, &height);
3272
3273       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3274         vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
3275       else 
3276         vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
3277
3278       gtk_paint_vline (style, window, state_type, area, widget,
3279                        detail,
3280                        y + style->ythickness + 1,
3281                        y + height - style->ythickness - 3,
3282                        vline_x);
3283     }
3284 }
3285
3286 static GdkGC*
3287 get_darkened_gc (GdkWindow *window,
3288                  GdkColor  *color,
3289                  gint       darken_count)
3290 {
3291   GdkColor src = *color;
3292   GdkColor shaded = *color;
3293   GdkGC *gc;
3294   
3295   gc = gdk_gc_new (window);
3296
3297   while (darken_count)
3298     {
3299       gtk_style_shade (&src, &shaded, 0.93);
3300       src = shaded;
3301       --darken_count;
3302     }
3303    
3304   gdk_gc_set_rgb_fg_color (gc, &shaded);
3305
3306   return gc;
3307 }
3308
3309 static void 
3310 gtk_default_draw_flat_box (GtkStyle      *style,
3311                            GdkWindow     *window,
3312                            GtkStateType   state_type,
3313                            GtkShadowType  shadow_type,
3314                            GdkRectangle  *area,
3315                            GtkWidget     *widget,
3316                            const gchar   *detail,
3317                            gint           x,
3318                            gint           y,
3319                            gint           width,
3320                            gint           height)
3321 {
3322   GdkGC *gc1;
3323   GdkGC *freeme = NULL;
3324   
3325   g_return_if_fail (GTK_IS_STYLE (style));
3326   g_return_if_fail (window != NULL);
3327   
3328   sanitize_size (window, &width, &height);
3329   
3330   if (detail)
3331     {
3332       if (state_type == GTK_STATE_SELECTED)
3333         {
3334           if (!strcmp ("text", detail))
3335             gc1 = style->bg_gc[GTK_STATE_SELECTED];
3336           else if (!strncmp ("cell_even", detail, strlen ("cell_even")) ||
3337                    !strncmp ("cell_odd", detail, strlen ("cell_odd")))
3338             {
3339               /* This has to be really broken; alex made me do it. -jrb */
3340               if (GTK_WIDGET_HAS_FOCUS (widget))
3341                 gc1 = style->base_gc[state_type];
3342               else 
3343                 gc1 = style->base_gc[GTK_STATE_ACTIVE];
3344             }
3345           else
3346             {
3347               gc1 = style->bg_gc[state_type];
3348             }
3349         }
3350       else
3351         {
3352           if (!strcmp ("viewportbin", detail))
3353             gc1 = style->bg_gc[GTK_STATE_NORMAL];
3354           else if (!strcmp ("entry_bg", detail))
3355             gc1 = style->base_gc[state_type];
3356
3357           /* For trees: even rows are base color, odd rows are a shade of
3358            * the base color, the sort column is a shade of the original color
3359            * for that row.
3360            */
3361
3362           else if (!strcmp ("cell_even", detail) ||
3363                    !strcmp ("cell_odd", detail) ||
3364                    !strcmp ("cell_even_ruled", detail))
3365             {
3366               GdkColor *color = NULL;
3367
3368               gtk_widget_style_get (widget,
3369                                     "even_row_color", &color,
3370                                     NULL);
3371
3372               if (color)
3373                 {
3374                   freeme = get_darkened_gc (window, color, 0);
3375                   gc1 = freeme;
3376
3377                   gdk_color_free (color);
3378                 }
3379               else
3380                 gc1 = style->base_gc[state_type];
3381             }
3382           else if (!strcmp ("cell_odd_ruled", detail))
3383             {
3384               GdkColor *color;
3385
3386               gtk_widget_style_get (widget,
3387                                     "odd_row_color", &color,
3388                                     NULL);
3389
3390               if (color)
3391                 {
3392                   freeme = get_darkened_gc (window, color, 0);
3393                   gc1 = freeme;
3394
3395                   gdk_color_free (color);
3396                 }
3397               else
3398                 {
3399                   gtk_widget_style_get (widget,
3400                                         "even_row_color", &color,
3401                                         NULL);
3402
3403                   if (color)
3404                     {
3405                       freeme = get_darkened_gc (window, color, 1);
3406                       gdk_color_free (color);
3407                     }
3408                   else
3409                     freeme = get_darkened_gc (window, &style->base[state_type], 1);
3410                   gc1 = freeme;
3411                 }
3412             }
3413           else if (!strcmp ("cell_even_sorted", detail) ||
3414                    !strcmp ("cell_odd_sorted", detail) ||
3415                    !strcmp ("cell_even_ruled_sorted", detail))
3416             {
3417               GdkColor *color = NULL;
3418
3419               if (!strcmp ("cell_odd_sorted", detail))
3420                 gtk_widget_style_get (widget,
3421                                       "odd_row_color", &color,
3422                                       NULL);
3423               else
3424                 gtk_widget_style_get (widget,
3425                                       "even_row_color", &color,
3426                                       NULL);
3427
3428               if (color)
3429                 {
3430                   freeme = get_darkened_gc (window, color, 1);
3431                   gc1 = freeme;
3432
3433                   gdk_color_free (color);
3434                 }
3435               else
3436                 {
3437                   freeme = get_darkened_gc (window, &style->base[state_type], 1);
3438                   gc1 = freeme;
3439                 }
3440             }
3441           else if (!strcmp ("cell_odd_ruled_sorted", detail))
3442             {
3443               GdkColor *color = NULL;
3444
3445               gtk_widget_style_get (widget,
3446                                     "odd_row_color", &color,
3447                                     NULL);
3448
3449               if (color)
3450                 {
3451                   freeme = get_darkened_gc (window, color, 1);
3452                   gc1 = freeme;
3453
3454                   gdk_color_free (color);
3455                 }
3456               else
3457                 {
3458                   gtk_widget_style_get (widget,
3459                                         "even_row_color", &color,
3460                                         NULL);
3461
3462                   if (color)
3463                     {
3464                       freeme = get_darkened_gc (window, color, 2);
3465                       gdk_color_free (color);
3466                     }
3467                   else
3468                     freeme = get_darkened_gc (window, &style->base[state_type], 2);
3469                   gc1 = freeme;
3470                 }
3471             }
3472           else
3473             gc1 = style->bg_gc[state_type];
3474         }
3475     }
3476   else
3477     gc1 = style->bg_gc[state_type];
3478   
3479   if (!style->bg_pixmap[state_type] || gc1 != style->bg_gc[state_type] ||
3480       GDK_IS_PIXMAP (window))
3481     {
3482       if (area)
3483         gdk_gc_set_clip_rectangle (gc1, area);
3484
3485       gdk_draw_rectangle (window, gc1, TRUE,
3486                           x, y, width, height);
3487
3488       if (detail && !strcmp ("tooltip", detail))
3489         gdk_draw_rectangle (window, style->black_gc, FALSE,
3490                             x, y, width - 1, height - 1);
3491
3492       if (area)
3493         gdk_gc_set_clip_rectangle (gc1, NULL);
3494     }
3495   else
3496     gtk_style_apply_default_background (style, window,
3497                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3498                                         state_type, area, x, y, width, height);
3499
3500
3501   if (freeme)
3502     g_object_unref (freeme);
3503 }
3504
3505 static GdkGC *
3506 create_aa_gc (GdkWindow *window, GtkStyle *style, GtkStateType state_type)
3507 {
3508   GdkColor aa_color;
3509   GdkGC *gc = gdk_gc_new (window);
3510    
3511   aa_color.red = (style->fg[state_type].red + style->bg[state_type].red) / 2;
3512   aa_color.green = (style->fg[state_type].green + style->bg[state_type].green) / 2;
3513   aa_color.blue = (style->fg[state_type].blue + style->bg[state_type].blue) / 2;
3514   
3515   gdk_gc_set_rgb_fg_color (gc, &aa_color);
3516
3517   return gc;
3518 }
3519
3520 static void 
3521 gtk_default_draw_check (GtkStyle      *style,
3522                         GdkWindow     *window,
3523                         GtkStateType   state_type,
3524                         GtkShadowType  shadow_type,
3525                         GdkRectangle  *area,
3526                         GtkWidget     *widget,
3527                         const gchar   *detail,
3528                         gint           x,
3529                         gint           y,
3530                         gint           width,
3531                         gint           height)
3532 {
3533   if (detail && strcmp (detail, "cellcheck") == 0)
3534     {
3535       gdk_draw_rectangle (window,
3536                           widget->style->base_gc[state_type],
3537                           TRUE,
3538                           x, y,
3539                           width, height);
3540       gdk_draw_rectangle (window,
3541                           widget->style->text_gc[state_type],
3542                           FALSE,
3543                           x, y,
3544                           width, height);
3545
3546       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3547       y -= (((1 + INDICATOR_PART_SIZE - height) / 2) - 1);
3548       if (shadow_type == GTK_SHADOW_IN)
3549         {
3550           draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT);
3551           draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA);
3552         }
3553       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3554         {
3555           draw_part (window, style->text_gc[state_type], area, x, y, CHECK_INCONSISTENT_TEXT);
3556         }
3557     }
3558   else
3559     {
3560       GdkGC *free_me = NULL;
3561       
3562       GdkGC *base_gc;
3563       GdkGC *text_gc;
3564       GdkGC *aa_gc;
3565
3566       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3567       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3568
3569       if (strcmp (detail, "check") == 0)        /* Menu item */
3570         {
3571           text_gc = style->fg_gc[state_type];
3572           base_gc = style->bg_gc[state_type];
3573           aa_gc = free_me = create_aa_gc (window, style, state_type);
3574         }
3575       else
3576         {
3577           if (state_type == GTK_STATE_ACTIVE)
3578             {
3579               text_gc = style->fg_gc[state_type];
3580               base_gc = style->bg_gc[state_type];
3581               aa_gc = free_me = create_aa_gc (window, style, state_type);
3582             }
3583           else
3584             {
3585               text_gc = style->text_gc[state_type];
3586               base_gc = style->base_gc[state_type];
3587               aa_gc = style->text_aa_gc[state_type];
3588             }
3589
3590           draw_part (window, base_gc, area, x, y, CHECK_BASE);
3591           draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
3592           draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_DARK);
3593           draw_part (window, style->mid_gc[state_type], area, x, y, CHECK_MID);
3594           draw_part (window, style->light_gc[state_type], area, x, y, CHECK_LIGHT);
3595         }
3596
3597       if (shadow_type == GTK_SHADOW_IN)
3598         {
3599           draw_part (window, text_gc, area, x, y, CHECK_TEXT);
3600           draw_part (window, aa_gc, area, x, y, CHECK_AA);
3601         }
3602       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3603         {
3604           draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT);
3605         }
3606
3607       if (free_me)
3608         g_object_unref (G_OBJECT (free_me));
3609     }
3610 }
3611
3612 static void 
3613 gtk_default_draw_option (GtkStyle      *style,
3614                          GdkWindow     *window,
3615                          GtkStateType   state_type,
3616                          GtkShadowType  shadow_type,
3617                          GdkRectangle  *area,
3618                          GtkWidget     *widget,
3619                          const gchar   *detail,
3620                          gint           x,
3621                          gint           y,
3622                          gint           width,
3623                          gint           height)
3624 {
3625   if (detail && strcmp (detail, "cellradio") == 0)
3626     {
3627       gdk_draw_arc (window,
3628                     widget->style->fg_gc[state_type],
3629                     FALSE,
3630                     x, y,
3631                     width,
3632                     height,
3633                     0, 360*64);
3634
3635       if (shadow_type == GTK_SHADOW_IN)
3636         {
3637           gdk_draw_arc (window,
3638                         widget->style->fg_gc[state_type],
3639                         TRUE,
3640                         x + 2,
3641                         y + 2,
3642                         width - 4,
3643                         height - 4,
3644                         0, 360*64);
3645         }
3646       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3647         {
3648           draw_part (window, widget->style->fg_gc[state_type],
3649                      area, x, y, CHECK_INCONSISTENT_TEXT);
3650         }
3651     }
3652   else
3653     {
3654       GdkGC *free_me = NULL;
3655       
3656       GdkGC *base_gc;
3657       GdkGC *text_gc;
3658       GdkGC *aa_gc;
3659
3660       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3661       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3662
3663       if (strcmp (detail, "option") == 0)       /* Menu item */
3664         {
3665           text_gc = style->fg_gc[state_type];
3666           base_gc = style->bg_gc[state_type];
3667           aa_gc = free_me = create_aa_gc (window, style, state_type);
3668         }
3669       else
3670         {
3671           if (state_type == GTK_STATE_ACTIVE)
3672             {
3673               text_gc = style->fg_gc[state_type];
3674               base_gc = style->bg_gc[state_type];
3675               aa_gc = free_me = create_aa_gc (window, style, state_type);
3676             }
3677           else
3678             {
3679               text_gc = style->text_gc[state_type];
3680               base_gc = style->base_gc[state_type];
3681               aa_gc = style->text_aa_gc[state_type];
3682             }
3683
3684           draw_part (window, base_gc, area, x, y, RADIO_BASE);
3685           draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
3686           draw_part (window, style->dark_gc[state_type], area, x, y, RADIO_DARK);
3687           draw_part (window, style->mid_gc[state_type], area, x, y, RADIO_MID);
3688           draw_part (window, style->light_gc[state_type], area, x, y, RADIO_LIGHT);
3689         }
3690
3691       if (shadow_type == GTK_SHADOW_IN)
3692         {
3693           draw_part (window, text_gc, area, x, y, RADIO_TEXT);
3694         }
3695       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3696         {
3697           if (strcmp (detail, "option") == 0)  /* Menu item */
3698             {
3699               draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT);
3700             }
3701           else
3702             {
3703               draw_part (window, text_gc, area, x, y, RADIO_INCONSISTENT_TEXT);
3704               draw_part (window, aa_gc, area, x, y, RADIO_INCONSISTENT_AA);
3705             }
3706         }
3707
3708       if (free_me)
3709         g_object_unref (G_OBJECT (free_me));
3710     }
3711 }
3712
3713 static void
3714 gtk_default_draw_tab (GtkStyle      *style,
3715                       GdkWindow     *window,
3716                       GtkStateType   state_type,
3717                       GtkShadowType  shadow_type,
3718                       GdkRectangle  *area,
3719                       GtkWidget     *widget,
3720                       const gchar   *detail,
3721                       gint           x,
3722                       gint           y,
3723                       gint           width,
3724                       gint           height)
3725 {
3726 #define ARROW_SPACE 4
3727
3728   GtkRequisition indicator_size;
3729   GtkBorder indicator_spacing;
3730   gint arrow_height;
3731   
3732   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3733
3734   indicator_size.width += (indicator_size.width % 2) - 1;
3735   arrow_height = indicator_size.width / 2 + 1;
3736
3737   x += (width - indicator_size.width) / 2;
3738   y += (height - (2 * arrow_height + ARROW_SPACE)) / 2;
3739
3740   if (state_type == GTK_STATE_INSENSITIVE)
3741     {
3742       draw_arrow (window, style->white_gc, area,
3743                   GTK_ARROW_UP, x + 1, y + 1,
3744                   indicator_size.width, arrow_height);
3745       
3746       draw_arrow (window, style->white_gc, area,
3747                   GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1,
3748                   indicator_size.width, arrow_height);
3749     }
3750   
3751   draw_arrow (window, style->fg_gc[state_type], area,
3752               GTK_ARROW_UP, x, y,
3753               indicator_size.width, arrow_height);
3754   
3755   
3756   draw_arrow (window, style->fg_gc[state_type], area,
3757               GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE,
3758               indicator_size.width, arrow_height);
3759 }
3760
3761 static void 
3762 gtk_default_draw_shadow_gap (GtkStyle       *style,
3763                              GdkWindow      *window,
3764                              GtkStateType    state_type,
3765                              GtkShadowType   shadow_type,
3766                              GdkRectangle   *area,
3767                              GtkWidget      *widget,
3768                              const gchar    *detail,
3769                              gint            x,
3770                              gint            y,
3771                              gint            width,
3772                              gint            height,
3773                              GtkPositionType gap_side,
3774                              gint            gap_x,
3775                              gint            gap_width)
3776 {
3777   GdkGC *gc1 = NULL;
3778   GdkGC *gc2 = NULL;
3779   GdkGC *gc3 = NULL;
3780   GdkGC *gc4 = NULL;
3781   
3782   g_return_if_fail (GTK_IS_STYLE (style));
3783   g_return_if_fail (window != NULL);
3784   
3785   sanitize_size (window, &width, &height);
3786   
3787   switch (shadow_type)
3788     {
3789     case GTK_SHADOW_NONE:
3790       return;
3791     case GTK_SHADOW_IN:
3792       gc1 = style->dark_gc[state_type];
3793       gc2 = style->black_gc;
3794       gc3 = style->bg_gc[state_type];
3795       gc4 = style->light_gc[state_type];
3796       break;
3797     case GTK_SHADOW_ETCHED_IN:
3798       gc1 = style->dark_gc[state_type];
3799       gc2 = style->light_gc[state_type];
3800       gc3 = style->dark_gc[state_type];
3801       gc4 = style->light_gc[state_type];
3802       break;
3803     case GTK_SHADOW_OUT:
3804       gc1 = style->light_gc[state_type];
3805       gc2 = style->bg_gc[state_type];
3806       gc3 = style->dark_gc[state_type];
3807       gc4 = style->black_gc;
3808       break;
3809     case GTK_SHADOW_ETCHED_OUT:
3810       gc1 = style->light_gc[state_type];
3811       gc2 = style->dark_gc[state_type];
3812       gc3 = style->light_gc[state_type];
3813       gc4 = style->dark_gc[state_type];
3814       break;
3815     }
3816   if (area)
3817     {
3818       gdk_gc_set_clip_rectangle (gc1, area);
3819       gdk_gc_set_clip_rectangle (gc2, area);
3820       gdk_gc_set_clip_rectangle (gc3, area);
3821       gdk_gc_set_clip_rectangle (gc4, area);
3822     }
3823   
3824   switch (shadow_type)
3825     {
3826     case GTK_SHADOW_NONE:
3827     case GTK_SHADOW_IN:
3828     case GTK_SHADOW_OUT:
3829     case GTK_SHADOW_ETCHED_IN:
3830     case GTK_SHADOW_ETCHED_OUT:
3831       switch (gap_side)
3832         {
3833         case GTK_POS_TOP:
3834           gdk_draw_line (window, gc1,
3835                          x, y, x, y + height - 1);
3836           gdk_draw_line (window, gc2,
3837                          x + 1, y, x + 1, y + height - 2);
3838           
3839           gdk_draw_line (window, gc3,
3840                          x + 1, y + height - 2, x + width - 2, y + height - 2);
3841           gdk_draw_line (window, gc3,
3842                          x + width - 2, y, x + width - 2, y + height - 2);
3843           gdk_draw_line (window, gc4,
3844                          x, y + height - 1, x + width - 1, y + height - 1);
3845           gdk_draw_line (window, gc4,
3846                          x + width - 1, y, x + width - 1, y + height - 1);
3847           if (gap_x > 0)
3848             {
3849               gdk_draw_line (window, gc1,
3850                              x, y, x + gap_x - 1, y);
3851               gdk_draw_line (window, gc2,
3852                              x + 1, y + 1, x + gap_x - 1, y + 1);
3853               gdk_draw_line (window, gc2,
3854                              x + gap_x, y, x + gap_x, y);
3855             }
3856           if ((width - (gap_x + gap_width)) > 0)
3857             {
3858               gdk_draw_line (window, gc1,
3859                              x + gap_x + gap_width, y, x + width - 2, y);
3860               gdk_draw_line (window, gc2,
3861                              x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
3862               gdk_draw_line (window, gc2,
3863                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3864             }
3865           break;
3866         case GTK_POS_BOTTOM:
3867           gdk_draw_line (window, gc1,
3868                          x, y, x + width - 1, y);
3869           gdk_draw_line (window, gc1,
3870                          x, y, x, y + height - 1);
3871           gdk_draw_line (window, gc2,
3872                          x + 1, y + 1, x + width - 2, y + 1);
3873           gdk_draw_line (window, gc2,
3874                          x + 1, y + 1, x + 1, y + height - 1);
3875           
3876           gdk_draw_line (window, gc3,
3877                          x + width - 2, y + 1, x + width - 2, y + height - 1);
3878           gdk_draw_line (window, gc4,
3879                          x + width - 1, y, x + width - 1, y + height - 1);
3880           if (gap_x > 0)
3881             {
3882               gdk_draw_line (window, gc4,
3883                              x, y + height - 1, x + gap_x - 1, y + height - 1);
3884               gdk_draw_line (window, gc3,
3885                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3886               gdk_draw_line (window, gc3,
3887                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3888             }
3889           if ((width - (gap_x + gap_width)) > 0)
3890             {
3891               gdk_draw_line (window, gc4,
3892                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3893               gdk_draw_line (window, gc3,
3894                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3895               gdk_draw_line (window, gc3,
3896                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3897             }
3898           break;
3899         case GTK_POS_LEFT:
3900           gdk_draw_line (window, gc1,
3901                          x, y, x + width - 1, y);
3902           gdk_draw_line (window, gc2,
3903                          x, y + 1, x + width - 2, y + 1);
3904           
3905           gdk_draw_line (window, gc3,
3906                          x, y + height - 2, x + width - 2, y + height - 2);
3907           gdk_draw_line (window, gc3,
3908                          x + width - 2, y + 1, x + width - 2, y + height - 2);
3909           gdk_draw_line (window, gc4,
3910                          x, y + height - 1, x + width - 1, y + height - 1);
3911           gdk_draw_line (window, gc4,
3912                          x + width - 1, y, x + width - 1, y + height - 1);
3913           if (gap_x > 0)
3914             {
3915               gdk_draw_line (window, gc1,
3916                              x, y, x, y + gap_x - 1);
3917               gdk_draw_line (window, gc2,
3918                              x + 1, y + 1, x + 1, y + gap_x - 1);
3919               gdk_draw_line (window, gc2,
3920                              x, y + gap_x, x, y + gap_x);
3921             }
3922           if ((width - (gap_x + gap_width)) > 0)
3923             {
3924               gdk_draw_line (window, gc1,
3925                              x, y + gap_x + gap_width, x, y + height - 2);
3926               gdk_draw_line (window, gc2,
3927                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3928               gdk_draw_line (window, gc2,
3929                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3930             }
3931           break;
3932         case GTK_POS_RIGHT:
3933           gdk_draw_line (window, gc1,
3934                          x, y, x + width - 1, y);
3935           gdk_draw_line (window, gc1,
3936                          x, y, x, y + height - 1);
3937           gdk_draw_line (window, gc2,
3938                          x + 1, y + 1, x + width - 1, y + 1);
3939           gdk_draw_line (window, gc2,
3940                          x + 1, y + 1, x + 1, y + height - 2);
3941           
3942           gdk_draw_line (window, gc3,
3943                          x + 1, y + height - 2, x + width - 1, y + height - 2);
3944           gdk_draw_line (window, gc4,
3945                          x, y + height - 1, x + width - 1, y + height - 1);
3946           if (gap_x > 0)
3947             {
3948               gdk_draw_line (window, gc4,
3949                              x + width - 1, y, x + width - 1, y + gap_x - 1);
3950               gdk_draw_line (window, gc3,
3951                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3952               gdk_draw_line (window, gc3,
3953                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3954             }
3955           if ((width - (gap_x + gap_width)) > 0)
3956             {
3957               gdk_draw_line (window, gc4,
3958                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3959               gdk_draw_line (window, gc3,
3960                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3961               gdk_draw_line (window, gc3,
3962                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3963             }
3964           break;
3965         }
3966     }
3967
3968   if (area)
3969     {
3970       gdk_gc_set_clip_rectangle (gc1, NULL);
3971       gdk_gc_set_clip_rectangle (gc2, NULL);
3972       gdk_gc_set_clip_rectangle (gc3, NULL);
3973       gdk_gc_set_clip_rectangle (gc4, NULL);
3974     }
3975 }
3976
3977 static void 
3978 gtk_default_draw_box_gap (GtkStyle       *style,
3979                           GdkWindow      *window,
3980                           GtkStateType    state_type,
3981                           GtkShadowType   shadow_type,
3982                           GdkRectangle   *area,
3983                           GtkWidget      *widget,
3984                           const gchar    *detail,
3985                           gint            x,
3986                           gint            y,
3987                           gint            width,
3988                           gint            height,
3989                           GtkPositionType gap_side,
3990                           gint            gap_x,
3991                           gint            gap_width)
3992 {
3993   GdkGC *gc1 = NULL;
3994   GdkGC *gc2 = NULL;
3995   GdkGC *gc3 = NULL;
3996   GdkGC *gc4 = NULL;
3997   
3998   g_return_if_fail (GTK_IS_STYLE (style));
3999   g_return_if_fail (window != NULL);
4000   
4001   gtk_style_apply_default_background (style, window,
4002                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4003                                       state_type, area, x, y, width, height);
4004   
4005   sanitize_size (window, &width, &height);
4006   
4007   switch (shadow_type)
4008     {
4009     case GTK_SHADOW_NONE:
4010       return;
4011     case GTK_SHADOW_IN:
4012       gc1 = style->dark_gc[state_type];
4013       gc2 = style->black_gc;
4014       gc3 = style->bg_gc[state_type];
4015       gc4 = style->light_gc[state_type];
4016       break;
4017     case GTK_SHADOW_ETCHED_IN:
4018       gc1 = style->dark_gc[state_type];
4019       gc2 = style->light_gc[state_type];
4020       gc3 = style->dark_gc[state_type];
4021       gc4 = style->light_gc[state_type];
4022       break;
4023     case GTK_SHADOW_OUT:
4024       gc1 = style->light_gc[state_type];
4025       gc2 = style->bg_gc[state_type];
4026       gc3 = style->dark_gc[state_type];
4027       gc4 = style->black_gc;
4028       break;
4029     case GTK_SHADOW_ETCHED_OUT:
4030       gc1 = style->light_gc[state_type];
4031       gc2 = style->dark_gc[state_type];
4032       gc3 = style->light_gc[state_type];
4033       gc4 = style->dark_gc[state_type];
4034       break;
4035     }
4036
4037   if (area)
4038     {
4039       gdk_gc_set_clip_rectangle (gc1, area);
4040       gdk_gc_set_clip_rectangle (gc2, area);
4041       gdk_gc_set_clip_rectangle (gc3, area);
4042       gdk_gc_set_clip_rectangle (gc4, area);
4043     }
4044   
4045   switch (shadow_type)
4046     {
4047     case GTK_SHADOW_NONE:
4048     case GTK_SHADOW_IN:
4049     case GTK_SHADOW_OUT:
4050     case GTK_SHADOW_ETCHED_IN:
4051     case GTK_SHADOW_ETCHED_OUT:
4052       switch (gap_side)
4053         {
4054         case GTK_POS_TOP:
4055           gdk_draw_line (window, gc1,
4056                          x, y, x, y + height - 1);
4057           gdk_draw_line (window, gc2,
4058                          x + 1, y, x + 1, y + height - 2);
4059           
4060           gdk_draw_line (window, gc3,
4061                          x + 1, y + height - 2, x + width - 2, y + height - 2);
4062           gdk_draw_line (window, gc3,
4063                          x + width - 2, y, x + width - 2, y + height - 2);
4064           gdk_draw_line (window, gc4,
4065                          x, y + height - 1, x + width - 1, y + height - 1);
4066           gdk_draw_line (window, gc4,
4067                          x + width - 1, y, x + width - 1, y + height - 1);
4068           if (gap_x > 0)
4069             {
4070               gdk_draw_line (window, gc1,
4071                              x, y, x + gap_x - 1, y);
4072               gdk_draw_line (window, gc2,
4073                              x + 1, y + 1, x + gap_x - 1, y + 1);
4074               gdk_draw_line (window, gc2,
4075                              x + gap_x, y, x + gap_x, y);
4076             }
4077           if ((width - (gap_x + gap_width)) > 0)
4078             {
4079               gdk_draw_line (window, gc1,
4080                              x + gap_x + gap_width, y, x + width - 2, y);
4081               gdk_draw_line (window, gc2,
4082                              x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
4083               gdk_draw_line (window, gc2,
4084                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
4085             }
4086           break;
4087         case  GTK_POS_BOTTOM:
4088           gdk_draw_line (window, gc1,
4089                          x, y, x + width - 1, y);
4090           gdk_draw_line (window, gc1,
4091                          x, y, x, y + height - 1);
4092           gdk_draw_line (window, gc2,
4093                          x + 1, y + 1, x + width - 2, y + 1);
4094           gdk_draw_line (window, gc2,
4095                          x + 1, y + 1, x + 1, y + height - 1);
4096           
4097           gdk_draw_line (window, gc3,
4098                          x + width - 2, y + 1, x + width - 2, y + height - 1);
4099           gdk_draw_line (window, gc4,
4100                          x + width - 1, y, x + width - 1, y + height - 1);
4101           if (gap_x > 0)
4102             {
4103               gdk_draw_line (window, gc4,
4104                              x, y + height - 1, x + gap_x - 1, y + height - 1);
4105               gdk_draw_line (window, gc3,
4106                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
4107               gdk_draw_line (window, gc3,
4108                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
4109             }
4110           if ((width - (gap_x + gap_width)) > 0)
4111             {
4112               gdk_draw_line (window, gc4,
4113                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
4114               gdk_draw_line (window, gc3,
4115                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
4116               gdk_draw_line (window, gc3,
4117                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
4118             }
4119           break;
4120         case GTK_POS_LEFT:
4121           gdk_draw_line (window, gc1,
4122                          x, y, x + width - 1, y);
4123           gdk_draw_line (window, gc2,
4124                          x, y + 1, x + width - 2, y + 1);
4125           
4126           gdk_draw_line (window, gc3,
4127                          x, y + height - 2, x + width - 2, y + height - 2);
4128           gdk_draw_line (window, gc3,
4129                          x + width - 2, y + 1, x + width - 2, y + height - 2);
4130           gdk_draw_line (window, gc4,
4131                          x, y + height - 1, x + width - 1, y + height - 1);
4132           gdk_draw_line (window, gc4,
4133                          x + width - 1, y, x + width - 1, y + height - 1);
4134           if (gap_x > 0)
4135             {
4136               gdk_draw_line (window, gc1,
4137                              x, y, x, y + gap_x - 1);
4138               gdk_draw_line (window, gc2,
4139                              x + 1, y + 1, x + 1, y + gap_x - 1);
4140               gdk_draw_line (window, gc2,
4141                              x, y + gap_x, x, y + gap_x);
4142             }
4143           if ((width - (gap_x + gap_width)) > 0)
4144             {
4145               gdk_draw_line (window, gc1,
4146                              x, y + gap_x + gap_width, x, y + height - 2);
4147               gdk_draw_line (window, gc2,
4148                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
4149               gdk_draw_line (window, gc2,
4150                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
4151             }
4152           break;
4153         case GTK_POS_RIGHT:
4154           gdk_draw_line (window, gc1,
4155                          x, y, x + width - 1, y);
4156           gdk_draw_line (window, gc1,
4157                          x, y, x, y + height - 1);
4158           gdk_draw_line (window, gc2,
4159                          x + 1, y + 1, x + width - 1, y + 1);
4160           gdk_draw_line (window, gc2,
4161                          x + 1, y + 1, x + 1, y + height - 2);
4162           
4163           gdk_draw_line (window, gc3,
4164                          x + 1, y + height - 2, x + width - 1, y + height - 2);
4165           gdk_draw_line (window, gc4,
4166                          x, y + height - 1, x + width - 1, y + height - 1);
4167           if (gap_x > 0)
4168             {
4169               gdk_draw_line (window, gc4,
4170                              x + width - 1, y, x + width - 1, y + gap_x - 1);
4171               gdk_draw_line (window, gc3,
4172                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
4173               gdk_draw_line (window, gc3,
4174                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
4175             }
4176           if ((width - (gap_x + gap_width)) > 0)
4177             {
4178               gdk_draw_line (window, gc4,
4179                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
4180               gdk_draw_line (window, gc3,
4181                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
4182               gdk_draw_line (window, gc3,
4183                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
4184             }
4185           break;
4186         }
4187     }
4188
4189   if (area)
4190     {
4191       gdk_gc_set_clip_rectangle (gc1, NULL);
4192       gdk_gc_set_clip_rectangle (gc2, NULL);
4193       gdk_gc_set_clip_rectangle (gc3, NULL);
4194       gdk_gc_set_clip_rectangle (gc4, NULL);
4195     }
4196 }
4197
4198 static void 
4199 gtk_default_draw_extension (GtkStyle       *style,
4200                             GdkWindow      *window,
4201                             GtkStateType    state_type,
4202                             GtkShadowType   shadow_type,
4203                             GdkRectangle   *area,
4204                             GtkWidget      *widget,
4205                             const gchar    *detail,
4206                             gint            x,
4207                             gint            y,
4208                             gint            width,
4209                             gint            height,
4210                             GtkPositionType gap_side)
4211 {
4212   GdkGC *gc1 = NULL;
4213   GdkGC *gc2 = NULL;
4214   GdkGC *gc3 = NULL;
4215   GdkGC *gc4 = NULL;
4216   
4217   g_return_if_fail (GTK_IS_STYLE (style));
4218   g_return_if_fail (window != NULL);
4219   
4220   gtk_style_apply_default_background (style, window,
4221                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4222                                       GTK_STATE_NORMAL, area, x, y, width, height);
4223   
4224   sanitize_size (window, &width, &height);
4225   
4226   switch (shadow_type)
4227     {
4228     case GTK_SHADOW_NONE:
4229       return;
4230     case GTK_SHADOW_IN:
4231       gc1 = style->dark_gc[state_type];
4232       gc2 = style->black_gc;
4233       gc3 = style->bg_gc[state_type];
4234       gc4 = style->light_gc[state_type];
4235       break;
4236     case GTK_SHADOW_ETCHED_IN:
4237       gc1 = style->dark_gc[state_type];
4238       gc2 = style->light_gc[state_type];
4239       gc3 = style->dark_gc[state_type];
4240       gc4 = style->light_gc[state_type];
4241       break;
4242     case GTK_SHADOW_OUT:
4243       gc1 = style->light_gc[state_type];
4244       gc2 = style->bg_gc[state_type];
4245       gc3 = style->dark_gc[state_type];
4246       gc4 = style->black_gc;
4247       break;
4248     case GTK_SHADOW_ETCHED_OUT:
4249       gc1 = style->light_gc[state_type];
4250       gc2 = style->dark_gc[state_type];
4251       gc3 = style->light_gc[state_type];
4252       gc4 = style->dark_gc[state_type];
4253       break;
4254     }
4255
4256   if (area)
4257     {
4258       gdk_gc_set_clip_rectangle (gc1, area);
4259       gdk_gc_set_clip_rectangle (gc2, area);
4260       gdk_gc_set_clip_rectangle (gc3, area);
4261       gdk_gc_set_clip_rectangle (gc4, area);
4262     }
4263
4264   switch (shadow_type)
4265     {
4266     case GTK_SHADOW_NONE:
4267     case GTK_SHADOW_IN:
4268     case GTK_SHADOW_OUT:
4269     case GTK_SHADOW_ETCHED_IN:
4270     case GTK_SHADOW_ETCHED_OUT:
4271       switch (gap_side)
4272         {
4273         case GTK_POS_TOP:
4274           gtk_style_apply_default_background (style, window,
4275                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4276                                               state_type, area,
4277                                               x + style->xthickness, 
4278                                               y, 
4279                                               width - (2 * style->xthickness), 
4280                                               height - (style->ythickness));
4281           gdk_draw_line (window, gc1,
4282                          x, y, x, y + height - 2);
4283           gdk_draw_line (window, gc2,
4284                          x + 1, y, x + 1, y + height - 2);
4285           
4286           gdk_draw_line (window, gc3,
4287                          x + 2, y + height - 2, x + width - 2, y + height - 2);
4288           gdk_draw_line (window, gc3,
4289                          x + width - 2, y, x + width - 2, y + height - 2);
4290           gdk_draw_line (window, gc4,
4291                          x + 1, y + height - 1, x + width - 2, y + height - 1);
4292           gdk_draw_line (window, gc4,
4293                          x + width - 1, y, x + width - 1, y + height - 2);
4294           break;
4295         case GTK_POS_BOTTOM:
4296           gtk_style_apply_default_background (style, window,
4297                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4298                                               state_type, area,
4299                                               x + style->xthickness, 
4300                                               y + style->ythickness, 
4301                                               width - (2 * style->xthickness), 
4302                                               height - (style->ythickness));
4303           gdk_draw_line (window, gc1,
4304                          x + 1, y, x + width - 2, y);
4305           gdk_draw_line (window, gc1,
4306                          x, y + 1, x, y + height - 1);
4307           gdk_draw_line (window, gc2,
4308                          x + 1, y + 1, x + width - 2, y + 1);
4309           gdk_draw_line (window, gc2,
4310                          x + 1, y + 1, x + 1, y + height - 1);
4311           
4312           gdk_draw_line (window, gc3,
4313                          x + width - 2, y + 2, x + width - 2, y + height - 1);
4314           gdk_draw_line (window, gc4,
4315                          x + width - 1, y + 1, x + width - 1, y + height - 1);
4316           break;
4317         case GTK_POS_LEFT:
4318           gtk_style_apply_default_background (style, window,
4319                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4320                                               state_type, area,
4321                                               x, 
4322                                               y + style->ythickness, 
4323                                               width - (style->xthickness), 
4324                                               height - (2 * style->ythickness));
4325           gdk_draw_line (window, gc1,
4326                          x, y, x + width - 2, y);
4327           gdk_draw_line (window, gc2,
4328                          x + 1, y + 1, x + width - 2, y + 1);
4329           
4330           gdk_draw_line (window, gc3,
4331                          x, y + height - 2, x + width - 2, y + height - 2);
4332           gdk_draw_line (window, gc3,
4333                          x + width - 2, y + 2, x + width - 2, y + height - 2);
4334           gdk_draw_line (window, gc4,
4335                          x, y + height - 1, x + width - 2, y + height - 1);
4336           gdk_draw_line (window, gc4,
4337                          x + width - 1, y + 1, x + width - 1, y + height - 2);
4338           break;
4339         case GTK_POS_RIGHT:
4340           gtk_style_apply_default_background (style, window,
4341                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4342                                               state_type, area,
4343                                               x + style->xthickness, 
4344                                               y + style->ythickness, 
4345                                               width - (style->xthickness), 
4346                                               height - (2 * style->ythickness));
4347           gdk_draw_line (window, gc1,
4348                          x + 1, y, x + width - 1, y);
4349           gdk_draw_line (window, gc1,
4350                          x, y + 1, x, y + height - 2);
4351           gdk_draw_line (window, gc2,
4352                          x + 1, y + 1, x + width - 1, y + 1);
4353           gdk_draw_line (window, gc2,
4354                          x + 1, y + 1, x + 1, y + height - 2);
4355           
4356           gdk_draw_line (window, gc3,
4357                          x + 2, y + height - 2, x + width - 1, y + height - 2);
4358           gdk_draw_line (window, gc4,
4359                          x + 1, y + height - 1, x + width - 1, y + height - 1);
4360           break;
4361         }
4362     }
4363
4364   if (area)
4365     {
4366       gdk_gc_set_clip_rectangle (gc1, NULL);
4367       gdk_gc_set_clip_rectangle (gc2, NULL);
4368       gdk_gc_set_clip_rectangle (gc3, NULL);
4369       gdk_gc_set_clip_rectangle (gc4, NULL);
4370     }
4371 }
4372
4373 static void 
4374 gtk_default_draw_focus (GtkStyle      *style,
4375                         GdkWindow     *window,
4376                         GtkStateType   state_type,
4377                         GdkRectangle  *area,
4378                         GtkWidget     *widget,
4379                         const gchar   *detail,
4380                         gint           x,
4381                         gint           y,
4382                         gint           width,
4383                         gint           height)
4384 {
4385   GdkPoint points[5];
4386   GdkGC    *gc;
4387   gboolean free_dash_list = FALSE;
4388   gint line_width = 1;
4389   gint8 *dash_list = "\1\1";
4390   gint dash_len;
4391
4392   gc = style->fg_gc[state_type];
4393
4394   if (widget)
4395     {
4396       gtk_widget_style_get (widget,
4397                             "focus-line-width", &line_width,
4398                             "focus-line-pattern", (gchar *)&dash_list,
4399                             NULL);
4400
4401       free_dash_list = TRUE;
4402   }
4403
4404   sanitize_size (window, &width, &height);
4405   
4406   if (area)
4407     gdk_gc_set_clip_rectangle (gc, area);
4408
4409   gdk_gc_set_line_attributes (gc, line_width,
4410                               dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID,
4411                               GDK_CAP_BUTT, GDK_JOIN_MITER);
4412
4413
4414   if (detail && !strcmp (detail, "add-mode"))
4415     {
4416       if (free_dash_list)
4417         g_free (dash_list);
4418       
4419       dash_list = "\4\4";
4420       free_dash_list = FALSE;
4421     }
4422
4423   points[0].x = x + line_width / 2;
4424   points[0].y = y + line_width / 2;
4425   points[1].x = x + width - line_width + line_width / 2;
4426   points[1].y = y + line_width / 2;
4427   points[2].x = x + width - line_width + line_width / 2;
4428   points[2].y = y + height - line_width + line_width / 2;
4429   points[3].x = x + line_width / 2;
4430   points[3].y = y + height - line_width + line_width / 2;
4431   points[4] = points[0];
4432
4433   if (!dash_list[0])
4434     {
4435       gdk_draw_lines (window, gc, points, 5);
4436     }
4437   else
4438     {
4439       /* We go through all the pain below because the X rasterization
4440        * rules don't really work right for dashed lines if you
4441        * want continuity in segments that go between top/right
4442        * and left/bottom. For instance, a top left corner
4443        * with a 1-1 dash is drawn as:
4444        *
4445        *  X X X 
4446        *  X
4447        *
4448        *  X
4449        *
4450        * This is because pixels on the top and left boundaries
4451        * of polygons are drawn, but not on the bottom and right.
4452        * So, if you have a line going up that turns the corner
4453        * and goes right, there is a one pixel shift in the pattern.
4454        *
4455        * So, to fix this, we drawn the top and right in one call,
4456        * then the left and bottom in another call, fixing up
4457        * the dash offset for the second call ourselves to get
4458        * continuity at the upper left.
4459        *
4460        * It's not perfect since we really should have a join at
4461        * the upper left and lower right instead of two intersecting
4462        * lines but that's only really apparent for no-dashes,
4463        * which (for this reason) are done as one polygon and
4464        * don't to through this code path.
4465        */
4466       
4467       dash_len = strlen (dash_list);
4468       
4469       if (dash_list[0])
4470         gdk_gc_set_dashes (gc, 0, dash_list, dash_len);
4471       
4472       gdk_draw_lines (window, gc, points, 3);
4473       
4474       /* We draw this line one farther over than it is "supposed" to
4475        * because of another rasterization problem ... if two 1 pixel
4476        * unjoined lines meet at the lower right, there will be a missing
4477        * pixel.
4478        */
4479       points[2].x += 1;
4480       
4481       if (dash_list[0])
4482         {
4483           gint dash_pixels = 0;
4484           gint i;
4485           
4486           /* Adjust the dash offset for the bottom and left so we
4487            * match up at the upper left.
4488            */
4489           for (i = 0; i < dash_len; i++)
4490             dash_pixels += dash_list[i];
4491       
4492           if (dash_len % 2 == 1)
4493             dash_pixels *= 2;
4494           
4495           gdk_gc_set_dashes (gc, dash_pixels - (width + height - 2 * line_width) % dash_pixels, dash_list, dash_len);
4496         }
4497       
4498       gdk_draw_lines (window, gc, points + 2, 3);
4499     }
4500
4501   gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
4502
4503   if (area)
4504     gdk_gc_set_clip_rectangle (gc, NULL);
4505
4506   if (free_dash_list)
4507     g_free (dash_list);
4508 }
4509
4510 static void 
4511 gtk_default_draw_slider (GtkStyle      *style,
4512                          GdkWindow     *window,
4513                          GtkStateType   state_type,
4514                          GtkShadowType  shadow_type,
4515                          GdkRectangle  *area,
4516                          GtkWidget     *widget,
4517                          const gchar   *detail,
4518                          gint           x,
4519                          gint           y,
4520                          gint           width,
4521                          gint           height,
4522                          GtkOrientation orientation)
4523 {
4524   g_return_if_fail (GTK_IS_STYLE (style));
4525   g_return_if_fail (window != NULL);
4526   
4527   sanitize_size (window, &width, &height);
4528   
4529   gtk_paint_box (style, window, state_type, shadow_type,
4530                  area, widget, detail, x, y, width, height);
4531
4532   if (detail &&
4533       (strcmp ("hscale", detail) == 0 ||
4534        strcmp ("vscale", detail) == 0))
4535     {
4536       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4537         gtk_paint_vline (style, window, state_type, area, widget, detail, 
4538                          y + style->ythickness, 
4539                          y + height - style->ythickness - 1, x + width / 2);
4540       else
4541         gtk_paint_hline (style, window, state_type, area, widget, detail, 
4542                          x + style->xthickness, 
4543                          x + width - style->xthickness - 1, y + height / 2);
4544     }
4545 }
4546
4547 static void
4548 draw_dot (GdkWindow    *window,
4549           GdkGC        *light_gc,
4550           GdkGC        *dark_gc,
4551           gint          x,
4552           gint          y,
4553           gushort       size)
4554 {
4555   
4556   size = CLAMP (size, 2, 3);
4557
4558   if (size == 2)
4559     {
4560       gdk_draw_point (window, light_gc, x, y);
4561       gdk_draw_point (window, light_gc, x+1, y+1);
4562     }
4563   else if (size == 3);
4564     {
4565       gdk_draw_point (window, light_gc, x, y);
4566       gdk_draw_point (window, light_gc, x+1, y);
4567       gdk_draw_point (window, light_gc, x, y+1);
4568       gdk_draw_point (window, dark_gc, x+1, y+2);
4569       gdk_draw_point (window, dark_gc, x+2, y+1);
4570       gdk_draw_point (window, dark_gc, x+2, y+2);
4571     }
4572 }
4573
4574 static void 
4575 gtk_default_draw_handle (GtkStyle      *style,
4576                          GdkWindow     *window,
4577                          GtkStateType   state_type,
4578                          GtkShadowType  shadow_type,
4579                          GdkRectangle  *area,
4580                          GtkWidget     *widget,
4581                          const gchar   *detail,
4582                          gint           x,
4583                          gint           y,
4584                          gint           width,
4585                          gint           height,
4586                          GtkOrientation orientation)
4587 {
4588   gint xx, yy;
4589   gint xthick, ythick;
4590   GdkGC *light_gc, *dark_gc;
4591   GdkRectangle rect;
4592   GdkRectangle dest;
4593   gint intersect;
4594   
4595   g_return_if_fail (GTK_IS_STYLE (style));
4596   g_return_if_fail (window != NULL);
4597   
4598   sanitize_size (window, &width, &height);
4599   
4600   gtk_paint_box (style, window, state_type, shadow_type, area, widget, 
4601                  detail, x, y, width, height);
4602   
4603   
4604   if (!strcmp (detail, "paned"))
4605     {
4606       /* we want to ignore the shadow border in paned widgets */
4607       xthick = 0;
4608       ythick = 0;
4609
4610       light_gc = style->light_gc[state_type];
4611       dark_gc = style->black_gc;
4612     }
4613   else
4614     {
4615       xthick = style->xthickness;
4616       ythick = style->ythickness;
4617
4618       light_gc = style->light_gc[state_type];
4619       dark_gc = style->dark_gc[state_type];
4620     }
4621   
4622   rect.x = x + xthick;
4623   rect.y = y + ythick;
4624   rect.width = width - (xthick * 2);
4625   rect.height = height - (ythick * 2);
4626
4627   if (area)
4628       intersect = gdk_rectangle_intersect (area, &rect, &dest);
4629   else
4630     {
4631       intersect = TRUE;
4632       dest = rect;
4633     }
4634
4635   if (!intersect)
4636     return;
4637
4638   gdk_gc_set_clip_rectangle (light_gc, &dest);
4639   gdk_gc_set_clip_rectangle (dark_gc, &dest);
4640
4641   if (!strcmp (detail, "paned"))
4642     {
4643       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4644         for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
4645           draw_dot (window, light_gc, dark_gc, xx, y + height/2 - 1, 3);
4646       else
4647         for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
4648           draw_dot (window, light_gc, dark_gc, x + width/2 - 1, yy, 3);
4649     }
4650   else
4651     {
4652       for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
4653         for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
4654           {
4655             draw_dot (window, light_gc, dark_gc, xx, yy, 2);
4656             draw_dot (window, light_gc, dark_gc, xx + 3, yy + 1, 2);
4657           }
4658     }
4659
4660   gdk_gc_set_clip_rectangle (light_gc, NULL);
4661   gdk_gc_set_clip_rectangle (dark_gc, NULL);
4662 }
4663
4664 static void
4665 create_expander_affine (gdouble affine[6],
4666                         gint    degrees,
4667                         gint    expander_size,
4668                         gint    x,
4669                         gint    y)
4670 {
4671   gdouble s, c;
4672   gdouble width;
4673   gdouble height;
4674
4675   width = expander_size / 4.0;
4676   height = expander_size / 2.0;
4677   
4678   s = sin (degrees * G_PI / 180.0);
4679   c = cos (degrees * G_PI / 180.0);
4680   
4681   affine[0] = c;
4682   affine[1] = s;
4683   affine[2] = -s;
4684   affine[3] = c;
4685   affine[4] = -width * c - height * -s + x;
4686   affine[5] = -width * s - height * c + y;
4687 }
4688
4689 static void
4690 apply_affine_on_point (double affine[6], GdkPoint *point)
4691 {
4692   gdouble x, y;
4693
4694   x = point->x * affine[0] + point->y * affine[2] + affine[4];
4695   y = point->x * affine[1] + point->y * affine[3] + affine[5];
4696
4697   point->x = x;
4698   point->y = y;
4699 }
4700
4701 static void
4702 gtk_style_draw_polygon_with_gc (GdkWindow *window, GdkGC *gc, gint line_width,
4703                                 gboolean do_fill, GdkPoint *points, gint n_points)
4704 {
4705   gdk_gc_set_line_attributes (gc, line_width,
4706                               GDK_LINE_SOLID,
4707                               GDK_CAP_BUTT, GDK_JOIN_MITER);
4708
4709   gdk_draw_polygon (window, gc, do_fill, points, n_points);
4710   gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
4711 }
4712
4713 static void
4714 gtk_default_draw_expander (GtkStyle        *style,
4715                            GdkWindow       *window,
4716                            GtkStateType     state_type,
4717                            GdkRectangle    *area,
4718                            GtkWidget       *widget,
4719                            const gchar     *detail,
4720                            gint             x,
4721                            gint             y,
4722                            GtkExpanderStyle expander_style)
4723 {
4724   gint expander_size;
4725   GdkPoint points[3];
4726   gint i;
4727   gint line_width;
4728   gdouble affine[6];
4729   gint degrees = 0;
4730
4731   gtk_widget_style_get (widget,
4732                         "expander_size", &expander_size,
4733                         NULL);
4734   line_width = MAX (1, expander_size/7);
4735
4736   if (area)
4737     {
4738       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], area);
4739       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], area);
4740     }
4741
4742   expander_size -= (line_width * 2 - 2);
4743   points[0].x = line_width / 2;
4744   points[0].y = line_width / 2;
4745   points[1].x = expander_size / 2 + line_width / 2;
4746   points[1].y = expander_size / 2 + line_width / 2;
4747   points[2].x = line_width / 2;
4748   points[2].y = expander_size + line_width / 2;
4749
4750   switch (expander_style)
4751     {
4752     case GTK_EXPANDER_COLLAPSED:
4753       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
4754       break;
4755     case GTK_EXPANDER_SEMI_COLLAPSED:
4756       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
4757       break;
4758     case GTK_EXPANDER_SEMI_EXPANDED:
4759       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
4760       break;
4761     case GTK_EXPANDER_EXPANDED:
4762       degrees = 90;
4763       break;
4764     default:
4765       g_assert_not_reached ();
4766     }
4767
4768   create_expander_affine (affine, degrees, expander_size, x, y);
4769
4770   for (i = 0; i < 3; i++)
4771     apply_affine_on_point (affine, &points[i]);
4772
4773   if (state_type == GTK_STATE_PRELIGHT)
4774     {
4775       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4776                                       1, TRUE, points, 3);
4777     }
4778   else if (state_type == GTK_STATE_ACTIVE)
4779     {
4780       gtk_style_draw_polygon_with_gc (window, style->light_gc[GTK_STATE_ACTIVE],
4781                                       1, TRUE, points, 3);
4782       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4783                                       line_width, FALSE, points, 3);
4784     }
4785   else
4786     {
4787       gtk_style_draw_polygon_with_gc (window, style->base_gc[GTK_STATE_NORMAL],
4788                                       1, TRUE, points, 3);
4789       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4790                                       line_width, FALSE, points, 3);
4791     }
4792   if (area)
4793     {
4794       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
4795       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
4796     }
4797 }
4798
4799 typedef struct _ByteRange ByteRange;
4800
4801 struct _ByteRange
4802 {
4803   guint start;
4804   guint end;
4805 };
4806
4807 static ByteRange*
4808 range_new (guint start,
4809            guint end)
4810 {
4811   ByteRange *br = g_new (ByteRange, 1);
4812
4813   br->start = start;
4814   br->end = end;
4815   
4816   return br;
4817 }
4818
4819 static PangoLayout*
4820 get_insensitive_layout (GdkDrawable *drawable,
4821                         PangoLayout *layout)
4822 {
4823   GSList *embossed_ranges = NULL;
4824   GSList *stippled_ranges = NULL;
4825   PangoLayoutIter *iter;
4826   GSList *tmp_list = NULL;
4827   PangoLayout *new_layout;
4828   PangoAttrList *attrs;
4829   GdkBitmap *stipple = NULL;
4830   
4831   iter = pango_layout_get_iter (layout);
4832   
4833   do
4834     {
4835       PangoLayoutRun *run;
4836       PangoAttribute *attr;
4837       gboolean need_stipple = FALSE;
4838       ByteRange *br;
4839       
4840       run = pango_layout_iter_get_run (iter);
4841
4842       if (run)
4843         {
4844           tmp_list = run->item->analysis.extra_attrs;
4845
4846           while (tmp_list != NULL)
4847             {
4848               attr = tmp_list->data;
4849               switch (attr->klass->type)
4850                 {
4851                 case PANGO_ATTR_FOREGROUND:
4852                 case PANGO_ATTR_BACKGROUND:
4853                   need_stipple = TRUE;
4854                   break;
4855               
4856                 default:
4857                   break;
4858                 }
4859
4860               if (need_stipple)
4861                 break;
4862           
4863               tmp_list = g_slist_next (tmp_list);
4864             }
4865
4866           br = range_new (run->item->offset, run->item->offset + run->item->length);
4867       
4868           if (need_stipple)
4869             stippled_ranges = g_slist_prepend (stippled_ranges, br);
4870           else
4871             embossed_ranges = g_slist_prepend (embossed_ranges, br);
4872         }
4873     }
4874   while (pango_layout_iter_next_run (iter));
4875
4876   pango_layout_iter_free (iter);
4877
4878   new_layout = pango_layout_copy (layout);
4879
4880   attrs = pango_layout_get_attributes (new_layout);
4881
4882   if (attrs == NULL)
4883     {
4884       /* Create attr list if there wasn't one */
4885       attrs = pango_attr_list_new ();
4886       pango_layout_set_attributes (new_layout, attrs);
4887       pango_attr_list_unref (attrs);
4888     }
4889   
4890   tmp_list = embossed_ranges;
4891   while (tmp_list != NULL)
4892     {
4893       PangoAttribute *attr;
4894       ByteRange *br = tmp_list->data;
4895
4896       attr = gdk_pango_attr_embossed_new (TRUE);
4897
4898       attr->start_index = br->start;
4899       attr->end_index = br->end;
4900       
4901       pango_attr_list_change (attrs, attr);
4902
4903       g_free (br);
4904       
4905       tmp_list = g_slist_next (tmp_list);
4906     }
4907
4908   g_slist_free (embossed_ranges);
4909   
4910   tmp_list = stippled_ranges;
4911   while (tmp_list != NULL)
4912     {
4913       PangoAttribute *attr;
4914       ByteRange *br = tmp_list->data;
4915
4916       if (stipple == NULL)
4917         {
4918 #define gray50_width 2
4919 #define gray50_height 2
4920           static char gray50_bits[] = {
4921             0x02, 0x01
4922           };
4923
4924           stipple = gdk_bitmap_create_from_data (drawable,
4925                                                  gray50_bits, gray50_width,
4926                                                  gray50_height);
4927         }
4928       
4929       attr = gdk_pango_attr_stipple_new (stipple);
4930
4931       attr->start_index = br->start;
4932       attr->end_index = br->end;
4933       
4934       pango_attr_list_change (attrs, attr);
4935
4936       g_free (br);
4937       
4938       tmp_list = g_slist_next (tmp_list);
4939     }
4940
4941   g_slist_free (stippled_ranges);
4942   
4943   if (stipple)
4944     g_object_unref (stipple);
4945
4946   return new_layout;
4947 }
4948
4949 static void
4950 gtk_default_draw_layout (GtkStyle        *style,
4951                          GdkWindow       *window,
4952                          GtkStateType     state_type,
4953                          gboolean         use_text,
4954                          GdkRectangle    *area,
4955                          GtkWidget       *widget,
4956                          const gchar     *detail,
4957                          gint             x,
4958                          gint             y,
4959                          PangoLayout     *layout)
4960 {
4961   GdkGC *gc;
4962   
4963   g_return_if_fail (GTK_IS_STYLE (style));
4964   g_return_if_fail (window != NULL);
4965
4966   gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
4967   
4968   if (area)
4969     gdk_gc_set_clip_rectangle (gc, area);
4970
4971   if (state_type == GTK_STATE_INSENSITIVE)
4972     {
4973       PangoLayout *ins;
4974
4975       ins = get_insensitive_layout (window, layout);
4976       
4977       gdk_draw_layout (window, gc, x, y, ins);
4978
4979       g_object_unref (ins);
4980     }
4981   else
4982     {
4983       gdk_draw_layout (window, gc, x, y, layout);
4984     }
4985
4986   if (area)
4987     gdk_gc_set_clip_rectangle (gc, NULL);
4988 }
4989
4990 static void
4991 gtk_default_draw_resize_grip (GtkStyle       *style,
4992                               GdkWindow      *window,
4993                               GtkStateType    state_type,
4994                               GdkRectangle   *area,
4995                               GtkWidget      *widget,
4996                               const gchar    *detail,
4997                               GdkWindowEdge   edge,
4998                               gint            x,
4999                               gint            y,
5000                               gint            width,
5001                               gint            height)
5002 {
5003   g_return_if_fail (GTK_IS_STYLE (style));
5004   g_return_if_fail (window != NULL);
5005   
5006   if (area)
5007     {
5008       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
5009       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
5010       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
5011     }
5012   
5013   switch (edge)
5014     {
5015     case GDK_WINDOW_EDGE_NORTH_WEST:
5016       /* make it square */
5017       if (width < height)
5018         {
5019           height = width;
5020         }
5021       else if (height < width)
5022         {
5023           width = height;
5024         }
5025       break;
5026     case GDK_WINDOW_EDGE_NORTH:
5027       if (width < height)
5028         {
5029           height = width;
5030         }
5031       break;
5032     case GDK_WINDOW_EDGE_NORTH_EAST:
5033       /* make it square, aligning to top right */
5034       if (width < height)
5035         {
5036           height = width;
5037         }
5038       else if (height < width)
5039         {
5040           x += (width - height);
5041           width = height;
5042         }
5043       break;
5044     case GDK_WINDOW_EDGE_WEST:
5045       if (height < width)
5046         {
5047            width = height;
5048         }
5049       break;
5050     case GDK_WINDOW_EDGE_EAST:
5051       /* aligning to right */
5052       if (height < width)
5053         {
5054           x += (width - height);
5055           width = height;
5056         }
5057       break;
5058     case GDK_WINDOW_EDGE_SOUTH_WEST:
5059       /* make it square, aligning to bottom left */
5060       if (width < height)
5061         {
5062           y += (height - width);
5063           height = width;
5064         }
5065       else if (height < width)
5066         {
5067           width = height;
5068         }
5069       break;
5070     case GDK_WINDOW_EDGE_SOUTH:
5071       /* align to bottom */
5072       if (width < height)
5073         {
5074           y += (height - width);
5075           height = width;
5076         }
5077       break;
5078     case GDK_WINDOW_EDGE_SOUTH_EAST:
5079       /* make it square, aligning to bottom right */
5080       if (width < height)
5081         {
5082           y += (height - width);
5083           height = width;
5084         }
5085       else if (height < width)
5086         {
5087           x += (width - height);
5088           width = height;
5089         }
5090       break;
5091     default:
5092       g_assert_not_reached ();
5093     }
5094   /* Clear background */
5095   gtk_style_apply_default_background (style, window, FALSE,
5096                                       state_type, area,
5097                                       x, y, width, height);   
5098
5099   switch (edge)
5100     {
5101     case GDK_WINDOW_EDGE_WEST:
5102     case GDK_WINDOW_EDGE_EAST:
5103       {
5104         gint xi;
5105
5106         xi = x;
5107
5108         while (xi < x + width)
5109           {
5110             gdk_draw_line (window,
5111                            style->light_gc[state_type],
5112                            xi, y,
5113                            xi, y + height);
5114
5115             xi++;
5116             gdk_draw_line (window,
5117                            style->dark_gc[state_type],
5118                            xi, y,
5119                            xi, y + height);
5120
5121             xi += 2;
5122           }
5123       }
5124       break;
5125     case GDK_WINDOW_EDGE_NORTH:
5126     case GDK_WINDOW_EDGE_SOUTH:
5127       {
5128         gint yi;
5129
5130         yi = y;
5131
5132         while (yi < y + height)
5133           {
5134             gdk_draw_line (window,
5135                            style->light_gc[state_type],
5136                            x, yi,
5137                            x + width, yi);
5138
5139             yi++;
5140             gdk_draw_line (window,
5141                            style->dark_gc[state_type],
5142                            x, yi,
5143                            x + width, yi);
5144
5145             yi+= 2;
5146           }
5147       }
5148       break;
5149     case GDK_WINDOW_EDGE_NORTH_WEST:
5150       {
5151         gint xi, yi;
5152
5153         xi = x + width;
5154         yi = y + height;
5155
5156         while (xi > x + 3)
5157           {
5158             gdk_draw_line (window,
5159                            style->dark_gc[state_type],
5160                            xi, y,
5161                            x, yi);
5162
5163             --xi;
5164             --yi;
5165
5166             gdk_draw_line (window,
5167                            style->dark_gc[state_type],
5168                            xi, y,
5169                            x, yi);
5170
5171             --xi;
5172             --yi;
5173
5174             gdk_draw_line (window,
5175                            style->light_gc[state_type],
5176                            xi, y,
5177                            x, yi);
5178
5179             xi -= 3;
5180             yi -= 3;
5181             
5182           }
5183       }
5184       break;
5185     case GDK_WINDOW_EDGE_NORTH_EAST:
5186       {
5187         gint xi, yi;
5188
5189         xi = x;
5190         yi = y + height;
5191
5192         while (xi < (x + width - 3))
5193           {
5194             gdk_draw_line (window,
5195                            style->light_gc[state_type],
5196                            xi, y,
5197                            x + width, yi);                           
5198
5199             ++xi;
5200             --yi;
5201             
5202             gdk_draw_line (window,
5203                            style->dark_gc[state_type],
5204                            xi, y,
5205                            x + width, yi);                           
5206
5207             ++xi;
5208             --yi;
5209             
5210             gdk_draw_line (window,
5211                            style->dark_gc[state_type],
5212                            xi, y,
5213                            x + width, yi);
5214
5215             xi += 3;
5216             yi -= 3;
5217           }
5218       }
5219       break;
5220     case GDK_WINDOW_EDGE_SOUTH_WEST:
5221       {
5222         gint xi, yi;
5223
5224         xi = x + width;
5225         yi = y;
5226
5227         while (xi > x + 3)
5228           {
5229             gdk_draw_line (window,
5230                            style->dark_gc[state_type],
5231                            x, yi,
5232                            xi, y + height);
5233
5234             --xi;
5235             ++yi;
5236
5237             gdk_draw_line (window,
5238                            style->dark_gc[state_type],
5239                            x, yi,
5240                            xi, y + height);
5241
5242             --xi;
5243             ++yi;
5244
5245             gdk_draw_line (window,
5246                            style->light_gc[state_type],
5247                            x, yi,
5248                            xi, y + height);
5249
5250             xi -= 3;
5251             yi += 3;
5252             
5253           }
5254       }
5255       break;
5256     case GDK_WINDOW_EDGE_SOUTH_EAST:
5257       {
5258         gint xi, yi;
5259
5260         xi = x;
5261         yi = y;
5262
5263         while (xi < (x + width - 3))
5264           {
5265             gdk_draw_line (window,
5266                            style->light_gc[state_type],
5267                            xi, y + height,
5268                            x + width, yi);                           
5269
5270             ++xi;
5271             ++yi;
5272             
5273             gdk_draw_line (window,
5274                            style->dark_gc[state_type],
5275                            xi, y + height,
5276                            x + width, yi);                           
5277
5278             ++xi;
5279             ++yi;
5280             
5281             gdk_draw_line (window,
5282                            style->dark_gc[state_type],
5283                            xi, y + height,
5284                            x + width, yi);
5285
5286             xi += 3;
5287             yi += 3;
5288           }
5289       }
5290       break;
5291     default:
5292       g_assert_not_reached ();
5293       break;
5294     }
5295   
5296   if (area)
5297     {
5298       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
5299       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
5300       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
5301     }
5302 }
5303
5304 static void
5305 gtk_style_shade (GdkColor *a,
5306                  GdkColor *b,
5307                  gdouble   k)
5308 {
5309   gdouble red;
5310   gdouble green;
5311   gdouble blue;
5312   
5313   red = (gdouble) a->red / 65535.0;
5314   green = (gdouble) a->green / 65535.0;
5315   blue = (gdouble) a->blue / 65535.0;
5316   
5317   rgb_to_hls (&red, &green, &blue);
5318   
5319   green *= k;
5320   if (green > 1.0)
5321     green = 1.0;
5322   else if (green < 0.0)
5323     green = 0.0;
5324   
5325   blue *= k;
5326   if (blue > 1.0)
5327     blue = 1.0;
5328   else if (blue < 0.0)
5329     blue = 0.0;
5330   
5331   hls_to_rgb (&red, &green, &blue);
5332   
5333   b->red = red * 65535.0;
5334   b->green = green * 65535.0;
5335   b->blue = blue * 65535.0;
5336 }
5337
5338 static void
5339 rgb_to_hls (gdouble *r,
5340             gdouble *g,
5341             gdouble *b)
5342 {
5343   gdouble min;
5344   gdouble max;
5345   gdouble red;
5346   gdouble green;
5347   gdouble blue;
5348   gdouble h, l, s;
5349   gdouble delta;
5350   
5351   red = *r;
5352   green = *g;
5353   blue = *b;
5354   
5355   if (red > green)
5356     {
5357       if (red > blue)
5358         max = red;
5359       else
5360         max = blue;
5361       
5362       if (green < blue)
5363         min = green;
5364       else
5365         min = blue;
5366     }
5367   else
5368     {
5369       if (green > blue)
5370         max = green;
5371       else
5372         max = blue;
5373       
5374       if (red < blue)
5375         min = red;
5376       else
5377         min = blue;
5378     }
5379   
5380   l = (max + min) / 2;
5381   s = 0;
5382   h = 0;
5383   
5384   if (max != min)
5385     {
5386       if (l <= 0.5)
5387         s = (max - min) / (max + min);
5388       else
5389         s = (max - min) / (2 - max - min);
5390       
5391       delta = max -min;
5392       if (red == max)
5393         h = (green - blue) / delta;
5394       else if (green == max)
5395         h = 2 + (blue - red) / delta;
5396       else if (blue == max)
5397         h = 4 + (red - green) / delta;
5398       
5399       h *= 60;
5400       if (h < 0.0)
5401         h += 360;
5402     }
5403   
5404   *r = h;
5405   *g = l;
5406   *b = s;
5407 }
5408
5409 static void
5410 hls_to_rgb (gdouble *h,
5411             gdouble *l,
5412             gdouble *s)
5413 {
5414   gdouble hue;
5415   gdouble lightness;
5416   gdouble saturation;
5417   gdouble m1, m2;
5418   gdouble r, g, b;
5419   
5420   lightness = *l;
5421   saturation = *s;
5422   
5423   if (lightness <= 0.5)
5424     m2 = lightness * (1 + saturation);
5425   else
5426     m2 = lightness + saturation - lightness * saturation;
5427   m1 = 2 * lightness - m2;
5428   
5429   if (saturation == 0)
5430     {
5431       *h = lightness;
5432       *l = lightness;
5433       *s = lightness;
5434     }
5435   else
5436     {
5437       hue = *h + 120;
5438       while (hue > 360)
5439         hue -= 360;
5440       while (hue < 0)
5441         hue += 360;
5442       
5443       if (hue < 60)
5444         r = m1 + (m2 - m1) * hue / 60;
5445       else if (hue < 180)
5446         r = m2;
5447       else if (hue < 240)
5448         r = m1 + (m2 - m1) * (240 - hue) / 60;
5449       else
5450         r = m1;
5451       
5452       hue = *h;
5453       while (hue > 360)
5454         hue -= 360;
5455       while (hue < 0)
5456         hue += 360;
5457       
5458       if (hue < 60)
5459         g = m1 + (m2 - m1) * hue / 60;
5460       else if (hue < 180)
5461         g = m2;
5462       else if (hue < 240)
5463         g = m1 + (m2 - m1) * (240 - hue) / 60;
5464       else
5465         g = m1;
5466       
5467       hue = *h - 120;
5468       while (hue > 360)
5469         hue -= 360;
5470       while (hue < 0)
5471         hue += 360;
5472       
5473       if (hue < 60)
5474         b = m1 + (m2 - m1) * hue / 60;
5475       else if (hue < 180)
5476         b = m2;
5477       else if (hue < 240)
5478         b = m1 + (m2 - m1) * (240 - hue) / 60;
5479       else
5480         b = m1;
5481       
5482       *h = r;
5483       *l = g;
5484       *s = b;
5485     }
5486 }
5487
5488
5489 /**
5490  * gtk_paint_hline:
5491  * @style: a #GtkStyle
5492  * @window: a #GdkWindow
5493  * @state_type: a state
5494  * @area: rectangle to which the output is clipped
5495  * @widget:
5496  * @detail: 
5497  * @x1: the starting x coordinate
5498  * @x2: the ending x coordinate
5499  * @y: the y coordinate
5500  * 
5501  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
5502  * using the given style and state.
5503  **/ 
5504 void 
5505 gtk_paint_hline (GtkStyle      *style,
5506                  GdkWindow     *window,
5507                  GtkStateType   state_type,
5508                  GdkRectangle  *area,
5509                  GtkWidget     *widget,
5510                  const gchar   *detail,
5511                  gint          x1,
5512                  gint          x2,
5513                  gint          y)
5514 {
5515   g_return_if_fail (GTK_IS_STYLE (style));
5516   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
5517   
5518   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y);
5519 }
5520
5521 /**
5522  * gtk_paint_vline:
5523  * @style: a #GtkStyle
5524  * @window: a #GdkWindow
5525  * @state_type: a state
5526  * @area: rectangle to which the output is clipped
5527  * @widget:
5528  * @detail: 
5529  * @y1_: the starting y coordinate
5530  * @y2_: the ending y coordinate
5531  * @x: the x coordinate
5532  * 
5533  * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @window
5534  * using the given style and state.
5535  */
5536 void
5537 gtk_paint_vline (GtkStyle      *style,
5538                  GdkWindow     *window,
5539                  GtkStateType   state_type,
5540                  GdkRectangle  *area,
5541                  GtkWidget     *widget,
5542                  const gchar   *detail,
5543                  gint          y1,
5544                  gint          y2,
5545                  gint          x)
5546 {
5547   g_return_if_fail (GTK_IS_STYLE (style));
5548   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
5549   
5550   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1, y2, x);
5551 }
5552
5553 void
5554 gtk_paint_shadow (GtkStyle     *style,
5555                   GdkWindow    *window,
5556                   GtkStateType  state_type,
5557                   GtkShadowType shadow_type,
5558                   GdkRectangle *area,
5559                   GtkWidget    *widget,
5560                   const gchar  *detail,
5561                   gint          x,
5562                   gint          y,
5563                   gint          width,
5564                   gint          height)
5565 {
5566   g_return_if_fail (GTK_IS_STYLE (style));
5567   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
5568   
5569   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5570 }
5571
5572 void
5573 gtk_paint_polygon (GtkStyle      *style,
5574                    GdkWindow     *window,
5575                    GtkStateType   state_type,
5576                    GtkShadowType  shadow_type,
5577                    GdkRectangle  *area,
5578                    GtkWidget     *widget,
5579                    const gchar   *detail,
5580                    GdkPoint      *points,
5581                    gint           npoints,
5582                    gboolean       fill)
5583 {
5584   g_return_if_fail (GTK_IS_STYLE (style));
5585   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
5586   
5587   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill);
5588 }
5589
5590 void
5591 gtk_paint_arrow (GtkStyle      *style,
5592                  GdkWindow     *window,
5593                  GtkStateType   state_type,
5594                  GtkShadowType  shadow_type,
5595                  GdkRectangle  *area,
5596                  GtkWidget     *widget,
5597                  const gchar   *detail,
5598                  GtkArrowType   arrow_type,
5599                  gboolean       fill,
5600                  gint           x,
5601                  gint           y,
5602                  gint           width,
5603                  gint           height)
5604 {
5605   g_return_if_fail (GTK_IS_STYLE (style));
5606   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
5607   
5608   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height);
5609 }
5610
5611 void
5612 gtk_paint_diamond (GtkStyle      *style,
5613                    GdkWindow     *window,
5614                    GtkStateType   state_type,
5615                    GtkShadowType  shadow_type,
5616                    GdkRectangle  *area,
5617                    GtkWidget     *widget,
5618                    const gchar   *detail,
5619                    gint        x,
5620                    gint        y,
5621                    gint        width,
5622                    gint        height)
5623 {
5624   g_return_if_fail (GTK_IS_STYLE (style));
5625   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
5626   
5627   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5628 }
5629
5630 /**
5631  * gtk_paint_string:
5632  * @style: a #GtkStyle
5633  * @window: a #GdkWindow
5634  * @state_type: a state
5635  * @area: clip rectangle
5636  * @widget: the widget
5637  * @detail: a style detail
5638  * @x: x origin
5639  * @y: y origin
5640  * @string: the string to draw
5641  * 
5642  * Draws a text string on @window with the given parameters.
5643  *
5644  * This function is deprecated, use gtk_paint_layout() instead.
5645  */
5646 void
5647 gtk_paint_string (GtkStyle      *style,
5648                   GdkWindow     *window,
5649                   GtkStateType   state_type,
5650                   GdkRectangle  *area,
5651                   GtkWidget     *widget,
5652                   const gchar   *detail,
5653                   gint           x,
5654                   gint           y,
5655                   const gchar   *string)
5656 {
5657   g_return_if_fail (GTK_IS_STYLE (style));
5658   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
5659   
5660   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string);
5661 }
5662
5663 void
5664 gtk_paint_box (GtkStyle      *style,
5665                GdkWindow     *window,
5666                GtkStateType   state_type,
5667                GtkShadowType  shadow_type,
5668                GdkRectangle  *area,
5669                GtkWidget     *widget,
5670                const gchar   *detail,
5671                gint           x,
5672                gint           y,
5673                gint           width,
5674                gint           height)
5675 {
5676   g_return_if_fail (GTK_IS_STYLE (style));
5677   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
5678   
5679   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5680 }
5681
5682 void
5683 gtk_paint_flat_box (GtkStyle      *style,
5684                     GdkWindow     *window,
5685                     GtkStateType   state_type,
5686                     GtkShadowType  shadow_type,
5687                     GdkRectangle  *area,
5688                     GtkWidget     *widget,
5689                     const gchar   *detail,
5690                     gint           x,
5691                     gint           y,
5692                     gint           width,
5693                     gint           height)
5694 {
5695   g_return_if_fail (GTK_IS_STYLE (style));
5696   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
5697   
5698   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5699 }
5700
5701 void
5702 gtk_paint_check (GtkStyle      *style,
5703                  GdkWindow     *window,
5704                  GtkStateType   state_type,
5705                  GtkShadowType  shadow_type,
5706                  GdkRectangle  *area,
5707                  GtkWidget     *widget,
5708                  const gchar   *detail,
5709                  gint           x,
5710                  gint           y,
5711                  gint           width,
5712                  gint           height)
5713 {
5714   g_return_if_fail (GTK_IS_STYLE (style));
5715   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
5716   
5717   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5718 }
5719
5720 void
5721 gtk_paint_option (GtkStyle      *style,
5722                   GdkWindow     *window,
5723                   GtkStateType   state_type,
5724                   GtkShadowType  shadow_type,
5725                   GdkRectangle  *area,
5726                   GtkWidget     *widget,
5727                   const gchar   *detail,
5728                   gint           x,
5729                   gint           y,
5730                   gint           width,
5731                   gint           height)
5732 {
5733   g_return_if_fail (GTK_IS_STYLE (style));
5734   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
5735   
5736   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5737 }
5738
5739 void
5740 gtk_paint_tab (GtkStyle      *style,
5741                GdkWindow     *window,
5742                GtkStateType   state_type,
5743                GtkShadowType  shadow_type,
5744                GdkRectangle  *area,
5745                GtkWidget     *widget,
5746                const gchar   *detail,
5747                gint           x,
5748                gint           y,
5749                gint           width,
5750                gint           height)
5751 {
5752   g_return_if_fail (GTK_IS_STYLE (style));
5753   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
5754   
5755   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5756 }
5757
5758 void
5759 gtk_paint_shadow_gap (GtkStyle       *style,
5760                       GdkWindow      *window,
5761                       GtkStateType    state_type,
5762                       GtkShadowType   shadow_type,
5763                       GdkRectangle   *area,
5764                       GtkWidget      *widget,
5765                       gchar          *detail,
5766                       gint            x,
5767                       gint            y,
5768                       gint            width,
5769                       gint            height,
5770                       GtkPositionType gap_side,
5771                       gint            gap_x,
5772                       gint            gap_width)
5773 {
5774   g_return_if_fail (GTK_IS_STYLE (style));
5775   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
5776   
5777   GTK_STYLE_GET_CLASS (style)->draw_shadow_gap (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side, gap_x, gap_width);
5778 }
5779
5780
5781 void
5782 gtk_paint_box_gap (GtkStyle       *style,
5783                    GdkWindow      *window,
5784                    GtkStateType    state_type,
5785                    GtkShadowType   shadow_type,
5786                    GdkRectangle   *area,
5787                    GtkWidget      *widget,
5788                    gchar          *detail,
5789                    gint            x,
5790                    gint            y,
5791                    gint            width,
5792                    gint            height,
5793                    GtkPositionType gap_side,
5794                    gint            gap_x,
5795                    gint            gap_width)
5796 {
5797   g_return_if_fail (GTK_IS_STYLE (style));
5798   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
5799   
5800   GTK_STYLE_GET_CLASS (style)->draw_box_gap (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side, gap_x, gap_width);
5801 }
5802
5803 void
5804 gtk_paint_extension (GtkStyle       *style,
5805                      GdkWindow      *window,
5806                      GtkStateType    state_type,
5807                      GtkShadowType   shadow_type,
5808                      GdkRectangle   *area,
5809                      GtkWidget      *widget,
5810                      gchar          *detail,
5811                      gint            x,
5812                      gint            y,
5813                      gint            width,
5814                      gint            height,
5815                      GtkPositionType gap_side)
5816 {
5817   g_return_if_fail (GTK_IS_STYLE (style));
5818   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
5819   
5820   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side);
5821 }
5822
5823 void
5824 gtk_paint_focus (GtkStyle      *style,
5825                  GdkWindow     *window,
5826                  GtkStateType   state_type,
5827                  GdkRectangle  *area,
5828                  GtkWidget     *widget,
5829                  const gchar   *detail,
5830                  gint           x,
5831                  gint           y,
5832                  gint           width,
5833                  gint           height)
5834 {
5835   g_return_if_fail (GTK_IS_STYLE (style));
5836   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
5837   
5838   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type, area, widget, detail, x, y, width, height);
5839 }
5840
5841 void
5842 gtk_paint_slider (GtkStyle      *style,
5843                   GdkWindow     *window,
5844                   GtkStateType   state_type,
5845                   GtkShadowType  shadow_type,
5846                   GdkRectangle  *area,
5847                   GtkWidget     *widget,
5848                   const gchar   *detail,
5849                   gint           x,
5850                   gint           y,
5851                   gint           width,
5852                   gint           height,
5853                   GtkOrientation orientation)
5854 {
5855   g_return_if_fail (GTK_IS_STYLE (style));
5856   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
5857   
5858   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
5859 }
5860
5861 void
5862 gtk_paint_handle (GtkStyle      *style,
5863                   GdkWindow     *window,
5864                   GtkStateType   state_type,
5865                   GtkShadowType  shadow_type,
5866                   GdkRectangle  *area,
5867                   GtkWidget     *widget,
5868                   const gchar   *detail,
5869                   gint           x,
5870                   gint           y,
5871                   gint           width,
5872                   gint           height,
5873                   GtkOrientation orientation)
5874 {
5875   g_return_if_fail (GTK_IS_STYLE (style));
5876   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
5877   
5878   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
5879 }
5880
5881 void
5882 gtk_paint_expander (GtkStyle        *style,
5883                     GdkWindow       *window,
5884                     GtkStateType     state_type,
5885                     GdkRectangle    *area,
5886                     GtkWidget       *widget,
5887                     const gchar     *detail,
5888                     gint             x,
5889                     gint             y,
5890                     GtkExpanderStyle expander_style)
5891 {
5892   g_return_if_fail (GTK_IS_STYLE (style));
5893   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
5894   
5895   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type, area,
5896                                               widget, detail, x, y, expander_style);
5897 }
5898
5899 void
5900 gtk_paint_layout (GtkStyle        *style,
5901                   GdkWindow       *window,
5902                   GtkStateType     state_type,
5903                   gboolean         use_text,
5904                   GdkRectangle    *area,
5905                   GtkWidget       *widget,
5906                   const gchar     *detail,
5907                   gint             x,
5908                   gint             y,
5909                   PangoLayout     *layout)
5910 {
5911   g_return_if_fail (GTK_IS_STYLE (style));
5912   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
5913   
5914   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text, area,
5915                                             widget, detail, x, y, layout);
5916 }
5917
5918 void
5919 gtk_paint_resize_grip (GtkStyle      *style,
5920                        GdkWindow     *window,
5921                        GtkStateType   state_type,
5922                        GdkRectangle  *area,
5923                        GtkWidget     *widget,
5924                        const gchar   *detail,
5925                        GdkWindowEdge  edge,
5926                        gint           x,
5927                        gint           y,
5928                        gint           width,
5929                        gint           height)
5930
5931 {
5932   g_return_if_fail (GTK_IS_STYLE (style));
5933   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
5934
5935   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
5936                                                  area, widget, detail,
5937                                                  edge, x, y, width, height);
5938 }
5939
5940 /**
5941  * gtk_border_copy:
5942  * @border_: a #GtkBorder.
5943  * @returns: a copy of @border_.
5944  *
5945  * Copies a #GtkBorder structure.
5946  **/
5947 GtkBorder *
5948 gtk_border_copy (const GtkBorder *border)
5949 {
5950   return (GtkBorder *)g_memdup (border, sizeof (GtkBorder));
5951 }
5952
5953 /**
5954  * gtk_border_free:
5955  * @border_: a #GtkBorder.
5956  * 
5957  * Frees a #GtkBorder structure.
5958  **/
5959 void
5960 gtk_border_free (GtkBorder *border)
5961 {
5962   g_free (border);
5963 }
5964
5965 GType
5966 gtk_border_get_type (void)
5967 {
5968   static GType our_type = 0;
5969   
5970   if (our_type == 0)
5971     our_type = g_boxed_type_register_static ("GtkBorder",
5972                                              (GBoxedCopyFunc) gtk_border_copy,
5973                                              (GBoxedFreeFunc) gtk_border_free);
5974
5975   return our_type;
5976 }
5977
5978 static GdkFont *
5979 gtk_style_get_font_internal (GtkStyle *style)
5980 {
5981   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
5982
5983   if (style->private_font && style->private_font_desc)
5984     {
5985       if (!style->font_desc ||
5986           !pango_font_description_equal (style->private_font_desc, style->font_desc))
5987         {
5988           gdk_font_unref (style->private_font);
5989           style->private_font = NULL;
5990           
5991           if (style->private_font_desc)
5992             {
5993               pango_font_description_free (style->private_font_desc);
5994               style->private_font_desc = NULL;
5995             }
5996         }
5997     }
5998   
5999   if (!style->private_font)
6000     {
6001       GdkDisplay *display;
6002
6003       if (style->colormap)
6004         {
6005           display = gdk_screen_get_display (gdk_colormap_get_screen (style->colormap));
6006         }
6007       else
6008         {
6009           display = gdk_display_get_default ();
6010           GTK_NOTE (MULTIHEAD,
6011                     g_warning ("gtk_style_get_font() should not be called on an unattached style"));
6012         }
6013       
6014       if (style->font_desc)
6015         {
6016           style->private_font = gdk_font_from_description_for_display (display, style->font_desc);
6017           style->private_font_desc = pango_font_description_copy (style->font_desc);
6018         }
6019
6020       if (!style->private_font)
6021         style->private_font = gdk_font_load_for_display (display, "fixed");
6022       
6023       if (!style->private_font) 
6024         g_error ("Unable to load \"fixed\" font");
6025     }
6026
6027   return style->private_font;
6028 }
6029
6030 /**
6031  * gtk_style_get_font:
6032  * @style: a #GtkStyle
6033  * 
6034  * Gets the #GdkFont to use for the given style. This is
6035  * meant only as a replacement for direct access to @style->font
6036  * and should not be used in new code. New code should
6037  * use @style->font_desc instead.
6038  * 
6039  * Return value: the #GdkFont for the style. This font is owned
6040  *   by the style; if you want to keep around a copy, you must
6041  *   call gdk_font_ref().
6042  **/
6043 GdkFont *
6044 gtk_style_get_font (GtkStyle *style)
6045 {
6046   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
6047
6048   return gtk_style_get_font_internal (style);
6049 }
6050
6051 /**
6052  * gtk_style_set_font:
6053  * @style: a #GtkStyle.
6054  * @font: a #GdkFont, or %NULL to use the #GdkFont corresponding
6055  *   to style->font_desc.
6056  * 
6057  * Sets the #GdkFont to use for a given style. This is
6058  * meant only as a replacement for direct access to style->font
6059  * and should not be used in new code. New code should
6060  * use style->font_desc instead.
6061  **/
6062 void
6063 gtk_style_set_font (GtkStyle *style,
6064                     GdkFont  *font)
6065 {
6066   GdkFont *old_font;
6067
6068   g_return_if_fail (GTK_IS_STYLE (style));
6069
6070   old_font = style->private_font;
6071
6072   style->private_font = font;
6073   if (font)
6074     gdk_font_ref (font);
6075
6076   if (old_font)
6077     gdk_font_unref (old_font);
6078
6079   if (style->private_font_desc)
6080     {
6081       pango_font_description_free (style->private_font_desc);
6082       style->private_font_desc = NULL;
6083     }
6084 }
6085
6086 typedef struct _CursorInfo CursorInfo;
6087
6088 struct _CursorInfo
6089 {
6090   GType for_type;
6091   GdkGC *primary_gc;
6092   GdkGC *secondary_gc;
6093 };
6094
6095 static void
6096 style_unrealize_cursor_gcs (GtkStyle *style)
6097 {
6098   CursorInfo *
6099   
6100   cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
6101   if (cursor_info)
6102     {
6103       if (cursor_info->primary_gc)
6104         gtk_gc_release (cursor_info->primary_gc);
6105
6106       if (cursor_info->secondary_gc)
6107         gtk_gc_release (cursor_info->secondary_gc);
6108       
6109       g_free (cursor_info);
6110       g_object_set_data (G_OBJECT (style), "gtk-style-cursor-info", NULL);
6111     }
6112 }
6113
6114 static GdkGC *
6115 make_cursor_gc (GtkWidget   *widget,
6116                 const gchar *property_name,
6117                 GdkColor    *fallback)
6118 {
6119   GdkGCValues gc_values;
6120   GdkGCValuesMask gc_values_mask;
6121   GdkColor *cursor_color;
6122
6123   gtk_widget_style_get (widget, property_name, &cursor_color, NULL);
6124   
6125   gc_values_mask = GDK_GC_FOREGROUND;
6126   if (cursor_color)
6127     {
6128       gc_values.foreground = *cursor_color;
6129       gdk_color_free (cursor_color);
6130     }
6131   else
6132     gc_values.foreground = *fallback;
6133   
6134   gdk_rgb_find_color (widget->style->colormap, &gc_values.foreground);
6135   return gtk_gc_get (widget->style->depth, widget->style->colormap, &gc_values, gc_values_mask);
6136 }
6137
6138 /**
6139  * _gtk_get_insertion_cursor_gc:
6140  * @widget: a #GtkWidget
6141  * @is_primary: if the cursor should be the primary cursor color.
6142  * 
6143  * Get a GC suitable for drawing the primary or secondary text
6144  * cursor.
6145  *
6146  * Note: the return value is ref'ed because calls to this function
6147  *  on other widgets could result in this the GC being released
6148  *  which would be an unexpected side effect. If made public,
6149  *  this function should possibly be called create_insertion_cursor_gc().
6150  *
6151  * Return value: an appropriate #GdkGC. Call g_object_unref() on
6152  *   the gc when you are done with it; this GC may be shared with
6153  *   other users, so you must not modify the GC except for temporarily
6154  *   setting the clip before drawing with the GC, and then unsetting the clip
6155  *   again afterwards.
6156  **/
6157 GdkGC *
6158 _gtk_get_insertion_cursor_gc (GtkWidget *widget,
6159                               gboolean   is_primary)
6160 {
6161   CursorInfo *cursor_info;
6162
6163   cursor_info = g_object_get_data (G_OBJECT (widget->style), "gtk-style-cursor-info");
6164   if (!cursor_info)
6165     {
6166       cursor_info = g_new (CursorInfo, 1);
6167       g_object_set_data (G_OBJECT (widget->style), "gtk-style-cursor-info", cursor_info);
6168       cursor_info->primary_gc = NULL;
6169       cursor_info->secondary_gc = NULL;
6170       cursor_info->for_type = G_TYPE_INVALID;
6171     }
6172
6173   /* We have to keep track of the type because gtk_widget_style_get()
6174    * can return different results when called on the same property and
6175    * same style but for different widgets. :-(. That is,
6176    * GtkEntry::cursor-color = "red" in a style will modify the cursor
6177    * color for entries but not for text view.
6178    */
6179   if (cursor_info->for_type != G_OBJECT_TYPE (widget))
6180     {
6181       cursor_info->for_type = G_OBJECT_TYPE (widget);
6182       if (cursor_info->primary_gc)
6183         {
6184           gtk_gc_release (cursor_info->primary_gc);
6185           cursor_info->primary_gc = NULL;
6186         }
6187       if (cursor_info->secondary_gc)
6188         {
6189           gtk_gc_release (cursor_info->secondary_gc);
6190           cursor_info->secondary_gc = NULL;
6191         }
6192     }
6193
6194   if (is_primary)
6195     {
6196       if (!cursor_info->primary_gc)
6197         cursor_info->primary_gc = make_cursor_gc (widget,
6198                                                   "cursor-color",
6199                                                   &widget->style->black);
6200         
6201       return g_object_ref (cursor_info->primary_gc);
6202     }
6203   else
6204     {
6205       static GdkColor gray = { 0, 0x8888, 0x8888, 0x8888 };
6206       
6207       if (!cursor_info->secondary_gc)
6208         cursor_info->secondary_gc = make_cursor_gc (widget,
6209                                                     "secondary-cursor-color",
6210                                                     &gray);
6211         
6212       return g_object_ref (cursor_info->secondary_gc);
6213     }
6214 }
6215
6216 /**
6217  * _gtk_draw_insertion_cursor:
6218  * @widget: a #GtkWidget
6219  * @drawable: a #GdkDrawable
6220  * @gc: a #GdkGC
6221  * @location: location where to draw the cursor (@location->width is ignored)
6222  * @direction: whether the cursor is left-to-right or
6223  *             right-to-left. Should never be #GTK_TEXT_DIR_NONE
6224  * @draw_arrow: %TRUE to draw a directional arrow on the
6225  *        cursor. Should be %FALSE unless the cursor is split.
6226  * 
6227  * Draws a text caret on @drawable at @location. This is not a style function
6228  * but merely a convenience function for drawing the standard cursor shape.
6229  **/
6230 void
6231 _gtk_draw_insertion_cursor (GtkWidget        *widget,
6232                             GdkDrawable      *drawable,
6233                             GdkGC            *gc,
6234                             GdkRectangle     *location,
6235                             GtkTextDirection  direction,
6236                             gboolean          draw_arrow)
6237 {
6238   gint stem_width;
6239   gint arrow_width;
6240   gint x, y;
6241   gint i;
6242   gfloat cursor_aspect_ratio;
6243   gint offset;
6244   
6245   g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
6246   
6247   gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
6248   
6249   stem_width = location->height * cursor_aspect_ratio + 1;
6250   arrow_width = stem_width + 1;
6251
6252   /* put (stem_width % 2) on the proper side of the cursor */
6253   if (direction == GTK_TEXT_DIR_LTR)
6254     offset = stem_width / 2;
6255   else
6256     offset = stem_width - stem_width / 2;
6257   
6258   for (i = 0; i < stem_width; i++)
6259     gdk_draw_line (drawable, gc,
6260                    location->x + i - offset, location->y,
6261                    location->x + i - offset, location->y + location->height - 1);
6262
6263   if (draw_arrow)
6264     {
6265       if (direction == GTK_TEXT_DIR_RTL)
6266         {
6267           x = location->x - offset - 1;
6268           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6269   
6270           for (i = 0; i < arrow_width; i++)
6271             {
6272               gdk_draw_line (drawable, gc,
6273                              x, y + i + 1,
6274                              x, y + 2 * arrow_width - i - 1);
6275               x --;
6276             }
6277         }
6278       else if (direction == GTK_TEXT_DIR_LTR)
6279         {
6280           x = location->x + stem_width - offset;
6281           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6282   
6283           for (i = 0; i < arrow_width; i++) 
6284             {
6285               gdk_draw_line (drawable, gc,
6286                              x, y + i + 1,
6287                              x, y + 2 * arrow_width - i - 1);
6288               x++;
6289             }
6290         }
6291     }
6292 }