]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
Add editable interface. This should be the last big GtkTreeView API
[~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
50 /* --- prototypes --- */
51 static void      gtk_style_init                 (GtkStyle       *style);
52 static void      gtk_style_class_init           (GtkStyleClass  *klass);
53 static void      gtk_style_finalize             (GObject        *object);
54 static void      gtk_style_realize              (GtkStyle       *style,
55                                                  GdkColormap    *colormap);
56 static void      gtk_style_real_realize        (GtkStyle        *style);
57 static void      gtk_style_real_unrealize      (GtkStyle        *style);
58 static void      gtk_style_real_copy           (GtkStyle        *style,
59                                                 GtkStyle        *src);
60 static void      gtk_style_real_set_background (GtkStyle        *style,
61                                                 GdkWindow       *window,
62                                                 GtkStateType     state_type);
63 static GtkStyle *gtk_style_real_clone          (GtkStyle        *style);
64 static void      gtk_style_real_init_from_rc   (GtkStyle        *style,
65                                                 GtkRcStyle      *rc_style);
66 static GdkPixbuf *gtk_default_render_icon      (GtkStyle            *style,
67                                                 const GtkIconSource *source,
68                                                 GtkTextDirection     direction,
69                                                 GtkStateType         state,
70                                                 GtkIconSize          size,
71                                                 GtkWidget           *widget,
72                                                 const gchar         *detail);
73 static void gtk_default_draw_hline      (GtkStyle        *style,
74                                          GdkWindow       *window,
75                                          GtkStateType     state_type,
76                                          GdkRectangle    *area,
77                                          GtkWidget       *widget,
78                                          const gchar     *detail,
79                                          gint             x1,
80                                          gint             x2,
81                                          gint             y);
82 static void gtk_default_draw_vline      (GtkStyle        *style,
83                                          GdkWindow       *window,
84                                          GtkStateType     state_type,
85                                          GdkRectangle    *area,
86                                          GtkWidget       *widget,
87                                          const gchar     *detail,
88                                          gint             y1,
89                                          gint             y2,
90                                          gint             x);
91 static void gtk_default_draw_shadow     (GtkStyle        *style,
92                                          GdkWindow       *window,
93                                          GtkStateType     state_type,
94                                          GtkShadowType    shadow_type,
95                                          GdkRectangle    *area,
96                                          GtkWidget       *widget,
97                                          const gchar     *detail,
98                                          gint             x,
99                                          gint             y,
100                                          gint             width,
101                                          gint             height);
102 static void gtk_default_draw_polygon    (GtkStyle        *style,
103                                          GdkWindow       *window,
104                                          GtkStateType     state_type,
105                                          GtkShadowType    shadow_type,
106                                          GdkRectangle    *area,
107                                          GtkWidget       *widget,
108                                          const gchar     *detail,
109                                          GdkPoint        *points,
110                                          gint             npoints,
111                                          gboolean         fill);
112 static void gtk_default_draw_arrow      (GtkStyle        *style,
113                                          GdkWindow       *window,
114                                          GtkStateType     state_type,
115                                          GtkShadowType    shadow_type,
116                                          GdkRectangle    *area,
117                                          GtkWidget       *widget,
118                                          const gchar     *detail,
119                                          GtkArrowType     arrow_type,
120                                          gboolean         fill,
121                                          gint             x,
122                                          gint             y,
123                                          gint             width,
124                                          gint             height);
125 static void gtk_default_draw_diamond    (GtkStyle        *style,
126                                          GdkWindow       *window,
127                                          GtkStateType     state_type,
128                                          GtkShadowType    shadow_type,
129                                          GdkRectangle    *area,
130                                          GtkWidget       *widget,
131                                          const gchar     *detail,
132                                          gint             x,
133                                          gint             y,
134                                          gint             width,
135                                          gint             height);
136 static void gtk_default_draw_string     (GtkStyle        *style,
137                                          GdkWindow       *window,
138                                          GtkStateType     state_type,
139                                          GdkRectangle    *area,
140                                          GtkWidget       *widget,
141                                          const gchar     *detail,
142                                          gint             x,
143                                          gint             y,
144                                          const gchar     *string);
145 static void gtk_default_draw_box        (GtkStyle        *style,
146                                          GdkWindow       *window,
147                                          GtkStateType     state_type,
148                                          GtkShadowType    shadow_type,
149                                          GdkRectangle    *area,
150                                          GtkWidget       *widget,
151                                          const gchar     *detail,
152                                          gint             x,
153                                          gint             y,
154                                          gint             width,
155                                          gint             height);
156 static void gtk_default_draw_flat_box   (GtkStyle        *style,
157                                          GdkWindow       *window,
158                                          GtkStateType     state_type,
159                                          GtkShadowType    shadow_type,
160                                          GdkRectangle    *area,
161                                          GtkWidget       *widget,
162                                          const gchar     *detail,
163                                          gint             x,
164                                          gint             y,
165                                          gint             width,
166                                          gint             height);
167 static void gtk_default_draw_check      (GtkStyle        *style,
168                                          GdkWindow       *window,
169                                          GtkStateType     state_type,
170                                          GtkShadowType    shadow_type,
171                                          GdkRectangle    *area,
172                                          GtkWidget       *widget,
173                                          const gchar     *detail,
174                                          gint             x,
175                                          gint             y,
176                                          gint             width,
177                                          gint             height);
178 static void gtk_default_draw_option     (GtkStyle        *style,
179                                          GdkWindow       *window,
180                                          GtkStateType     state_type,
181                                          GtkShadowType    shadow_type,
182                                          GdkRectangle    *area,
183                                          GtkWidget       *widget,
184                                          const gchar     *detail,
185                                          gint             x,
186                                          gint             y,
187                                          gint             width,
188                                          gint             height);
189 static void gtk_default_draw_tab        (GtkStyle        *style,
190                                          GdkWindow       *window,
191                                          GtkStateType     state_type,
192                                          GtkShadowType    shadow_type,
193                                          GdkRectangle    *area,
194                                          GtkWidget       *widget,
195                                          const gchar     *detail,
196                                          gint             x,
197                                          gint             y,
198                                          gint             width,
199                                          gint             height);
200 static void gtk_default_draw_shadow_gap (GtkStyle        *style,
201                                          GdkWindow       *window,
202                                          GtkStateType     state_type,
203                                          GtkShadowType    shadow_type,
204                                          GdkRectangle    *area,
205                                          GtkWidget       *widget,
206                                          const gchar     *detail,
207                                          gint             x,
208                                          gint             y,
209                                          gint             width,
210                                          gint             height,
211                                          GtkPositionType  gap_side,
212                                          gint             gap_x,
213                                          gint             gap_width);
214 static void gtk_default_draw_box_gap    (GtkStyle        *style,
215                                          GdkWindow       *window,
216                                          GtkStateType     state_type,
217                                          GtkShadowType    shadow_type,
218                                          GdkRectangle    *area,
219                                          GtkWidget       *widget,
220                                          const gchar     *detail,
221                                          gint             x,
222                                          gint             y,
223                                          gint             width,
224                                          gint             height,
225                                          GtkPositionType  gap_side,
226                                          gint             gap_x,
227                                          gint             gap_width);
228 static void gtk_default_draw_extension  (GtkStyle        *style,
229                                          GdkWindow       *window,
230                                          GtkStateType     state_type,
231                                          GtkShadowType    shadow_type,
232                                          GdkRectangle    *area,
233                                          GtkWidget       *widget,
234                                          const gchar     *detail,
235                                          gint             x,
236                                          gint             y,
237                                          gint             width,
238                                          gint             height,
239                                          GtkPositionType  gap_side);
240 static void gtk_default_draw_focus      (GtkStyle        *style,
241                                          GdkWindow       *window,
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
315 /*
316  * Data for default check and radio buttons
317  */
318
319 static GtkRequisition default_option_indicator_size = { 7, 13 };
320 static GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
321
322 #define INDICATOR_PART_SIZE 13
323
324 typedef enum {
325   CHECK_AA,
326   CHECK_BASE,
327   CHECK_BLACK,
328   CHECK_DARK,
329   CHECK_LIGHT,
330   CHECK_MID,
331   CHECK_TEXT,
332   RADIO_BASE,
333   RADIO_BLACK,
334   RADIO_DARK,
335   RADIO_LIGHT,
336   RADIO_MID,
337   RADIO_TEXT
338 } IndicatorPart;
339
340 static char check_aa_bits[] = {
341  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x58,0x00,0xa0,
342  0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
343 static char check_base_bits[] = {
344  0x00,0x00,0x00,0x00,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
345  0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0x00,0x00,0x00,0x00};
346 static char check_black_bits[] = {
347  0x00,0x00,0xfe,0x0f,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
348  0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00};
349 static char check_dark_bits[] = {
350  0xff,0x1f,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
351  0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
352 static char check_light_bits[] = {
353  0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
354  0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xfe,0x1f};
355 static char 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};
358 static char check_text_bits[] = {
359  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x80,0x01,0x80,0x00,0xd8,
360  0x00,0x60,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
361 static char radio_base_bits[] = {
362  0x00,0x00,0x00,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
363  0x07,0xfc,0x07,0xf8,0x03,0xf0,0x01,0x00,0x00,0x00,0x00};
364 static char radio_black_bits[] = {
365  0x00,0x00,0xf0,0x01,0x08,0x02,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
366  0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
367 static char radio_dark_bits[] = {
368  0xf0,0x01,0x08,0x02,0x04,0x04,0x02,0x04,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
369  0x00,0x01,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x00};
370 static char radio_light_bits[] = {
371  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
372  0x10,0x00,0x10,0x00,0x08,0x00,0x04,0x08,0x02,0xf0,0x01};
373 static char radio_mid_bits[] = {
374  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
375  0x08,0x00,0x08,0x00,0x04,0x00,0x02,0xf0,0x01,0x00,0x00};
376 static char radio_text_bits[] = {
377  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0x01,0xf0,0x01,0xf0,
378  0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
379
380 static struct {
381   char      *bits;
382   GdkBitmap *bmap;
383 } indicator_parts[] = {
384   { check_aa_bits, NULL },
385   { check_base_bits, NULL },
386   { check_black_bits, NULL },
387   { check_dark_bits, NULL },
388   { check_light_bits, NULL },
389   { check_mid_bits, NULL },
390   { check_text_bits, NULL },
391   { radio_base_bits, NULL },
392   { radio_black_bits, NULL },
393   { radio_dark_bits, NULL },
394   { radio_light_bits, NULL },
395   { radio_mid_bits, NULL },
396   { radio_text_bits, NULL }
397 };
398
399 /* --- variables --- */
400 static GdkColor gtk_default_normal_fg =      { 0,      0,      0,      0 };
401 static GdkColor gtk_default_active_fg =      { 0,      0,      0,      0 };
402 static GdkColor gtk_default_prelight_fg =    { 0,      0,      0,      0 };
403 static GdkColor gtk_default_selected_fg =    { 0, 0xffff, 0xffff, 0xffff };
404 static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 };
405
406 static GdkColor gtk_default_normal_bg =      { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
407 static GdkColor gtk_default_active_bg =      { 0, 0xc350, 0xc350, 0xc350 };
408 static GdkColor gtk_default_prelight_bg =    { 0, 0xea60, 0xea60, 0xea60 };
409 static GdkColor gtk_default_selected_bg =    { 0,      0,      0, 0x9c40 };
410 static GdkColor gtk_default_insensitive_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
411 static GdkColor gtk_default_selected_base =  { 0, 0xa4a4, 0xdfdf, 0xffff };
412 static GdkColor gtk_default_active_base =    { 0, 0xbcbc, 0xd2d2, 0xeeee };
413
414 static gpointer parent_class = NULL;
415 static GdkFont *static_default_font = NULL;
416
417
418 /* --- functions --- */
419 GType
420 gtk_style_get_type (void)
421 {
422   static GType style_type = 0;
423   
424   if (!style_type)
425     {
426       static const GTypeInfo style_info =
427       {
428         sizeof (GtkStyleClass),
429         (GBaseInitFunc) NULL,
430         (GBaseFinalizeFunc) NULL,
431         (GClassInitFunc) gtk_style_class_init,
432         NULL,           /* class_finalize */
433         NULL,           /* class_data */
434         sizeof (GtkStyle),
435         0,              /* n_preallocs */
436         (GInstanceInitFunc) gtk_style_init,
437       };
438       
439       style_type = g_type_register_static (G_TYPE_OBJECT,
440                                            "GtkStyle",
441                                            &style_info, 0);
442     }
443   
444   return style_type;
445 }
446
447 static void
448 gtk_style_init (GtkStyle *style)
449 {
450   gint i;
451   
452   style->font_desc = pango_font_description_from_string ("Sans 10");
453
454   if (!static_default_font)
455     {
456       static_default_font = gdk_font_from_description (style->font_desc);
457
458       if (!static_default_font) 
459         static_default_font = gdk_font_load ("fixed");
460
461       if (!static_default_font) 
462         g_error ("Unable to load \"fixed\" font");
463     }
464   
465   style->font = static_default_font;
466   gdk_font_ref (style->font);
467
468   style->attach_count = 0;
469   style->colormap = NULL;
470   style->depth = -1;
471   
472   style->black.red = 0;
473   style->black.green = 0;
474   style->black.blue = 0;
475   
476   style->white.red = 65535;
477   style->white.green = 65535;
478   style->white.blue = 65535;
479   
480   style->black_gc = NULL;
481   style->white_gc = NULL;
482   
483   style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
484   style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
485   style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
486   style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
487   style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
488   
489   style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
490   style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
491   style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
492   style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
493   style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
494   
495   for (i = 0; i < 4; i++)
496     {
497       style->text[i] = style->fg[i];
498       style->base[i] = style->white;
499     }
500
501   style->base[GTK_STATE_SELECTED] = gtk_default_selected_base;
502   style->text[GTK_STATE_SELECTED] = style->black;
503   style->base[GTK_STATE_ACTIVE] = gtk_default_active_base;
504   style->text[GTK_STATE_ACTIVE] = style->black;
505   style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg;
506   style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
507   
508   for (i = 0; i < 5; i++)
509     style->bg_pixmap[i] = NULL;
510   
511   style->rc_style = NULL;
512   
513   for (i = 0; i < 5; i++)
514     {
515       style->fg_gc[i] = NULL;
516       style->bg_gc[i] = NULL;
517       style->light_gc[i] = NULL;
518       style->dark_gc[i] = NULL;
519       style->mid_gc[i] = NULL;
520       style->text_gc[i] = NULL;
521       style->base_gc[i] = NULL;
522       style->text_aa_gc[i] = NULL;
523     }
524
525   style->xthickness = 2;
526   style->ythickness = 2;
527
528   style->property_cache = NULL;
529 }
530
531 static void
532 gtk_style_class_init (GtkStyleClass *klass)
533 {
534   GObjectClass *object_class = G_OBJECT_CLASS (klass);
535   
536   parent_class = g_type_class_peek_parent (klass);
537
538   object_class->finalize = gtk_style_finalize;
539
540   klass->clone = gtk_style_real_clone;
541   klass->copy = gtk_style_real_copy;
542   klass->init_from_rc = gtk_style_real_init_from_rc;
543   klass->realize = gtk_style_real_realize;
544   klass->unrealize = gtk_style_real_unrealize;
545   klass->set_background = gtk_style_real_set_background;
546   klass->render_icon = gtk_default_render_icon;
547
548   klass->draw_hline = gtk_default_draw_hline;
549   klass->draw_vline = gtk_default_draw_vline;
550   klass->draw_shadow = gtk_default_draw_shadow;
551   klass->draw_polygon = gtk_default_draw_polygon;
552   klass->draw_arrow = gtk_default_draw_arrow;
553   klass->draw_diamond = gtk_default_draw_diamond;
554   klass->draw_string = gtk_default_draw_string;
555   klass->draw_box = gtk_default_draw_box;
556   klass->draw_flat_box = gtk_default_draw_flat_box;
557   klass->draw_check = gtk_default_draw_check;
558   klass->draw_option = gtk_default_draw_option;
559   klass->draw_tab = gtk_default_draw_tab;
560   klass->draw_shadow_gap = gtk_default_draw_shadow_gap;
561   klass->draw_box_gap = gtk_default_draw_box_gap;
562   klass->draw_extension = gtk_default_draw_extension;
563   klass->draw_focus = gtk_default_draw_focus;
564   klass->draw_slider = gtk_default_draw_slider;
565   klass->draw_handle = gtk_default_draw_handle;
566   klass->draw_expander = gtk_default_draw_expander;
567   klass->draw_layout = gtk_default_draw_layout;
568   klass->draw_resize_grip = gtk_default_draw_resize_grip;
569 }
570
571 static void
572 clear_property_cache (GtkStyle *style)
573 {
574   if (style->property_cache)
575     {
576       guint i;
577
578       for (i = 0; i < style->property_cache->len; i++)
579         {
580           PropertyValue *node = &g_array_index (style->property_cache, PropertyValue, i);
581
582           g_param_spec_unref (node->pspec);
583           g_value_unset (&node->value);
584         }
585       g_array_free (style->property_cache, TRUE);
586       style->property_cache = NULL;
587     }
588 }
589
590 static void
591 gtk_style_finalize (GObject *object)
592 {
593   GtkStyle *style = GTK_STYLE (object);
594
595   g_return_if_fail (style->attach_count == 0);
596
597   clear_property_cache (style);
598   
599   if (style->styles)
600     {
601       if (style->styles->data != style)
602         g_slist_remove (style->styles, style);
603       else
604         {
605           GSList *tmp_list = style->styles->next;
606           
607           while (tmp_list)
608             {
609               GTK_STYLE (tmp_list->data)->styles = style->styles->next;
610               tmp_list = tmp_list->next;
611             }
612           g_slist_free_1 (style->styles);
613         }
614     }
615   
616   gdk_font_unref (style->font);
617   pango_font_description_free (style->font_desc);
618   
619   if (style->rc_style)
620     gtk_rc_style_unref (style->rc_style);
621   
622   G_OBJECT_CLASS (parent_class)->finalize (object);
623 }
624
625
626 GtkStyle*
627 gtk_style_copy (GtkStyle *style)
628 {
629   GtkStyle *new_style;
630   
631   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
632   
633   new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
634   GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
635
636   return new_style;
637 }
638
639 static GtkStyle*
640 gtk_style_duplicate (GtkStyle *style)
641 {
642   GtkStyle *new_style;
643   
644   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
645   
646   new_style = gtk_style_copy (style);
647   
648   style->styles = g_slist_append (style->styles, new_style);
649   new_style->styles = style->styles;  
650   
651   return new_style;
652 }
653
654 GtkStyle*
655 gtk_style_new (void)
656 {
657   GtkStyle *style;
658   
659   style = g_object_new (GTK_TYPE_STYLE, NULL);
660   
661   return style;
662 }
663
664 /*************************************************************
665  * gtk_style_attach:
666  *     Attach a style to a window; this process allocates the
667  *     colors and creates the GC's for the style - it specializes
668  *     it to a particular visual and colormap. The process
669  *     may involve the creation of a new style if the style
670  *     has already been attached to a window with a different
671  *     style and colormap.
672  *   arguments:
673  *     style:
674  *     window: 
675  *   results:
676  *     Either the style parameter, or a newly created style.
677  *     If the style is newly created, the style parameter
678  *     will be dereferenced, and the new style will have
679  *     a reference count belonging to the caller.
680  *
681  * FIXME: The sequence - 
682  *    create a style => s1
683  *    attach s1 to v1, c1 => s1
684  *    attach s1 to v2, c2 => s2
685  *    detach s1 from v1, c1
686  *    attach s1 to v2, c2 => s3
687  * results in two separate, unlinked styles s2 and s3 which
688  * are identical and could be shared. To fix this, we would
689  * want to never remove a style from the list of linked
690  * styles as long as as it has a reference count. However, the 
691  * disadvantage of doing it this way means that we would need two 
692  * passes through the linked list when attaching (one to check for 
693  * matching styles, one to look for empty unattached styles - but 
694  * it will almost never be longer than 2 elements.
695  *************************************************************/
696
697 GtkStyle*
698 gtk_style_attach (GtkStyle  *style,
699                   GdkWindow *window)
700 {
701   GSList *styles;
702   GtkStyle *new_style = NULL;
703   GdkColormap *colormap;
704   
705   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
706   g_return_val_if_fail (window != NULL, NULL);
707   
708   colormap = gdk_window_get_colormap (window);
709   
710   if (!style->styles)
711     style->styles = g_slist_append (NULL, style);
712   
713   styles = style->styles;
714   while (styles)
715     {
716       new_style = styles->data;
717       
718       if (new_style->attach_count == 0)
719         {
720           gtk_style_realize (new_style, colormap);
721           break;
722         }
723       else if (new_style->colormap == colormap)
724         break;
725       
726       new_style = NULL;
727       styles = styles->next;
728     }
729   
730   if (!new_style)
731     {
732       new_style = gtk_style_duplicate (style);
733       gtk_style_realize (new_style, colormap);
734     }
735
736   /* A style gets a refcount from being attached */
737   if (new_style->attach_count == 0)
738     gtk_style_ref (new_style);
739
740   /* Another refcount belongs to the parent */
741   if (style != new_style) 
742     {
743       gtk_style_unref (style);
744       gtk_style_ref (new_style);
745     }
746   
747   new_style->attach_count++;
748   
749   return new_style;
750 }
751
752 void
753 gtk_style_detach (GtkStyle *style)
754 {
755   g_return_if_fail (GTK_IS_STYLE (style));
756   
757   style->attach_count -= 1;
758   if (style->attach_count == 0)
759     {
760       GTK_STYLE_GET_CLASS (style)->unrealize (style);
761       
762       gdk_colormap_unref (style->colormap);
763       style->colormap = NULL;
764       
765       gtk_style_unref (style);
766     }
767 }
768
769 GtkStyle*
770 gtk_style_ref (GtkStyle *style)
771 {
772   return (GtkStyle *) g_object_ref (G_OBJECT (style));
773 }
774
775 void
776 gtk_style_unref (GtkStyle *style)
777 {
778   g_object_unref (G_OBJECT (style));
779 }
780
781 static void
782 gtk_style_realize (GtkStyle    *style,
783                    GdkColormap *colormap)
784 {
785   g_return_if_fail (GTK_IS_STYLE (style));
786   g_return_if_fail (GDK_IS_COLORMAP (colormap));
787   
788   style->colormap = gdk_colormap_ref (colormap);
789   style->depth = gdk_colormap_get_visual (colormap)->depth;
790
791   GTK_STYLE_GET_CLASS (style)->realize (style);
792 }
793
794 GtkIconSet*
795 gtk_style_lookup_icon_set (GtkStyle   *style,
796                            const char *stock_id)
797 {
798   GSList *iter;
799
800   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
801   g_return_val_if_fail (stock_id != NULL, NULL);
802   
803   iter = style->icon_factories;
804   while (iter != NULL)
805     {
806       GtkIconSet *icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
807                                                       stock_id);
808       if (icon_set)
809         return icon_set;
810       
811       iter = g_slist_next (iter);
812     }
813
814   return gtk_icon_factory_lookup_default (stock_id);
815 }
816
817 void
818 gtk_draw_hline (GtkStyle     *style,
819                 GdkWindow    *window,
820                 GtkStateType  state_type,
821                 gint          x1,
822                 gint          x2,
823                 gint          y)
824 {
825   g_return_if_fail (GTK_IS_STYLE (style));
826   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
827   
828   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, NULL, NULL, NULL, x1, x2, y);
829 }
830
831
832 void
833 gtk_draw_vline (GtkStyle     *style,
834                 GdkWindow    *window,
835                 GtkStateType  state_type,
836                 gint          y1,
837                 gint          y2,
838                 gint          x)
839 {
840   g_return_if_fail (GTK_IS_STYLE (style));
841   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
842   
843   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, NULL, NULL, NULL, y1, y2, x);
844 }
845
846
847 void
848 gtk_draw_shadow (GtkStyle      *style,
849                  GdkWindow     *window,
850                  GtkStateType   state_type,
851                  GtkShadowType  shadow_type,
852                  gint           x,
853                  gint           y,
854                  gint           width,
855                  gint           height)
856 {
857   g_return_if_fail (GTK_IS_STYLE (style));
858   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
859   
860   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
861 }
862
863 void
864 gtk_draw_polygon (GtkStyle      *style,
865                   GdkWindow     *window,
866                   GtkStateType   state_type,
867                   GtkShadowType  shadow_type,
868                   GdkPoint      *points,
869                   gint           npoints,
870                   gboolean       fill)
871 {
872   g_return_if_fail (GTK_IS_STYLE (style));
873   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_polygon != NULL);
874   
875   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, NULL, NULL, NULL, points, npoints, fill);
876 }
877
878 void
879 gtk_draw_arrow (GtkStyle      *style,
880                 GdkWindow     *window,
881                 GtkStateType   state_type,
882                 GtkShadowType  shadow_type,
883                 GtkArrowType   arrow_type,
884                 gboolean       fill,
885                 gint           x,
886                 gint           y,
887                 gint           width,
888                 gint           height)
889 {
890   g_return_if_fail (GTK_IS_STYLE (style));
891   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
892   
893   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, NULL, NULL, NULL, arrow_type, fill, x, y, width, height);
894 }
895
896
897 void
898 gtk_draw_diamond (GtkStyle      *style,
899                   GdkWindow     *window,
900                   GtkStateType   state_type,
901                   GtkShadowType  shadow_type,
902                   gint           x,
903                   gint           y,
904                   gint           width,
905                   gint           height)
906 {
907   g_return_if_fail (GTK_IS_STYLE (style));
908   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
909   
910   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
911 }
912
913
914 void
915 gtk_draw_string (GtkStyle      *style,
916                  GdkWindow     *window,
917                  GtkStateType   state_type,
918                  gint           x,
919                  gint           y,
920                  const gchar   *string)
921 {
922   g_return_if_fail (GTK_IS_STYLE (style));
923   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
924   
925   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, NULL, NULL, NULL, x, y, string);
926 }
927
928 void
929 gtk_draw_box (GtkStyle      *style,
930               GdkWindow     *window,
931               GtkStateType   state_type,
932               GtkShadowType  shadow_type,
933               gint           x,
934               gint           y,
935               gint           width,
936               gint           height)
937 {
938   g_return_if_fail (GTK_IS_STYLE (style));
939   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
940   
941   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
942 }
943
944 void
945 gtk_draw_flat_box (GtkStyle      *style,
946                    GdkWindow     *window,
947                    GtkStateType   state_type,
948                    GtkShadowType  shadow_type,
949                    gint           x,
950                    gint           y,
951                    gint           width,
952                    gint           height)
953 {
954   g_return_if_fail (GTK_IS_STYLE (style));
955   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
956   
957   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
958 }
959
960 void
961 gtk_draw_check (GtkStyle      *style,
962                 GdkWindow     *window,
963                 GtkStateType   state_type,
964                 GtkShadowType  shadow_type,
965                 gint           x,
966                 gint           y,
967                 gint           width,
968                 gint           height)
969 {
970   g_return_if_fail (GTK_IS_STYLE (style));
971   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
972   
973   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
974 }
975
976 void
977 gtk_draw_option (GtkStyle      *style,
978                  GdkWindow     *window,
979                  GtkStateType   state_type,
980                  GtkShadowType  shadow_type,
981                  gint           x,
982                  gint           y,
983                  gint           width,
984                  gint           height)
985 {
986   g_return_if_fail (GTK_IS_STYLE (style));
987   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
988   
989   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
990 }
991
992 void
993 gtk_draw_tab (GtkStyle      *style,
994               GdkWindow     *window,
995               GtkStateType   state_type,
996               GtkShadowType  shadow_type,
997               gint           x,
998               gint           y,
999               gint           width,
1000               gint           height)
1001 {
1002   g_return_if_fail (GTK_IS_STYLE (style));
1003   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
1004   
1005   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1006 }
1007
1008 void
1009 gtk_draw_shadow_gap (GtkStyle       *style,
1010                      GdkWindow      *window,
1011                      GtkStateType    state_type,
1012                      GtkShadowType   shadow_type,
1013                      gint            x,
1014                      gint            y,
1015                      gint            width,
1016                      gint            height,
1017                      GtkPositionType gap_side,
1018                      gint            gap_x,
1019                      gint            gap_width)
1020 {
1021   g_return_if_fail (GTK_IS_STYLE (style));
1022   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
1023   
1024   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);
1025 }
1026
1027 void
1028 gtk_draw_box_gap (GtkStyle       *style,
1029                   GdkWindow      *window,
1030                   GtkStateType    state_type,
1031                   GtkShadowType   shadow_type,
1032                   gint            x,
1033                   gint            y,
1034                   gint            width,
1035                   gint            height,
1036                   GtkPositionType gap_side,
1037                   gint            gap_x,
1038                   gint            gap_width)
1039 {
1040   g_return_if_fail (GTK_IS_STYLE (style));
1041   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
1042   
1043   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);
1044 }
1045
1046 void
1047 gtk_draw_extension (GtkStyle       *style,
1048                     GdkWindow      *window,
1049                     GtkStateType    state_type,
1050                     GtkShadowType   shadow_type,
1051                     gint            x,
1052                     gint            y,
1053                     gint            width,
1054                     gint            height,
1055                     GtkPositionType gap_side)
1056 {
1057   g_return_if_fail (GTK_IS_STYLE (style));
1058   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
1059   
1060   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side);
1061 }
1062
1063 void
1064 gtk_draw_focus (GtkStyle      *style,
1065                 GdkWindow     *window,
1066                 gint           x,
1067                 gint           y,
1068                 gint           width,
1069                 gint           height)
1070 {
1071   g_return_if_fail (GTK_IS_STYLE (style));
1072   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
1073   
1074   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, NULL, NULL, NULL, x, y, width, height);
1075 }
1076
1077 void 
1078 gtk_draw_slider (GtkStyle      *style,
1079                  GdkWindow     *window,
1080                  GtkStateType   state_type,
1081                  GtkShadowType  shadow_type,
1082                  gint           x,
1083                  gint           y,
1084                  gint           width,
1085                  gint           height,
1086                  GtkOrientation orientation)
1087 {
1088   g_return_if_fail (GTK_IS_STYLE (style));
1089   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
1090   
1091   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation);
1092 }
1093
1094 void 
1095 gtk_draw_handle (GtkStyle      *style,
1096                  GdkWindow     *window,
1097                  GtkStateType   state_type,
1098                  GtkShadowType  shadow_type,
1099                  gint           x,
1100                  gint           y,
1101                  gint           width,
1102                  gint           height,
1103                  GtkOrientation orientation)
1104 {
1105   g_return_if_fail (GTK_IS_STYLE (style));
1106   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
1107   
1108   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation);
1109 }
1110
1111 void
1112 gtk_draw_expander (GtkStyle        *style,
1113                    GdkWindow       *window,
1114                    GtkStateType     state_type,
1115                    gint             x,
1116                    gint             y,
1117                    GtkExpanderStyle expander_style)
1118 {
1119   g_return_if_fail (GTK_IS_STYLE (style));
1120   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
1121   
1122   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type,
1123                                               NULL, NULL, NULL,
1124                                               x, y, expander_style);
1125 }
1126
1127 void
1128 gtk_draw_layout (GtkStyle        *style,
1129                  GdkWindow       *window,
1130                  GtkStateType     state_type,
1131                  gboolean         use_text,
1132                  gint             x,
1133                  gint             y,
1134                  PangoLayout     *layout)
1135 {
1136   g_return_if_fail (GTK_IS_STYLE (style));
1137   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
1138   
1139   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text,
1140                                             NULL, NULL, NULL,
1141                                             x, y, layout);
1142 }
1143
1144 void
1145 gtk_draw_resize_grip (GtkStyle     *style,
1146                       GdkWindow    *window,
1147                       GtkStateType  state_type,
1148                       GdkWindowEdge edge,
1149                       gint          x,
1150                       gint          y,
1151                       gint          width,
1152                       gint          height)
1153 {
1154   g_return_if_fail (GTK_IS_STYLE (style));
1155   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
1156
1157   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
1158                                                  NULL, NULL, NULL,
1159                                                  edge,
1160                                                  x, y, width, height);
1161 }
1162
1163
1164 void
1165 gtk_style_set_background (GtkStyle    *style,
1166                           GdkWindow   *window,
1167                           GtkStateType state_type)
1168 {
1169   g_return_if_fail (GTK_IS_STYLE (style));
1170   g_return_if_fail (window != NULL);
1171   
1172   GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
1173 }
1174
1175 /* Default functions */
1176 static GtkStyle *
1177 gtk_style_real_clone (GtkStyle *style)
1178 {
1179   return GTK_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
1180 }
1181
1182 static void
1183 gtk_style_real_copy (GtkStyle *style,
1184                      GtkStyle *src)
1185 {
1186   gint i;
1187   
1188   for (i = 0; i < 5; i++)
1189     {
1190       style->fg[i] = src->fg[i];
1191       style->bg[i] = src->bg[i];
1192       style->text[i] = src->text[i];
1193       style->base[i] = src->base[i];
1194       
1195       style->bg_pixmap[i] = src->bg_pixmap[i];
1196     }
1197
1198   if (style->font)
1199     gdk_font_unref (style->font);
1200   style->font = src->font;
1201   if (style->font)
1202     gdk_font_ref (style->font);
1203
1204   if (style->font_desc)
1205     pango_font_description_free (style->font_desc);
1206   if (src->font_desc)
1207     style->font_desc = pango_font_description_copy (src->font_desc);
1208   else
1209     style->font_desc = NULL;
1210   
1211   style->xthickness = src->xthickness;
1212   style->ythickness = src->ythickness;
1213
1214   if (style->rc_style)
1215     gtk_rc_style_unref (style->rc_style);
1216   style->rc_style = src->rc_style;
1217   if (src->rc_style)
1218     gtk_rc_style_ref (src->rc_style);
1219
1220   /* don't copy, just clear cache */
1221   clear_property_cache (style);
1222 }
1223
1224 static void
1225 gtk_style_real_init_from_rc (GtkStyle   *style,
1226                              GtkRcStyle *rc_style)
1227 {
1228   GdkFont *old_font;
1229   gint i;
1230
1231   /* cache _should_ be still empty */
1232   clear_property_cache (style);
1233
1234   if (rc_style->font_desc)
1235     {
1236       pango_font_description_free (style->font_desc);
1237       style->font_desc = pango_font_description_copy (rc_style->font_desc);
1238
1239       old_font = style->font;
1240       style->font = gdk_font_from_description (style->font_desc);
1241       if (style->font)
1242         gdk_font_unref (old_font);
1243       else
1244         style->font = old_font;
1245     }
1246     
1247   for (i = 0; i < 5; i++)
1248     {
1249       if (rc_style->color_flags[i] & GTK_RC_FG)
1250         style->fg[i] = rc_style->fg[i];
1251       if (rc_style->color_flags[i] & GTK_RC_BG)
1252         style->bg[i] = rc_style->bg[i];
1253       if (rc_style->color_flags[i] & GTK_RC_TEXT)
1254         style->text[i] = rc_style->text[i];
1255       if (rc_style->color_flags[i] & GTK_RC_BASE)
1256         style->base[i] = rc_style->base[i];
1257     }
1258
1259   if (rc_style->xthickness >= 0)
1260     style->xthickness = rc_style->xthickness;
1261   if (rc_style->ythickness >= 0)
1262     style->ythickness = rc_style->ythickness;
1263
1264   if (rc_style->icon_factories)
1265     {
1266       GSList *iter;
1267
1268       style->icon_factories = g_slist_copy (rc_style->icon_factories);
1269       
1270       iter = style->icon_factories;
1271       while (iter != NULL)
1272         {
1273           g_object_ref (G_OBJECT (iter->data));
1274           
1275           iter = g_slist_next (iter);
1276         }
1277     }
1278 }
1279
1280 static gint
1281 style_property_values_cmp (gconstpointer bsearch_node1,
1282                            gconstpointer bsearch_node2)
1283 {
1284   const PropertyValue *val1 = bsearch_node1;
1285   const PropertyValue *val2 = bsearch_node2;
1286
1287   if (val1->widget_type == val2->widget_type)
1288     return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
1289   else
1290     return val1->widget_type < val2->widget_type ? -1 : 1;
1291 }
1292
1293 const GValue*
1294 _gtk_style_peek_property_value (GtkStyle           *style,
1295                                 GType               widget_type,
1296                                 GParamSpec         *pspec,
1297                                 GtkRcPropertyParser parser)
1298 {
1299   PropertyValue *pcache, key = { 0, NULL, { 0, } };
1300   const GtkRcProperty *rcprop = NULL;
1301   guint i;
1302
1303   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1304   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
1305   g_return_val_if_fail (g_type_is_a (pspec->owner_type, GTK_TYPE_WIDGET), NULL);
1306   g_return_val_if_fail (g_type_is_a (widget_type, pspec->owner_type), NULL);
1307
1308   key.widget_type = widget_type;
1309   key.pspec = pspec;
1310
1311   /* need value cache array */
1312   if (!style->property_cache)
1313     style->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
1314   else
1315     {
1316       pcache = bsearch (&key,
1317                         style->property_cache->data, style->property_cache->len,
1318                         sizeof (PropertyValue), style_property_values_cmp);
1319       if (pcache)
1320         return &pcache->value;
1321     }
1322
1323   i = 0;
1324   while (i < style->property_cache->len &&
1325          style_property_values_cmp (&key, &g_array_index (style->property_cache, PropertyValue, i)) >= 0)
1326     i++;
1327
1328   g_array_insert_val (style->property_cache, i, key);
1329   pcache = &g_array_index (style->property_cache, PropertyValue, i);
1330
1331   /* cache miss, initialize value type, then set contents */
1332   g_param_spec_ref (pcache->pspec);
1333   g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1334
1335   /* value provided by rc style? */
1336   if (style->rc_style)
1337     {
1338       GQuark prop_quark = g_quark_from_string (pspec->name);
1339
1340       do
1341         {
1342           rcprop = _gtk_rc_style_lookup_rc_property (style->rc_style,
1343                                                      g_type_qname (widget_type),
1344                                                      prop_quark);
1345           if (rcprop)
1346             break;
1347           widget_type = g_type_parent (widget_type);
1348         }
1349       while (g_type_is_a (widget_type, pspec->owner_type));
1350     }
1351
1352   /* when supplied by rc style, we need to convert */
1353   if (rcprop && !_gtk_settings_parse_convert (parser, &rcprop->value,
1354                                               pspec, &pcache->value))
1355     {
1356       gchar *contents = g_strdup_value_contents (&rcprop->value);
1357       
1358       g_message ("%s: failed to retrive property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
1359                  rcprop->origin,
1360                  g_type_name (pspec->owner_type), pspec->name,
1361                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1362                  contents,
1363                  G_VALUE_TYPE_NAME (&rcprop->value));
1364       g_free (contents);
1365       rcprop = NULL; /* needs default */
1366     }
1367   
1368   /* not supplied by rc style (or conversion failed), revert to default */
1369   if (!rcprop)
1370     g_param_value_set_default (pspec, &pcache->value);
1371
1372   return &pcache->value;
1373 }
1374
1375 GdkPixmap *
1376 load_bg_image (GdkColormap *colormap,
1377                GdkColor    *bg_color,
1378                const gchar *filename)
1379 {
1380   if (strcmp (filename, "<parent>") == 0)
1381     return (GdkPixmap*) GDK_PARENT_RELATIVE;
1382   else
1383     {
1384       return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
1385                                                   bg_color,
1386                                                   filename);
1387     }
1388 }
1389
1390 static void
1391 gtk_style_real_realize (GtkStyle *style)
1392 {
1393   GdkGCValues gc_values;
1394   GdkGCValuesMask gc_values_mask;
1395   
1396   gint i;
1397
1398   for (i = 0; i < 5; i++)
1399     {
1400       gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
1401       gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
1402       
1403       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1404       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
1405       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1406
1407       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1408       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
1409       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
1410     }
1411   
1412   gdk_color_black (style->colormap, &style->black);
1413   gdk_color_white (style->colormap, &style->white);
1414   
1415   gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_FONT;
1416   if (style->font->type == GDK_FONT_FONT)
1417     {
1418       gc_values.font = style->font;
1419     }
1420   else if (style->font->type == GDK_FONT_FONTSET)
1421     {
1422       gc_values.font = static_default_font;
1423     }
1424   
1425   gc_values.foreground = style->black;
1426   style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1427   
1428   gc_values.foreground = style->white;
1429   style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1430   
1431   for (i = 0; i < 5; i++)
1432     {
1433       if (style->rc_style && style->rc_style->bg_pixmap_name[i])
1434         style->bg_pixmap[i] = load_bg_image (style->colormap,
1435                                              &style->bg[i],
1436                                              style->rc_style->bg_pixmap_name[i]);
1437       
1438       if (!gdk_color_alloc (style->colormap, &style->fg[i]))
1439         g_warning ("unable to allocate color: ( %d %d %d )",
1440                    style->fg[i].red, style->fg[i].green, style->fg[i].blue);
1441       if (!gdk_color_alloc (style->colormap, &style->bg[i]))
1442         g_warning ("unable to allocate color: ( %d %d %d )",
1443                    style->bg[i].red, style->bg[i].green, style->bg[i].blue);
1444       if (!gdk_color_alloc (style->colormap, &style->light[i]))
1445         g_warning ("unable to allocate color: ( %d %d %d )",
1446                    style->light[i].red, style->light[i].green, style->light[i].blue);
1447       if (!gdk_color_alloc (style->colormap, &style->dark[i]))
1448         g_warning ("unable to allocate color: ( %d %d %d )",
1449                    style->dark[i].red, style->dark[i].green, style->dark[i].blue);
1450       if (!gdk_color_alloc (style->colormap, &style->mid[i]))
1451         g_warning ("unable to allocate color: ( %d %d %d )",
1452                    style->mid[i].red, style->mid[i].green, style->mid[i].blue);
1453       if (!gdk_color_alloc (style->colormap, &style->text[i]))
1454         g_warning ("unable to allocate color: ( %d %d %d )",
1455                    style->text[i].red, style->text[i].green, style->text[i].blue);
1456       if (!gdk_color_alloc (style->colormap, &style->base[i]))
1457         g_warning ("unable to allocate color: ( %d %d %d )",
1458                    style->base[i].red, style->base[i].green, style->base[i].blue);
1459       if (!gdk_color_alloc (style->colormap, &style->text_aa[i]))
1460         g_warning ("unable to allocate color: ( %d %d %d )",
1461                    style->text_aa[i].red, style->text_aa[i].green, style->text_aa[i].blue);
1462       
1463       gc_values.foreground = style->fg[i];
1464       style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1465       
1466       gc_values.foreground = style->bg[i];
1467       style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1468       
1469       gc_values.foreground = style->light[i];
1470       style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1471       
1472       gc_values.foreground = style->dark[i];
1473       style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1474       
1475       gc_values.foreground = style->mid[i];
1476       style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1477       
1478       gc_values.foreground = style->text[i];
1479       style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1480       
1481       gc_values.foreground = style->base[i];
1482       style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1483
1484       gc_values.foreground = style->text_aa[i];
1485       style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1486     }
1487 }
1488
1489 static void
1490 gtk_style_real_unrealize (GtkStyle *style)
1491 {
1492   int i;
1493
1494   gtk_gc_release (style->black_gc);
1495   gtk_gc_release (style->white_gc);
1496       
1497   for (i = 0; i < 5; i++)
1498     {
1499       gtk_gc_release (style->fg_gc[i]);
1500       gtk_gc_release (style->bg_gc[i]);
1501       gtk_gc_release (style->light_gc[i]);
1502       gtk_gc_release (style->dark_gc[i]);
1503       gtk_gc_release (style->mid_gc[i]);
1504       gtk_gc_release (style->text_gc[i]);
1505       gtk_gc_release (style->base_gc[i]);
1506       gtk_gc_release (style->text_aa_gc[i]);
1507
1508       if (style->bg_pixmap[i] &&  style->bg_pixmap[i] != (GdkPixmap*) GDK_PARENT_RELATIVE)
1509         gdk_pixmap_unref (style->bg_pixmap[i]);
1510     }
1511   
1512   gdk_colormap_free_colors (style->colormap, style->fg, 5);
1513   gdk_colormap_free_colors (style->colormap, style->bg, 5);
1514   gdk_colormap_free_colors (style->colormap, style->light, 5);
1515   gdk_colormap_free_colors (style->colormap, style->dark, 5);
1516   gdk_colormap_free_colors (style->colormap, style->mid, 5);
1517   gdk_colormap_free_colors (style->colormap, style->text, 5);
1518   gdk_colormap_free_colors (style->colormap, style->base, 5);
1519   gdk_colormap_free_colors (style->colormap, style->text_aa, 5);
1520 }
1521
1522 static void
1523 gtk_style_real_set_background (GtkStyle    *style,
1524                                GdkWindow   *window,
1525                                GtkStateType state_type)
1526 {
1527   GdkPixmap *pixmap;
1528   gint parent_relative;
1529   
1530   if (style->bg_pixmap[state_type])
1531     {
1532       if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1533         {
1534           pixmap = NULL;
1535           parent_relative = TRUE;
1536         }
1537       else
1538         {
1539           pixmap = style->bg_pixmap[state_type];
1540           parent_relative = FALSE;
1541         }
1542       
1543       gdk_window_set_back_pixmap (window, pixmap, parent_relative);
1544     }
1545   else
1546     gdk_window_set_background (window, &style->bg[state_type]);
1547 }
1548
1549 GdkPixbuf *
1550 gtk_style_render_icon (GtkStyle            *style,
1551                        const GtkIconSource *source,
1552                        GtkTextDirection     direction,
1553                        GtkStateType         state,
1554                        GtkIconSize          size,
1555                        GtkWidget           *widget,
1556                        const gchar         *detail)
1557 {
1558   GdkPixbuf *pixbuf;
1559   
1560   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1561   g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
1562   
1563   pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
1564                                                      size, widget, detail);
1565
1566   g_return_val_if_fail (pixbuf != NULL, NULL);
1567
1568   return pixbuf;
1569 }
1570
1571 /* Default functions */
1572 void
1573 gtk_style_apply_default_background (GtkStyle     *style,
1574                                     GdkWindow    *window,
1575                                     gboolean      set_bg,
1576                                     GtkStateType  state_type, 
1577                                     GdkRectangle *area, 
1578                                     gint          x, 
1579                                     gint          y, 
1580                                     gint          width, 
1581                                     gint          height)
1582 {
1583   GdkRectangle new_rect, old_rect;
1584   
1585   if (area)
1586     {
1587       old_rect.x = x;
1588       old_rect.y = y;
1589       old_rect.width = width;
1590       old_rect.height = height;
1591       
1592       if (!gdk_rectangle_intersect (area, &old_rect, &new_rect))
1593         return;
1594     }
1595   else
1596     {
1597       new_rect.x = x;
1598       new_rect.y = y;
1599       new_rect.width = width;
1600       new_rect.height = height;
1601     }
1602   
1603   if (!style->bg_pixmap[state_type] ||
1604       GDK_IS_PIXMAP (window) ||
1605       (!set_bg && style->bg_pixmap[state_type] != (GdkPixmap*) GDK_PARENT_RELATIVE))
1606     {
1607       GdkGC *gc = style->bg_gc[state_type];
1608       
1609       if (style->bg_pixmap[state_type])
1610         {
1611           gdk_gc_set_fill (gc, GDK_TILED);
1612           gdk_gc_set_tile (gc, style->bg_pixmap[state_type]);
1613         }
1614       
1615       gdk_draw_rectangle (window, gc, TRUE, 
1616                           new_rect.x, new_rect.y, new_rect.width, new_rect.height);
1617       if (style->bg_pixmap[state_type])
1618         gdk_gc_set_fill (gc, GDK_SOLID);
1619     }
1620   else
1621     {
1622       if (set_bg)
1623         {
1624           if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1625             gdk_window_set_back_pixmap (window, NULL, TRUE);
1626           else
1627             gdk_window_set_back_pixmap (window, style->bg_pixmap[state_type], FALSE);
1628         }
1629       
1630       gdk_window_clear_area (window, 
1631                              new_rect.x, new_rect.y, 
1632                              new_rect.width, new_rect.height);
1633     }
1634 }
1635
1636 static GdkPixbuf*
1637 scale_or_ref (GdkPixbuf *src,
1638               gint width,
1639               gint height)
1640 {
1641   if (width == gdk_pixbuf_get_width (src) &&
1642       height == gdk_pixbuf_get_height (src))
1643     {
1644       gdk_pixbuf_ref (src);
1645       return src;
1646     }
1647   else
1648     {
1649       return gdk_pixbuf_scale_simple (src,
1650                                       width, height,
1651                                       GDK_INTERP_BILINEAR);
1652     }
1653 }
1654
1655 static GdkPixbuf *
1656 gtk_default_render_icon (GtkStyle            *style,
1657                          const GtkIconSource *source,
1658                          GtkTextDirection     direction,
1659                          GtkStateType         state,
1660                          GtkIconSize          size,
1661                          GtkWidget           *widget,
1662                          const gchar         *detail)
1663 {
1664   gint width = 1;
1665   gint height = 1;
1666   GdkPixbuf *scaled;
1667   GdkPixbuf *stated;
1668   GdkPixbuf *base_pixbuf;
1669
1670   /* Oddly, style can be NULL in this function, because
1671    * GtkIconSet can be used without a style and if so
1672    * it uses this function.
1673    */
1674
1675   base_pixbuf = gtk_icon_source_get_pixbuf (source);
1676
1677   g_return_val_if_fail (base_pixbuf != NULL, NULL);
1678   
1679   if (!gtk_icon_size_lookup (size, &width, &height))
1680     {
1681       g_warning (G_STRLOC ": invalid icon size `%d'", size);
1682       return NULL;
1683     }
1684
1685   /* If the size was wildcarded, then scale; otherwise, leave it
1686    * alone.
1687    */
1688   if (gtk_icon_source_get_size_wildcarded (source))
1689     scaled = scale_or_ref (base_pixbuf, width, height);
1690   else
1691     scaled = GDK_PIXBUF (g_object_ref (G_OBJECT (base_pixbuf)));
1692
1693   /* If the state was wildcarded, then generate a state. */
1694   if (gtk_icon_source_get_state_wildcarded (source))
1695     {
1696       if (state == GTK_STATE_INSENSITIVE)
1697         {
1698           stated = gdk_pixbuf_copy (scaled);      
1699           
1700           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1701                                             0.8, TRUE);
1702           
1703           gdk_pixbuf_unref (scaled);
1704         }
1705       else if (state == GTK_STATE_PRELIGHT)
1706         {
1707           stated = gdk_pixbuf_copy (scaled);      
1708           
1709           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1710                                             1.2, FALSE);
1711           
1712           gdk_pixbuf_unref (scaled);
1713         }
1714       else
1715         {
1716           stated = scaled;
1717         }
1718     }
1719   else
1720     stated = scaled;
1721   
1722   return stated;
1723 }
1724
1725 static gboolean
1726 sanitize_size (GdkWindow *window,
1727                gint      *width,
1728                gint      *height)
1729 {
1730   gboolean set_bg = FALSE;
1731
1732   if ((*width == -1) && (*height == -1))
1733     {
1734       set_bg = GDK_IS_WINDOW (window);
1735       gdk_window_get_size (window, width, height);
1736     }
1737   else if (*width == -1)
1738     gdk_window_get_size (window, width, NULL);
1739   else if (*height == -1)
1740     gdk_window_get_size (window, NULL, height);
1741
1742   return set_bg;
1743 }
1744
1745 static void
1746 draw_part (GdkDrawable  *drawable,
1747            GdkGC        *gc,
1748            GdkRectangle *area,
1749            gint          x,
1750            gint          y,
1751            IndicatorPart part)
1752 {
1753   if (area)
1754     gdk_gc_set_clip_rectangle (gc, area);
1755   
1756   if (!indicator_parts[part].bmap)
1757     indicator_parts[part].bmap = gdk_bitmap_create_from_data (drawable,
1758                                                               indicator_parts[part].bits,
1759                                                               INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
1760
1761   gdk_gc_set_ts_origin (gc, x, y);
1762   gdk_gc_set_stipple (gc, indicator_parts[part].bmap);
1763   gdk_gc_set_fill (gc, GDK_STIPPLED);
1764
1765   gdk_draw_rectangle (drawable, gc, TRUE, x, y, INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
1766
1767   gdk_gc_set_fill (gc, GDK_SOLID);
1768
1769   if (area)
1770     gdk_gc_set_clip_rectangle (gc, NULL);
1771 }
1772
1773 static void
1774 gtk_default_draw_hline (GtkStyle     *style,
1775                         GdkWindow    *window,
1776                         GtkStateType  state_type,
1777                         GdkRectangle  *area,
1778                         GtkWidget     *widget,
1779                         const gchar   *detail,
1780                         gint          x1,
1781                         gint          x2,
1782                         gint          y)
1783 {
1784   gint thickness_light;
1785   gint thickness_dark;
1786   gint i;
1787   
1788   g_return_if_fail (GTK_IS_STYLE (style));
1789   g_return_if_fail (window != NULL);
1790   
1791   thickness_light = style->ythickness / 2;
1792   thickness_dark = style->ythickness - thickness_light;
1793   
1794   if (area)
1795     {
1796       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
1797       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
1798     }
1799   
1800   if (detail && !strcmp (detail, "label"))
1801     {
1802       if (state_type == GTK_STATE_INSENSITIVE)
1803         gdk_draw_line (window, style->white_gc, x1 + 1, y + 1, x2 + 1, y + 1);   
1804       gdk_draw_line (window, style->fg_gc[state_type], x1, y, x2, y);     
1805     }
1806   else
1807     {
1808       for (i = 0; i < thickness_dark; i++)
1809         {
1810           gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i);
1811           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i);
1812         }
1813       
1814       y += thickness_dark;
1815       for (i = 0; i < thickness_light; i++)
1816         {
1817           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
1818           gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i);
1819         }
1820     }
1821   
1822   if (area)
1823     {
1824       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
1825       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
1826     }
1827 }
1828
1829
1830 static void
1831 gtk_default_draw_vline (GtkStyle     *style,
1832                         GdkWindow    *window,
1833                         GtkStateType  state_type,
1834                         GdkRectangle  *area,
1835                         GtkWidget     *widget,
1836                         const gchar   *detail,
1837                         gint          y1,
1838                         gint          y2,
1839                         gint          x)
1840 {
1841   gint thickness_light;
1842   gint thickness_dark;
1843   gint i;
1844   
1845   g_return_if_fail (GTK_IS_STYLE (style));
1846   g_return_if_fail (window != NULL);
1847   
1848   thickness_light = style->xthickness / 2;
1849   thickness_dark = style->xthickness - thickness_light;
1850   
1851   if (area)
1852     {
1853       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
1854       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
1855     }
1856   for (i = 0; i < thickness_dark; i++)
1857     {
1858       gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2);
1859       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1);
1860     }
1861   
1862   x += thickness_dark;
1863   for (i = 0; i < thickness_light; i++)
1864     {
1865       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i);
1866       gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2);
1867     }
1868   if (area)
1869     {
1870       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
1871       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
1872     }
1873 }
1874
1875
1876 void
1877 draw_thin_shadow (GtkStyle      *style,
1878                   GdkWindow     *window,
1879                   GtkStateType   state,
1880                   GdkRectangle  *area,
1881                   gint           x,
1882                   gint           y,
1883                   gint           width,
1884                   gint           height)
1885 {
1886   GdkGC *gc1, *gc2;
1887
1888   sanitize_size (window, &width, &height);
1889   
1890   gc1 = style->light_gc[state];
1891   gc2 = style->dark_gc[state];
1892   
1893   if (area)
1894     {
1895       gdk_gc_set_clip_rectangle (gc1, area);
1896       gdk_gc_set_clip_rectangle (gc2, area);
1897     }
1898   
1899   gdk_draw_line (window, gc1,
1900                  x, y + height - 1, x + width - 1, y + height - 1);
1901   gdk_draw_line (window, gc1,
1902                  x + width - 1, y,  x + width - 1, y + height - 1);
1903       
1904   gdk_draw_line (window, gc2,
1905                  x, y, x + width - 1, y);
1906   gdk_draw_line (window, gc2,
1907                  x, y, x, y + height - 1);
1908
1909   if (area)
1910     {
1911       gdk_gc_set_clip_rectangle (gc1, NULL);
1912       gdk_gc_set_clip_rectangle (gc2, NULL);
1913     }
1914 }
1915
1916 void
1917 draw_spin_entry_shadow (GtkStyle      *style,
1918                         GdkWindow     *window,
1919                         GtkStateType   state,
1920                         GdkRectangle  *area,
1921                         gint           x,
1922                         gint           y,
1923                         gint           width,
1924                         gint           height)
1925 {
1926   gint window_width, window_height;
1927   gboolean focus_inset;
1928
1929   gdk_window_get_size (window, &window_width, &window_height);
1930
1931   if (width == -1)
1932     width = window_width;
1933   if (height == 1)
1934     height = window_height;
1935
1936   focus_inset = (width < window_width && height < window_height);
1937   
1938   if (area)
1939     {
1940       gdk_gc_set_clip_rectangle (style->light_gc[state], area);
1941       gdk_gc_set_clip_rectangle (style->dark_gc[state], area);
1942       gdk_gc_set_clip_rectangle (style->black_gc, area);
1943       gdk_gc_set_clip_rectangle (style->bg_gc[state], area);
1944       gdk_gc_set_clip_rectangle (style->base_gc[state], area);
1945     }
1946
1947   gdk_draw_line (window, style->light_gc[state],
1948                  x, y + height - 1, x + width - 1, y + height - 1);
1949
1950   gdk_draw_line (window, 
1951                  style->base_gc[state],
1952                  x + width - 1,  y + 1, x + width - 1,  y + height - 3);
1953       
1954   if (!focus_inset)
1955     {
1956       gdk_draw_line (window, style->bg_gc[state],
1957                      x + 1, y + height - 2, x + width - 1, y + height - 2);
1958       gdk_draw_line (window, 
1959                      style->base_gc[state],
1960                      x + width - 2, y + 1, x + width - 2, y + height - 3);
1961   
1962       gdk_draw_line (window, style->black_gc,
1963                      x + 1, y + 1, x + width - 1, y + 1);
1964       gdk_draw_line (window, style->black_gc,
1965                      x + 1, y + 1, x + 1, y + height - 2);
1966     }
1967       
1968   gdk_draw_line (window, style->dark_gc[state],
1969                  x, y, x + width - 1, y);
1970   gdk_draw_line (window, style->dark_gc[state],
1971                  x, y, x, y + height - 1);
1972
1973   if (area)
1974     {
1975       gdk_gc_set_clip_rectangle (style->light_gc[state], NULL);
1976       gdk_gc_set_clip_rectangle (style->dark_gc[state], NULL);
1977       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
1978       gdk_gc_set_clip_rectangle (style->bg_gc[state], NULL);
1979       gdk_gc_set_clip_rectangle (style->base_gc[state], NULL);
1980     }
1981 }
1982
1983 static void
1984 draw_spinbutton_shadow (GtkStyle      *style,
1985                         GdkWindow     *window,
1986                         GtkStateType   state,
1987                         GdkRectangle  *area,
1988                         gint           x,
1989                         gint           y,
1990                         gint           width,
1991                         gint           height)
1992 {
1993   gint y_middle = y + height / 2;
1994
1995   sanitize_size (window, &width, &height);
1996   
1997   if (area)
1998     {
1999       gdk_gc_set_clip_rectangle (style->black_gc, area);
2000       gdk_gc_set_clip_rectangle (style->bg_gc[state], area);
2001       gdk_gc_set_clip_rectangle (style->dark_gc[state], area);
2002       gdk_gc_set_clip_rectangle (style->light_gc[state], area);
2003     }
2004   
2005   gdk_draw_line (window, style->black_gc,
2006                  x, y + 2, x, y + height - 3);
2007   gdk_draw_line (window, style->black_gc,
2008                  x, y + 1, x + width - 2, y + 1);
2009   gdk_draw_line (window, style->black_gc,
2010                  x + width - 2, y + 2, x + width - 2, y + height - 3);
2011   
2012   gdk_draw_line (window, style->bg_gc[state],
2013                  x, y + height - 2, x + width - 2, y + height - 2);
2014
2015   gdk_draw_line (window, style->dark_gc[state],
2016                  x, y, x + width - 1, y);
2017   gdk_draw_line (window, style->dark_gc[state],
2018                  x + 1, y_middle - 1, x + width - 3, y_middle - 1);
2019   gdk_draw_line (window, style->dark_gc[state],
2020                  x + 1, y + height - 3, x + width - 3, y + height - 3);
2021
2022   gdk_draw_line (window, style->light_gc[state],
2023                  x + 1, y + 2, x + width - 3, y + 2);
2024   gdk_draw_line (window, style->light_gc[state],
2025                  x + 1, y_middle, x + width - 3, y_middle);
2026   gdk_draw_line (window, style->light_gc[state],
2027                  x + width - 1, y + 1, x + width - 1, y + height - 1);
2028   gdk_draw_line (window, style->light_gc[state],
2029                  x, y + height - 1, x + width - 2, y + height - 1);
2030       
2031   if (area)
2032     {
2033       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2034       gdk_gc_set_clip_rectangle (style->bg_gc[state], NULL);
2035       gdk_gc_set_clip_rectangle (style->dark_gc[state], NULL);
2036       gdk_gc_set_clip_rectangle (style->light_gc[state], NULL);
2037     }
2038 }
2039
2040 static void
2041 gtk_default_draw_shadow (GtkStyle      *style,
2042                          GdkWindow     *window,
2043                          GtkStateType   state_type,
2044                          GtkShadowType  shadow_type,
2045                          GdkRectangle  *area,
2046                          GtkWidget     *widget,
2047                          const gchar   *detail,
2048                          gint           x,
2049                          gint           y,
2050                          gint           width,
2051                          gint           height)
2052 {
2053   GdkGC *gc1 = NULL;
2054   GdkGC *gc2 = NULL;
2055   gint thickness_light;
2056   gint thickness_dark;
2057   gint i;
2058   
2059   g_return_if_fail (GTK_IS_STYLE (style));
2060   g_return_if_fail (window != NULL);
2061
2062   if (shadow_type == GTK_SHADOW_IN)
2063     {
2064       if (detail && (strcmp (detail, "buttondefault") == 0))
2065         {
2066           sanitize_size (window, &width, &height);
2067
2068           gdk_draw_rectangle (window, style->black_gc, FALSE,
2069                               x, y, width - 1, height - 1);
2070           
2071           return;
2072         }
2073       if (detail && strcmp (detail, "trough") == 0)
2074         {
2075           draw_thin_shadow (style, window, state_type, area,
2076                             x, y, width, height);
2077           return;
2078         }
2079       else if (widget && GTK_IS_SPIN_BUTTON (widget) &&
2080                detail && strcmp (detail, "entry") == 0)
2081         {
2082           draw_spin_entry_shadow (style, window, state_type, area,
2083                                   x, y, width, height);
2084           return;
2085         }
2086       else if (widget && GTK_IS_SPIN_BUTTON (widget) &&
2087                detail && strcmp (detail, "spinbutton") == 0)
2088         {
2089           draw_spinbutton_shadow (style, window, state_type,
2090                                   area, x, y, width, height);
2091           return;
2092         }
2093     }
2094   
2095   sanitize_size (window, &width, &height);
2096   
2097   switch (shadow_type)
2098     {
2099     case GTK_SHADOW_NONE:
2100       return;
2101     case GTK_SHADOW_IN:
2102     case GTK_SHADOW_ETCHED_IN:
2103       gc1 = style->light_gc[state_type];
2104       gc2 = style->dark_gc[state_type];
2105       break;
2106     case GTK_SHADOW_OUT:
2107     case GTK_SHADOW_ETCHED_OUT:
2108       gc1 = style->dark_gc[state_type];
2109       gc2 = style->light_gc[state_type];
2110       break;
2111     }
2112   
2113   if (area)
2114     {
2115       gdk_gc_set_clip_rectangle (gc1, area);
2116       gdk_gc_set_clip_rectangle (gc2, area);
2117       if (shadow_type == GTK_SHADOW_IN || 
2118           shadow_type == GTK_SHADOW_OUT)
2119         {
2120           gdk_gc_set_clip_rectangle (style->black_gc, area);
2121           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2122         }
2123     }
2124   
2125   switch (shadow_type)
2126     {
2127     case GTK_SHADOW_NONE:
2128       break;
2129       
2130     case GTK_SHADOW_IN:
2131       /* Light around right and bottom edge */
2132
2133       if (style->ythickness > 0)
2134         gdk_draw_line (window, gc1,
2135                        x, y + height - 1, x + width - 1, y + height - 1);
2136       if (style->xthickness > 0)
2137         gdk_draw_line (window, gc1,
2138                        x + width - 1, y, x + width - 1, y + height - 1);
2139
2140       if (style->ythickness > 1)
2141         gdk_draw_line (window, style->bg_gc[state_type],
2142                        x + 1, y + height - 2, x + width - 2, y + height - 2);
2143       if (style->xthickness > 1)
2144         gdk_draw_line (window, style->bg_gc[state_type],
2145                        x + width - 2, y + 1, x + width - 2, y + height - 2);
2146
2147       /* Dark around left and top */
2148
2149       if (style->ythickness > 1)
2150         gdk_draw_line (window, style->black_gc,
2151                        x + 1, y + 1, x + width - 2, y + 1);
2152       if (style->xthickness > 1)
2153         gdk_draw_line (window, style->black_gc,
2154                        x + 1, y + 1, x + 1, y + height - 2);
2155
2156       if (style->ythickness > 0)
2157         gdk_draw_line (window, gc2,
2158                        x, y, x + width - 1, y);
2159       if (style->xthickness > 0)
2160         gdk_draw_line (window, gc2,
2161                        x, y, x, y + height - 1);
2162       break;
2163       
2164     case GTK_SHADOW_OUT:
2165       /* Dark around right and bottom edge */
2166
2167       if (style->ythickness > 0)
2168         {
2169           if (style->ythickness > 1)
2170             {
2171               gdk_draw_line (window, gc1,
2172                              x + 1, y + height - 2, x + width - 2, y + height - 2);
2173               gdk_draw_line (window, style->black_gc,
2174                              x, y + height - 1, x + width - 1, y + height - 1);
2175             }
2176           else
2177             {
2178               gdk_draw_line (window, gc1,
2179                              x + 1, y + height - 1, x + width - 1, y + height - 1);
2180             }
2181         }
2182
2183       if (style->xthickness > 0)
2184         {
2185           if (style->xthickness > 1)
2186             {
2187               gdk_draw_line (window, gc1,
2188                              x + width - 2, y + 1, x + width - 2, y + height - 2);
2189               
2190               gdk_draw_line (window, style->black_gc,
2191                              x + width - 1, y, x + width - 1, y + height - 1);
2192             }
2193           else
2194             {
2195               gdk_draw_line (window, gc1,
2196                              x + width - 1, y + 1, x + width - 1, y + height - 1);
2197             }
2198         }
2199       
2200       /* Light around top and left */
2201
2202       if (style->ythickness > 0)
2203         gdk_draw_line (window, gc2,
2204                        x, y, x + width - 1, y);
2205       if (style->xthickness > 0)
2206         gdk_draw_line (window, gc2,
2207                        x, y, x, y + height - 1);
2208
2209       if (style->ythickness > 1)
2210         gdk_draw_line (window, style->bg_gc[state_type],
2211                        x + 1, y + 1, x + width - 2, y + 1);
2212       if (style->xthickness > 1)
2213         gdk_draw_line (window, style->bg_gc[state_type],
2214                        x + 1, y + 1, x + 1, y + height - 2);
2215       break;
2216       
2217     case GTK_SHADOW_ETCHED_IN:
2218     case GTK_SHADOW_ETCHED_OUT:
2219       if (style->xthickness > 0)
2220         {
2221           if (style->xthickness > 1)
2222             {
2223               thickness_light = 1;
2224               thickness_dark = 1;
2225       
2226               for (i = 0; i < thickness_dark; i++)
2227                 {
2228                   gdk_draw_line (window, gc1,
2229                                  x + width - i - 1,
2230                                  y + i,
2231                                  x + width - i - 1,
2232                                  y + height - i - 1);
2233                   gdk_draw_line (window, gc2,
2234                                  x + i,
2235                                  y + i,
2236                                  x + i,
2237                                  y + height - i - 2);
2238                 }
2239       
2240               for (i = 0; i < thickness_light; i++)
2241                 {
2242                   gdk_draw_line (window, gc1,
2243                                  x + thickness_dark + i,
2244                                  y + thickness_dark + i,
2245                                  x + thickness_dark + i,
2246                                  y + height - thickness_dark - i - 1);
2247                   gdk_draw_line (window, gc2,
2248                                  x + width - thickness_light - i - 1,
2249                                  y + thickness_dark + i,
2250                                  x + width - thickness_light - i - 1,
2251                                  y + height - thickness_light - 1);
2252                 }
2253             }
2254           else
2255             {
2256               gdk_draw_line (window, 
2257                              style->dark_gc[state_type],
2258                              x, y, x, y + height);                         
2259               gdk_draw_line (window, 
2260                              style->dark_gc[state_type],
2261                              x + width, y, x + width, y + height);
2262             }
2263         }
2264
2265       if (style->ythickness > 0)
2266         {
2267           if (style->ythickness > 1)
2268             {
2269               thickness_light = 1;
2270               thickness_dark = 1;
2271       
2272               for (i = 0; i < thickness_dark; i++)
2273                 {
2274                   gdk_draw_line (window, gc1,
2275                                  x + i,
2276                                  y + height - i - 1,
2277                                  x + width - i - 1,
2278                                  y + height - i - 1);
2279           
2280                   gdk_draw_line (window, gc2,
2281                                  x + i,
2282                                  y + i,
2283                                  x + width - i - 2,
2284                                  y + i);
2285                 }
2286       
2287               for (i = 0; i < thickness_light; i++)
2288                 {
2289                   gdk_draw_line (window, gc1,
2290                                  x + thickness_dark + i,
2291                                  y + thickness_dark + i,
2292                                  x + width - thickness_dark - i - 1,
2293                                  y + thickness_dark + i);
2294           
2295                   gdk_draw_line (window, gc2,
2296                                  x + thickness_dark + i,
2297                                  y + height - thickness_light - i - 1,
2298                                  x + width - thickness_light - 1,
2299                                  y + height - thickness_light - i - 1);
2300                 }
2301             }
2302           else
2303             {
2304               gdk_draw_line (window, 
2305                              style->dark_gc[state_type],
2306                              x, y, x + width, y);
2307               gdk_draw_line (window, 
2308                              style->dark_gc[state_type],
2309                              x, y + height, x + width, y + height);
2310             }
2311         }
2312       
2313       break;
2314     }
2315   if (area)
2316     {
2317       gdk_gc_set_clip_rectangle (gc1, NULL);
2318       gdk_gc_set_clip_rectangle (gc2, NULL);
2319       if (shadow_type == GTK_SHADOW_IN || 
2320           shadow_type == GTK_SHADOW_OUT)
2321         {
2322           gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2323           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2324         }
2325     }
2326 }
2327
2328 static void
2329 gtk_default_draw_polygon (GtkStyle      *style,
2330                           GdkWindow     *window,
2331                           GtkStateType   state_type,
2332                           GtkShadowType  shadow_type,
2333                           GdkRectangle  *area,
2334                           GtkWidget     *widget,
2335                           const gchar   *detail,
2336                           GdkPoint      *points,
2337                           gint           npoints,
2338                           gboolean       fill)
2339 {
2340   static const gdouble pi_over_4 = G_PI_4;
2341   static const gdouble pi_3_over_4 = G_PI_4 * 3;
2342   GdkGC *gc1;
2343   GdkGC *gc2;
2344   GdkGC *gc3;
2345   GdkGC *gc4;
2346   gdouble angle;
2347   gint xadjust;
2348   gint yadjust;
2349   gint i;
2350   
2351   g_return_if_fail (GTK_IS_STYLE (style));
2352   g_return_if_fail (window != NULL);
2353   g_return_if_fail (points != NULL);
2354   
2355   switch (shadow_type)
2356     {
2357     case GTK_SHADOW_IN:
2358       gc1 = style->bg_gc[state_type];
2359       gc2 = style->dark_gc[state_type];
2360       gc3 = style->light_gc[state_type];
2361       gc4 = style->black_gc;
2362       break;
2363     case GTK_SHADOW_ETCHED_IN:
2364       gc1 = style->light_gc[state_type];
2365       gc2 = style->dark_gc[state_type];
2366       gc3 = style->dark_gc[state_type];
2367       gc4 = style->light_gc[state_type];
2368       break;
2369     case GTK_SHADOW_OUT:
2370       gc1 = style->dark_gc[state_type];
2371       gc2 = style->light_gc[state_type];
2372       gc3 = style->black_gc;
2373       gc4 = style->bg_gc[state_type];
2374       break;
2375     case GTK_SHADOW_ETCHED_OUT:
2376       gc1 = style->dark_gc[state_type];
2377       gc2 = style->light_gc[state_type];
2378       gc3 = style->light_gc[state_type];
2379       gc4 = style->dark_gc[state_type];
2380       break;
2381     default:
2382       return;
2383     }
2384   
2385   if (area)
2386     {
2387       gdk_gc_set_clip_rectangle (gc1, area);
2388       gdk_gc_set_clip_rectangle (gc2, area);
2389       gdk_gc_set_clip_rectangle (gc3, area);
2390       gdk_gc_set_clip_rectangle (gc4, area);
2391     }
2392   
2393   if (fill)
2394     gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints);
2395   
2396   npoints--;
2397   
2398   for (i = 0; i < npoints; i++)
2399     {
2400       if ((points[i].x == points[i+1].x) &&
2401           (points[i].y == points[i+1].y))
2402         {
2403           angle = 0;
2404         }
2405       else
2406         {
2407           angle = atan2 (points[i+1].y - points[i].y,
2408                          points[i+1].x - points[i].x);
2409         }
2410       
2411       if ((angle > -pi_3_over_4) && (angle < pi_over_4))
2412         {
2413           if (angle > -pi_over_4)
2414             {
2415               xadjust = 0;
2416               yadjust = 1;
2417             }
2418           else
2419             {
2420               xadjust = 1;
2421               yadjust = 0;
2422             }
2423           
2424           gdk_draw_line (window, gc1,
2425                          points[i].x-xadjust, points[i].y-yadjust,
2426                          points[i+1].x-xadjust, points[i+1].y-yadjust);
2427           gdk_draw_line (window, gc3,
2428                          points[i].x, points[i].y,
2429                          points[i+1].x, points[i+1].y);
2430         }
2431       else
2432         {
2433           if ((angle < -pi_3_over_4) || (angle > pi_3_over_4))
2434             {
2435               xadjust = 0;
2436               yadjust = 1;
2437             }
2438           else
2439             {
2440               xadjust = 1;
2441               yadjust = 0;
2442             }
2443           
2444           gdk_draw_line (window, gc4,
2445                          points[i].x+xadjust, points[i].y+yadjust,
2446                          points[i+1].x+xadjust, points[i+1].y+yadjust);
2447           gdk_draw_line (window, gc2,
2448                          points[i].x, points[i].y,
2449                          points[i+1].x, points[i+1].y);
2450         }
2451     }
2452
2453   if (area)
2454     {
2455       gdk_gc_set_clip_rectangle (gc1, NULL);
2456       gdk_gc_set_clip_rectangle (gc2, NULL);
2457       gdk_gc_set_clip_rectangle (gc3, NULL);
2458       gdk_gc_set_clip_rectangle (gc4, NULL);
2459     }
2460 }
2461
2462 static void
2463 draw_varrow (GdkWindow     *window,
2464              GdkGC         *gc,
2465              GtkShadowType  shadow_type,
2466              GdkRectangle  *area,
2467              GtkArrowType   arrow_type,
2468              gint           x,
2469              gint           y,
2470              gint           width,
2471              gint           height)
2472 {
2473   gint steps, extra;
2474   gint y_start, y_increment;
2475   gint i;
2476
2477   if (area)
2478     gdk_gc_set_clip_rectangle (gc, area);
2479   
2480   width = width + width % 2 - 1;        /* Force odd */
2481   
2482   steps = 1 + width / 2;
2483
2484   extra = height - steps;
2485
2486   if (arrow_type == GTK_ARROW_DOWN)
2487     {
2488       y_start = y;
2489       y_increment = 1;
2490     }
2491   else
2492     {
2493       y_start = y + height - 1;
2494       y_increment = -1;
2495     }
2496
2497   for (i = 0; i < extra; i++)
2498     {
2499       gdk_draw_line (window, gc,
2500                      x,              y_start + i * y_increment,
2501                      x + width - 1,  y_start + i * y_increment);
2502     }
2503   for (; i < height; i++)
2504     {
2505       gdk_draw_line (window, gc,
2506                      x + (i - extra),              y_start + i * y_increment,
2507                      x + width - (i - extra) - 1,  y_start + i * y_increment);
2508     }
2509   
2510
2511   if (area)
2512     gdk_gc_set_clip_rectangle (gc, NULL);
2513 }
2514
2515 static void
2516 draw_harrow (GdkWindow     *window,
2517              GdkGC         *gc,
2518              GtkShadowType  shadow_type,
2519              GdkRectangle  *area,
2520              GtkArrowType   arrow_type,
2521              gint           x,
2522              gint           y,
2523              gint           width,
2524              gint           height)
2525 {
2526   gint steps, extra;
2527   gint x_start, x_increment;
2528   gint i;
2529
2530   if (area)
2531     gdk_gc_set_clip_rectangle (gc, area);
2532   
2533   height = height + height % 2 - 1;     /* Force odd */
2534   
2535   steps = 1 + height / 2;
2536
2537   extra = width - steps;
2538
2539   if (arrow_type == GTK_ARROW_RIGHT)
2540     {
2541       x_start = x;
2542       x_increment = 1;
2543     }
2544   else
2545     {
2546       x_start = x + width - 1;
2547       x_increment = -1;
2548     }
2549
2550   for (i = 0; i < extra; i++)
2551     {
2552       gdk_draw_line (window, gc,
2553                      x_start + i * x_increment, y,
2554                      x_start + i * x_increment, y + height - 1);
2555     }
2556   for (; i < width; i++)
2557     {
2558       gdk_draw_line (window, gc,
2559                      x_start + i * x_increment, y + (i - extra),
2560                      x_start + i * x_increment, y + height - (i - extra) - 1);
2561     }
2562   
2563
2564   if (area)
2565     gdk_gc_set_clip_rectangle (gc, NULL);
2566 }
2567
2568 static void
2569 gtk_default_draw_arrow (GtkStyle      *style,
2570                         GdkWindow     *window,
2571                         GtkStateType   state,
2572                         GtkShadowType  shadow,
2573                         GdkRectangle  *area,
2574                         GtkWidget     *widget,
2575                         const gchar   *detail,
2576                         GtkArrowType   arrow_type,
2577                         gboolean       fill,
2578                         gint           x,
2579                         gint           y,
2580                         gint           width,
2581                         gint           height)
2582 {
2583   sanitize_size (window, &width, &height);
2584   
2585   if (detail && strcmp (detail, "spinbutton") == 0)
2586     {
2587       x += (width - 7) / 2;
2588
2589       if (arrow_type == GTK_ARROW_UP)
2590         y += (height - 4) / 2;
2591       else
2592         y += (1 + height - 4) / 2;
2593
2594       draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
2595                    x, y, 7, 4);
2596     }
2597   else if (detail && strcmp (detail, "vscrollbar") == 0)
2598     {
2599       gtk_paint_box (style, window, state, shadow, area,
2600                      widget, detail, x, y, width, height);
2601       
2602       x += (width - 7) / 2;
2603       y += (height - 5) / 2;
2604
2605       draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
2606                    x, y, 7, 5);
2607       
2608     }
2609   else if (detail && strcmp (detail, "hscrollbar") == 0)
2610     {
2611       gtk_paint_box (style, window, state, shadow, area,
2612                      widget, detail, x, y, width, height);
2613       
2614       y += (height - 7) / 2;
2615       x += (width - 5) / 2;
2616
2617       draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
2618                    x, y, 5, 7);
2619     }
2620   else
2621     {
2622       if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
2623         {
2624           x += (width - 7) / 2;
2625           y += (height - 5) / 2;
2626           
2627           draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
2628                        x, y, 7, 5);
2629         }
2630       else
2631         {
2632           x += (width - 5) / 2;
2633           y += (height - 7) / 2;
2634           
2635           draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
2636                        x, y, 5, 7);
2637         }
2638     }
2639 }
2640
2641 static void
2642 gtk_default_draw_diamond (GtkStyle      *style,
2643                           GdkWindow     *window,
2644                           GtkStateType   state_type,
2645                           GtkShadowType  shadow_type,
2646                           GdkRectangle  *area,
2647                           GtkWidget     *widget,
2648                           const gchar   *detail,
2649                           gint           x,
2650                           gint           y,
2651                           gint           width,
2652                           gint           height)
2653 {
2654   gint half_width;
2655   gint half_height;
2656   GdkGC *outer_nw = NULL;
2657   GdkGC *outer_ne = NULL;
2658   GdkGC *outer_sw = NULL;
2659   GdkGC *outer_se = NULL;
2660   GdkGC *middle_nw = NULL;
2661   GdkGC *middle_ne = NULL;
2662   GdkGC *middle_sw = NULL;
2663   GdkGC *middle_se = NULL;
2664   GdkGC *inner_nw = NULL;
2665   GdkGC *inner_ne = NULL;
2666   GdkGC *inner_sw = NULL;
2667   GdkGC *inner_se = NULL;
2668   
2669   g_return_if_fail (GTK_IS_STYLE (style));
2670   g_return_if_fail (window != NULL);
2671   
2672   sanitize_size (window, &width, &height);
2673   
2674   half_width = width / 2;
2675   half_height = height / 2;
2676   
2677   if (area)
2678     {
2679       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2680       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2681       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2682       gdk_gc_set_clip_rectangle (style->black_gc, area);
2683     }
2684   
2685   switch (shadow_type)
2686     {
2687     case GTK_SHADOW_IN:
2688       inner_sw = inner_se = style->bg_gc[state_type];
2689       middle_sw = middle_se = style->light_gc[state_type];
2690       outer_sw = outer_se = style->light_gc[state_type];
2691       inner_nw = inner_ne = style->black_gc;
2692       middle_nw = middle_ne = style->dark_gc[state_type];
2693       outer_nw = outer_ne = style->dark_gc[state_type];
2694       break;
2695           
2696     case GTK_SHADOW_OUT:
2697       inner_sw = inner_se = style->dark_gc[state_type];
2698       middle_sw = middle_se = style->dark_gc[state_type];
2699       outer_sw = outer_se = style->black_gc;
2700       inner_nw = inner_ne = style->bg_gc[state_type];
2701       middle_nw = middle_ne = style->light_gc[state_type];
2702       outer_nw = outer_ne = style->light_gc[state_type];
2703       break;
2704
2705     case GTK_SHADOW_ETCHED_IN:
2706       inner_sw = inner_se = style->bg_gc[state_type];
2707       middle_sw = middle_se = style->dark_gc[state_type];
2708       outer_sw = outer_se = style->light_gc[state_type];
2709       inner_nw = inner_ne = style->bg_gc[state_type];
2710       middle_nw = middle_ne = style->light_gc[state_type];
2711       outer_nw = outer_ne = style->dark_gc[state_type];
2712       break;
2713
2714     case GTK_SHADOW_ETCHED_OUT:
2715       inner_sw = inner_se = style->bg_gc[state_type];
2716       middle_sw = middle_se = style->light_gc[state_type];
2717       outer_sw = outer_se = style->dark_gc[state_type];
2718       inner_nw = inner_ne = style->bg_gc[state_type];
2719       middle_nw = middle_ne = style->dark_gc[state_type];
2720       outer_nw = outer_ne = style->light_gc[state_type];
2721       break;
2722       
2723     default:
2724
2725       break;
2726     }
2727
2728   if (inner_sw)
2729     {
2730       gdk_draw_line (window, inner_sw,
2731                      x + 2, y + half_height,
2732                      x + half_width, y + height - 2);
2733       gdk_draw_line (window, inner_se,
2734                      x + half_width, y + height - 2,
2735                      x + width - 2, y + half_height);
2736       gdk_draw_line (window, middle_sw,
2737                      x + 1, y + half_height,
2738                      x + half_width, y + height - 1);
2739       gdk_draw_line (window, middle_se,
2740                      x + half_width, y + height - 1,
2741                      x + width - 1, y + half_height);
2742       gdk_draw_line (window, outer_sw,
2743                      x, y + half_height,
2744                      x + half_width, y + height);
2745       gdk_draw_line (window, outer_se,
2746                      x + half_width, y + height,
2747                      x + width, y + half_height);
2748   
2749       gdk_draw_line (window, inner_nw,
2750                      x + 2, y + half_height,
2751                      x + half_width, y + 2);
2752       gdk_draw_line (window, inner_ne,
2753                      x + half_width, y + 2,
2754                      x + width - 2, y + half_height);
2755       gdk_draw_line (window, middle_nw,
2756                      x + 1, y + half_height,
2757                      x + half_width, y + 1);
2758       gdk_draw_line (window, middle_ne,
2759                      x + half_width, y + 1,
2760                      x + width - 1, y + half_height);
2761       gdk_draw_line (window, outer_nw,
2762                      x, y + half_height,
2763                      x + half_width, y);
2764       gdk_draw_line (window, outer_ne,
2765                      x + half_width, y,
2766                      x + width, y + half_height);
2767     }
2768   
2769   if (area)
2770     {
2771       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2772       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2773       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2774       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2775     }
2776 }
2777
2778 static void
2779 gtk_default_draw_string (GtkStyle      *style,
2780                          GdkWindow     *window,
2781                          GtkStateType   state_type,
2782                          GdkRectangle  *area,
2783                          GtkWidget     *widget,
2784                          const gchar   *detail,
2785                          gint           x,
2786                          gint           y,
2787                          const gchar   *string)
2788 {
2789   g_return_if_fail (GTK_IS_STYLE (style));
2790   g_return_if_fail (window != NULL);
2791   
2792   if (area)
2793     {
2794       gdk_gc_set_clip_rectangle (style->white_gc, area);
2795       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area);
2796     }
2797
2798   if (state_type == GTK_STATE_INSENSITIVE)
2799     gdk_draw_string (window, style->font, style->white_gc, x + 1, y + 1, string);
2800
2801   gdk_draw_string (window, style->font, style->fg_gc[state_type], x, y, string);
2802
2803   if (area)
2804     {
2805       gdk_gc_set_clip_rectangle (style->white_gc, NULL);
2806       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL);
2807     }
2808 }
2809
2810 static void
2811 option_menu_get_props (GtkWidget      *widget,
2812                        GtkRequisition *indicator_size,
2813                        GtkBorder      *indicator_spacing)
2814 {
2815   GtkRequisition *tmp_size = NULL;
2816   GtkBorder *tmp_spacing = NULL;
2817   
2818   if (widget)
2819     gtk_widget_style_get (widget, 
2820                           "indicator_size", &tmp_size,
2821                           "indicator_spacing", &tmp_spacing,
2822                           NULL);
2823
2824   if (tmp_size)
2825     {
2826       *indicator_size = *tmp_size;
2827       g_free (tmp_size);
2828     }
2829   else
2830     *indicator_size = default_option_indicator_size;
2831
2832   if (tmp_spacing)
2833     {
2834       *indicator_spacing = *tmp_spacing;
2835       g_free (tmp_spacing);
2836     }
2837   else
2838     *indicator_spacing = default_option_indicator_spacing;
2839 }
2840
2841 static void 
2842 gtk_default_draw_box (GtkStyle      *style,
2843                       GdkWindow     *window,
2844                       GtkStateType   state_type,
2845                       GtkShadowType  shadow_type,
2846                       GdkRectangle  *area,
2847                       GtkWidget     *widget,
2848                       const gchar   *detail,
2849                       gint           x,
2850                       gint           y,
2851                       gint           width,
2852                       gint           height)
2853 {
2854   g_return_if_fail (GTK_IS_STYLE (style));
2855   g_return_if_fail (window != NULL);
2856   
2857   sanitize_size (window, &width, &height);
2858   
2859   if (!style->bg_pixmap[state_type] || 
2860       GDK_IS_PIXMAP (window))
2861     {
2862       if (area)
2863         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2864
2865       gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE,
2866                           x, y, width, height);
2867       if (area)
2868         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2869     }
2870   else
2871     gtk_style_apply_default_background (style, window,
2872                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
2873                                         state_type, area, x, y, width, height);
2874   
2875   gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
2876                     x, y, width, height);
2877
2878   if (detail && strcmp (detail, "optionmenu") == 0)
2879     {
2880       GtkRequisition indicator_size;
2881       GtkBorder indicator_spacing;
2882
2883       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2884
2885       sanitize_size (window, &width, &height);
2886   
2887       gtk_paint_vline (style, window, state_type, area, widget,
2888                        detail,
2889                        y + style->ythickness + 1,
2890                        y + height - style->ythickness - 3,
2891                        x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness);
2892     }
2893 }
2894
2895 static GdkGC*
2896 get_darkened_gc (GdkWindow *window,
2897                  GdkColor  *color,
2898                  gint       darken_count)
2899 {
2900   GdkColor src = *color;
2901   GdkColor shaded;
2902   GdkGC *gc;
2903   
2904   gc = gdk_gc_new (window);
2905
2906   while (darken_count)
2907     {
2908       gtk_style_shade (&src, &shaded, 0.93);
2909       src = shaded;
2910       --darken_count;
2911     }
2912   
2913   gdk_gc_set_rgb_fg_color (gc, &shaded);
2914
2915   return gc;
2916 }
2917
2918 static void 
2919 gtk_default_draw_flat_box (GtkStyle      *style,
2920                            GdkWindow     *window,
2921                            GtkStateType   state_type,
2922                            GtkShadowType  shadow_type,
2923                            GdkRectangle  *area,
2924                            GtkWidget     *widget,
2925                            const gchar   *detail,
2926                            gint           x,
2927                            gint           y,
2928                            gint           width,
2929                            gint           height)
2930 {
2931   GdkGC *gc1;
2932   GdkGC *freeme = NULL;
2933   
2934   g_return_if_fail (GTK_IS_STYLE (style));
2935   g_return_if_fail (window != NULL);
2936   
2937   sanitize_size (window, &width, &height);
2938   
2939   if (detail)
2940     {
2941       if (state_type == GTK_STATE_SELECTED)
2942         {
2943           if (!strcmp ("text", detail))
2944             gc1 = style->bg_gc[GTK_STATE_SELECTED];
2945           else if (!strncmp ("cell_even", detail, strlen ("cell_even")) ||
2946                    !strncmp ("cell_odd", detail, strlen ("cell_odd")))
2947             {
2948               /* This has to be really broken; alex made me do it. -jrb */
2949               if (GTK_WIDGET_HAS_FOCUS (widget))
2950                 gc1 = style->base_gc[state_type];
2951               else 
2952                 gc1 = style->base_gc[GTK_STATE_ACTIVE];
2953             }
2954           else
2955             {
2956               gc1 = style->bg_gc[state_type];
2957             }
2958         }
2959       else
2960         {
2961           if (!strcmp ("viewportbin", detail))
2962             gc1 = style->bg_gc[GTK_STATE_NORMAL];
2963           else if (!strcmp ("entry_bg", detail))
2964             gc1 = style->base_gc[state_type];
2965
2966           /* For trees: even rows are base color, odd rows are a shade of
2967            * the base color, the sort column is a shade of the original color
2968            * for that row.
2969            */
2970
2971           /* FIXME when we have style properties, clean this up.
2972            */
2973           
2974           else if (!strcmp ("cell_even", detail) ||
2975                    !strcmp ("cell_odd", detail) ||
2976                    !strcmp ("cell_even_ruled", detail))
2977             {
2978               gc1 = style->base_gc[state_type];
2979             }
2980           else if (!strcmp ("cell_even_sorted", detail) ||
2981                    !strcmp ("cell_odd_sorted", detail) ||
2982                    !strcmp ("cell_odd_ruled", detail) ||
2983                    !strcmp ("cell_even_ruled_sorted", detail))
2984             {
2985               freeme = get_darkened_gc (window, &style->base[state_type], 1);
2986               gc1 = freeme;
2987             }
2988           else if (!strcmp ("cell_odd_ruled_sorted", detail))
2989             {
2990               freeme = get_darkened_gc (window, &style->base[state_type], 2);
2991               gc1 = freeme;
2992             }
2993           else
2994             gc1 = style->bg_gc[state_type];
2995         }
2996     }
2997   else
2998     gc1 = style->bg_gc[state_type];
2999   
3000   if (!style->bg_pixmap[state_type] || gc1 != style->bg_gc[state_type] ||
3001       GDK_IS_PIXMAP (window))
3002     {
3003       if (area)
3004         gdk_gc_set_clip_rectangle (gc1, area);
3005
3006       gdk_draw_rectangle (window, gc1, TRUE,
3007                           x, y, width, height);
3008
3009       if (detail && !strcmp ("tooltip", detail))
3010         gdk_draw_rectangle (window, style->black_gc, FALSE,
3011                             x, y, width - 1, height - 1);
3012
3013       if (area)
3014         gdk_gc_set_clip_rectangle (gc1, NULL);
3015     }
3016   else
3017     gtk_style_apply_default_background (style, window,
3018                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3019                                         state_type, area, x, y, width, height);
3020
3021
3022   if (freeme)
3023     g_object_unref (G_OBJECT (freeme));
3024 }
3025
3026 static void 
3027 gtk_default_draw_check (GtkStyle      *style,
3028                         GdkWindow     *window,
3029                         GtkStateType   state_type,
3030                         GtkShadowType  shadow_type,
3031                         GdkRectangle  *area,
3032                         GtkWidget     *widget,
3033                         const gchar   *detail,
3034                         gint           x,
3035                         gint           y,
3036                         gint           width,
3037                         gint           height)
3038 {
3039   if (detail && strcmp (detail, "cellcheck") == 0)
3040     {
3041       gdk_draw_rectangle (window,
3042                           widget->style->fg_gc[state_type],
3043                           FALSE,
3044                           x, y,
3045                           width, height);
3046
3047       if (shadow_type == GTK_SHADOW_IN)
3048         {
3049           gdk_draw_line (window,
3050                          widget->style->fg_gc[state_type],
3051                          x, y,
3052                          x + width,
3053                          y + height);
3054           gdk_draw_line (window,
3055                          widget->style->fg_gc[state_type],
3056                          x + width,
3057                          y,
3058                          x,
3059                          y + height);
3060         }
3061     }
3062   else
3063     {
3064       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3065       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3066       
3067       if (strcmp (detail, "check") == 0)        /* Menu item */
3068         {
3069           if (shadow_type == GTK_SHADOW_IN)
3070             {
3071               draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
3072               draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_AA);
3073             }
3074         }
3075       else
3076         {
3077           draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
3078           draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_DARK);
3079           draw_part (window, style->mid_gc[state_type], area, x, y, CHECK_MID);
3080           draw_part (window, style->light_gc[state_type], area, x, y, CHECK_LIGHT);
3081           draw_part (window, style->base_gc[state_type], area, x, y, CHECK_BASE);
3082           
3083           if (shadow_type == GTK_SHADOW_IN)
3084             {
3085               draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT);
3086               draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA);
3087             }
3088         }
3089     }
3090
3091 }
3092
3093 static void 
3094 gtk_default_draw_option (GtkStyle      *style,
3095                          GdkWindow     *window,
3096                          GtkStateType   state_type,
3097                          GtkShadowType  shadow_type,
3098                          GdkRectangle  *area,
3099                          GtkWidget     *widget,
3100                          const gchar   *detail,
3101                          gint           x,
3102                          gint           y,
3103                          gint           width,
3104                          gint           height)
3105 {
3106   if (detail && strcmp (detail, "cellradio") == 0)
3107     {
3108       gdk_draw_arc (window,
3109                     widget->style->fg_gc[state_type],
3110                     FALSE,
3111                     x, y,
3112                     width,
3113                     height,
3114                     0, 360*64);
3115
3116       if (shadow_type == GTK_SHADOW_IN)
3117         {
3118           gdk_draw_arc (window,
3119                         widget->style->fg_gc[state_type],
3120                         TRUE,
3121                         x + 2,
3122                         y + 2,
3123                         width - 4,
3124                         height - 4,
3125                         0, 360*64);
3126         }
3127     }
3128   else
3129     {
3130       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3131       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3132       
3133       if (strcmp (detail, "option") == 0)       /* Menu item */
3134         {
3135           if (shadow_type == GTK_SHADOW_IN)
3136             draw_part (window, style->fg_gc[state_type], area, x, y, RADIO_TEXT);
3137         }
3138       else
3139         {
3140           draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
3141           draw_part (window, style->dark_gc[state_type], area, x, y, RADIO_DARK);
3142           draw_part (window, style->mid_gc[state_type], area, x, y, RADIO_MID);
3143           draw_part (window, style->light_gc[state_type], area, x, y, RADIO_LIGHT);
3144           draw_part (window, style->base_gc[state_type], area, x, y, RADIO_BASE);
3145           
3146           if (shadow_type == GTK_SHADOW_IN)
3147             draw_part (window, style->text_gc[state_type], area, x, y, RADIO_TEXT);
3148         }
3149     }
3150 }
3151
3152 static void
3153 gtk_default_draw_tab (GtkStyle      *style,
3154                       GdkWindow     *window,
3155                       GtkStateType   state_type,
3156                       GtkShadowType  shadow_type,
3157                       GdkRectangle  *area,
3158                       GtkWidget     *widget,
3159                       const gchar   *detail,
3160                       gint           x,
3161                       gint           y,
3162                       gint           width,
3163                       gint           height)
3164 {
3165   GtkRequisition indicator_size;
3166   GtkBorder indicator_spacing;
3167   
3168   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3169
3170   x += (width - indicator_size.width) / 2;
3171   y += (height - indicator_size.height) / 2 - 1;
3172
3173   draw_varrow (window, style->black_gc, shadow_type, area, GTK_ARROW_UP,
3174                x, y, indicator_size.width, 5);
3175   draw_varrow (window, style->black_gc, shadow_type, area, GTK_ARROW_DOWN,
3176                x, y + 8, indicator_size.width, 5);
3177 }
3178
3179 static void 
3180 gtk_default_draw_shadow_gap (GtkStyle       *style,
3181                              GdkWindow      *window,
3182                              GtkStateType    state_type,
3183                              GtkShadowType   shadow_type,
3184                              GdkRectangle   *area,
3185                              GtkWidget      *widget,
3186                              const gchar    *detail,
3187                              gint            x,
3188                              gint            y,
3189                              gint            width,
3190                              gint            height,
3191                              GtkPositionType gap_side,
3192                              gint            gap_x,
3193                              gint            gap_width)
3194 {
3195   GdkGC *gc1 = NULL;
3196   GdkGC *gc2 = NULL;
3197   GdkGC *gc3 = NULL;
3198   GdkGC *gc4 = NULL;
3199   
3200   g_return_if_fail (GTK_IS_STYLE (style));
3201   g_return_if_fail (window != NULL);
3202   
3203   sanitize_size (window, &width, &height);
3204   
3205   switch (shadow_type)
3206     {
3207     case GTK_SHADOW_NONE:
3208       return;
3209     case GTK_SHADOW_IN:
3210       gc1 = style->dark_gc[state_type];
3211       gc2 = style->black_gc;
3212       gc3 = style->bg_gc[state_type];
3213       gc4 = style->light_gc[state_type];
3214       break;
3215     case GTK_SHADOW_ETCHED_IN:
3216       gc1 = style->dark_gc[state_type];
3217       gc2 = style->light_gc[state_type];
3218       gc3 = style->dark_gc[state_type];
3219       gc4 = style->light_gc[state_type];
3220       break;
3221     case GTK_SHADOW_OUT:
3222       gc1 = style->light_gc[state_type];
3223       gc2 = style->bg_gc[state_type];
3224       gc3 = style->dark_gc[state_type];
3225       gc4 = style->black_gc;
3226       break;
3227     case GTK_SHADOW_ETCHED_OUT:
3228       gc1 = style->light_gc[state_type];
3229       gc2 = style->dark_gc[state_type];
3230       gc3 = style->light_gc[state_type];
3231       gc4 = style->dark_gc[state_type];
3232       break;
3233     }
3234   if (area)
3235     {
3236       gdk_gc_set_clip_rectangle (gc1, area);
3237       gdk_gc_set_clip_rectangle (gc2, area);
3238       gdk_gc_set_clip_rectangle (gc3, area);
3239       gdk_gc_set_clip_rectangle (gc4, area);
3240     }
3241   
3242   switch (shadow_type)
3243     {
3244     case GTK_SHADOW_NONE:
3245     case GTK_SHADOW_IN:
3246     case GTK_SHADOW_OUT:
3247     case GTK_SHADOW_ETCHED_IN:
3248     case GTK_SHADOW_ETCHED_OUT:
3249       switch (gap_side)
3250         {
3251         case GTK_POS_TOP:
3252           gdk_draw_line (window, gc1,
3253                          x, y, x, y + height - 1);
3254           gdk_draw_line (window, gc2,
3255                          x + 1, y, x + 1, y + height - 2);
3256           
3257           gdk_draw_line (window, gc3,
3258                          x + 1, y + height - 2, x + width - 2, y + height - 2);
3259           gdk_draw_line (window, gc3,
3260                          x + width - 2, y, x + width - 2, y + height - 2);
3261           gdk_draw_line (window, gc4,
3262                          x, y + height - 1, x + width - 1, y + height - 1);
3263           gdk_draw_line (window, gc4,
3264                          x + width - 1, y, x + width - 1, y + height - 1);
3265           if (gap_x > 0)
3266             {
3267               gdk_draw_line (window, gc1,
3268                              x, y, x + gap_x - 1, y);
3269               gdk_draw_line (window, gc2,
3270                              x + 1, y + 1, x + gap_x - 1, y + 1);
3271               gdk_draw_line (window, gc2,
3272                              x + gap_x, y, x + gap_x, y);
3273             }
3274           if ((width - (gap_x + gap_width)) > 0)
3275             {
3276               gdk_draw_line (window, gc1,
3277                              x + gap_x + gap_width, y, x + width - 2, y);
3278               gdk_draw_line (window, gc2,
3279                              x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
3280               gdk_draw_line (window, gc2,
3281                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3282             }
3283           break;
3284         case GTK_POS_BOTTOM:
3285           gdk_draw_line (window, gc1,
3286                          x, y, x + width - 1, y);
3287           gdk_draw_line (window, gc1,
3288                          x, y, x, y + height - 1);
3289           gdk_draw_line (window, gc2,
3290                          x + 1, y + 1, x + width - 2, y + 1);
3291           gdk_draw_line (window, gc2,
3292                          x + 1, y + 1, x + 1, y + height - 1);
3293           
3294           gdk_draw_line (window, gc3,
3295                          x + width - 2, y + 1, x + width - 2, y + height - 1);
3296           gdk_draw_line (window, gc4,
3297                          x + width - 1, y, x + width - 1, y + height - 1);
3298           if (gap_x > 0)
3299             {
3300               gdk_draw_line (window, gc4,
3301                              x, y + height - 1, x + gap_x - 1, y + height - 1);
3302               gdk_draw_line (window, gc3,
3303                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3304               gdk_draw_line (window, gc3,
3305                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3306             }
3307           if ((width - (gap_x + gap_width)) > 0)
3308             {
3309               gdk_draw_line (window, gc4,
3310                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3311               gdk_draw_line (window, gc3,
3312                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3313               gdk_draw_line (window, gc3,
3314                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3315             }
3316           break;
3317         case GTK_POS_LEFT:
3318           gdk_draw_line (window, gc1,
3319                          x, y, x + width - 1, y);
3320           gdk_draw_line (window, gc2,
3321                          x, y + 1, x + width - 2, y + 1);
3322           
3323           gdk_draw_line (window, gc3,
3324                          x, y + height - 2, x + width - 2, y + height - 2);
3325           gdk_draw_line (window, gc3,
3326                          x + width - 2, y + 1, x + width - 2, y + height - 2);
3327           gdk_draw_line (window, gc4,
3328                          x, y + height - 1, x + width - 1, y + height - 1);
3329           gdk_draw_line (window, gc4,
3330                          x + width - 1, y, x + width - 1, y + height - 1);
3331           if (gap_x > 0)
3332             {
3333               gdk_draw_line (window, gc1,
3334                              x, y, x, y + gap_x - 1);
3335               gdk_draw_line (window, gc2,
3336                              x + 1, y + 1, x + 1, y + gap_x - 1);
3337               gdk_draw_line (window, gc2,
3338                              x, y + gap_x, x, y + gap_x);
3339             }
3340           if ((width - (gap_x + gap_width)) > 0)
3341             {
3342               gdk_draw_line (window, gc1,
3343                              x, y + gap_x + gap_width, x, y + height - 2);
3344               gdk_draw_line (window, gc2,
3345                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3346               gdk_draw_line (window, gc2,
3347                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3348             }
3349           break;
3350         case GTK_POS_RIGHT:
3351           gdk_draw_line (window, gc1,
3352                          x, y, x + width - 1, y);
3353           gdk_draw_line (window, gc1,
3354                          x, y, x, y + height - 1);
3355           gdk_draw_line (window, gc2,
3356                          x + 1, y + 1, x + width - 1, y + 1);
3357           gdk_draw_line (window, gc2,
3358                          x + 1, y + 1, x + 1, y + height - 2);
3359           
3360           gdk_draw_line (window, gc3,
3361                          x + 1, y + height - 2, x + width - 1, y + height - 2);
3362           gdk_draw_line (window, gc4,
3363                          x, y + height - 1, x + width - 1, y + height - 1);
3364           if (gap_x > 0)
3365             {
3366               gdk_draw_line (window, gc4,
3367                              x + width - 1, y, x + width - 1, y + gap_x - 1);
3368               gdk_draw_line (window, gc3,
3369                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3370               gdk_draw_line (window, gc3,
3371                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3372             }
3373           if ((width - (gap_x + gap_width)) > 0)
3374             {
3375               gdk_draw_line (window, gc4,
3376                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3377               gdk_draw_line (window, gc3,
3378                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3379               gdk_draw_line (window, gc3,
3380                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3381             }
3382           break;
3383         }
3384     }
3385
3386   if (area)
3387     {
3388       gdk_gc_set_clip_rectangle (gc1, NULL);
3389       gdk_gc_set_clip_rectangle (gc2, NULL);
3390       gdk_gc_set_clip_rectangle (gc3, NULL);
3391       gdk_gc_set_clip_rectangle (gc4, NULL);
3392     }
3393 }
3394
3395 static void 
3396 gtk_default_draw_box_gap (GtkStyle       *style,
3397                           GdkWindow      *window,
3398                           GtkStateType    state_type,
3399                           GtkShadowType   shadow_type,
3400                           GdkRectangle   *area,
3401                           GtkWidget      *widget,
3402                           const gchar    *detail,
3403                           gint            x,
3404                           gint            y,
3405                           gint            width,
3406                           gint            height,
3407                           GtkPositionType gap_side,
3408                           gint            gap_x,
3409                           gint            gap_width)
3410 {
3411   GdkGC *gc1 = NULL;
3412   GdkGC *gc2 = NULL;
3413   GdkGC *gc3 = NULL;
3414   GdkGC *gc4 = NULL;
3415   
3416   g_return_if_fail (GTK_IS_STYLE (style));
3417   g_return_if_fail (window != NULL);
3418   
3419   gtk_style_apply_default_background (style, window,
3420                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
3421                                       state_type, area, x, y, width, height);
3422   
3423   sanitize_size (window, &width, &height);
3424   
3425   switch (shadow_type)
3426     {
3427     case GTK_SHADOW_NONE:
3428       return;
3429     case GTK_SHADOW_IN:
3430       gc1 = style->dark_gc[state_type];
3431       gc2 = style->black_gc;
3432       gc3 = style->bg_gc[state_type];
3433       gc4 = style->light_gc[state_type];
3434       break;
3435     case GTK_SHADOW_ETCHED_IN:
3436       gc1 = style->dark_gc[state_type];
3437       gc2 = style->light_gc[state_type];
3438       gc3 = style->dark_gc[state_type];
3439       gc4 = style->light_gc[state_type];
3440       break;
3441     case GTK_SHADOW_OUT:
3442       gc1 = style->light_gc[state_type];
3443       gc2 = style->bg_gc[state_type];
3444       gc3 = style->dark_gc[state_type];
3445       gc4 = style->black_gc;
3446       break;
3447     case GTK_SHADOW_ETCHED_OUT:
3448       gc1 = style->light_gc[state_type];
3449       gc2 = style->dark_gc[state_type];
3450       gc3 = style->light_gc[state_type];
3451       gc4 = style->dark_gc[state_type];
3452       break;
3453     }
3454
3455   if (area)
3456     {
3457       gdk_gc_set_clip_rectangle (gc1, area);
3458       gdk_gc_set_clip_rectangle (gc2, area);
3459       gdk_gc_set_clip_rectangle (gc3, area);
3460       gdk_gc_set_clip_rectangle (gc4, area);
3461     }
3462   
3463   switch (shadow_type)
3464     {
3465     case GTK_SHADOW_NONE:
3466     case GTK_SHADOW_IN:
3467     case GTK_SHADOW_OUT:
3468     case GTK_SHADOW_ETCHED_IN:
3469     case GTK_SHADOW_ETCHED_OUT:
3470       switch (gap_side)
3471         {
3472         case GTK_POS_TOP:
3473           gdk_draw_line (window, gc1,
3474                          x, y, x, y + height - 1);
3475           gdk_draw_line (window, gc2,
3476                          x + 1, y, x + 1, y + height - 2);
3477           
3478           gdk_draw_line (window, gc3,
3479                          x + 1, y + height - 2, x + width - 2, y + height - 2);
3480           gdk_draw_line (window, gc3,
3481                          x + width - 2, y, x + width - 2, y + height - 2);
3482           gdk_draw_line (window, gc4,
3483                          x, y + height - 1, x + width - 1, y + height - 1);
3484           gdk_draw_line (window, gc4,
3485                          x + width - 1, y, x + width - 1, y + height - 1);
3486           if (gap_x > 0)
3487             {
3488               gdk_draw_line (window, gc1,
3489                              x, y, x + gap_x - 1, y);
3490               gdk_draw_line (window, gc2,
3491                              x + 1, y + 1, x + gap_x - 1, y + 1);
3492               gdk_draw_line (window, gc2,
3493                              x + gap_x, y, x + gap_x, y);
3494             }
3495           if ((width - (gap_x + gap_width)) > 0)
3496             {
3497               gdk_draw_line (window, gc1,
3498                              x + gap_x + gap_width, y, x + width - 2, y);
3499               gdk_draw_line (window, gc2,
3500                              x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
3501               gdk_draw_line (window, gc2,
3502                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3503             }
3504           break;
3505         case  GTK_POS_BOTTOM:
3506           gdk_draw_line (window, gc1,
3507                          x, y, x + width - 1, y);
3508           gdk_draw_line (window, gc1,
3509                          x, y, x, y + height - 1);
3510           gdk_draw_line (window, gc2,
3511                          x + 1, y + 1, x + width - 2, y + 1);
3512           gdk_draw_line (window, gc2,
3513                          x + 1, y + 1, x + 1, y + height - 1);
3514           
3515           gdk_draw_line (window, gc3,
3516                          x + width - 2, y + 1, x + width - 2, y + height - 1);
3517           gdk_draw_line (window, gc4,
3518                          x + width - 1, y, x + width - 1, y + height - 1);
3519           if (gap_x > 0)
3520             {
3521               gdk_draw_line (window, gc4,
3522                              x, y + height - 1, x + gap_x - 1, y + height - 1);
3523               gdk_draw_line (window, gc3,
3524                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3525               gdk_draw_line (window, gc3,
3526                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3527             }
3528           if ((width - (gap_x + gap_width)) > 0)
3529             {
3530               gdk_draw_line (window, gc4,
3531                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3532               gdk_draw_line (window, gc3,
3533                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3534               gdk_draw_line (window, gc3,
3535                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3536             }
3537           break;
3538         case GTK_POS_LEFT:
3539           gdk_draw_line (window, gc1,
3540                          x, y, x + width - 1, y);
3541           gdk_draw_line (window, gc2,
3542                          x, y + 1, x + width - 2, y + 1);
3543           
3544           gdk_draw_line (window, gc3,
3545                          x, y + height - 2, x + width - 2, y + height - 2);
3546           gdk_draw_line (window, gc3,
3547                          x + width - 2, y + 1, x + width - 2, y + height - 2);
3548           gdk_draw_line (window, gc4,
3549                          x, y + height - 1, x + width - 1, y + height - 1);
3550           gdk_draw_line (window, gc4,
3551                          x + width - 1, y, x + width - 1, y + height - 1);
3552           if (gap_x > 0)
3553             {
3554               gdk_draw_line (window, gc1,
3555                              x, y, x, y + gap_x - 1);
3556               gdk_draw_line (window, gc2,
3557                              x + 1, y + 1, x + 1, y + gap_x - 1);
3558               gdk_draw_line (window, gc2,
3559                              x, y + gap_x, x, y + gap_x);
3560             }
3561           if ((width - (gap_x + gap_width)) > 0)
3562             {
3563               gdk_draw_line (window, gc1,
3564                              x, y + gap_x + gap_width, x, y + height - 2);
3565               gdk_draw_line (window, gc2,
3566                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3567               gdk_draw_line (window, gc2,
3568                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3569             }
3570           break;
3571         case GTK_POS_RIGHT:
3572           gdk_draw_line (window, gc1,
3573                          x, y, x + width - 1, y);
3574           gdk_draw_line (window, gc1,
3575                          x, y, x, y + height - 1);
3576           gdk_draw_line (window, gc2,
3577                          x + 1, y + 1, x + width - 1, y + 1);
3578           gdk_draw_line (window, gc2,
3579                          x + 1, y + 1, x + 1, y + height - 2);
3580           
3581           gdk_draw_line (window, gc3,
3582                          x + 1, y + height - 2, x + width - 1, y + height - 2);
3583           gdk_draw_line (window, gc4,
3584                          x, y + height - 1, x + width - 1, y + height - 1);
3585           if (gap_x > 0)
3586             {
3587               gdk_draw_line (window, gc4,
3588                              x + width - 1, y, x + width - 1, y + gap_x - 1);
3589               gdk_draw_line (window, gc3,
3590                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3591               gdk_draw_line (window, gc3,
3592                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3593             }
3594           if ((width - (gap_x + gap_width)) > 0)
3595             {
3596               gdk_draw_line (window, gc4,
3597                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3598               gdk_draw_line (window, gc3,
3599                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3600               gdk_draw_line (window, gc3,
3601                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3602             }
3603           break;
3604         }
3605     }
3606
3607   if (area)
3608     {
3609       gdk_gc_set_clip_rectangle (gc1, NULL);
3610       gdk_gc_set_clip_rectangle (gc2, NULL);
3611       gdk_gc_set_clip_rectangle (gc3, NULL);
3612       gdk_gc_set_clip_rectangle (gc4, NULL);
3613     }
3614 }
3615
3616 static void 
3617 gtk_default_draw_extension (GtkStyle       *style,
3618                             GdkWindow      *window,
3619                             GtkStateType    state_type,
3620                             GtkShadowType   shadow_type,
3621                             GdkRectangle   *area,
3622                             GtkWidget      *widget,
3623                             const gchar    *detail,
3624                             gint            x,
3625                             gint            y,
3626                             gint            width,
3627                             gint            height,
3628                             GtkPositionType gap_side)
3629 {
3630   GdkGC *gc1 = NULL;
3631   GdkGC *gc2 = NULL;
3632   GdkGC *gc3 = NULL;
3633   GdkGC *gc4 = NULL;
3634   
3635   g_return_if_fail (GTK_IS_STYLE (style));
3636   g_return_if_fail (window != NULL);
3637   
3638   gtk_style_apply_default_background (style, window,
3639                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
3640                                       GTK_STATE_NORMAL, area, x, y, width, height);
3641   
3642   sanitize_size (window, &width, &height);
3643   
3644   switch (shadow_type)
3645     {
3646     case GTK_SHADOW_NONE:
3647       return;
3648     case GTK_SHADOW_IN:
3649       gc1 = style->dark_gc[state_type];
3650       gc2 = style->black_gc;
3651       gc3 = style->bg_gc[state_type];
3652       gc4 = style->light_gc[state_type];
3653       break;
3654     case GTK_SHADOW_ETCHED_IN:
3655       gc1 = style->dark_gc[state_type];
3656       gc2 = style->light_gc[state_type];
3657       gc3 = style->dark_gc[state_type];
3658       gc4 = style->light_gc[state_type];
3659       break;
3660     case GTK_SHADOW_OUT:
3661       gc1 = style->light_gc[state_type];
3662       gc2 = style->bg_gc[state_type];
3663       gc3 = style->dark_gc[state_type];
3664       gc4 = style->black_gc;
3665       break;
3666     case GTK_SHADOW_ETCHED_OUT:
3667       gc1 = style->light_gc[state_type];
3668       gc2 = style->dark_gc[state_type];
3669       gc3 = style->light_gc[state_type];
3670       gc4 = style->dark_gc[state_type];
3671       break;
3672     }
3673
3674   if (area)
3675     {
3676       gdk_gc_set_clip_rectangle (gc1, area);
3677       gdk_gc_set_clip_rectangle (gc2, area);
3678       gdk_gc_set_clip_rectangle (gc3, area);
3679       gdk_gc_set_clip_rectangle (gc4, area);
3680     }
3681
3682   switch (shadow_type)
3683     {
3684     case GTK_SHADOW_NONE:
3685     case GTK_SHADOW_IN:
3686     case GTK_SHADOW_OUT:
3687     case GTK_SHADOW_ETCHED_IN:
3688     case GTK_SHADOW_ETCHED_OUT:
3689       switch (gap_side)
3690         {
3691         case GTK_POS_TOP:
3692           gtk_style_apply_default_background (style, window,
3693                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3694                                               state_type, area,
3695                                               x + style->xthickness, 
3696                                               y, 
3697                                               width - (2 * style->xthickness), 
3698                                               height - (style->ythickness));
3699           gdk_draw_line (window, gc1,
3700                          x, y, x, y + height - 2);
3701           gdk_draw_line (window, gc2,
3702                          x + 1, y, x + 1, y + height - 2);
3703           
3704           gdk_draw_line (window, gc3,
3705                          x + 2, y + height - 2, x + width - 2, y + height - 2);
3706           gdk_draw_line (window, gc3,
3707                          x + width - 2, y, x + width - 2, y + height - 2);
3708           gdk_draw_line (window, gc4,
3709                          x + 1, y + height - 1, x + width - 2, y + height - 1);
3710           gdk_draw_line (window, gc4,
3711                          x + width - 1, y, x + width - 1, y + height - 2);
3712           break;
3713         case GTK_POS_BOTTOM:
3714           gtk_style_apply_default_background (style, window,
3715                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3716                                               state_type, area,
3717                                               x + style->xthickness, 
3718                                               y + style->ythickness, 
3719                                               width - (2 * style->xthickness), 
3720                                               height - (style->ythickness));
3721           gdk_draw_line (window, gc1,
3722                          x + 1, y, x + width - 2, y);
3723           gdk_draw_line (window, gc1,
3724                          x, y + 1, x, y + height - 1);
3725           gdk_draw_line (window, gc2,
3726                          x + 1, y + 1, x + width - 2, y + 1);
3727           gdk_draw_line (window, gc2,
3728                          x + 1, y + 1, x + 1, y + height - 1);
3729           
3730           gdk_draw_line (window, gc3,
3731                          x + width - 2, y + 2, x + width - 2, y + height - 1);
3732           gdk_draw_line (window, gc4,
3733                          x + width - 1, y + 1, x + width - 1, y + height - 1);
3734           break;
3735         case GTK_POS_LEFT:
3736           gtk_style_apply_default_background (style, window,
3737                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3738                                               state_type, area,
3739                                               x, 
3740                                               y + style->ythickness, 
3741                                               width - (style->xthickness), 
3742                                               height - (2 * style->ythickness));
3743           gdk_draw_line (window, gc1,
3744                          x, y, x + width - 2, y);
3745           gdk_draw_line (window, gc2,
3746                          x + 1, y + 1, x + width - 2, y + 1);
3747           
3748           gdk_draw_line (window, gc3,
3749                          x, y + height - 2, x + width - 2, y + height - 2);
3750           gdk_draw_line (window, gc3,
3751                          x + width - 2, y + 2, x + width - 2, y + height - 2);
3752           gdk_draw_line (window, gc4,
3753                          x, y + height - 1, x + width - 2, y + height - 1);
3754           gdk_draw_line (window, gc4,
3755                          x + width - 1, y + 1, x + width - 1, y + height - 2);
3756           break;
3757         case GTK_POS_RIGHT:
3758           gtk_style_apply_default_background (style, window,
3759                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3760                                               state_type, area,
3761                                               x + style->xthickness, 
3762                                               y + style->ythickness, 
3763                                               width - (style->xthickness), 
3764                                               height - (2 * style->ythickness));
3765           gdk_draw_line (window, gc1,
3766                          x + 1, y, x + width - 1, y);
3767           gdk_draw_line (window, gc1,
3768                          x, y + 1, x, y + height - 2);
3769           gdk_draw_line (window, gc2,
3770                          x + 1, y + 1, x + width - 1, y + 1);
3771           gdk_draw_line (window, gc2,
3772                          x + 1, y + 1, x + 1, y + height - 2);
3773           
3774           gdk_draw_line (window, gc3,
3775                          x + 2, y + height - 2, x + width - 1, y + height - 2);
3776           gdk_draw_line (window, gc4,
3777                          x + 1, y + height - 1, x + width - 1, y + height - 1);
3778           break;
3779         }
3780     }
3781
3782   if (area)
3783     {
3784       gdk_gc_set_clip_rectangle (gc1, NULL);
3785       gdk_gc_set_clip_rectangle (gc2, NULL);
3786       gdk_gc_set_clip_rectangle (gc3, NULL);
3787       gdk_gc_set_clip_rectangle (gc4, NULL);
3788     }
3789 }
3790
3791 static void 
3792 gtk_default_draw_focus (GtkStyle      *style,
3793                         GdkWindow     *window,
3794                         GdkRectangle  *area,
3795                         GtkWidget     *widget,
3796                         const gchar   *detail,
3797                         gint           x,
3798                         gint           y,
3799                         gint           width,
3800                         gint           height)
3801 {
3802   GdkPoint points[5];
3803   
3804   sanitize_size (window, &width, &height);
3805   
3806   if (area)
3807     gdk_gc_set_clip_rectangle (style->black_gc, area);
3808
3809   gdk_gc_set_line_attributes (style->black_gc, 1, GDK_LINE_ON_OFF_DASH, 0, 0);
3810
3811   if (detail && !strcmp (detail, "add-mode"))
3812     gdk_gc_set_dashes (style->black_gc, 0, "\4\4", 2);
3813   else
3814     gdk_gc_set_dashes (style->black_gc, 0, "\1\1", 2);
3815
3816   points[0].x = x;
3817   points[0].y = y;
3818   points[1].x = x + width;
3819   points[1].y = y;
3820   points[2].x = x + width;
3821   points[2].y = y + height;
3822   points[3].x = x;
3823   points[3].y = y + height;
3824   points[4] = points[0];
3825   
3826   gdk_draw_polygon (window, style->black_gc, FALSE, points, 4);
3827   gdk_gc_set_line_attributes (style->black_gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
3828
3829   if (area)
3830     gdk_gc_set_clip_rectangle (style->black_gc, NULL);
3831 }
3832
3833 static void 
3834 gtk_default_draw_slider (GtkStyle      *style,
3835                          GdkWindow     *window,
3836                          GtkStateType   state_type,
3837                          GtkShadowType  shadow_type,
3838                          GdkRectangle  *area,
3839                          GtkWidget     *widget,
3840                          const gchar   *detail,
3841                          gint           x,
3842                          gint           y,
3843                          gint           width,
3844                          gint           height,
3845                          GtkOrientation orientation)
3846 {
3847   g_return_if_fail (GTK_IS_STYLE (style));
3848   g_return_if_fail (window != NULL);
3849   
3850   sanitize_size (window, &width, &height);
3851   
3852   gtk_paint_box (style, window, state_type, shadow_type,
3853                  area, widget, detail, x, y, width, height);
3854
3855   if (detail &&
3856       (strcmp ("hscale", detail) == 0 ||
3857        strcmp ("vscale", detail) == 0))
3858     {
3859       if (orientation == GTK_ORIENTATION_HORIZONTAL)
3860         gtk_paint_vline (style, window, state_type, area, widget, detail, 
3861                          y + style->ythickness, 
3862                          y + height - style->ythickness - 1, x + width / 2);
3863       else
3864         gtk_paint_hline (style, window, state_type, area, widget, detail, 
3865                          x + style->xthickness, 
3866                          x + width - style->xthickness - 1, y + height / 2);
3867     }
3868 }
3869
3870 static void
3871 draw_dot (GdkWindow    *window,
3872           GdkGC        *light_gc,
3873           GdkGC        *dark_gc,
3874           gint          x,
3875           gint          y,
3876           gushort       size)
3877 {
3878   
3879   size = CLAMP (size, 2, 3);
3880
3881   if (size == 2)
3882     {
3883       gdk_draw_point (window, light_gc, x, y);
3884       gdk_draw_point (window, light_gc, x+1, y+1);
3885     }
3886   else if (size == 3);
3887     {
3888       gdk_draw_point (window, light_gc, x, y);
3889       gdk_draw_point (window, light_gc, x+1, y);
3890       gdk_draw_point (window, light_gc, x, y+1);
3891       gdk_draw_point (window, dark_gc, x+1, y+2);
3892       gdk_draw_point (window, dark_gc, x+2, y+1);
3893       gdk_draw_point (window, dark_gc, x+2, y+2);
3894     }
3895 }
3896
3897 static void 
3898 gtk_default_draw_handle (GtkStyle      *style,
3899                          GdkWindow     *window,
3900                          GtkStateType   state_type,
3901                          GtkShadowType  shadow_type,
3902                          GdkRectangle  *area,
3903                          GtkWidget     *widget,
3904                          const gchar   *detail,
3905                          gint           x,
3906                          gint           y,
3907                          gint           width,
3908                          gint           height,
3909                          GtkOrientation orientation)
3910 {
3911   gint xx, yy;
3912   gint xthick, ythick;
3913   GdkGC *light_gc, *dark_gc;
3914   GdkRectangle rect;
3915   GdkRectangle dest;
3916   gint intersect;
3917   
3918   g_return_if_fail (GTK_IS_STYLE (style));
3919   g_return_if_fail (window != NULL);
3920   
3921   sanitize_size (window, &width, &height);
3922   
3923   gtk_paint_box (style, window, state_type, shadow_type, area, widget, 
3924                  detail, x, y, width, height);
3925   
3926   
3927   if (!strcmp (detail, "paned"))
3928     {
3929       /* we want to ignore the shadow border in paned widgets */
3930       xthick = 0;
3931       ythick = 0;
3932
3933       light_gc = style->light_gc[state_type];
3934       dark_gc = style->black_gc;
3935     }
3936   else
3937     {
3938       xthick = style->xthickness;
3939       ythick = style->ythickness;
3940
3941       light_gc = style->light_gc[state_type];
3942       dark_gc = style->dark_gc[state_type];
3943     }
3944   
3945   rect.x = x + xthick;
3946   rect.y = y + ythick;
3947   rect.width = width - (xthick * 2);
3948   rect.height = height - (ythick * 2);
3949
3950   if (area)
3951       intersect = gdk_rectangle_intersect (area, &rect, &dest);
3952   else
3953     {
3954       intersect = TRUE;
3955       dest = rect;
3956     }
3957
3958   if (!intersect)
3959     return;
3960
3961   gdk_gc_set_clip_rectangle (light_gc, &dest);
3962   gdk_gc_set_clip_rectangle (dark_gc, &dest);
3963
3964   if (!strcmp (detail, "paned"))
3965     {
3966       gint window_width;
3967       gint window_height;
3968
3969       gdk_window_get_size (window, &window_width, &window_height);
3970
3971       if (orientation == GTK_ORIENTATION_HORIZONTAL)
3972         for (xx = window_width/2 - 15; xx <= window_width/2 + 15; xx += 5)
3973           draw_dot (window, light_gc, dark_gc, xx, window_height/2 - 1, 3);
3974       else
3975         for (yy = window_height/2 - 15; yy <= window_height/2 + 15; yy += 5)
3976           draw_dot (window, light_gc, dark_gc, window_width/2 - 1, yy, 3);
3977     }
3978   else
3979     {
3980       for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
3981         for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
3982           {
3983             draw_dot (window, light_gc, dark_gc, xx, yy, 2);
3984             draw_dot (window, light_gc, dark_gc, xx + 3, yy + 1, 2);
3985           }
3986     }
3987
3988   gdk_gc_set_clip_rectangle (light_gc, NULL);
3989   gdk_gc_set_clip_rectangle (dark_gc, NULL);
3990 }
3991
3992 static void
3993 create_expander_affine (gdouble affine[6],
3994                         gint    degrees,
3995                         gint    expander_size,
3996                         gint    x,
3997                         gint    y)
3998 {
3999   gdouble s, c;
4000   gdouble width;
4001   gdouble height;
4002
4003   width = expander_size / 4.0;
4004   height = expander_size / 2.0;
4005   
4006   s = sin (degrees * G_PI / 180.0);
4007   c = cos (degrees * G_PI / 180.0);
4008   
4009   affine[0] = c;
4010   affine[1] = s;
4011   affine[2] = -s;
4012   affine[3] = c;
4013   affine[4] = -width * c - height * -s + x;
4014   affine[5] = -width * s - height * c + y;
4015 }
4016
4017 static void
4018 apply_affine_on_point (double affine[6], GdkPoint *point)
4019 {
4020   gdouble x, y;
4021
4022   x = point->x * affine[0] + point->y * affine[2] + affine[4];
4023   y = point->x * affine[1] + point->y * affine[3] + affine[5];
4024
4025   point->x = x;
4026   point->y = y;
4027 }
4028
4029 static void
4030 gtk_default_draw_expander (GtkStyle        *style,
4031                            GdkWindow       *window,
4032                            GtkStateType     state_type,
4033                            GdkRectangle    *area,
4034                            GtkWidget       *widget,
4035                            const gchar     *detail,
4036                            gint             x,
4037                            gint             y,
4038                            GtkExpanderStyle expander_style)
4039 {
4040   gint expander_size;
4041   GdkPoint points[3];
4042   gint i;
4043   gdouble affine[6];
4044   gint degrees = 0;
4045   
4046   gtk_widget_style_get (widget,
4047                         "expander_size", &expander_size,
4048                         NULL);
4049
4050   if (area)
4051     {
4052       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], area);
4053       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], area);
4054     }
4055
4056   points[0].x = 0;
4057   points[0].y = 0;
4058   points[1].x = expander_size / 2;
4059   points[1].y =  expander_size / 2;
4060   points[2].x = 0;
4061   points[2].y = expander_size;
4062
4063   switch (expander_style)
4064     {
4065     case GTK_EXPANDER_COLLAPSED:
4066       degrees = 0;
4067       break;
4068     case GTK_EXPANDER_SEMI_COLLAPSED:
4069       degrees = 30;
4070       break;
4071     case GTK_EXPANDER_SEMI_EXPANDED:
4072       degrees = 60;
4073       break;
4074     case GTK_EXPANDER_EXPANDED:
4075       degrees = 90;
4076       break;
4077     default:
4078       g_assert_not_reached ();
4079     }
4080   
4081   create_expander_affine (affine, degrees, expander_size, x, y);
4082
4083   for (i = 0; i < 3; i++)
4084     apply_affine_on_point (affine, &points[i]);
4085
4086   if (state_type == GTK_STATE_PRELIGHT)
4087     {
4088       gdk_draw_polygon (window, style->base_gc[GTK_STATE_NORMAL],
4089                         TRUE, points, 3);
4090       gdk_draw_polygon (window, style->fg_gc[GTK_STATE_NORMAL],
4091                         FALSE, points, 3);
4092     }
4093   else if (state_type == GTK_STATE_ACTIVE)
4094     {
4095       gdk_draw_polygon (window, style->light_gc[GTK_STATE_ACTIVE],
4096                         TRUE, points, 3);
4097       gdk_draw_polygon (window, style->fg_gc[GTK_STATE_NORMAL],
4098                         FALSE, points, 3);
4099     }
4100   else
4101     {
4102       gdk_draw_polygon (window, style->fg_gc[GTK_STATE_NORMAL],
4103                         TRUE, points, 3);
4104     }
4105   if (area)
4106     {
4107       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
4108       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
4109     }
4110 }
4111
4112 typedef struct _ByteRange ByteRange;
4113
4114 struct _ByteRange
4115 {
4116   guint start;
4117   guint end;
4118 };
4119
4120 static ByteRange*
4121 range_new (guint start,
4122            guint end)
4123 {
4124   ByteRange *br = g_new (ByteRange, 1);
4125
4126   br->start = start;
4127   br->end = end;
4128   
4129   return br;
4130 }
4131
4132 static PangoLayout*
4133 get_insensitive_layout (PangoLayout *layout)
4134 {
4135   GSList *embossed_ranges = NULL;
4136   GSList *stippled_ranges = NULL;
4137   PangoLayoutIter *iter;
4138   GSList *tmp_list = NULL;
4139   PangoLayout *new_layout;
4140   PangoAttrList *attrs;
4141   GdkBitmap *stipple = NULL;
4142   
4143   iter = pango_layout_get_iter (layout);
4144   
4145   do
4146     {
4147       PangoLayoutRun *run;
4148       PangoAttribute *attr;
4149       gboolean need_stipple = FALSE;
4150       ByteRange *br;
4151       
4152       run = pango_layout_iter_get_run (iter);
4153
4154       if (run)
4155         {
4156           tmp_list = run->item->analysis.extra_attrs;
4157
4158           while (tmp_list != NULL)
4159             {
4160               attr = tmp_list->data;
4161               switch (attr->klass->type)
4162                 {
4163                 case PANGO_ATTR_FOREGROUND:
4164                 case PANGO_ATTR_BACKGROUND:
4165                   need_stipple = TRUE;
4166                   break;
4167               
4168                 default:
4169                   break;
4170                 }
4171
4172               if (need_stipple)
4173                 break;
4174           
4175               tmp_list = g_slist_next (tmp_list);
4176             }
4177
4178           br = range_new (run->item->offset, run->item->offset + run->item->length);
4179       
4180           if (need_stipple)
4181             stippled_ranges = g_slist_prepend (stippled_ranges, br);
4182           else
4183             embossed_ranges = g_slist_prepend (embossed_ranges, br);
4184         }
4185     }
4186   while (pango_layout_iter_next_run (iter));
4187
4188   pango_layout_iter_free (iter);
4189
4190   new_layout = pango_layout_copy (layout);
4191
4192   attrs = pango_layout_get_attributes (new_layout);
4193
4194   if (attrs == NULL)
4195     {
4196       /* Create attr list if there wasn't one */
4197       attrs = pango_attr_list_new ();
4198       pango_layout_set_attributes (new_layout, attrs);
4199       pango_attr_list_unref (attrs);
4200     }
4201   
4202   tmp_list = embossed_ranges;
4203   while (tmp_list != NULL)
4204     {
4205       PangoAttribute *attr;
4206       ByteRange *br = tmp_list->data;
4207
4208       attr = gdk_pango_attr_embossed_new (TRUE);
4209
4210       attr->start_index = br->start;
4211       attr->end_index = br->end;
4212       
4213       pango_attr_list_change (attrs, attr);
4214
4215       g_free (br);
4216       
4217       tmp_list = g_slist_next (tmp_list);
4218     }
4219
4220   g_slist_free (embossed_ranges);
4221   
4222   tmp_list = stippled_ranges;
4223   while (tmp_list != NULL)
4224     {
4225       PangoAttribute *attr;
4226       ByteRange *br = tmp_list->data;
4227
4228       if (stipple == NULL)
4229         {
4230 #define gray50_width 2
4231 #define gray50_height 2
4232           static char gray50_bits[] = {
4233             0x02, 0x01
4234           };
4235
4236           stipple = gdk_bitmap_create_from_data (NULL,
4237                                                  gray50_bits, gray50_width,
4238                                                  gray50_height);
4239         }
4240       
4241       attr = gdk_pango_attr_stipple_new (stipple);
4242
4243       attr->start_index = br->start;
4244       attr->end_index = br->end;
4245       
4246       pango_attr_list_change (attrs, attr);
4247
4248       g_free (br);
4249       
4250       tmp_list = g_slist_next (tmp_list);
4251     }
4252
4253   g_slist_free (stippled_ranges);
4254   
4255   if (stipple)
4256     g_object_unref (G_OBJECT (stipple));
4257
4258   return new_layout;
4259 }
4260
4261 static void
4262 gtk_default_draw_layout (GtkStyle        *style,
4263                          GdkWindow       *window,
4264                          GtkStateType     state_type,
4265                          gboolean         use_text,
4266                          GdkRectangle    *area,
4267                          GtkWidget       *widget,
4268                          const gchar     *detail,
4269                          gint             x,
4270                          gint             y,
4271                          PangoLayout     *layout)
4272 {
4273   GdkGC *gc;
4274   
4275   g_return_if_fail (GTK_IS_STYLE (style));
4276   g_return_if_fail (window != NULL);
4277
4278   gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
4279   
4280   if (area)
4281     gdk_gc_set_clip_rectangle (gc, area);
4282
4283   if (state_type == GTK_STATE_INSENSITIVE)
4284     {
4285       PangoLayout *ins;
4286
4287       ins = get_insensitive_layout (layout);
4288       
4289       gdk_draw_layout (window, gc, x, y, ins);
4290
4291       g_object_unref (G_OBJECT (ins));
4292     }
4293   else
4294     {
4295       gdk_draw_layout (window, gc, x, y, layout);
4296     }
4297
4298   if (area)
4299     gdk_gc_set_clip_rectangle (gc, NULL);
4300 }
4301
4302 static void
4303 gtk_default_draw_resize_grip (GtkStyle       *style,
4304                               GdkWindow      *window,
4305                               GtkStateType    state_type,
4306                               GdkRectangle   *area,
4307                               GtkWidget      *widget,
4308                               const gchar    *detail,
4309                               GdkWindowEdge   edge,
4310                               gint            x,
4311                               gint            y,
4312                               gint            width,
4313                               gint            height)
4314 {
4315   g_return_if_fail (GTK_IS_STYLE (style));
4316   g_return_if_fail (window != NULL);
4317   
4318   if (area)
4319     {
4320       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
4321       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
4322       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
4323     }
4324
4325   /* make it square, aligning to bottom right */
4326   if (width < height)
4327     {
4328       y += (height - width);
4329       height = width;
4330     }
4331   else if (height < width)
4332     {
4333       x += (width - height);
4334       width = height;
4335     }
4336
4337   /* Clear background */
4338   gdk_draw_rectangle (window,
4339                       style->bg_gc[state_type],
4340                       TRUE,
4341                       x, y, width, height);
4342   
4343   switch (edge)
4344     {
4345     case GDK_WINDOW_EDGE_SOUTH_EAST:
4346       {
4347         gint xi, yi;
4348
4349         xi = x;
4350         yi = y;
4351
4352         while (xi < (x + width - 3))
4353           {
4354             gdk_draw_line (window,
4355                            style->light_gc[state_type],
4356                            xi, y + height,
4357                            x + width, yi);                           
4358
4359             ++xi;
4360             ++yi;
4361             
4362             gdk_draw_line (window,
4363                            style->dark_gc[state_type],
4364                            xi, y + height,
4365                            x + width, yi);                           
4366
4367             ++xi;
4368             ++yi;
4369             
4370             gdk_draw_line (window,
4371                            style->dark_gc[state_type],
4372                            xi, y + height,
4373                            x + width, yi);
4374
4375             xi += 3;
4376             yi += 3;
4377           }
4378       }
4379       break;
4380     default:
4381       g_assert_not_reached ();
4382       break;
4383     }
4384   
4385   if (area)
4386     {
4387       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
4388       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
4389       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
4390     }
4391 }
4392
4393 static void
4394 gtk_style_shade (GdkColor *a,
4395                  GdkColor *b,
4396                  gdouble   k)
4397 {
4398   gdouble red;
4399   gdouble green;
4400   gdouble blue;
4401   
4402   red = (gdouble) a->red / 65535.0;
4403   green = (gdouble) a->green / 65535.0;
4404   blue = (gdouble) a->blue / 65535.0;
4405   
4406   rgb_to_hls (&red, &green, &blue);
4407   
4408   green *= k;
4409   if (green > 1.0)
4410     green = 1.0;
4411   else if (green < 0.0)
4412     green = 0.0;
4413   
4414   blue *= k;
4415   if (blue > 1.0)
4416     blue = 1.0;
4417   else if (blue < 0.0)
4418     blue = 0.0;
4419   
4420   hls_to_rgb (&red, &green, &blue);
4421   
4422   b->red = red * 65535.0;
4423   b->green = green * 65535.0;
4424   b->blue = blue * 65535.0;
4425 }
4426
4427 static void
4428 rgb_to_hls (gdouble *r,
4429             gdouble *g,
4430             gdouble *b)
4431 {
4432   gdouble min;
4433   gdouble max;
4434   gdouble red;
4435   gdouble green;
4436   gdouble blue;
4437   gdouble h, l, s;
4438   gdouble delta;
4439   
4440   red = *r;
4441   green = *g;
4442   blue = *b;
4443   
4444   if (red > green)
4445     {
4446       if (red > blue)
4447         max = red;
4448       else
4449         max = blue;
4450       
4451       if (green < blue)
4452         min = green;
4453       else
4454         min = blue;
4455     }
4456   else
4457     {
4458       if (green > blue)
4459         max = green;
4460       else
4461         max = blue;
4462       
4463       if (red < blue)
4464         min = red;
4465       else
4466         min = blue;
4467     }
4468   
4469   l = (max + min) / 2;
4470   s = 0;
4471   h = 0;
4472   
4473   if (max != min)
4474     {
4475       if (l <= 0.5)
4476         s = (max - min) / (max + min);
4477       else
4478         s = (max - min) / (2 - max - min);
4479       
4480       delta = max -min;
4481       if (red == max)
4482         h = (green - blue) / delta;
4483       else if (green == max)
4484         h = 2 + (blue - red) / delta;
4485       else if (blue == max)
4486         h = 4 + (red - green) / delta;
4487       
4488       h *= 60;
4489       if (h < 0.0)
4490         h += 360;
4491     }
4492   
4493   *r = h;
4494   *g = l;
4495   *b = s;
4496 }
4497
4498 static void
4499 hls_to_rgb (gdouble *h,
4500             gdouble *l,
4501             gdouble *s)
4502 {
4503   gdouble hue;
4504   gdouble lightness;
4505   gdouble saturation;
4506   gdouble m1, m2;
4507   gdouble r, g, b;
4508   
4509   lightness = *l;
4510   saturation = *s;
4511   
4512   if (lightness <= 0.5)
4513     m2 = lightness * (1 + saturation);
4514   else
4515     m2 = lightness + saturation - lightness * saturation;
4516   m1 = 2 * lightness - m2;
4517   
4518   if (saturation == 0)
4519     {
4520       *h = lightness;
4521       *l = lightness;
4522       *s = lightness;
4523     }
4524   else
4525     {
4526       hue = *h + 120;
4527       while (hue > 360)
4528         hue -= 360;
4529       while (hue < 0)
4530         hue += 360;
4531       
4532       if (hue < 60)
4533         r = m1 + (m2 - m1) * hue / 60;
4534       else if (hue < 180)
4535         r = m2;
4536       else if (hue < 240)
4537         r = m1 + (m2 - m1) * (240 - hue) / 60;
4538       else
4539         r = m1;
4540       
4541       hue = *h;
4542       while (hue > 360)
4543         hue -= 360;
4544       while (hue < 0)
4545         hue += 360;
4546       
4547       if (hue < 60)
4548         g = m1 + (m2 - m1) * hue / 60;
4549       else if (hue < 180)
4550         g = m2;
4551       else if (hue < 240)
4552         g = m1 + (m2 - m1) * (240 - hue) / 60;
4553       else
4554         g = m1;
4555       
4556       hue = *h - 120;
4557       while (hue > 360)
4558         hue -= 360;
4559       while (hue < 0)
4560         hue += 360;
4561       
4562       if (hue < 60)
4563         b = m1 + (m2 - m1) * hue / 60;
4564       else if (hue < 180)
4565         b = m2;
4566       else if (hue < 240)
4567         b = m1 + (m2 - m1) * (240 - hue) / 60;
4568       else
4569         b = m1;
4570       
4571       *h = r;
4572       *l = g;
4573       *s = b;
4574     }
4575 }
4576
4577 void 
4578 gtk_paint_hline (GtkStyle      *style,
4579                  GdkWindow     *window,
4580                  GtkStateType   state_type,
4581                  GdkRectangle  *area,
4582                  GtkWidget     *widget,
4583                  const gchar   *detail,
4584                  gint          x1,
4585                  gint          x2,
4586                  gint          y)
4587 {
4588   g_return_if_fail (GTK_IS_STYLE (style));
4589   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
4590   
4591   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y);
4592 }
4593
4594 void
4595 gtk_paint_vline (GtkStyle      *style,
4596                  GdkWindow     *window,
4597                  GtkStateType   state_type,
4598                  GdkRectangle  *area,
4599                  GtkWidget     *widget,
4600                  const gchar   *detail,
4601                  gint          y1,
4602                  gint          y2,
4603                  gint          x)
4604 {
4605   g_return_if_fail (GTK_IS_STYLE (style));
4606   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
4607   
4608   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1, y2, x);
4609 }
4610
4611 void
4612 gtk_paint_shadow (GtkStyle     *style,
4613                   GdkWindow    *window,
4614                   GtkStateType  state_type,
4615                   GtkShadowType shadow_type,
4616                   GdkRectangle *area,
4617                   GtkWidget    *widget,
4618                   const gchar  *detail,
4619                   gint          x,
4620                   gint          y,
4621                   gint          width,
4622                   gint          height)
4623 {
4624   g_return_if_fail (GTK_IS_STYLE (style));
4625   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
4626   
4627   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4628 }
4629
4630 void
4631 gtk_paint_polygon (GtkStyle      *style,
4632                    GdkWindow     *window,
4633                    GtkStateType   state_type,
4634                    GtkShadowType  shadow_type,
4635                    GdkRectangle  *area,
4636                    GtkWidget     *widget,
4637                    const gchar   *detail,
4638                    GdkPoint      *points,
4639                    gint           npoints,
4640                    gboolean       fill)
4641 {
4642   g_return_if_fail (GTK_IS_STYLE (style));
4643   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
4644   
4645   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill);
4646 }
4647
4648 void
4649 gtk_paint_arrow (GtkStyle      *style,
4650                  GdkWindow     *window,
4651                  GtkStateType   state_type,
4652                  GtkShadowType  shadow_type,
4653                  GdkRectangle  *area,
4654                  GtkWidget     *widget,
4655                  const gchar   *detail,
4656                  GtkArrowType   arrow_type,
4657                  gboolean       fill,
4658                  gint           x,
4659                  gint           y,
4660                  gint           width,
4661                  gint           height)
4662 {
4663   g_return_if_fail (GTK_IS_STYLE (style));
4664   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
4665   
4666   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height);
4667 }
4668
4669 void
4670 gtk_paint_diamond (GtkStyle      *style,
4671                    GdkWindow     *window,
4672                    GtkStateType   state_type,
4673                    GtkShadowType  shadow_type,
4674                    GdkRectangle  *area,
4675                    GtkWidget     *widget,
4676                    const gchar   *detail,
4677                    gint        x,
4678                    gint        y,
4679                    gint        width,
4680                    gint        height)
4681 {
4682   g_return_if_fail (GTK_IS_STYLE (style));
4683   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
4684   
4685   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4686 }
4687
4688 void
4689 gtk_paint_string (GtkStyle      *style,
4690                   GdkWindow     *window,
4691                   GtkStateType   state_type,
4692                   GdkRectangle  *area,
4693                   GtkWidget     *widget,
4694                   const gchar   *detail,
4695                   gint           x,
4696                   gint           y,
4697                   const gchar   *string)
4698 {
4699   g_return_if_fail (GTK_IS_STYLE (style));
4700   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
4701   
4702   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string);
4703 }
4704
4705 void
4706 gtk_paint_box (GtkStyle      *style,
4707                GdkWindow     *window,
4708                GtkStateType   state_type,
4709                GtkShadowType  shadow_type,
4710                GdkRectangle  *area,
4711                GtkWidget     *widget,
4712                const gchar   *detail,
4713                gint           x,
4714                gint           y,
4715                gint           width,
4716                gint           height)
4717 {
4718   g_return_if_fail (GTK_IS_STYLE (style));
4719   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
4720   
4721   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4722 }
4723
4724 void
4725 gtk_paint_flat_box (GtkStyle      *style,
4726                     GdkWindow     *window,
4727                     GtkStateType   state_type,
4728                     GtkShadowType  shadow_type,
4729                     GdkRectangle  *area,
4730                     GtkWidget     *widget,
4731                     const gchar   *detail,
4732                     gint           x,
4733                     gint           y,
4734                     gint           width,
4735                     gint           height)
4736 {
4737   g_return_if_fail (GTK_IS_STYLE (style));
4738   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
4739   
4740   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4741 }
4742
4743 void
4744 gtk_paint_check (GtkStyle      *style,
4745                  GdkWindow     *window,
4746                  GtkStateType   state_type,
4747                  GtkShadowType  shadow_type,
4748                  GdkRectangle  *area,
4749                  GtkWidget     *widget,
4750                  const gchar   *detail,
4751                  gint           x,
4752                  gint           y,
4753                  gint           width,
4754                  gint           height)
4755 {
4756   g_return_if_fail (GTK_IS_STYLE (style));
4757   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
4758   
4759   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4760 }
4761
4762 void
4763 gtk_paint_option (GtkStyle      *style,
4764                   GdkWindow     *window,
4765                   GtkStateType   state_type,
4766                   GtkShadowType  shadow_type,
4767                   GdkRectangle  *area,
4768                   GtkWidget     *widget,
4769                   const gchar   *detail,
4770                   gint           x,
4771                   gint           y,
4772                   gint           width,
4773                   gint           height)
4774 {
4775   g_return_if_fail (GTK_IS_STYLE (style));
4776   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
4777   
4778   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4779 }
4780
4781 void
4782 gtk_paint_tab (GtkStyle      *style,
4783                GdkWindow     *window,
4784                GtkStateType   state_type,
4785                GtkShadowType  shadow_type,
4786                GdkRectangle  *area,
4787                GtkWidget     *widget,
4788                const gchar   *detail,
4789                gint           x,
4790                gint           y,
4791                gint           width,
4792                gint           height)
4793 {
4794   g_return_if_fail (GTK_IS_STYLE (style));
4795   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
4796   
4797   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4798 }
4799
4800 void
4801 gtk_paint_shadow_gap (GtkStyle       *style,
4802                       GdkWindow      *window,
4803                       GtkStateType    state_type,
4804                       GtkShadowType   shadow_type,
4805                       GdkRectangle   *area,
4806                       GtkWidget      *widget,
4807                       gchar          *detail,
4808                       gint            x,
4809                       gint            y,
4810                       gint            width,
4811                       gint            height,
4812                       GtkPositionType gap_side,
4813                       gint            gap_x,
4814                       gint            gap_width)
4815 {
4816   g_return_if_fail (GTK_IS_STYLE (style));
4817   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
4818   
4819   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);
4820 }
4821
4822
4823 void
4824 gtk_paint_box_gap (GtkStyle       *style,
4825                    GdkWindow      *window,
4826                    GtkStateType    state_type,
4827                    GtkShadowType   shadow_type,
4828                    GdkRectangle   *area,
4829                    GtkWidget      *widget,
4830                    gchar          *detail,
4831                    gint            x,
4832                    gint            y,
4833                    gint            width,
4834                    gint            height,
4835                    GtkPositionType gap_side,
4836                    gint            gap_x,
4837                    gint            gap_width)
4838 {
4839   g_return_if_fail (GTK_IS_STYLE (style));
4840   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
4841   
4842   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);
4843 }
4844
4845 void
4846 gtk_paint_extension (GtkStyle       *style,
4847                      GdkWindow      *window,
4848                      GtkStateType    state_type,
4849                      GtkShadowType   shadow_type,
4850                      GdkRectangle   *area,
4851                      GtkWidget      *widget,
4852                      gchar          *detail,
4853                      gint            x,
4854                      gint            y,
4855                      gint            width,
4856                      gint            height,
4857                      GtkPositionType gap_side)
4858 {
4859   g_return_if_fail (GTK_IS_STYLE (style));
4860   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
4861   
4862   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side);
4863 }
4864
4865 void
4866 gtk_paint_focus (GtkStyle      *style,
4867                  GdkWindow     *window,
4868                  GdkRectangle  *area,
4869                  GtkWidget     *widget,
4870                  const gchar   *detail,
4871                  gint           x,
4872                  gint           y,
4873                  gint           width,
4874                  gint           height)
4875 {
4876   g_return_if_fail (GTK_IS_STYLE (style));
4877   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
4878   
4879   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, area, widget, detail, x, y, width, height);
4880 }
4881
4882 void
4883 gtk_paint_slider (GtkStyle      *style,
4884                   GdkWindow     *window,
4885                   GtkStateType   state_type,
4886                   GtkShadowType  shadow_type,
4887                   GdkRectangle  *area,
4888                   GtkWidget     *widget,
4889                   const gchar   *detail,
4890                   gint           x,
4891                   gint           y,
4892                   gint           width,
4893                   gint           height,
4894                   GtkOrientation orientation)
4895 {
4896   g_return_if_fail (GTK_IS_STYLE (style));
4897   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
4898   
4899   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
4900 }
4901
4902 void
4903 gtk_paint_handle (GtkStyle      *style,
4904                   GdkWindow     *window,
4905                   GtkStateType   state_type,
4906                   GtkShadowType  shadow_type,
4907                   GdkRectangle  *area,
4908                   GtkWidget     *widget,
4909                   const gchar   *detail,
4910                   gint           x,
4911                   gint           y,
4912                   gint           width,
4913                   gint           height,
4914                   GtkOrientation orientation)
4915 {
4916   g_return_if_fail (GTK_IS_STYLE (style));
4917   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
4918   
4919   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
4920 }
4921
4922 void
4923 gtk_paint_expander (GtkStyle        *style,
4924                     GdkWindow       *window,
4925                     GtkStateType     state_type,
4926                     GdkRectangle    *area,
4927                     GtkWidget       *widget,
4928                     const gchar     *detail,
4929                     gint             x,
4930                     gint             y,
4931                     GtkExpanderStyle expander_style)
4932 {
4933   g_return_if_fail (GTK_IS_STYLE (style));
4934   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
4935   
4936   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type, area,
4937                                               widget, detail, x, y, expander_style);
4938 }
4939
4940 void
4941 gtk_paint_layout (GtkStyle        *style,
4942                   GdkWindow       *window,
4943                   GtkStateType     state_type,
4944                   gboolean         use_text,
4945                   GdkRectangle    *area,
4946                   GtkWidget       *widget,
4947                   const gchar     *detail,
4948                   gint             x,
4949                   gint             y,
4950                   PangoLayout     *layout)
4951 {
4952   g_return_if_fail (GTK_IS_STYLE (style));
4953   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
4954   
4955   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text, area,
4956                                             widget, detail, x, y, layout);
4957 }
4958
4959 void
4960 gtk_paint_resize_grip (GtkStyle      *style,
4961                        GdkWindow     *window,
4962                        GtkStateType   state_type,
4963                        GdkRectangle  *area,
4964                        GtkWidget     *widget,
4965                        const gchar   *detail,
4966                        GdkWindowEdge  edge,
4967                        gint           x,
4968                        gint           y,
4969                        gint           width,
4970                        gint           height)
4971
4972 {
4973   g_return_if_fail (GTK_IS_STYLE (style));
4974   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
4975
4976   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
4977                                                  area, widget, detail,
4978                                                  edge, x, y, width, height);
4979 }
4980
4981 GtkBorder *
4982 gtk_border_copy (const GtkBorder *border)
4983 {
4984   return (GtkBorder *)g_memdup (border, sizeof (GtkBorder));
4985 }
4986
4987 void
4988 gtk_border_free (GtkBorder *border)
4989 {
4990   g_free (border);
4991 }
4992