]> Pileus Git - ~andy/gtk/blob - gtk/gtkstyle.c
we make an active server grab now, this way we can change the cursor
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <math.h>
19 #include "gtkgc.h"
20 #include "gtkstyle.h"
21 #include "gtkwidget.h"
22
23
24 #define LIGHTNESS_MULT  1.3
25 #define DARKNESS_MULT   0.7
26
27
28 typedef struct _GtkStyleKey GtkStyleKey;
29
30 struct _GtkStyleKey
31 {
32   GdkColor fg[5];
33   GdkColor bg[5];
34   GdkColor text[5];
35   GdkColor base[5];
36
37   GdkPixmap *bg_pixmap[5];
38
39   GdkFont *font;
40
41   gint depth;
42   GdkColormap *colormap;
43   GtkStyleClass *klass;
44 };
45
46
47 static void         gtk_style_init         (GtkStyle    *style);
48 static void         gtk_styles_init        (void);
49 static void         gtk_style_remove       (GtkStyle    *style);
50 static GtkStyle*    gtk_style_find         (GtkStyle    *style,
51                                             GdkColormap *cmap,
52                                             gint         depth);
53 static GtkStyle*    gtk_style_new_from_key (GtkStyleKey *key);
54 static GtkStyleKey* gtk_style_key_dup      (GtkStyleKey *key);
55 static void         gtk_style_destroy      (GtkStyle    *style);
56 static void         gtk_style_key_destroy  (GtkStyleKey *key);
57 static guint        gtk_style_key_hash     (GtkStyleKey *key);
58 static guint        gtk_style_value_hash   (GtkStyle    *style);
59 static gint         gtk_style_key_compare  (GtkStyleKey *a,
60                                             GtkStyleKey *b);
61
62 static void gtk_default_draw_hline   (GtkStyle      *style,
63                                       GdkWindow     *window,
64                                       GtkStateType   state_type,
65                                       gint           x1,
66                                       gint           x2,
67                                       gint           y);
68 static void gtk_default_draw_vline   (GtkStyle      *style,
69                                       GdkWindow     *window,
70                                       GtkStateType   state_type,
71                                       gint           y1,
72                                       gint           y2,
73                                       gint           x);
74 static void gtk_default_draw_shadow  (GtkStyle      *style,
75                                       GdkWindow     *window,
76                                       GtkStateType   state_type,
77                                       GtkShadowType  shadow_type,
78                                       gint           x,
79                                       gint           y,
80                                       gint           width,
81                                       gint           height);
82 static void gtk_default_draw_polygon (GtkStyle      *style,
83                                       GdkWindow     *window,
84                                       GtkStateType   state_type,
85                                       GtkShadowType  shadow_type,
86                                       GdkPoint      *points,
87                                       gint           npoints,
88                                       gint           fill);
89 static void gtk_default_draw_arrow   (GtkStyle      *style,
90                                       GdkWindow     *window,
91                                       GtkStateType   state_type,
92                                       GtkShadowType  shadow_type,
93                                       GtkArrowType   arrow_type,
94                                       gint           fill,
95                                       gint           x,
96                                       gint           y,
97                                       gint           width,
98                                       gint           height);
99 static void gtk_default_draw_diamond (GtkStyle      *style,
100                                       GdkWindow     *window,
101                                       GtkStateType   state_type,
102                                       GtkShadowType  shadow_type,
103                                       gint           x,
104                                       gint           y,
105                                       gint           width,
106                                       gint           height);
107 static void gtk_default_draw_oval    (GtkStyle      *style,
108                                       GdkWindow     *window,
109                                       GtkStateType   state_type,
110                                       GtkShadowType  shadow_type,
111                                       gint           x,
112                                       gint           y,
113                                       gint           width,
114                                       gint           height);
115 static void gtk_default_draw_string  (GtkStyle      *style,
116                                       GdkWindow     *window,
117                                       GtkStateType   state_type,
118                                       gint           x,
119                                       gint           y,
120                                       const gchar   *string);
121
122 static void gtk_style_shade (GdkColor *a, GdkColor *b, gdouble k);
123 static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b);
124 static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s);
125
126
127 static GtkStyleClass default_class =
128 {
129   2,
130   2,
131   gtk_default_draw_hline,
132   gtk_default_draw_vline,
133   gtk_default_draw_shadow,
134   gtk_default_draw_polygon,
135   gtk_default_draw_arrow,
136   gtk_default_draw_diamond,
137   gtk_default_draw_oval,
138   gtk_default_draw_string,
139 };
140
141 static GdkColor gtk_default_normal_fg =      { 0,      0,      0,      0 };
142 static GdkColor gtk_default_active_fg =      { 0,      0,      0,      0 };
143 static GdkColor gtk_default_prelight_fg =    { 0,      0,      0,      0 };
144 static GdkColor gtk_default_selected_fg =    { 0, 0xffff, 0xffff, 0xffff };
145 static GdkColor gtk_default_insensitive_fg = { 0, 0x7530, 0x7530, 0x7530 };
146
147 static GdkColor gtk_default_normal_bg =      { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
148 static GdkColor gtk_default_active_bg =      { 0, 0xc350, 0xc350, 0xc350 };
149 static GdkColor gtk_default_prelight_bg =    { 0, 0xea60, 0xea60, 0xea60 };
150 static GdkColor gtk_default_selected_bg =    { 0,      0,      0, 0x9c40 };
151 static GdkColor gtk_default_insensitive_bg = { 0, 0xd6d6, 0xd6d6, 0xd6d6 };
152
153 static GdkFont *default_font = NULL;
154
155 static gint initialize = TRUE;
156 static GCache *style_cache = NULL;
157 static GSList *unattached_styles = NULL;
158
159 static GMemChunk *key_mem_chunk = NULL;
160
161 GtkStyle*
162 gtk_style_copy (GtkStyle     *style)
163 {
164   GtkStyle *new_style;
165   guint i;
166
167   g_return_val_if_fail (style != NULL, NULL);
168
169   new_style = gtk_style_new ();
170
171   for (i = 0; i < 5; i++)
172     {
173       new_style->fg[i] = style->fg[i];
174       new_style->bg[i] = style->bg[i];
175       new_style->text[i] = style->text[i];
176       new_style->base[i] = style->base[i];
177
178       new_style->bg_pixmap[i] = style->bg_pixmap[i];
179     }
180
181   new_style->font = style->font;
182   gdk_font_ref (new_style->font);
183
184   return new_style;
185 }
186
187 GtkStyle*
188 gtk_style_new ()
189 {
190   GtkStyle *style;
191   gint i;
192
193   style = g_new0 (GtkStyle, 1);
194
195   if (!default_font)
196     default_font =
197       gdk_font_load ("-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*");
198
199   style->font = default_font;
200   gdk_font_ref (style->font);
201
202   style->ref_count = 1;
203   style->attach_count = 0;
204   style->colormap = NULL;
205   style->depth = -1;
206   style->klass = &default_class;
207
208   style->black.red = 0;
209   style->black.green = 0;
210   style->black.blue = 0;
211
212   style->white.red = 65535;
213   style->white.green = 65535;
214   style->white.blue = 65535;
215
216   style->black_gc = NULL;
217   style->white_gc = NULL;
218
219   style->fg[GTK_STATE_NORMAL] = gtk_default_normal_fg;
220   style->fg[GTK_STATE_ACTIVE] = gtk_default_active_fg;
221   style->fg[GTK_STATE_PRELIGHT] = gtk_default_prelight_fg;
222   style->fg[GTK_STATE_SELECTED] = gtk_default_selected_fg;
223   style->fg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_fg;
224
225   style->bg[GTK_STATE_NORMAL] = gtk_default_normal_bg;
226   style->bg[GTK_STATE_ACTIVE] = gtk_default_active_bg;
227   style->bg[GTK_STATE_PRELIGHT] = gtk_default_prelight_bg;
228   style->bg[GTK_STATE_SELECTED] = gtk_default_selected_bg;
229   style->bg[GTK_STATE_INSENSITIVE] = gtk_default_insensitive_bg;
230
231   for (i = 0; i < 5; i++)
232     {
233       style->text[i] = style->fg[i];
234       style->base[i] = style->white;
235     }
236
237   for (i = 0; i < 5; i++)
238     style->bg_pixmap[i] = NULL;
239
240   for (i = 0; i < 5; i++)
241     {
242       style->fg_gc[i] = NULL;
243       style->bg_gc[i] = NULL;
244       style->light_gc[i] = NULL;
245       style->dark_gc[i] = NULL;
246       style->mid_gc[i] = NULL;
247       style->text_gc[i] = NULL;
248       style->base_gc[i] = NULL;
249     }
250
251   unattached_styles = g_slist_prepend (unattached_styles, style);
252
253   return style;
254 }
255
256 GtkStyle*
257 gtk_style_attach (GtkStyle  *style,
258                   GdkWindow *window)
259 {
260   GtkStyle *new_style;
261   GdkColormap *colormap;
262   gint depth;
263
264   g_return_val_if_fail (style != NULL, NULL);
265   g_return_val_if_fail (window != NULL, NULL);
266
267   colormap = gdk_window_get_colormap (window);
268   gdk_window_get_geometry (window, NULL, NULL, NULL, NULL, &depth);
269
270   new_style = gtk_style_find (style, colormap, depth);
271
272   if (new_style && (new_style != style))
273     {
274       gtk_style_unref (style);
275       style = new_style;
276       gtk_style_ref (style);
277     }
278
279   if (style->attach_count == 0)
280     unattached_styles = g_slist_remove (unattached_styles, style);
281
282   style->attach_count += 1;
283
284   return style;
285 }
286
287 void
288 gtk_style_detach (GtkStyle *style)
289 {
290   gint i;
291
292   g_return_if_fail (style != NULL);
293
294   style->attach_count -= 1;
295   if (style->attach_count == 0)
296     {
297       unattached_styles = g_slist_prepend (unattached_styles, style);
298
299       gtk_gc_release (style->black_gc);
300       gtk_gc_release (style->white_gc);
301
302       style->black_gc = NULL;
303       style->white_gc = NULL;
304
305       for (i = 0; i < 5; i++)
306         {
307           gtk_gc_release (style->fg_gc[i]);
308           gtk_gc_release (style->bg_gc[i]);
309           gtk_gc_release (style->light_gc[i]);
310           gtk_gc_release (style->dark_gc[i]);
311           gtk_gc_release (style->mid_gc[i]);
312           gtk_gc_release (style->text_gc[i]);
313           gtk_gc_release (style->base_gc[i]);
314
315           style->fg_gc[i] = NULL;
316           style->bg_gc[i] = NULL;
317           style->light_gc[i] = NULL;
318           style->dark_gc[i] = NULL;
319           style->mid_gc[i] = NULL;
320           style->text_gc[i] = NULL;
321           style->base_gc[i] = NULL;
322         }
323
324       style->depth = -1;
325       style->colormap = NULL;
326     }
327
328   gtk_style_remove (style);
329 }
330
331 GtkStyle*
332 gtk_style_ref (GtkStyle *style)
333 {
334   g_return_val_if_fail (style != NULL, NULL);
335
336   style->ref_count += 1;
337   return style;
338 }
339
340 void
341 gtk_style_unref (GtkStyle *style)
342 {
343   g_return_if_fail (style != NULL);
344
345   style->ref_count -= 1;
346   if (style->ref_count == 0)
347     gtk_style_destroy (style);
348 }
349
350 void
351 gtk_style_set_background (GtkStyle     *style,
352                           GdkWindow    *window,
353                           GtkStateType  state_type)
354 {
355   GdkPixmap *pixmap;
356   gint parent_relative;
357
358   g_return_if_fail (style != NULL);
359   g_return_if_fail (window != NULL);
360
361   if (style->bg_pixmap[state_type])
362     {
363       if (style->bg_pixmap[state_type] == (GdkPixmap*) GDK_PARENT_RELATIVE)
364         {
365           pixmap = NULL;
366           parent_relative = TRUE;
367         }
368       else
369         {
370           pixmap = style->bg_pixmap[state_type];
371           parent_relative = FALSE;
372         }
373
374       gdk_window_set_back_pixmap (window, pixmap, parent_relative);
375     }
376   else
377     gdk_window_set_background (window, &style->bg[state_type]);
378 }
379
380
381 void
382 gtk_draw_hline (GtkStyle     *style,
383                 GdkWindow    *window,
384                 GtkStateType  state_type,
385                 gint          x1,
386                 gint          x2,
387                 gint          y)
388 {
389   g_return_if_fail (style != NULL);
390   g_return_if_fail (style->klass != NULL);
391   g_return_if_fail (style->klass->draw_hline != NULL);
392
393   (*style->klass->draw_hline) (style, window, state_type, x1, x2, y);
394 }
395
396
397 void
398 gtk_draw_vline (GtkStyle     *style,
399                 GdkWindow    *window,
400                 GtkStateType  state_type,
401                 gint          y1,
402                 gint          y2,
403                 gint          x)
404 {
405   g_return_if_fail (style != NULL);
406   g_return_if_fail (style->klass != NULL);
407   g_return_if_fail (style->klass->draw_vline != NULL);
408
409   (*style->klass->draw_vline) (style, window, state_type, y1, y2, x);
410 }
411
412
413 void
414 gtk_draw_shadow (GtkStyle      *style,
415                  GdkWindow     *window,
416                  GtkStateType   state_type,
417                  GtkShadowType  shadow_type,
418                  gint           x,
419                  gint           y,
420                  gint           width,
421                  gint           height)
422 {
423   g_return_if_fail (style != NULL);
424   g_return_if_fail (style->klass != NULL);
425   g_return_if_fail (style->klass->draw_shadow != NULL);
426
427   (*style->klass->draw_shadow) (style, window, state_type, shadow_type, x, y, width, height);
428 }
429
430 void
431 gtk_draw_polygon (GtkStyle      *style,
432                   GdkWindow     *window,
433                   GtkStateType   state_type,
434                   GtkShadowType  shadow_type,
435                   GdkPoint      *points,
436                   gint           npoints,
437                   gint           fill)
438 {
439   g_return_if_fail (style != NULL);
440   g_return_if_fail (style->klass != NULL);
441   g_return_if_fail (style->klass->draw_shadow != NULL);
442
443   (*style->klass->draw_polygon) (style, window, state_type, shadow_type, points, npoints, fill);
444 }
445
446 void
447 gtk_draw_arrow (GtkStyle      *style,
448                 GdkWindow     *window,
449                 GtkStateType   state_type,
450                 GtkShadowType  shadow_type,
451                 GtkArrowType   arrow_type,
452                 gint           fill,
453                 gint           x,
454                 gint           y,
455                 gint           width,
456                 gint           height)
457 {
458   g_return_if_fail (style != NULL);
459   g_return_if_fail (style->klass != NULL);
460   g_return_if_fail (style->klass->draw_arrow != NULL);
461
462   (*style->klass->draw_arrow) (style, window, state_type, shadow_type, arrow_type, fill, x, y, width, height);
463 }
464
465
466 void
467 gtk_draw_diamond (GtkStyle      *style,
468                   GdkWindow     *window,
469                   GtkStateType   state_type,
470                   GtkShadowType  shadow_type,
471                   gint           x,
472                   gint           y,
473                   gint           width,
474                   gint           height)
475 {
476   g_return_if_fail (style != NULL);
477   g_return_if_fail (style->klass != NULL);
478   g_return_if_fail (style->klass->draw_diamond != NULL);
479
480   (*style->klass->draw_diamond) (style, window, state_type, shadow_type, x, y, width, height);
481 }
482
483
484 void
485 gtk_draw_oval (GtkStyle      *style,
486                GdkWindow     *window,
487                GtkStateType   state_type,
488                GtkShadowType  shadow_type,
489                gint           x,
490                gint           y,
491                gint           width,
492                gint           height)
493 {
494   g_return_if_fail (style != NULL);
495   g_return_if_fail (style->klass != NULL);
496   g_return_if_fail (style->klass->draw_oval != NULL);
497
498   (*style->klass->draw_oval) (style, window, state_type, shadow_type, x, y, width, height);
499 }
500
501 void
502 gtk_draw_string (GtkStyle      *style,
503                  GdkWindow     *window,
504                  GtkStateType   state_type,
505                  gint           x,
506                  gint           y,
507                  const gchar   *string)
508 {
509   g_return_if_fail (style != NULL);
510   g_return_if_fail (style->klass != NULL);
511   g_return_if_fail (style->klass->draw_oval != NULL);
512
513   (*style->klass->draw_string) (style, window, state_type, x, y, string);
514 }
515
516
517 static void
518 gtk_style_init (GtkStyle *style)
519 {
520   GdkGCValues gc_values;
521   GdkGCValuesMask gc_values_mask;
522   GdkColormap *colormap;
523   gint i;
524
525   g_return_if_fail (style != NULL);
526
527   if (style->attach_count == 0)
528     {
529       for (i = 0; i < 5; i++)
530         {
531           gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
532           gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
533
534           style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
535           style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
536           style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
537         }
538
539       colormap = style->colormap;
540
541       gdk_color_black (colormap, &style->black);
542       gdk_color_white (colormap, &style->white);
543
544       gc_values_mask = GDK_GC_FOREGROUND | GDK_GC_FONT;
545       if (style->font->type == GDK_FONT_FONT)
546         {
547           gc_values.font = style->font;
548         }
549       else if (style->font->type == GDK_FONT_FONTSET)
550         {
551           gc_values.font = default_font;
552         }
553
554       gc_values.foreground = style->black;
555       style->black_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
556
557       gc_values.foreground = style->white;
558       style->white_gc = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
559
560       for (i = 0; i < 5; i++)
561         {
562           if (!gdk_color_alloc (colormap, &style->fg[i]))
563             g_warning ("unable to allocate color: ( %d %d %d )",
564                        style->fg[i].red, style->fg[i].green, style->fg[i].blue);
565           if (!gdk_color_alloc (colormap, &style->bg[i]))
566             g_warning ("unable to allocate color: ( %d %d %d )",
567                        style->bg[i].red, style->bg[i].green, style->bg[i].blue);
568           if (!gdk_color_alloc (colormap, &style->light[i]))
569             g_warning ("unable to allocate color: ( %d %d %d )",
570                        style->light[i].red, style->light[i].green, style->light[i].blue);
571           if (!gdk_color_alloc (colormap, &style->dark[i]))
572             g_warning ("unable to allocate color: ( %d %d %d )",
573                        style->dark[i].red, style->dark[i].green, style->dark[i].blue);
574           if (!gdk_color_alloc (colormap, &style->mid[i]))
575             g_warning ("unable to allocate color: ( %d %d %d )",
576                        style->mid[i].red, style->mid[i].green, style->mid[i].blue);
577           if (!gdk_color_alloc (colormap, &style->text[i]))
578             g_warning ("unable to allocate color: ( %d %d %d )",
579                        style->text[i].red, style->text[i].green, style->text[i].blue);
580           if (!gdk_color_alloc (colormap, &style->base[i]))
581             g_warning ("unable to allocate color: ( %d %d %d )",
582                        style->base[i].red, style->base[i].green, style->base[i].blue);
583
584           gc_values.foreground = style->fg[i];
585           style->fg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
586
587           gc_values.foreground = style->bg[i];
588           style->bg_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
589
590           gc_values.foreground = style->light[i];
591           style->light_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
592
593           gc_values.foreground = style->dark[i];
594           style->dark_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
595
596           gc_values.foreground = style->mid[i];
597           style->mid_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
598
599           gc_values.foreground = style->text[i];
600           style->text_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
601
602           gc_values.foreground = style->base[i];
603           style->base_gc[i] = gtk_gc_get (style->depth, style->colormap, &gc_values, gc_values_mask);
604         }
605     }
606 }
607
608 static void
609 gtk_styles_init ()
610 {
611   if (initialize)
612     {
613       initialize = FALSE;
614
615       style_cache = g_cache_new ((GCacheNewFunc) gtk_style_new_from_key,
616                                  (GCacheDestroyFunc) gtk_style_unref,
617                                  (GCacheDupFunc) gtk_style_key_dup,
618                                  (GCacheDestroyFunc) gtk_style_key_destroy,
619                                  (GHashFunc) gtk_style_key_hash,
620                                  (GHashFunc) gtk_style_value_hash,
621                                  (GCompareFunc) gtk_style_key_compare);
622     }
623 }
624
625 static void
626 gtk_style_remove (GtkStyle *style)
627 {
628   if (initialize)
629     gtk_styles_init ();
630   g_cache_remove (style_cache, style);
631 }
632
633 static GtkStyle*
634 gtk_style_find (GtkStyle    *style,
635                 GdkColormap *cmap,
636                 gint         depth)
637 {
638   GtkStyleKey key;
639   gint i;
640
641   if (initialize)
642     gtk_styles_init ();
643
644   for (i = 0; i < 5; i++)
645     {
646       key.fg[i] = style->fg[i];
647       key.bg[i] = style->bg[i];
648       key.text[i] = style->text[i];
649       key.base[i] = style->base[i];
650       key.bg_pixmap[i] = style->bg_pixmap[i];
651     }
652
653   key.font = style->font;
654   key.klass = style->klass;
655   key.depth = depth;
656   key.colormap = cmap;
657
658   style = g_cache_insert (style_cache, &key);
659
660   return style;
661 }
662
663 static GtkStyle*
664 gtk_style_new_from_key (GtkStyleKey *key)
665 {
666   GtkStyle *style;
667   GSList *list;
668   gint i;
669
670   style = NULL;
671   list = unattached_styles;
672
673   while (list)
674     {
675       style = list->data;
676       list = list->next;
677
678       if ((style->depth != -1) && (style->depth != key->depth))
679         {
680           style = NULL;
681           continue;
682         }
683       if (style->colormap && (style->colormap != key->colormap))
684         {
685           style = NULL;
686           continue;
687         }
688       if (style->klass != key->klass)
689         {
690           style = NULL;
691           continue;
692         }
693       if (!gdk_font_equal (style->font, key->font))
694         {
695           style = NULL;
696           continue;
697         }
698
699       for (i = 0; style && (i < 5); i++)
700         {
701           if (style->bg_pixmap[i] != key->bg_pixmap[i])
702             {
703               style = NULL;
704               continue;
705             }
706
707           if ((style->fg[i].red != key->fg[i].red) ||
708               (style->fg[i].green != key->fg[i].green) ||
709               (style->fg[i].blue != key->fg[i].blue))
710             {
711               style = NULL;
712               continue;
713             }
714
715           if ((style->bg[i].red != key->bg[i].red) ||
716               (style->bg[i].green != key->bg[i].green) ||
717               (style->bg[i].blue != key->bg[i].blue))
718             {
719               style = NULL;
720               continue;
721             }
722
723           if ((style->text[i].red != key->text[i].red) ||
724               (style->text[i].green != key->text[i].green) ||
725               (style->text[i].blue != key->text[i].blue))
726             {
727               style = NULL;
728               continue;
729             }
730
731           if ((style->base[i].red != key->base[i].red) ||
732               (style->base[i].green != key->base[i].green) ||
733               (style->base[i].blue != key->base[i].blue))
734             {
735               style = NULL;
736               continue;
737             }
738         }
739
740       if (style)
741         {
742           gtk_style_ref (style);
743           break;
744         }
745     }
746
747   if (!style)
748     {
749       style = g_new0 (GtkStyle, 1);
750
751       style->ref_count = 1;
752       style->attach_count = 0;
753
754       style->font = key->font;
755       gdk_font_ref (style->font);
756
757       style->depth = key->depth;
758       style->colormap = key->colormap;
759       style->klass = key->klass;
760
761       style->black.red = 0;
762       style->black.green = 0;
763       style->black.blue = 0;
764
765       style->white.red = 65535;
766       style->white.green = 65535;
767       style->white.blue = 65535;
768
769       style->black_gc = NULL;
770       style->white_gc = NULL;
771
772       for (i = 0; i < 5; i++)
773         {
774           style->fg[i] = key->fg[i];
775           style->bg[i] = key->bg[i];
776           style->text[i] = key->text[i];
777           style->base[i] = key->base[i];
778         }
779
780       for (i = 0; i < 5; i++)
781         style->bg_pixmap[i] = key->bg_pixmap[i];
782
783       for (i = 0; i < 5; i++)
784         {
785           style->fg_gc[i] = NULL;
786           style->bg_gc[i] = NULL;
787           style->light_gc[i] = NULL;
788           style->dark_gc[i] = NULL;
789           style->mid_gc[i] = NULL;
790           style->text_gc[i] = NULL;
791           style->base_gc[i] = NULL;
792         }
793     }
794
795   if (style->depth == -1)
796     style->depth = key->depth;
797   if (!style->colormap)
798     style->colormap = key->colormap;
799
800   gtk_style_init (style);
801
802   return style;
803 }
804
805 static GtkStyleKey*
806 gtk_style_key_dup (GtkStyleKey *key)
807 {
808   GtkStyleKey *new_key;
809
810   if (!key_mem_chunk)
811     key_mem_chunk = g_mem_chunk_new ("key mem chunk", sizeof (GtkStyleKey),
812                                      1024, G_ALLOC_AND_FREE);
813
814   new_key = g_chunk_new (GtkStyleKey, key_mem_chunk);
815
816   *new_key = *key;
817
818   return new_key;
819 }
820
821 static void
822 gtk_style_destroy (GtkStyle *style)
823 {
824   gint i;
825
826   if (style->attach_count > 0)
827     {
828       gtk_gc_release (style->black_gc);
829       gtk_gc_release (style->white_gc);
830
831       for (i = 0; i < 5; i++)
832         {
833           gtk_gc_release (style->fg_gc[i]);
834           gtk_gc_release (style->bg_gc[i]);
835           gtk_gc_release (style->light_gc[i]);
836           gtk_gc_release (style->dark_gc[i]);
837           gtk_gc_release (style->mid_gc[i]);
838           gtk_gc_release (style->text_gc[i]);
839           gtk_gc_release (style->base_gc[i]);
840         }
841     }
842
843   unattached_styles = g_slist_remove (unattached_styles, style);
844
845   gdk_font_unref (style->font);
846   g_free (style);
847 }
848
849 static void
850 gtk_style_key_destroy (GtkStyleKey *key)
851 {
852   g_mem_chunk_free (key_mem_chunk, key);
853 }
854
855 static guint
856 gtk_style_key_hash (GtkStyleKey *key)
857 {
858   guint hash_val;
859   gint i;
860
861   hash_val = 0;
862
863   for (i = 0; i < 5; i++)
864     {
865       hash_val += key->fg[i].red + key->fg[i].green + key->fg[i].blue;
866       hash_val += key->bg[i].red + key->bg[i].green + key->bg[i].blue;
867       hash_val += key->text[i].red + key->text[i].green + key->text[i].blue;
868       hash_val += key->base[i].red + key->base[i].green + key->base[i].blue;
869     }
870
871   hash_val += (guint) gdk_font_id (key->font);
872   hash_val += (guint) key->depth;
873   hash_val += (gulong) key->colormap;
874   hash_val += (gulong) key->klass;
875
876   return hash_val;
877 }
878
879 static guint
880 gtk_style_value_hash (GtkStyle *style)
881 {
882   guint hash_val;
883   gint i;
884
885   hash_val = 0;
886
887   for (i = 0; i < 5; i++)
888     {
889       hash_val += style->fg[i].red + style->fg[i].green + style->fg[i].blue;
890       hash_val += style->bg[i].red + style->bg[i].green + style->bg[i].blue;
891       hash_val += style->text[i].red + style->text[i].green + style->text[i].blue;
892       hash_val += style->base[i].red + style->base[i].green + style->base[i].blue;
893     }
894
895   hash_val += (guint) gdk_font_id (style->font);
896   hash_val += (gulong) style->klass;
897
898   return hash_val;
899 }
900
901 static gint
902 gtk_style_key_compare (GtkStyleKey *a,
903                        GtkStyleKey *b)
904 {
905   gint i;
906
907   if (a->depth != b->depth)
908     return FALSE;
909   if (a->colormap != b->colormap)
910     return FALSE;
911   if (a->klass != b->klass)
912     return FALSE;
913   if (!gdk_font_equal (a->font, b->font))
914     return FALSE;
915
916   for (i = 0; i < 5; i++)
917     {
918       if (a->bg_pixmap[i] != b->bg_pixmap[i])
919         return FALSE;
920
921       if ((a->fg[i].red != b->fg[i].red) ||
922           (a->fg[i].green != b->fg[i].green) ||
923           (a->fg[i].blue != b->fg[i].blue))
924         return FALSE;
925       if ((a->bg[i].red != b->bg[i].red) ||
926           (a->bg[i].green != b->bg[i].green) ||
927           (a->bg[i].blue != b->bg[i].blue))
928         return FALSE;
929       if ((a->text[i].red != b->text[i].red) ||
930           (a->text[i].green != b->text[i].green) ||
931           (a->text[i].blue != b->text[i].blue))
932         return FALSE;
933       if ((a->base[i].red != b->base[i].red) ||
934           (a->base[i].green != b->base[i].green) ||
935           (a->base[i].blue != b->base[i].blue))
936         return FALSE;
937     }
938
939   return TRUE;
940 }
941
942
943 static void
944 gtk_default_draw_hline (GtkStyle     *style,
945                         GdkWindow    *window,
946                         GtkStateType  state_type,
947                         gint          x1,
948                         gint          x2,
949                         gint          y)
950 {
951   gint thickness_light;
952   gint thickness_dark;
953   gint i;
954
955   g_return_if_fail (style != NULL);
956   g_return_if_fail (window != NULL);
957
958   thickness_light = style->klass->ythickness / 2;
959   thickness_dark = style->klass->ythickness - thickness_light;
960
961   for (i = 0; i < thickness_dark; i++)
962     {
963       gdk_draw_line (window, style->light_gc[state_type], x2 - i - 1, y + i, x2, y + i);
964       gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x2 - i - 1, y + i);
965     }
966
967   y += thickness_dark;
968   for (i = 0; i < thickness_light; i++)
969     {
970       gdk_draw_line (window, style->dark_gc[state_type], x1, y + i, x1 + thickness_light - i - 1, y + i);
971       gdk_draw_line (window, style->light_gc[state_type], x1 + thickness_light - i - 1, y + i, x2, y + i);
972     }
973 }
974
975
976 static void
977 gtk_default_draw_vline (GtkStyle     *style,
978                         GdkWindow    *window,
979                         GtkStateType  state_type,
980                         gint          y1,
981                         gint          y2,
982                         gint          x)
983 {
984   gint thickness_light;
985   gint thickness_dark;
986   gint i;
987
988   g_return_if_fail (style != NULL);
989   g_return_if_fail (window != NULL);
990
991   thickness_light = style->klass->xthickness / 2;
992   thickness_dark = style->klass->xthickness - thickness_light;
993
994   for (i = 0; i < thickness_dark; i++)
995     {
996       gdk_draw_line (window, style->light_gc[state_type], x + i, y2 - i - 1, x + i, y2);
997       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y2 - i - 1);
998     }
999
1000   x += thickness_dark;
1001   for (i = 0; i < thickness_light; i++)
1002     {
1003       gdk_draw_line (window, style->dark_gc[state_type], x + i, y1, x + i, y1 + thickness_light - i);
1004       gdk_draw_line (window, style->light_gc[state_type], x + i, y1 + thickness_light - i, x + i, y2);
1005     }
1006 }
1007
1008
1009 static void
1010 gtk_default_draw_shadow (GtkStyle      *style,
1011                          GdkWindow     *window,
1012                          GtkStateType   state_type,
1013                          GtkShadowType  shadow_type,
1014                          gint           x,
1015                          gint           y,
1016                          gint           width,
1017                          gint           height)
1018 {
1019   GdkGC *gc1;
1020   GdkGC *gc2;
1021   gint thickness_light;
1022   gint thickness_dark;
1023   gint i;
1024
1025   g_return_if_fail (style != NULL);
1026   g_return_if_fail (window != NULL);
1027
1028   if ((width == -1) && (height == -1))
1029     gdk_window_get_size (window, &width, &height);
1030   else if (width == -1)
1031     gdk_window_get_size (window, &width, NULL);
1032   else if (height == -1)
1033     gdk_window_get_size (window, NULL, &height);
1034
1035   switch (shadow_type)
1036     {
1037     case GTK_SHADOW_NONE:
1038       gc1 = NULL;
1039       gc2 = NULL;
1040       break;
1041     case GTK_SHADOW_IN:
1042     case GTK_SHADOW_ETCHED_IN:
1043       gc1 = style->light_gc[state_type];
1044       gc2 = style->dark_gc[state_type];
1045       break;
1046     case GTK_SHADOW_OUT:
1047     case GTK_SHADOW_ETCHED_OUT:
1048       gc1 = style->dark_gc[state_type];
1049       gc2 = style->light_gc[state_type];
1050       break;
1051     }
1052
1053   switch (shadow_type)
1054     {
1055     case GTK_SHADOW_NONE:
1056       break;
1057
1058     case GTK_SHADOW_IN:
1059       gdk_draw_line (window, gc1,
1060                      x, y + height - 1, x + width - 1, y + height - 1);
1061       gdk_draw_line (window, gc1,
1062                      x + width - 1, y, x + width - 1, y + height - 1);
1063
1064       gdk_draw_line (window, style->bg_gc[state_type],
1065                      x + 1, y + height - 2, x + width - 2, y + height - 2);
1066       gdk_draw_line (window, style->bg_gc[state_type],
1067                      x + width - 2, y + 1, x + width - 2, y + height - 2);
1068
1069       gdk_draw_line (window, style->black_gc,
1070                      x + 1, y + 1, x + width - 2, y + 1);
1071       gdk_draw_line (window, style->black_gc,
1072                      x + 1, y + 1, x + 1, y + height - 2);
1073
1074       gdk_draw_line (window, gc2,
1075                      x, y, x + width - 1, y);
1076       gdk_draw_line (window, gc2,
1077                      x, y, x, y + height - 1);
1078       break;
1079
1080     case GTK_SHADOW_OUT:
1081       gdk_draw_line (window, gc1,
1082                      x + 1, y + height - 2, x + width - 2, y + height - 2);
1083       gdk_draw_line (window, gc1,
1084                      x + width - 2, y + 1, x + width - 2, y + height - 2);
1085
1086       gdk_draw_line (window, gc2,
1087                      x, y, x + width - 1, y);
1088       gdk_draw_line (window, gc2,
1089                      x, y, x, y + height - 1);
1090
1091       gdk_draw_line (window, style->bg_gc[state_type],
1092                      x + 1, y + 1, x + width - 2, y + 1);
1093       gdk_draw_line (window, style->bg_gc[state_type],
1094                      x + 1, y + 1, x + 1, y + height - 2);
1095
1096       gdk_draw_line (window, style->black_gc,
1097                      x, y + height - 1, x + width - 1, y + height - 1);
1098       gdk_draw_line (window, style->black_gc,
1099                      x + width - 1, y, x + width - 1, y + height - 1);
1100       break;
1101
1102     case GTK_SHADOW_ETCHED_IN:
1103     case GTK_SHADOW_ETCHED_OUT:
1104       thickness_light = 1;
1105       thickness_dark = 1;
1106
1107       for (i = 0; i < thickness_dark; i++)
1108         {
1109           gdk_draw_line (window, gc1,
1110                          x + i,
1111                          y + height - i - 1,
1112                          x + width - i - 1,
1113                          y + height - i - 1);
1114           gdk_draw_line (window, gc1,
1115                          x + width - i - 1,
1116                          y + i,
1117                          x + width - i - 1,
1118                          y + height - i - 1);
1119
1120           gdk_draw_line (window, gc2,
1121                          x + i,
1122                          y + i,
1123                          x + width - i - 2,
1124                          y + i);
1125           gdk_draw_line (window, gc2,
1126                          x + i,
1127                          y + i,
1128                          x + i,
1129                          y + height - i - 2);
1130         }
1131
1132       for (i = 0; i < thickness_light; i++)
1133         {
1134           gdk_draw_line (window, gc1,
1135                          x + thickness_dark + i,
1136                          y + thickness_dark + i,
1137                          x + width - thickness_dark - i - 1,
1138                          y + thickness_dark + i);
1139           gdk_draw_line (window, gc1,
1140                          x + thickness_dark + i,
1141                          y + thickness_dark + i,
1142                          x + thickness_dark + i,
1143                          y + height - thickness_dark - i - 1);
1144
1145           gdk_draw_line (window, gc2,
1146                          x + thickness_dark + i,
1147                          y + height - thickness_light - i - 1,
1148                          x + width - thickness_light - 1,
1149                          y + height - thickness_light - i - 1);
1150           gdk_draw_line (window, gc2,
1151                          x + width - thickness_light - i - 1,
1152                          y + thickness_dark + i,
1153                          x + width - thickness_light - i - 1,
1154                          y + height - thickness_light - 1);
1155         }
1156       break;
1157     }
1158 }
1159
1160
1161 static void
1162 gtk_default_draw_polygon (GtkStyle      *style,
1163                           GdkWindow     *window,
1164                           GtkStateType   state_type,
1165                           GtkShadowType  shadow_type,
1166                           GdkPoint      *points,
1167                           gint           npoints,
1168                           gint           fill)
1169 {
1170 #ifndef M_PI
1171 #define M_PI    3.14159265358979323846
1172 #endif /* M_PI */
1173 #ifndef M_PI_4
1174 #define M_PI_4  0.78539816339744830962
1175 #endif /* M_PI_4 */
1176
1177   static const gdouble pi_over_4 = M_PI_4;
1178   static const gdouble pi_3_over_4 = M_PI_4 * 3;
1179
1180   GdkGC *gc1;
1181   GdkGC *gc2;
1182   GdkGC *gc3;
1183   GdkGC *gc4;
1184   gdouble angle;
1185   gint xadjust;
1186   gint yadjust;
1187   gint i;
1188
1189   g_return_if_fail (style != NULL);
1190   g_return_if_fail (window != NULL);
1191   g_return_if_fail (points != NULL);
1192
1193   switch (shadow_type)
1194     {
1195     case GTK_SHADOW_IN:
1196       gc1 = style->bg_gc[state_type];
1197       gc2 = style->dark_gc[state_type];
1198       gc3 = style->light_gc[state_type];
1199       gc4 = style->black_gc;
1200       break;
1201     case GTK_SHADOW_OUT:
1202       gc1 = style->dark_gc[state_type];
1203       gc2 = style->light_gc[state_type];
1204       gc3 = style->black_gc;
1205       gc4 = style->bg_gc[state_type];
1206       break;
1207     default:
1208       return;
1209     }
1210
1211   if (fill)
1212     gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, npoints);
1213
1214   npoints--;
1215
1216   for (i = 0; i < npoints; i++)
1217     {
1218       if ((points[i].x == points[i+1].x) &&
1219           (points[i].y == points[i+1].y))
1220         {
1221           angle = 0;
1222         }
1223       else
1224         {
1225           angle = atan2 (points[i+1].y - points[i].y,
1226                          points[i+1].x - points[i].x);
1227         }
1228
1229       if ((angle > -pi_3_over_4) && (angle < pi_over_4))
1230         {
1231           if (angle > -pi_over_4)
1232             {
1233               xadjust = 0;
1234               yadjust = 1;
1235             }
1236           else
1237             {
1238               xadjust = 1;
1239               yadjust = 0;
1240             }
1241
1242           gdk_draw_line (window, gc1,
1243                          points[i].x-xadjust, points[i].y-yadjust,
1244                          points[i+1].x-xadjust, points[i+1].y-yadjust);
1245           gdk_draw_line (window, gc3,
1246                          points[i].x, points[i].y,
1247                          points[i+1].x, points[i+1].y);
1248         }
1249       else
1250         {
1251           if ((angle < -pi_3_over_4) || (angle > pi_3_over_4))
1252             {
1253               xadjust = 0;
1254               yadjust = 1;
1255             }
1256           else
1257             {
1258               xadjust = 1;
1259               yadjust = 0;
1260             }
1261
1262           gdk_draw_line (window, gc4,
1263                          points[i].x+xadjust, points[i].y+yadjust,
1264                          points[i+1].x+xadjust, points[i+1].y+yadjust);
1265           gdk_draw_line (window, gc2,
1266                          points[i].x, points[i].y,
1267                          points[i+1].x, points[i+1].y);
1268         }
1269     }
1270 }
1271
1272
1273 static void
1274 gtk_default_draw_arrow (GtkStyle      *style,
1275                         GdkWindow     *window,
1276                         GtkStateType   state_type,
1277                         GtkShadowType  shadow_type,
1278                         GtkArrowType   arrow_type,
1279                         gint           fill,
1280                         gint           x,
1281                         gint           y,
1282                         gint           width,
1283                         gint           height)
1284 {
1285   GdkGC *gc1;
1286   GdkGC *gc2;
1287   GdkGC *gc3;
1288   GdkGC *gc4;
1289   gint half_width;
1290   gint half_height;
1291   GdkPoint points[3];
1292
1293   g_return_if_fail (style != NULL);
1294   g_return_if_fail (window != NULL);
1295
1296   switch (shadow_type)
1297     {
1298     case GTK_SHADOW_IN:
1299       gc1 = style->bg_gc[state_type];
1300       gc2 = style->dark_gc[state_type];
1301       gc3 = style->light_gc[state_type];
1302       gc4 = style->black_gc;
1303       break;
1304     case GTK_SHADOW_OUT:
1305       gc1 = style->dark_gc[state_type];
1306       gc2 = style->light_gc[state_type];
1307       gc3 = style->black_gc;
1308       gc4 = style->bg_gc[state_type];
1309       break;
1310     default:
1311       return;
1312     }
1313
1314   if ((width == -1) && (height == -1))
1315     gdk_window_get_size (window, &width, &height);
1316   else if (width == -1)
1317     gdk_window_get_size (window, &width, NULL);
1318   else if (height == -1)
1319     gdk_window_get_size (window, NULL, &height);
1320
1321   half_width = width / 2;
1322   half_height = height / 2;
1323
1324   switch (arrow_type)
1325     {
1326     case GTK_ARROW_UP:
1327       if (fill)
1328         {
1329           points[0].x = x + half_width;
1330           points[0].y = y;
1331           points[1].x = x;
1332           points[1].y = y + height - 1;
1333           points[2].x = x + width - 1;
1334           points[2].y = y + height - 1;
1335
1336           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1337         }
1338
1339       gdk_draw_line (window, gc1,
1340                      x + 1, y + height - 2,
1341                      x + width - 2, y + height - 2);
1342       gdk_draw_line (window, gc3,
1343                      x + 0, y + height - 1,
1344                      x + width - 1, y + height - 1);
1345
1346       gdk_draw_line (window, gc1,
1347                      x + width - 2, y + height - 1,
1348                      x + half_width, y + 1);
1349       gdk_draw_line (window, gc3,
1350                      x + width - 1, y + height - 1,
1351                      x + half_width, y);
1352
1353       gdk_draw_line (window, gc4,
1354                      x + half_width, y + 1,
1355                      x + 1, y + height - 1);
1356       gdk_draw_line (window, gc2,
1357                      x + half_width, y,
1358                      x, y + height - 1);
1359       break;
1360     case GTK_ARROW_DOWN:
1361       if (fill)
1362         {
1363           points[0].x = x + width - 1;
1364           points[0].y = y;
1365           points[1].x = x;
1366           points[1].y = y;
1367           points[2].x = x + half_width;
1368           points[2].y = y + height - 1;
1369
1370           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1371         }
1372
1373       gdk_draw_line (window, gc4,
1374                      x + width - 2,
1375                      y + 1, x + 1, y + 1);
1376       gdk_draw_line (window, gc2,
1377                      x + width - 1, y,
1378                      x, y);
1379
1380       gdk_draw_line (window, gc4,
1381                      x + 1, y,
1382                      x + half_width, y + height - 2);
1383       gdk_draw_line (window, gc2,
1384                      x, y,
1385                      x + half_width, y + height - 1);
1386
1387       gdk_draw_line (window, gc1,
1388                      x + half_width, y + height - 2,
1389                      x + width - 2, y);
1390       gdk_draw_line (window, gc3,
1391                      x + half_width, y + height - 1,
1392                      x + width - 1, y);
1393       break;
1394     case GTK_ARROW_LEFT:
1395       if (fill)
1396         {
1397           points[0].x = x;
1398           points[0].y = y + half_height;
1399           points[1].x = x + width - 1;
1400           points[1].y = y + height - 1;
1401           points[2].x = x + width - 1;
1402           points[2].y = y;
1403
1404           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1405         }
1406
1407       gdk_draw_line (window, gc1,
1408                      x + 1, y + half_height,
1409                      x + width - 1, y + height - 1);
1410       gdk_draw_line (window, gc3,
1411                      x, y + half_height,
1412                      x + width - 1, y + height - 1);
1413
1414       gdk_draw_line (window, gc1,
1415                      x + width - 2, y + height - 1,
1416                      x + width - 2, y + 1);
1417       gdk_draw_line (window, gc3,
1418                      x + width - 1, y + height - 1,
1419                      x + width - 1, y);
1420
1421       gdk_draw_line (window, gc4,
1422                      x + width - 1, y + 1,
1423                      x + 1, y + half_width);
1424       gdk_draw_line (window, gc2,
1425                      x + width - 1, y,
1426                      x, y + half_width);
1427       break;
1428     case GTK_ARROW_RIGHT:
1429       if (fill)
1430         {
1431           points[0].x = x + width - 1;
1432           points[0].y = y + half_height;
1433           points[1].x = x;
1434           points[1].y = y;
1435           points[2].x = x;
1436           points[2].y = y + height - 1;
1437
1438           gdk_draw_polygon (window, style->bg_gc[state_type], TRUE, points, 3);
1439         }
1440
1441       gdk_draw_line (window, gc4,
1442                      x + width - 1, y + half_height,
1443                      x + 1, y + 1);
1444       gdk_draw_line (window, gc2,
1445                      x + width - 1, y + half_height,
1446                      x, y);
1447
1448       gdk_draw_line (window, gc4,
1449                      x + 1, y + 1,
1450                      x + 1, y + height - 2);
1451       gdk_draw_line (window, gc2,
1452                      x, y,
1453                      x, y + height - 1);
1454
1455       gdk_draw_line (window, gc1,
1456                      x + 1, y + height - 2,
1457                      x + width - 1, y + half_height);
1458       gdk_draw_line (window, gc3,
1459                      x, y + height - 1,
1460                      x + width - 1, y + half_height);
1461       break;
1462     }
1463 }
1464
1465
1466 static void
1467 gtk_default_draw_diamond (GtkStyle      *style,
1468                           GdkWindow     *window,
1469                           GtkStateType   state_type,
1470                           GtkShadowType  shadow_type,
1471                           gint           x,
1472                           gint           y,
1473                           gint           width,
1474                           gint           height)
1475 {
1476   gint half_width;
1477   gint half_height;
1478
1479   g_return_if_fail (style != NULL);
1480   g_return_if_fail (window != NULL);
1481
1482   if ((width == -1) && (height == -1))
1483     gdk_window_get_size (window, &width, &height);
1484   else if (width == -1)
1485     gdk_window_get_size (window, &width, NULL);
1486   else if (height == -1)
1487     gdk_window_get_size (window, NULL, &height);
1488
1489   half_width = width / 2;
1490   half_height = height / 2;
1491
1492   switch (shadow_type)
1493     {
1494     case GTK_SHADOW_IN:
1495       gdk_draw_line (window, style->bg_gc[state_type],
1496                      x + 2, y + half_height,
1497                      x + half_width, y + height - 2);
1498       gdk_draw_line (window, style->bg_gc[state_type],
1499                      x + half_width, y + height - 2,
1500                      x + width - 2, y + half_height);
1501       gdk_draw_line (window, style->light_gc[state_type],
1502                      x + 1, y + half_height,
1503                      x + half_width, y + height - 1);
1504       gdk_draw_line (window, style->light_gc[state_type],
1505                      x + half_width, y + height - 1,
1506                      x + width - 1, y + half_height);
1507       gdk_draw_line (window, style->light_gc[state_type],
1508                      x, y + half_height,
1509                      x + half_width, y + height);
1510       gdk_draw_line (window, style->light_gc[state_type],
1511                      x + half_width, y + height,
1512                      x + width, y + half_height);
1513
1514       gdk_draw_line (window, style->black_gc,
1515                      x + 2, y + half_height,
1516                      x + half_width, y + 2);
1517       gdk_draw_line (window, style->black_gc,
1518                      x + half_width, y + 2,
1519                      x + width - 2, y + half_height);
1520       gdk_draw_line (window, style->dark_gc[state_type],
1521                      x + 1, y + half_height,
1522                      x + half_width, y + 1);
1523       gdk_draw_line (window, style->dark_gc[state_type],
1524                      x + half_width, y + 1,
1525                      x + width - 1, y + half_height);
1526       gdk_draw_line (window, style->dark_gc[state_type],
1527                      x, y + half_height,
1528                      x + half_width, y);
1529       gdk_draw_line (window, style->dark_gc[state_type],
1530                      x + half_width, y,
1531                      x + width, y + half_height);
1532       break;
1533     case GTK_SHADOW_OUT:
1534       gdk_draw_line (window, style->dark_gc[state_type],
1535                      x + 2, y + half_height,
1536                      x + half_width, y + height - 2);
1537       gdk_draw_line (window, style->dark_gc[state_type],
1538                      x + half_width, y + height - 2,
1539                      x + width - 2, y + half_height);
1540       gdk_draw_line (window, style->dark_gc[state_type],
1541                      x + 1, y + half_height,
1542                      x + half_width, y + height - 1);
1543       gdk_draw_line (window, style->dark_gc[state_type],
1544                      x + half_width, y + height - 1,
1545                      x + width - 1, y + half_height);
1546       gdk_draw_line (window, style->black_gc,
1547                      x, y + half_height,
1548                      x + half_width, y + height);
1549       gdk_draw_line (window, style->black_gc,
1550                      x + half_width, y + height,
1551                      x + width, y + half_height);
1552
1553       gdk_draw_line (window, style->bg_gc[state_type],
1554                      x + 2, y + half_height,
1555                      x + half_width, y + 2);
1556       gdk_draw_line (window, style->bg_gc[state_type],
1557                      x + half_width, y + 2,
1558                      x + width - 2, y + half_height);
1559       gdk_draw_line (window, style->light_gc[state_type],
1560                      x + 1, y + half_height,
1561                      x + half_width, y + 1);
1562       gdk_draw_line (window, style->light_gc[state_type],
1563                      x + half_width, y + 1,
1564                      x + width - 1, y + half_height);
1565       gdk_draw_line (window, style->light_gc[state_type],
1566                      x, y + half_height,
1567                      x + half_width, y);
1568       gdk_draw_line (window, style->light_gc[state_type],
1569                      x + half_width, y,
1570                      x + width, y + half_height);
1571       break;
1572     default:
1573       break;
1574     }
1575 }
1576
1577
1578 static void
1579 gtk_default_draw_oval (GtkStyle      *style,
1580                        GdkWindow     *window,
1581                        GtkStateType   state_type,
1582                        GtkShadowType  shadow_type,
1583                        gint           x,
1584                        gint           y,
1585                        gint           width,
1586                        gint           height)
1587 {
1588   g_return_if_fail (style != NULL);
1589   g_return_if_fail (window != NULL);
1590 }
1591
1592 static void
1593 gtk_default_draw_string (GtkStyle      *style,
1594                          GdkWindow     *window,
1595                          GtkStateType   state_type,
1596                          gint           x,
1597                          gint           y,
1598                          const gchar   *string)
1599 {
1600   g_return_if_fail (style != NULL);
1601   g_return_if_fail (window != NULL);
1602
1603   if (state_type == GTK_STATE_INSENSITIVE)
1604     gdk_draw_string (window, style->font, style->white_gc, x + 1, y + 1, string);
1605   gdk_draw_string (window, style->font, style->fg_gc[state_type], x, y, string);
1606 }
1607
1608
1609 static void
1610 gtk_style_shade (GdkColor *a,
1611                  GdkColor *b,
1612                  gdouble   k)
1613 {
1614   gdouble red;
1615   gdouble green;
1616   gdouble blue;
1617
1618   red = (gdouble) a->red / 65535.0;
1619   green = (gdouble) a->green / 65535.0;
1620   blue = (gdouble) a->blue / 65535.0;
1621
1622   rgb_to_hls (&red, &green, &blue);
1623
1624   green *= k;
1625   if (green > 1.0)
1626     green = 1.0;
1627   else if (green < 0.0)
1628     green = 0.0;
1629
1630   blue *= k;
1631   if (blue > 1.0)
1632     blue = 1.0;
1633   else if (blue < 0.0)
1634     blue = 0.0;
1635
1636   hls_to_rgb (&red, &green, &blue);
1637
1638   b->red = red * 65535.0;
1639   b->green = green * 65535.0;
1640   b->blue = blue * 65535.0;
1641 }
1642
1643 static void
1644 rgb_to_hls (gdouble *r,
1645             gdouble *g,
1646             gdouble *b)
1647 {
1648   gdouble min;
1649   gdouble max;
1650   gdouble red;
1651   gdouble green;
1652   gdouble blue;
1653   gdouble h, l, s;
1654   gdouble delta;
1655
1656   red = *r;
1657   green = *g;
1658   blue = *b;
1659
1660   if (red > green)
1661     {
1662       if (red > blue)
1663         max = red;
1664       else
1665         max = blue;
1666
1667       if (green < blue)
1668         min = green;
1669       else
1670         min = blue;
1671     }
1672   else
1673     {
1674       if (green > blue)
1675         max = green;
1676       else
1677         max = blue;
1678
1679       if (red < blue)
1680         min = red;
1681       else
1682         min = blue;
1683     }
1684
1685   l = (max + min) / 2;
1686   s = 0;
1687   h = 0;
1688
1689   if (max != min)
1690     {
1691       if (l <= 0.5)
1692         s = (max - min) / (max + min);
1693       else
1694         s = (max - min) / (2 - max - min);
1695
1696       delta = max -min;
1697       if (red == max)
1698         h = (green - blue) / delta;
1699       else if (green == max)
1700         h = 2 + (blue - red) / delta;
1701       else if (blue == max)
1702         h = 4 + (red - green) / delta;
1703
1704       h *= 60;
1705       if (h < 0.0)
1706         h += 360;
1707     }
1708
1709   *r = h;
1710   *g = l;
1711   *b = s;
1712 }
1713
1714 static void
1715 hls_to_rgb (gdouble *h,
1716             gdouble *l,
1717             gdouble *s)
1718 {
1719   gdouble hue;
1720   gdouble lightness;
1721   gdouble saturation;
1722   gdouble m1, m2;
1723   gdouble r, g, b;
1724
1725   lightness = *l;
1726   saturation = *s;
1727
1728   if (lightness <= 0.5)
1729     m2 = lightness * (1 + saturation);
1730   else
1731     m2 = lightness + saturation - lightness * saturation;
1732   m1 = 2 * lightness - m2;
1733
1734   if (saturation == 0)
1735     {
1736       *h = lightness;
1737       *l = lightness;
1738       *s = lightness;
1739     }
1740   else
1741     {
1742       hue = *h + 120;
1743       while (hue > 360)
1744         hue -= 360;
1745       while (hue < 0)
1746         hue += 360;
1747
1748       if (hue < 60)
1749         r = m1 + (m2 - m1) * hue / 60;
1750       else if (hue < 180)
1751         r = m2;
1752       else if (hue < 240)
1753         r = m1 + (m2 - m1) * (240 - hue) / 60;
1754       else
1755         r = m1;
1756
1757       hue = *h;
1758       while (hue > 360)
1759         hue -= 360;
1760       while (hue < 0)
1761         hue += 360;
1762
1763       if (hue < 60)
1764         g = m1 + (m2 - m1) * hue / 60;
1765       else if (hue < 180)
1766         g = m2;
1767       else if (hue < 240)
1768         g = m1 + (m2 - m1) * (240 - hue) / 60;
1769       else
1770         g = m1;
1771
1772       hue = *h - 120;
1773       while (hue > 360)
1774         hue -= 360;
1775       while (hue < 0)
1776         hue += 360;
1777
1778       if (hue < 60)
1779         b = m1 + (m2 - m1) * hue / 60;
1780       else if (hue < 180)
1781         b = m2;
1782       else if (hue < 240)
1783         b = m1 + (m2 - m1) * (240 - hue) / 60;
1784       else
1785         b = m1;
1786
1787       *h = r;
1788       *l = g;
1789       *s = b;
1790     }
1791 }