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