+static gboolean
+all_columns_selected (PsppSheetView *tree_view)
+{
+ GList *list;
+
+ for (list = tree_view->priv->columns; list; list = list->next)
+ {
+ PsppSheetViewColumn *column = list->data;
+ if (column->selectable && !column->selected)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+pspp_sheet_view_row_head_clicked (PsppSheetView *tree_view,
+ gint node,
+ PsppSheetViewColumn *column,
+ GdkEventButton *event)
+{
+ PsppSheetSelection *selection;
+ PsppSheetSelectionMode mode;
+ GtkTreePath *path;
+ gboolean update_anchor;
+ gboolean handled;
+ guint modifiers;
+
+ g_return_val_if_fail (tree_view != NULL, FALSE);
+ g_return_val_if_fail (column != NULL, FALSE);
+
+ selection = tree_view->priv->selection;
+ mode = pspp_sheet_selection_get_mode (selection);
+ if (mode != PSPP_SHEET_SELECTION_RECTANGLE)
+ return FALSE;
+
+ if (!column->row_head)
+ return FALSE;
+
+ if (event)
+ {
+ modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
+ if (event->type != GDK_BUTTON_PRESS
+ || (modifiers != GDK_CONTROL_MASK && modifiers != GDK_SHIFT_MASK))
+ return FALSE;
+ }
+ else
+ modifiers = 0;
+
+ path = gtk_tree_path_new_from_indices (node, -1);
+ if (event == NULL)
+ {
+ pspp_sheet_selection_unselect_all (selection);
+ pspp_sheet_selection_select_path (selection, path);
+ pspp_sheet_selection_select_all_columns (selection);
+ update_anchor = TRUE;
+ handled = TRUE;
+ }
+ else if (event->type == GDK_BUTTON_PRESS && event->button == 3)
+ {
+ if (pspp_sheet_selection_count_selected_rows (selection) <= 1
+ || !all_columns_selected (tree_view))
+ {
+ pspp_sheet_selection_unselect_all (selection);
+ pspp_sheet_selection_select_path (selection, path);
+ pspp_sheet_selection_select_all_columns (selection);
+ update_anchor = TRUE;
+ handled = FALSE;
+ }
+ else
+ update_anchor = handled = FALSE;
+ }
+ else if (event->type == GDK_BUTTON_PRESS && event->button == 1
+ && modifiers == GDK_CONTROL_MASK)
+ {
+ if (!all_columns_selected (tree_view))
+ {
+ pspp_sheet_selection_unselect_all (selection);
+ pspp_sheet_selection_select_all_columns (selection);
+ }
+
+ if (pspp_sheet_selection_path_is_selected (selection, path))
+ pspp_sheet_selection_unselect_path (selection, path);
+ else
+ pspp_sheet_selection_select_path (selection, path);
+ update_anchor = TRUE;
+ handled = TRUE;
+ }
+ else if (event->type == GDK_BUTTON_PRESS && event->button == 1
+ && modifiers == GDK_SHIFT_MASK)
+ {
+ GtkTreeRowReference *anchor = tree_view->priv->anchor;
+ GtkTreePath *anchor_path;
+
+ if (all_columns_selected (tree_view)
+ && gtk_tree_row_reference_valid (anchor))
+ {
+ update_anchor = FALSE;
+ anchor_path = gtk_tree_row_reference_get_path (anchor);
+ }
+ else
+ {
+ update_anchor = TRUE;
+ anchor_path = gtk_tree_path_copy (path);
+ }
+
+ pspp_sheet_selection_unselect_all (selection);
+ pspp_sheet_selection_select_range (selection, anchor_path, path);
+ pspp_sheet_selection_select_all_columns (selection);
+
+ gtk_tree_path_free (anchor_path);
+
+ handled = TRUE;
+ }
+ else
+ update_anchor = handled = FALSE;
+
+ if (update_anchor)
+ {
+ if (tree_view->priv->anchor)
+ gtk_tree_row_reference_free (tree_view->priv->anchor);
+ tree_view->priv->anchor =
+ gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
+ tree_view->priv->model,
+ path);
+ }
+
+ gtk_tree_path_free (path);
+ return handled;
+}
+
+static gboolean
+find_click (PsppSheetView *tree_view,
+ gint x, gint y,
+ gint *node,
+ PsppSheetViewColumn **column,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area)
+{
+ gint y_offset;
+ gboolean rtl;
+ GList *list;
+ gint new_y;
+
+ /* find the node that was clicked */
+ new_y = TREE_WINDOW_Y_TO_RBTREE_Y(tree_view, y);
+ if (new_y < 0)
+ new_y = 0;
+ y_offset = -pspp_sheet_view_find_offset (tree_view, new_y, node);
+
+ if (*node < 0)
+ return FALSE;
+
+ background_area->y = y_offset + y;
+ background_area->height = ROW_HEIGHT (tree_view);
+ background_area->x = 0;
+
+ /* Let the column have a chance at selecting it. */
+ rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+ for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+ list; list = (rtl ? list->prev : list->next))
+ {
+ PsppSheetViewColumn *candidate = list->data;
+
+ if (!candidate->visible)
+ continue;
+
+ background_area->width = candidate->width;
+ if ((background_area->x > x) ||
+ (background_area->x + background_area->width <= x))
+ {
+ background_area->x += background_area->width;
+ continue;
+ }
+
+ /* we found the focus column */
+
+ pspp_sheet_view_adjust_cell_area (tree_view, candidate, background_area,
+ TRUE, cell_area);
+ *column = candidate;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+