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