]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
add trailing */ on doc comment.
[~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 <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "gtkgc.h"
31 #include "gtkrc.h"
32 #include "gtkspinbutton.h"
33 #include "gtkstyle.h"
34 #include "gtkwidget.h"
35 #include "gtkthemes.h"
36 #include "gtkiconfactory.h"
37 #include "gtksettings.h"        /* _gtk_settings_parse_convert() */
38
39 #define LIGHTNESS_MULT  1.3
40 #define DARKNESS_MULT   0.7
41
42 /* --- typedefs & structures --- */
43 typedef struct {
44   GType       widget_type;
45   GParamSpec *pspec;
46   GValue      value;
47 } PropertyValue;
48
49
50 /* --- prototypes --- */
51 static void      gtk_style_init                 (GtkStyle       *style);
52 static void      gtk_style_class_init           (GtkStyleClass  *klass);
53 static void      gtk_style_finalize             (GObject        *object);
54 static void      gtk_style_realize              (GtkStyle       *style,
55                                                  GdkColormap    *colormap);
56 static void      gtk_style_real_realize        (GtkStyle        *style);
57 static void      gtk_style_real_unrealize      (GtkStyle        *style);
58 static void      gtk_style_real_copy           (GtkStyle        *style,
59                                                 GtkStyle        *src);
60 static void      gtk_style_real_set_background (GtkStyle        *style,
61                                                 GdkWindow       *window,
62                                                 GtkStateType     state_type);
63 static GtkStyle *gtk_style_real_clone          (GtkStyle        *style);
64 static void      gtk_style_real_init_from_rc   (GtkStyle        *style,
65                                                 GtkRcStyle      *rc_style);
66 static GdkPixbuf *gtk_default_render_icon      (GtkStyle            *style,
67                                                 const GtkIconSource *source,
68                                                 GtkTextDirection     direction,
69                                                 GtkStateType         state,
70                                                 GtkIconSize          size,
71                                                 GtkWidget           *widget,
72                                                 const gchar         *detail);
73 static void gtk_default_draw_hline      (GtkStyle        *style,
74                                          GdkWindow       *window,
75                                          GtkStateType     state_type,
76                                          GdkRectangle    *area,
77                                          GtkWidget       *widget,
78                                          const gchar     *detail,
79                                          gint             x1,
80                                          gint             x2,
81                                          gint             y);
82 static void gtk_default_draw_vline      (GtkStyle        *style,
83                                          GdkWindow       *window,
84                                          GtkStateType     state_type,
85                                          GdkRectangle    *area,
86                                          GtkWidget       *widget,
87                                          const gchar     *detail,
88                                          gint             y1,
89                                          gint             y2,
90                                          gint             x);
91 static void gtk_default_draw_shadow     (GtkStyle        *style,
92                                          GdkWindow       *window,
93                                          GtkStateType     state_type,
94                                          GtkShadowType    shadow_type,
95                                          GdkRectangle    *area,
96                                          GtkWidget       *widget,
97                                          const gchar     *detail,
98                                          gint             x,
99                                          gint             y,
100                                          gint             width,
101                                          gint             height);
102 static void gtk_default_draw_polygon    (GtkStyle        *style,
103                                          GdkWindow       *window,
104                                          GtkStateType     state_type,
105                                          GtkShadowType    shadow_type,
106                                          GdkRectangle    *area,
107                                          GtkWidget       *widget,
108                                          const gchar     *detail,
109                                          GdkPoint        *points,
110                                          gint             npoints,
111                                          gboolean         fill);
112 static void gtk_default_draw_arrow      (GtkStyle        *style,
113                                          GdkWindow       *window,
114                                          GtkStateType     state_type,
115                                          GtkShadowType    shadow_type,
116                                          GdkRectangle    *area,
117                                          GtkWidget       *widget,
118                                          const gchar     *detail,
119                                          GtkArrowType     arrow_type,
120                                          gboolean         fill,
121                                          gint             x,
122                                          gint             y,
123                                          gint             width,
124                                          gint             height);
125 static void gtk_default_draw_diamond    (GtkStyle        *style,
126                                          GdkWindow       *window,
127                                          GtkStateType     state_type,
128                                          GtkShadowType    shadow_type,
129                                          GdkRectangle    *area,
130                                          GtkWidget       *widget,
131                                          const gchar     *detail,
132                                          gint             x,
133                                          gint             y,
134                                          gint             width,
135                                          gint             height);
136 static void gtk_default_draw_string     (GtkStyle        *style,
137                                          GdkWindow       *window,
138                                          GtkStateType     state_type,
139                                          GdkRectangle    *area,
140                                          GtkWidget       *widget,
141                                          const gchar     *detail,
142                                          gint             x,
143                                          gint             y,
144                                          const gchar     *string);
145 static void gtk_default_draw_box        (GtkStyle        *style,
146                                          GdkWindow       *window,
147                                          GtkStateType     state_type,
148                                          GtkShadowType    shadow_type,
149                                          GdkRectangle    *area,
150                                          GtkWidget       *widget,
151                                          const gchar     *detail,
152                                          gint             x,
153                                          gint             y,
154                                          gint             width,
155                                          gint             height);
156 static void gtk_default_draw_flat_box   (GtkStyle        *style,
157                                          GdkWindow       *window,
158                                          GtkStateType     state_type,
159                                          GtkShadowType    shadow_type,
160                                          GdkRectangle    *area,
161                                          GtkWidget       *widget,
162                                          const gchar     *detail,
163                                          gint             x,
164                                          gint             y,
165                                          gint             width,
166                                          gint             height);
167 static void gtk_default_draw_check      (GtkStyle        *style,
168                                          GdkWindow       *window,
169                                          GtkStateType     state_type,
170                                          GtkShadowType    shadow_type,
171                                          GdkRectangle    *area,
172                                          GtkWidget       *widget,
173                                          const gchar     *detail,
174                                          gint             x,
175                                          gint             y,
176                                          gint             width,
177                                          gint             height);
178 static void gtk_default_draw_option     (GtkStyle        *style,
179                                          GdkWindow       *window,
180                                          GtkStateType     state_type,
181                                          GtkShadowType    shadow_type,
182                                          GdkRectangle    *area,
183                                          GtkWidget       *widget,
184                                          const gchar     *detail,
185                                          gint             x,
186                                          gint             y,
187                                          gint             width,
188                                          gint             height);
189 static void gtk_default_draw_tab        (GtkStyle        *style,
190                                          GdkWindow       *window,
191                                          GtkStateType     state_type,
192                                          GtkShadowType    shadow_type,
193                                          GdkRectangle    *area,
194                                          GtkWidget       *widget,
195                                          const gchar     *detail,
196                                          gint             x,
197                                          gint             y,
198                                          gint             width,
199                                          gint             height);
200 static void gtk_default_draw_shadow_gap (GtkStyle        *style,
201                                          GdkWindow       *window,
202                                          GtkStateType     state_type,
203                                          GtkShadowType    shadow_type,
204                                          GdkRectangle    *area,
205                                          GtkWidget       *widget,
206                                          const gchar     *detail,
207                                          gint             x,
208                                          gint             y,
209                                          gint             width,
210                                          gint             height,
211                                          GtkPositionType  gap_side,
212                                          gint             gap_x,
213                                          gint             gap_width);
214 static void gtk_default_draw_box_gap    (GtkStyle        *style,
215                                          GdkWindow       *window,
216                                          GtkStateType     state_type,
217                                          GtkShadowType    shadow_type,
218                                          GdkRectangle    *area,
219                                          GtkWidget       *widget,
220                                          const gchar     *detail,
221                                          gint             x,
222                                          gint             y,
223                                          gint             width,
224                                          gint             height,
225                                          GtkPositionType  gap_side,
226                                          gint             gap_x,
227                                          gint             gap_width);
228 static void gtk_default_draw_extension  (GtkStyle        *style,
229                                          GdkWindow       *window,
230                                          GtkStateType     state_type,
231                                          GtkShadowType    shadow_type,
232                                          GdkRectangle    *area,
233                                          GtkWidget       *widget,
234                                          const gchar     *detail,
235                                          gint             x,
236                                          gint             y,
237                                          gint             width,
238                                          gint             height,
239                                          GtkPositionType  gap_side);
240 static void gtk_default_draw_focus      (GtkStyle        *style,
241                                          GdkWindow       *window,
242                                          GtkStateType     state_type,
243                                          GdkRectangle    *area,
244                                          GtkWidget       *widget,
245                                          const gchar     *detail,
246                                          gint             x,
247                                          gint             y,
248                                          gint             width,
249                                          gint             height);
250 static void gtk_default_draw_slider     (GtkStyle        *style,
251                                          GdkWindow       *window,
252                                          GtkStateType     state_type,
253                                          GtkShadowType    shadow_type,
254                                          GdkRectangle    *area,
255                                          GtkWidget       *widget,
256                                          const gchar     *detail,
257                                          gint             x,
258                                          gint             y,
259                                          gint             width,
260                                          gint             height,
261                                          GtkOrientation   orientation);
262 static void gtk_default_draw_handle     (GtkStyle        *style,
263                                          GdkWindow       *window,
264                                          GtkStateType     state_type,
265                                          GtkShadowType    shadow_type,
266                                          GdkRectangle    *area,
267                                          GtkWidget       *widget,
268                                          const gchar     *detail,
269                                          gint             x,
270                                          gint             y,
271                                          gint             width,
272                                          gint             height,
273                                          GtkOrientation   orientation);
274 static void gtk_default_draw_expander   (GtkStyle        *style,
275                                          GdkWindow       *window,
276                                          GtkStateType     state_type,
277                                          GdkRectangle    *area,
278                                          GtkWidget       *widget,
279                                          const gchar     *detail,
280                                          gint             x,
281                                          gint             y,
282                                          GtkExpanderStyle expander_style);
283 static void gtk_default_draw_layout     (GtkStyle        *style,
284                                          GdkWindow       *window,
285                                          GtkStateType     state_type,
286                                          gboolean         use_text,
287                                          GdkRectangle    *area,
288                                          GtkWidget       *widget,
289                                          const gchar     *detail,
290                                          gint             x,
291                                          gint             y,
292                                          PangoLayout     *layout);
293 static void gtk_default_draw_resize_grip (GtkStyle       *style,
294                                           GdkWindow      *window,
295                                           GtkStateType    state_type,
296                                           GdkRectangle   *area,
297                                           GtkWidget      *widget,
298                                           const gchar    *detail,
299                                           GdkWindowEdge   edge,
300                                           gint            x,
301                                           gint            y,
302                                           gint            width,
303                                           gint            height);
304
305 static void gtk_style_shade             (GdkColor        *a,
306                                          GdkColor        *b,
307                                          gdouble          k);
308 static void rgb_to_hls                  (gdouble         *r,
309                                          gdouble         *g,
310                                          gdouble         *b);
311 static void hls_to_rgb                  (gdouble         *h,
312                                          gdouble         *l,
313                                          gdouble         *s);
314
315
316 /*
317  * Data for default check and radio buttons
318  */
319
320 static GtkRequisition default_option_indicator_size = { 7, 13 };
321 static GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 };
322
323 #define INDICATOR_PART_SIZE 13
324
325 typedef enum {
326   CHECK_AA,
327   CHECK_BASE,
328   CHECK_BLACK,
329   CHECK_DARK,
330   CHECK_LIGHT,
331   CHECK_MID,
332   CHECK_TEXT,
333   RADIO_BASE,
334   RADIO_BLACK,
335   RADIO_DARK,
336   RADIO_LIGHT,
337   RADIO_MID,
338   RADIO_TEXT
339 } IndicatorPart;
340
341 static char check_aa_bits[] = {
342  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x58,0x00,0xa0,
343  0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
344 static char check_base_bits[] = {
345  0x00,0x00,0x00,0x00,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
346  0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0x00,0x00,0x00,0x00};
347 static char check_black_bits[] = {
348  0x00,0x00,0xfe,0x0f,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
349  0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00};
350 static char check_dark_bits[] = {
351  0xff,0x1f,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
352  0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00};
353 static char check_light_bits[] = {
354  0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
355  0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xfe,0x1f};
356 static char check_mid_bits[] = {
357  0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
358  0x08,0x00,0x08,0x00,0x08,0x00,0x08,0xfc,0x0f,0x00,0x00};
359 static char check_text_bits[] = {
360  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x80,0x01,0x80,0x00,0xd8,
361  0x00,0x60,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
362 static char radio_base_bits[] = {
363  0x00,0x00,0x00,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,
364  0x07,0xfc,0x07,0xf8,0x03,0xf0,0x01,0x00,0x00,0x00,0x00};
365 static char radio_black_bits[] = {
366  0x00,0x00,0xf0,0x01,0x08,0x02,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,
367  0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
368 static char radio_dark_bits[] = {
369  0xf0,0x01,0x08,0x02,0x04,0x04,0x02,0x04,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
370  0x00,0x01,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x00};
371 static char radio_light_bits[] = {
372  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x10,0x00,
373  0x10,0x00,0x10,0x00,0x08,0x00,0x04,0x08,0x02,0xf0,0x01};
374 static char radio_mid_bits[] = {
375  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
376  0x08,0x00,0x08,0x00,0x04,0x00,0x02,0xf0,0x01,0x00,0x00};
377 static char radio_text_bits[] = {
378  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0x01,0xf0,0x01,0xf0,
379  0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
380
381 static struct {
382   char      *bits;
383   GdkBitmap *bmap;
384 } indicator_parts[] = {
385   { check_aa_bits, NULL },
386   { check_base_bits, NULL },
387   { check_black_bits, NULL },
388   { check_dark_bits, NULL },
389   { check_light_bits, NULL },
390   { check_mid_bits, NULL },
391   { check_text_bits, NULL },
392   { radio_base_bits, NULL },
393   { radio_black_bits, NULL },
394   { radio_dark_bits, NULL },
395   { radio_light_bits, NULL },
396   { radio_mid_bits, NULL },
397   { radio_text_bits, NULL }
398 };
399
400 /* --- variables --- */
401 static GdkColor gtk_default_normal_fg =      { 0,      0,      0,      0 };
402 static GdkColor gtk_default_active_fg =      { 0,      0,      0,      0 };
403 static GdkColor gtk_default_prelight_fg =    { 0,      0,      0,      0 };
404 static GdkColor gtk_default_selected_fg =    { 0, 0xffff, 0xffff, 0xffff };
405 static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 };
406
407 static GdkColor gtk_default_normal_bg =      { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
408 static GdkColor gtk_default_active_bg =      { 0, 0xc350, 0xc350, 0xc350 };
409 static GdkColor gtk_default_prelight_bg =    { 0, 0xea60, 0xea60, 0xea60 };
410 static GdkColor gtk_default_selected_bg =    { 0,      0,      0, 0x9c40 };
411 static GdkColor gtk_default_insensitive_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
412 static GdkColor gtk_default_selected_base =  { 0, 0xa4a4, 0xdfdf, 0xffff };
413 static GdkColor gtk_default_active_base =    { 0, 0xbcbc, 0xd2d2, 0xeeee };
414
415 static gpointer parent_class = NULL;
416
417
418 /* --- functions --- */
419 GType
420 gtk_style_get_type (void)
421 {
422   static GType style_type = 0;
423   
424   if (!style_type)
425     {
426       static const GTypeInfo style_info =
427       {
428         sizeof (GtkStyleClass),
429         (GBaseInitFunc) NULL,
430         (GBaseFinalizeFunc) NULL,
431         (GClassInitFunc) gtk_style_class_init,
432         NULL,           /* class_finalize */
433         NULL,           /* class_data */
434         sizeof (GtkStyle),
435         0,              /* n_preallocs */
436         (GInstanceInitFunc) gtk_style_init,
437       };
438       
439       style_type = g_type_register_static (G_TYPE_OBJECT,
440                                            "GtkStyle",
441                                            &style_info, 0);
442     }
443   
444   return style_type;
445 }
446
447 static void
448 gtk_style_init (GtkStyle *style)
449 {
450   gint i;
451   
452   style->font_desc = pango_font_description_from_string ("Sans 10");
453
454   style->attach_count = 0;
455   style->colormap = NULL;
456   style->depth = -1;
457   
458   style->black.red = 0;
459   style->black.green = 0;
460   style->black.blue = 0;
461   
462   style->white.red = 65535;
463   style->white.green = 65535;
464   style->white.blue = 65535;
465   
466   style->black_gc = NULL;
467   style->white_gc = NULL;
468   
469   style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
470   style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
471   style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
472   style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
473   style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
474   
475   style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
476   style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
477   style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
478   style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
479   style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
480   
481   for (i = 0; i < 4; i++)
482     {
483       style->text[i] = style->fg[i];
484       style->base[i] = style->white;
485     }
486
487   style->base[GTK_STATE_SELECTED] = gtk_default_selected_base;
488   style->text[GTK_STATE_SELECTED] = style->black;
489   style->base[GTK_STATE_ACTIVE] = gtk_default_active_base;
490   style->text[GTK_STATE_ACTIVE] = style->black;
491   style->base[GTK_STATE_INSENSITIVE] = gtk_default_prelight_bg;
492   style->text[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
493   
494   for (i = 0; i < 5; i++)
495     style->bg_pixmap[i] = NULL;
496   
497   style->rc_style = NULL;
498   
499   for (i = 0; i < 5; i++)
500     {
501       style->fg_gc[i] = NULL;
502       style->bg_gc[i] = NULL;
503       style->light_gc[i] = NULL;
504       style->dark_gc[i] = NULL;
505       style->mid_gc[i] = NULL;
506       style->text_gc[i] = NULL;
507       style->base_gc[i] = NULL;
508       style->text_aa_gc[i] = NULL;
509     }
510
511   style->xthickness = 2;
512   style->ythickness = 2;
513
514   style->property_cache = NULL;
515 }
516
517 static void
518 gtk_style_class_init (GtkStyleClass *klass)
519 {
520   GObjectClass *object_class = G_OBJECT_CLASS (klass);
521   
522   parent_class = g_type_class_peek_parent (klass);
523
524   object_class->finalize = gtk_style_finalize;
525
526   klass->clone = gtk_style_real_clone;
527   klass->copy = gtk_style_real_copy;
528   klass->init_from_rc = gtk_style_real_init_from_rc;
529   klass->realize = gtk_style_real_realize;
530   klass->unrealize = gtk_style_real_unrealize;
531   klass->set_background = gtk_style_real_set_background;
532   klass->render_icon = gtk_default_render_icon;
533
534   klass->draw_hline = gtk_default_draw_hline;
535   klass->draw_vline = gtk_default_draw_vline;
536   klass->draw_shadow = gtk_default_draw_shadow;
537   klass->draw_polygon = gtk_default_draw_polygon;
538   klass->draw_arrow = gtk_default_draw_arrow;
539   klass->draw_diamond = gtk_default_draw_diamond;
540   klass->draw_string = gtk_default_draw_string;
541   klass->draw_box = gtk_default_draw_box;
542   klass->draw_flat_box = gtk_default_draw_flat_box;
543   klass->draw_check = gtk_default_draw_check;
544   klass->draw_option = gtk_default_draw_option;
545   klass->draw_tab = gtk_default_draw_tab;
546   klass->draw_shadow_gap = gtk_default_draw_shadow_gap;
547   klass->draw_box_gap = gtk_default_draw_box_gap;
548   klass->draw_extension = gtk_default_draw_extension;
549   klass->draw_focus = gtk_default_draw_focus;
550   klass->draw_slider = gtk_default_draw_slider;
551   klass->draw_handle = gtk_default_draw_handle;
552   klass->draw_expander = gtk_default_draw_expander;
553   klass->draw_layout = gtk_default_draw_layout;
554   klass->draw_resize_grip = gtk_default_draw_resize_grip;
555 }
556
557 static void
558 clear_property_cache (GtkStyle *style)
559 {
560   if (style->property_cache)
561     {
562       guint i;
563
564       for (i = 0; i < style->property_cache->len; i++)
565         {
566           PropertyValue *node = &g_array_index (style->property_cache, PropertyValue, i);
567
568           g_param_spec_unref (node->pspec);
569           g_value_unset (&node->value);
570         }
571       g_array_free (style->property_cache, TRUE);
572       style->property_cache = NULL;
573     }
574 }
575
576 static void
577 gtk_style_finalize (GObject *object)
578 {
579   GtkStyle *style = GTK_STYLE (object);
580
581   g_return_if_fail (style->attach_count == 0);
582
583   clear_property_cache (style);
584   
585   if (style->styles)
586     {
587       if (style->styles->data != style)
588         g_slist_remove (style->styles, style);
589       else
590         {
591           GSList *tmp_list = style->styles->next;
592           
593           while (tmp_list)
594             {
595               GTK_STYLE (tmp_list->data)->styles = style->styles->next;
596               tmp_list = tmp_list->next;
597             }
598           g_slist_free_1 (style->styles);
599         }
600     }
601
602   pango_font_description_free (style->font_desc);
603   
604   if (style->private_font)
605     gdk_font_unref (style->private_font);
606
607   if (style->private_font_desc)
608     pango_font_description_free (style->private_font_desc);
609   
610   if (style->rc_style)
611     gtk_rc_style_unref (style->rc_style);
612   
613   G_OBJECT_CLASS (parent_class)->finalize (object);
614 }
615
616
617 GtkStyle*
618 gtk_style_copy (GtkStyle *style)
619 {
620   GtkStyle *new_style;
621   
622   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
623   
624   new_style = GTK_STYLE_GET_CLASS (style)->clone (style);
625   GTK_STYLE_GET_CLASS (style)->copy (new_style, style);
626
627   return new_style;
628 }
629
630 static GtkStyle*
631 gtk_style_duplicate (GtkStyle *style)
632 {
633   GtkStyle *new_style;
634   
635   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
636   
637   new_style = gtk_style_copy (style);
638   
639   style->styles = g_slist_append (style->styles, new_style);
640   new_style->styles = style->styles;  
641   
642   return new_style;
643 }
644
645 /**
646  * gtk_style_new:
647  * @returns: a new #GtkStyle.
648  *
649  * Creates a new #GtkStyle.
650  **/
651 GtkStyle*
652 gtk_style_new (void)
653 {
654   GtkStyle *style;
655   
656   style = g_object_new (GTK_TYPE_STYLE, NULL);
657   
658   return style;
659 }
660
661 /**
662  * gtk_style_attach:
663  * @style: a #GtkStyle.
664  * @window: a #GtkWindow.
665  * @returns: Either @style, or a newly-created #GtkStyle.
666  *   If the style is newly created, the style parameter
667  *   will be dereferenced, and the new style will have
668  *   a reference count belonging to the caller.
669  *
670  * Attaches a style to a window; this process allocates the
671  * colors and creates the GC's for the style - it specializes
672  * it to a particular visual and colormap. The process may 
673  * involve the creation of a new style if the style has already 
674  * been attached to a window with a different style and colormap.
675  **/
676  /*
677  * FIXME: The sequence - 
678  *    create a style => s1
679  *    attach s1 to v1, c1 => s1
680  *    attach s1 to v2, c2 => s2
681  *    detach s1 from v1, c1
682  *    attach s1 to v2, c2 => s3
683  * results in two separate, unlinked styles s2 and s3 which
684  * are identical and could be shared. To fix this, we would
685  * want to never remove a style from the list of linked
686  * styles as long as as it has a reference count. However, the 
687  * disadvantage of doing it this way means that we would need two 
688  * passes through the linked list when attaching (one to check for 
689  * matching styles, one to look for empty unattached styles - but 
690  * it will almost never be longer than 2 elements.
691  */
692 GtkStyle*
693 gtk_style_attach (GtkStyle  *style,
694                   GdkWindow *window)
695 {
696   GSList *styles;
697   GtkStyle *new_style = NULL;
698   GdkColormap *colormap;
699   
700   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
701   g_return_val_if_fail (window != NULL, NULL);
702   
703   colormap = gdk_window_get_colormap (window);
704   
705   if (!style->styles)
706     style->styles = g_slist_append (NULL, style);
707   
708   styles = style->styles;
709   while (styles)
710     {
711       new_style = styles->data;
712       
713       if (new_style->attach_count == 0)
714         {
715           gtk_style_realize (new_style, colormap);
716           break;
717         }
718       else if (new_style->colormap == colormap)
719         break;
720       
721       new_style = NULL;
722       styles = styles->next;
723     }
724   
725   if (!new_style)
726     {
727       new_style = gtk_style_duplicate (style);
728       gtk_style_realize (new_style, colormap);
729     }
730
731   /* A style gets a refcount from being attached */
732   if (new_style->attach_count == 0)
733     g_object_ref (new_style);
734
735   /* Another refcount belongs to the parent */
736   if (style != new_style) 
737     {
738       g_object_unref (style);
739       g_object_ref (new_style);
740     }
741   
742   new_style->attach_count++;
743   
744   return new_style;
745 }
746
747 void
748 gtk_style_detach (GtkStyle *style)
749 {
750   g_return_if_fail (GTK_IS_STYLE (style));
751   
752   style->attach_count -= 1;
753   if (style->attach_count == 0)
754     {
755       GTK_STYLE_GET_CLASS (style)->unrealize (style);
756       
757       gdk_colormap_unref (style->colormap);
758       style->colormap = NULL;
759       
760       g_object_unref (style);
761     }
762 }
763
764 /**
765  * gtk_style_ref:
766  * @style: a #GtkStyle.
767  * @returns: @style.
768  *
769  * Deprecated equivalent of g_object_ref().
770  **/
771 GtkStyle*
772 gtk_style_ref (GtkStyle *style)
773 {
774   return (GtkStyle *) g_object_ref (G_OBJECT (style));
775 }
776
777 /**
778  * gtk_style_unref:
779  * @style: a #GtkStyle.
780  *
781  * Deprecated equivalent of g_object_unref().
782  **/
783 void
784 gtk_style_unref (GtkStyle *style)
785 {
786   g_object_unref (G_OBJECT (style));
787 }
788
789 static void
790 gtk_style_realize (GtkStyle    *style,
791                    GdkColormap *colormap)
792 {
793   g_return_if_fail (GTK_IS_STYLE (style));
794   g_return_if_fail (GDK_IS_COLORMAP (colormap));
795   
796   style->colormap = gdk_colormap_ref (colormap);
797   style->depth = gdk_colormap_get_visual (colormap)->depth;
798
799   GTK_STYLE_GET_CLASS (style)->realize (style);
800 }
801
802 GtkIconSet*
803 gtk_style_lookup_icon_set (GtkStyle   *style,
804                            const char *stock_id)
805 {
806   GSList *iter;
807
808   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
809   g_return_val_if_fail (stock_id != NULL, NULL);
810   
811   iter = style->icon_factories;
812   while (iter != NULL)
813     {
814       GtkIconSet *icon_set = gtk_icon_factory_lookup (GTK_ICON_FACTORY (iter->data),
815                                                       stock_id);
816       if (icon_set)
817         return icon_set;
818       
819       iter = g_slist_next (iter);
820     }
821
822   return gtk_icon_factory_lookup_default (stock_id);
823 }
824
825 /**
826  * gtk_draw_hline:
827  * @style: a #GtkStyle
828  * @window: a #GdkWindow
829  * @state_type: a state
830  * @x1: the starting x coordinate
831  * @x2: the ending x coordinate
832  * @y: the y coordinate
833  * 
834  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
835  * using the given style and state.
836  * 
837  * This function is deprecated, use gtk_paint_hline() instead.
838  **/
839 void
840 gtk_draw_hline (GtkStyle     *style,
841                 GdkWindow    *window,
842                 GtkStateType  state_type,
843                 gint          x1,
844                 gint          x2,
845                 gint          y)
846 {
847   g_return_if_fail (GTK_IS_STYLE (style));
848   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
849   
850   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, NULL, NULL, NULL, x1, x2, y);
851 }
852
853
854 /**
855  * gtk_draw_vline:
856  * @style: a #GtkStyle
857  * @window: a #GdkWindow
858  * @state_type: a state
859  * @y1: the starting y coordinate
860  * @y2: the ending y coordinate
861  * @x: the x coordinate
862  * 
863  * Draws a vertical line from (@x, @y1) to (@x, @y2) in @window
864  * using the given style and state.
865  * 
866  * This function is deprecated, use gtk_paint_vline() instead.
867  **/
868 void
869 gtk_draw_vline (GtkStyle     *style,
870                 GdkWindow    *window,
871                 GtkStateType  state_type,
872                 gint          y1,
873                 gint          y2,
874                 gint          x)
875 {
876   g_return_if_fail (GTK_IS_STYLE (style));
877   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
878   
879   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, NULL, NULL, NULL, y1, y2, x);
880 }
881
882
883 void
884 gtk_draw_shadow (GtkStyle      *style,
885                  GdkWindow     *window,
886                  GtkStateType   state_type,
887                  GtkShadowType  shadow_type,
888                  gint           x,
889                  gint           y,
890                  gint           width,
891                  gint           height)
892 {
893   g_return_if_fail (GTK_IS_STYLE (style));
894   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
895   
896   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
897 }
898
899 void
900 gtk_draw_polygon (GtkStyle      *style,
901                   GdkWindow     *window,
902                   GtkStateType   state_type,
903                   GtkShadowType  shadow_type,
904                   GdkPoint      *points,
905                   gint           npoints,
906                   gboolean       fill)
907 {
908   g_return_if_fail (GTK_IS_STYLE (style));
909   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_polygon != NULL);
910   
911   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, NULL, NULL, NULL, points, npoints, fill);
912 }
913
914 void
915 gtk_draw_arrow (GtkStyle      *style,
916                 GdkWindow     *window,
917                 GtkStateType   state_type,
918                 GtkShadowType  shadow_type,
919                 GtkArrowType   arrow_type,
920                 gboolean       fill,
921                 gint           x,
922                 gint           y,
923                 gint           width,
924                 gint           height)
925 {
926   g_return_if_fail (GTK_IS_STYLE (style));
927   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
928   
929   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, NULL, NULL, NULL, arrow_type, fill, x, y, width, height);
930 }
931
932
933 void
934 gtk_draw_diamond (GtkStyle      *style,
935                   GdkWindow     *window,
936                   GtkStateType   state_type,
937                   GtkShadowType  shadow_type,
938                   gint           x,
939                   gint           y,
940                   gint           width,
941                   gint           height)
942 {
943   g_return_if_fail (GTK_IS_STYLE (style));
944   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
945   
946   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
947 }
948
949
950 void
951 gtk_draw_string (GtkStyle      *style,
952                  GdkWindow     *window,
953                  GtkStateType   state_type,
954                  gint           x,
955                  gint           y,
956                  const gchar   *string)
957 {
958   g_return_if_fail (GTK_IS_STYLE (style));
959   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
960   
961   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, NULL, NULL, NULL, x, y, string);
962 }
963
964 void
965 gtk_draw_box (GtkStyle      *style,
966               GdkWindow     *window,
967               GtkStateType   state_type,
968               GtkShadowType  shadow_type,
969               gint           x,
970               gint           y,
971               gint           width,
972               gint           height)
973 {
974   g_return_if_fail (GTK_IS_STYLE (style));
975   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
976   
977   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
978 }
979
980 void
981 gtk_draw_flat_box (GtkStyle      *style,
982                    GdkWindow     *window,
983                    GtkStateType   state_type,
984                    GtkShadowType  shadow_type,
985                    gint           x,
986                    gint           y,
987                    gint           width,
988                    gint           height)
989 {
990   g_return_if_fail (GTK_IS_STYLE (style));
991   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
992   
993   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
994 }
995
996 void
997 gtk_draw_check (GtkStyle      *style,
998                 GdkWindow     *window,
999                 GtkStateType   state_type,
1000                 GtkShadowType  shadow_type,
1001                 gint           x,
1002                 gint           y,
1003                 gint           width,
1004                 gint           height)
1005 {
1006   g_return_if_fail (GTK_IS_STYLE (style));
1007   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
1008   
1009   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1010 }
1011
1012 void
1013 gtk_draw_option (GtkStyle      *style,
1014                  GdkWindow     *window,
1015                  GtkStateType   state_type,
1016                  GtkShadowType  shadow_type,
1017                  gint           x,
1018                  gint           y,
1019                  gint           width,
1020                  gint           height)
1021 {
1022   g_return_if_fail (GTK_IS_STYLE (style));
1023   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
1024   
1025   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1026 }
1027
1028 void
1029 gtk_draw_tab (GtkStyle      *style,
1030               GdkWindow     *window,
1031               GtkStateType   state_type,
1032               GtkShadowType  shadow_type,
1033               gint           x,
1034               gint           y,
1035               gint           width,
1036               gint           height)
1037 {
1038   g_return_if_fail (GTK_IS_STYLE (style));
1039   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
1040   
1041   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height);
1042 }
1043
1044 void
1045 gtk_draw_shadow_gap (GtkStyle       *style,
1046                      GdkWindow      *window,
1047                      GtkStateType    state_type,
1048                      GtkShadowType   shadow_type,
1049                      gint            x,
1050                      gint            y,
1051                      gint            width,
1052                      gint            height,
1053                      GtkPositionType gap_side,
1054                      gint            gap_x,
1055                      gint            gap_width)
1056 {
1057   g_return_if_fail (GTK_IS_STYLE (style));
1058   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
1059   
1060   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);
1061 }
1062
1063 void
1064 gtk_draw_box_gap (GtkStyle       *style,
1065                   GdkWindow      *window,
1066                   GtkStateType    state_type,
1067                   GtkShadowType   shadow_type,
1068                   gint            x,
1069                   gint            y,
1070                   gint            width,
1071                   gint            height,
1072                   GtkPositionType gap_side,
1073                   gint            gap_x,
1074                   gint            gap_width)
1075 {
1076   g_return_if_fail (GTK_IS_STYLE (style));
1077   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
1078   
1079   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);
1080 }
1081
1082 void
1083 gtk_draw_extension (GtkStyle       *style,
1084                     GdkWindow      *window,
1085                     GtkStateType    state_type,
1086                     GtkShadowType   shadow_type,
1087                     gint            x,
1088                     gint            y,
1089                     gint            width,
1090                     gint            height,
1091                     GtkPositionType gap_side)
1092 {
1093   g_return_if_fail (GTK_IS_STYLE (style));
1094   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
1095   
1096   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, gap_side);
1097 }
1098
1099 void
1100 gtk_draw_focus (GtkStyle      *style,
1101                 GdkWindow     *window,
1102                 gint           x,
1103                 gint           y,
1104                 gint           width,
1105                 gint           height)
1106 {
1107   g_return_if_fail (GTK_IS_STYLE (style));
1108   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
1109   
1110   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, GTK_STATE_NORMAL, NULL, NULL, NULL, x, y, width, height);
1111 }
1112
1113 void 
1114 gtk_draw_slider (GtkStyle      *style,
1115                  GdkWindow     *window,
1116                  GtkStateType   state_type,
1117                  GtkShadowType  shadow_type,
1118                  gint           x,
1119                  gint           y,
1120                  gint           width,
1121                  gint           height,
1122                  GtkOrientation orientation)
1123 {
1124   g_return_if_fail (GTK_IS_STYLE (style));
1125   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
1126   
1127   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation);
1128 }
1129
1130 void 
1131 gtk_draw_handle (GtkStyle      *style,
1132                  GdkWindow     *window,
1133                  GtkStateType   state_type,
1134                  GtkShadowType  shadow_type,
1135                  gint           x,
1136                  gint           y,
1137                  gint           width,
1138                  gint           height,
1139                  GtkOrientation orientation)
1140 {
1141   g_return_if_fail (GTK_IS_STYLE (style));
1142   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
1143   
1144   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, NULL, NULL, NULL, x, y, width, height, orientation);
1145 }
1146
1147 void
1148 gtk_draw_expander (GtkStyle        *style,
1149                    GdkWindow       *window,
1150                    GtkStateType     state_type,
1151                    gint             x,
1152                    gint             y,
1153                    GtkExpanderStyle expander_style)
1154 {
1155   g_return_if_fail (GTK_IS_STYLE (style));
1156   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
1157   
1158   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type,
1159                                               NULL, NULL, NULL,
1160                                               x, y, expander_style);
1161 }
1162
1163 void
1164 gtk_draw_layout (GtkStyle        *style,
1165                  GdkWindow       *window,
1166                  GtkStateType     state_type,
1167                  gboolean         use_text,
1168                  gint             x,
1169                  gint             y,
1170                  PangoLayout     *layout)
1171 {
1172   g_return_if_fail (GTK_IS_STYLE (style));
1173   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
1174   
1175   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text,
1176                                             NULL, NULL, NULL,
1177                                             x, y, layout);
1178 }
1179
1180 void
1181 gtk_draw_resize_grip (GtkStyle     *style,
1182                       GdkWindow    *window,
1183                       GtkStateType  state_type,
1184                       GdkWindowEdge edge,
1185                       gint          x,
1186                       gint          y,
1187                       gint          width,
1188                       gint          height)
1189 {
1190   g_return_if_fail (GTK_IS_STYLE (style));
1191   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
1192
1193   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
1194                                                  NULL, NULL, NULL,
1195                                                  edge,
1196                                                  x, y, width, height);
1197 }
1198
1199
1200 void
1201 gtk_style_set_background (GtkStyle    *style,
1202                           GdkWindow   *window,
1203                           GtkStateType state_type)
1204 {
1205   g_return_if_fail (GTK_IS_STYLE (style));
1206   g_return_if_fail (window != NULL);
1207   
1208   GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
1209 }
1210
1211 /* Default functions */
1212 static GtkStyle *
1213 gtk_style_real_clone (GtkStyle *style)
1214 {
1215   return GTK_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
1216 }
1217
1218 static void
1219 gtk_style_real_copy (GtkStyle *style,
1220                      GtkStyle *src)
1221 {
1222   gint i;
1223   
1224   for (i = 0; i < 5; i++)
1225     {
1226       style->fg[i] = src->fg[i];
1227       style->bg[i] = src->bg[i];
1228       style->text[i] = src->text[i];
1229       style->base[i] = src->base[i];
1230       
1231       style->bg_pixmap[i] = src->bg_pixmap[i];
1232     }
1233
1234   if (style->private_font)
1235     gdk_font_unref (style->private_font);
1236   style->private_font = src->private_font;
1237   if (style->private_font)
1238     gdk_font_ref (style->private_font);
1239
1240   if (style->font_desc)
1241     pango_font_description_free (style->font_desc);
1242   if (src->font_desc)
1243     style->font_desc = pango_font_description_copy (src->font_desc);
1244   else
1245     style->font_desc = NULL;
1246   
1247   style->xthickness = src->xthickness;
1248   style->ythickness = src->ythickness;
1249
1250   if (style->rc_style)
1251     gtk_rc_style_unref (style->rc_style);
1252   style->rc_style = src->rc_style;
1253   if (src->rc_style)
1254     gtk_rc_style_ref (src->rc_style);
1255
1256   /* don't copy, just clear cache */
1257   clear_property_cache (style);
1258 }
1259
1260 static void
1261 gtk_style_real_init_from_rc (GtkStyle   *style,
1262                              GtkRcStyle *rc_style)
1263 {
1264   gint i;
1265
1266   /* cache _should_ be still empty */
1267   clear_property_cache (style);
1268
1269   if (rc_style->font_desc)
1270     pango_font_description_merge (style->font_desc, rc_style->font_desc, TRUE);
1271     
1272   for (i = 0; i < 5; i++)
1273     {
1274       if (rc_style->color_flags[i] & GTK_RC_FG)
1275         style->fg[i] = rc_style->fg[i];
1276       if (rc_style->color_flags[i] & GTK_RC_BG)
1277         style->bg[i] = rc_style->bg[i];
1278       if (rc_style->color_flags[i] & GTK_RC_TEXT)
1279         style->text[i] = rc_style->text[i];
1280       if (rc_style->color_flags[i] & GTK_RC_BASE)
1281         style->base[i] = rc_style->base[i];
1282     }
1283
1284   if (rc_style->xthickness >= 0)
1285     style->xthickness = rc_style->xthickness;
1286   if (rc_style->ythickness >= 0)
1287     style->ythickness = rc_style->ythickness;
1288
1289   if (rc_style->icon_factories)
1290     {
1291       GSList *iter;
1292
1293       style->icon_factories = g_slist_copy (rc_style->icon_factories);
1294       
1295       iter = style->icon_factories;
1296       while (iter != NULL)
1297         {
1298           g_object_ref (G_OBJECT (iter->data));
1299           
1300           iter = g_slist_next (iter);
1301         }
1302     }
1303 }
1304
1305 static gint
1306 style_property_values_cmp (gconstpointer bsearch_node1,
1307                            gconstpointer bsearch_node2)
1308 {
1309   const PropertyValue *val1 = bsearch_node1;
1310   const PropertyValue *val2 = bsearch_node2;
1311
1312   if (val1->widget_type == val2->widget_type)
1313     return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
1314   else
1315     return val1->widget_type < val2->widget_type ? -1 : 1;
1316 }
1317
1318 const GValue*
1319 _gtk_style_peek_property_value (GtkStyle           *style,
1320                                 GType               widget_type,
1321                                 GParamSpec         *pspec,
1322                                 GtkRcPropertyParser parser)
1323 {
1324   PropertyValue *pcache, key = { 0, NULL, { 0, } };
1325   const GtkRcProperty *rcprop = NULL;
1326   guint i;
1327
1328   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1329   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
1330   g_return_val_if_fail (g_type_is_a (pspec->owner_type, GTK_TYPE_WIDGET), NULL);
1331   g_return_val_if_fail (g_type_is_a (widget_type, pspec->owner_type), NULL);
1332
1333   key.widget_type = widget_type;
1334   key.pspec = pspec;
1335
1336   /* need value cache array */
1337   if (!style->property_cache)
1338     style->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
1339   else
1340     {
1341       pcache = bsearch (&key,
1342                         style->property_cache->data, style->property_cache->len,
1343                         sizeof (PropertyValue), style_property_values_cmp);
1344       if (pcache)
1345         return &pcache->value;
1346     }
1347
1348   i = 0;
1349   while (i < style->property_cache->len &&
1350          style_property_values_cmp (&key, &g_array_index (style->property_cache, PropertyValue, i)) >= 0)
1351     i++;
1352
1353   g_array_insert_val (style->property_cache, i, key);
1354   pcache = &g_array_index (style->property_cache, PropertyValue, i);
1355
1356   /* cache miss, initialize value type, then set contents */
1357   g_param_spec_ref (pcache->pspec);
1358   g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1359
1360   /* value provided by rc style? */
1361   if (style->rc_style)
1362     {
1363       GQuark prop_quark = g_quark_from_string (pspec->name);
1364
1365       do
1366         {
1367           rcprop = _gtk_rc_style_lookup_rc_property (style->rc_style,
1368                                                      g_type_qname (widget_type),
1369                                                      prop_quark);
1370           if (rcprop)
1371             break;
1372           widget_type = g_type_parent (widget_type);
1373         }
1374       while (g_type_is_a (widget_type, pspec->owner_type));
1375     }
1376
1377   /* when supplied by rc style, we need to convert */
1378   if (rcprop && !_gtk_settings_parse_convert (parser, &rcprop->value,
1379                                               pspec, &pcache->value))
1380     {
1381       gchar *contents = g_strdup_value_contents (&rcprop->value);
1382       
1383       g_message ("%s: failed to retrieve property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
1384                  rcprop->origin,
1385                  g_type_name (pspec->owner_type), pspec->name,
1386                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1387                  contents,
1388                  G_VALUE_TYPE_NAME (&rcprop->value));
1389       g_free (contents);
1390       rcprop = NULL; /* needs default */
1391     }
1392   
1393   /* not supplied by rc style (or conversion failed), revert to default */
1394   if (!rcprop)
1395     g_param_value_set_default (pspec, &pcache->value);
1396
1397   return &pcache->value;
1398 }
1399
1400 static GdkPixmap *
1401 load_bg_image (GdkColormap *colormap,
1402                GdkColor    *bg_color,
1403                const gchar *filename)
1404 {
1405   if (strcmp (filename, "<parent>") == 0)
1406     return (GdkPixmap*) GDK_PARENT_RELATIVE;
1407   else
1408     {
1409       return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
1410                                                   bg_color,
1411                                                   filename);
1412     }
1413 }
1414
1415 static void
1416 gtk_style_real_realize (GtkStyle *style)
1417 {
1418   GdkGCValues gc_values;
1419   GdkGCValuesMask gc_values_mask;
1420   
1421   gint i;
1422
1423   for (i = 0; i < 5; i++)
1424     {
1425       gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
1426       gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
1427       
1428       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1429       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
1430       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1431
1432       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1433       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
1434       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
1435     }
1436   
1437   gdk_color_black (style->colormap, &style->black);
1438   gdk_color_white (style->colormap, &style->white);
1439   
1440   gc_values_mask = GDK_GC_FOREGROUND;
1441   
1442   gc_values.foreground = style->black;
1443   style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1444   
1445   gc_values.foreground = style->white;
1446   style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1447   
1448   for (i = 0; i < 5; i++)
1449     {
1450       if (style->rc_style && style->rc_style->bg_pixmap_name[i])
1451         style->bg_pixmap[i] = load_bg_image (style->colormap,
1452                                              &style->bg[i],
1453                                              style->rc_style->bg_pixmap_name[i]);
1454       
1455       if (!gdk_color_alloc (style->colormap, &style->fg[i]))
1456         g_warning ("unable to allocate color: ( %d %d %d )",
1457                    style->fg[i].red, style->fg[i].green, style->fg[i].blue);
1458       if (!gdk_color_alloc (style->colormap, &style->bg[i]))
1459         g_warning ("unable to allocate color: ( %d %d %d )",
1460                    style->bg[i].red, style->bg[i].green, style->bg[i].blue);
1461       if (!gdk_color_alloc (style->colormap, &style->light[i]))
1462         g_warning ("unable to allocate color: ( %d %d %d )",
1463                    style->light[i].red, style->light[i].green, style->light[i].blue);
1464       if (!gdk_color_alloc (style->colormap, &style->dark[i]))
1465         g_warning ("unable to allocate color: ( %d %d %d )",
1466                    style->dark[i].red, style->dark[i].green, style->dark[i].blue);
1467       if (!gdk_color_alloc (style->colormap, &style->mid[i]))
1468         g_warning ("unable to allocate color: ( %d %d %d )",
1469                    style->mid[i].red, style->mid[i].green, style->mid[i].blue);
1470       if (!gdk_color_alloc (style->colormap, &style->text[i]))
1471         g_warning ("unable to allocate color: ( %d %d %d )",
1472                    style->text[i].red, style->text[i].green, style->text[i].blue);
1473       if (!gdk_color_alloc (style->colormap, &style->base[i]))
1474         g_warning ("unable to allocate color: ( %d %d %d )",
1475                    style->base[i].red, style->base[i].green, style->base[i].blue);
1476       if (!gdk_color_alloc (style->colormap, &style->text_aa[i]))
1477         g_warning ("unable to allocate color: ( %d %d %d )",
1478                    style->text_aa[i].red, style->text_aa[i].green, style->text_aa[i].blue);
1479       
1480       gc_values.foreground = style->fg[i];
1481       style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1482       
1483       gc_values.foreground = style->bg[i];
1484       style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1485       
1486       gc_values.foreground = style->light[i];
1487       style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1488       
1489       gc_values.foreground = style->dark[i];
1490       style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1491       
1492       gc_values.foreground = style->mid[i];
1493       style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1494       
1495       gc_values.foreground = style->text[i];
1496       style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1497       
1498       gc_values.foreground = style->base[i];
1499       style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1500
1501       gc_values.foreground = style->text_aa[i];
1502       style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1503     }
1504 }
1505
1506 static void
1507 gtk_style_real_unrealize (GtkStyle *style)
1508 {
1509   int i;
1510
1511   gtk_gc_release (style->black_gc);
1512   gtk_gc_release (style->white_gc);
1513       
1514   for (i = 0; i < 5; i++)
1515     {
1516       gtk_gc_release (style->fg_gc[i]);
1517       gtk_gc_release (style->bg_gc[i]);
1518       gtk_gc_release (style->light_gc[i]);
1519       gtk_gc_release (style->dark_gc[i]);
1520       gtk_gc_release (style->mid_gc[i]);
1521       gtk_gc_release (style->text_gc[i]);
1522       gtk_gc_release (style->base_gc[i]);
1523       gtk_gc_release (style->text_aa_gc[i]);
1524
1525       if (style->bg_pixmap[i] &&  style->bg_pixmap[i] != (GdkPixmap*) GDK_PARENT_RELATIVE)
1526         gdk_pixmap_unref (style->bg_pixmap[i]);
1527     }
1528   
1529   gdk_colormap_free_colors (style->colormap, style->fg, 5);
1530   gdk_colormap_free_colors (style->colormap, style->bg, 5);
1531   gdk_colormap_free_colors (style->colormap, style->light, 5);
1532   gdk_colormap_free_colors (style->colormap, style->dark, 5);
1533   gdk_colormap_free_colors (style->colormap, style->mid, 5);
1534   gdk_colormap_free_colors (style->colormap, style->text, 5);
1535   gdk_colormap_free_colors (style->colormap, style->base, 5);
1536   gdk_colormap_free_colors (style->colormap, style->text_aa, 5);
1537 }
1538
1539 static void
1540 gtk_style_real_set_background (GtkStyle    *style,
1541                                GdkWindow   *window,
1542                                GtkStateType state_type)
1543 {
1544   GdkPixmap *pixmap;
1545   gint parent_relative;
1546   
1547   if (style->bg_pixmap[state_type])
1548     {
1549       if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1550         {
1551           pixmap = NULL;
1552           parent_relative = TRUE;
1553         }
1554       else
1555         {
1556           pixmap = style->bg_pixmap[state_type];
1557           parent_relative = FALSE;
1558         }
1559       
1560       gdk_window_set_back_pixmap (window, pixmap, parent_relative);
1561     }
1562   else
1563     gdk_window_set_background (window, &style->bg[state_type]);
1564 }
1565
1566 GdkPixbuf *
1567 gtk_style_render_icon (GtkStyle            *style,
1568                        const GtkIconSource *source,
1569                        GtkTextDirection     direction,
1570                        GtkStateType         state,
1571                        GtkIconSize          size,
1572                        GtkWidget           *widget,
1573                        const gchar         *detail)
1574 {
1575   GdkPixbuf *pixbuf;
1576   
1577   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1578   g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
1579   
1580   pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
1581                                                      size, widget, detail);
1582
1583   g_return_val_if_fail (pixbuf != NULL, NULL);
1584
1585   return pixbuf;
1586 }
1587
1588 /* Default functions */
1589 void
1590 gtk_style_apply_default_background (GtkStyle     *style,
1591                                     GdkWindow    *window,
1592                                     gboolean      set_bg,
1593                                     GtkStateType  state_type, 
1594                                     GdkRectangle *area, 
1595                                     gint          x, 
1596                                     gint          y, 
1597                                     gint          width, 
1598                                     gint          height)
1599 {
1600   GdkRectangle new_rect, old_rect;
1601   
1602   if (area)
1603     {
1604       old_rect.x = x;
1605       old_rect.y = y;
1606       old_rect.width = width;
1607       old_rect.height = height;
1608       
1609       if (!gdk_rectangle_intersect (area, &old_rect, &new_rect))
1610         return;
1611     }
1612   else
1613     {
1614       new_rect.x = x;
1615       new_rect.y = y;
1616       new_rect.width = width;
1617       new_rect.height = height;
1618     }
1619   
1620   if (!style->bg_pixmap[state_type] ||
1621       GDK_IS_PIXMAP (window) ||
1622       (!set_bg && style->bg_pixmap[state_type] != (GdkPixmap*) GDK_PARENT_RELATIVE))
1623     {
1624       GdkGC *gc = style->bg_gc[state_type];
1625       
1626       if (style->bg_pixmap[state_type])
1627         {
1628           gdk_gc_set_fill (gc, GDK_TILED);
1629           gdk_gc_set_tile (gc, style->bg_pixmap[state_type]);
1630         }
1631       
1632       gdk_draw_rectangle (window, gc, TRUE, 
1633                           new_rect.x, new_rect.y, new_rect.width, new_rect.height);
1634       if (style->bg_pixmap[state_type])
1635         gdk_gc_set_fill (gc, GDK_SOLID);
1636     }
1637   else
1638     {
1639       if (set_bg)
1640         {
1641           if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1642             gdk_window_set_back_pixmap (window, NULL, TRUE);
1643           else
1644             gdk_window_set_back_pixmap (window, style->bg_pixmap[state_type], FALSE);
1645         }
1646       
1647       gdk_window_clear_area (window, 
1648                              new_rect.x, new_rect.y, 
1649                              new_rect.width, new_rect.height);
1650     }
1651 }
1652
1653 static GdkPixbuf*
1654 scale_or_ref (GdkPixbuf *src,
1655               gint width,
1656               gint height)
1657 {
1658   if (width == gdk_pixbuf_get_width (src) &&
1659       height == gdk_pixbuf_get_height (src))
1660     {
1661       gdk_pixbuf_ref (src);
1662       return src;
1663     }
1664   else
1665     {
1666       return gdk_pixbuf_scale_simple (src,
1667                                       width, height,
1668                                       GDK_INTERP_BILINEAR);
1669     }
1670 }
1671
1672 static GdkPixbuf *
1673 gtk_default_render_icon (GtkStyle            *style,
1674                          const GtkIconSource *source,
1675                          GtkTextDirection     direction,
1676                          GtkStateType         state,
1677                          GtkIconSize          size,
1678                          GtkWidget           *widget,
1679                          const gchar         *detail)
1680 {
1681   gint width = 1;
1682   gint height = 1;
1683   GdkPixbuf *scaled;
1684   GdkPixbuf *stated;
1685   GdkPixbuf *base_pixbuf;
1686
1687   /* Oddly, style can be NULL in this function, because
1688    * GtkIconSet can be used without a style and if so
1689    * it uses this function.
1690    */
1691
1692   base_pixbuf = gtk_icon_source_get_pixbuf (source);
1693
1694   g_return_val_if_fail (base_pixbuf != NULL, NULL);
1695   
1696   if (!gtk_icon_size_lookup (size, &width, &height))
1697     {
1698       g_warning (G_STRLOC ": invalid icon size `%d'", size);
1699       return NULL;
1700     }
1701
1702   /* If the size was wildcarded, then scale; otherwise, leave it
1703    * alone.
1704    */
1705   if (gtk_icon_source_get_size_wildcarded (source))
1706     scaled = scale_or_ref (base_pixbuf, width, height);
1707   else
1708     scaled = GDK_PIXBUF (g_object_ref (G_OBJECT (base_pixbuf)));
1709
1710   /* If the state was wildcarded, then generate a state. */
1711   if (gtk_icon_source_get_state_wildcarded (source))
1712     {
1713       if (state == GTK_STATE_INSENSITIVE)
1714         {
1715           stated = gdk_pixbuf_copy (scaled);      
1716           
1717           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1718                                             0.8, TRUE);
1719           
1720           gdk_pixbuf_unref (scaled);
1721         }
1722       else if (state == GTK_STATE_PRELIGHT)
1723         {
1724           stated = gdk_pixbuf_copy (scaled);      
1725           
1726           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
1727                                             1.2, FALSE);
1728           
1729           gdk_pixbuf_unref (scaled);
1730         }
1731       else
1732         {
1733           stated = scaled;
1734         }
1735     }
1736   else
1737     stated = scaled;
1738   
1739   return stated;
1740 }
1741
1742 static gboolean
1743 sanitize_size (GdkWindow *window,
1744                gint      *width,
1745                gint      *height)
1746 {
1747   gboolean set_bg = FALSE;
1748
1749   if ((*width == -1) && (*height == -1))
1750     {
1751       set_bg = GDK_IS_WINDOW (window);
1752       gdk_window_get_size (window, width, height);
1753     }
1754   else if (*width == -1)
1755     gdk_window_get_size (window, width, NULL);
1756   else if (*height == -1)
1757     gdk_window_get_size (window, NULL, height);
1758
1759   return set_bg;
1760 }
1761
1762 static void
1763 draw_part (GdkDrawable  *drawable,
1764            GdkGC        *gc,
1765            GdkRectangle *area,
1766            gint          x,
1767            gint          y,
1768            IndicatorPart part)
1769 {
1770   if (area)
1771     gdk_gc_set_clip_rectangle (gc, area);
1772   
1773   if (!indicator_parts[part].bmap)
1774     indicator_parts[part].bmap = gdk_bitmap_create_from_data (drawable,
1775                                                               indicator_parts[part].bits,
1776                                                               INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
1777
1778   gdk_gc_set_ts_origin (gc, x, y);
1779   gdk_gc_set_stipple (gc, indicator_parts[part].bmap);
1780   gdk_gc_set_fill (gc, GDK_STIPPLED);
1781
1782   gdk_draw_rectangle (drawable, gc, TRUE, x, y, INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
1783
1784   gdk_gc_set_fill (gc, GDK_SOLID);
1785
1786   if (area)
1787     gdk_gc_set_clip_rectangle (gc, NULL);
1788 }
1789
1790 static void
1791 gtk_default_draw_hline (GtkStyle     *style,
1792                         GdkWindow    *window,
1793                         GtkStateType  state_type,
1794                         GdkRectangle  *area,
1795                         GtkWidget     *widget,
1796                         const gchar   *detail,
1797                         gint          x1,
1798                         gint          x2,
1799                         gint          y)
1800 {
1801   gint thickness_light;
1802   gint thickness_dark;
1803   gint i;
1804   
1805   g_return_if_fail (GTK_IS_STYLE (style));
1806   g_return_if_fail (window != NULL);
1807   
1808   thickness_light = style->ythickness / 2;
1809   thickness_dark = style->ythickness - thickness_light;
1810   
1811   if (area)
1812     {
1813       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
1814       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
1815     }
1816   
1817   if (detail && !strcmp (detail, "label"))
1818     {
1819       if (state_type == GTK_STATE_INSENSITIVE)
1820         gdk_draw_line (window, style->white_gc, x1 + 1, y + 1, x2 + 1, y + 1);   
1821       gdk_draw_line (window, style->fg_gc[state_type], x1, y, x2, y);     
1822     }
1823   else
1824     {
1825       for (i = 0; i < thickness_dark; i++)
1826         {
1827           gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i);
1828           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i);
1829         }
1830       
1831       y += thickness_dark;
1832       for (i = 0; i < thickness_light; i++)
1833         {
1834           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
1835           gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i);
1836         }
1837     }
1838   
1839   if (area)
1840     {
1841       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
1842       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
1843     }
1844 }
1845
1846
1847 static void
1848 gtk_default_draw_vline (GtkStyle     *style,
1849                         GdkWindow    *window,
1850                         GtkStateType  state_type,
1851                         GdkRectangle  *area,
1852                         GtkWidget     *widget,
1853                         const gchar   *detail,
1854                         gint          y1,
1855                         gint          y2,
1856                         gint          x)
1857 {
1858   gint thickness_light;
1859   gint thickness_dark;
1860   gint i;
1861   
1862   g_return_if_fail (GTK_IS_STYLE (style));
1863   g_return_if_fail (window != NULL);
1864   
1865   thickness_light = style->xthickness / 2;
1866   thickness_dark = style->xthickness - thickness_light;
1867   
1868   if (area)
1869     {
1870       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
1871       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
1872     }
1873   for (i = 0; i < thickness_dark; i++)
1874     {
1875       gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2);
1876       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1);
1877     }
1878   
1879   x += thickness_dark;
1880   for (i = 0; i < thickness_light; i++)
1881     {
1882       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i);
1883       gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2);
1884     }
1885   if (area)
1886     {
1887       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
1888       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
1889     }
1890 }
1891
1892
1893 void
1894 draw_thin_shadow (GtkStyle      *style,
1895                   GdkWindow     *window,
1896                   GtkStateType   state,
1897                   GdkRectangle  *area,
1898                   gint           x,
1899                   gint           y,
1900                   gint           width,
1901                   gint           height)
1902 {
1903   GdkGC *gc1, *gc2;
1904
1905   sanitize_size (window, &width, &height);
1906   
1907   gc1 = style->light_gc[state];
1908   gc2 = style->dark_gc[state];
1909   
1910   if (area)
1911     {
1912       gdk_gc_set_clip_rectangle (gc1, area);
1913       gdk_gc_set_clip_rectangle (gc2, area);
1914     }
1915   
1916   gdk_draw_line (window, gc1,
1917                  x, y + height - 1, x + width - 1, y + height - 1);
1918   gdk_draw_line (window, gc1,
1919                  x + width - 1, y,  x + width - 1, y + height - 1);
1920       
1921   gdk_draw_line (window, gc2,
1922                  x, y, x + width - 1, y);
1923   gdk_draw_line (window, gc2,
1924                  x, y, x, y + height - 1);
1925
1926   if (area)
1927     {
1928       gdk_gc_set_clip_rectangle (gc1, NULL);
1929       gdk_gc_set_clip_rectangle (gc2, NULL);
1930     }
1931 }
1932
1933 void
1934 draw_spin_entry_shadow (GtkStyle      *style,
1935                         GdkWindow     *window,
1936                         GtkStateType   state,
1937                         GdkRectangle  *area,
1938                         gint           x,
1939                         gint           y,
1940                         gint           width,
1941                         gint           height)
1942 {
1943   gint window_width, window_height;
1944   gboolean focus_inset;
1945
1946   gdk_window_get_size (window, &window_width, &window_height);
1947
1948   if (width == -1)
1949     width = window_width;
1950   if (height == 1)
1951     height = window_height;
1952
1953   focus_inset = (width < window_width && height < window_height);
1954   
1955   if (area)
1956     {
1957       gdk_gc_set_clip_rectangle (style->light_gc[state], area);
1958       gdk_gc_set_clip_rectangle (style->dark_gc[state], area);
1959       gdk_gc_set_clip_rectangle (style->black_gc, area);
1960       gdk_gc_set_clip_rectangle (style->bg_gc[state], area);
1961       gdk_gc_set_clip_rectangle (style->base_gc[state], area);
1962     }
1963
1964   gdk_draw_line (window, style->light_gc[state],
1965                  x, y + height - 1, x + width - 1, y + height - 1);
1966
1967   gdk_draw_line (window, 
1968                  style->base_gc[state],
1969                  x + width - 1,  y + 1, x + width - 1,  y + height - 3);
1970       
1971   if (!focus_inset)
1972     {
1973       gdk_draw_line (window, style->bg_gc[state],
1974                      x + 1, y + height - 2, x + width - 1, y + height - 2);
1975       gdk_draw_line (window, 
1976                      style->base_gc[state],
1977                      x + width - 2, y + 1, x + width - 2, y + height - 3);
1978   
1979       gdk_draw_line (window, style->black_gc,
1980                      x + 1, y + 1, x + width - 1, y + 1);
1981       gdk_draw_line (window, style->black_gc,
1982                      x + 1, y + 1, x + 1, y + height - 2);
1983     }
1984       
1985   gdk_draw_line (window, style->dark_gc[state],
1986                  x, y, x + width - 1, y);
1987   gdk_draw_line (window, style->dark_gc[state],
1988                  x, y, x, y + height - 1);
1989
1990   if (area)
1991     {
1992       gdk_gc_set_clip_rectangle (style->light_gc[state], NULL);
1993       gdk_gc_set_clip_rectangle (style->dark_gc[state], NULL);
1994       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
1995       gdk_gc_set_clip_rectangle (style->bg_gc[state], NULL);
1996       gdk_gc_set_clip_rectangle (style->base_gc[state], NULL);
1997     }
1998 }
1999
2000 static void
2001 draw_spinbutton_shadow (GtkStyle      *style,
2002                         GdkWindow     *window,
2003                         GtkStateType   state,
2004                         GdkRectangle  *area,
2005                         gint           x,
2006                         gint           y,
2007                         gint           width,
2008                         gint           height)
2009 {
2010   gint y_middle = y + height / 2;
2011
2012   sanitize_size (window, &width, &height);
2013   
2014   if (area)
2015     {
2016       gdk_gc_set_clip_rectangle (style->black_gc, area);
2017       gdk_gc_set_clip_rectangle (style->bg_gc[state], area);
2018       gdk_gc_set_clip_rectangle (style->dark_gc[state], area);
2019       gdk_gc_set_clip_rectangle (style->light_gc[state], area);
2020     }
2021   
2022   gdk_draw_line (window, style->black_gc,
2023                  x, y + 2, x, y + height - 3);
2024   gdk_draw_line (window, style->black_gc,
2025                  x, y + 1, x + width - 2, y + 1);
2026   gdk_draw_line (window, style->black_gc,
2027                  x + width - 2, y + 2, x + width - 2, y + height - 3);
2028   
2029   gdk_draw_line (window, style->bg_gc[state],
2030                  x, y + height - 2, x + width - 2, y + height - 2);
2031
2032   gdk_draw_line (window, style->dark_gc[state],
2033                  x, y, x + width - 1, y);
2034   gdk_draw_line (window, style->dark_gc[state],
2035                  x + 1, y_middle - 1, x + width - 3, y_middle - 1);
2036   gdk_draw_line (window, style->dark_gc[state],
2037                  x + 1, y + height - 3, x + width - 3, y + height - 3);
2038
2039   gdk_draw_line (window, style->light_gc[state],
2040                  x + 1, y + 2, x + width - 3, y + 2);
2041   gdk_draw_line (window, style->light_gc[state],
2042                  x + 1, y_middle, x + width - 3, y_middle);
2043   gdk_draw_line (window, style->light_gc[state],
2044                  x + width - 1, y + 1, x + width - 1, y + height - 1);
2045   gdk_draw_line (window, style->light_gc[state],
2046                  x, y + height - 1, x + width - 2, y + height - 1);
2047       
2048   if (area)
2049     {
2050       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2051       gdk_gc_set_clip_rectangle (style->bg_gc[state], NULL);
2052       gdk_gc_set_clip_rectangle (style->dark_gc[state], NULL);
2053       gdk_gc_set_clip_rectangle (style->light_gc[state], NULL);
2054     }
2055 }
2056
2057 static void
2058 gtk_default_draw_shadow (GtkStyle      *style,
2059                          GdkWindow     *window,
2060                          GtkStateType   state_type,
2061                          GtkShadowType  shadow_type,
2062                          GdkRectangle  *area,
2063                          GtkWidget     *widget,
2064                          const gchar   *detail,
2065                          gint           x,
2066                          gint           y,
2067                          gint           width,
2068                          gint           height)
2069 {
2070   GdkGC *gc1 = NULL;
2071   GdkGC *gc2 = NULL;
2072   gint thickness_light;
2073   gint thickness_dark;
2074   gint i;
2075   
2076   g_return_if_fail (GTK_IS_STYLE (style));
2077   g_return_if_fail (window != NULL);
2078
2079   if (shadow_type == GTK_SHADOW_IN)
2080     {
2081       if (detail && (strcmp (detail, "buttondefault") == 0))
2082         {
2083           sanitize_size (window, &width, &height);
2084
2085           gdk_draw_rectangle (window, style->black_gc, FALSE,
2086                               x, y, width - 1, height - 1);
2087           
2088           return;
2089         }
2090       if (detail && strcmp (detail, "trough") == 0)
2091         {
2092           draw_thin_shadow (style, window, state_type, area,
2093                             x, y, width, height);
2094           return;
2095         }
2096       else if (widget && GTK_IS_SPIN_BUTTON (widget) &&
2097                detail && strcmp (detail, "entry") == 0)
2098         {
2099           draw_spin_entry_shadow (style, window, state_type, area,
2100                                   x, y, width, height);
2101           return;
2102         }
2103       else if (widget && GTK_IS_SPIN_BUTTON (widget) &&
2104                detail && strcmp (detail, "spinbutton") == 0)
2105         {
2106           draw_spinbutton_shadow (style, window, state_type,
2107                                   area, x, y, width, height);
2108           return;
2109         }
2110     }
2111   
2112   sanitize_size (window, &width, &height);
2113   
2114   switch (shadow_type)
2115     {
2116     case GTK_SHADOW_NONE:
2117       return;
2118     case GTK_SHADOW_IN:
2119     case GTK_SHADOW_ETCHED_IN:
2120       gc1 = style->light_gc[state_type];
2121       gc2 = style->dark_gc[state_type];
2122       break;
2123     case GTK_SHADOW_OUT:
2124     case GTK_SHADOW_ETCHED_OUT:
2125       gc1 = style->dark_gc[state_type];
2126       gc2 = style->light_gc[state_type];
2127       break;
2128     }
2129   
2130   if (area)
2131     {
2132       gdk_gc_set_clip_rectangle (gc1, area);
2133       gdk_gc_set_clip_rectangle (gc2, area);
2134       if (shadow_type == GTK_SHADOW_IN || 
2135           shadow_type == GTK_SHADOW_OUT)
2136         {
2137           gdk_gc_set_clip_rectangle (style->black_gc, area);
2138           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2139         }
2140     }
2141   
2142   switch (shadow_type)
2143     {
2144     case GTK_SHADOW_NONE:
2145       break;
2146       
2147     case GTK_SHADOW_IN:
2148       /* Light around right and bottom edge */
2149
2150       if (style->ythickness > 0)
2151         gdk_draw_line (window, gc1,
2152                        x, y + height - 1, x + width - 1, y + height - 1);
2153       if (style->xthickness > 0)
2154         gdk_draw_line (window, gc1,
2155                        x + width - 1, y, x + width - 1, y + height - 1);
2156
2157       if (style->ythickness > 1)
2158         gdk_draw_line (window, style->bg_gc[state_type],
2159                        x + 1, y + height - 2, x + width - 2, y + height - 2);
2160       if (style->xthickness > 1)
2161         gdk_draw_line (window, style->bg_gc[state_type],
2162                        x + width - 2, y + 1, x + width - 2, y + height - 2);
2163
2164       /* Dark around left and top */
2165
2166       if (style->ythickness > 1)
2167         gdk_draw_line (window, style->black_gc,
2168                        x + 1, y + 1, x + width - 2, y + 1);
2169       if (style->xthickness > 1)
2170         gdk_draw_line (window, style->black_gc,
2171                        x + 1, y + 1, x + 1, y + height - 2);
2172
2173       if (style->ythickness > 0)
2174         gdk_draw_line (window, gc2,
2175                        x, y, x + width - 1, y);
2176       if (style->xthickness > 0)
2177         gdk_draw_line (window, gc2,
2178                        x, y, x, y + height - 1);
2179       break;
2180       
2181     case GTK_SHADOW_OUT:
2182       /* Dark around right and bottom edge */
2183
2184       if (style->ythickness > 0)
2185         {
2186           if (style->ythickness > 1)
2187             {
2188               gdk_draw_line (window, gc1,
2189                              x + 1, y + height - 2, x + width - 2, y + height - 2);
2190               gdk_draw_line (window, style->black_gc,
2191                              x, y + height - 1, x + width - 1, y + height - 1);
2192             }
2193           else
2194             {
2195               gdk_draw_line (window, gc1,
2196                              x + 1, y + height - 1, x + width - 1, y + height - 1);
2197             }
2198         }
2199
2200       if (style->xthickness > 0)
2201         {
2202           if (style->xthickness > 1)
2203             {
2204               gdk_draw_line (window, gc1,
2205                              x + width - 2, y + 1, x + width - 2, y + height - 2);
2206               
2207               gdk_draw_line (window, style->black_gc,
2208                              x + width - 1, y, x + width - 1, y + height - 1);
2209             }
2210           else
2211             {
2212               gdk_draw_line (window, gc1,
2213                              x + width - 1, y + 1, x + width - 1, y + height - 1);
2214             }
2215         }
2216       
2217       /* Light around top and left */
2218
2219       if (style->ythickness > 0)
2220         gdk_draw_line (window, gc2,
2221                        x, y, x + width - 1, y);
2222       if (style->xthickness > 0)
2223         gdk_draw_line (window, gc2,
2224                        x, y, x, y + height - 1);
2225
2226       if (style->ythickness > 1)
2227         gdk_draw_line (window, style->bg_gc[state_type],
2228                        x + 1, y + 1, x + width - 2, y + 1);
2229       if (style->xthickness > 1)
2230         gdk_draw_line (window, style->bg_gc[state_type],
2231                        x + 1, y + 1, x + 1, y + height - 2);
2232       break;
2233       
2234     case GTK_SHADOW_ETCHED_IN:
2235     case GTK_SHADOW_ETCHED_OUT:
2236       if (style->xthickness > 0)
2237         {
2238           if (style->xthickness > 1)
2239             {
2240               thickness_light = 1;
2241               thickness_dark = 1;
2242       
2243               for (i = 0; i < thickness_dark; i++)
2244                 {
2245                   gdk_draw_line (window, gc1,
2246                                  x + width - i - 1,
2247                                  y + i,
2248                                  x + width - i - 1,
2249                                  y + height - i - 1);
2250                   gdk_draw_line (window, gc2,
2251                                  x + i,
2252                                  y + i,
2253                                  x + i,
2254                                  y + height - i - 2);
2255                 }
2256       
2257               for (i = 0; i < thickness_light; i++)
2258                 {
2259                   gdk_draw_line (window, gc1,
2260                                  x + thickness_dark + i,
2261                                  y + thickness_dark + i,
2262                                  x + thickness_dark + i,
2263                                  y + height - thickness_dark - i - 1);
2264                   gdk_draw_line (window, gc2,
2265                                  x + width - thickness_light - i - 1,
2266                                  y + thickness_dark + i,
2267                                  x + width - thickness_light - i - 1,
2268                                  y + height - thickness_light - 1);
2269                 }
2270             }
2271           else
2272             {
2273               gdk_draw_line (window, 
2274                              style->dark_gc[state_type],
2275                              x, y, x, y + height);                         
2276               gdk_draw_line (window, 
2277                              style->dark_gc[state_type],
2278                              x + width, y, x + width, y + height);
2279             }
2280         }
2281
2282       if (style->ythickness > 0)
2283         {
2284           if (style->ythickness > 1)
2285             {
2286               thickness_light = 1;
2287               thickness_dark = 1;
2288       
2289               for (i = 0; i < thickness_dark; i++)
2290                 {
2291                   gdk_draw_line (window, gc1,
2292                                  x + i,
2293                                  y + height - i - 1,
2294                                  x + width - i - 1,
2295                                  y + height - i - 1);
2296           
2297                   gdk_draw_line (window, gc2,
2298                                  x + i,
2299                                  y + i,
2300                                  x + width - i - 2,
2301                                  y + i);
2302                 }
2303       
2304               for (i = 0; i < thickness_light; i++)
2305                 {
2306                   gdk_draw_line (window, gc1,
2307                                  x + thickness_dark + i,
2308                                  y + thickness_dark + i,
2309                                  x + width - thickness_dark - i - 1,
2310                                  y + thickness_dark + i);
2311           
2312                   gdk_draw_line (window, gc2,
2313                                  x + thickness_dark + i,
2314                                  y + height - thickness_light - i - 1,
2315                                  x + width - thickness_light - 1,
2316                                  y + height - thickness_light - i - 1);
2317                 }
2318             }
2319           else
2320             {
2321               gdk_draw_line (window, 
2322                              style->dark_gc[state_type],
2323                              x, y, x + width, y);
2324               gdk_draw_line (window, 
2325                              style->dark_gc[state_type],
2326                              x, y + height, x + width, y + height);
2327             }
2328         }
2329       
2330       break;
2331     }
2332   if (area)
2333     {
2334       gdk_gc_set_clip_rectangle (gc1, NULL);
2335       gdk_gc_set_clip_rectangle (gc2, NULL);
2336       if (shadow_type == GTK_SHADOW_IN || 
2337           shadow_type == GTK_SHADOW_OUT)
2338         {
2339           gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2340           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2341         }
2342     }
2343 }
2344
2345 static void
2346 gtk_default_draw_polygon (GtkStyle      *style,
2347                           GdkWindow     *window,
2348                           GtkStateType   state_type,
2349                           GtkShadowType  shadow_type,
2350                           GdkRectangle  *area,
2351                           GtkWidget     *widget,
2352                           const gchar   *detail,
2353                           GdkPoint      *points,
2354                           gint           npoints,
2355                           gboolean       fill)
2356 {
2357   static const gdouble pi_over_4 = G_PI_4;
2358   static const gdouble pi_3_over_4 = G_PI_4 * 3;
2359   GdkGC *gc1;
2360   GdkGC *gc2;
2361   GdkGC *gc3;
2362   GdkGC *gc4;
2363   gdouble angle;
2364   gint xadjust;
2365   gint yadjust;
2366   gint i;
2367   
2368   g_return_if_fail (GTK_IS_STYLE (style));
2369   g_return_if_fail (window != NULL);
2370   g_return_if_fail (points != NULL);
2371   
2372   switch (shadow_type)
2373     {
2374     case GTK_SHADOW_IN:
2375       gc1 = style->bg_gc[state_type];
2376       gc2 = style->dark_gc[state_type];
2377       gc3 = style->light_gc[state_type];
2378       gc4 = style->black_gc;
2379       break;
2380     case GTK_SHADOW_ETCHED_IN:
2381       gc1 = style->light_gc[state_type];
2382       gc2 = style->dark_gc[state_type];
2383       gc3 = style->dark_gc[state_type];
2384       gc4 = style->light_gc[state_type];
2385       break;
2386     case GTK_SHADOW_OUT:
2387       gc1 = style->dark_gc[state_type];
2388       gc2 = style->light_gc[state_type];
2389       gc3 = style->black_gc;
2390       gc4 = style->bg_gc[state_type];
2391       break;
2392     case GTK_SHADOW_ETCHED_OUT:
2393       gc1 = style->dark_gc[state_type];
2394       gc2 = style->light_gc[state_type];
2395       gc3 = style->light_gc[state_type];
2396       gc4 = style->dark_gc[state_type];
2397       break;
2398     default:
2399       return;
2400     }
2401   
2402   if (area)
2403     {
2404       gdk_gc_set_clip_rectangle (gc1, area);
2405       gdk_gc_set_clip_rectangle (gc2, area);
2406       gdk_gc_set_clip_rectangle (gc3, area);
2407       gdk_gc_set_clip_rectangle (gc4, area);
2408     }
2409   
2410   if (fill)
2411     gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints);
2412   
2413   npoints--;
2414   
2415   for (i = 0; i < npoints; i++)
2416     {
2417       if ((points[i].x == points[i+1].x) &&
2418           (points[i].y == points[i+1].y))
2419         {
2420           angle = 0;
2421         }
2422       else
2423         {
2424           angle = atan2 (points[i+1].y - points[i].y,
2425                          points[i+1].x - points[i].x);
2426         }
2427       
2428       if ((angle > -pi_3_over_4) && (angle < pi_over_4))
2429         {
2430           if (angle > -pi_over_4)
2431             {
2432               xadjust = 0;
2433               yadjust = 1;
2434             }
2435           else
2436             {
2437               xadjust = 1;
2438               yadjust = 0;
2439             }
2440           
2441           gdk_draw_line (window, gc1,
2442                          points[i].x-xadjust, points[i].y-yadjust,
2443                          points[i+1].x-xadjust, points[i+1].y-yadjust);
2444           gdk_draw_line (window, gc3,
2445                          points[i].x, points[i].y,
2446                          points[i+1].x, points[i+1].y);
2447         }
2448       else
2449         {
2450           if ((angle < -pi_3_over_4) || (angle > pi_3_over_4))
2451             {
2452               xadjust = 0;
2453               yadjust = 1;
2454             }
2455           else
2456             {
2457               xadjust = 1;
2458               yadjust = 0;
2459             }
2460           
2461           gdk_draw_line (window, gc4,
2462                          points[i].x+xadjust, points[i].y+yadjust,
2463                          points[i+1].x+xadjust, points[i+1].y+yadjust);
2464           gdk_draw_line (window, gc2,
2465                          points[i].x, points[i].y,
2466                          points[i+1].x, points[i+1].y);
2467         }
2468     }
2469
2470   if (area)
2471     {
2472       gdk_gc_set_clip_rectangle (gc1, NULL);
2473       gdk_gc_set_clip_rectangle (gc2, NULL);
2474       gdk_gc_set_clip_rectangle (gc3, NULL);
2475       gdk_gc_set_clip_rectangle (gc4, NULL);
2476     }
2477 }
2478
2479 static void
2480 draw_varrow (GdkWindow     *window,
2481              GdkGC         *gc,
2482              GtkShadowType  shadow_type,
2483              GdkRectangle  *area,
2484              GtkArrowType   arrow_type,
2485              gint           x,
2486              gint           y,
2487              gint           width,
2488              gint           height)
2489 {
2490   gint steps, extra;
2491   gint y_start, y_increment;
2492   gint i;
2493
2494   if (area)
2495     gdk_gc_set_clip_rectangle (gc, area);
2496   
2497   width = width + width % 2 - 1;        /* Force odd */
2498   
2499   steps = 1 + width / 2;
2500
2501   extra = height - steps;
2502
2503   if (arrow_type == GTK_ARROW_DOWN)
2504     {
2505       y_start = y;
2506       y_increment = 1;
2507     }
2508   else
2509     {
2510       y_start = y + height - 1;
2511       y_increment = -1;
2512     }
2513
2514   for (i = 0; i < extra; i++)
2515     {
2516       gdk_draw_line (window, gc,
2517                      x,              y_start + i * y_increment,
2518                      x + width - 1,  y_start + i * y_increment);
2519     }
2520   for (; i < height; i++)
2521     {
2522       gdk_draw_line (window, gc,
2523                      x + (i - extra),              y_start + i * y_increment,
2524                      x + width - (i - extra) - 1,  y_start + i * y_increment);
2525     }
2526   
2527
2528   if (area)
2529     gdk_gc_set_clip_rectangle (gc, NULL);
2530 }
2531
2532 static void
2533 draw_harrow (GdkWindow     *window,
2534              GdkGC         *gc,
2535              GtkShadowType  shadow_type,
2536              GdkRectangle  *area,
2537              GtkArrowType   arrow_type,
2538              gint           x,
2539              gint           y,
2540              gint           width,
2541              gint           height)
2542 {
2543   gint steps, extra;
2544   gint x_start, x_increment;
2545   gint i;
2546
2547   if (area)
2548     gdk_gc_set_clip_rectangle (gc, area);
2549   
2550   height = height + height % 2 - 1;     /* Force odd */
2551   
2552   steps = 1 + height / 2;
2553
2554   extra = width - steps;
2555
2556   if (arrow_type == GTK_ARROW_RIGHT)
2557     {
2558       x_start = x;
2559       x_increment = 1;
2560     }
2561   else
2562     {
2563       x_start = x + width - 1;
2564       x_increment = -1;
2565     }
2566
2567   for (i = 0; i < extra; i++)
2568     {
2569       gdk_draw_line (window, gc,
2570                      x_start + i * x_increment, y,
2571                      x_start + i * x_increment, y + height - 1);
2572     }
2573   for (; i < width; i++)
2574     {
2575       gdk_draw_line (window, gc,
2576                      x_start + i * x_increment, y + (i - extra),
2577                      x_start + i * x_increment, y + height - (i - extra) - 1);
2578     }
2579   
2580
2581   if (area)
2582     gdk_gc_set_clip_rectangle (gc, NULL);
2583 }
2584
2585 static void
2586 gtk_default_draw_arrow (GtkStyle      *style,
2587                         GdkWindow     *window,
2588                         GtkStateType   state,
2589                         GtkShadowType  shadow,
2590                         GdkRectangle  *area,
2591                         GtkWidget     *widget,
2592                         const gchar   *detail,
2593                         GtkArrowType   arrow_type,
2594                         gboolean       fill,
2595                         gint           x,
2596                         gint           y,
2597                         gint           width,
2598                         gint           height)
2599 {
2600   sanitize_size (window, &width, &height);
2601   
2602   if (detail && strcmp (detail, "spinbutton") == 0)
2603     {
2604       int hpad, vpad;
2605       int my_height = height;
2606       int my_width = width;
2607       int vpad_add = 0;
2608
2609       if (my_height > my_width)
2610         {
2611           vpad_add = (my_height - my_width) / 2;
2612           my_height = my_width;
2613         }
2614
2615       hpad = my_width / 4;
2616
2617       if (hpad < 4)
2618         hpad = 4;
2619
2620       vpad = 2 * hpad - 1;
2621
2622       x += hpad / 2;
2623       y += vpad / 2;
2624
2625       y += vpad_add;
2626
2627       draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
2628                    x, y, my_width - hpad, my_height - vpad);
2629     }
2630   else if (detail && strcmp (detail, "vscrollbar") == 0)
2631     {
2632       gtk_paint_box (style, window, state, shadow, area,
2633                      widget, detail, x, y, width, height);
2634       
2635       x += (width - 7) / 2;
2636       y += (height - 5) / 2;
2637       
2638       draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
2639                    x, y, 7, 5);
2640     }
2641   else if (detail && strcmp (detail, "hscrollbar") == 0)
2642     {
2643       gtk_paint_box (style, window, state, shadow, area,
2644                      widget, detail, x, y, width, height);
2645       
2646       y += (height - 7) / 2;
2647       x += (width - 5) / 2;
2648
2649       draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
2650                    x, y, 5, 7);
2651     }
2652   else
2653     {
2654       if (arrow_type == GTK_ARROW_UP || arrow_type == GTK_ARROW_DOWN)
2655         {
2656           x += (width - 7) / 2;
2657           y += (height - 5) / 2;
2658           
2659           draw_varrow (window, style->fg_gc[state], shadow, area, arrow_type,
2660                        x, y, 7, 5);
2661         }
2662       else
2663         {
2664           x += (width - 5) / 2;
2665           y += (height - 7) / 2;
2666           
2667           draw_harrow (window, style->fg_gc[state], shadow, area, arrow_type,
2668                        x, y, 5, 7);
2669         }
2670     }
2671 }
2672
2673 static void
2674 gtk_default_draw_diamond (GtkStyle      *style,
2675                           GdkWindow     *window,
2676                           GtkStateType   state_type,
2677                           GtkShadowType  shadow_type,
2678                           GdkRectangle  *area,
2679                           GtkWidget     *widget,
2680                           const gchar   *detail,
2681                           gint           x,
2682                           gint           y,
2683                           gint           width,
2684                           gint           height)
2685 {
2686   gint half_width;
2687   gint half_height;
2688   GdkGC *outer_nw = NULL;
2689   GdkGC *outer_ne = NULL;
2690   GdkGC *outer_sw = NULL;
2691   GdkGC *outer_se = NULL;
2692   GdkGC *middle_nw = NULL;
2693   GdkGC *middle_ne = NULL;
2694   GdkGC *middle_sw = NULL;
2695   GdkGC *middle_se = NULL;
2696   GdkGC *inner_nw = NULL;
2697   GdkGC *inner_ne = NULL;
2698   GdkGC *inner_sw = NULL;
2699   GdkGC *inner_se = NULL;
2700   
2701   g_return_if_fail (GTK_IS_STYLE (style));
2702   g_return_if_fail (window != NULL);
2703   
2704   sanitize_size (window, &width, &height);
2705   
2706   half_width = width / 2;
2707   half_height = height / 2;
2708   
2709   if (area)
2710     {
2711       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2712       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2713       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2714       gdk_gc_set_clip_rectangle (style->black_gc, area);
2715     }
2716   
2717   switch (shadow_type)
2718     {
2719     case GTK_SHADOW_IN:
2720       inner_sw = inner_se = style->bg_gc[state_type];
2721       middle_sw = middle_se = style->light_gc[state_type];
2722       outer_sw = outer_se = style->light_gc[state_type];
2723       inner_nw = inner_ne = style->black_gc;
2724       middle_nw = middle_ne = style->dark_gc[state_type];
2725       outer_nw = outer_ne = style->dark_gc[state_type];
2726       break;
2727           
2728     case GTK_SHADOW_OUT:
2729       inner_sw = inner_se = style->dark_gc[state_type];
2730       middle_sw = middle_se = style->dark_gc[state_type];
2731       outer_sw = outer_se = style->black_gc;
2732       inner_nw = inner_ne = style->bg_gc[state_type];
2733       middle_nw = middle_ne = style->light_gc[state_type];
2734       outer_nw = outer_ne = style->light_gc[state_type];
2735       break;
2736
2737     case GTK_SHADOW_ETCHED_IN:
2738       inner_sw = inner_se = style->bg_gc[state_type];
2739       middle_sw = middle_se = style->dark_gc[state_type];
2740       outer_sw = outer_se = style->light_gc[state_type];
2741       inner_nw = inner_ne = style->bg_gc[state_type];
2742       middle_nw = middle_ne = style->light_gc[state_type];
2743       outer_nw = outer_ne = style->dark_gc[state_type];
2744       break;
2745
2746     case GTK_SHADOW_ETCHED_OUT:
2747       inner_sw = inner_se = style->bg_gc[state_type];
2748       middle_sw = middle_se = style->light_gc[state_type];
2749       outer_sw = outer_se = style->dark_gc[state_type];
2750       inner_nw = inner_ne = style->bg_gc[state_type];
2751       middle_nw = middle_ne = style->dark_gc[state_type];
2752       outer_nw = outer_ne = style->light_gc[state_type];
2753       break;
2754       
2755     default:
2756
2757       break;
2758     }
2759
2760   if (inner_sw)
2761     {
2762       gdk_draw_line (window, inner_sw,
2763                      x + 2, y + half_height,
2764                      x + half_width, y + height - 2);
2765       gdk_draw_line (window, inner_se,
2766                      x + half_width, y + height - 2,
2767                      x + width - 2, y + half_height);
2768       gdk_draw_line (window, middle_sw,
2769                      x + 1, y + half_height,
2770                      x + half_width, y + height - 1);
2771       gdk_draw_line (window, middle_se,
2772                      x + half_width, y + height - 1,
2773                      x + width - 1, y + half_height);
2774       gdk_draw_line (window, outer_sw,
2775                      x, y + half_height,
2776                      x + half_width, y + height);
2777       gdk_draw_line (window, outer_se,
2778                      x + half_width, y + height,
2779                      x + width, y + half_height);
2780   
2781       gdk_draw_line (window, inner_nw,
2782                      x + 2, y + half_height,
2783                      x + half_width, y + 2);
2784       gdk_draw_line (window, inner_ne,
2785                      x + half_width, y + 2,
2786                      x + width - 2, y + half_height);
2787       gdk_draw_line (window, middle_nw,
2788                      x + 1, y + half_height,
2789                      x + half_width, y + 1);
2790       gdk_draw_line (window, middle_ne,
2791                      x + half_width, y + 1,
2792                      x + width - 1, y + half_height);
2793       gdk_draw_line (window, outer_nw,
2794                      x, y + half_height,
2795                      x + half_width, y);
2796       gdk_draw_line (window, outer_ne,
2797                      x + half_width, y,
2798                      x + width, y + half_height);
2799     }
2800   
2801   if (area)
2802     {
2803       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2804       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2805       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2806       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2807     }
2808 }
2809
2810 static void
2811 gtk_default_draw_string (GtkStyle      *style,
2812                          GdkWindow     *window,
2813                          GtkStateType   state_type,
2814                          GdkRectangle  *area,
2815                          GtkWidget     *widget,
2816                          const gchar   *detail,
2817                          gint           x,
2818                          gint           y,
2819                          const gchar   *string)
2820 {
2821   g_return_if_fail (GTK_IS_STYLE (style));
2822   g_return_if_fail (window != NULL);
2823   
2824   if (area)
2825     {
2826       gdk_gc_set_clip_rectangle (style->white_gc, area);
2827       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area);
2828     }
2829
2830   if (state_type == GTK_STATE_INSENSITIVE)
2831     gdk_draw_string (window, gtk_style_get_font (style), style->white_gc, x + 1, y + 1, string);
2832
2833   gdk_draw_string (window, gtk_style_get_font (style), style->fg_gc[state_type], x, y, string);
2834
2835   if (area)
2836     {
2837       gdk_gc_set_clip_rectangle (style->white_gc, NULL);
2838       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL);
2839     }
2840 }
2841
2842 static void
2843 option_menu_get_props (GtkWidget      *widget,
2844                        GtkRequisition *indicator_size,
2845                        GtkBorder      *indicator_spacing)
2846 {
2847   GtkRequisition *tmp_size = NULL;
2848   GtkBorder *tmp_spacing = NULL;
2849   
2850   if (widget)
2851     gtk_widget_style_get (widget, 
2852                           "indicator_size", &tmp_size,
2853                           "indicator_spacing", &tmp_spacing,
2854                           NULL);
2855
2856   if (tmp_size)
2857     {
2858       *indicator_size = *tmp_size;
2859       g_free (tmp_size);
2860     }
2861   else
2862     *indicator_size = default_option_indicator_size;
2863
2864   if (tmp_spacing)
2865     {
2866       *indicator_spacing = *tmp_spacing;
2867       g_free (tmp_spacing);
2868     }
2869   else
2870     *indicator_spacing = default_option_indicator_spacing;
2871 }
2872
2873 static void 
2874 gtk_default_draw_box (GtkStyle      *style,
2875                       GdkWindow     *window,
2876                       GtkStateType   state_type,
2877                       GtkShadowType  shadow_type,
2878                       GdkRectangle  *area,
2879                       GtkWidget     *widget,
2880                       const gchar   *detail,
2881                       gint           x,
2882                       gint           y,
2883                       gint           width,
2884                       gint           height)
2885 {
2886   g_return_if_fail (GTK_IS_STYLE (style));
2887   g_return_if_fail (window != NULL);
2888   
2889   sanitize_size (window, &width, &height);
2890   
2891   if (!style->bg_pixmap[state_type] || 
2892       GDK_IS_PIXMAP (window))
2893     {
2894       if (area)
2895         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2896
2897       gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE,
2898                           x, y, width, height);
2899       if (area)
2900         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2901     }
2902   else
2903     gtk_style_apply_default_background (style, window,
2904                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
2905                                         state_type, area, x, y, width, height);
2906   
2907   gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
2908                     x, y, width, height);
2909
2910   if (detail && strcmp (detail, "optionmenu") == 0)
2911     {
2912       GtkRequisition indicator_size;
2913       GtkBorder indicator_spacing;
2914
2915       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
2916
2917       sanitize_size (window, &width, &height);
2918   
2919       gtk_paint_vline (style, window, state_type, area, widget,
2920                        detail,
2921                        y + style->ythickness + 1,
2922                        y + height - style->ythickness - 3,
2923                        x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness);
2924     }
2925 }
2926
2927 static GdkGC*
2928 get_darkened_gc (GdkWindow *window,
2929                  GdkColor  *color,
2930                  gint       darken_count)
2931 {
2932   GdkColor src = *color;
2933   GdkColor shaded;
2934   GdkGC *gc;
2935   
2936   gc = gdk_gc_new (window);
2937
2938   while (darken_count)
2939     {
2940       gtk_style_shade (&src, &shaded, 0.93);
2941       src = shaded;
2942       --darken_count;
2943     }
2944   
2945   gdk_gc_set_rgb_fg_color (gc, &shaded);
2946
2947   return gc;
2948 }
2949
2950 static void 
2951 gtk_default_draw_flat_box (GtkStyle      *style,
2952                            GdkWindow     *window,
2953                            GtkStateType   state_type,
2954                            GtkShadowType  shadow_type,
2955                            GdkRectangle  *area,
2956                            GtkWidget     *widget,
2957                            const gchar   *detail,
2958                            gint           x,
2959                            gint           y,
2960                            gint           width,
2961                            gint           height)
2962 {
2963   GdkGC *gc1;
2964   GdkGC *freeme = NULL;
2965   
2966   g_return_if_fail (GTK_IS_STYLE (style));
2967   g_return_if_fail (window != NULL);
2968   
2969   sanitize_size (window, &width, &height);
2970   
2971   if (detail)
2972     {
2973       if (state_type == GTK_STATE_SELECTED)
2974         {
2975           if (!strcmp ("text", detail))
2976             gc1 = style->bg_gc[GTK_STATE_SELECTED];
2977           else if (!strncmp ("cell_even", detail, strlen ("cell_even")) ||
2978                    !strncmp ("cell_odd", detail, strlen ("cell_odd")))
2979             {
2980               /* This has to be really broken; alex made me do it. -jrb */
2981               if (GTK_WIDGET_HAS_FOCUS (widget))
2982                 gc1 = style->base_gc[state_type];
2983               else 
2984                 gc1 = style->base_gc[GTK_STATE_ACTIVE];
2985             }
2986           else
2987             {
2988               gc1 = style->bg_gc[state_type];
2989             }
2990         }
2991       else
2992         {
2993           if (!strcmp ("viewportbin", detail))
2994             gc1 = style->bg_gc[GTK_STATE_NORMAL];
2995           else if (!strcmp ("entry_bg", detail))
2996             gc1 = style->base_gc[state_type];
2997
2998           /* For trees: even rows are base color, odd rows are a shade of
2999            * the base color, the sort column is a shade of the original color
3000            * for that row.
3001            */
3002
3003           /* FIXME when we have style properties, clean this up.
3004            */
3005           
3006           else if (!strcmp ("cell_even", detail) ||
3007                    !strcmp ("cell_odd", detail) ||
3008                    !strcmp ("cell_even_ruled", detail))
3009             {
3010               gc1 = style->base_gc[state_type];
3011             }
3012           else if (!strcmp ("cell_even_sorted", detail) ||
3013                    !strcmp ("cell_odd_sorted", detail) ||
3014                    !strcmp ("cell_odd_ruled", detail) ||
3015                    !strcmp ("cell_even_ruled_sorted", detail))
3016             {
3017               freeme = get_darkened_gc (window, &style->base[state_type], 1);
3018               gc1 = freeme;
3019             }
3020           else if (!strcmp ("cell_odd_ruled_sorted", detail))
3021             {
3022               freeme = get_darkened_gc (window, &style->base[state_type], 2);
3023               gc1 = freeme;
3024             }
3025           else
3026             gc1 = style->bg_gc[state_type];
3027         }
3028     }
3029   else
3030     gc1 = style->bg_gc[state_type];
3031   
3032   if (!style->bg_pixmap[state_type] || gc1 != style->bg_gc[state_type] ||
3033       GDK_IS_PIXMAP (window))
3034     {
3035       if (area)
3036         gdk_gc_set_clip_rectangle (gc1, area);
3037
3038       gdk_draw_rectangle (window, gc1, TRUE,
3039                           x, y, width, height);
3040
3041       if (detail && !strcmp ("tooltip", detail))
3042         gdk_draw_rectangle (window, style->black_gc, FALSE,
3043                             x, y, width - 1, height - 1);
3044
3045       if (area)
3046         gdk_gc_set_clip_rectangle (gc1, NULL);
3047     }
3048   else
3049     gtk_style_apply_default_background (style, window,
3050                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3051                                         state_type, area, x, y, width, height);
3052
3053
3054   if (freeme)
3055     g_object_unref (G_OBJECT (freeme));
3056 }
3057
3058 static void 
3059 gtk_default_draw_check (GtkStyle      *style,
3060                         GdkWindow     *window,
3061                         GtkStateType   state_type,
3062                         GtkShadowType  shadow_type,
3063                         GdkRectangle  *area,
3064                         GtkWidget     *widget,
3065                         const gchar   *detail,
3066                         gint           x,
3067                         gint           y,
3068                         gint           width,
3069                         gint           height)
3070 {
3071   if (detail && strcmp (detail, "cellcheck") == 0)
3072     {
3073       gdk_draw_rectangle (window,
3074                           widget->style->base_gc[state_type],
3075                           TRUE,
3076                           x, y,
3077                           width, height);
3078       gdk_draw_rectangle (window,
3079                           widget->style->text_gc[state_type],
3080                           FALSE,
3081                           x, y,
3082                           width, height);
3083
3084       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3085       y -= (((1 + INDICATOR_PART_SIZE - height) / 2) - 1);
3086       if (shadow_type == GTK_SHADOW_IN)
3087         {
3088           draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT);
3089           draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA);
3090         }
3091     }
3092   else
3093     {
3094       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3095       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3096       
3097       if (strcmp (detail, "check") == 0)        /* Menu item */
3098         {
3099           if (shadow_type == GTK_SHADOW_IN)
3100             {
3101               draw_part (window, style->black_gc, area, x, y, CHECK_TEXT);
3102               draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_AA);
3103             }
3104         }
3105       else
3106         {
3107           draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
3108           draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_DARK);
3109           draw_part (window, style->mid_gc[state_type], area, x, y, CHECK_MID);
3110           draw_part (window, style->light_gc[state_type], area, x, y, CHECK_LIGHT);
3111           draw_part (window, style->base_gc[state_type], area, x, y, CHECK_BASE);
3112           
3113           if (shadow_type == GTK_SHADOW_IN)
3114             {
3115               draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT);
3116               draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA);
3117             }
3118         }
3119     }
3120
3121 }
3122
3123 static void 
3124 gtk_default_draw_option (GtkStyle      *style,
3125                          GdkWindow     *window,
3126                          GtkStateType   state_type,
3127                          GtkShadowType  shadow_type,
3128                          GdkRectangle  *area,
3129                          GtkWidget     *widget,
3130                          const gchar   *detail,
3131                          gint           x,
3132                          gint           y,
3133                          gint           width,
3134                          gint           height)
3135 {
3136   if (detail && strcmp (detail, "cellradio") == 0)
3137     {
3138       gdk_draw_arc (window,
3139                     widget->style->fg_gc[state_type],
3140                     FALSE,
3141                     x, y,
3142                     width,
3143                     height,
3144                     0, 360*64);
3145
3146       if (shadow_type == GTK_SHADOW_IN)
3147         {
3148           gdk_draw_arc (window,
3149                         widget->style->fg_gc[state_type],
3150                         TRUE,
3151                         x + 2,
3152                         y + 2,
3153                         width - 4,
3154                         height - 4,
3155                         0, 360*64);
3156         }
3157     }
3158   else
3159     {
3160       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3161       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3162       
3163       if (strcmp (detail, "option") == 0)       /* Menu item */
3164         {
3165           if (shadow_type == GTK_SHADOW_IN)
3166             draw_part (window, style->fg_gc[state_type], area, x, y, RADIO_TEXT);
3167         }
3168       else
3169         {
3170           draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
3171           draw_part (window, style->dark_gc[state_type], area, x, y, RADIO_DARK);
3172           draw_part (window, style->mid_gc[state_type], area, x, y, RADIO_MID);
3173           draw_part (window, style->light_gc[state_type], area, x, y, RADIO_LIGHT);
3174           draw_part (window, style->base_gc[state_type], area, x, y, RADIO_BASE);
3175           
3176           if (shadow_type == GTK_SHADOW_IN)
3177             draw_part (window, style->text_gc[state_type], area, x, y, RADIO_TEXT);
3178         }
3179     }
3180 }
3181
3182 static void
3183 gtk_default_draw_tab (GtkStyle      *style,
3184                       GdkWindow     *window,
3185                       GtkStateType   state_type,
3186                       GtkShadowType  shadow_type,
3187                       GdkRectangle  *area,
3188                       GtkWidget     *widget,
3189                       const gchar   *detail,
3190                       gint           x,
3191                       gint           y,
3192                       gint           width,
3193                       gint           height)
3194 {
3195   GtkRequisition indicator_size;
3196   GtkBorder indicator_spacing;
3197   
3198   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3199
3200   x += (width - indicator_size.width) / 2;
3201   y += (height - indicator_size.height) / 2 - 1;
3202
3203   draw_varrow (window, style->black_gc, shadow_type, area, GTK_ARROW_UP,
3204                x, y, indicator_size.width, 5);
3205   draw_varrow (window, style->black_gc, shadow_type, area, GTK_ARROW_DOWN,
3206                x, y + 8, indicator_size.width, 5);
3207 }
3208
3209 static void 
3210 gtk_default_draw_shadow_gap (GtkStyle       *style,
3211                              GdkWindow      *window,
3212                              GtkStateType    state_type,
3213                              GtkShadowType   shadow_type,
3214                              GdkRectangle   *area,
3215                              GtkWidget      *widget,
3216                              const gchar    *detail,
3217                              gint            x,
3218                              gint            y,
3219                              gint            width,
3220                              gint            height,
3221                              GtkPositionType gap_side,
3222                              gint            gap_x,
3223                              gint            gap_width)
3224 {
3225   GdkGC *gc1 = NULL;
3226   GdkGC *gc2 = NULL;
3227   GdkGC *gc3 = NULL;
3228   GdkGC *gc4 = NULL;
3229   
3230   g_return_if_fail (GTK_IS_STYLE (style));
3231   g_return_if_fail (window != NULL);
3232   
3233   sanitize_size (window, &width, &height);
3234   
3235   switch (shadow_type)
3236     {
3237     case GTK_SHADOW_NONE:
3238       return;
3239     case GTK_SHADOW_IN:
3240       gc1 = style->dark_gc[state_type];
3241       gc2 = style->black_gc;
3242       gc3 = style->bg_gc[state_type];
3243       gc4 = style->light_gc[state_type];
3244       break;
3245     case GTK_SHADOW_ETCHED_IN:
3246       gc1 = style->dark_gc[state_type];
3247       gc2 = style->light_gc[state_type];
3248       gc3 = style->dark_gc[state_type];
3249       gc4 = style->light_gc[state_type];
3250       break;
3251     case GTK_SHADOW_OUT:
3252       gc1 = style->light_gc[state_type];
3253       gc2 = style->bg_gc[state_type];
3254       gc3 = style->dark_gc[state_type];
3255       gc4 = style->black_gc;
3256       break;
3257     case GTK_SHADOW_ETCHED_OUT:
3258       gc1 = style->light_gc[state_type];
3259       gc2 = style->dark_gc[state_type];
3260       gc3 = style->light_gc[state_type];
3261       gc4 = style->dark_gc[state_type];
3262       break;
3263     }
3264   if (area)
3265     {
3266       gdk_gc_set_clip_rectangle (gc1, area);
3267       gdk_gc_set_clip_rectangle (gc2, area);
3268       gdk_gc_set_clip_rectangle (gc3, area);
3269       gdk_gc_set_clip_rectangle (gc4, area);
3270     }
3271   
3272   switch (shadow_type)
3273     {
3274     case GTK_SHADOW_NONE:
3275     case GTK_SHADOW_IN:
3276     case GTK_SHADOW_OUT:
3277     case GTK_SHADOW_ETCHED_IN:
3278     case GTK_SHADOW_ETCHED_OUT:
3279       switch (gap_side)
3280         {
3281         case GTK_POS_TOP:
3282           gdk_draw_line (window, gc1,
3283                          x, y, x, y + height - 1);
3284           gdk_draw_line (window, gc2,
3285                          x + 1, y, x + 1, y + height - 2);
3286           
3287           gdk_draw_line (window, gc3,
3288                          x + 1, y + height - 2, x + width - 2, y + height - 2);
3289           gdk_draw_line (window, gc3,
3290                          x + width - 2, y, x + width - 2, y + height - 2);
3291           gdk_draw_line (window, gc4,
3292                          x, y + height - 1, x + width - 1, y + height - 1);
3293           gdk_draw_line (window, gc4,
3294                          x + width - 1, y, x + width - 1, y + height - 1);
3295           if (gap_x > 0)
3296             {
3297               gdk_draw_line (window, gc1,
3298                              x, y, x + gap_x - 1, y);
3299               gdk_draw_line (window, gc2,
3300                              x + 1, y + 1, x + gap_x - 1, y + 1);
3301               gdk_draw_line (window, gc2,
3302                              x + gap_x, y, x + gap_x, y);
3303             }
3304           if ((width - (gap_x + gap_width)) > 0)
3305             {
3306               gdk_draw_line (window, gc1,
3307                              x + gap_x + gap_width, y, x + width - 2, y);
3308               gdk_draw_line (window, gc2,
3309                              x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
3310               gdk_draw_line (window, gc2,
3311                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3312             }
3313           break;
3314         case GTK_POS_BOTTOM:
3315           gdk_draw_line (window, gc1,
3316                          x, y, x + width - 1, y);
3317           gdk_draw_line (window, gc1,
3318                          x, y, x, y + height - 1);
3319           gdk_draw_line (window, gc2,
3320                          x + 1, y + 1, x + width - 2, y + 1);
3321           gdk_draw_line (window, gc2,
3322                          x + 1, y + 1, x + 1, y + height - 1);
3323           
3324           gdk_draw_line (window, gc3,
3325                          x + width - 2, y + 1, x + width - 2, y + height - 1);
3326           gdk_draw_line (window, gc4,
3327                          x + width - 1, y, x + width - 1, y + height - 1);
3328           if (gap_x > 0)
3329             {
3330               gdk_draw_line (window, gc4,
3331                              x, y + height - 1, x + gap_x - 1, y + height - 1);
3332               gdk_draw_line (window, gc3,
3333                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3334               gdk_draw_line (window, gc3,
3335                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3336             }
3337           if ((width - (gap_x + gap_width)) > 0)
3338             {
3339               gdk_draw_line (window, gc4,
3340                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3341               gdk_draw_line (window, gc3,
3342                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3343               gdk_draw_line (window, gc3,
3344                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3345             }
3346           break;
3347         case GTK_POS_LEFT:
3348           gdk_draw_line (window, gc1,
3349                          x, y, x + width - 1, y);
3350           gdk_draw_line (window, gc2,
3351                          x, y + 1, x + width - 2, y + 1);
3352           
3353           gdk_draw_line (window, gc3,
3354                          x, y + height - 2, x + width - 2, y + height - 2);
3355           gdk_draw_line (window, gc3,
3356                          x + width - 2, y + 1, x + width - 2, y + height - 2);
3357           gdk_draw_line (window, gc4,
3358                          x, y + height - 1, x + width - 1, y + height - 1);
3359           gdk_draw_line (window, gc4,
3360                          x + width - 1, y, x + width - 1, y + height - 1);
3361           if (gap_x > 0)
3362             {
3363               gdk_draw_line (window, gc1,
3364                              x, y, x, y + gap_x - 1);
3365               gdk_draw_line (window, gc2,
3366                              x + 1, y + 1, x + 1, y + gap_x - 1);
3367               gdk_draw_line (window, gc2,
3368                              x, y + gap_x, x, y + gap_x);
3369             }
3370           if ((width - (gap_x + gap_width)) > 0)
3371             {
3372               gdk_draw_line (window, gc1,
3373                              x, y + gap_x + gap_width, x, y + height - 2);
3374               gdk_draw_line (window, gc2,
3375                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3376               gdk_draw_line (window, gc2,
3377                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3378             }
3379           break;
3380         case GTK_POS_RIGHT:
3381           gdk_draw_line (window, gc1,
3382                          x, y, x + width - 1, y);
3383           gdk_draw_line (window, gc1,
3384                          x, y, x, y + height - 1);
3385           gdk_draw_line (window, gc2,
3386                          x + 1, y + 1, x + width - 1, y + 1);
3387           gdk_draw_line (window, gc2,
3388                          x + 1, y + 1, x + 1, y + height - 2);
3389           
3390           gdk_draw_line (window, gc3,
3391                          x + 1, y + height - 2, x + width - 1, y + height - 2);
3392           gdk_draw_line (window, gc4,
3393                          x, y + height - 1, x + width - 1, y + height - 1);
3394           if (gap_x > 0)
3395             {
3396               gdk_draw_line (window, gc4,
3397                              x + width - 1, y, x + width - 1, y + gap_x - 1);
3398               gdk_draw_line (window, gc3,
3399                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3400               gdk_draw_line (window, gc3,
3401                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3402             }
3403           if ((width - (gap_x + gap_width)) > 0)
3404             {
3405               gdk_draw_line (window, gc4,
3406                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3407               gdk_draw_line (window, gc3,
3408                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3409               gdk_draw_line (window, gc3,
3410                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3411             }
3412           break;
3413         }
3414     }
3415
3416   if (area)
3417     {
3418       gdk_gc_set_clip_rectangle (gc1, NULL);
3419       gdk_gc_set_clip_rectangle (gc2, NULL);
3420       gdk_gc_set_clip_rectangle (gc3, NULL);
3421       gdk_gc_set_clip_rectangle (gc4, NULL);
3422     }
3423 }
3424
3425 static void 
3426 gtk_default_draw_box_gap (GtkStyle       *style,
3427                           GdkWindow      *window,
3428                           GtkStateType    state_type,
3429                           GtkShadowType   shadow_type,
3430                           GdkRectangle   *area,
3431                           GtkWidget      *widget,
3432                           const gchar    *detail,
3433                           gint            x,
3434                           gint            y,
3435                           gint            width,
3436                           gint            height,
3437                           GtkPositionType gap_side,
3438                           gint            gap_x,
3439                           gint            gap_width)
3440 {
3441   GdkGC *gc1 = NULL;
3442   GdkGC *gc2 = NULL;
3443   GdkGC *gc3 = NULL;
3444   GdkGC *gc4 = NULL;
3445   
3446   g_return_if_fail (GTK_IS_STYLE (style));
3447   g_return_if_fail (window != NULL);
3448   
3449   gtk_style_apply_default_background (style, window,
3450                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
3451                                       state_type, area, x, y, width, height);
3452   
3453   sanitize_size (window, &width, &height);
3454   
3455   switch (shadow_type)
3456     {
3457     case GTK_SHADOW_NONE:
3458       return;
3459     case GTK_SHADOW_IN:
3460       gc1 = style->dark_gc[state_type];
3461       gc2 = style->black_gc;
3462       gc3 = style->bg_gc[state_type];
3463       gc4 = style->light_gc[state_type];
3464       break;
3465     case GTK_SHADOW_ETCHED_IN:
3466       gc1 = style->dark_gc[state_type];
3467       gc2 = style->light_gc[state_type];
3468       gc3 = style->dark_gc[state_type];
3469       gc4 = style->light_gc[state_type];
3470       break;
3471     case GTK_SHADOW_OUT:
3472       gc1 = style->light_gc[state_type];
3473       gc2 = style->bg_gc[state_type];
3474       gc3 = style->dark_gc[state_type];
3475       gc4 = style->black_gc;
3476       break;
3477     case GTK_SHADOW_ETCHED_OUT:
3478       gc1 = style->light_gc[state_type];
3479       gc2 = style->dark_gc[state_type];
3480       gc3 = style->light_gc[state_type];
3481       gc4 = style->dark_gc[state_type];
3482       break;
3483     }
3484
3485   if (area)
3486     {
3487       gdk_gc_set_clip_rectangle (gc1, area);
3488       gdk_gc_set_clip_rectangle (gc2, area);
3489       gdk_gc_set_clip_rectangle (gc3, area);
3490       gdk_gc_set_clip_rectangle (gc4, area);
3491     }
3492   
3493   switch (shadow_type)
3494     {
3495     case GTK_SHADOW_NONE:
3496     case GTK_SHADOW_IN:
3497     case GTK_SHADOW_OUT:
3498     case GTK_SHADOW_ETCHED_IN:
3499     case GTK_SHADOW_ETCHED_OUT:
3500       switch (gap_side)
3501         {
3502         case GTK_POS_TOP:
3503           gdk_draw_line (window, gc1,
3504                          x, y, x, y + height - 1);
3505           gdk_draw_line (window, gc2,
3506                          x + 1, y, x + 1, y + height - 2);
3507           
3508           gdk_draw_line (window, gc3,
3509                          x + 1, y + height - 2, x + width - 2, y + height - 2);
3510           gdk_draw_line (window, gc3,
3511                          x + width - 2, y, x + width - 2, y + height - 2);
3512           gdk_draw_line (window, gc4,
3513                          x, y + height - 1, x + width - 1, y + height - 1);
3514           gdk_draw_line (window, gc4,
3515                          x + width - 1, y, x + width - 1, y + height - 1);
3516           if (gap_x > 0)
3517             {
3518               gdk_draw_line (window, gc1,
3519                              x, y, x + gap_x - 1, y);
3520               gdk_draw_line (window, gc2,
3521                              x + 1, y + 1, x + gap_x - 1, y + 1);
3522               gdk_draw_line (window, gc2,
3523                              x + gap_x, y, x + gap_x, y);
3524             }
3525           if ((width - (gap_x + gap_width)) > 0)
3526             {
3527               gdk_draw_line (window, gc1,
3528                              x + gap_x + gap_width, y, x + width - 2, y);
3529               gdk_draw_line (window, gc2,
3530                              x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
3531               gdk_draw_line (window, gc2,
3532                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3533             }
3534           break;
3535         case  GTK_POS_BOTTOM:
3536           gdk_draw_line (window, gc1,
3537                          x, y, x + width - 1, y);
3538           gdk_draw_line (window, gc1,
3539                          x, y, x, y + height - 1);
3540           gdk_draw_line (window, gc2,
3541                          x + 1, y + 1, x + width - 2, y + 1);
3542           gdk_draw_line (window, gc2,
3543                          x + 1, y + 1, x + 1, y + height - 1);
3544           
3545           gdk_draw_line (window, gc3,
3546                          x + width - 2, y + 1, x + width - 2, y + height - 1);
3547           gdk_draw_line (window, gc4,
3548                          x + width - 1, y, x + width - 1, y + height - 1);
3549           if (gap_x > 0)
3550             {
3551               gdk_draw_line (window, gc4,
3552                              x, y + height - 1, x + gap_x - 1, y + height - 1);
3553               gdk_draw_line (window, gc3,
3554                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3555               gdk_draw_line (window, gc3,
3556                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3557             }
3558           if ((width - (gap_x + gap_width)) > 0)
3559             {
3560               gdk_draw_line (window, gc4,
3561                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3562               gdk_draw_line (window, gc3,
3563                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3564               gdk_draw_line (window, gc3,
3565                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3566             }
3567           break;
3568         case GTK_POS_LEFT:
3569           gdk_draw_line (window, gc1,
3570                          x, y, x + width - 1, y);
3571           gdk_draw_line (window, gc2,
3572                          x, y + 1, x + width - 2, y + 1);
3573           
3574           gdk_draw_line (window, gc3,
3575                          x, y + height - 2, x + width - 2, y + height - 2);
3576           gdk_draw_line (window, gc3,
3577                          x + width - 2, y + 1, x + width - 2, y + height - 2);
3578           gdk_draw_line (window, gc4,
3579                          x, y + height - 1, x + width - 1, y + height - 1);
3580           gdk_draw_line (window, gc4,
3581                          x + width - 1, y, x + width - 1, y + height - 1);
3582           if (gap_x > 0)
3583             {
3584               gdk_draw_line (window, gc1,
3585                              x, y, x, y + gap_x - 1);
3586               gdk_draw_line (window, gc2,
3587                              x + 1, y + 1, x + 1, y + gap_x - 1);
3588               gdk_draw_line (window, gc2,
3589                              x, y + gap_x, x, y + gap_x);
3590             }
3591           if ((width - (gap_x + gap_width)) > 0)
3592             {
3593               gdk_draw_line (window, gc1,
3594                              x, y + gap_x + gap_width, x, y + height - 2);
3595               gdk_draw_line (window, gc2,
3596                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
3597               gdk_draw_line (window, gc2,
3598                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
3599             }
3600           break;
3601         case GTK_POS_RIGHT:
3602           gdk_draw_line (window, gc1,
3603                          x, y, x + width - 1, y);
3604           gdk_draw_line (window, gc1,
3605                          x, y, x, y + height - 1);
3606           gdk_draw_line (window, gc2,
3607                          x + 1, y + 1, x + width - 1, y + 1);
3608           gdk_draw_line (window, gc2,
3609                          x + 1, y + 1, x + 1, y + height - 2);
3610           
3611           gdk_draw_line (window, gc3,
3612                          x + 1, y + height - 2, x + width - 1, y + height - 2);
3613           gdk_draw_line (window, gc4,
3614                          x, y + height - 1, x + width - 1, y + height - 1);
3615           if (gap_x > 0)
3616             {
3617               gdk_draw_line (window, gc4,
3618                              x + width - 1, y, x + width - 1, y + gap_x - 1);
3619               gdk_draw_line (window, gc3,
3620                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
3621               gdk_draw_line (window, gc3,
3622                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
3623             }
3624           if ((width - (gap_x + gap_width)) > 0)
3625             {
3626               gdk_draw_line (window, gc4,
3627                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
3628               gdk_draw_line (window, gc3,
3629                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
3630               gdk_draw_line (window, gc3,
3631                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
3632             }
3633           break;
3634         }
3635     }
3636
3637   if (area)
3638     {
3639       gdk_gc_set_clip_rectangle (gc1, NULL);
3640       gdk_gc_set_clip_rectangle (gc2, NULL);
3641       gdk_gc_set_clip_rectangle (gc3, NULL);
3642       gdk_gc_set_clip_rectangle (gc4, NULL);
3643     }
3644 }
3645
3646 static void 
3647 gtk_default_draw_extension (GtkStyle       *style,
3648                             GdkWindow      *window,
3649                             GtkStateType    state_type,
3650                             GtkShadowType   shadow_type,
3651                             GdkRectangle   *area,
3652                             GtkWidget      *widget,
3653                             const gchar    *detail,
3654                             gint            x,
3655                             gint            y,
3656                             gint            width,
3657                             gint            height,
3658                             GtkPositionType gap_side)
3659 {
3660   GdkGC *gc1 = NULL;
3661   GdkGC *gc2 = NULL;
3662   GdkGC *gc3 = NULL;
3663   GdkGC *gc4 = NULL;
3664   
3665   g_return_if_fail (GTK_IS_STYLE (style));
3666   g_return_if_fail (window != NULL);
3667   
3668   gtk_style_apply_default_background (style, window,
3669                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
3670                                       GTK_STATE_NORMAL, area, x, y, width, height);
3671   
3672   sanitize_size (window, &width, &height);
3673   
3674   switch (shadow_type)
3675     {
3676     case GTK_SHADOW_NONE:
3677       return;
3678     case GTK_SHADOW_IN:
3679       gc1 = style->dark_gc[state_type];
3680       gc2 = style->black_gc;
3681       gc3 = style->bg_gc[state_type];
3682       gc4 = style->light_gc[state_type];
3683       break;
3684     case GTK_SHADOW_ETCHED_IN:
3685       gc1 = style->dark_gc[state_type];
3686       gc2 = style->light_gc[state_type];
3687       gc3 = style->dark_gc[state_type];
3688       gc4 = style->light_gc[state_type];
3689       break;
3690     case GTK_SHADOW_OUT:
3691       gc1 = style->light_gc[state_type];
3692       gc2 = style->bg_gc[state_type];
3693       gc3 = style->dark_gc[state_type];
3694       gc4 = style->black_gc;
3695       break;
3696     case GTK_SHADOW_ETCHED_OUT:
3697       gc1 = style->light_gc[state_type];
3698       gc2 = style->dark_gc[state_type];
3699       gc3 = style->light_gc[state_type];
3700       gc4 = style->dark_gc[state_type];
3701       break;
3702     }
3703
3704   if (area)
3705     {
3706       gdk_gc_set_clip_rectangle (gc1, area);
3707       gdk_gc_set_clip_rectangle (gc2, area);
3708       gdk_gc_set_clip_rectangle (gc3, area);
3709       gdk_gc_set_clip_rectangle (gc4, area);
3710     }
3711
3712   switch (shadow_type)
3713     {
3714     case GTK_SHADOW_NONE:
3715     case GTK_SHADOW_IN:
3716     case GTK_SHADOW_OUT:
3717     case GTK_SHADOW_ETCHED_IN:
3718     case GTK_SHADOW_ETCHED_OUT:
3719       switch (gap_side)
3720         {
3721         case GTK_POS_TOP:
3722           gtk_style_apply_default_background (style, window,
3723                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3724                                               state_type, area,
3725                                               x + style->xthickness, 
3726                                               y, 
3727                                               width - (2 * style->xthickness), 
3728                                               height - (style->ythickness));
3729           gdk_draw_line (window, gc1,
3730                          x, y, x, y + height - 2);
3731           gdk_draw_line (window, gc2,
3732                          x + 1, y, x + 1, y + height - 2);
3733           
3734           gdk_draw_line (window, gc3,
3735                          x + 2, y + height - 2, x + width - 2, y + height - 2);
3736           gdk_draw_line (window, gc3,
3737                          x + width - 2, y, x + width - 2, y + height - 2);
3738           gdk_draw_line (window, gc4,
3739                          x + 1, y + height - 1, x + width - 2, y + height - 1);
3740           gdk_draw_line (window, gc4,
3741                          x + width - 1, y, x + width - 1, y + height - 2);
3742           break;
3743         case GTK_POS_BOTTOM:
3744           gtk_style_apply_default_background (style, window,
3745                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3746                                               state_type, area,
3747                                               x + style->xthickness, 
3748                                               y + style->ythickness, 
3749                                               width - (2 * style->xthickness), 
3750                                               height - (style->ythickness));
3751           gdk_draw_line (window, gc1,
3752                          x + 1, y, x + width - 2, y);
3753           gdk_draw_line (window, gc1,
3754                          x, y + 1, x, y + height - 1);
3755           gdk_draw_line (window, gc2,
3756                          x + 1, y + 1, x + width - 2, y + 1);
3757           gdk_draw_line (window, gc2,
3758                          x + 1, y + 1, x + 1, y + height - 1);
3759           
3760           gdk_draw_line (window, gc3,
3761                          x + width - 2, y + 2, x + width - 2, y + height - 1);
3762           gdk_draw_line (window, gc4,
3763                          x + width - 1, y + 1, x + width - 1, y + height - 1);
3764           break;
3765         case GTK_POS_LEFT:
3766           gtk_style_apply_default_background (style, window,
3767                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3768                                               state_type, area,
3769                                               x, 
3770                                               y + style->ythickness, 
3771                                               width - (style->xthickness), 
3772                                               height - (2 * style->ythickness));
3773           gdk_draw_line (window, gc1,
3774                          x, y, x + width - 2, y);
3775           gdk_draw_line (window, gc2,
3776                          x + 1, y + 1, x + width - 2, y + 1);
3777           
3778           gdk_draw_line (window, gc3,
3779                          x, y + height - 2, x + width - 2, y + height - 2);
3780           gdk_draw_line (window, gc3,
3781                          x + width - 2, y + 2, x + width - 2, y + height - 2);
3782           gdk_draw_line (window, gc4,
3783                          x, y + height - 1, x + width - 2, y + height - 1);
3784           gdk_draw_line (window, gc4,
3785                          x + width - 1, y + 1, x + width - 1, y + height - 2);
3786           break;
3787         case GTK_POS_RIGHT:
3788           gtk_style_apply_default_background (style, window,
3789                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
3790                                               state_type, area,
3791                                               x + style->xthickness, 
3792                                               y + style->ythickness, 
3793                                               width - (style->xthickness), 
3794                                               height - (2 * style->ythickness));
3795           gdk_draw_line (window, gc1,
3796                          x + 1, y, x + width - 1, y);
3797           gdk_draw_line (window, gc1,
3798                          x, y + 1, x, y + height - 2);
3799           gdk_draw_line (window, gc2,
3800                          x + 1, y + 1, x + width - 1, y + 1);
3801           gdk_draw_line (window, gc2,
3802                          x + 1, y + 1, x + 1, y + height - 2);
3803           
3804           gdk_draw_line (window, gc3,
3805                          x + 2, y + height - 2, x + width - 1, y + height - 2);
3806           gdk_draw_line (window, gc4,
3807                          x + 1, y + height - 1, x + width - 1, y + height - 1);
3808           break;
3809         }
3810     }
3811
3812   if (area)
3813     {
3814       gdk_gc_set_clip_rectangle (gc1, NULL);
3815       gdk_gc_set_clip_rectangle (gc2, NULL);
3816       gdk_gc_set_clip_rectangle (gc3, NULL);
3817       gdk_gc_set_clip_rectangle (gc4, NULL);
3818     }
3819 }
3820
3821 static void 
3822 gtk_default_draw_focus (GtkStyle      *style,
3823                         GdkWindow     *window,
3824                         GtkStateType   state_type,
3825                         GdkRectangle  *area,
3826                         GtkWidget     *widget,
3827                         const gchar   *detail,
3828                         gint           x,
3829                         gint           y,
3830                         gint           width,
3831                         gint           height)
3832 {
3833   GdkPoint points[5];
3834   GdkGC    *gc;
3835   gboolean free_dash_list = FALSE;
3836   gint line_width = 1;
3837   gchar *dash_list = "\1\1";
3838   gint dash_len;
3839
3840   gc = style->fg_gc[state_type];
3841
3842   if (widget)
3843     {
3844       gtk_widget_style_get (widget,
3845                             "focus-line-width", &line_width,
3846                             "focus-line-pattern", (gchar *)&dash_list,
3847                             NULL);
3848
3849       free_dash_list = TRUE;
3850   }
3851
3852   sanitize_size (window, &width, &height);
3853   
3854   if (area)
3855     gdk_gc_set_clip_rectangle (gc, area);
3856
3857   gdk_gc_set_line_attributes (gc, line_width,
3858                               dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID,
3859                               GDK_CAP_BUTT, GDK_JOIN_MITER);
3860
3861
3862   if (detail && !strcmp (detail, "add-mode"))
3863     {
3864       if (free_dash_list)
3865         g_free (dash_list);
3866       
3867       dash_list = "\4\4";
3868       free_dash_list = FALSE;
3869     }
3870
3871   points[0].x = x + line_width / 2;
3872   points[0].y = y + line_width / 2;
3873   points[1].x = x + width - line_width + line_width / 2;
3874   points[1].y = y + line_width / 2;
3875   points[2].x = x + width - line_width + line_width / 2;
3876   points[2].y = y + height - line_width + line_width / 2;
3877   points[3].x = x + line_width / 2;
3878   points[3].y = y + height - line_width + line_width / 2;
3879   points[4] = points[0];
3880
3881   if (!dash_list[0])
3882     {
3883       gdk_draw_lines (window, gc, points, 5);
3884     }
3885   else
3886     {
3887       /* We go through all the pain below because the X rasterization
3888        * rules don't really work right for dashed lines if you
3889        * want continuity in segments that go between top/right
3890        * and left/bottom. For instance, a top left corner
3891        * with a 1-1 dash is drawn as:
3892        *
3893        *  X X X 
3894        *  X
3895        *
3896        *  X
3897        *
3898        * This is because pixels on the top and left boundaries
3899        * of polygons are drawn, but not on the bottom and right.
3900        * So, if you have a line going up that turns the corner
3901        * and goes right, there is a one pixel shift in the pattern.
3902        *
3903        * So, to fix this, we drawn the top and right in one call,
3904        * then the left and bottom in another call, fixing up
3905        * the dash offset for the second call ourselves to get
3906        * continuity at the upper left.
3907        *
3908        * It's not perfect since we really should have a join at
3909        * the upper left and lower right instead of two intersecting
3910        * lines but that's only really apparent for no-dashes,
3911        * which (for this reason) are done as one polygon and
3912        * don't to through this code path.
3913        */
3914       
3915       dash_len = strlen (dash_list);
3916       
3917       if (dash_list[0])
3918         gdk_gc_set_dashes (gc, 0, dash_list, dash_len);
3919       
3920       gdk_draw_lines (window, gc, points, 3);
3921       
3922       /* We draw this line one farther over than it is "supposed" to
3923        * because of another rasterization problem ... if two 1 pixel
3924        * unjoined lines meet at the lower right, there will be a missing
3925        * pixel.
3926        */
3927       points[2].x += 1;
3928       
3929       if (dash_list[0])
3930         {
3931           gint dash_pixels = 0;
3932           gint i;
3933           
3934           /* Adjust the dash offset for the bottom and left so we
3935            * match up at the upper left.
3936            */
3937           for (i = 0; i < dash_len; i++)
3938             dash_pixels += dash_list[i];
3939       
3940           if (dash_len % 2 == 1)
3941             dash_pixels *= 2;
3942           
3943           gdk_gc_set_dashes (gc, dash_pixels - (width + height - 2 * line_width) % dash_pixels, dash_list, dash_len);
3944         }
3945       
3946       gdk_draw_lines (window, gc, points + 2, 3);
3947     }
3948
3949   gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
3950
3951   if (area)
3952     gdk_gc_set_clip_rectangle (gc, NULL);
3953
3954   if (free_dash_list)
3955     g_free (dash_list);
3956 }
3957
3958 static void 
3959 gtk_default_draw_slider (GtkStyle      *style,
3960                          GdkWindow     *window,
3961                          GtkStateType   state_type,
3962                          GtkShadowType  shadow_type,
3963                          GdkRectangle  *area,
3964                          GtkWidget     *widget,
3965                          const gchar   *detail,
3966                          gint           x,
3967                          gint           y,
3968                          gint           width,
3969                          gint           height,
3970                          GtkOrientation orientation)
3971 {
3972   g_return_if_fail (GTK_IS_STYLE (style));
3973   g_return_if_fail (window != NULL);
3974   
3975   sanitize_size (window, &width, &height);
3976   
3977   gtk_paint_box (style, window, state_type, shadow_type,
3978                  area, widget, detail, x, y, width, height);
3979
3980   if (detail &&
3981       (strcmp ("hscale", detail) == 0 ||
3982        strcmp ("vscale", detail) == 0))
3983     {
3984       if (orientation == GTK_ORIENTATION_HORIZONTAL)
3985         gtk_paint_vline (style, window, state_type, area, widget, detail, 
3986                          y + style->ythickness, 
3987                          y + height - style->ythickness - 1, x + width / 2);
3988       else
3989         gtk_paint_hline (style, window, state_type, area, widget, detail, 
3990                          x + style->xthickness, 
3991                          x + width - style->xthickness - 1, y + height / 2);
3992     }
3993 }
3994
3995 static void
3996 draw_dot (GdkWindow    *window,
3997           GdkGC        *light_gc,
3998           GdkGC        *dark_gc,
3999           gint          x,
4000           gint          y,
4001           gushort       size)
4002 {
4003   
4004   size = CLAMP (size, 2, 3);
4005
4006   if (size == 2)
4007     {
4008       gdk_draw_point (window, light_gc, x, y);
4009       gdk_draw_point (window, light_gc, x+1, y+1);
4010     }
4011   else if (size == 3);
4012     {
4013       gdk_draw_point (window, light_gc, x, y);
4014       gdk_draw_point (window, light_gc, x+1, y);
4015       gdk_draw_point (window, light_gc, x, y+1);
4016       gdk_draw_point (window, dark_gc, x+1, y+2);
4017       gdk_draw_point (window, dark_gc, x+2, y+1);
4018       gdk_draw_point (window, dark_gc, x+2, y+2);
4019     }
4020 }
4021
4022 static void 
4023 gtk_default_draw_handle (GtkStyle      *style,
4024                          GdkWindow     *window,
4025                          GtkStateType   state_type,
4026                          GtkShadowType  shadow_type,
4027                          GdkRectangle  *area,
4028                          GtkWidget     *widget,
4029                          const gchar   *detail,
4030                          gint           x,
4031                          gint           y,
4032                          gint           width,
4033                          gint           height,
4034                          GtkOrientation orientation)
4035 {
4036   gint xx, yy;
4037   gint xthick, ythick;
4038   GdkGC *light_gc, *dark_gc;
4039   GdkRectangle rect;
4040   GdkRectangle dest;
4041   gint intersect;
4042   
4043   g_return_if_fail (GTK_IS_STYLE (style));
4044   g_return_if_fail (window != NULL);
4045   
4046   sanitize_size (window, &width, &height);
4047   
4048   gtk_paint_box (style, window, state_type, shadow_type, area, widget, 
4049                  detail, x, y, width, height);
4050   
4051   
4052   if (!strcmp (detail, "paned"))
4053     {
4054       /* we want to ignore the shadow border in paned widgets */
4055       xthick = 0;
4056       ythick = 0;
4057
4058       light_gc = style->light_gc[state_type];
4059       dark_gc = style->black_gc;
4060     }
4061   else
4062     {
4063       xthick = style->xthickness;
4064       ythick = style->ythickness;
4065
4066       light_gc = style->light_gc[state_type];
4067       dark_gc = style->dark_gc[state_type];
4068     }
4069   
4070   rect.x = x + xthick;
4071   rect.y = y + ythick;
4072   rect.width = width - (xthick * 2);
4073   rect.height = height - (ythick * 2);
4074
4075   if (area)
4076       intersect = gdk_rectangle_intersect (area, &rect, &dest);
4077   else
4078     {
4079       intersect = TRUE;
4080       dest = rect;
4081     }
4082
4083   if (!intersect)
4084     return;
4085
4086   gdk_gc_set_clip_rectangle (light_gc, &dest);
4087   gdk_gc_set_clip_rectangle (dark_gc, &dest);
4088
4089   if (!strcmp (detail, "paned"))
4090     {
4091       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4092         for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
4093           draw_dot (window, light_gc, dark_gc, xx, y + height/2 - 1, 3);
4094       else
4095         for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
4096           draw_dot (window, light_gc, dark_gc, x + width/2 - 1, yy, 3);
4097     }
4098   else
4099     {
4100       for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
4101         for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
4102           {
4103             draw_dot (window, light_gc, dark_gc, xx, yy, 2);
4104             draw_dot (window, light_gc, dark_gc, xx + 3, yy + 1, 2);
4105           }
4106     }
4107
4108   gdk_gc_set_clip_rectangle (light_gc, NULL);
4109   gdk_gc_set_clip_rectangle (dark_gc, NULL);
4110 }
4111
4112 static void
4113 create_expander_affine (gdouble affine[6],
4114                         gint    degrees,
4115                         gint    expander_size,
4116                         gint    x,
4117                         gint    y)
4118 {
4119   gdouble s, c;
4120   gdouble width;
4121   gdouble height;
4122
4123   width = expander_size / 4.0;
4124   height = expander_size / 2.0;
4125   
4126   s = sin (degrees * G_PI / 180.0);
4127   c = cos (degrees * G_PI / 180.0);
4128   
4129   affine[0] = c;
4130   affine[1] = s;
4131   affine[2] = -s;
4132   affine[3] = c;
4133   affine[4] = -width * c - height * -s + x;
4134   affine[5] = -width * s - height * c + y;
4135 }
4136
4137 static void
4138 apply_affine_on_point (double affine[6], GdkPoint *point)
4139 {
4140   gdouble x, y;
4141
4142   x = point->x * affine[0] + point->y * affine[2] + affine[4];
4143   y = point->x * affine[1] + point->y * affine[3] + affine[5];
4144
4145   point->x = x;
4146   point->y = y;
4147 }
4148
4149 static void
4150 gtk_default_draw_expander (GtkStyle        *style,
4151                            GdkWindow       *window,
4152                            GtkStateType     state_type,
4153                            GdkRectangle    *area,
4154                            GtkWidget       *widget,
4155                            const gchar     *detail,
4156                            gint             x,
4157                            gint             y,
4158                            GtkExpanderStyle expander_style)
4159 {
4160   gint expander_size;
4161   GdkPoint points[3];
4162   gint i;
4163   gdouble affine[6];
4164   gint degrees = 0;
4165   
4166   gtk_widget_style_get (widget,
4167                         "expander_size", &expander_size,
4168                         NULL);
4169
4170   if (area)
4171     {
4172       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], area);
4173       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], area);
4174     }
4175
4176   points[0].x = 0;
4177   points[0].y = 0;
4178   points[1].x = expander_size / 2;
4179   points[1].y =  expander_size / 2;
4180   points[2].x = 0;
4181   points[2].y = expander_size;
4182
4183   switch (expander_style)
4184     {
4185     case GTK_EXPANDER_COLLAPSED:
4186       degrees = 0;
4187       break;
4188     case GTK_EXPANDER_SEMI_COLLAPSED:
4189       degrees = 30;
4190       break;
4191     case GTK_EXPANDER_SEMI_EXPANDED:
4192       degrees = 60;
4193       break;
4194     case GTK_EXPANDER_EXPANDED:
4195       degrees = 90;
4196       break;
4197     default:
4198       g_assert_not_reached ();
4199     }
4200   
4201   create_expander_affine (affine, degrees, expander_size, x, y);
4202
4203   for (i = 0; i < 3; i++)
4204     apply_affine_on_point (affine, &points[i]);
4205
4206   if (state_type == GTK_STATE_PRELIGHT)
4207     {
4208       gdk_draw_polygon (window, style->fg_gc[GTK_STATE_NORMAL],
4209                         TRUE, points, 3);
4210     }
4211   else if (state_type == GTK_STATE_ACTIVE)
4212     {
4213       gdk_draw_polygon (window, style->light_gc[GTK_STATE_ACTIVE],
4214                         TRUE, points, 3);
4215       gdk_draw_polygon (window, style->fg_gc[GTK_STATE_NORMAL],
4216                         FALSE, points, 3);
4217     }
4218   else
4219     {
4220       gdk_draw_polygon (window, style->base_gc[GTK_STATE_NORMAL],
4221                         TRUE, points, 3);
4222       gdk_draw_polygon (window, style->fg_gc[GTK_STATE_NORMAL],
4223                         FALSE, points, 3);
4224     }
4225   if (area)
4226     {
4227       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
4228       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
4229     }
4230 }
4231
4232 typedef struct _ByteRange ByteRange;
4233
4234 struct _ByteRange
4235 {
4236   guint start;
4237   guint end;
4238 };
4239
4240 static ByteRange*
4241 range_new (guint start,
4242            guint end)
4243 {
4244   ByteRange *br = g_new (ByteRange, 1);
4245
4246   br->start = start;
4247   br->end = end;
4248   
4249   return br;
4250 }
4251
4252 static PangoLayout*
4253 get_insensitive_layout (PangoLayout *layout)
4254 {
4255   GSList *embossed_ranges = NULL;
4256   GSList *stippled_ranges = NULL;
4257   PangoLayoutIter *iter;
4258   GSList *tmp_list = NULL;
4259   PangoLayout *new_layout;
4260   PangoAttrList *attrs;
4261   GdkBitmap *stipple = NULL;
4262   
4263   iter = pango_layout_get_iter (layout);
4264   
4265   do
4266     {
4267       PangoLayoutRun *run;
4268       PangoAttribute *attr;
4269       gboolean need_stipple = FALSE;
4270       ByteRange *br;
4271       
4272       run = pango_layout_iter_get_run (iter);
4273
4274       if (run)
4275         {
4276           tmp_list = run->item->analysis.extra_attrs;
4277
4278           while (tmp_list != NULL)
4279             {
4280               attr = tmp_list->data;
4281               switch (attr->klass->type)
4282                 {
4283                 case PANGO_ATTR_FOREGROUND:
4284                 case PANGO_ATTR_BACKGROUND:
4285                   need_stipple = TRUE;
4286                   break;
4287               
4288                 default:
4289                   break;
4290                 }
4291
4292               if (need_stipple)
4293                 break;
4294           
4295               tmp_list = g_slist_next (tmp_list);
4296             }
4297
4298           br = range_new (run->item->offset, run->item->offset + run->item->length);
4299       
4300           if (need_stipple)
4301             stippled_ranges = g_slist_prepend (stippled_ranges, br);
4302           else
4303             embossed_ranges = g_slist_prepend (embossed_ranges, br);
4304         }
4305     }
4306   while (pango_layout_iter_next_run (iter));
4307
4308   pango_layout_iter_free (iter);
4309
4310   new_layout = pango_layout_copy (layout);
4311
4312   attrs = pango_layout_get_attributes (new_layout);
4313
4314   if (attrs == NULL)
4315     {
4316       /* Create attr list if there wasn't one */
4317       attrs = pango_attr_list_new ();
4318       pango_layout_set_attributes (new_layout, attrs);
4319       pango_attr_list_unref (attrs);
4320     }
4321   
4322   tmp_list = embossed_ranges;
4323   while (tmp_list != NULL)
4324     {
4325       PangoAttribute *attr;
4326       ByteRange *br = tmp_list->data;
4327
4328       attr = gdk_pango_attr_embossed_new (TRUE);
4329
4330       attr->start_index = br->start;
4331       attr->end_index = br->end;
4332       
4333       pango_attr_list_change (attrs, attr);
4334
4335       g_free (br);
4336       
4337       tmp_list = g_slist_next (tmp_list);
4338     }
4339
4340   g_slist_free (embossed_ranges);
4341   
4342   tmp_list = stippled_ranges;
4343   while (tmp_list != NULL)
4344     {
4345       PangoAttribute *attr;
4346       ByteRange *br = tmp_list->data;
4347
4348       if (stipple == NULL)
4349         {
4350 #define gray50_width 2
4351 #define gray50_height 2
4352           static char gray50_bits[] = {
4353             0x02, 0x01
4354           };
4355
4356           stipple = gdk_bitmap_create_from_data (NULL,
4357                                                  gray50_bits, gray50_width,
4358                                                  gray50_height);
4359         }
4360       
4361       attr = gdk_pango_attr_stipple_new (stipple);
4362
4363       attr->start_index = br->start;
4364       attr->end_index = br->end;
4365       
4366       pango_attr_list_change (attrs, attr);
4367
4368       g_free (br);
4369       
4370       tmp_list = g_slist_next (tmp_list);
4371     }
4372
4373   g_slist_free (stippled_ranges);
4374   
4375   if (stipple)
4376     g_object_unref (G_OBJECT (stipple));
4377
4378   return new_layout;
4379 }
4380
4381 static void
4382 gtk_default_draw_layout (GtkStyle        *style,
4383                          GdkWindow       *window,
4384                          GtkStateType     state_type,
4385                          gboolean         use_text,
4386                          GdkRectangle    *area,
4387                          GtkWidget       *widget,
4388                          const gchar     *detail,
4389                          gint             x,
4390                          gint             y,
4391                          PangoLayout     *layout)
4392 {
4393   GdkGC *gc;
4394   
4395   g_return_if_fail (GTK_IS_STYLE (style));
4396   g_return_if_fail (window != NULL);
4397
4398   gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
4399   
4400   if (area)
4401     gdk_gc_set_clip_rectangle (gc, area);
4402
4403   if (state_type == GTK_STATE_INSENSITIVE)
4404     {
4405       PangoLayout *ins;
4406
4407       ins = get_insensitive_layout (layout);
4408       
4409       gdk_draw_layout (window, gc, x, y, ins);
4410
4411       g_object_unref (G_OBJECT (ins));
4412     }
4413   else
4414     {
4415       gdk_draw_layout (window, gc, x, y, layout);
4416     }
4417
4418   if (area)
4419     gdk_gc_set_clip_rectangle (gc, NULL);
4420 }
4421
4422 static void
4423 gtk_default_draw_resize_grip (GtkStyle       *style,
4424                               GdkWindow      *window,
4425                               GtkStateType    state_type,
4426                               GdkRectangle   *area,
4427                               GtkWidget      *widget,
4428                               const gchar    *detail,
4429                               GdkWindowEdge   edge,
4430                               gint            x,
4431                               gint            y,
4432                               gint            width,
4433                               gint            height)
4434 {
4435   g_return_if_fail (GTK_IS_STYLE (style));
4436   g_return_if_fail (window != NULL);
4437   
4438   if (area)
4439     {
4440       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
4441       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
4442       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
4443     }
4444
4445   /* make it square, aligning to bottom right */
4446   if (width < height)
4447     {
4448       y += (height - width);
4449       height = width;
4450     }
4451   else if (height < width)
4452     {
4453       x += (width - height);
4454       width = height;
4455     }
4456
4457   /* Clear background */
4458   gdk_draw_rectangle (window,
4459                       style->bg_gc[state_type],
4460                       TRUE,
4461                       x, y, width, height);
4462   
4463   switch (edge)
4464     {
4465     case GDK_WINDOW_EDGE_SOUTH_EAST:
4466       {
4467         gint xi, yi;
4468
4469         xi = x;
4470         yi = y;
4471
4472         while (xi < (x + width - 3))
4473           {
4474             gdk_draw_line (window,
4475                            style->light_gc[state_type],
4476                            xi, y + height,
4477                            x + width, yi);                           
4478
4479             ++xi;
4480             ++yi;
4481             
4482             gdk_draw_line (window,
4483                            style->dark_gc[state_type],
4484                            xi, y + height,
4485                            x + width, yi);                           
4486
4487             ++xi;
4488             ++yi;
4489             
4490             gdk_draw_line (window,
4491                            style->dark_gc[state_type],
4492                            xi, y + height,
4493                            x + width, yi);
4494
4495             xi += 3;
4496             yi += 3;
4497           }
4498       }
4499       break;
4500     default:
4501       g_assert_not_reached ();
4502       break;
4503     }
4504   
4505   if (area)
4506     {
4507       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
4508       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
4509       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
4510     }
4511 }
4512
4513 static void
4514 gtk_style_shade (GdkColor *a,
4515                  GdkColor *b,
4516                  gdouble   k)
4517 {
4518   gdouble red;
4519   gdouble green;
4520   gdouble blue;
4521   
4522   red = (gdouble) a->red / 65535.0;
4523   green = (gdouble) a->green / 65535.0;
4524   blue = (gdouble) a->blue / 65535.0;
4525   
4526   rgb_to_hls (&red, &green, &blue);
4527   
4528   green *= k;
4529   if (green > 1.0)
4530     green = 1.0;
4531   else if (green < 0.0)
4532     green = 0.0;
4533   
4534   blue *= k;
4535   if (blue > 1.0)
4536     blue = 1.0;
4537   else if (blue < 0.0)
4538     blue = 0.0;
4539   
4540   hls_to_rgb (&red, &green, &blue);
4541   
4542   b->red = red * 65535.0;
4543   b->green = green * 65535.0;
4544   b->blue = blue * 65535.0;
4545 }
4546
4547 static void
4548 rgb_to_hls (gdouble *r,
4549             gdouble *g,
4550             gdouble *b)
4551 {
4552   gdouble min;
4553   gdouble max;
4554   gdouble red;
4555   gdouble green;
4556   gdouble blue;
4557   gdouble h, l, s;
4558   gdouble delta;
4559   
4560   red = *r;
4561   green = *g;
4562   blue = *b;
4563   
4564   if (red > green)
4565     {
4566       if (red > blue)
4567         max = red;
4568       else
4569         max = blue;
4570       
4571       if (green < blue)
4572         min = green;
4573       else
4574         min = blue;
4575     }
4576   else
4577     {
4578       if (green > blue)
4579         max = green;
4580       else
4581         max = blue;
4582       
4583       if (red < blue)
4584         min = red;
4585       else
4586         min = blue;
4587     }
4588   
4589   l = (max + min) / 2;
4590   s = 0;
4591   h = 0;
4592   
4593   if (max != min)
4594     {
4595       if (l <= 0.5)
4596         s = (max - min) / (max + min);
4597       else
4598         s = (max - min) / (2 - max - min);
4599       
4600       delta = max -min;
4601       if (red == max)
4602         h = (green - blue) / delta;
4603       else if (green == max)
4604         h = 2 + (blue - red) / delta;
4605       else if (blue == max)
4606         h = 4 + (red - green) / delta;
4607       
4608       h *= 60;
4609       if (h < 0.0)
4610         h += 360;
4611     }
4612   
4613   *r = h;
4614   *g = l;
4615   *b = s;
4616 }
4617
4618 static void
4619 hls_to_rgb (gdouble *h,
4620             gdouble *l,
4621             gdouble *s)
4622 {
4623   gdouble hue;
4624   gdouble lightness;
4625   gdouble saturation;
4626   gdouble m1, m2;
4627   gdouble r, g, b;
4628   
4629   lightness = *l;
4630   saturation = *s;
4631   
4632   if (lightness <= 0.5)
4633     m2 = lightness * (1 + saturation);
4634   else
4635     m2 = lightness + saturation - lightness * saturation;
4636   m1 = 2 * lightness - m2;
4637   
4638   if (saturation == 0)
4639     {
4640       *h = lightness;
4641       *l = lightness;
4642       *s = lightness;
4643     }
4644   else
4645     {
4646       hue = *h + 120;
4647       while (hue > 360)
4648         hue -= 360;
4649       while (hue < 0)
4650         hue += 360;
4651       
4652       if (hue < 60)
4653         r = m1 + (m2 - m1) * hue / 60;
4654       else if (hue < 180)
4655         r = m2;
4656       else if (hue < 240)
4657         r = m1 + (m2 - m1) * (240 - hue) / 60;
4658       else
4659         r = m1;
4660       
4661       hue = *h;
4662       while (hue > 360)
4663         hue -= 360;
4664       while (hue < 0)
4665         hue += 360;
4666       
4667       if (hue < 60)
4668         g = m1 + (m2 - m1) * hue / 60;
4669       else if (hue < 180)
4670         g = m2;
4671       else if (hue < 240)
4672         g = m1 + (m2 - m1) * (240 - hue) / 60;
4673       else
4674         g = m1;
4675       
4676       hue = *h - 120;
4677       while (hue > 360)
4678         hue -= 360;
4679       while (hue < 0)
4680         hue += 360;
4681       
4682       if (hue < 60)
4683         b = m1 + (m2 - m1) * hue / 60;
4684       else if (hue < 180)
4685         b = m2;
4686       else if (hue < 240)
4687         b = m1 + (m2 - m1) * (240 - hue) / 60;
4688       else
4689         b = m1;
4690       
4691       *h = r;
4692       *l = g;
4693       *s = b;
4694     }
4695 }
4696
4697
4698 /**
4699  * gtk_paint_hline:
4700  * @style: a #GtkStyle
4701  * @window: a #GdkWindow
4702  * @state_type: a state
4703  * @area: rectangle to which the output is clipped
4704  * @widget:
4705  * @detail: 
4706  * @x1: the starting x coordinate
4707  * @x2: the ending x coordinate
4708  * @y: the y coordinate
4709  * 
4710  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
4711  * using the given style and state.
4712  **/ 
4713 void 
4714 gtk_paint_hline (GtkStyle      *style,
4715                  GdkWindow     *window,
4716                  GtkStateType   state_type,
4717                  GdkRectangle  *area,
4718                  GtkWidget     *widget,
4719                  const gchar   *detail,
4720                  gint          x1,
4721                  gint          x2,
4722                  gint          y)
4723 {
4724   g_return_if_fail (GTK_IS_STYLE (style));
4725   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
4726   
4727   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y);
4728 }
4729
4730 /**
4731  * gtk_paint_vline:
4732  * @style: a #GtkStyle
4733  * @window: a #GdkWindow
4734  * @state_type: a state
4735  * @area: rectangle to which the output is clipped
4736  * @widget:
4737  * @detail: 
4738  * @y1: the starting y coordinate
4739  * @y2: the ending y coordinate
4740  * @x: the x coordinate
4741  * 
4742  * Draws a vertical line from (@x, @y1) to (@x, @y1) in @window
4743  * using the given style and state.
4744  */
4745 void
4746 gtk_paint_vline (GtkStyle      *style,
4747                  GdkWindow     *window,
4748                  GtkStateType   state_type,
4749                  GdkRectangle  *area,
4750                  GtkWidget     *widget,
4751                  const gchar   *detail,
4752                  gint          y1,
4753                  gint          y2,
4754                  gint          x)
4755 {
4756   g_return_if_fail (GTK_IS_STYLE (style));
4757   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
4758   
4759   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1, y2, x);
4760 }
4761
4762 void
4763 gtk_paint_shadow (GtkStyle     *style,
4764                   GdkWindow    *window,
4765                   GtkStateType  state_type,
4766                   GtkShadowType shadow_type,
4767                   GdkRectangle *area,
4768                   GtkWidget    *widget,
4769                   const gchar  *detail,
4770                   gint          x,
4771                   gint          y,
4772                   gint          width,
4773                   gint          height)
4774 {
4775   g_return_if_fail (GTK_IS_STYLE (style));
4776   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
4777   
4778   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4779 }
4780
4781 void
4782 gtk_paint_polygon (GtkStyle      *style,
4783                    GdkWindow     *window,
4784                    GtkStateType   state_type,
4785                    GtkShadowType  shadow_type,
4786                    GdkRectangle  *area,
4787                    GtkWidget     *widget,
4788                    const gchar   *detail,
4789                    GdkPoint      *points,
4790                    gint           npoints,
4791                    gboolean       fill)
4792 {
4793   g_return_if_fail (GTK_IS_STYLE (style));
4794   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
4795   
4796   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill);
4797 }
4798
4799 void
4800 gtk_paint_arrow (GtkStyle      *style,
4801                  GdkWindow     *window,
4802                  GtkStateType   state_type,
4803                  GtkShadowType  shadow_type,
4804                  GdkRectangle  *area,
4805                  GtkWidget     *widget,
4806                  const gchar   *detail,
4807                  GtkArrowType   arrow_type,
4808                  gboolean       fill,
4809                  gint           x,
4810                  gint           y,
4811                  gint           width,
4812                  gint           height)
4813 {
4814   g_return_if_fail (GTK_IS_STYLE (style));
4815   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
4816   
4817   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height);
4818 }
4819
4820 void
4821 gtk_paint_diamond (GtkStyle      *style,
4822                    GdkWindow     *window,
4823                    GtkStateType   state_type,
4824                    GtkShadowType  shadow_type,
4825                    GdkRectangle  *area,
4826                    GtkWidget     *widget,
4827                    const gchar   *detail,
4828                    gint        x,
4829                    gint        y,
4830                    gint        width,
4831                    gint        height)
4832 {
4833   g_return_if_fail (GTK_IS_STYLE (style));
4834   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
4835   
4836   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4837 }
4838
4839 void
4840 gtk_paint_string (GtkStyle      *style,
4841                   GdkWindow     *window,
4842                   GtkStateType   state_type,
4843                   GdkRectangle  *area,
4844                   GtkWidget     *widget,
4845                   const gchar   *detail,
4846                   gint           x,
4847                   gint           y,
4848                   const gchar   *string)
4849 {
4850   g_return_if_fail (GTK_IS_STYLE (style));
4851   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
4852   
4853   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string);
4854 }
4855
4856 void
4857 gtk_paint_box (GtkStyle      *style,
4858                GdkWindow     *window,
4859                GtkStateType   state_type,
4860                GtkShadowType  shadow_type,
4861                GdkRectangle  *area,
4862                GtkWidget     *widget,
4863                const gchar   *detail,
4864                gint           x,
4865                gint           y,
4866                gint           width,
4867                gint           height)
4868 {
4869   g_return_if_fail (GTK_IS_STYLE (style));
4870   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
4871   
4872   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4873 }
4874
4875 void
4876 gtk_paint_flat_box (GtkStyle      *style,
4877                     GdkWindow     *window,
4878                     GtkStateType   state_type,
4879                     GtkShadowType  shadow_type,
4880                     GdkRectangle  *area,
4881                     GtkWidget     *widget,
4882                     const gchar   *detail,
4883                     gint           x,
4884                     gint           y,
4885                     gint           width,
4886                     gint           height)
4887 {
4888   g_return_if_fail (GTK_IS_STYLE (style));
4889   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
4890   
4891   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4892 }
4893
4894 void
4895 gtk_paint_check (GtkStyle      *style,
4896                  GdkWindow     *window,
4897                  GtkStateType   state_type,
4898                  GtkShadowType  shadow_type,
4899                  GdkRectangle  *area,
4900                  GtkWidget     *widget,
4901                  const gchar   *detail,
4902                  gint           x,
4903                  gint           y,
4904                  gint           width,
4905                  gint           height)
4906 {
4907   g_return_if_fail (GTK_IS_STYLE (style));
4908   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
4909   
4910   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4911 }
4912
4913 void
4914 gtk_paint_option (GtkStyle      *style,
4915                   GdkWindow     *window,
4916                   GtkStateType   state_type,
4917                   GtkShadowType  shadow_type,
4918                   GdkRectangle  *area,
4919                   GtkWidget     *widget,
4920                   const gchar   *detail,
4921                   gint           x,
4922                   gint           y,
4923                   gint           width,
4924                   gint           height)
4925 {
4926   g_return_if_fail (GTK_IS_STYLE (style));
4927   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
4928   
4929   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4930 }
4931
4932 void
4933 gtk_paint_tab (GtkStyle      *style,
4934                GdkWindow     *window,
4935                GtkStateType   state_type,
4936                GtkShadowType  shadow_type,
4937                GdkRectangle  *area,
4938                GtkWidget     *widget,
4939                const gchar   *detail,
4940                gint           x,
4941                gint           y,
4942                gint           width,
4943                gint           height)
4944 {
4945   g_return_if_fail (GTK_IS_STYLE (style));
4946   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
4947   
4948   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
4949 }
4950
4951 void
4952 gtk_paint_shadow_gap (GtkStyle       *style,
4953                       GdkWindow      *window,
4954                       GtkStateType    state_type,
4955                       GtkShadowType   shadow_type,
4956                       GdkRectangle   *area,
4957                       GtkWidget      *widget,
4958                       gchar          *detail,
4959                       gint            x,
4960                       gint            y,
4961                       gint            width,
4962                       gint            height,
4963                       GtkPositionType gap_side,
4964                       gint            gap_x,
4965                       gint            gap_width)
4966 {
4967   g_return_if_fail (GTK_IS_STYLE (style));
4968   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
4969   
4970   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);
4971 }
4972
4973
4974 void
4975 gtk_paint_box_gap (GtkStyle       *style,
4976                    GdkWindow      *window,
4977                    GtkStateType    state_type,
4978                    GtkShadowType   shadow_type,
4979                    GdkRectangle   *area,
4980                    GtkWidget      *widget,
4981                    gchar          *detail,
4982                    gint            x,
4983                    gint            y,
4984                    gint            width,
4985                    gint            height,
4986                    GtkPositionType gap_side,
4987                    gint            gap_x,
4988                    gint            gap_width)
4989 {
4990   g_return_if_fail (GTK_IS_STYLE (style));
4991   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
4992   
4993   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);
4994 }
4995
4996 void
4997 gtk_paint_extension (GtkStyle       *style,
4998                      GdkWindow      *window,
4999                      GtkStateType    state_type,
5000                      GtkShadowType   shadow_type,
5001                      GdkRectangle   *area,
5002                      GtkWidget      *widget,
5003                      gchar          *detail,
5004                      gint            x,
5005                      gint            y,
5006                      gint            width,
5007                      gint            height,
5008                      GtkPositionType gap_side)
5009 {
5010   g_return_if_fail (GTK_IS_STYLE (style));
5011   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
5012   
5013   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side);
5014 }
5015
5016 void
5017 gtk_paint_focus (GtkStyle      *style,
5018                  GdkWindow     *window,
5019                  GtkStateType   state_type,
5020                  GdkRectangle  *area,
5021                  GtkWidget     *widget,
5022                  const gchar   *detail,
5023                  gint           x,
5024                  gint           y,
5025                  gint           width,
5026                  gint           height)
5027 {
5028   g_return_if_fail (GTK_IS_STYLE (style));
5029   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
5030   
5031   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type, area, widget, detail, x, y, width, height);
5032 }
5033
5034 void
5035 gtk_paint_slider (GtkStyle      *style,
5036                   GdkWindow     *window,
5037                   GtkStateType   state_type,
5038                   GtkShadowType  shadow_type,
5039                   GdkRectangle  *area,
5040                   GtkWidget     *widget,
5041                   const gchar   *detail,
5042                   gint           x,
5043                   gint           y,
5044                   gint           width,
5045                   gint           height,
5046                   GtkOrientation orientation)
5047 {
5048   g_return_if_fail (GTK_IS_STYLE (style));
5049   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
5050   
5051   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
5052 }
5053
5054 void
5055 gtk_paint_handle (GtkStyle      *style,
5056                   GdkWindow     *window,
5057                   GtkStateType   state_type,
5058                   GtkShadowType  shadow_type,
5059                   GdkRectangle  *area,
5060                   GtkWidget     *widget,
5061                   const gchar   *detail,
5062                   gint           x,
5063                   gint           y,
5064                   gint           width,
5065                   gint           height,
5066                   GtkOrientation orientation)
5067 {
5068   g_return_if_fail (GTK_IS_STYLE (style));
5069   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
5070   
5071   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
5072 }
5073
5074 void
5075 gtk_paint_expander (GtkStyle        *style,
5076                     GdkWindow       *window,
5077                     GtkStateType     state_type,
5078                     GdkRectangle    *area,
5079                     GtkWidget       *widget,
5080                     const gchar     *detail,
5081                     gint             x,
5082                     gint             y,
5083                     GtkExpanderStyle expander_style)
5084 {
5085   g_return_if_fail (GTK_IS_STYLE (style));
5086   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
5087   
5088   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type, area,
5089                                               widget, detail, x, y, expander_style);
5090 }
5091
5092 void
5093 gtk_paint_layout (GtkStyle        *style,
5094                   GdkWindow       *window,
5095                   GtkStateType     state_type,
5096                   gboolean         use_text,
5097                   GdkRectangle    *area,
5098                   GtkWidget       *widget,
5099                   const gchar     *detail,
5100                   gint             x,
5101                   gint             y,
5102                   PangoLayout     *layout)
5103 {
5104   g_return_if_fail (GTK_IS_STYLE (style));
5105   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
5106   
5107   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text, area,
5108                                             widget, detail, x, y, layout);
5109 }
5110
5111 void
5112 gtk_paint_resize_grip (GtkStyle      *style,
5113                        GdkWindow     *window,
5114                        GtkStateType   state_type,
5115                        GdkRectangle  *area,
5116                        GtkWidget     *widget,
5117                        const gchar   *detail,
5118                        GdkWindowEdge  edge,
5119                        gint           x,
5120                        gint           y,
5121                        gint           width,
5122                        gint           height)
5123
5124 {
5125   g_return_if_fail (GTK_IS_STYLE (style));
5126   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
5127
5128   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
5129                                                  area, widget, detail,
5130                                                  edge, x, y, width, height);
5131 }
5132
5133 /**
5134  * gtk_border_copy:
5135  * @border: a #GtkBorder.
5136  * @returns: a copy of @border.
5137  *
5138  * Copies a #GtkBorder structure.
5139  **/
5140 GtkBorder *
5141 gtk_border_copy (const GtkBorder *border)
5142 {
5143   return (GtkBorder *)g_memdup (border, sizeof (GtkBorder));
5144 }
5145
5146 /**
5147  * gtk_border_free:
5148  * @border: a #GtkBorder.
5149  * 
5150  * Frees a #GtkBorder structure.
5151  **/
5152 void
5153 gtk_border_free (GtkBorder *border)
5154 {
5155   g_free (border);
5156 }
5157
5158 /**
5159  * gtk_style_get_font:
5160  * @style: a #GtkStyle
5161  * 
5162  * Gets the #GdkFont to use for the given style. This is
5163  * meant only as a replacement for direct access to @style->font
5164  * and should not be used in new code. New code should
5165  * use @style->font_desc instead.
5166  * 
5167  * Return value: the #GdkFont for the style. This font is owned
5168  *   by the style; if you want to keep around a copy, you must
5169  *   call gdk_font_ref().
5170  **/
5171 GdkFont *
5172 gtk_style_get_font (GtkStyle *style)
5173 {
5174   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
5175
5176   if (style->private_font && style->private_font_desc)
5177     {
5178       if (!style->font_desc ||
5179           !pango_font_description_equal (style->private_font_desc, style->font_desc))
5180         {
5181           gdk_font_unref (style->private_font);
5182           style->private_font = NULL;
5183           
5184           if (style->private_font_desc)
5185             {
5186               pango_font_description_free (style->private_font_desc);
5187               style->private_font_desc = NULL;
5188             }
5189         }
5190     }
5191   
5192   if (!style->private_font)
5193     {
5194       if (style->font_desc)
5195         {
5196           style->private_font = gdk_font_from_description (style->font_desc);
5197           style->private_font_desc = pango_font_description_copy (style->font_desc);
5198         }
5199
5200       if (!style->private_font)
5201         style->private_font = gdk_font_load ("fixed");
5202
5203       if (!style->private_font) 
5204         g_error ("Unable to load \"fixed\" font");
5205     }
5206
5207   return style->private_font;
5208 }
5209
5210 /**
5211  * gtk_style_set_font:
5212  * @style: a #GtkStyle.
5213  * @font: a #GdkFont, or %NULL to use the #GdkFont corresponding
5214  *   to style->font_desc.
5215  * 
5216  * Sets the #GdkFont to use for a given style. This is
5217  * meant only as a replacement for direct access to style->font
5218  * and should not be used in new code. New code should
5219  * use style->font_desc instead.
5220  **/
5221 void
5222 gtk_style_set_font (GtkStyle *style,
5223                     GdkFont  *font)
5224 {
5225   GdkFont *old_font;
5226
5227   g_return_if_fail (GTK_IS_STYLE (style));
5228
5229   old_font = style->private_font;
5230
5231   style->private_font = font;
5232   if (font)
5233     gdk_font_ref (font);
5234
5235   if (old_font)
5236     gdk_font_unref (old_font);
5237
5238   if (style->private_font_desc)
5239     {
5240       pango_font_description_free (style->private_font_desc);
5241       style->private_font_desc = NULL;
5242     }
5243 }
5244
5245 /**
5246  * _gtk_draw_insertion_cursor:
5247  * @drawable: a #GdkDrawable
5248  * @gc: a #GdkGC
5249  * @location: location where to draw the cursor (@location->width is ignored)
5250  * @dir: text direction for the cursor, used to decide whether to draw a
5251  *       directional arrow on the cursor and in what direction. Unless both
5252  *       strong and weak cursors are displayed, this should be %GTK_TEXT_DIR_NONE.
5253  * 
5254  * Draws a text caret on @drawable at @location. This is not a style function
5255  * but merely a convenience function for drawing the standard cursor shape.
5256  **/
5257 void
5258 _gtk_draw_insertion_cursor (GdkDrawable      *drawable,
5259                             GdkGC            *gc,
5260                             GdkRectangle     *location,
5261                             GtkTextDirection  dir)
5262 {
5263   gint stem_width = location->height / 30 + 1;
5264   gint arrow_width = stem_width + 1;
5265   gint x, y;
5266   gint i;
5267
5268   for (i = 0; i < stem_width; i++)
5269     gdk_draw_line (drawable, gc,
5270                    location->x + i - stem_width / 2, location->y,
5271                    location->x + i - stem_width / 2, location->y + location->height);
5272
5273   if (dir == GTK_TEXT_DIR_RTL)
5274     {
5275       x = location->x - stem_width / 2 - 1;
5276       y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5277   
5278       for (i = 0; i < arrow_width; i++)
5279         {
5280           gdk_draw_line (drawable, gc,
5281                          x, y + i + 1,
5282                          x, y + 2 * arrow_width - i - 1);
5283           x --;
5284         }
5285     }
5286   else if (dir == GTK_TEXT_DIR_LTR)
5287     {
5288       x = location->x + stem_width - stem_width / 2;
5289       y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
5290   
5291       for (i = 0; i < arrow_width; i++) 
5292         {
5293           gdk_draw_line (drawable, gc,
5294                          x, y + i + 1,
5295                          x, y + 2 * arrow_width - i - 1);
5296           x++;
5297         }
5298     }
5299 }