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