r18713 - gnucash/trunk/src/register/register-gnome - Bug #605802: Fix input of Japanese characters in register with SCIM, IIIMF and XIM

Christian Stimming cstim at code.gnucash.org
Tue Feb 23 15:46:41 EST 2010


Author: cstim
Date: 2010-02-23 15:46:41 -0500 (Tue, 23 Feb 2010)
New Revision: 18713
Trac: http://svn.gnucash.org/trac/changeset/18713

Modified:
   gnucash/trunk/src/register/register-gnome/gnucash-item-edit.c
   gnucash/trunk/src/register/register-gnome/gnucash-sheet.c
   gnucash/trunk/src/register/register-gnome/gnucash-sheet.h
Log:
Bug #605802: Fix input of Japanese characters in register with SCIM, IIIMF and XIM

Patch by Yasuaki Taniguchi. Revised and extended version of r18638.

The main functions are as follows:
(1) synchronization of preedit string between the register window and
sheet->entry,
(2) application to pango attributes to preedit string in the register window,
(3) include scroll offset patch (id=153514),
(4) include preedit string rollback patch (id=153518),
(5) fix formula and account cells input problem which Christian pointed out,
(6) surpress quick-fill when preedit string exists,
(7) fix Windows IME problem.
(8) Fix quick-fill problem.

Modified: gnucash/trunk/src/register/register-gnome/gnucash-item-edit.c
===================================================================
--- gnucash/trunk/src/register/register-gnome/gnucash-item-edit.c	2010-02-23 20:28:20 UTC (rev 18712)
+++ gnucash/trunk/src/register/register-gnome/gnucash-item-edit.c	2010-02-23 20:46:41 UTC (rev 18713)
@@ -184,8 +184,10 @@
         const gchar *text;
 	PangoRectangle strong_pos;
 	PangoAttribute *attr;
-	PangoAttrList *attr_list;
+        PangoAttrList *attr_list;
+        GnucashSheet *sheet;
 
+        sheet = GNUCASH_SHEET (item_edit->sheet);
         style = item_edit->style;
         table = item_edit->sheet->table;
 
@@ -233,6 +235,17 @@
 
 	info->layout = gtk_widget_create_pango_layout (GTK_WIDGET (item_edit->sheet), text);
 
+	/* IMContext attributes*/
+	if (sheet->preedit_length && sheet->preedit_attrs != NULL) {
+		PangoAttrList *tmp_attrs = pango_attr_list_new ();
+		pango_attr_list_splice (tmp_attrs, sheet->preedit_attrs,
+					g_utf8_offset_to_pointer (text, sheet->preedit_start_position) - text  ,
+					g_utf8_offset_to_pointer (text, sheet->preedit_start_position + sheet->preedit_char_length) - text);
+		pango_layout_set_attributes (info->layout, tmp_attrs);
+		pango_attr_list_unref (tmp_attrs);
+	}
+
+
 	/* Selection */
         if (start_pos != end_pos)
         {
@@ -298,6 +311,18 @@
         }
 
         gnc_item_edit_update_offset (item_edit, info);
+
+	/* Calcurate IMContext aux window position */
+	{
+		gint xoff, yoff;
+		GdkRectangle rect;
+		rect = info->cursor_rect;
+		gnome_canvas_get_scroll_offsets(GNOME_CANVAS(sheet), &xoff, &yoff);
+		rect.x += (x - xoff + item_edit->x_offset);
+		rect.y += (y - yoff);
+		gtk_im_context_set_cursor_location (sheet->im_context, &rect);
+	}
+
 }
 
 static void

Modified: gnucash/trunk/src/register/register-gnome/gnucash-sheet.c
===================================================================
--- gnucash/trunk/src/register/register-gnome/gnucash-sheet.c	2010-02-23 20:28:20 UTC (rev 18712)
+++ gnucash/trunk/src/register/register-gnome/gnucash-sheet.c	2010-02-23 20:46:41 UTC (rev 18713)
@@ -40,6 +40,7 @@
 #include "gnucash-style.h"
 #include "gnucash-header.h"
 #include "gnucash-item-edit.h"
