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