]> Pileus Git - ~andy/gtk/commitdiff
use gtk_text_iter_can_insert
authorHavoc Pennington <hp@redhat.com>
Tue, 25 Sep 2001 22:51:26 +0000 (22:51 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Tue, 25 Sep 2001 22:51:26 +0000 (22:51 +0000)
2001-09-25  Havoc Pennington  <hp@redhat.com>

* gtk/gtktextview.c (gtk_text_view_key_press_event): use
gtk_text_iter_can_insert

* gtk/gtktextbuffer.c: use gtk_text_iter_can_insert

* gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
 (gtk_text_iter_can_insert): new function to fix #60282, should
also fix msw's "can paste into empty buffer" bug.

* gtk/gtktexttag.c (gtk_text_tag_event): change type check for
"event object,"  #59091

* gtk/gtktextbtree.c: indentation fixes

* gtk/gtktextiter.c (find_by_log_attrs): fixes

17 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
docs/reference/gtk/tmpl/gtk-unused.sgml
docs/reference/gtk/tmpl/gtkmenu.sgml
docs/reference/gtk/tmpl/gtktreeviewcolumn.sgml
gtk/gtktextbtree.c
gtk/gtktextbuffer.c
gtk/gtktextiter.c
gtk/gtktextiter.h
gtk/gtktexttag.c
gtk/gtktextview.c
tests/testtextbuffer.c

index 41b4b9fa0119712803a6aa2a9350a88bd9938102..694d0d53af5491783e5d7eb3d6db2b7a5d153d50 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2001-09-25  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_key_press_event): use 
+       gtk_text_iter_can_insert
+
+       * gtk/gtktextbuffer.c: use gtk_text_iter_can_insert
+
+       * gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
+        (gtk_text_iter_can_insert): new function to fix #60282, should
+       also fix msw's "can paste into empty buffer" bug.
+
+       * gtk/gtktexttag.c (gtk_text_tag_event): change type check for 
+       "event object,"  #59091
+
+       * gtk/gtktextbtree.c: indentation fixes
+
+       * gtk/gtktextiter.c (find_by_log_attrs): fixes
+
 Tue Sep 25 12:41:17 2001  Owen Taylor  <otaylor@redhat.com>
 
        * configure.in: Version 1.3.9, interface age 0, binary age 0.
index 41b4b9fa0119712803a6aa2a9350a88bd9938102..694d0d53af5491783e5d7eb3d6db2b7a5d153d50 100644 (file)
@@ -1,3 +1,21 @@
+2001-09-25  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_key_press_event): use 
+       gtk_text_iter_can_insert
+
+       * gtk/gtktextbuffer.c: use gtk_text_iter_can_insert
+
+       * gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
+        (gtk_text_iter_can_insert): new function to fix #60282, should
+       also fix msw's "can paste into empty buffer" bug.
+
+       * gtk/gtktexttag.c (gtk_text_tag_event): change type check for 
+       "event object,"  #59091
+
+       * gtk/gtktextbtree.c: indentation fixes
+
+       * gtk/gtktextiter.c (find_by_log_attrs): fixes
+
 Tue Sep 25 12:41:17 2001  Owen Taylor  <otaylor@redhat.com>
 
        * configure.in: Version 1.3.9, interface age 0, binary age 0.
index 41b4b9fa0119712803a6aa2a9350a88bd9938102..694d0d53af5491783e5d7eb3d6db2b7a5d153d50 100644 (file)
@@ -1,3 +1,21 @@
+2001-09-25  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_key_press_event): use 
+       gtk_text_iter_can_insert
+
+       * gtk/gtktextbuffer.c: use gtk_text_iter_can_insert
+
+       * gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
+        (gtk_text_iter_can_insert): new function to fix #60282, should
+       also fix msw's "can paste into empty buffer" bug.
+
+       * gtk/gtktexttag.c (gtk_text_tag_event): change type check for 
+       "event object,"  #59091
+
+       * gtk/gtktextbtree.c: indentation fixes
+
+       * gtk/gtktextiter.c (find_by_log_attrs): fixes
+
 Tue Sep 25 12:41:17 2001  Owen Taylor  <otaylor@redhat.com>
 
        * configure.in: Version 1.3.9, interface age 0, binary age 0.
