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