]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtktextiter.c
Fix backward search bug exposed by the unit test
[~andy/gtk] / gtk / gtktextiter.c
index a757ad3c67e7818aa0712880c4de6b63e954d47e..380778f90c8e4e483541e14b510b8dac58e9afb4 100644 (file)
  */
 
 #define GTK_TEXT_USE_INTERNAL_UNSUPPORTED_API
-#include <config.h>
+#include "config.h"
 #include "gtktextiter.h"
 #include "gtktextbtree.h"
 #include "gtktextiterprivate.h"
+#include "gtkintl.h"
 #include "gtkdebug.h"
-#include "gtkalias.h"
+
 #include <string.h>
 
+
+/**
+ * SECTION:gtktextiter
+ * @Short_description: Text buffer iterator
+ * @Title: GtkTextIter
+ *
+ * You may wish to begin by reading the <link linkend="TextWidget">text widget
+ * conceptual overview</link> which gives an overview of all the objects and data
+ * types related to the text widget and how they work together.
+ */
+
+
 #define FIX_OVERFLOWS(varname) if ((varname) == G_MININT) (varname) = G_MININT + 1
 
 typedef struct _GtkTextRealIter GtkTextRealIter;
 
-struct _GtkTextRealIter
+struct G_GNUC_MAY_ALIAS _GtkTextRealIter
 {
   /* Always-valid information */
   GtkTextBTree *tree;
@@ -299,24 +312,12 @@ iter_init_from_char_offset (GtkTextIter *iter,
   return real;
 }
 
-static inline void
-invalidate_segment (GtkTextRealIter *iter)
-{
-  iter->segments_changed_stamp -= 1;
-}
-
 static inline void
 invalidate_char_index (GtkTextRealIter *iter)
 {
   iter->cached_char_index = -1;
 }
 
-static inline void
-invalidate_line_number (GtkTextRealIter *iter)
-{
-  iter->cached_line_number = -1;
-}
-
 static inline void
 adjust_char_index (GtkTextRealIter *iter, gint count)
 {
@@ -331,28 +332,6 @@ adjust_line_number (GtkTextRealIter *iter, gint count)
     iter->cached_line_number += count;
 }
 
-static inline void
-adjust_char_offsets (GtkTextRealIter *iter, gint count)
-{
-  if (iter->line_char_offset >= 0)
-    {
-      iter->line_char_offset += count;
-      g_assert (iter->segment_char_offset >= 0);
-      iter->segment_char_offset += count;
-    }
-}
-
-static inline void
-adjust_byte_offsets (GtkTextRealIter *iter, gint count)
-{
-  if (iter->line_byte_offset >= 0)
-    {
-      iter->line_byte_offset += count;
-      g_assert (iter->segment_byte_offset >= 0);
-      iter->segment_byte_offset += count;
-    }
-}
-
 static inline void
 ensure_char_offsets (GtkTextRealIter *iter)
 {
@@ -391,11 +370,11 @@ is_segment_start (GtkTextRealIter *real)
 static void
 check_invariants (const GtkTextIter *iter)
 {
-  if (gtk_debug_flags & GTK_DEBUG_TEXT)
+  if (gtk_get_debug_flags () & GTK_DEBUG_TEXT)
     _gtk_text_iter_check (iter);
 }
 #else
-#define check_invariants (x)
+#define check_invariants(x)
 #endif
 
 /**
@@ -404,7 +383,7 @@ check_invariants (const GtkTextIter *iter)
  *
  * Returns the #GtkTextBuffer this iterator is associated with.
  *
- * Return value: the buffer
+ * Return value: (transfer none): the buffer
  **/
 GtkTextBuffer*
 gtk_text_iter_get_buffer (const GtkTextIter *iter)
@@ -465,18 +444,9 @@ gtk_text_iter_free (GtkTextIter *iter)
   g_slice_free (GtkTextIter, iter);
 }
 
-GType
-gtk_text_iter_get_type (void)
-{
-  static GType our_type = 0;
-  
-  if (our_type == 0)
-    our_type = g_boxed_type_register_static ("GtkTextIter",
-                                            (GBoxedCopyFunc) gtk_text_iter_copy,
-                                            (GBoxedFreeFunc) gtk_text_iter_free);
-
-  return our_type;
-}
+G_DEFINE_BOXED_TYPE (GtkTextIter, gtk_text_iter,
+                     gtk_text_iter_copy,
+                     gtk_text_iter_free)
 
 GtkTextLineSegment*
 _gtk_text_iter_get_indexable_segment (const GtkTextIter *iter)
@@ -1005,7 +975,7 @@ gtk_text_iter_get_visible_text (const GtkTextIter  *start,
  * (with no new reference count added). Otherwise,
  * %NULL is returned.
  *
- * Return value: the pixbuf at @iter
+ * Return value: (transfer none): the pixbuf at @iter
  **/
 GdkPixbuf*
 gtk_text_iter_get_pixbuf (const GtkTextIter *iter)
@@ -1035,7 +1005,7 @@ gtk_text_iter_get_pixbuf (const GtkTextIter *iter)
  * anchor is returned (with no new reference count added). Otherwise,
  * %NULL is returned.
  *
- * Return value: the anchor at @iter
+ * Return value: (transfer none): the anchor at @iter
  **/
 GtkTextChildAnchor*
 gtk_text_iter_get_child_anchor (const GtkTextIter *iter)
@@ -1067,7 +1037,7 @@ gtk_text_iter_get_child_anchor (const GtkTextIter *iter)
  * can exist in the same place. The returned list is not in any
  * meaningful order.
  *
- * Return value: list of #GtkTextMark
+ * Return value: (element-type GtkTextMark) (transfer container): list of #GtkTextMark
  **/
 GSList*
 gtk_text_iter_get_marks (const GtkTextIter *iter)
@@ -1113,7 +1083,7 @@ gtk_text_iter_get_marks (const GtkTextIter *iter)
  * a tag is toggled off, then some non-empty range following @iter
  * does <emphasis>not</emphasis> have the tag applied to it.
  *
- * Return value: tags toggled at this point
+ * Return value: (element-type GtkTextTag) (transfer container): tags toggled at this point
  **/
 GSList*
 gtk_text_iter_get_toggled_tags  (const GtkTextIter  *iter,
@@ -1162,7 +1132,7 @@ gtk_text_iter_get_toggled_tags  (const GtkTextIter  *iter,
 /**
  * gtk_text_iter_begins_tag:
  * @iter: an iterator
- * @tag: a #GtkTextTag, or %NULL
+ * @tag: (allow-none): a #GtkTextTag, or %NULL
  *
  * Returns %TRUE if @tag is toggled on at exactly this point. If @tag
  * is %NULL, returns %TRUE if any tag is toggled on at this point. Note
@@ -1208,7 +1178,7 @@ gtk_text_iter_begins_tag    (const GtkTextIter  *iter,
 /**
  * gtk_text_iter_ends_tag:
  * @iter: an iterator
- * @tag: a #GtkTextTag, or %NULL
+ * @tag: (allow-none): a #GtkTextTag, or %NULL
  *
  * Returns %TRUE if @tag is toggled off at exactly this point. If @tag
  * is %NULL, returns %TRUE if any tag is toggled off at this point. Note
@@ -1255,7 +1225,7 @@ gtk_text_iter_ends_tag   (const GtkTextIter  *iter,
 /**
  * gtk_text_iter_toggles_tag:
  * @iter: an iterator
- * @tag: a #GtkTextTag, or %NULL
+ * @tag: (allow-none): a #GtkTextTag, or %NULL
  *
  * This is equivalent to (gtk_text_iter_begins_tag () ||
  * gtk_text_iter_ends_tag ()), i.e. it tells you whether a range with
@@ -1340,8 +1310,8 @@ gtk_text_iter_has_tag (const GtkTextIter   *iter,
  * priority (highest-priority tags are last). The #GtkTextTag in the
  * list don't have a reference added, but you have to free the list
  * itself.
- * 
- * Return value: list of #GtkTextTag
+ *
+ * Return value: (element-type GtkTextTag) (transfer container): list of #GtkTextTag
  **/
 GSList*
 gtk_text_iter_get_tags (const GtkTextIter *iter)
@@ -1359,15 +1329,11 @@ gtk_text_iter_get_tags (const GtkTextIter *iter)
   /* No tags, use default style */
   if (tags == NULL || tag_count == 0)
     {
-      if (tags)
-        g_free (tags);
+      g_free (tags);
 
       return NULL;
     }
 
-  /* Sort tags in ascending order of priority */
-  _gtk_text_tag_array_sort (tags, tag_count);
-
   retval = NULL;
   i = 0;
   while (i < tag_count)
@@ -1564,10 +1530,23 @@ gtk_text_iter_ends_line (const GtkTextIter   *iter)
     return TRUE;
   else if (wc == '\n')
     {
+      GtkTextIter tmp = *iter;
+
       /* need to determine if a \r precedes the \n, in which case
-       * we aren't the end of the line
+       * we aren't the end of the line.
+       * Note however that if \r and \n are on different lines, they
+       * both are terminators. This for instance may happen after
+       * deleting some text:
+
+          1 some text\r    delete 'a'    1 some text\r
+          2 a\n            --------->    2 \n
+          3 ...                          3 ...
+
        */
-      GtkTextIter tmp = *iter;
+
+      if (gtk_text_iter_get_line_offset (&tmp) == 0)
+        return TRUE;
+
       if (!gtk_text_iter_backward_char (&tmp))
         return TRUE;
 
@@ -1764,15 +1743,11 @@ gtk_text_iter_get_attributes (const GtkTextIter  *iter,
   /* No tags, use default style */
   if (tags == NULL || tag_count == 0)
     {
-      if (tags)
-        g_free (tags);
+      g_free (tags);
 
       return FALSE;
     }
 
-  /* Sort tags in ascending order of priority */
-  _gtk_text_tag_array_sort (tags, tag_count);
-
   _gtk_text_attributes_fill_from_tags (values,
                                        tags,
                                        tag_count);
@@ -2501,10 +2476,10 @@ gtk_text_iter_backward_text_chars (GtkTextIter *iter,
  * gtk_text_iter_forward_line:
  * @iter: an iterator
  *
- * Moves @iter to the start of the next line. Returns %TRUE if there
- * was a next line to move to, and %FALSE if @iter was simply moved to
- * the end of the buffer and is now not dereferenceable, or if @iter was
- * already at the end of the buffer.
+ * Moves @iter to the start of the next line. If the iter is already on the
+ * last line of the buffer, moves the iter to the end of the current line.
+ * If after the operation, the iter is at the end of the buffer and not
+ * dereferencable, returns %FALSE. Otherwise, returns %TRUE.
  *
  * Return value: whether @iter can be dereferenced
  **/
@@ -3267,7 +3242,7 @@ gtk_text_iter_forward_word_ends (GtkTextIter      *iter,
 }
 
 /**
- * gtk_text_iter_backward_word_starts
+ * gtk_text_iter_backward_word_starts:
  * @iter: a #GtkTextIter
  * @count: number of times to move
  * 
@@ -3345,7 +3320,7 @@ gtk_text_iter_forward_visible_word_ends (GtkTextIter *iter,
 }
 
 /**
- * gtk_text_iter_backward_visible_word_starts
+ * gtk_text_iter_backward_visible_word_starts:
  * @iter: a #GtkTextIter
  * @count: number of times to move
  * 
@@ -3904,7 +3879,6 @@ gtk_text_iter_set_visible_line_index (GtkTextIter *iter,
                                       gint         byte_on_line)
 {
   GtkTextRealIter *real;
-  gint bytes_in_line = 0;
   gint offset = 0;
   GtkTextIter pos;
   GtkTextLineSegment *seg;
@@ -3913,8 +3887,6 @@ gtk_text_iter_set_visible_line_index (GtkTextIter *iter,
 
   gtk_text_iter_set_line_offset (iter, 0);
 
-  bytes_in_line = gtk_text_iter_get_bytes_in_line (iter);
-
   pos = *iter;
 
   real = gtk_text_iter_make_real (&pos);
@@ -4142,7 +4114,7 @@ gtk_text_iter_forward_to_line_end (GtkTextIter *iter)
 /**
  * gtk_text_iter_forward_to_tag_toggle:
  * @iter: a #GtkTextIter
- * @tag: a #GtkTextTag, or %NULL
+ * @tag: (allow-none): a #GtkTextTag, or %NULL
  *
  * Moves forward to the next toggle (on or off) of the
  * #GtkTextTag @tag, or to the next toggle of any tag if
@@ -4224,7 +4196,7 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
 /**
  * gtk_text_iter_backward_to_tag_toggle:
  * @iter: a #GtkTextIter
- * @tag: a #GtkTextTag, or %NULL
+ * @tag: (allow-none): a #GtkTextTag, or %NULL
  *
  * Moves backward to the next toggle (on or off) of the
  * #GtkTextTag @tag, or to the next toggle of any tag if
@@ -4337,9 +4309,9 @@ matches_pred (GtkTextIter *iter,
 /**
  * gtk_text_iter_forward_find_char:
  * @iter: a #GtkTextIter
- * @pred: a function to be called on each character
+ * @pred: (scope call): a function to be called on each character
  * @user_data: user data for @pred
- * @limit: search limit, or %NULL for none 
+ * @limit: (allow-none): search limit, or %NULL for none 
  * 
  * Advances @iter, calling @pred on each character. If
  * @pred returns %TRUE, returns %TRUE and stops scanning.
@@ -4375,9 +4347,9 @@ gtk_text_iter_forward_find_char (GtkTextIter         *iter,
 /**
  * gtk_text_iter_backward_find_char:
  * @iter: a #GtkTextIter
- * @pred: function to be called on each character
+ * @pred: (scope call): function to be called on each character
  * @user_data: user data for @pred
- * @limit: search limit, or %NULL for none
+ * @limit: (allow-none): search limit, or %NULL for none
  * 
  * Same as gtk_text_iter_forward_find_char(), but goes backward from @iter.
  * 
@@ -4602,12 +4574,12 @@ strbreakup (const char *string,
  * @iter: start of search
  * @str: a search string
  * @flags: flags affecting how the search is done
- * @match_start: return location for start of match, or %NULL
- * @match_end: return location for end of match, or %NULL
- * @limit: bound for the search, or %NULL for the end of the buffer
- * 
- * Searches forward for @str. Any match is returned by setting 
- * @match_start to the first character of the match and @match_end to the 
+ * @match_start: (out caller-allocates) (allow-none): return location for start of match, or %NULL
+ * @match_end: (out caller-allocates) (allow-none): return location for end of match, or %NULL
+ * @limit: (allow-none): bound for the search, or %NULL for the end of the buffer
+ *
+ * Searches forward for @str. Any match is returned by setting
+ * @match_start to the first character of the match and @match_end to the
  * first character after the match. The search will not continue past
  * @limit. Note that a search is a linear or O(n) operation, so you
  * may wish to use @limit to avoid locking up your UI on large
@@ -4831,6 +4803,8 @@ lines_window_init (LinesWindow       *win,
         }
 
       win->lines[i] = line_text;
+      win->first_line_start = line_start;
+      win->first_line_end = line_end;
 
       line_end = line_start;
       gtk_text_iter_backward_line (&line_start);
@@ -4899,12 +4873,12 @@ lines_window_free (LinesWindow *win)
  * @iter: a #GtkTextIter where the search begins
  * @str: search string
  * @flags: bitmask of flags affecting the search
- * @match_start: return location for start of match, or %NULL
- * @match_end: return location for end of match, or %NULL
- * @limit: location of last possible @match_start, or %NULL for start of buffer
- * 
+ * @match_start: (out caller-allocates) (allow-none): return location for start of match, or %NULL
+ * @match_end: (out caller-allocates) (allow-none): return location for end of match, or %NULL
+ * @limit: (allow-none): location of last possible @match_start, or %NULL for start of buffer
+ *
  * Same as gtk_text_iter_forward_search(), but moves backward.
- * 
+ *
  * Return value: whether a match was found
  **/
 gboolean
@@ -5603,6 +5577,3 @@ _gtk_text_iter_check (const GtkTextIter *iter)
   if (_gtk_text_line_is_last (real->line, real->tree))
     g_error ("Iterator was on last line (past the end iterator)");
 }
-
-#define __GTK_TEXT_ITER_C__
-#include "gtkaliasdef.c"