]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktextview.c
Deprecate widget flag: GTK_WIDGET_VISIBLE
[~andy/gtk] / gtk / gtktextview.c
index 5f18ec01ea6c028bf6989e0c65f6c156d31d7c5e..589e8af8592697bfefe988b63afeeae626211f97 100644 (file)
@@ -25,7 +25,7 @@
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
-#include <config.h>
+#include "config.h"
 #include <string.h>
 
 #define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
@@ -108,6 +108,7 @@ struct _GtkTextViewPrivate
 {
   guint blink_time;  /* time in msec the cursor has blinked since last user event */
   guint im_spot_idle;
+  gchar *im_module;
 };
 
 
@@ -137,6 +138,7 @@ enum
   MOVE_VIEWPORT,
   SELECT_ALL,
   TOGGLE_CURSOR_VISIBLE,
+  PREEDIT_CHANGED,
   LAST_SIGNAL
 };
 
@@ -157,7 +159,7 @@ enum
   PROP_BUFFER,
   PROP_OVERWRITE,
   PROP_ACCEPTS_TAB,
-  LAST_PROP
+  PROP_IM_MODULE
 };
 
 static void gtk_text_view_destroy              (GtkObject        *object);
@@ -330,9 +332,13 @@ static void gtk_text_view_mark_set_handler       (GtkTextBuffer     *buffer,
 static void gtk_text_view_target_list_notify     (GtkTextBuffer     *buffer,
                                                   const GParamSpec  *pspec,
                                                   gpointer           data);
+static void gtk_text_view_paste_done_handler     (GtkTextBuffer     *buffer,
+                                                  GtkClipboard      *clipboard,
+                                                  gpointer           data);
 static void gtk_text_view_get_cursor_location    (GtkTextView       *text_view,
                                                  GdkRectangle      *pos);
 static void gtk_text_view_get_virtual_cursor_pos (GtkTextView       *text_view,
+                                                  GtkTextIter       *cursor,
                                                   gint              *x,
                                                   gint              *y);
 static void gtk_text_view_set_virtual_cursor_pos (GtkTextView       *text_view,
@@ -345,6 +351,7 @@ static GtkAdjustment* get_vadjustment            (GtkTextView       *text_view);
 static void gtk_text_view_do_popup               (GtkTextView       *text_view,
                                                  GdkEventButton    *event);
 
+static void cancel_pending_scroll                (GtkTextView   *text_view);
 static void gtk_text_view_queue_scroll           (GtkTextView   *text_view,
                                                   GtkTextMark   *mark,
                                                   gdouble        within_margin,
@@ -444,14 +451,14 @@ add_move_binding (GtkBindingSet  *binding_set,
   g_assert ((modmask & GDK_SHIFT_MASK) == 0);
 
   gtk_binding_entry_add_signal (binding_set, keyval, modmask,
-                                "move_cursor", 3,
+                                "move-cursor", 3,
                                 G_TYPE_ENUM, step,
                                 G_TYPE_INT, count,
                                 G_TYPE_BOOLEAN, FALSE);
 
   /* Selection-extending version */
   gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
-                                "move_cursor", 3,
+                                "move-cursor", 3,
                                 G_TYPE_ENUM, step,
                                 G_TYPE_INT, count,
                                 G_TYPE_BOOLEAN, TRUE);
@@ -493,14 +500,12 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
   widget_class->expose_event = gtk_text_view_expose_event;
   widget_class->focus = gtk_text_view_focus;
 
-  /* need to override the base class function via override_class_closure,
+  /* need to override the base class function via override_class_handler,
    * because the signal slot is not available in GtkWidgetCLass
    */
-  g_signal_override_class_closure (g_signal_lookup ("move-focus",
-                                                    GTK_TYPE_WIDGET),
+  g_signal_override_class_handler ("move-focus",
                                    GTK_TYPE_TEXT_VIEW,
-                                   g_cclosure_new (G_CALLBACK (gtk_text_view_move_focus),
-                                                   NULL, NULL));
+                                   G_CALLBACK (gtk_text_view_move_focus));
 
   widget_class->drag_begin = gtk_text_view_drag_begin;
   widget_class->drag_end = gtk_text_view_drag_end;
@@ -661,6 +666,26 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
                                                         TRUE,
                                                         GTK_PARAM_READWRITE));
 
+   /**
+    * GtkTextView:im-module:
+    *
+    * Which IM (input method) module should be used for this entry. 
+    * See #GtkIMContext.
+    *
+    * Setting this to a non-%NULL value overrides the
+    * system-wide IM module setting. See the GtkSettings 
+    * #GtkSettings:gtk-im-module property.
+    *
+    * Since: 2.16
+    */
+   g_object_class_install_property (gobject_class,
+                                    PROP_IM_MODULE,
+                                    g_param_spec_string ("im-module",
+                                                         P_("IM module"),
+                                                         P_("Which IM module should be used"),
+                                                         NULL,
+                                                         GTK_PARAM_READWRITE));
+
   /*
    * Style properties
    */
@@ -689,7 +714,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * the viewport to be moved instead.
    *
    * Applications should not connect to it, but may emit it with 
-   * g_signal_emit_by_name() if they need to control scrolling 
+   * g_signal_emit_by_name() if they need to control the cursor
    * programmatically.
    *
    * The default bindings for this signal come in two variants,
@@ -705,7 +730,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * </itemizedlist>
    */
   signals[MOVE_CURSOR] = 
-    g_signal_new (I_("move_cursor"),
+    g_signal_new (I_("move-cursor"),
                  G_OBJECT_CLASS_TYPE (gobject_class), 
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 
                  G_STRUCT_OFFSET (GtkTextViewClass, move_cursor),
@@ -732,7 +757,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * granularity.
    */
   signals[PAGE_HORIZONTALLY] =
-    g_signal_new (I_("page_horizontally"),
+    g_signal_new (I_("page-horizontally"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, page_horizontally),
@@ -757,18 +782,30 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * There are no default bindings for this signal.
    */
   signals[MOVE_VIEWPORT] =
-    _gtk_binding_signal_new (I_("move_viewport"),
-                            G_OBJECT_CLASS_TYPE (gobject_class),
-                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-                            G_CALLBACK (gtk_text_view_move_viewport),
-                            NULL, NULL,
-                            _gtk_marshal_VOID__ENUM_INT,
-                            G_TYPE_NONE, 2,
-                            GTK_TYPE_SCROLL_STEP,
-                            G_TYPE_INT);
+    g_signal_new_class_handler (I_("move-viewport"),
+                                G_OBJECT_CLASS_TYPE (gobject_class),
+                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                G_CALLBACK (gtk_text_view_move_viewport),
+                                NULL, NULL,
+                                _gtk_marshal_VOID__ENUM_INT,
+                                G_TYPE_NONE, 2,
+                                GTK_TYPE_SCROLL_STEP,
+                                G_TYPE_INT);
 
+  /**
+   * GtkTextView::set-anchor:
+   * @text_view: the object which received the signal
+   *
+   * The ::set-anchor signal is a
+   * <link linkend="keybinding-signals">keybinding signal</link>
+   * which gets emitted when the user initiates setting the "anchor" 
+   * mark. The "anchor" mark gets placed at the same position as the
+   * "insert" mark.
+   *
+   * This signal has no default bindings.
+   */   
   signals[SET_ANCHOR] =
-    g_signal_new (I_("set_anchor"),
+    g_signal_new (I_("set-anchor"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, set_anchor),
@@ -776,8 +813,20 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
                  _gtk_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
 
+  /**
+   * GtkTextView::insert-at-cursor:
+   * @text_view: the object which received the signal
+   * @string: the string to insert
+   *
+   * The ::insert-at-cursor signal is a
+   * <link linkend="keybinding-signals">keybinding signal</link>
+   * which gets emitted when the user initiates the insertion of a 
+   * fixed string at the cursor.
+   *
+   * This signal has no default bindings.
+   */
   signals[INSERT_AT_CURSOR] =
-    g_signal_new (I_("insert_at_cursor"),
+    g_signal_new (I_("insert-at-cursor"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, insert_at_cursor),
@@ -806,7 +855,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * backwords.
    */
   signals[DELETE_FROM_CURSOR] =
-    g_signal_new (I_("delete_from_cursor"),
+    g_signal_new (I_("delete-from-cursor"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, delete_from_cursor),
@@ -848,7 +897,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * Ctrl-x and Shift-Delete.
    */
   signals[CUT_CLIPBOARD] =
-    g_signal_new (I_("cut_clipboard"),
+    g_signal_new (I_("cut-clipboard"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, cut_clipboard),
@@ -868,7 +917,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * Ctrl-c and Ctrl-Insert.
    */
   signals[COPY_CLIPBOARD] =
-    g_signal_new (I_("copy_clipboard"),
+    g_signal_new (I_("copy-clipboard"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, copy_clipboard),
@@ -889,7 +938,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * Ctrl-v and Shift-Insert.
    */
   signals[PASTE_CLIPBOARD] =
-    g_signal_new (I_("paste_clipboard"),
+    g_signal_new (I_("paste-clipboard"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, paste_clipboard),
@@ -903,12 +952,12 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    *
    * The ::toggle-overwrite signal is a 
    * <link linkend="keybinding-signals">keybinding signal</link> 
-   * which gets emitted to change the editability of the text view.
+   * which gets emitted to toggle the overwrite mode of the text view.
    * 
    * The default bindings for this signal is Insert.
    */ 
   signals[TOGGLE_OVERWRITE] =
-    g_signal_new (I_("toggle_overwrite"),
+    g_signal_new (I_("toggle-overwrite"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, toggle_overwrite),
@@ -916,8 +965,17 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
                  _gtk_marshal_VOID__VOID,
                  G_TYPE_NONE, 0);
 
+  /**
+   * GtkTextView::set-scroll-adjustments
+   * @horizontal: the horizontal #GtkAdjustment
+   * @vertical: the vertical #GtkAdjustment
+   *
+   * Set the scroll adjustments for the text view. Usually scrolled containers
+   * like #GtkScrolledWindow will emit this signal to connect two instances
+   * of #GtkScrollbar to the scroll directions of the #GtkTextView.
+   */
   signals[SET_SCROLL_ADJUSTMENTS] =
-    g_signal_new (I_("set_scroll_adjustments"),
+    g_signal_new (I_("set-scroll-adjustments"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkTextViewClass, set_scroll_adjustments),
@@ -928,8 +986,19 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
                  GTK_TYPE_ADJUSTMENT);
   widget_class->set_scroll_adjustments_signal = signals[SET_SCROLL_ADJUSTMENTS];
 
+  /**
+   * GtkTextView::populate-popup:
+   * @entry: The text view on which the signal is emitted
+   * @menu: the menu that is being populated
+   *
+   * The ::populate-popup signal gets emitted before showing the 
+   * context menu of the text view.
+   *
+   * If you need to add items to the context menu, connect
+   * to this signal and append your menuitems to the @menu.
+   */
   signals[POPULATE_POPUP] =
-    g_signal_new (I_("populate_popup"),
+    g_signal_new (I_("populate-popup"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkTextViewClass, populate_popup),
@@ -952,13 +1021,13 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * for selecting and Shift-Ctrl-a and Ctrl-\ for unselecting.
    */
   signals[SELECT_ALL] =
-    _gtk_binding_signal_new (I_("select_all"),
-                            G_OBJECT_CLASS_TYPE (object_class),
-                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-                            G_CALLBACK (gtk_text_view_select_all),
-                            NULL, NULL,
-                            _gtk_marshal_VOID__BOOLEAN,
-                            G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+    g_signal_new_class_handler (I_("select-all"),
+                                G_OBJECT_CLASS_TYPE (object_class),
+                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                G_CALLBACK (gtk_text_view_select_all),
+                                NULL, NULL,
+                                _gtk_marshal_VOID__BOOLEAN,
+                                G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
 
   /**
    * GtkTextView::toggle-cursor-visible:
@@ -971,13 +1040,37 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
    * The default binding for this signal is F7.
    */ 
   signals[TOGGLE_CURSOR_VISIBLE] =
-    _gtk_binding_signal_new (I_("toggle_cursor_visible"),
-                            G_OBJECT_CLASS_TYPE (object_class),
-                            G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-                            G_CALLBACK (gtk_text_view_toggle_cursor_visible),
-                            NULL, NULL,
-                            _gtk_marshal_VOID__VOID,
-                            G_TYPE_NONE, 0);
+    g_signal_new_class_handler (I_("toggle-cursor-visible"),
+                                G_OBJECT_CLASS_TYPE (object_class),
+                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                G_CALLBACK (gtk_text_view_toggle_cursor_visible),
+                                NULL, NULL,
+                                _gtk_marshal_VOID__VOID,
+                                G_TYPE_NONE, 0);
+
+  /**
+   * GtkTextView::preedit-changed:
+   * @text_view: the object which received the signal
+   * @preedit: the current preedit string
+   *
+   * If an input method is used, the typed text will not immediately
+   * be committed to the buffer. So if you are interested in the text,
+   * connect to this signal.
+   *
+   * This signal is only emitted if the text at the given position
+   * is actually editable.
+   *
+   * Since: 2.20
+   */
+  signals[PREEDIT_CHANGED] =
+    g_signal_new_class_handler (I_("preedit-changed"),
+                                G_OBJECT_CLASS_TYPE (object_class),
+                                G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                NULL,
+                                NULL, NULL,
+                                _gtk_marshal_VOID__STRING,
+                                G_TYPE_NONE, 1,
+                                G_TYPE_STRING);
 
   /*
    * Key bindings
@@ -1084,30 +1177,30 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
 
   /* Select all */
   gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK,
-                               "select_all", 1,
+                               "select-all", 1,
                                G_TYPE_BOOLEAN, TRUE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
-                               "select_all", 1,
+                               "select-all", 1,
                                G_TYPE_BOOLEAN, TRUE);
   
   /* Unselect all */
   gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_CONTROL_MASK,
-                                "select_all", 1,
+                                "select-all", 1,
                                 G_TYPE_BOOLEAN, FALSE);
 
   gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                                "select_all", 1,
+                                "select-all", 1,
                                 G_TYPE_BOOLEAN, FALSE);
 
   /* Deleting text */
   gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
-                               "delete_from_cursor", 2,
+                               "delete-from-cursor", 2,
                                G_TYPE_ENUM, GTK_DELETE_CHARS,
                                G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, 0,
-                               "delete_from_cursor", 2,
+                               "delete-from-cursor", 2,
                                G_TYPE_ENUM, GTK_DELETE_CHARS,
                                G_TYPE_INT, 1);
   
@@ -1119,59 +1212,74 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
                                "backspace", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
-                               "delete_from_cursor", 2,
+                               "delete-from-cursor", 2,
                                G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                G_TYPE_INT, 1);
 
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, GDK_CONTROL_MASK,
-                               "delete_from_cursor", 2,
+                               "delete-from-cursor", 2,
                                G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                G_TYPE_INT, 1);
   
   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK,
-                               "delete_from_cursor", 2,
+                               "delete-from-cursor", 2,
                                G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
                                G_TYPE_INT, -1);
 
+  gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_KP_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+                               G_TYPE_INT, 1);
+
+  gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+                               "delete-from-cursor", 2,
+                               G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+                               G_TYPE_INT, -1);
+
   /* Cut/copy/paste */
 
   gtk_binding_entry_add_signal (binding_set, GDK_x, GDK_CONTROL_MASK,
-                               "cut_clipboard", 0);
+                               "cut-clipboard", 0);
   gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
-                               "copy_clipboard", 0);
+                               "copy-clipboard", 0);
   gtk_binding_entry_add_signal (binding_set, GDK_v, GDK_CONTROL_MASK,
-                               "paste_clipboard", 0);
+                               "paste-clipboard", 0);
 
   gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_SHIFT_MASK,
-                               "cut_clipboard", 0);
+                               "cut-clipboard", 0);
   gtk_binding_entry_add_signal (binding_set, GDK_Insert, GDK_CONTROL_MASK,
-                               "copy_clipboard", 0);
+                               "copy-clipboard", 0);
   gtk_binding_entry_add_signal (binding_set, GDK_Insert, GDK_SHIFT_MASK,
-                               "paste_clipboard", 0);
+                               "paste-clipboard", 0);
 
   /* Overwrite */
   gtk_binding_entry_add_signal (binding_set, GDK_Insert, 0,
-                               "toggle_overwrite", 0);
+                               "toggle-overwrite", 0);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Insert, 0,
-                               "toggle_overwrite", 0);
+                               "toggle-overwrite", 0);
 
   /* Caret mode */
   gtk_binding_entry_add_signal (binding_set, GDK_F7, 0,
-                               "toggle_cursor_visible", 0);
+                               "toggle-cursor-visible", 0);
 
   /* Control-tab focus motion */
   gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_CONTROL_MASK,
-                               "move_focus", 1,
+                               "move-focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_CONTROL_MASK,
-                               "move_focus", 1,
+                               "move-focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
   
   gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                               "move_focus", 1,
+                               "move-focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
-                               "move_focus", 1,
+                               "move-focus", 1,
                                GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
 
   g_type_class_add_private (gobject_class, sizeof (GtkTextViewPrivate));
@@ -1214,11 +1322,11 @@ gtk_text_view_init (GtkTextView *text_view)
 
   g_signal_connect (text_view->im_context, "commit",
                     G_CALLBACK (gtk_text_view_commit_handler), text_view);
-  g_signal_connect (text_view->im_context, "preedit_changed",
+  g_signal_connect (text_view->im_context, "preedit-changed",
                    G_CALLBACK (gtk_text_view_preedit_changed_handler), text_view);
-  g_signal_connect (text_view->im_context, "retrieve_surrounding",
+  g_signal_connect (text_view->im_context, "retrieve-surrounding",
                    G_CALLBACK (gtk_text_view_retrieve_surrounding_handler), text_view);
-  g_signal_connect (text_view->im_context, "delete_surrounding",
+  g_signal_connect (text_view->im_context, "delete-surrounding",
                    G_CALLBACK (gtk_text_view_delete_surrounding_handler), text_view);
 
   text_view->cursor_visible = TRUE;
@@ -1281,7 +1389,7 @@ gtk_text_view_new_with_buffer (GtkTextBuffer *buffer)
 /**
  * gtk_text_view_set_buffer:
  * @text_view: a #GtkTextView
- * @buffer: a #GtkTextBuffer
+ * @buffer: (allow-none): a #GtkTextBuffer
  *
  * Sets @buffer as the buffer being displayed by @text_view. The previous
  * buffer displayed by the text view is unreferenced, and a reference is
@@ -1328,29 +1436,37 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
       g_signal_handlers_disconnect_by_func (text_view->buffer,
                                             gtk_text_view_target_list_notify,
                                             text_view);
-      g_object_unref (text_view->buffer);
-      text_view->dnd_mark = NULL;
-      text_view->first_para_mark = NULL;
+      g_signal_handlers_disconnect_by_func (text_view->buffer,
+                                            gtk_text_view_paste_done_handler,
+                                            text_view);
 
       if (GTK_WIDGET_REALIZED (text_view))
        {
          GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (text_view),
                                                              GDK_SELECTION_PRIMARY);
          gtk_text_buffer_remove_selection_clipboard (text_view->buffer, clipboard);
-       }
+        }
+
+      if (text_view->layout)
+        gtk_text_layout_set_buffer (text_view->layout, NULL);
+
+      g_object_unref (text_view->buffer);
+      text_view->dnd_mark = NULL;
+      text_view->first_para_mark = NULL;
+      cancel_pending_scroll (text_view);
     }
 
   text_view->buffer = buffer;
 
+  if (text_view->layout)
+    gtk_text_layout_set_buffer (text_view->layout, buffer);
+
   if (buffer != NULL)
     {
       GtkTextIter start;
 
       g_object_ref (buffer);
 
-      if (text_view->layout)
-        gtk_text_layout_set_buffer (text_view->layout, buffer);
-
       gtk_text_buffer_get_iter_at_offset (text_view->buffer, &start, 0);
 
       text_view->dnd_mark = gtk_text_buffer_create_mark (text_view->buffer,
@@ -1363,12 +1479,15 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
 
       text_view->first_para_pixels = 0;
 
-      g_signal_connect (text_view->buffer, "mark_set",
+      g_signal_connect (text_view->buffer, "mark-set",
                        G_CALLBACK (gtk_text_view_mark_set_handler),
                         text_view);
       g_signal_connect (text_view->buffer, "notify::paste-target-list",
                        G_CALLBACK (gtk_text_view_target_list_notify),
                         text_view);
+      g_signal_connect (text_view->buffer, "paste-done",
+                       G_CALLBACK (gtk_text_view_paste_done_handler),
+                        text_view);
 
       gtk_text_view_target_list_notify (text_view->buffer, NULL, text_view);
 
@@ -1382,7 +1501,7 @@ gtk_text_view_set_buffer (GtkTextView   *text_view,
 
   g_object_notify (G_OBJECT (text_view), "buffer");
   
-  if (GTK_WIDGET_VISIBLE (text_view))
+  if (gtk_widget_get_visible (GTK_WIDGET (text_view)))
     gtk_widget_queue_draw (GTK_WIDGET (text_view));
 
   DV(g_print ("Invalidating due to set_buffer\n"));
@@ -1411,7 +1530,7 @@ get_buffer (GtkTextView *text_view)
  * The reference count on the buffer is not incremented; the caller
  * of this function won't own a new reference.
  *
- * Return value: a #GtkTextBuffer
+ * Return value: (transfer none): a #GtkTextBuffer
  **/
 GtkTextBuffer*
 gtk_text_view_get_buffer (GtkTextView *text_view)
@@ -1453,7 +1572,7 @@ gtk_text_view_get_iter_at_location (GtkTextView *text_view,
  * gtk_text_view_get_iter_at_position:
  * @text_view: a #GtkTextView
  * @iter: a #GtkTextIter
- * @trailing: location to store an integer indicating where
+ * @trailing: if non-%NULL, location to store an integer indicating where
  *    in the grapheme the user clicked. It will either be
  *    zero, or the number of characters in the grapheme. 
  *    0 represents the trailing edge of the grapheme.
@@ -1772,9 +1891,13 @@ gtk_text_view_scroll_to_iter (GtkTextView   *text_view,
     }
   
   if (retval)
-    DV(g_print (">Actually scrolled ("G_STRLOC")\n"));
+    {
+      DV(g_print (">Actually scrolled ("G_STRLOC")\n"));
+    }
   else
-    DV(g_print (">Didn't end up scrolling ("G_STRLOC")\n"));
+    {
+      DV(g_print (">Didn't end up scrolling ("G_STRLOC")\n"));
+    }
   
   return retval;
 }
@@ -2067,6 +2190,11 @@ gtk_text_view_scroll_to_mark (GtkTextView *text_view,
   g_return_if_fail (xalign >= 0.0 && xalign <= 1.0);
   g_return_if_fail (yalign >= 0.0 && yalign <= 1.0);
 
+  /* We need to verify that the buffer contains the mark, otherwise this
+   * can lead to data structure corruption later on.
+   */
+  g_return_if_fail (get_buffer (text_view) == gtk_text_mark_get_buffer (mark));
+
   gtk_text_view_queue_scroll (text_view, mark,
                               within_margin,
                               use_align,
@@ -2096,6 +2224,11 @@ gtk_text_view_scroll_mark_onscreen (GtkTextView *text_view,
   g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
   g_return_if_fail (GTK_IS_TEXT_MARK (mark));
 
+  /* We need to verify that the buffer contains the mark, otherwise this
+   * can lead to data structure corruption later on.
+   */
+  g_return_if_fail (get_buffer (text_view) == gtk_text_mark_get_buffer (mark));
+
   gtk_text_view_scroll_to_mark (text_view, mark, 0.0, FALSE, 0.0, 0.0);
 }
 
@@ -2235,8 +2368,18 @@ gtk_text_view_set_editable (GtkTextView *text_view,
 
   if (text_view->editable != setting)
     {
+      if (!setting)
+       {
+         gtk_text_view_reset_im_context(text_view);
+         if (gtk_widget_has_focus (GTK_WIDGET (text_view)))
+           gtk_im_context_focus_out (text_view->im_context);
+       }
+
       text_view->editable = setting;
 
+      if (setting && gtk_widget_has_focus (GTK_WIDGET (text_view)))
+       gtk_im_context_focus_in (text_view->im_context);
+
       if (text_view->layout)
         {
          gtk_text_layout_set_overwrite_mode (text_view->layout,
@@ -2663,7 +2806,7 @@ gtk_text_view_set_cursor_visible (GtkTextView *text_view,
     {
       text_view->cursor_visible = setting;
 
-      if (GTK_WIDGET_HAS_FOCUS (text_view))
+      if (gtk_widget_has_focus (GTK_WIDGET (text_view)))
         {
           if (text_view->layout)
             {
@@ -2763,15 +2906,17 @@ gtk_text_view_destroy (GtkObject *object)
       priv->im_spot_idle = 0;
     }
 
-  (* GTK_OBJECT_CLASS (gtk_text_view_parent_class)->destroy) (object);
+  GTK_OBJECT_CLASS (gtk_text_view_parent_class)->destroy (object);
 }
 
 static void
 gtk_text_view_finalize (GObject *object)
 {
   GtkTextView *text_view;
+  GtkTextViewPrivate *priv;
 
   text_view = GTK_TEXT_VIEW (object);
+  priv = GTK_TEXT_VIEW_GET_PRIVATE (text_view);
 
   g_assert (text_view->buffer == NULL);
 
@@ -2803,8 +2948,10 @@ gtk_text_view_finalize (GObject *object)
     text_window_free (text_view->bottom_window);
 
   g_object_unref (text_view->im_context);
-  
-  (* G_OBJECT_CLASS (gtk_text_view_parent_class)->finalize) (object);
+
+  g_free (priv->im_module);
+
+  G_OBJECT_CLASS (gtk_text_view_parent_class)->finalize (object);
 }
 
 static void
@@ -2814,8 +2961,10 @@ gtk_text_view_set_property (GObject         *object,
                            GParamSpec      *pspec)
 {
   GtkTextView *text_view;
+  GtkTextViewPrivate *priv;
 
   text_view = GTK_TEXT_VIEW (object);
+  priv = GTK_TEXT_VIEW_GET_PRIVATE (text_view);
 
   switch (prop_id)
     {
@@ -2875,6 +3024,13 @@ gtk_text_view_set_property (GObject         *object,
       gtk_text_view_set_accepts_tab (text_view, g_value_get_boolean (value));
       break;
       
+    case PROP_IM_MODULE:
+      g_free (priv->im_module);
+      priv->im_module = g_value_dup_string (value);
+      if (GTK_IS_IM_MULTICONTEXT (text_view->im_context))
+        gtk_im_multicontext_set_context_id (GTK_IM_MULTICONTEXT (text_view->im_context), priv->im_module);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2888,8 +3044,10 @@ gtk_text_view_get_property (GObject         *object,
                            GParamSpec      *pspec)
 {
   GtkTextView *text_view;
+  GtkTextViewPrivate *priv;
 
   text_view = GTK_TEXT_VIEW (object);
+  priv = GTK_TEXT_VIEW_GET_PRIVATE (text_view);
 
   switch (prop_id)
     {
@@ -2949,6 +3107,10 @@ gtk_text_view_get_property (GObject         *object,
       g_value_set_boolean (value, text_view->accepts_tab);
       break;
       
+    case PROP_IM_MODULE:
+      g_value_set_string (value, priv->im_module);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -3721,6 +3883,9 @@ gtk_text_view_realize (GtkWidget *widget)
       
       tmp_list = tmp_list->next;
     }
+
+  /* Ensure updating the spot location. */
+  gtk_text_view_update_im_spot_location (text_view);
 }
 
 static void
@@ -3760,11 +3925,11 @@ gtk_text_view_unrealize (GtkWidget *widget)
     text_window_unrealize (text_view->bottom_window);
 
   gtk_text_view_destroy_layout (text_view);
-  
-  (* GTK_WIDGET_CLASS (gtk_text_view_parent_class)->unrealize) (widget);
+
+  GTK_WIDGET_CLASS (gtk_text_view_parent_class)->unrealize (widget);
 }
 
-static void 
+static void
 gtk_text_view_set_background (GtkTextView *text_view)
 {
   GtkWidget *widget = GTK_WIDGET (text_view);
@@ -3847,7 +4012,7 @@ gtk_text_view_state_changed (GtkWidget      *widget,
     {
       gtk_text_view_set_background (text_view);
 
-      if (GTK_WIDGET_IS_SENSITIVE (widget))
+      if (gtk_widget_is_sensitive (widget))
         cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), GDK_XTERM);
       else
         cursor = NULL;
@@ -3860,7 +4025,7 @@ gtk_text_view_state_changed (GtkWidget      *widget,
       text_view->mouse_cursor_obscured = FALSE;
     }
 
-  if (!GTK_WIDGET_IS_SENSITIVE (widget))
+  if (!gtk_widget_is_sensitive (widget))
     {
       /* Clear any selection */
       gtk_text_view_unselect (text_view);
@@ -3872,28 +4037,15 @@ gtk_text_view_state_changed (GtkWidget      *widget,
 static void
 set_invisible_cursor (GdkWindow *window)
 {
-  GdkBitmap *empty_bitmap;
+  GdkDisplay *display;
   GdkCursor *cursor;
-  GdkColor useless;
-  char invisible_cursor_bits[] = { 0x0 };      
-       
-  useless.red = useless.green = useless.blue = 0;
-  useless.pixel = 0;
-  
-  empty_bitmap = gdk_bitmap_create_from_data (window,
-                                             invisible_cursor_bits,
-                                             1, 1);
-  
-  cursor = gdk_cursor_new_from_pixmap (empty_bitmap,
-                                      empty_bitmap,
-                                      &useless,
-                                      &useless, 0, 0);
-  
+
+  display = gdk_drawable_get_display (window);
+  cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR);
   gdk_window_set_cursor (window, cursor);
   
   gdk_cursor_unref (cursor);
-  
-  g_object_unref (empty_bitmap);
 }
 
 static void
@@ -4088,12 +4240,14 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
       retval = TRUE;
     }
   /* Binding set */
-  else if (GTK_WIDGET_CLASS (gtk_text_view_parent_class)->key_press_event &&
-          GTK_WIDGET_CLASS (gtk_text_view_parent_class)->key_press_event (widget, event))
-    retval = TRUE;
+  else if (GTK_WIDGET_CLASS (gtk_text_view_parent_class)->key_press_event (widget, event))
+    {
+      retval = TRUE;
+    }
   /* use overall editability not can_insert, more predictable for users */
   else if (text_view->editable &&
            (event->keyval == GDK_Return ||
+            event->keyval == GDK_ISO_Enter ||
             event->keyval == GDK_KP_Enter))
     {
       /* this won't actually insert the newline if the cursor isn't
@@ -4206,7 +4360,8 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
 
           if (gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
                                                     &start, &end) &&
-              gtk_text_iter_in_range (&iter, &start, &end))
+              gtk_text_iter_in_range (&iter, &start, &end) &&
+              !(event->state & GDK_SHIFT_MASK))
             {
               text_view->drag_start_x = event->x;
               text_view->drag_start_y = event->y;
@@ -4330,12 +4485,15 @@ gtk_text_view_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
     }
 
   g_signal_connect (gdk_keymap_get_for_display (gtk_widget_get_display (widget)),
-                   "direction_changed",
+                   "direction-changed",
                    G_CALLBACK (keymap_direction_changed), text_view);
   gtk_text_view_check_keymap_direction (text_view);
-  
-  text_view->need_im_reset = TRUE;
-  gtk_im_context_focus_in (GTK_TEXT_VIEW (widget)->im_context);
+
+  if (text_view->editable)
+    {
+      text_view->need_im_reset = TRUE;
+      gtk_im_context_focus_in (GTK_TEXT_VIEW (widget)->im_context);
+    }
 
   return FALSE;
 }
@@ -4361,8 +4519,11 @@ gtk_text_view_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
                                        keymap_direction_changed,
                                        text_view);
 
-  text_view->need_im_reset = TRUE;
-  gtk_im_context_focus_out (GTK_TEXT_VIEW (widget)->im_context);
+  if (text_view->editable)
+    {
+      text_view->need_im_reset = TRUE;
+      gtk_im_context_focus_out (GTK_TEXT_VIEW (widget)->im_context);
+    }
 
   return FALSE;
 }
@@ -4417,7 +4578,6 @@ gtk_text_view_paint (GtkWidget      *widget,
   GtkTextView *text_view;
   GList *child_exposes;
   GList *tmp_list;
-  GdkRegion *updates;
   
   text_view = GTK_TEXT_VIEW (widget);
 
@@ -4432,19 +4592,6 @@ gtk_text_view_paint (GtkWidget      *widget,
       gtk_text_view_flush_first_validate (text_view);
     }
 
-  /* More regions could have become invalid in the above loop */
-  updates = gdk_window_get_update_area (text_view->text_window->bin_window);
-  if (updates)
-    {
-      GdkRectangle rect;
-      
-      gdk_region_get_clipbox (updates, &rect);
-
-      gdk_rectangle_union (area, &rect, area);
-      
-      gdk_region_destroy (updates);
-    }
-  
   if (!text_view->onscreen_validated)
     {
       g_warning (G_STRLOC ": somehow some text lines were modified or scrolling occurred since the last validation of lines on the screen - may be a text widget bug.");
@@ -4532,9 +4679,9 @@ gtk_text_view_draw_focus (GtkWidget *widget)
                        "interior-focus", &interior_focus,
                        NULL);
   
-  if (GTK_WIDGET_DRAWABLE (widget))
+  if (gtk_widget_is_drawable (widget))
     {
-      if (GTK_WIDGET_HAS_FOCUS (widget) && !interior_focus)
+      if (gtk_widget_has_focus (widget) && !interior_focus)
         {          
           gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget), 
                            NULL, widget, "textview",
@@ -4741,7 +4888,7 @@ blink_cb (gpointer data)
   text_view = GTK_TEXT_VIEW (data);
   priv = GTK_TEXT_VIEW_GET_PRIVATE (text_view);
 
-  if (!GTK_WIDGET_HAS_FOCUS (text_view))
+  if (!gtk_widget_has_focus (GTK_WIDGET (text_view)))
     {
       g_warning ("GtkTextView - did not receive focus-out-event. If you\n"
                  "connect a handler to this signal, it must return\n"
@@ -4811,7 +4958,7 @@ gtk_text_view_check_cursor_blink (GtkTextView *text_view)
 {
   if (text_view->layout != NULL &&
       text_view->cursor_visible &&
-      GTK_WIDGET_HAS_FOCUS (text_view))
+      gtk_widget_has_focus (GTK_WIDGET (text_view)))
     {
       if (cursor_blinks (text_view))
        {
@@ -4842,7 +4989,7 @@ gtk_text_view_pend_cursor_blink (GtkTextView *text_view)
 {
   if (text_view->layout != NULL &&
       text_view->cursor_visible &&
-      GTK_WIDGET_HAS_FOCUS (text_view) &&
+      gtk_widget_has_focus (GTK_WIDGET (text_view)) &&
       cursor_blinks (text_view))
     {
       gtk_text_view_stop_cursor_blink (text_view);
@@ -4914,6 +5061,7 @@ gtk_text_view_move_cursor_internal (GtkTextView     *text_view,
 {
   GtkTextIter insert;
   GtkTextIter newplace;
+  gboolean cancel_selection = FALSE;
   gint cursor_x_pos = 0;
   GtkDirectionType leave_direction = -1;
 
@@ -4990,20 +5138,46 @@ gtk_text_view_move_cursor_internal (GtkTextView     *text_view,
 
   gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert,
                                     gtk_text_buffer_get_insert (get_buffer (text_view)));
+
+  if (! extend_selection)
+    {
+      GtkTextIter sel_bound;
+
+      gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &sel_bound,
+                                        gtk_text_buffer_get_selection_bound (get_buffer (text_view)));
+
+      /* if we move forward, assume the cursor is at the end of the selection;
+       * if we move backward, assume the cursor is at the start
+       */
+      if (count > 0)
+        gtk_text_iter_order (&sel_bound, &insert);
+      else
+        gtk_text_iter_order (&insert, &sel_bound);
+
+      /* if we actually have a selection, just move *to* the beginning/end
+       * of the selection and not *from* there on LOGICAL_POSITIONS
+       * and VISUAL_POSITIONS movement
+       */
+      if (! gtk_text_iter_equal (&sel_bound, &insert))
+        cancel_selection = TRUE;
+    }
+
   newplace = insert;
 
   if (step == GTK_MOVEMENT_DISPLAY_LINES)
-    gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, NULL);
+    gtk_text_view_get_virtual_cursor_pos (text_view, &insert, &cursor_x_pos, NULL);
 
   switch (step)
     {
     case GTK_MOVEMENT_LOGICAL_POSITIONS:
-      gtk_text_iter_forward_visible_cursor_positions (&newplace, count);
+      if (! cancel_selection)
+        gtk_text_iter_forward_visible_cursor_positions (&newplace, count);
       break;
 
     case GTK_MOVEMENT_VISUAL_POSITIONS:
-      gtk_text_layout_move_iter_visually (text_view->layout,
-                                          &newplace, count);
+      if (! cancel_selection)
+        gtk_text_layout_move_iter_visually (text_view->layout,
+                                            &newplace, count);
       break;
 
     case GTK_MOVEMENT_WORDS:
@@ -5112,7 +5286,7 @@ gtk_text_view_move_cursor_internal (GtkTextView     *text_view,
           g_signal_emit_by_name (text_view, "move-focus", leave_direction);
         }
     }
-  else
+  else if (! cancel_selection)
     {
       gtk_widget_error_bell (GTK_WIDGET (text_view));
     }
@@ -5265,7 +5439,7 @@ gtk_text_view_scroll_pages (GtkTextView *text_view,
     }
   else
     {
-      gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
+      gtk_text_view_get_virtual_cursor_pos (text_view, NULL, &cursor_x_pos, &cursor_y_pos);
 
       oldval = adj->value;
       newval = adj->value;
@@ -5346,7 +5520,7 @@ gtk_text_view_scroll_hpages (GtkTextView *text_view,
     }
   else
     {
-      gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
+      gtk_text_view_get_virtual_cursor_pos (text_view, NULL, &cursor_x_pos, &cursor_y_pos);
 
       oldval = adj->value;
       newval = adj->value;
@@ -5465,26 +5639,42 @@ gtk_text_view_delete_from_cursor (GtkTextView   *text_view,
       break;
 
     case GTK_DELETE_PARAGRAPH_ENDS:
-      /* If we're already at a newline, we need to
-       * simply delete that newline, instead of
-       * moving to the next one.
-       */
-      if (gtk_text_iter_ends_line (&end))
+      if (count > 0)
         {
-          gtk_text_iter_forward_line (&end);
-          --count;
-        }
+          /* If we're already at a newline, we need to
+           * simply delete that newline, instead of
+           * moving to the next one.
+           */
+          if (gtk_text_iter_ends_line (&end))
+            {
+              gtk_text_iter_forward_line (&end);
+              --count;
+            }
 
-      while (count > 0)
-        {
-          if (!gtk_text_iter_forward_to_line_end (&end))
-            break;
+          while (count > 0)
+            {
+              if (!gtk_text_iter_forward_to_line_end (&end))
+                break;
 
-          --count;
+              --count;
+            }
         }
+      else if (count < 0)
+        {
+          if (gtk_text_iter_starts_line (&start))
+            {
+              gtk_text_iter_backward_line (&start);
+              if (!gtk_text_iter_ends_line (&end))
+                gtk_text_iter_forward_to_line_end (&start);
+            }
+          else
+            {
+              gtk_text_iter_set_line_offset (&start, 0);
+            }
+          ++count;
 
-      /* FIXME figure out what a negative count means
-         and support that */
+          gtk_text_iter_backward_lines (&start, -count);
+        }
       break;
 
     case GTK_DELETE_PARAGRAPHS:
@@ -5612,9 +5802,16 @@ gtk_text_view_paste_clipboard (GtkTextView *text_view)
                                   clipboard,
                                   NULL,
                                   text_view->editable);
+}
+
+static void
+gtk_text_view_paste_done_handler (GtkTextBuffer *buffer,
+                                  GtkClipboard  *clipboard,
+                                  gpointer       data)
+{
+  GtkTextView *text_view = data;
   DV(g_print (G_STRLOC": scrolling onscreen\n"));
-  gtk_text_view_scroll_mark_onscreen (text_view,
-                                      gtk_text_buffer_get_insert (get_buffer (text_view)));
+  gtk_text_view_scroll_mark_onscreen (text_view, gtk_text_buffer_get_insert (buffer));
 }
 
 static void
@@ -5740,22 +5937,10 @@ gtk_text_view_compat_move_focus (GtkTextView     *text_view,
     {
       /*  if this is a signal emission, chain up  */
 
-      GValue instance_and_params[2] = { { 0, }, { 0, } };
-      GValue return_value = { 0, };
-
-      g_value_init (&instance_and_params[0], GTK_TYPE_WIDGET);
-      g_value_set_object (&instance_and_params[0], text_view);
-
-      g_value_init (&instance_and_params[1], GTK_TYPE_DIRECTION_TYPE);
-      g_value_set_enum (&instance_and_params[1], direction_type);
-
-      g_value_init (&return_value, G_TYPE_BOOLEAN);
-
-      g_signal_chain_from_overridden (instance_and_params, &return_value);
+      gboolean retval;
 
-      g_value_unset (&instance_and_params[0]);
-      g_value_unset (&instance_and_params[1]);
-      g_value_unset (&return_value);
+      g_signal_chain_from_overridden_handler (text_view,
+                                              direction_type, &retval);
     }
   else
     {
@@ -6130,7 +6315,7 @@ gtk_text_view_start_selection_drag (GtkTextView       *text_view,
   gtk_text_view_check_cursor_blink (text_view);
 
   text_view->selection_drag_handler = g_signal_connect_data (text_view,
-                                                             "motion_notify_event",
+                                                             "motion-notify-event",
                                                              G_CALLBACK (selection_motion_event_handler),
                                                              data,
                                                              (GClosureNotify) selection_data_free, 0);  
@@ -6233,14 +6418,14 @@ gtk_text_view_ensure_layout (GtkTextView *text_view)
                        text_view);
 
       g_signal_connect (text_view->layout,
-                       "allocate_child",
+                       "allocate-child",
                        G_CALLBACK (gtk_text_view_child_allocated),
                        text_view);
       
       if (get_buffer (text_view))
         gtk_text_layout_set_buffer (text_view->layout, get_buffer (text_view));
 
-      if ((GTK_WIDGET_HAS_FOCUS (text_view) && text_view->cursor_visible))
+      if ((gtk_widget_has_focus (widget) && text_view->cursor_visible))
         gtk_text_view_pend_cursor_blink (text_view);
       else
         gtk_text_layout_set_cursor_visible (text_view->layout, FALSE);
@@ -6341,9 +6526,9 @@ gtk_text_view_destroy_layout (GtkTextView *text_view)
                                            invalidated_handler,
                                            text_view);
       g_signal_handlers_disconnect_by_func (text_view->layout,
-                                           changed_handler, 
+                                           changed_handler,
                                            text_view);
-      
+
       /* Remove layout from all anchored children */
       tmp_list = text_view->children;
       while (tmp_list != NULL)
@@ -6358,7 +6543,7 @@ gtk_text_view_destroy_layout (GtkTextView *text_view)
 
           tmp_list = g_slist_next (tmp_list);
         }
-      
+
       gtk_text_view_stop_cursor_blink (text_view);
       gtk_text_view_end_selection_drag (text_view);
 
@@ -6425,7 +6610,7 @@ gtk_text_view_start_selection_dnd (GtkTextView       *text_view,
 
   target_list = gtk_text_buffer_get_copy_target_list (get_buffer (text_view));
 
-  g_signal_connect (text_view, "drag_begin",
+  g_signal_connect (text_view, "drag-begin",
                     G_CALLBACK (drag_begin_cb), NULL);
   gtk_drag_begin (GTK_WIDGET (text_view), target_list,
                  GDK_ACTION_COPY | GDK_ACTION_MOVE,
@@ -6889,7 +7074,7 @@ gtk_text_view_set_scroll_adjustments (GtkTextView   *text_view,
       text_view->hadjustment = hadj;
       g_object_ref_sink (text_view->hadjustment);
       
-      g_signal_connect (text_view->hadjustment, "value_changed",
+      g_signal_connect (text_view->hadjustment, "value-changed",
                         G_CALLBACK (gtk_text_view_value_changed),
                        text_view);
       need_adjust = TRUE;
@@ -6900,7 +7085,7 @@ gtk_text_view_set_scroll_adjustments (GtkTextView   *text_view,
       text_view->vadjustment = vadj;
       g_object_ref_sink (text_view->vadjustment);
       
-      g_signal_connect (text_view->vadjustment, "value_changed",
+      g_signal_connect (text_view->vadjustment, "value-changed",
                         G_CALLBACK (gtk_text_view_value_changed),
                        text_view);
       need_adjust = TRUE;
@@ -6923,7 +7108,7 @@ typedef struct
 
 /* The window to which widget->window is relative */
 #define ALLOCATION_WINDOW(widget)              \
-   (GTK_WIDGET_NO_WINDOW (widget) ?            \
+   (!gtk_widget_get_has_window (widget) ?              \
     (widget)->window :                          \
      gdk_window_get_parent ((widget)->window))
 
@@ -6939,7 +7124,7 @@ adjust_allocation_recurse (GtkWidget *widget,
    */
   if (!GTK_WIDGET_REALIZED (widget))
     {
-      if (GTK_WIDGET_VISIBLE (widget))
+      if (gtk_widget_get_visible (widget))
        {
          GdkRectangle tmp_rectangle = widget->allocation;
          tmp_rectangle.x += scroll_data->dx;
@@ -7084,6 +7269,11 @@ gtk_text_view_value_changed (GtkAdjustment *adj,
    */
   gtk_text_view_update_layout_width (text_view);
   
+  /* We also update the IM spot location here, since the IM context
+   * might do something that leads to validation.
+   */
+  gtk_text_view_update_im_spot_location (text_view);
+
   /* note that validation of onscreen could invoke this function
    * recursively, by scrolling to maintain first_para, or in response
    * to updating the layout width, however there is no problem with
@@ -7118,6 +7308,9 @@ gtk_text_view_value_changed (GtkAdjustment *adj,
       text_view->first_validate_idle = 0;
     }
 
+  /* Finally we update the IM cursor location again, to ensure any
+   * changes made by the validation are pushed through.
+   */
   gtk_text_view_update_im_spot_location (text_view);
   
   DV(g_print(">End scroll offset changed handler ("G_STRLOC")\n"));
@@ -7158,7 +7351,7 @@ gtk_text_view_commit_text (GtkTextView   *text_view,
       if (!had_selection && text_view->overwrite_mode)
        {
          GtkTextIter insert;
-         
+
          gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
                                            &insert,
                                            gtk_text_buffer_get_insert (get_buffer (text_view)));
@@ -7190,26 +7383,32 @@ gtk_text_view_preedit_changed_handler (GtkIMContext *context,
   gint cursor_pos;
   GtkTextIter iter;
 
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &iter, 
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &iter,
                                    gtk_text_buffer_get_insert (text_view->buffer));
 
-  /* Keypress events are passed to input method even if cursor position is not editable;
-   * so beep here if it's multi-key input sequence, input method will be reset in 
-   * key-press-event handler. */
-  if (!gtk_text_iter_can_insert (&iter, text_view->editable))
+  /* Keypress events are passed to input method even if cursor position is
+   * not editable; so beep here if it's multi-key input sequence, input
+   * method will be reset in key-press-event handler.
+   */
+  gtk_im_context_get_preedit_string (context, &str, &attrs, &cursor_pos);
+
+  if (str && str[0] && !gtk_text_iter_can_insert (&iter, text_view->editable))
     {
       gtk_widget_error_bell (GTK_WIDGET (text_view));
-      return;
+      goto out;
     }
 
-  gtk_im_context_get_preedit_string (context, &str, &attrs, &cursor_pos);
-  gtk_text_layout_set_preedit_string (text_view->layout, str, attrs, cursor_pos);
-  pango_attr_list_unref (attrs);
-  g_free (str);
+  g_signal_emit (text_view, signals[PREEDIT_CHANGED], 0, str);
 
-  if (GTK_WIDGET_HAS_FOCUS (text_view))
+  if (text_view->layout)
+    gtk_text_layout_set_preedit_string (text_view->layout, str, attrs, cursor_pos);
+  if (gtk_widget_has_focus (GTK_WIDGET (text_view)))
     gtk_text_view_scroll_mark_onscreen (text_view,
                                        gtk_text_buffer_get_insert (get_buffer (text_view)));
+
+out:
+  pango_attr_list_unref (attrs);
+  g_free (str);
 }
 
 static gboolean
@@ -7221,7 +7420,7 @@ gtk_text_view_retrieve_surrounding_handler (GtkIMContext  *context,
   gint pos;
   gchar *text;
 
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &start,  
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &start,
                                    gtk_text_buffer_get_insert (text_view->buffer));
   end = start;
 
@@ -7245,7 +7444,7 @@ gtk_text_view_delete_surrounding_handler (GtkIMContext  *context,
   GtkTextIter start;
   GtkTextIter end;
 
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &start,  
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &start,
                                    gtk_text_buffer_get_insert (text_view->buffer));
   end = start;
 
@@ -7340,14 +7539,22 @@ gtk_text_view_get_cursor_location  (GtkTextView   *text_view,
 
 static void
 gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
+                                      GtkTextIter *cursor,
                                       gint        *x,
                                       gint        *y)
 {
+  GtkTextIter insert;
   GdkRectangle pos;
 
+  if (cursor)
+    insert = *cursor;
+  else
+    gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &insert,
+                                      gtk_text_buffer_get_insert (get_buffer (text_view)));
+
   if ((x && text_view->virtual_cursor_x == -1) ||
       (y && text_view->virtual_cursor_y == -1))
-    gtk_text_view_get_cursor_location (text_view, &pos);
+    gtk_text_layout_get_cursor_locations (text_view->layout, &insert, &pos, NULL);
 
   if (x)
     {
@@ -7606,13 +7813,13 @@ popup_targets_received (GtkClipboard     *clipboard,
       
       can_insert = gtk_text_iter_can_insert (&iter, text_view->editable);
       
-      append_action_signal (text_view, text_view->popup_menu, GTK_STOCK_CUT, "cut_clipboard",
+      append_action_signal (text_view, text_view->popup_menu, GTK_STOCK_CUT, "cut-clipboard",
                            have_selection &&
                             range_contains_editable_text (&sel_start, &sel_end,
                                                           text_view->editable));
-      append_action_signal (text_view, text_view->popup_menu, GTK_STOCK_COPY, "copy_clipboard",
+      append_action_signal (text_view, text_view->popup_menu, GTK_STOCK_COPY, "copy-clipboard",
                            have_selection);
-      append_action_signal (text_view, text_view->popup_menu, GTK_STOCK_PASTE, "paste_clipboard",
+      append_action_signal (text_view, text_view->popup_menu, GTK_STOCK_PASTE, "paste-clipboard",
                            can_insert && clipboard_contains_text);
       
       menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_DELETE, NULL);
@@ -7823,7 +8030,7 @@ text_window_realize (GtkTextWindow *win,
 
   if (win->type == GTK_TEXT_WINDOW_TEXT)
     {
-      if (GTK_WIDGET_IS_SENSITIVE (widget))
+      if (gtk_widget_is_sensitive (widget))
         {
           /* I-beam cursor */
           cursor = gdk_cursor_new_for_display (gdk_drawable_get_display (widget->window),
@@ -7935,7 +8142,7 @@ text_window_invalidate_rect (GtkTextWindow *win,
       break;
 
     default:
-      g_warning ("%s: bug!", G_STRLOC);
+      g_warning ("%s: bug!", G_STRFUNC);
       return;
       break;
     }
@@ -8055,7 +8262,7 @@ text_window_get_height (GtkTextWindow *win)
  * height is 0, and are nonexistent before the widget has been
  * realized.
  *
- * Return value: a #GdkWindow, or %NULL
+ * Return value: (transfer none): a #GdkWindow, or %NULL
  **/
 GdkWindow*
 gtk_text_view_get_window (GtkTextView *text_view,
@@ -8102,12 +8309,12 @@ gtk_text_view_get_window (GtkTextView *text_view,
       break;
 
     case GTK_TEXT_WINDOW_PRIVATE:
-      g_warning ("%s: You can't get GTK_TEXT_WINDOW_PRIVATE, it has \"PRIVATE\" in the name because it is private.", G_STRLOC);
+      g_warning ("%s: You can't get GTK_TEXT_WINDOW_PRIVATE, it has \"PRIVATE\" in the name because it is private.", G_STRFUNC);
       return NULL;
       break;
     }
 
-  g_warning ("%s: Unknown GtkTextWindowType", G_STRLOC);
+  g_warning ("%s: Unknown GtkTextWindowType", G_STRFUNC);
   return NULL;
 }
 
@@ -8275,11 +8482,11 @@ gtk_text_view_buffer_to_window_coords (GtkTextView      *text_view,
       break;
 
     case GTK_TEXT_WINDOW_PRIVATE:
-      g_warning ("%s: can't get coords for private windows", G_STRLOC);
+      g_warning ("%s: can't get coords for private windows", G_STRFUNC);
       break;
 
     default:
-      g_warning ("%s: Unknown GtkTextWindowType", G_STRLOC);
+      g_warning ("%s: Unknown GtkTextWindowType", G_STRFUNC);
       break;
     }
 }
@@ -8415,11 +8622,11 @@ gtk_text_view_window_to_buffer_coords (GtkTextView      *text_view,
       break;
 
     case GTK_TEXT_WINDOW_PRIVATE:
-      g_warning ("%s: can't get coords for private windows", G_STRLOC);
+      g_warning ("%s: can't get coords for private windows", G_STRFUNC);
       break;
 
     default:
-      g_warning ("%s: Unknown GtkTextWindowType", G_STRLOC);
+      g_warning ("%s: Unknown GtkTextWindowType", G_STRFUNC);
       break;
     }
 }
@@ -8818,7 +9025,8 @@ gtk_text_view_move_child (GtkTextView *text_view,
   vc->x = xpos;
   vc->y = ypos;
 
-  if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (text_view))
+  if (gtk_widget_get_visible (child) &&
+      gtk_widget_get_visible (GTK_WIDGET (text_view)))
     gtk_widget_queue_resize (child);
 }