index 41b4b9fa0119712803a6aa2a9350a88bd9938102..694d0d53af5491783e5d7eb3d6db2b7a5d153d50 100644 (file)
@@ -1,3 +1,21 @@
+2001-09-25  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_key_press_event): use 
+       gtk_text_iter_can_insert
+
+       * gtk/gtktextbuffer.c: use gtk_text_iter_can_insert
+
+       * gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
+        (gtk_text_iter_can_insert): new function to fix #60282, should
+       also fix msw's "can paste into empty buffer" bug.
+
+       * gtk/gtktexttag.c (gtk_text_tag_event): change type check for 
+       "event object,"  #59091
+
+       * gtk/gtktextbtree.c: indentation fixes
+
+       * gtk/gtktextiter.c (find_by_log_attrs): fixes
+
 Tue Sep 25 12:41:17 2001  Owen Taylor  <otaylor@redhat.com>
 
        * configure.in: Version 1.3.9, interface age 0, binary age 0.
index 41b4b9fa0119712803a6aa2a9350a88bd9938102..694d0d53af5491783e5d7eb3d6db2b7a5d153d50 100644 (file)
@@ -1,3 +1,21 @@
+2001-09-25  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_key_press_event): use 
+       gtk_text_iter_can_insert
+
+       * gtk/gtktextbuffer.c: use gtk_text_iter_can_insert
+
+       * gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
+        (gtk_text_iter_can_insert): new function to fix #60282, should
+       also fix msw's "can paste into empty buffer" bug.
+
+       * gtk/gtktexttag.c (gtk_text_tag_event): change type check for 
+       "event object,"  #59091
+
+       * gtk/gtktextbtree.c: indentation fixes
+
+       * gtk/gtktextiter.c (find_by_log_attrs): fixes
+
 Tue Sep 25 12:41:17 2001  Owen Taylor  <otaylor@redhat.com>
 
        * configure.in: Version 1.3.9, interface age 0, binary age 0.
index 41b4b9fa0119712803a6aa2a9350a88bd9938102..694d0d53af5491783e5d7eb3d6db2b7a5d153d50 100644 (file)
@@ -1,3 +1,21 @@
+2001-09-25  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_key_press_event): use 
+       gtk_text_iter_can_insert
+
+       * gtk/gtktextbuffer.c: use gtk_text_iter_can_insert
+
+       * gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
+        (gtk_text_iter_can_insert): new function to fix #60282, should
+       also fix msw's "can paste into empty buffer" bug.
+
+       * gtk/gtktexttag.c (gtk_text_tag_event): change type check for 
+       "event object,"  #59091
+
+       * gtk/gtktextbtree.c: indentation fixes
+
+       * gtk/gtktextiter.c (find_by_log_attrs): fixes
+
 Tue Sep 25 12:41:17 2001  Owen Taylor  <otaylor@redhat.com>
 
        * configure.in: Version 1.3.9, interface age 0, binary age 0.
index 41b4b9fa0119712803a6aa2a9350a88bd9938102..694d0d53af5491783e5d7eb3d6db2b7a5d153d50 100644 (file)
@@ -1,3 +1,21 @@
+2001-09-25  Havoc Pennington  <hp@redhat.com>
+
+       * gtk/gtktextview.c (gtk_text_view_key_press_event): use 
+       gtk_text_iter_can_insert
+
+       * gtk/gtktextbuffer.c: use gtk_text_iter_can_insert
+
+       * gtk/gtktextiter.c (find_line_log_attrs): fixes, #57611, #57613
+        (gtk_text_iter_can_insert): new function to fix #60282, should
+       also fix msw's "can paste into empty buffer" bug.
+
+       * gtk/gtktexttag.c (gtk_text_tag_event): change type check for 
+       "event object,"  #59091
+
+       * gtk/gtktextbtree.c: indentation fixes
+
+       * gtk/gtktextiter.c (find_by_log_attrs): fixes
+
 Tue Sep 25 12:41:17 2001  Owen Taylor  <otaylor@redhat.com>
 
        * configure.in: Version 1.3.9, interface age 0, binary age 0.
