[evolution-patches] patch to implement editable text interface



Hi Radek,

The patch is tested with GOK, please review.

After the patch, I can select a paragraph of text in mail composer, and
copy, cut and paste using GOK's text manipulation interface.

The editable-text.patch implemented insert_text, copy_text, cut_text,
delete_text and paste_text method.

Note that at end of paste_text and cut_text method, there is a
grab_focus signal emitted. This is because after these operations, html
object tree changed, and the focused html object may also changed. Thus
we need to use atk_focus_notify API to notify AT app.

And the htmlobject.patch and a new datalist to html object. The data
list different from orginal one in that it will not be copied when you
dup a htmlobject. See the copy() in htmlobject.c, 

    static void
    copy (HTMLObject *self, HTMLObject *dest)
    {
	... ...
        g_datalist_init (&dest->object_data);
	html_object_copy_data_from_object (dest, self);
	... ...
    }

This will cause html object associated to a wrong acc object in
composer. So in the utils.[ch], change to use the new datalist instead
of the old one.

Another change in utils.c is add a acc_unref(). By setting it to the
destroy function of the new datalist, acc_unref will called when the
htmlobject is destroyed, we need to break the htmlobject<->acc
association.


Regards
York
Index: text.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/a11y/text.c,v
retrieving revision 1.4
diff -u -r1.4 text.c
--- text.c	6 Aug 2003 10:47:16 -0000	1.4
+++ text.c	21 Aug 2003 05:39:22 -0000
@@ -62,6 +62,32 @@
 static gint html_a11y_text_get_caret_offset (AtkText *text);
 static gboolean html_a11y_text_set_caret_offset (AtkText *text, gint offset);
 
+/* Editable text interface. */
+static void 	atk_editable_text_interface_init      (AtkEditableTextIface *iface);
+static void	html_a11y_text_set_text_contents	(AtkEditableText      *text,
+							 const gchar          *string);
+static void	html_a11y_text_insert_text	(AtkEditableText      *text,
+						 const gchar          *string,
+						 gint                 length,
+						 gint                 *position);
+static void	html_a11y_text_copy_text	(AtkEditableText      *text,
+						 gint                 start_pos,
+						 gint                 end_pos);
+static void	html_a11y_text_cut_text		(AtkEditableText      *text,
+						 gint                 start_pos,
+						 gint                 end_pos);
+static void	html_a11y_text_delete_text	(AtkEditableText      *text,
+						 gint                 start_pos,
+						 gint                 end_pos);
+static void	html_a11y_text_paste_text	(AtkEditableText      *text,
+						 gint                 position);
+static void	html_a11y_text_paste_received	(GtkClipboard *clipboard,
+						 const gchar  *text,
+						 gpointer     data);
+
+static AtkStateSet* html_a11y_text_ref_state_set	(AtkObject	*accessible);
+
+
 static AtkObjectClass *parent_class = NULL;
 
 GType
@@ -95,9 +121,17 @@
 			NULL
 		};
 
+		static const GInterfaceInfo atk_editable_text_info =
+		{
+			(GInterfaceInitFunc) atk_editable_text_interface_init,
+			(GInterfaceFinalizeFunc) NULL,
+			NULL
+		};
+
 		type = g_type_register_static (G_TYPE_HTML_A11Y, "HTMLA11YText", &tinfo, 0);
 		g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info);
 		g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info);
+		g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info);
 	}
 
 	return type;
@@ -127,6 +161,7 @@
 	iface->get_selection = html_a11y_text_get_selection;
 	iface->remove_selection = html_a11y_text_remove_selection;
 	iface->set_selection = html_a11y_text_set_selection;
+	iface->add_selection = html_a11y_text_add_selection;
 	iface->get_caret_offset = html_a11y_text_get_caret_offset;
 	iface->set_caret_offset = html_a11y_text_set_caret_offset;
 }
@@ -167,6 +202,7 @@
 	parent_class = g_type_class_peek_parent (klass);
 
 	atk_class->initialize = html_a11y_text_initialize;
+	atk_class->ref_state_set = html_a11y_text_ref_state_set;
 	gobject_class->finalize = html_a11y_text_finalize;
 }
 
@@ -195,6 +231,28 @@
 	return accessible;
 }
 
+/* atkobject.h */
+
+static AtkStateSet*
+html_a11y_text_ref_state_set (AtkObject *accessible)
+{
+	AtkStateSet *state_set;
+	GtkHTML * html;
+
+	state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible);
+	html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(accessible)));
+	if (!html || !html->engine)
+		return state_set;
+
+	if (html_engine_get_editable(html->engine))
+		atk_state_set_add_state (state_set, ATK_STATE_EDITABLE);
+
+	atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
+	atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
+
+	return state_set;
+}
+
 /*
  * AtkComponent interface
  */
@@ -276,6 +334,7 @@
 	g_return_val_if_fail(p && HTML_IS_TEXT(p), 0);
 
 	html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+
 	g_return_val_if_fail(html && GTK_IS_HTML(html) && html->engine, 0);
 
 	e = html_engine_get_top_html_engine(html->engine);
