Index: gal-a11y-e-cell-text.c
===================================================================
RCS file: /export/src/cvs/gal/gal/a11y/e-table/gal-a11y-e-cell-text.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 gal-a11y-e-cell-text.c
--- gal-a11y-e-cell-text.c	2003/09/26 06:37:13	1.1.1.1
+++ gal-a11y-e-cell-text.c	2003/11/06 12:58:30
@@ -34,6 +34,9 @@
 	char *full_text =
 		e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
 
+	if (full_text == NULL)
+		return NULL;
+
 	if (end_offset == -1)
 		end_offset = strlen (full_text);
 	else
Index: gal-a11y-e-cell.c
===================================================================
RCS file: /export/src/cvs/gal/gal/a11y/e-table/gal-a11y-e-cell.c,v
retrieving revision 1.4
diff -u -r1.4 gal-a11y-e-cell.c
--- gal-a11y-e-cell.c	2003/11/03 04:36:47	1.4
+++ gal-a11y-e-cell.c	2003/11/06 12:58:30
@@ -38,7 +38,7 @@
 #endif 
 
 static void
-eti_dispose (GObject *object)
+gal_a11y_e_cell_dispose (GObject *object)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (object);
 
@@ -57,20 +57,23 @@
 	a11y->view_col = -1;
 	a11y->row = -1;
 
+	if (a11y->state_set)
+		g_object_unref (a11y->state_set);
+
 	if (parent_class->dispose)
 		parent_class->dispose (object);
 }
 
 /* Static functions */
 static AtkObject*
-eti_get_parent (AtkObject *accessible)
+gal_a11y_e_cell_get_parent (AtkObject *accessible)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible);
 	return a11y->parent;
 }
 
 static gint
-eti_get_index_in_parent (AtkObject *accessible)
+gal_a11y_e_cell_get_index_in_parent (AtkObject *accessible)
 {
 	GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible);
 
@@ -80,7 +83,7 @@
 
 /* Component IFace */
 static void
-eti_get_extents (AtkComponent *component,
+gal_a11y_e_cell_get_extents (AtkComponent *component,
 		gint *x,
 		gint *y,
 		gint *width,
@@ -114,7 +117,7 @@
 }
 
 static gboolean
-eti_grab_focus (AtkComponent *component)
+gal_a11y_e_cell_grab_focus (AtkComponent *component)
 {
 	GalA11yECell *a11y;
 	gint view_row;
@@ -136,28 +139,41 @@
 /* Table IFace */
 
 static void
-eti_atk_component_iface_init (AtkComponentIface *iface)
+gal_a11y_e_cell_atk_component_iface_init (AtkComponentIface *iface)
+{
+	iface->get_extents = gal_a11y_e_cell_get_extents;
+	iface->grab_focus  = gal_a11y_e_cell_grab_focus;
+}
+
+
+static AtkStateSet *
+gal_a11y_e_cell_ref_state_set (AtkObject *obj)
 {
-	iface->get_extents = eti_get_extents;
-	iface->grab_focus  = eti_grab_focus;
+  GalA11yECell *cell = GAL_A11Y_E_CELL (obj);
+  g_return_val_if_fail (cell->state_set, NULL);
+                                                                                
+  g_object_ref(cell->state_set);
+  return cell->state_set;
 }
 
+
 static void
-eti_class_init (GalA11yECellClass *klass)
+gal_a11y_e_cell_class_init (GalA11yECellClass *klass)
 {
 	AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
 	parent_class                          = g_type_class_ref (PARENT_TYPE);
 
-	object_class->dispose                 = eti_dispose;
+	object_class->dispose                 = gal_a11y_e_cell_dispose;
 
-	atk_object_class->get_parent          = eti_get_parent;
-	atk_object_class->get_index_in_parent = eti_get_index_in_parent;
+	atk_object_class->get_parent          = gal_a11y_e_cell_get_parent;
+	atk_object_class->get_index_in_parent = gal_a11y_e_cell_get_index_in_parent;
+	atk_object_class->ref_state_set = gal_a11y_e_cell_ref_state_set;
 }
 
 static void
-eti_init (GalA11yECell *a11y)
+gal_a11y_e_cell_init (GalA11yECell *a11y)
 {
 	a11y->item = NULL;
 	a11y->cell_view = NULL;
@@ -165,6 +181,9 @@
 	a11y->model_col = -1;
 	a11y->view_col = -1;
 	a11y->row = -1;
+	a11y->state_set = atk_state_set_new ();
+	atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT);
+	atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED);
 }
 
 