index b6ac0926fa44b68a2e50af87690e6504c782137a..05a643ba934de6d618663fd33878869125d69237 100644 (file)
@@ -2361,6 +2361,14 @@ a gtk_object_unref().
 @tree_model: 
 @iter: 
 
+<!-- ##### FUNCTION gtk_tree_view_column_set_cell_renderer ##### -->
+<para>
+
+</para>
+
+@tree_column: 
+@cell: 
+
 <!-- ##### FUNCTION gtk_tree_view_column_set_width ##### -->
 <para>
 
index b8f6c879354f39e68fa2b852deeb6fbb9f7d7dc5..b51c366a4b8e9cfdb935d43b88694d40851c99fa 100644 (file)
@@ -96,9 +96,9 @@ Creates a new #GtkMenu.
 Adds a new #GtkMenuItem to the end of the menu's item list.
 </para>
 
+<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
-<!-- # Unused Parameters # -->
 @m: 
 @c: 
 
@@ -108,9 +108,9 @@ Adds a new #GtkMenuItem to the end of the menu's item list.
 Adds a new #GtkMenuItem to the beginning of the menu's item list.
 </para>
 
+<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
-<!-- # Unused Parameters # -->
 @menu_child: 
 @m: 
 @c: 
@@ -122,10 +122,10 @@ Adds a new #GtkMenuItem to the menu's item list at the position
 indicated by @position. 
 </para>
 
+<!-- # Unused Parameters # -->
 @menu: a #GtkMenu.
 @child: The #GtkMenuItem to add.
 @pos: 
-<!-- # Unused Parameters # -->
 @position: The position in the item list where @child is added.
 Positions are numbered from 0 to n-1.
 
index 824738e698bdc554f8ba4e555d690a01cd33fc9c..11ed879af0e076c515de42de3e7193e23b3b9299 100644 (file)
@@ -87,15 +87,6 @@ GtkTreeViewColumn
 @Returns: 
 
 
-<!-- ##### FUNCTION gtk_tree_view_column_set_cell_renderer ##### -->
-<para>
-
-</para>
-
-@tree_column: 
-@cell: 
-
-
 <!-- ##### FUNCTION gtk_tree_view_column_add_attribute ##### -->
 <para>
 
