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