[gtk+/gtk-3-18] textbuffer: nicer get_iter functions
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-3-18] textbuffer: nicer get_iter functions
- Date: Mon, 9 Nov 2015 13:50:49 +0000 (UTC)
commit cf51c4f6dbd91dae1878a0cb0d08b24c67e15232
Author: Sébastien Wilmet <swilmet gnome org>
Date: Thu Oct 15 10:43:10 2015 +0200
textbuffer: nicer get_iter functions
Avoid crashes when passing an invalid location to a
gtk_text_buffer_get_iter_at_*() function.
A boolean is returned to know if @iter has been set to the exact
location.
Unit tests are added.
https://bugzilla.gnome.org/show_bug.cgi?id=735341
gtk/gtktextbuffer.c | 95 +++++++++++++++++++++++++++-------
gtk/gtktextbuffer.h | 34 ++++++------
testsuite/gtk/textbuffer.c | 123 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 215 insertions(+), 37 deletions(-)
---
diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index 1bf1b68..7295021 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -2862,22 +2862,48 @@ gtk_text_buffer_remove_all_tags (GtkTextBuffer *buffer,
* @line_number: line number counting from 0
* @char_offset: char offset from start of line
*
- * Obtains an iterator pointing to @char_offset within the given
- * line. The @char_offset must exist, offsets off the end of the line
- * are not allowed. Note characters, not bytes;
- * UTF-8 may encode one character as multiple bytes.
+ * Obtains an iterator pointing to @char_offset within the given line. Note
+ * characters, not bytes; UTF-8 may encode one character as multiple bytes.
+ *
+ * Before the 3.20 version, it was not allowed to pass an invalid location.
+ *
+ * Since the 3.20 version, if @line_number is greater than the number of lines
+ * in the @buffer, the end iterator is returned. And if @char_offset is off the
+ * end of the line, the iterator at the end of the line is returned.
+ *
+ * Returns: whether the exact position has been found (since 3.20).
**/
-void
+gboolean
gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
GtkTextIter *iter,
gint line_number,
gint char_offset)
{
- g_return_if_fail (iter != NULL);
- g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ GtkTextIter end_line_iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
+
+ if (line_number >= gtk_text_buffer_get_line_count (buffer))
+ {
+ gtk_text_buffer_get_end_iter (buffer, iter);
+ return FALSE;
+ }
+
+ _gtk_text_btree_get_iter_at_line_char (get_btree (buffer), iter, line_number, 0);
- _gtk_text_btree_get_iter_at_line_char (get_btree (buffer),
- iter, line_number, char_offset);
+ end_line_iter = *iter;
+ if (!gtk_text_iter_ends_line (&end_line_iter))
+ gtk_text_iter_forward_to_line_end (&end_line_iter);
+
+ if (char_offset > gtk_text_iter_get_line_offset (&end_line_iter))
+ {
+ *iter = end_line_iter;
+ return FALSE;
+ }
+
+ gtk_text_iter_set_line_offset (iter, char_offset);
+ return TRUE;
}
/**
@@ -2888,21 +2914,48 @@ gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
* @byte_index: byte index from start of line
*
* Obtains an iterator pointing to @byte_index within the given line.
- * @byte_index must be the start of a UTF-8 character, and must not be
- * beyond the end of the line. Note bytes, not
+ * @byte_index must be the start of a UTF-8 character. Note bytes, not
* characters; UTF-8 may encode one character as multiple bytes.
+ *
+ * Before the 3.20 version, it was not allowed to pass an invalid location.
+ *
+ * Since the 3.20 version, if @line_number is greater than the number of lines
+ * in the @buffer, the end iterator is returned. And if @byte_index is off the
+ * end of the line, the iterator at the end of the line is returned.
+ *
+ * Returns: whether the exact position has been found (since 3.20).
**/
-void
+gboolean
gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
GtkTextIter *iter,
gint line_number,
gint byte_index)
{
- g_return_if_fail (iter != NULL);
- g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ GtkTextIter end_line_iter;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
+
+ if (line_number >= gtk_text_buffer_get_line_count (buffer))
+ {
+ gtk_text_buffer_get_end_iter (buffer, iter);
+ return FALSE;
+ }
+
+ gtk_text_buffer_get_iter_at_line (buffer, iter, line_number);
+
+ end_line_iter = *iter;
+ if (!gtk_text_iter_ends_line (&end_line_iter))
+ gtk_text_iter_forward_to_line_end (&end_line_iter);
- _gtk_text_btree_get_iter_at_line_byte (get_btree (buffer),
- iter, line_number, byte_index);
+ if (byte_index > gtk_text_iter_get_line_index (&end_line_iter))
+ {
+ *iter = end_line_iter;
+ return FALSE;
+ }
+
+ gtk_text_iter_set_line_index (iter, byte_index);
+ return TRUE;
}
/**
@@ -2913,16 +2966,18 @@ gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
*
* Initializes @iter to the start of the given line. If @line_number is greater
* than the number of lines in the @buffer, the end iterator is returned.
+ *
+ * Returns: whether the exact position has been found (since 3.20).
**/
-void
+gboolean
gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
GtkTextIter *iter,
gint line_number)
{
- g_return_if_fail (iter != NULL);
- g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
- gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
+ return gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
}
/**
diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h
index 9227be8..8894542 100644
--- a/gtk/gtktextbuffer.h
+++ b/gtk/gtktextbuffer.h
@@ -373,23 +373,23 @@ GtkTextTag *gtk_text_buffer_create_tag (GtkTextBuffer *buffer,
* iterator around using the GtkTextIter operators
*/
GDK_AVAILABLE_IN_ALL
-void gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- gint line_number,
- gint char_offset);
-GDK_AVAILABLE_IN_ALL
-void gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- gint line_number,
- gint byte_index);
-GDK_AVAILABLE_IN_ALL
-void gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- gint char_offset);
-GDK_AVAILABLE_IN_ALL
-void gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
- GtkTextIter *iter,
- gint line_number);
+gboolean gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ gint line_number,
+ gint char_offset);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_text_buffer_get_iter_at_line_index (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ gint line_number,
+ gint byte_index);
+GDK_AVAILABLE_IN_ALL
+void gtk_text_buffer_get_iter_at_offset (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ gint char_offset);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ gint line_number);
GDK_AVAILABLE_IN_ALL
void gtk_text_buffer_get_start_iter (GtkTextBuffer *buffer,
GtkTextIter *iter);
diff --git a/testsuite/gtk/textbuffer.c b/testsuite/gtk/textbuffer.c
index 6e16ff2..37243dc 100644
--- a/testsuite/gtk/textbuffer.c
+++ b/testsuite/gtk/textbuffer.c
@@ -1434,6 +1434,128 @@ test_clipboard (void)
g_object_unref (buffer);
}
+static void
+test_get_iter (void)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ gint offset;
+
+ buffer = gtk_text_buffer_new (NULL);
+
+ /* ß takes 2 bytes in UTF-8 */
+ gtk_text_buffer_set_text (buffer, "ab\nßd\r\nef", -1);
+
+ /* Test get_iter_at_line() */
+ g_assert (gtk_text_buffer_get_iter_at_line (buffer, &iter, 0));
+ g_assert (gtk_text_iter_is_start (&iter));
+
+ g_assert (gtk_text_buffer_get_iter_at_line (buffer, &iter, 1));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 3);
+
+ g_assert (gtk_text_buffer_get_iter_at_line (buffer, &iter, 2));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 7);
+
+ g_assert (!gtk_text_buffer_get_iter_at_line (buffer, &iter, 3));
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ /* Test get_iter_at_line_offset() */
+ g_assert (gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 0));
+ g_assert (gtk_text_iter_is_start (&iter));
+
+ g_assert (gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 1));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 1);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 2));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 2);
+
+ g_assert (!gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 3));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 2);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 1, 1));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 4);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 2, 1));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 8);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 2, 2));
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ g_assert (!gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 2, 3));
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ g_assert (!gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 3, 1));
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ /* Test get_iter_at_line_index() */
+ g_assert (gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 0, 0));
+ g_assert (gtk_text_iter_is_start (&iter));
+
+ g_assert (gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 0, 1));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 1);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 0, 2));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 2);
+
+ g_assert (!gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 0, 3));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 2);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 1, 0));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 3);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 1, 2));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 4);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 1, 3));
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 5);
+
+ g_assert (gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 2, 2));
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ g_assert (!gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 2, 3));
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ g_assert (!gtk_text_buffer_get_iter_at_line_index (buffer, &iter, 3, 1));
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ /* Test get_iter_at_offset() */
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
+ g_assert (gtk_text_iter_is_start (&iter));
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 1);
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
+ offset = gtk_text_iter_get_offset (&iter);
+ g_assert_cmpint (offset, ==, 8);
+ g_assert (!gtk_text_iter_is_end (&iter));
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, 9);
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, 100);
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, -1);
+ g_assert (gtk_text_iter_is_end (&iter));
+
+ g_object_unref (buffer);
+}
+
int
main (int argc, char** argv)
{
@@ -1452,6 +1574,7 @@ main (int argc, char** argv)
g_test_add_func ("/TextBuffer/Fill and Empty", test_fill_empty);
g_test_add_func ("/TextBuffer/Tag", test_tag);
g_test_add_func ("/TextBuffer/Clipboard", test_clipboard);
+ g_test_add_func ("/TextBuffer/Get iter", test_get_iter);
return g_test_run();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]