aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog9
-rw-r--r--e-util/Makefile.am6
-rw-r--r--e-util/e-canvas.c19
-rw-r--r--e-util/e-iterator.c169
-rw-r--r--e-util/e-iterator.h61
-rw-r--r--e-util/e-list-iterator.c199
-rw-r--r--e-util/e-list-iterator.h44
-rw-r--r--e-util/e-list.c140
-rw-r--r--e-util/e-list.h60
-rw-r--r--widgets/misc/e-canvas.c19
10 files changed, 726 insertions, 0 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog
index 638c588038..43e01a9bc8 100644
--- a/e-util/ChangeLog
+++ b/e-util/ChangeLog
@@ -1,3 +1,12 @@
+2000-07-03 Christopher James Lahey <clahey@helixcode.com>
+
+ * e-iterator.c, e-iterator.h, e-list-iterator.c,
+ e-list-iterator.h, e-list.c, e-list.h: New list class with
+ iterators.
+
+ * e-canvas.c: Made it so that you don't get the same selection in
+ the selection list more than once.
+
2000-07-01 Ettore Perazzoli <ettore@helixcode.com>
* e-gui-utils.h: #include <libgnomeui/gnome-messagebox.h>. It's
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index 0e9680dc3d..43998022b4 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -23,6 +23,12 @@ libeutil_la_SOURCES = \
e-gui-utils.h \
e-html-utils.c \
e-html-utils.h \
+ e-iterator.c \
+ e-iterator.h \
+ e-list.c \
+ e-list.h \
+ e-list-iterator.c \
+ e-list-iterator.h \
e-popup-menu.c \
e-popup-menu.h \
e-printable.c \
diff --git a/e-util/e-canvas.c b/e-util/e-canvas.c
index 0da4dade28..4cb912283e 100644
--- a/e-util/e-canvas.c
+++ b/e-util/e-canvas.c
@@ -583,6 +583,7 @@ e_canvas_item_add_selection (GnomeCanvasItem *item, gpointer id)
ECanvas *canvas;
ECanvasSelectionInfo *info;
ECanvasItemSelectionFunc func;
+ GList *list;
g_return_if_fail(item != NULL);
g_return_if_fail(GNOME_IS_CANVAS_ITEM(item));
@@ -602,6 +603,24 @@ e_canvas_item_add_selection (GnomeCanvasItem *item, gpointer id)
flags = E_CANVAS_ITEM_SELECTION_SELECT | E_CANVAS_ITEM_SELECTION_CURSOR;
+ for (list = canvas->selection; list; list = g_list_next(list)) {
+ ECanvasSelectionInfo *search;
+ search = list->data;
+
+ if (search->item == item) {
+ ECanvasItemSelectionCompareFunc compare_func;
+ compare_func = gtk_object_get_data(GTK_OBJECT(search->item), "ECanvasItem::selection_compare_callback");
+
+ if (compare_func(search->item, search->id, id, 0) == 0) {
+ canvas->cursor = search;
+ func = gtk_object_get_data(GTK_OBJECT(item), "ECanvasItem::selection_callback");
+ if (func)
+ func(item, flags, search->id);
+ return;
+ }
+ }
+ }
+
info = g_new(ECanvasSelectionInfo, 1);
info->item = item;
info->id = id;
diff --git a/e-util/e-iterator.c b/e-util/e-iterator.c
new file mode 100644
index 0000000000..cff6fec946
--- /dev/null
+++ b/e-util/e-iterator.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors:
+ * Christopher James Lahey <clahey@umich.edu>
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 1999 The Free Software Foundation
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+
+#include "e-iterator.h"
+
+#define ECI_CLASS(object) (E_ITERATOR_CLASS(GTK_OBJECT((object))->klass))
+
+static void e_iterator_init (EIterator *card);
+static void e_iterator_class_init (EIteratorClass *klass);
+
+#define PARENT_TYPE (gtk_object_get_type ())
+
+static GtkObjectClass *parent_class;
+
+enum {
+ INVALIDATE,
+ LAST_SIGNAL
+};
+
+static guint e_iterator_signals [LAST_SIGNAL] = { 0, };
+
+/**
+ * e_iterator_get_type:
+ * @void:
+ *
+ * Registers the &EIterator class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &EIterator class.
+ **/
+GtkType
+e_iterator_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type) {
+ GtkTypeInfo info = {
+ "EIterator",
+ sizeof (EIterator),
+ sizeof (EIteratorClass),
+ (GtkClassInitFunc) e_iterator_class_init,
+ (GtkObjectInitFunc) e_iterator_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_TYPE, &info);
+ }
+
+ return type;
+}
+
+static void
+e_iterator_class_init (EIteratorClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = GTK_OBJECT_CLASS(klass);
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+
+ e_iterator_signals [INVALIDATE] =
+ gtk_signal_new ("invalidate",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EIteratorClass, invalidate),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, e_iterator_signals, LAST_SIGNAL);
+
+ klass->invalidate = NULL;
+ klass->get = NULL;
+ klass->reset = NULL;
+ klass->next = NULL;
+ klass->prev = NULL;
+ klass->delete = NULL;
+ klass->set = NULL;
+ klass->is_valid = NULL;
+}
+
+/**
+ * e_iterator_init:
+ */
+static void
+e_iterator_init (EIterator *card)
+{
+}
+
+/*
+ * Virtual functions:
+ */
+const void *
+e_iterator_get (EIterator *iterator)
+{
+ if (ECI_CLASS(iterator)->get)
+ return ECI_CLASS(iterator)->get(iterator);
+ else
+ return NULL;
+}
+
+void
+e_iterator_reset (EIterator *iterator)
+{
+ if (ECI_CLASS(iterator)->reset)
+ ECI_CLASS(iterator)->reset(iterator);
+}
+
+gboolean
+e_iterator_next (EIterator *iterator)
+{
+ if (ECI_CLASS(iterator)->next)
+ return ECI_CLASS(iterator)->next(iterator);
+ else
+ return FALSE;
+}
+
+gboolean
+e_iterator_prev (EIterator *iterator)
+{
+ if (ECI_CLASS(iterator)->prev)
+ return ECI_CLASS(iterator)->prev(iterator);
+ else
+ return FALSE;
+}
+
+void
+e_iterator_delete (EIterator *iterator)
+{
+ if (ECI_CLASS(iterator)->delete)
+ ECI_CLASS(iterator)->delete(iterator);
+}
+
+void
+e_iterator_set (EIterator *iterator,
+ const void *object)
+{
+ if (ECI_CLASS(iterator)->set)
+ ECI_CLASS(iterator)->set(iterator, object);
+}
+
+gboolean
+e_iterator_is_valid (EIterator *iterator)
+{
+ if (ECI_CLASS(iterator)->is_valid)
+ return ECI_CLASS(iterator)->is_valid(iterator);
+ else
+ return FALSE;
+}
+
+void
+e_iterator_invalidate (EIterator *iterator)
+{
+ g_return_if_fail (iterator != NULL);
+ g_return_if_fail (E_IS_ITERATOR (iterator));
+
+ gtk_signal_emit (GTK_OBJECT (iterator),
+ e_iterator_signals [INVALIDATE]);
+}
diff --git a/e-util/e-iterator.h b/e-util/e-iterator.h
new file mode 100644
index 0000000000..eb983e9da9
--- /dev/null
+++ b/e-util/e-iterator.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors:
+ * Chris Lahey <clahey@helixcode.com>
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 1999 The Free Software Foundation
+ */
+
+#ifndef __E_ITERATOR_H__
+#define __E_ITERATOR_H__
+
+#include <time.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+#define E_TYPE_ITERATOR (e_iterator_get_type ())
+#define E_ITERATOR(obj) (GTK_CHECK_CAST ((obj), E_TYPE_ITERATOR, EIterator))
+#define E_ITERATOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_ITERATOR, EIteratorClass))
+#define E_IS_ITERATOR(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_ITERATOR))
+#define E_IS_ITERATOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_ITERATOR))
+
+typedef struct _EIterator EIterator;
+typedef struct _EIteratorClass EIteratorClass;
+
+struct _EIterator {
+ GtkObject object;
+};
+
+struct _EIteratorClass {
+ GtkObjectClass parent_class;
+
+ /* Signals */
+ void (*invalidate) (EIterator *iterator);
+
+ /* Virtual functions */
+ const void * (*get) (EIterator *iterator);
+ void (*reset) (EIterator *iterator);
+ gboolean (*next) (EIterator *iterator);
+ gboolean (*prev) (EIterator *iterator);
+ void (*delete) (EIterator *iterator);
+ void (*set) (EIterator *iterator,
+ const void *object);
+ gboolean (*is_valid) (EIterator *iterator);
+};
+
+const void *e_iterator_get (EIterator *iterator);
+void e_iterator_reset (EIterator *iterator);
+gboolean e_iterator_next (EIterator *iterator);
+gboolean e_iterator_prev (EIterator *iterator);
+void e_iterator_delete (EIterator *iterator);
+void e_iterator_set (EIterator *iterator,
+ const void *object);
+gboolean e_iterator_is_valid (EIterator *iterator);
+
+void e_iterator_invalidate (EIterator *iterator);
+
+/* Standard Gtk function */
+GtkType e_iterator_get_type (void);
+
+#endif /* ! __E_ITERATOR_H__ */
diff --git a/e-util/e-list-iterator.c b/e-util/e-list-iterator.c
new file mode 100644
index 0000000000..19ebbef681
--- /dev/null
+++ b/e-util/e-list-iterator.c
@@ -0,0 +1,199 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors:
+ * Christopher James Lahey <clahey@umich.edu>
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 1999 The Free Software Foundation
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+
+#include "e-list-iterator.h"
+#include "e-list.h"
+
+static void e_list_iterator_init (EListIterator *list);
+static void e_list_iterator_class_init (EListIteratorClass *klass);
+
+static void e_list_iterator_invalidate (EIterator *iterator);
+static gboolean e_list_iterator_is_valid (EIterator *iterator);
+static void e_list_iterator_set (EIterator *iterator,
+ const void *object);
+static void e_list_iterator_delete (EIterator *iterator);
+static gboolean e_list_iterator_prev (EIterator *iterator);
+static gboolean e_list_iterator_next (EIterator *iterator);
+static void e_list_iterator_reset (EIterator *iterator);
+static const void *e_list_iterator_get (EIterator *iterator);
+static void e_list_iterator_destroy (GtkObject *object);
+
+#define PARENT_TYPE (e_iterator_get_type ())
+
+static GtkObjectClass *parent_class;
+#define PARENT_CLASS (E_LIST_ITERATOR_CLASS(parent_class))
+
+/**
+ * e_list_iterator_get_type:
+ * @void:
+ *
+ * Registers the &EListIterator class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &EListIterator class.
+ **/
+GtkType
+e_list_iterator_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type) {
+ GtkTypeInfo info = {
+ "EListIterator",
+ sizeof (EListIterator),
+ sizeof (EListIteratorClass),
+ (GtkClassInitFunc) e_list_iterator_class_init,
+ (GtkObjectInitFunc) e_list_iterator_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_TYPE, &info);
+ }
+
+ return type;
+}
+
+static void
+e_list_iterator_class_init (EListIteratorClass *klass)
+{
+ GtkObjectClass *object_class;
+ EIteratorClass *iterator_class;
+
+ object_class = GTK_OBJECT_CLASS(klass);
+ iterator_class = E_ITERATOR_CLASS(klass);
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+
+ object_class->destroy = e_list_iterator_destroy;
+
+ iterator_class->invalidate = e_list_iterator_invalidate;
+ iterator_class->get = e_list_iterator_get;
+ iterator_class->reset = e_list_iterator_reset;
+ iterator_class->next = e_list_iterator_next;
+ iterator_class->prev = e_list_iterator_prev;
+ iterator_class->delete = e_list_iterator_delete;
+ iterator_class->set = e_list_iterator_set;
+ iterator_class->is_valid = e_list_iterator_is_valid;
+}
+
+
+
+/**
+ * e_list_iterator_init:
+ */
+static void
+e_list_iterator_init (EListIterator *list)
+{
+}
+
+EIterator *
+e_list_iterator_new (EList *list)
+{
+ EListIterator *iterator = gtk_type_new(e_list_iterator_get_type());
+
+ iterator->list = list;
+ gtk_object_ref(GTK_OBJECT(list));
+ iterator->iterator = list->list;
+
+ return E_ITERATOR(iterator);
+}
+
+/*
+ * Virtual functions:
+ */
+static void
+e_list_iterator_destroy (GtkObject *object)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(object);
+ e_list_remove_iterator(iterator->list, E_ITERATOR(iterator));
+ gtk_object_unref(GTK_OBJECT(iterator->list));
+}
+
+static const void *
+e_list_iterator_get (EIterator *_iterator)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ if (iterator->iterator)
+ return iterator->iterator->data;
+ else
+ return NULL;
+}
+
+static void
+e_list_iterator_reset (EIterator *_iterator)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ iterator->iterator = iterator->list->list;
+}
+
+static gboolean
+e_list_iterator_next (EIterator *_iterator)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ if (iterator->iterator)
+ iterator->iterator = g_list_next(iterator->iterator);
+ return (iterator->iterator != NULL);
+}
+
+static gboolean
+e_list_iterator_prev (EIterator *_iterator)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ if (iterator->iterator)
+ iterator->iterator = g_list_previous(iterator->iterator);
+ return (iterator->iterator != NULL);
+}
+
+static void
+e_list_iterator_delete (EIterator *_iterator)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ if (iterator->iterator) {
+ GList *temp = iterator->iterator->next;
+ if (iterator->list->free)
+ iterator->list->free(iterator->iterator->data, iterator->list->closure);
+ iterator->list->list = g_list_remove_link(iterator->list->list, iterator->iterator);
+ iterator->iterator = temp;
+ e_list_invalidate_iterators(iterator->list, E_ITERATOR(iterator));
+ }
+}
+
+static void
+e_list_iterator_set (EIterator *_iterator,
+ const void *object)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ if (iterator->iterator) {
+ if (iterator->list->free)
+ iterator->list->free(iterator->iterator->data, iterator->list->closure);
+ if (iterator->list->copy)
+ iterator->iterator->data = iterator->list->copy(object, iterator->list->closure);
+ else
+ iterator->iterator->data = (void *) object;
+ }
+}
+
+static gboolean
+e_list_iterator_is_valid (EIterator *_iterator)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ return iterator->iterator != NULL;
+}
+
+static void
+e_list_iterator_invalidate (EIterator *_iterator)
+{
+ EListIterator *iterator = E_LIST_ITERATOR(_iterator);
+ iterator->iterator = NULL;
+}
diff --git a/e-util/e-list-iterator.h b/e-util/e-list-iterator.h
new file mode 100644
index 0000000000..a2b7d82988
--- /dev/null
+++ b/e-util/e-list-iterator.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors:
+ * Chris Lahey <clahey@helixcode.com>
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 1999 The Free Software Foundation
+ */
+
+#ifndef __E_LIST_ITERATOR_H__
+#define __E_LIST_ITERATOR_H__
+
+typedef struct _EListIterator EListIterator;
+typedef struct _EListIteratorClass EListIteratorClass;
+
+#include <time.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <e-util/e-iterator.h>
+#include <e-util/e-list.h>
+
+#define E_TYPE_LIST_ITERATOR (e_list_iterator_get_type ())
+#define E_LIST_ITERATOR(obj) (GTK_CHECK_CAST ((obj), E_TYPE_LIST_ITERATOR, EListIterator))
+#define E_LIST_ITERATOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_LIST_ITERATOR, EListIteratorClass))
+#define E_IS_LIST_ITERATOR(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_LIST_ITERATOR))
+#define E_IS_LIST_ITERATOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_LIST_ITERATOR))
+
+struct _EListIterator {
+ EIterator parent;
+
+ EList *list;
+ GList *iterator;
+};
+
+struct _EListIteratorClass {
+ EIteratorClass parent_class;
+};
+
+EIterator *e_list_iterator_new (EList *list);
+
+/* Standard Gtk function */
+GtkType e_list_iterator_get_type (void);
+
+#endif /* ! __E_LIST_ITERATOR_H__ */
diff --git a/e-util/e-list.c b/e-util/e-list.c
new file mode 100644
index 0000000000..bc5769fb38
--- /dev/null
+++ b/e-util/e-list.c
@@ -0,0 +1,140 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors:
+ * Christopher James Lahey <clahey@umich.edu>
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 1999 The Free Software Foundation
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+
+#include "e-list.h"
+#include "e-list-iterator.h"
+
+#define ECL_CLASS(object) (E_LIST_CLASS(GTK_OBJECT((object))->klass))
+
+static void e_list_init (EList *list);
+static void e_list_class_init (EListClass *klass);
+static void e_list_destroy (GtkObject *object);
+
+#define PARENT_TYPE (gtk_object_get_type ())
+
+static GtkObjectClass *parent_class;
+
+/**
+ * e_list_get_type:
+ * @void:
+ *
+ * Registers the &EList class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the &EList class.
+ **/
+GtkType
+e_list_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (!type) {
+ GtkTypeInfo info = {
+ "EList",
+ sizeof (EList),
+ sizeof (EListClass),
+ (GtkClassInitFunc) e_list_class_init,
+ (GtkObjectInitFunc) e_list_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ type = gtk_type_unique (PARENT_TYPE, &info);
+ }
+
+ return type;
+}
+
+static void
+e_list_class_init (EListClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = GTK_OBJECT_CLASS(klass);
+
+ parent_class = gtk_type_class (PARENT_TYPE);
+
+ object_class->destroy = e_list_destroy;
+}
+
+/**
+ * e_list_init:
+ */
+static void
+e_list_init (EList *list)
+{
+ list->list = NULL;
+ list->iterators = NULL;
+}
+
+EList *
+e_list_new (EListCopyFunc copy, EListFreeFunc free, void *closure)
+{
+ EList *list = gtk_type_new(e_list_get_type());
+ list->copy = copy;
+ list->free = free;
+ list->closure = closure;
+ return list;
+}
+
+EIterator *
+e_list_get_iterator (EList *list)
+{
+ EIterator *iterator = e_list_iterator_new(list);
+ list->iterators = g_list_append(list->iterators, iterator);
+ return iterator;
+}
+
+int
+e_list_length (EList *list)
+{
+ return g_list_length(list->list);
+}
+
+void
+e_list_append (EList *list, const void *data)
+{
+ e_list_invalidate_iterators(list, NULL);
+ if (list->copy)
+ list->list = g_list_append(list->list, list->copy(data, list->closure));
+ else
+ list->list = g_list_append(list->list, (void *) data);
+}
+
+void
+e_list_invalidate_iterators (EList *list, EIterator *skip)
+{
+ GList *iterators = list->iterators;
+ for (; iterators; iterators = iterators->next) {
+ if (iterators->data != skip) {
+ e_iterator_invalidate(E_ITERATOR(iterators->data));
+ }
+ }
+}
+
+void
+e_list_remove_iterator (EList *list, EIterator *iterator)
+{
+ list->iterators = g_list_remove(list->iterators, iterator);
+}
+
+/*
+ * Virtual functions
+ */
+static void
+e_list_destroy (GtkObject *object)
+{
+ EList *list = E_LIST(object);
+ g_list_foreach(list->list, (GFunc) list->free, list->closure);
+ g_list_free(list->list);
+}
diff --git a/e-util/e-list.h b/e-util/e-list.h
new file mode 100644
index 0000000000..545798fbf9
--- /dev/null
+++ b/e-util/e-list.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors:
+ * Chris Lahey <clahey@helixcode.com>
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ * Copyright (C) 1999 The Free Software Foundation
+ */
+
+#ifndef __E_LIST_H__
+#define __E_LIST_H__
+
+typedef struct _EList EList;
+typedef struct _EListClass EListClass;
+
+#include <time.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <e-util/e-list-iterator.h>
+
+#define E_TYPE_LIST (e_list_get_type ())
+#define E_LIST(obj) (GTK_CHECK_CAST ((obj), E_TYPE_LIST, EList))
+#define E_LIST_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_LIST, EListClass))
+#define E_IS_LIST(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_LIST))
+#define E_IS_LIST_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_LIST))
+
+typedef void *(*EListCopyFunc) (const void *data, void *closure);
+typedef void (*EListFreeFunc) (void *data, void *closure);
+
+struct _EList {
+ GtkObject object;
+ GList *list;
+ GList *iterators;
+ EListCopyFunc copy;
+ EListFreeFunc free;
+ void *closure;
+};
+
+struct _EListClass {
+ GtkObjectClass parent_class;
+};
+
+EList *e_list_new (EListCopyFunc copy,
+ EListFreeFunc free,
+ void *closure);
+EIterator *e_list_get_iterator (EList *list);
+void e_list_append (EList *list,
+ const void *data);
+int e_list_length (EList *list);
+
+/* For iterators to call. */
+void e_list_invalidate_iterators (EList *list,
+ EIterator *skip);
+void e_list_remove_iterator (EList *list,
+ EIterator *iterator);
+
+/* Standard Gtk function */
+GtkType e_list_get_type (void);
+
+#endif /* ! __E_LIST_H__ */
diff --git a/widgets/misc/e-canvas.c b/widgets/misc/e-canvas.c
index 0da4dade28..4cb912283e 100644
--- a/widgets/misc/e-canvas.c
+++ b/widgets/misc/e-canvas.c
@@ -583,6 +583,7 @@ e_canvas_item_add_selection (GnomeCanvasItem *item, gpointer id)
ECanvas *canvas;
ECanvasSelectionInfo *info;
ECanvasItemSelectionFunc func;
+ GList *list;
g_return_if_fail(item != NULL);
g_return_if_fail(GNOME_IS_CANVAS_ITEM(item));
@@ -602,6 +603,24 @@ e_canvas_item_add_selection (GnomeCanvasItem *item, gpointer id)
flags = E_CANVAS_ITEM_SELECTION_SELECT | E_CANVAS_ITEM_SELECTION_CURSOR;
+ for (list = canvas->selection; list; list = g_list_next(list)) {
+ ECanvasSelectionInfo *search;
+ search = list->data;
+
+ if (search->item == item) {
+ ECanvasItemSelectionCompareFunc compare_func;
+ compare_func = gtk_object_get_data(GTK_OBJECT(search->item), "ECanvasItem::selection_compare_callback");
+
+ if (compare_func(search->item, search->id, id, 0) == 0) {
+ canvas->cursor = search;
+ func = gtk_object_get_data(GTK_OBJECT(item), "ECanvasItem::selection_callback");
+ if (func)
+ func(item, flags, search->id);
+ return;
+ }
+ }
+ }
+
info = g_new(ECanvasSelectionInfo, 1);
info->item = item;
info->id = id;