@@ -426,3 +485,156 @@
                                                    gint             offset);
 
 */
+
+ 
+static void
+atk_editable_text_interface_init (AtkEditableTextIface *iface)
+{
+	g_return_if_fail (iface != NULL);
+
+	iface->set_text_contents = html_a11y_text_set_text_contents;
+	iface->insert_text = html_a11y_text_insert_text;
+	iface->copy_text = html_a11y_text_copy_text;
+	iface->cut_text = html_a11y_text_cut_text;
+	iface->delete_text = html_a11y_text_delete_text;
+	iface->paste_text = html_a11y_text_paste_text;
+	iface->set_run_attributes = NULL;
+}
+
+static void
+html_a11y_text_set_text_contents (AtkEditableText *text,
+				  const gchar     *string)
+{
+	GtkHTML * html;
+	HTMLText *t;
+
+	/* fprintf(stderr, "atk set text contents called \n");*/
+	g_return_if_fail(string);
+
+        html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+	g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+	t = HTML_TEXT(HTML_A11Y_HTML(text));
+	g_return_if_fail (t);
+
+	html_engine_freeze (html->engine);
+	html_text_set_text (t, string);
+	html_engine_thaw (html->engine);
+}
+
+static void
+html_a11y_text_insert_text (AtkEditableText *text,
+			    const gchar     *string,
+			    gint            length,
+			    gint            *position)
+{
+	GtkHTML * html;
+	HTMLText *t;
+	gint index;
+
+	/* fprintf(stderr, "atk insert text called \n"); */
+
+	g_return_if_fail(string && (length > 0));
+	t = HTML_TEXT(HTML_A11Y_HTML(text));
+	g_return_if_fail (t);
+
+        html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+	g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+	html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), *position);
+	html_engine_paste_text(html->engine, string, -1);
+}
+
+static void
+html_a11y_text_copy_text	(AtkEditableText *text,
+				 gint            start_pos,
+				 gint            end_pos)
+{
+	GtkHTML * html;
+	gchar * str;
+	HTMLText *t;
+	gint start_index, end_index;
+
+	/* fprintf(stderr, "atk copy text called \n"); */
+        html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+	g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+	t = HTML_TEXT(HTML_A11Y_HTML(text));
+	g_return_if_fail (t);
+
+        html_engine_hide_cursor (html->engine);
+	html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), start_pos);
+	html_engine_set_mark(html->engine);
+	html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), end_pos);
+	html_engine_update_selection_if_necessary (html->engine);
+
+	html_engine_copy(html->engine);
+        html_engine_show_cursor (html->engine);
+}
+
+static void
+html_a11y_text_cut_text (AtkEditableText *text,
+			 gint            start_pos,
+			 gint            end_pos)
+{
+	GtkHTML * html;
+	HTMLText *t;
+	gint start_index, end_index;
+	gchar * str;
+
+	/* fprintf(stderr, "atk cut text called.\n"); */
+        html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+	g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+	t = HTML_TEXT(HTML_A11Y_HTML(text));
+	g_return_if_fail (t);
+
+        html_engine_hide_cursor (html->engine);
+	html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), start_pos);
+	html_engine_set_mark(html->engine);
+	html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), end_pos);
+	html_engine_update_selection_if_necessary (html->engine);
+	html_engine_cut(html->engine);
+	html_engine_show_cursor (html->engine); 
+
+        g_signal_emit_by_name(html, "grab_focus");
+}
+
+static void
+html_a11y_text_delete_text	(AtkEditableText *text,
+		  	 gint            start_pos,
+			 gint            end_pos)
+{
+	GtkHTML * html;
+	HTMLText *t;
+	gint start_index, end_index;
+	gchar * str;
+
+	/* fprintf(stderr, "atk delete text called.\n"); */
+        html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+	g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+	t = HTML_TEXT(HTML_A11Y_HTML(text));
+	g_return_if_fail (t);
+
+	html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), start_pos);
+	html_engine_delete_n(html->engine, end_pos-start_pos, TRUE);
+        g_signal_emit_by_name(html, "grab_focus");
+}
+
+static void
+html_a11y_text_paste_text	(AtkEditableText *text,
+			 	 gint            position)
+{
+	GtkHTML * html;
+	HTMLText *t;
+
+	/* fprintf(stderr, "atk paste text called.\n"); */
+
+        html = GTK_HTML_A11Y_GTKHTML(html_a11y_get_gtkhtml_parent(HTML_A11Y(text)));
+	g_return_if_fail(html && html->engine && html_engine_get_editable(html->engine));
+	t = HTML_TEXT(HTML_A11Y_HTML(text));
+	g_return_if_fail (t);
+
+        html_engine_show_cursor (html->engine);
+	html_cursor_jump_to(html->engine->cursor, html->engine, HTML_OBJECT(t), position);
+	html_engine_paste(html->engine);
+        html_engine_show_cursor (html->engine);
+
+        g_signal_emit_by_name(html, "grab_focus");
+}
Index: utils.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/a11y/utils.c,v
retrieving revision 1.4
diff -u -r1.4 utils.c
--- utils.c	6 Aug 2003 10:47:16 -0000	1.4
+++ utils.c	21 Aug 2003 05:39:22 -0000
@@ -85,6 +85,13 @@
 	return accessible;
 }
 