+#include "split-register.h"
 #include "gnc-engine.h"		// For debugging, e.g. ENTER(), LEAVE()
 
 #define DEFAULT_REGISTER_HEIGHT 400
@@ -83,8 +84,20 @@
 static void gnucash_sheet_activate_cursor_cell (GnucashSheet *sheet,
                                                 gboolean changed_cells);
 static void gnucash_sheet_stop_editing (GnucashSheet *sheet);
+static void gnucash_sheet_im_context_reset (GnucashSheet *sheet);
+static void gnucash_sheet_commit_cb (GtkIMContext *context, const gchar *str,
+				     GnucashSheet *sheet);
+static void gnucash_sheet_preedit_changed_cb (GtkIMContext *context, 
+					      GnucashSheet *sheet);
+static gboolean gnucash_sheet_retrieve_surrounding_cb (GtkIMContext *context,
+						       GnucashSheet *sheet);
+static gboolean gnucash_sheet_delete_surrounding_cb (GtkIMContext *context,
+						     gint offset,
+						     gint n_chars,
+						     GnucashSheet *sheet);
+static gboolean gnucash_sheet_check_direct_update_cell(GnucashSheet *sheet,
+                                                       const VirtualLocation virt_loc);
 
-
 /** Implementation *****************************************************/
 
 void
@@ -191,15 +204,35 @@
 static void
 gnucash_sheet_stop_editing (GnucashSheet *sheet)
 {
+        /* Rollback an uncommitted string if it exists   *
+         * *before* disconnecting signal handlers.       */
+        gnucash_sheet_im_context_reset(sheet);
+
         if (sheet->insert_signal != 0)
                 g_signal_handler_disconnect (G_OBJECT(sheet->entry),
                                              sheet->insert_signal);
         if (sheet->delete_signal != 0)
                 g_signal_handler_disconnect (G_OBJECT(sheet->entry),
                                              sheet->delete_signal);
-
+        if (sheet->commit_signal != 0)
+                g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
+                                             sheet->commit_signal);
+        if (sheet->preedit_changed_signal != 0)
+                g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
+                                             sheet->preedit_changed_signal);
+	if (sheet->retrieve_surrounding_signal != 0)
+                g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
+                                             sheet->retrieve_surrounding_signal);
+	if (sheet->delete_surrounding_signal != 0)
+                g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
+                                             sheet->delete_surrounding_signal);
         sheet->insert_signal = 0;
         sheet->delete_signal = 0;
+        sheet->commit_signal = 0;
+        sheet->preedit_changed_signal = 0;
+        sheet->retrieve_surrounding_signal = 0;
+        sheet->delete_surrounding_signal = 0;
+        sheet->direct_update_cell = FALSE;
 
         gnucash_sheet_hide_editing_cursor (sheet);
 
@@ -270,11 +303,12 @@
                 gnucash_sheet_redraw_block (sheet, virt_loc.vcell_loc);
 	else
         {
+		gnucash_sheet_im_context_reset(sheet);
 		gnucash_sheet_start_editing_at_cursor (sheet);
-
                 gtk_editable_set_position (editable, cursor_pos);
-
                 gtk_editable_select_region (editable, start_sel, end_sel);
+                sheet->direct_update_cell = 
+                        gnucash_sheet_check_direct_update_cell (sheet, virt_loc);
         }
 
         gtk_widget_grab_focus (GTK_WIDGET(sheet));
@@ -657,6 +691,10 @@
         if (G_OBJECT_CLASS (sheet_parent_class)->finalize)
                 (*G_OBJECT_CLASS (sheet_parent_class)->finalize)(object);
 
+        /* Clean up IMContext and unref */
+        gnucash_sheet_im_context_reset(sheet);
+        g_object_unref (sheet->im_context);
+
 	/* This has to come after the parent destroy, so the item edit
 	   destruction can do its disconnects. */
         g_object_unref (sheet->entry);
@@ -674,6 +712,8 @@
         window = widget->window;
         gdk_window_set_back_pixmap (GTK_LAYOUT (widget)->bin_window,
 				    NULL, FALSE);
+	gtk_im_context_set_client_window( GNUCASH_SHEET (widget)->im_context,
+					  window);
 }
 
 
