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