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