]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkstyle.c
removed the "widget &&" part from "widget && GTK_IS_FOO (widget)" checks.
[~andy/gtk] / gtk / gtkstyle.c
index 8f9adc4d3aa61834ab3dbf58973ad96ff168c2d4..58f4d0ef9aefba05d35ed9c5e1c31ba1fa01930e 100644 (file)
@@ -28,7 +28,6 @@
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
-#include "gtkalias.h"
 #include "gtkgc.h"
 #include "gtkmarshalers.h"
 #include "gtkrc.h"
@@ -38,6 +37,8 @@
 #include "gtkthemes.h"
 #include "gtkiconfactory.h"
 #include "gtksettings.h"       /* _gtk_settings_parse_convert() */
+#include "gtkintl.h"
+#include "gtkalias.h"
 
 #define LIGHTNESS_MULT  1.3
 #define DARKNESS_MULT   0.7
@@ -49,9 +50,15 @@ typedef struct {
   GValue      value;
 } PropertyValue;
 
+#define GTK_STYLE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_STYLE, GtkStylePrivate))
+
+typedef struct _GtkStylePrivate GtkStylePrivate;
+
+struct _GtkStylePrivate {
+  GSList *color_hashes;
+};
+
 /* --- prototypes --- */
-static void     gtk_style_init                 (GtkStyle       *style);
-static void     gtk_style_class_init           (GtkStyleClass  *klass);
 static void     gtk_style_finalize             (GObject        *object);
 static void     gtk_style_realize              (GtkStyle       *style,
                                                 GdkColormap    *colormap);
@@ -304,9 +311,6 @@ static void gtk_default_draw_resize_grip (GtkStyle       *style,
                                           gint            width,
                                           gint            height);
 
-static void gtk_style_shade            (GdkColor        *a,
-                                        GdkColor        *b,
-                                        gdouble          k);
 static void rgb_to_hls                 (gdouble         *r,
                                         gdouble         *g,
                                         gdouble         *b);
@@ -349,39 +353,13 @@ static const GdkColor gtk_default_insensitive_bg = { 0, GTK_GRAY };
 static const GdkColor gtk_default_selected_base =  { 0, GTK_BLUE };
 static const GdkColor gtk_default_active_base =    { 0, GTK_VERY_DARK_GRAY };
 
-static gpointer parent_class = NULL;
-
 /* --- signals --- */
 static guint realize_signal = 0;
 static guint unrealize_signal = 0;
 
+G_DEFINE_TYPE (GtkStyle, gtk_style, G_TYPE_OBJECT)
+
 /* --- functions --- */
-GType
-gtk_style_get_type (void)
-{
-  static GType style_type = 0;
-  
-  if (!style_type)
-    {
-      static const GTypeInfo style_info =
-      {
-        sizeof (GtkStyleClass),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gtk_style_class_init,
-        NULL,           /* class_finalize */
-        NULL,           /* class_data */
-        sizeof (GtkStyle),
-        0,              /* n_preallocs */
-        (GInstanceInitFunc) gtk_style_init,
-      };
-      
-      style_type = g_type_register_static (G_TYPE_OBJECT, "GtkStyle",
-                                          &style_info, 0);
-    }
-  
-  return style_type;
-}
 
 /**
  * _gtk_style_init_for_settings:
@@ -499,8 +477,6 @@ gtk_style_class_init (GtkStyleClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   
-  parent_class = g_type_class_peek_parent (klass);
-
   object_class->finalize = gtk_style_finalize;
 
   klass->clone = gtk_style_real_clone;
@@ -533,7 +509,8 @@ gtk_style_class_init (GtkStyleClass *klass)
   klass->draw_layout = gtk_default_draw_layout;
   klass->draw_resize_grip = gtk_default_draw_resize_grip;
 
-  
+  g_type_class_add_private (object_class, sizeof (GtkStylePrivate));
+
   /**
    * GtkStyle::realize:
    * @style: the object which received the signal
@@ -545,7 +522,7 @@ gtk_style_class_init (GtkStyleClass *klass)
    *
    * Since: 2.4
    */
-  realize_signal = g_signal_new ("realize",
+  realize_signal = g_signal_new (I_("realize"),
                                 G_TYPE_FROM_CLASS (object_class),
                                 G_SIGNAL_RUN_FIRST,
                                 G_STRUCT_OFFSET (GtkStyleClass, realize),
@@ -563,7 +540,7 @@ gtk_style_class_init (GtkStyleClass *klass)
    *
    * Since: 2.4
    */
-  unrealize_signal = g_signal_new ("unrealize",
+  unrealize_signal = g_signal_new (I_("unrealize"),
                                   G_TYPE_FROM_CLASS (object_class),
                                   G_SIGNAL_RUN_FIRST,
                                   G_STRUCT_OFFSET (GtkStyleClass, unrealize),
@@ -595,6 +572,7 @@ static void
 gtk_style_finalize (GObject *object)
 {
   GtkStyle *style = GTK_STYLE (object);
+  GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
 
   g_return_if_fail (style->attach_count == 0);
 
@@ -624,18 +602,11 @@ gtk_style_finalize (GObject *object)
         }
     }
 
-  if (style->icon_factories)
-    {
-      GSList *tmp_list = style->icon_factories;
-
-      while (tmp_list)
-       {
-         g_object_unref (tmp_list->data);
-         tmp_list = tmp_list->next;
-       }
+  g_slist_foreach (style->icon_factories, (GFunc) g_object_unref, NULL);
+  g_slist_free (style->icon_factories);
 
-      g_slist_free (style->icon_factories);
-    }
+  g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_unref, NULL);
+  g_slist_free (priv->color_hashes);
 
   pango_font_description_free (style->font_desc);
   
@@ -648,7 +619,7 @@ gtk_style_finalize (GObject *object)
   if (style->rc_style)
     gtk_rc_style_unref (style->rc_style);
   
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gtk_style_parent_class)->finalize (object);
 }
 
 
