]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
Fix doc comment.
[~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
1457  * @x: the x origin of the rectangle in which to draw the resize grip
1458  * @y: the y origin of the rectangle in which to draw the resize grip
1459  * @width: the width of the rectangle in which to draw the resize grip
1460  * @height: the height of the rectangle in which to draw the resize grip
1461  *
1462  * Draws a resize grip in the given rectangle on @window using the given
1463  * parameters. 
1464  * 
1465  * This function is deprecated, use gtk_paint_resize_grip() instead.
1466  */
1467 void
1468 gtk_draw_resize_grip (GtkStyle     *style,
1469                       GdkWindow    *window,
1470                       GtkStateType  state_type,
1471                       GdkWindowEdge edge,
1472                       gint          x,
1473                       gint          y,
1474                       gint          width,
1475                       gint          height)
1476 {
1477   g_return_if_fail (GTK_IS_STYLE (style));
1478   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
1479
1480   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
1481                                                  NULL, NULL, NULL,
1482                                                  edge,
1483                                                  x, y, width, height);
1484 }
1485
1486
1487 /**
1488  * gtk_style_set_background:
1489  * @style: a #GtkStyle
1490  * @window: a #GdkWindow
1491  * @state_type: a state
1492  * 
1493  * Sets the background of @window to the background color or pixmap
1494  * specified by @style for the given state.
1495  */
1496 void
1497 gtk_style_set_background (GtkStyle    *style,
1498                           GdkWindow   *window,
1499                           GtkStateType state_type)
1500 {
1501   g_return_if_fail (GTK_IS_STYLE (style));
1502   g_return_if_fail (window != NULL);
1503   
1504   GTK_STYLE_GET_CLASS (style)->set_background (style, window, state_type);
1505 }
1506
1507 /* Default functions */
1508 static GtkStyle *
1509 gtk_style_real_clone (GtkStyle *style)
1510 {
1511   return GTK_STYLE (g_object_new (G_OBJECT_TYPE (style), NULL));
1512 }
1513
1514 static void
1515 gtk_style_real_copy (GtkStyle *style,
1516                      GtkStyle *src)
1517 {
1518   gint i;
1519   
1520   for (i = 0; i < 5; i++)
1521     {
1522       style->fg[i] = src->fg[i];
1523       style->bg[i] = src->bg[i];
1524       style->text[i] = src->text[i];
1525       style->base[i] = src->base[i];
1526       
1527       style->bg_pixmap[i] = src->bg_pixmap[i];
1528     }
1529
1530   if (style->private_font)
1531     gdk_font_unref (style->private_font);
1532   style->private_font = src->private_font;
1533   if (style->private_font)
1534     gdk_font_ref (style->private_font);
1535
1536   if (style->font_desc)
1537     pango_font_description_free (style->font_desc);
1538   if (src->font_desc)
1539     style->font_desc = pango_font_description_copy (src->font_desc);
1540   else
1541     style->font_desc = NULL;
1542   
1543   style->xthickness = src->xthickness;
1544   style->ythickness = src->ythickness;
1545
1546   if (style->rc_style)
1547     gtk_rc_style_unref (style->rc_style);
1548   style->rc_style = src->rc_style;
1549   if (src->rc_style)
1550     gtk_rc_style_ref (src->rc_style);
1551
1552   /* don't copy, just clear cache */
1553   clear_property_cache (style);
1554 }
1555
1556 static void
1557 gtk_style_real_init_from_rc (GtkStyle   *style,
1558                              GtkRcStyle *rc_style)
1559 {
1560   gint i;
1561
1562   /* cache _should_ be still empty */
1563   clear_property_cache (style);
1564
1565   if (rc_style->font_desc)
1566     pango_font_description_merge (style->font_desc, rc_style->font_desc, TRUE);
1567     
1568   for (i = 0; i < 5; i++)
1569     {
1570       if (rc_style->color_flags[i] & GTK_RC_FG)
1571         style->fg[i] = rc_style->fg[i];
1572       if (rc_style->color_flags[i] & GTK_RC_BG)
1573         style->bg[i] = rc_style->bg[i];
1574       if (rc_style->color_flags[i] & GTK_RC_TEXT)
1575         style->text[i] = rc_style->text[i];
1576       if (rc_style->color_flags[i] & GTK_RC_BASE)
1577         style->base[i] = rc_style->base[i];
1578     }
1579
1580   if (rc_style->xthickness >= 0)
1581     style->xthickness = rc_style->xthickness;
1582   if (rc_style->ythickness >= 0)
1583     style->ythickness = rc_style->ythickness;
1584
1585   if (rc_style->icon_factories)
1586     {
1587       GSList *iter;
1588
1589       style->icon_factories = g_slist_copy (rc_style->icon_factories);
1590       
1591       iter = style->icon_factories;
1592       while (iter != NULL)
1593         {
1594           g_object_ref (iter->data);
1595           iter = g_slist_next (iter);
1596         }
1597     }
1598 }
1599
1600 static gint
1601 style_property_values_cmp (gconstpointer bsearch_node1,
1602                            gconstpointer bsearch_node2)
1603 {
1604   const PropertyValue *val1 = bsearch_node1;
1605   const PropertyValue *val2 = bsearch_node2;
1606
1607   if (val1->widget_type == val2->widget_type)
1608     return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
1609   else
1610     return val1->widget_type < val2->widget_type ? -1 : 1;
1611 }
1612
1613 const GValue*
1614 _gtk_style_peek_property_value (GtkStyle           *style,
1615                                 GType               widget_type,
1616                                 GParamSpec         *pspec,
1617                                 GtkRcPropertyParser parser)
1618 {
1619   PropertyValue *pcache, key = { 0, NULL, { 0, } };
1620   const GtkRcProperty *rcprop = NULL;
1621   guint i;
1622
1623   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1624   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
1625   g_return_val_if_fail (g_type_is_a (pspec->owner_type, GTK_TYPE_WIDGET), NULL);
1626   g_return_val_if_fail (g_type_is_a (widget_type, pspec->owner_type), NULL);
1627
1628   key.widget_type = widget_type;
1629   key.pspec = pspec;
1630
1631   /* need value cache array */
1632   if (!style->property_cache)
1633     style->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
1634   else
1635     {
1636       pcache = bsearch (&key,
1637                         style->property_cache->data, style->property_cache->len,
1638                         sizeof (PropertyValue), style_property_values_cmp);
1639       if (pcache)
1640         return &pcache->value;
1641     }
1642
1643   i = 0;
1644   while (i < style->property_cache->len &&
1645          style_property_values_cmp (&key, &g_array_index (style->property_cache, PropertyValue, i)) >= 0)
1646     i++;
1647
1648   g_array_insert_val (style->property_cache, i, key);
1649   pcache = &g_array_index (style->property_cache, PropertyValue, i);
1650
1651   /* cache miss, initialize value type, then set contents */
1652   g_param_spec_ref (pcache->pspec);
1653   g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1654
1655   /* value provided by rc style? */
1656   if (style->rc_style)
1657     {
1658       GQuark prop_quark = g_quark_from_string (pspec->name);
1659
1660       do
1661         {
1662           rcprop = _gtk_rc_style_lookup_rc_property (style->rc_style,
1663                                                      g_type_qname (widget_type),
1664                                                      prop_quark);
1665           if (rcprop)
1666             break;
1667           widget_type = g_type_parent (widget_type);
1668         }
1669       while (g_type_is_a (widget_type, pspec->owner_type));
1670     }
1671
1672   /* when supplied by rc style, we need to convert */
1673   if (rcprop && !_gtk_settings_parse_convert (parser, &rcprop->value,
1674                                               pspec, &pcache->value))
1675     {
1676       gchar *contents = g_strdup_value_contents (&rcprop->value);
1677       
1678       g_message ("%s: failed to retrieve property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
1679                  rcprop->origin,
1680                  g_type_name (pspec->owner_type), pspec->name,
1681                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1682                  contents,
1683                  G_VALUE_TYPE_NAME (&rcprop->value));
1684       g_free (contents);
1685       rcprop = NULL; /* needs default */
1686     }
1687   
1688   /* not supplied by rc style (or conversion failed), revert to default */
1689   if (!rcprop)
1690     g_param_value_set_default (pspec, &pcache->value);
1691
1692   return &pcache->value;
1693 }
1694
1695 static GdkPixmap *
1696 load_bg_image (GdkColormap *colormap,
1697                GdkColor    *bg_color,
1698                const gchar *filename)
1699 {
1700   if (strcmp (filename, "<parent>") == 0)
1701     return (GdkPixmap*) GDK_PARENT_RELATIVE;
1702   else
1703     {
1704       return gdk_pixmap_colormap_create_from_xpm (NULL, colormap, NULL,
1705                                                   bg_color,
1706                                                   filename);
1707     }
1708 }
1709
1710 static void
1711 gtk_style_real_realize (GtkStyle *style)
1712 {
1713   GdkGCValues gc_values;
1714   GdkGCValuesMask gc_values_mask;
1715   
1716   gint i;
1717
1718   for (i = 0; i < 5; i++)
1719     {
1720       gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
1721       gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
1722       
1723       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
1724       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
1725       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
1726
1727       style->text_aa[i].red = (style->text[i].red + style->base[i].red) / 2;
1728       style->text_aa[i].green = (style->text[i].green + style->base[i].green) / 2;
1729       style->text_aa[i].blue = (style->text[i].blue + style->base[i].blue) / 2;
1730     }
1731
1732   style->black.red = 0x0000;
1733   style->black.green = 0x0000;
1734   style->black.blue = 0x0000;
1735   gdk_colormap_alloc_color (style->colormap, &style->black, FALSE, TRUE);
1736
1737   style->white.red = 0xffff;
1738   style->white.green = 0xffff;
1739   style->white.blue = 0xffff;
1740   gdk_colormap_alloc_color (style->colormap, &style->white, FALSE, TRUE);
1741
1742   gc_values_mask = GDK_GC_FOREGROUND;
1743   
1744   gc_values.foreground = style->black;
1745   style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1746   
1747   gc_values.foreground = style->white;
1748   style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1749   
1750   for (i = 0; i < 5; i++)
1751     {
1752       if (style->rc_style && style->rc_style->bg_pixmap_name[i])
1753         style->bg_pixmap[i] = load_bg_image (style->colormap,
1754                                              &style->bg[i],
1755                                              style->rc_style->bg_pixmap_name[i]);
1756       
1757       if (!gdk_colormap_alloc_color (style->colormap, &style->fg[i], FALSE, TRUE))
1758         g_warning ("unable to allocate color: ( %d %d %d )",
1759                    style->fg[i].red, style->fg[i].green, style->fg[i].blue);
1760       if (!gdk_colormap_alloc_color (style->colormap, &style->bg[i], FALSE, TRUE))
1761         g_warning ("unable to allocate color: ( %d %d %d )",
1762                    style->bg[i].red, style->bg[i].green, style->bg[i].blue);
1763       if (!gdk_colormap_alloc_color (style->colormap, &style->light[i], FALSE, TRUE))
1764         g_warning ("unable to allocate color: ( %d %d %d )",
1765                    style->light[i].red, style->light[i].green, style->light[i].blue);
1766       if (!gdk_colormap_alloc_color (style->colormap, &style->dark[i], FALSE, TRUE))
1767         g_warning ("unable to allocate color: ( %d %d %d )",
1768                    style->dark[i].red, style->dark[i].green, style->dark[i].blue);
1769       if (!gdk_colormap_alloc_color (style->colormap, &style->mid[i], FALSE, TRUE))
1770         g_warning ("unable to allocate color: ( %d %d %d )",
1771                    style->mid[i].red, style->mid[i].green, style->mid[i].blue);
1772       if (!gdk_colormap_alloc_color (style->colormap, &style->text[i], FALSE, TRUE))
1773         g_warning ("unable to allocate color: ( %d %d %d )",
1774                    style->text[i].red, style->text[i].green, style->text[i].blue);
1775       if (!gdk_colormap_alloc_color (style->colormap, &style->base[i], FALSE, TRUE))
1776         g_warning ("unable to allocate color: ( %d %d %d )",
1777                    style->base[i].red, style->base[i].green, style->base[i].blue);
1778       if (!gdk_colormap_alloc_color (style->colormap, &style->text_aa[i], FALSE, TRUE))
1779         g_warning ("unable to allocate color: ( %d %d %d )",
1780                    style->text_aa[i].red, style->text_aa[i].green, style->text_aa[i].blue);
1781       
1782       gc_values.foreground = style->fg[i];
1783       style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1784       
1785       gc_values.foreground = style->bg[i];
1786       style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1787       
1788       gc_values.foreground = style->light[i];
1789       style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1790       
1791       gc_values.foreground = style->dark[i];
1792       style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1793       
1794       gc_values.foreground = style->mid[i];
1795       style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1796       
1797       gc_values.foreground = style->text[i];
1798       style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1799       
1800       gc_values.foreground = style->base[i];
1801       style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1802
1803       gc_values.foreground = style->text_aa[i];
1804       style->text_aa_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
1805     }
1806 }
1807
1808 static void
1809 gtk_style_real_unrealize (GtkStyle *style)
1810 {
1811   int i;
1812
1813   gtk_gc_release (style->black_gc);
1814   gtk_gc_release (style->white_gc);
1815       
1816   for (i = 0; i < 5; i++)
1817     {
1818       gtk_gc_release (style->fg_gc[i]);
1819       gtk_gc_release (style->bg_gc[i]);
1820       gtk_gc_release (style->light_gc[i]);
1821       gtk_gc_release (style->dark_gc[i]);
1822       gtk_gc_release (style->mid_gc[i]);
1823       gtk_gc_release (style->text_gc[i]);
1824       gtk_gc_release (style->base_gc[i]);
1825       gtk_gc_release (style->text_aa_gc[i]);
1826
1827       if (style->bg_pixmap[i] &&  style->bg_pixmap[i] != (GdkPixmap*) GDK_PARENT_RELATIVE)
1828         g_object_unref (style->bg_pixmap[i]);
1829     }
1830   
1831   gdk_colormap_free_colors (style->colormap, style->fg, 5);
1832   gdk_colormap_free_colors (style->colormap, style->bg, 5);
1833   gdk_colormap_free_colors (style->colormap, style->light, 5);
1834   gdk_colormap_free_colors (style->colormap, style->dark, 5);
1835   gdk_colormap_free_colors (style->colormap, style->mid, 5);
1836   gdk_colormap_free_colors (style->colormap, style->text, 5);
1837   gdk_colormap_free_colors (style->colormap, style->base, 5);
1838   gdk_colormap_free_colors (style->colormap, style->text_aa, 5);
1839
1840   style_unrealize_cursor_gcs (style);
1841 }
1842
1843 static void
1844 gtk_style_real_set_background (GtkStyle    *style,
1845                                GdkWindow   *window,
1846                                GtkStateType state_type)
1847 {
1848   GdkPixmap *pixmap;
1849   gint parent_relative;
1850   
1851   if (style->bg_pixmap[state_type])
1852     {
1853       if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1854         {
1855           pixmap = NULL;
1856           parent_relative = TRUE;
1857         }
1858       else
1859         {
1860           pixmap = style->bg_pixmap[state_type];
1861           parent_relative = FALSE;
1862         }
1863       
1864       gdk_window_set_back_pixmap (window, pixmap, parent_relative);
1865     }
1866   else
1867     gdk_window_set_background (window, &style->bg[state_type]);
1868 }
1869
1870 /**
1871  * gtk_style_render_icon:
1872  * @style: a #GtkStyle
1873  * @source: the #GtkIconSource specifying the icon to render
1874  * @direction: a text direction
1875  * @state: a state
1876  * @size: the size to render the icon at. A size of (GtkIconSize)-1
1877  *        means render at the size of the source and don't scale.
1878  * @widget: the widget 
1879  * @detail: a style detail
1880  * @returns: a newly-created #GdkPixbuf containing the rendered icon
1881  *
1882  * Renders the icon specified by @source at the given @size 
1883  * according to the given parameters and returns the result in a 
1884  * pixbuf.
1885  */
1886 GdkPixbuf *
1887 gtk_style_render_icon (GtkStyle            *style,
1888                        const GtkIconSource *source,
1889                        GtkTextDirection     direction,
1890                        GtkStateType         state,
1891                        GtkIconSize          size,
1892                        GtkWidget           *widget,
1893                        const gchar         *detail)
1894 {
1895   GdkPixbuf *pixbuf;
1896   
1897   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
1898   g_return_val_if_fail (GTK_STYLE_GET_CLASS (style)->render_icon != NULL, NULL);
1899   
1900   pixbuf = GTK_STYLE_GET_CLASS (style)->render_icon (style, source, direction, state,
1901                                                      size, widget, detail);
1902
1903   g_return_val_if_fail (pixbuf != NULL, NULL);
1904
1905   return pixbuf;
1906 }
1907
1908 /* Default functions */
1909 void
1910 gtk_style_apply_default_background (GtkStyle     *style,
1911                                     GdkWindow    *window,
1912                                     gboolean      set_bg,
1913                                     GtkStateType  state_type, 
1914                                     GdkRectangle *area, 
1915                                     gint          x, 
1916                                     gint          y, 
1917                                     gint          width, 
1918                                     gint          height)
1919 {
1920   GdkRectangle new_rect, old_rect;
1921   
1922   if (area)
1923     {
1924       old_rect.x = x;
1925       old_rect.y = y;
1926       old_rect.width = width;
1927       old_rect.height = height;
1928       
1929       if (!gdk_rectangle_intersect (area, &old_rect, &new_rect))
1930         return;
1931     }
1932   else
1933     {
1934       new_rect.x = x;
1935       new_rect.y = y;
1936       new_rect.width = width;
1937       new_rect.height = height;
1938     }
1939   
1940   if (!style->bg_pixmap[state_type] ||
1941       GDK_IS_PIXMAP (window) ||
1942       (!set_bg && style->bg_pixmap[state_type] != (GdkPixmap*) GDK_PARENT_RELATIVE))
1943     {
1944       GdkGC *gc = style->bg_gc[state_type];
1945       
1946       if (style->bg_pixmap[state_type])
1947         {
1948           gdk_gc_set_fill (gc, GDK_TILED);
1949           gdk_gc_set_tile (gc, style->bg_pixmap[state_type]);
1950         }
1951       
1952       gdk_draw_rectangle (window, gc, TRUE, 
1953                           new_rect.x, new_rect.y, new_rect.width, new_rect.height);
1954       if (style->bg_pixmap[state_type])
1955         gdk_gc_set_fill (gc, GDK_SOLID);
1956     }
1957   else
1958     {
1959       if (set_bg)
1960         {
1961           if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
1962             gdk_window_set_back_pixmap (window, NULL, TRUE);
1963           else
1964             gdk_window_set_back_pixmap (window, style->bg_pixmap[state_type], FALSE);
1965         }
1966       
1967       gdk_window_clear_area (window, 
1968                              new_rect.x, new_rect.y, 
1969                              new_rect.width, new_rect.height);
1970     }
1971 }
1972
1973 static GdkPixbuf*
1974 scale_or_ref (GdkPixbuf *src,
1975               gint width,
1976               gint height)
1977 {
1978   if (width == gdk_pixbuf_get_width (src) &&
1979       height == gdk_pixbuf_get_height (src))
1980     {
1981       return g_object_ref (src);
1982     }
1983   else
1984     {
1985       return gdk_pixbuf_scale_simple (src,
1986                                       width, height,
1987                                       GDK_INTERP_BILINEAR);
1988     }
1989 }
1990
1991 static GdkPixbuf *
1992 gtk_default_render_icon (GtkStyle            *style,
1993                          const GtkIconSource *source,
1994                          GtkTextDirection     direction,
1995                          GtkStateType         state,
1996                          GtkIconSize          size,
1997                          GtkWidget           *widget,
1998                          const gchar         *detail)
1999 {
2000   gint width = 1;
2001   gint height = 1;
2002   GdkPixbuf *scaled;
2003   GdkPixbuf *stated;
2004   GdkPixbuf *base_pixbuf;
2005   GdkScreen *screen;
2006   GtkSettings *settings;
2007
2008   /* Oddly, style can be NULL in this function, because
2009    * GtkIconSet can be used without a style and if so
2010    * it uses this function.
2011    */
2012
2013   base_pixbuf = gtk_icon_source_get_pixbuf (source);
2014
2015   g_return_val_if_fail (base_pixbuf != NULL, NULL);
2016
2017   if (widget && gtk_widget_has_screen (widget))
2018     {
2019       screen = gtk_widget_get_screen (widget);
2020       settings = gtk_settings_get_for_screen (screen);
2021     }
2022   else if (style->colormap)
2023     {
2024       screen = gdk_colormap_get_screen (style->colormap);
2025       settings = gtk_settings_get_for_screen (screen);
2026     }
2027   else
2028     {
2029       settings = gtk_settings_get_default ();
2030       GTK_NOTE (MULTIHEAD,
2031                 g_warning ("Using the default screen for gtk_default_render_icon()"));
2032     }
2033
2034   
2035   if (size != (GtkIconSize) -1 && !gtk_icon_size_lookup_for_settings (settings, size, &width, &height))
2036     {
2037       g_warning (G_STRLOC ": invalid icon size '%d'", size);
2038       return NULL;
2039     }
2040
2041   /* If the size was wildcarded, and we're allowed to scale, then scale; otherwise,
2042    * leave it alone.
2043    */
2044   if (size != (GtkIconSize)-1 && gtk_icon_source_get_size_wildcarded (source))
2045     scaled = scale_or_ref (base_pixbuf, width, height);
2046   else
2047     scaled = g_object_ref (base_pixbuf);
2048
2049   /* If the state was wildcarded, then generate a state. */
2050   if (gtk_icon_source_get_state_wildcarded (source))
2051     {
2052       if (state == GTK_STATE_INSENSITIVE)
2053         {
2054           stated = gdk_pixbuf_copy (scaled);      
2055           
2056           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
2057                                             0.8, TRUE);
2058           
2059           g_object_unref (scaled);
2060         }
2061       else if (state == GTK_STATE_PRELIGHT)
2062         {
2063           stated = gdk_pixbuf_copy (scaled);      
2064           
2065           gdk_pixbuf_saturate_and_pixelate (scaled, stated,
2066                                             1.2, FALSE);
2067           
2068           g_object_unref (scaled);
2069         }
2070       else
2071         {
2072           stated = scaled;
2073         }
2074     }
2075   else
2076     stated = scaled;
2077   
2078   return stated;
2079 }
2080
2081 static void
2082 sanitize_size (GdkWindow *window,
2083                gint      *width,
2084                gint      *height)
2085 {
2086   if ((*width == -1) && (*height == -1))
2087     gdk_drawable_get_size (window, width, height);
2088   else if (*width == -1)
2089     gdk_drawable_get_size (window, width, NULL);
2090   else if (*height == -1)
2091     gdk_drawable_get_size (window, NULL, height);
2092 }
2093
2094 static GdkBitmap * 
2095 get_indicator_for_screen (GdkDrawable   *drawable,
2096                           IndicatorPart  part)
2097                           
2098 {
2099   GdkScreen *screen = gdk_drawable_get_screen (drawable);
2100   GdkBitmap *bitmap;
2101   GList *tmp_list;
2102   
2103   tmp_list = indicator_parts[part].bmap_list;
2104   while (tmp_list)
2105     {
2106       bitmap = tmp_list->data;
2107       
2108       if (gdk_drawable_get_screen (bitmap) == screen)
2109         return bitmap;
2110       
2111       tmp_list = tmp_list->next;
2112     }
2113   
2114   bitmap = gdk_bitmap_create_from_data (drawable,
2115                                         (gchar *)indicator_parts[part].bits,
2116                                         INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
2117   indicator_parts[part].bmap_list = g_list_prepend (indicator_parts[part].bmap_list, bitmap);
2118
2119   return bitmap;
2120 }
2121
2122 static void
2123 draw_part (GdkDrawable  *drawable,
2124            GdkGC        *gc,
2125            GdkRectangle *area,
2126            gint          x,
2127            gint          y,
2128            IndicatorPart part)
2129 {
2130   if (area)
2131     gdk_gc_set_clip_rectangle (gc, area);
2132   
2133   gdk_gc_set_ts_origin (gc, x, y);
2134   gdk_gc_set_stipple (gc, get_indicator_for_screen (drawable, part));
2135   gdk_gc_set_fill (gc, GDK_STIPPLED);
2136
2137   gdk_draw_rectangle (drawable, gc, TRUE, x, y, INDICATOR_PART_SIZE, INDICATOR_PART_SIZE);
2138
2139   gdk_gc_set_fill (gc, GDK_SOLID);
2140
2141   if (area)
2142     gdk_gc_set_clip_rectangle (gc, NULL);
2143 }
2144
2145 static void
2146 gtk_default_draw_hline (GtkStyle     *style,
2147                         GdkWindow    *window,
2148                         GtkStateType  state_type,
2149                         GdkRectangle  *area,
2150                         GtkWidget     *widget,
2151                         const gchar   *detail,
2152                         gint          x1,
2153                         gint          x2,
2154                         gint          y)
2155 {
2156   gint thickness_light;
2157   gint thickness_dark;
2158   gint i;
2159   
2160   g_return_if_fail (GTK_IS_STYLE (style));
2161   g_return_if_fail (window != NULL);
2162   
2163   thickness_light = style->ythickness / 2;
2164   thickness_dark = style->ythickness - thickness_light;
2165   
2166   if (area)
2167     {
2168       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2169       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2170     }
2171   
2172   if (detail && !strcmp (detail, "label"))
2173     {
2174       if (state_type == GTK_STATE_INSENSITIVE)
2175         gdk_draw_line (window, style->white_gc, x1 + 1, y + 1, x2 + 1, y + 1);   
2176       gdk_draw_line (window, style->fg_gc[state_type], x1, y, x2, y);     
2177     }
2178   else
2179     {
2180       for (i = 0; i < thickness_dark; i++)
2181         {
2182           gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i);
2183           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i);
2184         }
2185       
2186       y += thickness_dark;
2187       for (i = 0; i < thickness_light; i++)
2188         {
2189           gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
2190           gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i);
2191         }
2192     }
2193   
2194   if (area)
2195     {
2196       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2197       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2198     }
2199 }
2200
2201
2202 static void
2203 gtk_default_draw_vline (GtkStyle     *style,
2204                         GdkWindow    *window,
2205                         GtkStateType  state_type,
2206                         GdkRectangle  *area,
2207                         GtkWidget     *widget,
2208                         const gchar   *detail,
2209                         gint          y1,
2210                         gint          y2,
2211                         gint          x)
2212 {
2213   gint thickness_light;
2214   gint thickness_dark;
2215   gint i;
2216   
2217   g_return_if_fail (GTK_IS_STYLE (style));
2218   g_return_if_fail (window != NULL);
2219   
2220   thickness_light = style->xthickness / 2;
2221   thickness_dark = style->xthickness - thickness_light;
2222   
2223   if (area)
2224     {
2225       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
2226       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
2227     }
2228   for (i = 0; i < thickness_dark; i++)
2229     {
2230       gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2);
2231       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1);
2232     }
2233   
2234   x += thickness_dark;
2235   for (i = 0; i < thickness_light; i++)
2236     {
2237       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i);
2238       gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2);
2239     }
2240   if (area)
2241     {
2242       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
2243       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
2244     }
2245 }
2246
2247
2248 static void
2249 draw_thin_shadow (GtkStyle      *style,
2250                   GdkWindow     *window,
2251                   GtkStateType   state,
2252                   GdkRectangle  *area,
2253                   gint           x,
2254                   gint           y,
2255                   gint           width,
2256                   gint           height)
2257 {
2258   GdkGC *gc1, *gc2;
2259
2260   sanitize_size (window, &width, &height);
2261   
2262   gc1 = style->light_gc[state];
2263   gc2 = style->dark_gc[state];
2264   
2265   if (area)
2266     {
2267       gdk_gc_set_clip_rectangle (gc1, area);
2268       gdk_gc_set_clip_rectangle (gc2, area);
2269     }
2270   
2271   gdk_draw_line (window, gc1,
2272                  x, y + height - 1, x + width - 1, y + height - 1);
2273   gdk_draw_line (window, gc1,
2274                  x + width - 1, y,  x + width - 1, y + height - 1);
2275       
2276   gdk_draw_line (window, gc2,
2277                  x, y, x + width - 2, y);
2278   gdk_draw_line (window, gc2,
2279                  x, y, x, y + height - 2);
2280
2281   if (area)
2282     {
2283       gdk_gc_set_clip_rectangle (gc1, NULL);
2284       gdk_gc_set_clip_rectangle (gc2, NULL);
2285     }
2286 }
2287
2288 #if 0
2289 /*
2290  * See http://bugzilla.gnome.org/show_bug.cgi?id=80229
2291  */
2292 static void
2293 draw_spin_entry_shadow (GtkStyle      *style,
2294                         GdkWindow     *window,
2295                         GtkStateType   state,
2296                         GdkRectangle  *area,
2297                         gint           x,
2298                         gint           y,
2299                         gint           width,
2300                         gint           height)
2301 {
2302   gint window_width, window_height;
2303   gboolean focus_inset;
2304
2305   gdk_drawable_get_size (window, &window_width, &window_height);
2306
2307   if (width == -1)
2308     width = window_width;
2309   if (height == 1)
2310     height = window_height;
2311
2312   focus_inset = (width < window_width && height < window_height);
2313   
2314   if (area)
2315     {
2316       gdk_gc_set_clip_rectangle (style->light_gc[state], area);
2317       gdk_gc_set_clip_rectangle (style->dark_gc[state], area);
2318       gdk_gc_set_clip_rectangle (style->black_gc, area);
2319       gdk_gc_set_clip_rectangle (style->bg_gc[state], area);
2320       gdk_gc_set_clip_rectangle (style->base_gc[state], area);
2321     }
2322
2323   gdk_draw_line (window, style->light_gc[state],
2324                  x, y + height - 1, x + width - 1, y + height - 1);
2325
2326   gdk_draw_line (window, 
2327                  style->base_gc[state],
2328                  x + width - 1,  y + 1, x + width - 1,  y + height - 3);
2329       
2330   if (!focus_inset)
2331     {
2332       gdk_draw_line (window, style->bg_gc[state],
2333                      x + 1, y + height - 2, x + width - 1, y + height - 2);
2334       gdk_draw_line (window, 
2335                      style->base_gc[state],
2336                      x + width - 2, y + 1, x + width - 2, y + height - 3);
2337   
2338       gdk_draw_line (window, style->black_gc,
2339                      x + 1, y + 1, x + width - 1, y + 1);
2340       gdk_draw_line (window, style->black_gc,
2341                      x + 1, y + 1, x + 1, y + height - 2);
2342     }
2343       
2344   gdk_draw_line (window, style->dark_gc[state],
2345                  x, y, x + width - 1, y);
2346   gdk_draw_line (window, style->dark_gc[state],
2347                  x, y, x, y + height - 1);
2348
2349   if (area)
2350     {
2351       gdk_gc_set_clip_rectangle (style->light_gc[state], NULL);
2352       gdk_gc_set_clip_rectangle (style->dark_gc[state], NULL);
2353       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2354       gdk_gc_set_clip_rectangle (style->bg_gc[state], NULL);
2355       gdk_gc_set_clip_rectangle (style->base_gc[state], NULL);
2356     }
2357 }
2358 #endif
2359
2360 static void
2361 draw_spinbutton_shadow (GtkStyle        *style,
2362                         GdkWindow       *window,
2363                         GtkStateType     state,
2364                         GtkTextDirection direction,
2365                         GdkRectangle    *area,
2366                         gint             x,
2367                         gint             y,
2368                         gint             width,
2369                         gint             height)
2370 {
2371   sanitize_size (window, &width, &height);
2372
2373   if (area)
2374     {
2375       gdk_gc_set_clip_rectangle (style->black_gc, area);
2376       gdk_gc_set_clip_rectangle (style->bg_gc[state], area);
2377       gdk_gc_set_clip_rectangle (style->dark_gc[state], area);
2378       gdk_gc_set_clip_rectangle (style->light_gc[state], area);
2379     }
2380
2381   if (direction == GTK_TEXT_DIR_LTR)
2382     {
2383       gdk_draw_line (window, style->dark_gc[state],
2384                      x, y, x + width - 1, y);
2385       gdk_draw_line (window, style->black_gc,
2386                      x, y + 1, x + width - 2, y + 1);
2387       gdk_draw_line (window, style->black_gc,
2388                      x + width - 2, y + 2, x + width - 2, y + height - 3);
2389       gdk_draw_line (window, style->light_gc[state],
2390                      x + width - 1, y + 1, x + width - 1, y + height - 2);
2391       gdk_draw_line (window, style->light_gc[state],
2392                      x, y + height - 1, x + width - 1, y + height - 1);
2393       gdk_draw_line (window, style->bg_gc[state],
2394                      x, y + height - 2, x + width - 2, y + height - 2);
2395       gdk_draw_line (window, style->black_gc,
2396                      x, y + 2, x, y + height - 3);
2397     }
2398   else
2399     {
2400       gdk_draw_line (window, style->dark_gc[state],
2401                      x, y, x + width - 1, y);
2402       gdk_draw_line (window, style->dark_gc[state],
2403                      x, y + 1, x, y + height - 1);
2404       gdk_draw_line (window, style->black_gc,
2405                      x + 1, y + 1, x + width - 1, y + 1);
2406       gdk_draw_line (window, style->black_gc,
2407                      x + 1, y + 2, x + 1, y + height - 2);
2408       gdk_draw_line (window, style->black_gc,
2409                      x + width - 1, y + 2, x + width - 1, y + height - 3);
2410       gdk_draw_line (window, style->light_gc[state],
2411                      x + 1, y + height - 1, x + width - 1, y + height - 1);
2412       gdk_draw_line (window, style->bg_gc[state],
2413                      x + 2, y + height - 2, x + width - 1, y + height - 2);
2414     }
2415   
2416   if (area)
2417     {
2418       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2419       gdk_gc_set_clip_rectangle (style->bg_gc[state], NULL);
2420       gdk_gc_set_clip_rectangle (style->dark_gc[state], NULL);
2421       gdk_gc_set_clip_rectangle (style->light_gc[state], NULL);
2422     }
2423 }
2424
2425 static void
2426 gtk_default_draw_shadow (GtkStyle      *style,
2427                          GdkWindow     *window,
2428                          GtkStateType   state_type,
2429                          GtkShadowType  shadow_type,
2430                          GdkRectangle  *area,
2431                          GtkWidget     *widget,
2432                          const gchar   *detail,
2433                          gint           x,
2434                          gint           y,
2435                          gint           width,
2436                          gint           height)
2437 {
2438   GdkGC *gc1 = NULL;
2439   GdkGC *gc2 = NULL;
2440   gint thickness_light;
2441   gint thickness_dark;
2442   gint i;
2443   
2444   g_return_if_fail (GTK_IS_STYLE (style));
2445   g_return_if_fail (window != NULL);
2446
2447   if (shadow_type == GTK_SHADOW_IN)
2448     {
2449       if (detail && (strcmp (detail, "buttondefault") == 0))
2450         {
2451           sanitize_size (window, &width, &height);
2452
2453           gdk_draw_rectangle (window, style->black_gc, FALSE,
2454                               x, y, width - 1, height - 1);
2455           
2456           return;
2457         }
2458       if (detail && strcmp (detail, "trough") == 0)
2459         {
2460           draw_thin_shadow (style, window, state_type, area,
2461                             x, y, width, height);
2462           return;
2463         }
2464       if (widget && GTK_IS_SPIN_BUTTON (widget) &&
2465          detail && strcmp (detail, "spinbutton") == 0)
2466         {
2467           draw_spinbutton_shadow (style, window, state_type,
2468                                   gtk_widget_get_direction (widget), area, x, y, width, height);
2469           
2470           return;
2471         }
2472     }
2473   
2474   sanitize_size (window, &width, &height);
2475   
2476   switch (shadow_type)
2477     {
2478     case GTK_SHADOW_NONE:
2479       return;
2480     case GTK_SHADOW_IN:
2481     case GTK_SHADOW_ETCHED_IN:
2482       gc1 = style->light_gc[state_type];
2483       gc2 = style->dark_gc[state_type];
2484       break;
2485     case GTK_SHADOW_OUT:
2486     case GTK_SHADOW_ETCHED_OUT:
2487       gc1 = style->dark_gc[state_type];
2488       gc2 = style->light_gc[state_type];
2489       break;
2490     }
2491   
2492   if (area)
2493     {
2494       gdk_gc_set_clip_rectangle (gc1, area);
2495       gdk_gc_set_clip_rectangle (gc2, area);
2496       if (shadow_type == GTK_SHADOW_IN || 
2497           shadow_type == GTK_SHADOW_OUT)
2498         {
2499           gdk_gc_set_clip_rectangle (style->black_gc, area);
2500           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
2501         }
2502     }
2503   
2504   switch (shadow_type)
2505     {
2506     case GTK_SHADOW_NONE:
2507       break;
2508       
2509     case GTK_SHADOW_IN:
2510       /* Light around right and bottom edge */
2511
2512       if (style->ythickness > 0)
2513         gdk_draw_line (window, gc1,
2514                        x, y + height - 1, x + width - 1, y + height - 1);
2515       if (style->xthickness > 0)
2516         gdk_draw_line (window, gc1,
2517                        x + width - 1, y, x + width - 1, y + height - 1);
2518
2519       if (style->ythickness > 1)
2520         gdk_draw_line (window, style->bg_gc[state_type],
2521                        x + 1, y + height - 2, x + width - 2, y + height - 2);
2522       if (style->xthickness > 1)
2523         gdk_draw_line (window, style->bg_gc[state_type],
2524                        x + width - 2, y + 1, x + width - 2, y + height - 2);
2525
2526       /* Dark around left and top */
2527
2528       if (style->ythickness > 1)
2529         gdk_draw_line (window, style->black_gc,
2530                        x + 1, y + 1, x + width - 2, y + 1);
2531       if (style->xthickness > 1)
2532         gdk_draw_line (window, style->black_gc,
2533                        x + 1, y + 1, x + 1, y + height - 2);
2534
2535       if (style->ythickness > 0)
2536         gdk_draw_line (window, gc2,
2537                        x, y, x + width - 1, y);
2538       if (style->xthickness > 0)
2539         gdk_draw_line (window, gc2,
2540                        x, y, x, y + height - 1);
2541       break;
2542       
2543     case GTK_SHADOW_OUT:
2544       /* Dark around right and bottom edge */
2545
2546       if (style->ythickness > 0)
2547         {
2548           if (style->ythickness > 1)
2549             {
2550               gdk_draw_line (window, gc1,
2551                              x + 1, y + height - 2, x + width - 2, y + height - 2);
2552               gdk_draw_line (window, style->black_gc,
2553                              x, y + height - 1, x + width - 1, y + height - 1);
2554             }
2555           else
2556             {
2557               gdk_draw_line (window, gc1,
2558                              x + 1, y + height - 1, x + width - 1, y + height - 1);
2559             }
2560         }
2561
2562       if (style->xthickness > 0)
2563         {
2564           if (style->xthickness > 1)
2565             {
2566               gdk_draw_line (window, gc1,
2567                              x + width - 2, y + 1, x + width - 2, y + height - 2);
2568               
2569               gdk_draw_line (window, style->black_gc,
2570                              x + width - 1, y, x + width - 1, y + height - 1);
2571             }
2572           else
2573             {
2574               gdk_draw_line (window, gc1,
2575                              x + width - 1, y + 1, x + width - 1, y + height - 1);
2576             }
2577         }
2578       
2579       /* Light around top and left */
2580
2581       if (style->ythickness > 0)
2582         gdk_draw_line (window, gc2,
2583                        x, y, x + width - 2, y);
2584       if (style->xthickness > 0)
2585         gdk_draw_line (window, gc2,
2586                        x, y, x, y + height - 2);
2587
2588       if (style->ythickness > 1)
2589         gdk_draw_line (window, style->bg_gc[state_type],
2590                        x + 1, y + 1, x + width - 3, y + 1);
2591       if (style->xthickness > 1)
2592         gdk_draw_line (window, style->bg_gc[state_type],
2593                        x + 1, y + 1, x + 1, y + height - 3);
2594       break;
2595       
2596     case GTK_SHADOW_ETCHED_IN:
2597     case GTK_SHADOW_ETCHED_OUT:
2598       if (style->xthickness > 0)
2599         {
2600           if (style->xthickness > 1)
2601             {
2602               thickness_light = 1;
2603               thickness_dark = 1;
2604       
2605               for (i = 0; i < thickness_dark; i++)
2606                 {
2607                   gdk_draw_line (window, gc1,
2608                                  x + width - i - 1,
2609                                  y + i,
2610                                  x + width - i - 1,
2611                                  y + height - i - 1);
2612                   gdk_draw_line (window, gc2,
2613                                  x + i,
2614                                  y + i,
2615                                  x + i,
2616                                  y + height - i - 2);
2617                 }
2618       
2619               for (i = 0; i < thickness_light; i++)
2620                 {
2621                   gdk_draw_line (window, gc1,
2622                                  x + thickness_dark + i,
2623                                  y + thickness_dark + i,
2624                                  x + thickness_dark + i,
2625                                  y + height - thickness_dark - i - 1);
2626                   gdk_draw_line (window, gc2,
2627                                  x + width - thickness_light - i - 1,
2628                                  y + thickness_dark + i,
2629                                  x + width - thickness_light - i - 1,
2630                                  y + height - thickness_light - 1);
2631                 }
2632             }
2633           else
2634             {
2635               gdk_draw_line (window, 
2636                              style->dark_gc[state_type],
2637                              x, y, x, y + height);                         
2638               gdk_draw_line (window, 
2639                              style->dark_gc[state_type],
2640                              x + width, y, x + width, y + height);
2641             }
2642         }
2643
2644       if (style->ythickness > 0)
2645         {
2646           if (style->ythickness > 1)
2647             {
2648               thickness_light = 1;
2649               thickness_dark = 1;
2650       
2651               for (i = 0; i < thickness_dark; i++)
2652                 {
2653                   gdk_draw_line (window, gc1,
2654                                  x + i,
2655                                  y + height - i - 1,
2656                                  x + width - i - 1,
2657                                  y + height - i - 1);
2658           
2659                   gdk_draw_line (window, gc2,
2660                                  x + i,
2661                                  y + i,
2662                                  x + width - i - 2,
2663                                  y + i);
2664                 }
2665       
2666               for (i = 0; i < thickness_light; i++)
2667                 {
2668                   gdk_draw_line (window, gc1,
2669                                  x + thickness_dark + i,
2670                                  y + thickness_dark + i,
2671                                  x + width - thickness_dark - i - 2,
2672                                  y + thickness_dark + i);
2673           
2674                   gdk_draw_line (window, gc2,
2675                                  x + thickness_dark + i,
2676                                  y + height - thickness_light - i - 1,
2677                                  x + width - thickness_light - 1,
2678                                  y + height - thickness_light - i - 1);
2679                 }
2680             }
2681           else
2682             {
2683               gdk_draw_line (window, 
2684                              style->dark_gc[state_type],
2685                              x, y, x + width, y);
2686               gdk_draw_line (window, 
2687                              style->dark_gc[state_type],
2688                              x, y + height, x + width, y + height);
2689             }
2690         }
2691       
2692       break;
2693     }
2694
2695   if (shadow_type == GTK_SHADOW_IN &&
2696       widget && GTK_IS_SPIN_BUTTON (widget) &&
2697       detail && strcmp (detail, "entry") == 0)
2698     {
2699       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
2700         {
2701           gdk_draw_line (window,
2702                          style->base_gc[state_type],
2703                          x + width - 1, y + 2,
2704                          x + width - 1, y + height - 3);
2705           gdk_draw_line (window,
2706                          style->base_gc[state_type],
2707                          x + width - 2, y + 2,
2708                          x + width - 2, y + height - 3);
2709           gdk_draw_point (window,
2710                           style->black_gc,
2711                           x + width - 1, y + 1);
2712           gdk_draw_point (window,
2713                           style->bg_gc[state_type],
2714                           x + width - 1, y + height - 2);
2715         }
2716       else
2717         {
2718           gdk_draw_line (window,
2719                          style->base_gc[state_type],
2720                          x, y + 2,
2721                          x, y + height - 3);
2722           gdk_draw_line (window,
2723                          style->base_gc[state_type],
2724                          x + 1, y + 2,
2725                          x + 1, y + height - 3);
2726           gdk_draw_point (window,
2727                           style->black_gc,
2728                           x, y + 1);
2729           gdk_draw_line (window,
2730                          style->bg_gc[state_type],
2731                          x, y + height - 2,
2732                          x + 1, y + height - 2);
2733           gdk_draw_point (window,
2734                           style->light_gc[state_type],
2735                           x, y + height - 1);
2736         }
2737     }
2738
2739
2740   if (area)
2741     {
2742       gdk_gc_set_clip_rectangle (gc1, NULL);
2743       gdk_gc_set_clip_rectangle (gc2, NULL);
2744       if (shadow_type == GTK_SHADOW_IN || 
2745           shadow_type == GTK_SHADOW_OUT)
2746         {
2747           gdk_gc_set_clip_rectangle (style->black_gc, NULL);
2748           gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
2749         }
2750     }
2751 }
2752
2753 static void
2754 gtk_default_draw_polygon (GtkStyle      *style,
2755                           GdkWindow     *window,
2756                           GtkStateType   state_type,
2757                           GtkShadowType  shadow_type,
2758                           GdkRectangle  *area,
2759                           GtkWidget     *widget,
2760                           const gchar   *detail,
2761                           GdkPoint      *points,
2762                           gint           npoints,
2763                           gboolean       fill)
2764 {
2765   static const gdouble pi_over_4 = G_PI_4;
2766   static const gdouble pi_3_over_4 = G_PI_4 * 3;
2767   GdkGC *gc1;
2768   GdkGC *gc2;
2769   GdkGC *gc3;
2770   GdkGC *gc4;
2771   gdouble angle;
2772   gint xadjust;
2773   gint yadjust;
2774   gint i;
2775   
2776   g_return_if_fail (GTK_IS_STYLE (style));
2777   g_return_if_fail (window != NULL);
2778   g_return_if_fail (points != NULL);
2779   
2780   switch (shadow_type)
2781     {
2782     case GTK_SHADOW_IN:
2783       gc1 = style->bg_gc[state_type];
2784       gc2 = style->dark_gc[state_type];
2785       gc3 = style->light_gc[state_type];
2786       gc4 = style->black_gc;
2787       break;
2788     case GTK_SHADOW_ETCHED_IN:
2789       gc1 = style->light_gc[state_type];
2790       gc2 = style->dark_gc[state_type];
2791       gc3 = style->dark_gc[state_type];
2792       gc4 = style->light_gc[state_type];
2793       break;
2794     case GTK_SHADOW_OUT:
2795       gc1 = style->dark_gc[state_type];
2796       gc2 = style->light_gc[state_type];
2797       gc3 = style->black_gc;
2798       gc4 = style->bg_gc[state_type];
2799       break;
2800     case GTK_SHADOW_ETCHED_OUT:
2801       gc1 = style->dark_gc[state_type];
2802       gc2 = style->light_gc[state_type];
2803       gc3 = style->light_gc[state_type];
2804       gc4 = style->dark_gc[state_type];
2805       break;
2806     default:
2807       return;
2808     }
2809   
2810   if (area)
2811     {
2812       gdk_gc_set_clip_rectangle (gc1, area);
2813       gdk_gc_set_clip_rectangle (gc2, area);
2814       gdk_gc_set_clip_rectangle (gc3, area);
2815       gdk_gc_set_clip_rectangle (gc4, area);
2816     }
2817   
2818   if (fill)
2819     gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints);
2820   
2821   npoints--;
2822   
2823   for (i = 0; i < npoints; i++)
2824     {
2825       if ((points[i].x == points[i+1].x) &&
2826           (points[i].y == points[i+1].y))
2827         {
2828           angle = 0;
2829         }
2830       else
2831         {
2832           angle = atan2 (points[i+1].y - points[i].y,
2833                          points[i+1].x - points[i].x);
2834         }
2835       
2836       if ((angle > -pi_3_over_4) && (angle < pi_over_4))
2837         {
2838           if (angle > -pi_over_4)
2839             {
2840               xadjust = 0;
2841               yadjust = 1;
2842             }
2843           else
2844             {
2845               xadjust = 1;
2846               yadjust = 0;
2847             }
2848           
2849           gdk_draw_line (window, gc1,
2850                          points[i].x-xadjust, points[i].y-yadjust,
2851                          points[i+1].x-xadjust, points[i+1].y-yadjust);
2852           gdk_draw_line (window, gc3,
2853                          points[i].x, points[i].y,
2854                          points[i+1].x, points[i+1].y);
2855         }
2856       else
2857         {
2858           if ((angle < -pi_3_over_4) || (angle > pi_3_over_4))
2859             {
2860               xadjust = 0;
2861               yadjust = 1;
2862             }
2863           else
2864             {
2865               xadjust = 1;
2866               yadjust = 0;
2867             }
2868           
2869           gdk_draw_line (window, gc4,
2870                          points[i].x+xadjust, points[i].y+yadjust,
2871                          points[i+1].x+xadjust, points[i+1].y+yadjust);
2872           gdk_draw_line (window, gc2,
2873                          points[i].x, points[i].y,
2874                          points[i+1].x, points[i+1].y);
2875         }
2876     }
2877
2878   if (area)
2879     {
2880       gdk_gc_set_clip_rectangle (gc1, NULL);
2881       gdk_gc_set_clip_rectangle (gc2, NULL);
2882       gdk_gc_set_clip_rectangle (gc3, NULL);
2883       gdk_gc_set_clip_rectangle (gc4, NULL);
2884     }
2885 }
2886
2887 static void
2888 draw_arrow (GdkWindow     *window,
2889             GdkGC         *gc,
2890             GdkRectangle  *area,
2891             GtkArrowType   arrow_type,
2892             gint           x,
2893             gint           y,
2894             gint           width,
2895             gint           height)
2896 {
2897   gint i, j;
2898
2899   if (area)
2900     gdk_gc_set_clip_rectangle (gc, area);
2901
2902   if (arrow_type == GTK_ARROW_DOWN)
2903     {
2904       for (i = 0, j = 0; i < height; i++, j++)
2905         gdk_draw_line (window, gc, x + j, y + i, x + width - j - 1, y + i);
2906     }
2907   else if (arrow_type == GTK_ARROW_UP)
2908     {
2909       for (i = height - 1, j = 0; i >= 0; i--, j++)
2910         gdk_draw_line (window, gc, x + j, y + i, x + width - j - 1, y + i);
2911     }
2912   else if (arrow_type == GTK_ARROW_LEFT)
2913     {
2914       for (i = width - 1, j = 0; i >= 0; i--, j++)
2915         gdk_draw_line (window, gc, x + i, y + j, x + i, y + height - j - 1);
2916     }
2917   else if (arrow_type == GTK_ARROW_RIGHT)
2918     {
2919       for (i = 0, j = 0; i < width; i++, j++)
2920         gdk_draw_line (window, gc, x + i, y + j, x + i, y + height - j - 1);
2921     }
2922
2923   if (area)
2924     gdk_gc_set_clip_rectangle (gc, NULL);
2925 }
2926
2927 static void
2928 calculate_arrow_geometry (GtkArrowType  arrow_type,
2929                           gint         *x,
2930                           gint         *y,
2931                           gint         *width,
2932                           gint         *height)
2933 {
2934   gint w = *width;
2935   gint h = *height;
2936   
2937   switch (arrow_type)
2938     {
2939     case GTK_ARROW_UP:
2940     case GTK_ARROW_DOWN:
2941       w += (w % 2) - 1;
2942       h = (w / 2 + 1);
2943       
2944       if (h > *height)
2945         {
2946           h = *height;
2947           w = 2 * h - 1;
2948         }
2949       
2950       if (arrow_type == GTK_ARROW_DOWN)
2951         {
2952           if (*height % 2 == 1 || h % 2 == 0)
2953             *height += 1;
2954         }
2955       else
2956         {
2957           if (*height % 2 == 0 || h % 2 == 0)
2958             *height -= 1;
2959         }
2960       break;
2961
2962     case GTK_ARROW_RIGHT:
2963     case GTK_ARROW_LEFT:
2964       h += (h % 2) - 1;
2965       w = (h / 2 + 1);
2966       
2967       if (w > *width)
2968         {
2969           w = *width;
2970           h = 2 * w - 1;
2971         }
2972       
2973       if (arrow_type == GTK_ARROW_RIGHT)
2974         {
2975           if (*width % 2 == 1 || w % 2 == 0)
2976             *width += 1;
2977         }
2978       else
2979         {
2980           if (*width % 2 == 0 || w % 2 == 0)
2981             *width -= 1;
2982         }
2983       break;
2984       
2985     default:
2986       /* should not be reached */
2987       break;
2988     }
2989
2990   *x += (*width - w) / 2;
2991   *y += (*height - h) / 2;
2992   *height = h;
2993   *width = w;
2994 }
2995
2996 static void
2997 gtk_default_draw_arrow (GtkStyle      *style,
2998                         GdkWindow     *window,
2999                         GtkStateType   state,
3000                         GtkShadowType  shadow,
3001                         GdkRectangle  *area,
3002                         GtkWidget     *widget,
3003                         const gchar   *detail,
3004                         GtkArrowType   arrow_type,
3005                         gboolean       fill,
3006                         gint           x,
3007                         gint           y,
3008                         gint           width,
3009                         gint           height)
3010 {
3011   gint original_width, original_x;
3012   
3013   sanitize_size (window, &width, &height);
3014
3015   original_width = width;
3016   original_x = x;
3017
3018   calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
3019
3020   if (detail && strcmp (detail, "menuitem") == 0
3021       && gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
3022     x = original_x + original_width - width;
3023
3024   if (state == GTK_STATE_INSENSITIVE)
3025     draw_arrow (window, style->white_gc, area, arrow_type,
3026                 x + 1, y + 1, width, height);
3027   draw_arrow (window, style->fg_gc[state], area, arrow_type,
3028               x, y, width, height);
3029 }
3030
3031 static void
3032 gtk_default_draw_diamond (GtkStyle      *style,
3033                           GdkWindow     *window,
3034                           GtkStateType   state_type,
3035                           GtkShadowType  shadow_type,
3036                           GdkRectangle  *area,
3037                           GtkWidget     *widget,
3038                           const gchar   *detail,
3039                           gint           x,
3040                           gint           y,
3041                           gint           width,
3042                           gint           height)
3043 {
3044   gint half_width;
3045   gint half_height;
3046   GdkGC *outer_nw = NULL;
3047   GdkGC *outer_ne = NULL;
3048   GdkGC *outer_sw = NULL;
3049   GdkGC *outer_se = NULL;
3050   GdkGC *middle_nw = NULL;
3051   GdkGC *middle_ne = NULL;
3052   GdkGC *middle_sw = NULL;
3053   GdkGC *middle_se = NULL;
3054   GdkGC *inner_nw = NULL;
3055   GdkGC *inner_ne = NULL;
3056   GdkGC *inner_sw = NULL;
3057   GdkGC *inner_se = NULL;
3058   
3059   g_return_if_fail (GTK_IS_STYLE (style));
3060   g_return_if_fail (window != NULL);
3061   
3062   sanitize_size (window, &width, &height);
3063   
3064   half_width = width / 2;
3065   half_height = height / 2;
3066   
3067   if (area)
3068     {
3069       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3070       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
3071       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3072       gdk_gc_set_clip_rectangle (style->black_gc, area);
3073     }
3074   
3075   switch (shadow_type)
3076     {
3077     case GTK_SHADOW_IN:
3078       inner_sw = inner_se = style->bg_gc[state_type];
3079       middle_sw = middle_se = style->light_gc[state_type];
3080       outer_sw = outer_se = style->light_gc[state_type];
3081       inner_nw = inner_ne = style->black_gc;
3082       middle_nw = middle_ne = style->dark_gc[state_type];
3083       outer_nw = outer_ne = style->dark_gc[state_type];
3084       break;
3085           
3086     case GTK_SHADOW_OUT:
3087       inner_sw = inner_se = style->dark_gc[state_type];
3088       middle_sw = middle_se = style->dark_gc[state_type];
3089       outer_sw = outer_se = style->black_gc;
3090       inner_nw = inner_ne = style->bg_gc[state_type];
3091       middle_nw = middle_ne = style->light_gc[state_type];
3092       outer_nw = outer_ne = style->light_gc[state_type];
3093       break;
3094
3095     case GTK_SHADOW_ETCHED_IN:
3096       inner_sw = inner_se = style->bg_gc[state_type];
3097       middle_sw = middle_se = style->dark_gc[state_type];
3098       outer_sw = outer_se = style->light_gc[state_type];
3099       inner_nw = inner_ne = style->bg_gc[state_type];
3100       middle_nw = middle_ne = style->light_gc[state_type];
3101       outer_nw = outer_ne = style->dark_gc[state_type];
3102       break;
3103
3104     case GTK_SHADOW_ETCHED_OUT:
3105       inner_sw = inner_se = style->bg_gc[state_type];
3106       middle_sw = middle_se = style->light_gc[state_type];
3107       outer_sw = outer_se = style->dark_gc[state_type];
3108       inner_nw = inner_ne = style->bg_gc[state_type];
3109       middle_nw = middle_ne = style->dark_gc[state_type];
3110       outer_nw = outer_ne = style->light_gc[state_type];
3111       break;
3112       
3113     default:
3114
3115       break;
3116     }
3117
3118   if (inner_sw)
3119     {
3120       gdk_draw_line (window, inner_sw,
3121                      x + 2, y + half_height,
3122                      x + half_width, y + height - 2);
3123       gdk_draw_line (window, inner_se,
3124                      x + half_width, y + height - 2,
3125                      x + width - 2, y + half_height);
3126       gdk_draw_line (window, middle_sw,
3127                      x + 1, y + half_height,
3128                      x + half_width, y + height - 1);
3129       gdk_draw_line (window, middle_se,
3130                      x + half_width, y + height - 1,
3131                      x + width - 1, y + half_height);
3132       gdk_draw_line (window, outer_sw,
3133                      x, y + half_height,
3134                      x + half_width, y + height);
3135       gdk_draw_line (window, outer_se,
3136                      x + half_width, y + height,
3137                      x + width, y + half_height);
3138   
3139       gdk_draw_line (window, inner_nw,
3140                      x + 2, y + half_height,
3141                      x + half_width, y + 2);
3142       gdk_draw_line (window, inner_ne,
3143                      x + half_width, y + 2,
3144                      x + width - 2, y + half_height);
3145       gdk_draw_line (window, middle_nw,
3146                      x + 1, y + half_height,
3147                      x + half_width, y + 1);
3148       gdk_draw_line (window, middle_ne,
3149                      x + half_width, y + 1,
3150                      x + width - 1, y + half_height);
3151       gdk_draw_line (window, outer_nw,
3152                      x, y + half_height,
3153                      x + half_width, y);
3154       gdk_draw_line (window, outer_ne,
3155                      x + half_width, y,
3156                      x + width, y + half_height);
3157     }
3158   
3159   if (area)
3160     {
3161       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3162       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
3163       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3164       gdk_gc_set_clip_rectangle (style->black_gc, NULL);
3165     }
3166 }
3167
3168 static void
3169 gtk_default_draw_string (GtkStyle      *style,
3170                          GdkWindow     *window,
3171                          GtkStateType   state_type,
3172                          GdkRectangle  *area,
3173                          GtkWidget     *widget,
3174                          const gchar   *detail,
3175                          gint           x,
3176                          gint           y,
3177                          const gchar   *string)
3178 {
3179   GdkDisplay *display;
3180   
3181   g_return_if_fail (GTK_IS_STYLE (style));
3182   g_return_if_fail (window != NULL);
3183   
3184   display = gdk_drawable_get_display (window);
3185   
3186   if (area)
3187     {
3188       gdk_gc_set_clip_rectangle (style->white_gc, area);
3189       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], area);
3190     }
3191
3192   if (state_type == GTK_STATE_INSENSITIVE)
3193     gdk_draw_string (window,
3194                      gtk_style_get_font_internal (style),
3195                      style->white_gc, x + 1, y + 1, string);
3196
3197   gdk_draw_string (window,
3198                    gtk_style_get_font_internal (style),
3199                    style->fg_gc[state_type], x, y, string);
3200
3201   if (area)
3202     {
3203       gdk_gc_set_clip_rectangle (style->white_gc, NULL);
3204       gdk_gc_set_clip_rectangle (style->fg_gc[state_type], NULL);
3205     }
3206 }
3207
3208 static void
3209 option_menu_get_props (GtkWidget      *widget,
3210                        GtkRequisition *indicator_size,
3211                        GtkBorder      *indicator_spacing)
3212 {
3213   GtkRequisition *tmp_size = NULL;
3214   GtkBorder *tmp_spacing = NULL;
3215   
3216   if (widget)
3217     gtk_widget_style_get (widget, 
3218                           "indicator_size", &tmp_size,
3219                           "indicator_spacing", &tmp_spacing,
3220                           NULL);
3221
3222   if (tmp_size)
3223     {
3224       *indicator_size = *tmp_size;
3225       g_free (tmp_size);
3226     }
3227   else
3228     *indicator_size = default_option_indicator_size;
3229
3230   if (tmp_spacing)
3231     {
3232       *indicator_spacing = *tmp_spacing;
3233       g_free (tmp_spacing);
3234     }
3235   else
3236     *indicator_spacing = default_option_indicator_spacing;
3237 }
3238
3239 static void 
3240 gtk_default_draw_box (GtkStyle      *style,
3241                       GdkWindow     *window,
3242                       GtkStateType   state_type,
3243                       GtkShadowType  shadow_type,
3244                       GdkRectangle  *area,
3245                       GtkWidget     *widget,
3246                       const gchar   *detail,
3247                       gint           x,
3248                       gint           y,
3249                       gint           width,
3250                       gint           height)
3251 {
3252   gboolean is_spinbutton_box = FALSE;
3253   
3254   g_return_if_fail (GTK_IS_STYLE (style));
3255   g_return_if_fail (window != NULL);
3256   
3257   sanitize_size (window, &width, &height);
3258
3259   if (widget && GTK_IS_SPIN_BUTTON (widget) && detail)
3260     {
3261       if (strcmp (detail, "spinbutton_up") == 0)
3262         {
3263           y += 2;
3264           width -= 3;
3265           height -= 2;
3266
3267           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3268             x += 2;
3269           else
3270             x += 1;
3271
3272           is_spinbutton_box = TRUE;
3273         }
3274       else if (strcmp (detail, "spinbutton_down") == 0)
3275         {
3276           width -= 3;
3277           height -= 2;
3278
3279           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3280             x += 2;
3281           else
3282             x += 1;
3283
3284           is_spinbutton_box = TRUE;
3285         }
3286     }
3287   
3288   if (!style->bg_pixmap[state_type] || 
3289       GDK_IS_PIXMAP (window))
3290     {
3291       if (area)
3292         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
3293
3294       gdk_draw_rectangle (window, style->bg_gc[state_type], TRUE,
3295                           x, y, width, height);
3296       if (area)
3297         gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
3298     }
3299   else
3300     gtk_style_apply_default_background (style, window,
3301                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3302                                         state_type, area, x, y, width, height);
3303
3304   if (is_spinbutton_box)
3305     {
3306       GdkGC *upper_gc;
3307       GdkGC *lower_gc;
3308       
3309       lower_gc = style->dark_gc[state_type];
3310       if (shadow_type == GTK_SHADOW_OUT)
3311         upper_gc = style->light_gc[state_type];
3312       else
3313         upper_gc = style->dark_gc[state_type];
3314
3315       if (area)
3316         {
3317           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
3318           gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
3319         }
3320       
3321       gdk_draw_line (window, upper_gc, x, y, x + width - 1, y);
3322       gdk_draw_line (window, lower_gc, x, y + height - 1, x + width - 1, y + height - 1);
3323
3324       if (area)
3325         {
3326           gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
3327           gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
3328         }
3329       return;
3330     }
3331
3332   gtk_paint_shadow (style, window, state_type, shadow_type, area, widget, detail,
3333                     x, y, width, height);
3334
3335   if (detail && strcmp (detail, "optionmenu") == 0)
3336     {
3337       GtkRequisition indicator_size;
3338       GtkBorder indicator_spacing;
3339       gint vline_x;
3340
3341       option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3342
3343       sanitize_size (window, &width, &height);
3344
3345       if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
3346         vline_x = x + indicator_size.width + indicator_spacing.left + indicator_spacing.right;
3347       else 
3348         vline_x = x + width - (indicator_size.width + indicator_spacing.left + indicator_spacing.right) - style->xthickness;
3349
3350       gtk_paint_vline (style, window, state_type, area, widget,
3351                        detail,
3352                        y + style->ythickness + 1,
3353                        y + height - style->ythickness - 3,
3354                        vline_x);
3355     }
3356 }
3357
3358 static GdkGC*
3359 get_darkened_gc (GdkWindow *window,
3360                  GdkColor  *color,
3361                  gint       darken_count)
3362 {
3363   GdkColor src = *color;
3364   GdkColor shaded = *color;
3365   GdkGC *gc;
3366   
3367   gc = gdk_gc_new (window);
3368
3369   while (darken_count)
3370     {
3371       gtk_style_shade (&src, &shaded, 0.93);
3372       src = shaded;
3373       --darken_count;
3374     }
3375    
3376   gdk_gc_set_rgb_fg_color (gc, &shaded);
3377
3378   return gc;
3379 }
3380
3381 static void 
3382 gtk_default_draw_flat_box (GtkStyle      *style,
3383                            GdkWindow     *window,
3384                            GtkStateType   state_type,
3385                            GtkShadowType  shadow_type,
3386                            GdkRectangle  *area,
3387                            GtkWidget     *widget,
3388                            const gchar   *detail,
3389                            gint           x,
3390                            gint           y,
3391                            gint           width,
3392                            gint           height)
3393 {
3394   GdkGC *gc1;
3395   GdkGC *freeme = NULL;
3396   
3397   g_return_if_fail (GTK_IS_STYLE (style));
3398   g_return_if_fail (window != NULL);
3399   
3400   sanitize_size (window, &width, &height);
3401   
3402   if (detail)
3403     {
3404       if (state_type == GTK_STATE_SELECTED)
3405         {
3406           if (!strcmp ("text", detail))
3407             gc1 = style->bg_gc[GTK_STATE_SELECTED];
3408           else if (!strncmp ("cell_even", detail, strlen ("cell_even")) ||
3409                    !strncmp ("cell_odd", detail, strlen ("cell_odd")))
3410             {
3411               /* This has to be really broken; alex made me do it. -jrb */
3412               if (GTK_WIDGET_HAS_FOCUS (widget))
3413                 gc1 = style->base_gc[state_type];
3414               else 
3415                 gc1 = style->base_gc[GTK_STATE_ACTIVE];
3416             }
3417           else
3418             {
3419               gc1 = style->bg_gc[state_type];
3420             }
3421         }
3422       else
3423         {
3424           if (!strcmp ("viewportbin", detail))
3425             gc1 = style->bg_gc[GTK_STATE_NORMAL];
3426           else if (!strcmp ("entry_bg", detail))
3427             gc1 = style->base_gc[state_type];
3428
3429           /* For trees: even rows are base color, odd rows are a shade of
3430            * the base color, the sort column is a shade of the original color
3431            * for that row.
3432            */
3433
3434           else if (!strcmp ("cell_even", detail) ||
3435                    !strcmp ("cell_odd", detail) ||
3436                    !strcmp ("cell_even_ruled", detail))
3437             {
3438               GdkColor *color = NULL;
3439
3440               gtk_widget_style_get (widget,
3441                                     "even_row_color", &color,
3442                                     NULL);
3443
3444               if (color)
3445                 {
3446                   freeme = get_darkened_gc (window, color, 0);
3447                   gc1 = freeme;
3448
3449                   gdk_color_free (color);
3450                 }
3451               else
3452                 gc1 = style->base_gc[state_type];
3453             }
3454           else if (!strcmp ("cell_odd_ruled", detail))
3455             {
3456               GdkColor *color;
3457
3458               gtk_widget_style_get (widget,
3459                                     "odd_row_color", &color,
3460                                     NULL);
3461
3462               if (color)
3463                 {
3464                   freeme = get_darkened_gc (window, color, 0);
3465                   gc1 = freeme;
3466
3467                   gdk_color_free (color);
3468                 }
3469               else
3470                 {
3471                   gtk_widget_style_get (widget,
3472                                         "even_row_color", &color,
3473                                         NULL);
3474
3475                   if (color)
3476                     {
3477                       freeme = get_darkened_gc (window, color, 1);
3478                       gdk_color_free (color);
3479                     }
3480                   else
3481                     freeme = get_darkened_gc (window, &style->base[state_type], 1);
3482                   gc1 = freeme;
3483                 }
3484             }
3485           else if (!strcmp ("cell_even_sorted", detail) ||
3486                    !strcmp ("cell_odd_sorted", detail) ||
3487                    !strcmp ("cell_even_ruled_sorted", detail))
3488             {
3489               GdkColor *color = NULL;
3490
3491               if (!strcmp ("cell_odd_sorted", detail))
3492                 gtk_widget_style_get (widget,
3493                                       "odd_row_color", &color,
3494                                       NULL);
3495               else
3496                 gtk_widget_style_get (widget,
3497                                       "even_row_color", &color,
3498                                       NULL);
3499
3500               if (color)
3501                 {
3502                   freeme = get_darkened_gc (window, color, 1);
3503                   gc1 = freeme;
3504
3505                   gdk_color_free (color);
3506                 }
3507               else
3508                 {
3509                   freeme = get_darkened_gc (window, &style->base[state_type], 1);
3510                   gc1 = freeme;
3511                 }
3512             }
3513           else if (!strcmp ("cell_odd_ruled_sorted", detail))
3514             {
3515               GdkColor *color = NULL;
3516
3517               gtk_widget_style_get (widget,
3518                                     "odd_row_color", &color,
3519                                     NULL);
3520
3521               if (color)
3522                 {
3523                   freeme = get_darkened_gc (window, color, 1);
3524                   gc1 = freeme;
3525
3526                   gdk_color_free (color);
3527                 }
3528               else
3529                 {
3530                   gtk_widget_style_get (widget,
3531                                         "even_row_color", &color,
3532                                         NULL);
3533
3534                   if (color)
3535                     {
3536                       freeme = get_darkened_gc (window, color, 2);
3537                       gdk_color_free (color);
3538                     }
3539                   else
3540                     freeme = get_darkened_gc (window, &style->base[state_type], 2);
3541                   gc1 = freeme;
3542                 }
3543             }
3544           else
3545             gc1 = style->bg_gc[state_type];
3546         }
3547     }
3548   else
3549     gc1 = style->bg_gc[state_type];
3550   
3551   if (!style->bg_pixmap[state_type] || gc1 != style->bg_gc[state_type] ||
3552       GDK_IS_PIXMAP (window))
3553     {
3554       if (area)
3555         gdk_gc_set_clip_rectangle (gc1, area);
3556
3557       gdk_draw_rectangle (window, gc1, TRUE,
3558                           x, y, width, height);
3559
3560       if (detail && !strcmp ("tooltip", detail))
3561         gdk_draw_rectangle (window, style->black_gc, FALSE,
3562                             x, y, width - 1, height - 1);
3563
3564       if (area)
3565         gdk_gc_set_clip_rectangle (gc1, NULL);
3566     }
3567   else
3568     gtk_style_apply_default_background (style, window,
3569                                         widget && !GTK_WIDGET_NO_WINDOW (widget),
3570                                         state_type, area, x, y, width, height);
3571
3572
3573   if (freeme)
3574     g_object_unref (freeme);
3575 }
3576
3577 static GdkGC *
3578 create_aa_gc (GdkWindow *window, GtkStyle *style, GtkStateType state_type)
3579 {
3580   GdkColor aa_color;
3581   GdkGC *gc = gdk_gc_new (window);
3582    
3583   aa_color.red = (style->fg[state_type].red + style->bg[state_type].red) / 2;
3584   aa_color.green = (style->fg[state_type].green + style->bg[state_type].green) / 2;
3585   aa_color.blue = (style->fg[state_type].blue + style->bg[state_type].blue) / 2;
3586   
3587   gdk_gc_set_rgb_fg_color (gc, &aa_color);
3588
3589   return gc;
3590 }
3591
3592 static void 
3593 gtk_default_draw_check (GtkStyle      *style,
3594                         GdkWindow     *window,
3595                         GtkStateType   state_type,
3596                         GtkShadowType  shadow_type,
3597                         GdkRectangle  *area,
3598                         GtkWidget     *widget,
3599                         const gchar   *detail,
3600                         gint           x,
3601                         gint           y,
3602                         gint           width,
3603                         gint           height)
3604 {
3605   if (detail && strcmp (detail, "cellcheck") == 0)
3606     {
3607       gdk_draw_rectangle (window,
3608                           widget->style->base_gc[state_type],
3609                           TRUE,
3610                           x, y,
3611                           width, height);
3612       gdk_draw_rectangle (window,
3613                           widget->style->text_gc[state_type],
3614                           FALSE,
3615                           x, y,
3616                           width, height);
3617
3618       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3619       y -= (((1 + INDICATOR_PART_SIZE - height) / 2) - 1);
3620       if (shadow_type == GTK_SHADOW_IN)
3621         {
3622           draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT);
3623           draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA);
3624         }
3625       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3626         {
3627           draw_part (window, style->text_gc[state_type], area, x, y, CHECK_INCONSISTENT_TEXT);
3628         }
3629     }
3630   else
3631     {
3632       GdkGC *free_me = NULL;
3633       
3634       GdkGC *base_gc;
3635       GdkGC *text_gc;
3636       GdkGC *aa_gc;
3637
3638       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3639       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3640
3641       if (strcmp (detail, "check") == 0)        /* Menu item */
3642         {
3643           text_gc = style->fg_gc[state_type];
3644           base_gc = style->bg_gc[state_type];
3645           aa_gc = free_me = create_aa_gc (window, style, state_type);
3646         }
3647       else
3648         {
3649           if (state_type == GTK_STATE_ACTIVE)
3650             {
3651               text_gc = style->fg_gc[state_type];
3652               base_gc = style->bg_gc[state_type];
3653               aa_gc = free_me = create_aa_gc (window, style, state_type);
3654             }
3655           else
3656             {
3657               text_gc = style->text_gc[state_type];
3658               base_gc = style->base_gc[state_type];
3659               aa_gc = style->text_aa_gc[state_type];
3660             }
3661
3662           draw_part (window, base_gc, area, x, y, CHECK_BASE);
3663           draw_part (window, style->black_gc, area, x, y, CHECK_BLACK);
3664           draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_DARK);
3665           draw_part (window, style->mid_gc[state_type], area, x, y, CHECK_MID);
3666           draw_part (window, style->light_gc[state_type], area, x, y, CHECK_LIGHT);
3667         }
3668
3669       if (shadow_type == GTK_SHADOW_IN)
3670         {
3671           draw_part (window, text_gc, area, x, y, CHECK_TEXT);
3672           draw_part (window, aa_gc, area, x, y, CHECK_AA);
3673         }
3674       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3675         {
3676           draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT);
3677         }
3678
3679       if (free_me)
3680         g_object_unref (G_OBJECT (free_me));
3681     }
3682 }
3683
3684 static void 
3685 gtk_default_draw_option (GtkStyle      *style,
3686                          GdkWindow     *window,
3687                          GtkStateType   state_type,
3688                          GtkShadowType  shadow_type,
3689                          GdkRectangle  *area,
3690                          GtkWidget     *widget,
3691                          const gchar   *detail,
3692                          gint           x,
3693                          gint           y,
3694                          gint           width,
3695                          gint           height)
3696 {
3697   if (detail && strcmp (detail, "cellradio") == 0)
3698     {
3699       gdk_draw_arc (window,
3700                     widget->style->fg_gc[state_type],
3701                     FALSE,
3702                     x, y,
3703                     width,
3704                     height,
3705                     0, 360*64);
3706
3707       if (shadow_type == GTK_SHADOW_IN)
3708         {
3709           gdk_draw_arc (window,
3710                         widget->style->fg_gc[state_type],
3711                         TRUE,
3712                         x + 2,
3713                         y + 2,
3714                         width - 4,
3715                         height - 4,
3716                         0, 360*64);
3717         }
3718       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3719         {
3720           draw_part (window, widget->style->fg_gc[state_type],
3721                      area, x, y, CHECK_INCONSISTENT_TEXT);
3722         }
3723     }
3724   else
3725     {
3726       GdkGC *free_me = NULL;
3727       
3728       GdkGC *base_gc;
3729       GdkGC *text_gc;
3730       GdkGC *aa_gc;
3731
3732       x -= (1 + INDICATOR_PART_SIZE - width) / 2;
3733       y -= (1 + INDICATOR_PART_SIZE - height) / 2;
3734
3735       if (strcmp (detail, "option") == 0)       /* Menu item */
3736         {
3737           text_gc = style->fg_gc[state_type];
3738           base_gc = style->bg_gc[state_type];
3739           aa_gc = free_me = create_aa_gc (window, style, state_type);
3740         }
3741       else
3742         {
3743           if (state_type == GTK_STATE_ACTIVE)
3744             {
3745               text_gc = style->fg_gc[state_type];
3746               base_gc = style->bg_gc[state_type];
3747               aa_gc = free_me = create_aa_gc (window, style, state_type);
3748             }
3749           else
3750             {
3751               text_gc = style->text_gc[state_type];
3752               base_gc = style->base_gc[state_type];
3753               aa_gc = style->text_aa_gc[state_type];
3754             }
3755
3756           draw_part (window, base_gc, area, x, y, RADIO_BASE);
3757           draw_part (window, style->black_gc, area, x, y, RADIO_BLACK);
3758           draw_part (window, style->dark_gc[state_type], area, x, y, RADIO_DARK);
3759           draw_part (window, style->mid_gc[state_type], area, x, y, RADIO_MID);
3760           draw_part (window, style->light_gc[state_type], area, x, y, RADIO_LIGHT);
3761         }
3762
3763       if (shadow_type == GTK_SHADOW_IN)
3764         {
3765           draw_part (window, text_gc, area, x, y, RADIO_TEXT);
3766         }
3767       else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
3768         {
3769           if (strcmp (detail, "option") == 0)  /* Menu item */
3770             {
3771               draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT);
3772             }
3773           else
3774             {
3775               draw_part (window, text_gc, area, x, y, RADIO_INCONSISTENT_TEXT);
3776               draw_part (window, aa_gc, area, x, y, RADIO_INCONSISTENT_AA);
3777             }
3778         }
3779
3780       if (free_me)
3781         g_object_unref (G_OBJECT (free_me));
3782     }
3783 }
3784
3785 static void
3786 gtk_default_draw_tab (GtkStyle      *style,
3787                       GdkWindow     *window,
3788                       GtkStateType   state_type,
3789                       GtkShadowType  shadow_type,
3790                       GdkRectangle  *area,
3791                       GtkWidget     *widget,
3792                       const gchar   *detail,
3793                       gint           x,
3794                       gint           y,
3795                       gint           width,
3796                       gint           height)
3797 {
3798 #define ARROW_SPACE 4
3799
3800   GtkRequisition indicator_size;
3801   GtkBorder indicator_spacing;
3802   gint arrow_height;
3803   
3804   option_menu_get_props (widget, &indicator_size, &indicator_spacing);
3805
3806   indicator_size.width += (indicator_size.width % 2) - 1;
3807   arrow_height = indicator_size.width / 2 + 1;
3808
3809   x += (width - indicator_size.width) / 2;
3810   y += (height - (2 * arrow_height + ARROW_SPACE)) / 2;
3811
3812   if (state_type == GTK_STATE_INSENSITIVE)
3813     {
3814       draw_arrow (window, style->white_gc, area,
3815                   GTK_ARROW_UP, x + 1, y + 1,
3816                   indicator_size.width, arrow_height);
3817       
3818       draw_arrow (window, style->white_gc, area,
3819                   GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1,
3820                   indicator_size.width, arrow_height);
3821     }
3822   
3823   draw_arrow (window, style->fg_gc[state_type], area,
3824               GTK_ARROW_UP, x, y,
3825               indicator_size.width, arrow_height);
3826   
3827   
3828   draw_arrow (window, style->fg_gc[state_type], area,
3829               GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE,
3830               indicator_size.width, arrow_height);
3831 }
3832
3833 static void 
3834 gtk_default_draw_shadow_gap (GtkStyle       *style,
3835                              GdkWindow      *window,
3836                              GtkStateType    state_type,
3837                              GtkShadowType   shadow_type,
3838                              GdkRectangle   *area,
3839                              GtkWidget      *widget,
3840                              const gchar    *detail,
3841                              gint            x,
3842                              gint            y,
3843                              gint            width,
3844                              gint            height,
3845                              GtkPositionType gap_side,
3846                              gint            gap_x,
3847                              gint            gap_width)
3848 {
3849   GdkGC *gc1 = NULL;
3850   GdkGC *gc2 = NULL;
3851   GdkGC *gc3 = NULL;
3852   GdkGC *gc4 = NULL;
3853   
3854   g_return_if_fail (GTK_IS_STYLE (style));
3855   g_return_if_fail (window != NULL);
3856   
3857   sanitize_size (window, &width, &height);
3858   
3859   switch (shadow_type)
3860     {
3861     case GTK_SHADOW_NONE:
3862       return;
3863     case GTK_SHADOW_IN:
3864       gc1 = style->dark_gc[state_type];
3865       gc2 = style->black_gc;
3866       gc3 = style->bg_gc[state_type];
3867       gc4 = style->light_gc[state_type];
3868       break;
3869     case GTK_SHADOW_ETCHED_IN:
3870       gc1 = style->dark_gc[state_type];
3871       gc2 = style->light_gc[state_type];
3872       gc3 = style->dark_gc[state_type];
3873       gc4 = style->light_gc[state_type];
3874       break;
3875     case GTK_SHADOW_OUT:
3876       gc1 = style->light_gc[state_type];
3877       gc2 = style->bg_gc[state_type];
3878       gc3 = style->dark_gc[state_type];
3879       gc4 = style->black_gc;
3880       break;
3881     case GTK_SHADOW_ETCHED_OUT:
3882       gc1 = style->light_gc[state_type];
3883       gc2 = style->dark_gc[state_type];
3884       gc3 = style->light_gc[state_type];
3885       gc4 = style->dark_gc[state_type];
3886       break;
3887     }
3888   if (area)
3889     {
3890       gdk_gc_set_clip_rectangle (gc1, area);
3891       gdk_gc_set_clip_rectangle (gc2, area);
3892       gdk_gc_set_clip_rectangle (gc3, area);
3893       gdk_gc_set_clip_rectangle (gc4, area);
3894     }
3895   
3896   switch (shadow_type)
3897     {
3898     case GTK_SHADOW_NONE:
3899     case GTK_SHADOW_IN:
3900     case GTK_SHADOW_OUT:
3901     case GTK_SHADOW_ETCHED_IN:
3902     case GTK_SHADOW_ETCHED_OUT:
3903       switch (gap_side)
3904         {
3905         case GTK_POS_TOP:
3906           gdk_draw_line (window, gc1,
3907                          x, y, x, y + height - 1);
3908           gdk_draw_line (window, gc2,
3909                          x + 1, y, x + 1, y + height - 2);
3910           
3911           gdk_draw_line (window, gc3,
3912                          x + 1, y + height - 2, x + width - 2, y + height - 2);
3913           gdk_draw_line (window, gc3,
3914                          x + width - 2, y, x + width - 2, y + height - 2);
3915           gdk_draw_line (window, gc4,
3916                          x, y + height - 1, x + width - 1, y + height - 1);
3917           gdk_draw_line (window, gc4,
3918                          x + width - 1, y, x + width - 1, y + height - 1);
3919           if (gap_x > 0)
3920             {
3921               gdk_draw_line (window, gc1,
3922                              x, y, x + gap_x - 1, y);
3923               gdk_draw_line (window, gc2,
3924                              x + 1, y + 1, x + gap_x - 1, y + 1);
3925               gdk_draw_line (window, gc2,
3926                              x + gap_x, y, x + gap_x, y);
3927             }
3928           if ((width - (gap_x + gap_width)) > 0)
3929             {
3930               gdk_draw_line (window, gc1,
3931                              x + gap_x + gap_width, y, x + width - 2, y);
3932               gdk_draw_line (window, gc2,
3933                              x + gap_x + gap_width, y + 1, x + width - 3, y + 1);
3934               gdk_draw_line (window, gc2,
3935                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
3936             }
3937           break;
3938         case GTK_POS_BOTTOM:
3939           gdk_draw_line (window, gc1,
3940                          x, y, x + width - 1, y);
3941           gdk_draw_line (window, gc1,
3942                          x, y, x, y + height - 1);
3943           gdk_draw_line (window, gc2,
3944                          x + 1, y + 1, x + width - 2, y + 1);
3945           gdk_draw_line (window, gc2,
3946                          x + 1, y + 1, x + 1, y + height - 1);
3947           
3948           gdk_draw_line (window, gc3,
3949                          x + width - 2, y + 1, x + width - 2, y + height - 1);
3950           gdk_draw_line (window, gc4,
3951                          x + width - 1, y, x + width - 1, y + height - 1);
3952           if (gap_x > 0)
3953             {
3954               gdk_draw_line (window, gc4,
3955                              x, y + height - 1, x + gap_x - 1, y + height - 1);
3956               gdk_draw_line (window, gc3,
3957                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
3958               gdk_draw_line (window, gc3,
3959                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
3960             }
3961           if ((width - (gap_x + gap_width)) > 0)
3962             {
3963               gdk_draw_line (window, gc4,
3964                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
3965               gdk_draw_line (window, gc3,
3966                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
3967               gdk_draw_line (window, gc3,
3968                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
3969             }
3970           break;
3971         case GTK_POS_LEFT:
3972           gdk_draw_line (window, gc1,
3973                          x, y, x + width - 1, y);
3974           gdk_draw_line (window, gc2,
3975                          x, y + 1, x + width - 2, y + 1);
3976           
3977           gdk_draw_line (window, gc3,
3978                          x, y + height - 2, x + width - 2, y + height - 2);
3979           gdk_draw_line (window, gc3,
3980                          x + width - 2, y + 1, x + width - 2, y + height - 2);
3981           gdk_draw_line (window, gc4,
3982                          x, y + height - 1, x + width - 1, y + height - 1);
3983           gdk_draw_line (window, gc4,
3984                          x + width - 1, y, x + width - 1, y + height - 1);
3985           if (gap_x > 0)
3986             {
3987               gdk_draw_line (window, gc1,
3988                              x, y, x, y + gap_x - 1);
3989               gdk_draw_line (window, gc2,
3990                              x + 1, y + 1, x + 1, y + gap_x - 1);
3991               gdk_draw_line (window, gc2,
3992                              x, y + gap_x, x, y + gap_x);
3993             }
3994           if ((width - (gap_x + gap_width)) > 0)
3995             {
3996               gdk_draw_line (window, gc1,
3997                              x, y + gap_x + gap_width, x, y + height - 2);
3998               gdk_draw_line (window, gc2,
3999                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
4000               gdk_draw_line (window, gc2,
4001                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
4002             }
4003           break;
4004         case GTK_POS_RIGHT:
4005           gdk_draw_line (window, gc1,
4006                          x, y, x + width - 1, y);
4007           gdk_draw_line (window, gc1,
4008                          x, y, x, y + height - 1);
4009           gdk_draw_line (window, gc2,
4010                          x + 1, y + 1, x + width - 1, y + 1);
4011           gdk_draw_line (window, gc2,
4012                          x + 1, y + 1, x + 1, y + height - 2);
4013           
4014           gdk_draw_line (window, gc3,
4015                          x + 1, y + height - 2, x + width - 1, y + height - 2);
4016           gdk_draw_line (window, gc4,
4017                          x, y + height - 1, x + width - 1, y + height - 1);
4018           if (gap_x > 0)
4019             {
4020               gdk_draw_line (window, gc4,
4021                              x + width - 1, y, x + width - 1, y + gap_x - 1);
4022               gdk_draw_line (window, gc3,
4023                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
4024               gdk_draw_line (window, gc3,
4025                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
4026             }
4027           if ((width - (gap_x + gap_width)) > 0)
4028             {
4029               gdk_draw_line (window, gc4,
4030                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
4031               gdk_draw_line (window, gc3,
4032                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
4033               gdk_draw_line (window, gc3,
4034                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
4035             }
4036           break;
4037         }
4038     }
4039
4040   if (area)
4041     {
4042       gdk_gc_set_clip_rectangle (gc1, NULL);
4043       gdk_gc_set_clip_rectangle (gc2, NULL);
4044       gdk_gc_set_clip_rectangle (gc3, NULL);
4045       gdk_gc_set_clip_rectangle (gc4, NULL);
4046     }
4047 }
4048
4049 static void 
4050 gtk_default_draw_box_gap (GtkStyle       *style,
4051                           GdkWindow      *window,
4052                           GtkStateType    state_type,
4053                           GtkShadowType   shadow_type,
4054                           GdkRectangle   *area,
4055                           GtkWidget      *widget,
4056                           const gchar    *detail,
4057                           gint            x,
4058                           gint            y,
4059                           gint            width,
4060                           gint            height,
4061                           GtkPositionType gap_side,
4062                           gint            gap_x,
4063                           gint            gap_width)
4064 {
4065   GdkGC *gc1 = NULL;
4066   GdkGC *gc2 = NULL;
4067   GdkGC *gc3 = NULL;
4068   GdkGC *gc4 = NULL;
4069   
4070   g_return_if_fail (GTK_IS_STYLE (style));
4071   g_return_if_fail (window != NULL);
4072   
4073   gtk_style_apply_default_background (style, window,
4074                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4075                                       state_type, area, x, y, width, height);
4076   
4077   sanitize_size (window, &width, &height);
4078   
4079   switch (shadow_type)
4080     {
4081     case GTK_SHADOW_NONE:
4082       return;
4083     case GTK_SHADOW_IN:
4084       gc1 = style->dark_gc[state_type];
4085       gc2 = style->black_gc;
4086       gc3 = style->bg_gc[state_type];
4087       gc4 = style->light_gc[state_type];
4088       break;
4089     case GTK_SHADOW_ETCHED_IN:
4090       gc1 = style->dark_gc[state_type];
4091       gc2 = style->light_gc[state_type];
4092       gc3 = style->dark_gc[state_type];
4093       gc4 = style->light_gc[state_type];
4094       break;
4095     case GTK_SHADOW_OUT:
4096       gc1 = style->light_gc[state_type];
4097       gc2 = style->bg_gc[state_type];
4098       gc3 = style->dark_gc[state_type];
4099       gc4 = style->black_gc;
4100       break;
4101     case GTK_SHADOW_ETCHED_OUT:
4102       gc1 = style->light_gc[state_type];
4103       gc2 = style->dark_gc[state_type];
4104       gc3 = style->light_gc[state_type];
4105       gc4 = style->dark_gc[state_type];
4106       break;
4107     }
4108
4109   if (area)
4110     {
4111       gdk_gc_set_clip_rectangle (gc1, area);
4112       gdk_gc_set_clip_rectangle (gc2, area);
4113       gdk_gc_set_clip_rectangle (gc3, area);
4114       gdk_gc_set_clip_rectangle (gc4, area);
4115     }
4116   
4117   switch (shadow_type)
4118     {
4119     case GTK_SHADOW_NONE:
4120     case GTK_SHADOW_IN:
4121     case GTK_SHADOW_OUT:
4122     case GTK_SHADOW_ETCHED_IN:
4123     case GTK_SHADOW_ETCHED_OUT:
4124       switch (gap_side)
4125         {
4126         case GTK_POS_TOP:
4127           gdk_draw_line (window, gc1,
4128                          x, y, x, y + height - 1);
4129           gdk_draw_line (window, gc2,
4130                          x + 1, y, x + 1, y + height - 2);
4131           
4132           gdk_draw_line (window, gc3,
4133                          x + 1, y + height - 2, x + width - 2, y + height - 2);
4134           gdk_draw_line (window, gc3,
4135                          x + width - 2, y, x + width - 2, y + height - 2);
4136           gdk_draw_line (window, gc4,
4137                          x, y + height - 1, x + width - 1, y + height - 1);
4138           gdk_draw_line (window, gc4,
4139                          x + width - 1, y, x + width - 1, y + height - 1);
4140           if (gap_x > 0)
4141             {
4142               gdk_draw_line (window, gc1,
4143                              x, y, x + gap_x - 1, y);
4144               gdk_draw_line (window, gc2,
4145                              x + 1, y + 1, x + gap_x - 1, y + 1);
4146               gdk_draw_line (window, gc2,
4147                              x + gap_x, y, x + gap_x, y);
4148             }
4149           if ((width - (gap_x + gap_width)) > 0)
4150             {
4151               gdk_draw_line (window, gc1,
4152                              x + gap_x + gap_width, y, x + width - 2, y);
4153               gdk_draw_line (window, gc2,
4154                              x + gap_x + gap_width, y + 1, x + width - 2, y + 1);
4155               gdk_draw_line (window, gc2,
4156                              x + gap_x + gap_width - 1, y, x + gap_x + gap_width - 1, y);
4157             }
4158           break;
4159         case  GTK_POS_BOTTOM:
4160           gdk_draw_line (window, gc1,
4161                          x, y, x + width - 1, y);
4162           gdk_draw_line (window, gc1,
4163                          x, y, x, y + height - 1);
4164           gdk_draw_line (window, gc2,
4165                          x + 1, y + 1, x + width - 2, y + 1);
4166           gdk_draw_line (window, gc2,
4167                          x + 1, y + 1, x + 1, y + height - 1);
4168           
4169           gdk_draw_line (window, gc3,
4170                          x + width - 2, y + 1, x + width - 2, y + height - 1);
4171           gdk_draw_line (window, gc4,
4172                          x + width - 1, y, x + width - 1, y + height - 1);
4173           if (gap_x > 0)
4174             {
4175               gdk_draw_line (window, gc4,
4176                              x, y + height - 1, x + gap_x - 1, y + height - 1);
4177               gdk_draw_line (window, gc3,
4178                              x + 1, y + height - 2, x + gap_x - 1, y + height - 2);
4179               gdk_draw_line (window, gc3,
4180                              x + gap_x, y + height - 1, x + gap_x, y + height - 1);
4181             }
4182           if ((width - (gap_x + gap_width)) > 0)
4183             {
4184               gdk_draw_line (window, gc4,
4185                              x + gap_x + gap_width, y + height - 1, x + width - 2, y + height - 1);
4186               gdk_draw_line (window, gc3,
4187                              x + gap_x + gap_width, y + height - 2, x + width - 2, y + height - 2);
4188               gdk_draw_line (window, gc3,
4189                              x + gap_x + gap_width - 1, y + height - 1, x + gap_x + gap_width - 1, y + height - 1);
4190             }
4191           break;
4192         case GTK_POS_LEFT:
4193           gdk_draw_line (window, gc1,
4194                          x, y, x + width - 1, y);
4195           gdk_draw_line (window, gc2,
4196                          x, y + 1, x + width - 2, y + 1);
4197           
4198           gdk_draw_line (window, gc3,
4199                          x, y + height - 2, x + width - 2, y + height - 2);
4200           gdk_draw_line (window, gc3,
4201                          x + width - 2, y + 1, x + width - 2, y + height - 2);
4202           gdk_draw_line (window, gc4,
4203                          x, y + height - 1, x + width - 1, y + height - 1);
4204           gdk_draw_line (window, gc4,
4205                          x + width - 1, y, x + width - 1, y + height - 1);
4206           if (gap_x > 0)
4207             {
4208               gdk_draw_line (window, gc1,
4209                              x, y, x, y + gap_x - 1);
4210               gdk_draw_line (window, gc2,
4211                              x + 1, y + 1, x + 1, y + gap_x - 1);
4212               gdk_draw_line (window, gc2,
4213                              x, y + gap_x, x, y + gap_x);
4214             }
4215           if ((width - (gap_x + gap_width)) > 0)
4216             {
4217               gdk_draw_line (window, gc1,
4218                              x, y + gap_x + gap_width, x, y + height - 2);
4219               gdk_draw_line (window, gc2,
4220                              x + 1, y + gap_x + gap_width, x + 1, y + height - 2);
4221               gdk_draw_line (window, gc2,
4222                              x, y + gap_x + gap_width - 1, x, y + gap_x + gap_width - 1);
4223             }
4224           break;
4225         case GTK_POS_RIGHT:
4226           gdk_draw_line (window, gc1,
4227                          x, y, x + width - 1, y);
4228           gdk_draw_line (window, gc1,
4229                          x, y, x, y + height - 1);
4230           gdk_draw_line (window, gc2,
4231                          x + 1, y + 1, x + width - 1, y + 1);
4232           gdk_draw_line (window, gc2,
4233                          x + 1, y + 1, x + 1, y + height - 2);
4234           
4235           gdk_draw_line (window, gc3,
4236                          x + 1, y + height - 2, x + width - 1, y + height - 2);
4237           gdk_draw_line (window, gc4,
4238                          x, y + height - 1, x + width - 1, y + height - 1);
4239           if (gap_x > 0)
4240             {
4241               gdk_draw_line (window, gc4,
4242                              x + width - 1, y, x + width - 1, y + gap_x - 1);
4243               gdk_draw_line (window, gc3,
4244                              x + width - 2, y + 1, x + width - 2, y + gap_x - 1);
4245               gdk_draw_line (window, gc3,
4246                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
4247             }
4248           if ((width - (gap_x + gap_width)) > 0)
4249             {
4250               gdk_draw_line (window, gc4,
4251                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
4252               gdk_draw_line (window, gc3,
4253                              x + width - 2, y + gap_x + gap_width, x + width - 2, y + height - 2);
4254               gdk_draw_line (window, gc3,
4255                              x + width - 1, y + gap_x + gap_width - 1, x + width - 1, y + gap_x + gap_width - 1);
4256             }
4257           break;
4258         }
4259     }
4260
4261   if (area)
4262     {
4263       gdk_gc_set_clip_rectangle (gc1, NULL);
4264       gdk_gc_set_clip_rectangle (gc2, NULL);
4265       gdk_gc_set_clip_rectangle (gc3, NULL);
4266       gdk_gc_set_clip_rectangle (gc4, NULL);
4267     }
4268 }
4269
4270 static void 
4271 gtk_default_draw_extension (GtkStyle       *style,
4272                             GdkWindow      *window,
4273                             GtkStateType    state_type,
4274                             GtkShadowType   shadow_type,
4275                             GdkRectangle   *area,
4276                             GtkWidget      *widget,
4277                             const gchar    *detail,
4278                             gint            x,
4279                             gint            y,
4280                             gint            width,
4281                             gint            height,
4282                             GtkPositionType gap_side)
4283 {
4284   GdkGC *gc1 = NULL;
4285   GdkGC *gc2 = NULL;
4286   GdkGC *gc3 = NULL;
4287   GdkGC *gc4 = NULL;
4288   
4289   g_return_if_fail (GTK_IS_STYLE (style));
4290   g_return_if_fail (window != NULL);
4291   
4292   gtk_style_apply_default_background (style, window,
4293                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
4294                                       GTK_STATE_NORMAL, area, x, y, width, height);
4295   
4296   sanitize_size (window, &width, &height);
4297   
4298   switch (shadow_type)
4299     {
4300     case GTK_SHADOW_NONE:
4301       return;
4302     case GTK_SHADOW_IN:
4303       gc1 = style->dark_gc[state_type];
4304       gc2 = style->black_gc;
4305       gc3 = style->bg_gc[state_type];
4306       gc4 = style->light_gc[state_type];
4307       break;
4308     case GTK_SHADOW_ETCHED_IN:
4309       gc1 = style->dark_gc[state_type];
4310       gc2 = style->light_gc[state_type];
4311       gc3 = style->dark_gc[state_type];
4312       gc4 = style->light_gc[state_type];
4313       break;
4314     case GTK_SHADOW_OUT:
4315       gc1 = style->light_gc[state_type];
4316       gc2 = style->bg_gc[state_type];
4317       gc3 = style->dark_gc[state_type];
4318       gc4 = style->black_gc;
4319       break;
4320     case GTK_SHADOW_ETCHED_OUT:
4321       gc1 = style->light_gc[state_type];
4322       gc2 = style->dark_gc[state_type];
4323       gc3 = style->light_gc[state_type];
4324       gc4 = style->dark_gc[state_type];
4325       break;
4326     }
4327
4328   if (area)
4329     {
4330       gdk_gc_set_clip_rectangle (gc1, area);
4331       gdk_gc_set_clip_rectangle (gc2, area);
4332       gdk_gc_set_clip_rectangle (gc3, area);
4333       gdk_gc_set_clip_rectangle (gc4, area);
4334     }
4335
4336   switch (shadow_type)
4337     {
4338     case GTK_SHADOW_NONE:
4339     case GTK_SHADOW_IN:
4340     case GTK_SHADOW_OUT:
4341     case GTK_SHADOW_ETCHED_IN:
4342     case GTK_SHADOW_ETCHED_OUT:
4343       switch (gap_side)
4344         {
4345         case GTK_POS_TOP:
4346           gtk_style_apply_default_background (style, window,
4347                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4348                                               state_type, area,
4349                                               x + style->xthickness, 
4350                                               y, 
4351                                               width - (2 * style->xthickness), 
4352                                               height - (style->ythickness));
4353           gdk_draw_line (window, gc1,
4354                          x, y, x, y + height - 2);
4355           gdk_draw_line (window, gc2,
4356                          x + 1, y, x + 1, y + height - 2);
4357           
4358           gdk_draw_line (window, gc3,
4359                          x + 2, y + height - 2, x + width - 2, y + height - 2);
4360           gdk_draw_line (window, gc3,
4361                          x + width - 2, y, x + width - 2, y + height - 2);
4362           gdk_draw_line (window, gc4,
4363                          x + 1, y + height - 1, x + width - 2, y + height - 1);
4364           gdk_draw_line (window, gc4,
4365                          x + width - 1, y, x + width - 1, y + height - 2);
4366           break;
4367         case GTK_POS_BOTTOM:
4368           gtk_style_apply_default_background (style, window,
4369                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4370                                               state_type, area,
4371                                               x + style->xthickness, 
4372                                               y + style->ythickness, 
4373                                               width - (2 * style->xthickness), 
4374                                               height - (style->ythickness));
4375           gdk_draw_line (window, gc1,
4376                          x + 1, y, x + width - 2, y);
4377           gdk_draw_line (window, gc1,
4378                          x, y + 1, x, y + height - 1);
4379           gdk_draw_line (window, gc2,
4380                          x + 1, y + 1, x + width - 2, y + 1);
4381           gdk_draw_line (window, gc2,
4382                          x + 1, y + 1, x + 1, y + height - 1);
4383           
4384           gdk_draw_line (window, gc3,
4385                          x + width - 2, y + 2, x + width - 2, y + height - 1);
4386           gdk_draw_line (window, gc4,
4387                          x + width - 1, y + 1, x + width - 1, y + height - 1);
4388           break;
4389         case GTK_POS_LEFT:
4390           gtk_style_apply_default_background (style, window,
4391                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4392                                               state_type, area,
4393                                               x, 
4394                                               y + style->ythickness, 
4395                                               width - (style->xthickness), 
4396                                               height - (2 * style->ythickness));
4397           gdk_draw_line (window, gc1,
4398                          x, y, x + width - 2, y);
4399           gdk_draw_line (window, gc2,
4400                          x + 1, y + 1, x + width - 2, y + 1);
4401           
4402           gdk_draw_line (window, gc3,
4403                          x, y + height - 2, x + width - 2, y + height - 2);
4404           gdk_draw_line (window, gc3,
4405                          x + width - 2, y + 2, x + width - 2, y + height - 2);
4406           gdk_draw_line (window, gc4,
4407                          x, y + height - 1, x + width - 2, y + height - 1);
4408           gdk_draw_line (window, gc4,
4409                          x + width - 1, y + 1, x + width - 1, y + height - 2);
4410           break;
4411         case GTK_POS_RIGHT:
4412           gtk_style_apply_default_background (style, window,
4413                                               widget && !GTK_WIDGET_NO_WINDOW (widget),
4414                                               state_type, area,
4415                                               x + style->xthickness, 
4416                                               y + style->ythickness, 
4417                                               width - (style->xthickness), 
4418                                               height - (2 * style->ythickness));
4419           gdk_draw_line (window, gc1,
4420                          x + 1, y, x + width - 1, y);
4421           gdk_draw_line (window, gc1,
4422                          x, y + 1, x, y + height - 2);
4423           gdk_draw_line (window, gc2,
4424                          x + 1, y + 1, x + width - 1, y + 1);
4425           gdk_draw_line (window, gc2,
4426                          x + 1, y + 1, x + 1, y + height - 2);
4427           
4428           gdk_draw_line (window, gc3,
4429                          x + 2, y + height - 2, x + width - 1, y + height - 2);
4430           gdk_draw_line (window, gc4,
4431                          x + 1, y + height - 1, x + width - 1, y + height - 1);
4432           break;
4433         }
4434     }
4435
4436   if (area)
4437     {
4438       gdk_gc_set_clip_rectangle (gc1, NULL);
4439       gdk_gc_set_clip_rectangle (gc2, NULL);
4440       gdk_gc_set_clip_rectangle (gc3, NULL);
4441       gdk_gc_set_clip_rectangle (gc4, NULL);
4442     }
4443 }
4444
4445 static void 
4446 gtk_default_draw_focus (GtkStyle      *style,
4447                         GdkWindow     *window,
4448                         GtkStateType   state_type,
4449                         GdkRectangle  *area,
4450                         GtkWidget     *widget,
4451                         const gchar   *detail,
4452                         gint           x,
4453                         gint           y,
4454                         gint           width,
4455                         gint           height)
4456 {
4457   GdkPoint points[5];
4458   GdkGC    *gc;
4459   gboolean free_dash_list = FALSE;
4460   gint line_width = 1;
4461   gint8 *dash_list = "\1\1";
4462   gint dash_len;
4463
4464   gc = style->fg_gc[state_type];
4465
4466   if (widget)
4467     {
4468       gtk_widget_style_get (widget,
4469                             "focus-line-width", &line_width,
4470                             "focus-line-pattern", (gchar *)&dash_list,
4471                             NULL);
4472
4473       free_dash_list = TRUE;
4474   }
4475
4476   sanitize_size (window, &width, &height);
4477   
4478   if (area)
4479     gdk_gc_set_clip_rectangle (gc, area);
4480
4481   gdk_gc_set_line_attributes (gc, line_width,
4482                               dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID,
4483                               GDK_CAP_BUTT, GDK_JOIN_MITER);
4484
4485
4486   if (detail && !strcmp (detail, "add-mode"))
4487     {
4488       if (free_dash_list)
4489         g_free (dash_list);
4490       
4491       dash_list = "\4\4";
4492       free_dash_list = FALSE;
4493     }
4494
4495   points[0].x = x + line_width / 2;
4496   points[0].y = y + line_width / 2;
4497   points[1].x = x + width - line_width + line_width / 2;
4498   points[1].y = y + line_width / 2;
4499   points[2].x = x + width - line_width + line_width / 2;
4500   points[2].y = y + height - line_width + line_width / 2;
4501   points[3].x = x + line_width / 2;
4502   points[3].y = y + height - line_width + line_width / 2;
4503   points[4] = points[0];
4504
4505   if (!dash_list[0])
4506     {
4507       gdk_draw_lines (window, gc, points, 5);
4508     }
4509   else
4510     {
4511       /* We go through all the pain below because the X rasterization
4512        * rules don't really work right for dashed lines if you
4513        * want continuity in segments that go between top/right
4514        * and left/bottom. For instance, a top left corner
4515        * with a 1-1 dash is drawn as:
4516        *
4517        *  X X X 
4518        *  X
4519        *
4520        *  X
4521        *
4522        * This is because pixels on the top and left boundaries
4523        * of polygons are drawn, but not on the bottom and right.
4524        * So, if you have a line going up that turns the corner
4525        * and goes right, there is a one pixel shift in the pattern.
4526        *
4527        * So, to fix this, we drawn the top and right in one call,
4528        * then the left and bottom in another call, fixing up
4529        * the dash offset for the second call ourselves to get
4530        * continuity at the upper left.
4531        *
4532        * It's not perfect since we really should have a join at
4533        * the upper left and lower right instead of two intersecting
4534        * lines but that's only really apparent for no-dashes,
4535        * which (for this reason) are done as one polygon and
4536        * don't to through this code path.
4537        */
4538       
4539       dash_len = strlen (dash_list);
4540       
4541       if (dash_list[0])
4542         gdk_gc_set_dashes (gc, 0, dash_list, dash_len);
4543       
4544       gdk_draw_lines (window, gc, points, 3);
4545       
4546       /* We draw this line one farther over than it is "supposed" to
4547        * because of another rasterization problem ... if two 1 pixel
4548        * unjoined lines meet at the lower right, there will be a missing
4549        * pixel.
4550        */
4551       points[2].x += 1;
4552       
4553       if (dash_list[0])
4554         {
4555           gint dash_pixels = 0;
4556           gint i;
4557           
4558           /* Adjust the dash offset for the bottom and left so we
4559            * match up at the upper left.
4560            */
4561           for (i = 0; i < dash_len; i++)
4562             dash_pixels += dash_list[i];
4563       
4564           if (dash_len % 2 == 1)
4565             dash_pixels *= 2;
4566           
4567           gdk_gc_set_dashes (gc, dash_pixels - (width + height - 2 * line_width) % dash_pixels, dash_list, dash_len);
4568         }
4569       
4570       gdk_draw_lines (window, gc, points + 2, 3);
4571     }
4572
4573   gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
4574
4575   if (area)
4576     gdk_gc_set_clip_rectangle (gc, NULL);
4577
4578   if (free_dash_list)
4579     g_free (dash_list);
4580 }
4581
4582 static void 
4583 gtk_default_draw_slider (GtkStyle      *style,
4584                          GdkWindow     *window,
4585                          GtkStateType   state_type,
4586                          GtkShadowType  shadow_type,
4587                          GdkRectangle  *area,
4588                          GtkWidget     *widget,
4589                          const gchar   *detail,
4590                          gint           x,
4591                          gint           y,
4592                          gint           width,
4593                          gint           height,
4594                          GtkOrientation orientation)
4595 {
4596   g_return_if_fail (GTK_IS_STYLE (style));
4597   g_return_if_fail (window != NULL);
4598   
4599   sanitize_size (window, &width, &height);
4600   
4601   gtk_paint_box (style, window, state_type, shadow_type,
4602                  area, widget, detail, x, y, width, height);
4603
4604   if (detail &&
4605       (strcmp ("hscale", detail) == 0 ||
4606        strcmp ("vscale", detail) == 0))
4607     {
4608       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4609         gtk_paint_vline (style, window, state_type, area, widget, detail, 
4610                          y + style->ythickness, 
4611                          y + height - style->ythickness - 1, x + width / 2);
4612       else
4613         gtk_paint_hline (style, window, state_type, area, widget, detail, 
4614                          x + style->xthickness, 
4615                          x + width - style->xthickness - 1, y + height / 2);
4616     }
4617 }
4618
4619 static void
4620 draw_dot (GdkWindow    *window,
4621           GdkGC        *light_gc,
4622           GdkGC        *dark_gc,
4623           gint          x,
4624           gint          y,
4625           gushort       size)
4626 {
4627   
4628   size = CLAMP (size, 2, 3);
4629
4630   if (size == 2)
4631     {
4632       gdk_draw_point (window, light_gc, x, y);
4633       gdk_draw_point (window, light_gc, x+1, y+1);
4634     }
4635   else if (size == 3);
4636     {
4637       gdk_draw_point (window, light_gc, x, y);
4638       gdk_draw_point (window, light_gc, x+1, y);
4639       gdk_draw_point (window, light_gc, x, y+1);
4640       gdk_draw_point (window, dark_gc, x+1, y+2);
4641       gdk_draw_point (window, dark_gc, x+2, y+1);
4642       gdk_draw_point (window, dark_gc, x+2, y+2);
4643     }
4644 }
4645
4646 static void 
4647 gtk_default_draw_handle (GtkStyle      *style,
4648                          GdkWindow     *window,
4649                          GtkStateType   state_type,
4650                          GtkShadowType  shadow_type,
4651                          GdkRectangle  *area,
4652                          GtkWidget     *widget,
4653                          const gchar   *detail,
4654                          gint           x,
4655                          gint           y,
4656                          gint           width,
4657                          gint           height,
4658                          GtkOrientation orientation)
4659 {
4660   gint xx, yy;
4661   gint xthick, ythick;
4662   GdkGC *light_gc, *dark_gc;
4663   GdkRectangle rect;
4664   GdkRectangle dest;
4665   gint intersect;
4666   
4667   g_return_if_fail (GTK_IS_STYLE (style));
4668   g_return_if_fail (window != NULL);
4669   
4670   sanitize_size (window, &width, &height);
4671   
4672   gtk_paint_box (style, window, state_type, shadow_type, area, widget, 
4673                  detail, x, y, width, height);
4674   
4675   
4676   if (!strcmp (detail, "paned"))
4677     {
4678       /* we want to ignore the shadow border in paned widgets */
4679       xthick = 0;
4680       ythick = 0;
4681
4682       light_gc = style->light_gc[state_type];
4683       dark_gc = style->black_gc;
4684     }
4685   else
4686     {
4687       xthick = style->xthickness;
4688       ythick = style->ythickness;
4689
4690       light_gc = style->light_gc[state_type];
4691       dark_gc = style->dark_gc[state_type];
4692     }
4693   
4694   rect.x = x + xthick;
4695   rect.y = y + ythick;
4696   rect.width = width - (xthick * 2);
4697   rect.height = height - (ythick * 2);
4698
4699   if (area)
4700       intersect = gdk_rectangle_intersect (area, &rect, &dest);
4701   else
4702     {
4703       intersect = TRUE;
4704       dest = rect;
4705     }
4706
4707   if (!intersect)
4708     return;
4709
4710   gdk_gc_set_clip_rectangle (light_gc, &dest);
4711   gdk_gc_set_clip_rectangle (dark_gc, &dest);
4712
4713   if (!strcmp (detail, "paned"))
4714     {
4715       if (orientation == GTK_ORIENTATION_HORIZONTAL)
4716         for (xx = x + width/2 - 15; xx <= x + width/2 + 15; xx += 5)
4717           draw_dot (window, light_gc, dark_gc, xx, y + height/2 - 1, 3);
4718       else
4719         for (yy = y + height/2 - 15; yy <= y + height/2 + 15; yy += 5)
4720           draw_dot (window, light_gc, dark_gc, x + width/2 - 1, yy, 3);
4721     }
4722   else
4723     {
4724       for (yy = y + ythick; yy < (y + height - ythick); yy += 3)
4725         for (xx = x + xthick; xx < (x + width - xthick); xx += 6)
4726           {
4727             draw_dot (window, light_gc, dark_gc, xx, yy, 2);
4728             draw_dot (window, light_gc, dark_gc, xx + 3, yy + 1, 2);
4729           }
4730     }
4731
4732   gdk_gc_set_clip_rectangle (light_gc, NULL);
4733   gdk_gc_set_clip_rectangle (dark_gc, NULL);
4734 }
4735
4736 static void
4737 create_expander_affine (gdouble affine[6],
4738                         gint    degrees,
4739                         gint    expander_size,
4740                         gint    x,
4741                         gint    y)
4742 {
4743   gdouble s, c;
4744   gdouble width;
4745   gdouble height;
4746
4747   width = expander_size / 4.0;
4748   height = expander_size / 2.0;
4749   
4750   s = sin (degrees * G_PI / 180.0);
4751   c = cos (degrees * G_PI / 180.0);
4752   
4753   affine[0] = c;
4754   affine[1] = s;
4755   affine[2] = -s;
4756   affine[3] = c;
4757   affine[4] = -width * c - height * -s + x;
4758   affine[5] = -width * s - height * c + y;
4759 }
4760
4761 static void
4762 apply_affine_on_point (double affine[6], GdkPoint *point)
4763 {
4764   gdouble x, y;
4765
4766   x = point->x * affine[0] + point->y * affine[2] + affine[4];
4767   y = point->x * affine[1] + point->y * affine[3] + affine[5];
4768
4769   point->x = x;
4770   point->y = y;
4771 }
4772
4773 static void
4774 gtk_style_draw_polygon_with_gc (GdkWindow *window, GdkGC *gc, gint line_width,
4775                                 gboolean do_fill, GdkPoint *points, gint n_points)
4776 {
4777   gdk_gc_set_line_attributes (gc, line_width,
4778                               GDK_LINE_SOLID,
4779                               GDK_CAP_BUTT, GDK_JOIN_MITER);
4780
4781   gdk_draw_polygon (window, gc, do_fill, points, n_points);
4782   gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
4783 }
4784
4785 static void
4786 gtk_default_draw_expander (GtkStyle        *style,
4787                            GdkWindow       *window,
4788                            GtkStateType     state_type,
4789                            GdkRectangle    *area,
4790                            GtkWidget       *widget,
4791                            const gchar     *detail,
4792                            gint             x,
4793                            gint             y,
4794                            GtkExpanderStyle expander_style)
4795 {
4796   gint expander_size;
4797   GdkPoint points[3];
4798   gint i;
4799   gint line_width;
4800   gdouble affine[6];
4801   gint degrees = 0;
4802
4803   gtk_widget_style_get (widget,
4804                         "expander_size", &expander_size,
4805                         NULL);
4806   line_width = MAX (1, expander_size/7);
4807
4808   if (area)
4809     {
4810       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], area);
4811       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], area);
4812     }
4813
4814   expander_size -= (line_width * 2 - 2);
4815   points[0].x = line_width / 2;
4816   points[0].y = line_width / 2;
4817   points[1].x = expander_size / 2 + line_width / 2;
4818   points[1].y = expander_size / 2 + line_width / 2;
4819   points[2].x = line_width / 2;
4820   points[2].y = expander_size + line_width / 2;
4821
4822   switch (expander_style)
4823     {
4824     case GTK_EXPANDER_COLLAPSED:
4825       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
4826       break;
4827     case GTK_EXPANDER_SEMI_COLLAPSED:
4828       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
4829       break;
4830     case GTK_EXPANDER_SEMI_EXPANDED:
4831       degrees = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
4832       break;
4833     case GTK_EXPANDER_EXPANDED:
4834       degrees = 90;
4835       break;
4836     default:
4837       g_assert_not_reached ();
4838     }
4839
4840   create_expander_affine (affine, degrees, expander_size, x, y);
4841
4842   for (i = 0; i < 3; i++)
4843     apply_affine_on_point (affine, &points[i]);
4844
4845   if (state_type == GTK_STATE_PRELIGHT)
4846     {
4847       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4848                                       1, TRUE, points, 3);
4849     }
4850   else if (state_type == GTK_STATE_ACTIVE)
4851     {
4852       gtk_style_draw_polygon_with_gc (window, style->light_gc[GTK_STATE_ACTIVE],
4853                                       1, TRUE, points, 3);
4854       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4855                                       line_width, FALSE, points, 3);
4856     }
4857   else
4858     {
4859       gtk_style_draw_polygon_with_gc (window, style->base_gc[GTK_STATE_NORMAL],
4860                                       1, TRUE, points, 3);
4861       gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
4862                                       line_width, FALSE, points, 3);
4863     }
4864   if (area)
4865     {
4866       gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
4867       gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
4868     }
4869 }
4870
4871 typedef struct _ByteRange ByteRange;
4872
4873 struct _ByteRange
4874 {
4875   guint start;
4876   guint end;
4877 };
4878
4879 static ByteRange*
4880 range_new (guint start,
4881            guint end)
4882 {
4883   ByteRange *br = g_new (ByteRange, 1);
4884
4885   br->start = start;
4886   br->end = end;
4887   
4888   return br;
4889 }
4890
4891 static PangoLayout*
4892 get_insensitive_layout (GdkDrawable *drawable,
4893                         PangoLayout *layout)
4894 {
4895   GSList *embossed_ranges = NULL;
4896   GSList *stippled_ranges = NULL;
4897   PangoLayoutIter *iter;
4898   GSList *tmp_list = NULL;
4899   PangoLayout *new_layout;
4900   PangoAttrList *attrs;
4901   GdkBitmap *stipple = NULL;
4902   
4903   iter = pango_layout_get_iter (layout);
4904   
4905   do
4906     {
4907       PangoLayoutRun *run;
4908       PangoAttribute *attr;
4909       gboolean need_stipple = FALSE;
4910       ByteRange *br;
4911       
4912       run = pango_layout_iter_get_run (iter);
4913
4914       if (run)
4915         {
4916           tmp_list = run->item->analysis.extra_attrs;
4917
4918           while (tmp_list != NULL)
4919             {
4920               attr = tmp_list->data;
4921               switch (attr->klass->type)
4922                 {
4923                 case PANGO_ATTR_FOREGROUND:
4924                 case PANGO_ATTR_BACKGROUND:
4925                   need_stipple = TRUE;
4926                   break;
4927               
4928                 default:
4929                   break;
4930                 }
4931
4932               if (need_stipple)
4933                 break;
4934           
4935               tmp_list = g_slist_next (tmp_list);
4936             }
4937
4938           br = range_new (run->item->offset, run->item->offset + run->item->length);
4939       
4940           if (need_stipple)
4941             stippled_ranges = g_slist_prepend (stippled_ranges, br);
4942           else
4943             embossed_ranges = g_slist_prepend (embossed_ranges, br);
4944         }
4945     }
4946   while (pango_layout_iter_next_run (iter));
4947
4948   pango_layout_iter_free (iter);
4949
4950   new_layout = pango_layout_copy (layout);
4951
4952   attrs = pango_layout_get_attributes (new_layout);
4953
4954   if (attrs == NULL)
4955     {
4956       /* Create attr list if there wasn't one */
4957       attrs = pango_attr_list_new ();
4958       pango_layout_set_attributes (new_layout, attrs);
4959       pango_attr_list_unref (attrs);
4960     }
4961   
4962   tmp_list = embossed_ranges;
4963   while (tmp_list != NULL)
4964     {
4965       PangoAttribute *attr;
4966       ByteRange *br = tmp_list->data;
4967
4968       attr = gdk_pango_attr_embossed_new (TRUE);
4969
4970       attr->start_index = br->start;
4971       attr->end_index = br->end;
4972       
4973       pango_attr_list_change (attrs, attr);
4974
4975       g_free (br);
4976       
4977       tmp_list = g_slist_next (tmp_list);
4978     }
4979
4980   g_slist_free (embossed_ranges);
4981   
4982   tmp_list = stippled_ranges;
4983   while (tmp_list != NULL)
4984     {
4985       PangoAttribute *attr;
4986       ByteRange *br = tmp_list->data;
4987
4988       if (stipple == NULL)
4989         {
4990 #define gray50_width 2
4991 #define gray50_height 2
4992           static char gray50_bits[] = {
4993             0x02, 0x01
4994           };
4995
4996           stipple = gdk_bitmap_create_from_data (drawable,
4997                                                  gray50_bits, gray50_width,
4998                                                  gray50_height);
4999         }
5000       
5001       attr = gdk_pango_attr_stipple_new (stipple);
5002
5003       attr->start_index = br->start;
5004       attr->end_index = br->end;
5005       
5006       pango_attr_list_change (attrs, attr);
5007
5008       g_free (br);
5009       
5010       tmp_list = g_slist_next (tmp_list);
5011     }
5012
5013   g_slist_free (stippled_ranges);
5014   
5015   if (stipple)
5016     g_object_unref (stipple);
5017
5018   return new_layout;
5019 }
5020
5021 static void
5022 gtk_default_draw_layout (GtkStyle        *style,
5023                          GdkWindow       *window,
5024                          GtkStateType     state_type,
5025                          gboolean         use_text,
5026                          GdkRectangle    *area,
5027                          GtkWidget       *widget,
5028                          const gchar     *detail,
5029                          gint             x,
5030                          gint             y,
5031                          PangoLayout     *layout)
5032 {
5033   GdkGC *gc;
5034   
5035   g_return_if_fail (GTK_IS_STYLE (style));
5036   g_return_if_fail (window != NULL);
5037
5038   gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
5039   
5040   if (area)
5041     gdk_gc_set_clip_rectangle (gc, area);
5042
5043   if (state_type == GTK_STATE_INSENSITIVE)
5044     {
5045       PangoLayout *ins;
5046
5047       ins = get_insensitive_layout (window, layout);
5048       
5049       gdk_draw_layout (window, gc, x, y, ins);
5050
5051       g_object_unref (ins);
5052     }
5053   else
5054     {
5055       gdk_draw_layout (window, gc, x, y, layout);
5056     }
5057
5058   if (area)
5059     gdk_gc_set_clip_rectangle (gc, NULL);
5060 }
5061
5062 static void
5063 gtk_default_draw_resize_grip (GtkStyle       *style,
5064                               GdkWindow      *window,
5065                               GtkStateType    state_type,
5066                               GdkRectangle   *area,
5067                               GtkWidget      *widget,
5068                               const gchar    *detail,
5069                               GdkWindowEdge   edge,
5070                               gint            x,
5071                               gint            y,
5072                               gint            width,
5073                               gint            height)
5074 {
5075   g_return_if_fail (GTK_IS_STYLE (style));
5076   g_return_if_fail (window != NULL);
5077   
5078   if (area)
5079     {
5080       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
5081       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], area);
5082       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], area);
5083     }
5084   
5085   switch (edge)
5086     {
5087     case GDK_WINDOW_EDGE_NORTH_WEST:
5088       /* make it square */
5089       if (width < height)
5090         {
5091           height = width;
5092         }
5093       else if (height < width)
5094         {
5095           width = height;
5096         }
5097       break;
5098     case GDK_WINDOW_EDGE_NORTH:
5099       if (width < height)
5100         {
5101           height = width;
5102         }
5103       break;
5104     case GDK_WINDOW_EDGE_NORTH_EAST:
5105       /* make it square, aligning to top right */
5106       if (width < height)
5107         {
5108           height = width;
5109         }
5110       else if (height < width)
5111         {
5112           x += (width - height);
5113           width = height;
5114         }
5115       break;
5116     case GDK_WINDOW_EDGE_WEST:
5117       if (height < width)
5118         {
5119            width = height;
5120         }
5121       break;
5122     case GDK_WINDOW_EDGE_EAST:
5123       /* aligning to right */
5124       if (height < width)
5125         {
5126           x += (width - height);
5127           width = height;
5128         }
5129       break;
5130     case GDK_WINDOW_EDGE_SOUTH_WEST:
5131       /* make it square, aligning to bottom left */
5132       if (width < height)
5133         {
5134           y += (height - width);
5135           height = width;
5136         }
5137       else if (height < width)
5138         {
5139           width = height;
5140         }
5141       break;
5142     case GDK_WINDOW_EDGE_SOUTH:
5143       /* align to bottom */
5144       if (width < height)
5145         {
5146           y += (height - width);
5147           height = width;
5148         }
5149       break;
5150     case GDK_WINDOW_EDGE_SOUTH_EAST:
5151       /* make it square, aligning to bottom right */
5152       if (width < height)
5153         {
5154           y += (height - width);
5155           height = width;
5156         }
5157       else if (height < width)
5158         {
5159           x += (width - height);
5160           width = height;
5161         }
5162       break;
5163     default:
5164       g_assert_not_reached ();
5165     }
5166   /* Clear background */
5167   gtk_style_apply_default_background (style, window, FALSE,
5168                                       state_type, area,
5169                                       x, y, width, height);   
5170
5171   switch (edge)
5172     {
5173     case GDK_WINDOW_EDGE_WEST:
5174     case GDK_WINDOW_EDGE_EAST:
5175       {
5176         gint xi;
5177
5178         xi = x;
5179
5180         while (xi < x + width)
5181           {
5182             gdk_draw_line (window,
5183                            style->light_gc[state_type],
5184                            xi, y,
5185                            xi, y + height);
5186
5187             xi++;
5188             gdk_draw_line (window,
5189                            style->dark_gc[state_type],
5190                            xi, y,
5191                            xi, y + height);
5192
5193             xi += 2;
5194           }
5195       }
5196       break;
5197     case GDK_WINDOW_EDGE_NORTH:
5198     case GDK_WINDOW_EDGE_SOUTH:
5199       {
5200         gint yi;
5201
5202         yi = y;
5203
5204         while (yi < y + height)
5205           {
5206             gdk_draw_line (window,
5207                            style->light_gc[state_type],
5208                            x, yi,
5209                            x + width, yi);
5210
5211             yi++;
5212             gdk_draw_line (window,
5213                            style->dark_gc[state_type],
5214                            x, yi,
5215                            x + width, yi);
5216
5217             yi+= 2;
5218           }
5219       }
5220       break;
5221     case GDK_WINDOW_EDGE_NORTH_WEST:
5222       {
5223         gint xi, yi;
5224
5225         xi = x + width;
5226         yi = y + height;
5227
5228         while (xi > x + 3)
5229           {
5230             gdk_draw_line (window,
5231                            style->dark_gc[state_type],
5232                            xi, y,
5233                            x, yi);
5234
5235             --xi;
5236             --yi;
5237
5238             gdk_draw_line (window,
5239                            style->dark_gc[state_type],
5240                            xi, y,
5241                            x, yi);
5242
5243             --xi;
5244             --yi;
5245
5246             gdk_draw_line (window,
5247                            style->light_gc[state_type],
5248                            xi, y,
5249                            x, yi);
5250
5251             xi -= 3;
5252             yi -= 3;
5253             
5254           }
5255       }
5256       break;
5257     case GDK_WINDOW_EDGE_NORTH_EAST:
5258       {
5259         gint xi, yi;
5260
5261         xi = x;
5262         yi = y + height;
5263
5264         while (xi < (x + width - 3))
5265           {
5266             gdk_draw_line (window,
5267                            style->light_gc[state_type],
5268                            xi, y,
5269                            x + width, yi);                           
5270
5271             ++xi;
5272             --yi;
5273             
5274             gdk_draw_line (window,
5275                            style->dark_gc[state_type],
5276                            xi, y,
5277                            x + width, yi);                           
5278
5279             ++xi;
5280             --yi;
5281             
5282             gdk_draw_line (window,
5283                            style->dark_gc[state_type],
5284                            xi, y,
5285                            x + width, yi);
5286
5287             xi += 3;
5288             yi -= 3;
5289           }
5290       }
5291       break;
5292     case GDK_WINDOW_EDGE_SOUTH_WEST:
5293       {
5294         gint xi, yi;
5295
5296         xi = x + width;
5297         yi = y;
5298
5299         while (xi > x + 3)
5300           {
5301             gdk_draw_line (window,
5302                            style->dark_gc[state_type],
5303                            x, yi,
5304                            xi, y + height);
5305
5306             --xi;
5307             ++yi;
5308
5309             gdk_draw_line (window,
5310                            style->dark_gc[state_type],
5311                            x, yi,
5312                            xi, y + height);
5313
5314             --xi;
5315             ++yi;
5316
5317             gdk_draw_line (window,
5318                            style->light_gc[state_type],
5319                            x, yi,
5320                            xi, y + height);
5321
5322             xi -= 3;
5323             yi += 3;
5324             
5325           }
5326       }
5327       break;
5328     case GDK_WINDOW_EDGE_SOUTH_EAST:
5329       {
5330         gint xi, yi;
5331
5332         xi = x;
5333         yi = y;
5334
5335         while (xi < (x + width - 3))
5336           {
5337             gdk_draw_line (window,
5338                            style->light_gc[state_type],
5339                            xi, y + height,
5340                            x + width, yi);                           
5341
5342             ++xi;
5343             ++yi;
5344             
5345             gdk_draw_line (window,
5346                            style->dark_gc[state_type],
5347                            xi, y + height,
5348                            x + width, yi);                           
5349
5350             ++xi;
5351             ++yi;
5352             
5353             gdk_draw_line (window,
5354                            style->dark_gc[state_type],
5355                            xi, y + height,
5356                            x + width, yi);
5357
5358             xi += 3;
5359             yi += 3;
5360           }
5361       }
5362       break;
5363     default:
5364       g_assert_not_reached ();
5365       break;
5366     }
5367   
5368   if (area)
5369     {
5370       gdk_gc_set_clip_rectangle (style->light_gc[state_type], NULL);
5371       gdk_gc_set_clip_rectangle (style->dark_gc[state_type], NULL);
5372       gdk_gc_set_clip_rectangle (style->bg_gc[state_type], NULL);
5373     }
5374 }
5375
5376 static void
5377 gtk_style_shade (GdkColor *a,
5378                  GdkColor *b,
5379                  gdouble   k)
5380 {
5381   gdouble red;
5382   gdouble green;
5383   gdouble blue;
5384   
5385   red = (gdouble) a->red / 65535.0;
5386   green = (gdouble) a->green / 65535.0;
5387   blue = (gdouble) a->blue / 65535.0;
5388   
5389   rgb_to_hls (&red, &green, &blue);
5390   
5391   green *= k;
5392   if (green > 1.0)
5393     green = 1.0;
5394   else if (green < 0.0)
5395     green = 0.0;
5396   
5397   blue *= k;
5398   if (blue > 1.0)
5399     blue = 1.0;
5400   else if (blue < 0.0)
5401     blue = 0.0;
5402   
5403   hls_to_rgb (&red, &green, &blue);
5404   
5405   b->red = red * 65535.0;
5406   b->green = green * 65535.0;
5407   b->blue = blue * 65535.0;
5408 }
5409
5410 static void
5411 rgb_to_hls (gdouble *r,
5412             gdouble *g,
5413             gdouble *b)
5414 {
5415   gdouble min;
5416   gdouble max;
5417   gdouble red;
5418   gdouble green;
5419   gdouble blue;
5420   gdouble h, l, s;
5421   gdouble delta;
5422   
5423   red = *r;
5424   green = *g;
5425   blue = *b;
5426   
5427   if (red > green)
5428     {
5429       if (red > blue)
5430         max = red;
5431       else
5432         max = blue;
5433       
5434       if (green < blue)
5435         min = green;
5436       else
5437         min = blue;
5438     }
5439   else
5440     {
5441       if (green > blue)
5442         max = green;
5443       else
5444         max = blue;
5445       
5446       if (red < blue)
5447         min = red;
5448       else
5449         min = blue;
5450     }
5451   
5452   l = (max + min) / 2;
5453   s = 0;
5454   h = 0;
5455   
5456   if (max != min)
5457     {
5458       if (l <= 0.5)
5459         s = (max - min) / (max + min);
5460       else
5461         s = (max - min) / (2 - max - min);
5462       
5463       delta = max -min;
5464       if (red == max)
5465         h = (green - blue) / delta;
5466       else if (green == max)
5467         h = 2 + (blue - red) / delta;
5468       else if (blue == max)
5469         h = 4 + (red - green) / delta;
5470       
5471       h *= 60;
5472       if (h < 0.0)
5473         h += 360;
5474     }
5475   
5476   *r = h;
5477   *g = l;
5478   *b = s;
5479 }
5480
5481 static void
5482 hls_to_rgb (gdouble *h,
5483             gdouble *l,
5484             gdouble *s)
5485 {
5486   gdouble hue;
5487   gdouble lightness;
5488   gdouble saturation;
5489   gdouble m1, m2;
5490   gdouble r, g, b;
5491   
5492   lightness = *l;
5493   saturation = *s;
5494   
5495   if (lightness <= 0.5)
5496     m2 = lightness * (1 + saturation);
5497   else
5498     m2 = lightness + saturation - lightness * saturation;
5499   m1 = 2 * lightness - m2;
5500   
5501   if (saturation == 0)
5502     {
5503       *h = lightness;
5504       *l = lightness;
5505       *s = lightness;
5506     }
5507   else
5508     {
5509       hue = *h + 120;
5510       while (hue > 360)
5511         hue -= 360;
5512       while (hue < 0)
5513         hue += 360;
5514       
5515       if (hue < 60)
5516         r = m1 + (m2 - m1) * hue / 60;
5517       else if (hue < 180)
5518         r = m2;
5519       else if (hue < 240)
5520         r = m1 + (m2 - m1) * (240 - hue) / 60;
5521       else
5522         r = m1;
5523       
5524       hue = *h;
5525       while (hue > 360)
5526         hue -= 360;
5527       while (hue < 0)
5528         hue += 360;
5529       
5530       if (hue < 60)
5531         g = m1 + (m2 - m1) * hue / 60;
5532       else if (hue < 180)
5533         g = m2;
5534       else if (hue < 240)
5535         g = m1 + (m2 - m1) * (240 - hue) / 60;
5536       else
5537         g = m1;
5538       
5539       hue = *h - 120;
5540       while (hue > 360)
5541         hue -= 360;
5542       while (hue < 0)
5543         hue += 360;
5544       
5545       if (hue < 60)
5546         b = m1 + (m2 - m1) * hue / 60;
5547       else if (hue < 180)
5548         b = m2;
5549       else if (hue < 240)
5550         b = m1 + (m2 - m1) * (240 - hue) / 60;
5551       else
5552         b = m1;
5553       
5554       *h = r;
5555       *l = g;
5556       *s = b;
5557     }
5558 }
5559
5560
5561 /**
5562  * gtk_paint_hline:
5563  * @style: a #GtkStyle
5564  * @window: a #GdkWindow
5565  * @state_type: a state
5566  * @area: rectangle to which the output is clipped
5567  * @widget:
5568  * @detail: 
5569  * @x1: the starting x coordinate
5570  * @x2: the ending x coordinate
5571  * @y: the y coordinate
5572  * 
5573  * Draws a horizontal line from (@x1, @y) to (@x2, @y) in @window
5574  * using the given style and state.
5575  **/ 
5576 void 
5577 gtk_paint_hline (GtkStyle      *style,
5578                  GdkWindow     *window,
5579                  GtkStateType   state_type,
5580                  GdkRectangle  *area,
5581                  GtkWidget     *widget,
5582                  const gchar   *detail,
5583                  gint          x1,
5584                  gint          x2,
5585                  gint          y)
5586 {
5587   g_return_if_fail (GTK_IS_STYLE (style));
5588   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_hline != NULL);
5589   
5590   GTK_STYLE_GET_CLASS (style)->draw_hline (style, window, state_type, area, widget, detail, x1, x2, y);
5591 }
5592
5593 /**
5594  * gtk_paint_vline:
5595  * @style: a #GtkStyle
5596  * @window: a #GdkWindow
5597  * @state_type: a state
5598  * @area: rectangle to which the output is clipped
5599  * @widget:
5600  * @detail: 
5601  * @y1_: the starting y coordinate
5602  * @y2_: the ending y coordinate
5603  * @x: the x coordinate
5604  * 
5605  * Draws a vertical line from (@x, @y1_) to (@x, @y2_) in @window
5606  * using the given style and state.
5607  */
5608 void
5609 gtk_paint_vline (GtkStyle      *style,
5610                  GdkWindow     *window,
5611                  GtkStateType   state_type,
5612                  GdkRectangle  *area,
5613                  GtkWidget     *widget,
5614                  const gchar   *detail,
5615                  gint          y1,
5616                  gint          y2,
5617                  gint          x)
5618 {
5619   g_return_if_fail (GTK_IS_STYLE (style));
5620   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_vline != NULL);
5621   
5622   GTK_STYLE_GET_CLASS (style)->draw_vline (style, window, state_type, area, widget, detail, y1, y2, x);
5623 }
5624
5625 void
5626 gtk_paint_shadow (GtkStyle     *style,
5627                   GdkWindow    *window,
5628                   GtkStateType  state_type,
5629                   GtkShadowType shadow_type,
5630                   GdkRectangle *area,
5631                   GtkWidget    *widget,
5632                   const gchar  *detail,
5633                   gint          x,
5634                   gint          y,
5635                   gint          width,
5636                   gint          height)
5637 {
5638   g_return_if_fail (GTK_IS_STYLE (style));
5639   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
5640   
5641   GTK_STYLE_GET_CLASS (style)->draw_shadow (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5642 }
5643
5644 void
5645 gtk_paint_polygon (GtkStyle      *style,
5646                    GdkWindow     *window,
5647                    GtkStateType   state_type,
5648                    GtkShadowType  shadow_type,
5649                    GdkRectangle  *area,
5650                    GtkWidget     *widget,
5651                    const gchar   *detail,
5652                    GdkPoint      *points,
5653                    gint           npoints,
5654                    gboolean       fill)
5655 {
5656   g_return_if_fail (GTK_IS_STYLE (style));
5657   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow != NULL);
5658   
5659   GTK_STYLE_GET_CLASS (style)->draw_polygon (style, window, state_type, shadow_type, area, widget, detail, points, npoints, fill);
5660 }
5661
5662 void
5663 gtk_paint_arrow (GtkStyle      *style,
5664                  GdkWindow     *window,
5665                  GtkStateType   state_type,
5666                  GtkShadowType  shadow_type,
5667                  GdkRectangle  *area,
5668                  GtkWidget     *widget,
5669                  const gchar   *detail,
5670                  GtkArrowType   arrow_type,
5671                  gboolean       fill,
5672                  gint           x,
5673                  gint           y,
5674                  gint           width,
5675                  gint           height)
5676 {
5677   g_return_if_fail (GTK_IS_STYLE (style));
5678   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_arrow != NULL);
5679   
5680   GTK_STYLE_GET_CLASS (style)->draw_arrow (style, window, state_type, shadow_type, area, widget, detail, arrow_type, fill, x, y, width, height);
5681 }
5682
5683 void
5684 gtk_paint_diamond (GtkStyle      *style,
5685                    GdkWindow     *window,
5686                    GtkStateType   state_type,
5687                    GtkShadowType  shadow_type,
5688                    GdkRectangle  *area,
5689                    GtkWidget     *widget,
5690                    const gchar   *detail,
5691                    gint        x,
5692                    gint        y,
5693                    gint        width,
5694                    gint        height)
5695 {
5696   g_return_if_fail (GTK_IS_STYLE (style));
5697   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_diamond != NULL);
5698   
5699   GTK_STYLE_GET_CLASS (style)->draw_diamond (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5700 }
5701
5702 /**
5703  * gtk_paint_string:
5704  * @style: a #GtkStyle
5705  * @window: a #GdkWindow
5706  * @state_type: a state
5707  * @area: clip rectangle
5708  * @widget: the widget
5709  * @detail: a style detail
5710  * @x: x origin
5711  * @y: y origin
5712  * @string: the string to draw
5713  * 
5714  * Draws a text string on @window with the given parameters.
5715  *
5716  * This function is deprecated, use gtk_paint_layout() instead.
5717  */
5718 void
5719 gtk_paint_string (GtkStyle      *style,
5720                   GdkWindow     *window,
5721                   GtkStateType   state_type,
5722                   GdkRectangle  *area,
5723                   GtkWidget     *widget,
5724                   const gchar   *detail,
5725                   gint           x,
5726                   gint           y,
5727                   const gchar   *string)
5728 {
5729   g_return_if_fail (GTK_IS_STYLE (style));
5730   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_string != NULL);
5731   
5732   GTK_STYLE_GET_CLASS (style)->draw_string (style, window, state_type, area, widget, detail, x, y, string);
5733 }
5734
5735 void
5736 gtk_paint_box (GtkStyle      *style,
5737                GdkWindow     *window,
5738                GtkStateType   state_type,
5739                GtkShadowType  shadow_type,
5740                GdkRectangle  *area,
5741                GtkWidget     *widget,
5742                const gchar   *detail,
5743                gint           x,
5744                gint           y,
5745                gint           width,
5746                gint           height)
5747 {
5748   g_return_if_fail (GTK_IS_STYLE (style));
5749   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box != NULL);
5750   
5751   GTK_STYLE_GET_CLASS (style)->draw_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5752 }
5753
5754 void
5755 gtk_paint_flat_box (GtkStyle      *style,
5756                     GdkWindow     *window,
5757                     GtkStateType   state_type,
5758                     GtkShadowType  shadow_type,
5759                     GdkRectangle  *area,
5760                     GtkWidget     *widget,
5761                     const gchar   *detail,
5762                     gint           x,
5763                     gint           y,
5764                     gint           width,
5765                     gint           height)
5766 {
5767   g_return_if_fail (GTK_IS_STYLE (style));
5768   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_flat_box != NULL);
5769   
5770   GTK_STYLE_GET_CLASS (style)->draw_flat_box (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5771 }
5772
5773 void
5774 gtk_paint_check (GtkStyle      *style,
5775                  GdkWindow     *window,
5776                  GtkStateType   state_type,
5777                  GtkShadowType  shadow_type,
5778                  GdkRectangle  *area,
5779                  GtkWidget     *widget,
5780                  const gchar   *detail,
5781                  gint           x,
5782                  gint           y,
5783                  gint           width,
5784                  gint           height)
5785 {
5786   g_return_if_fail (GTK_IS_STYLE (style));
5787   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_check != NULL);
5788   
5789   GTK_STYLE_GET_CLASS (style)->draw_check (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5790 }
5791
5792 void
5793 gtk_paint_option (GtkStyle      *style,
5794                   GdkWindow     *window,
5795                   GtkStateType   state_type,
5796                   GtkShadowType  shadow_type,
5797                   GdkRectangle  *area,
5798                   GtkWidget     *widget,
5799                   const gchar   *detail,
5800                   gint           x,
5801                   gint           y,
5802                   gint           width,
5803                   gint           height)
5804 {
5805   g_return_if_fail (GTK_IS_STYLE (style));
5806   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_option != NULL);
5807   
5808   GTK_STYLE_GET_CLASS (style)->draw_option (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5809 }
5810
5811 void
5812 gtk_paint_tab (GtkStyle      *style,
5813                GdkWindow     *window,
5814                GtkStateType   state_type,
5815                GtkShadowType  shadow_type,
5816                GdkRectangle  *area,
5817                GtkWidget     *widget,
5818                const gchar   *detail,
5819                gint           x,
5820                gint           y,
5821                gint           width,
5822                gint           height)
5823 {
5824   g_return_if_fail (GTK_IS_STYLE (style));
5825   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_tab != NULL);
5826   
5827   GTK_STYLE_GET_CLASS (style)->draw_tab (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height);
5828 }
5829
5830 void
5831 gtk_paint_shadow_gap (GtkStyle       *style,
5832                       GdkWindow      *window,
5833                       GtkStateType    state_type,
5834                       GtkShadowType   shadow_type,
5835                       GdkRectangle   *area,
5836                       GtkWidget      *widget,
5837                       gchar          *detail,
5838                       gint            x,
5839                       gint            y,
5840                       gint            width,
5841                       gint            height,
5842                       GtkPositionType gap_side,
5843                       gint            gap_x,
5844                       gint            gap_width)
5845 {
5846   g_return_if_fail (GTK_IS_STYLE (style));
5847   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_shadow_gap != NULL);
5848   
5849   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);
5850 }
5851
5852
5853 void
5854 gtk_paint_box_gap (GtkStyle       *style,
5855                    GdkWindow      *window,
5856                    GtkStateType    state_type,
5857                    GtkShadowType   shadow_type,
5858                    GdkRectangle   *area,
5859                    GtkWidget      *widget,
5860                    gchar          *detail,
5861                    gint            x,
5862                    gint            y,
5863                    gint            width,
5864                    gint            height,
5865                    GtkPositionType gap_side,
5866                    gint            gap_x,
5867                    gint            gap_width)
5868 {
5869   g_return_if_fail (GTK_IS_STYLE (style));
5870   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_box_gap != NULL);
5871   
5872   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);
5873 }
5874
5875 void
5876 gtk_paint_extension (GtkStyle       *style,
5877                      GdkWindow      *window,
5878                      GtkStateType    state_type,
5879                      GtkShadowType   shadow_type,
5880                      GdkRectangle   *area,
5881                      GtkWidget      *widget,
5882                      gchar          *detail,
5883                      gint            x,
5884                      gint            y,
5885                      gint            width,
5886                      gint            height,
5887                      GtkPositionType gap_side)
5888 {
5889   g_return_if_fail (GTK_IS_STYLE (style));
5890   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_extension != NULL);
5891   
5892   GTK_STYLE_GET_CLASS (style)->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, gap_side);
5893 }
5894
5895 void
5896 gtk_paint_focus (GtkStyle      *style,
5897                  GdkWindow     *window,
5898                  GtkStateType   state_type,
5899                  GdkRectangle  *area,
5900                  GtkWidget     *widget,
5901                  const gchar   *detail,
5902                  gint           x,
5903                  gint           y,
5904                  gint           width,
5905                  gint           height)
5906 {
5907   g_return_if_fail (GTK_IS_STYLE (style));
5908   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_focus != NULL);
5909   
5910   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type, area, widget, detail, x, y, width, height);
5911 }
5912
5913 void
5914 gtk_paint_slider (GtkStyle      *style,
5915                   GdkWindow     *window,
5916                   GtkStateType   state_type,
5917                   GtkShadowType  shadow_type,
5918                   GdkRectangle  *area,
5919                   GtkWidget     *widget,
5920                   const gchar   *detail,
5921                   gint           x,
5922                   gint           y,
5923                   gint           width,
5924                   gint           height,
5925                   GtkOrientation orientation)
5926 {
5927   g_return_if_fail (GTK_IS_STYLE (style));
5928   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_slider != NULL);
5929   
5930   GTK_STYLE_GET_CLASS (style)->draw_slider (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
5931 }
5932
5933 void
5934 gtk_paint_handle (GtkStyle      *style,
5935                   GdkWindow     *window,
5936                   GtkStateType   state_type,
5937                   GtkShadowType  shadow_type,
5938                   GdkRectangle  *area,
5939                   GtkWidget     *widget,
5940                   const gchar   *detail,
5941                   gint           x,
5942                   gint           y,
5943                   gint           width,
5944                   gint           height,
5945                   GtkOrientation orientation)
5946 {
5947   g_return_if_fail (GTK_IS_STYLE (style));
5948   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_handle != NULL);
5949   
5950   GTK_STYLE_GET_CLASS (style)->draw_handle (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, orientation);
5951 }
5952
5953 void
5954 gtk_paint_expander (GtkStyle        *style,
5955                     GdkWindow       *window,
5956                     GtkStateType     state_type,
5957                     GdkRectangle    *area,
5958                     GtkWidget       *widget,
5959                     const gchar     *detail,
5960                     gint             x,
5961                     gint             y,
5962                     GtkExpanderStyle expander_style)
5963 {
5964   g_return_if_fail (GTK_IS_STYLE (style));
5965   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_expander != NULL);
5966   
5967   GTK_STYLE_GET_CLASS (style)->draw_expander (style, window, state_type, area,
5968                                               widget, detail, x, y, expander_style);
5969 }
5970
5971 void
5972 gtk_paint_layout (GtkStyle        *style,
5973                   GdkWindow       *window,
5974                   GtkStateType     state_type,
5975                   gboolean         use_text,
5976                   GdkRectangle    *area,
5977                   GtkWidget       *widget,
5978                   const gchar     *detail,
5979                   gint             x,
5980                   gint             y,
5981                   PangoLayout     *layout)
5982 {
5983   g_return_if_fail (GTK_IS_STYLE (style));
5984   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_layout != NULL);
5985   
5986   GTK_STYLE_GET_CLASS (style)->draw_layout (style, window, state_type, use_text, area,
5987                                             widget, detail, x, y, layout);
5988 }
5989
5990 void
5991 gtk_paint_resize_grip (GtkStyle      *style,
5992                        GdkWindow     *window,
5993                        GtkStateType   state_type,
5994                        GdkRectangle  *area,
5995                        GtkWidget     *widget,
5996                        const gchar   *detail,
5997                        GdkWindowEdge  edge,
5998                        gint           x,
5999                        gint           y,
6000                        gint           width,
6001                        gint           height)
6002
6003 {
6004   g_return_if_fail (GTK_IS_STYLE (style));
6005   g_return_if_fail (GTK_STYLE_GET_CLASS (style)->draw_resize_grip != NULL);
6006
6007   GTK_STYLE_GET_CLASS (style)->draw_resize_grip (style, window, state_type,
6008                                                  area, widget, detail,
6009                                                  edge, x, y, width, height);
6010 }
6011
6012 /**
6013  * gtk_border_copy:
6014  * @border_: a #GtkBorder.
6015  * @returns: a copy of @border_.
6016  *
6017  * Copies a #GtkBorder structure.
6018  **/
6019 GtkBorder *
6020 gtk_border_copy (const GtkBorder *border)
6021 {
6022   return (GtkBorder *)g_memdup (border, sizeof (GtkBorder));
6023 }
6024
6025 /**
6026  * gtk_border_free:
6027  * @border_: a #GtkBorder.
6028  * 
6029  * Frees a #GtkBorder structure.
6030  **/
6031 void
6032 gtk_border_free (GtkBorder *border)
6033 {
6034   g_free (border);
6035 }
6036
6037 GType
6038 gtk_border_get_type (void)
6039 {
6040   static GType our_type = 0;
6041   
6042   if (our_type == 0)
6043     our_type = g_boxed_type_register_static ("GtkBorder",
6044                                              (GBoxedCopyFunc) gtk_border_copy,
6045                                              (GBoxedFreeFunc) gtk_border_free);
6046
6047   return our_type;
6048 }
6049
6050 static GdkFont *
6051 gtk_style_get_font_internal (GtkStyle *style)
6052 {
6053   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
6054
6055   if (style->private_font && style->private_font_desc)
6056     {
6057       if (!style->font_desc ||
6058           !pango_font_description_equal (style->private_font_desc, style->font_desc))
6059         {
6060           gdk_font_unref (style->private_font);
6061           style->private_font = NULL;
6062           
6063           if (style->private_font_desc)
6064             {
6065               pango_font_description_free (style->private_font_desc);
6066               style->private_font_desc = NULL;
6067             }
6068         }
6069     }
6070   
6071   if (!style->private_font)
6072     {
6073       GdkDisplay *display;
6074
6075       if (style->colormap)
6076         {
6077           display = gdk_screen_get_display (gdk_colormap_get_screen (style->colormap));
6078         }
6079       else
6080         {
6081           display = gdk_display_get_default ();
6082           GTK_NOTE (MULTIHEAD,
6083                     g_warning ("gtk_style_get_font() should not be called on an unattached style"));
6084         }
6085       
6086       if (style->font_desc)
6087         {
6088           style->private_font = gdk_font_from_description_for_display (display, style->font_desc);
6089           style->private_font_desc = pango_font_description_copy (style->font_desc);
6090         }
6091
6092       if (!style->private_font)
6093         style->private_font = gdk_font_load_for_display (display, "fixed");
6094       
6095       if (!style->private_font) 
6096         g_error ("Unable to load \"fixed\" font");
6097     }
6098
6099   return style->private_font;
6100 }
6101
6102 /**
6103  * gtk_style_get_font:
6104  * @style: a #GtkStyle
6105  * 
6106  * Gets the #GdkFont to use for the given style. This is
6107  * meant only as a replacement for direct access to @style->font
6108  * and should not be used in new code. New code should
6109  * use @style->font_desc instead.
6110  * 
6111  * Return value: the #GdkFont for the style. This font is owned
6112  *   by the style; if you want to keep around a copy, you must
6113  *   call gdk_font_ref().
6114  **/
6115 GdkFont *
6116 gtk_style_get_font (GtkStyle *style)
6117 {
6118   g_return_val_if_fail (GTK_IS_STYLE (style), NULL);
6119
6120   return gtk_style_get_font_internal (style);
6121 }
6122
6123 /**
6124  * gtk_style_set_font:
6125  * @style: a #GtkStyle.
6126  * @font: a #GdkFont, or %NULL to use the #GdkFont corresponding
6127  *   to style->font_desc.
6128  * 
6129  * Sets the #GdkFont to use for a given style. This is
6130  * meant only as a replacement for direct access to style->font
6131  * and should not be used in new code. New code should
6132  * use style->font_desc instead.
6133  **/
6134 void
6135 gtk_style_set_font (GtkStyle *style,
6136                     GdkFont  *font)
6137 {
6138   GdkFont *old_font;
6139
6140   g_return_if_fail (GTK_IS_STYLE (style));
6141
6142   old_font = style->private_font;
6143
6144   style->private_font = font;
6145   if (font)
6146     gdk_font_ref (font);
6147
6148   if (old_font)
6149     gdk_font_unref (old_font);
6150
6151   if (style->private_font_desc)
6152     {
6153       pango_font_description_free (style->private_font_desc);
6154       style->private_font_desc = NULL;
6155     }
6156 }
6157
6158 typedef struct _CursorInfo CursorInfo;
6159
6160 struct _CursorInfo
6161 {
6162   GType for_type;
6163   GdkGC *primary_gc;
6164   GdkGC *secondary_gc;
6165 };
6166
6167 static void
6168 style_unrealize_cursor_gcs (GtkStyle *style)
6169 {
6170   CursorInfo *
6171   
6172   cursor_info = g_object_get_data (G_OBJECT (style), "gtk-style-cursor-info");
6173   if (cursor_info)
6174     {
6175       if (cursor_info->primary_gc)
6176         gtk_gc_release (cursor_info->primary_gc);
6177
6178       if (cursor_info->secondary_gc)
6179         gtk_gc_release (cursor_info->secondary_gc);
6180       
6181       g_free (cursor_info);
6182       g_object_set_data (G_OBJECT (style), "gtk-style-cursor-info", NULL);
6183     }
6184 }
6185
6186 static GdkGC *
6187 make_cursor_gc (GtkWidget   *widget,
6188                 const gchar *property_name,
6189                 GdkColor    *fallback)
6190 {
6191   GdkGCValues gc_values;
6192   GdkGCValuesMask gc_values_mask;
6193   GdkColor *cursor_color;
6194
6195   gtk_widget_style_get (widget, property_name, &cursor_color, NULL);
6196   
6197   gc_values_mask = GDK_GC_FOREGROUND;
6198   if (cursor_color)
6199     {
6200       gc_values.foreground = *cursor_color;
6201       gdk_color_free (cursor_color);
6202     }
6203   else
6204     gc_values.foreground = *fallback;
6205   
6206   gdk_rgb_find_color (widget->style->colormap, &gc_values.foreground);
6207   return gtk_gc_get (widget->style->depth, widget->style->colormap, &gc_values, gc_values_mask);
6208 }
6209
6210 /**
6211  * _gtk_get_insertion_cursor_gc:
6212  * @widget: a #GtkWidget
6213  * @is_primary: if the cursor should be the primary cursor color.
6214  * 
6215  * Get a GC suitable for drawing the primary or secondary text
6216  * cursor.
6217  *
6218  * Note: the return value is ref'ed because calls to this function
6219  *  on other widgets could result in this the GC being released
6220  *  which would be an unexpected side effect. If made public,
6221  *  this function should possibly be called create_insertion_cursor_gc().
6222  *
6223  * Return value: an appropriate #GdkGC. Call g_object_unref() on
6224  *   the gc when you are done with it; this GC may be shared with
6225  *   other users, so you must not modify the GC except for temporarily
6226  *   setting the clip before drawing with the GC, and then unsetting the clip
6227  *   again afterwards.
6228  **/
6229 GdkGC *
6230 _gtk_get_insertion_cursor_gc (GtkWidget *widget,
6231                               gboolean   is_primary)
6232 {
6233   CursorInfo *cursor_info;
6234
6235   cursor_info = g_object_get_data (G_OBJECT (widget->style), "gtk-style-cursor-info");
6236   if (!cursor_info)
6237     {
6238       cursor_info = g_new (CursorInfo, 1);
6239       g_object_set_data (G_OBJECT (widget->style), "gtk-style-cursor-info", cursor_info);
6240       cursor_info->primary_gc = NULL;
6241       cursor_info->secondary_gc = NULL;
6242       cursor_info->for_type = G_TYPE_INVALID;
6243     }
6244
6245   /* We have to keep track of the type because gtk_widget_style_get()
6246    * can return different results when called on the same property and
6247    * same style but for different widgets. :-(. That is,
6248    * GtkEntry::cursor-color = "red" in a style will modify the cursor
6249    * color for entries but not for text view.
6250    */
6251   if (cursor_info->for_type != G_OBJECT_TYPE (widget))
6252     {
6253       cursor_info->for_type = G_OBJECT_TYPE (widget);
6254       if (cursor_info->primary_gc)
6255         {
6256           gtk_gc_release (cursor_info->primary_gc);
6257           cursor_info->primary_gc = NULL;
6258         }
6259       if (cursor_info->secondary_gc)
6260         {
6261           gtk_gc_release (cursor_info->secondary_gc);
6262           cursor_info->secondary_gc = NULL;
6263         }
6264     }
6265
6266   if (is_primary)
6267     {
6268       if (!cursor_info->primary_gc)
6269         cursor_info->primary_gc = make_cursor_gc (widget,
6270                                                   "cursor-color",
6271                                                   &widget->style->black);
6272         
6273       return g_object_ref (cursor_info->primary_gc);
6274     }
6275   else
6276     {
6277       static GdkColor gray = { 0, 0x8888, 0x8888, 0x8888 };
6278       
6279       if (!cursor_info->secondary_gc)
6280         cursor_info->secondary_gc = make_cursor_gc (widget,
6281                                                     "secondary-cursor-color",
6282                                                     &gray);
6283         
6284       return g_object_ref (cursor_info->secondary_gc);
6285     }
6286 }
6287
6288 /**
6289  * _gtk_draw_insertion_cursor:
6290  * @widget: a #GtkWidget
6291  * @drawable: a #GdkDrawable
6292  * @gc: a #GdkGC
6293  * @location: location where to draw the cursor (@location->width is ignored)
6294  * @direction: whether the cursor is left-to-right or
6295  *             right-to-left. Should never be #GTK_TEXT_DIR_NONE
6296  * @draw_arrow: %TRUE to draw a directional arrow on the
6297  *        cursor. Should be %FALSE unless the cursor is split.
6298  * 
6299  * Draws a text caret on @drawable at @location. This is not a style function
6300  * but merely a convenience function for drawing the standard cursor shape.
6301  **/
6302 void
6303 _gtk_draw_insertion_cursor (GtkWidget        *widget,
6304                             GdkDrawable      *drawable,
6305                             GdkGC            *gc,
6306                             GdkRectangle     *location,
6307                             GtkTextDirection  direction,
6308                             gboolean          draw_arrow)
6309 {
6310   gint stem_width;
6311   gint arrow_width;
6312   gint x, y;
6313   gint i;
6314   gfloat cursor_aspect_ratio;
6315   gint offset;
6316   
6317   g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
6318   
6319   gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
6320   
6321   stem_width = location->height * cursor_aspect_ratio + 1;
6322   arrow_width = stem_width + 1;
6323
6324   /* put (stem_width % 2) on the proper side of the cursor */
6325   if (direction == GTK_TEXT_DIR_LTR)
6326     offset = stem_width / 2;
6327   else
6328     offset = stem_width - stem_width / 2;
6329   
6330   for (i = 0; i < stem_width; i++)
6331     gdk_draw_line (drawable, gc,
6332                    location->x + i - offset, location->y,
6333                    location->x + i - offset, location->y + location->height - 1);
6334
6335   if (draw_arrow)
6336     {
6337       if (direction == GTK_TEXT_DIR_RTL)
6338         {
6339           x = location->x - offset - 1;
6340           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6341   
6342           for (i = 0; i < arrow_width; i++)
6343             {
6344               gdk_draw_line (drawable, gc,
6345                              x, y + i + 1,
6346                              x, y + 2 * arrow_width - i - 1);
6347               x --;
6348             }
6349         }
6350       else if (direction == GTK_TEXT_DIR_LTR)
6351         {
6352           x = location->x + stem_width - offset;
6353           y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
6354   
6355           for (i = 0; i < arrow_width; i++) 
6356             {
6357               gdk_draw_line (drawable, gc,
6358                              x, y + i + 1,
6359                              x, y + 2 * arrow_width - i - 1);
6360               x++;
6361             }
6362         }
6363     }
6364 }