Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gal/ChangeLog,v
retrieving revision 1.830
diff -u -r1.830 ChangeLog
--- ChangeLog	2 Dec 2003 06:14:33 -0000	1.830
+++ ChangeLog	2 Dec 2003 07:00:09 -0000
@@ -1,5 +1,21 @@
 2003-12-02  Tim Wo  <tim.wo@sun.com>
 
+	* gal/a11y/e-table/gal-a11y-e-cell-text.c: (ect_get_text),
+	(ect_get_character_at_offset), (ect_get_caret_offset),
+	(ect_get_character_count), (ect_get_n_selections),
+	(ect_get_selection), (ect_add_selection), (ect_remove_selection),
+	(ect_set_selection), (ect_set_caret_offset),
+	(ect_set_text_contents), (ect_insert_text), (ect_copy_text),
+	(ect_delete_text), (ect_cut_text), (ect_paste_text),
+	(ect_class_init): a11y implementations for ECellText.
+	* gal/e-table/e-cell-text.c: (e_cell_text_set_selection),
+	(e_cell_text_get_selection), (e_cell_text_copy_clipboard),
+	(e_cell_text_paste_clipboard), (e_cell_text_delete_selection): new
+	functions to support corresponding atk operations.
+	* gal/e-table/e-cell-text.h: some APIs added to support atk operations.
+
+2003-12-02  Tim Wo  <tim.wo@sun.com>
+
 	* gal/a11y/e-table/gal-a11y-e-cell-toggle.c:
 	(gal_a11y_e_cell_toggle_dispose): use table item to get the model.
 	(gal_a11y_e_cell_toggle_new): use table item to get the model.
Index: gal/a11y/e-table/gal-a11y-e-cell-text.c
===================================================================
RCS file: /cvs/gnome/gal/gal/a11y/e-table/gal-a11y-e-cell-text.c,v
retrieving revision 1.3
diff -u -r1.3 gal-a11y-e-cell-text.c
--- gal/a11y/e-table/gal-a11y-e-cell-text.c	21 Nov 2003 04:28:04 -0000	1.3
+++ gal/a11y/e-table/gal-a11y-e-cell-text.c	2 Dec 2003 07:00:09 -0000
@@ -19,10 +19,6 @@
 static AtkObjectClass *parent_class;
 #define PARENT_TYPE (gal_a11y_e_cell_get_type ())
 
-/* XXX: these functions are undefined */
-#define e_cell_text_get_selection(a,b,c,d,e) NULL
-#define e_cell_text_set_selection(a,b,c,d,e) FALSE
-
 /* Static functions */
 static G_CONST_RETURN gchar*
 ect_get_name (AtkObject * a11y)
@@ -39,9 +35,8 @@
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
-	char *ret_val;
-	char *full_text =
-		e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	gchar *ret_val;
+	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
 
 	if (end_offset == -1)
 		end_offset = strlen (full_text);
@@ -86,10 +81,8 @@
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 	gunichar ret_val;
-	char *full_text;
-	char *at_offset;
-
-	full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	gchar *at_offset;
+	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
 	at_offset = g_utf8_offset_to_pointer (full_text, offset);
 	ret_val = g_utf8_get_char_validated (at_offset, -1);
 	e_cell_text_free_text (ect, full_text);
@@ -114,26 +107,22 @@
 ect_get_caret_offset (AtkText *text)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	int start, end;
+	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+	gint start, end;
+
 	if (e_cell_text_get_selection (gaec->cell_view,
 				       gaec->view_col, gaec->row,
-				       &start, &end)
-	    && start == end) {
-		char *full_text;
-		int ret_val;
-		ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
-
-		full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
-		ret_val = g_utf8_pointer_to_offset (full_text, full_text + start);
+				       &start, &end)) {
+		gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+		end = g_utf8_pointer_to_offset (full_text, full_text + end);
 		e_cell_text_free_text (ect, full_text);
-
-		return ret_val;
-	} else {
-		return -1;
+		
+		return end;
 	}