+static void
+acc_unref(gpointer data)
+{
+	g_object_set_data(G_OBJECT(data), HTML_ID, NULL);
+	g_object_unref(G_OBJECT(data));
+}
+
 AtkObject *
 html_utils_get_accessible (HTMLObject *o, AtkObject *parent)
 {
@@ -92,13 +99,13 @@
 
 	g_return_val_if_fail(o != NULL, NULL);
 
-	accessible = html_object_get_data (o, ACCESSIBLE_ID);
+	accessible = html_object_get_data_nocp (o, ACCESSIBLE_ID);
 
 	if (!accessible) {
 		accessible = create_accessible (o, parent);
 		if (accessible) {
 			g_object_ref (accessible);
-			html_object_set_data_full (o, ACCESSIBLE_ID, accessible, g_object_unref);
+			html_object_set_data_full_nocp (o, ACCESSIBLE_ID, accessible, acc_unref);
 		}
 	}
 
Index: utils.h
===================================================================
RCS file: /cvs/gnome/gtkhtml/a11y/utils.h,v
retrieving revision 1.2
diff -u -r1.2 utils.h
--- utils.h	1 Nov 2002 15:34:27 -0000	1.2
+++ utils.h	21 Aug 2003 05:39:22 -0000
@@ -28,7 +28,7 @@
 #include "htmlobject.h"
 
 #define ACCESSIBLE_ID "atk-accessible-object"
-#define HTML_OBJECT_ACCESSIBLE(o) ATK_OBJECT (html_object_get_data (HTML_OBJECT (o), ACCESSIBLE_ID))
+#define HTML_OBJECT_ACCESSIBLE(o) ATK_OBJECT (html_object_get_data_nocp (HTML_OBJECT (o), ACCESSIBLE_ID))
 
 AtkObject *html_utils_get_accessible (HTMLObject *o, AtkObject *parent);
 
Index: htmlobject.c
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmlobject.c,v
retrieving revision 1.164
diff -u -r1.164 htmlobject.c
--- htmlobject.c	1 Aug 2003 08:43:56 -0000	1.164
+++ htmlobject.c	21 Aug 2003 06:17:00 -0000
@@ -64,7 +64,9 @@
 	self->next = NULL;
 	self->prev = NULL;
 #endif
+
 	g_datalist_clear (&self->object_data);
+	g_datalist_clear (&self->object_data_nocp);
 	
 	if (self->redraw_pending) {
 		self->free_pending = TRUE;
@@ -98,6 +100,8 @@
 
 	g_datalist_init (&dest->object_data);
 	html_object_copy_data_from_object (dest, self);
+
+	g_datalist_init (&dest->object_data_nocp);
 }
 
 static HTMLObject *
@@ -677,6 +681,7 @@
 	o->draw_focused = FALSE;
 
 	g_datalist_init (&o->object_data);
+	g_datalist_init (&o->object_data_nocp);
 }
 
 HTMLObject *
@@ -1571,6 +1576,24 @@
 html_object_get_index (HTMLObject *self, guint offset)
 {
 	return html_object_is_text (self) ? html_text_get_index (HTML_TEXT (self), offset) : offset;
+}
+
+void
+html_object_set_data_nocp (HTMLObject *object, const gchar *key, const gchar *value)
+{
+	g_datalist_set_data_full (&object->object_data_nocp, key, g_strdup (value), g_free);
+}
+
+void
+html_object_set_data_full_nocp (HTMLObject *object, const gchar *key, const gpointer value, GDestroyNotify func)
+{
+	g_datalist_set_data_full (&object->object_data_nocp, key, value, func);
+}
+
+gpointer
+html_object_get_data_nocp (HTMLObject *object, const gchar *key)
+{
+	return g_datalist_get_data (&object->object_data_nocp, key);
 }
 
 void
Index: htmlobject.h
===================================================================
RCS file: /cvs/gnome/gtkhtml/src/htmlobject.h,v
retrieving revision 1.124
diff -u -r1.124 htmlobject.h
--- htmlobject.h	23 Jul 2003 17:35:22 -0000	1.124
+++ htmlobject.h	21 Aug 2003 06:17:01 -0000
@@ -71,6 +71,7 @@
 	guint draw_focused : 1; 
 
 	GData *object_data;
+	GData *object_data_nocp;
 };
 
 struct _HTMLObjectClearRectangle {
@@ -518,6 +519,18 @@
 					      HTMLObject          *src);
 gboolean  html_object_save_data              (HTMLObject          *self,
 					      HTMLEngineSaveState *state);
+
+/* for acc object */
+void      html_object_set_data_nocp          (HTMLObject          *object,
+					      const gchar         *key,
+					      const gchar         *value);
+void      html_object_set_data_full_nocp     (HTMLObject          *object,
+					      const gchar         *key,
+					      const gpointer       value,
+					      GDestroyNotify       func);
+gpointer  html_object_get_data_nocp          (HTMLObject          *object,
+					      const gchar         *key);
+
 /*
  * editing
 */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]