Blame gtk/gtktreeselection.c

Packit 98cdb6
/* gtktreeselection.h
Packit 98cdb6
 * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
Packit 98cdb6
 *
Packit 98cdb6
 * This library is free software; you can redistribute it and/or
Packit 98cdb6
 * modify it under the terms of the GNU Library General Public
Packit 98cdb6
 * License as published by the Free Software Foundation; either
Packit 98cdb6
 * version 2 of the License, or (at your option) any later version.
Packit 98cdb6
 *
Packit 98cdb6
 * This library is distributed in the hope that it will be useful,
Packit 98cdb6
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 98cdb6
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 98cdb6
 * Library General Public License for more details.
Packit 98cdb6
 *
Packit 98cdb6
 * You should have received a copy of the GNU Library General Public
Packit 98cdb6
 * License along with this library; if not, write to the
Packit 98cdb6
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 98cdb6
 * Boston, MA 02111-1307, USA.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
#include "config.h"
Packit 98cdb6
#include <string.h>
Packit 98cdb6
#include "gtktreeselection.h"
Packit 98cdb6
#include "gtktreeprivate.h"
Packit 98cdb6
#include "gtkrbtree.h"
Packit 98cdb6
#include "gtkmarshalers.h"
Packit 98cdb6
#include "gtkintl.h"
Packit 98cdb6
#include "gtkalias.h"
Packit 98cdb6
Packit 98cdb6
static void gtk_tree_selection_finalize          (GObject               *object);
Packit 98cdb6
static gint gtk_tree_selection_real_select_all   (GtkTreeSelection      *selection);
Packit 98cdb6
static gint gtk_tree_selection_real_unselect_all (GtkTreeSelection      *selection);
Packit 98cdb6
static gint gtk_tree_selection_real_select_node  (GtkTreeSelection      *selection,
Packit 98cdb6
						  GtkRBTree             *tree,
Packit 98cdb6
						  GtkRBNode             *node,
Packit 98cdb6
						  gboolean               select);
Packit 98cdb6
Packit 98cdb6
enum
Packit 98cdb6
{
Packit 98cdb6
  CHANGED,
Packit 98cdb6
  LAST_SIGNAL
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static guint tree_selection_signals [LAST_SIGNAL] = { 0 };
Packit 98cdb6
Packit 98cdb6
G_DEFINE_TYPE (GtkTreeSelection, gtk_tree_selection, G_TYPE_OBJECT)
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
Packit 98cdb6
{
Packit 98cdb6
  GObjectClass *object_class;
Packit 98cdb6
Packit 98cdb6
  object_class = (GObjectClass*) class;
Packit 98cdb6
Packit 98cdb6
  object_class->finalize = gtk_tree_selection_finalize;
Packit 98cdb6
  class->changed = NULL;
Packit 98cdb6
Packit 98cdb6
  tree_selection_signals[CHANGED] =
Packit 98cdb6
    g_signal_new (I_("changed"),
Packit 98cdb6
		  G_OBJECT_CLASS_TYPE (object_class),
Packit 98cdb6
		  G_SIGNAL_RUN_FIRST,
Packit 98cdb6
		  G_STRUCT_OFFSET (GtkTreeSelectionClass, changed),
Packit 98cdb6
		  NULL, NULL,
Packit 98cdb6
		  _gtk_marshal_VOID__VOID,
Packit 98cdb6
		  G_TYPE_NONE, 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_tree_selection_init (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  selection->type = GTK_SELECTION_SINGLE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_tree_selection_finalize (GObject *object)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreeSelection *selection = GTK_TREE_SELECTION (object);
Packit 98cdb6
Packit 98cdb6
  if (selection->destroy)
Packit 98cdb6
    {
Packit 98cdb6
      GDestroyNotify d = selection->destroy;
Packit 98cdb6
Packit 98cdb6
      selection->destroy = NULL;
Packit 98cdb6
      d (selection->user_data);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  /* chain parent_class' handler */
Packit 98cdb6
  G_OBJECT_CLASS (gtk_tree_selection_parent_class)->finalize (object);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_tree_selection_new:
Packit 98cdb6
 *
Packit 98cdb6
 * Creates a new #GtkTreeSelection object.  This function should not be invoked,
Packit 98cdb6
 * as each #GtkTreeView will create its own #GtkTreeSelection.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: A newly created #GtkTreeSelection object.
Packit 98cdb6
 **/
Packit 98cdb6
GtkTreeSelection*
Packit 98cdb6
_gtk_tree_selection_new (void)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreeSelection *selection;
Packit 98cdb6
Packit 98cdb6
  selection = g_object_new (GTK_TYPE_TREE_SELECTION, NULL);
Packit 98cdb6
Packit 98cdb6
  return selection;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_tree_selection_new_with_tree_view:
Packit 98cdb6
 * @tree_view: The #GtkTreeView.
Packit 98cdb6
 *
Packit 98cdb6
 * Creates a new #GtkTreeSelection object.  This function should not be invoked,
Packit 98cdb6
 * as each #GtkTreeView will create its own #GtkTreeSelection.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: A newly created #GtkTreeSelection object.
Packit 98cdb6
 **/
Packit 98cdb6
GtkTreeSelection*
Packit 98cdb6
_gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreeSelection *selection;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
Packit 98cdb6
Packit 98cdb6
  selection = _gtk_tree_selection_new ();
Packit 98cdb6
  _gtk_tree_selection_set_tree_view (selection, tree_view);
Packit 98cdb6
Packit 98cdb6
  return selection;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * _gtk_tree_selection_set_tree_view:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @tree_view: The #GtkTreeView.
Packit 98cdb6
 *
Packit 98cdb6
 * Sets the #GtkTreeView of @selection.  This function should not be invoked, as
Packit 98cdb6
 * it is used internally by #GtkTreeView.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
_gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
Packit 98cdb6
                                   GtkTreeView      *tree_view)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  if (tree_view != NULL)
Packit 98cdb6
    g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
Packit 98cdb6
Packit 98cdb6
  selection->tree_view = tree_view;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_set_mode:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @type: The selection mode
Packit 98cdb6
 *
Packit 98cdb6
 * Sets the selection mode of the @selection.  If the previous type was
Packit 98cdb6
 * #GTK_SELECTION_MULTIPLE, then the anchor is kept selected, if it was
Packit 98cdb6
 * previously selected.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_set_mode (GtkTreeSelection *selection,
Packit 98cdb6
			     GtkSelectionMode  type)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreeSelectionFunc tmp_func;
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
Packit 98cdb6
  if (selection->type == type)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  
Packit 98cdb6
  if (type == GTK_SELECTION_NONE)
Packit 98cdb6
    {
Packit 98cdb6
      /* We do this so that we unconditionally unset all rows
Packit 98cdb6
       */
Packit 98cdb6
      tmp_func = selection->user_func;
Packit 98cdb6
      selection->user_func = NULL;
Packit 98cdb6
      gtk_tree_selection_unselect_all (selection);
Packit 98cdb6
      selection->user_func = tmp_func;
Packit 98cdb6
Packit 98cdb6
      gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
      selection->tree_view->priv->anchor = NULL;
Packit 98cdb6
    }
