Remove unreachable code
[claws.git] / src / gtk / gtkcmclist.c
index d61343002f8635fb1e2886e7eca9618d61b77049..7980b8a2469d184c4f18055461d12ac61b743671 100644 (file)
@@ -175,6 +175,13 @@ enum {
   ARG_REORDERABLE,
   ARG_USE_DRAG_ICONS,
   ARG_SORT_TYPE
+#if GTK_CHECK_VERSION(3, 0, 0)
+  ,
+  ARG_HADJUSTMENT,
+  ARG_VADJUSTMENT,
+  ARG_HADJUSTMENT_POLICY,
+  ARG_VADJUSTMENT_POLICY
+#endif
 };
 
 /* GtkCMCList Methods */
@@ -185,7 +192,11 @@ static GObject* gtk_cmclist_constructor (GType                  type,
                                       GObjectConstructParam *construct_params);
 
 /* GtkObject Methods */
+#if !GTK_CHECK_VERSION(3, 0, 0)
 static void gtk_cmclist_destroy  (GtkObject *object);
+#else
+static void gtk_cmclist_destroy  (GtkWidget *object);
+#endif
 static void gtk_cmclist_finalize (GObject   *object);
 static void gtk_cmclist_set_arg  (GObject *object,
                                guint      arg_id,
@@ -197,21 +208,36 @@ static void gtk_cmclist_get_arg  (GObject *object,
                                GParamSpec *spec);
 
 /* GtkWidget Methods */
+#if !GTK_CHECK_VERSION(3, 0, 0)
 static void gtk_cmclist_set_scroll_adjustments (GtkCMCList      *clist,
                                              GtkAdjustment *hadjustment,
                                              GtkAdjustment *vadjustment);
+#endif
 static void gtk_cmclist_realize         (GtkWidget        *widget);
 static void gtk_cmclist_unrealize       (GtkWidget        *widget);
 static void gtk_cmclist_map             (GtkWidget        *widget);
 static void gtk_cmclist_unmap           (GtkWidget        *widget);
+#if !GTK_CHECK_VERSION(3, 0, 0)
 static gint gtk_cmclist_expose          (GtkWidget        *widget,
-                                      GdkEventExpose   *event);
+                                         GdkEventExpose   *event);
+#else
+static gint gtk_cmclist_expose          (GtkWidget *widget,
+                                         cairo_t *event);
+#endif
 static gint gtk_cmclist_button_press    (GtkWidget        *widget,
                                       GdkEventButton   *event);
 static gint gtk_cmclist_button_release  (GtkWidget        *widget,
                                       GdkEventButton   *event);
 static gint gtk_cmclist_motion          (GtkWidget        *widget, 
                                       GdkEventMotion   *event);