@@ -947,29 +987,63 @@
         {
                 retval = old_text;
 
+		/* reset IMContext if disallowed chars and clear preedit*/
+		gnucash_sheet_im_context_reset(sheet);
                 /* the entry was disallowed, so we stop the insert signal */
                 g_signal_stop_emission_by_name (G_OBJECT (sheet->entry),
                                                 "insert_text");
         }
-        if (*position < 0)
-                *position = g_utf8_strlen(retval, -1);
 
+	/* sync cursor position and selection to preedit if it exists */
+	if (sheet->preedit_length) {
+		gtk_editable_set_position (editable,
+					   sheet->preedit_start_position
+					   + sheet->preedit_cursor_position);
+	}
+	else if (*position < 0)
+		*position = g_utf8_strlen(retval, -1);
+
 #if GTK_ALLOWED_SELECTION_WITHIN_INSERT_SIGNAL
-        gtk_editable_select_region (editable, start_sel, end_sel);
-#else
-        {
-                select_info *info;
-                if (start_sel != end_sel) {
-                        info = g_malloc(sizeof(*info));
-                        info->editable = editable;
-                        info->start_sel = start_sel;
-                        info->end_sel = end_sel;
-                        g_timeout_add(/*ASAP*/ 1,
-                                (GSourceFunc)gnucash_sheet_select_data_cb,
-                                info);
-                }
-        }
-#endif
+	if (sheet->preedit_length
+	    && sheet->preedit_selection_length != 0) {
+		gtk_editable_select_region (editable,
+					    sheet->preedit_start_position 
+					    + sheet->preedit_char_length,
+					    sheet->preedit_start_position 
+					    + sheet->preedit_char_length
+					    + sheet->preedit_selection_length);
+	}
+	else
+		gtk_editable_select_region (editable, start_sel, end_sel);
+#else /* !GTK_ALLOWED_SELECTION_WITHIN_INSERT_SIGNAL */
+	if (sheet->preedit_length
+	    && sheet->preedit_selection_length != 0) {
+		select_info *info;
+		
+		info = g_malloc(sizeof(*info));
+		info->editable = editable;
+		info->start_sel = sheet->preedit_start_position
+			+ sheet->preedit_char_length;
+		info->end_sel = sheet->preedit_start_position
+			+ sheet->preedit_char_length
+			+ sheet->preedit_selection_length;
+		g_timeout_add(/*ASAP*/ 1,
+			      (GSourceFunc)gnucash_sheet_select_data_cb,
+			      info);
+		
+	} else if (start_sel != end_sel) {
+		select_info *info;
+		
+		info = g_malloc(sizeof(*info));
+		info->editable = editable;
+		info->start_sel = start_sel;
+		info->end_sel = end_sel;
+		g_timeout_add(/*ASAP*/ 1,
+			      (GSourceFunc)gnucash_sheet_select_data_cb,
+			      info);
+	}
+#endif /* GTK_ALLOWED_SELECTION_WITHIN_INSERT_SIGNAL */
+
         g_string_free (new_text_gs, TRUE);
         g_string_free (change_text_gs, TRUE);
 }
@@ -1070,10 +1144,28 @@
                                                 "delete_text");
         }
 
-        gtk_editable_set_position (editable, cursor_position);
-        if (start_sel != end_sel)
-		gtk_editable_select_region(editable, start_sel, end_sel);
 
+	/* sync cursor position and selection to preedit if it exists */
+	if (sheet->preedit_length) {
+		gtk_editable_set_position (editable,
+					   sheet->preedit_start_position
+					   + sheet->preedit_cursor_position);
+	} else {
+		gtk_editable_set_position (editable, cursor_position);
+	}
+
+	if (sheet->preedit_length
+	    && sheet->preedit_selection_length != 0) {
+		gtk_editable_select_region (editable,
+					    sheet->preedit_start_position 
+					    + sheet->preedit_char_length,
+					    sheet->preedit_start_position 
+					    + sheet->preedit_char_length
+					    + sheet->preedit_selection_length);
+	}
+	else if (start_sel != end_sel)
+		gtk_editable_select_region (editable, start_sel, end_sel);
+
         g_string_free (new_text_gs, TRUE);
 }
 