+	else
+		return -1;
 }
 
-
 static AtkAttributeSet*
 ect_get_run_attributes (AtkText *text,
 			gint offset,
@@ -171,9 +160,9 @@
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
-	int ret_val;
+	gint ret_val;
 
-	char *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
 
 	ret_val = g_utf8_strlen (full_text, -1);
 	e_cell_text_free_text (ect, full_text);
@@ -196,12 +185,12 @@
 ect_get_n_selections (AtkText *text)
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
-	int selection_start, selection_end;
+	gint selection_start, selection_end;
 	if (e_cell_text_get_selection (gaec->cell_view,
 				       gaec->view_col, gaec->row,
 				       &selection_start,
-				       &selection_end) &&
-	    selection_start != selection_end)
+				       &selection_end)
+	    && selection_start != selection_end)
 		return 1;
 	return 0;
 }
@@ -215,29 +204,42 @@
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
-	int selection_start, selection_end;
-	if (selection_num == 0 &&
-	    e_cell_text_get_selection (gaec->cell_view,
-				       gaec->view_col, gaec->row,
-				       &selection_start,
-				       &selection_end) &&
-	    selection_start != selection_end) {
-		char *ret_val;
-		char *full_text =
-			e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	gchar *ret_val;
+	gint selection_start, selection_end;
 
-		ret_val = g_strndup (full_text + selection_start, selection_end - selection_start);
+	if (selection_num == 0
+	    && e_cell_text_get_selection (gaec->cell_view,
+					  gaec->view_col, gaec->row,
+					  &selection_start,
+					  &selection_end)
+	    && selection_start != selection_end) {
+		gint real_start, real_end, len;
+		gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+		len = strlen (full_text);
+		real_start = MIN (selection_start, selection_end);
+		real_end   = MAX (selection_start, selection_end);
+		real_start = MIN (MAX (0, real_start), len);
+		real_end   = MIN (MAX (0, real_end), len);
+
+		ret_val = g_strndup (full_text + real_start, real_end - real_start);
+
+		real_start = g_utf8_pointer_to_offset (full_text, full_text + real_start);
+		real_end   = g_utf8_pointer_to_offset (full_text, full_text + real_end);
 
 		if (start_offset)
-			*start_offset = g_utf8_pointer_to_offset (full_text, full_text + selection_start);
+			*start_offset = real_start;
 		if (end_offset)
-			*end_offset = g_utf8_pointer_to_offset (full_text, full_text + selection_end);
-
+			*end_offset = real_end;
 		e_cell_text_free_text (ect, full_text);
-
-		return ret_val;
+	} else {
+		if (start_offset)
+			*start_offset = 0;
+		if (end_offset)
+			*end_offset = 0;
+		ret_val = NULL;
 	}
-	return NULL;
+
+	return ret_val;
 }
 
 
@@ -248,24 +250,34 @@
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
-	int selection_start, selection_end;
-	if (e_cell_text_get_selection (gaec->cell_view,
-				       gaec->view_col, gaec->row,
-				       &selection_start,
-				       &selection_end) &&
-	    selection_start == selection_end &&
-	    start_offset != end_offset) {
-		char *full_text;
 
-		full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
-		start_offset = g_utf8_offset_to_pointer (full_text, start_offset) - full_text;
-		end_offset = g_utf8_offset_to_pointer (full_text, end_offset) - full_text;
+	if (start_offset != end_offset) {
+		gint real_start, real_end, len;
+		gchar *full_text =
+			e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+
+		len = g_utf8_strlen (full_text, -1);
+		if (end_offset == -1)
+			end_offset = len;
+
+		real_start = MIN (start_offset, end_offset);
+		real_end   = MAX (start_offset, end_offset);
+		
+		real_start = MIN (MAX (0, real_start), len);
+		real_end   = MIN (MAX (0, real_end), len);
+
+		real_start = g_utf8_offset_to_pointer (full_text, real_start) - full_text;
+		real_end   = g_utf8_offset_to_pointer (full_text, real_end) - full_text;
 		e_cell_text_free_text (ect, full_text);
 
-		return e_cell_text_set_selection (gaec->cell_view,
-						  gaec->view_col, gaec->row,
-						  start_offset, end_offset);
+		if (e_cell_text_set_selection (gaec->cell_view,
+					       gaec->view_col, gaec->row,
+					       real_start, real_end)) {
+			g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed");
+			return TRUE;
+		}
 	}
+
 	return FALSE;
 }
 
