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