index 73cf60de37081582d225bc15e08542cd50ebdbf3..8402b2508e5a2c9b3427fc7e8fe124725f667581 100644 (file)
@@ -3115,9 +3115,9 @@ find_toggle_outside_current_line (GtkTextLine *line,
 /* FIXME this function is far too slow, for no good reason. */
 gboolean
 _gtk_text_line_char_has_tag (GtkTextLine *line,
-                            GtkTextBTree *tree,
-                            gint char_in_line,
-                            GtkTextTag *tag)
+                             GtkTextBTree *tree,
+                             gint char_in_line,
+                             GtkTextTag *tag)
 {
   GtkTextLineSegment *toggle_seg;
 
@@ -3139,9 +3139,9 @@ _gtk_text_line_char_has_tag (GtkTextLine *line,
 
 gboolean
 _gtk_text_line_byte_has_tag (GtkTextLine *line,
-                            GtkTextBTree *tree,
-                            gint byte_in_line,
-                            GtkTextTag *tag)
+                             GtkTextBTree *tree,
+                             gint byte_in_line,
+                             GtkTextTag *tag)
 {
   GtkTextLineSegment *toggle_seg;
 
@@ -3163,7 +3163,7 @@ _gtk_text_line_byte_has_tag (GtkTextLine *line,
 
 gboolean
 _gtk_text_line_is_last (GtkTextLine *line,
-                       GtkTextBTree *tree)
+                        GtkTextBTree *tree)
 {
   return line == get_last_line (tree);
 }
index 3a11c9dfa8dc3f44e5810fa73b53496a8e716f9f..12d8eeb27082a8ba43f91918c0577a4693cff31d 100644 (file)
@@ -561,7 +561,7 @@ gtk_text_buffer_insert_interactive (GtkTextBuffer *buffer,
   g_return_val_if_fail (text != NULL, FALSE);
   g_return_val_if_fail (gtk_text_iter_get_buffer (iter) == buffer, FALSE);
 
-  if (gtk_text_iter_editable (iter, default_editable))
+  if (gtk_text_iter_can_insert (iter, default_editable))
     {
       gtk_text_buffer_begin_user_action (buffer);
       gtk_text_buffer_emit_insert (buffer, iter, text, len);
@@ -965,7 +965,7 @@ gtk_text_buffer_insert_range_interactive (GtkTextBuffer     *buffer,
                         buffer->tag_table, FALSE);
 
 
-  if (gtk_text_iter_editable (iter, default_editable))
+  if (gtk_text_iter_can_insert (iter, default_editable))
     {
       gtk_text_buffer_real_insert_range (buffer, iter, start, end, TRUE);
       return TRUE;
index 6f7c778cdc0aca858e71e9f6f933a6a9b4582f2c..3e24beb385e1f7ab37fcc988978fc0e44ddb681f 100644 (file)
@@ -1242,8 +1242,8 @@ gtk_text_iter_ends_tag   (const GtkTextIter  *iter,
  * Return value: whether @tag is toggled on or off at @iter
  **/
 gboolean
-gtk_text_iter_toggles_tag       (const GtkTextIter  *iter,
-                                 GtkTextTag         *tag)
+gtk_text_iter_toggles_tag (const GtkTextIter  *iter,
+                           GtkTextTag         *tag)
 {
   GtkTextRealIter *real;
   GtkTextLineSegment *seg;
@@ -1282,8 +1282,8 @@ gtk_text_iter_toggles_tag       (const GtkTextIter  *iter,
  * Return value: whether @iter is tagged with @tag
  **/
 gboolean
-gtk_text_iter_has_tag           (const GtkTextIter   *iter,
-                                 GtkTextTag          *tag)
+gtk_text_iter_has_tag (const GtkTextIter   *iter,
+                       GtkTextTag          *tag)
 {
   GtkTextRealIter *real;
 
@@ -1300,13 +1300,13 @@ gtk_text_iter_has_tag           (const GtkTextIter   *iter,
   if (real->line_byte_offset >= 0)
     {
       return _gtk_text_line_byte_has_tag (real->line, real->tree,
-                                         real->line_byte_offset, tag);
+                                          real->line_byte_offset, tag);
     }
   else
     {
       g_assert (real->line_char_offset >= 0);
       return _gtk_text_line_char_has_tag (real->line, real->tree,
-                                         real->line_char_offset, tag);
+                                          real->line_char_offset, tag);
     }
 }
 
@@ -1363,14 +1363,21 @@ gtk_text_iter_get_tags (const GtkTextIter *iter)
 /**
  * gtk_text_iter_editable:
  * @iter: an iterator
- * @default_setting: TRUE if text is editable by default
+ * @default_setting: %TRUE if text is editable by default
  *
- * Returns whether @iter is within an editable region of text.
- * Non-editable text is "locked" and can't be changed by the user via
- * #GtkTextView. This function is simply a convenience wrapper around
- * gtk_text_iter_get_attributes (). If no tags applied to this text
- * affect editability, @default_setting will be returned.
+ * Returns whether the character at @iter is within an editable region
+ * of text.  Non-editable text is "locked" and can't be changed by the
+ * user via #GtkTextView. This function is simply a convenience
+ * wrapper around gtk_text_iter_get_attributes (). If no tags applied
+ * to this text affect editability, @default_setting will be returned.
  *
+ * You don't want to use this function to decide whether text can be
+ * inserted at @iter, because for insertion you don't want to know
+ * whether the char at @iter is inside an editable range, you want to
+ * know whether a new character inserted at @iter would be inside an
+ * editable range. Use gtk_text_iter_can_insert() to handle this
+ * case.
+ * 
  * Return value: whether @iter is inside an editable range
  **/
 gboolean
@@ -1380,6 +1387,8 @@ gtk_text_iter_editable (const GtkTextIter *iter,
   GtkTextAttributes *values;
   gboolean retval;
 
+  g_return_val_if_fail (iter != NULL, FALSE);
+  
   values = gtk_text_attributes_new ();
 
   values->editable = default_setting;
@@ -1393,6 +1402,46 @@ gtk_text_iter_editable (const GtkTextIter *iter,
   return retval;
 }
 
+/**
+ * gtk_text_iter_can_insert:
+ * @iter: an iterator
+ * @default_editability: %TRUE if text is editable by default
+ * 
+ * Considering the default editability of the buffer, and tags that
+ * affect editability, determines whether text inserted at @iter would
+ * be editable. If text inserted at @iter would be editable then the
+ * user should be allowed to insert text at @iter.
+ * gtk_text_buffer_insert_interactive() uses this function to decide
+ * whether insertions are allowed at a given position.
+ * 
+ * Return value: whether text inserted at @iter would be editable
+ **/
+gboolean
+gtk_text_iter_can_insert (const GtkTextIter *iter,
+                          gboolean           default_editability)
+{
+  g_return_val_if_fail (iter != NULL, FALSE);
+  
+  if (gtk_text_iter_editable (iter, default_editability))
+    return TRUE;
+  /* If at start/end of buffer, default editability is used */
+  else if ((gtk_text_iter_is_start (iter) ||
+            gtk_text_iter_is_end (iter)) &&
+           default_editability)
+    return TRUE;
+  else
+    {
+      /* if iter isn't editable, and the char before iter is,
+       * then iter is the first char in an editable region
+       * and thus insertion at iter results in editable text.
+       */
+      GtkTextIter prev = *iter;
+      gtk_text_iter_backward_char (&prev);
+      return gtk_text_iter_editable (&prev, default_editability);
+    }
+}
+
+
 /**
  * gtk_text_iter_get_language:
  * @iter: an iterator
@@ -1677,7 +1726,7 @@ gtk_text_iter_get_bytes_in_line (const GtkTextIter   *iter)
  **/
 gboolean
 gtk_text_iter_get_attributes (const GtkTextIter  *iter,
-                              GtkTextAttributes *values)
+                              GtkTextAttributes  *values)
 {
   GtkTextTag** tags;
   gint tag_count = 0;
@@ -2827,12 +2876,12 @@ find_line_log_attrs (const GtkTextIter *iter,
                                                iter, &char_len);      
 
   offset = gtk_text_iter_get_line_offset (iter);
-
+  
   /* char_len may be 0 and attrs will be NULL if so, if
    * iter is the end iter and the last line is empty
    */
   
-  if (offset < char_len)
+  if (attrs)
     result = (* func) (attrs, offset, 0, char_len, found_offset,
                        already_moved_initially);
 
@@ -2868,22 +2917,29 @@ find_by_log_attrs (GtkTextIter    *iter,
         }
       else
         {                    
-          /* go to end of previous line */
-          gtk_text_iter_set_line_offset (iter, 0);
-          
-          if (gtk_text_iter_backward_char (iter))
-            return find_by_log_attrs (iter, func, forward,
-                                      TRUE);
+          /* go to end of previous line. need to check that
+           * line is > 0 because backward_line snaps to start of
+           * line 0 if it's on line 0
+           */
+          if (gtk_text_iter_get_line (iter) > 0 && 
+              gtk_text_iter_backward_line (iter))
+            {
+              if (!gtk_text_iter_ends_line (iter))
+                gtk_text_iter_forward_to_line_end (iter);
+              
+              return find_by_log_attrs (iter, func, forward,
+                                        TRUE);
+            }
           else
             return FALSE;
         }
     }
   else
-    {
+    {      
       gtk_text_iter_set_line_offset (iter, offset);
 
       return
-        !gtk_text_iter_equal (iter, &orig) &&
+        (already_moved_initially || !gtk_text_iter_equal (iter, &orig)) &&
         !gtk_text_iter_is_end (iter);
     }
 }
@@ -3235,7 +3291,7 @@ find_backward_cursor_pos_func (const PangoLogAttr *attrs,
                                gint          len,
                                gint         *found_offset,
                                gboolean      already_moved_initially)
-{
+{  
   if (!already_moved_initially)
     --offset;
 
index e48ab466e4608b4686aae6a69652fc47811dab7f..72303ea931373522bf41f8064807955be42bf1e7 100644 (file)
@@ -128,6 +128,8 @@ GSList  *gtk_text_iter_get_tags          (const GtkTextIter   *iter);
 
 gboolean gtk_text_iter_editable          (const GtkTextIter   *iter,
                                           gboolean             default_setting);
+gboolean gtk_text_iter_can_insert        (const GtkTextIter   *iter,
+                                          gboolean             default_editability);
 
 gboolean gtk_text_iter_starts_word        (const GtkTextIter   *iter);
 gboolean gtk_text_iter_ends_word          (const GtkTextIter   *iter);
index f4f1c749ec0bb3155a412457190e9b49eaecbe8c..d71b4880f8cfc748a61f639cc5b63f8a289920e3 100644 (file)
@@ -1742,7 +1742,7 @@ gtk_text_tag_event (GtkTextTag        *tag,
   gboolean retval = FALSE;
 
   g_return_val_if_fail (GTK_IS_TEXT_TAG (tag), FALSE);
-  g_return_val_if_fail (GTK_IS_OBJECT (event_object), FALSE);
+  g_return_val_if_fail (G_IS_OBJECT (event_object), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
   g_signal_emit (G_OBJECT (tag),
index 254ad44c5ebc9c1ada7a2ed5482346903168e793..75df338719e5c3f3eacd8d2975422178799f6e26 100644 (file)
@@ -3250,7 +3250,7 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
 
   insert = gtk_text_buffer_get_insert (get_buffer (text_view));
   gtk_text_buffer_get_iter_at_mark (get_buffer (text_view), &iter, insert);
-  if (gtk_text_iter_editable (&iter, text_view->editable) &&
+  if (gtk_text_iter_can_insert (&iter, text_view->editable) &&
       gtk_im_context_filter_keypress (text_view->im_context, event))
     {
       text_view->need_im_reset = TRUE;
@@ -4829,7 +4829,7 @@ gtk_text_view_drag_motion (GtkWidget        *widget,
     }
   else
     {      
-      if (gtk_text_iter_editable (&newplace, text_view->editable))
+      if (gtk_text_iter_can_insert (&newplace, text_view->editable))
         {
           GtkWidget *source_widget;
           
@@ -5429,7 +5429,7 @@ gtk_text_view_do_popup (GtkTextView    *text_view,
                                     &iter,
                                     gtk_text_buffer_get_insert (get_buffer (text_view)));
   
-  can_insert = gtk_text_iter_editable (&iter, text_view->editable);
+  can_insert = gtk_text_iter_can_insert (&iter, text_view->editable);
   
   append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard",
                         have_selection);
index 4dcfa291c1b43fce31ccf6dd0bb718fb9ef35be9..9f2d332d75dce90768e95f07f60b59750050f652 100644 (file)
@@ -28,6 +28,8 @@ static void check_get_set_text (GtkTextBuffer *buffer,
 
 static void line_separator_tests (void);
 
+static void logical_motion_tests (void);
+
 int
 main (int argc, char** argv)
 {
@@ -48,6 +50,9 @@ main (int argc, char** argv)
 
   /* Check some line separator stuff */
   line_separator_tests ();
+
+  /* Check log attr motion */
+  logical_motion_tests ();
   
   /* Create a buffer */
   buffer = gtk_text_buffer_new (NULL);
@@ -884,4 +889,106 @@ line_separator_tests (void)
   str = g_strdup_printf ("line%sqw", buf);
   test_line_separation (str, TRUE, FALSE, 2, 4, 5);
   g_free (str);
+
+  g_print ("Line separator tests passed\n");
+}
+
+static void
+logical_motion_tests (void)
+{
+  char *str;
+  char buf1[7] = { '\0', };
+  char buf2[7] = { '\0', };
+  char buf3[7] = { '\0', };
+  int expected[30];
+  int expected_steps;
+  int i;
+  GtkTextBuffer *buffer;
+  GtkTextIter iter;
+  
+  buffer = gtk_text_buffer_new (NULL);
+  
+#define LEADING_JAMO 0x1111
+#define VOWEL_JAMO 0x1167
+#define TRAILING_JAMO 0x11B9
+  
+  g_unichar_to_utf8 (LEADING_JAMO, buf1);
+  g_unichar_to_utf8 (VOWEL_JAMO, buf2);
+  g_unichar_to_utf8 (TRAILING_JAMO, buf3);
+
+  /* Build the string "abc<leading><vowel><trailing>def\r\nxyz" */
+  str = g_strconcat ("abc", buf1, buf2, buf3, "def\r\nxyz", NULL);
+  gtk_text_buffer_set_text (buffer, str, -1);
+  g_free (str);
+  
+  /* Check cursor positions */
+  memset (expected, 0, sizeof (expected));
+  expected[0] = 0;    /* before 'a' */
+  expected[1] = 1;    /* before 'b' */
+  expected[2] = 2;    /* before 'c' */
+  expected[3] = 3;    /* before jamo */
+  expected[4] = 6;    /* before 'd' */
+  expected[5] = 7;    /* before 'e' */
+  expected[6] = 8;    /* before 'f' */
+  expected[7] = 9;    /* before '\r' */
+  expected[8] = 11;   /* before 'x' */
+  expected[9] = 12;   /* before 'y' */
+  expected[10] = 13;  /* before 'z' */
+  expected[11] = 14;  /* after 'z' */
+  expected_steps = 11;
+  
+  gtk_text_buffer_get_start_iter (buffer, &iter);
+  i = 0;
+  do
+    {
+      int pos;
+
+      pos = gtk_text_iter_get_offset (&iter);
+      
+      if (pos != expected[i])
+        {
+          g_error ("Cursor position %d, expected %d",
+                   pos, expected[i]);
+        }
+
+      /* g_print ("%d = %d\n", pos, expected[i]); */
+
+      ++i;      
+    }
+  while (gtk_text_iter_forward_cursor_position (&iter));
+
+  if (i != expected_steps)
+    g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
+
+  if (!gtk_text_iter_is_end (&iter))
+    g_error ("Expected to stop at the end iterator\n");
+
+  i = expected_steps;
+  do
+    {
+      int pos;
+
+      pos = gtk_text_iter_get_offset (&iter);
+      
+      if (pos != expected[i])
+        {
+          g_error ("Moving backward, cursor position %d, expected %d",
+                   pos, expected[i]);
+        }
+
+      /* g_print ("%d = %d\n", pos, expected[i]); */
+      
+      --i;
+    }
+  while (gtk_text_iter_backward_cursor_position (&iter));
+
+  if (i != -1)
+    g_error ("Expected %d steps, there were actually %d\n", expected_steps - i, i);
+
+  if (!gtk_text_iter_is_start (&iter))
+    g_error ("Expected to stop at the start iterator\n");
+  
+  g_print ("Logical motion tests passed\n");
+
+  g_object_unref (G_OBJECT (buffer));
 }