@@ -274,8 +286,24 @@
 ect_remove_selection (AtkText *text,
 		      gint selection_num)
 {
-	/* Unimplemented */
-	return FALSE;
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
+	gint selection_start, selection_end;
+
+	if (selection_num == 0
+	    && e_cell_text_get_selection (gaec->cell_view,
+					  gaec->view_col, gaec->row,
+					  &selection_start,
+					  &selection_end)
+	    && selection_start != selection_end 
+	    && e_cell_text_set_selection (gaec->cell_view,
+					  gaec->view_col, gaec->row,
+					  selection_end, selection_end)) {
+		g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed");
+		return TRUE;
+	}
+	else
+		return FALSE;
 }
 
 
@@ -285,8 +313,12 @@
 		   gint start_offset,
 		   gint end_offset)
 {
-	/* Unimplemented */
-	return FALSE;
+	if (selection_num == 0) {
+		atk_text_add_selection (text, start_offset, end_offset);
+		return TRUE;
+	}
+	else
+		return FALSE;
 }
 
 
@@ -296,10 +328,19 @@
 {
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
-	char *full_text;
+	gchar *full_text;
+	gint len;
 
 	full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+
+	len = g_utf8_strlen (full_text, -1);
+	if (offset == -1)
+		offset = len;
+	else
+		offset = MIN (MAX (0, offset), len);
+	
 	offset = g_utf8_offset_to_pointer (full_text, offset) - full_text;
+
 	e_cell_text_free_text (ect, full_text);
 
 	return e_cell_text_set_selection (gaec->cell_view,
@@ -325,6 +366,7 @@
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 
 	e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, string);
+	e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row);
 }
 
 static void
@@ -337,8 +379,8 @@
 	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
 	ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell);
 
-	char *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
-	char *result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position);
+	gchar *full_text = e_cell_text_get_text (ect, gaec->item->table_model, gaec->model_col, gaec->row);
+	gchar *result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position);
 
 	e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, result);
 
@@ -353,32 +395,46 @@
 	       gint start_pos,
 	       gint end_pos)
 {
-	/* Unimplemented */
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+	if (start_pos != end_pos
+	    && atk_text_set_selection (text, 0, start_pos, end_pos))
+		e_cell_text_copy_clipboard (gaec->cell_view,
+					    gaec->view_col, gaec->row);
 }
 
 static void
-ect_cut_text (AtkEditableText *text,
-	      gint start_pos,
-	      gint end_pos)
+ect_delete_text (AtkEditableText *text,
+		 gint start_pos,
+		 gint end_pos)
 {
-	/* Unimplemented */
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+	if (start_pos != end_pos
+	    && atk_text_set_selection (text, 0, start_pos, end_pos))
+		e_cell_text_delete_selection (gaec->cell_view,
+					      gaec->view_col, gaec->row);
 }
 
 static void
-ect_delete_text (AtkEditableText *text,
-		 gint start_pos,
-		 gint end_pos)
+ect_cut_text (AtkEditableText *text,
+	      gint start_pos,
+	      gint end_pos)
 {
-	/* Unimplemented */
+	ect_copy_text (text, start_pos, end_pos);
+	ect_delete_text (text, start_pos, end_pos);
 }
 
 static void
 ect_paste_text (AtkEditableText *text,
 		gint position)
 {
-	/* Unimplemented */
-}
+	GalA11yECell *gaec = GAL_A11Y_E_CELL (text);
+
+	e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row);
 