+#if GTK_CHECK_VERSION(3, 0, 0)
+static void gtk_cmclist_get_preferred_height (GtkWidget *widget,
+                                 gint      *minimal_height,
+                                 gint      *natural_height);
+static void gtk_cmclist_get_preferred_width (GtkWidget *widget,
+                                 gint      *minimal_width,
+                                 gint      *natural_width);
+#endif
 static void gtk_cmclist_size_request    (GtkWidget        *widget,
                                       GtkRequisition   *requisition);
 static void gtk_cmclist_size_allocate   (GtkWidget        *widget,
@@ -364,12 +390,8 @@ static void column_button_clicked     (GtkWidget      *widget,
 /* Adjustments */
 static void adjust_adjustments        (GtkCMCList       *clist,
                                       gboolean        block_resize);
-static void vadjustment_changed       (GtkAdjustment  *adjustment,
-                                      gpointer        data);
 static void vadjustment_value_changed (GtkAdjustment  *adjustment,
                                       gpointer        data);
-static void hadjustment_changed       (GtkAdjustment  *adjustment,
-                                      gpointer        data);
 static void hadjustment_value_changed (GtkAdjustment  *adjustment,
                                       gpointer        data);
 
@@ -454,11 +476,13 @@ static void drag_dest_cell            (GtkCMCList         *clist,
 
 
 
-static GtkContainerClass *parent_class = NULL;
 static guint clist_signals[LAST_SIGNAL] = {0};
 
 static const GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
 
+#if !GTK_CHECK_VERSION(3, 0, 0)
+static gpointer gtk_cmclist_parent_class = NULL;
+
 GType
 gtk_cmclist_get_type (void)
 {
@@ -486,26 +510,41 @@ gtk_cmclist_get_type (void)
 
   return clist_type;
 }
+#else
+G_DEFINE_TYPE_WITH_CODE (GtkCMCList, gtk_cmclist, GTK_TYPE_CONTAINER,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE,
+                         NULL))
+#endif
 
 static void
 gtk_cmclist_class_init (GtkCMCListClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+#if !GTK_CHECK_VERSION(3, 0, 0)
   GtkObjectClass *gtk_object_class;
+#endif
   GtkWidgetClass *widget_class;
   GtkContainerClass *container_class;
   GtkBindingSet *binding_set;
 
   object_class->constructor = gtk_cmclist_constructor;
 
+#if !GTK_CHECK_VERSION(3, 0, 0)
   gtk_object_class = (GtkObjectClass *) klass;
+#endif
   widget_class = (GtkWidgetClass *) klass;
   container_class = (GtkContainerClass *) klass;
 
-  parent_class = g_type_class_peek (GTK_TYPE_CONTAINER);
+#if !GTK_CHECK_VERSION(3, 0, 0)
+  gtk_cmclist_parent_class = g_type_class_peek (GTK_TYPE_CONTAINER);
+#endif
 
   object_class->finalize = gtk_cmclist_finalize;
+#if !GTK_CHECK_VERSION(3, 0, 0)
   gtk_object_class->destroy = gtk_cmclist_destroy;
+#else
+  widget_class->destroy = gtk_cmclist_destroy;
+#endif
   object_class->set_property = gtk_cmclist_set_arg;
   object_class->get_property = gtk_cmclist_get_arg;
   
@@ -517,8 +556,17 @@ gtk_cmclist_class_init (GtkCMCListClass *klass)
   widget_class->button_press_event = gtk_cmclist_button_press;
   widget_class->button_release_event = gtk_cmclist_button_release;
   widget_class->motion_notify_event = gtk_cmclist_motion;
+#if !GTK_CHECK_VERSION(3, 0, 0)
   widget_class->expose_event = gtk_cmclist_expose;
+#else
+  widget_class->draw = gtk_cmclist_expose;
+#endif
+#if !GTK_CHECK_VERSION(3, 0, 0)
   widget_class->size_request = gtk_cmclist_size_request;
+#else
+  widget_class->get_preferred_width = gtk_cmclist_get_preferred_width;
+  widget_class->get_preferred_height = gtk_cmclist_get_preferred_height;
+#endif
   widget_class->size_allocate = gtk_cmclist_size_allocate;
   widget_class->focus_in_event = gtk_cmclist_focus_in;
   widget_class->focus_out_event = gtk_cmclist_focus_out;
@@ -538,7 +586,9 @@ gtk_cmclist_class_init (GtkCMCListClass *klass)
   container_class->forall = gtk_cmclist_forall;
   container_class->set_focus_child = gtk_cmclist_set_focus_child;
 
+#if !GTK_CHECK_VERSION(3, 0, 0)
   klass->set_scroll_adjustments = gtk_cmclist_set_scroll_adjustments;
+#endif
   klass->refresh = clist_refresh;
   klass->select_row = real_select_row;
   klass->unselect_row = real_unselect_row;
@@ -627,6 +677,7 @@ gtk_cmclist_class_init (GtkCMCListClass *klass)
                                "sort-type",
                                GTK_TYPE_SORT_TYPE, 0,
                                G_PARAM_READWRITE));
+#if !GTK_CHECK_VERSION(3, 0, 0)
   widget_class->set_scroll_adjustments_signal =
                g_signal_new ("set_scroll_adjustments",
                              G_TYPE_FROM_CLASS (object_class),
@@ -636,6 +687,13 @@ gtk_cmclist_class_init (GtkCMCListClass *klass)
                              claws_marshal_VOID__OBJECT_OBJECT,
                              G_TYPE_NONE, 2,
                              GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
+#else
+  /* Scrollable interface properties */
+  g_object_class_override_property (object_class, ARG_HADJUSTMENT, "hadjustment");
+  g_object_class_override_property (object_class, ARG_VADJUSTMENT, "vadjustment");
+  g_object_class_override_property (object_class, ARG_HADJUSTMENT_POLICY, "hscroll-policy");
+  g_object_class_override_property (object_class, ARG_VADJUSTMENT_POLICY, "vscroll-policy");
+#endif
 
   clist_signals[SELECT_ROW] =
                g_signal_new ("select_row",
@@ -926,9 +984,9 @@ gtk_cmclist_class_init (GtkCMCListClass *klass)
                                "toggle_add_mode", 0);
   gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
                                "toggle_add_mode", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
                                "select_all", 0);
-  gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, GDK_CONTROL_MASK,
+  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Divide, GDK_CONTROL_MASK,
                                "select_all", 0);
   gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
                                "unselect_all", 0);
@@ -987,6 +1045,17 @@ gtk_cmclist_set_arg (GObject *object,
     case ARG_SORT_TYPE:
       gtk_cmclist_set_sort_type (clist, g_value_get_enum (value));
       break;
+#if GTK_CHECK_VERSION(3, 0, 0)
+    case ARG_HADJUSTMENT:
+      gtk_cmclist_set_hadjustment (clist, g_value_get_object (value));
+      break;
+    case ARG_VADJUSTMENT:
+      gtk_cmclist_set_vadjustment (clist, g_value_get_object (value));
+      break;
+    case ARG_HADJUSTMENT_POLICY:
+    case ARG_VADJUSTMENT_POLICY:
+      break;
+#endif
     }
 }
 
