Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/vte/ChangeLog,v
retrieving revision 1.454
diff -u -p -r1.454 ChangeLog
--- ChangeLog	16 Jul 2003 23:03:51 -0000	1.454
+++ ChangeLog	18 Jul 2003 10:48:10 -0000
@@ -1,3 +1,23 @@
+2003-07-18  Padraig O'Briain  <padraig.obriain@sun.com>
+	* src/vte.c, src/vteint.h:
+	Add new functions to support accessible text selection: 
+	_vte_terminal_get_selection, _vte_terminal_get_start_selection,
+	_vte_terminal_get_end_selection, _vte_terminal_select_text,
+	_vte_terminal_remove_selection
+	* vteaccess.c:
+	(xy_from_offset): Fix for offset being entire text.
+	(vte_terminal_accessibility_selectin_changed): VteTerminal's
+	selection-changed signal handler which emites text-selection-changed 
+	signal.
+	(vte_terminal_accessible_new): Remove unnecessary assignment of 
+	access->widget. Connect to VteTerminal's selection-changed signal.
+	Some minor tidy up.
+	(vte_terminal_accessible_get_n_selections) Add implementation.
+	(vte_terminal_accessible_get_selection) Add implementation.
+	(vte_terminal_accessible_add_selection) Add implementation.
+	(vte_terminal_accessible_remove_selection) Add implementation.
+	(vte_terminal_accessible_set_selection) Add implementation.
+
 2003-07-16 nalin
 	* gnome-pty-helper/configure.in: check for grantpt in libc and then
 	in libpt.  Check for openpty in libc before checking libutil.  Check for
Index: src/vte.c
===================================================================
RCS file: /cvs/gnome/vte/src/vte.c,v
retrieving revision 1.373
diff -u -p -r1.373 vte.c
--- src/vte.c	10 Jul 2003 20:32:07 -0000	1.373
+++ src/vte.c	18 Jul 2003 10:48:11 -0000
@@ -14875,3 +14875,76 @@ _vte_terminal_accessible_ref(VteTerminal
 	g_return_if_fail(VTE_IS_TERMINAL(terminal));
 	terminal->pvt->accessible_emit = TRUE;
 }
+
+char * _vte_terminal_get_selection(VteTerminal *terminal)
+{
+	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
+
+	return g_strdup (terminal->pvt->selection);
+}
+
+void _vte_terminal_get_start_selection (VteTerminal *terminal, long *x, long *y)
+{
+	struct selection_cell_coords ss;
+
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
+	ss = terminal->pvt->selection_start;
+	
+	if (x)
+		*x = ss.x;
+
+	if (y)
+		*y = ss.y;
+}
+
+void _vte_terminal_get_end_selection (VteTerminal *terminal, long *x, long *y)
+{
+	struct selection_cell_coords se;
+
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
+	se = terminal->pvt->selection_end;
+	
+	if (x)
+		*x = se.x;
+
+	if (y)
+		*y = se.y;
+}
+
+void _vte_terminal_select_text(VteTerminal *terminal, long start_x, long start_y, long end_x, long end_y, int start_offset, int end_offset)
+{
+	enum vte_selection_type selection_type;
+
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
+	if (start_offset == end_offset + 1 ||
+	    start_offset == end_offset - 1)
+		selection_type = selection_type_char;
+	else if (start_y != end_y)
+		selection_type = selection_type_line;
+	else selection_type = selection_type_word;
+
+	terminal->pvt->selection_type = selection_type;
+	terminal->pvt->has_selection = TRUE;
+	terminal->pvt->selecting_had_delta = TRUE;
+	terminal->pvt->selection_start.x = start_x;
+	terminal->pvt->selection_start.y = start_y;
+	terminal->pvt->selection_end.x = end_x;
+	terminal->pvt->selection_end.y = end_y;
+	vte_terminal_copy(terminal,
+			  GDK_SELECTION_PRIMARY);
+	vte_invalidate_cells (terminal, 
+			      0,
+			      terminal->column_count,
+			      MIN (start_y, end_y),
+			      ABS (start_y - end_y) + 1);
+
+	vte_terminal_emit_selection_changed(terminal);
+}
+
+void _vte_terminal_remove_selection(VteTerminal *terminal)
+{
+	vte_terminal_deselect_all (terminal);
+}
Index: src/vteaccess.c
===================================================================
RCS file: /cvs/gnome/vte/src/vteaccess.c,v
retrieving revision 1.42
diff -u -p -r1.42 vteaccess.c
--- src/vteaccess.c	16 Jun 2003 21:23:02 -0000	1.42
+++ src/vteaccess.c	18 Jul 2003 10:48:11 -0000
@@ -148,7 +148,7 @@ xy_from_offset (VteTerminalAccessiblePri
 		}
 	}
 	if (i == priv->snapshot_linebreaks->len) {
-		if (offset < priv->snapshot_characters->len) {
+		if (offset <= priv->snapshot_characters->len) {
 			cur_x = offset - cur_offset;
 			cur_y = i - 1;	
 		}
@@ -732,6 +732,16 @@ vte_terminal_accessible_visibility_notif
 				       visible);
 }
 