@@ -1136,7 +1228,12 @@
                         (widget, event);
 
         gnc_item_edit_focus_in (GNC_ITEM_EDIT(sheet->item_editor));
+        gtk_im_context_focus_in(sheet->im_context);
 
+#ifdef G_OS_WIN32
+        gnucash_sheet_im_context_reset(sheet);
+#endif /* G_OS_WIN32 */
+	
         return FALSE;
 }
 
@@ -1149,11 +1246,38 @@
                 (*GTK_WIDGET_CLASS (sheet_parent_class)->focus_out_event)
                         (widget, event);
 
+#ifdef G_OS_WIN32
+        gnucash_sheet_im_context_reset(sheet);
+#endif /* G_OS_WIN32 */
+
+        gtk_im_context_focus_out (sheet->im_context);
         gnc_item_edit_focus_out (GNC_ITEM_EDIT(sheet->item_editor));
-
         return FALSE;
 }
 
+static gboolean
+gnucash_sheet_check_direct_update_cell(GnucashSheet *sheet,
+				       const VirtualLocation virt_loc)
+{
+	const gchar *dupdate_list[] =
+		{ /* From src/register/ledger-core/split-register.{h.c}
+		          src/register/ledger-core/split-register-layout.c */
+			DATE_CELL,
+			DDUE_CELL,
+			NULL,
+		};
+	const gchar *cell_name;
+	int i;
+
+	cell_name = gnc_table_get_cell_name (sheet->table, virt_loc);
+	for (i=0; dupdate_list[i]; i++){
+		if (gnc_cell_name_equal (cell_name,
+					 dupdate_list[i]))
+			return TRUE;
+	}
+	return FALSE;
+}
+
 static void
 gnucash_sheet_start_editing_at_cursor (GnucashSheet *sheet)
 {
@@ -1184,8 +1308,26 @@
         sheet->delete_signal =
                 g_signal_connect(G_OBJECT(sheet->entry), "delete_text",
                                  G_CALLBACK(gnucash_sheet_delete_cb), sheet);
+
+        sheet->commit_signal = 
+                g_signal_connect (G_OBJECT (sheet->im_context), "commit",
+                                  G_CALLBACK (gnucash_sheet_commit_cb), sheet);
+        sheet->preedit_changed_signal =
+                g_signal_connect (G_OBJECT (sheet->im_context), "preedit_changed",
+                                  G_CALLBACK (gnucash_sheet_preedit_changed_cb),
+                                  sheet);
+        sheet->retrieve_surrounding_signal =
+                g_signal_connect (G_OBJECT (sheet->im_context), 
+                                  "retrieve_surrounding",
+                                  G_CALLBACK (gnucash_sheet_retrieve_surrounding_cb),
+                                  sheet);
+        sheet->delete_surrounding_signal =
+                g_signal_connect (G_OBJECT (sheet->im_context), "delete_surrounding",
+                                  G_CALLBACK (gnucash_sheet_delete_surrounding_cb),
+                                  sheet);
 }
 
+
 static gboolean
 gnucash_motion_event (GtkWidget *widget, GdkEventMotion *event)
 {
@@ -1645,7 +1787,7 @@
 }
 
 static gint
-gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
+gnucash_sheet_key_press_event_internal (GtkWidget *widget, GdkEventKey *event)
 {
         Table *table;
         GnucashSheet *sheet;
@@ -1673,7 +1815,7 @@
 
 	/* Don't process any keystrokes where a modifier key (Alt,
 	 * Meta, etc.) is being held down.  This should't include
-	 * MOD2, aka NUM LOCK. */
+         * MOD2, aka NUM LOCK. */	
 	if (event->state & (GDK_MOD1_MASK | GDK_MOD3_MASK |
 			    GDK_MOD4_MASK | GDK_MOD5_MASK))
 		pass_on = TRUE;
@@ -1771,8 +1913,17 @@
 	}
 
 	/* Forward the keystroke to the input line */