@@ -1035,6 +1104,18 @@ gtk_cmclist_get_arg (GObject *object,
     case ARG_SORT_TYPE:
       g_value_set_enum(value, clist->sort_type);
       break;
+#if GTK_CHECK_VERSION(3, 0, 0)
+    case ARG_HADJUSTMENT:
+      g_value_set_object(value, gtk_cmclist_get_hadjustment(clist));
+      break;
+    case ARG_VADJUSTMENT:
+      g_value_set_object(value, gtk_cmclist_get_vadjustment(clist));
+      break;
+    case ARG_HADJUSTMENT_POLICY:
+    case ARG_VADJUSTMENT_POLICY:
+      g_value_set_enum(value, GTK_SCROLL_NATURAL);
+      break;
+#endif
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, spec);
       break;
@@ -1051,12 +1132,6 @@ gtk_cmclist_init (GtkCMCList *clist)
   GTK_CMCLIST_SET_FLAG (clist, CMCLIST_DRAW_DRAG_LINE);
   GTK_CMCLIST_SET_FLAG (clist, CMCLIST_USE_DRAG_ICONS);
 
-
-#if !GLIB_CHECK_VERSION(2,10,0)
-  clist->row_mem_chunk = NULL;
-  clist->cell_mem_chunk = NULL;
-#endif
-
   clist->freeze_count = 0;
 
   clist->rows = 0;
@@ -1124,27 +1199,11 @@ gtk_cmclist_constructor (GType                  type,
                       guint                  n_construct_properties,
                       GObjectConstructParam *construct_properties)
 {
-  GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
+  GObject *object = G_OBJECT_CLASS (gtk_cmclist_parent_class)->constructor (type,
                                                                n_construct_properties,
                                                                construct_properties);
   GtkCMCList *clist = GTK_CMCLIST (object);
   
-#if !GLIB_CHECK_VERSION(2,10,0)
-  if (!clist->row_mem_chunk)
-    clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
-                                           sizeof (GtkCMCListRow),
-                                           sizeof (GtkCMCListRow) *
-                                           CMCLIST_OPTIMUM_SIZE, 
-                                           G_ALLOC_AND_FREE);
-  
-  if (!clist->cell_mem_chunk)
-    clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
-                                            sizeof (GtkCMCell) * clist->columns,
-                                            sizeof (GtkCMCell) * clist->columns *
-                                            CMCLIST_OPTIMUM_SIZE, 
-                                            G_ALLOC_AND_FREE);
-#endif
-
   /* allocate memory for columns */
   clist->column = columns_new (clist);
   
