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