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