@@ -410,6 +429,34 @@
 	}
 }
 
+gboolean
+gal_a11y_e_cell_remove_state (GalA11yECell     *cell,
+			      AtkStateType state_type,
+			      gboolean     emit_signal)
+{
+  if (atk_state_set_contains_state (cell->state_set, state_type))
+    {
+      gboolean rc;
+      AtkObject *parent;
+                                                                                
+      rc = atk_state_set_remove_state (cell->state_set, state_type);
+      /*
+       * The signal should only be generated if the value changed,
+       * not when the cell is set up.  So states that are set
+       * initially should pass FALSE as the emit_signal argument.
+       */
+                                                                                
+      if (emit_signal)
+        {
+          atk_object_notify_state_change (ATK_OBJECT (cell), state_type, FALSE);          /* If state_type is ATK_STATE_VISIBLE, additional notification */
+          if (state_type == ATK_STATE_VISIBLE)
+            g_signal_emit_by_name (cell, "visible_data_changed");
+        }
+    }
+  else
+    return FALSE;
+}
+
 
 /**
  * gal_a11y_e_cell_get_type:
@@ -430,17 +477,17 @@
 			sizeof (GalA11yECellClass),
 			(GBaseInitFunc) NULL,
 			(GBaseFinalizeFunc) NULL,
-			(GClassInitFunc) eti_class_init,
+			(GClassInitFunc) gal_a11y_e_cell_class_init,
 			(GClassFinalizeFunc) NULL,
 			NULL, /* class_data */
 			sizeof (GalA11yECell),
 			0,
-			(GInstanceInitFunc) eti_init,
+			(GInstanceInitFunc) gal_a11y_e_cell_init,
 			NULL /* value_cell */
 		};
 
 		static const GInterfaceInfo atk_component_info = {
-			(GInterfaceInitFunc) eti_atk_component_iface_init,
+			(GInterfaceInitFunc) gal_a11y_e_cell_atk_component_iface_init,
 			(GInterfaceFinalizeFunc) NULL,
 			NULL
 		};
Index: gal-a11y-e-cell.h
===================================================================
RCS file: /export/src/cvs/gal/gal/a11y/e-table/gal-a11y-e-cell.h,v
retrieving revision 1.2
diff -u -r1.2 gal-a11y-e-cell.h
--- gal-a11y-e-cell.h	2003/10/28 06:55:15	1.2
+++ gal-a11y-e-cell.h	2003/11/06 12:58:30
@@ -87,5 +87,9 @@
 gboolean gal_a11y_e_cell_remove_action_by_name (GalA11yECell        *cell,
                                           	const gchar     *action_name);
 
+gboolean gal_a11y_e_cell_add_state	(GalA11yECell     *cell,
+					 AtkStateType state_type,
+					 gboolean     emit_signal);
+
 
 #endif /* ! __GAL_A11Y_E_CELL_H__ */
Index: gal-a11y-e-table-item.c
===================================================================
RCS file: /export/src/cvs/gal/gal/a11y/e-table/gal-a11y-e-table-item.c,v
retrieving revision 1.4
diff -u -r1.4 gal-a11y-e-table-item.c
--- gal-a11y-e-table-item.c	2003/11/03 08:17:20	1.4
+++ gal-a11y-e-table-item.c	2003/11/06 12:58:30
@@ -10,6 +10,7 @@
 #include <config.h>
 #include "gal-a11y-e-table-item.h"
 #include "gal-a11y-e-cell-registry.h"