@@ -715,6 +686,10 @@ gtk_style_new (void)
  * it to a particular visual and colormap. The process may 
  * involve the creation of a new style if the style has already 
  * been attached to a window with a different style and colormap.
+ *
+ * Since this function may return a new object, you have to use it 
+ * in the following way: 
+ * <literal>style = gtk_style_attach (style, window)</literal>
  **/
 GtkStyle*
 gtk_style_attach (GtkStyle  *style,
@@ -791,10 +766,19 @@ gtk_style_attach (GtkStyle  *style,
   return new_style;
 }
 
+/**
+ * gtk_style_detach:
+ * @style: a #GtkStyle
+ *
+ * Detaches a style from a window. If the style is not attached
+ * to any windows anymore, it is unrealized. See gtk_style_attach().
+ * 
+ */
 void
 gtk_style_detach (GtkStyle *style)
 {
   g_return_if_fail (GTK_IS_STYLE (style));
+  g_return_if_fail (style->attach_count > 0);
   
   style->attach_count -= 1;
   if (style->attach_count == 0)
@@ -849,9 +833,6 @@ static void
 gtk_style_realize (GtkStyle    *style,
                    GdkColormap *colormap)
 {
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (GDK_IS_COLORMAP (colormap));
-  
   style->colormap = g_object_ref (colormap);
   style->depth = gdk_colormap_get_visual (colormap)->depth;
 
@@ -881,6 +862,53 @@ gtk_style_lookup_icon_set (GtkStyle   *style,
   return gtk_icon_factory_lookup_default (stock_id);
 }
 
+/**
+ * gtk_style_lookup_color:
+ * @style: a #GtkStyle
+ * @color_name: the name of the logical color to look up
+ * @color: the #GdkColor to fill in
+ *
+ * Looks up @color_name in the style's logical color mappings,
+ * filling in @color and returning %TRUE if found, otherwise
+ * returning %FALSE. Do not cache the found mapping, because
+ * it depends on the #GtkStyle and might change when a theme
+ * switch occurs.
+ *
+ * Return value: %TRUE if the mapping was found.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gtk_style_lookup_color (GtkStyle   *style,
+                        const char *color_name,
+                        GdkColor   *color)
+{
+  GtkStylePrivate *priv;
+  GSList *iter;
+
+  g_return_val_if_fail (GTK_IS_STYLE (style), FALSE);
+  g_return_val_if_fail (color_name != NULL, FALSE);
+  g_return_val_if_fail (color != NULL, FALSE);
+
+  priv = GTK_STYLE_GET_PRIVATE (style);
+
+  for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
+    {
+      GHashTable *hash    = iter->data;
+      GdkColor   *mapping = g_hash_table_lookup (hash, color_name);
+
+      if (mapping)
+        {
+          color->red = mapping->red;
+          color->green = mapping->green;
+          color->blue = mapping->blue;
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 /**
  * gtk_draw_hline:
  * @style: a #GtkStyle
@@ -1586,10 +1614,10 @@ gtk_style_real_copy (GtkStyle *style,
   style->ythickness = src->ythickness;
 
   if (style->rc_style)
-    gtk_rc_style_unref (style->rc_style);
+    g_object_unref (style->rc_style);
   style->rc_style = src->rc_style;
   if (src->rc_style)
-    gtk_rc_style_ref (src->rc_style);
+    g_object_ref (src->rc_style);
 
   /* don't copy, just clear cache */
   clear_property_cache (style);
@@ -1599,6 +1627,7 @@ static void
 gtk_style_real_init_from_rc (GtkStyle   *style,
                             GtkRcStyle *rc_style)
 {
+  GtkStylePrivate *priv = GTK_STYLE_GET_PRIVATE (style);
   gint i;
 
   /* cache _should_ be still empty */
@@ -1624,19 +1653,11 @@ gtk_style_real_init_from_rc (GtkStyle   *style,
   if (rc_style->ythickness >= 0)
     style->ythickness = rc_style->ythickness;
 
-  if (rc_style->icon_factories)
-    {
-      GSList *iter;
+  style->icon_factories = g_slist_copy (rc_style->icon_factories);
+  g_slist_foreach (style->icon_factories, (GFunc) g_object_ref, NULL);
 
-      style->icon_factories = g_slist_copy (rc_style->icon_factories);
-      
-      iter = style->icon_factories;
-      while (iter != NULL)
-        {
-          g_object_ref (iter->data);
-          iter = g_slist_next (iter);
-        }
-    }
+  priv->color_hashes = g_slist_copy (_gtk_rc_style_get_color_hashes (rc_style));
+  g_slist_foreach (priv->color_hashes, (GFunc) g_hash_table_ref, NULL);
 }
 
 static gint
@@ -1718,7 +1739,7 @@ _gtk_style_peek_property_value (GtkStyle           *style,
       gchar *contents = g_strdup_value_contents (&rcprop->value);
       
       g_message ("%s: failed to retrieve property `%s::%s' of type `%s' from rc file value \"%s\" of type `%s'",
-                rcprop->origin,
+                rcprop->origin ? rcprop->origin : "(for origin information, set GTK_DEBUG)",
                 g_type_name (pspec->owner_type), pspec->name,
                 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
                 contents,
@@ -1759,9 +1780,9 @@ gtk_style_real_realize (GtkStyle *style)
 
   for (i = 0; i < 5; i++)
     {
-      gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
-      gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
-      
+      _gtk_style_shade (&style->bg[i], &style->light[i], LIGHTNESS_MULT);
+      _gtk_style_shade (&style->bg[i], &style->dark[i], DARKNESS_MULT);
+
       style->mid[i].red = (style->light[i].red + style->dark[i].red) / 2;
       style->mid[i].green = (style->light[i].green + style->dark[i].green) / 2;
       style->mid[i].blue = (style->light[i].blue + style->dark[i].blue) / 2;
@@ -2156,9 +2177,6 @@ gtk_default_draw_hline (GtkStyle     *style,
   gint thickness_dark;
   gint i;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   thickness_light = style->ythickness / 2;
   thickness_dark = style->ythickness - thickness_light;
   
@@ -2213,9 +2231,6 @@ gtk_default_draw_vline (GtkStyle     *style,
   gint thickness_dark;
   gint i;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   thickness_light = style->xthickness / 2;
   thickness_dark = style->xthickness - thickness_light;
   
@@ -2441,12 +2456,9 @@ gtk_default_draw_shadow (GtkStyle      *style,
   gint thickness_dark;
   gint i;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-
   if (shadow_type == GTK_SHADOW_IN)
     {
-      if (detail && (strcmp (detail, "buttondefault") == 0))
+      if (detail && strcmp (detail, "buttondefault") == 0)
        {
          sanitize_size (window, &width, &height);
 
@@ -2461,7 +2473,7 @@ gtk_default_draw_shadow (GtkStyle      *style,
                            x, y, width, height);
          return;
        }
-      if (widget && GTK_IS_SPIN_BUTTON (widget) &&
+      if (GTK_IS_SPIN_BUTTON (widget) &&
          detail && strcmp (detail, "spinbutton") == 0)
        {
          draw_spinbutton_shadow (style, window, state_type, 
@@ -2699,7 +2711,7 @@ gtk_default_draw_shadow (GtkStyle      *style,
     }
 
   if (shadow_type == GTK_SHADOW_IN &&
-      widget && GTK_IS_SPIN_BUTTON (widget) &&
+      GTK_IS_SPIN_BUTTON (widget) &&
       detail && strcmp (detail, "entry") == 0)
     {
       if (get_direction (widget) == GTK_TEXT_DIR_LTR)
@@ -2779,10 +2791,6 @@ gtk_default_draw_polygon (GtkStyle      *style,
   gint yadjust;
   gint i;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  g_return_if_fail (points != NULL);
-  
   switch (shadow_type)
     {
     case GTK_SHADOW_IN:
@@ -2900,15 +2908,13 @@ draw_arrow (GdkWindow     *window,
            gint           width,
            gint           height)
 {
-  cairo_t *cr = gdk_drawable_create_cairo_context (window);
+  cairo_t *cr = gdk_cairo_create (window);
   gdk_cairo_set_source_color (cr, color);
   
   if (area)
     {
-      cairo_save (cr);
-      cairo_rectangle (cr, area->x, area->y, area->width, area->height);
+      gdk_cairo_rectangle (cr, area);
       cairo_clip (cr);
-      cairo_new_path (cr);
     }
     
   if (arrow_type == GTK_ARROW_DOWN)
@@ -2939,9 +2945,6 @@ draw_arrow (GdkWindow     *window,
   cairo_close_path (cr);
   cairo_fill (cr);
 
-  if (area)
-    cairo_restore (cr);
-
   cairo_destroy (cr);
 }
 
@@ -3029,13 +3032,8 @@ gtk_default_draw_arrow (GtkStyle      *style,
                        gint           width,
                        gint           height)
 {
-  gint original_width, original_x;
-  
   sanitize_size (window, &width, &height);
 
-  original_width = width;
-  original_x = x;
-
   calculate_arrow_geometry (arrow_type, &x, &y, &width, &height);
 
   if (detail && strcmp (detail, "menu_scroll_arrow_up") == 0)
@@ -3076,9 +3074,6 @@ gtk_default_draw_diamond (GtkStyle      *style,
   GdkGC *inner_sw = NULL;
   GdkGC *inner_se = NULL;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   sanitize_size (window, &width, &height);
   
   half_width = width / 2;
@@ -3196,13 +3191,6 @@ gtk_default_draw_string (GtkStyle      *style,
                          gint           y,
                          const gchar   *string)
 {
-  GdkDisplay *display;
-  
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
-  display = gdk_drawable_get_display (window);
-  
   if (area)
     {
       gdk_gc_set_clip_rectangle (style->white_gc, area);
@@ -3235,8 +3223,8 @@ option_menu_get_props (GtkWidget      *widget,
   
   if (widget)
     gtk_widget_style_get (widget, 
-                         "indicator_size", &tmp_size,
-                         "indicator_spacing", &tmp_spacing,
+                         "indicator-size", &tmp_size,
+                         "indicator-spacing", &tmp_spacing,
                          NULL);
 
   if (tmp_size)
@@ -3271,12 +3259,9 @@ gtk_default_draw_box (GtkStyle      *style,
 {
   gboolean is_spinbutton_box = FALSE;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   sanitize_size (window, &width, &height);
 
-  if (widget && GTK_IS_SPIN_BUTTON (widget) && detail)
+  if (GTK_IS_SPIN_BUTTON (widget) && detail)
     {
       if (strcmp (detail, "spinbutton_up") == 0)
        {
@@ -3396,7 +3381,7 @@ get_darkened_gc (GdkWindow *window,
 
   while (darken_count)
     {
-      gtk_style_shade (&src, &shaded, 0.93);
+      _gtk_style_shade (&src, &shaded, 0.93);
       src = shaded;
       --darken_count;
     }
@@ -3422,9 +3407,6 @@ gtk_default_draw_flat_box (GtkStyle      *style,
   GdkGC *gc1;
   GdkGC *freeme = NULL;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   sanitize_size (window, &width, &height);
   
   if (detail)
@@ -3433,15 +3415,26 @@ gtk_default_draw_flat_box (GtkStyle      *style,
         {
           if (!strcmp ("text", detail))
             gc1 = style->bg_gc[GTK_STATE_SELECTED];
-          else if (!strncmp ("cell_even", detail, strlen ("cell_even")) ||
-                  !strncmp ("cell_odd", detail, strlen ("cell_odd")))
+          else if (!strcmp ("cell_even", detail) ||
+                   !strcmp ("cell_odd", detail) ||
+                   !strcmp ("cell_even_ruled", detail) ||
+                  !strcmp ("cell_even_ruled_sorted", detail))
             {
              /* This has to be really broken; alex made me do it. -jrb */
              if (GTK_WIDGET_HAS_FOCUS (widget))
                gc1 = style->base_gc[state_type];
-             else 
-               gc1 = style->base_gc[GTK_STATE_ACTIVE];
+             else
+               gc1 = style->base_gc[GTK_STATE_ACTIVE];
             }
+         else if (!strcmp ("cell_odd_ruled", detail) ||
+                  !strcmp ("cell_odd_ruled_sorted", detail))
+           {
+             if (GTK_WIDGET_HAS_FOCUS (widget))
+               freeme = get_darkened_gc (window, &style->base[state_type], 1);
+             else
+               freeme = get_darkened_gc (window, &style->base[GTK_STATE_ACTIVE], 1);
+             gc1 = freeme;
+           }
           else
             {
               gc1 = style->bg_gc[state_type];
@@ -3466,7 +3459,7 @@ gtk_default_draw_flat_box (GtkStyle      *style,
              GdkColor *color = NULL;
 
              gtk_widget_style_get (widget,
-                                   "even_row_color", &color,
+                                   "even-row-color", &color,
                                    NULL);
 
              if (color)
@@ -3484,7 +3477,7 @@ gtk_default_draw_flat_box (GtkStyle      *style,
              GdkColor *color;
 
              gtk_widget_style_get (widget,
-                                   "odd_row_color", &color,
+                                   "odd-row-color", &color,
                                    NULL);
 
              if (color)
@@ -3497,7 +3490,7 @@ gtk_default_draw_flat_box (GtkStyle      *style,
              else
                {
                  gtk_widget_style_get (widget,
-                                       "even_row_color", &color,
+                                       "even-row-color", &color,
                                        NULL);
 
                  if (color)
@@ -3518,11 +3511,11 @@ gtk_default_draw_flat_box (GtkStyle      *style,
 
              if (!strcmp ("cell_odd_sorted", detail))
                gtk_widget_style_get (widget,
-                                     "odd_row_color", &color,
+                                     "odd-row-color", &color,
                                      NULL);
              else
                gtk_widget_style_get (widget,
-                                     "even_row_color", &color,
+                                     "even-row-color", &color,
                                      NULL);
 
              if (color)
@@ -3543,7 +3536,7 @@ gtk_default_draw_flat_box (GtkStyle      *style,
              GdkColor *color = NULL;
 
              gtk_widget_style_get (widget,
-                                   "odd_row_color", &color,
+                                   "odd-row-color", &color,
                                    NULL);
 
              if (color)
@@ -3556,7 +3549,7 @@ gtk_default_draw_flat_box (GtkStyle      *style,
              else
                {
                  gtk_widget_style_get (widget,
-                                       "even_row_color", &color,
+                                       "even-row-color", &color,
                                        NULL);
 
                  if (color)
@@ -3615,7 +3608,7 @@ gtk_default_draw_check (GtkStyle      *style,
                        gint           width,
                        gint           height)
 {
-  cairo_t *cr = gdk_drawable_create_cairo_context (window);
+  cairo_t *cr = gdk_cairo_create (window);
   enum { BUTTON, MENU, CELL } type = BUTTON;
   int exterior_size;
   int interior_size;
@@ -3631,10 +3624,8 @@ gtk_default_draw_check (GtkStyle      *style,
       
   if (area)
     {
-      cairo_save (cr);
-      cairo_rectangle (cr, area->x, area->y, area->width, area->height);
+      gdk_cairo_rectangle (cr, area);
       cairo_clip (cr);
-      cairo_new_path (cr);
     }
   
   exterior_size = MIN (width, height);
@@ -3726,9 +3717,6 @@ gtk_default_draw_check (GtkStyle      *style,
       cairo_fill (cr);
     }
   
-  if (area)
-    cairo_restore (cr);
-  
   cairo_destroy (cr);
 }
 
@@ -3745,7 +3733,7 @@ gtk_default_draw_option (GtkStyle      *style,
                         gint           width,
                         gint           height)
 {
-  cairo_t *cr = gdk_drawable_create_cairo_context (window);
+  cairo_t *cr = gdk_cairo_create (window);
   enum { BUTTON, MENU, CELL } type = BUTTON;
   int exterior_size;
   
@@ -3759,10 +3747,8 @@ gtk_default_draw_option (GtkStyle      *style,
       
   if (area)
     {
-      cairo_save (cr);
-      cairo_rectangle (cr, area->x, area->y, area->width, area->height);
+      gdk_cairo_rectangle (cr, area);
       cairo_clip (cr);
-      cairo_new_path (cr);
     }
   
   exterior_size = MIN (width, height);
@@ -3782,11 +3768,9 @@ gtk_default_draw_option (GtkStyle      *style,
                 x + exterior_size / 2.,
                 y + exterior_size / 2.,
                 (exterior_size - 1) / 2.,
-                0, 2 * M_PI);
+                0, 2 * G_PI);
 
-      cairo_save (cr);
-      cairo_fill (cr);
-      cairo_restore (cr);
+      cairo_fill_preserve (cr);
 
       if (type == BUTTON)
        gdk_cairo_set_source_color (cr, &style->fg[state_type]);
@@ -3828,7 +3812,7 @@ gtk_default_draw_option (GtkStyle      *style,
                 x + pad + interior_size / 2.,
                 y + pad + interior_size / 2.,
                 interior_size / 2.,
-                0, 2 * M_PI);
+                0, 2 * G_PI);
       cairo_fill (cr);
     }
   else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */
@@ -3853,9 +3837,6 @@ gtk_default_draw_option (GtkStyle      *style,
       cairo_fill (cr);
     }
   
-  if (area)
-    cairo_restore (cr);
-  
   cairo_destroy (cr);
 }
 
@@ -3928,9 +3909,6 @@ gtk_default_draw_shadow_gap (GtkStyle       *style,
   GdkGC *gc3 = NULL;
   GdkGC *gc4 = NULL;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   sanitize_size (window, &width, &height);
   
   switch (shadow_type)
@@ -4144,9 +4122,6 @@ gtk_default_draw_box_gap (GtkStyle       *style,
   GdkGC *gc3 = NULL;
   GdkGC *gc4 = NULL;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   gtk_style_apply_default_background (style, window,
                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
                                       state_type, area, x, y, width, height);
@@ -4289,7 +4264,7 @@ gtk_default_draw_box_gap (GtkStyle       *style,
               gdk_draw_line (window, gc2,
                              x, y + gap_x, x, y + gap_x);
             }
-          if ((width - (gap_x + gap_width)) > 0)
+          if ((height - (gap_x + gap_width)) > 0)
             {
               gdk_draw_line (window, gc1,
                              x, y + gap_x + gap_width, x, y + height - 2);
@@ -4322,7 +4297,7 @@ gtk_default_draw_box_gap (GtkStyle       *style,
               gdk_draw_line (window, gc3,
                              x + width - 1, y + gap_x, x + width - 1, y + gap_x);
             }
-          if ((width - (gap_x + gap_width)) > 0)
+          if ((height - (gap_x + gap_width)) > 0)
             {
               gdk_draw_line (window, gc4,
                              x + width - 1, y + gap_x + gap_width, x + width - 1, y + height - 2);
@@ -4363,9 +4338,6 @@ gtk_default_draw_extension (GtkStyle       *style,
   GdkGC *gc3 = NULL;
   GdkGC *gc4 = NULL;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   gtk_style_apply_default_background (style, window,
                                       widget && !GTK_WIDGET_NO_WINDOW (widget),
                                       GTK_STATE_NORMAL, area, x, y, width, height);
@@ -4557,12 +4529,12 @@ gtk_default_draw_focus (GtkStyle      *style,
 
   sanitize_size (window, &width, &height);
 
-  cr = gdk_drawable_create_cairo_context (window);
+  cr = gdk_cairo_create (window);
   
   if (detail && !strcmp (detail, "colorwheel_light"))
-    cairo_set_rgb_color (cr, 0., 0., 0.);
+    cairo_set_source_rgb (cr, 0., 0., 0.);
   else if (detail && !strcmp (detail, "colorwheel_dark"))
-    cairo_set_rgb_color (cr, 1., 1., 1.);
+    cairo_set_source_rgb (cr, 1., 1., 1.);
   else
     gdk_cairo_set_source_color (cr, &style->fg[state_type]);
 
@@ -4597,10 +4569,8 @@ gtk_default_draw_focus (GtkStyle      *style,
 
   if (area)
     {
-      cairo_rectangle (cr,
-                      area->x, area->y, area->width, area->height);
+      gdk_cairo_rectangle (cr, area);
       cairo_clip (cr);
-      cairo_new_path (cr);
     }
 
   cairo_rectangle (cr,
@@ -4629,9 +4599,6 @@ gtk_default_draw_slider (GtkStyle      *style,
                          gint           height,
                          GtkOrientation orientation)
 {
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   sanitize_size (window, &width, &height);
   
   gtk_paint_box (style, window, state_type, shadow_type,
@@ -4660,7 +4627,6 @@ draw_dot (GdkWindow    *window,
          gint          y,
          gushort       size)
 {
-  
   size = CLAMP (size, 2, 3);
 
   if (size == 2)
@@ -4701,9 +4667,6 @@ gtk_default_draw_handle (GtkStyle      *style,
   GdkRectangle dest;
   gint intersect;
   
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   sanitize_size (window, &width, &height);
   
   gtk_paint_box (style, window, state_type, shadow_type, area, widget, 
@@ -4719,9 +4682,9 @@ gtk_default_draw_handle (GtkStyle      *style,
       if (state_type == GTK_STATE_SELECTED && widget && !GTK_WIDGET_HAS_FOCUS (widget))
        {
          GdkColor unfocused_light;
-      
-         gtk_style_shade (&style->base[GTK_STATE_ACTIVE], &unfocused_light,
-                          LIGHTNESS_MULT);
+
+         _gtk_style_shade (&style->base[GTK_STATE_ACTIVE], &unfocused_light,
+                            LIGHTNESS_MULT);
 
          light_gc = free_me = gdk_gc_new (window);
          gdk_gc_set_rgb_fg_color (light_gc, &unfocused_light);
@@ -4786,72 +4749,6 @@ gtk_default_draw_handle (GtkStyle      *style,
     g_object_unref (free_me);
 }
 
-static void
-create_expander_affine (gdouble affine[6],
-                       gint    degrees,
-                       gint    expander_size,
-                       gint    x,
-                       gint    y)
-{
-  gdouble s, c;
-  gdouble width;
-  gdouble height;
-
-  width = expander_size / 4.0;
-  height = expander_size / 2.0;
-
-  switch (degrees)
-    {
-    case 0:
-      s = 0.0;
-      c = 1.0;
-      break;
-    case 90:
-      s = 1.0;
-      c = 0.0;
-      break;
-    case 180:
-      s = 0.0;
-      c = -1.0;
-      break;
-    default:
-      s = sin (degrees * G_PI / 180.0);
-      c = cos (degrees * G_PI / 180.0);
-      break;
-    }
-  
-  affine[0] = c;
-  affine[1] = s;
-  affine[2] = -s;
-  affine[3] = c;
-  affine[4] = -width * c - height * -s + x;
-  affine[5] = -width * s - height * c + y;
-}
-
-static void
-apply_affine_on_point (double affine[6], GdkPoint *point)
-{
-  gdouble x, y;
-
-  x = point->x * affine[0] + point->y * affine[2] + affine[4];
-  y = point->x * affine[1] + point->y * affine[3] + affine[5];
-
-  point->x = floor (x);
-  point->y = floor (y);
-}
-
-static void
-gtk_style_draw_polygon_with_gc (GdkWindow *window, GdkGC *gc, gint line_width,
-                               gboolean do_fill, GdkPoint *points, gint n_points)
-{
-  gdk_gc_set_line_attributes (gc, line_width,
-                             GDK_LINE_SOLID,
-                             GDK_CAP_BUTT, GDK_JOIN_MITER);
-
-  gdk_draw_polygon (window, gc, do_fill, points, n_points);
-  gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
-}
-
 static void
 gtk_default_draw_expander (GtkStyle        *style,
                            GdkWindow       *window,
@@ -4863,82 +4760,127 @@ gtk_default_draw_expander (GtkStyle        *style,
                            gint             y,
                           GtkExpanderStyle expander_style)
 {
+#define DEFAULT_EXPANDER_SIZE 12
+
   gint expander_size;
-  GdkPoint points[3];
-  gint i;
-  gint line_width, o;
-  gdouble affine[6];
+  gint line_width;
+  double vertical_overshoot;
+  int diameter;
+  double radius;
+  double interp;               /* interpolation factor for center position */
+  double x_double_horz, y_double_horz;
+  double x_double_vert, y_double_vert;
+  double x_double, y_double;
   gint degrees = 0;
 
-  gtk_widget_style_get (widget,
-                       "expander-size", &expander_size,
-                       NULL);
-  line_width = MAX (1, expander_size/9);
-
+  cairo_t *cr = gdk_cairo_create (window);
+  
   if (area)
     {
-      gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], area);
-      gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], area);
+      gdk_cairo_rectangle (cr, area);
+      cairo_clip (cr);
     }
 
-  /* a rough estimate of how much the joins of the triangle will overshoot. 
-   * 2.4 ~ 1 / tan (45 / 2)
-   */
-  o = ceil (2.4 * line_width / 2.0);
-  points[0].x = line_width / 2;
-  points[0].y = o;
-  points[1].x = expander_size / 2 + line_width / 2 - o;
-  points[1].y = expander_size / 2;
-  points[2].x = line_width / 2;
-  points[2].y = expander_size - o;
+  if (widget &&
+      gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget),
+                                           "expander-size"))
+    {
+      gtk_widget_style_get (widget,
+                           "expander-size", &expander_size,
+                           NULL);
+    }
+  else
+    expander_size = DEFAULT_EXPANDER_SIZE;
+    
+  line_width = MAX (1, expander_size/9);
 
   switch (expander_style)
     {
     case GTK_EXPANDER_COLLAPSED:
       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 180 : 0;
+      interp = 0.0;
       break;
     case GTK_EXPANDER_SEMI_COLLAPSED:
       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 150 : 30;
+      interp = 0.25;
       break;
     case GTK_EXPANDER_SEMI_EXPANDED:
       degrees = (get_direction (widget) == GTK_TEXT_DIR_RTL) ? 120 : 60;
+      interp = 0.75;
       break;
     case GTK_EXPANDER_EXPANDED:
       degrees = 90;
+      interp = 1.0;
       break;
     default:
       g_assert_not_reached ();
     }
 
-  create_expander_affine (affine, degrees, expander_size, x, y);
+  /* Compute distance that the stroke extends beyonds the end
+   * of the triangle we draw.
+   */
+  vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8));
+
+  /* For odd line widths, we end the vertical line of the triangle
+   * at a half pixel, so we round differently.
+   */
+  if (line_width % 2 == 1)
+    vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5;
+  else
+    vertical_overshoot = ceil (vertical_overshoot);
+
+  /* Adjust the size of the triangle we draw so that the entire stroke fits
+   */
+  diameter = MAX (3, expander_size - 2 * vertical_overshoot);
+
+  /* If the line width is odd, we want the diameter to be even,
+   * and vice versa, so force the sum to be odd. This relationship
+   * makes the point of the triangle look right.
+   */
+  diameter -= (1 - (diameter + line_width) % 2);
+  
+  radius = diameter / 2.;
+
+  /* Adjust the center so that the stroke is properly aligned with
+   * the pixel grid. The center adjustment is different for the
+   * horizontal and vertical orientations. For intermediate positions
+   * we interpolate between the two.
+   */
+  x_double_vert = floor (x - (radius + line_width) / 2.) + (radius + line_width) / 2.;
+  y_double_vert = y - 0.5;
 
-  for (i = 0; i < 3; i++)
-    apply_affine_on_point (affine, &points[i]);
+  x_double_horz = x - 0.5;
+  y_double_horz = floor (y - (radius + line_width) / 2.) + (radius + line_width) / 2.;
+
+  x_double = x_double_vert * (1 - interp) + x_double_horz * interp;
+  y_double = y_double_vert * (1 - interp) + y_double_horz * interp;
+  
+  cairo_translate (cr, x_double, y_double);
+  cairo_rotate (cr, degrees * G_PI / 180);
+
+  cairo_move_to (cr, - radius / 2., - radius);
+  cairo_line_to (cr,   radius / 2.,   0);
+  cairo_line_to (cr, - radius / 2.,   radius);
+  cairo_close_path (cr);
+  
+  cairo_set_line_width (cr, line_width);
 
   if (state_type == GTK_STATE_PRELIGHT)
-    {
-      gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_PRELIGHT],
-                                     1, TRUE, points, 3);
-    }
+    gdk_cairo_set_source_color (cr,
+                               &style->fg[GTK_STATE_PRELIGHT]);
   else if (state_type == GTK_STATE_ACTIVE)
-    {
-      gtk_style_draw_polygon_with_gc (window, style->light_gc[GTK_STATE_ACTIVE],
-                                     1, TRUE, points, 3);
-      gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
-                                     line_width, FALSE, points, 3);
-    }
+    gdk_cairo_set_source_color (cr,
+                               &style->light[GTK_STATE_ACTIVE]);
   else
-    {
-      gtk_style_draw_polygon_with_gc (window, style->base_gc[GTK_STATE_NORMAL],
-                                     1, TRUE, points, 3);
-      gtk_style_draw_polygon_with_gc (window, style->fg_gc[GTK_STATE_NORMAL],
-                                     line_width, FALSE, points, 3);
-    }
-  if (area)
-    {
-      gdk_gc_set_clip_rectangle (style->fg_gc[GTK_STATE_NORMAL], NULL);
-      gdk_gc_set_clip_rectangle (style->base_gc[GTK_STATE_NORMAL], NULL);
-    }
+    gdk_cairo_set_source_color (cr,
+                               &style->base[GTK_STATE_NORMAL]);
+  
+  cairo_fill_preserve (cr);
+  
+  gdk_cairo_set_source_color (cr, &style->fg[state_type]);
+  cairo_stroke (cr);
+  
+  cairo_destroy (cr);
 }
 
 typedef struct _ByteRange ByteRange;
@@ -5104,9 +5046,6 @@ gtk_default_draw_layout (GtkStyle        *style,
                          PangoLayout     *layout)
 {
   GdkGC *gc;
-  
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
 
   gc = use_text ? style->text_gc[state_type] : style->fg_gc[state_type];
   
@@ -5148,9 +5087,6 @@ gtk_default_draw_resize_grip (GtkStyle       *style,
   GdkPoint points[4];
   gint i, j, skip;
 
-  g_return_if_fail (GTK_IS_STYLE (style));
-  g_return_if_fail (window != NULL);
-  
   if (area)
     {
       gdk_gc_set_clip_rectangle (style->light_gc[state_type], area);
@@ -5452,10 +5388,10 @@ gtk_default_draw_resize_grip (GtkStyle       *style,
     }
 }
 
-static void
-gtk_style_shade (GdkColor *a,
-                 GdkColor *b,
-                 gdouble   k)
+void
+_gtk_style_shade (GdkColor *a,
+                  GdkColor *b,
+                  gdouble   k)
 {
   gdouble red;
   gdouble green;
@@ -6246,6 +6182,25 @@ gtk_paint_focus (GtkStyle      *style,
   GTK_STYLE_GET_CLASS (style)->draw_focus (style, window, state_type, area, widget, detail, x, y, width, height);
 }
 
+/**
+ * gtk_paint_slider:
+ * @style: a #GtkStyle
+ * @window: a #GdkWindow
+ * @state_type: a state
+ * @shadow_type: a shadow
+ * @area: clip rectangle, or %NULL if the
+ *        output should not be clipped
+ * @widget: the widget (may be %NULL)
+ * @detail: a style detail (may be %NULL)
+ * @x: the x origin of the rectangle in which to draw a slider
+ * @y: the y origin of the rectangle in which to draw a slider
+ * @width: the width of the rectangle in which to draw a slider
+ * @height: the height of the rectangle in which to draw a slider
+ * @orientation: the orientation to be used
+ *
+ * Draws a slider in the given rectangle on @window using the
+ * given style and orientation.
+ **/
 void
 gtk_paint_slider (GtkStyle      *style,
                   GdkWindow     *window,
@@ -6317,9 +6272,19 @@ gtk_paint_handle (GtkStyle      *style,
  * @detail: a style detail (may be %NULL)
  * @x: the x position to draw the expander at
  * @y: the y position to draw the expander at
- * @expander_style: the style to draw the expander in
+ * @expander_style: the style to draw the expander in; determines
+ *   whether the expander is collapsed, expanded, or in an
+ *   intermediate state.
  * 
- * Draws an expander as used in #GtkTreeView.
+ * Draws an expander as used in #GtkTreeView. @x and @y specify the
+ * center the expander. The size of the expander is determined by the
+ * "expander-size" style property of @widget.  (If widget is not
+ * specified or doesn't have an "expander-size" property, an
+ * unspecified default size will be used, since the caller doesn't
+ * have sufficient information to position the expander, this is
+ * likely not useful.) The expander is expander_size pixels tall
+ * in the collapsed position and expander_size pixels wide in the
+ * expanded position.
  **/
 void
 gtk_paint_expander (GtkStyle        *style,
@@ -6340,11 +6305,28 @@ gtk_paint_expander (GtkStyle        *style,
                                               widget, detail, x, y, expander_style);
 }
 
+/**
+ * gtk_paint_layout:
+ * @style: a #GtkStyle
+ * @window: a #GdkWindow
+ * @state_type: a state
+ * @use_text: whether to use the text or foreground
+ *            graphics context of @style
+ * @area: clip rectangle, or %NULL if the
+ *        output should not be clipped
+ * @widget: the widget (may be %NULL)
+ * @detail: a style detail (may be %NULL)
+ * @x: x origin
+ * @y: y origin
+ * @layout: the layout to draw
+ * 
+ * Draws a layout on @window using the given parameters.
+ **/
 void
 gtk_paint_layout (GtkStyle        *style,
                   GdkWindow       *window,
                   GtkStateType     state_type,
-                 gboolean         use_text,
+                  gboolean         use_text,
                   GdkRectangle    *area,
                   GtkWidget       *widget,
                   const gchar     *detail,
@@ -6432,7 +6414,7 @@ gtk_border_get_type (void)
   static GType our_type = 0;
   
   if (our_type == 0)
-    our_type = g_boxed_type_register_static ("GtkBorder",
+    our_type = g_boxed_type_register_static (I_("GtkBorder"),
                                             (GBoxedCopyFunc) gtk_border_copy,
                                             (GBoxedFreeFunc) gtk_border_free);
 
@@ -6571,7 +6553,7 @@ style_unrealize_cursor_gcs (GtkStyle *style)
        gtk_gc_release (cursor_info->secondary_gc);
       
       g_free (cursor_info);
-      g_object_set_data (G_OBJECT (style), "gtk-style-cursor-info", NULL);
+      g_object_set_data (G_OBJECT (style), I_("gtk-style-cursor-info"), NULL);
     }
 }
 
@@ -6609,7 +6591,7 @@ get_insertion_cursor_gc (GtkWidget *widget,
   if (!cursor_info)
     {
       cursor_info = g_new (CursorInfo, 1);
-      g_object_set_data (G_OBJECT (widget->style), "gtk-style-cursor-info", cursor_info);
+      g_object_set_data (G_OBJECT (widget->style), I_("gtk-style-cursor-info"), cursor_info);
       cursor_info->primary_gc = NULL;
       cursor_info->secondary_gc = NULL;
       cursor_info->for_type = G_TYPE_INVALID;
@@ -6673,8 +6655,10 @@ draw_insertion_cursor (GtkWidget        *widget,
   gfloat cursor_aspect_ratio;
   gint offset;
   
-  g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
-  
+  /* When changing the shape or size of the cursor here,
+   * propagate the changes to gtktextview.c:text_window_invalidate_cursors().
+   */
+
   gtk_widget_style_get (widget, "cursor-aspect-ratio", &cursor_aspect_ratio, NULL);
   
   stem_width = location->height * cursor_aspect_ratio + 1;
@@ -6766,3 +6750,6 @@ gtk_draw_insertion_cursor (GtkWidget        *widget,
   if (area)
     gdk_gc_set_clip_rectangle (gc, NULL);
 }
+
+#define __GTK_STYLE_C__
+#include "gtkaliasdef.c"