source: trunk/third/gtk2/tests/testtextbuffer.c @ 18785

Revision 18785, 32.1 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18784, which included commits to RCS files with non-trunk default branches.
Line 
1/* Simplistic test suite */
2
3
4#include <stdio.h>
5#include <string.h>
6
7#include <gtk/gtk.h>
8#include "../gtk/gtktexttypes.h" /* Private header, for UNKNOWN_CHAR */
9
10static void
11gtk_text_iter_spew (const GtkTextIter *iter, const gchar *desc)
12{
13  g_print (" %20s: line %d / char %d / line char %d / line byte %d\n",
14           desc,
15           gtk_text_iter_get_line (iter),
16           gtk_text_iter_get_offset (iter),
17           gtk_text_iter_get_line_offset (iter),
18           gtk_text_iter_get_line_index (iter));
19}
20
21static void fill_buffer (GtkTextBuffer *buffer);
22
23static void run_tests (GtkTextBuffer *buffer);
24
25static void check_get_set_text (GtkTextBuffer *buffer,
26                                const char    *str);
27
28
29static void line_separator_tests (void);
30
31static void logical_motion_tests (void);
32
33int
34main (int argc, char** argv)
35{
36  GtkTextBuffer *buffer;
37  int n;
38  gunichar ch;
39  GtkTextIter start, end;
40 
41  gtk_init (&argc, &argv);
42
43  /* Check UTF8 unknown char thing */
44  g_assert (g_utf8_strlen (gtk_text_unknown_char_utf8, 3) == 1);
45  ch = g_utf8_get_char (gtk_text_unknown_char_utf8);
46  g_assert (ch == GTK_TEXT_UNKNOWN_CHAR);
47
48  /* First, we turn on btree debugging. */
49  gtk_debug_flags |= GTK_DEBUG_TEXT;
50
51  /* Check some line separator stuff */
52  line_separator_tests ();
53
54  /* Check log attr motion */
55  logical_motion_tests ();
56 
57  /* Create a buffer */
58  buffer = gtk_text_buffer_new (NULL);
59
60  /* Check that buffer starts with one empty line and zero chars */
61
62  n = gtk_text_buffer_get_line_count (buffer);
63  if (n != 1)
64    g_error ("%d lines, expected 1", n);
65
66  n = gtk_text_buffer_get_char_count (buffer);
67  if (n != 0)
68    g_error ("%d chars, expected 0", n);
69
70  /* empty first line contains 0 chars */
71  gtk_text_buffer_get_start_iter (buffer, &start);
72  n = gtk_text_iter_get_chars_in_line (&start);
73  if (n != 0)
74    g_error ("%d chars in first line, expected 0", n);
75  n = gtk_text_iter_get_bytes_in_line (&start);
76  if (n != 0)
77    g_error ("%d bytes in first line, expected 0", n);
78 
79  /* Run gruesome alien test suite on buffer */
80  run_tests (buffer);
81
82  /* Check set/get text */
83  check_get_set_text (buffer, "Hello");
84  check_get_set_text (buffer, "Hello\n");
85  check_get_set_text (buffer, "Hello\r\n");
86  check_get_set_text (buffer, "Hello\r");
87  check_get_set_text (buffer, "Hello\nBar\nFoo");
88  check_get_set_text (buffer, "Hello\nBar\nFoo\n");
89
90  g_print ("get/set tests passed.\n");
91 
92  /* Put stuff in the buffer */
93
94  fill_buffer (buffer);
95
96  /* Subject stuff-bloated buffer to further torment */
97  run_tests (buffer);
98
99  /* Delete all stuff from the buffer */
100  gtk_text_buffer_get_bounds (buffer, &start, &end);
101  gtk_text_buffer_delete (buffer, &start, &end);
102
103  /* Check buffer for emptiness (note that a single
104     empty line always remains in the buffer) */
105  n = gtk_text_buffer_get_line_count (buffer);
106  if (n != 1)
107    g_error ("%d lines, expected 1", n);
108
109  n = gtk_text_buffer_get_char_count (buffer);
110  if (n != 0)
111    g_error ("%d chars, expected 0", n);
112
113  run_tests (buffer);
114
115  gtk_text_buffer_set_text (buffer, "adcdef", -1);
116  gtk_text_buffer_get_iter_at_offset (buffer, &start, 1);
117  gtk_text_buffer_get_iter_at_offset (buffer, &end, 3);
118  gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &start, &end);
119 
120  run_tests (buffer);
121 
122  g_object_unref (buffer);
123 
124  g_print ("All tests passed.\n");
125
126  return 0;
127}
128
129static void
130check_get_set_text (GtkTextBuffer *buffer,
131                    const char    *str)
132{
133  GtkTextIter start, end, iter;
134  char *text;
135  int n;
136 
137  gtk_text_buffer_set_text (buffer, str, -1);
138  if (gtk_text_buffer_get_char_count (buffer) != g_utf8_strlen (str, -1))
139    g_error ("Wrong number of chars (%d not %d)",
140             gtk_text_buffer_get_char_count (buffer),
141             (int) g_utf8_strlen (str, -1));
142  gtk_text_buffer_get_bounds (buffer, &start, &end);
143  text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
144  if (strcmp (text, str) != 0)
145    g_error ("Got '%s' as buffer contents", text);
146  g_free (text);
147
148  /* line char counts */
149  iter = start;
150  n = 0;
151  do
152    {
153      n += gtk_text_iter_get_chars_in_line (&iter);
154    }
155  while (gtk_text_iter_forward_line (&iter));
156
157  if (n != gtk_text_buffer_get_char_count (buffer))
158    g_error ("Sum of chars in lines is %d but buffer char count is %d",
159             n, gtk_text_buffer_get_char_count (buffer));
160
161  /* line byte counts */
162  iter = start;
163  n = 0;
164  do
165    {
166      n += gtk_text_iter_get_bytes_in_line (&iter);
167    }
168  while (gtk_text_iter_forward_line (&iter));
169
170  if (n != strlen (str))
171    g_error ("Sum of chars in lines is %d but buffer byte count is %d",
172             n, (int) strlen (str));
173 
174  gtk_text_buffer_set_text (buffer, "", -1);
175
176  n = gtk_text_buffer_get_line_count (buffer);
177  if (n != 1)
178    g_error ("%d lines, expected 1", n);
179
180  n = gtk_text_buffer_get_char_count (buffer);
181  if (n != 0)
182    g_error ("%d chars, expected 0", n);
183}
184
185static gint
186count_toggles_at_iter (GtkTextIter *iter,
187                       GtkTextTag  *of_tag)
188{
189  GSList *tags;
190  GSList *tmp;
191  gint count = 0;
192 
193  /* get toggle-ons and toggle-offs */
194  tags = gtk_text_iter_get_toggled_tags (iter, TRUE);
195  tags = g_slist_concat (tags,
196                         gtk_text_iter_get_toggled_tags (iter, FALSE));
197 
198  tmp = tags;
199  while (tmp != NULL)
200    {
201      if (of_tag == NULL)
202        ++count;
203      else if (of_tag == tmp->data)
204        ++count;
205     
206      tmp = g_slist_next (tmp);
207    }
208 
209  g_slist_free (tags);
210
211  return count;
212}
213
214static gint
215count_toggles_in_range_by_char (GtkTextBuffer     *buffer,
216                                GtkTextTag        *of_tag,
217                                const GtkTextIter *start,
218                                const GtkTextIter *end)
219{
220  GtkTextIter iter;
221  gint count = 0;
222 
223  iter = *start;
224  do
225    {
226      count += count_toggles_at_iter (&iter, of_tag);
227      if (!gtk_text_iter_forward_char (&iter))
228        {
229          /* end iterator */
230          count += count_toggles_at_iter (&iter, of_tag);
231          break;
232        }
233    }
234  while (gtk_text_iter_compare (&iter, end) <= 0);
235 
236  return count;
237}
238
239static gint
240count_toggles_in_buffer (GtkTextBuffer *buffer,
241                         GtkTextTag    *of_tag)
242{
243  GtkTextIter start, end;
244
245  gtk_text_buffer_get_bounds (buffer, &start, &end);
246
247  return count_toggles_in_range_by_char (buffer, of_tag, &start, &end);
248}
249
250static void
251check_specific_tag_in_range (GtkTextBuffer     *buffer,
252                             const gchar       *tag_name,
253                             const GtkTextIter *start,
254                             const GtkTextIter *end)
255{
256  GtkTextIter iter;
257  GtkTextTag *tag;
258  gboolean state;
259  gint count;
260  gint buffer_count;
261  gint last_offset;
262
263  if (gtk_text_iter_compare (start, end) > 0)
264    {
265      g_print ("  (inverted range for checking tags, skipping)\n");
266      return;
267    }
268 
269  tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer),
270                                   tag_name);
271
272  buffer_count = count_toggles_in_range_by_char (buffer, tag, start, end);
273 
274  state = FALSE;
275  count = 0;
276
277  last_offset = -1;
278  iter = *start;
279  if (gtk_text_iter_toggles_tag (&iter, tag) ||
280      gtk_text_iter_forward_to_tag_toggle (&iter, tag))
281    {
282      do
283        {
284          gint this_offset;
285         
286          ++count;
287
288          this_offset = gtk_text_iter_get_offset (&iter);
289
290          if (this_offset <= last_offset)
291            g_error ("forward_to_tag_toggle moved in wrong direction");
292
293          last_offset = this_offset;
294         
295          if (gtk_text_iter_begins_tag (&iter, tag))
296            {
297              if (state)
298                g_error ("Tag %p is already on, and was toggled on?", tag);
299              state = TRUE;
300            }         
301          else if (gtk_text_iter_ends_tag (&iter, tag))
302            {
303              if (!state)
304                g_error ("Tag %p toggled off, but wasn't toggled on?", tag);
305              state = FALSE;
306            }
307          else
308            g_error ("forward_to_tag_toggle went to a location without a toggle");
309        }
310      while (gtk_text_iter_forward_to_tag_toggle (&iter, tag) &&
311             gtk_text_iter_compare (&iter, end) <= 0);
312    }
313
314  if (count != buffer_count)
315    g_error ("Counted %d tags iterating by char, %d iterating forward by tag toggle\n",
316             buffer_count, count);
317 
318  state = FALSE;
319  count = 0;
320 
321  iter = *end;
322  last_offset = gtk_text_iter_get_offset (&iter);
323  if (gtk_text_iter_toggles_tag (&iter, tag) ||
324      gtk_text_iter_backward_to_tag_toggle (&iter, tag))
325    {
326      do
327        {
328          gint this_offset;
329         
330          ++count;
331
332          this_offset = gtk_text_iter_get_offset (&iter);
333         
334          if (this_offset >= last_offset)
335            g_error ("backward_to_tag_toggle moved in wrong direction");
336         
337          last_offset = this_offset;
338
339          if (gtk_text_iter_begins_tag (&iter, tag))
340            {
341              if (!state)
342                g_error ("Tag %p wasn't on when we got to the on toggle going backward?", tag);
343              state = FALSE;
344            }
345          else if (gtk_text_iter_ends_tag (&iter, tag))
346            {
347              if (state)
348                g_error ("Tag %p off toggle, but we were already inside a tag?", tag);
349              state = TRUE;
350            }
351          else
352            g_error ("backward_to_tag_toggle went to a location without a toggle");
353        }
354      while (gtk_text_iter_backward_to_tag_toggle (&iter, tag) &&
355             gtk_text_iter_compare (&iter, start) >= 0);
356    }
357
358  if (count != buffer_count)
359    g_error ("Counted %d tags iterating by char, %d iterating backward by tag toggle\n",
360             buffer_count, count);
361}
362
363static void
364check_specific_tag (GtkTextBuffer *buffer,
365                    const gchar   *tag_name)
366{
367  GtkTextIter start, end;
368
369  gtk_text_buffer_get_bounds (buffer, &start, &end);
370  check_specific_tag_in_range (buffer, tag_name, &start, &end);
371  gtk_text_iter_forward_chars (&start, 2);
372  gtk_text_iter_backward_chars (&end, 2);
373  if (gtk_text_iter_compare (&start, &end) < 0)
374    check_specific_tag_in_range (buffer, tag_name, &start, &end);
375}
376
377static void
378run_tests (GtkTextBuffer *buffer)
379{
380  GtkTextIter iter;
381  GtkTextIter start;
382  GtkTextIter end;
383  GtkTextIter mark;
384  gint i, j;
385  gint num_chars;
386  GtkTextMark *bar_mark;
387  GtkTextTag *tag;
388  GHashTable *tag_states;
389  gint count;
390  gint buffer_count;
391 
392  gtk_text_buffer_get_bounds (buffer, &start, &end);
393
394  /* Check that walking the tree via chars and via iterators produces
395   * the same number of indexable locations.
396   */
397  num_chars = gtk_text_buffer_get_char_count (buffer);
398  iter = start;
399  bar_mark = gtk_text_buffer_create_mark (buffer, "bar", &iter, FALSE);
400  i = 0;
401  while (i < num_chars)
402    {
403      GtkTextIter current;
404      GtkTextMark *foo_mark;
405
406      gtk_text_buffer_get_iter_at_offset (buffer, &current, i);
407
408      if (!gtk_text_iter_equal (&iter, &current))
409        {
410          g_error ("get_char_index didn't return current iter");
411        }
412
413      j = gtk_text_iter_get_offset (&iter);
414
415      if (i != j)
416        {
417          g_error ("iter converted to %d not %d", j, i);
418        }
419
420      /* get/set mark */
421      gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
422
423      if (!gtk_text_iter_equal (&iter, &mark))
424        {
425          gtk_text_iter_spew (&iter, "iter");
426          gtk_text_iter_spew (&mark, "mark");
427          g_error ("Mark not moved to the right place.");
428        }
429
430      foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
431      gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
432      gtk_text_buffer_delete_mark (buffer, foo_mark);
433
434      if (!gtk_text_iter_equal (&iter, &mark))
435        {
436          gtk_text_iter_spew (&iter, "iter");
437          gtk_text_iter_spew (&mark, "mark");
438          g_error ("Mark not created in the right place.");
439        }
440
441      if (gtk_text_iter_is_end (&iter))
442        g_error ("iterators ran out before chars (offset %d of %d)",
443                 i, num_chars);
444
445      gtk_text_iter_forward_char (&iter);
446
447      gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
448
449      ++i;
450    }
451
452  if (!gtk_text_iter_equal (&iter, &end))
453    g_error ("Iterating over all chars didn't end with the end iter");
454
455  /* Do the tree-walk backward
456   */
457  num_chars = gtk_text_buffer_get_char_count (buffer);
458  gtk_text_buffer_get_iter_at_offset (buffer, &iter, -1);
459
460  gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
461
462  i = num_chars;
463
464  if (!gtk_text_iter_equal (&iter, &end))
465    g_error ("iter at char -1 is not equal to the end iterator");
466
467  while (i >= 0)
468    {
469      GtkTextIter current;
470      GtkTextMark *foo_mark;
471
472      gtk_text_buffer_get_iter_at_offset (buffer, &current, i);
473
474      if (!gtk_text_iter_equal (&iter, &current))
475        {
476          g_error ("get_char_index didn't return current iter while going backward");
477        }
478      j = gtk_text_iter_get_offset (&iter);
479
480      if (i != j)
481        {
482          g_error ("going backward, iter converted to %d not %d", j, i);
483        }
484
485      /* get/set mark */
486      gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
487
488      if (!gtk_text_iter_equal (&iter, &mark))
489        {
490          gtk_text_iter_spew (&iter, "iter");
491          gtk_text_iter_spew (&mark, "mark");
492          g_error ("Mark not moved to the right place.");
493        }
494
495      foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
496      gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
497      gtk_text_buffer_delete_mark (buffer, foo_mark);
498
499      if (!gtk_text_iter_equal (&iter, &mark))
500        {
501          gtk_text_iter_spew (&iter, "iter");
502          gtk_text_iter_spew (&mark, "mark");
503          g_error ("Mark not created in the right place.");
504        }
505
506      if (i > 0)
507        {
508          if (!gtk_text_iter_backward_char (&iter))
509            g_error ("iterators ran out before char indexes");
510
511          gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
512        }
513      else
514        {
515          if (gtk_text_iter_backward_char (&iter))
516            g_error ("went backward from 0?");
517        }
518
519      --i;
520    }
521
522  if (!gtk_text_iter_equal (&iter, &start))
523    g_error ("Iterating backward over all chars didn't end with the start iter");
524
525  /*
526   * Check that get_line_count returns the same number of lines
527   * as walking the tree by line
528   */
529  i = 1; /* include current (first) line */
530  gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
531  while (gtk_text_iter_forward_line (&iter))
532    ++i;
533
534  if (i != gtk_text_buffer_get_line_count (buffer))
535    g_error ("Counted %d lines, buffer has %d", i,
536             gtk_text_buffer_get_line_count (buffer));
537
538  /*
539   * Check that moving over tag toggles thinks about working.
540   */
541
542  buffer_count = count_toggles_in_buffer (buffer, NULL);
543 
544  tag_states = g_hash_table_new (NULL, NULL);
545  count = 0;
546 
547  gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
548  if (gtk_text_iter_toggles_tag (&iter, NULL) ||
549      gtk_text_iter_forward_to_tag_toggle (&iter, NULL))
550    {
551      do
552        {
553          GSList *tags;
554          GSList *tmp;
555          gboolean found_some = FALSE;
556         
557          /* get toggled-on tags */
558          tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
559
560          if (tags)
561            found_some = TRUE;
562         
563          tmp = tags;
564          while (tmp != NULL)
565            {
566              ++count;
567             
568              tag = tmp->data;
569             
570              if (g_hash_table_lookup (tag_states, tag))
571                g_error ("Tag %p is already on, and was toggled on?", tag);
572
573              g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
574         
575              tmp = g_slist_next (tmp);
576            }
577
578          g_slist_free (tags);
579     
580          /* get toggled-off tags */
581          tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
582
583          if (tags)
584            found_some = TRUE;
585         
586          tmp = tags;
587          while (tmp != NULL)
588            {
589              ++count;
590             
591              tag = tmp->data;
592
593              if (!g_hash_table_lookup (tag_states, tag))
594                g_error ("Tag %p is already off, and was toggled off?", tag);
595
596              g_hash_table_remove (tag_states, tag);
597         
598              tmp = g_slist_next (tmp);
599            }
600
601          g_slist_free (tags);
602
603          if (!found_some)
604            g_error ("No tags found going forward to tag toggle.");
605
606        }
607      while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL));
608    }
609 
610  g_hash_table_destroy (tag_states);
611
612  if (count != buffer_count)
613    g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
614             buffer_count, count);
615 
616  /* Go backward; here TRUE in the hash means we saw
617   * an off toggle last.
618   */
619 
620  tag_states = g_hash_table_new (NULL, NULL);
621  count = 0;
622 
623  gtk_text_buffer_get_end_iter (buffer, &iter);
624  if (gtk_text_iter_toggles_tag (&iter, NULL) ||
625      gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
626    {
627      do
628        {
629          GSList *tags;
630          GSList *tmp;
631          gboolean found_some = FALSE;
632         
633          /* get toggled-off tags */
634          tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
635
636          if (tags)
637            found_some = TRUE;
638         
639          tmp = tags;
640          while (tmp != NULL)
641            {
642              ++count;
643             
644              tag = tmp->data;
645
646              if (g_hash_table_lookup (tag_states, tag))
647                g_error ("Tag %p has two off-toggles in a row?", tag);
648         
649              g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
650         
651              tmp = g_slist_next (tmp);
652            }
653
654          g_slist_free (tags);
655     
656          /* get toggled-on tags */
657          tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
658
659          if (tags)
660            found_some = TRUE;
661         
662          tmp = tags;
663          while (tmp != NULL)
664            {
665              ++count;
666             
667              tag = tmp->data;
668
669              if (!g_hash_table_lookup (tag_states, tag))
670                g_error ("Tag %p was toggled on, but saw no off-toggle?", tag);
671
672              g_hash_table_remove (tag_states, tag);
673         
674              tmp = g_slist_next (tmp);
675            }
676
677          g_slist_free (tags);
678
679          if (!found_some)
680            g_error ("No tags found going backward to tag toggle.");
681        }
682      while (gtk_text_iter_backward_to_tag_toggle (&iter, NULL));
683    }
684 
685  g_hash_table_destroy (tag_states);
686
687  if (count != buffer_count)
688    g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
689             buffer_count, count);
690
691  check_specific_tag (buffer, "fg_red");
692  check_specific_tag (buffer, "bg_green");
693  check_specific_tag (buffer, "front_tag");
694  check_specific_tag (buffer, "center_tag");
695  check_specific_tag (buffer, "end_tag");
696}
697
698
699static const char  *book_closed_xpm[] = {
700"16 16 6 1",
701"       c None s None",
702".      c black",
703"X      c red",
704"o      c yellow",
705"O      c #808080",
706"#      c white",
707"                ",
708"       ..       ",
709"     ..XX.      ",
710"   ..XXXXX.     ",
711" ..XXXXXXXX.    ",
712".ooXXXXXXXXX.   ",
713"..ooXXXXXXXXX.  ",
714".X.ooXXXXXXXXX. ",
715".XX.ooXXXXXX..  ",
716" .XX.ooXXX..#O  ",
717"  .XX.oo..##OO. ",
718"   .XX..##OO..  ",
719"    .X.#OO..    ",
720"     ..O..      ",
721"      ..        ",
722"                "};
723
724static void
725fill_buffer (GtkTextBuffer *buffer)
726{
727  GtkTextTag *tag;
728  GdkColor color, color2;
729  GtkTextIter iter;
730  GtkTextIter iter2;
731  GdkPixbuf *pixbuf;
732  int i;
733
734  color.red = color.green = 0;
735  color.blue = 0xffff;
736  color2.red = 0xfff;
737  color2.blue = 0x0;
738  color2.green = 0;
739 
740  gtk_text_buffer_create_tag (buffer, "fg_blue",
741                              "foreground_gdk", &color,
742                              "background_gdk", &color2,
743                              "font", "-*-courier-bold-r-*-*-30-*-*-*-*-*-*-*",
744                              NULL);
745
746  color.blue = color.green = 0;
747  color.red = 0xffff;
748 
749  gtk_text_buffer_create_tag (buffer, "fg_red",
750                              "rise", -4,
751                              "foreground_gdk", &color,
752                              NULL);
753
754  color.blue = color.red = 0;
755  color.green = 0xffff;
756 
757  gtk_text_buffer_create_tag (buffer, "bg_green",
758                              "background_gdk", &color,
759                              "font", "-*-courier-bold-r-*-*-10-*-*-*-*-*-*-*",
760                              NULL);
761
762  pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
763
764  g_assert (pixbuf != NULL);
765
766  i = 0;
767  while (i < 10)
768    {
769      gchar *str;
770
771      gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
772
773      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
774
775      gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
776
777      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
778
779      str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
780                            i);
781
782      gtk_text_buffer_insert (buffer, &iter, str, -1);
783
784      g_free (str);
785
786      gtk_text_buffer_insert (buffer, &iter,
787                              "(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"
788                              /* This is UTF8 stuff, Emacs doesn't
789                                 really know how to display it */
790                              "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",
791                              -1);
792
793      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
794      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
795
796      gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
797
798      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
799
800      gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
801
802      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
803
804      gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
805
806      gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
807
808      gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
809      iter2 = iter;
810      gtk_text_iter_forward_chars (&iter2, 10);
811
812      gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
813
814      gtk_text_iter_forward_chars (&iter, 7);
815      gtk_text_iter_forward_chars (&iter2, 10);
816
817      gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
818
819      gtk_text_iter_forward_chars (&iter, 12);
820      gtk_text_iter_forward_chars (&iter2, 10);
821
822      gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
823
824      gtk_text_iter_forward_chars (&iter, 10);
825      gtk_text_iter_forward_chars (&iter2, 15);
826
827      gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
828      gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
829
830      gtk_text_iter_forward_chars (&iter, 20);
831      gtk_text_iter_forward_chars (&iter2, 20);
832
833      gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
834      gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
835
836      gtk_text_iter_backward_chars (&iter, 25);
837      gtk_text_iter_forward_chars (&iter2, 5);
838
839      gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
840      gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
841
842      gtk_text_iter_forward_chars (&iter, 15);
843      gtk_text_iter_backward_chars (&iter2, 10);
844
845      gtk_text_buffer_remove_tag_by_name (buffer, "fg_red", &iter, &iter2);
846      gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
847
848      ++i;
849    }
850
851  /* Put in tags that are just at the beginning, and just near the end,
852   * and just near the middle.
853   */
854  tag = gtk_text_buffer_create_tag (buffer, "front_tag", NULL);
855  gtk_text_buffer_get_iter_at_offset (buffer, &iter, 3);
856  gtk_text_buffer_get_iter_at_offset (buffer, &iter2, 300);
857
858  gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2); 
859 
860  tag = gtk_text_buffer_create_tag (buffer, "end_tag", NULL);
861  gtk_text_buffer_get_end_iter (buffer, &iter2);
862  gtk_text_iter_backward_chars (&iter2, 12);
863  iter = iter2;
864  gtk_text_iter_backward_chars (&iter, 157);
865
866  gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
867 
868  tag = gtk_text_buffer_create_tag (buffer, "center_tag", NULL);
869  gtk_text_buffer_get_iter_at_offset (buffer, &iter,
870                                      gtk_text_buffer_get_char_count (buffer)/2);
871  gtk_text_iter_backward_chars (&iter, 37);
872  iter2 = iter;
873  gtk_text_iter_forward_chars (&iter2, 57);
874
875  gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2); 
876
877  g_object_unref (pixbuf);
878}
879
880
881/*
882 * Line separator tests (initially to avoid regression on bugzilla #57428)
883 */
884
885static void
886test_line_separation (const char* str,
887                      gboolean    expect_next_line,
888                      gboolean    expect_end_iter,
889                      int         expected_line_count,
890                      int         expected_line_break,
891                      int         expected_next_line_start)
892{
893  GtkTextIter iter;
894  GtkTextBuffer* buffer;
895  gboolean on_next_line;
896  gboolean on_end_iter;
897  gint new_pos;
898
899  buffer = gtk_text_buffer_new (NULL);
900
901  gtk_text_buffer_set_text (buffer, str, -1);
902  gtk_text_buffer_get_iter_at_offset (buffer, &iter, expected_line_break);
903
904  g_assert (gtk_text_iter_ends_line (&iter) || gtk_text_iter_is_end (&iter));
905
906  g_assert (gtk_text_buffer_get_line_count (buffer) == expected_line_count);
907 
908  on_next_line = gtk_text_iter_forward_line (&iter);
909
910  g_assert (expect_next_line == on_next_line);
911
912  on_end_iter = gtk_text_iter_is_end (&iter);
913
914  g_assert (on_end_iter == expect_end_iter);
915 
916  new_pos = gtk_text_iter_get_offset (&iter);
917   
918  if (on_next_line)
919    g_assert (expected_next_line_start == new_pos);
920
921  ++expected_line_break;
922  while (expected_line_break < expected_next_line_start)
923    {
924      gtk_text_buffer_get_iter_at_offset (buffer, &iter, expected_line_break);
925
926      g_assert (!gtk_text_iter_ends_line (&iter));
927
928      on_next_line = gtk_text_iter_forward_line (&iter);
929       
930      g_assert (expect_next_line == on_next_line);
931       
932      new_pos = gtk_text_iter_get_offset (&iter);
933       
934      if (on_next_line)
935        g_assert (expected_next_line_start == new_pos);
936       
937      ++expected_line_break;
938    }
939
940  /* FIXME tests for backward line */
941 
942  g_object_unref (buffer);
943}
944
945
946static void
947line_separator_tests (void)
948{
949  char *str;
950  char buf[7] = { '\0', };
951
952  /* Only one character has type G_UNICODE_PARAGRAPH_SEPARATOR in
953   * Unicode 3.0; update this if that changes.
954   */
955#define PARAGRAPH_SEPARATOR 0x2029
956 
957  test_line_separation ("line", FALSE, TRUE, 1, 4, 4);
958  test_line_separation ("line\r\n", FALSE, TRUE, 2, 4, 6);
959  test_line_separation ("line\r", FALSE, TRUE, 2, 4, 5);
960  test_line_separation ("line\n", FALSE, TRUE, 2, 4, 5);
961  test_line_separation ("line\rqw", TRUE, FALSE, 2, 4, 5);
962  test_line_separation ("line\nqw", TRUE, FALSE, 2, 4, 5);
963  test_line_separation ("line\r\nqw", TRUE, FALSE, 2, 4, 6);
964 
965  g_unichar_to_utf8 (PARAGRAPH_SEPARATOR, buf);
966 
967  str = g_strdup_printf ("line%s", buf);
968  test_line_separation (str, FALSE, TRUE, 2, 4, 5);
969  g_free (str);
970  str = g_strdup_printf ("line%sqw", buf);
971  test_line_separation (str, TRUE, FALSE, 2, 4, 5);
972  g_free (str);
973
974  g_print ("Line separator tests passed\n");
975}
976
977static void
978logical_motion_tests (void)
979{
980  char *str;
981  char buf1[7] = { '\0', };
982  char buf2[7] = { '\0', };
983  char buf3[7] = { '\0', };
984  int expected[30];
985  int expected_steps;
986  int i;
987  GtkTextBuffer *buffer;
988  GtkTextIter iter;
989 
990  buffer = gtk_text_buffer_new (NULL);
991 
992#define LEADING_JAMO 0x1111
993#define VOWEL_JAMO 0x1167
994#define TRAILING_JAMO 0x11B9
995 
996  g_unichar_to_utf8 (LEADING_JAMO, buf1);
997  g_unichar_to_utf8 (VOWEL_JAMO, buf2);
998  g_unichar_to_utf8 (TRAILING_JAMO, buf3);
999
1000  /* Build the string "abc<leading><vowel><trailing>def\r\nxyz" */
1001  str = g_strconcat ("abc", buf1, buf2, buf3, "def\r\nxyz", NULL);
1002  gtk_text_buffer_set_text (buffer, str, -1);
1003  g_free (str);
1004 
1005  /* Check cursor positions */
1006  memset (expected, 0, sizeof (expected));
1007  expected[0] = 0;    /* before 'a' */
1008  expected[1] = 1;    /* before 'b' */
1009  expected[2] = 2;    /* before 'c' */
1010  expected[3] = 3;    /* before jamo */
1011  expected[4] = 6;    /* before 'd' */
1012  expected[5] = 7;    /* before 'e' */
1013  expected[6] = 8;    /* before 'f' */
1014  expected[7] = 9;    /* before '\r' */
1015  expected[8] = 11;   /* before 'x' */
1016  expected[9] = 12;   /* before 'y' */
1017  expected[10] = 13;  /* before 'z' */
1018  expected[11] = 14;  /* after 'z' (only matters going backward) */
1019  expected_steps = 11;
1020 
1021  gtk_text_buffer_get_start_iter (buffer, &iter);
1022  i = 0;
1023  do
1024    {
1025      int pos;
1026
1027      pos = gtk_text_iter_get_offset (&iter);
1028     
1029      if (pos != expected[i])
1030        {
1031          g_error ("Cursor position %d, expected %d",
1032                   pos, expected[i]);
1033        }
1034
1035      ++i;     
1036    }
1037  while (gtk_text_iter_forward_cursor_position (&iter));
1038
1039  if (!gtk_text_iter_is_end (&iter))
1040    g_error ("Expected to stop at the end iterator\n");
1041
1042  if (!gtk_text_iter_is_cursor_position (&iter))
1043    g_error ("Should be a cursor position before the end iterator");
1044 
1045  if (i != expected_steps)
1046    g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1047
1048  i = expected_steps;
1049  do
1050    {
1051      int pos;
1052
1053      pos = gtk_text_iter_get_offset (&iter);
1054     
1055      if (pos != expected[i])
1056        {
1057          g_error ("Moving backward, cursor position %d, expected %d",
1058                   pos, expected[i]);
1059        }
1060
1061      /* g_print ("%d = %d\n", pos, expected[i]); */
1062     
1063      --i;
1064    }
1065  while (gtk_text_iter_backward_cursor_position (&iter));
1066
1067  if (i != -1)
1068    g_error ("Expected %d steps, there were actually %d\n", expected_steps - i, i);
1069
1070  if (!gtk_text_iter_is_start (&iter))
1071    g_error ("Expected to stop at the start iterator\n");
1072
1073
1074  /* Check sentence boundaries */
1075 
1076  gtk_text_buffer_set_text (buffer, "Hi.\nHi. \nHi! Hi. Hi? Hi.", -1);
1077
1078  memset (expected, 0, sizeof (expected));
1079
1080  expected[0] = 0;    /* before first Hi */
1081  expected[1] = 3;    /* After first . */
1082  expected[2] = 7;    /* After second . */
1083  expected[3] = 12;   /* After ! */
1084  expected[4] = 16;   /* After third . */
1085  expected[5] = 20;   /* After ? */
1086 
1087  expected_steps = 6;
1088 
1089  gtk_text_buffer_get_start_iter (buffer, &iter);
1090  i = 0;
1091  do
1092    {
1093      int pos;
1094
1095      pos = gtk_text_iter_get_offset (&iter);
1096
1097      if (pos != expected[i])
1098        {
1099          g_error ("Sentence position %d, expected %d",
1100                   pos, expected[i]);
1101        }
1102
1103      if (i != 0 &&
1104          !gtk_text_iter_is_end (&iter) &&
1105          !gtk_text_iter_ends_sentence (&iter))
1106        g_error ("Iterator at %d should end a sentence", pos);
1107     
1108      ++i;
1109    }
1110  while (gtk_text_iter_forward_sentence_end (&iter));
1111
1112  if (i != expected_steps)
1113    g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1114
1115  if (!gtk_text_iter_is_end (&iter))
1116    g_error ("Expected to stop at the end iterator\n");
1117 
1118  gtk_text_buffer_set_text (buffer, "Hi.\nHi. \nHi! Hi. Hi? Hi.", -1);
1119
1120  memset (expected, 0, sizeof (expected));
1121
1122  expected[0] = 24;
1123  expected[1] = 21;
1124  expected[2] = 17;
1125  expected[3] = 13;
1126  expected[4] = 9;
1127  expected[5] = 4;
1128  expected[6] = 0;
1129 
1130  expected_steps = 7;
1131 
1132  gtk_text_buffer_get_end_iter (buffer, &iter);
1133  i = 0;
1134  do
1135    {
1136      int pos;
1137
1138      pos = gtk_text_iter_get_offset (&iter);
1139
1140      if (pos != expected[i])
1141        {
1142          g_error ("Sentence position %d, expected %d",
1143                   pos, expected[i]);
1144        }
1145
1146      if (pos != 0 &&
1147          !gtk_text_iter_is_end (&iter) &&
1148          !gtk_text_iter_starts_sentence (&iter))
1149        g_error ("Iterator at %d should start a sentence", pos);
1150     
1151      ++i;
1152    }
1153  while (gtk_text_iter_backward_sentence_start (&iter));
1154
1155  if (i != expected_steps)
1156    g_error ("Expected %d steps, there were actually %d\n", expected_steps, i);
1157
1158  if (gtk_text_iter_get_offset (&iter) != 0)
1159    g_error ("Expected to stop at the start iterator\n");
1160 
1161  g_print ("Logical motion tests passed\n");
1162
1163  g_object_unref (buffer);
1164}
Note: See TracBrowser for help on using the repository browser.