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