+#include "gal-a11y-e-cell.h"
 #include "gal-a11y-util.h"
 #include <gal/e-table/e-table-subset.h>
 
@@ -32,6 +33,7 @@
 struct _GalA11yETableItemPrivate {
 	AtkObject *parent;
 	gint index_in_parent;
+	gpointer *cell_data;
 	int selection_change_id;
 	int cursor_change_id;
 };
@@ -76,16 +78,13 @@
 static void
 eti_dispose (GObject *object)
 {
+	gint i,j;
 	GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (object);
 	GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y);
 
-#if 0
-	if (priv->item)
-		g_object_weak_unref (G_OBJECT (priv->item), unref_accessible, a11y);
+	g_free (priv->cell_data);
+	priv->cell_data = NULL;
 
-	if (priv->parent)
-		g_object_unref (priv->parent);
-#endif
 	priv->parent = NULL;
 
 	if (parent_class->dispose)
@@ -225,11 +224,33 @@
 
 
 /* atk table */
+static void
+cell_destroyed (gpointer data)
+{
+	AtkObject *parent;
+	gint index, n_cols;
+	GalA11yETableItem * item;
+	GalA11yECell * cell;
+
+	g_return_if_fail (GAL_A11Y_IS_E_CELL (data));
+
+	parent = atk_object_get_parent (ATK_OBJECT (data));
+
+	item = GAL_A11Y_E_TABLE_ITEM(parent);
+	if (item == NULL)
+		return;
+
+	index = cell->row * cell->item->cols + cell->view_col;
+
+	if (GET_PRIVATE (item)->cell_data [index])
+		GET_PRIVATE (item)->cell_data [index] = NULL;
+}
 
 static AtkObject*
 eti_ref_at (AtkTable *table, gint row, gint column)
 {
 	ETableItem *item;
+	AtkObject* ret;
 
 	item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table)));
 	if (!item)
@@ -242,13 +263,30 @@
 	    item->cell_views_realized) {
 		ECellView *cell_view = item->cell_views[column];
 		ETableCol *ecol = e_table_header_get_column (item->header, column);
-		return gal_a11y_e_cell_registry_get_object (NULL,
+		gpointer * cell_data;
+
+		cell_data = GET_PRIVATE (table)->cell_data;
+
+		if (cell_data[row*item->cols + column] == NULL) {
+			ret = gal_a11y_e_cell_registry_get_object (NULL,
 							    item,
 							    cell_view,
 							    ATK_OBJECT (table),
 							    ecol->col_idx,
 							    column,
 							    row);
+			cell_data[row*item->cols + column] = ret;
+			g_object_weak_ref (G_OBJECT (ret),
+					   (GWeakNotify) cell_destroyed,
+					   ret);
+
+		} else {
+			ret = (AtkObject *) cell_data[row*item->cols + column];
+			g_object_ref (ret);
+		}
+
+
+		return ret;
 	}
 
 	return NULL;
@@ -526,6 +564,101 @@
 }
 
 static void