-	if (pass_on)
-		return gtk_widget_event (sheet->entry, (GdkEvent *) event);
+	if (pass_on) {
+		GValue gval = {0,};
+		gboolean result;
+		g_value_init (&gval, G_TYPE_BOOLEAN);
+		g_value_set_boolean (&gval, TRUE);
+		g_object_set_property (G_OBJECT (sheet->entry), "editable", &gval);
+		result = gtk_widget_event (sheet->entry, (GdkEvent *) event);
+		g_value_set_boolean (&gval, FALSE);
+		g_object_set_property (G_OBJECT (sheet->entry), "editable", &gval);
+		return result;
+	}
 
 	abort_move = gnc_table_traverse_update (table, cur_virt_loc,
                                                 direction, &new_virt_loc);
@@ -1787,8 +1938,238 @@
         return TRUE;
 }
 
+static gint
+gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
+{
+        GnucashSheet *sheet;
+	gint result;
 
+        g_return_val_if_fail(widget != NULL, TRUE);
+        g_return_val_if_fail(GNUCASH_IS_SHEET(widget), TRUE);
+        g_return_val_if_fail(event != NULL, TRUE);
+
+        sheet = GNUCASH_SHEET (widget);
+
+	if (gtk_im_context_filter_keypress (sheet->im_context, event)) {
+		sheet->need_im_reset = TRUE;
+		return TRUE;
+	}
+
+	return gnucash_sheet_key_press_event_internal (widget, event);
+}
+
+static gint
+gnucash_sheet_key_release_event(GtkWidget *widget, GdkEventKey *event)
+{
+	GnucashSheet *sheet;
+
+        g_return_val_if_fail(widget != NULL, TRUE);
+        g_return_val_if_fail(GNUCASH_IS_SHEET(widget), TRUE);
+        g_return_val_if_fail(event != NULL, TRUE);
+
+	sheet = GNUCASH_SHEET (widget);
+
+	if(gtk_im_context_filter_keypress (sheet->im_context, event)){
+		sheet->need_im_reset = TRUE;
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 static void
+gnucash_sheet_im_context_reset_flags(GnucashSheet *sheet)
+{
+	sheet->preedit_length = 0;
+	sheet->preedit_char_length = 0;
+	sheet->preedit_start_position = -1;
+	sheet->preedit_cursor_position = 0;
+	sheet->preedit_selection_length = 0;
+}
+
+static void
+gnucash_sheet_im_context_reset(GnucashSheet *sheet)
+{
+	if (sheet->need_im_reset) {
+		if (sheet->preedit_attrs) {
+			pango_attr_list_unref (sheet->preedit_attrs);
+			sheet->preedit_attrs = NULL;
+		}
+		gtk_im_context_reset (sheet->im_context);
+		sheet->need_im_reset = FALSE;
+	}
+	gnucash_sheet_im_context_reset_flags(sheet);
+}
+
+static void
+gnucash_sheet_commit_cb (GtkIMContext *context, const gchar *str,
+			 GnucashSheet *sheet)
+{
+        GtkEditable *editable;
+        gint tmp_pos, length, sel_start, sel_end;
+
+        g_return_if_fail(strlen(str) > 0);
+        g_return_if_fail(sheet->editing == TRUE);
+
+        editable = GTK_EDITABLE (sheet->entry);
+
+        if(strlen(str) == 1 && sheet->direct_update_cell) {
+                /* Reconstruct keyevent and direct update */
+                GdkEvent *event;
+                GdkEventKey *keyevent;
+                gboolean result;
+
+                event = gdk_event_new (GDK_KEY_PRESS);
+                keyevent = (GdkEventKey *) event;
+                keyevent->keyval = gdk_unicode_to_keyval(str[0]);
+                result = gnucash_sheet_direct_event(sheet, event);
+                gdk_event_free(event);
+
+                if (result) {
+                        gnucash_sheet_im_context_reset_flags(sheet);
+                        return;
+                }
+        }
+
+        /* delete preedit string from editable*/
+        if (sheet->preedit_length){
+                g_signal_handler_block (G_OBJECT (sheet->entry),
+                                        sheet->delete_signal);
+                gtk_editable_delete_text (editable, sheet->preedit_start_position,
+                                          sheet->preedit_start_position 
+                                          + sheet->preedit_char_length);
+                g_signal_handler_unblock (G_OBJECT (sheet->entry),
+                                          sheet->delete_signal);
+        }
+
+	if (gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end)){
+		if (sel_start != sel_end) {
+                        gtk_editable_delete_selection (editable);
+                        sheet->preedit_selection_length = 0;
+                }
+        }
+	
+        tmp_pos = (sheet->preedit_start_position == -1)?
+                gtk_editable_get_position (editable)
+                :sheet->preedit_start_position;
+        gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
+        gtk_editable_set_position (editable, tmp_pos);
+        gnucash_sheet_im_context_reset_flags(sheet);
+}
+
+static void 
+gnucash_sheet_preedit_changed_cb (GtkIMContext *context, GnucashSheet *sheet)
+{
+	gchar *preedit_string;
+	GtkEditable *editable;
+
+	g_return_if_fail(context != NULL);
+	g_return_if_fail(sheet->editing == TRUE);
+
+	editable = GTK_EDITABLE (sheet->entry);
+
+	/* save preedit start position and selection */
+	if(sheet->preedit_length == 0) {
+		int start_pos, end_pos;
+		if ( gtk_editable_get_selection_bounds (editable, &start_pos, &end_pos)) {
+			sheet->preedit_start_position = start_pos;
+			sheet->preedit_selection_length = end_pos - start_pos;
+		} else {
+			sheet->preedit_start_position = 
+				gtk_editable_get_position (editable);
+		}
+	}
+#ifdef G_OS_WIN32
+	else {/* sheet->preedit_length != 0 */
+		/* On Windows, gtk_im_context_reset() in gnucash_sheet_key_press_event()
+		 * always returns FALSE because Windows IME handles key press at the
+		 * top level window. So sheet->need_im_reset = TRUE here. */
+		sheet->need_im_reset = TRUE;
+	}
+#endif /* G_OS_WIN32 */
+
+	if (sheet->preedit_attrs)
+		pango_attr_list_unref (sheet->preedit_attrs);
+
+	gtk_im_context_get_preedit_string (sheet->im_context, &preedit_string,
+					   &sheet->preedit_attrs, &(sheet->preedit_cursor_position));
+
+	if (sheet->preedit_length){
+                g_signal_handler_block (G_OBJECT (sheet->entry),
+                                        sheet->delete_signal);
+		gtk_editable_delete_text (editable, sheet->preedit_start_position,
+					  sheet->preedit_start_position 
+					  + sheet->preedit_char_length);
+                g_signal_handler_unblock (G_OBJECT (sheet->entry),
+                                          sheet->delete_signal);
+	}
+
+	sheet->preedit_length = strlen (preedit_string);
+	sheet->preedit_char_length = g_utf8_strlen(preedit_string, -1);
+
+	if (sheet->preedit_length) {
+		int tmp_pos = sheet->preedit_start_position;
+                g_signal_handler_block (G_OBJECT (sheet->entry),
+                                        sheet->insert_signal);
+		gtk_editable_insert_text (editable, preedit_string, sheet->preedit_length,
+					  &tmp_pos);
+                g_signal_handler_unblock (G_OBJECT (sheet->entry),
+                                          sheet->insert_signal);
+
+		gtk_editable_set_position (editable, sheet->preedit_start_position 
+					   + sheet->preedit_cursor_position);
+
+		if( sheet->preedit_selection_length != 0) {
+			gtk_editable_select_region (editable,
+						    sheet->preedit_start_position
+						    + sheet->preedit_char_length,
+						    sheet->preedit_start_position
+						    + sheet->preedit_char_length
+						    + sheet->preedit_selection_length);
+		}
+	} else {
+		gnucash_sheet_im_context_reset_flags(sheet);
+	}
+
+	g_free (preedit_string);
+}
+
+static gboolean
+gnucash_sheet_retrieve_surrounding_cb (GtkIMContext *context, GnucashSheet *sheet)
+{
+	GtkEditable *editable;
+	gchar *surrounding;
+	gint   cur_pos;
+
+	editable = GTK_EDITABLE (sheet->entry);
+	surrounding = gtk_editable_get_chars (editable, 0, -1);
+	cur_pos = gtk_editable_get_position (editable);
+
+	gtk_im_context_set_surrounding (context,
+					surrounding, strlen (surrounding),
+					g_utf8_offset_to_pointer (surrounding, cur_pos) - surrounding);
+	g_free (surrounding);
+	return TRUE;
+}
+
+static gboolean
+gnucash_sheet_delete_surrounding_cb (GtkIMContext *context, gint offset,
+				     gint n_chars, GnucashSheet *sheet)
+{
+	GtkEditable *editable;
+	gint cur_pos;
+
+	editable = GTK_EDITABLE (sheet->entry);
+	cur_pos = gtk_editable_get_position (editable);
+
+	gtk_editable_delete_text (editable,
+				  cur_pos + offset,
+				  cur_pos + offset + n_chars);
+	return TRUE;
+}
+
+
+static void
 gnucash_sheet_goto_virt_loc (GnucashSheet *sheet, VirtualLocation virt_loc)
 {
         Table *table;
@@ -2237,6 +2618,11 @@
 static void
 gnucash_sheet_realize_entry (GnucashSheet *sheet, GtkWidget *entry)
 {
+	GValue gval = {0,};
+	g_value_init (&gval, G_TYPE_BOOLEAN);
+	g_value_set_boolean (&gval, FALSE);
+	g_object_set_property (G_OBJECT (entry), "editable", &gval);
+
 	gtk_widget_realize (entry);
 }
 
@@ -2368,6 +2754,7 @@
         widget_class->focus_out_event = gnucash_sheet_focus_out_event;
 
         widget_class->key_press_event = gnucash_sheet_key_press_event;
+        widget_class->key_release_event = gnucash_sheet_key_release_event;
         widget_class->button_press_event = gnucash_button_press_event;
         widget_class->button_release_event = gnucash_button_release_event;
         widget_class->motion_notify_event = gnucash_motion_event;
@@ -2412,6 +2799,21 @@
         sheet->blocks = g_table_new (sizeof (SheetBlock),
                                      gnucash_sheet_block_construct,
                                      gnucash_sheet_block_destroy, NULL);
+
+        /* setup IMContext */
+        sheet->im_context = gtk_im_multicontext_new ();
+        sheet->preedit_length = 0;
+        sheet->preedit_char_length = 0;
+        sheet->preedit_start_position = -1;
+        sheet->preedit_cursor_position = 0;
+        sheet->preedit_selection_length = 0;
+        sheet->preedit_attrs = NULL;
+        sheet->direct_update_cell = FALSE;
+        sheet->need_im_reset = FALSE;
+        sheet->commit_signal = 0;
+        sheet->preedit_changed_signal = 0;
+        sheet->retrieve_surrounding_signal = 0;
+        sheet->delete_surrounding_signal = 0;
 }
 
 

Modified: gnucash/trunk/src/register/register-gnome/gnucash-sheet.h
===================================================================
--- gnucash/trunk/src/register/register-gnome/gnucash-sheet.h	2010-02-23 20:28:20 UTC (rev 18712)
+++ gnucash/trunk/src/register/register-gnome/gnucash-sheet.h	2010-02-23 20:46:41 UTC (rev 18713)
@@ -126,6 +126,23 @@
 
 	GFunc moved_cb;
 	gpointer moved_cb_data;
+
+        /* IMContext */
+        GtkIMContext *im_context;
+        gint preedit_length; /* num of bytes */
+        gint preedit_char_length; /* num of chars in UTF-8 */
+        gint preedit_start_position; /* save preedit start position   *
+                                      * combined with selection start */
+        gint preedit_cursor_position; /* save preedit cursor position */
+        gint preedit_selection_length;
+        PangoAttrList *preedit_attrs;
+        gboolean need_im_reset;
+        gboolean direct_update_cell;
+        guint commit_signal;
+        guint preedit_changed_signal;
+        guint retrieve_surrounding_signal;
+        guint delete_surrounding_signal;
+
 } GnucashSheet;
 
 



More information about the gnucash-changes mailing list