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