Packit 98cdb6
  else if (type == GTK_SELECTION_SINGLE ||
Packit 98cdb6
	   type == GTK_SELECTION_BROWSE)
Packit 98cdb6
    {
Packit 98cdb6
      GtkRBTree *tree = NULL;
Packit 98cdb6
      GtkRBNode *node = NULL;
Packit 98cdb6
      gint selected = FALSE;
Packit 98cdb6
      GtkTreePath *anchor_path = NULL;
Packit 98cdb6
Packit 98cdb6
      if (selection->tree_view->priv->anchor)
Packit 98cdb6
	{
Packit 98cdb6
          anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
          if (anchor_path)
Packit 98cdb6
            {
Packit 98cdb6
              _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
                                        anchor_path,
Packit 98cdb6
                                        &tree,
Packit 98cdb6
                                        &node);
Packit 98cdb6
Packit 98cdb6
              if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
                selected = TRUE;
Packit 98cdb6
            }
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      /* We do this so that we unconditionally unset all rows
Packit 98cdb6
       */
Packit 98cdb6
      tmp_func = selection->user_func;
Packit 98cdb6
      selection->user_func = NULL;
Packit 98cdb6
      gtk_tree_selection_unselect_all (selection);
Packit 98cdb6
      selection->user_func = tmp_func;
Packit 98cdb6
Packit 98cdb6
      if (node && selected)
Packit 98cdb6
	_gtk_tree_selection_internal_select_node (selection,
Packit 98cdb6
						  node,
Packit 98cdb6
						  tree,
Packit 98cdb6
						  anchor_path,
Packit 98cdb6
                                                  0,
Packit 98cdb6
						  FALSE);
Packit 98cdb6
      if (anchor_path)
Packit 98cdb6
	gtk_tree_path_free (anchor_path);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  selection->type = type;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_get_mode:
Packit 98cdb6
 * @selection: a #GtkTreeSelection
Packit 98cdb6
 *
Packit 98cdb6
 * Gets the selection mode for @selection. See
Packit 98cdb6
 * gtk_tree_selection_set_mode().
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: the current selection mode
Packit 98cdb6
 **/
Packit 98cdb6
GtkSelectionMode
Packit 98cdb6
gtk_tree_selection_get_mode (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), GTK_SELECTION_SINGLE);
Packit 98cdb6
Packit 98cdb6
  return selection->type;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_set_select_function:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @func: The selection function.
Packit 98cdb6
 * @data: The selection function's data.
Packit 98cdb6
 * @destroy: The destroy function for user data.  May be NULL.
Packit 98cdb6
 *
Packit 98cdb6
 * Sets the selection function.  If set, this function is called before any node
Packit 98cdb6
 * is selected or unselected, giving some control over which nodes are selected.
Packit 98cdb6
 * The select function should return %TRUE if the state of the node may be toggled,
Packit 98cdb6
 * and %FALSE if the state of the node should be left unchanged.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_set_select_function (GtkTreeSelection     *selection,
Packit 98cdb6
					GtkTreeSelectionFunc  func,
Packit 98cdb6
					gpointer              data,
Packit 98cdb6
					GDestroyNotify        destroy)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (func != NULL);
Packit 98cdb6
Packit 98cdb6
  if (selection->destroy)
