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