1 /* testtextbuffer.c -- Simplistic test suite
2 * Copyright (C) 2000 Red Hat, Inc
3 * Author: Havoc Pennington
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
26 #include "gtk/gtktexttypes.h" /* Private header, for UNKNOWN_CHAR */
29 gtk_text_iter_spew (const GtkTextIter *iter, const gchar *desc)
31 g_print (" %20s: line %d / char %d / line char %d / line byte %d\n",
33 gtk_text_iter_get_line (iter),
34 gtk_text_iter_get_offset (iter),
35 gtk_text_iter_get_line_offset (iter),
36 gtk_text_iter_get_line_index (iter));
40 check_get_set_text (GtkTextBuffer *buffer,
43 GtkTextIter start, end, iter;
47 gtk_text_buffer_set_text (buffer, str, -1);
48 if (gtk_text_buffer_get_char_count (buffer) != g_utf8_strlen (str, -1))
49 g_error ("Wrong number of chars (%d not %d)",
50 gtk_text_buffer_get_char_count (buffer),
51 (int) g_utf8_strlen (str, -1));
52 gtk_text_buffer_get_bounds (buffer, &start, &end);
53 text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
54 if (strcmp (text, str) != 0)
55 g_error ("Got '%s' as buffer contents", text);
58 /* line char counts */
63 n += gtk_text_iter_get_chars_in_line (&iter);
65 while (gtk_text_iter_forward_line (&iter));
67 if (n != gtk_text_buffer_get_char_count (buffer))
68 g_error ("Sum of chars in lines is %d but buffer char count is %d",
69 n, gtk_text_buffer_get_char_count (buffer));
71 /* line byte counts */
76 n += gtk_text_iter_get_bytes_in_line (&iter);
78 while (gtk_text_iter_forward_line (&iter));
80 if (n != strlen (str))
81 g_error ("Sum of chars in lines is %d but buffer byte count is %d",
82 n, (int) strlen (str));
84 gtk_text_buffer_set_text (buffer, "", -1);
86 n = gtk_text_buffer_get_line_count (buffer);
88 g_error ("%d lines, expected 1", n);
90 n = gtk_text_buffer_get_char_count (buffer);
92 g_error ("%d chars, expected 0", n);
96 count_toggles_at_iter (GtkTextIter *iter,
103 /* get toggle-ons and toggle-offs */
104 tags = gtk_text_iter_get_toggled_tags (iter, TRUE);
105 tags = g_slist_concat (tags,
106 gtk_text_iter_get_toggled_tags (iter, FALSE));
113 else if (of_tag == tmp->data)
116 tmp = g_slist_next (tmp);
125 count_toggles_in_range_by_char (GtkTextBuffer *buffer,
127 const GtkTextIter *start,
128 const GtkTextIter *end)
136 count += count_toggles_at_iter (&iter, of_tag);
137 if (!gtk_text_iter_forward_char (&iter))
140 count += count_toggles_at_iter (&iter, of_tag);
144 while (gtk_text_iter_compare (&iter, end) <= 0);
150 count_toggles_in_buffer (GtkTextBuffer *buffer,
153 GtkTextIter start, end;
155 gtk_text_buffer_get_bounds (buffer, &start, &end);
157 return count_toggles_in_range_by_char (buffer, of_tag, &start, &end);
161 check_specific_tag_in_range (GtkTextBuffer *buffer,
162 const gchar *tag_name,
163 const GtkTextIter *start,
164 const GtkTextIter *end)
173 if (gtk_text_iter_compare (start, end) > 0)
175 g_print (" (inverted range for checking tags, skipping)\n");
179 tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer),
182 buffer_count = count_toggles_in_range_by_char (buffer, tag, start, end);
189 if (gtk_text_iter_toggles_tag (&iter, tag) ||
190 gtk_text_iter_forward_to_tag_toggle (&iter, tag))
198 this_offset = gtk_text_iter_get_offset (&iter);
200 if (this_offset <= last_offset)
201 g_error ("forward_to_tag_toggle moved in wrong direction");
203 last_offset = this_offset;
205 if (gtk_text_iter_begins_tag (&iter, tag))
208 g_error ("Tag %p is already on, and was toggled on?", tag);
211 else if (gtk_text_iter_ends_tag (&iter, tag))
214 g_error ("Tag %p toggled off, but wasn't toggled on?", tag);
218 g_error ("forward_to_tag_toggle went to a location without a toggle");
220 while (gtk_text_iter_forward_to_tag_toggle (&iter, tag) &&
221 gtk_text_iter_compare (&iter, end) <= 0);
224 if (count != buffer_count)
225 g_error ("Counted %d tags iterating by char, %d iterating forward by tag toggle\n",
226 buffer_count, count);
232 last_offset = gtk_text_iter_get_offset (&iter);
233 if (gtk_text_iter_toggles_tag (&iter, tag) ||
234 gtk_text_iter_backward_to_tag_toggle (&iter, tag))
242 this_offset = gtk_text_iter_get_offset (&iter);
244 if (this_offset >= last_offset)
245 g_error ("backward_to_tag_toggle moved in wrong direction");
247 last_offset = this_offset;
249 if (gtk_text_iter_begins_tag (&iter, tag))
252 g_error ("Tag %p wasn't on when we got to the on toggle going backward?", tag);
255 else if (gtk_text_iter_ends_tag (&iter, tag))
258 g_error ("Tag %p off toggle, but we were already inside a tag?", tag);
262 g_error ("backward_to_tag_toggle went to a location without a toggle");
264 while (gtk_text_iter_backward_to_tag_toggle (&iter, tag) &&
265 gtk_text_iter_compare (&iter, start) >= 0);
268 if (count != buffer_count)
269 g_error ("Counted %d tags iterating by char, %d iterating backward by tag toggle\n",
270 buffer_count, count);
274 check_specific_tag (GtkTextBuffer *buffer,
275 const gchar *tag_name)
277 GtkTextIter start, end;
279 gtk_text_buffer_get_bounds (buffer, &start, &end);
280 check_specific_tag_in_range (buffer, tag_name, &start, &end);
281 gtk_text_iter_forward_chars (&start, 2);
282 gtk_text_iter_backward_chars (&end, 2);
283 if (gtk_text_iter_compare (&start, &end) < 0)
284 check_specific_tag_in_range (buffer, tag_name, &start, &end);
288 run_tests (GtkTextBuffer *buffer)
296 GtkTextMark *bar_mark;
298 GHashTable *tag_states;
302 gtk_text_buffer_get_bounds (buffer, &start, &end);
304 /* Check that walking the tree via chars and via iterators produces
305 * the same number of indexable locations.
307 num_chars = gtk_text_buffer_get_char_count (buffer);
309 bar_mark = gtk_text_buffer_create_mark (buffer, "bar", &iter, FALSE);
311 while (i < num_chars)
314 GtkTextMark *foo_mark;
316 gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
318 if (!gtk_text_iter_equal (&iter, ¤t))
320 g_error ("get_char_index didn't return current iter");
323 j = gtk_text_iter_get_offset (&iter);
327 g_error ("iter converted to %d not %d", j, i);
331 gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
333 if (!gtk_text_iter_equal (&iter, &mark))
335 gtk_text_iter_spew (&iter, "iter");
336 gtk_text_iter_spew (&mark, "mark");
337 g_error ("Mark not moved to the right place.");
340 foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
341 gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
342 gtk_text_buffer_delete_mark (buffer, foo_mark);
344 if (!gtk_text_iter_equal (&iter, &mark))
346 gtk_text_iter_spew (&iter, "iter");
347 gtk_text_iter_spew (&mark, "mark");
348 g_error ("Mark not created in the right place.");
351 if (gtk_text_iter_is_end (&iter))
352 g_error ("iterators ran out before chars (offset %d of %d)",
355 gtk_text_iter_forward_char (&iter);
357 gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
362 if (!gtk_text_iter_equal (&iter, &end))
363 g_error ("Iterating over all chars didn't end with the end iter");
365 /* Do the tree-walk backward
367 num_chars = gtk_text_buffer_get_char_count (buffer);
368 gtk_text_buffer_get_iter_at_offset (buffer, &iter, -1);
370 gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
374 if (!gtk_text_iter_equal (&iter, &end))
375 g_error ("iter at char -1 is not equal to the end iterator");
380 GtkTextMark *foo_mark;
382 gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
384 if (!gtk_text_iter_equal (&iter, ¤t))
386 g_error ("get_char_index didn't return current iter while going backward");
388 j = gtk_text_iter_get_offset (&iter);
392 g_error ("going backward, iter converted to %d not %d", j, i);
396 gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
398 if (!gtk_text_iter_equal (&iter, &mark))
400 gtk_text_iter_spew (&iter, "iter");
401 gtk_text_iter_spew (&mark, "mark");
402 g_error ("Mark not moved to the right place.");
405 foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
406 gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
407 gtk_text_buffer_delete_mark (buffer, foo_mark);
409 if (!gtk_text_iter_equal (&iter, &mark))
411 gtk_text_iter_spew (&iter, "iter");
412 gtk_text_iter_spew (&mark, "mark");
413 g_error ("Mark not created in the right place.");
418 if (!gtk_text_iter_backward_char (&iter))
419 g_error ("iterators ran out before char indexes");
421 gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
425 if (gtk_text_iter_backward_char (&iter))
426 g_error ("went backward from 0?");
432 if (!gtk_text_iter_equal (&iter, &start))
433 g_error ("Iterating backward over all chars didn't end with the start iter");
436 * Check that get_line_count returns the same number of lines
437 * as walking the tree by line
439 i = 1; /* include current (first) line */
440 gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
441 while (gtk_text_iter_forward_line (&iter))
444 if (i != gtk_text_buffer_get_line_count (buffer))
445 g_error ("Counted %d lines, buffer has %d", i,
446 gtk_text_buffer_get_line_count (buffer));
449 * Check that moving over tag toggles thinks about working.
452 buffer_count = count_toggles_in_buffer (buffer, NULL);
454 tag_states = g_hash_table_new (NULL, NULL);
457 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
458 if (gtk_text_iter_toggles_tag (&iter, NULL) ||
459 gtk_text_iter_forward_to_tag_toggle (&iter, NULL))
465 gboolean found_some = FALSE;
467 /* get toggled-on tags */
468 tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
480 if (g_hash_table_lookup (tag_states, tag))
481 g_error ("Tag %p is already on, and was toggled on?", tag);
483 g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
485 tmp = g_slist_next (tmp);
490 /* get toggled-off tags */
491 tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
503 if (!g_hash_table_lookup (tag_states, tag))
504 g_error ("Tag %p is already off, and was toggled off?", tag);
506 g_hash_table_remove (tag_states, tag);
508 tmp = g_slist_next (tmp);
514 g_error ("No tags found going forward to tag toggle.");
517 while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL));
520 g_hash_table_destroy (tag_states);
522 if (count != buffer_count)
523 g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
524 buffer_count, count);
526 /* Go backward; here TRUE in the hash means we saw
527 * an off toggle last.
530 tag_states = g_hash_table_new (NULL, NULL);
533 gtk_text_buffer_get_end_iter (buffer, &iter);
534 if (gtk_text_iter_toggles_tag (&iter, NULL) ||
535 gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
541 gboolean found_some = FALSE;
543 /* get toggled-off tags */
544 tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
556 if (g_hash_table_lookup (tag_states, tag))
557 g_error ("Tag %p has two off-toggles in a row?", tag);
559 g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
561 tmp = g_slist_next (tmp);
566 /* get toggled-on tags */
567 tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
579 if (!g_hash_table_lookup (tag_states, tag))
580 g_error ("Tag %p was toggled on, but saw no off-toggle?", tag);
582 g_hash_table_remove (tag_states, tag);
584 tmp = g_slist_next (tmp);
590 g_error ("No tags found going backward to tag toggle.");
592 while (gtk_text_iter_backward_to_tag_toggle (&iter, NULL));
595 g_hash_table_destroy (tag_states);
597 if (count != buffer_count)
598 g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
599 buffer_count, count);
601 check_specific_tag (buffer, "fg_red");
602 check_specific_tag (buffer, "bg_green");
603 check_specific_tag (buffer, "front_tag");
604 check_specific_tag (buffer, "center_tag");
605 check_specific_tag (buffer, "end_tag");
609 static const char *book_closed_xpm[] = {
635 fill_buffer (GtkTextBuffer *buffer)
638 GdkColor color, color2;
644 color.red = color.green = 0;
650 gtk_text_buffer_create_tag (buffer, "fg_blue",
651 "foreground_gdk", &color,
652 "background_gdk", &color2,
653 "font", "-*-courier-bold-r-*-*-30-*-*-*-*-*-*-*",
656 color.blue = color.green = 0;
659 gtk_text_buffer_create_tag (buffer, "fg_red",
661 "foreground_gdk", &color,
664 color.blue = color.red = 0;
665 color.green = 0xffff;
667 gtk_text_buffer_create_tag (buffer, "bg_green",
668 "background_gdk", &color,
669 "font", "-*-courier-bold-r-*-*-10-*-*-*-*-*-*-*",
672 pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
674 g_assert (pixbuf != NULL);
681 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
683 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
685 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
687 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
689 str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
692 gtk_text_buffer_insert (buffer, &iter, str, -1);
696 gtk_text_buffer_insert (buffer, &iter,
697 "(Hello World!)\nfoo foo Hello this is some text we are using to text word wrap. It has punctuation! gee; blah - hmm, great.\nnew line\n\n"
698 /* This is UTF8 stuff, Emacs doesn't
699 really know how to display it */
700 "Spanish (Espa\303\261ol) \302\241Hola! / French (Fran\303\247ais) Bonjour, Salut / German (Deutsch S\303\274d) Gr\303\274\303\237 Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash) (\340\270\240\340\270\262\340\270\251\340\270\262\340\271\204\340\270\227\340\270\242) \340\270\252\340\270\247\340\270\261\340\270\252\340\270\224\340\270\265\340\270\204\340\270\243\340\270\261\340\270\232, \340\270\252\340\270\247\340\270\261\340\270\252\340\270\224\340\270\265\340\270\204\340\271\210\340\270\260\n",
703 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
704 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
706 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
708 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
710 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
712 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
714 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
716 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
718 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
720 gtk_text_iter_forward_chars (&iter2, 10);
722 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
724 gtk_text_iter_forward_chars (&iter, 7);
725 gtk_text_iter_forward_chars (&iter2, 10);
727 gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
729 gtk_text_iter_forward_chars (&iter, 12);
730 gtk_text_iter_forward_chars (&iter2, 10);
732 gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
734 gtk_text_iter_forward_chars (&iter, 10);
735 gtk_text_iter_forward_chars (&iter2, 15);
737 gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
738 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
740 gtk_text_iter_forward_chars (&iter, 20);
741 gtk_text_iter_forward_chars (&iter2, 20);
743 gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
744 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
746 gtk_text_iter_backward_chars (&iter, 25);
747 gtk_text_iter_forward_chars (&iter2, 5);
749 gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
750 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
752 gtk_text_iter_forward_chars (&iter, 15);
753 gtk_text_iter_backward_chars (&iter2, 10);
755 gtk_text_buffer_remove_tag_by_name (buffer, "fg_red", &iter, &iter2);
756 gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
761 /* Put in tags that are just at the beginning, and just near the end,
762 * and just near the middle.
764 tag = gtk_text_buffer_create_tag (buffer, "front_tag", NULL);
765 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 3);
766 gtk_text_buffer_get_iter_at_offset (buffer, &iter2, 300);
768 gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
770 tag = gtk_text_buffer_create_tag (buffer, "end_tag", NULL);
771 gtk_text_buffer_get_end_iter (buffer, &iter2);
772 gtk_text_iter_backward_chars (&iter2, 12);
774 gtk_text_iter_backward_chars (&iter, 157);
776 gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
778 tag = gtk_text_buffer_create_tag (buffer, "center_tag", NULL);
779 gtk_text_buffer_get_iter_at_offset (buffer, &iter,
780 gtk_text_buffer_get_char_count (buffer)/2);
781 gtk_text_iter_backward_chars (&iter, 37);
783 gtk_text_iter_forward_chars (&iter2, 57);
785 gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
787 g_object_unref (pixbuf);
792 * Line separator tests (initially to avoid regression on bugzilla #57428)
796 test_line_separation (const char* str,
797 gboolean expect_next_line,
798 gboolean expect_end_iter,
799 int expected_line_count,
800 int expected_line_break,
801 int expected_next_line_start)
804 GtkTextBuffer* buffer;
805 gboolean on_next_line;
806 gboolean on_end_iter;
809 buffer = gtk_text_buffer_new (NULL);
811 gtk_text_buffer_set_text (buffer, str, -1);
812 gtk_text_buffer_get_iter_at_offset (buffer, &iter, expected_line_break);
814 g_assert (gtk_text_iter_ends_line (&iter) || gtk_text_iter_is_end (&iter));
816 g_assert (gtk_text_buffer_get_line_count (buffer) == expected_line_count);
818 on_next_line = gtk_text_iter_forward_line (&iter);
820 g_assert (expect_next_line == on_next_line);
822 on_end_iter = gtk_text_iter_is_end (&iter);
824 g_assert (on_end_iter == expect_end_iter);
826 new_pos = gtk_text_iter_get_offset (&iter);
829 g_assert (expected_next_line_start == new_pos);
831 ++expected_line_break;
832 while (expected_line_break < expected_next_line_start)
834 gtk_text_buffer_get_iter_at_offset (buffer, &iter, expected_line_break);
836 g_assert (!gtk_text_iter_ends_line (&iter));
838 on_next_line = gtk_text_iter_forward_line (&iter);
840 g_assert (expect_next_line == on_next_line);
842 new_pos = gtk_text_iter_get_offset (&iter);
845 g_assert (expected_next_line_start == new_pos);
847 ++expected_line_break;
850 /* FIXME tests for backward line */
852 g_object_unref (buffer);
855 /* there are cases where \r and \n should not be treated like \r\n,
856 * originally bug #337022. */
858 split_r_n_separators_test (void)
860 GtkTextBuffer *buffer;
863 buffer = gtk_text_buffer_new (NULL);
865 gtk_text_buffer_set_text (buffer, "foo\ra\nbar\n", -1);
867 /* delete 'a' so that we have
873 * and both \r and \n are line separators */
875 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 5);
876 gtk_text_buffer_backspace (buffer, &iter, TRUE, TRUE);
878 g_assert (gtk_text_iter_ends_line (&iter));
880 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 3);
881 g_assert (gtk_text_iter_ends_line (&iter));
883 g_object_unref (buffer);
887 test_line_separator (void)
890 char buf[7] = { '\0', };
892 /* Only one character has type G_UNICODE_PARAGRAPH_SEPARATOR in
893 * Unicode 3.0; update this if that changes.
895 #define PARAGRAPH_SEPARATOR 0x2029
897 test_line_separation ("line", FALSE, TRUE, 1, 4, 4);
898 test_line_separation ("line\r\n", FALSE, TRUE, 2, 4, 6);
899 test_line_separation ("line\r", FALSE, TRUE, 2, 4, 5);
900 test_line_separation ("line\n", FALSE, TRUE, 2, 4, 5);
901 test_line_separation ("line\rqw", TRUE, FALSE, 2, 4, 5);
902 test_line_separation ("line\nqw", TRUE, FALSE, 2, 4, 5);
903 test_line_separation ("line\r\nqw", TRUE, FALSE, 2, 4, 6);
905 g_unichar_to_utf8 (PARAGRAPH_SEPARATOR, buf);
907 str = g_strdup_printf ("line%s", buf);
908 test_line_separation (str, FALSE, TRUE, 2, 4, 5);
910 str = g_strdup_printf ("line%sqw", buf);
911 test_line_separation (str, TRUE, FALSE, 2, 4, 5);
914 split_r_n_separators_test ();
918 test_backspace (void)
920 GtkTextBuffer *buffer;
924 buffer = gtk_text_buffer_new (NULL);
926 gtk_text_buffer_set_text (buffer, "foo", -1);
927 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 2);
928 ret = gtk_text_buffer_backspace (buffer, &iter, TRUE, TRUE);
930 g_assert_cmpint (1, ==, gtk_text_iter_get_offset (&iter));
931 g_assert_cmpint (2, ==, gtk_text_buffer_get_char_count (buffer));
933 gtk_text_buffer_set_text (buffer, "foo", -1);
934 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
935 ret = gtk_text_buffer_backspace (buffer, &iter, TRUE, TRUE);
937 g_assert_cmpint (0, ==, gtk_text_iter_get_offset (&iter));
938 g_assert_cmpint (3, ==, gtk_text_buffer_get_char_count (buffer));
940 /* test bug #544724 */
941 gtk_text_buffer_set_text (buffer, "foo\r\n\r\nbar", -1);
942 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 5);
943 ret = gtk_text_buffer_backspace (buffer, &iter, TRUE, TRUE);
945 g_assert_cmpint (0, ==, gtk_text_iter_get_line (&iter));
946 g_assert_cmpint (8, ==, gtk_text_buffer_get_char_count (buffer));
948 g_object_unref (buffer);
952 test_logical_motion (void)
955 char buf1[7] = { '\0', };
956 char buf2[7] = { '\0', };
957 char buf3[7] = { '\0', };
961 GtkTextBuffer *buffer;
964 buffer = gtk_text_buffer_new (NULL);
966 #define LEADING_JAMO 0x1111
967 #define VOWEL_JAMO 0x1167
968 #define TRAILING_JAMO 0x11B9
970 g_unichar_to_utf8 (LEADING_JAMO, buf1);
971 g_unichar_to_utf8 (VOWEL_JAMO, buf2);
972 g_unichar_to_utf8 (TRAILING_JAMO, buf3);
974 /* Build the string "abc<leading><vowel><trailing>def\r\nxyz" */
975 str = g_strconcat ("abc", buf1, buf2, buf3, "def\r\nxyz", NULL);
976 gtk_text_buffer_set_text (buffer, str, -1);
979 /* Check cursor positions */
980 memset (expected, 0, sizeof (expected));
981 expected[0] = 0; /* before 'a' */
982 expected[1] = 1; /* before 'b' */
983 expected[2] = 2; /* before 'c' */
984 expected[3] = 3; /* before jamo */
985 expected[4] = 6; /* before 'd' */
986 expected[5] = 7; /* before 'e' */
987 expected[6] = 8; /* before 'f' */
988 expected[7] = 9; /* before '\r' */
989 expected[8] = 11; /* before 'x' */
990 expected[9] = 12; /* before 'y' */
991 expected[10] = 13; /* before 'z' */
992 expected[11] = 14; /* after 'z' (only matters going backward) */
995 gtk_text_buffer_get_start_iter (buffer, &iter);
1001 pos = gtk_text_iter_get_offset (&iter);
1003 if (pos != expected[i])
1005 g_error ("Cursor position %d, expected %d",
1011 while (gtk_text_iter_forward_cursor_position (&iter));
1013 if (!gtk_text_iter_is_end (&iter))
1014 g_error ("Expected to stop at the end iterator\n");
1016 if (!gtk_text_iter_is_cursor_position (&iter))
1017 g_error ("Should be a cursor position before the end iterator");
1019 if (i != expected_steps)
1020 g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1027 pos = gtk_text_iter_get_offset (&iter);
1029 if (pos != expected[i])
1031 g_error ("Moving backward, cursor position %d, expected %d",
1035 /* g_print ("%d = %d\n", pos, expected[i]); */
1039 while (gtk_text_iter_backward_cursor_position (&iter));
1042 g_error ("Expected %d steps, there were actually %d\n", expected_steps - i, i);
1044 if (!gtk_text_iter_is_start (&iter))
1045 g_error ("Expected to stop at the start iterator\n");
1048 /* Check sentence boundaries */
1050 gtk_text_buffer_set_text (buffer, "Hi.\nHi. \nHi! Hi. Hi? Hi.", -1);
1052 memset (expected, 0, sizeof (expected));
1054 expected[0] = 0; /* before first Hi */
1055 expected[1] = 3; /* After first . */
1056 expected[2] = 7; /* After second . */
1057 expected[3] = 12; /* After ! */
1058 expected[4] = 16; /* After third . */
1059 expected[5] = 20; /* After ? */
1063 gtk_text_buffer_get_start_iter (buffer, &iter);
1069 pos = gtk_text_iter_get_offset (&iter);
1071 if (pos != expected[i])
1073 g_error ("Sentence position %d, expected %d",
1078 !gtk_text_iter_is_end (&iter) &&
1079 !gtk_text_iter_ends_sentence (&iter))
1080 g_error ("Iterator at %d should end a sentence", pos);
1084 while (gtk_text_iter_forward_sentence_end (&iter));
1086 if (i != expected_steps)
1087 g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1089 if (!gtk_text_iter_is_end (&iter))
1090 g_error ("Expected to stop at the end iterator\n");
1092 gtk_text_buffer_set_text (buffer, "Hi.\nHi. \nHi! Hi. Hi? Hi.", -1);
1094 memset (expected, 0, sizeof (expected));
1106 gtk_text_buffer_get_end_iter (buffer, &iter);
1112 pos = gtk_text_iter_get_offset (&iter);
1114 if (pos != expected[i])
1116 g_error ("Sentence position %d, expected %d",
1121 !gtk_text_iter_is_end (&iter) &&
1122 !gtk_text_iter_starts_sentence (&iter))
1123 g_error ("Iterator at %d should start a sentence", pos);
1127 while (gtk_text_iter_backward_sentence_start (&iter));
1129 if (i != expected_steps)
1130 g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1132 if (gtk_text_iter_get_offset (&iter) != 0)
1133 g_error ("Expected to stop at the start iterator\n");
1135 g_object_unref (buffer);
1141 GtkTextBuffer *buf1, *buf2;
1145 buf1 = gtk_text_buffer_new (NULL);
1146 buf2 = gtk_text_buffer_new (NULL);
1148 gtk_text_buffer_get_start_iter (buf1, &iter);
1149 mark = gtk_text_buffer_create_mark (buf1, "foo", &iter, TRUE);
1150 g_object_ref (mark);
1151 gtk_text_mark_set_visible (mark, TRUE);
1152 gtk_text_buffer_delete_mark (buf1, mark);
1154 g_assert (gtk_text_mark_get_visible (mark));
1155 g_assert (gtk_text_mark_get_left_gravity (mark));
1156 g_assert (!strcmp ("foo", gtk_text_mark_get_name (mark)));
1157 g_assert (gtk_text_mark_get_buffer (mark) == NULL);
1158 g_assert (gtk_text_mark_get_deleted (mark));
1159 g_assert (gtk_text_buffer_get_mark (buf1, "foo") == NULL);
1161 gtk_text_buffer_get_start_iter (buf2, &iter);
1162 gtk_text_buffer_add_mark (buf2, mark, &iter);
1163 gtk_text_buffer_insert (buf2, &iter, "ewfwefwefwe", -1);
1164 gtk_text_buffer_get_iter_at_mark (buf2, &iter, mark);
1166 g_assert (gtk_text_mark_get_visible (mark));
1167 g_assert (gtk_text_iter_is_start (&iter));
1168 g_assert (gtk_text_mark_get_left_gravity (mark));
1169 g_assert (!strcmp ("foo", gtk_text_mark_get_name (mark)));
1170 g_assert (gtk_text_mark_get_buffer (mark) == buf2);
1171 g_assert (!gtk_text_mark_get_deleted (mark));
1172 g_assert (gtk_text_buffer_get_mark (buf2, "foo") == mark);
1174 gtk_text_buffer_delete_mark (buf2, mark);
1175 gtk_text_mark_set_visible (mark, FALSE);
1176 g_object_unref (mark);
1178 mark = gtk_text_mark_new ("blah", TRUE);
1179 gtk_text_buffer_get_start_iter (buf1, &iter);
1180 gtk_text_mark_set_visible (mark, TRUE);
1181 gtk_text_buffer_add_mark (buf1, mark, &iter);
1183 g_assert (gtk_text_mark_get_visible (mark));
1184 g_assert (gtk_text_mark_get_buffer (mark) == buf1);
1185 g_assert (!gtk_text_mark_get_deleted (mark));
1186 g_assert (gtk_text_buffer_get_mark (buf1, "blah") == mark);
1187 g_assert (!strcmp ("blah", gtk_text_mark_get_name (mark)));
1189 gtk_text_mark_set_visible (mark, FALSE);
1190 gtk_text_buffer_delete_mark (buf1, mark);
1191 g_assert (!gtk_text_mark_get_visible (mark));
1192 g_assert (gtk_text_buffer_get_mark (buf1, "blah") == NULL);
1193 g_assert (gtk_text_mark_get_buffer (mark) == NULL);
1194 g_assert (gtk_text_mark_get_deleted (mark));
1196 gtk_text_buffer_get_start_iter (buf2, &iter);
1197 gtk_text_buffer_add_mark (buf2, mark, &iter);
1198 g_assert (gtk_text_mark_get_buffer (mark) == buf2);
1199 g_assert (!gtk_text_mark_get_deleted (mark));
1200 g_assert (gtk_text_buffer_get_mark (buf2, "blah") == mark);
1201 g_assert (!strcmp ("blah", gtk_text_mark_get_name (mark)));
1203 g_object_unref (mark);
1204 g_object_unref (buf1);
1205 g_object_unref (buf2);
1213 /* Check UTF8 unknown char thing */
1214 g_assert (GTK_TEXT_UNKNOWN_CHAR_UTF8_LEN == 3);
1215 g_assert (g_utf8_strlen (gtk_text_unknown_char_utf8_gtk_tests_only (), 3) == 1);
1216 ch = g_utf8_get_char (gtk_text_unknown_char_utf8_gtk_tests_only ());
1217 g_assert (ch == GTK_TEXT_UNKNOWN_CHAR);
1221 test_empty_buffer (void)
1223 GtkTextBuffer *buffer;
1227 buffer = gtk_text_buffer_new (NULL);
1229 /* Check that buffer starts with one empty line and zero chars */
1230 n = gtk_text_buffer_get_line_count (buffer);
1232 g_error ("%d lines, expected 1", n);
1234 n = gtk_text_buffer_get_char_count (buffer);
1236 g_error ("%d chars, expected 0", n);
1238 /* empty first line contains 0 chars */
1239 gtk_text_buffer_get_start_iter (buffer, &start);
1240 n = gtk_text_iter_get_chars_in_line (&start);
1242 g_error ("%d chars in first line, expected 0", n);
1243 n = gtk_text_iter_get_bytes_in_line (&start);
1245 g_error ("%d bytes in first line, expected 0", n);
1247 /* Run gruesome alien test suite on buffer */
1250 g_object_unref (buffer);
1256 GtkTextBuffer *buffer;
1258 buffer = gtk_text_buffer_new (NULL);
1260 check_get_set_text (buffer, "Hello");
1261 check_get_set_text (buffer, "Hello\n");
1262 check_get_set_text (buffer, "Hello\r\n");
1263 check_get_set_text (buffer, "Hello\r");
1264 check_get_set_text (buffer, "Hello\nBar\nFoo");
1265 check_get_set_text (buffer, "Hello\nBar\nFoo\n");
1267 g_object_unref (buffer);
1271 test_fill_empty (void)
1273 GtkTextBuffer *buffer;
1275 GtkTextIter start, end;
1277 buffer = gtk_text_buffer_new (NULL);
1279 /* Put stuff in the buffer */
1280 fill_buffer (buffer);
1282 /* Subject stuff-bloated buffer to further torment */
1285 /* Delete all stuff from the buffer */
1286 gtk_text_buffer_get_bounds (buffer, &start, &end);
1287 gtk_text_buffer_delete (buffer, &start, &end);
1289 /* Check buffer for emptiness (note that a single
1290 empty line always remains in the buffer) */
1291 n = gtk_text_buffer_get_line_count (buffer);
1293 g_error ("%d lines, expected 1", n);
1295 n = gtk_text_buffer_get_char_count (buffer);
1297 g_error ("%d chars, expected 0", n);
1301 g_object_unref (buffer);
1307 GtkTextBuffer *buffer;
1308 GtkTextIter start, end;
1310 buffer = gtk_text_buffer_new (NULL);
1312 fill_buffer (buffer);
1314 gtk_text_buffer_set_text (buffer, "adcdef", -1);
1315 gtk_text_buffer_get_iter_at_offset (buffer, &start, 1);
1316 gtk_text_buffer_get_iter_at_offset (buffer, &end, 3);
1317 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &start, &end);
1321 g_object_unref (buffer);
1324 extern void pixbuf_init (void);
1327 main (int argc, char** argv)
1329 /* First, we turn on btree debugging. */
1330 gtk_set_debug_flags (gtk_get_debug_flags () | GTK_DEBUG_TEXT);
1332 gtk_test_init (&argc, &argv);
1335 g_test_add_func ("/TextBuffer/UTF8 unknown char", test_utf8);
1336 g_test_add_func ("/TextBuffer/Line separator", test_line_separator);
1337 g_test_add_func ("/TextBuffer/Backspace", test_backspace);
1338 g_test_add_func ("/TextBuffer/Logical motion", test_logical_motion);
1339 g_test_add_func ("/TextBuffer/Marks", test_marks);
1340 g_test_add_func ("/TextBuffer/Empty buffer", test_empty_buffer);
1341 g_test_add_func ("/TextBuffer/Get and Set", test_get_set);
1342 g_test_add_func ("/TextBuffer/Fill and Empty", test_fill_empty);
1343 g_test_add_func ("/TextBuffer/Tag", test_tag);
1345 return g_test_run();