@@ -1225,15 +1284,7 @@ gtk_cmclist_set_hadjustment (GtkCMCList      *clist,
 
   if (clist->hadjustment)
     {
-#if GLIB_CHECK_VERSION(2,10,0)
       g_object_ref_sink (clist->hadjustment);
-#else
-      gtk_object_ref (G_OBJECT (clist->hadjustment));
-      gtk_object_sink (G_OBJECT (clist->hadjustment));
-#endif
-      g_signal_connect (G_OBJECT (clist->hadjustment), "changed",
-                         G_CALLBACK( hadjustment_changed),
-                         (gpointer) clist);
       g_signal_connect (G_OBJECT (clist->hadjustment), "value_changed",
                          G_CALLBACK( hadjustment_value_changed),
                          (gpointer) clist);
@@ -1277,16 +1328,8 @@ gtk_cmclist_set_vadjustment (GtkCMCList      *clist,
 
   if (clist->vadjustment)
     {
-#if GLIB_CHECK_VERSION(2,10,0)
       g_object_ref_sink (clist->vadjustment);
-#else
-      gtk_object_ref (G_OBJECT (clist->vadjustment));
-      gtk_object_sink (G_OBJECT (clist->vadjustment));
-#endif
 
-      g_signal_connect (G_OBJECT (clist->vadjustment), "changed",
-                         G_CALLBACK(vadjustment_changed),
-                         (gpointer) clist);
       g_signal_connect (G_OBJECT (clist->vadjustment), "value_changed",
                          G_CALLBACK(vadjustment_value_changed),
                          (gpointer) clist);
@@ -1304,6 +1347,7 @@ gtk_cmclist_get_vadjustment (GtkCMCList *clist)
   return clist->vadjustment;
 }
 
+#if !GTK_CHECK_VERSION(3, 0, 0)
 static void
 gtk_cmclist_set_scroll_adjustments (GtkCMCList      *clist,
                                  GtkAdjustment *hadjustment,
@@ -1314,6 +1358,7 @@ gtk_cmclist_set_scroll_adjustments (GtkCMCList      *clist,
   if (clist->vadjustment != vadjustment)
     gtk_cmclist_set_vadjustment (clist, vadjustment);
 }
+#endif
 
 void
 gtk_cmclist_set_shadow_type (GtkCMCList      *clist,
@@ -3123,7 +3168,7 @@ gtk_cmclist_set_row_height (GtkCMCList *clist,
        {
          clist->row_height = (pango_font_metrics_get_ascent (metrics) +
                               pango_font_metrics_get_descent (metrics));
-         clist->row_height = PANGO_PIXELS (clist->row_height) + 2;
+         clist->row_height = PANGO_PIXELS (clist->row_height) + 1;
        }
 
       pango_font_metrics_unref (metrics);
@@ -3283,9 +3328,11 @@ gtk_cmclist_set_foreground (GtkCMCList       *clist,
     {
       clist_row->foreground = *color;
       clist_row->fg_set = TRUE;
+#if !GTK_CHECK_VERSION(3, 0, 0)
       if (gtk_widget_get_realized (GTK_WIDGET(clist)))
        gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (clist)),
                         &clist_row->foreground, TRUE, TRUE);
+#endif
     }
   else
     clist_row->fg_set = FALSE;
@@ -3312,9 +3359,11 @@ gtk_cmclist_set_background (GtkCMCList       *clist,
     {
       clist_row->background = *color;
       clist_row->bg_set = TRUE;
+#if !GTK_CHECK_VERSION(3, 0, 0)
       if (gtk_widget_get_realized (GTK_WIDGET(clist)))
        gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (clist)),
                         &clist_row->background, TRUE, TRUE);
+#endif
     }
   else
     clist_row->bg_set = FALSE;
@@ -3646,6 +3695,7 @@ toggle_row (GtkCMCList *clist,
                           row, column, event);
          return;
        }
+      break;
     case GTK_SELECTION_BROWSE:
       g_signal_emit (G_OBJECT (clist), clist_signals[SELECT_ROW], 0,
                       row, column, event);
@@ -4421,7 +4471,11 @@ sync_selection (GtkCMCList *clist,
  *   gtk_cmclist_finalize
  */
 static void
+#if !GTK_CHECK_VERSION(3, 0, 0)
 gtk_cmclist_destroy (GtkObject *object)
+#else
+gtk_cmclist_destroy (GtkWidget *object)
+#endif
 {
   gint i;
   GtkCMCList *clist;
@@ -4469,8 +4523,13 @@ gtk_cmclist_destroy (GtkObject *object)
        clist->column[i].button = NULL;
       }
 
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+#if !GTK_CHECK_VERSION(3, 0, 0)
+  if (GTK_OBJECT_CLASS (gtk_cmclist_parent_class)->destroy)
+    (*GTK_OBJECT_CLASS (gtk_cmclist_parent_class)->destroy) (object);
+#else
+  if (GTK_WIDGET_CLASS (gtk_cmclist_parent_class)->destroy)
+    (*GTK_WIDGET_CLASS (gtk_cmclist_parent_class)->destroy) (object);
+#endif
 }
 
 static void
@@ -4484,11 +4543,7 @@ gtk_cmclist_finalize (GObject *object)
 
   columns_delete (clist);
 
-#if !GLIB_CHECK_VERSION(2,10,0)
-  g_mem_chunk_destroy (clist->cell_mem_chunk);
-  g_mem_chunk_destroy (clist->row_mem_chunk);
-#endif
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gtk_cmclist_parent_class)->finalize (object);
 }
 
 /* GTKWIDGET
@@ -4509,10 +4564,9 @@ gtk_cmclist_realize (GtkWidget *widget)
 {
   GtkAllocation allocation;
   GtkCMCList *clist;
-  GtkStyle *style;
+  GtkStyle *style, *attached_style;
   GdkWindow *window;
   GdkWindowAttr attributes;
-  GdkGCValues values;
   GtkCMCListRow *clist_row;
   GList *list;
   gint attributes_mask;
@@ -4537,24 +4591,32 @@ gtk_cmclist_realize (GtkWidget *widget)
   attributes.height = allocation.height - border_width * 2;
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.visual = gtk_widget_get_visual (widget);
+#if !GTK_CHECK_VERSION(3, 0, 0)
   attributes.colormap = gtk_widget_get_colormap (widget);
+#endif
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_EXPOSURE_MASK |
                            GDK_BUTTON_PRESS_MASK |
                            GDK_BUTTON_RELEASE_MASK |
                            GDK_KEY_RELEASE_MASK);
+#if !GTK_CHECK_VERSION(3, 0, 0)
   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+#else
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+#endif
 
   /* main window */
-  window = gtk_widget_get_window (widget);
   window = gdk_window_new (gtk_widget_get_parent_window (widget),
                                   &attributes, attributes_mask);
   gdk_window_set_user_data (window, clist);
   gtk_widget_set_window (widget, window);
 
   style = gtk_widget_get_style (widget);
-  style = gtk_style_attach (style, window);
-  gtk_widget_set_style (widget, style);
+  attached_style = gtk_style_attach (style, window);
+  if (attached_style != style) {
+       gtk_widget_set_style(widget, attached_style);
+       style = attached_style;
+  }
 
   gtk_style_set_background (style, window, GTK_STATE_NORMAL);
 
@@ -4595,8 +4657,13 @@ gtk_cmclist_realize (GtkWidget *widget)
   gdk_window_set_background (clist->clist_window,
                             &style->base[GTK_STATE_NORMAL]);
   gdk_window_show (clist->clist_window);
+#if GTK_CHECK_VERSION(2,24,0)
+  clist->clist_window_width = gdk_window_get_width(clist->clist_window);
+  clist->clist_window_height = gdk_window_get_height(clist->clist_window);
+#else
   gdk_drawable_get_size (clist->clist_window, &clist->clist_window_width,
                       &clist->clist_window_height);
+#endif
 
   /* create resize windows */
   attributes.wclass = GDK_INPUT_ONLY;
@@ -4637,6 +4704,7 @@ gtk_cmclist_realize (GtkWidget *widget)
        clist_row->style = gtk_style_attach (clist_row->style,
                                             clist->clist_window);
 
+#if !GTK_CHECK_VERSION(3, 0, 0)
       if (clist_row->fg_set || clist_row->bg_set)
        {
          GdkColormap *colormap;
@@ -4647,6 +4715,7 @@ gtk_cmclist_realize (GtkWidget *widget)
          if (clist_row->bg_set)
            gdk_colormap_alloc_color (colormap, &clist_row->background, TRUE, TRUE);
        }
+#endif
       
       for (j = 0; j < clist->columns; j++)
        if  (clist_row->cell[j].style)
@@ -4718,8 +4787,8 @@ gtk_cmclist_unrealize (GtkWidget *widget)
 
   clist->cursor_drag = NULL;
 
-  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
-    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+  if (GTK_WIDGET_CLASS (gtk_cmclist_parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS (gtk_cmclist_parent_class)->unrealize) (widget);
 }
 
 static void
@@ -4817,50 +4886,60 @@ gtk_cmclist_unmap (GtkWidget *widget)
     }
 }
 