+eti_rows_inserted (ETableModel * model, int row, int count, 
+		   AtkObject * table_item)
+{
+	gint n_cols,n_rows,i,j;
+	gint size;
+	gpointer *cell_data;
+	ETableItem *item = E_TABLE_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (table_item)));
+
+        n_cols = atk_table_get_n_columns (ATK_TABLE(table_item));
+	n_rows = atk_table_get_n_rows (ATK_TABLE(table_item));
+	
+	g_return_if_fail (n_cols > 0 && n_rows > 0);
+
+	cell_data = GET_PRIVATE(table_item)->cell_data;
+	GET_PRIVATE(table_item)->cell_data = g_realloc (cell_data, sizeof(gpointer)*(n_rows*n_cols));
+	cell_data = GET_PRIVATE(table_item)->cell_data;
+	/* Initialize new added mem to 0s. */
+	for (i = 0 ; i < count; i ++) {
+		for (j = 0 ;  j < n_cols; j ++) {
+			cell_data [(n_rows-i-1)*n_cols+j] = NULL;
+		}
+	}
+
+	for (i = row; i < (n_rows-count); i ++) {
+		for (j = 0; j < n_cols; j ++)
+			if (cell_data[i*n_cols + j] != NULL) {
+				AtkObject * a11y;
+
+				a11y = ATK_OBJECT(cell_data[i*n_cols + j]);
+				gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL(a11y), ATK_STATE_STALE, TRUE);
+				cell_data[i*n_cols + j] = NULL;
+			}
+	}
+
+        for (i = row; i < (row + count); i ++) {
+                for (j = 0; j < n_cols; j ++) {
+			g_signal_emit_by_name (table_item,
+					       "children_changed::add",
+                                               ( (i*n_cols) + j), NULL, NULL);
+		}
+        }
+
+	g_signal_emit_by_name (table_item, "visible-data-changed");
+}
+
+static void
+eti_rows_deleted (ETableModel * model, int row, int count, 
+		  AtkObject * table_item)
+{
+	gint i,j, n_rows,n_cols;
+	gpointer *cell_data;
+	ETableItem *item = E_TABLE_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (table_item)));
+
+	n_rows = atk_table_get_n_rows (ATK_TABLE(table_item));
+        n_cols = atk_table_get_n_columns (ATK_TABLE(table_item));
+
+	cell_data = GET_PRIVATE(table_item)->cell_data;
+
+	for (i = row; i < (n_rows + count); i ++) {
+		for (j = 0; j < n_cols; j ++)
+			if (cell_data[i*n_cols + j] != NULL) {
+				AtkObject * a11y;
+
+				a11y = ATK_OBJECT(cell_data[i*n_cols + j]);
+				gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL(a11y), ATK_STATE_STALE, TRUE);
+				cell_data[i*n_cols + j] = NULL;
+			}
+	}
+
+	g_signal_emit_by_name (table_item, "row-deleted", row,
+			       count, NULL);
+	g_signal_emit_by_name (table_item, "visible-data-changed");
+}
+
+static void
+eti_real_initialize (AtkObject *obj, 
+		     gpointer data)
+{
+	ETableItem * eti;
+	ETableModel * model;
+
+	ATK_OBJECT_CLASS (parent_class)->initialize (obj, data);
+	eti = E_TABLE_ITEM (data);
+
+	model = eti->table_model;
+
+	g_signal_connect (model, "model-rows-inserted",
+			  G_CALLBACK (eti_rows_inserted),
+			  obj);
+	g_signal_connect (model, "model-rows-deleted",
+			  G_CALLBACK (eti_rows_deleted),
+				obj);
+}
+
+static void
 eti_class_init (GalA11yETableItemClass *klass)
 {
 	AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass);
@@ -541,6 +674,7 @@
 	atk_object_class->get_n_children      = eti_get_n_children;
 	atk_object_class->ref_child           = eti_ref_child;
 	atk_object_class->get_index_in_parent = eti_get_index_in_parent;
+	atk_object_class->initialize	      = eti_real_initialize;
 }
 
 static void
@@ -647,6 +781,7 @@
 			   int index_in_parent)
 {
 	GalA11yETableItem *a11y;
+	int n;
 
 	a11y = g_object_new (gal_a11y_e_table_item_get_type (), NULL);
 
@@ -654,6 +789,10 @@
 
 	GET_PRIVATE (a11y)->parent = parent;
 	GET_PRIVATE (a11y)->index_in_parent = index_in_parent;
+
+	/* Initialize cell data. */
+	n = item->cols * item->rows;
+	GET_PRIVATE (a11y)->cell_data = g_malloc0(n*sizeof(gpointer));
 
 	if (item) {
 		g_signal_connect (G_OBJECT(item), "selection_model_removed",
