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