+static void
+vte_terminal_accessible_selection_changed (VteTerminal *terminal,
+					   gpointer data)
+{
+	g_return_if_fail(VTE_IS_TERMINAL_ACCESSIBLE(data));
+	g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
+	g_signal_emit_by_name (data, "text_selection_changed");
+}
+
 /**
  * vte_terminal_accessible_new:
  * @terminal: a #VteTerminal
@@ -745,6 +755,7 @@ vte_terminal_accessible_new(VteTerminal 
 {
 	GtkAccessible *access;
 	AtkObject *parent;
+	AtkObject *atk_obj;
 	GObject *object;
 
 	g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
@@ -753,14 +764,14 @@ vte_terminal_accessible_new(VteTerminal 
 	g_return_val_if_fail(GTK_IS_ACCESSIBLE(object), NULL);
 
 	access = GTK_ACCESSIBLE(object);
-	atk_object_initialize(ATK_OBJECT(access), G_OBJECT(terminal));
+	atk_obj = ATK_OBJECT (object);
+	atk_object_initialize(atk_obj, terminal);
 
-	access->widget = GTK_WIDGET(terminal);
 	_vte_terminal_accessible_ref(terminal);
 	g_object_add_weak_pointer(G_OBJECT(terminal),
 				  (gpointer*)&access->widget);
 
-	g_object_set_data(G_OBJECT(access),
+	g_object_set_data(object,
 			  VTE_TERMINAL_ACCESSIBLE_PRIVATE_DATA,
 			  vte_terminal_accessible_new_private_data());
 
@@ -781,38 +792,41 @@ vte_terminal_accessible_new(VteTerminal 
 			 object);
 	g_signal_connect(G_OBJECT(terminal), "window-title-changed",
 			 GTK_SIGNAL_FUNC(vte_terminal_accessible_title_changed),
-			 access);
+			 object);
 	g_signal_connect(G_OBJECT(terminal), "focus-in-event",
 			 GTK_SIGNAL_FUNC(vte_terminal_accessible_focus_in),
-			 access);
+			 object);
 	g_signal_connect(G_OBJECT(terminal), "focus-out-event",
 			 GTK_SIGNAL_FUNC(vte_terminal_accessible_focus_out),
-			 access);
+			 object);
 	g_signal_connect(G_OBJECT(terminal), "visibility-notify-event",
 			 GTK_SIGNAL_FUNC(vte_terminal_accessible_visibility_notify),
-			 access);
+			 object);
+	g_signal_connect(G_OBJECT(terminal), "selection-changed",
+			 GTK_SIGNAL_FUNC(vte_terminal_accessible_selection_changed),
+			 object);
 
 	if (GTK_IS_WIDGET((GTK_WIDGET(terminal))->parent)) {
 		parent = gtk_widget_get_accessible((GTK_WIDGET(terminal))->parent);
 		if (ATK_IS_OBJECT(parent)) {
-			atk_object_set_parent(ATK_OBJECT(access), parent);
+			atk_object_set_parent(atk_obj, parent);
 		}
 	}
 
-	atk_object_set_name(ATK_OBJECT(access), "Terminal");
-	atk_object_set_description(ATK_OBJECT(access),
+	atk_object_set_name(atk_obj, "Terminal");
+	atk_object_set_description(atk_obj,
 				   terminal->window_title ?
 				   terminal->window_title :
 				   "");
 
-	atk_object_notify_state_change(ATK_OBJECT(access),
+	atk_object_notify_state_change(atk_obj,
 				       ATK_STATE_FOCUSABLE, TRUE);
-	atk_object_notify_state_change(ATK_OBJECT(access),
+	atk_object_notify_state_change(atk_obj,
 				       ATK_STATE_EXPANDABLE, FALSE);
-	atk_object_notify_state_change(ATK_OBJECT(access),
+	atk_object_notify_state_change(atk_obj,
 				       ATK_STATE_RESIZABLE, TRUE);
 
-	return ATK_OBJECT(access);
+	return atk_obj;
 }
 
 static void
@@ -1374,55 +1388,126 @@ vte_terminal_accessible_get_offset_at_po
 static gint
 vte_terminal_accessible_get_n_selections(AtkText *text)
 {
-	g_return_val_if_fail(VTE_IS_TERMINAL_ACCESSIBLE(text), 0);
+	GtkWidget *widget;
+	VteTerminal *terminal;
+
+	g_return_val_if_fail(VTE_IS_TERMINAL_ACCESSIBLE(text), -1);
 	vte_terminal_accessible_update_private_data_if_needed(ATK_OBJECT(text),
 							      NULL, NULL);
-	/* FIXME? */
-	return 0;
+
+	widget = GTK_ACCESSIBLE(text)->widget;
+	if (widget == NULL)
+		/* State is defunct */
+		return -1;
+	g_return_val_if_fail (VTE_IS_TERMINAL (widget), -1);
+	terminal = VTE_TERMINAL (widget);
+	return (vte_terminal_get_has_selection (terminal)) ? 1 : 0;
 }
 
 static gchar *
 vte_terminal_accessible_get_selection(AtkText *text, gint selection_number,
 				      gint *start_offset, gint *end_offset)
 {
+	GtkWidget *widget;
+	VteTerminal *terminal;
+	VteTerminalAccessiblePrivate *priv;
+	long start_x, start_y, end_x, end_y;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL_ACCESSIBLE(text), NULL);
 	vte_terminal_accessible_update_private_data_if_needed(ATK_OBJECT(text),
 							      NULL, NULL);
