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