Index: gtktextiter.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktextiter.c,v
retrieving revision 1.85.2.2
diff -u -p -r1.85.2.2 gtktextiter.c
--- gtktextiter.c	14 Nov 2005 04:24:02 -0000	1.85.2.2
+++ gtktextiter.c	15 Nov 2005 19:11:54 -0000
@@ -3891,12 +3891,6 @@ gtk_text_iter_set_visible_line_offset (G
     gtk_text_iter_forward_line (iter);
 }
 
-static gint
-bytes_in_char (GtkTextIter *iter)
-{
-  return g_unichar_to_utf8 (gtk_text_iter_get_char (iter), NULL);
-}
-
 /**
  * gtk_text_iter_set_visible_line_index:
  * @iter: a #GtkTextIter
@@ -3907,39 +3901,66 @@ bytes_in_char (GtkTextIter *iter)
  * in the index.
  **/
 void
-gtk_text_iter_set_visible_line_index  (GtkTextIter *iter,
-                                       gint         byte_on_line)
+gtk_text_iter_set_visible_line_index (GtkTextIter *iter,
+                                      gint         byte_on_line)
 {
+  GtkTextRealIter *real;
+  gint bytes_in_line = 0;
   gint bytes_seen = 0;
-  gint skipped = 0;
+  gint offset = 0;
   GtkTextIter pos;
+  GtkTextLineSegment *seg;
 
   g_return_if_fail (iter != NULL);
-  
+
   gtk_text_iter_set_line_offset (iter, 0);
 
   pos = *iter;
 
-  /* For now we use a ludicrously slow implementation */
+  real = gtk_text_iter_make_surreal (&pos);
+
+  if (real == NULL)
+    return;
+
+  check_invariants (iter);
+
+  bytes_in_line = gtk_text_iter_get_bytes_in_line (&pos);
+
+  g_return_if_fail (byte_on_line <= bytes_in_line);
+
+  seg = real->segment;
+
   while (bytes_seen < byte_on_line)
     {
-      if (!_gtk_text_btree_char_is_invisible (&pos))
-        bytes_seen += bytes_in_char (&pos);
-      else skipped++;
-
-      if (!gtk_text_iter_forward_char (&pos))
+      if (seg == NULL)
         break;
 
-      if (bytes_seen >= byte_on_line)
-        break;
+      if (_gtk_text_btree_char_is_invisible (&pos))
+        {
+          offset += seg->byte_count;
+          seg = seg->next;
+          iter_set_from_byte_offset (real, real->line, offset);
+          continue;
+        }
+
+      if (byte_on_line - bytes_seen > seg->byte_count)
+        {
+          offset += seg->byte_count;
+          bytes_seen += seg->byte_count;
+          seg = seg->next;
+          iter_set_from_byte_offset (real, real->line, offset);
+          continue;
+        }
+
+      if (offset + byte_on_line - bytes_seen <= bytes_in_line)
+        {
+          iter_set_from_byte_offset (real, real->line, offset + byte_on_line - bytes_seen);
+          break;
+        }
+
+      g_return_if_reached ();
     }
 
-  if (bytes_seen > byte_on_line)
-    g_warning ("%s: Incorrect visible byte index %d falls in the middle of a UTF-8 "
-               "character; this will crash the text buffer. "
-               "Byte indexes must refer to the start of a character.",
-               G_STRLOC, byte_on_line);
-  
   if (_gtk_text_iter_get_text_line (&pos) == _gtk_text_iter_get_text_line (iter))
     *iter = pos;
   else
@@ -4685,7 +4706,7 @@ gtk_text_iter_forward_search (const GtkT
         {
           if (limit == NULL ||
               (limit &&
-               gtk_text_iter_compare (&end, limit) <= 0))
+               gtk_text_iter_compare (&end, limit) < 0))
             {
               retval = TRUE;
               