+#if !GTK_CHECK_VERSION(3, 0, 0)
 static gint
 gtk_cmclist_expose (GtkWidget      *widget,
                  GdkEventExpose *event)
+#else
+static gint
+gtk_cmclist_expose (GtkWidget *widget,
+          cairo_t *event)
+#endif
 {
-  GdkWindow *window;
   GtkCMCList *clist;
-  GtkStyle *style;
 
   cm_return_val_if_fail (GTK_IS_CMCLIST (widget), FALSE);
   cm_return_val_if_fail (event != NULL, FALSE);
 
-  window = gtk_widget_get_window (widget);
-  style = gtk_widget_get_style (widget);
-
   if (gtk_widget_is_drawable (widget))
     {
       clist = GTK_CMCLIST (widget);
 
-      /* draw border */
-      if (event->window == window)
-       gtk_paint_shadow (style, window,
-                        GTK_STATE_NORMAL, clist->shadow_type,
-                        NULL, NULL, NULL,
-                        0, 0,
-                        clist->clist_window_width +
-                        (2 * style->xthickness),
-                        clist->clist_window_height +
-                        (2 * style->ythickness) +
-                        clist->column_title_area.height);
-
       /* exposure events on the list */
+#if !GTK_CHECK_VERSION(3, 0, 0)
       if (event->window == clist->clist_window)
        draw_rows (clist, &event->area);
+#else
+      if (gtk_cairo_should_draw_window (event, clist->clist_window))
+        {
+       GdkRectangle area;
 
+       /* FIXME: get proper area */
+       if (gdk_cairo_get_clip_rectangle (event, &area))
+         draw_rows (clist, &area);
+        }
+#endif
+
+#if !GTK_CHECK_VERSION(3, 0, 0)
       if (event->window == clist->title_window)
+#else
+      if (gtk_cairo_should_draw_window (event, clist->title_window))
+#endif
        {
          gint i;
          
          for (i = 0; i < clist->columns; i++)
            {
              if (clist->column[i].button) {
+#if !GTK_CHECK_VERSION(3, 0, 0)
                gtk_container_propagate_expose (GTK_CONTAINER (clist),
                                                clist->column[i].button,
                                                event);
+#else
+               gtk_container_propagate_draw (GTK_CONTAINER (clist),
+                                               clist->column[i].button,
+                                               event);
+#endif
              }
            }
        }
@@ -4878,8 +4957,8 @@ gtk_cmclist_style_set (GtkWidget *widget,
 
   cm_return_if_fail (GTK_IS_CMCLIST (widget));
 
-  if (GTK_WIDGET_CLASS (parent_class)->style_set)
-    (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
+  if (GTK_WIDGET_CLASS (gtk_cmclist_parent_class)->style_set)
+    (*GTK_WIDGET_CLASS (gtk_cmclist_parent_class)->style_set) (widget, previous_style);
 
   clist = GTK_CMCLIST (widget);
 
@@ -5389,6 +5468,32 @@ gtk_cmclist_motion (GtkWidget      *widget,
   return FALSE;
 }
 
+#if GTK_CHECK_VERSION(3, 0, 0)
+static void
+gtk_cmclist_get_preferred_width (GtkWidget *widget,
+                                 gint      *minimal_width,
+                                 gint      *natural_width)
+{
+  GtkRequisition requisition;
+
+  gtk_cmclist_size_request (widget, &requisition);
+
+  *minimal_width = *natural_width = requisition.width;
+}
+
+static void
+gtk_cmclist_get_preferred_height (GtkWidget *widget,
+                                  gint      *minimal_height,
+                                  gint      *natural_height)
+{
+  GtkRequisition requisition;
+
+  gtk_cmclist_size_request (widget, &requisition);
+
+  *minimal_height = *natural_height = requisition.height;
+}
+#endif
+
 static void
 gtk_cmclist_size_request (GtkWidget      *widget,
                        GtkRequisition *requisition)
@@ -5396,7 +5501,6 @@ gtk_cmclist_size_request (GtkWidget      *widget,
   GtkCMCList *clist;
   GtkStyle *style;
   gint i;
-  gint font_height = 0;
   guint border_width;
   cm_return_if_fail (GTK_IS_CMCLIST (widget));
   cm_return_if_fail (requisition != NULL);
@@ -5410,7 +5514,6 @@ gtk_cmclist_size_request (GtkWidget      *widget,
   /* compute the size of the column title (title) area */
   clist->column_title_area.height = 0;
   if (GTK_CMCLIST_SHOW_TITLES(clist)) {
-    font_height = (pango_font_description_get_size(style->font_desc)/PANGO_SCALE)*2+4;
     for (i = 0; i < clist->columns; i++)
       if (clist->column[i].button)
        {
@@ -5646,7 +5749,6 @@ draw_row (GtkCMCList     *clist,
   gint state;
   gint i;
   cairo_t *cr;
-  const double dashes[] = {4.0, 4.0};
   cm_return_if_fail (clist != NULL);
 
   /* bail now if we arn't drawable yet */
@@ -5654,13 +5756,14 @@ draw_row (GtkCMCList     *clist,
     return;
 
   widget = GTK_WIDGET (clist);
-  style = gtk_widget_get_style (widget);
 
   /* if the function is passed the pointer to the row instead of null,
    * it avoids this expensive lookup */
   if (!clist_row)
     clist_row = ROW_ELEMENT (clist, row)->data;
 
+  style = clist_row->style ? clist_row->style : gtk_widget_get_style (widget);
+
   /* rectangle of the entire row */
   row_rectangle.x = 0;
   row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
@@ -5842,7 +5945,7 @@ draw_row (GtkCMCList     *clist,
          if (layout)
            {
              gint row_center_offset = (clist->row_height - logical_rect.height - 1) / 2;
-             gdk_cairo_set_source_color(cr, &gtk_widget_get_style(GTK_WIDGET(clist))->fg[state]);
+             gdk_cairo_set_source_color(cr, clist_row->fg_set ? &clist_row->foreground : &style->fg[state]);
              cairo_move_to(cr, offset, row_rectangle.y + row_center_offset + clist_row->cell[i].vertical);
              pango_cairo_show_layout(cr, layout);
               g_object_unref (G_OBJECT (layout));
@@ -5861,16 +5964,16 @@ draw_row (GtkCMCList     *clist,
       gtk_widget_get_can_focus (widget) && gtk_widget_has_focus(widget))
     {
       if (!area) {
-       cairo_rectangle(cr, row_rectangle.x + 1, row_rectangle.y,
-                           row_rectangle.width - 1, row_rectangle.height);
+       cairo_rectangle(cr, row_rectangle.x, row_rectangle.y,
+                           row_rectangle.width + 1, row_rectangle.height);
        gdk_cairo_set_source_color(cr, &style->fg[GTK_STATE_NORMAL]);
        cairo_stroke(cr);
       }
       else if (gdk_rectangle_intersect (area, &row_rectangle,
                                        &intersect_rectangle))
        {
-         cairo_rectangle(cr, row_rectangle.x + 1, row_rectangle.y,
-                           row_rectangle.width - 1, row_rectangle.height);
+         cairo_rectangle(cr, row_rectangle.x, row_rectangle.y,
+                           row_rectangle.width + 1, row_rectangle.height);
          gdk_cairo_set_source_color(cr, &style->fg[GTK_STATE_NORMAL]);
          cairo_stroke(cr);
        }
@@ -5929,11 +6032,19 @@ draw_rows (GtkCMCList     *clist,
 
   if (!area) {
     int w, h, y;
-    gdk_drawable_get_size (GDK_DRAWABLE (clist->clist_window), &w, &h);
+    cairo_t *cr;
+#if GTK_CHECK_VERSION(2,24,0)
+    w = gdk_window_get_width(clist->clist_window);
+    h = gdk_window_get_height(clist->clist_window);
+#else
+    gdk_drawable_get_size(clist->clist_window, &w, &h);
+#endif
+    cr = gdk_cairo_create(clist->clist_window);
     y = ROW_TOP_YPIXEL (clist, i);
-    gdk_window_clear_area (clist->clist_window,
-                           0, y,
-                           w, h - y);
+    gdk_cairo_set_source_color(cr, &gtk_widget_get_style(GTK_WIDGET(clist))->base[GTK_STATE_NORMAL]);
+    cairo_rectangle(cr, 0, y, w, h - y);
+    cairo_fill(cr);
+    cairo_destroy(cr);
   }
 }
 
@@ -6082,30 +6193,6 @@ adjust_adjustments (GtkCMCList *clist,
     }
 }
 
-static void
-vadjustment_changed (GtkAdjustment *adjustment,
-                    gpointer       data)
-{
-  GtkCMCList *clist;
-
-  cm_return_if_fail (adjustment != NULL);
-  cm_return_if_fail (data != NULL);
-
-  clist = GTK_CMCLIST (data);
-}
-
-static void
-hadjustment_changed (GtkAdjustment *adjustment,
-                    gpointer       data)
-{
-  GtkCMCList *clist;
-
-  cm_return_if_fail (adjustment != NULL);
-  cm_return_if_fail (data != NULL);
-
-  clist = GTK_CMCLIST (data);
-}
-
 static void
 vadjustment_value_changed (GtkAdjustment *adjustment,
                           gpointer       data)
@@ -6202,7 +6289,6 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
 {
   GtkCMCList *clist;
   GtkContainer *container;
-  GdkRectangle area;
   gint i;
   gint y = 0;
   gint value;
@@ -6239,18 +6325,19 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
   if (gtk_widget_is_drawable (GTK_WIDGET(clist)))
     {
       GtkWidget *focus_child = gtk_container_get_focus_child (container);
+      gdk_window_scroll (clist->clist_window, dx, 0);
+      gdk_window_process_updates (clist->clist_window, FALSE);
+
       if (gtk_widget_get_can_focus(GTK_WIDGET(clist)) && 
           gtk_widget_has_focus(GTK_WIDGET(clist)) &&
           !focus_child && GTK_CMCLIST_ADD_MODE(clist))
         {
           y = ROW_TOP_YPIXEL (clist, clist->focus_row);
-         cairo_rectangle(cr, 0, y, clist->clist_window_width - 1,
-                              clist->row_height - 1);
+         cairo_rectangle(cr, 0, y, clist->clist_window_width + 1,
+                              clist->row_height);
          cairo_stroke(cr);
         }
-      gdk_window_scroll (clist->clist_window, dx, 0);
-      gdk_window_process_updates (clist->clist_window, FALSE);
 
       if (gtk_widget_get_can_focus(GTK_WIDGET(clist)) && 
           gtk_widget_has_focus(GTK_WIDGET(clist)) &&
@@ -6262,38 +6349,14 @@ hadjustment_value_changed (GtkAdjustment *adjustment,
          
               focus_row = clist->focus_row;
               clist->focus_row = -1;
-              draw_rows (clist, &area);
+              draw_rows (clist, NULL);
               clist->focus_row = focus_row;
          
-             cairo_rectangle(cr, 0, y, clist->clist_window_width - 1,
-                              clist->row_height - 1);
+             cairo_rectangle(cr, 0, y, clist->clist_window_width + 1,
+                              clist->row_height);
              cairo_stroke(cr);
               return;
             }
-          else if (ABS(dx) < clist->clist_window_width - 1)
-            {
-              gint x0;
-              gint x1;
-         
-              if (dx > 0)
-                {
-                  x0 = clist->clist_window_width - 1;
-                  x1 = dx;
-                }
-              else
-                {
-                  x0 = 0;
-                  x1 = clist->clist_window_width - 1 + dx;
-                }
-
-              y = ROW_TOP_YPIXEL (clist, clist->focus_row);
-             cairo_move_to(cr, x0, y + 1);
-             cairo_line_to(cr, x0, y + clist->row_height - 2);
-             cairo_stroke(cr);
-             cairo_move_to(cr, x1, y + 1);
-             cairo_line_to(cr, x1, y + clist->row_height - 2);
-             cairo_stroke(cr);
-            }
         }
     }
     cairo_destroy(cr);
@@ -6367,13 +6430,8 @@ row_new (GtkCMCList *clist)
   int i;
   GtkCMCListRow *clist_row;
 
-#if GLIB_CHECK_VERSION(2,10,0)
   clist_row = g_slice_new (GtkCMCListRow);
   clist_row->cell = g_slice_alloc (sizeof (GtkCMCell) * clist->columns);
-#else
-  clist_row = g_chunk_new (GtkCMCListRow, (GMemChunk *)clist->row_mem_chunk);
-  clist_row->cell = g_chunk_new (GtkCMCell, (GMemChunk *)clist->cell_mem_chunk);
-#endif
 
   for (i = 0; i < clist->columns; i++)
     {
@@ -6422,13 +6480,8 @@ row_delete (GtkCMCList    *clist,
   if (clist_row->destroy)
     clist_row->destroy (clist_row->data);
 
-#if GLIB_CHECK_VERSION(2,10,0)  
   g_slice_free1 (sizeof (GtkCMCell) * clist->columns, clist_row->cell);
   g_slice_free (GtkCMCListRow, clist_row);
-#else
-  g_mem_chunk_free ((GMemChunk *)clist->cell_mem_chunk, clist_row->cell);
-  g_mem_chunk_free ((GMemChunk *)clist->row_mem_chunk, clist_row);
-#endif
 }
 
 /* FOCUS FUNCTIONS
@@ -6536,7 +6589,8 @@ gtk_cmclist_set_focus_child (GtkContainer *container,
     if (clist->column[i].button == child)
       clist->focus_header_column = i;
   
-  parent_class->set_focus_child (container, child);
+  if (GTK_CONTAINER_CLASS (gtk_cmclist_parent_class)->set_focus_child)
+    (*GTK_CONTAINER_CLASS (gtk_cmclist_parent_class)->set_focus_child) (container, child);
 }
 
 static void
@@ -6556,8 +6610,8 @@ gtk_cmclist_draw_focus (GtkWidget *widget)
     cairo_dash_from_add_mode(clist, cr);
     cairo_set_line_width(cr, 1.0);
     cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
-    cairo_rectangle(cr, 1, ROW_TOP_YPIXEL(clist, clist->focus_row),
-                       clist->clist_window_width - 1,
+    cairo_rectangle(cr, 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
+                       clist->clist_window_width + 1,
                        clist->row_height);
     cairo_stroke(cr);
     cairo_destroy(cr);
@@ -6568,17 +6622,32 @@ static void
 gtk_cmclist_undraw_focus (GtkWidget *widget)
 {
   GtkCMCList *clist;
-
+  int row;
   cm_return_if_fail (GTK_IS_CMCLIST (widget));
 
+  clist = GTK_CMCLIST(widget);
+
+  if (clist->focus_row < 0)
+    return;
+
   if (!gtk_widget_is_drawable (widget) || !gtk_widget_get_can_focus (widget))
     return;
 
   clist = GTK_CMCLIST (widget);
   if (clist->focus_row >= 0) {
-    GTK_CMCLIST_GET_CLASS(clist)->draw_row(clist, NULL, clist->focus_row, 
-       ROW_ELEMENT (clist, clist->focus_row)->data);
+    cairo_t *cr = gdk_cairo_create(clist->clist_window);
+    cairo_set_line_width(cr, 1.0);
+    gdk_cairo_set_source_color(cr, &gtk_widget_get_style(widget)->base[GTK_STATE_NORMAL]);
+    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
+    cairo_rectangle(cr, 0, ROW_TOP_YPIXEL(clist, clist->focus_row),
+                       clist->clist_window_width + 1,
+                       clist->row_height);
+    cairo_stroke(cr);
+    cairo_destroy(cr);
   }
+
+  row = clist->focus_row;
+  GTK_CMCLIST_GET_CLASS(GTK_CMCLIST(widget))->draw_row(clist, NULL, row, ROW_ELEMENT (clist, row)->data);
 }
 
 static gint
@@ -6966,16 +7035,8 @@ scroll_vertical (GtkCMCList      *clist,
       move_focus_row (clist, scroll_type, position);
 
       if (old_focus_row != clist->focus_row)
-       {
-         if (clist->selection_mode == GTK_SELECTION_BROWSE)
-           g_signal_emit (G_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
-                            old_focus_row, -1, NULL);
-         else if (!GTK_CMCLIST_ADD_MODE(clist))
-           {
-             gtk_cmclist_unselect_all (clist);
-             clist->undo_anchor = old_focus_row;
-           }
-       }
+         g_signal_emit (G_OBJECT (clist), clist_signals[UNSELECT_ROW], 0,
+                               old_focus_row, -1, NULL);
 
       switch (gtk_cmclist_row_is_visible (clist, clist->focus_row))
        {
@@ -7023,6 +7084,7 @@ scroll_vertical (GtkCMCList      *clist,
            default:
              break;
            }
+         /* fallback is intentional */ 
        default:
          if (old_focus_row != clist->focus_row &&
              !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
@@ -7305,6 +7367,9 @@ gtk_cmclist_merge (GtkCMCList *clist,
 
   c = &z;
 
+  if (!a && !b)
+       return NULL;
+
   while (a || b)
     {
       if (a && !b)
@@ -7327,8 +7392,7 @@ gtk_cmclist_merge (GtkCMCList *clist,
        {
          cmp = clist->compare (clist, GTK_CMCLIST_ROW (a), GTK_CMCLIST_ROW (b));
          if ((cmp >= 0 && clist->sort_type == GTK_SORT_DESCENDING) ||
-             (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING) ||
-             (a && !b))
+             (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING))
            {
              c->next = a;
              a->prev = c;