Packit 98cdb6
    {
Packit 98cdb6
      GDestroyNotify d = selection->destroy;
Packit 98cdb6
Packit 98cdb6
      selection->destroy = NULL;
Packit 98cdb6
      d (selection->user_data);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  selection->user_func = func;
Packit 98cdb6
  selection->user_data = data;
Packit 98cdb6
  selection->destroy = destroy;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_get_select_function: (skip)
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 *
Packit 98cdb6
 * Returns the current selection function.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: The function.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.14
Packit 98cdb6
 **/
Packit 98cdb6
GtkTreeSelectionFunc
Packit 98cdb6
gtk_tree_selection_get_select_function (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
Packit 98cdb6
Packit 98cdb6
  return selection->user_func;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_get_user_data: (skip)
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 *
Packit 98cdb6
 * Returns the user data for the selection function.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: The user data.
Packit 98cdb6
 **/
Packit 98cdb6
gpointer
Packit 98cdb6
gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
Packit 98cdb6
Packit 98cdb6
  return selection->user_data;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_get_tree_view:
Packit 98cdb6
 * @selection: A #GtkTreeSelection
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns the tree view associated with @selection.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: (transfer none): A #GtkTreeView
Packit 98cdb6
 **/
Packit 98cdb6
GtkTreeView *
Packit 98cdb6
gtk_tree_selection_get_tree_view (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
Packit 98cdb6
Packit 98cdb6
  return selection->tree_view;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_get_selected:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @model: (out) (allow-none) (transfer none): A pointer to set to the #GtkTreeModel, or NULL.
Packit 98cdb6
 * @iter: (out) (allow-none): The #GtkTreeIter, or NULL.
Packit 98cdb6
 *
Packit 98cdb6
 * Sets @iter to the currently selected node if @selection is set to
Packit 98cdb6
 * #GTK_SELECTION_SINGLE or #GTK_SELECTION_BROWSE.  @iter may be NULL if you
Packit 98cdb6
 * just want to test if @selection has any selected nodes.  @model is filled
Packit 98cdb6
 * with the current model as a convenience.  This function will not work if you
Packit 98cdb6
 * use @selection is #GTK_SELECTION_MULTIPLE.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: TRUE, if there is a selected node.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_tree_selection_get_selected (GtkTreeSelection  *selection,
Packit 98cdb6
				 GtkTreeModel     **model,
Packit 98cdb6
				 GtkTreeIter       *iter)
Packit 98cdb6
{
Packit 98cdb6
  GtkRBTree *tree;
Packit 98cdb6
  GtkRBNode *node;
Packit 98cdb6
  GtkTreePath *anchor_path;
Packit 98cdb6
  gboolean retval;
Packit 98cdb6
  gboolean found_node;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
Packit 98cdb6
  g_return_val_if_fail (selection->type != GTK_SELECTION_MULTIPLE, FALSE);
Packit 98cdb6
  g_return_val_if_fail (selection->tree_view != NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  /* Clear the iter */
Packit 98cdb6
  if (iter)
Packit 98cdb6
    memset (iter, 0, sizeof (GtkTreeIter));
Packit 98cdb6
Packit 98cdb6
  if (model)
Packit 98cdb6
    *model = selection->tree_view->priv->model;
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->anchor == NULL)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
  if (anchor_path == NULL)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  retval = FALSE;
Packit 98cdb6
Packit 98cdb6
  found_node = !_gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
                                          anchor_path,
Packit 98cdb6
                                          &tree,
Packit 98cdb6
                                          &node);
Packit 98cdb6
Packit 98cdb6
  if (found_node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
    {
Packit 98cdb6
      /* we only want to return the anchor if it exists in the rbtree and
Packit 98cdb6
       * is selected.
Packit 98cdb6
       */
Packit 98cdb6
      if (iter == NULL)
Packit 98cdb6
	retval = TRUE;
Packit 98cdb6
      else
Packit 98cdb6
        retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
Packit 98cdb6
                                          iter,
Packit 98cdb6
                                          anchor_path);
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      /* We don't want to return the anchor if it isn't actually selected.
Packit 98cdb6
       */
Packit 98cdb6
      retval = FALSE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  gtk_tree_path_free (anchor_path);
Packit 98cdb6
Packit 98cdb6
  return retval;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_get_selected_rows:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @model: (out) (allow-none) (transfer none): A pointer to set to the #GtkTreeModel, or %NULL.
Packit 98cdb6
 *
Packit 98cdb6
 * Creates a list of path of all selected rows. Additionally, if you are
Packit 98cdb6
 * planning on modifying the model after calling this function, you may
Packit 98cdb6
 * want to convert the returned list into a list of #GtkTreeRowReferences.
Packit 98cdb6
 * To do this, you can use gtk_tree_row_reference_new().
Packit 98cdb6
 *
Packit 98cdb6
 * To free the return value, use:
Packit 98cdb6
 * |[
Packit 98cdb6
 * g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
Packit 98cdb6
 * g_list_free (list);
Packit 98cdb6
 * ]|
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
GList *
Packit 98cdb6
gtk_tree_selection_get_selected_rows (GtkTreeSelection   *selection,
Packit 98cdb6
                                      GtkTreeModel      **model)
Packit 98cdb6
{
Packit 98cdb6
  GList *list = NULL;
Packit 98cdb6
  GtkRBTree *tree = NULL;
Packit 98cdb6
  GtkRBNode *node = NULL;
Packit 98cdb6
  GtkTreePath *path;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
Packit 98cdb6
  g_return_val_if_fail (selection->tree_view != NULL, NULL);
Packit 98cdb6
Packit 98cdb6
  if (model)
Packit 98cdb6
    *model = selection->tree_view->priv->model;
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->tree == NULL ||
Packit 98cdb6
      selection->tree_view->priv->tree->root == NULL)
Packit 98cdb6
    return NULL;
Packit 98cdb6
Packit 98cdb6
  if (selection->type == GTK_SELECTION_NONE)
Packit 98cdb6
    return NULL;
Packit 98cdb6
  else if (selection->type != GTK_SELECTION_MULTIPLE)
Packit 98cdb6
    {
Packit 98cdb6
      GtkTreeIter iter;
Packit 98cdb6
Packit 98cdb6
      if (gtk_tree_selection_get_selected (selection, NULL, &iter))
Packit 98cdb6
        {
Packit 98cdb6
	  GtkTreePath *path;
Packit 98cdb6
Packit 98cdb6
	  path = gtk_tree_model_get_path (selection->tree_view->priv->model, &iter);
Packit 98cdb6
	  list = g_list_append (list, path);
Packit 98cdb6
Packit 98cdb6
	  return list;
Packit 98cdb6
	}
Packit 98cdb6
Packit 98cdb6
      return NULL;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  tree = selection->tree_view->priv->tree;
Packit 98cdb6
  node = selection->tree_view->priv->tree->root;
Packit 98cdb6
Packit 98cdb6
  while (node->left != tree->nil)
Packit 98cdb6
    node = node->left;
Packit 98cdb6
  path = gtk_tree_path_new_first ();
Packit 98cdb6
Packit 98cdb6
  do
Packit 98cdb6
    {
Packit 98cdb6
      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
	list = g_list_prepend (list, gtk_tree_path_copy (path));
Packit 98cdb6
Packit 98cdb6
      if (node->children)
Packit 98cdb6
        {
Packit 98cdb6
	  tree = node->children;
Packit 98cdb6
	  node = tree->root;
Packit 98cdb6
Packit 98cdb6
	  while (node->left != tree->nil)
Packit 98cdb6
	    node = node->left;
Packit 98cdb6
Packit 98cdb6
	  gtk_tree_path_append_index (path, 0);
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
        {
Packit 98cdb6
	  gboolean done = FALSE;
Packit 98cdb6
Packit 98cdb6
	  do
Packit 98cdb6
	    {
Packit 98cdb6
	      node = _gtk_rbtree_next (tree, node);
Packit 98cdb6
	      if (node != NULL)
Packit 98cdb6
	        {
Packit 98cdb6
		  done = TRUE;
Packit 98cdb6
		  gtk_tree_path_next (path);
Packit 98cdb6
		}
Packit 98cdb6
	      else
Packit 98cdb6
	        {
Packit 98cdb6
		  node = tree->parent_node;
Packit 98cdb6
		  tree = tree->parent_tree;
Packit 98cdb6
Packit 98cdb6
		  if (!tree)
Packit 98cdb6
		    {
Packit 98cdb6
		      gtk_tree_path_free (path);
Packit 98cdb6
Packit 98cdb6
		      goto done; 
Packit 98cdb6
		    }
Packit 98cdb6
Packit 98cdb6
		  gtk_tree_path_up (path);
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	  while (!done);
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  while (TRUE);
Packit 98cdb6
Packit 98cdb6
  gtk_tree_path_free (path);
Packit 98cdb6
Packit 98cdb6
 done:
Packit 98cdb6
  return g_list_reverse (list);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
gtk_tree_selection_count_selected_rows_helper (GtkRBTree *tree,
Packit 98cdb6
					       GtkRBNode *node,
Packit 98cdb6
					       gpointer   data)
Packit 98cdb6
{
Packit 98cdb6
  gint *count = (gint *)data;
Packit 98cdb6
Packit 98cdb6
  if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
    (*count)++;
Packit 98cdb6
Packit 98cdb6
  if (node->children)
Packit 98cdb6
    _gtk_rbtree_traverse (node->children, node->children->root,
Packit 98cdb6
			  G_PRE_ORDER,
Packit 98cdb6
			  gtk_tree_selection_count_selected_rows_helper, data);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_count_selected_rows:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 *
Packit 98cdb6
 * Returns the number of rows that have been selected in @tree.
Packit 98cdb6
 *
Packit 98cdb6
 * Return value: The number of rows selected.
Packit 98cdb6
 * 
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
gint
Packit 98cdb6
gtk_tree_selection_count_selected_rows (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  gint count = 0;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), 0);
Packit 98cdb6
  g_return_val_if_fail (selection->tree_view != NULL, 0);
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->tree == NULL ||
Packit 98cdb6
      selection->tree_view->priv->tree->root == NULL)
Packit 98cdb6
    return 0;
Packit 98cdb6
Packit 98cdb6
  if (selection->type == GTK_SELECTION_SINGLE ||
Packit 98cdb6
      selection->type == GTK_SELECTION_BROWSE)
Packit 98cdb6
    {
Packit 98cdb6
      if (gtk_tree_selection_get_selected (selection, NULL, NULL))
Packit 98cdb6
	return 1;
Packit 98cdb6
      else
Packit 98cdb6
	return 0;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  _gtk_rbtree_traverse (selection->tree_view->priv->tree,
Packit 98cdb6
                        selection->tree_view->priv->tree->root,
Packit 98cdb6
			G_PRE_ORDER,
Packit 98cdb6
			gtk_tree_selection_count_selected_rows_helper,
Packit 98cdb6
			&count);
Packit 98cdb6
Packit 98cdb6
  return count;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* gtk_tree_selection_selected_foreach helper */
Packit 98cdb6
static void
Packit 98cdb6
model_changed (gpointer data)
Packit 98cdb6
{
Packit 98cdb6
  gboolean *stop = (gboolean *)data;
Packit 98cdb6
Packit 98cdb6
  *stop = TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_selected_foreach:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @func: (scope call): The function to call for each selected node.
Packit 98cdb6
 * @data: user data to pass to the function.
Packit 98cdb6
 *
Packit 98cdb6
 * Calls a function for each selected node. Note that you cannot modify
Packit 98cdb6
 * the tree or selection from within this function. As a result,
Packit 98cdb6
 * gtk_tree_selection_get_selected_rows() might be more useful.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_selected_foreach (GtkTreeSelection            *selection,
Packit 98cdb6
				     GtkTreeSelectionForeachFunc  func,
Packit 98cdb6
				     gpointer                     data)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreePath *path;
Packit 98cdb6
  GtkRBTree *tree;
Packit 98cdb6
  GtkRBNode *node;
Packit 98cdb6
  GtkTreeIter iter;
Packit 98cdb6
  GtkTreeModel *model;
Packit 98cdb6
Packit 98cdb6
  gulong inserted_id, deleted_id, reordered_id, changed_id;
Packit 98cdb6
  gboolean stop = FALSE;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
Packit 98cdb6
  if (func == NULL ||
Packit 98cdb6
      selection->tree_view->priv->tree == NULL ||
Packit 98cdb6
      selection->tree_view->priv->tree->root == NULL)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  if (selection->type == GTK_SELECTION_SINGLE ||
Packit 98cdb6
      selection->type == GTK_SELECTION_BROWSE)
Packit 98cdb6
    {
Packit 98cdb6
      if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
Packit 98cdb6
	{
Packit 98cdb6
	  path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
Packit 98cdb6
	  gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
Packit 98cdb6
	  (* func) (selection->tree_view->priv->model, path, &iter, data);
Packit 98cdb6
	  gtk_tree_path_free (path);
Packit 98cdb6
	}
Packit 98cdb6
      return;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  tree = selection->tree_view->priv->tree;
Packit 98cdb6
  node = selection->tree_view->priv->tree->root;
Packit 98cdb6
  
Packit 98cdb6
  while (node->left != tree->nil)
Packit 98cdb6
    node = node->left;
Packit 98cdb6
Packit 98cdb6
  model = selection->tree_view->priv->model;
Packit 98cdb6
  g_object_ref (model);
Packit 98cdb6
Packit 98cdb6
  /* connect to signals to monitor changes in treemodel */
Packit 98cdb6
  inserted_id = g_signal_connect_swapped (model, "row-inserted",
Packit 98cdb6
					  G_CALLBACK (model_changed),
Packit 98cdb6
				          &stop);
Packit 98cdb6
  deleted_id = g_signal_connect_swapped (model, "row-deleted",
Packit 98cdb6
					 G_CALLBACK (model_changed),
Packit 98cdb6
				         &stop);
Packit 98cdb6
  reordered_id = g_signal_connect_swapped (model, "rows-reordered",
Packit 98cdb6
					   G_CALLBACK (model_changed),
Packit 98cdb6
				           &stop);
Packit 98cdb6
  changed_id = g_signal_connect_swapped (selection->tree_view, "notify::model",
Packit 98cdb6
					 G_CALLBACK (model_changed), 
Packit 98cdb6
					 &stop);
Packit 98cdb6
Packit 98cdb6
  /* find the node internally */
Packit 98cdb6
  path = gtk_tree_path_new_first ();
Packit 98cdb6
Packit 98cdb6
  do
Packit 98cdb6
    {
Packit 98cdb6
      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
        {
Packit 98cdb6
          gtk_tree_model_get_iter (model, &iter, path);
Packit 98cdb6
	  (* func) (model, path, &iter, data);
Packit 98cdb6
        }
Packit 98cdb6
Packit 98cdb6
      if (stop)
Packit 98cdb6
	goto out;
Packit 98cdb6
Packit 98cdb6
      if (node->children)
Packit 98cdb6
	{
Packit 98cdb6
	  tree = node->children;
Packit 98cdb6
	  node = tree->root;
Packit 98cdb6
Packit 98cdb6
	  while (node->left != tree->nil)
Packit 98cdb6
	    node = node->left;
Packit 98cdb6
Packit 98cdb6
	  gtk_tree_path_append_index (path, 0);
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	{
Packit 98cdb6
	  gboolean done = FALSE;
Packit 98cdb6
Packit 98cdb6
	  do
Packit 98cdb6
	    {
Packit 98cdb6
	      node = _gtk_rbtree_next (tree, node);
Packit 98cdb6
	      if (node != NULL)
Packit 98cdb6
		{
Packit 98cdb6
		  done = TRUE;
Packit 98cdb6
		  gtk_tree_path_next (path);
Packit 98cdb6
		}
Packit 98cdb6
	      else
Packit 98cdb6
		{
Packit 98cdb6
		  node = tree->parent_node;
Packit 98cdb6
		  tree = tree->parent_tree;
Packit 98cdb6
Packit 98cdb6
		  if (tree == NULL)
Packit 98cdb6
		    {
Packit 98cdb6
		      /* we've run out of tree */
Packit 98cdb6
		      /* We're done with this function */
Packit 98cdb6
Packit 98cdb6
		      goto out;
Packit 98cdb6
		    }
Packit 98cdb6
Packit 98cdb6
		  gtk_tree_path_up (path);
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	  while (!done);
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  while (TRUE);
Packit 98cdb6
Packit 98cdb6
out:
Packit 98cdb6
  if (path)
Packit 98cdb6
    gtk_tree_path_free (path);
Packit 98cdb6
Packit 98cdb6
  g_signal_handler_disconnect (model, inserted_id);
Packit 98cdb6
  g_signal_handler_disconnect (model, deleted_id);
Packit 98cdb6
  g_signal_handler_disconnect (model, reordered_id);
Packit 98cdb6
  g_signal_handler_disconnect (selection->tree_view, changed_id);
Packit 98cdb6
  g_object_unref (model);
Packit 98cdb6
Packit 98cdb6
  /* check if we have to spew a scary message */
Packit 98cdb6
  if (stop)
Packit 98cdb6
    g_warning ("The model has been modified from within gtk_tree_selection_selected_foreach.\n"
Packit 98cdb6
	       "This function is for observing the selections of the tree only.  If\n"
Packit 98cdb6
	       "you are trying to get all selected items from the tree, try using\n"
Packit 98cdb6
	       "gtk_tree_selection_get_selected_rows instead.\n");
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_select_path:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @path: The #GtkTreePath to be selected.
Packit 98cdb6
 *
Packit 98cdb6
 * Select the row at @path.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_select_path (GtkTreeSelection *selection,
Packit 98cdb6
				GtkTreePath      *path)
Packit 98cdb6
{
Packit 98cdb6
  GtkRBNode *node;
Packit 98cdb6
  GtkRBTree *tree;
Packit 98cdb6
  gboolean ret;
Packit 98cdb6
  GtkTreeSelectMode mode = 0;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
  g_return_if_fail (path != NULL);
Packit 98cdb6
Packit 98cdb6
  ret = _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				  path,
Packit 98cdb6
				  &tree,
Packit 98cdb6
				  &node);
Packit 98cdb6
Packit 98cdb6
  if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
Packit 98cdb6
      ret == TRUE)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  if (selection->type == GTK_SELECTION_MULTIPLE)
Packit 98cdb6
    mode = GTK_TREE_SELECT_MODE_TOGGLE;
Packit 98cdb6
Packit 98cdb6
  _gtk_tree_selection_internal_select_node (selection,
Packit 98cdb6
					    node,
Packit 98cdb6
					    tree,
Packit 98cdb6
					    path,
Packit 98cdb6
                                            mode,
Packit 98cdb6
					    FALSE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_unselect_path:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @path: The #GtkTreePath to be unselected.
Packit 98cdb6
 *
Packit 98cdb6
 * Unselects the row at @path.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
Packit 98cdb6
				  GtkTreePath      *path)
Packit 98cdb6
{
Packit 98cdb6
  GtkRBNode *node;
Packit 98cdb6
  GtkRBTree *tree;
Packit 98cdb6
  gboolean ret;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
  g_return_if_fail (path != NULL);
Packit 98cdb6
Packit 98cdb6
  ret = _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				  path,
Packit 98cdb6
				  &tree,
Packit 98cdb6
				  &node);
Packit 98cdb6
Packit 98cdb6
  if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
Packit 98cdb6
      ret == TRUE)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  _gtk_tree_selection_internal_select_node (selection,
Packit 98cdb6
					    node,
Packit 98cdb6
					    tree,
Packit 98cdb6
					    path,
Packit 98cdb6
                                            GTK_TREE_SELECT_MODE_TOGGLE,
Packit 98cdb6
					    TRUE);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_select_iter:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @iter: The #GtkTreeIter to be selected.
Packit 98cdb6
 *
Packit 98cdb6
 * Selects the specified iterator.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_select_iter (GtkTreeSelection *selection,
Packit 98cdb6
				GtkTreeIter      *iter)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreePath *path;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
  g_return_if_fail (selection->tree_view->priv->model != NULL);
Packit 98cdb6
  g_return_if_fail (iter != NULL);
Packit 98cdb6
Packit 98cdb6
  path = gtk_tree_model_get_path (selection->tree_view->priv->model,
Packit 98cdb6
				  iter);
Packit 98cdb6
Packit 98cdb6
  if (path == NULL)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  gtk_tree_selection_select_path (selection, path);
Packit 98cdb6
  gtk_tree_path_free (path);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_unselect_iter:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @iter: The #GtkTreeIter to be unselected.
Packit 98cdb6
 *
Packit 98cdb6
 * Unselects the specified iterator.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
Packit 98cdb6
				  GtkTreeIter      *iter)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreePath *path;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
  g_return_if_fail (selection->tree_view->priv->model != NULL);
Packit 98cdb6
  g_return_if_fail (iter != NULL);
Packit 98cdb6
Packit 98cdb6
  path = gtk_tree_model_get_path (selection->tree_view->priv->model,
Packit 98cdb6
				  iter);
Packit 98cdb6
Packit 98cdb6
  if (path == NULL)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  gtk_tree_selection_unselect_path (selection, path);
Packit 98cdb6
  gtk_tree_path_free (path);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_path_is_selected:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @path: A #GtkTreePath to check selection on.
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns %TRUE if the row pointed to by @path is currently selected.  If @path
Packit 98cdb6
 * does not point to a valid location, %FALSE is returned
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: %TRUE if @path is selected.
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_tree_selection_path_is_selected (GtkTreeSelection *selection,
Packit 98cdb6
				     GtkTreePath      *path)
Packit 98cdb6
{
Packit 98cdb6
  GtkRBNode *node;
Packit 98cdb6
  GtkRBTree *tree;
Packit 98cdb6
  gboolean ret;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
Packit 98cdb6
  g_return_val_if_fail (path != NULL, FALSE);
Packit 98cdb6
  g_return_val_if_fail (selection->tree_view != NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->model == NULL)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  ret = _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				  path,
Packit 98cdb6
				  &tree,
Packit 98cdb6
				  &node);
Packit 98cdb6
Packit 98cdb6
  if ((node == NULL) || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
Packit 98cdb6
      ret == TRUE)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_iter_is_selected:
Packit 98cdb6
 * @selection: A #GtkTreeSelection
Packit 98cdb6
 * @iter: A valid #GtkTreeIter
Packit 98cdb6
 * 
Packit 98cdb6
 * Returns %TRUE if the row at @iter is currently selected.
Packit 98cdb6
 * 
Packit 98cdb6
 * Return value: %TRUE, if @iter is selected
Packit 98cdb6
 **/
Packit 98cdb6
gboolean
Packit 98cdb6
gtk_tree_selection_iter_is_selected (GtkTreeSelection *selection,
Packit 98cdb6
				     GtkTreeIter      *iter)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreePath *path;
Packit 98cdb6
  gboolean retval;
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
Packit 98cdb6
  g_return_val_if_fail (iter != NULL, FALSE);
Packit 98cdb6
  g_return_val_if_fail (selection->tree_view != NULL, FALSE);
Packit 98cdb6
  g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  path = gtk_tree_model_get_path (selection->tree_view->priv->model, iter);
Packit 98cdb6
  if (path == NULL)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  retval = gtk_tree_selection_path_is_selected (selection, path);
Packit 98cdb6
  gtk_tree_path_free (path);
Packit 98cdb6
Packit 98cdb6
  return retval;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/* Wish I was in python, right now... */
Packit 98cdb6
struct _TempTuple {
Packit 98cdb6
  GtkTreeSelection *selection;
Packit 98cdb6
  gint dirty;
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
select_all_helper (GtkRBTree  *tree,
Packit 98cdb6
		   GtkRBNode  *node,
Packit 98cdb6
		   gpointer    data)
Packit 98cdb6
{
Packit 98cdb6
  struct _TempTuple *tuple = data;
Packit 98cdb6
Packit 98cdb6
  if (node->children)
Packit 98cdb6
    _gtk_rbtree_traverse (node->children,
Packit 98cdb6
			  node->children->root,
Packit 98cdb6
			  G_PRE_ORDER,
Packit 98cdb6
			  select_all_helper,
Packit 98cdb6
			  data);
Packit 98cdb6
  if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
    {
Packit 98cdb6
      tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/* We have a real_{un,}select_all function that doesn't emit the signal, so we
Packit 98cdb6
 * can use it in other places without fear of the signal being emitted.
Packit 98cdb6
 */
Packit 98cdb6
static gint
Packit 98cdb6
gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  struct _TempTuple *tuple;
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->tree == NULL)
Packit 98cdb6
    return FALSE;
Packit 98cdb6
Packit 98cdb6
  /* Mark all nodes selected */
Packit 98cdb6
  tuple = g_new (struct _TempTuple, 1);
Packit 98cdb6
  tuple->selection = selection;
Packit 98cdb6
  tuple->dirty = FALSE;
Packit 98cdb6
Packit 98cdb6
  _gtk_rbtree_traverse (selection->tree_view->priv->tree,
Packit 98cdb6
			selection->tree_view->priv->tree->root,
Packit 98cdb6
			G_PRE_ORDER,
Packit 98cdb6
			select_all_helper,
Packit 98cdb6
			tuple);
Packit 98cdb6
  if (tuple->dirty)
Packit 98cdb6
    {
Packit 98cdb6
      g_free (tuple);
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
  g_free (tuple);
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_select_all:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 *
Packit 98cdb6
 * Selects all the nodes. @selection must be set to #GTK_SELECTION_MULTIPLE
Packit 98cdb6
 * mode.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_select_all (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->tree == NULL || selection->tree_view->priv->model == NULL)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
Packit 98cdb6
Packit 98cdb6
  if (gtk_tree_selection_real_select_all (selection))
Packit 98cdb6
    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static void
Packit 98cdb6
unselect_all_helper (GtkRBTree  *tree,
Packit 98cdb6
		     GtkRBNode  *node,
Packit 98cdb6
		     gpointer    data)
Packit 98cdb6
{
Packit 98cdb6
  struct _TempTuple *tuple = data;
Packit 98cdb6
Packit 98cdb6
  if (node->children)
Packit 98cdb6
    _gtk_rbtree_traverse (node->children,
Packit 98cdb6
			  node->children->root,
Packit 98cdb6
			  G_PRE_ORDER,
Packit 98cdb6
			  unselect_all_helper,
Packit 98cdb6
			  data);
Packit 98cdb6
  if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
    {
Packit 98cdb6
      tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
static gboolean
Packit 98cdb6
gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  struct _TempTuple *tuple;
Packit 98cdb6
Packit 98cdb6
  if (selection->type == GTK_SELECTION_SINGLE ||
Packit 98cdb6
      selection->type == GTK_SELECTION_BROWSE)
Packit 98cdb6
    {
Packit 98cdb6
      GtkRBTree *tree = NULL;
Packit 98cdb6
      GtkRBNode *node = NULL;
Packit 98cdb6
      GtkTreePath *anchor_path;
Packit 98cdb6
Packit 98cdb6
      if (selection->tree_view->priv->anchor == NULL)
Packit 98cdb6
	return FALSE;
Packit 98cdb6
Packit 98cdb6
      anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
      if (anchor_path == NULL)
Packit 98cdb6
        return FALSE;
Packit 98cdb6
Packit 98cdb6
      _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
                                anchor_path,
Packit 98cdb6
				&tree,
Packit 98cdb6
				&node);
Packit 98cdb6
Packit 98cdb6
      gtk_tree_path_free (anchor_path);
Packit 98cdb6
Packit 98cdb6
      if (tree == NULL)
Packit 98cdb6
        return FALSE;
Packit 98cdb6
Packit 98cdb6
      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
Packit 98cdb6
	{
Packit 98cdb6
	  if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
Packit 98cdb6
	    {
Packit 98cdb6
	      gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
	      selection->tree_view->priv->anchor = NULL;
Packit 98cdb6
	      return TRUE;
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
  else
Packit 98cdb6
    {
Packit 98cdb6
      tuple = g_new (struct _TempTuple, 1);
Packit 98cdb6
      tuple->selection = selection;
Packit 98cdb6
      tuple->dirty = FALSE;
Packit 98cdb6
Packit 98cdb6
      _gtk_rbtree_traverse (selection->tree_view->priv->tree,
Packit 98cdb6
                            selection->tree_view->priv->tree->root,
Packit 98cdb6
                            G_PRE_ORDER,
Packit 98cdb6
                            unselect_all_helper,
Packit 98cdb6
                            tuple);
Packit 98cdb6
Packit 98cdb6
      if (tuple->dirty)
Packit 98cdb6
        {
Packit 98cdb6
          g_free (tuple);
Packit 98cdb6
          return TRUE;
Packit 98cdb6
        }
Packit 98cdb6
      g_free (tuple);
Packit 98cdb6
      return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_unselect_all:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 *
Packit 98cdb6
 * Unselects all the nodes.
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->tree == NULL || selection->tree_view->priv->model == NULL)
Packit 98cdb6
    return;
Packit 98cdb6
  
Packit 98cdb6
  if (gtk_tree_selection_real_unselect_all (selection))
Packit 98cdb6
    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
enum
Packit 98cdb6
{
Packit 98cdb6
  RANGE_SELECT,
Packit 98cdb6
  RANGE_UNSELECT
Packit 98cdb6
};
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gtk_tree_selection_real_modify_range (GtkTreeSelection *selection,
Packit 98cdb6
                                      gint              mode,
Packit 98cdb6
				      GtkTreePath      *start_path,
Packit 98cdb6
				      GtkTreePath      *end_path)
Packit 98cdb6
{
Packit 98cdb6
  GtkRBNode *start_node, *end_node;
Packit 98cdb6
  GtkRBTree *start_tree, *end_tree;
Packit 98cdb6
  GtkTreePath *anchor_path = NULL;
Packit 98cdb6
  gboolean dirty = FALSE;
Packit 98cdb6
Packit 98cdb6
  switch (gtk_tree_path_compare (start_path, end_path))
Packit 98cdb6
    {
Packit 98cdb6
    case 1:
Packit 98cdb6
      _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				end_path,
Packit 98cdb6
				&start_tree,
Packit 98cdb6
				&start_node);
Packit 98cdb6
      _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				start_path,
Packit 98cdb6
				&end_tree,
Packit 98cdb6
				&end_node);
Packit 98cdb6
      anchor_path = start_path;
Packit 98cdb6
      break;
Packit 98cdb6
    case 0:
Packit 98cdb6
      _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				start_path,
Packit 98cdb6
				&start_tree,
Packit 98cdb6
				&start_node);
Packit 98cdb6
      end_tree = start_tree;
Packit 98cdb6
      end_node = start_node;
Packit 98cdb6
      anchor_path = start_path;
Packit 98cdb6
      break;
Packit 98cdb6
    case -1:
Packit 98cdb6
      _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				start_path,
Packit 98cdb6
				&start_tree,
Packit 98cdb6
				&start_node);
Packit 98cdb6
      _gtk_tree_view_find_node (selection->tree_view,
Packit 98cdb6
				end_path,
Packit 98cdb6
				&end_tree,
Packit 98cdb6
				&end_node);
Packit 98cdb6
      anchor_path = start_path;
Packit 98cdb6
      break;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  g_return_val_if_fail (start_node != NULL, FALSE);
Packit 98cdb6
  g_return_val_if_fail (end_node != NULL, FALSE);
Packit 98cdb6
Packit 98cdb6
  if (anchor_path)
Packit 98cdb6
    {
Packit 98cdb6
      if (selection->tree_view->priv->anchor)
Packit 98cdb6
	gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
      selection->tree_view->priv->anchor =
Packit 98cdb6
	gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view),
Packit 98cdb6
	                                  selection->tree_view->priv->model,
Packit 98cdb6
					  anchor_path);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  do
Packit 98cdb6
    {
Packit 98cdb6
      dirty |= gtk_tree_selection_real_select_node (selection, start_tree, start_node, (mode == RANGE_SELECT)?TRUE:FALSE);
Packit 98cdb6
Packit 98cdb6
      if (start_node == end_node)
Packit 98cdb6
	break;
Packit 98cdb6
Packit 98cdb6
      if (start_node->children)
Packit 98cdb6
	{
Packit 98cdb6
	  start_tree = start_node->children;
Packit 98cdb6
	  start_node = start_tree->root;
Packit 98cdb6
	  while (start_node->left != start_tree->nil)
Packit 98cdb6
	    start_node = start_node->left;
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	{
Packit 98cdb6
	  _gtk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
Packit 98cdb6
	  if (start_tree == NULL)
Packit 98cdb6
	    {
Packit 98cdb6
	      /* we just ran out of tree.  That means someone passed in bogus values.
Packit 98cdb6
	       */
Packit 98cdb6
	      return dirty;
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  while (TRUE);
Packit 98cdb6
Packit 98cdb6
  return dirty;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_select_range:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @start_path: The initial node of the range.
Packit 98cdb6
 * @end_path: The final node of the range.
Packit 98cdb6
 *
Packit 98cdb6
 * Selects a range of nodes, determined by @start_path and @end_path inclusive.
Packit 98cdb6
 * @selection must be set to #GTK_SELECTION_MULTIPLE mode. 
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_select_range (GtkTreeSelection *selection,
Packit 98cdb6
				 GtkTreePath      *start_path,
Packit 98cdb6
				 GtkTreePath      *end_path)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
  g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
Packit 98cdb6
  g_return_if_fail (selection->tree_view->priv->model != NULL);
Packit 98cdb6
Packit 98cdb6
  if (gtk_tree_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path))
Packit 98cdb6
    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/**
Packit 98cdb6
 * gtk_tree_selection_unselect_range:
Packit 98cdb6
 * @selection: A #GtkTreeSelection.
Packit 98cdb6
 * @start_path: The initial node of the range.
Packit 98cdb6
 * @end_path: The initial node of the range.
Packit 98cdb6
 *
Packit 98cdb6
 * Unselects a range of nodes, determined by @start_path and @end_path
Packit 98cdb6
 * inclusive.
Packit 98cdb6
 *
Packit 98cdb6
 * Since: 2.2
Packit 98cdb6
 **/
Packit 98cdb6
void
Packit 98cdb6
gtk_tree_selection_unselect_range (GtkTreeSelection *selection,
Packit 98cdb6
                                   GtkTreePath      *start_path,
Packit 98cdb6
				   GtkTreePath      *end_path)
Packit 98cdb6
{
Packit 98cdb6
  g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
Packit 98cdb6
  g_return_if_fail (selection->tree_view != NULL);
Packit 98cdb6
  g_return_if_fail (selection->tree_view->priv->model != NULL);
Packit 98cdb6
Packit 98cdb6
  if (gtk_tree_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path))
Packit 98cdb6
    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
gboolean
Packit 98cdb6
_gtk_tree_selection_row_is_selectable (GtkTreeSelection *selection,
Packit 98cdb6
				       GtkRBNode        *node,
Packit 98cdb6
				       GtkTreePath      *path)
Packit 98cdb6
{
Packit 98cdb6
  GtkTreeIter iter;
Packit 98cdb6
  gboolean sensitive = FALSE;
Packit 98cdb6
Packit 98cdb6
  if (!gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path))
Packit 98cdb6
    sensitive = TRUE;
Packit 98cdb6
Packit 98cdb6
  if (!sensitive && selection->tree_view->priv->row_separator_func)
Packit 98cdb6
    {
Packit 98cdb6
      /* never allow separators to be selected */
Packit 98cdb6
      if ((* selection->tree_view->priv->row_separator_func) (selection->tree_view->priv->model,
Packit 98cdb6
							      &iter,
Packit 98cdb6
							      selection->tree_view->priv->row_separator_data))
Packit 98cdb6
	return FALSE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (selection->user_func)
Packit 98cdb6
    return (*selection->user_func) (selection, selection->tree_view->priv->model, path,
Packit 98cdb6
				    GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
Packit 98cdb6
				    selection->user_data);
Packit 98cdb6
  else
Packit 98cdb6
    return TRUE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
/* Called internally by gtktreeview.c It handles actually selecting the tree.
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
/*
Packit 98cdb6
 * docs about the 'override_browse_mode', we set this flag when we want to
Packit 98cdb6
 * unset select the node and override the select browse mode behaviour (that is
Packit 98cdb6
 * 'one node should *always* be selected').
Packit 98cdb6
 */
Packit 98cdb6
void
Packit 98cdb6
_gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
Packit 98cdb6
					  GtkRBNode        *node,
Packit 98cdb6
					  GtkRBTree        *tree,
Packit 98cdb6
					  GtkTreePath      *path,
Packit 98cdb6
                                          GtkTreeSelectMode mode,
Packit 98cdb6
					  gboolean          override_browse_mode)
Packit 98cdb6
{
Packit 98cdb6
  gint flags;
Packit 98cdb6
  gint dirty = FALSE;
Packit 98cdb6
  GtkTreePath *anchor_path = NULL;
Packit 98cdb6
Packit 98cdb6
  if (selection->type == GTK_SELECTION_NONE)
Packit 98cdb6
    return;
Packit 98cdb6
Packit 98cdb6
  if (selection->tree_view->priv->anchor)
Packit 98cdb6
    anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
  if (selection->type == GTK_SELECTION_SINGLE ||
Packit 98cdb6
      selection->type == GTK_SELECTION_BROWSE)
Packit 98cdb6
    {
Packit 98cdb6
      /* just unselect */
Packit 98cdb6
      if (selection->type == GTK_SELECTION_BROWSE && override_browse_mode)
Packit 98cdb6
        {
Packit 98cdb6
	  dirty = gtk_tree_selection_real_unselect_all (selection);
Packit 98cdb6
	}
Packit 98cdb6
      /* Did we try to select the same node again? */
Packit 98cdb6
      else if (selection->type == GTK_SELECTION_SINGLE &&
Packit 98cdb6
	       anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
Packit 98cdb6
	{
Packit 98cdb6
	  if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
Packit 98cdb6
	    {
Packit 98cdb6
	      dirty = gtk_tree_selection_real_unselect_all (selection);
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	{
Packit 98cdb6
	  if (anchor_path)
Packit 98cdb6
	    {
Packit 98cdb6
	      /* We only want to select the new node if we can unselect the old one,
Packit 98cdb6
	       * and we can select the new one. */
Packit 98cdb6
	      dirty = _gtk_tree_selection_row_is_selectable (selection, node, path);
Packit 98cdb6
Packit 98cdb6
	      /* if dirty is FALSE, we weren't able to select the new one, otherwise, we try to
Packit 98cdb6
	       * unselect the new one
Packit 98cdb6
	       */
Packit 98cdb6
	      if (dirty)
Packit 98cdb6
		dirty = gtk_tree_selection_real_unselect_all (selection);
Packit 98cdb6
Packit 98cdb6
	      /* if dirty is TRUE at this point, we successfully unselected the
Packit 98cdb6
	       * old one, and can then select the new one */
Packit 98cdb6
	      if (dirty)
Packit 98cdb6
		{
Packit 98cdb6
		  if (selection->tree_view->priv->anchor)
Packit 98cdb6
                    {
Packit 98cdb6
                      gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
                      selection->tree_view->priv->anchor = NULL;
Packit 98cdb6
                    }
Packit 98cdb6
Packit 98cdb6
		  if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
Packit 98cdb6
		    {
Packit 98cdb6
		      selection->tree_view->priv->anchor =
Packit 98cdb6
			gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
Packit 98cdb6
		    }
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	  else
Packit 98cdb6
	    {
Packit 98cdb6
	      if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
Packit 98cdb6
		{
Packit 98cdb6
		  dirty = TRUE;
Packit 98cdb6
		  if (selection->tree_view->priv->anchor)
Packit 98cdb6
		    gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
		  selection->tree_view->priv->anchor =
Packit 98cdb6
		    gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
Packit 98cdb6
		}
Packit 98cdb6
	    }
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
  else if (selection->type == GTK_SELECTION_MULTIPLE)
Packit 98cdb6
    {
Packit 98cdb6
      if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND
Packit 98cdb6
          && (anchor_path == NULL))
Packit 98cdb6
	{
Packit 98cdb6
	  if (selection->tree_view->priv->anchor)
Packit 98cdb6
	    gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
	  selection->tree_view->priv->anchor =
Packit 98cdb6
	    gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
Packit 98cdb6
	  dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
Packit 98cdb6
	}
Packit 98cdb6
      else if ((mode & (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE)) == (GTK_TREE_SELECT_MODE_EXTEND | GTK_TREE_SELECT_MODE_TOGGLE))
Packit 98cdb6
	{
Packit 98cdb6
	  gtk_tree_selection_select_range (selection,
Packit 98cdb6
					   anchor_path,
Packit 98cdb6
					   path);
Packit 98cdb6
	}
Packit 98cdb6
      else if ((mode & GTK_TREE_SELECT_MODE_TOGGLE) == GTK_TREE_SELECT_MODE_TOGGLE)
Packit 98cdb6
	{
Packit 98cdb6
	  flags = node->flags;
Packit 98cdb6
	  if (selection->tree_view->priv->anchor)
Packit 98cdb6
	    gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
	  selection->tree_view->priv->anchor =
Packit 98cdb6
	    gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
Packit 98cdb6
Packit 98cdb6
	  if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
Packit 98cdb6
	    dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
Packit 98cdb6
	  else
Packit 98cdb6
	    dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
Packit 98cdb6
	}
Packit 98cdb6
      else if ((mode & GTK_TREE_SELECT_MODE_EXTEND) == GTK_TREE_SELECT_MODE_EXTEND)
Packit 98cdb6
	{
Packit 98cdb6
	  dirty = gtk_tree_selection_real_unselect_all (selection);
Packit 98cdb6
	  dirty |= gtk_tree_selection_real_modify_range (selection,
Packit 98cdb6
                                                         RANGE_SELECT,
Packit 98cdb6
							 anchor_path,
Packit 98cdb6
							 path);
Packit 98cdb6
	}
Packit 98cdb6
      else
Packit 98cdb6
	{
Packit 98cdb6
	  dirty = gtk_tree_selection_real_unselect_all (selection);
Packit 98cdb6
Packit 98cdb6
	  if (selection->tree_view->priv->anchor)
Packit 98cdb6
	    gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
Packit 98cdb6
Packit 98cdb6
	  selection->tree_view->priv->anchor =
Packit 98cdb6
	    gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
Packit 98cdb6
Packit 98cdb6
	  dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
Packit 98cdb6
	}
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (anchor_path)
Packit 98cdb6
    gtk_tree_path_free (anchor_path);
Packit 98cdb6
Packit 98cdb6
  if (dirty)
Packit 98cdb6
    g_signal_emit (selection, tree_selection_signals[CHANGED], 0);  
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
Packit 98cdb6
void 
Packit 98cdb6
_gtk_tree_selection_emit_changed (GtkTreeSelection *selection)
Packit 98cdb6
{
Packit 98cdb6
  g_signal_emit (selection, tree_selection_signals[CHANGED], 0);  
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
/* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
Packit 98cdb6
 */
Packit 98cdb6
Packit 98cdb6
static gint
Packit 98cdb6
gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
Packit 98cdb6
				     GtkRBTree        *tree,
Packit 98cdb6
				     GtkRBNode        *node,
Packit 98cdb6
				     gboolean          select)
Packit 98cdb6
{
Packit 98cdb6
  gboolean toggle = FALSE;
Packit 98cdb6
  GtkTreePath *path = NULL;
Packit 98cdb6
Packit 98cdb6
  select = !! select;
Packit 98cdb6
Packit 98cdb6
  if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
Packit 98cdb6
    {
Packit 98cdb6
      path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
Packit 98cdb6
      toggle = _gtk_tree_selection_row_is_selectable (selection, node, path);
Packit 98cdb6
      gtk_tree_path_free (path);
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  if (toggle)
Packit 98cdb6
    {
Packit 98cdb6
      node->flags ^= GTK_RBNODE_IS_SELECTED;
Packit 98cdb6
Packit 98cdb6
      _gtk_tree_view_queue_draw_node (selection->tree_view, tree, node, NULL);
Packit 98cdb6
      
Packit 98cdb6
      return TRUE;
Packit 98cdb6
    }
Packit 98cdb6
Packit 98cdb6
  return FALSE;
Packit 98cdb6
}
Packit 98cdb6
Packit 98cdb6
#define __GTK_TREE_SELECTION_C__
Packit 98cdb6
#include "gtkaliasdef.c"