According to Owen's suggestion, this patch (against 2004-05-03 cvs snapshot)
adds a new signal to GtkEntry for handling the Backspace key, so that the
deletion is done properly according to backspace_deltes_character Pango
attribute. Normalization is also concerned.

Theppitak Karoonboonyanan.

Index: gtk/gtkentry.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
retrieving revision 1.247
diff -u -r1.247 gtkentry.c
--- gtk/gtkentry.c	21 Apr 2004 22:08:08 -0000	1.247
+++ gtk/gtkentry.c	3 May 2004 09:26:17 -0000
@@ -81,6 +81,7 @@
   MOVE_CURSOR,
   INSERT_AT_CURSOR,
   DELETE_FROM_CURSOR,
+  BACKSPACE,
   CUT_CLIPBOARD,
   COPY_CLIPBOARD,
   PASTE_CLIPBOARD,
@@ -242,6 +243,7 @@
 static void gtk_entry_delete_from_cursor (GtkEntry        *entry,
 					  GtkDeleteType    type,
 					  gint             count);
+static void gtk_entry_backspace          (GtkEntry        *entry);
 static void gtk_entry_cut_clipboard      (GtkEntry        *entry);
 static void gtk_entry_copy_clipboard     (GtkEntry        *entry);
 static void gtk_entry_paste_clipboard    (GtkEntry        *entry);
@@ -445,6 +447,7 @@
   class->move_cursor = gtk_entry_move_cursor;
   class->insert_at_cursor = gtk_entry_insert_at_cursor;
   class->delete_from_cursor = gtk_entry_delete_from_cursor;
+  class->backspace = gtk_entry_backspace;
   class->cut_clipboard = gtk_entry_cut_clipboard;
   class->copy_clipboard = gtk_entry_copy_clipboard;
   class->paste_clipboard = gtk_entry_paste_clipboard;
@@ -612,6 +615,15 @@
 		  GTK_TYPE_DELETE_TYPE,
 		  G_TYPE_INT);
 
+  signals[BACKSPACE] =
+    g_signal_new ("backspace",
+		  G_OBJECT_CLASS_TYPE (gobject_class),
+		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		  G_STRUCT_OFFSET (GtkEntryClass, backspace),
+		  NULL, NULL,
+		  _gtk_marshal_VOID__VOID,
+		  G_TYPE_NONE, 0);
+
   signals[CUT_CLIPBOARD] =
     g_signal_new ("cut_clipboard",
 		  G_OBJECT_CLASS_TYPE (gobject_class),
@@ -736,15 +748,11 @@
 				G_TYPE_INT, 1);
   
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
-				"delete_from_cursor", 2,
-				G_TYPE_ENUM, GTK_DELETE_CHARS,
-				G_TYPE_INT, -1);
+				"backspace", 0);
 
   /* Make this do the same as Backspace, to help with mis-typing */
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_SHIFT_MASK,
-                                "delete_from_cursor", 2,
-                                G_TYPE_ENUM, GTK_DELETE_CHARS,
-                                G_TYPE_INT, -1);
+				"backspace", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
 				"delete_from_cursor", 2,
@@ -2327,6 +2335,72 @@
       break;
     }
   
+  gtk_entry_pend_cursor_blink (entry);
+}
+
+static void
+gtk_entry_backspace (GtkEntry *entry)
+{
+  GtkEditable *editable = GTK_EDITABLE (entry);
+  gint prev_pos;
+
+  gtk_entry_reset_im_context (entry);
+
+  if (!entry->editable || !entry->visible || !entry->text)
+    return;
+
+  if (entry->selection_bound != entry->current_pos)
+    {
+      gtk_editable_delete_selection (editable);
+      return;
+    }
+
+  prev_pos = gtk_entry_move_logically(entry, entry->current_pos, -1);
+
+  if (prev_pos < entry->current_pos)
+    {
+      PangoLayout *layout = gtk_entry_ensure_layout (entry, FALSE);
+      PangoLogAttr *log_attrs;
+      gint n_attrs;
+
+      pango_layout_get_log_attrs (layout, &log_attrs, &n_attrs);
+
+      if (log_attrs[prev_pos].backspace_deletes_character)
+	{
+	  gchar *cluster_text;
+	  gchar *normalized_text;
+          glong  len;
+
+	  cluster_text = gtk_editable_get_chars (editable,
+			  			 prev_pos,
+						 entry->current_pos);
+	  normalized_text = g_utf8_normalize (cluster_text,
+			  		      strlen (cluster_text),
+					      G_NORMALIZE_NFD);
+          len = g_utf8_strlen (normalized_text, -1);
+
+          gtk_editable_delete_text (editable, prev_pos, entry->current_pos);
+	  if (len > 1)
+	    {
+	      gint pos = entry->current_pos;
+
+	      gtk_editable_insert_text (editable, normalized_text,
+					g_utf8_offset_to_pointer (normalized_text, len - 1) - normalized_text,
+					&pos);
+	      gtk_editable_set_position (editable, pos);
+	    }
+
+	  g_free (normalized_text);
+	  g_free (cluster_text);
+	}
+      else
+	{
+          gtk_editable_delete_text (editable, prev_pos, entry->current_pos);
+	}
+      
+      g_free (log_attrs);
+    }
+
   gtk_entry_pend_cursor_blink (entry);
 }
 
Index: gtk/gtkentry.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkentry.h,v
retrieving revision 1.60
diff -u -r1.60 gtkentry.h
--- gtk/gtkentry.h	1 Mar 2004 16:07:45 -0000	1.60
+++ gtk/gtkentry.h	3 May 2004 09:26:18 -0000
@@ -137,6 +137,7 @@
   void (* delete_from_cursor) (GtkEntry       *entry,
 			       GtkDeleteType   type,
 			       gint            count);
+  void (* backspace)          (GtkEntry       *entry);
   void (* cut_clipboard)      (GtkEntry       *entry);
   void (* copy_clipboard)     (GtkEntry       *entry);
   void (* paste_clipboard)    (GtkEntry       *entry);
