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