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