+	if (atk_text_set_caret_offset (text, position))
+		e_cell_text_paste_clipboard (gaec->cell_view,
+					     gaec->view_col, gaec->row);
+}
 
 static void
 ect_do_action_edit (AtkAction *action)
@@ -424,7 +480,7 @@
 static void
 ect_class_init (GalA11yECellTextClass *klass)
 {
-	AtkObjectClass *a11y      = ATK_OBJECT_CLASS (klass);
+	AtkObjectClass *a11y      = ATK_OBJECT_CLASS (klass);   
 	parent_class              = g_type_class_ref (PARENT_TYPE);
 	a11y->get_name            = ect_get_name;
 }
@@ -487,6 +543,7 @@
 
 	return type;
 }
+
 AtkObject *
 gal_a11y_e_cell_text_new (ETableItem *item,
 			  ECellView  *cell_view,
Index: gal/e-table/e-cell-text.c
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-text.c,v
retrieving revision 1.133
diff -u -r1.133 e-cell-text.c
--- gal/e-table/e-cell-text.c	3 Nov 2003 04:20:09 -0000	1.133
+++ gal/e-table/e-cell-text.c	2 Dec 2003 07:00:11 -0000
@@ -2574,3 +2574,183 @@
 	return color;
 }
 
+/**
+ * e_cell_text_set_selection:
+ * @cell_view: the given cell view
+ * @col: column of the given cell in the view
+ * @row: row of the given cell in the view
+ * @start: start offset of the selection
+ * @end: end offset of the selection
+ *
+ * Sets the selection of given text cell.
+ * If the current editing cell is not the given cell, this function
+ * will return FALSE;
+ *
+ * If success, the [start, end) part of the text will be selected.
+ *
+ * This API is most likely to be used by a11y implementations.
+ * 
+ * Returns: whether the action is successful.
+ */
+gboolean
+e_cell_text_set_selection (ECellView *cell_view,
+			   gint col,
+			   gint row,
+			   gint start,
+			   gint end)
+{
+	ECellTextView *ectv;
+	CellEdit *edit;
+	ETextEventProcessorCommand command1, command2;
+
+	ectv = (ECellTextView *)cell_view;
+	edit = ectv->edit;
+	if (!edit)
+		return FALSE;
+
+	if (edit->view_col != col || edit->row != row)
+		return FALSE;
+
+	command1.action = E_TEP_MOVE;
+	command1.position = E_TEP_VALUE;
+	command1.value = start;
+	e_cell_text_view_command (edit->tep, &command1, edit);
+
+	command2.action = E_TEP_SELECT;
+	command2.position = E_TEP_VALUE;
+	command2.value = end;
+	e_cell_text_view_command (edit->tep, &command2, edit);
+
+	return TRUE;
+}
+
+/**
+ * e_cell_text_get_selection:
+ * @cell_view: the given cell view
+ * @col: column of the given cell in the view
+ * @row: row of the given cell in the view
+ * @start: a pointer to an int value indicates the start offset of the selection
+ * @end: a pointer to an int value indicates the end offset of the selection
+ *
+ * Gets the selection of given text cell.
+ * If the current editing cell is not the given cell, this function
+ * will return FALSE;
+ *
+ * This API is most likely to be used by a11y implementations.
+ * 
+ * Returns: whether the action is successful.
+ */
+gboolean
+e_cell_text_get_selection (ECellView *cell_view,
+			   gint col,
+			   gint row,
+			   gint *start,
+			   gint *end)
+{
+	ECellTextView *ectv;
+	CellEdit *edit;
+
+	ectv = (ECellTextView *)cell_view;
+	edit = ectv->edit;
+	if (!edit)
+		return FALSE;
+
+	if (edit->view_col != col || edit->row != row)
+		return FALSE;
+
+	if (start)
+		*start = edit->selection_start;
+	if (end)
+		*end = edit->selection_end;
+	return TRUE;
+}
+
+/**
+ * e_cell_text_copy_clipboard:
+ * @cell_view: the given cell view
+ * @col: column of the given cell in the view
+ * @row: row of the given cell in the view
+ *
+ * Copys the selected text to clipboard.
+ *
+ * This API is most likely to be used by a11y implementations.
+ */
+void
+e_cell_text_copy_clipboard (ECellView *cell_view, gint col, gint row)
+{
+	ECellTextView *ectv;
+	CellEdit *edit;
+	ETextEventProcessorCommand command;
+
+	ectv = (ECellTextView *)cell_view;
+	edit = ectv->edit;
+	if (!edit)
+		return;
+
+	if (edit->view_col != col || edit->row != row)
+		return;
+
+	command.action = E_TEP_COPY;
+	command.time = GDK_CURRENT_TIME;
+	e_cell_text_view_command (edit->tep, &command, edit);
+}
+
+/**
+ * e_cell_text_paste_clipboard:
+ * @cell_view: the given cell view
+ * @col: column of the given cell in the view
+ * @row: row of the given cell in the view
+ *
+ * Pastes the text from the clipboardt.
+ *
+ * This API is most likely to be used by a11y implementations.
+ */
+void
+e_cell_text_paste_clipboard (ECellView *cell_view, gint col, gint row)
+{
+	ECellTextView *ectv;
+	CellEdit *edit;
+	ETextEventProcessorCommand command;
+
+	ectv = (ECellTextView *)cell_view;
+	edit = ectv->edit;
+	if (!edit)
+		return;
+
+	if (edit->view_col != col || edit->row != row)
+		return;
+
+	command.action = E_TEP_PASTE;
+	command.time = GDK_CURRENT_TIME;
+	e_cell_text_view_command (edit->tep, &command, edit);
+}
+
+/**
+ * e_cell_text_delete_selection:
+ * @cell_view: the given cell view
+ * @col: column of the given cell in the view
+ * @row: row of the given cell in the view
+ *
+ * Deletes the selected text of the cell.
+ *
+ * This API is most likely to be used by a11y implementations.
+ */
+void
+e_cell_text_delete_selection (ECellView *cell_view, gint col, gint row)
+{
+	ECellTextView *ectv;
+	CellEdit *edit;
+	ETextEventProcessorCommand command;
+
+	ectv = (ECellTextView *)cell_view;
+	edit = ectv->edit;
+	if (!edit)
+		return;
+
+	if (edit->view_col != col || edit->row != row)
+		return;
+
+	command.action = E_TEP_DELETE;
+	command.position = E_TEP_SELECTION;
+	e_cell_text_view_command (edit->tep, &command, edit);
+}
Index: gal/e-table/e-cell-text.h
===================================================================
RCS file: /cvs/gnome/gal/gal/e-table/e-cell-text.h,v
retrieving revision 1.31
diff -u -r1.31 e-cell-text.h
--- gal/e-table/e-cell-text.h	14 Oct 2003 18:20:17 -0000	1.31
+++ gal/e-table/e-cell-text.h	2 Dec 2003 07:00:11 -0000
@@ -101,6 +101,21 @@
 /* Sets the ETableModel value, based on the given string. */
 void	   e_cell_text_set_value (ECellText *cell, ETableModel *model, int col, int row, const char *text);
 
+/* Sets the selection of given text cell */
+gboolean e_cell_text_set_selection (ECellView *cell_view, gint col, gint row, gint start, gint end);
+
+/* Gets the selection of given text cell */
+gboolean e_cell_text_get_selection (ECellView *cell_view, gint col, gint row, gint *start, gint *end);
+
+/* Copys the selected text to the clipboard */
+void e_cell_text_copy_clipboard (ECellView *cell_view, gint col, gint row);
+
+/* Pastes the text from the clipboard */
+void e_cell_text_paste_clipboard (ECellView *cell_view, gint col, gint row);
+
+/* Deletes selected text */
+void e_cell_text_delete_selection (ECellView *cell_view, gint col, gint row);
+
 G_END_DECLS
 
 #endif /* _E_CELL_TEXT_H_ */
