]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
Make the paned handles gray when the the widget is_focus() but not
[~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       GdkGC *gc = style->bg_gc[state_type];
3369       
3370       if (state_type == GTK_STATE_SELECTED && strcmp (detail, "paned") == 0)
3371         {
3372           if (!GTK_WIDGET_HAS_FOCUS (widget))
3373             gc = style->base_gc[GTK_STATE_ACTIVE];
3374         }
3375
3376       if (area)
3377         gdk_gc_set_clip_rectangle (gc, area);
3378
3379       gdk_draw_rectangle (window, gc, TRUE,
3380                           x, y, width, height);
3381       if (area)
3382         gdk_gc_set_clip_rectangle (gc, NULL);
3383     }
3384   else
3385     gtk_style_apply_default_background (style, window,
3386                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3387                                         state_type, area, x, y, width, height);
3388
3389   if (is_spinbutton_box)
3390     {
3391       GdkGC *upper_gc;
3392       GdkGC *lower_gc;
3393       
3394       lower_gc = style->dark_gc[state_type];
3395       if (shadow_type == GTK_SHADOW_OUT)
3396         upper_gc = style->light_gc[state_type];
3397       else
3398         upper_gc = style->dark_gc[state_type];
3399
3400       if (area)
3401         {
3402           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3403           gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3404         }
3405       
3406       gdk_draw_line (window, upper_gc, x, y, x + width - 1, y);
3407       gdk_draw_line (window, lower_gc, x, y + height - 1, x + width - 1, y + height - 1);
3408
3409       if (area)
3410         {
3411           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3412           gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3413         }
3414       return;
3415     }
3416
3417   gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
3418                     x, y, width, height);
3419
3420   if (detail && strcmp (detail, "optionmenu") == 0)
3421     {
3422       GtkRequisition indicator_size;
3423       GtkBorder indicator_spacing;
3424       gint vline_x;
3425
3426       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3427
3428       sanitize_size (window, &width, &height);
3429
3430       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3431         vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
3432       else 
3433         vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
3434
3435       gtk_paint_vline (style, window, state_type, area, widget,
3436                        detail,
3437                        y + style->ythickness + 1,
3438                        y + height - style->ythickness - 3,
3439                        vline_x);
3440     }
3441 }
3442
3443 static GdkGC*
3444 get_darkened_gc (GdkWindow *window,
3445                  GdkColor  *color,
3446                  gint       darken_count)
3447 {
3448   GdkColor src = *color;
3449   GdkColor shaded = *color;
3450   GdkGC *gc;
3451   
3452   gc = gdk_gc_new (window);
3453
3454   while (darken_count)
3455     {
3456       gtk_style_shade (&src, &shaded, 0.93);
3457       src = shaded;
3458       --darken_count;
3459     }
3460    
3461   gdk_gc_set_rgb_fg_color (gc, &shaded);
3462
3463   return gc;
3464 }
3465
3466 static void 
3467 gtk_default_draw_flat_box (GtkStyle      *style,
3468                            GdkWindow     *window,
3469                            GtkStateType   state_type,
3470                            GtkShadowType  shadow_type,
3471                            GdkRectangle  *area,
3472                            GtkWidget     *widget,
3473                            const gchar   *detail,
3474                            gint           x,
3475                            gint           y,
3476                            gint           width,
3477                            gint           height)
3478 {
3479   GdkGC *gc1;
3480   GdkGC *freeme = NULL;
3481   
3482   g_return_if_fail (GTK_IS_STYLE (style));
3483   g_return_if_fail (window != NULL);
3484   
3485   sanitize_size (window, &width, &height);
3486   
3487   if (detail)
3488     {
3489       if (state_type == GTK_STATE_SELECTED)
3490         {
3491           if (!strcmp ("text", detail))
3492             gc1 = style->bg_gc[GTK_STATE_SELECTED];
3493           else if (!strncmp ("cell_even", detail, strlen ("cell_even")) ||
3494                    !strncmp ("cell_odd", detail, strlen ("cell_odd")))
3495             {
3496               /* This has to be really broken; alex made me do it. -jrb */
3497               if (GTK_WIDGET_HAS_FOCUS (widget))
3498                 gc1 = style->base_gc[state_type];
3499               else 
3500                 gc1 = style->base_gc[GTK_STATE_ACTIVE];
3501             }
3502           else
3503             {
3504               gc1 = style->bg_gc[state_type];
3505             }
3506         }
3507       else
3508         {
3509           if (!strcmp ("viewportbin", detail))
3510             gc1 = style->bg_gc[GTK_STATE_NORMAL];
3511           else if (!strcmp ("entry_bg", detail))
3512             gc1 = style->base_gc[state_type];
3513
3514           /* For trees: even rows are base color, odd rows are a shade of
3515            * the base color, the sort column is a shade of the original color
3516            * for that row.
3517            */
3518
3519           else if (!strcmp ("cell_even", detail) ||
3520                    !strcmp ("cell_odd", detail) ||
3521                    !strcmp ("cell_even_ruled", detail))
3522             {
3523               GdkColor *color = NULL;
3524
3525               gtk_widget_style_get (widget,
3526                                     "even_row_color", &color,
3527                                     NULL);
3528
3529               if (color)
3530                 {
3531                   freeme = get_darkened_gc (window, color, 0);
3532                   gc1 = freeme;
3533
3534                   gdk_color_free (color);
3535                 }
3536               else
3537                 gc1 = style->base_gc[state_type];
3538             }
3539           else if (!strcmp ("cell_odd_ruled", detail))
3540             {
3541               GdkColor *color;
3542
3543               gtk_widget_style_get (widget,
3544                                     "odd_row_color", &color,
3545                                     NULL);
3546
3547               if (color)
3548                 {
3549                   freeme = get_darkened_gc (window, color, 0);
3550                   gc1 = freeme;
3551
3552                   gdk_color_free (color);
3553                 }
3554               else
3555                 {
3556                   gtk_widget_style_get (widget,
3557                                         "even_row_color", &color,
3558                                         NULL);
3559
3560                   if (color)
3561                     {
3562                       freeme = get_darkened_gc (window, color, 1);
3563                       gdk_color_free (color);
3564                     }
3565                   else
3566                     freeme = get_darkened_gc (window, &style->base[state_type], 1);
3567                   gc1 = freeme;
3568                 }
3569             }
3570           else if (!strcmp ("cell_even_sorted", detail) ||
3571                    !strcmp ("cell_odd_sorted", detail) ||
3572                    !strcmp ("cell_even_ruled_sorted", detail))
3573             {
3574               GdkColor *color = NULL;
3575
3576               if (!strcmp ("cell_odd_sorted", detail))
3577                 gtk_widget_style_get (widget,
3578                                       "odd_row_color", &color,
3579                                       NULL);
3580               else
3581                 gtk_widget_style_get (widget,
3582                                       "even_row_color", &color,
3583                                       NULL);
3584
3585               if (color)
3586                 {
3587                   freeme = get_darkened_gc (window, color, 1);
3588                   gc1 = freeme;
3589
3590                   gdk_color_free (color);
3591                 }
3592               else
3593                 {
3594                   freeme = get_darkened_gc (window, &style->base[state_type], 1);
3595                   gc1 = freeme;
3596                 }
3597             }
3598           else if (!strcmp ("cell_odd_ruled_sorted", detail))
3599             {
3600               GdkColor *color = NULL;
3601
3602               gtk_widget_style_get (widget,
3603                                     "odd_row_color", &color,
3604                                     NULL);
3605
3606               if (color)
3607                 {
3608                   freeme = get_darkened_gc (window, color, 1);
3609                   gc1 = freeme;
3610
3611                   gdk_color_free (color);
3612                 }
3613               else
3614                 {
3615                   gtk_widget_style_get (widget,
3616                                         "even_row_color", &color,
3617                                         NULL);
3618
3619                   if (color)
3620                     {
3621                       freeme = get_darkened_gc (window, color, 2);
3622                       gdk_color_free (color);
3623                     }
3624                   else
3625                     freeme = get_darkened_gc (window, &style->base[state_type], 2);
3626                   gc1 = freeme;
3627                 }
3628             }
3629           else
3630             gc1 = style->bg_gc[state_type];
3631         }
3632     }
3633   else
3634     gc1 = style->bg_gc[state_type];
3635   
3636   if (!style->bg_pixmap[state_type] || gc1 != style->bg_gc[state_type] ||
3637       GDK_IS_PIXMAP (window))
3638     {
3639       if (area)
3640         gdk_gc_set_clip_rectangle (gc1, area);
3641
3642       gdk_draw_rectangle (window, gc1, TRUE,
3643                           x, y, width, height);
3644
3645       if (detail && !strcmp ("tooltip", detail))
3646         gdk_draw_rectangle (window, style->black_gc, FALSE,
3647                             x, y, width - 1, height - 1);
3648
3649       if (area)
3650         gdk_gc_set_clip_rectangle (gc1, NULL);
3651     }
3652   else
3653     gtk_style_apply_default_background (style, window,
3654                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3655                                         state_type, area, x, y, width, height);
3656
3657
3658   if (freeme)
3659     g_object_unref (freeme);
3660 }
3661
3662 static GdkGC *
3663 create_aa_gc (GdkWindow *window, GtkStyle *style, GtkStateType state_type)
3664 {
3665   GdkColor aa_color;
3666   GdkGC *gc = gdk_gc_new (window);
3667    
3668   aa_color.red = (style->fg[state_type].red + style->bg[state_type].red) / 2;
3669   aa_color.green = (style->fg[state_type].green + style->bg[state_type].green) / 2;
3670   aa_color.blue = (style->fg[state_type].blue + style->bg[state_type].blue) / 2;
3671   
3672   gdk_gc_set_rgb_fg_color (gc, &aa_color);
3673
3674   return gc;
3675 }
3676
3677 static void 
3678 gtk_default_draw_check (GtkStyle      *style,
3679                         GdkWindow     *window,
3680                         GtkStateType   state_type,
3681                         GtkShadowType  shadow_type,
3682                         GdkRectangle  *area,
3683                         GtkWidget     *widget,
3684                         const gchar   *detail,
3685                         gint           x,
3686                         gint           y,
3687                         gint           width,
3688                         gint           height)
3689 {
3690   if (detail && strcmp (detail, "cellcheck") == 0)
3691     {
3692       if (area)               
3693         gdk_gc_set_clip_rectangle (widget->style->base_gc[state_type], area);
3694       gdk_draw_rectangle (window,
3695                           widget->style->base_gc[state_type],
3696                           TRUE,
3697                           x, y,
3698                           width, height);
3699       if (area)
3700         {
3701           gdk_gc_set_clip_rectangle (widget->style->base_gc[state_type], NULL);
3702           gdk_gc_set_clip_rectangle (widget->style->text_gc[state_type], area);
3703         }
3704       gdk_draw_rectangle (window,
3705                           widget->style->text_gc[state_type],
3706                           FALSE,
3707                           x, y,
3708                           width, height);
3709       if (area)               
3710         gdk_gc_set_clip_rectangle (widget->style->text_gc[state_type], NULL);
3711
3712       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3713       y -= (((1 + INDICATOR_PART_SIZE - height) / 2) - 1);
3714       if (shadow_type == GTK_SHADOW_IN)
3715         {
3716           draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT);
3717           draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA);
3718         }
3719       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3720         {
3721           draw_part (window, style->text_gc[state_type], area, x, y, CHECK_INCONSISTENT_TEXT);
3722         }
3723     }
3724   else
3725     {
3726       GdkGC *free_me = NULL;
3727       
3728       GdkGC *base_gc;
3729       GdkGC *text_gc;
3730       GdkGC *aa_gc;
3731
3732       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3733       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3734
3735       if (strcmp (detail, "check") == 0)        /* Menu item */
3736         {
3737           text_gc = style->fg_gc[state_type];
3738           base_gc = style->bg_gc[state_type];
3739           aa_gc = free_me = create_aa_gc (window, style, state_type);
3740         }
3741       else
3742         {
3743           if (state_type == GTK_STATE_ACTIVE)
3744             {
3745               text_gc = style->fg_gc[state_type];
3746               base_gc = style->bg_gc[state_type];
3747               aa_gc = free_me = create_aa_gc (window, style, state_type);
3748             }
3749           else
3750             {
3751               text_gc = style->text_gc[state_type];
3752               base_gc = style->base_gc[state_type];
3753               aa_gc = style->text_aa_gc[state_type];
3754             }
3755
3756           draw_part (window, base_gc, area, x, y, CHECK_BASE);
3757           draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
3758           draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_DARK);
3759           draw_part (window, style->mid_gc[state_type], area, x, y, CHECK_MID);
3760           draw_part (window, style->light_gc[state_type], area, x, y, CHECK_LIGHT);
3761         }
3762
3763       if (shadow_type == GTK_SHADOW_IN)
3764         {
3765           draw_part (window, text_gc, area, x, y, CHECK_TEXT);
3766           draw_part (window, aa_gc, area, x, y, CHECK_AA);
3767         }
3768       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3769         {
3770           draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT);
3771         }
3772
3773       if (free_me)
3774         g_object_unref (free_me);
3775     }
3776 }
3777
3778 static void 
3779 gtk_default_draw_option (GtkStyle      *style,
3780                          GdkWindow     *window,
3781                          GtkStateType   state_type,
3782                          GtkShadowType  shadow_type,
3783                          GdkRectangle  *area,
3784                          GtkWidget     *widget,
3785                          const gchar   *detail,
3786                          gint           x,
3787                          gint           y,
3788                          gint           width,
3789                          gint           height)
3790 {
3791   if (detail && strcmp (detail, "cellradio") == 0)
3792     {
3793       if (area)               
3794         gdk_gc_set_clip_rectangle (widget->style->fg_gc[state_type], area);
3795       gdk_draw_arc (window,
3796                     widget->style->fg_gc[state_type],
3797                     FALSE,
3798                     x, y,
3799                     width,
3800                     height,
3801                     0, 360*64);
3802
3803       if (shadow_type == GTK_SHADOW_IN)
3804         {
3805           gdk_draw_arc (window,
3806                         widget->style->fg_gc[state_type],
3807                         TRUE,
3808                         x + 2,
3809                         y + 2,
3810                         width - 4,
3811                         height - 4,
3812                         0, 360*64);
3813         }
3814       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3815         {
3816           draw_part (window, widget->style->fg_gc[state_type],
3817                      area, x, y, CHECK_INCONSISTENT_TEXT);
3818         }
3819       if (area)               
3820         gdk_gc_set_clip_rectangle (widget->style->fg_gc[state_type], NULL);
3821     }
3822   else
3823     {
3824       GdkGC *free_me = NULL;
3825       
3826       GdkGC *base_gc;
3827       GdkGC *text_gc;
3828       GdkGC *aa_gc;
3829
3830       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3831       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3832
3833       if (strcmp (detail, "option") == 0)       /* Menu item */
3834         {
3835           text_gc = style->fg_gc[state_type];
3836           base_gc = style->bg_gc[state_type];
3837           aa_gc = free_me = create_aa_gc (window, style, state_type);
3838         }
3839       else
3840         {
3841           if (state_type == GTK_STATE_ACTIVE)
3842             {
3843               text_gc = style->fg_gc[state_type];
3844               base_gc = style->bg_gc[state_type];
3845               aa_gc = free_me = create_aa_gc (window, style, state_type);
3846             }
3847           else
3848             {
3849               text_gc = style->text_gc[state_type];
3850               base_gc = style->base_gc[state_type];
3851               aa_gc = style->text_aa_gc[state_type];
3852             }
3853
3854           draw_part (window, base_gc, area, x, y, RADIO_BASE);
3855           draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
3856           draw_part (window, style->dark_gc[state_type], area, x, y, RADIO_DARK);
3857           draw_part (window, style->mid_gc[state_type], area, x, y, RADIO_MID);
3858           draw_part (window, style->light_gc[state_type], area, x, y, RADIO_LIGHT);
3859         }
3860
3861       if (shadow_type == GTK_SHADOW_IN)
3862         {
3863           draw_part (window, text_gc, area, x, y, RADIO_TEXT);
3864         }
3865       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3866         {
3867           if (strcmp (detail, "option") == 0)  /* Menu item */
3868             {
3869               draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT);
3870             }
3871           else
3872             {
3873               draw_part (window, text_gc, area, x, y, RADIO_INCONSISTENT_TEXT);
3874               draw_part (window, aa_gc, area, x, y, RADIO_INCONSISTENT_AA);
3875             }
3876         }
3877
3878       if (free_me)
3879         g_object_unref (free_me);
3880     }
3881 }
3882
3883 static void
3884 gtk_default_draw_tab (GtkStyle      *style,
3885                       GdkWindow     *window,
3886                       GtkStateType   state_type,
3887                       GtkShadowType  shadow_type,
3888                       GdkRectangle  *area,
3889                       GtkWidget     *widget,
3890                       const gchar   *detail,
3891                       gint           x,
3892                       gint           y,
3893                       gint           width,
3894                       gint           height)
3895 {
3896 #define ARROW_SPACE 4
3897
3898   GtkRequisition indicator_size;
3899   GtkBorder indicator_spacing;
3900   gint arrow_height;
3901   
3902   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3903
3904   indicator_size.width += (indicator_size.width % 2) - 1;
3905   arrow_height = indicator_size.width / 2 + 1;
3906
3907   x += (width - indicator_size.width) / 2;
3908   y += (height - (2 * arrow_height + ARROW_SPACE)) / 2;
3909
3910   if (state_type == GTK_STATE_INSENSITIVE)
3911     {
3912       draw_arrow (window, style->white_gc, area,
3913                   GTK_ARROW_UP, x + 1, y + 1,
3914                   indicator_size.width, arrow_height);
3915       
3916       draw_arrow (window, style->white_gc, area,
3917                   GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1,
3918                   indicator_size.width, arrow_height);
3919     }
3920   
3921   draw_arrow (window, style->fg_gc[state_type], area,
3922               GTK_ARROW_UP, x, y,
3923               indicator_size.width, arrow_height);
3924   
3925   
3926   draw_arrow (window, style->fg_gc[state_type], area,
3927               GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE,
3928               indicator_size.width, arrow_height);
3929 }
3930
3931 static void 
3932 gtk_default_draw_shadow_gap (GtkStyle       *style,
3933                              GdkWindow      *window,
3934                              GtkStateType    state_type,
3935                              GtkShadowType   shadow_type,
3936                              GdkRectangle   *area,
3937                              GtkWidget      *widget,
3938                              const gchar    *detail,
3939                              gint            x,
3940                              gint            y,
3941                              gint            width,
3942                              gint            height,
3943                              GtkPositionType gap_side,
3944                              gint            gap_x,
3945                              gint            gap_width)
3946 {
3947   GdkGC *gc1 = NULL;
3948   GdkGC *gc2 = NULL;
3949   GdkGC *gc3 = NULL;
3950   GdkGC *gc4 = NULL;
3951   
3952   g_return_if_fail (GTK_IS_STYLE (style));
3953   g_return_if_fail (window != NULL);
3954   
3955   sanitize_size (window, &width, &height);
3956   
3957   switch (shadow_type)
3958     {
3959     case GTK_SHADOW_NONE:
3960       return;
3961     case GTK_SHADOW_IN:
3962       gc1 = style->dark_gc[state_type];
3963       gc2 = style->black_gc;
3964       gc3 = style->bg_gc[state_type];
3965       gc4 = style->light_gc[state_type];
3966       break;
3967     case GTK_SHADOW_ETCHED_IN:
3968       gc1 = style->dark_gc[state_type];
3969       gc2 = style->light_gc[state_type];
3970       gc3 = style->dark_gc[state_type];
3971       gc4 = style->light_gc[state_type];
3972       break;
3973     case GTK_SHADOW_OUT:
3974       gc1 = style->light_gc[state_type];
3975       gc2 = style->bg_gc[state_type];
3976       gc3 = style->dark_gc[state_type];
3977       gc4 = style->black_gc;
3978       break;
3979     case GTK_SHADOW_ETCHED_OUT:
3980       gc1 = style->light_gc[state_type];
3981       gc2 = style->dark_gc[state_type];
3982       gc3 = style->light_gc[state_type];
3983       gc4 = style->dark_gc[state_type];
3984       break;
3985     }
3986   if (area)
3987     {
3988       gdk_gc_set_clip_rectangle (gc1, area);
3989       gdk_gc_set_clip_rectangle (gc2, area);
3990       gdk_gc_set_clip_rectangle (gc3, area);
3991       gdk_gc_set_clip_rectangle (gc4, area);
3992     }
3993   
3994   switch (shadow_type)
3995     {
3996     case GTK_SHADOW_NONE:
3997     case GTK_SHADOW_IN:
3998     case GTK_SHADOW_OUT:
3999     case GTK_SHADOW_ETCHED_IN:
4000     case GTK_SHADOW_ETCHED_OUT:
4001       switch (gap_side)
4002         {
4003         case GTK_POS_TOP:
4004           gdk_draw_line (window, gc1,
4005                          x, y, x, y + height - 1);
4006           gdk_draw_line (window, gc2,
4007                          x + 1, y, x + 1, y + height - 2);
4008           
4009           gdk_draw_line (window, gc3,
4010                          x + 1, y + height - 2, x + width - 2, y + height - 2);
4011           gdk_draw_line (window, gc3,
4012                          x + width - 2, y, x + width - 2, y + height - 2);
4013           gdk_draw_line (window, gc4,
4014                          x, y + height - 1, x + width - 1, y + height - 1);
4015           gdk_draw_line (window, gc4,
4016                          x + width - 1, y, x + width - 1, y + height - 1);
4017           if (gap_x > 0)
4018             {
4019               gdk_draw_line (window, gc1,
4020                              x, y, x + gap_x - 1, y);
4021               gdk_draw_line (window, gc2,
4022                              x + 1, y + 1, x + gap_x - 1, y + 1);
4023               gdk_draw_line (window, gc2,
4024                              x + gap_x, y, x + gap_x, y);
4025             }
4026           if ((width - (gap_x + gap_width)) > 0)
4027             {
4028               gdk_draw_line (window, gc1,
4029                              x + gap_x + gap_width, y, x + width - 2, y);
4030               gdk_draw_line (window, gc2,
4031                              x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
4032               gdk_draw_line (window, gc2,
4033                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
4034             }
4035           break;
4036         case GTK_POS_BOTTOM:
4037           gdk_draw_line (window, gc1,
4038                          x, y, x + width - 1, y);
4039           gdk_draw_line (window, gc1,
4040                          x, y, x, y + height - 1);
4041           gdk_draw_line (window, gc2,
4042                          x + 1, y + 1, x + width - 2, y + 1);
4043           gdk_draw_line (window, gc2,
4044                          x + 1, y + 1, x + 1, y + height - 1);
4045           
4046           gdk_draw_line (window, gc3,
4047                          x + width - 2, y + 1, x + width - 2, y + height - 1);
4048           gdk_draw_line (window, gc4,
4049                          x + width - 1, y, x + width - 1, y + height - 1);
4050           if (gap_x > 0)
4051             {
4052               gdk_draw_line (window, gc4,
4053                              x, y + height - 1, x + gap_x - 1, y + height - 1);
4054               gdk_draw_line (window, gc3,
4055                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
4056               gdk_draw_line (window, gc3,
4057                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
4058             }
4059           if ((width - (gap_x + gap_width)) > 0)
4060             {
4061               gdk_draw_line (window, gc4,
4062                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
4063               gdk_draw_line (window, gc3,
4064                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
4065               gdk_draw_line (window, gc3,
4066                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
4067             }
4068           break;
4069         case GTK_POS_LEFT:
4070           gdk_draw_line (window, gc1,
4071                          x, y, x + width - 1, y);
4072           gdk_draw_line (window, gc2,
4073                          x, y + 1, x + width - 2, y + 1);
4074           
4075           gdk_draw_line (window, gc3,
4076                          x, y + height - 2, x + width - 2, y + height - 2);
4077           gdk_draw_line (window, gc3,
4078                          x + width - 2, y + 1, x + width - 2, y + height - 2);
4079           gdk_draw_line (window, gc4,
4080                          x, y + height - 1, x + width - 1, y + height - 1);
4081           gdk_draw_line (window, gc4,
4082                          x + width - 1, y, x + width - 1, y + height - 1);
4083           if (gap_x > 0)
4084             {
4085               gdk_draw_line (window, gc1,
4086                              x, y, x, y + gap_x - 1);
4087               gdk_draw_line (window, gc2,
4088                              x + 1, y + 1, x + 1, y + gap_x - 1);
4089               gdk_draw_line (window, gc2,
4090                              x, y + gap_x, x, y + gap_x);
4091             }
4092           if ((width - (gap_x + gap_width)) > 0)
4093             {
4094               gdk_draw_line (window, gc1,
4095                              x, y + gap_x + gap_width, x, y + height - 2);
4096               gdk_draw_line (window, gc2,
4097                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
4098               gdk_draw_line (window, gc2,
4099                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
4100             }
4101           break;
4102         case GTK_POS_RIGHT:
4103           gdk_draw_line (window, gc1,
4104                          x, y, x + width - 1, y);
4105           gdk_draw_line (window, gc1,
4106                          x, y, x, y + height - 1);
4107           gdk_draw_line (window, gc2,
4108                          x + 1, y + 1, x + width - 1, y + 1);
4109           gdk_draw_line (window, gc2,
4110                          x + 1, y + 1, x + 1, y + height - 2);
4111           
4112           gdk_draw_line (window, gc3,
4113                          x + 1, y + height - 2, x + width - 1, y + height - 2);
4114           gdk_draw_line (window, gc4,
4115                          x, y + height - 1, x + width - 1, y + height - 1);
4116           if (gap_x > 0)
4117             {
4118               gdk_draw_line (window, gc4,
4119                              x + width - 1, y, x + width - 1, y + gap_x - 1);
4120               gdk_draw_line (window, gc3,
4121                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
4122               gdk_draw_line (window, gc3,
4123                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
4124             }
4125           if ((width - (gap_x + gap_width)) > 0)
4126             {
4127               gdk_draw_line (window, gc4,
4128                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
4129               gdk_draw_line (window, gc3,
4130                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
4131               gdk_draw_line (window, gc3,
4132                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
4133             }
4134           break;
4135         }
4136     }
4137
4138   if (area)
4139     {
4140       gdk_gc_set_clip_rectangle (gc1, NULL);
4141       gdk_gc_set_clip_rectangle (gc2, NULL);
4142       gdk_gc_set_clip_rectangle (gc3, NULL);
4143       gdk_gc_set_clip_rectangle (gc4, NULL);
4144     }
4145 }
4146
4147 static void 
4148 gtk_default_draw_box_gap (GtkStyle       *style,
4149                           GdkWindow      *window,
4150                           GtkStateType    state_type,
4151                           GtkShadowType   shadow_type,
4152                           GdkRectangle   *area,
4153                           GtkWidget      *widget,
4154                           const gchar    *detail,
4155                           gint            x,
4156                           gint            y,
4157                           gint            width,
4158                           gint            height,
4159                           GtkPositionType gap_side,
4160                           gint            gap_x,
4161                           gint            gap_width)
4162 {
4163   GdkGC *gc1 = NULL;
4164   GdkGC *gc2 = NULL;
4165   GdkGC *gc3 = NULL;
4166   GdkGC *gc4 = NULL;
4167   
4168   g_return_if_fail (GTK_IS_STYLE (style));
4169   g_return_if_fail (window != NULL);
4170   
4171   gtk_style_apply_default_background (style, window,
4172                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4173                                       state_type, area, x, y, width, height);
4174   
4175   sanitize_size (window, &width, &height);
4176   
4177   switch (shadow_type)
4178     {
4179     case GTK_SHADOW_NONE:
4180       return;
4181     case GTK_SHADOW_IN:
4182       gc1 = style->dark_gc[state_type];
4183       gc2 = style->black_gc;
4184       gc3 = style->bg_gc[state_type];
4185       gc4 = style->light_gc[state_type];
4186       break;
4187     case GTK_SHADOW_ETCHED_IN:
4188       gc1 = style->dark_gc[state_type];
4189       gc2 = style->light_gc[state_type];
4190       gc3 = style->dark_gc[state_type];
4191       gc4 = style->light_gc[state_type];
4192       break;
4193     case GTK_SHADOW_OUT:
4194       gc1 = style->light_gc[state_type];
4195       gc2 = style->bg_gc[state_type];
4196       gc3 = style->dark_gc[state_type];
4197       gc4 = style->black_gc;
4198       break;
4199     case GTK_SHADOW_ETCHED_OUT:
4200       gc1 = style->light_gc[state_type];
4201       gc2 = style->dark_gc[state_type];
4202       gc3 = style->light_gc[state_type];
4203       gc4 = style->dark_gc[state_type];
4204       break;
4205     }
4206
4207   if (area)
4208     {
4209       gdk_gc_set_clip_rectangle (gc1, area);
4210       gdk_gc_set_clip_rectangle (gc2, area);
4211       gdk_gc_set_clip_rectangle (gc3, area);
4212       gdk_gc_set_clip_rectangle (gc4, area);
4213     }
4214   
4215   switch (shadow_type)
4216     {
4217     case GTK_SHADOW_NONE:
4218     case GTK_SHADOW_IN:
4219     case GTK_SHADOW_OUT:
4220     case GTK_SHADOW_ETCHED_IN:
4221     case GTK_SHADOW_ETCHED_OUT:
4222       switch (gap_side)
4223         {
4224         case GTK_POS_TOP:
4225           gdk_draw_line (window, gc1,
4226                          x, y, x, y + height - 1);
4227           gdk_draw_line (window, gc2,
4228                          x + 1, y, x + 1, y + height - 2);
4229           
4230           gdk_draw_line (window, gc3,
4231                          x + 1, y + height - 2, x + width - 2, y + height - 2);
4232           gdk_draw_line (window, gc3,
4233                          x + width - 2, y, x + width - 2, y + height - 2);
4234           gdk_draw_line (window, gc4,
4235                          x, y + height - 1, x + width - 1, y + height - 1);
4236           gdk_draw_line (window, gc4,
4237                          x + width - 1, y, x + width - 1, y + height - 1);
4238           if (gap_x > 0)
4239             {
4240               gdk_draw_line (window, gc1,
4241                              x, y, x + gap_x - 1, y);
4242               gdk_draw_line (window, gc2,
4243                              x + 1, y + 1, x + gap_x - 1, y + 1);
4244               gdk_draw_line (window, gc2,
4245                              x + gap_x, y, x + gap_x, y);
4246             }
4247           if ((width - (gap_x + gap_width)) > 0)
4248             {
4249               gdk_draw_line (window, gc1,
4250                              x + gap_x + gap_width, y, x + width - 2, y);
4251               gdk_draw_line (window, gc2,
4252                              x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
4253               gdk_draw_line (window, gc2,
4254                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
4255             }
4256           break;
4257         case  GTK_POS_BOTTOM:
4258           gdk_draw_line (window, gc1,
4259                          x, y, x + width - 1, y);
4260           gdk_draw_line (window, gc1,
4261                          x, y, x, y + height - 1);
4262           gdk_draw_line (window, gc2,
4263                          x + 1, y + 1, x + width - 2, y + 1);
4264           gdk_draw_line (window, gc2,
4265                          x + 1, y + 1, x + 1, y + height - 1);
4266           
4267           gdk_draw_line (window, gc3,
4268                          x + width - 2, y + 1, x + width - 2, y + height - 1);
4269           gdk_draw_line (window, gc4,
4270                          x + width - 1, y, x + width - 1, y + height - 1);
4271           if (gap_x > 0)
4272             {
4273               gdk_draw_line (window, gc4,
4274                              x, y + height - 1, x + gap_x - 1, y + height - 1);
4275               gdk_draw_line (window, gc3,
4276                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
4277               gdk_draw_line (window, gc3,
4278                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
4279             }
4280           if ((width - (gap_x + gap_width)) > 0)
4281             {
4282               gdk_draw_line (window, gc4,
4283                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
4284               gdk_draw_line (window, gc3,
4285                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
4286               gdk_draw_line (window, gc3,
4287                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
4288             }
4289           break;
4290         case GTK_POS_LEFT:
4291           gdk_draw_line (window, gc1,
4292                          x, y, x + width - 1, y);
4293           gdk_draw_line (window, gc2,
4294                          x, y + 1, x + width - 2, y + 1);
4295           
4296           gdk_draw_line (window, gc3,
4297                          x, y + height - 2, x + width - 2, y + height - 2);
4298           gdk_draw_line (window, gc3,
4299                          x + width - 2, y + 1, x + width - 2, y + height - 2);
4300           gdk_draw_line (window, gc4,
4301                          x, y + height - 1, x + width - 1, y + height - 1);
4302           gdk_draw_line (window, gc4,
4303                          x + width - 1, y, x + width - 1, y + height - 1);
4304           if (gap_x > 0)
4305             {
4306               gdk_draw_line (window, gc1,
4307                              x, y, x, y + gap_x - 1);
4308               gdk_draw_line (window, gc2,
4309                              x + 1, y + 1, x + 1, y + gap_x - 1);
4310               gdk_draw_line (window, gc2,
4311                              x, y + gap_x, x, y + gap_x);
4312             }
4313           if ((width - (gap_x + gap_width)) > 0)
4314             {
4315               gdk_draw_line (window, gc1,
4316                              x, y + gap_x + gap_width, x, y + height - 2);
4317               gdk_draw_line (window, gc2,
4318                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
4319               gdk_draw_line (window, gc2,
4320                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
4321             }
4322           break;
4323         case GTK_POS_RIGHT:
4324           gdk_draw_line (window, gc1,
4325                          x, y, x + width - 1, y);
4326           gdk_draw_line (window, gc1,
4327                          x, y, x, y + height - 1);
4328           gdk_draw_line (window, gc2,
4329                          x + 1, y + 1, x + width - 1, y + 1);
4330           gdk_draw_line (window, gc2,
4331                          x + 1, y + 1, x + 1, y + height - 2);
4332           
4333           gdk_draw_line (window, gc3,
4334                          x + 1, y + height - 2, x + width - 1, y + height - 2);
4335           gdk_draw_line (window, gc4,
4336                          x, y + height - 1, x + width - 1, y + height - 1);
4337           if (gap_x > 0)
4338             {
4339               gdk_draw_line (window, gc4,
4340                              x + width - 1, y, x + width - 1, y + gap_x - 1);
4341               gdk_draw_line (window, gc3,
4342                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
4343               gdk_draw_line (window, gc3,
4344                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
4345             }
4346           if ((width - (gap_x + gap_width)) > 0)
4347             {
4348               gdk_draw_line (window, gc4,
4349                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
4350               gdk_draw_line (window, gc3,
4351                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
4352               gdk_draw_line (window, gc3,
4353                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
4354             }
4355           break;
4356         }
4357     }
4358
4359   if (area)
4360     {
4361       gdk_gc_set_clip_rectangle (gc1, NULL);
4362       gdk_gc_set_clip_rectangle (gc2, NULL);
4363       gdk_gc_set_clip_rectangle (gc3, NULL);
4364       gdk_gc_set_clip_rectangle (gc4, NULL);
4365     }
4366 }
4367
4368 static void 
4369 gtk_default_draw_extension (GtkStyle       *style,
4370                             GdkWindow      *window,
4371                             GtkStateType    state_type,
4372                             GtkShadowType   shadow_type,
4373                             GdkRectangle   *area,
4374                             GtkWidget      *widget,
4375                             const gchar    *detail,
4376                             gint            x,
4377                             gint            y,
4378                             gint            width,
4379                             gint            height,
4380                             GtkPositionType gap_side)
4381 {
4382   GdkGC *gc1 = NULL;
4383   GdkGC *gc2 = NULL;
4384   GdkGC *gc3 = NULL;
4385   GdkGC *gc4 = NULL;
4386   
4387   g_return_if_fail (GTK_IS_STYLE (style));
4388   g_return_if_fail (window != NULL);
4389   
4390   gtk_style_apply_default_background (style, window,
4391                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4392                                       GTK_STATE_NORMAL, area, x, y, width, height);
4393   
4394   sanitize_size (window, &width, &height);
4395   
4396   switch (shadow_type)
4397     {
4398     case GTK_SHADOW_NONE:
4399       return;
4400     case GTK_SHADOW_IN:
4401       gc1 = style->dark_gc[state_type];
4402       gc2 = style->black_gc;
4403       gc3 = style->bg_gc[state_type];
4404       gc4 = style->light_gc[state_type];
4405       break;
4406     case GTK_SHADOW_ETCHED_IN:
4407       gc1 = style->dark_gc[state_type];
4408       gc2 = style->light_gc[state_type];
4409       gc3 = style->dark_gc[state_type];
4410       gc4 = style->light_gc[state_type];
4411       break;
4412     case GTK_SHADOW_OUT:
4413       gc1 = style->light_gc[state_type];
4414       gc2 = style->bg_gc[state_type];
4415       gc3 = style->dark_gc[state_type];
4416       gc4 = style->black_gc;
4417       break;
4418     case GTK_SHADOW_ETCHED_OUT:
4419       gc1 = style->light_gc[state_type];
4420       gc2 = style->dark_gc[state_type];
4421       gc3 = style->light_gc[state_type];
4422       gc4 = style->dark_gc[state_type];
4423       break;
4424     }
4425
4426   if (area)
4427     {
4428       gdk_gc_set_clip_rectangle (gc1, area);
4429       gdk_gc_set_clip_rectangle (gc2, area);
4430       gdk_gc_set_clip_rectangle (gc3, area);
4431       gdk_gc_set_clip_rectangle (gc4, area);
4432     }
4433
4434   switch (shadow_type)
4435     {
4436     case GTK_SHADOW_NONE:
4437     case GTK_SHADOW_IN:
4438     case GTK_SHADOW_OUT:
4439     case GTK_SHADOW_ETCHED_IN:
4440     case GTK_SHADOW_ETCHED_OUT:
4441       switch (gap_side)
4442         {
4443         case GTK_POS_TOP:
4444           gtk_style_apply_default_background (style, window,
4445                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4446                                               state_type, area,
4447                                               x + style->xthickness, 
4448                                               y, 
4449                                               width - (2 * style->xthickness), 
4450                                               height - (style->ythickness));
4451           gdk_draw_line (window, gc1,
4452                          x, y, x, y + height - 2);
4453           gdk_draw_line (window, gc2,
4454                          x + 1, y, x + 1, y + height - 2);
4455           
4456           gdk_draw_line (window, gc3,
4457                          x + 2, y + height - 2, x + width - 2, y + height - 2);
4458           gdk_draw_line (window, gc3,
4459                          x + width - 2, y, x + width - 2, y + height - 2);
4460           gdk_draw_line (window, gc4,
4461                          x + 1, y + height - 1, x + width - 2, y + height - 1);
4462           gdk_draw_line (window, gc4,
4463                          x + width - 1, y, x + width - 1, y + height - 2);
4464           break;
4465         case GTK_POS_BOTTOM:
4466           gtk_style_apply_default_background (style, window,
4467                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4468                                               state_type, area,
4469                                               x + style->xthickness, 
4470                                               y + style->ythickness, 
4471                                               width - (2 * style->xthickness), 
4472                                               height - (style->ythickness));
4473           gdk_draw_line (window, gc1,
4474                          x + 1, y, x + width - 2, y);
4475           gdk_draw_line (window, gc1,
4476                          x, y + 1, x, y + height - 1);
4477           gdk_draw_line (window, gc2,
4478                          x + 1, y + 1, x + width - 2, y + 1);
4479           gdk_draw_line (window, gc2,
4480                          x + 1, y + 1, x + 1, y + height - 1);
4481           
4482           gdk_draw_line (window, gc3,
4483                          x + width - 2, y + 2, x + width - 2, y + height - 1);
4484           gdk_draw_line (window, gc4,
4485                          x + width - 1, y + 1, x + width - 1, y + height - 1);
4486           break;
4487         case GTK_POS_LEFT:
4488           gtk_style_apply_default_background (style, window,
4489                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4490                                               state_type, area,
4491                                               x, 
4492                                               y + style->ythickness, 
4493                                               width - (style->xthickness), 
4494                                               height - (2 * style->ythickness));
4495           gdk_draw_line (window, gc1,
4496                          x, y, x + width - 2, y);
4497           gdk_draw_line (window, gc2,
4498                          x + 1, y + 1, x + width - 2, y + 1);
4499           
4500           gdk_draw_line (window, gc3,
4501                          x, y + height - 2, x + width - 2, y + height - 2);
4502           gdk_draw_line (window, gc3,
4503                          x + width - 2, y + 2, x + width - 2, y + height - 2);
4504           gdk_draw_line (window, gc4,
4505                          x, y + height - 1, x + width - 2, y + height - 1);
4506           gdk_draw_line (window, gc4,
4507                          x + width - 1, y + 1, x + width - 1, y + height - 2);
4508           break;
4509         case GTK_POS_RIGHT:
4510           gtk_style_apply_default_background (style, window,
4511                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4512                                               state_type, area,
4513                                               x + style->xthickness, 
4514                                               y + style->ythickness, 
4515                                               width - (style->xthickness), 
4516                                               height - (2 * style->ythickness));
4517           gdk_draw_line (window, gc1,
4518                          x + 1, y, x + width - 1, y);
4519           gdk_draw_line (window, gc1,
4520                          x, y + 1, x, y + height - 2);
4521           gdk_draw_line (window, gc2,
4522                          x + 1, y + 1, x + width - 1, y + 1);
4523           gdk_draw_line (window, gc2,
4524                          x + 1, y + 1, x + 1, y + height - 2);
4525           
4526           gdk_draw_line (window, gc3,
4527                          x + 2, y + height - 2, x + width - 1, y + height - 2);
4528           gdk_draw_line (window, gc4,
4529                          x + 1, y + height - 1, x + width - 1, y + height - 1);
4530           break;
4531         }
4532     }
4533
4534   if (area)
4535     {
4536       gdk_gc_set_clip_rectangle (gc1, NULL);
4537       gdk_gc_set_clip_rectangle (gc2, NULL);
4538       gdk_gc_set_clip_rectangle (gc3, NULL);
4539       gdk_gc_set_clip_rectangle (gc4, NULL);
4540     }
4541 }
4542
4543 static void 
4544 gtk_default_draw_focus (GtkStyle      *style,
4545                         GdkWindow     *window,
4546                         GtkStateType   state_type,
4547                         GdkRectangle  *area,
4548                         GtkWidget     *widget,
4549                         const gchar   *detail,
4550                         gint           x,
4551                         gint           y,
4552                         gint           width,
4553                         gint           height)
4554 {
4555   GdkPoint points[5];
4556   GdkGC    *gc;
4557   gboolean free_dash_list = FALSE;
4558   gint line_width = 1;
4559   gint8 *dash_list = "\1\1";
4560   gint dash_len;
4561
4562   gc = style->fg_gc[state_type];
4563
4564   if (widget)
4565     {
4566       gtk_widget_style_get (widget,
4567                             "focus-line-width", &line_width,
4568                             "focus-line-pattern", (gchar *)&dash_list,
4569                             NULL);
4570
4571       free_dash_list = TRUE;
4572   }
4573
4574   sanitize_size (window, &width, &height);
4575   
4576   if (area)
4577     gdk_gc_set_clip_rectangle (gc, area);
4578
4579   gdk_gc_set_line_attributes (gc, line_width,
4580                               dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID,
4581                               GDK_CAP_BUTT, GDK_JOIN_MITER);
4582
4583
4584   if (detail && !strcmp (detail, "add-mode"))
4585     {
4586       if (free_dash_list)
4587         g_free (dash_list);
4588       
4589       dash_list = "\4\4";
4590       free_dash_list = FALSE;
4591     }
4592
4593   points[0].x = x + line_width / 2;
4594   points[0].y = y + line_width / 2;
4595   points[1].x = x + width - line_width + line_width / 2;
4596   points[1].y = y + line_width / 2;
4597   points[2].x = x + width - line_width + line_width / 2;
4598   points[2].y = y + height - line_width + line_width / 2;
4599   points[3].x = x + line_width / 2;
4600   points[3].y = y + height - line_width + line_width / 2;
4601   points[4] = points[0];
4602
4603   if (!dash_list[0])
4604     {
4605       gdk_draw_lines (window, gc, points, 5);
4606     }
4607   else
4608     {
4609       /* We go through all the pain below because the X rasterization
4610        * rules don't really work right for dashed lines if you
4611        * want continuity in segments that go between top/right
4612        * and left/bottom. For instance, a top left corner
4613        * with a 1-1 dash is drawn as:
4614        *
4615        *  X X X 
4616        *  X
4617        *
4618        *  X
4619        *
4620        * This is because pixels on the top and left boundaries
4621        * of polygons are drawn, but not on the bottom and right.
4622        * So, if you have a line going up that turns the corner
4623        * and goes right, there is a one pixel shift in the pattern.
4624        *
4625        * So, to fix this, we drawn the top and right in one call,
4626        * then the left and bottom in another call, fixing up
4627        * the dash offset for the second call ourselves to get
4628        * continuity at the upper left.
4629        *
4630        * It's not perfect since we really should have a join at
4631        * the upper left and lower right instead of two intersecting
4632        * lines but that's only really apparent for no-dashes,
4633        * which (for this reason) are done as one polygon and
4634        * don't to through this code path.
4635        */
4636       
4637       dash_len = strlen (dash_list);
4638       
4639       if (dash_list[0])
4640         gdk_gc_set_dashes (gc, 0, dash_list, dash_len);
4641       
4642       gdk_draw_lines (window, gc, points, 3);
4643       
4644       /* We draw this line one farther over than it is "supposed" to
4645        * because of another rasterization problem ... if two 1 pixel
4646        * unjoined lines meet at the lower right, there will be a missing
4647        * pixel.
4648        */
4649       points[2].x += 1;
4650       
4651       if (dash_list[0])
4652         {
4653           gint dash_pixels = 0;
4654           gint i;
4655           
4656           /* Adjust the dash offset for the bottom and left so we
4657            * match up at the upper left.
4658            */
4659           for (i = 0; i < dash_len; i++)
4660             dash_pixels += dash_list[i];
4661       
4662           if (dash_len % 2 == 1)
4663             dash_pixels *= 2;
4664           
4665           gdk_gc_set_dashes (gc, dash_pixels - (width + height - 2 * line_width) % dash_pixels, dash_list, dash_len);
4666         }
4667       
4668       gdk_draw_lines (window, gc, points + 2, 3);
4669     }
4670
4671   gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
4672
4673   if (area)
4674     gdk_gc_set_clip_rectangle (gc, NULL);
4675
4676   if (free_dash_list)
4677     g_free (dash_list);
4678 }
4679
4680 static void 
4681 gtk_default_draw_slider (GtkStyle      *style,
4682                          GdkWindow     *window,
4683                          GtkStateType   state_type,
4684                          GtkShadowType  shadow_type,
4685                          GdkRectangle  *area,
4686                          GtkWidget     *widget,
4687                          const gchar   *detail,
4688                          gint           x,
4689                          gint           y,
4690                          gint           width,
4691                          gint           height,
4692                          GtkOrientation orientation)
4693 {
4694   g_return_if_fail (GTK_IS_STYLE (style));
4695   g_return_if_fail (window != NULL);
4696   
4697   sanitize_size (window, &width, &height);
4698   
4699   gtk_paint_box (style, window, state_type, shadow_type,
4700                  area, widget, detail, x, y, width, height);
4701
4702   if (detail &&
4703       (strcmp ("hscale", detail) == 0 ||
4704        strcmp ("vscale", detail) == 0))
4705     {
4706       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4707         gtk_paint_vline (style, window, state_type, area, widget, detail, 
4708                          y + style->ythickness, 
4709                          y + height - style->ythickness - 1, x + width / 2);
4710       else
4711         gtk_paint_hline (style, window, state_type, area, widget, detail, 
4712                          x + style->xthickness, 
4713                          x + width - style->xthickness - 1, y + height / 2);
4714     }
4715 }
4716
4717 static void
4718 draw_dot (GdkWindow    *window,
4719           GdkGC        *light_gc,
4720           GdkGC        *dark_gc,
4721           gint          x,
4722           gint          y,
4723           gushort       size)
4724 {
4725   
4726   size = CLAMP (size, 2, 3);
4727
4728   if (size == 2)
4729     {
4730       gdk_draw_point (window, light_gc, x, y);
4731       gdk_draw_point (window, light_gc, x+1, y+1);
4732     }
4733   else if (size == 3);
4734     {
4735       gdk_draw_point (window, light_gc, x, y);
4736       gdk_draw_point (window, light_gc, x+1, y);
4737       gdk_draw_point (window, light_gc, x, y+1);
4738       gdk_draw_point (window, dark_gc, x+1, y+2);
4739       gdk_draw_point (window, dark_gc, x+2, y+1);
4740       gdk_draw_point (window, dark_gc, x+2, y+2);
4741     }
4742 }
4743
4744 static void 
4745 gtk_default_draw_handle (GtkStyle      *style,
4746                          GdkWindow     *window,
4747                          GtkStateType   state_type,
4748                          GtkShadowType  shadow_type,
4749                          GdkRectangle  *area,
4750                          GtkWidget     *widget,
4751                          const gchar   *detail,
4752                          gint           x,
4753                          gint           y,
4754                          gint           width,
4755                          gint           height,
4756                          GtkOrientation orientation)
4757 {
4758   gint xx, yy;
4759   gint xthick, ythick;
4760   GdkGC *light_gc, *dark_gc;
4761   GdkGC *free_me = NULL;
4762   GdkRectangle rect;
4763   GdkRectangle dest;
4764   gint intersect;
4765   
4766   g_return_if_fail (GTK_IS_STYLE (style));
4767   g_return_if_fail (window != NULL);
4768   
4769   sanitize_size (window, &width, &height);
4770   
4771   gtk_paint_box (style, window, state_type, shadow_type, area, widget, 
4772                  detail, x, y, width, height);
4773   
4774   
4775   if (!strcmp (detail, "paned"))
4776     {
4777       /* we want to ignore the shadow border in paned widgets */
4778       xthick = 0;
4779       ythick = 0;
4780
4781       if (state_type == GTK_STATE_SELECTED && !GTK_WIDGET_HAS_FOCUS (widget))
4782         {
4783           GdkColor unfocused_light;
4784       
4785           gtk_style_shade (&style->base[GTK_STATE_ACTIVE], &unfocused_light,
4786                            LIGHTNESS_MULT);
4787
4788           light_gc = free_me = gdk_gc_new (window);
4789           gdk_gc_set_rgb_fg_color (light_gc, &unfocused_light);
4790         }
4791       else
4792         light_gc = style->light_gc[state_type];
4793
4794       dark_gc = style->black_gc;
4795     }
4796   else
4797     {
4798       xthick = style->xthickness;
4799       ythick = style->ythickness;
4800
4801       light_gc = style->light_gc[state_type];
4802       dark_gc = style->dark_gc[state_type];
4803     }
4804   
4805   rect.x = x + xthick;
4806   rect.y = y + ythick;
4807   rect.width = width - (xthick * 2);
4808   rect.height = height - (ythick * 2);
4809
4810   if (area)
4811     intersect = gdk_rectangle_intersect (area, &rect, &dest);
4812   else
4813     {
4814       intersect = TRUE;
4815       dest = rect;
4816     }
4817
4818   if (!intersect)
4819     goto out;
4820
4821   gdk_gc_set_clip_rectangle (light_gc, &dest);
4822   gdk_gc_set_clip_rectangle (dark_gc, &dest);
4823
4824   if (!strcmp (detail, "paned"))
4825     {
4826       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4827         for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
4828           draw_dot (window, light_gc, dark_gc, xx, y + height/2 - 1, 3);
4829       else
4830         for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
4831           draw_dot (window, light_gc, dark_gc, x + width/2 - 1, yy, 3);
4832     }
4833   else
4834     {
4835       for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
4836         for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
4837           {
4838             draw_dot (window, light_gc, dark_gc, xx, yy, 2);
4839             draw_dot (window, light_gc, dark_gc, xx + 3, yy + 1, 2);
4840           }
4841     }
4842
4843   gdk_gc_set_clip_rectangle (light_gc, NULL);
4844   gdk_gc_set_clip_rectangle (dark_gc, NULL);
4845
4846  out:
4847   if (free_me)
4848     g_object_unref (G_OBJECT (free_me));
4849 }
4850
4851 static void
4852 create_expander_affine (gdouble affine[6],
4853                         gint    degrees,
4854                         gint    expander_size,
4855                         gint    x,
4856                         gint    y)
4857 {
4858   gdouble s, c;
4859   gdouble width;
4860   gdouble height;
4861
4862   width = expander_size / 4.0;
4863   height = expander_size / 2.0;
4864   
4865   s = sin (degrees * G_PI / 180.0);
4866   c = cos (degrees * G_PI / 180.0);
4867   
4868   affine[0] = c;
4869   affine[1] = s;
4870   affine[2] = -s;
4871   affine[3] = c;
4872   affine[4] = -width * c - height * -s + x;
4873   affine[5] = -width * s - height * c + y;
4874 }
4875
4876 static void
4877 apply_affine_on_point (double affine[6], GdkPoint *point)
4878 {
4879   gdouble x, y;
4880
4881   x = point->x * affine[0] + point->y * affine[2] + affine[4];
4882   y = point->x * affine[1] + point->y * affine[3] + affine[5];
4883
4884   point->x = floor (x);
4885   point->y = floor (y);
4886 }
4887
4888 static void
4889 gtk_style_draw_polygon_with_gc (GdkWindow *window, GdkGC *gc, gint line_width,
4890                                 gboolean do_fill, GdkPoint *points, gint n_points)
4891 {
4892   gdk_gc_set_line_attributes (gc, line_width,
4893                               GDK_LINE_SOLID,
4894                               GDK_CAP_BUTT, GDK_JOIN_MITER);
4895
4896   gdk_draw_polygon (window, gc, do_fill, points, n_points);
4897   gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
4898 }
4899
4900 static void
4901 gtk_default_draw_expander (GtkStyle        *style,
4902                            GdkWindow       *window,
4903                            GtkStateType     state_type,
4904                            GdkRectangle    *area,
4905                            GtkWidget       *widget,
4906                            const gchar     *detail,
4907                            gint             x,
4908                            gint             y,
4909                            GtkExpanderStyle expander_style)
4910 {
4911   gint expander_size;
4912   GdkPoint points[3];
4913   gint i;
4914   gint line_width;
4915   gdouble affine[6];
4916   gint degrees = 0;
4917
4918   gtk_widget_style_get (widget,
4919                         "expander_size", &expander_size,
4920                         NULL);
4921   line_width = MAX (1, expander_size/7);
4922
4923   if (area)
4924     {
4925       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], area);
4926       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], area);
4927     }
4928
4929   expander_size -= (line_width * 2 - 2);
4930   points[0].x = line_width / 2;
4931   points[0].y = line_width / 2;
4932   points[1].x = expander_size / 2 + line_width / 2;
4933   points[1].y = expander_size / 2 + line_width / 2;
4934   points[2].x = line_width / 2;
4935   points[2].y = expander_size + line_width / 2;
4936
4937   switch (expander_style)
4938     {
4939     case GTK_EXPANDER_COLLAPSED:
4940       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
4941       break;
4942     case GTK_EXPANDER_SEMI_COLLAPSED:
4943       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
4944       break;
4945     case GTK_EXPANDER_SEMI_EXPANDED:
4946       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
4947       break;
4948     case GTK_EXPANDER_EXPANDED:
4949       degrees = 90;
4950       break;
4951     default:
4952       g_assert_not_reached ();
4953     }
4954
4955   create_expander_affine (affine, degrees, expander_size, x, y);
4956
4957   for (i = 0; i < 3; i++)
4958     apply_affine_on_point (affine, &points[i]);
4959
4960   if (state_type == GTK_STATE_PRELIGHT)
4961     {
4962       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4963                                       1, TRUE, points, 3);
4964     }
4965   else if (state_type == GTK_STATE_ACTIVE)
4966     {
4967       gtk_style_draw_polygon_with_gc (window, style->light_gc[GTK_STATE_ACTIVE],
4968                                       1, TRUE, points, 3);
4969       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4970                                       line_width, FALSE, points, 3);
4971     }
4972   else
4973     {
4974       gtk_style_draw_polygon_with_gc (window, style->base_gc[GTK_STATE_NORMAL],
4975                                       1, TRUE, points, 3);
4976       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4977                                       line_width, FALSE, points, 3);
4978     }
4979   if (area)
4980     {
4981       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
4982       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
4983     }
4984 }
4985
4986 typedef struct _ByteRange ByteRange;
4987
4988 struct _ByteRange
4989 {
4990   guint start;
4991   guint end;
4992 };
4993
4994 static ByteRange*
4995 range_new (guint start,
4996            guint end)
4997 {
4998   ByteRange *br = g_new (ByteRange, 1);
4999
5000   br->start = start;
5001   br->end = end;
5002   
5003   return br;
5004 }
5005
5006 static PangoLayout*
5007 get_insensitive_layout (GdkDrawable *drawable,
5008                         PangoLayout *layout)
5009 {
5010   GSList *embossed_ranges = NULL;
5011   GSList *stippled_ranges = NULL;
5012   PangoLayoutIter *iter;
5013   GSList *tmp_list = NULL;
5014   PangoLayout *new_layout;
5015   PangoAttrList *attrs;
5016   GdkBitmap *stipple = NULL;
5017   
5018   iter = pango_layout_get_iter (layout);
5019   
5020   do
5021     {
5022       PangoLayoutRun *run;
5023       PangoAttribute *attr;
5024       gboolean need_stipple = FALSE;
5025       ByteRange *br;
5026       
5027       run = pango_layout_iter_get_run (iter);
5028
5029       if (run)
5030         {
5031           tmp_list = run->item->analysis.extra_attrs;
5032
5033           while (tmp_list != NULL)
5034             {
5035               attr = tmp_list->data;
5036               switch (attr->klass->type)
5037                 {
5038                 case PANGO_ATTR_FOREGROUND:
5039                 case PANGO_ATTR_BACKGROUND:
5040                   need_stipple = TRUE;
5041                   break;
5042               
5043                 default:
5044                   break;
5045                 }
5046
5047               if (need_stipple)
5048                 break;
5049           
5050               tmp_list = g_slist_next (tmp_list);
5051             }
5052
5053           br = range_new (run->item->offset, run->item->offset + run->item->length);
5054       
5055           if (need_stipple)
5056             stippled_ranges = g_slist_prepend (stippled_ranges, br);
5057           else
5058             embossed_ranges = g_slist_prepend (embossed_ranges, br);
5059         }
5060     }
5061   while (pango_layout_iter_next_run (iter));
5062
5063   pango_layout_iter_free (iter);
5064
5065   new_layout = pango_layout_copy (layout);
5066
5067   attrs = pango_layout_get_attributes (new_layout);
5068
5069   if (attrs == NULL)
5070     {
5071       /* Create attr list if there wasn't one */
5072       attrs = pango_attr_list_new ();
5073       pango_layout_set_attributes (new_layout, attrs);
5074       pango_attr_list_unref (attrs);
5075     }
5076   
5077   tmp_list = embossed_ranges;
5078   while (tmp_list != NULL)
5079     {
5080       PangoAttribute *attr;
5081       ByteRange *br = tmp_list->data;
5082
5083       attr = gdk_pango_attr_embossed_new (TRUE);
5084
5085       attr->start_index = br->start;
5086       attr->end_index = br->end;
5087       
5088       pango_attr_list_change (attrs, attr);
5089
5090       g_free (br);
5091       
5092       tmp_list = g_slist_next (tmp_list);
5093     }
5094
5095   g_slist_free (embossed_ranges);
5096   
5097   tmp_list = stippled_ranges;
5098   while (tmp_list != NULL)
5099     {
5100       PangoAttribute *attr;
5101       ByteRange *br = tmp_list->data;
5102
5103       if (stipple == NULL)
5104         {
5105 #define gray50_width 2
5106 #define gray50_height 2
5107           static const char gray50_bits[] = {
5108             0x02, 0x01
5109           };
5110
5111           stipple = gdk_bitmap_create_from_data (drawable,
5112                                                  gray50_bits, gray50_width,
5113                                                  gray50_height);
5114         }
5115       
5116       attr = gdk_pango_attr_stipple_new (stipple);
5117
5118       attr->start_index = br->start;
5119       attr->end_index = br->end;
5120       
5121       pango_attr_list_change (attrs, attr);
5122
5123       g_free (br);
5124       
5125       tmp_list = g_slist_next (tmp_list);
5126     }
5127
5128   g_slist_free (stippled_ranges);
5129   
5130   if (stipple)
5131     g_object_unref (stipple);
5132
5133   return new_layout;
5134 }
5135
5136 static void
5137 gtk_default_draw_layout (GtkStyle        *style,
5138                          GdkWindow       *window,
5139                          GtkStateType     state_type,
5140                          gboolean         use_text,
5141                          GdkRectangle    *area,
5142                          GtkWidget       *widget,
5143                          const gchar     *detail,
5144                          gint             x,
5145                          gint             y,
5146                          PangoLayout     *layout)
5147 {
5148   GdkGC *gc;
5149   
5150   g_return_if_fail (GTK_IS_STYLE (style));
5151   g_return_if_fail (window != NULL);
5152
5153   gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
5154   
5155   if (area)
5156     gdk_gc_set_clip_rectangle (gc, area);
5157
5158   if (state_type == GTK_STATE_INSENSITIVE)
5159     {
5160       PangoLayout *ins;
5161
5162       ins = get_insensitive_layout (window, layout);
5163       
5164       gdk_draw_layout (window, gc, x, y, ins);
5165
5166       g_object_unref (ins);
5167     }
5168   else
5169     {
5170       gdk_draw_layout (window, gc, x, y, layout);
5171     }
5172
5173   if (area)
5174     gdk_gc_set_clip_rectangle (gc, NULL);
5175 }
5176
5177 static void
5178 gtk_default_draw_resize_grip (GtkStyle       *style,
5179                               GdkWindow      *window,
5180                               GtkStateType    state_type,
5181                               GdkRectangle   *area,
5182                               GtkWidget      *widget,
5183                               const gchar    *detail,
5184                               GdkWindowEdge   edge,
5185                               gint            x,
5186                               gint            y,
5187                               gint            width,
5188                               gint            height)
5189 {
5190   g_return_if_fail (GTK_IS_STYLE (style));
5191   g_return_if_fail (window != NULL);
5192   
5193   if (area)
5194     {
5195       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
5196       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
5197       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
5198     }
5199   
5200   switch (edge)
5201     {
5202     case GDK_WINDOW_EDGE_NORTH_WEST:
5203       /* make it square */
5204       if (width < height)
5205         {
5206           height = width;
5207         }
5208       else if (height < width)
5209         {
5210           width = height;
5211         }
5212       break;
5213     case GDK_WINDOW_EDGE_NORTH:
5214       if (width < height)
5215         {
5216           height = width;
5217         }
5218       break;
5219     case GDK_WINDOW_EDGE_NORTH_EAST:
5220       /* make it square, aligning to top right */
5221       if (width < height)
5222         {
5223           height = width;
5224         }
5225       else if (height < width)
5226         {
5227           x += (width - height);
5228           width = height;
5229         }
5230       break;
5231     case GDK_WINDOW_EDGE_WEST:
5232       if (height < width)
5233         {
5234            width = height;
5235         }
5236       break;
5237     case GDK_WINDOW_EDGE_EAST:
5238       /* aligning to right */
5239       if (height < width)
5240         {
5241           x += (width - height);
5242           width = height;
5243         }
5244       break;
5245     case GDK_WINDOW_EDGE_SOUTH_WEST:
5246       /* make it square, aligning to bottom left */
5247       if (width < height)
5248         {
5249           y += (height - width);
5250           height = width;
5251         }
5252       else if (height < width)
5253         {
5254           width = height;
5255         }
5256       break;
5257     case GDK_WINDOW_EDGE_SOUTH:
5258       /* align to bottom */
5259       if (width < height)
5260         {
5261           y += (height - width);
5262           height = width;
5263         }
5264       break;
5265     case GDK_WINDOW_EDGE_SOUTH_EAST:
5266       /* make it square, aligning to bottom right */
5267       if (width < height)
5268         {
5269           y += (height - width);
5270           height = width;
5271         }
5272       else if (height < width)
5273         {
5274           x += (width - height);
5275           width = height;
5276         }
5277       break;
5278     default:
5279       g_assert_not_reached ();
5280     }
5281   /* Clear background */
5282   gtk_style_apply_default_background (style, window, FALSE,
5283                                       state_type, area,
5284                                       x, y, width, height);   
5285
5286   switch (edge)
5287     {
5288     case GDK_WINDOW_EDGE_WEST:
5289     case GDK_WINDOW_EDGE_EAST:
5290       {
5291         gint xi;
5292
5293         xi = x;
5294
5295         while (xi < x + width)
5296           {
5297             gdk_draw_line (window,
5298                            style->light_gc[state_type],
5299                            xi, y,
5300                            xi, y + height);
5301
5302             xi++;
5303             gdk_draw_line (window,
5304                            style->dark_gc[state_type],
5305                            xi, y,
5306                            xi, y + height);
5307
5308             xi += 2;
5309           }
5310       }
5311       break;
5312     case GDK_WINDOW_EDGE_NORTH:
5313     case GDK_WINDOW_EDGE_SOUTH:
5314       {
5315         gint yi;
5316
5317         yi = y;
5318
5319         while (yi < y + height)
5320           {
5321             gdk_draw_line (window,
5322                            style->light_gc[state_type],
5323                            x, yi,
5324                            x + width, yi);
5325
5326             yi++;
5327             gdk_draw_line (window,
5328                            style->dark_gc[state_type],
5329                            x, yi,
5330                            x + width, yi);
5331
5332             yi+= 2;
5333           }
5334       }
5335       break;
5336     case GDK_WINDOW_EDGE_NORTH_WEST:
5337       {
5338         gint xi, yi;
5339
5340         xi = x + width;
5341         yi = y + height;
5342
5343         while (xi > x + 3)
5344           {
5345             gdk_draw_line (window,
5346                            style->dark_gc[state_type],
5347                            xi, y,
5348                            x, yi);
5349
5350             --xi;
5351             --yi;
5352
5353             gdk_draw_line (window,
5354                            style->dark_gc[state_type],
5355                            xi, y,
5356                            x, yi);
5357
5358             --xi;
5359             --yi;
5360
5361             gdk_draw_line (window,
5362                            style->light_gc[state_type],
5363                            xi, y,
5364                            x, yi);
5365
5366             xi -= 3;
5367             yi -= 3;
5368             
5369           }
5370       }
5371       break;
5372     case GDK_WINDOW_EDGE_NORTH_EAST:
5373       {
5374         gint xi, yi;
5375
5376         xi = x;
5377         yi = y + height;
5378
5379         while (xi < (x + width - 3))
5380           {
5381             gdk_draw_line (window,
5382                            style->light_gc[state_type],
5383                            xi, y,
5384                            x + width, yi);                           
5385
5386             ++xi;
5387             --yi;
5388             
5389             gdk_draw_line (window,
5390                            style->dark_gc[state_type],
5391                            xi, y,
5392                            x + width, yi);                           
5393
5394             ++xi;
5395             --yi;
5396             
5397             gdk_draw_line (window,
5398                            style->dark_gc[state_type],
5399                            xi, y,
5400                            x + width, yi);
5401
5402             xi += 3;
5403             yi -= 3;
5404           }
5405       }
5406       break;
5407     case GDK_WINDOW_EDGE_SOUTH_WEST:
5408       {
5409         gint xi, yi;
5410
5411         xi = x + width;
5412         yi = y;
5413
5414         while (xi > x + 3)
5415           {
5416             gdk_draw_line (window,
5417                            style->dark_gc[state_type],
5418                            x, yi,
5419                            xi, y + height);
5420
5421             --xi;
5422             ++yi;
5423
5424             gdk_draw_line (window,
5425                            style->dark_gc[state_type],
5426                            x, yi,
5427                            xi, y + height);
5428
5429             --xi;
5430             ++yi;
5431
5432             gdk_draw_line (window,
5433                            style->light_gc[state_type],
5434                            x, yi,
5435                            xi, y + height);
5436
5437             xi -= 3;
5438             yi += 3;
5439             
5440           }
5441       }
5442       break;
5443     case GDK_WINDOW_EDGE_SOUTH_EAST:
5444       {
5445         gint xi, yi;
5446
5447         xi = x;
5448         yi = y;
5449
5450         while (xi < (x + width - 3))
5451           {
5452             gdk_draw_line (window,
5453                            style->light_gc[state_type],
5454                            xi, y + height,
5455                            x + width, yi);                           
5456
5457             ++xi;
5458             ++yi;
5459             
5460             gdk_draw_line (window,
5461                            style->dark_gc[state_type],
5462                            xi, y + height,
5463                            x + width, yi);                           
5464
5465             ++xi;
5466             ++yi;
5467             
5468             gdk_draw_line (window,
5469                            style->dark_gc[state_type],
5470                            xi, y + height,
5471                            x + width, yi);
5472
5473             xi += 3;
5474             yi += 3;
5475           }
5476       }
5477       break;
5478     default:
5479       g_assert_not_reached ();
5480       break;
5481     }
5482   
5483   if (area)
5484     {
5485       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
5486       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
5487       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
5488     }
5489 }
5490
5491 static void
5492 gtk_style_shade (GdkColor *a,
5493                  GdkColor *b,
5494                  gdouble   k)
5495 {
5496   gdouble red;
5497   gdouble green;
5498   gdouble blue;
5499   
5500   red = (gdouble) a->red / 65535.0;
5501   green = (gdouble) a->green / 65535.0;
5502   blue = (gdouble) a->blue / 65535.0;
5503   
5504   rgb_to_hls (&red, &green, &blue);
5505   
5506   green *= k;
5507   if (green > 1.0)
5508     green = 1.0;
5509   else if (green < 0.0)
5510     green = 0.0;
5511   
5512   blue *= k;
5513   if (blue > 1.0)
5514     blue = 1.0;
5515   else if (blue < 0.0)
5516     blue = 0.0;
5517   
5518   hls_to_rgb (&red, &green, &blue);
5519   
5520   b->red = red * 65535.0;
5521   b->green = green * 65535.0;
5522   b->blue = blue * 65535.0;
5523 }
5524
5525 static void
5526 rgb_to_hls (gdouble *r,
5527             gdouble *g,
5528             gdouble *b)
5529 {
5530   gdouble min;
5531   gdouble max;
5532   gdouble red;
5533   gdouble green;
5534   gdouble blue;
5535   gdouble h, l, s;
5536   gdouble delta;
5537   
5538   red = *r;
5539   green = *g;
5540   blue = *b;
5541   
5542   if (red > green)
5543     {
5544       if (red > blue)
5545         max = red;
5546       else
5547         max = blue;
5548       
5549       if (green < blue)
5550         min = green;
5551       else
5552         min = blue;
5553     }
5554   else
5555     {
5556       if (green > blue)
5557         max = green;
5558       else
5559         max = blue;
5560       
5561       if (red < blue)
5562         min = red;
5563       else
5564         min = blue;
5565     }
5566   
5567   l = (max + min) / 2;
5568   s = 0;
5569   h = 0;
5570   
5571   if (max != min)
5572     {
5573       if (l <= 0.5)
5574         s = (max - min) / (max + min);
5575       else
5576         s = (max - min) / (2 - max - min);
5577       
5578       delta = max -min;
5579       if (red == max)
5580         h = (green - blue) / delta;
5581       else if (green == max)
5582         h = 2 + (blue - red) / delta;
5583       else if (blue == max)
5584         h = 4 + (red - green) / delta;
5585       
5586       h *= 60;
5587       if (h < 0.0)
5588         h += 360;
5589     }
5590   
5591   *r = h;
5592   *g = l;
5593   *b = s;
5594 }
5595
5596 static void
5597 hls_to_rgb (gdouble *h,
5598             gdouble *l,
5599             gdouble *s)
5600 {
5601   gdouble hue;
5602   gdouble lightness;
5603   gdouble saturation;
5604   gdouble m1, m2;
5605   gdouble r, g, b;
5606   
5607   lightness = *l;
5608   saturation = *s;
5609   
5610   if (lightness <= 0.5)
5611     m2 = lightness * (1 + saturation);
5612   else
5613     m2 = lightness + saturation - lightness * saturation;
5614   m1 = 2 * lightness - m2;
5615   
5616   if (saturation == 0)
5617     {
5618       *h = lightness;
5619       *l = lightness;
5620       *s = lightness;
5621     }
5622   else
5623     {
5624       hue = *h + 120;
5625       while (hue > 360)
5626         hue -= 360;
5627       while (hue < 0)
5628         hue += 360;
5629       
5630       if (hue < 60)
5631         r = m1 + (m2 - m1) * hue / 60;
5632       else if (hue < 180)
5633         r = m2;
5634       else if (hue < 240)
5635         r = m1 + (m2 - m1) * (240 - hue) / 60;
5636       else
5637         r = m1;
5638       
5639       hue = *h;
5640       while (hue > 360)
5641         hue -= 360;
5642       while (hue < 0)
5643         hue += 360;
5644       
5645       if (hue < 60)
5646         g = m1 + (m2 - m1) * hue / 60;
5647       else if (hue < 180)
5648         g = m2;
5649       else if (hue < 240)
5650         g = m1 + (m2 - m1) * (240 - hue) / 60;
5651       else
5652         g = m1;
5653       
5654       hue = *h - 120;
5655       while (hue > 360)
5656         hue -= 360;
5657       while (hue < 0)
5658         hue += 360;
5659       
5660       if (hue < 60)
5661         b = m1 + (m2 - m1) * hue / 60;
5662       else if (hue < 180)
5663         b = m2;
5664       else if (hue < 240)
5665         b = m1 + (m2 - m1) * (240 - hue) / 60;
5666       else
5667         b = m1;
5668       
5669       *h = r;
5670       *l = g;
5671       *s = b;
5672     }
5673 }
5674
5675
5676 /**
5677  * gtk_paint_hline:
5678  * @style: a #GtkStyle
5679  * @window: a #GdkWindow
5680  * @state_type: a state
5681  * @area: rectangle to which the output is clipped
5682  * @widget: the widget
5683  * @detail: a style detail
5684  * @x1: the starting x coordinate
5685  * @x2: the ending x coordinate
5686  * @y: the y coordinate
5687  * 
5688  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
5689  * using the given style and state.
5690  **/ 
5691 void 
5692 gtk_paint_hline (GtkStyle      *style,
5693                  GdkWindow     *window,
5694                  GtkStateType   state_type,
5695                  GdkRectangle  *area,
5696                  GtkWidget     *widget,
5697                  const gchar   *detail,
5698                  gint          x1,
5699                  gint          x2,
5700                  gint          y)
5701 {
5702   g_return_if_fail (GTK_IS_STYLE (style));
5703   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
5704   
5705   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y);
5706 }
5707
5708 /**
5709  * gtk_paint_vline:
5710  * @style: a #GtkStyle
5711  * @window: a #GdkWindow
5712  * @state_type: a state
5713  * @area: rectangle to which the output is clipped
5714  * @widget: the widget
5715  * @detail: a style detail
5716  * @y1_: the starting y coordinate
5717  * @y2_: the ending y coordinate
5718  * @x: the x coordinate
5719  * 
5720  * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @window
5721  * using the given style and state.
5722  */
5723 void
5724 gtk_paint_vline (GtkStyle      *style,
5725                  GdkWindow     *window,
5726                  GtkStateType   state_type,
5727                  GdkRectangle  *area,
5728                  GtkWidget     *widget,
5729                  const gchar   *detail,
5730                  gint          y1_,
5731                  gint          y2_,
5732                  gint          x)
5733 {
5734   g_return_if_fail (GTK_IS_STYLE (style));
5735   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
5736   
5737   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1_, y2_, x);
5738 }
5739
5740 /**
5741  * gtk_paint_shadow:
5742  * @style: a #GtkStyle
5743  * @window: a #GdkWindow
5744  * @state_type: a state
5745  * @shadow_type: type of shadow to draw
5746  * @area: clip rectangle
5747  * @widget: the widget
5748  * @detail: a style detail
5749  * @x: x origin of the rectangle
5750  * @y: y origin of the rectangle
5751  * @width: width of the rectangle 
5752  * @height: width of the rectangle 
5753  *
5754  * Draws a shadow around the given rectangle in @window 
5755  * using the given style and state and shadow type.
5756  */
5757 void
5758 gtk_paint_shadow (GtkStyle     *style,
5759                   GdkWindow    *window,
5760                   GtkStateType  state_type,
5761                   GtkShadowType shadow_type,
5762                   GdkRectangle *area,
5763                   GtkWidget    *widget,
5764                   const gchar  *detail,
5765                   gint          x,
5766                   gint          y,
5767                   gint          width,
5768                   gint          height)
5769 {
5770   g_return_if_fail (GTK_IS_STYLE (style));
5771   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
5772   
5773   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5774 }
5775
5776 /**
5777  * gtk_paint_polygon:
5778  * @style: a #GtkStyle
5779  * @window: a #GdkWindow
5780  * @state_type: a state
5781  * @shadow_type: type of shadow to draw
5782  * @area: clip rectangle
5783  * @widget: the widget
5784  * @detail: a style detail
5785  * @points: an array of #GdkPoint<!-- -->s
5786  * @npoints: length of @points
5787  * @fill: %TRUE if the polygon should be filled
5788  * 
5789  * Draws a polygon on @window with the given parameters.
5790  */ 
5791 void
5792 gtk_paint_polygon (GtkStyle      *style,
5793                    GdkWindow     *window,
5794                    GtkStateType   state_type,
5795                    GtkShadowType  shadow_type,
5796                    GdkRectangle  *area,
5797                    GtkWidget     *widget,
5798                    const gchar   *detail,
5799                    GdkPoint      *points,
5800                    gint           npoints,
5801                    gboolean       fill)
5802 {
5803   g_return_if_fail (GTK_IS_STYLE (style));
5804   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
5805   
5806   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill);
5807 }
5808
5809 /**
5810  * gtk_paint_arrow:
5811  * @style: a #GtkStyle
5812  * @window: a #GdkWindow
5813  * @state_type: a state
5814  * @shadow_type: the type of shadow to draw
5815  * @area: clip rectangle
5816  * @widget: the widget
5817  * @detail: a style detail
5818  * @arrow_type: the type of arrow to draw
5819  * @fill: %TRUE if the arrow tip should be filled
5820  * @x: x origin of the rectangle to draw the arrow in
5821  * @y: y origin of the rectangle to draw the arrow in
5822  * @width: width of the rectangle to draw the arrow in
5823  * @height: height of the rectangle to draw the arrow in
5824  * 
5825  * Draws an arrow in the given rectangle on @window using the given 
5826  * parameters. @arrow_type determines the direction of the arrow.
5827  */
5828 void
5829 gtk_paint_arrow (GtkStyle      *style,
5830                  GdkWindow     *window,
5831                  GtkStateType   state_type,
5832                  GtkShadowType  shadow_type,
5833                  GdkRectangle  *area,
5834                  GtkWidget     *widget,
5835                  const gchar   *detail,
5836                  GtkArrowType   arrow_type,
5837                  gboolean       fill,
5838                  gint           x,
5839                  gint           y,
5840                  gint           width,
5841                  gint           height)
5842 {
5843   g_return_if_fail (GTK_IS_STYLE (style));
5844   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
5845   
5846   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height);
5847 }
5848
5849 /**
5850  * gtk_paint_diamond:
5851  * @style: a #GtkStyle
5852  * @window: a #GdkWindow
5853  * @state_type: a state
5854  * @shadow_type: the type of shadow to draw
5855  * @area: clip rectangle
5856  * @widget: the widget
5857  * @detail: a style detail
5858  * @x: x origin of the rectangle to draw the diamond in
5859  * @y: y origin of the rectangle to draw the diamond in
5860  * @width: width of the rectangle to draw the diamond in
5861  * @height: height of the rectangle to draw the diamond in
5862  *
5863  * Draws a diamond in the given rectangle on @window using the given
5864  * parameters.
5865  */
5866 void
5867 gtk_paint_diamond (GtkStyle      *style,
5868                    GdkWindow     *window,
5869                    GtkStateType   state_type,
5870                    GtkShadowType  shadow_type,
5871                    GdkRectangle  *area,
5872                    GtkWidget     *widget,
5873                    const gchar   *detail,
5874                    gint        x,
5875                    gint        y,
5876                    gint        width,
5877                    gint        height)
5878 {
5879   g_return_if_fail (GTK_IS_STYLE (style));
5880   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
5881   
5882   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5883 }
5884
5885 /**
5886  * gtk_paint_string:
5887  * @style: a #GtkStyle
5888  * @window: a #GdkWindow
5889  * @state_type: a state
5890  * @area: clip rectangle
5891  * @widget: the widget
5892  * @detail: a style detail
5893  * @x: x origin
5894  * @y: y origin
5895  * @string: the string to draw
5896  * 
5897  * Draws a text string on @window with the given parameters.
5898  *
5899  * Deprecated: Use gtk_paint_layout() instead.
5900  */
5901 void
5902 gtk_paint_string (GtkStyle      *style,
5903                   GdkWindow     *window,
5904                   GtkStateType   state_type,
5905                   GdkRectangle  *area,
5906                   GtkWidget     *widget,
5907                   const gchar   *detail,
5908                   gint           x,
5909                   gint           y,
5910                   const gchar   *string)
5911 {
5912   g_return_if_fail (GTK_IS_STYLE (style));
5913   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
5914   
5915   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string);
5916 }
5917
5918 /**
5919  * gtk_paint_box:
5920  * @style: a #GtkStyle
5921  * @window: a #GdkWindow
5922  * @state_type: a state
5923  * @shadow_type: the type of shadow to draw
5924  * @area: clip rectangle
5925  * @widget: the widget
5926  * @detail: a style detail
5927  * @x: x origin of the box
5928  * @y: y origin of the box
5929  * @width: the width of the box
5930  * @height: the height of the box
5931  * 
5932  * Draws a box on @window with the given parameters.
5933  */
5934 void
5935 gtk_paint_box (GtkStyle      *style,
5936                GdkWindow     *window,
5937                GtkStateType   state_type,
5938                GtkShadowType  shadow_type,
5939                GdkRectangle  *area,
5940                GtkWidget     *widget,
5941                const gchar   *detail,
5942                gint           x,
5943                gint           y,
5944                gint           width,
5945                gint           height)
5946 {
5947   g_return_if_fail (GTK_IS_STYLE (style));
5948   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
5949   
5950   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5951 }
5952
5953 /**
5954  * gtk_paint_flat_box:
5955  * @style: a #GtkStyle
5956  * @window: a #GdkWindow
5957  * @state_type: a state
5958  * @shadow_type: the type of shadow to draw
5959  * @area: clip rectangle
5960  * @widget: the widget
5961  * @detail: a style detail
5962  * @x: x origin of the box
5963  * @y: y origin of the box
5964  * @width: the width of the box
5965  * @height: the height of the box
5966  * 
5967  * Draws a flat box on @window with the given parameters.
5968  */
5969 void
5970 gtk_paint_flat_box (GtkStyle      *style,
5971                     GdkWindow     *window,
5972                     GtkStateType   state_type,
5973                     GtkShadowType  shadow_type,
5974                     GdkRectangle  *area,
5975                     GtkWidget     *widget,
5976                     const gchar   *detail,
5977                     gint           x,
5978                     gint           y,
5979                     gint           width,
5980                     gint           height)
5981 {
5982   g_return_if_fail (GTK_IS_STYLE (style));
5983   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
5984   
5985   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5986 }
5987
5988 /**
5989  * gtk_paint_check:
5990  * @style: a #GtkStyle
5991  * @window: a #GdkWindow
5992  * @state_type: a state
5993  * @shadow_type: the type of shadow to draw
5994  * @area: clip rectangle
5995  * @widget: the widget
5996  * @detail: a style detail
5997  * @x: x origin of the rectangle to draw the check in
5998  * @y: y origin of the rectangle to draw the check in
5999  * @width: the width of the rectangle to draw the check in
6000  * @height: the height of the rectangle to draw the check in
6001  * 
6002  * Draws a check button indicator in the given rectangle on @window with 
6003  * the given parameters.
6004  */
6005 void
6006 gtk_paint_check (GtkStyle      *style,
6007                  GdkWindow     *window,
6008                  GtkStateType   state_type,
6009                  GtkShadowType  shadow_type,
6010                  GdkRectangle  *area,
6011                  GtkWidget     *widget,
6012                  const gchar   *detail,
6013                  gint           x,
6014                  gint           y,
6015                  gint           width,
6016                  gint           height)
6017 {
6018   g_return_if_fail (GTK_IS_STYLE (style));
6019   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
6020   
6021   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
6022 }
6023
6024 /**
6025  * gtk_paint_option:
6026  * @style: a #GtkStyle
6027  * @window: a #GdkWindow
6028  * @state_type: a state
6029  * @shadow_type: the type of shadow to draw
6030  * @area: clip rectangle
6031  * @widget: the widget
6032  * @detail: a style detail
6033  * @x: x origin of the rectangle to draw the option in
6034  * @y: y origin of the rectangle to draw the option in
6035  * @width: the width of the rectangle to draw the option in
6036  * @height: the height of the rectangle to draw the option in
6037  *
6038  * Draws a radio button indicator in the given rectangle on @window with 
6039  * the given parameters.
6040  */
6041 void
6042 gtk_paint_option (GtkStyle      *style,
6043                   GdkWindow     *window,
6044                   GtkStateType   state_type,
6045                   GtkShadowType  shadow_type,
6046                   GdkRectangle  *area,
6047                   GtkWidget     *widget,
6048                   const gchar   *detail,
6049                   gint           x,
6050                   gint           y,
6051                   gint           width,
6052                   gint           height)
6053 {
6054   g_return_if_fail (GTK_IS_STYLE (style));
6055   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
6056   
6057   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
6058 }
6059
6060 /**
6061  * gtk_paint_tab:
6062  * @style: a #GtkStyle
6063  * @window: a #GdkWindow
6064  * @state_type: a state
6065  * @shadow_type: the type of shadow to draw
6066  * @area: clip rectangle
6067  * @widget: the widget
6068  * @detail: a style detail
6069  * @x: x origin of the rectangle to draw the tab in
6070  * @y: y origin of the rectangle to draw the tab in
6071  * @width: the width of the rectangle to draw the tab in
6072  * @height: the height of the rectangle to draw the tab in
6073  *
6074  * Draws an option menu tab (i.e. the up and down pointing arrows)
6075  * in the given rectangle on @window using the given parameters.
6076  */ 
6077 void
6078 gtk_paint_tab (GtkStyle      *style,
6079                GdkWindow     *window,
6080                GtkStateType   state_type,
6081                GtkShadowType  shadow_type,
6082                GdkRectangle  *area,
6083                GtkWidget     *widget,
6084                const gchar   *detail,
6085                gint           x,
6086                gint           y,
6087                gint           width,
6088                gint           height)
6089 {
6090   g_return_if_fail (GTK_IS_STYLE (style));
6091   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
6092   
6093   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
6094 }
6095
6096 /**
6097  * gtk_paint_shadow_gap:
6098  * @style: a #GtkStyle
6099  * @window: a #GdkWindow
6100  * @state_type: a state
6101  * @shadow_type: type of shadow to draw
6102  * @area: clip rectangle
6103  * @widget: the widget
6104  * @detail: a style detail
6105  * @x: x origin of the rectangle
6106  * @y: y origin of the rectangle
6107  * @width: width of the rectangle 
6108  * @height: width of the rectangle 
6109  * @gap_side: side in which to leave the gap
6110  * @gap_x: starting position of the gap
6111  * @gap_width: width of the gap
6112  *
6113  * Draws a shadow around the given rectangle in @window 
6114  * using the given style and state and shadow type, leaving a 
6115  * gap in one side.
6116 */
6117 void
6118 gtk_paint_shadow_gap (GtkStyle       *style,
6119                       GdkWindow      *window,
6120                       GtkStateType    state_type,
6121                       GtkShadowType   shadow_type,
6122                       GdkRectangle   *area,
6123                       GtkWidget      *widget,
6124                       gchar          *detail,
6125                       gint            x,
6126                       gint            y,
6127                       gint            width,
6128                       gint            height,
6129                       GtkPositionType gap_side,
6130                       gint            gap_x,
6131                       gint            gap_width)
6132 {
6133   g_return_if_fail (GTK_IS_STYLE (style));
6134   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
6135   
6136   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);
6137 }
6138
6139
6140 /**
6141  * gtk_paint_box_gap:
6142  * @style: a #GtkStyle
6143  * @window: a #GdkWindow
6144  * @state_type: a state
6145  * @shadow_type: type of shadow to draw
6146  * @area: clip rectangle
6147  * @widget: the widget
6148  * @detail: a style detail
6149  * @x: x origin of the rectangle
6150  * @y: y origin of the rectangle
6151  * @width: width of the rectangle 
6152  * @height: width of the rectangle 
6153  * @gap_side: side in which to leave the gap
6154  * @gap_x: starting position of the gap
6155  * @gap_width: width of the gap
6156  *
6157  * Draws a box in @window using the given style and state and shadow type, 
6158  * leaving a gap in one side.
6159  */
6160 void
6161 gtk_paint_box_gap (GtkStyle       *style,
6162                    GdkWindow      *window,
6163                    GtkStateType    state_type,
6164                    GtkShadowType   shadow_type,
6165                    GdkRectangle   *area,
6166                    GtkWidget      *widget,
6167                    gchar          *detail,
6168                    gint            x,
6169                    gint            y,
6170                    gint            width,
6171                    gint            height,
6172                    GtkPositionType gap_side,
6173                    gint            gap_x,
6174                    gint            gap_width)
6175 {
6176   g_return_if_fail (GTK_IS_STYLE (style));
6177   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
6178   
6179   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);
6180 }
6181
6182 /**
6183  * gtk_paint_extension: 
6184  * @style: a #GtkStyle
6185  * @window: a #GdkWindow
6186  * @state_type: a state
6187  * @shadow_type: type of shadow to draw
6188  * @area: clip rectangle
6189  * @widget: the widget
6190  * @detail: a style detail
6191  * @x: x origin of the extension
6192  * @y: y origin of the extension
6193  * @width: width of the extension 
6194  * @height: width of the extension 
6195  * @gap_side: the side on to which the extension is attached
6196  * 
6197  * Draws an extension, i.e. a notebook tab.
6198  **/
6199 void
6200 gtk_paint_extension (GtkStyle       *style,
6201                      GdkWindow      *window,
6202                      GtkStateType    state_type,
6203                      GtkShadowType   shadow_type,
6204                      GdkRectangle   *area,
6205                      GtkWidget      *widget,
6206                      gchar          *detail,
6207                      gint            x,
6208                      gint            y,
6209                      gint            width,
6210                      gint            height,
6211                      GtkPositionType gap_side)
6212 {
6213   g_return_if_fail (GTK_IS_STYLE (style));
6214   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
6215   
6216   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side);
6217 }
6218
6219 /**
6220  * gtk_paint_focus:
6221  * @style: a #GtkStyle
6222  * @window: a #GdkWindow
6223  * @state_type: a state
6224  * @area: clip rectangle
6225  * @widget: the widget
6226  * @detail: a style detail
6227  * @x: the x origin of the rectangle around which to draw a focus indicator
6228  * @y: the y origin of the rectangle around which to draw a focus indicator
6229  * @width: the width of the rectangle around which to draw a focus indicator
6230  * @height: the height of the rectangle around which to draw a focus indicator
6231  *
6232  * Draws a focus indicator around the given rectangle on @window using the
6233  * given style.
6234  */
6235 void
6236 gtk_paint_focus (GtkStyle      *style,
6237                  GdkWindow     *window,
6238                  GtkStateType   state_type,
6239                  GdkRectangle  *area,
6240                  GtkWidget     *widget,
6241                  const gchar   *detail,
6242                  gint           x,
6243                  gint           y,
6244                  gint           width,
6245                  gint           height)
6246 {
6247   g_return_if_fail (GTK_IS_STYLE (style));
6248   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
6249   
6250   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type, area, widget, detail, x, y, width, height);
6251 }
6252
6253 void
6254 gtk_paint_slider (GtkStyle      *style,
6255                   GdkWindow     *window,
6256                   GtkStateType   state_type,
6257                   GtkShadowType  shadow_type,
6258                   GdkRectangle  *area,
6259                   GtkWidget     *widget,
6260                   const gchar   *detail,
6261                   gint           x,
6262                   gint           y,
6263                   gint           width,
6264                   gint           height,
6265                   GtkOrientation orientation)
6266 {
6267   g_return_if_fail (GTK_IS_STYLE (style));
6268   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
6269   
6270   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
6271 }
6272
6273 /**
6274  * gtk_paint_handle:
6275  * @style: a #GtkStyle
6276  * @window: a #GdkWindow
6277  * @state_type: a state
6278  * @shadow_type: type of shadow to draw
6279  * @area: clip rectangle
6280  * @widget: the widget
6281  * @detail: a style detail
6282  * @x: x origin of the handle
6283  * @y: y origin of the handle
6284  * @width: with of the handle
6285  * @height: height of the handle
6286  * @orientation: the orientation of the handle
6287  * 
6288  * Draws a handle as used in #GtkHandleBox and #GtkPaned.
6289  **/
6290 void
6291 gtk_paint_handle (GtkStyle      *style,
6292                   GdkWindow     *window,
6293                   GtkStateType   state_type,
6294                   GtkShadowType  shadow_type,
6295                   GdkRectangle  *area,
6296                   GtkWidget     *widget,
6297                   const gchar   *detail,
6298                   gint           x,
6299                   gint           y,
6300                   gint           width,
6301                   gint           height,
6302                   GtkOrientation orientation)
6303 {
6304   g_return_if_fail (GTK_IS_STYLE (style));
6305   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
6306   
6307   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
6308 }
6309
6310 /**
6311  * gtk_paint_expander:
6312  * @style: a #GtkStyle
6313  * @window: a #GdkWindow
6314  * @state_type: a state
6315  * @area: clip rectangle
6316  * @widget: the widget
6317  * @detail: a style detail
6318  * @x: the x position to draw the expander at
6319  * @y: the y position to draw the expander at
6320  * @expander_style: the style to draw the expander in
6321  * 
6322  * Draws an expander as used in #GtkTreeView.
6323  **/
6324 void
6325 gtk_paint_expander (GtkStyle        *style,
6326                     GdkWindow       *window,
6327                     GtkStateType     state_type,
6328                     GdkRectangle    *area,
6329                     GtkWidget       *widget,
6330                     const gchar     *detail,
6331                     gint             x,
6332                     gint             y,
6333                     GtkExpanderStyle expander_style)
6334 {
6335   g_return_if_fail (GTK_IS_STYLE (style));
6336   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
6337   
6338   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type, area,
6339                                               widget, detail, x, y, expander_style);
6340 }
6341
6342 void
6343 gtk_paint_layout (GtkStyle        *style,
6344                   GdkWindow       *window,
6345                   GtkStateType     state_type,
6346                   gboolean         use_text,
6347                   GdkRectangle    *area,
6348                   GtkWidget       *widget,
6349                   const gchar     *detail,
6350                   gint             x,
6351                   gint             y,
6352                   PangoLayout     *layout)
6353 {
6354   g_return_if_fail (GTK_IS_STYLE (style));
6355   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
6356   
6357   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text, area,
6358                                             widget, detail, x, y, layout);
6359 }
6360
6361 /**
6362  * gtk_paint_resize_grip:
6363  * @style: a #GtkStyle
6364  * @window: a #GdkWindow
6365  * @state_type: a state
6366  * @area: clip rectangle
6367  * @widget: the widget
6368  * @detail: a style detail
6369  * @edge: the edge in which to draw the resize grip
6370  * @x: the x origin of the rectangle in which to draw the resize grip
6371  * @y: the y origin of the rectangle in which to draw the resize grip
6372  * @width: the width of the rectangle in which to draw the resize grip
6373  * @height: the height of the rectangle in which to draw the resize grip
6374  *
6375  * Draws a resize grip in the given rectangle on @window using the given
6376  * parameters. 
6377  */
6378 void
6379 gtk_paint_resize_grip (GtkStyle      *style,
6380                        GdkWindow     *window,
6381                        GtkStateType   state_type,
6382                        GdkRectangle  *area,
6383                        GtkWidget     *widget,
6384                        const gchar   *detail,
6385                        GdkWindowEdge  edge,
6386                        gint           x,
6387                        gint           y,
6388                        gint           width,
6389                        gint           height)
6390
6391 {
6392   g_return_if_fail (GTK_IS_STYLE (style));
6393   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
6394
6395   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
6396                                                  area, widget, detail,
6397                                                  edge, x, y, width, height);
6398 }
6399
6400 /**
6401  * gtk_border_copy:
6402  * @border_: a #GtkBorder.
6403  * @returns: a copy of @border_.
6404  *
6405  * Copies a #GtkBorder structure.
6406  **/
6407 GtkBorder *
6408 gtk_border_copy (const GtkBorder *border)
6409 {
6410   return (GtkBorder *)g_memdup (border, sizeof (GtkBorder));
6411 }
6412
6413 /**
6414  * gtk_border_free:
6415  * @border_: a #GtkBorder.
6416  * 
6417  * Frees a #GtkBorder structure.
6418  **/
6419 void
6420 gtk_border_free (GtkBorder *border)
6421 {
6422   g_free (border);
6423 }
6424
6425 GType
6426 gtk_border_get_type (void)
6427 {
6428   static GType our_type = 0;
6429   
6430   if (our_type == 0)
6431     our_type = g_boxed_type_register_static ("GtkBorder",
6432                                              (GBoxedCopyFunc) gtk_border_copy,
6433                                              (GBoxedFreeFunc) gtk_border_free);
6434
6435   return our_type;
6436 }
6437
6438 static GdkFont *
6439 gtk_style_get_font_internal (GtkStyle *style)
6440 {
6441   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
6442
6443   if (style->private_font && style->private_font_desc)
6444     {
6445       if (!style->font_desc ||
6446           !pango_font_description_equal (style->private_font_desc, style->font_desc))
6447         {
6448           gdk_font_unref (style->private_font);
6449           style->private_font = NULL;
6450           
6451           if (style->private_font_desc)
6452             {
6453               pango_font_description_free (style->private_font_desc);
6454               style->private_font_desc = NULL;
6455             }
6456         }
6457     }
6458   
6459   if (!style->private_font)
6460     {
6461       GdkDisplay *display;
6462
6463       if (style->colormap)
6464         {
6465           display = gdk_screen_get_display (gdk_colormap_get_screen (style->colormap));
6466         }
6467       else
6468         {
6469           display = gdk_display_get_default ();
6470           GTK_NOTE (MULTIHEAD,
6471                     g_warning ("gtk_style_get_font() should not be called on an unattached style"));
6472         }
6473       
6474       if (style->font_desc)
6475         {
6476           style->private_font = gdk_font_from_description_for_display (display, style->font_desc);
6477           style->private_font_desc = pango_font_description_copy (style->font_desc);
6478         }
6479
6480       if (!style->private_font)
6481         style->private_font = gdk_font_load_for_display (display, "fixed");
6482       
6483       if (!style->private_font) 
6484         g_error ("Unable to load \"fixed\" font");
6485     }
6486
6487   return style->private_font;
6488 }
6489
6490 /**
6491  * gtk_style_get_font:
6492  * @style: a #GtkStyle
6493  * 
6494  * Gets the #GdkFont to use for the given style. This is
6495  * meant only as a replacement for direct access to @style->font
6496  * and should not be used in new code. New code should
6497  * use @style->font_desc instead.
6498  * 
6499  * Return value: the #GdkFont for the style. This font is owned
6500  *   by the style; if you want to keep around a copy, you must
6501  *   call gdk_font_ref().
6502  **/
6503 GdkFont *
6504 gtk_style_get_font (GtkStyle *style)
6505 {
6506   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
6507
6508   return gtk_style_get_font_internal (style);
6509 }
6510
6511 /**
6512  * gtk_style_set_font:
6513  * @style: a #GtkStyle.
6514  * @font: a #GdkFont, or %NULL to use the #GdkFont corresponding
6515  *   to style->font_desc.
6516  * 
6517  * Sets the #GdkFont to use for a given style. This is
6518  * meant only as a replacement for direct access to style->font
6519  * and should not be used in new code. New code should
6520  * use style->font_desc instead.
6521  **/
6522 void
6523 gtk_style_set_font (GtkStyle *style,
6524                     GdkFont  *font)
6525 {
6526   GdkFont *old_font;
6527
6528   g_return_if_fail (GTK_IS_STYLE (style));
6529
6530   old_font = style->private_font;
6531
6532   style->private_font = font;
6533   if (font)
6534     gdk_font_ref (font);
6535
6536   if (old_font)
6537     gdk_font_unref (old_font);
6538
6539   if (style->private_font_desc)
6540     {
6541       pango_font_description_free (style->private_font_desc);
6542       style->private_font_desc = NULL;
6543     }
6544 }
6545
6546 typedef struct _CursorInfo CursorInfo;
6547
6548 struct _CursorInfo
6549 {
6550   GType for_type;
6551   GdkGC *primary_gc;
6552   GdkGC *secondary_gc;
6553 };
6554
6555 static void
6556 style_unrealize_cursor_gcs (GtkStyle *style)
6557 {
6558   CursorInfo *
6559   
6560   cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
6561   if (cursor_info)
6562     {
6563       if (cursor_info->primary_gc)
6564         gtk_gc_release (cursor_info->primary_gc);
6565
6566       if (cursor_info->secondary_gc)
6567         gtk_gc_release (cursor_info->secondary_gc);
6568       
6569       g_free (cursor_info);
6570       g_object_set_data (G_OBJECT (style), "gtk-style-cursor-info", NULL);
6571     }
6572 }
6573
6574 static GdkGC *
6575 make_cursor_gc (GtkWidget   *widget,
6576                 const gchar *property_name,
6577                 const GdkColor *fallback)
6578 {
6579   GdkGCValues gc_values;
6580   GdkGCValuesMask gc_values_mask;
6581   GdkColor *cursor_color;
6582
6583   gtk_widget_style_get (widget, property_name, &cursor_color, NULL);
6584   
6585   gc_values_mask = GDK_GC_FOREGROUND;
6586   if (cursor_color)
6587     {
6588       gc_values.foreground = *cursor_color;
6589       gdk_color_free (cursor_color);
6590     }
6591   else
6592     gc_values.foreground = *fallback;
6593   
6594   gdk_rgb_find_color (widget->style->colormap, &gc_values.foreground);
6595   return gtk_gc_get (widget->style->depth, widget->style->colormap, &gc_values, gc_values_mask);
6596 }
6597
6598 /**
6599  * _gtk_get_insertion_cursor_gc:
6600  * @widget: a #GtkWidget
6601  * @is_primary: if the cursor should be the primary cursor color.
6602  * 
6603  * Get a GC suitable for drawing the primary or secondary text
6604  * cursor.
6605  *
6606  * Note: the return value is ref'ed because calls to this function
6607  *  on other widgets could result in this the GC being released
6608  *  which would be an unexpected side effect. If made public,
6609  *  this function should possibly be called create_insertion_cursor_gc().
6610  *
6611  * Return value: an appropriate #GdkGC. Call g_object_unref() on
6612  *   the gc when you are done with it; this GC may be shared with
6613  *   other users, so you must not modify the GC except for temporarily
6614  *   setting the clip before drawing with the GC, and then unsetting the clip
6615  *   again afterwards.
6616  **/
6617 GdkGC *
6618 _gtk_get_insertion_cursor_gc (GtkWidget *widget,
6619                               gboolean   is_primary)
6620 {
6621   CursorInfo *cursor_info;
6622
6623   cursor_info = g_object_get_data (G_OBJECT (widget->style), "gtk-style-cursor-info");
6624   if (!cursor_info)
6625     {
6626       cursor_info = g_new (CursorInfo, 1);
6627       g_object_set_data (G_OBJECT (widget->style), "gtk-style-cursor-info", cursor_info);
6628       cursor_info->primary_gc = NULL;
6629       cursor_info->secondary_gc = NULL;
6630       cursor_info->for_type = G_TYPE_INVALID;
6631     }
6632
6633   /* We have to keep track of the type because gtk_widget_style_get()
6634    * can return different results when called on the same property and
6635    * same style but for different widgets. :-(. That is,
6636    * GtkEntry::cursor-color = "red" in a style will modify the cursor
6637    * color for entries but not for text view.
6638    */
6639   if (cursor_info->for_type != G_OBJECT_TYPE (widget))
6640     {
6641       cursor_info->for_type = G_OBJECT_TYPE (widget);
6642       if (cursor_info->primary_gc)
6643         {
6644           gtk_gc_release (cursor_info->primary_gc);
6645           cursor_info->primary_gc = NULL;
6646         }
6647       if (cursor_info->secondary_gc)
6648         {
6649           gtk_gc_release (cursor_info->secondary_gc);
6650           cursor_info->secondary_gc = NULL;
6651         }
6652     }
6653
6654   if (is_primary)
6655     {
6656       if (!cursor_info->primary_gc)
6657         cursor_info->primary_gc = make_cursor_gc (widget,
6658                                                   "cursor-color",
6659                                                   &widget->style->black);
6660         
6661       return g_object_ref (cursor_info->primary_gc);
6662     }
6663   else
6664     {
6665       static const GdkColor gray = { 0, 0x8888, 0x8888, 0x8888 };
6666       
6667       if (!cursor_info->secondary_gc)
6668         cursor_info->secondary_gc = make_cursor_gc (widget,
6669                                                     "secondary-cursor-color",
6670                                                     &gray);
6671         
6672       return g_object_ref (cursor_info->secondary_gc);
6673     }
6674 }
6675
6676 /**
6677  * _gtk_draw_insertion_cursor:
6678  * @widget: a #GtkWidget
6679  * @drawable: a #GdkDrawable
6680  * @gc: a #GdkGC
6681  * @location: location where to draw the cursor (@location->width is ignored)
6682  * @direction: whether the cursor is left-to-right or
6683  *             right-to-left. Should never be #GTK_TEXT_DIR_NONE
6684  * @draw_arrow: %TRUE to draw a directional arrow on the
6685  *        cursor. Should be %FALSE unless the cursor is split.
6686  * 
6687  * Draws a text caret on @drawable at @location. This is not a style function
6688  * but merely a convenience function for drawing the standard cursor shape.
6689  **/
6690 void
6691 _gtk_draw_insertion_cursor (GtkWidget        *widget,
6692                             GdkDrawable      *drawable,
6693                             GdkGC            *gc,
6694                             GdkRectangle     *location,
6695                             GtkTextDirection  direction,
6696                             gboolean          draw_arrow)
6697 {
6698   gint stem_width;
6699   gint arrow_width;
6700   gint x, y;
6701   gint i;
6702   gfloat cursor_aspect_ratio;
6703   gint offset;
6704   
6705   g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
6706   
6707   gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
6708   
6709   stem_width = location->height * cursor_aspect_ratio + 1;
6710   arrow_width = stem_width + 1;
6711
6712   /* put (stem_width % 2) on the proper side of the cursor */
6713   if (direction == GTK_TEXT_DIR_LTR)
6714     offset = stem_width / 2;
6715   else
6716     offset = stem_width - stem_width / 2;
6717   
6718   for (i = 0; i < stem_width; i++)
6719     gdk_draw_line (drawable, gc,
6720                    location->x + i - offset, location->y,
6721                    location->x + i - offset, location->y + location->height - 1);
6722
6723   if (draw_arrow)
6724     {
6725       if (direction == GTK_TEXT_DIR_RTL)
6726         {
6727           x = location->x - offset - 1;
6728           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6729   
6730           for (i = 0; i < arrow_width; i++)
6731             {
6732               gdk_draw_line (drawable, gc,
6733                              x, y + i + 1,
6734                              x, y + 2 * arrow_width - i - 1);
6735               x --;
6736             }
6737         }
6738       else if (direction == GTK_TEXT_DIR_LTR)
6739         {
6740           x = location->x + stem_width - offset;
6741           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6742   
6743           for (i = 0; i < arrow_width; i++) 
6744             {
6745               gdk_draw_line (drawable, gc,
6746                              x, y + i + 1,
6747                              x, y + 2 * arrow_width - i - 1);
6748               x++;
6749             }
6750         }
6751     }
6752 }