]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
gtk/gtkstyle.c gtk/gtkcolorsel.c gtk/gtkhsv.c gtk/gtkiconview.c Update to
[~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_drawable_create_cairo_context (window);
2904   gdk_cairo_set_source_color (cr, color);
2905   
2906   if (area)
2907     {
2908       cairo_save (cr);
2909       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
2910       cairo_clip (cr);
2911       cairo_new_path (cr);
2912     }
2913     
2914   if (arrow_type == GTK_ARROW_DOWN)
2915     {
2916       cairo_move_to (cr, x,              y);
2917       cairo_line_to (cr, x + width,      y);
2918       cairo_line_to (cr, x + width / 2., y + height);
2919     }
2920   else if (arrow_type == GTK_ARROW_UP)
2921     {
2922       cairo_move_to (cr, x,              y + height);
2923       cairo_line_to (cr, x + width / 2., y);
2924       cairo_line_to (cr, x + width,      y + height);
2925     }
2926   else if (arrow_type == GTK_ARROW_LEFT)
2927     {
2928       cairo_move_to (cr, x + width,      y);
2929       cairo_line_to (cr, x + width,      y + height);
2930       cairo_line_to (cr, x,              y + height / 2.);
2931     }
2932   else if (arrow_type == GTK_ARROW_RIGHT)
2933     {
2934       cairo_move_to (cr, x,              y);
2935       cairo_line_to (cr, x + width,      y + height / 2.);
2936       cairo_line_to (cr, x,              y + height);
2937     }
2938
2939   cairo_close_path (cr);
2940   cairo_fill (cr);
2941
2942   if (area)
2943     cairo_restore (cr);
2944
2945   cairo_destroy (cr);
2946 }
2947
2948 static void
2949 calculate_arrow_geometry (GtkArrowType  arrow_type,
2950                           gint         *x,
2951                           gint         *y,
2952                           gint         *width,
2953                           gint         *height)
2954 {
2955   gint w = *width;
2956   gint h = *height;
2957   
2958   switch (arrow_type)
2959     {
2960     case GTK_ARROW_UP:
2961     case GTK_ARROW_DOWN:
2962       w += (w % 2) - 1;
2963       h = (w / 2 + 1);
2964       
2965       if (h > *height)
2966         {
2967           h = *height;
2968           w = 2 * h - 1;
2969         }
2970       
2971       if (arrow_type == GTK_ARROW_DOWN)
2972         {
2973           if (*height % 2 == 1 || h % 2 == 0)
2974             *height += 1;
2975         }
2976       else
2977         {
2978           if (*height % 2 == 0 || h % 2 == 0)
2979             *height -= 1;
2980         }
2981       break;
2982
2983     case GTK_ARROW_RIGHT:
2984     case GTK_ARROW_LEFT:
2985       h += (h % 2) - 1;
2986       w = (h / 2 + 1);
2987       
2988       if (w > *width)
2989         {
2990           w = *width;
2991           h = 2 * w - 1;
2992         }
2993       
2994       if (arrow_type == GTK_ARROW_RIGHT)
2995         {
2996           if (*width % 2 == 1 || w % 2 == 0)
2997             *width += 1;
2998         }
2999       else
3000         {
3001           if (*width % 2 == 0 || w % 2 == 0)
3002             *width -= 1;
3003         }
3004       break;
3005       
3006     default:
3007       /* should not be reached */
3008       break;
3009     }
3010
3011   *x += (*width - w) / 2;
3012   *y += (*height - h) / 2;
3013   *height = h;
3014   *width = w;
3015 }
3016
3017 static void
3018 gtk_default_draw_arrow (GtkStyle      *style,
3019                         GdkWindow     *window,
3020                         GtkStateType   state,
3021                         GtkShadowType  shadow,
3022                         GdkRectangle  *area,
3023                         GtkWidget     *widget,
3024                         const gchar   *detail,
3025                         GtkArrowType   arrow_type,
3026                         gboolean       fill,
3027                         gint           x,
3028                         gint           y,
3029                         gint           width,
3030                         gint           height)
3031 {
3032   gint original_width, original_x;
3033   
3034   sanitize_size (window, &width, &height);
3035
3036   original_width = width;
3037   original_x = x;
3038
3039   calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
3040
3041   if (detail && strcmp (detail, "menu_scroll_arrow_up") == 0)
3042     y++;
3043
3044   if (state == GTK_STATE_INSENSITIVE)
3045     draw_arrow (window, &style->white, area, arrow_type,
3046                 x + 1, y + 1, width, height);
3047   draw_arrow (window, &style->fg[state], area, arrow_type,
3048               x, y, width, height);
3049 }
3050
3051 static void
3052 gtk_default_draw_diamond (GtkStyle      *style,
3053                           GdkWindow     *window,
3054                           GtkStateType   state_type,
3055                           GtkShadowType  shadow_type,
3056                           GdkRectangle  *area,
3057                           GtkWidget     *widget,
3058                           const gchar   *detail,
3059                           gint           x,
3060                           gint           y,
3061                           gint           width,
3062                           gint           height)
3063 {
3064   gint half_width;
3065   gint half_height;
3066   GdkGC *outer_nw = NULL;
3067   GdkGC *outer_ne = NULL;
3068   GdkGC *outer_sw = NULL;
3069   GdkGC *outer_se = NULL;
3070   GdkGC *middle_nw = NULL;
3071   GdkGC *middle_ne = NULL;
3072   GdkGC *middle_sw = NULL;
3073   GdkGC *middle_se = NULL;
3074   GdkGC *inner_nw = NULL;
3075   GdkGC *inner_ne = NULL;
3076   GdkGC *inner_sw = NULL;
3077   GdkGC *inner_se = NULL;
3078   
3079   g_return_if_fail (GTK_IS_STYLE (style));
3080   g_return_if_fail (window != NULL);
3081   
3082   sanitize_size (window, &width, &height);
3083   
3084   half_width = width / 2;
3085   half_height = height / 2;
3086   
3087   if (area)
3088     {
3089       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3090       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
3091       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3092       gdk_gc_set_clip_rectangle (style->black_gc, area);
3093     }
3094   
3095   switch (shadow_type)
3096     {
3097     case GTK_SHADOW_IN:
3098       inner_sw = inner_se = style->bg_gc[state_type];
3099       middle_sw = middle_se = style->light_gc[state_type];
3100       outer_sw = outer_se = style->light_gc[state_type];
3101       inner_nw = inner_ne = style->black_gc;
3102       middle_nw = middle_ne = style->dark_gc[state_type];
3103       outer_nw = outer_ne = style->dark_gc[state_type];
3104       break;
3105           
3106     case GTK_SHADOW_OUT:
3107       inner_sw = inner_se = style->dark_gc[state_type];
3108       middle_sw = middle_se = style->dark_gc[state_type];
3109       outer_sw = outer_se = style->black_gc;
3110       inner_nw = inner_ne = style->bg_gc[state_type];
3111       middle_nw = middle_ne = style->light_gc[state_type];
3112       outer_nw = outer_ne = style->light_gc[state_type];
3113       break;
3114
3115     case GTK_SHADOW_ETCHED_IN:
3116       inner_sw = inner_se = style->bg_gc[state_type];
3117       middle_sw = middle_se = style->dark_gc[state_type];
3118       outer_sw = outer_se = style->light_gc[state_type];
3119       inner_nw = inner_ne = style->bg_gc[state_type];
3120       middle_nw = middle_ne = style->light_gc[state_type];
3121       outer_nw = outer_ne = style->dark_gc[state_type];
3122       break;
3123
3124     case GTK_SHADOW_ETCHED_OUT:
3125       inner_sw = inner_se = style->bg_gc[state_type];
3126       middle_sw = middle_se = style->light_gc[state_type];
3127       outer_sw = outer_se = style->dark_gc[state_type];
3128       inner_nw = inner_ne = style->bg_gc[state_type];
3129       middle_nw = middle_ne = style->dark_gc[state_type];
3130       outer_nw = outer_ne = style->light_gc[state_type];
3131       break;
3132       
3133     default:
3134
3135       break;
3136     }
3137
3138   if (inner_sw)
3139     {
3140       gdk_draw_line (window, inner_sw,
3141                      x + 2, y + half_height,
3142                      x + half_width, y + height - 2);
3143       gdk_draw_line (window, inner_se,
3144                      x + half_width, y + height - 2,
3145                      x + width - 2, y + half_height);
3146       gdk_draw_line (window, middle_sw,
3147                      x + 1, y + half_height,
3148                      x + half_width, y + height - 1);
3149       gdk_draw_line (window, middle_se,
3150                      x + half_width, y + height - 1,
3151                      x + width - 1, y + half_height);
3152       gdk_draw_line (window, outer_sw,
3153                      x, y + half_height,
3154                      x + half_width, y + height);
3155       gdk_draw_line (window, outer_se,
3156                      x + half_width, y + height,
3157                      x + width, y + half_height);
3158   
3159       gdk_draw_line (window, inner_nw,
3160                      x + 2, y + half_height,
3161                      x + half_width, y + 2);
3162       gdk_draw_line (window, inner_ne,
3163                      x + half_width, y + 2,
3164                      x + width - 2, y + half_height);
3165       gdk_draw_line (window, middle_nw,
3166                      x + 1, y + half_height,
3167                      x + half_width, y + 1);
3168       gdk_draw_line (window, middle_ne,
3169                      x + half_width, y + 1,
3170                      x + width - 1, y + half_height);
3171       gdk_draw_line (window, outer_nw,
3172                      x, y + half_height,
3173                      x + half_width, y);
3174       gdk_draw_line (window, outer_ne,
3175                      x + half_width, y,
3176                      x + width, y + half_height);
3177     }
3178   
3179   if (area)
3180     {
3181       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3182       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
3183       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3184       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
3185     }
3186 }
3187
3188 static void
3189 gtk_default_draw_string (GtkStyle      *style,
3190                          GdkWindow     *window,
3191                          GtkStateType   state_type,
3192                          GdkRectangle  *area,
3193                          GtkWidget     *widget,
3194                          const gchar   *detail,
3195                          gint           x,
3196                          gint           y,
3197                          const gchar   *string)
3198 {
3199   GdkDisplay *display;
3200   
3201   g_return_if_fail (GTK_IS_STYLE (style));
3202   g_return_if_fail (window != NULL);
3203   
3204   display = gdk_drawable_get_display (window);
3205   
3206   if (area)
3207     {
3208       gdk_gc_set_clip_rectangle (style->white_gc, area);
3209       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area);
3210     }
3211
3212   if (state_type == GTK_STATE_INSENSITIVE)
3213     gdk_draw_string (window,
3214                      gtk_style_get_font_internal (style),
3215                      style->white_gc, x + 1, y + 1, string);
3216
3217   gdk_draw_string (window,
3218                    gtk_style_get_font_internal (style),
3219                    style->fg_gc[state_type], x, y, string);
3220
3221   if (area)
3222     {
3223       gdk_gc_set_clip_rectangle (style->white_gc, NULL);
3224       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL);
3225     }
3226 }
3227
3228 static void
3229 option_menu_get_props (GtkWidget      *widget,
3230                        GtkRequisition *indicator_size,
3231                        GtkBorder      *indicator_spacing)
3232 {
3233   GtkRequisition *tmp_size = NULL;
3234   GtkBorder *tmp_spacing = NULL;
3235   
3236   if (widget)
3237     gtk_widget_style_get (widget, 
3238                           "indicator-size", &tmp_size,
3239                           "indicator-spacing", &tmp_spacing,
3240                           NULL);
3241
3242   if (tmp_size)
3243     {
3244       *indicator_size = *tmp_size;
3245       g_free (tmp_size);
3246     }
3247   else
3248     *indicator_size = default_option_indicator_size;
3249
3250   if (tmp_spacing)
3251     {
3252       *indicator_spacing = *tmp_spacing;
3253       g_free (tmp_spacing);
3254     }
3255   else
3256     *indicator_spacing = default_option_indicator_spacing;
3257 }
3258
3259 static void 
3260 gtk_default_draw_box (GtkStyle      *style,
3261                       GdkWindow     *window,
3262                       GtkStateType   state_type,
3263                       GtkShadowType  shadow_type,
3264                       GdkRectangle  *area,
3265                       GtkWidget     *widget,
3266                       const gchar   *detail,
3267                       gint           x,
3268                       gint           y,
3269                       gint           width,
3270                       gint           height)
3271 {
3272   gboolean is_spinbutton_box = FALSE;
3273   
3274   g_return_if_fail (GTK_IS_STYLE (style));
3275   g_return_if_fail (window != NULL);
3276   
3277   sanitize_size (window, &width, &height);
3278
3279   if (widget && GTK_IS_SPIN_BUTTON (widget) && detail)
3280     {
3281       if (strcmp (detail, "spinbutton_up") == 0)
3282         {
3283           y += 2;
3284           width -= 3;
3285           height -= 2;
3286
3287           if (get_direction (widget) == GTK_TEXT_DIR_RTL)
3288             x += 2;
3289           else
3290             x += 1;
3291
3292           is_spinbutton_box = TRUE;
3293         }
3294       else if (strcmp (detail, "spinbutton_down") == 0)
3295         {
3296           width -= 3;
3297           height -= 2;
3298
3299           if (get_direction (widget) == GTK_TEXT_DIR_RTL)
3300             x += 2;
3301           else
3302             x += 1;
3303
3304           is_spinbutton_box = TRUE;
3305         }
3306     }
3307   
3308   if (!style->bg_pixmap[state_type] || 
3309       GDK_IS_PIXMAP (window))
3310     {
3311       GdkGC *gc = style->bg_gc[state_type];
3312       
3313       if (state_type == GTK_STATE_SELECTED && detail && strcmp (detail, "paned") == 0)
3314         {
3315           if (widget && !GTK_WIDGET_HAS_FOCUS (widget))
3316             gc = style->base_gc[GTK_STATE_ACTIVE];
3317         }
3318
3319       if (area)
3320         gdk_gc_set_clip_rectangle (gc, area);
3321
3322       gdk_draw_rectangle (window, gc, TRUE,
3323                           x, y, width, height);
3324       if (area)
3325         gdk_gc_set_clip_rectangle (gc, NULL);
3326     }
3327   else
3328     gtk_style_apply_default_background (style, window,
3329                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3330                                         state_type, area, x, y, width, height);
3331
3332   if (is_spinbutton_box)
3333     {
3334       GdkGC *upper_gc;
3335       GdkGC *lower_gc;
3336       
3337       lower_gc = style->dark_gc[state_type];
3338       if (shadow_type == GTK_SHADOW_OUT)
3339         upper_gc = style->light_gc[state_type];
3340       else
3341         upper_gc = style->dark_gc[state_type];
3342
3343       if (area)
3344         {
3345           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3346           gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3347         }
3348       
3349       gdk_draw_line (window, upper_gc, x, y, x + width - 1, y);
3350       gdk_draw_line (window, lower_gc, x, y + height - 1, x + width - 1, y + height - 1);
3351
3352       if (area)
3353         {
3354           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3355           gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3356         }
3357       return;
3358     }
3359
3360   gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
3361                     x, y, width, height);
3362
3363   if (detail && strcmp (detail, "optionmenu") == 0)
3364     {
3365       GtkRequisition indicator_size;
3366       GtkBorder indicator_spacing;
3367       gint vline_x;
3368
3369       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3370
3371       sanitize_size (window, &width, &height);
3372
3373       if (get_direction (widget) == GTK_TEXT_DIR_RTL)
3374         vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
3375       else 
3376         vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
3377
3378       gtk_paint_vline (style, window, state_type, area, widget,
3379                        detail,
3380                        y + style->ythickness + 1,
3381                        y + height - style->ythickness - 3,
3382                        vline_x);
3383     }
3384 }
3385
3386 static GdkGC*
3387 get_darkened_gc (GdkWindow *window,
3388                  GdkColor  *color,
3389                  gint       darken_count)
3390 {
3391   GdkColor src = *color;
3392   GdkColor shaded = *color;
3393   GdkGC *gc;
3394   
3395   gc = gdk_gc_new (window);
3396
3397   while (darken_count)
3398     {
3399       gtk_style_shade (&src, &shaded, 0.93);
3400       src = shaded;
3401       --darken_count;
3402     }
3403    
3404   gdk_gc_set_rgb_fg_color (gc, &shaded);
3405
3406   return gc;
3407 }
3408
3409 static void 
3410 gtk_default_draw_flat_box (GtkStyle      *style,
3411                            GdkWindow     *window,
3412                            GtkStateType   state_type,
3413                            GtkShadowType  shadow_type,
3414                            GdkRectangle  *area,
3415                            GtkWidget     *widget,
3416                            const gchar   *detail,
3417                            gint           x,
3418                            gint           y,
3419                            gint           width,
3420                            gint           height)
3421 {
3422   GdkGC *gc1;
3423   GdkGC *freeme = NULL;
3424   
3425   g_return_if_fail (GTK_IS_STYLE (style));
3426   g_return_if_fail (window != NULL);
3427   
3428   sanitize_size (window, &width, &height);
3429   
3430   if (detail)
3431     {
3432       if (state_type == GTK_STATE_SELECTED)
3433         {
3434           if (!strcmp ("text", detail))
3435             gc1 = style->bg_gc[GTK_STATE_SELECTED];
3436           else if (!strncmp ("cell_even", detail, strlen ("cell_even")) ||
3437                    !strncmp ("cell_odd", detail, strlen ("cell_odd")))
3438             {
3439               /* This has to be really broken; alex made me do it. -jrb */
3440               if (GTK_WIDGET_HAS_FOCUS (widget))
3441                 gc1 = style->base_gc[state_type];
3442               else 
3443                 gc1 = style->base_gc[GTK_STATE_ACTIVE];
3444             }
3445           else
3446             {
3447               gc1 = style->bg_gc[state_type];
3448             }
3449         }
3450       else
3451         {
3452           if (!strcmp ("viewportbin", detail))
3453             gc1 = style->bg_gc[GTK_STATE_NORMAL];
3454           else if (!strcmp ("entry_bg", detail))
3455             gc1 = style->base_gc[state_type];
3456
3457           /* For trees: even rows are base color, odd rows are a shade of
3458            * the base color, the sort column is a shade of the original color
3459            * for that row.
3460            */
3461
3462           else if (!strcmp ("cell_even", detail) ||
3463                    !strcmp ("cell_odd", detail) ||
3464                    !strcmp ("cell_even_ruled", detail))
3465             {
3466               GdkColor *color = NULL;
3467
3468               gtk_widget_style_get (widget,
3469                                     "even-row-color", &color,
3470                                     NULL);
3471
3472               if (color)
3473                 {
3474                   freeme = get_darkened_gc (window, color, 0);
3475                   gc1 = freeme;
3476
3477                   gdk_color_free (color);
3478                 }
3479               else
3480                 gc1 = style->base_gc[state_type];
3481             }
3482           else if (!strcmp ("cell_odd_ruled", detail))
3483             {
3484               GdkColor *color;
3485
3486               gtk_widget_style_get (widget,
3487                                     "odd-row-color", &color,
3488                                     NULL);
3489
3490               if (color)
3491                 {
3492                   freeme = get_darkened_gc (window, color, 0);
3493                   gc1 = freeme;
3494
3495                   gdk_color_free (color);
3496                 }
3497               else
3498                 {
3499                   gtk_widget_style_get (widget,
3500                                         "even-row-color", &color,
3501                                         NULL);
3502
3503                   if (color)
3504                     {
3505                       freeme = get_darkened_gc (window, color, 1);
3506                       gdk_color_free (color);
3507                     }
3508                   else
3509                     freeme = get_darkened_gc (window, &style->base[state_type], 1);
3510                   gc1 = freeme;
3511                 }
3512             }
3513           else if (!strcmp ("cell_even_sorted", detail) ||
3514                    !strcmp ("cell_odd_sorted", detail) ||
3515                    !strcmp ("cell_even_ruled_sorted", detail))
3516             {
3517               GdkColor *color = NULL;
3518
3519               if (!strcmp ("cell_odd_sorted", detail))
3520                 gtk_widget_style_get (widget,
3521                                       "odd-row-color", &color,
3522                                       NULL);
3523               else
3524                 gtk_widget_style_get (widget,
3525                                       "even-row-color", &color,
3526                                       NULL);
3527
3528               if (color)
3529                 {
3530                   freeme = get_darkened_gc (window, color, 1);
3531                   gc1 = freeme;
3532
3533                   gdk_color_free (color);
3534                 }
3535               else
3536                 {
3537                   freeme = get_darkened_gc (window, &style->base[state_type], 1);
3538                   gc1 = freeme;
3539                 }
3540             }
3541           else if (!strcmp ("cell_odd_ruled_sorted", detail))
3542             {
3543               GdkColor *color = NULL;
3544
3545               gtk_widget_style_get (widget,
3546                                     "odd-row-color", &color,
3547                                     NULL);
3548
3549               if (color)
3550                 {
3551                   freeme = get_darkened_gc (window, color, 1);
3552                   gc1 = freeme;
3553
3554                   gdk_color_free (color);
3555                 }
3556               else
3557                 {
3558                   gtk_widget_style_get (widget,
3559                                         "even-row-color", &color,
3560                                         NULL);
3561
3562                   if (color)
3563                     {
3564                       freeme = get_darkened_gc (window, color, 2);
3565                       gdk_color_free (color);
3566                     }
3567                   else
3568                     freeme = get_darkened_gc (window, &style->base[state_type], 2);
3569                   gc1 = freeme;
3570                 }
3571             }
3572           else
3573             gc1 = style->bg_gc[state_type];
3574         }
3575     }
3576   else
3577     gc1 = style->bg_gc[state_type];
3578   
3579   if (!style->bg_pixmap[state_type] || gc1 != style->bg_gc[state_type] ||
3580       GDK_IS_PIXMAP (window))
3581     {
3582       if (area)
3583         gdk_gc_set_clip_rectangle (gc1, area);
3584
3585       gdk_draw_rectangle (window, gc1, TRUE,
3586                           x, y, width, height);
3587
3588       if (detail && !strcmp ("tooltip", detail))
3589         gdk_draw_rectangle (window, style->black_gc, FALSE,
3590                             x, y, width - 1, height - 1);
3591
3592       if (area)
3593         gdk_gc_set_clip_rectangle (gc1, NULL);
3594     }
3595   else
3596     gtk_style_apply_default_background (style, window,
3597                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3598                                         state_type, area, x, y, width, height);
3599
3600
3601   if (freeme)
3602     g_object_unref (freeme);
3603 }
3604
3605 static void 
3606 gtk_default_draw_check (GtkStyle      *style,
3607                         GdkWindow     *window,
3608                         GtkStateType   state_type,
3609                         GtkShadowType  shadow_type,
3610                         GdkRectangle  *area,
3611                         GtkWidget     *widget,
3612                         const gchar   *detail,
3613                         gint           x,
3614                         gint           y,
3615                         gint           width,
3616                         gint           height)
3617 {
3618   cairo_t *cr = gdk_drawable_create_cairo_context (window);
3619   enum { BUTTON, MENU, CELL } type = BUTTON;
3620   int exterior_size;
3621   int interior_size;
3622   int pad;
3623   
3624   if (detail)
3625     {
3626       if (strcmp (detail, "cellcheck") == 0)
3627         type = CELL;
3628       else if (strcmp (detail, "check") == 0)
3629         type = MENU;
3630     }
3631       
3632   if (area)
3633     {
3634       cairo_save (cr);
3635       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
3636       cairo_clip (cr);
3637       cairo_new_path (cr);
3638     }
3639   
3640   exterior_size = MIN (width, height);
3641   if (exterior_size % 2 == 0) /* Ensure odd */
3642     exterior_size -= -1;
3643
3644   pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
3645   interior_size = MAX (1, exterior_size - 2 * pad);
3646
3647   if (interior_size < 7)
3648     {
3649       interior_size = 7;
3650       pad = MAX (0, (exterior_size - interior_size) / 2);
3651     }
3652
3653   x -= (1 + exterior_size - width) / 2;
3654   y -= (1 + exterior_size - height) / 2;
3655
3656   switch (type)
3657     {
3658     case BUTTON:
3659     case CELL:
3660       if (type == BUTTON)
3661         gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3662       else
3663         gdk_cairo_set_source_color (cr, &style->text[state_type]);
3664         
3665       cairo_set_line_width (cr, 1.0);
3666       cairo_rectangle (cr, x + 0.5, y + 0.5, exterior_size - 1, exterior_size - 1);
3667       cairo_stroke (cr);
3668
3669       gdk_cairo_set_source_color (cr, &style->base[state_type]);
3670       cairo_rectangle (cr, x + 1, y + 1, exterior_size - 2, exterior_size - 2);
3671       cairo_fill (cr);
3672       break;
3673
3674     case MENU:
3675       break;
3676     }
3677       
3678   switch (type)
3679     {
3680     case BUTTON:
3681     case CELL:
3682       gdk_cairo_set_source_color (cr, &style->text[state_type]);
3683       break;
3684     case MENU:
3685       gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3686       break;
3687     }
3688
3689   if (shadow_type == GTK_SHADOW_IN)
3690     {
3691       cairo_translate (cr,
3692                        x + pad, y + pad);
3693       
3694       cairo_scale (cr, interior_size / 7., interior_size / 7.);
3695       
3696       cairo_move_to  (cr, 7.0, 0.0);
3697       cairo_line_to  (cr, 7.5, 1.0);
3698       cairo_curve_to (cr, 5.3, 2.0,
3699                       4.3, 4.0,
3700                       3.5, 7.0);
3701       cairo_curve_to (cr, 3.0, 5.7,
3702                       1.3, 4.7,
3703                       0.0, 4.7);
3704       cairo_line_to  (cr, 0.2, 3.5);
3705       cairo_curve_to (cr, 1.1, 3.5,
3706                       2.3, 4.3,
3707                       3.0, 5.0);
3708       cairo_curve_to (cr, 1.0, 3.9,
3709                       2.4, 4.1,
3710                       3.2, 4.9);
3711       cairo_curve_to (cr, 3.5, 3.1,
3712                       5.2, 2.0,
3713                       7.0, 0.0);
3714       
3715       cairo_fill (cr);
3716     }
3717   else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3718     {
3719       int line_thickness = MAX (1, (3 + interior_size * 2) / 7);
3720
3721       cairo_rectangle (cr,
3722                        x + pad,
3723                        y + pad + (1 + interior_size - line_thickness) / 2,
3724                        interior_size,
3725                        line_thickness);
3726       cairo_fill (cr);
3727     }
3728   
3729   if (area)
3730     cairo_restore (cr);
3731   
3732   cairo_destroy (cr);
3733 }
3734
3735 static void 
3736 gtk_default_draw_option (GtkStyle      *style,
3737                          GdkWindow     *window,
3738                          GtkStateType   state_type,
3739                          GtkShadowType  shadow_type,
3740                          GdkRectangle  *area,
3741                          GtkWidget     *widget,
3742                          const gchar   *detail,
3743                          gint           x,
3744                          gint           y,
3745                          gint           width,
3746                          gint           height)
3747 {
3748   cairo_t *cr = gdk_drawable_create_cairo_context (window);
3749   enum { BUTTON, MENU, CELL } type = BUTTON;
3750   int exterior_size;
3751   
3752   if (detail)
3753     {
3754       if (strcmp (detail, "radio") == 0)
3755         type = CELL;
3756       else if (strcmp (detail, "option") == 0)
3757         type = MENU;
3758     }
3759       
3760   if (area)
3761     {
3762       cairo_save (cr);
3763       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
3764       cairo_clip (cr);
3765       cairo_new_path (cr);
3766     }
3767   
3768   exterior_size = MIN (width, height);
3769   if (exterior_size % 2 == 0) /* Ensure odd */
3770     exterior_size -= -1;
3771   
3772   x -= (1 + exterior_size - width) / 2;
3773   y -= (1 + exterior_size - height) / 2;
3774
3775   switch (type)
3776     {
3777     case BUTTON:
3778     case CELL:
3779       gdk_cairo_set_source_color (cr, &style->base[state_type]);
3780       
3781       cairo_arc (cr,
3782                  x + exterior_size / 2.,
3783                  y + exterior_size / 2.,
3784                  (exterior_size - 1) / 2.,
3785                  0, 2 * G_PI);
3786
3787       cairo_save (cr);
3788       cairo_fill (cr);
3789       cairo_restore (cr);
3790
3791       if (type == BUTTON)
3792         gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3793       else
3794         gdk_cairo_set_source_color (cr, &style->text[state_type]);
3795         
3796       cairo_set_line_width (cr, 1.);
3797       cairo_stroke (cr);
3798       break;
3799
3800     case MENU:
3801       break;
3802     }
3803       
3804   switch (type)
3805     {
3806     case BUTTON:
3807       gdk_cairo_set_source_color (cr, &style->text[state_type]);
3808       break;
3809     case CELL:
3810       break;
3811     case MENU:
3812       gdk_cairo_set_source_color (cr, &style->fg[state_type]);
3813       break;
3814     }
3815
3816   if (shadow_type == GTK_SHADOW_IN)
3817     {
3818       int pad = style->xthickness + MAX (1, 2 * (exterior_size - 2 * style->xthickness) / 9);
3819       int interior_size = MAX (1, exterior_size - 2 * pad);
3820
3821       if (interior_size < 5)
3822         {
3823           interior_size = 7;
3824           pad = MAX (0, (exterior_size - interior_size) / 2);
3825         }
3826
3827       cairo_arc (cr,
3828                  x + pad + interior_size / 2.,
3829                  y + pad + interior_size / 2.,
3830                  interior_size / 2.,
3831                  0, 2 * G_PI);
3832       cairo_fill (cr);
3833     }
3834   else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3835     {
3836       int pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9);
3837       int interior_size = MAX (1, exterior_size - 2 * pad);
3838       int line_thickness;
3839
3840       if (interior_size < 7)
3841         {
3842           interior_size = 7;
3843           pad = MAX (0, (exterior_size - interior_size) / 2);
3844         }
3845
3846       line_thickness = MAX (1, (3 + interior_size * 2) / 7);
3847
3848       cairo_rectangle (cr,
3849                        x + pad,
3850                        y + pad + (interior_size - line_thickness) / 2.,
3851                        interior_size,
3852                        line_thickness);
3853       cairo_fill (cr);
3854     }
3855   
3856   if (area)
3857     cairo_restore (cr);
3858   
3859   cairo_destroy (cr);
3860 }
3861
3862 static void
3863 gtk_default_draw_tab (GtkStyle      *style,
3864                       GdkWindow     *window,
3865                       GtkStateType   state_type,
3866                       GtkShadowType  shadow_type,
3867                       GdkRectangle  *area,
3868                       GtkWidget     *widget,
3869                       const gchar   *detail,
3870                       gint           x,
3871                       gint           y,
3872                       gint           width,
3873                       gint           height)
3874 {
3875 #define ARROW_SPACE 4
3876
3877   GtkRequisition indicator_size;
3878   GtkBorder indicator_spacing;
3879   gint arrow_height;
3880   
3881   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3882
3883   indicator_size.width += (indicator_size.width % 2) - 1;
3884   arrow_height = indicator_size.width / 2 + 1;
3885
3886   x += (width - indicator_size.width) / 2;
3887   y += (height - (2 * arrow_height + ARROW_SPACE)) / 2;
3888
3889   if (state_type == GTK_STATE_INSENSITIVE)
3890     {
3891       draw_arrow (window, &style->white, area,
3892                   GTK_ARROW_UP, x + 1, y + 1,
3893                   indicator_size.width, arrow_height);
3894       
3895       draw_arrow (window, &style->white, area,
3896                   GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1,
3897                   indicator_size.width, arrow_height);
3898     }
3899   
3900   draw_arrow (window, &style->fg[state_type], area,
3901               GTK_ARROW_UP, x, y,
3902               indicator_size.width, arrow_height);
3903   
3904   
3905   draw_arrow (window, &style->fg[state_type], area,
3906               GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE,
3907               indicator_size.width, arrow_height);
3908 }
3909
3910 static void 
3911 gtk_default_draw_shadow_gap (GtkStyle       *style,
3912                              GdkWindow      *window,
3913                              GtkStateType    state_type,
3914                              GtkShadowType   shadow_type,
3915                              GdkRectangle   *area,
3916                              GtkWidget      *widget,
3917                              const gchar    *detail,
3918                              gint            x,
3919                              gint            y,
3920                              gint            width,
3921                              gint            height,
3922                              GtkPositionType gap_side,
3923                              gint            gap_x,
3924                              gint            gap_width)
3925 {
3926   GdkGC *gc1 = NULL;
3927   GdkGC *gc2 = NULL;
3928   GdkGC *gc3 = NULL;
3929   GdkGC *gc4 = NULL;
3930   
3931   g_return_if_fail (GTK_IS_STYLE (style));
3932   g_return_if_fail (window != NULL);
3933   
3934   sanitize_size (window, &width, &height);
3935   
3936   switch (shadow_type)
3937     {
3938     case GTK_SHADOW_NONE:
3939       return;
3940     case GTK_SHADOW_IN:
3941       gc1 = style->dark_gc[state_type];
3942       gc2 = style->black_gc;
3943       gc3 = style->bg_gc[state_type];
3944       gc4 = style->light_gc[state_type];
3945       break;
3946     case GTK_SHADOW_ETCHED_IN:
3947       gc1 = style->dark_gc[state_type];
3948       gc2 = style->light_gc[state_type];
3949       gc3 = style->dark_gc[state_type];
3950       gc4 = style->light_gc[state_type];
3951       break;
3952     case GTK_SHADOW_OUT:
3953       gc1 = style->light_gc[state_type];
3954       gc2 = style->bg_gc[state_type];
3955       gc3 = style->dark_gc[state_type];
3956       gc4 = style->black_gc;
3957       break;
3958     case GTK_SHADOW_ETCHED_OUT:
3959       gc1 = style->light_gc[state_type];
3960       gc2 = style->dark_gc[state_type];
3961       gc3 = style->light_gc[state_type];
3962       gc4 = style->dark_gc[state_type];
3963       break;
3964     }
3965   if (area)
3966     {
3967       gdk_gc_set_clip_rectangle (gc1, area);
3968       gdk_gc_set_clip_rectangle (gc2, area);
3969       gdk_gc_set_clip_rectangle (gc3, area);
3970       gdk_gc_set_clip_rectangle (gc4, area);
3971     }
3972   
3973   switch (shadow_type)
3974     {
3975     case GTK_SHADOW_NONE:
3976     case GTK_SHADOW_IN:
3977     case GTK_SHADOW_OUT:
3978     case GTK_SHADOW_ETCHED_IN:
3979     case GTK_SHADOW_ETCHED_OUT:
3980       switch (gap_side)
3981         {
3982         case GTK_POS_TOP:
3983           gdk_draw_line (window, gc1,
3984                          x, y, x, y + height - 1);
3985           gdk_draw_line (window, gc2,
3986                          x + 1, y, x + 1, y + height - 2);
3987           
3988           gdk_draw_line (window, gc3,
3989                          x + 1, y + height - 2, x + width - 2, y + height - 2);
3990           gdk_draw_line (window, gc3,
3991                          x + width - 2, y, x + width - 2, y + height - 2);
3992           gdk_draw_line (window, gc4,
3993                          x, y + height - 1, x + width - 1, y + height - 1);
3994           gdk_draw_line (window, gc4,
3995                          x + width - 1, y, x + width - 1, y + height - 1);
3996           if (gap_x > 0)
3997             {
3998               gdk_draw_line (window, gc1,
3999                              x, y, x + gap_x - 1, y);
4000               gdk_draw_line (window, gc2,
4001                              x + 1, y + 1, x + gap_x - 1, y + 1);
4002               gdk_draw_line (window, gc2,
4003                              x + gap_x, y, x + gap_x, y);
4004             }
4005           if ((width - (gap_x + gap_width)) > 0)
4006             {
4007               gdk_draw_line (window, gc1,
4008                              x + gap_x + gap_width, y, x + width - 2, y);
4009               gdk_draw_line (window, gc2,
4010                              x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
4011               gdk_draw_line (window, gc2,
4012                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
4013             }
4014           break;
4015         case GTK_POS_BOTTOM:
4016           gdk_draw_line (window, gc1,
4017                          x, y, x + width - 1, y);
4018           gdk_draw_line (window, gc1,
4019                          x, y, x, y + height - 1);
4020           gdk_draw_line (window, gc2,
4021                          x + 1, y + 1, x + width - 2, y + 1);
4022           gdk_draw_line (window, gc2,
4023                          x + 1, y + 1, x + 1, y + height - 1);
4024           
4025           gdk_draw_line (window, gc3,
4026                          x + width - 2, y + 1, x + width - 2, y + height - 1);
4027           gdk_draw_line (window, gc4,
4028                          x + width - 1, y, x + width - 1, y + height - 1);
4029           if (gap_x > 0)
4030             {
4031               gdk_draw_line (window, gc4,
4032                              x, y + height - 1, x + gap_x - 1, y + height - 1);
4033               gdk_draw_line (window, gc3,
4034                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
4035               gdk_draw_line (window, gc3,
4036                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
4037             }
4038           if ((width - (gap_x + gap_width)) > 0)
4039             {
4040               gdk_draw_line (window, gc4,
4041                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
4042               gdk_draw_line (window, gc3,
4043                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
4044               gdk_draw_line (window, gc3,
4045                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
4046             }
4047           break;
4048         case GTK_POS_LEFT:
4049           gdk_draw_line (window, gc1,
4050                          x, y, x + width - 1, y);
4051           gdk_draw_line (window, gc2,
4052                          x, y + 1, x + width - 2, y + 1);
4053           
4054           gdk_draw_line (window, gc3,
4055                          x, y + height - 2, x + width - 2, y + height - 2);
4056           gdk_draw_line (window, gc3,
4057                          x + width - 2, y + 1, x + width - 2, y + height - 2);
4058           gdk_draw_line (window, gc4,
4059                          x, y + height - 1, x + width - 1, y + height - 1);
4060           gdk_draw_line (window, gc4,
4061                          x + width - 1, y, x + width - 1, y + height - 1);
4062           if (gap_x > 0)
4063             {
4064               gdk_draw_line (window, gc1,
4065                              x, y, x, y + gap_x - 1);
4066               gdk_draw_line (window, gc2,
4067                              x + 1, y + 1, x + 1, y + gap_x - 1);
4068               gdk_draw_line (window, gc2,
4069                              x, y + gap_x, x, y + gap_x);
4070             }
4071           if ((width - (gap_x + gap_width)) > 0)
4072             {
4073               gdk_draw_line (window, gc1,
4074                              x, y + gap_x + gap_width, x, y + height - 2);
4075               gdk_draw_line (window, gc2,
4076                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
4077               gdk_draw_line (window, gc2,
4078                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
4079             }
4080           break;
4081         case GTK_POS_RIGHT:
4082           gdk_draw_line (window, gc1,
4083                          x, y, x + width - 1, y);
4084           gdk_draw_line (window, gc1,
4085                          x, y, x, y + height - 1);
4086           gdk_draw_line (window, gc2,
4087                          x + 1, y + 1, x + width - 1, y + 1);
4088           gdk_draw_line (window, gc2,
4089                          x + 1, y + 1, x + 1, y + height - 2);
4090           
4091           gdk_draw_line (window, gc3,
4092                          x + 1, y + height - 2, x + width - 1, y + height - 2);
4093           gdk_draw_line (window, gc4,
4094                          x, y + height - 1, x + width - 1, y + height - 1);
4095           if (gap_x > 0)
4096             {
4097               gdk_draw_line (window, gc4,
4098                              x + width - 1, y, x + width - 1, y + gap_x - 1);
4099               gdk_draw_line (window, gc3,
4100                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
4101               gdk_draw_line (window, gc3,
4102                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
4103             }
4104           if ((width - (gap_x + gap_width)) > 0)
4105             {
4106               gdk_draw_line (window, gc4,
4107                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
4108               gdk_draw_line (window, gc3,
4109                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
4110               gdk_draw_line (window, gc3,
4111                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
4112             }
4113           break;
4114         }
4115     }
4116
4117   if (area)
4118     {
4119       gdk_gc_set_clip_rectangle (gc1, NULL);
4120       gdk_gc_set_clip_rectangle (gc2, NULL);
4121       gdk_gc_set_clip_rectangle (gc3, NULL);
4122       gdk_gc_set_clip_rectangle (gc4, NULL);
4123     }
4124 }
4125
4126 static void 
4127 gtk_default_draw_box_gap (GtkStyle       *style,
4128                           GdkWindow      *window,
4129                           GtkStateType    state_type,
4130                           GtkShadowType   shadow_type,
4131                           GdkRectangle   *area,
4132                           GtkWidget      *widget,
4133                           const gchar    *detail,
4134                           gint            x,
4135                           gint            y,
4136                           gint            width,
4137                           gint            height,
4138                           GtkPositionType gap_side,
4139                           gint            gap_x,
4140                           gint            gap_width)
4141 {
4142   GdkGC *gc1 = NULL;
4143   GdkGC *gc2 = NULL;
4144   GdkGC *gc3 = NULL;
4145   GdkGC *gc4 = NULL;
4146   
4147   g_return_if_fail (GTK_IS_STYLE (style));
4148   g_return_if_fail (window != NULL);
4149   
4150   gtk_style_apply_default_background (style, window,
4151                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4152                                       state_type, area, x, y, width, height);
4153   
4154   sanitize_size (window, &width, &height);
4155   
4156   switch (shadow_type)
4157     {
4158     case GTK_SHADOW_NONE:
4159       return;
4160     case GTK_SHADOW_IN:
4161       gc1 = style->dark_gc[state_type];
4162       gc2 = style->black_gc;
4163       gc3 = style->bg_gc[state_type];
4164       gc4 = style->light_gc[state_type];
4165       break;
4166     case GTK_SHADOW_ETCHED_IN:
4167       gc1 = style->dark_gc[state_type];
4168       gc2 = style->light_gc[state_type];
4169       gc3 = style->dark_gc[state_type];
4170       gc4 = style->light_gc[state_type];
4171       break;
4172     case GTK_SHADOW_OUT:
4173       gc1 = style->light_gc[state_type];
4174       gc2 = style->bg_gc[state_type];
4175       gc3 = style->dark_gc[state_type];
4176       gc4 = style->black_gc;
4177       break;
4178     case GTK_SHADOW_ETCHED_OUT:
4179       gc1 = style->light_gc[state_type];
4180       gc2 = style->dark_gc[state_type];
4181       gc3 = style->light_gc[state_type];
4182       gc4 = style->dark_gc[state_type];
4183       break;
4184     }
4185
4186   if (area)
4187     {
4188       gdk_gc_set_clip_rectangle (gc1, area);
4189       gdk_gc_set_clip_rectangle (gc2, area);
4190       gdk_gc_set_clip_rectangle (gc3, area);
4191       gdk_gc_set_clip_rectangle (gc4, area);
4192     }
4193   
4194   switch (shadow_type)
4195     {
4196     case GTK_SHADOW_NONE:
4197     case GTK_SHADOW_IN:
4198     case GTK_SHADOW_OUT:
4199     case GTK_SHADOW_ETCHED_IN:
4200     case GTK_SHADOW_ETCHED_OUT:
4201       switch (gap_side)
4202         {
4203         case GTK_POS_TOP:
4204           gdk_draw_line (window, gc1,
4205                          x, y, x, y + height - 1);
4206           gdk_draw_line (window, gc2,
4207                          x + 1, y, x + 1, y + height - 2);
4208           
4209           gdk_draw_line (window, gc3,
4210                          x + 1, y + height - 2, x + width - 2, y + height - 2);
4211           gdk_draw_line (window, gc3,
4212                          x + width - 2, y, x + width - 2, y + height - 2);
4213           gdk_draw_line (window, gc4,
4214                          x, y + height - 1, x + width - 1, y + height - 1);
4215           gdk_draw_line (window, gc4,
4216                          x + width - 1, y, x + width - 1, y + height - 1);
4217           if (gap_x > 0)
4218             {
4219               gdk_draw_line (window, gc1,
4220                              x, y, x + gap_x - 1, y);
4221               gdk_draw_line (window, gc2,
4222                              x + 1, y + 1, x + gap_x - 1, y + 1);
4223               gdk_draw_line (window, gc2,
4224                              x + gap_x, y, x + gap_x, y);
4225             }
4226           if ((width - (gap_x + gap_width)) > 0)
4227             {
4228               gdk_draw_line (window, gc1,
4229                              x + gap_x + gap_width, y, x + width - 2, y);
4230               gdk_draw_line (window, gc2,
4231                              x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
4232               gdk_draw_line (window, gc2,
4233                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
4234             }
4235           break;
4236         case  GTK_POS_BOTTOM:
4237           gdk_draw_line (window, gc1,
4238                          x, y, x + width - 1, y);
4239           gdk_draw_line (window, gc1,
4240                          x, y, x, y + height - 1);
4241           gdk_draw_line (window, gc2,
4242                          x + 1, y + 1, x + width - 2, y + 1);
4243           gdk_draw_line (window, gc2,
4244                          x + 1, y + 1, x + 1, y + height - 1);
4245           
4246           gdk_draw_line (window, gc3,
4247                          x + width - 2, y + 1, x + width - 2, y + height - 1);
4248           gdk_draw_line (window, gc4,
4249                          x + width - 1, y, x + width - 1, y + height - 1);
4250           if (gap_x > 0)
4251             {
4252               gdk_draw_line (window, gc4,
4253                              x, y + height - 1, x + gap_x - 1, y + height - 1);
4254               gdk_draw_line (window, gc3,
4255                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
4256               gdk_draw_line (window, gc3,
4257                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
4258             }
4259           if ((width - (gap_x + gap_width)) > 0)
4260             {
4261               gdk_draw_line (window, gc4,
4262                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
4263               gdk_draw_line (window, gc3,
4264                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
4265               gdk_draw_line (window, gc3,
4266                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
4267             }
4268           break;
4269         case GTK_POS_LEFT:
4270           gdk_draw_line (window, gc1,
4271                          x, y, x + width - 1, y);
4272           gdk_draw_line (window, gc2,
4273                          x, y + 1, x + width - 2, y + 1);
4274           
4275           gdk_draw_line (window, gc3,
4276                          x, y + height - 2, x + width - 2, y + height - 2);
4277           gdk_draw_line (window, gc3,
4278                          x + width - 2, y + 1, x + width - 2, y + height - 2);
4279           gdk_draw_line (window, gc4,
4280                          x, y + height - 1, x + width - 1, y + height - 1);
4281           gdk_draw_line (window, gc4,
4282                          x + width - 1, y, x + width - 1, y + height - 1);
4283           if (gap_x > 0)
4284             {
4285               gdk_draw_line (window, gc1,
4286                              x, y, x, y + gap_x - 1);
4287               gdk_draw_line (window, gc2,
4288                              x + 1, y + 1, x + 1, y + gap_x - 1);
4289               gdk_draw_line (window, gc2,
4290                              x, y + gap_x, x, y + gap_x);
4291             }
4292           if ((width - (gap_x + gap_width)) > 0)
4293             {
4294               gdk_draw_line (window, gc1,
4295                              x, y + gap_x + gap_width, x, y + height - 2);
4296               gdk_draw_line (window, gc2,
4297                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
4298               gdk_draw_line (window, gc2,
4299                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
4300             }
4301           break;
4302         case GTK_POS_RIGHT:
4303           gdk_draw_line (window, gc1,
4304                          x, y, x + width - 1, y);
4305           gdk_draw_line (window, gc1,
4306                          x, y, x, y + height - 1);
4307           gdk_draw_line (window, gc2,
4308                          x + 1, y + 1, x + width - 1, y + 1);
4309           gdk_draw_line (window, gc2,
4310                          x + 1, y + 1, x + 1, y + height - 2);
4311           
4312           gdk_draw_line (window, gc3,
4313                          x + 1, y + height - 2, x + width - 1, y + height - 2);
4314           gdk_draw_line (window, gc4,
4315                          x, y + height - 1, x + width - 1, y + height - 1);
4316           if (gap_x > 0)
4317             {
4318               gdk_draw_line (window, gc4,
4319                              x + width - 1, y, x + width - 1, y + gap_x - 1);
4320               gdk_draw_line (window, gc3,
4321                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
4322               gdk_draw_line (window, gc3,
4323                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
4324             }
4325           if ((width - (gap_x + gap_width)) > 0)
4326             {
4327               gdk_draw_line (window, gc4,
4328                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
4329               gdk_draw_line (window, gc3,
4330                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
4331               gdk_draw_line (window, gc3,
4332                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
4333             }
4334           break;
4335         }
4336     }
4337
4338   if (area)
4339     {
4340       gdk_gc_set_clip_rectangle (gc1, NULL);
4341       gdk_gc_set_clip_rectangle (gc2, NULL);
4342       gdk_gc_set_clip_rectangle (gc3, NULL);
4343       gdk_gc_set_clip_rectangle (gc4, NULL);
4344     }
4345 }
4346
4347 static void 
4348 gtk_default_draw_extension (GtkStyle       *style,
4349                             GdkWindow      *window,
4350                             GtkStateType    state_type,
4351                             GtkShadowType   shadow_type,
4352                             GdkRectangle   *area,
4353                             GtkWidget      *widget,
4354                             const gchar    *detail,
4355                             gint            x,
4356                             gint            y,
4357                             gint            width,
4358                             gint            height,
4359                             GtkPositionType gap_side)
4360 {
4361   GdkGC *gc1 = NULL;
4362   GdkGC *gc2 = NULL;
4363   GdkGC *gc3 = NULL;
4364   GdkGC *gc4 = NULL;
4365   
4366   g_return_if_fail (GTK_IS_STYLE (style));
4367   g_return_if_fail (window != NULL);
4368   
4369   gtk_style_apply_default_background (style, window,
4370                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4371                                       GTK_STATE_NORMAL, area, x, y, width, height);
4372   
4373   sanitize_size (window, &width, &height);
4374   
4375   switch (shadow_type)
4376     {
4377     case GTK_SHADOW_NONE:
4378       return;
4379     case GTK_SHADOW_IN:
4380       gc1 = style->dark_gc[state_type];
4381       gc2 = style->black_gc;
4382       gc3 = style->bg_gc[state_type];
4383       gc4 = style->light_gc[state_type];
4384       break;
4385     case GTK_SHADOW_ETCHED_IN:
4386       gc1 = style->dark_gc[state_type];
4387       gc2 = style->light_gc[state_type];
4388       gc3 = style->dark_gc[state_type];
4389       gc4 = style->light_gc[state_type];
4390       break;
4391     case GTK_SHADOW_OUT:
4392       gc1 = style->light_gc[state_type];
4393       gc2 = style->bg_gc[state_type];
4394       gc3 = style->dark_gc[state_type];
4395       gc4 = style->black_gc;
4396       break;
4397     case GTK_SHADOW_ETCHED_OUT:
4398       gc1 = style->light_gc[state_type];
4399       gc2 = style->dark_gc[state_type];
4400       gc3 = style->light_gc[state_type];
4401       gc4 = style->dark_gc[state_type];
4402       break;
4403     }
4404
4405   if (area)
4406     {
4407       gdk_gc_set_clip_rectangle (gc1, area);
4408       gdk_gc_set_clip_rectangle (gc2, area);
4409       gdk_gc_set_clip_rectangle (gc3, area);
4410       gdk_gc_set_clip_rectangle (gc4, area);
4411     }
4412
4413   switch (shadow_type)
4414     {
4415     case GTK_SHADOW_NONE:
4416     case GTK_SHADOW_IN:
4417     case GTK_SHADOW_OUT:
4418     case GTK_SHADOW_ETCHED_IN:
4419     case GTK_SHADOW_ETCHED_OUT:
4420       switch (gap_side)
4421         {
4422         case GTK_POS_TOP:
4423           gtk_style_apply_default_background (style, window,
4424                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4425                                               state_type, area,
4426                                               x + style->xthickness, 
4427                                               y, 
4428                                               width - (2 * style->xthickness), 
4429                                               height - (style->ythickness));
4430           gdk_draw_line (window, gc1,
4431                          x, y, x, y + height - 2);
4432           gdk_draw_line (window, gc2,
4433                          x + 1, y, x + 1, y + height - 2);
4434           
4435           gdk_draw_line (window, gc3,
4436                          x + 2, y + height - 2, x + width - 2, y + height - 2);
4437           gdk_draw_line (window, gc3,
4438                          x + width - 2, y, x + width - 2, y + height - 2);
4439           gdk_draw_line (window, gc4,
4440                          x + 1, y + height - 1, x + width - 2, y + height - 1);
4441           gdk_draw_line (window, gc4,
4442                          x + width - 1, y, x + width - 1, y + height - 2);
4443           break;
4444         case GTK_POS_BOTTOM:
4445           gtk_style_apply_default_background (style, window,
4446                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4447                                               state_type, area,
4448                                               x + style->xthickness, 
4449                                               y + style->ythickness, 
4450                                               width - (2 * style->xthickness), 
4451                                               height - (style->ythickness));
4452           gdk_draw_line (window, gc1,
4453                          x + 1, y, x + width - 2, y);
4454           gdk_draw_line (window, gc1,
4455                          x, y + 1, x, y + height - 1);
4456           gdk_draw_line (window, gc2,
4457                          x + 1, y + 1, x + width - 2, y + 1);
4458           gdk_draw_line (window, gc2,
4459                          x + 1, y + 1, x + 1, y + height - 1);
4460           
4461           gdk_draw_line (window, gc3,
4462                          x + width - 2, y + 2, x + width - 2, y + height - 1);
4463           gdk_draw_line (window, gc4,
4464                          x + width - 1, y + 1, x + width - 1, y + height - 1);
4465           break;
4466         case GTK_POS_LEFT:
4467           gtk_style_apply_default_background (style, window,
4468                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4469                                               state_type, area,
4470                                               x, 
4471                                               y + style->ythickness, 
4472                                               width - (style->xthickness), 
4473                                               height - (2 * style->ythickness));
4474           gdk_draw_line (window, gc1,
4475                          x, y, x + width - 2, y);
4476           gdk_draw_line (window, gc2,
4477                          x + 1, y + 1, x + width - 2, y + 1);
4478           
4479           gdk_draw_line (window, gc3,
4480                          x, y + height - 2, x + width - 2, y + height - 2);
4481           gdk_draw_line (window, gc3,
4482                          x + width - 2, y + 2, x + width - 2, y + height - 2);
4483           gdk_draw_line (window, gc4,
4484                          x, y + height - 1, x + width - 2, y + height - 1);
4485           gdk_draw_line (window, gc4,
4486                          x + width - 1, y + 1, x + width - 1, y + height - 2);
4487           break;
4488         case GTK_POS_RIGHT:
4489           gtk_style_apply_default_background (style, window,
4490                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4491                                               state_type, area,
4492                                               x + style->xthickness, 
4493                                               y + style->ythickness, 
4494                                               width - (style->xthickness), 
4495                                               height - (2 * style->ythickness));
4496           gdk_draw_line (window, gc1,
4497                          x + 1, y, x + width - 1, y);
4498           gdk_draw_line (window, gc1,
4499                          x, y + 1, x, y + height - 2);
4500           gdk_draw_line (window, gc2,
4501                          x + 1, y + 1, x + width - 1, y + 1);
4502           gdk_draw_line (window, gc2,
4503                          x + 1, y + 1, x + 1, y + height - 2);
4504           
4505           gdk_draw_line (window, gc3,
4506                          x + 2, y + height - 2, x + width - 1, y + height - 2);
4507           gdk_draw_line (window, gc4,
4508                          x + 1, y + height - 1, x + width - 1, y + height - 1);
4509           break;
4510         }
4511     }
4512
4513   if (area)
4514     {
4515       gdk_gc_set_clip_rectangle (gc1, NULL);
4516       gdk_gc_set_clip_rectangle (gc2, NULL);
4517       gdk_gc_set_clip_rectangle (gc3, NULL);
4518       gdk_gc_set_clip_rectangle (gc4, NULL);
4519     }
4520 }
4521
4522 static void 
4523 gtk_default_draw_focus (GtkStyle      *style,
4524                         GdkWindow     *window,
4525                         GtkStateType   state_type,
4526                         GdkRectangle  *area,
4527                         GtkWidget     *widget,
4528                         const gchar   *detail,
4529                         gint           x,
4530                         gint           y,
4531                         gint           width,
4532                         gint           height)
4533 {
4534   cairo_t *cr;
4535   gboolean free_dash_list = FALSE;
4536   gint line_width = 1;
4537   gint8 *dash_list = "\1\1";
4538
4539   if (widget)
4540     {
4541       gtk_widget_style_get (widget,
4542                             "focus-line-width", &line_width,
4543                             "focus-line-pattern", (gchar *)&dash_list,
4544                             NULL);
4545
4546       free_dash_list = TRUE;
4547   }
4548
4549   if (detail && !strcmp (detail, "add-mode"))
4550     {
4551       if (free_dash_list)
4552         g_free (dash_list);
4553       
4554       dash_list = "\4\4";
4555       free_dash_list = FALSE;
4556     }
4557
4558   sanitize_size (window, &width, &height);
4559
4560   cr = gdk_drawable_create_cairo_context (window);
4561   
4562   if (detail && !strcmp (detail, "colorwheel_light"))
4563     cairo_set_source_rgb (cr, 0., 0., 0.);
4564   else if (detail && !strcmp (detail, "colorwheel_dark"))
4565     cairo_set_source_rgb (cr, 1., 1., 1.);
4566   else
4567     gdk_cairo_set_source_color (cr, &style->fg[state_type]);
4568
4569   cairo_set_line_width (cr, line_width);
4570
4571   if (dash_list[0])
4572     {
4573       gint n_dashes = strlen (dash_list);
4574       gdouble *dashes = g_new (gdouble, n_dashes);
4575       gdouble total_length = 0;
4576       gdouble dash_offset;
4577       gint i;
4578
4579       for (i = 0; i < n_dashes; i++)
4580         {
4581           dashes[i] = dash_list[i];
4582           total_length += dash_list[i];
4583         }
4584
4585       /* The dash offset here aligns the pattern to integer pixels
4586        * by starting the dash at the right side of the left border
4587        * Negative dash offsets in cairo don't work
4588        * (https://bugs.freedesktop.org/show_bug.cgi?id=2729)
4589        */
4590       dash_offset = - line_width / 2.;
4591       while (dash_offset < 0)
4592         dash_offset += total_length;
4593       
4594       cairo_set_dash (cr, dashes, n_dashes, dash_offset);
4595       g_free (dashes);
4596     }
4597
4598   if (area)
4599     {
4600       cairo_rectangle (cr,
4601                        area->x, area->y, area->width, area->height);
4602       cairo_clip (cr);
4603       cairo_new_path (cr);
4604     }
4605
4606   cairo_rectangle (cr,
4607                    x + line_width / 2.,
4608                    y + line_width / 2.,
4609                    width - line_width,
4610                    height - line_width);
4611   cairo_stroke (cr);
4612   cairo_destroy (cr);
4613
4614   if (free_dash_list)
4615     g_free (dash_list);
4616 }
4617
4618 static void 
4619 gtk_default_draw_slider (GtkStyle      *style,
4620                          GdkWindow     *window,
4621                          GtkStateType   state_type,
4622                          GtkShadowType  shadow_type,
4623                          GdkRectangle  *area,
4624                          GtkWidget     *widget,
4625                          const gchar   *detail,
4626                          gint           x,
4627                          gint           y,
4628                          gint           width,
4629                          gint           height,
4630                          GtkOrientation orientation)
4631 {
4632   g_return_if_fail (GTK_IS_STYLE (style));
4633   g_return_if_fail (window != NULL);
4634   
4635   sanitize_size (window, &width, &height);
4636   
4637   gtk_paint_box (style, window, state_type, shadow_type,
4638                  area, widget, detail, x, y, width, height);
4639
4640   if (detail &&
4641       (strcmp ("hscale", detail) == 0 ||
4642        strcmp ("vscale", detail) == 0))
4643     {
4644       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4645         gtk_paint_vline (style, window, state_type, area, widget, detail, 
4646                          y + style->ythickness, 
4647                          y + height - style->ythickness - 1, x + width / 2);
4648       else
4649         gtk_paint_hline (style, window, state_type, area, widget, detail, 
4650                          x + style->xthickness, 
4651                          x + width - style->xthickness - 1, y + height / 2);
4652     }
4653 }
4654
4655 static void
4656 draw_dot (GdkWindow    *window,
4657           GdkGC        *light_gc,
4658           GdkGC        *dark_gc,
4659           gint          x,
4660           gint          y,
4661           gushort       size)
4662 {
4663   
4664   size = CLAMP (size, 2, 3);
4665
4666   if (size == 2)
4667     {
4668       gdk_draw_point (window, light_gc, x, y);
4669       gdk_draw_point (window, light_gc, x+1, y+1);
4670     }
4671   else if (size == 3)
4672     {
4673       gdk_draw_point (window, light_gc, x, y);
4674       gdk_draw_point (window, light_gc, x+1, y);
4675       gdk_draw_point (window, light_gc, x, y+1);
4676       gdk_draw_point (window, dark_gc, x+1, y+2);
4677       gdk_draw_point (window, dark_gc, x+2, y+1);
4678       gdk_draw_point (window, dark_gc, x+2, y+2);
4679     }
4680 }
4681
4682 static void 
4683 gtk_default_draw_handle (GtkStyle      *style,
4684                          GdkWindow     *window,
4685                          GtkStateType   state_type,
4686                          GtkShadowType  shadow_type,
4687                          GdkRectangle  *area,
4688                          GtkWidget     *widget,
4689                          const gchar   *detail,
4690                          gint           x,
4691                          gint           y,
4692                          gint           width,
4693                          gint           height,
4694                          GtkOrientation orientation)
4695 {
4696   gint xx, yy;
4697   gint xthick, ythick;
4698   GdkGC *light_gc, *dark_gc;
4699   GdkGC *free_me = NULL;
4700   GdkRectangle rect;
4701   GdkRectangle dest;
4702   gint intersect;
4703   
4704   g_return_if_fail (GTK_IS_STYLE (style));
4705   g_return_if_fail (window != NULL);
4706   
4707   sanitize_size (window, &width, &height);
4708   
4709   gtk_paint_box (style, window, state_type, shadow_type, area, widget, 
4710                  detail, x, y, width, height);
4711   
4712   
4713   if (detail && !strcmp (detail, "paned"))
4714     {
4715       /* we want to ignore the shadow border in paned widgets */
4716       xthick = 0;
4717       ythick = 0;
4718
4719       if (state_type == GTK_STATE_SELECTED && widget && !GTK_WIDGET_HAS_FOCUS (widget))
4720         {
4721           GdkColor unfocused_light;
4722       
4723           gtk_style_shade (&style->base[GTK_STATE_ACTIVE], &unfocused_light,
4724                            LIGHTNESS_MULT);
4725
4726           light_gc = free_me = gdk_gc_new (window);
4727           gdk_gc_set_rgb_fg_color (light_gc, &unfocused_light);
4728         }
4729       else
4730         light_gc = style->light_gc[state_type];
4731
4732       dark_gc = style->black_gc;
4733     }
4734   else
4735     {
4736       xthick = style->xthickness;
4737       ythick = style->ythickness;
4738
4739       light_gc = style->light_gc[state_type];
4740       dark_gc = style->dark_gc[state_type];
4741     }
4742   
4743   rect.x = x + xthick;
4744   rect.y = y + ythick;
4745   rect.width = width - (xthick * 2);
4746   rect.height = height - (ythick * 2);
4747
4748   if (area)
4749     intersect = gdk_rectangle_intersect (area, &rect, &dest);
4750   else
4751     {
4752       intersect = TRUE;
4753       dest = rect;
4754     }
4755
4756   if (!intersect)
4757     goto out;
4758
4759   gdk_gc_set_clip_rectangle (light_gc, &dest);
4760   gdk_gc_set_clip_rectangle (dark_gc, &dest);
4761
4762   if (detail && !strcmp (detail, "paned"))
4763     {
4764       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4765         for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
4766           draw_dot (window, light_gc, dark_gc, xx, y + height/2 - 1, 3);
4767       else
4768         for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
4769           draw_dot (window, light_gc, dark_gc, x + width/2 - 1, yy, 3);
4770     }
4771   else
4772     {
4773       for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
4774         for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
4775           {
4776             draw_dot (window, light_gc, dark_gc, xx, yy, 2);
4777             draw_dot (window, light_gc, dark_gc, xx + 3, yy + 1, 2);
4778           }
4779     }
4780
4781   gdk_gc_set_clip_rectangle (light_gc, NULL);
4782   gdk_gc_set_clip_rectangle (dark_gc, NULL);
4783
4784  out:
4785   if (free_me)
4786     g_object_unref (free_me);
4787 }
4788
4789 static void
4790 gtk_default_draw_expander (GtkStyle        *style,
4791                            GdkWindow       *window,
4792                            GtkStateType     state_type,
4793                            GdkRectangle    *area,
4794                            GtkWidget       *widget,
4795                            const gchar     *detail,
4796                            gint             x,
4797                            gint             y,
4798                            GtkExpanderStyle expander_style)
4799 {
4800 #define DEFAULT_EXPANDER_SIZE 12
4801
4802   gint expander_size;
4803   gint line_width;
4804   double vertical_overshoot;
4805   int diameter;
4806   double radius;
4807   double x_double, y_double;
4808   gint degrees = 0;
4809
4810   cairo_t *cr = gdk_drawable_create_cairo_context (window);
4811   
4812   if (area)
4813     {
4814       cairo_save (cr);
4815       cairo_rectangle (cr, area->x, area->y, area->width, area->height);
4816       cairo_clip (cr);
4817       cairo_new_path (cr);
4818     }
4819
4820   if (widget &&
4821       gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget),
4822                                             "expander-size"))
4823     {
4824       gtk_widget_style_get (widget,
4825                             "expander-size", &expander_size,
4826                             NULL);
4827     }
4828   else
4829     expander_size = DEFAULT_EXPANDER_SIZE;
4830     
4831   line_width = MAX (1, expander_size/9);
4832
4833   switch (expander_style)
4834     {
4835     case GTK_EXPANDER_COLLAPSED:
4836       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
4837       break;
4838     case GTK_EXPANDER_SEMI_COLLAPSED:
4839       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
4840       break;
4841     case GTK_EXPANDER_SEMI_EXPANDED:
4842       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
4843       break;
4844     case GTK_EXPANDER_EXPANDED:
4845       degrees = 90;
4846       break;
4847     default:
4848       g_assert_not_reached ();
4849     }
4850
4851   /* Compute distance that the stroke extends beyonds the end
4852    * of the triangle we draw.
4853    */
4854   vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8));
4855
4856   /* For odd line widths, we end the vertical line of the triangle
4857    * at a half pixel, so we round differently.
4858    */
4859   if (line_width % 2 == 1)
4860     vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5;
4861   else
4862     vertical_overshoot = ceil (vertical_overshoot);
4863
4864   /* Adjust the size of the triangle we draw so that the entire stroke fits
4865    */
4866   diameter = MAX (3, expander_size - 2 * vertical_overshoot);
4867
4868   /* If the line width is odd, we want the diameter to be even,
4869    * and vice versa, so force the sum to be odd
4870    */
4871   diameter -= (1 - (diameter + line_width) % 2);
4872   
4873   radius = diameter / 2.;
4874
4875   /* Adjust the center so that the stroke is properly aligned with
4876    * the pixel grid
4877    */
4878   x_double = floor (x - (radius + line_width) / 2.) + (radius + line_width) / 2.;
4879   y_double = y + 0.5;
4880   
4881   cairo_translate (cr, x_double, y_double);
4882   cairo_rotate (cr, degrees * M_PI / 180);
4883
4884   cairo_move_to (cr, - radius / 2., - radius);
4885   cairo_line_to (cr,   radius / 2.,   0);
4886   cairo_line_to (cr, - radius / 2.,   radius);
4887   cairo_close_path (cr);
4888   
4889   cairo_set_line_width (cr, line_width);
4890
4891   cairo_save (cr);
4892   if (state_type == GTK_STATE_PRELIGHT)
4893     gdk_cairo_set_source_color (cr,
4894                                 &style->fg[GTK_STATE_PRELIGHT]);
4895   else if (state_type == GTK_STATE_ACTIVE)
4896     gdk_cairo_set_source_color (cr,
4897                                 &style->light[GTK_STATE_ACTIVE]);
4898   else
4899     gdk_cairo_set_source_color (cr,
4900                                 &style->base[GTK_STATE_NORMAL]);
4901   
4902   cairo_fill (cr);
4903   cairo_restore (cr);
4904   
4905   gdk_cairo_set_source_color (cr, &style->fg[state_type]);
4906   cairo_stroke (cr);
4907   
4908   if (area)
4909     cairo_restore (cr);
4910
4911   cairo_destroy (cr);
4912 }
4913
4914 typedef struct _ByteRange ByteRange;
4915
4916 struct _ByteRange
4917 {
4918   guint start;
4919   guint end;
4920 };
4921
4922 static ByteRange*
4923 range_new (guint start,
4924            guint end)
4925 {
4926   ByteRange *br = g_new (ByteRange, 1);
4927
4928   br->start = start;
4929   br->end = end;
4930   
4931   return br;
4932 }
4933
4934 static PangoLayout*
4935 get_insensitive_layout (GdkDrawable *drawable,
4936                         PangoLayout *layout)
4937 {
4938   GSList *embossed_ranges = NULL;
4939   GSList *stippled_ranges = NULL;
4940   PangoLayoutIter *iter;
4941   GSList *tmp_list = NULL;
4942   PangoLayout *new_layout;
4943   PangoAttrList *attrs;
4944   GdkBitmap *stipple = NULL;
4945   
4946   iter = pango_layout_get_iter (layout);
4947   
4948   do
4949     {
4950       PangoLayoutRun *run;
4951       PangoAttribute *attr;
4952       gboolean need_stipple = FALSE;
4953       ByteRange *br;
4954       
4955       run = pango_layout_iter_get_run (iter);
4956
4957       if (run)
4958         {
4959           tmp_list = run->item->analysis.extra_attrs;
4960
4961           while (tmp_list != NULL)
4962             {
4963               attr = tmp_list->data;
4964               switch (attr->klass->type)
4965                 {
4966                 case PANGO_ATTR_FOREGROUND:
4967                 case PANGO_ATTR_BACKGROUND:
4968                   need_stipple = TRUE;
4969                   break;
4970               
4971                 default:
4972                   break;
4973                 }
4974
4975               if (need_stipple)
4976                 break;
4977           
4978               tmp_list = g_slist_next (tmp_list);
4979             }
4980
4981           br = range_new (run->item->offset, run->item->offset + run->item->length);
4982       
4983           if (need_stipple)
4984             stippled_ranges = g_slist_prepend (stippled_ranges, br);
4985           else
4986             embossed_ranges = g_slist_prepend (embossed_ranges, br);
4987         }
4988     }
4989   while (pango_layout_iter_next_run (iter));
4990
4991   pango_layout_iter_free (iter);
4992
4993   new_layout = pango_layout_copy (layout);
4994
4995   attrs = pango_layout_get_attributes (new_layout);
4996
4997   if (attrs == NULL)
4998     {
4999       /* Create attr list if there wasn't one */
5000       attrs = pango_attr_list_new ();
5001       pango_layout_set_attributes (new_layout, attrs);
5002       pango_attr_list_unref (attrs);
5003     }
5004   
5005   tmp_list = embossed_ranges;
5006   while (tmp_list != NULL)
5007     {
5008       PangoAttribute *attr;
5009       ByteRange *br = tmp_list->data;
5010
5011       attr = gdk_pango_attr_embossed_new (TRUE);
5012
5013       attr->start_index = br->start;
5014       attr->end_index = br->end;
5015       
5016       pango_attr_list_change (attrs, attr);
5017
5018       g_free (br);
5019       
5020       tmp_list = g_slist_next (tmp_list);
5021     }
5022
5023   g_slist_free (embossed_ranges);
5024   
5025   tmp_list = stippled_ranges;
5026   while (tmp_list != NULL)
5027     {
5028       PangoAttribute *attr;
5029       ByteRange *br = tmp_list->data;
5030
5031       if (stipple == NULL)
5032         {
5033 #define gray50_width 2
5034 #define gray50_height 2
5035           static const char gray50_bits[] = {
5036             0x02, 0x01
5037           };
5038
5039           stipple = gdk_bitmap_create_from_data (drawable,
5040                                                  gray50_bits, gray50_width,
5041                                                  gray50_height);
5042         }
5043       
5044       attr = gdk_pango_attr_stipple_new (stipple);
5045
5046       attr->start_index = br->start;
5047       attr->end_index = br->end;
5048       
5049       pango_attr_list_change (attrs, attr);
5050
5051       g_free (br);
5052       
5053       tmp_list = g_slist_next (tmp_list);
5054     }
5055
5056   g_slist_free (stippled_ranges);
5057   
5058   if (stipple)
5059     g_object_unref (stipple);
5060
5061   return new_layout;
5062 }
5063
5064 static void
5065 gtk_default_draw_layout (GtkStyle        *style,
5066                          GdkWindow       *window,
5067                          GtkStateType     state_type,
5068                          gboolean         use_text,
5069                          GdkRectangle    *area,
5070                          GtkWidget       *widget,
5071                          const gchar     *detail,
5072                          gint             x,
5073                          gint             y,
5074                          PangoLayout     *layout)
5075 {
5076   GdkGC *gc;
5077   
5078   g_return_if_fail (GTK_IS_STYLE (style));
5079   g_return_if_fail (window != NULL);
5080
5081   gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
5082   
5083   if (area)
5084     gdk_gc_set_clip_rectangle (gc, area);
5085
5086   if (state_type == GTK_STATE_INSENSITIVE)
5087     {
5088       PangoLayout *ins;
5089
5090       ins = get_insensitive_layout (window, layout);
5091       
5092       gdk_draw_layout (window, gc, x, y, ins);
5093
5094       g_object_unref (ins);
5095     }
5096   else
5097     {
5098       gdk_draw_layout (window, gc, x, y, layout);
5099     }
5100
5101   if (area)
5102     gdk_gc_set_clip_rectangle (gc, NULL);
5103 }
5104
5105 static void
5106 gtk_default_draw_resize_grip (GtkStyle       *style,
5107                               GdkWindow      *window,
5108                               GtkStateType    state_type,
5109                               GdkRectangle   *area,
5110                               GtkWidget      *widget,
5111                               const gchar    *detail,
5112                               GdkWindowEdge   edge,
5113                               gint            x,
5114                               gint            y,
5115                               gint            width,
5116                               gint            height)
5117 {
5118   GdkPoint points[4];
5119   gint i, j, skip;
5120
5121   g_return_if_fail (GTK_IS_STYLE (style));
5122   g_return_if_fail (window != NULL);
5123   
5124   if (area)
5125     {
5126       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
5127       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
5128       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
5129     }
5130   
5131   skip = -1;
5132   switch (edge)
5133     {
5134     case GDK_WINDOW_EDGE_NORTH_WEST:
5135       /* make it square */
5136       if (width < height)
5137         height = width;
5138       else if (height < width)
5139         width = height;
5140       skip = 2;
5141       break;
5142     case GDK_WINDOW_EDGE_NORTH:
5143       if (width < height)
5144         height = width;
5145       break;
5146     case GDK_WINDOW_EDGE_NORTH_EAST:
5147       /* make it square, aligning to top right */
5148       if (width < height)
5149         height = width;
5150       else if (height < width)
5151         {
5152           x += (width - height);
5153           width = height;
5154         }
5155       skip = 3;
5156       break;
5157     case GDK_WINDOW_EDGE_WEST:
5158       if (height < width)
5159         width = height;
5160       break;
5161     case GDK_WINDOW_EDGE_EAST:
5162       /* aligning to right */
5163       if (height < width)
5164         {
5165           x += (width - height);
5166           width = height;
5167         }
5168       break;
5169     case GDK_WINDOW_EDGE_SOUTH_WEST:
5170       /* make it square, aligning to bottom left */
5171       if (width < height)
5172         {
5173           y += (height - width);
5174           height = width;
5175         }
5176       else if (height < width)
5177         width = height;
5178       skip = 1;
5179       break;
5180     case GDK_WINDOW_EDGE_SOUTH:
5181       /* align to bottom */
5182       if (width < height)
5183         {
5184           y += (height - width);
5185           height = width;
5186         }
5187       break;
5188     case GDK_WINDOW_EDGE_SOUTH_EAST:
5189       /* make it square, aligning to bottom right */
5190       if (width < height)
5191         {
5192           y += (height - width);
5193           height = width;
5194         }
5195       else if (height < width)
5196         {
5197           x += (width - height);
5198           width = height;
5199         }
5200       skip = 0;
5201       break;
5202     default:
5203       g_assert_not_reached ();
5204     }
5205   /* Clear background */
5206   j = 0;
5207   for (i = 0; i < 4; i++)
5208     {
5209       if (skip != i)
5210         {
5211           points[j].x = (i == 0 || i == 3) ? x : x + width;
5212           points[j].y = (i < 2) ? y : y + height;
5213           j++;
5214         }
5215     }
5216   
5217   gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, 
5218                     points, skip < 0 ? 4 : 3);
5219   
5220   switch (edge)
5221     {
5222     case GDK_WINDOW_EDGE_WEST:
5223     case GDK_WINDOW_EDGE_EAST:
5224       {
5225         gint xi;
5226
5227         xi = x;
5228
5229         while (xi < x + width)
5230           {
5231             gdk_draw_line (window,
5232                            style->light_gc[state_type],
5233                            xi, y,
5234                            xi, y + height);
5235
5236             xi++;
5237             gdk_draw_line (window,
5238                            style->dark_gc[state_type],
5239                            xi, y,
5240                            xi, y + height);
5241
5242             xi += 2;
5243           }
5244       }
5245       break;
5246     case GDK_WINDOW_EDGE_NORTH:
5247     case GDK_WINDOW_EDGE_SOUTH:
5248       {
5249         gint yi;
5250
5251         yi = y;
5252
5253         while (yi < y + height)
5254           {
5255             gdk_draw_line (window,
5256                            style->light_gc[state_type],
5257                            x, yi,
5258                            x + width, yi);
5259
5260             yi++;
5261             gdk_draw_line (window,
5262                            style->dark_gc[state_type],
5263                            x, yi,
5264                            x + width, yi);
5265
5266             yi+= 2;
5267           }
5268       }
5269       break;
5270     case GDK_WINDOW_EDGE_NORTH_WEST:
5271       {
5272         gint xi, yi;
5273
5274         xi = x + width;
5275         yi = y + height;
5276
5277         while (xi > x + 3)
5278           {
5279             gdk_draw_line (window,
5280                            style->dark_gc[state_type],
5281                            xi, y,
5282                            x, yi);
5283
5284             --xi;
5285             --yi;
5286
5287             gdk_draw_line (window,
5288                            style->dark_gc[state_type],
5289                            xi, y,
5290                            x, yi);
5291
5292             --xi;
5293             --yi;
5294
5295             gdk_draw_line (window,
5296                            style->light_gc[state_type],
5297                            xi, y,
5298                            x, yi);
5299
5300             xi -= 3;
5301             yi -= 3;
5302             
5303           }
5304       }
5305       break;
5306     case GDK_WINDOW_EDGE_NORTH_EAST:
5307       {
5308         gint xi, yi;
5309
5310         xi = x;
5311         yi = y + height;
5312
5313         while (xi < (x + width - 3))
5314           {
5315             gdk_draw_line (window,
5316                            style->light_gc[state_type],
5317                            xi, y,
5318                            x + width, yi);                           
5319
5320             ++xi;
5321             --yi;
5322             
5323             gdk_draw_line (window,
5324                            style->dark_gc[state_type],
5325                            xi, y,
5326                            x + width, yi);                           
5327
5328             ++xi;
5329             --yi;
5330             
5331             gdk_draw_line (window,
5332                            style->dark_gc[state_type],
5333                            xi, y,
5334                            x + width, yi);
5335
5336             xi += 3;
5337             yi -= 3;
5338           }
5339       }
5340       break;
5341     case GDK_WINDOW_EDGE_SOUTH_WEST:
5342       {
5343         gint xi, yi;
5344
5345         xi = x + width;
5346         yi = y;
5347
5348         while (xi > x + 3)
5349           {
5350             gdk_draw_line (window,
5351                            style->dark_gc[state_type],
5352                            x, yi,
5353                            xi, y + height);
5354
5355             --xi;
5356             ++yi;
5357
5358             gdk_draw_line (window,
5359                            style->dark_gc[state_type],
5360                            x, yi,
5361                            xi, y + height);
5362
5363             --xi;
5364             ++yi;
5365
5366             gdk_draw_line (window,
5367                            style->light_gc[state_type],
5368                            x, yi,
5369                            xi, y + height);
5370
5371             xi -= 3;
5372             yi += 3;
5373             
5374           }
5375       }
5376       break;
5377     case GDK_WINDOW_EDGE_SOUTH_EAST:
5378       {
5379         gint xi, yi;
5380
5381         xi = x;
5382         yi = y;
5383
5384         while (xi < (x + width - 3))
5385           {
5386             gdk_draw_line (window,
5387                            style->light_gc[state_type],
5388                            xi, y + height,
5389                            x + width, yi);                           
5390
5391             ++xi;
5392             ++yi;
5393             
5394             gdk_draw_line (window,
5395                            style->dark_gc[state_type],
5396                            xi, y + height,
5397                            x + width, yi);                           
5398
5399             ++xi;
5400             ++yi;
5401             
5402             gdk_draw_line (window,
5403                            style->dark_gc[state_type],
5404                            xi, y + height,
5405                            x + width, yi);
5406
5407             xi += 3;
5408             yi += 3;
5409           }
5410       }
5411       break;
5412     default:
5413       g_assert_not_reached ();
5414       break;
5415     }
5416   
5417   if (area)
5418     {
5419       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
5420       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
5421       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
5422     }
5423 }
5424
5425 static void
5426 gtk_style_shade (GdkColor *a,
5427                  GdkColor *b,
5428                  gdouble   k)
5429 {
5430   gdouble red;
5431   gdouble green;
5432   gdouble blue;
5433   
5434   red = (gdouble) a->red / 65535.0;
5435   green = (gdouble) a->green / 65535.0;
5436   blue = (gdouble) a->blue / 65535.0;
5437   
5438   rgb_to_hls (&red, &green, &blue);
5439   
5440   green *= k;
5441   if (green > 1.0)
5442     green = 1.0;
5443   else if (green < 0.0)
5444     green = 0.0;
5445   
5446   blue *= k;
5447   if (blue > 1.0)
5448     blue = 1.0;
5449   else if (blue < 0.0)
5450     blue = 0.0;
5451   
5452   hls_to_rgb (&red, &green, &blue);
5453   
5454   b->red = red * 65535.0;
5455   b->green = green * 65535.0;
5456   b->blue = blue * 65535.0;
5457 }
5458
5459 static void
5460 rgb_to_hls (gdouble *r,
5461             gdouble *g,
5462             gdouble *b)
5463 {
5464   gdouble min;
5465   gdouble max;
5466   gdouble red;
5467   gdouble green;
5468   gdouble blue;
5469   gdouble h, l, s;
5470   gdouble delta;
5471   
5472   red = *r;
5473   green = *g;
5474   blue = *b;
5475   
5476   if (red > green)
5477     {
5478       if (red > blue)
5479         max = red;
5480       else
5481         max = blue;
5482       
5483       if (green < blue)
5484         min = green;
5485       else
5486         min = blue;
5487     }
5488   else
5489     {
5490       if (green > blue)
5491         max = green;
5492       else
5493         max = blue;
5494       
5495       if (red < blue)
5496         min = red;
5497       else
5498         min = blue;
5499     }
5500   
5501   l = (max + min) / 2;
5502   s = 0;
5503   h = 0;
5504   
5505   if (max != min)
5506     {
5507       if (l <= 0.5)
5508         s = (max - min) / (max + min);
5509       else
5510         s = (max - min) / (2 - max - min);
5511       
5512       delta = max -min;
5513       if (red == max)
5514         h = (green - blue) / delta;
5515       else if (green == max)
5516         h = 2 + (blue - red) / delta;
5517       else if (blue == max)
5518         h = 4 + (red - green) / delta;
5519       
5520       h *= 60;
5521       if (h < 0.0)
5522         h += 360;
5523     }
5524   
5525   *r = h;
5526   *g = l;
5527   *b = s;
5528 }
5529
5530 static void
5531 hls_to_rgb (gdouble *h,
5532             gdouble *l,
5533             gdouble *s)
5534 {
5535   gdouble hue;
5536   gdouble lightness;
5537   gdouble saturation;
5538   gdouble m1, m2;
5539   gdouble r, g, b;
5540   
5541   lightness = *l;
5542   saturation = *s;
5543   
5544   if (lightness <= 0.5)
5545     m2 = lightness * (1 + saturation);
5546   else
5547     m2 = lightness + saturation - lightness * saturation;
5548   m1 = 2 * lightness - m2;
5549   
5550   if (saturation == 0)
5551     {
5552       *h = lightness;
5553       *l = lightness;
5554       *s = lightness;
5555     }
5556   else
5557     {
5558       hue = *h + 120;
5559       while (hue > 360)
5560         hue -= 360;
5561       while (hue < 0)
5562         hue += 360;
5563       
5564       if (hue < 60)
5565         r = m1 + (m2 - m1) * hue / 60;
5566       else if (hue < 180)
5567         r = m2;
5568       else if (hue < 240)
5569         r = m1 + (m2 - m1) * (240 - hue) / 60;
5570       else
5571         r = m1;
5572       
5573       hue = *h;
5574       while (hue > 360)
5575         hue -= 360;
5576       while (hue < 0)
5577         hue += 360;
5578       
5579       if (hue < 60)
5580         g = m1 + (m2 - m1) * hue / 60;
5581       else if (hue < 180)
5582         g = m2;
5583       else if (hue < 240)
5584         g = m1 + (m2 - m1) * (240 - hue) / 60;
5585       else
5586         g = m1;
5587       
5588       hue = *h - 120;
5589       while (hue > 360)
5590         hue -= 360;
5591       while (hue < 0)
5592         hue += 360;
5593       
5594       if (hue < 60)
5595         b = m1 + (m2 - m1) * hue / 60;
5596       else if (hue < 180)
5597         b = m2;
5598       else if (hue < 240)
5599         b = m1 + (m2 - m1) * (240 - hue) / 60;
5600       else
5601         b = m1;
5602       
5603       *h = r;
5604       *l = g;
5605       *s = b;
5606     }
5607 }
5608
5609
5610 /**
5611  * gtk_paint_hline:
5612  * @style: a #GtkStyle
5613  * @window: a #GdkWindow
5614  * @state_type: a state
5615  * @area: rectangle to which the output is clipped, or %NULL if the
5616  *        output should not be clipped
5617  * @widget: the widget (may be %NULL)
5618  * @detail: a style detail (may be %NULL)
5619  * @x1: the starting x coordinate
5620  * @x2: the ending x coordinate
5621  * @y: the y coordinate
5622  * 
5623  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
5624  * using the given style and state.
5625  **/ 
5626 void 
5627 gtk_paint_hline (GtkStyle      *style,
5628                  GdkWindow     *window,
5629                  GtkStateType   state_type,
5630                  GdkRectangle  *area,
5631                  GtkWidget     *widget,
5632                  const gchar   *detail,
5633                  gint          x1,
5634                  gint          x2,
5635                  gint          y)
5636 {
5637   g_return_if_fail (GTK_IS_STYLE (style));
5638   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
5639   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5640   
5641   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y);
5642 }
5643
5644 /**
5645  * gtk_paint_vline:
5646  * @style: a #GtkStyle
5647  * @window: a #GdkWindow
5648  * @state_type: a state
5649  * @area: rectangle to which the output is clipped, or %NULL if the
5650  *        output should not be clipped
5651  * @widget: the widget (may be %NULL)
5652  * @detail: a style detail (may be %NULL)
5653  * @y1_: the starting y coordinate
5654  * @y2_: the ending y coordinate
5655  * @x: the x coordinate
5656  * 
5657  * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @window
5658  * using the given style and state.
5659  */
5660 void
5661 gtk_paint_vline (GtkStyle      *style,
5662                  GdkWindow     *window,
5663                  GtkStateType   state_type,
5664                  GdkRectangle  *area,
5665                  GtkWidget     *widget,
5666                  const gchar   *detail,
5667                  gint          y1_,
5668                  gint          y2_,
5669                  gint          x)
5670 {
5671   g_return_if_fail (GTK_IS_STYLE (style));
5672   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
5673   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5674   
5675   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1_, y2_, x);
5676 }
5677
5678 /**
5679  * gtk_paint_shadow:
5680  * @style: a #GtkStyle
5681  * @window: a #GdkWindow
5682  * @state_type: a state
5683  * @shadow_type: type of shadow to draw
5684  * @area: clip rectangle or %NULL if the
5685  *        output should not be clipped
5686  * @widget: the widget (may be %NULL)
5687  * @detail: a style detail (may be %NULL)
5688  * @x: x origin of the rectangle
5689  * @y: y origin of the rectangle
5690  * @width: width of the rectangle 
5691  * @height: width of the rectangle 
5692  *
5693  * Draws a shadow around the given rectangle in @window 
5694  * using the given style and state and shadow type.
5695  */
5696 void
5697 gtk_paint_shadow (GtkStyle     *style,
5698                   GdkWindow    *window,
5699                   GtkStateType  state_type,
5700                   GtkShadowType shadow_type,
5701                   GdkRectangle *area,
5702                   GtkWidget    *widget,
5703                   const gchar  *detail,
5704                   gint          x,
5705                   gint          y,
5706                   gint          width,
5707                   gint          height)
5708 {
5709   g_return_if_fail (GTK_IS_STYLE (style));
5710   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
5711   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5712   
5713   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5714 }
5715
5716 /**
5717  * gtk_paint_polygon:
5718  * @style: a #GtkStyle
5719  * @window: a #GdkWindow
5720  * @state_type: a state
5721  * @shadow_type: type of shadow to draw
5722  * @area: clip rectangle, or %NULL if the
5723  *        output should not be clipped
5724  * @widget: the widget (may be %NULL)
5725  * @detail: a style detail (may be %NULL)
5726  * @points: an array of #GdkPoint<!-- -->s
5727  * @npoints: length of @points
5728  * @fill: %TRUE if the polygon should be filled
5729  * 
5730  * Draws a polygon on @window with the given parameters.
5731  */ 
5732 void
5733 gtk_paint_polygon (GtkStyle      *style,
5734                    GdkWindow     *window,
5735                    GtkStateType   state_type,
5736                    GtkShadowType  shadow_type,
5737                    GdkRectangle  *area,
5738                    GtkWidget     *widget,
5739                    const gchar   *detail,
5740                    GdkPoint      *points,
5741                    gint           npoints,
5742                    gboolean       fill)
5743 {
5744   g_return_if_fail (GTK_IS_STYLE (style));
5745   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_polygon != NULL);
5746   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5747   
5748   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill);
5749 }
5750
5751 /**
5752  * gtk_paint_arrow:
5753  * @style: a #GtkStyle
5754  * @window: a #GdkWindow
5755  * @state_type: a state
5756  * @shadow_type: the type of shadow to draw
5757  * @area: clip rectangle, or %NULL if the
5758  *        output should not be clipped
5759  * @widget: the widget (may be %NULL)
5760  * @detail: a style detail (may be %NULL)
5761  * @arrow_type: the type of arrow to draw
5762  * @fill: %TRUE if the arrow tip should be filled
5763  * @x: x origin of the rectangle to draw the arrow in
5764  * @y: y origin of the rectangle to draw the arrow in
5765  * @width: width of the rectangle to draw the arrow in
5766  * @height: height of the rectangle to draw the arrow in
5767  * 
5768  * Draws an arrow in the given rectangle on @window using the given 
5769  * parameters. @arrow_type determines the direction of the arrow.
5770  */
5771 void
5772 gtk_paint_arrow (GtkStyle      *style,
5773                  GdkWindow     *window,
5774                  GtkStateType   state_type,
5775                  GtkShadowType  shadow_type,
5776                  GdkRectangle  *area,
5777                  GtkWidget     *widget,
5778                  const gchar   *detail,
5779                  GtkArrowType   arrow_type,
5780                  gboolean       fill,
5781                  gint           x,
5782                  gint           y,
5783                  gint           width,
5784                  gint           height)
5785 {
5786   g_return_if_fail (GTK_IS_STYLE (style));
5787   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
5788   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5789   
5790   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height);
5791 }
5792
5793 /**
5794  * gtk_paint_diamond:
5795  * @style: a #GtkStyle
5796  * @window: a #GdkWindow
5797  * @state_type: a state
5798  * @shadow_type: the type of shadow to draw
5799  * @area: clip rectangle, or %NULL if the
5800  *        output should not be clipped
5801  * @widget: the widget (may be %NULL)
5802  * @detail: a style detail (may be %NULL)
5803  * @x: x origin of the rectangle to draw the diamond in
5804  * @y: y origin of the rectangle to draw the diamond in
5805  * @width: width of the rectangle to draw the diamond in
5806  * @height: height of the rectangle to draw the diamond in
5807  *
5808  * Draws a diamond in the given rectangle on @window using the given
5809  * parameters.
5810  */
5811 void
5812 gtk_paint_diamond (GtkStyle      *style,
5813                    GdkWindow     *window,
5814                    GtkStateType   state_type,
5815                    GtkShadowType  shadow_type,
5816                    GdkRectangle  *area,
5817                    GtkWidget     *widget,
5818                    const gchar   *detail,
5819                    gint        x,
5820                    gint        y,
5821                    gint        width,
5822                    gint        height)
5823 {
5824   g_return_if_fail (GTK_IS_STYLE (style));
5825   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
5826   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5827   
5828   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5829 }
5830
5831 /**
5832  * gtk_paint_string:
5833  * @style: a #GtkStyle
5834  * @window: a #GdkWindow
5835  * @state_type: a state
5836  * @area: clip rectangle, or %NULL if the
5837  *        output should not be clipped
5838  * @widget: the widget (may be %NULL)
5839  * @detail: a style detail (may be %NULL)
5840  * @x: x origin
5841  * @y: y origin
5842  * @string: the string to draw
5843  * 
5844  * Draws a text string on @window with the given parameters.
5845  *
5846  * Deprecated: Use gtk_paint_layout() instead.
5847  */
5848 void
5849 gtk_paint_string (GtkStyle      *style,
5850                   GdkWindow     *window,
5851                   GtkStateType   state_type,
5852                   GdkRectangle  *area,
5853                   GtkWidget     *widget,
5854                   const gchar   *detail,
5855                   gint           x,
5856                   gint           y,
5857                   const gchar   *string)
5858 {
5859   g_return_if_fail (GTK_IS_STYLE (style));
5860   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
5861   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5862   
5863   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string);
5864 }
5865
5866 /**
5867  * gtk_paint_box:
5868  * @style: a #GtkStyle
5869  * @window: a #GdkWindow
5870  * @state_type: a state
5871  * @shadow_type: the type of shadow to draw
5872  * @area: clip rectangle, or %NULL if the
5873  *        output should not be clipped
5874  * @widget: the widget (may be %NULL)
5875  * @detail: a style detail (may be %NULL)
5876  * @x: x origin of the box
5877  * @y: y origin of the box
5878  * @width: the width of the box
5879  * @height: the height of the box
5880  * 
5881  * Draws a box on @window with the given parameters.
5882  */
5883 void
5884 gtk_paint_box (GtkStyle      *style,
5885                GdkWindow     *window,
5886                GtkStateType   state_type,
5887                GtkShadowType  shadow_type,
5888                GdkRectangle  *area,
5889                GtkWidget     *widget,
5890                const gchar   *detail,
5891                gint           x,
5892                gint           y,
5893                gint           width,
5894                gint           height)
5895 {
5896   g_return_if_fail (GTK_IS_STYLE (style));
5897   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
5898   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5899   
5900   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5901 }
5902
5903 /**
5904  * gtk_paint_flat_box:
5905  * @style: a #GtkStyle
5906  * @window: a #GdkWindow
5907  * @state_type: a state
5908  * @shadow_type: the type of shadow to draw
5909  * @area: clip rectangle, or %NULL if the
5910  *        output should not be clipped
5911  * @widget: the widget (may be %NULL)
5912  * @detail: a style detail (may be %NULL)
5913  * @x: x origin of the box
5914  * @y: y origin of the box
5915  * @width: the width of the box
5916  * @height: the height of the box
5917  * 
5918  * Draws a flat box on @window with the given parameters.
5919  */
5920 void
5921 gtk_paint_flat_box (GtkStyle      *style,
5922                     GdkWindow     *window,
5923                     GtkStateType   state_type,
5924                     GtkShadowType  shadow_type,
5925                     GdkRectangle  *area,
5926                     GtkWidget     *widget,
5927                     const gchar   *detail,
5928                     gint           x,
5929                     gint           y,
5930                     gint           width,
5931                     gint           height)
5932 {
5933   g_return_if_fail (GTK_IS_STYLE (style));
5934   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
5935   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5936   
5937   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5938 }
5939
5940 /**
5941  * gtk_paint_check:
5942  * @style: a #GtkStyle
5943  * @window: a #GdkWindow
5944  * @state_type: a state
5945  * @shadow_type: the type of shadow to draw
5946  * @area: clip rectangle, or %NULL if the
5947  *        output should not be clipped
5948  * @widget: the widget (may be %NULL)
5949  * @detail: a style detail (may be %NULL)
5950  * @x: x origin of the rectangle to draw the check in
5951  * @y: y origin of the rectangle to draw the check in
5952  * @width: the width of the rectangle to draw the check in
5953  * @height: the height of the rectangle to draw the check in
5954  * 
5955  * Draws a check button indicator in the given rectangle on @window with 
5956  * the given parameters.
5957  */
5958 void
5959 gtk_paint_check (GtkStyle      *style,
5960                  GdkWindow     *window,
5961                  GtkStateType   state_type,
5962                  GtkShadowType  shadow_type,
5963                  GdkRectangle  *area,
5964                  GtkWidget     *widget,
5965                  const gchar   *detail,
5966                  gint           x,
5967                  gint           y,
5968                  gint           width,
5969                  gint           height)
5970 {
5971   g_return_if_fail (GTK_IS_STYLE (style));
5972   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
5973   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
5974   
5975   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5976 }
5977
5978 /**
5979  * gtk_paint_option:
5980  * @style: a #GtkStyle
5981  * @window: a #GdkWindow
5982  * @state_type: a state
5983  * @shadow_type: the type of shadow to draw
5984  * @area: clip rectangle, or %NULL if the
5985  *        output should not be clipped
5986  * @widget: the widget (may be %NULL)
5987  * @detail: a style detail (may be %NULL)
5988  * @x: x origin of the rectangle to draw the option in
5989  * @y: y origin of the rectangle to draw the option in
5990  * @width: the width of the rectangle to draw the option in
5991  * @height: the height of the rectangle to draw the option in
5992  *
5993  * Draws a radio button indicator in the given rectangle on @window with 
5994  * the given parameters.
5995  */
5996 void
5997 gtk_paint_option (GtkStyle      *style,
5998                   GdkWindow     *window,
5999                   GtkStateType   state_type,
6000                   GtkShadowType  shadow_type,
6001                   GdkRectangle  *area,
6002                   GtkWidget     *widget,
6003                   const gchar   *detail,
6004                   gint           x,
6005                   gint           y,
6006                   gint           width,
6007                   gint           height)
6008 {
6009   g_return_if_fail (GTK_IS_STYLE (style));
6010   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
6011   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6012   
6013   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
6014 }
6015
6016 /**
6017  * gtk_paint_tab:
6018  * @style: a #GtkStyle
6019  * @window: a #GdkWindow
6020  * @state_type: a state
6021  * @shadow_type: the type of shadow to draw
6022  * @area: clip rectangle, or %NULL if the
6023  *        output should not be clipped
6024  * @widget: the widget (may be %NULL)
6025  * @detail: a style detail (may be %NULL)
6026  * @x: x origin of the rectangle to draw the tab in
6027  * @y: y origin of the rectangle to draw the tab in
6028  * @width: the width of the rectangle to draw the tab in
6029  * @height: the height of the rectangle to draw the tab in
6030  *
6031  * Draws an option menu tab (i.e. the up and down pointing arrows)
6032  * in the given rectangle on @window using the given parameters.
6033  */ 
6034 void
6035 gtk_paint_tab (GtkStyle      *style,
6036                GdkWindow     *window,
6037                GtkStateType   state_type,
6038                GtkShadowType  shadow_type,
6039                GdkRectangle  *area,
6040                GtkWidget     *widget,
6041                const gchar   *detail,
6042                gint           x,
6043                gint           y,
6044                gint           width,
6045                gint           height)
6046 {
6047   g_return_if_fail (GTK_IS_STYLE (style));
6048   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
6049   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6050   
6051   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
6052 }
6053
6054 /**
6055  * gtk_paint_shadow_gap:
6056  * @style: a #GtkStyle
6057  * @window: a #GdkWindow
6058  * @state_type: a state
6059  * @shadow_type: type of shadow to draw
6060  * @area: clip rectangle, or %NULL if the
6061  *        output should not be clipped
6062  * @widget: the widget (may be %NULL)
6063  * @detail: a style detail (may be %NULL)
6064  * @x: x origin of the rectangle
6065  * @y: y origin of the rectangle
6066  * @width: width of the rectangle 
6067  * @height: width of the rectangle 
6068  * @gap_side: side in which to leave the gap
6069  * @gap_x: starting position of the gap
6070  * @gap_width: width of the gap
6071  *
6072  * Draws a shadow around the given rectangle in @window 
6073  * using the given style and state and shadow type, leaving a 
6074  * gap in one side.
6075 */
6076 void
6077 gtk_paint_shadow_gap (GtkStyle       *style,
6078                       GdkWindow      *window,
6079                       GtkStateType    state_type,
6080                       GtkShadowType   shadow_type,
6081                       GdkRectangle   *area,
6082                       GtkWidget      *widget,
6083                       gchar          *detail,
6084                       gint            x,
6085                       gint            y,
6086                       gint            width,
6087                       gint            height,
6088                       GtkPositionType gap_side,
6089                       gint            gap_x,
6090                       gint            gap_width)
6091 {
6092   g_return_if_fail (GTK_IS_STYLE (style));
6093   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
6094   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6095   
6096   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);
6097 }
6098
6099
6100 /**
6101  * gtk_paint_box_gap:
6102  * @style: a #GtkStyle
6103  * @window: a #GdkWindow
6104  * @state_type: a state
6105  * @shadow_type: type of shadow to draw
6106  * @area: clip rectangle, or %NULL if the
6107  *        output should not be clipped
6108  * @widget: the widget (may be %NULL)
6109  * @detail: a style detail (may be %NULL)
6110  * @x: x origin of the rectangle
6111  * @y: y origin of the rectangle
6112  * @width: width of the rectangle 
6113  * @height: width of the rectangle 
6114  * @gap_side: side in which to leave the gap
6115  * @gap_x: starting position of the gap
6116  * @gap_width: width of the gap
6117  *
6118  * Draws a box in @window using the given style and state and shadow type, 
6119  * leaving a gap in one side.
6120  */
6121 void
6122 gtk_paint_box_gap (GtkStyle       *style,
6123                    GdkWindow      *window,
6124                    GtkStateType    state_type,
6125                    GtkShadowType   shadow_type,
6126                    GdkRectangle   *area,
6127                    GtkWidget      *widget,
6128                    gchar          *detail,
6129                    gint            x,
6130                    gint            y,
6131                    gint            width,
6132                    gint            height,
6133                    GtkPositionType gap_side,
6134                    gint            gap_x,
6135                    gint            gap_width)
6136 {
6137   g_return_if_fail (GTK_IS_STYLE (style));
6138   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
6139   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6140   
6141   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);
6142 }
6143
6144 /**
6145  * gtk_paint_extension: 
6146  * @style: a #GtkStyle
6147  * @window: a #GdkWindow
6148  * @state_type: a state
6149  * @shadow_type: type of shadow to draw
6150  * @area: clip rectangle, or %NULL if the
6151  *        output should not be clipped
6152  * @widget: the widget (may be %NULL)
6153  * @detail: a style detail (may be %NULL)
6154  * @x: x origin of the extension
6155  * @y: y origin of the extension
6156  * @width: width of the extension 
6157  * @height: width of the extension 
6158  * @gap_side: the side on to which the extension is attached
6159  * 
6160  * Draws an extension, i.e. a notebook tab.
6161  **/
6162 void
6163 gtk_paint_extension (GtkStyle       *style,
6164                      GdkWindow      *window,
6165                      GtkStateType    state_type,
6166                      GtkShadowType   shadow_type,
6167                      GdkRectangle   *area,
6168                      GtkWidget      *widget,
6169                      gchar          *detail,
6170                      gint            x,
6171                      gint            y,
6172                      gint            width,
6173                      gint            height,
6174                      GtkPositionType gap_side)
6175 {
6176   g_return_if_fail (GTK_IS_STYLE (style));
6177   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
6178   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6179   
6180   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side);
6181 }
6182
6183 /**
6184  * gtk_paint_focus:
6185  * @style: a #GtkStyle
6186  * @window: a #GdkWindow
6187  * @state_type: a state
6188  * @area: clip rectangle, or %NULL if the
6189  *        output should not be clipped
6190  * @widget: the widget (may be %NULL)
6191  * @detail: a style detail (may be %NULL)
6192  * @x: the x origin of the rectangle around which to draw a focus indicator
6193  * @y: the y origin of the rectangle around which to draw a focus indicator
6194  * @width: the width of the rectangle around which to draw a focus indicator
6195  * @height: the height of the rectangle around which to draw a focus indicator
6196  *
6197  * Draws a focus indicator around the given rectangle on @window using the
6198  * given style.
6199  */
6200 void
6201 gtk_paint_focus (GtkStyle      *style,
6202                  GdkWindow     *window,
6203                  GtkStateType   state_type,
6204                  GdkRectangle  *area,
6205                  GtkWidget     *widget,
6206                  const gchar   *detail,
6207                  gint           x,
6208                  gint           y,
6209                  gint           width,
6210                  gint           height)
6211 {
6212   g_return_if_fail (GTK_IS_STYLE (style));
6213   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
6214   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6215   
6216   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type, area, widget, detail, x, y, width, height);
6217 }
6218
6219 void
6220 gtk_paint_slider (GtkStyle      *style,
6221                   GdkWindow     *window,
6222                   GtkStateType   state_type,
6223                   GtkShadowType  shadow_type,
6224                   GdkRectangle  *area,
6225                   GtkWidget     *widget,
6226                   const gchar   *detail,
6227                   gint           x,
6228                   gint           y,
6229                   gint           width,
6230                   gint           height,
6231                   GtkOrientation orientation)
6232 {
6233   g_return_if_fail (GTK_IS_STYLE (style));
6234   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
6235   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6236   
6237   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
6238 }
6239
6240 /**
6241  * gtk_paint_handle:
6242  * @style: a #GtkStyle
6243  * @window: a #GdkWindow
6244  * @state_type: a state
6245  * @shadow_type: type of shadow to draw
6246  * @area: clip rectangle, or %NULL if the
6247  *        output should not be clipped
6248  * @widget: the widget (may be %NULL)
6249  * @detail: a style detail (may be %NULL)
6250  * @x: x origin of the handle
6251  * @y: y origin of the handle
6252  * @width: with of the handle
6253  * @height: height of the handle
6254  * @orientation: the orientation of the handle
6255  * 
6256  * Draws a handle as used in #GtkHandleBox and #GtkPaned.
6257  **/
6258 void
6259 gtk_paint_handle (GtkStyle      *style,
6260                   GdkWindow     *window,
6261                   GtkStateType   state_type,
6262                   GtkShadowType  shadow_type,
6263                   GdkRectangle  *area,
6264                   GtkWidget     *widget,
6265                   const gchar   *detail,
6266                   gint           x,
6267                   gint           y,
6268                   gint           width,
6269                   gint           height,
6270                   GtkOrientation orientation)
6271 {
6272   g_return_if_fail (GTK_IS_STYLE (style));
6273   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
6274   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6275   
6276   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
6277 }
6278
6279 /**
6280  * gtk_paint_expander:
6281  * @style: a #GtkStyle
6282  * @window: a #GdkWindow
6283  * @state_type: a state
6284  * @area: clip rectangle, or %NULL if the
6285  *        output should not be clipped
6286  * @widget: the widget (may be %NULL)
6287  * @detail: a style detail (may be %NULL)
6288  * @x: the x position to draw the expander at
6289  * @y: the y position to draw the expander at
6290  * @expander_style: the style to draw the expander in; determines
6291  *   whether the expander is collapsed, expanded, or in an
6292  *   intermediate state.
6293  * 
6294  * Draws an expander as used in #GtkTreeView. @x and @y specify the
6295  * center the expander. The size of the expander is determined by the
6296  * "expander-size" style property of @widget.  (If widget is not
6297  * specified or doesn't have an "expander-size" property, an
6298  * unspecified default size will be used, since the caller doesn't
6299  * have sufficient information to position the expander, this is
6300  * likely not useful.) The expander is expander_size pixels tall
6301  * in the collapsed position and expander_size pixels wide in the
6302  * expanded position.
6303  **/
6304 void
6305 gtk_paint_expander (GtkStyle        *style,
6306                     GdkWindow       *window,
6307                     GtkStateType     state_type,
6308                     GdkRectangle    *area,
6309                     GtkWidget       *widget,
6310                     const gchar     *detail,
6311                     gint             x,
6312                     gint             y,
6313                     GtkExpanderStyle expander_style)
6314 {
6315   g_return_if_fail (GTK_IS_STYLE (style));
6316   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
6317   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6318   
6319   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type, area,
6320                                               widget, detail, x, y, expander_style);
6321 }
6322
6323 void
6324 gtk_paint_layout (GtkStyle        *style,
6325                   GdkWindow       *window,
6326                   GtkStateType     state_type,
6327                   gboolean         use_text,
6328                   GdkRectangle    *area,
6329                   GtkWidget       *widget,
6330                   const gchar     *detail,
6331                   gint             x,
6332                   gint             y,
6333                   PangoLayout     *layout)
6334 {
6335   g_return_if_fail (GTK_IS_STYLE (style));
6336   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
6337   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6338   
6339   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text, area,
6340                                             widget, detail, x, y, layout);
6341 }
6342
6343 /**
6344  * gtk_paint_resize_grip:
6345  * @style: a #GtkStyle
6346  * @window: a #GdkWindow
6347  * @state_type: a state
6348  * @area: clip rectangle, or %NULL if the
6349  *        output should not be clipped
6350  * @widget: the widget (may be %NULL)
6351  * @detail: a style detail (may be %NULL)
6352  * @edge: the edge in which to draw the resize grip
6353  * @x: the x origin of the rectangle in which to draw the resize grip
6354  * @y: the y origin of the rectangle in which to draw the resize grip
6355  * @width: the width of the rectangle in which to draw the resize grip
6356  * @height: the height of the rectangle in which to draw the resize grip
6357  *
6358  * Draws a resize grip in the given rectangle on @window using the given
6359  * parameters. 
6360  */
6361 void
6362 gtk_paint_resize_grip (GtkStyle      *style,
6363                        GdkWindow     *window,
6364                        GtkStateType   state_type,
6365                        GdkRectangle  *area,
6366                        GtkWidget     *widget,
6367                        const gchar   *detail,
6368                        GdkWindowEdge  edge,
6369                        gint           x,
6370                        gint           y,
6371                        gint           width,
6372                        gint           height)
6373
6374 {
6375   g_return_if_fail (GTK_IS_STYLE (style));
6376   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
6377   g_return_if_fail (style->depth == gdk_drawable_get_depth (window));
6378
6379   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
6380                                                  area, widget, detail,
6381                                                  edge, x, y, width, height);
6382 }
6383
6384 /**
6385  * gtk_border_copy:
6386  * @border_: a #GtkBorder.
6387  * @returns: a copy of @border_.
6388  *
6389  * Copies a #GtkBorder structure.
6390  **/
6391 GtkBorder *
6392 gtk_border_copy (const GtkBorder *border)
6393 {
6394   return (GtkBorder *)g_memdup (border, sizeof (GtkBorder));
6395 }
6396
6397 /**
6398  * gtk_border_free:
6399  * @border_: a #GtkBorder.
6400  * 
6401  * Frees a #GtkBorder structure.
6402  **/
6403 void
6404 gtk_border_free (GtkBorder *border)
6405 {
6406   g_free (border);
6407 }
6408
6409 GType
6410 gtk_border_get_type (void)
6411 {
6412   static GType our_type = 0;
6413   
6414   if (our_type == 0)
6415     our_type = g_boxed_type_register_static ("GtkBorder",
6416                                              (GBoxedCopyFunc) gtk_border_copy,
6417                                              (GBoxedFreeFunc) gtk_border_free);
6418
6419   return our_type;
6420 }
6421
6422 static GdkFont *
6423 gtk_style_get_font_internal (GtkStyle *style)
6424 {
6425   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
6426
6427   if (style->private_font && style->private_font_desc)
6428     {
6429       if (!style->font_desc ||
6430           !pango_font_description_equal (style->private_font_desc, style->font_desc))
6431         {
6432           gdk_font_unref (style->private_font);
6433           style->private_font = NULL;
6434           
6435           if (style->private_font_desc)
6436             {
6437               pango_font_description_free (style->private_font_desc);
6438               style->private_font_desc = NULL;
6439             }
6440         }
6441     }
6442   
6443   if (!style->private_font)
6444     {
6445       GdkDisplay *display;
6446
6447       if (style->colormap)
6448         {
6449           display = gdk_screen_get_display (gdk_colormap_get_screen (style->colormap));
6450         }
6451       else
6452         {
6453           display = gdk_display_get_default ();
6454           GTK_NOTE (MULTIHEAD,
6455                     g_warning ("gtk_style_get_font() should not be called on an unattached style"));
6456         }
6457       
6458       if (style->font_desc)
6459         {
6460           style->private_font = gdk_font_from_description_for_display (display, style->font_desc);
6461           style->private_font_desc = pango_font_description_copy (style->font_desc);
6462         }
6463
6464       if (!style->private_font)
6465         style->private_font = gdk_font_load_for_display (display, "fixed");
6466       
6467       if (!style->private_font) 
6468         g_error ("Unable to load \"fixed\" font");
6469     }
6470
6471   return style->private_font;
6472 }
6473
6474 /**
6475  * gtk_style_get_font:
6476  * @style: a #GtkStyle
6477  * 
6478  * Gets the #GdkFont to use for the given style. This is
6479  * meant only as a replacement for direct access to @style->font
6480  * and should not be used in new code. New code should
6481  * use @style->font_desc instead.
6482  * 
6483  * Return value: the #GdkFont for the style. This font is owned
6484  *   by the style; if you want to keep around a copy, you must
6485  *   call gdk_font_ref().
6486  **/
6487 GdkFont *
6488 gtk_style_get_font (GtkStyle *style)
6489 {
6490   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
6491
6492   return gtk_style_get_font_internal (style);
6493 }
6494
6495 /**
6496  * gtk_style_set_font:
6497  * @style: a #GtkStyle.
6498  * @font: a #GdkFont, or %NULL to use the #GdkFont corresponding
6499  *   to style->font_desc.
6500  * 
6501  * Sets the #GdkFont to use for a given style. This is
6502  * meant only as a replacement for direct access to style->font
6503  * and should not be used in new code. New code should
6504  * use style->font_desc instead.
6505  **/
6506 void
6507 gtk_style_set_font (GtkStyle *style,
6508                     GdkFont  *font)
6509 {
6510   GdkFont *old_font;
6511
6512   g_return_if_fail (GTK_IS_STYLE (style));
6513
6514   old_font = style->private_font;
6515
6516   style->private_font = font;
6517   if (font)
6518     gdk_font_ref (font);
6519
6520   if (old_font)
6521     gdk_font_unref (old_font);
6522
6523   if (style->private_font_desc)
6524     {
6525       pango_font_description_free (style->private_font_desc);
6526       style->private_font_desc = NULL;
6527     }
6528 }
6529
6530 typedef struct _CursorInfo CursorInfo;
6531
6532 struct _CursorInfo
6533 {
6534   GType for_type;
6535   GdkGC *primary_gc;
6536   GdkGC *secondary_gc;
6537 };
6538
6539 static void
6540 style_unrealize_cursor_gcs (GtkStyle *style)
6541 {
6542   CursorInfo *
6543   
6544   cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
6545   if (cursor_info)
6546     {
6547       if (cursor_info->primary_gc)
6548         gtk_gc_release (cursor_info->primary_gc);
6549
6550       if (cursor_info->secondary_gc)
6551         gtk_gc_release (cursor_info->secondary_gc);
6552       
6553       g_free (cursor_info);
6554       g_object_set_data (G_OBJECT (style), "gtk-style-cursor-info", NULL);
6555     }
6556 }
6557
6558 static GdkGC *
6559 make_cursor_gc (GtkWidget   *widget,
6560                 const gchar *property_name,
6561                 const GdkColor *fallback)
6562 {
6563   GdkGCValues gc_values;
6564   GdkGCValuesMask gc_values_mask;
6565   GdkColor *cursor_color;
6566
6567   gtk_widget_style_get (widget, property_name, &cursor_color, NULL);
6568   
6569   gc_values_mask = GDK_GC_FOREGROUND;
6570   if (cursor_color)
6571     {
6572       gc_values.foreground = *cursor_color;
6573       gdk_color_free (cursor_color);
6574     }
6575   else
6576     gc_values.foreground = *fallback;
6577   
6578   gdk_rgb_find_color (widget->style->colormap, &gc_values.foreground);
6579   return gtk_gc_get (widget->style->depth, widget->style->colormap, &gc_values, gc_values_mask);
6580 }
6581
6582 static GdkGC *
6583 get_insertion_cursor_gc (GtkWidget *widget,
6584                          gboolean   is_primary)
6585 {
6586   CursorInfo *cursor_info;
6587
6588   cursor_info = g_object_get_data (G_OBJECT (widget->style), "gtk-style-cursor-info");
6589   if (!cursor_info)
6590     {
6591       cursor_info = g_new (CursorInfo, 1);
6592       g_object_set_data (G_OBJECT (widget->style), "gtk-style-cursor-info", cursor_info);
6593       cursor_info->primary_gc = NULL;
6594       cursor_info->secondary_gc = NULL;
6595       cursor_info->for_type = G_TYPE_INVALID;
6596     }
6597
6598   /* We have to keep track of the type because gtk_widget_style_get()
6599    * can return different results when called on the same property and
6600    * same style but for different widgets. :-(. That is,
6601    * GtkEntry::cursor-color = "red" in a style will modify the cursor
6602    * color for entries but not for text view.
6603    */
6604   if (cursor_info->for_type != G_OBJECT_TYPE (widget))
6605     {
6606       cursor_info->for_type = G_OBJECT_TYPE (widget);
6607       if (cursor_info->primary_gc)
6608         {
6609           gtk_gc_release (cursor_info->primary_gc);
6610           cursor_info->primary_gc = NULL;
6611         }
6612       if (cursor_info->secondary_gc)
6613         {
6614           gtk_gc_release (cursor_info->secondary_gc);
6615           cursor_info->secondary_gc = NULL;
6616         }
6617     }
6618
6619   if (is_primary)
6620     {
6621       if (!cursor_info->primary_gc)
6622         cursor_info->primary_gc = make_cursor_gc (widget,
6623                                                   "cursor-color",
6624                                                   &widget->style->black);
6625         
6626       return cursor_info->primary_gc;
6627     }
6628   else
6629     {
6630       static const GdkColor gray = { 0, 0x8888, 0x8888, 0x8888 };
6631       
6632       if (!cursor_info->secondary_gc)
6633         cursor_info->secondary_gc = make_cursor_gc (widget,
6634                                                     "secondary-cursor-color",
6635                                                     &gray);
6636         
6637       return cursor_info->secondary_gc;
6638     }
6639 }
6640
6641 static void
6642 draw_insertion_cursor (GtkWidget        *widget,
6643                        GdkDrawable      *drawable,
6644                        GdkGC            *gc,
6645                        GdkRectangle     *location,
6646                        GtkTextDirection  direction,
6647                        gboolean          draw_arrow)
6648 {
6649   gint stem_width;
6650   gint arrow_width;
6651   gint x, y;
6652   gint i;
6653   gfloat cursor_aspect_ratio;
6654   gint offset;
6655   
6656   g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
6657   
6658   gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
6659   
6660   stem_width = location->height * cursor_aspect_ratio + 1;
6661   arrow_width = stem_width + 1;
6662
6663   /* put (stem_width % 2) on the proper side of the cursor */
6664   if (direction == GTK_TEXT_DIR_LTR)
6665     offset = stem_width / 2;
6666   else
6667     offset = stem_width - stem_width / 2;
6668   
6669   for (i = 0; i < stem_width; i++)
6670     gdk_draw_line (drawable, gc,
6671                    location->x + i - offset, location->y,
6672                    location->x + i - offset, location->y + location->height - 1);
6673
6674   if (draw_arrow)
6675     {
6676       if (direction == GTK_TEXT_DIR_RTL)
6677         {
6678           x = location->x - offset - 1;
6679           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6680   
6681           for (i = 0; i < arrow_width; i++)
6682             {
6683               gdk_draw_line (drawable, gc,
6684                              x, y + i + 1,
6685                              x, y + 2 * arrow_width - i - 1);
6686               x --;
6687             }
6688         }
6689       else if (direction == GTK_TEXT_DIR_LTR)
6690         {
6691           x = location->x + stem_width - offset;
6692           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6693   
6694           for (i = 0; i < arrow_width; i++) 
6695             {
6696               gdk_draw_line (drawable, gc,
6697                              x, y + i + 1,
6698                              x, y + 2 * arrow_width - i - 1);
6699               x++;
6700             }
6701         }
6702     }
6703 }
6704
6705 /**
6706  * gtk_draw_insertion_cursor:
6707  * @widget:  a #GtkWidget
6708  * @drawable: a #GdkDrawable 
6709  * @area: rectangle to which the output is clipped, or %NULL if the
6710  *        output should not be clipped
6711  * @location: location where to draw the cursor (@location->width is ignored)
6712  * @is_primary: if the cursor should be the primary cursor color.
6713  * @direction: whether the cursor is left-to-right or
6714  *             right-to-left. Should never be #GTK_TEXT_DIR_NONE
6715  * @draw_arrow: %TRUE to draw a directional arrow on the
6716  *        cursor. Should be %FALSE unless the cursor is split.
6717  * 
6718  * Draws a text caret on @drawable at @location. This is not a style function
6719  * but merely a convenience function for drawing the standard cursor shape.
6720  *
6721  * Since: 2.4
6722  **/
6723 void
6724 gtk_draw_insertion_cursor (GtkWidget        *widget,
6725                            GdkDrawable      *drawable,
6726                            GdkRectangle     *area,
6727                            GdkRectangle     *location,
6728                            gboolean          is_primary,
6729                            GtkTextDirection  direction,
6730                            gboolean          draw_arrow)
6731 {
6732   GdkGC *gc;
6733
6734   g_return_if_fail (GTK_IS_WIDGET (widget));
6735   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
6736   g_return_if_fail (location != NULL);
6737   g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
6738
6739   gc = get_insertion_cursor_gc (widget, is_primary);
6740   if (area)
6741     gdk_gc_set_clip_rectangle (gc, area);
6742   
6743   draw_insertion_cursor (widget, drawable, gc,
6744                          location, direction, draw_arrow);
6745   
6746   if (area)
6747     gdk_gc_set_clip_rectangle (gc, NULL);
6748 }
6749
6750 #define __GTK_STYLE_C__
6751 #include "gtkaliasdef.c"