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