-	/* FIXME? */
-	return NULL;
+	widget = GTK_ACCESSIBLE(text)->widget;
+	if (widget == NULL)
+		/* State is defunct */
+		return NULL;
+	g_return_val_if_fail (VTE_IS_TERMINAL (widget), NULL);
+	terminal = VTE_TERMINAL (widget);
+	if (!vte_terminal_get_has_selection (terminal))
+		return NULL;
+	if (selection_number != 0)
+		return NULL;
+
+	priv = g_object_get_data(G_OBJECT(text),
+				 VTE_TERMINAL_ACCESSIBLE_PRIVATE_DATA);
+	_vte_terminal_get_start_selection (terminal, &start_x, &start_y);
+	*start_offset = offset_from_xy (priv, start_x, start_y);
+	_vte_terminal_get_end_selection (terminal, &end_x, &end_y);
+	*end_offset = offset_from_xy (priv, end_x, end_y);
+	return _vte_terminal_get_selection (terminal);
 }
 
 static gboolean
 vte_terminal_accessible_add_selection(AtkText *text,
 				      gint start_offset, gint end_offset)
 {
+	GtkWidget *widget;
+	VteTerminal *terminal;
+	VteTerminalAccessiblePrivate *priv;
+	gint start_x, start_y, end_x, end_y;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL_ACCESSIBLE(text), FALSE);
 	vte_terminal_accessible_update_private_data_if_needed(ATK_OBJECT(text),
 							      NULL, NULL);
