[nautilus-actions] Fix various memory leaks
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Fix various memory leaks
- Date: Sat, 26 Sep 2009 22:49:21 +0000 (UTC)
commit 22202ad3e97d06286f9ad79ab4c37a9d5c13b709
Author: Pierre Wieser <pwieser trychlos org>
Date: Wed Sep 23 01:14:08 2009 +0200
Fix various memory leaks
ChangeLog | 12 +++-
src/common/na-iduplicable.c | 2 -
src/common/na-object-api.h | 2 +-
src/common/na-object-fn.h | 2 +-
src/common/na-object-item.c | 4 -
src/common/na-object.c | 47 +++++++------
src/common/na-pivot.c | 9 ++-
src/nact/base-dialog.h | 2 +-
src/nact/nact-application.c | 13 ++++
src/nact/nact-clipboard.c | 151 +++++++++++++++++++++++++++++++++++++++++-
src/nact/nact-clipboard.h | 53 +++++++++++++--
src/nact/nact-main-menubar.c | 2 +-
src/nact/nact-main-window.c | 10 +++
13 files changed, 264 insertions(+), 45 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 963b10f..f60cdde 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,7 +16,7 @@
Fix equality check if a profile is modified.
* src/common/na-object-api.h (na_object_dump_norec,
- na_object_dump_tree, na_object_rewind_origin): New functions.
+ na_object_dump_tree, na_object_reset_origin): New functions.
na_object_insert_item(): Add a sibling pointer.
* src/common/na-object.c:
@@ -38,11 +38,20 @@
* src/common/na-pivot.c:
* src/common/na-pivot.h (na_pivot_get_item): New function.
+ na_pivot_remove_item(): The removed object may have been already
+ deleted.
+
+ * src/nact/nact-application.c (appli_initialize_application):
+ Allocate a fake NAObjectAction to initialize NAIDuplicable
+ interface.
* src/nact/nact-assistant-import.c:
Actually imports the actions into the tree store before
confirming the operation was done.
+ * src/nact/nact-clipboard.c:
+ * src/nact/nact-clipboard.h: Make it a convenience class.
+
* nact/nact-iactions-list.c:
* nact/nact-iactions-list.h (nact_iactions_list_get_item):
New function.
@@ -53,6 +62,7 @@
* src/nact/nact-main-window.c (nact_main_window_action_exists):
Restore the function, searching in NAPivot and in tree store.
+ instance_dispose(): Clear the clipboard.
* src/nact/nact-tree-model.c:
Now inserts the new row before a given sibling object.
diff --git a/src/common/na-iduplicable.c b/src/common/na-iduplicable.c
index 8f0e994..56b2e93 100644
--- a/src/common/na-iduplicable.c
+++ b/src/common/na-iduplicable.c
@@ -129,7 +129,6 @@ interface_base_init( NAIDuplicableInterface *klass )
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
klass->private = g_new0( NAIDuplicableInterfacePrivate, 1 );
-
klass->private->consumers = NULL;
/**
@@ -179,7 +178,6 @@ interface_base_init( NAIDuplicableInterface *klass )
G_TYPE_POINTER );
st_interface = klass;
-
st_initialized = TRUE;
}
}
diff --git a/src/common/na-object-api.h b/src/common/na-object-api.h
index 29fdd3d..bc40017 100644
--- a/src/common/na-object-api.h
+++ b/src/common/na-object-api.h
@@ -50,7 +50,6 @@ G_BEGIN_DECLS
#define na_object_dump_tree( tree ) na_object_object_dump_tree( tree )
#define na_object_get_clipboard_id( object ) na_object_object_get_clipboard_id( NA_OBJECT( object ))
#define na_object_ref( object ) na_object_object_ref( NA_OBJECT( object ))
-#define na_object_rewind_origin( target, source ) na_object_object_rewind_origin( NA_OBJECT( target ), NA_OBJECT( source ))
/* NAIDuplicable
*/
@@ -61,6 +60,7 @@ G_BEGIN_DECLS
#define na_object_get_origin( object ) na_object_iduplicable_get_origin( NA_OBJECT( object ))
#define na_object_set_origin( object, origin ) na_object_iduplicable_set_origin( NA_OBJECT( object ), NA_OBJECT( origin ))
+#define na_object_reset_origin( object, origin ) na_object_object_reset_origin( NA_OBJECT( object ), NA_OBJECT( origin ))
/* NAObjectId
*/
diff --git a/src/common/na-object-fn.h b/src/common/na-object-fn.h
index 923a9f2..0ec7159 100644
--- a/src/common/na-object-fn.h
+++ b/src/common/na-object-fn.h
@@ -64,7 +64,7 @@ void na_object_object_dump_norec( const NAObject *object );
void na_object_object_dump_tree( GList *tree );
gchar *na_object_object_get_clipboard_id( const NAObject *object );
NAObject *na_object_object_ref( const NAObject *object );
-void na_object_object_rewind_origin( NAObject *target, const NAObject *source );
+void na_object_object_reset_origin( NAObject *object, const NAObject *origin );
GList *na_object_get_hierarchy( const NAObject *object );
void na_object_free_hierarchy( GList *hierarchy );
diff --git a/src/common/na-object-item.c b/src/common/na-object-item.c
index c7c69bd..1057309 100644
--- a/src/common/na-object-item.c
+++ b/src/common/na-object-item.c
@@ -715,7 +715,6 @@ na_object_item_append_item( NAObjectItem *item, const NAObject *object )
g_return_if_fail( NA_IS_OBJECT( object ));
if( !g_list_find( item->private->items, ( gpointer ) object )){
- /*item->private->items = g_list_append( item->private->items, g_object_ref(( gpointer ) object ));*/
item->private->items = g_list_append( item->private->items, ( gpointer ) object );
}
}
@@ -743,10 +742,8 @@ na_object_item_insert_item( NAObjectItem *item, const NAObject *object, const NA
if( !g_list_find( item->private->items, ( gpointer ) object )){
before_list = g_list_find( item->private->items, ( gconstpointer ) before );
if( before_list ){
- /*item->private->items = g_list_insert_before( item->private->items, before_list, g_object_ref(( gpointer ) object ));*/
item->private->items = g_list_insert_before( item->private->items, before_list, ( gpointer ) object );
} else {
- /*item->private->items = g_list_prepend( item->private->items, g_object_ref(( gpointer ) object ));*/
item->private->items = g_list_prepend( item->private->items, ( gpointer ) object );
}
}
@@ -770,7 +767,6 @@ na_object_item_remove_item( NAObjectItem *item, const NAObject *object )
if( g_list_find( item->private->items, ( gconstpointer ) object )){
item->private->items = g_list_remove( item->private->items, ( gconstpointer ) object );
- /*g_object_unref(( gpointer ) object );*/
}
}
diff --git a/src/common/na-object.c b/src/common/na-object.c
index 643f9eb..a82ef3b 100644
--- a/src/common/na-object.c
+++ b/src/common/na-object.c
@@ -529,39 +529,42 @@ na_object_object_ref( const NAObject *object )
}
/**
- * na_object_object_rewind_origin:
- * @target: must be a duplication of @source.
- * @source: a #NAObject-derived object.
+ * na_object_object_reset_origin:
+ * @object: a #NAObject-derived object.
+ * @origin: must be a duplication of @object.
*
- * Recursively rewind origin between @source to @target, so that
- * @target appear as the origin of @source.
+ * Recursively reset origin of @object and its childs to @origin and
+ * its childs), so that @origin appear as the actual origin of @object.
*
- * The origin of @target itself is set to NULL.
+ * The origin of @origin itself is set to NULL.
*
- * This only works if @target has just been duplicated from @source,
+ * This only works if @origin has just been duplicated from @object,
* and thus we do not have to check if childs lists are equal.
*/
void
-na_object_object_rewind_origin( NAObject *target, const NAObject *source )
+na_object_object_reset_origin( NAObject *object, const NAObject *origin )
{
- GList *childs, *ic;
- NAObject *origin;
+ GList *origin_childs, *iorig;
+ GList *object_childs, *iobj;
+ NAObject *orig_object;
- g_return_if_fail( NA_IS_OBJECT( target ));
- g_return_if_fail( !target->private->dispose_has_run );
- g_return_if_fail( NA_IS_OBJECT( source ));
- g_return_if_fail( !source->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( origin ));
+ g_return_if_fail( !origin->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
- childs = v_get_childs( target );
- for( ic = childs ; ic ; ic = ic->next ){
- origin = na_object_get_origin( ic->data );
- na_object_rewind_origin( ic->data, origin );
+ origin_childs = v_get_childs( origin );
+ object_childs = v_get_childs( object );
+ for( iorig = origin_childs, iobj = object_childs ; iorig && iobj ; iorig = iorig->next, iobj = iobj->next ){
+ orig_object = na_object_get_origin( iorig->data );
+ g_return_if_fail( orig_object == iobj->data );
+ na_object_reset_origin( iobj->data, iorig->data );
}
- origin = na_object_get_origin( target );
- g_return_if_fail( origin == source );
- na_iduplicable_set_origin( NA_IDUPLICABLE( source ), NA_IDUPLICABLE( target ));
- na_iduplicable_set_origin( NA_IDUPLICABLE( target ), NULL );
+ orig_object = na_object_get_origin( origin );
+ g_return_if_fail( orig_object == object );
+ na_iduplicable_set_origin( NA_IDUPLICABLE( object ), NA_IDUPLICABLE( origin ));
+ na_iduplicable_set_origin( NA_IDUPLICABLE( origin ), NULL );
}
/**
diff --git a/src/common/na-pivot.c b/src/common/na-pivot.c
index 88c47da..fb77891 100644
--- a/src/common/na-pivot.c
+++ b/src/common/na-pivot.c
@@ -492,6 +492,9 @@ na_pivot_get_item( const NAPivot *pivot, const gchar *uuid )
* Removes a #NAObjectItem from the hierarchical tree.
*
* Note that #NAPivot also g_object_unref() the removed #NAObjectItem.
+ *
+ * Last, note that the @item may have been already deleted, when its
+ * parents has itself been removed from @pivot.
*/
void
na_pivot_remove_item( NAPivot *pivot, NAObject *item )
@@ -502,10 +505,12 @@ na_pivot_remove_item( NAPivot *pivot, NAObject *item )
g_return_if_fail( NA_IS_PIVOT( pivot ));
g_return_if_fail( !pivot->private->dispose_has_run );
- g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
pivot->private->tree = g_list_remove( pivot->private->tree, ( gconstpointer ) item );
- g_object_unref( item );
+
+ if( NA_IS_OBJECT( item )){
+ g_object_unref( item );
+ }
}
/**
diff --git a/src/nact/base-dialog.h b/src/nact/base-dialog.h
index be843cc..ade1e31 100644
--- a/src/nact/base-dialog.h
+++ b/src/nact/base-dialog.h
@@ -34,7 +34,7 @@
/**
* SECTION: base_dialog
* @short_description: #BaseDialog class definition.
- * @include: base/base-dialog.h
+ * @include: nact/base-dialog.h
*
* This class is derived from BaseWindow class, and serves as a base
* class for all Nautilus Actions dialogs.
diff --git a/src/nact/nact-application.c b/src/nact/nact-application.c
index da13609..593d9e1 100644
--- a/src/nact/nact-application.c
+++ b/src/nact/nact-application.c
@@ -36,6 +36,7 @@
#include <gtk/gtk.h>
#include <common/na-about.h>
+#include <common/na-iduplicable.h>
#include <common/na-ipivot-consumer.h>
#include "nact-application.h"
@@ -323,15 +324,27 @@ appli_initialize_unique_app( BaseApplication *application )
* NAPivot notification messages
*
* At last, let the base class do its work, i.e. creating the main window.
+ *
+ * When the pivot will be empty, NAIDuplicable signals must yet be
+ * recorded in the system. Done here because :
+ * - I don't want do this in NAPivot which is also used by the plugin,
+ * - this is the last place where I'm pretty sure NAObject has not yet
+ * been registered.
+ * So we allocate a new NAObject-derived object to be sure the interface
+ * is correctly initialized.
*/
static gboolean
appli_initialize_application( BaseApplication *application )
{
static const gchar *thisfn = "nact_application_appli_initialize_application";
gboolean ok;
+ NAObjectAction *fake;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
+ fake = na_object_action_new();
+ g_object_unref( fake );
+
NACT_APPLICATION( application )->private->pivot = na_pivot_new( NULL );
/* call parent class */
diff --git a/src/nact/nact-clipboard.c b/src/nact/nact-clipboard.c
index 3ba9cf3..a965e1c 100644
--- a/src/nact/nact-clipboard.c
+++ b/src/nact/nact-clipboard.c
@@ -44,6 +44,19 @@
#include "nact-clipboard.h"
+/* private class data
+ */
+struct NactClipboardClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NactClipboardPrivate {
+ gboolean dispose_has_run;
+ GtkClipboard *primary;
+};
+
#define NACT_CLIPBOARD_ATOM gdk_atom_intern( "_NACT_CLIPBOARD", FALSE )
#define NACT_CLIPBOARD_NACT_ATOM gdk_atom_intern( "ClipboardNautilusActions", FALSE )
@@ -74,6 +87,14 @@ typedef struct {
}
NactClipboardData;
+static GObjectClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( NactClipboardClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *application );
+static void instance_finalize( GObject *application );
+
static GtkClipboard *get_nact_clipboard( void );
static GtkClipboard *get_primary_clipboard( void );
static void add_item_to_clipboard0( NAObject *object, gboolean copy_data, gboolean only_profiles, GList **copied );
@@ -84,6 +105,132 @@ static void get_from_clipboard_callback( GtkClipboard *clipboard, GtkSe
static void clear_clipboard_callback( GtkClipboard *clipboard, NactClipboardData *data );
static void renumber_items( GList *items );
+GType
+nact_clipboard_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = register_type();
+ }
+
+ return( type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "nact_clipboard_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( NactClipboardClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( NactClipboard ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( G_TYPE_OBJECT, "NactClipboard", &info, 0 );
+
+ return( type );
+}
+
+static void
+class_init( NactClipboardClass *klass )
+{
+ static const gchar *thisfn = "nact_clipboard_class_init";
+ GObjectClass *object_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = instance_dispose;
+ object_class->finalize = instance_finalize;
+
+ klass->private = g_new0( NactClipboardClassPrivate, 1 );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "nact_clipboard_instance_init";
+ NactClipboard *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( NACT_IS_CLIPBOARD( instance ));
+ self = NACT_CLIPBOARD( instance );
+
+ self->private = g_new0( NactClipboardPrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+ self->private->primary = get_primary_clipboard();
+}
+
+static void
+instance_dispose( GObject *window )
+{
+ static const gchar *thisfn = "nact_clipboard_instance_dispose";
+ NactClipboard *self;
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_assert( NACT_IS_CLIPBOARD( window ));
+ self = NACT_CLIPBOARD( window );
+
+ if( !self->private->dispose_has_run ){
+
+ self->private->dispose_has_run = TRUE;
+
+ gtk_clipboard_clear( self->private->primary );
+
+ /* chain up to the parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ }
+ }
+}
+
+static void
+instance_finalize( GObject *window )
+{
+ static const gchar *thisfn = "nact_clipboard_instance_finalize";
+ NactClipboard *self;
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_assert( NACT_IS_CLIPBOARD( window ));
+ self = NACT_CLIPBOARD( window );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( window );
+ }
+}
+
+/**
+ * nact_clipboard_new:
+ *
+ * Returns: a new #NactClipboard object.
+ */
+NactClipboard *
+nact_clipboard_new( void )
+{
+ NactClipboard *clipboard;
+
+ clipboard = g_object_new( NACT_CLIPBOARD_TYPE, NULL );
+
+ return( clipboard );
+}
+
/**
* nact_clipboard_get_data_for_intern_use:
*
@@ -325,7 +472,7 @@ get_nact_clipboard( void )
GtkClipboard *clipboard;
display = gdk_display_get_default();
- clipboard = gtk_clipboard_get_for_display( display, GDK_SELECTION_PRIMARY );
+ clipboard = gtk_clipboard_get_for_display( display, NACT_CLIPBOARD_ATOM );
return( clipboard );
}
@@ -337,7 +484,7 @@ get_primary_clipboard( void )
GtkClipboard *clipboard;
display = gdk_display_get_default();
- clipboard = gtk_clipboard_get_for_display( display, NACT_CLIPBOARD_ATOM );
+ clipboard = gtk_clipboard_get_for_display( display, GDK_SELECTION_PRIMARY );
return( clipboard );
}
diff --git a/src/nact/nact-clipboard.h b/src/nact/nact-clipboard.h
index 4b95837..2b15d76 100644
--- a/src/nact/nact-clipboard.h
+++ b/src/nact/nact-clipboard.h
@@ -31,20 +31,57 @@
#ifndef __NACT_CLIPBOARD_H__
#define __NACT_CLIPBOARD_H__
-#include <glib.h>
+/*
+ * SECTION: nact_clipboard.
+ * @short_description: #NactClipboard class definition.
+ * @include: nact/nact-clipboard.h
+ *
+ * This is just a convenience class to extract clipboard functions
+ * from main window code. There is a unique object which manages all
+ * clipboard buffers.
+ */
+
+#include <glib-object.h>
G_BEGIN_DECLS
-void nact_clipboard_get_data_for_intern_use( GList *selected_items, gboolean copy_data );
-char *nact_clipboard_get_data_for_extern_use( GList *selected_items );
+#define NACT_CLIPBOARD_TYPE ( nact_clipboard_get_type())
+#define NACT_CLIPBOARD( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_CLIPBOARD_TYPE, NactClipboard ))
+#define NACT_CLIPBOARD_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NACT_CLIPBOARD_TYPE, NactClipboardClass ))
+#define NACT_IS_CLIPBOARD( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_CLIPBOARD_TYPE ))
+#define NACT_IS_CLIPBOARD_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_CLIPBOARD_TYPE ))
+#define NACT_CLIPBOARD_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_CLIPBOARD_TYPE, NactClipboardClass ))
+
+typedef struct NactClipboardPrivate NactClipboardPrivate;
+
+typedef struct {
+ GObject parent;
+ NactClipboardPrivate *private;
+}
+ NactClipboard;
+
+typedef struct NactClipboardClassPrivate NactClipboardClassPrivate;
+
+typedef struct {
+ GObjectClass parent;
+ NactClipboardClassPrivate *private;
+}
+ NactClipboardClass;
+
+GType nact_clipboard_get_type( void );
+
+NactClipboard *nact_clipboard_new( void );
+
+void nact_clipboard_get_data_for_intern_use( GList *selected_items, gboolean copy_data );
+char *nact_clipboard_get_data_for_extern_use( GList *selected_items );
-void nact_clipboard_primary_set( GList *items, gboolean renumber_items );
-GList *nact_clipboard_primary_get( void );
-void nact_clipboard_primary_counts( guint *actions, guint *profiles, guint *menus );
+void nact_clipboard_primary_set( GList *items, gboolean renumber_items );
+GList *nact_clipboard_primary_get( void );
+void nact_clipboard_primary_counts( guint *actions, guint *profiles, guint *menus );
-void nact_clipboard_free_items( GSList *items );
+void nact_clipboard_free_items( GSList *items );
-void nact_clipboard_export_items( const gchar *uri, GList *items );
+void nact_clipboard_export_items( const gchar *uri, GList *items );
G_END_DECLS
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index 3fe1747..82923d3 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -448,7 +448,7 @@ save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item )
}
dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( item ));
- na_object_rewind_origin( dup_pivot, item );
+ na_object_reset_origin( item, dup_pivot );
na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
na_object_check_edition_status( item );
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index ea55e59..8374cc4 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -45,6 +45,7 @@
#include "base-iprefs.h"
#include "nact-application.h"
+#include "nact-clipboard.h"
#include "nact-iactions-list.h"
#include "nact-iaction-tab.h"
#include "nact-icommand-tab.h"
@@ -89,6 +90,11 @@ struct NactMainWindowPrivate {
* (because an action cannot have zero profile).
*/
NAObjectProfile *edited_profile;
+
+ /**
+ * The convenience clipboard object.
+ */
+ NactClipboard *clipboard;
};
/* action properties
@@ -485,6 +491,8 @@ instance_dispose( GObject *window )
self->private->dispose_has_run = TRUE;
+ g_object_unref( self->private->clipboard );
+
pane = base_window_get_widget( BASE_WINDOW( window ), "MainPaned" );
pos = gtk_paned_get_position( GTK_PANED( pane ));
base_iprefs_set_int( BASE_WINDOW( window ), "main-paned", pos );
@@ -716,6 +724,8 @@ on_base_initial_load_toplevel( NactMainWindow *window, gpointer user_data )
g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
g_assert( NACT_IS_MAIN_WINDOW( window ));
+ window->private->clipboard = nact_clipboard_new();
+
pos = base_iprefs_get_int( BASE_WINDOW( window ), "main-paned" );
if( pos ){
pane = base_window_get_widget( BASE_WINDOW( window ), "MainPaned" );
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]