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));
39 static void fill_buffer (GtkTextBuffer *buffer);
41 static void run_tests (GtkTextBuffer *buffer);
43 static void check_get_set_text (GtkTextBuffer *buffer,
47 static void line_separator_tests (void);
49 static void logical_motion_tests (void);
52 main (int argc, char** argv)
54 GtkTextBuffer *buffer;
57 GtkTextIter start, end;
59 gtk_init (&argc, &argv);
61 /* Check UTF8 unknown char thing */
62 g_assert (g_utf8_strlen (gtk_text_unknown_char_utf8, 3) == 1);
63 ch = g_utf8_get_char (gtk_text_unknown_char_utf8);
64 g_assert (ch == GTK_TEXT_UNKNOWN_CHAR);
66 /* First, we turn on btree debugging. */
67 gtk_debug_flags |= GTK_DEBUG_TEXT;
69 /* Check some line separator stuff */
70 line_separator_tests ();
72 /* Check log attr motion */
73 logical_motion_tests ();
76 buffer = gtk_text_buffer_new (NULL);
78 /* Check that buffer starts with one empty line and zero chars */
80 n = gtk_text_buffer_get_line_count (buffer);
82 g_error ("%d lines, expected 1", n);
84 n = gtk_text_buffer_get_char_count (buffer);
86 g_error ("%d chars, expected 0", n);
88 /* empty first line contains 0 chars */
89 gtk_text_buffer_get_start_iter (buffer, &start);
90 n = gtk_text_iter_get_chars_in_line (&start);
92 g_error ("%d chars in first line, expected 0", n);
93 n = gtk_text_iter_get_bytes_in_line (&start);
95 g_error ("%d bytes in first line, expected 0", n);
97 /* Run gruesome alien test suite on buffer */
100 /* Check set/get text */
101 check_get_set_text (buffer, "Hello");
102 check_get_set_text (buffer, "Hello\n");
103 check_get_set_text (buffer, "Hello\r\n");
104 check_get_set_text (buffer, "Hello\r");
105 check_get_set_text (buffer, "Hello\nBar\nFoo");
106 check_get_set_text (buffer, "Hello\nBar\nFoo\n");
108 g_print ("get/set tests passed.\n");
110 /* Put stuff in the buffer */
112 fill_buffer (buffer);
114 /* Subject stuff-bloated buffer to further torment */
117 /* Delete all stuff from the buffer */
118 gtk_text_buffer_get_bounds (buffer, &start, &end);
119 gtk_text_buffer_delete (buffer, &start, &end);
121 /* Check buffer for emptiness (note that a single
122 empty line always remains in the buffer) */
123 n = gtk_text_buffer_get_line_count (buffer);
125 g_error ("%d lines, expected 1", n);
127 n = gtk_text_buffer_get_char_count (buffer);
129 g_error ("%d chars, expected 0", n);
133 gtk_text_buffer_set_text (buffer, "adcdef", -1);
134 gtk_text_buffer_get_iter_at_offset (buffer, &start, 1);
135 gtk_text_buffer_get_iter_at_offset (buffer, &end, 3);
136 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &start, &end);
140 g_object_unref (buffer);
142 g_print ("All tests passed.\n");
148 check_get_set_text (GtkTextBuffer *buffer,
151 GtkTextIter start, end, iter;
155 gtk_text_buffer_set_text (buffer, str, -1);
156 if (gtk_text_buffer_get_char_count (buffer) != g_utf8_strlen (str, -1))
157 g_error ("Wrong number of chars (%d not %d)",
158 gtk_text_buffer_get_char_count (buffer),
159 (int) g_utf8_strlen (str, -1));
160 gtk_text_buffer_get_bounds (buffer, &start, &end);
161 text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
162 if (strcmp (text, str) != 0)
163 g_error ("Got '%s' as buffer contents", text);
166 /* line char counts */
171 n += gtk_text_iter_get_chars_in_line (&iter);
173 while (gtk_text_iter_forward_line (&iter));
175 if (n != gtk_text_buffer_get_char_count (buffer))
176 g_error ("Sum of chars in lines is %d but buffer char count is %d",
177 n, gtk_text_buffer_get_char_count (buffer));
179 /* line byte counts */
184 n += gtk_text_iter_get_bytes_in_line (&iter);
186 while (gtk_text_iter_forward_line (&iter));
188 if (n != strlen (str))
189 g_error ("Sum of chars in lines is %d but buffer byte count is %d",
190 n, (int) strlen (str));
192 gtk_text_buffer_set_text (buffer, "", -1);
194 n = gtk_text_buffer_get_line_count (buffer);
196 g_error ("%d lines, expected 1", n);
198 n = gtk_text_buffer_get_char_count (buffer);
200 g_error ("%d chars, expected 0", n);
204 count_toggles_at_iter (GtkTextIter *iter,
211 /* get toggle-ons and toggle-offs */
212 tags = gtk_text_iter_get_toggled_tags (iter, TRUE);
213 tags = g_slist_concat (tags,
214 gtk_text_iter_get_toggled_tags (iter, FALSE));
221 else if (of_tag == tmp->data)
224 tmp = g_slist_next (tmp);
233 count_toggles_in_range_by_char (GtkTextBuffer *buffer,
235 const GtkTextIter *start,
236 const GtkTextIter *end)
244 count += count_toggles_at_iter (&iter, of_tag);
245 if (!gtk_text_iter_forward_char (&iter))
248 count += count_toggles_at_iter (&iter, of_tag);
252 while (gtk_text_iter_compare (&iter, end) <= 0);
258 count_toggles_in_buffer (GtkTextBuffer *buffer,
261 GtkTextIter start, end;
263 gtk_text_buffer_get_bounds (buffer, &start, &end);
265 return count_toggles_in_range_by_char (buffer, of_tag, &start, &end);
269 check_specific_tag_in_range (GtkTextBuffer *buffer,
270 const gchar *tag_name,
271 const GtkTextIter *start,
272 const GtkTextIter *end)
281 if (gtk_text_iter_compare (start, end) > 0)
283 g_print (" (inverted range for checking tags, skipping)\n");
287 tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer),
290 buffer_count = count_toggles_in_range_by_char (buffer, tag, start, end);
297 if (gtk_text_iter_toggles_tag (&iter, tag) ||
298 gtk_text_iter_forward_to_tag_toggle (&iter, tag))
306 this_offset = gtk_text_iter_get_offset (&iter);
308 if (this_offset <= last_offset)
309 g_error ("forward_to_tag_toggle moved in wrong direction");
311 last_offset = this_offset;
313 if (gtk_text_iter_begins_tag (&iter, tag))
316 g_error ("Tag %p is already on, and was toggled on?", tag);
319 else if (gtk_text_iter_ends_tag (&iter, tag))
322 g_error ("Tag %p toggled off, but wasn't toggled on?", tag);
326 g_error ("forward_to_tag_toggle went to a location without a toggle");
328 while (gtk_text_iter_forward_to_tag_toggle (&iter, tag) &&
329 gtk_text_iter_compare (&iter, end) <= 0);
332 if (count != buffer_count)
333 g_error ("Counted %d tags iterating by char, %d iterating forward by tag toggle\n",
334 buffer_count, count);
340 last_offset = gtk_text_iter_get_offset (&iter);
341 if (gtk_text_iter_toggles_tag (&iter, tag) ||
342 gtk_text_iter_backward_to_tag_toggle (&iter, tag))
350 this_offset = gtk_text_iter_get_offset (&iter);
352 if (this_offset >= last_offset)
353 g_error ("backward_to_tag_toggle moved in wrong direction");
355 last_offset = this_offset;
357 if (gtk_text_iter_begins_tag (&iter, tag))
360 g_error ("Tag %p wasn't on when we got to the on toggle going backward?", tag);
363 else if (gtk_text_iter_ends_tag (&iter, tag))
366 g_error ("Tag %p off toggle, but we were already inside a tag?", tag);
370 g_error ("backward_to_tag_toggle went to a location without a toggle");
372 while (gtk_text_iter_backward_to_tag_toggle (&iter, tag) &&
373 gtk_text_iter_compare (&iter, start) >= 0);
376 if (count != buffer_count)
377 g_error ("Counted %d tags iterating by char, %d iterating backward by tag toggle\n",
378 buffer_count, count);
382 check_specific_tag (GtkTextBuffer *buffer,
383 const gchar *tag_name)
385 GtkTextIter start, end;
387 gtk_text_buffer_get_bounds (buffer, &start, &end);
388 check_specific_tag_in_range (buffer, tag_name, &start, &end);
389 gtk_text_iter_forward_chars (&start, 2);
390 gtk_text_iter_backward_chars (&end, 2);
391 if (gtk_text_iter_compare (&start, &end) < 0)
392 check_specific_tag_in_range (buffer, tag_name, &start, &end);
396 run_tests (GtkTextBuffer *buffer)
404 GtkTextMark *bar_mark;
406 GHashTable *tag_states;
410 gtk_text_buffer_get_bounds (buffer, &start, &end);
412 /* Check that walking the tree via chars and via iterators produces
413 * the same number of indexable locations.
415 num_chars = gtk_text_buffer_get_char_count (buffer);
417 bar_mark = gtk_text_buffer_create_mark (buffer, "bar", &iter, FALSE);
419 while (i < num_chars)
422 GtkTextMark *foo_mark;
424 gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
426 if (!gtk_text_iter_equal (&iter, ¤t))
428 g_error ("get_char_index didn't return current iter");
431 j = gtk_text_iter_get_offset (&iter);
435 g_error ("iter converted to %d not %d", j, i);
439 gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
441 if (!gtk_text_iter_equal (&iter, &mark))
443 gtk_text_iter_spew (&iter, "iter");
444 gtk_text_iter_spew (&mark, "mark");
445 g_error ("Mark not moved to the right place.");
448 foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
449 gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
450 gtk_text_buffer_delete_mark (buffer, foo_mark);
452 if (!gtk_text_iter_equal (&iter, &mark))
454 gtk_text_iter_spew (&iter, "iter");
455 gtk_text_iter_spew (&mark, "mark");
456 g_error ("Mark not created in the right place.");
459 if (gtk_text_iter_is_end (&iter))
460 g_error ("iterators ran out before chars (offset %d of %d)",
463 gtk_text_iter_forward_char (&iter);
465 gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
470 if (!gtk_text_iter_equal (&iter, &end))
471 g_error ("Iterating over all chars didn't end with the end iter");
473 /* Do the tree-walk backward
475 num_chars = gtk_text_buffer_get_char_count (buffer);
476 gtk_text_buffer_get_iter_at_offset (buffer, &iter, -1);
478 gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
482 if (!gtk_text_iter_equal (&iter, &end))
483 g_error ("iter at char -1 is not equal to the end iterator");
488 GtkTextMark *foo_mark;
490 gtk_text_buffer_get_iter_at_offset (buffer, ¤t, i);
492 if (!gtk_text_iter_equal (&iter, ¤t))
494 g_error ("get_char_index didn't return current iter while going backward");
496 j = gtk_text_iter_get_offset (&iter);
500 g_error ("going backward, iter converted to %d not %d", j, i);
504 gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
506 if (!gtk_text_iter_equal (&iter, &mark))
508 gtk_text_iter_spew (&iter, "iter");
509 gtk_text_iter_spew (&mark, "mark");
510 g_error ("Mark not moved to the right place.");
513 foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
514 gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
515 gtk_text_buffer_delete_mark (buffer, foo_mark);
517 if (!gtk_text_iter_equal (&iter, &mark))
519 gtk_text_iter_spew (&iter, "iter");
520 gtk_text_iter_spew (&mark, "mark");
521 g_error ("Mark not created in the right place.");
526 if (!gtk_text_iter_backward_char (&iter))
527 g_error ("iterators ran out before char indexes");
529 gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
533 if (gtk_text_iter_backward_char (&iter))
534 g_error ("went backward from 0?");
540 if (!gtk_text_iter_equal (&iter, &start))
541 g_error ("Iterating backward over all chars didn't end with the start iter");
544 * Check that get_line_count returns the same number of lines
545 * as walking the tree by line
547 i = 1; /* include current (first) line */
548 gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
549 while (gtk_text_iter_forward_line (&iter))
552 if (i != gtk_text_buffer_get_line_count (buffer))
553 g_error ("Counted %d lines, buffer has %d", i,
554 gtk_text_buffer_get_line_count (buffer));
557 * Check that moving over tag toggles thinks about working.
560 buffer_count = count_toggles_in_buffer (buffer, NULL);
562 tag_states = g_hash_table_new (NULL, NULL);
565 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
566 if (gtk_text_iter_toggles_tag (&iter, NULL) ||
567 gtk_text_iter_forward_to_tag_toggle (&iter, NULL))
573 gboolean found_some = FALSE;
575 /* get toggled-on tags */
576 tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
588 if (g_hash_table_lookup (tag_states, tag))
589 g_error ("Tag %p is already on, and was toggled on?", tag);
591 g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
593 tmp = g_slist_next (tmp);
598 /* get toggled-off tags */
599 tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
611 if (!g_hash_table_lookup (tag_states, tag))
612 g_error ("Tag %p is already off, and was toggled off?", tag);
614 g_hash_table_remove (tag_states, tag);
616 tmp = g_slist_next (tmp);
622 g_error ("No tags found going forward to tag toggle.");
625 while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL));
628 g_hash_table_destroy (tag_states);
630 if (count != buffer_count)
631 g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
632 buffer_count, count);
634 /* Go backward; here TRUE in the hash means we saw
635 * an off toggle last.
638 tag_states = g_hash_table_new (NULL, NULL);
641 gtk_text_buffer_get_end_iter (buffer, &iter);
642 if (gtk_text_iter_toggles_tag (&iter, NULL) ||
643 gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
649 gboolean found_some = FALSE;
651 /* get toggled-off tags */
652 tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
664 if (g_hash_table_lookup (tag_states, tag))
665 g_error ("Tag %p has two off-toggles in a row?", tag);
667 g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
669 tmp = g_slist_next (tmp);
674 /* get toggled-on tags */
675 tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
687 if (!g_hash_table_lookup (tag_states, tag))
688 g_error ("Tag %p was toggled on, but saw no off-toggle?", tag);
690 g_hash_table_remove (tag_states, tag);
692 tmp = g_slist_next (tmp);
698 g_error ("No tags found going backward to tag toggle.");
700 while (gtk_text_iter_backward_to_tag_toggle (&iter, NULL));
703 g_hash_table_destroy (tag_states);
705 if (count != buffer_count)
706 g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
707 buffer_count, count);
709 check_specific_tag (buffer, "fg_red");
710 check_specific_tag (buffer, "bg_green");
711 check_specific_tag (buffer, "front_tag");
712 check_specific_tag (buffer, "center_tag");
713 check_specific_tag (buffer, "end_tag");
717 static const char *book_closed_xpm[] = {
743 fill_buffer (GtkTextBuffer *buffer)
746 GdkColor color, color2;
752 color.red = color.green = 0;
758 gtk_text_buffer_create_tag (buffer, "fg_blue",
759 "foreground_gdk", &color,
760 "background_gdk", &color2,
761 "font", "-*-courier-bold-r-*-*-30-*-*-*-*-*-*-*",
764 color.blue = color.green = 0;
767 gtk_text_buffer_create_tag (buffer, "fg_red",
769 "foreground_gdk", &color,
772 color.blue = color.red = 0;
773 color.green = 0xffff;
775 gtk_text_buffer_create_tag (buffer, "bg_green",
776 "background_gdk", &color,
777 "font", "-*-courier-bold-r-*-*-10-*-*-*-*-*-*-*",
780 pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
782 g_assert (pixbuf != NULL);
789 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
791 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
793 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
795 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
797 str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
800 gtk_text_buffer_insert (buffer, &iter, str, -1);
804 gtk_text_buffer_insert (buffer, &iter,
805 "(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"
806 /* This is UTF8 stuff, Emacs doesn't
807 really know how to display it */
808 "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",
811 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
812 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
814 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
816 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
818 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
820 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
822 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
824 gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
826 gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
828 gtk_text_iter_forward_chars (&iter2, 10);
830 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
832 gtk_text_iter_forward_chars (&iter, 7);
833 gtk_text_iter_forward_chars (&iter2, 10);
835 gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
837 gtk_text_iter_forward_chars (&iter, 12);
838 gtk_text_iter_forward_chars (&iter2, 10);
840 gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
842 gtk_text_iter_forward_chars (&iter, 10);
843 gtk_text_iter_forward_chars (&iter2, 15);
845 gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
846 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
848 gtk_text_iter_forward_chars (&iter, 20);
849 gtk_text_iter_forward_chars (&iter2, 20);
851 gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
852 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
854 gtk_text_iter_backward_chars (&iter, 25);
855 gtk_text_iter_forward_chars (&iter2, 5);
857 gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
858 gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
860 gtk_text_iter_forward_chars (&iter, 15);
861 gtk_text_iter_backward_chars (&iter2, 10);
863 gtk_text_buffer_remove_tag_by_name (buffer, "fg_red", &iter, &iter2);
864 gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
869 /* Put in tags that are just at the beginning, and just near the end,
870 * and just near the middle.
872 tag = gtk_text_buffer_create_tag (buffer, "front_tag", NULL);
873 gtk_text_buffer_get_iter_at_offset (buffer, &iter, 3);
874 gtk_text_buffer_get_iter_at_offset (buffer, &iter2, 300);
876 gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
878 tag = gtk_text_buffer_create_tag (buffer, "end_tag", NULL);
879 gtk_text_buffer_get_end_iter (buffer, &iter2);
880 gtk_text_iter_backward_chars (&iter2, 12);
882 gtk_text_iter_backward_chars (&iter, 157);
884 gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
886 tag = gtk_text_buffer_create_tag (buffer, "center_tag", NULL);
887 gtk_text_buffer_get_iter_at_offset (buffer, &iter,
888 gtk_text_buffer_get_char_count (buffer)/2);
889 gtk_text_iter_backward_chars (&iter, 37);
891 gtk_text_iter_forward_chars (&iter2, 57);
893 gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
895 g_object_unref (pixbuf);
900 * Line separator tests (initially to avoid regression on bugzilla #57428)
904 test_line_separation (const char* str,
905 gboolean expect_next_line,
906 gboolean expect_end_iter,
907 int expected_line_count,
908 int expected_line_break,
909 int expected_next_line_start)
912 GtkTextBuffer* buffer;
913 gboolean on_next_line;
914 gboolean on_end_iter;
917 buffer = gtk_text_buffer_new (NULL);
919 gtk_text_buffer_set_text (buffer, str, -1);
920 gtk_text_buffer_get_iter_at_offset (buffer, &iter, expected_line_break);
922 g_assert (gtk_text_iter_ends_line (&iter) || gtk_text_iter_is_end (&iter));
924 g_assert (gtk_text_buffer_get_line_count (buffer) == expected_line_count);
926 on_next_line = gtk_text_iter_forward_line (&iter);
928 g_assert (expect_next_line == on_next_line);
930 on_end_iter = gtk_text_iter_is_end (&iter);
932 g_assert (on_end_iter == expect_end_iter);
934 new_pos = gtk_text_iter_get_offset (&iter);
937 g_assert (expected_next_line_start == new_pos);
939 ++expected_line_break;
940 while (expected_line_break < expected_next_line_start)
942 gtk_text_buffer_get_iter_at_offset (buffer, &iter, expected_line_break);
944 g_assert (!gtk_text_iter_ends_line (&iter));
946 on_next_line = gtk_text_iter_forward_line (&iter);
948 g_assert (expect_next_line == on_next_line);
950 new_pos = gtk_text_iter_get_offset (&iter);
953 g_assert (expected_next_line_start == new_pos);
955 ++expected_line_break;
958 /* FIXME tests for backward line */
960 g_object_unref (buffer);
965 line_separator_tests (void)
968 char buf[7] = { '\0', };
970 /* Only one character has type G_UNICODE_PARAGRAPH_SEPARATOR in
971 * Unicode 3.0; update this if that changes.
973 #define PARAGRAPH_SEPARATOR 0x2029
975 test_line_separation ("line", FALSE, TRUE, 1, 4, 4);
976 test_line_separation ("line\r\n", FALSE, TRUE, 2, 4, 6);
977 test_line_separation ("line\r", FALSE, TRUE, 2, 4, 5);
978 test_line_separation ("line\n", FALSE, TRUE, 2, 4, 5);
979 test_line_separation ("line\rqw", TRUE, FALSE, 2, 4, 5);
980 test_line_separation ("line\nqw", TRUE, FALSE, 2, 4, 5);
981 test_line_separation ("line\r\nqw", TRUE, FALSE, 2, 4, 6);
983 g_unichar_to_utf8 (PARAGRAPH_SEPARATOR, buf);
985 str = g_strdup_printf ("line%s", buf);
986 test_line_separation (str, FALSE, TRUE, 2, 4, 5);
988 str = g_strdup_printf ("line%sqw", buf);
989 test_line_separation (str, TRUE, FALSE, 2, 4, 5);
992 g_print ("Line separator tests passed\n");
996 logical_motion_tests (void)
999 char buf1[7] = { '\0', };
1000 char buf2[7] = { '\0', };
1001 char buf3[7] = { '\0', };
1005 GtkTextBuffer *buffer;
1008 buffer = gtk_text_buffer_new (NULL);
1010 #define LEADING_JAMO 0x1111
1011 #define VOWEL_JAMO 0x1167
1012 #define TRAILING_JAMO 0x11B9
1014 g_unichar_to_utf8 (LEADING_JAMO, buf1);
1015 g_unichar_to_utf8 (VOWEL_JAMO, buf2);
1016 g_unichar_to_utf8 (TRAILING_JAMO, buf3);
1018 /* Build the string "abc<leading><vowel><trailing>def\r\nxyz" */
1019 str = g_strconcat ("abc", buf1, buf2, buf3, "def\r\nxyz", NULL);
1020 gtk_text_buffer_set_text (buffer, str, -1);
1023 /* Check cursor positions */
1024 memset (expected, 0, sizeof (expected));
1025 expected[0] = 0; /* before 'a' */
1026 expected[1] = 1; /* before 'b' */
1027 expected[2] = 2; /* before 'c' */
1028 expected[3] = 3; /* before jamo */
1029 expected[4] = 6; /* before 'd' */
1030 expected[5] = 7; /* before 'e' */
1031 expected[6] = 8; /* before 'f' */
1032 expected[7] = 9; /* before '\r' */
1033 expected[8] = 11; /* before 'x' */
1034 expected[9] = 12; /* before 'y' */
1035 expected[10] = 13; /* before 'z' */
1036 expected[11] = 14; /* after 'z' (only matters going backward) */
1037 expected_steps = 11;
1039 gtk_text_buffer_get_start_iter (buffer, &iter);
1045 pos = gtk_text_iter_get_offset (&iter);
1047 if (pos != expected[i])
1049 g_error ("Cursor position %d, expected %d",
1055 while (gtk_text_iter_forward_cursor_position (&iter));
1057 if (!gtk_text_iter_is_end (&iter))
1058 g_error ("Expected to stop at the end iterator\n");
1060 if (!gtk_text_iter_is_cursor_position (&iter))
1061 g_error ("Should be a cursor position before the end iterator");
1063 if (i != expected_steps)
1064 g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1071 pos = gtk_text_iter_get_offset (&iter);
1073 if (pos != expected[i])
1075 g_error ("Moving backward, cursor position %d, expected %d",
1079 /* g_print ("%d = %d\n", pos, expected[i]); */
1083 while (gtk_text_iter_backward_cursor_position (&iter));
1086 g_error ("Expected %d steps, there were actually %d\n", expected_steps - i, i);
1088 if (!gtk_text_iter_is_start (&iter))
1089 g_error ("Expected to stop at the start iterator\n");
1092 /* Check sentence boundaries */
1094 gtk_text_buffer_set_text (buffer, "Hi.\nHi. \nHi! Hi. Hi? Hi.", -1);
1096 memset (expected, 0, sizeof (expected));
1098 expected[0] = 0; /* before first Hi */
1099 expected[1] = 3; /* After first . */
1100 expected[2] = 7; /* After second . */
1101 expected[3] = 12; /* After ! */
1102 expected[4] = 16; /* After third . */
1103 expected[5] = 20; /* After ? */
1107 gtk_text_buffer_get_start_iter (buffer, &iter);
1113 pos = gtk_text_iter_get_offset (&iter);
1115 if (pos != expected[i])
1117 g_error ("Sentence position %d, expected %d",
1122 !gtk_text_iter_is_end (&iter) &&
1123 !gtk_text_iter_ends_sentence (&iter))
1124 g_error ("Iterator at %d should end a sentence", pos);
1128 while (gtk_text_iter_forward_sentence_end (&iter));
1130 if (i != expected_steps)
1131 g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1133 if (!gtk_text_iter_is_end (&iter))
1134 g_error ("Expected to stop at the end iterator\n");
1136 gtk_text_buffer_set_text (buffer, "Hi.\nHi. \nHi! Hi. Hi? Hi.", -1);
1138 memset (expected, 0, sizeof (expected));
1150 gtk_text_buffer_get_end_iter (buffer, &iter);
1156 pos = gtk_text_iter_get_offset (&iter);
1158 if (pos != expected[i])
1160 g_error ("Sentence position %d, expected %d",
1165 !gtk_text_iter_is_end (&iter) &&
1166 !gtk_text_iter_starts_sentence (&iter))
1167 g_error ("Iterator at %d should start a sentence", pos);
1171 while (gtk_text_iter_backward_sentence_start (&iter));
1173 if (i != expected_steps)
1174 g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1176 if (gtk_text_iter_get_offset (&iter) != 0)
1177 g_error ("Expected to stop at the start iterator\n");
1179 g_print ("Logical motion tests passed\n");
1181 g_object_unref (buffer);