-	/* FIXME? */
-	return FALSE;
+	widget = GTK_ACCESSIBLE(text)->widget;
+	if (widget == NULL)
+		/* State is defunct */
+		return FALSE;
+	g_return_val_if_fail (VTE_IS_TERMINAL (widget), FALSE);
+	terminal = VTE_TERMINAL (widget);
+	g_return_val_if_fail (!vte_terminal_get_has_selection (terminal), FALSE);
+	priv = g_object_get_data(G_OBJECT(text),
+				 VTE_TERMINAL_ACCESSIBLE_PRIVATE_DATA);
+	xy_from_offset (priv, start_offset, &start_x, &start_y);
+	xy_from_offset (priv, end_offset, &end_x, &end_y);
+	_vte_terminal_select_text (terminal, start_x, start_y, end_x, end_y, start_offset, end_offset);
+	return TRUE;
 }
 
 static gboolean
 vte_terminal_accessible_remove_selection(AtkText *text,
 					 gint selection_number)
 {
+	GtkWidget *widget;
+	VteTerminal *terminal;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL_ACCESSIBLE(text), FALSE);
 	vte_terminal_accessible_update_private_data_if_needed(ATK_OBJECT(text),
 							      NULL, NULL);
-	/* FIXME? */
-	return FALSE;
+	widget = GTK_ACCESSIBLE(text)->widget;
+	if (widget == NULL)
+		/* State is defunct */
+		return FALSE;
+	g_return_val_if_fail (VTE_IS_TERMINAL (widget), FALSE);
+	terminal = VTE_TERMINAL (widget);
+	if (selection_number == 0 && vte_terminal_get_has_selection (terminal)) {
+		_vte_terminal_remove_selection (terminal);
+		return TRUE;
+	} else
+		return FALSE;
 }
 
 static gboolean
 vte_terminal_accessible_set_selection(AtkText *text, gint selection_number,
 				      gint start_offset, gint end_offset)
 {
+	GtkWidget *widget;
+	VteTerminal *terminal;
+
 	g_return_val_if_fail(VTE_IS_TERMINAL_ACCESSIBLE(text), FALSE);
 	vte_terminal_accessible_update_private_data_if_needed(ATK_OBJECT(text),
 							      NULL, NULL);
-	/* FIXME? */
-	return FALSE;
+	widget = GTK_ACCESSIBLE(text)->widget;
+	if (widget == NULL)
+		/* State is defunct */
+		return FALSE;
+	g_return_val_if_fail (VTE_IS_TERMINAL (widget), FALSE);
+	terminal = VTE_TERMINAL (widget);
+	if (selection_number != 0)
+		return FALSE;
+	if (vte_terminal_get_has_selection (terminal))
+		_vte_terminal_remove_selection (terminal);
+
+	return vte_terminal_accessible_add_selection (text, start_offset, end_offset);
 }
 
 static gboolean
Index: src/vteint.h
===================================================================
RCS file: /cvs/gnome/vte/src/vteint.h,v
retrieving revision 1.1
diff -u -p -r1.1 vteint.h
--- src/vteint.h	16 Jun 2003 21:16:33 -0000	1.1
+++ src/vteint.h	18 Jul 2003 10:48:11 -0000
@@ -26,6 +26,11 @@
 G_BEGIN_DECLS
 
 void _vte_terminal_accessible_ref(VteTerminal *terminal);
+char* _vte_terminal_get_selection(VteTerminal *terminal);
+void _vte_terminal_get_start_selection(VteTerminal *terminal, long *x, long *y);
+void _vte_terminal_get_end_selection(VteTerminal *terminal, long *x, long *y);
+void _vte_terminal_select_text(VteTerminal *terminal, long start_x, long start_y, long end_x, long end_y, int start_offset, int end_offset);
+void _vte_terminal_remove_selection(VteTerminal *terminal);
 
 G_END_DECLS
 
