]> Pileus Git - ~andy/gtk/blob - tests/testtextbuffer.c
Updated.
[~andy/gtk] / tests / testtextbuffer.c
1 /* Simplistic test suite */
2
3
4 #include <stdio.h>
5
6 #include <gtk/gtk.h>
7 #include "../gtk/gtktexttypes.h" /* Private header, for UNKNOWN_CHAR */
8
9 static void fill_buffer (GtkTextBuffer *buffer);
10
11 static void run_tests (GtkTextBuffer *buffer);
12
13 int
14 main (int argc, char** argv)
15 {
16   GtkTextBuffer *buffer;
17   int n;
18   gunichar ch;
19   GtkTextIter start, end;
20
21   gtk_init (&argc, &argv);
22
23   /* Check UTF8 unknown char thing */
24   g_assert (g_utf8_strlen (gtk_text_unknown_char_utf8, 3) == 1);
25   ch = g_utf8_get_char (gtk_text_unknown_char_utf8);
26   g_assert (ch == GTK_TEXT_UNKNOWN_CHAR);
27
28   /* First, we turn on btree debugging. */
29   gtk_debug_flags |= GTK_DEBUG_TEXT;
30
31   /* Create a buffer */
32   buffer = gtk_text_buffer_new (NULL);
33
34   /* Check that buffer starts with one empty line and zero chars */
35
36   n = gtk_text_buffer_get_line_count (buffer);
37   if (n != 1)
38     g_error ("%d lines, expected 1", n);
39
40   n = gtk_text_buffer_get_char_count (buffer);
41   if (n != 1)
42     g_error ("%d chars, expected 1", n);
43
44   /* Run gruesome alien test suite on buffer */
45   run_tests (buffer);
46
47   /* Put stuff in the buffer */
48
49   fill_buffer (buffer);
50
51   /* Subject stuff-bloated buffer to further torment */
52   run_tests (buffer);
53
54   /* Delete all stuff from the buffer */
55   gtk_text_buffer_get_bounds (buffer, &start, &end);
56   gtk_text_buffer_delete (buffer, &start, &end);
57
58   /* Check buffer for emptiness (note that a single
59      empty line always remains in the buffer) */
60   n = gtk_text_buffer_get_line_count (buffer);
61   if (n != 1)
62     g_error ("%d lines, expected 1", n);
63
64   n = gtk_text_buffer_get_char_count (buffer);
65   if (n != 1)
66     g_error ("%d chars, expected 1", n);
67
68   run_tests (buffer);
69
70   g_object_unref (G_OBJECT (buffer));
71   
72   g_print ("All tests passed.\n");
73
74   return 0;
75 }
76
77 static gint
78 count_toggles_at_iter (GtkTextIter *iter,
79                        GtkTextTag  *of_tag)
80 {
81   GSList *tags;
82   GSList *tmp;
83   gint count = 0;
84   
85   /* get toggle-ons and toggle-offs */
86   tags = gtk_text_iter_get_toggled_tags (iter, TRUE);
87   tags = g_slist_concat (tags,
88                          gtk_text_iter_get_toggled_tags (iter, FALSE));
89   
90   tmp = tags;
91   while (tmp != NULL)
92     {
93       if (of_tag == NULL)
94         ++count;
95       else if (of_tag == tmp->data)
96         ++count;
97       
98       tmp = g_slist_next (tmp);
99     }
100   
101   g_slist_free (tags);
102
103   return count;
104 }
105      
106 static gint
107 count_toggles_in_buffer (GtkTextBuffer *buffer,
108                          GtkTextTag    *of_tag)
109 {
110   GtkTextIter iter;
111   gint count = 0;
112   
113   gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
114   do
115     {
116       count += count_toggles_at_iter (&iter, of_tag);
117     }
118   while (gtk_text_iter_forward_char (&iter));
119
120   /* Do the end iterator, because forward_char won't return TRUE
121    * on it.
122    */
123   count += count_toggles_at_iter (&iter, of_tag);
124   
125   return count;
126 }
127
128 static void
129 check_specific_tag (GtkTextBuffer *buffer,
130                     const gchar   *tag_name)
131 {
132   GtkTextIter iter;
133   GtkTextTag *tag;
134   gboolean state;
135   gint count;
136   gint buffer_count;
137   gint last_offset;
138   
139   tag = gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table (buffer),
140                                    tag_name);
141
142   buffer_count = count_toggles_in_buffer (buffer, tag);
143   
144   state = FALSE;
145   count = 0;
146
147   last_offset = -1;
148   gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
149   if (gtk_text_iter_toggles_tag (&iter, tag) ||
150       gtk_text_iter_forward_to_tag_toggle (&iter, tag))
151     {
152       do
153         {
154           gint this_offset;
155           
156           ++count;
157
158           this_offset = gtk_text_iter_get_offset (&iter);
159
160           if (this_offset <= last_offset)
161             g_error ("forward_to_tag_toggle moved in wrong direction");
162
163           last_offset = this_offset;
164           
165           if (gtk_text_iter_begins_tag (&iter, tag))
166             {
167               if (state)
168                 g_error ("Tag %p is already on, and was toggled on?", tag);
169               state = TRUE;
170             }          
171           else if (gtk_text_iter_ends_tag (&iter, tag))
172             {
173               if (!state)
174                 g_error ("Tag %p toggled off, but wasn't toggled on?", tag);
175               state = FALSE;
176             }
177           else
178             g_error ("forward_to_tag_toggle went to a location without a toggle");
179         }
180       while (gtk_text_iter_forward_to_tag_toggle (&iter, tag));
181     }
182
183   if (count != buffer_count)
184     g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
185              buffer_count, count);
186   
187   state = FALSE;
188   count = 0;
189   
190   gtk_text_buffer_get_end_iter (buffer, &iter);
191   last_offset = gtk_text_iter_get_offset (&iter);
192   if (gtk_text_iter_toggles_tag (&iter, tag) ||
193       gtk_text_iter_backward_to_tag_toggle (&iter, tag))
194     {
195       do
196         {
197           gint this_offset;
198           
199           ++count;
200
201           this_offset = gtk_text_iter_get_offset (&iter);
202           
203           if (this_offset >= last_offset)
204             g_error ("backward_to_tag_toggle moved in wrong direction");
205           
206           last_offset = this_offset;
207
208           if (gtk_text_iter_begins_tag (&iter, tag))
209             {
210               if (!state)
211                 g_error ("Tag %p wasn't on when we got to the on toggle going backward?", tag);
212               state = FALSE;
213             }
214           else if (gtk_text_iter_ends_tag (&iter, tag))
215             {
216               if (state)
217                 g_error ("Tag %p off toggle, but we were already inside a tag?", tag);
218               state = TRUE;
219             }
220           else
221             g_error ("backward_to_tag_toggle went to a location without a toggle");
222         }
223       while (gtk_text_iter_backward_to_tag_toggle (&iter, tag));
224     }
225
226   if (count != buffer_count)
227     g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
228              buffer_count, count);
229
230 }
231
232 static void
233 run_tests (GtkTextBuffer *buffer)
234 {
235   GtkTextIter iter;
236   GtkTextIter start;
237   GtkTextIter end;
238   GtkTextIter mark;
239   gint i, j;
240   gint num_chars;
241   GtkTextMark *bar_mark;
242   GtkTextTag *tag;
243   GHashTable *tag_states;
244   gint count;
245   gint buffer_count;
246   
247   gtk_text_buffer_get_bounds (buffer, &start, &end);
248
249   /* Check that walking the tree via chars and via iterators produces
250    * the same number of indexable locations.
251    */
252   num_chars = gtk_text_buffer_get_char_count (buffer);
253   iter = start;
254   bar_mark = gtk_text_buffer_create_mark (buffer, "bar", &iter, FALSE);
255   i = 0;
256   while (i < num_chars)
257     {
258       GtkTextIter current;
259       GtkTextMark *foo_mark;
260
261       gtk_text_buffer_get_iter_at_offset (buffer, &current, i);
262
263       if (!gtk_text_iter_equal (&iter, &current))
264         {
265           g_error ("get_char_index didn't return current iter");
266         }
267
268       j = gtk_text_iter_get_offset (&iter);
269
270       if (i != j)
271         {
272           g_error ("iter converted to %d not %d", j, i);
273         }
274
275       /* get/set mark */
276       gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
277
278       if (!gtk_text_iter_equal (&iter, &mark))
279         {
280           gtk_text_iter_spew (&iter, "iter");
281           gtk_text_iter_spew (&mark, "mark");
282           g_error ("Mark not moved to the right place.");
283         }
284
285       foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
286       gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
287       gtk_text_buffer_delete_mark (buffer, foo_mark);
288
289       if (!gtk_text_iter_equal (&iter, &mark))
290         {
291           gtk_text_iter_spew (&iter, "iter");
292           gtk_text_iter_spew (&mark, "mark");
293           g_error ("Mark not created in the right place.");
294         }
295
296       if (gtk_text_iter_is_end (&iter))
297         g_error ("iterators ran out before chars (offset %d of %d)",
298                  i, num_chars);
299
300       gtk_text_iter_forward_char (&iter);
301
302       gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
303
304       ++i;
305     }
306
307   if (!gtk_text_iter_equal (&iter, &end))
308     g_error ("Iterating over all chars didn't end with the end iter");
309
310   /* Do the tree-walk backward
311    */
312   num_chars = gtk_text_buffer_get_char_count (buffer);
313   gtk_text_buffer_get_iter_at_offset (buffer, &iter, -1);
314
315   gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
316
317   i = num_chars;
318
319   if (!gtk_text_iter_equal (&iter, &end))
320     g_error ("iter at char -1 is not equal to the end iterator");
321
322   while (i >= 0)
323     {
324       GtkTextIter current;
325       GtkTextMark *foo_mark;
326
327       gtk_text_buffer_get_iter_at_offset (buffer, &current, i);
328
329       if (!gtk_text_iter_equal (&iter, &current))
330         {
331           g_error ("get_char_index didn't return current iter while going backward");
332         }
333       j = gtk_text_iter_get_offset (&iter);
334
335       if (i != j)
336         {
337           g_error ("going backward, iter converted to %d not %d", j, i);
338         }
339
340       /* get/set mark */
341       gtk_text_buffer_get_iter_at_mark (buffer, &mark, bar_mark);
342
343       if (!gtk_text_iter_equal (&iter, &mark))
344         {
345           gtk_text_iter_spew (&iter, "iter");
346           gtk_text_iter_spew (&mark, "mark");
347           g_error ("Mark not moved to the right place.");
348         }
349
350       foo_mark = gtk_text_buffer_create_mark (buffer, "foo", &iter, FALSE);
351       gtk_text_buffer_get_iter_at_mark (buffer, &mark, foo_mark);
352       gtk_text_buffer_delete_mark (buffer, foo_mark);
353
354       if (!gtk_text_iter_equal (&iter, &mark))
355         {
356           gtk_text_iter_spew (&iter, "iter");
357           gtk_text_iter_spew (&mark, "mark");
358           g_error ("Mark not created in the right place.");
359         }
360
361       if (i > 0)
362         {
363           if (!gtk_text_iter_backward_char (&iter))
364             g_error ("iterators ran out before char indexes");
365
366           gtk_text_buffer_move_mark (buffer, bar_mark, &iter);
367         }
368       else
369         {
370           if (gtk_text_iter_backward_char (&iter))
371             g_error ("went backward from 0?");
372         }
373
374       --i;
375     }
376
377   if (!gtk_text_iter_equal (&iter, &start))
378     g_error ("Iterating backward over all chars didn't end with the start iter");
379
380   /*
381    * Check that get_line_count returns the same number of lines
382    * as walking the tree by line
383    */
384   i = 1; /* include current (first) line */
385   gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
386   while (gtk_text_iter_forward_line (&iter))
387     ++i;
388
389   if (i != gtk_text_buffer_get_line_count (buffer))
390     g_error ("Counted %d lines, buffer has %d", i,
391              gtk_text_buffer_get_line_count (buffer));
392
393   /*
394    * Check that moving over tag toggles thinks about working.
395    */
396
397   buffer_count = count_toggles_in_buffer (buffer, NULL);
398   
399   tag_states = g_hash_table_new (NULL, NULL);
400   count = 0;
401   
402   gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
403   if (gtk_text_iter_toggles_tag (&iter, NULL) ||
404       gtk_text_iter_forward_to_tag_toggle (&iter, NULL))
405     {
406       do
407         {
408           GSList *tags;
409           GSList *tmp;
410           gboolean found_some = FALSE;
411           
412           /* get toggled-on tags */
413           tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
414
415           if (tags)
416             found_some = TRUE;
417           
418           tmp = tags;
419           while (tmp != NULL)
420             {
421               ++count;
422               
423               tag = tmp->data;
424               
425               if (g_hash_table_lookup (tag_states, tag))
426                 g_error ("Tag %p is already on, and was toggled on?", tag);
427
428               g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
429           
430               tmp = g_slist_next (tmp);
431             }
432
433           g_slist_free (tags);
434       
435           /* get toggled-off tags */
436           tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
437
438           if (tags)
439             found_some = TRUE;
440           
441           tmp = tags;
442           while (tmp != NULL)
443             {
444               ++count;
445               
446               tag = tmp->data;
447
448               if (!g_hash_table_lookup (tag_states, tag))
449                 g_error ("Tag %p is already off, and was toggled off?", tag);
450
451               g_hash_table_remove (tag_states, tag);
452           
453               tmp = g_slist_next (tmp);
454             }
455
456           g_slist_free (tags);
457
458           if (!found_some)
459             g_error ("No tags found going forward to tag toggle.");
460
461         }
462       while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL));
463     }
464   
465   g_hash_table_destroy (tag_states);
466
467   if (count != buffer_count)
468     g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
469              buffer_count, count);
470   
471   /* Go backward; here TRUE in the hash means we saw
472    * an off toggle last.
473    */
474   
475   tag_states = g_hash_table_new (NULL, NULL);
476   count = 0;
477   
478   gtk_text_buffer_get_end_iter (buffer, &iter);
479   if (gtk_text_iter_toggles_tag (&iter, NULL) ||
480       gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
481     {
482       do
483         {
484           GSList *tags;
485           GSList *tmp;
486           gboolean found_some = FALSE;
487           
488           /* get toggled-off tags */
489           tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
490
491           if (tags)
492             found_some = TRUE;
493           
494           tmp = tags;
495           while (tmp != NULL)
496             {
497               ++count;
498               
499               tag = tmp->data;
500
501               if (g_hash_table_lookup (tag_states, tag))
502                 g_error ("Tag %p has two off-toggles in a row?", tag);
503           
504               g_hash_table_insert (tag_states, tag, GINT_TO_POINTER (TRUE));
505           
506               tmp = g_slist_next (tmp);
507             }
508
509           g_slist_free (tags);
510       
511           /* get toggled-on tags */
512           tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
513
514           if (tags)
515             found_some = TRUE;
516           
517           tmp = tags;
518           while (tmp != NULL)
519             {
520               ++count;
521               
522               tag = tmp->data;
523
524               if (!g_hash_table_lookup (tag_states, tag))
525                 g_error ("Tag %p was toggled on, but saw no off-toggle?", tag);
526
527               g_hash_table_remove (tag_states, tag);
528           
529               tmp = g_slist_next (tmp);
530             }
531
532           g_slist_free (tags);
533
534           if (!found_some)
535             g_error ("No tags found going backward to tag toggle.");
536         }
537       while (gtk_text_iter_backward_to_tag_toggle (&iter, NULL));
538     }
539   
540   g_hash_table_destroy (tag_states);
541
542   if (count != buffer_count)
543     g_error ("Counted %d tags iterating by char, %d iterating by tag toggle\n",
544              buffer_count, count);
545
546   check_specific_tag (buffer, "fg_red");
547   check_specific_tag (buffer, "bg_green");
548   check_specific_tag (buffer, "front_tag");
549   check_specific_tag (buffer, "center_tag");
550   check_specific_tag (buffer, "end_tag");
551 }
552
553
554 static char  *book_closed_xpm[] = {
555 "16 16 6 1",
556 "       c None s None",
557 ".      c black",
558 "X      c red",
559 "o      c yellow",
560 "O      c #808080",
561 "#      c white",
562 "                ",
563 "       ..       ",
564 "     ..XX.      ",
565 "   ..XXXXX.     ",
566 " ..XXXXXXXX.    ",
567 ".ooXXXXXXXXX.   ",
568 "..ooXXXXXXXXX.  ",
569 ".X.ooXXXXXXXXX. ",
570 ".XX.ooXXXXXX..  ",
571 " .XX.ooXXX..#O  ",
572 "  .XX.oo..##OO. ",
573 "   .XX..##OO..  ",
574 "    .X.#OO..    ",
575 "     ..O..      ",
576 "      ..        ",
577 "                "};
578
579 static void
580 fill_buffer (GtkTextBuffer *buffer)
581 {
582   GtkTextTag *tag;
583   GdkColor color, color2;
584   GtkTextIter iter;
585   GtkTextIter iter2;
586   GdkPixbuf *pixbuf;
587   int i;
588
589   color.red = color.green = 0;
590   color.blue = 0xffff;
591   color2.red = 0xfff;
592   color2.blue = 0x0;
593   color2.green = 0;
594   
595   gtk_text_buffer_create_tag (buffer, "fg_blue",
596                               "foreground_gdk", &color,
597                               "background_gdk", &color2,
598                               "font", "-*-courier-bold-r-*-*-30-*-*-*-*-*-*-*",
599                               NULL);
600
601   color.blue = color.green = 0;
602   color.red = 0xffff;
603   
604   gtk_text_buffer_create_tag (buffer, "fg_red",
605                               "rise", -4,
606                               "foreground_gdk", &color,
607                               NULL);
608
609   color.blue = color.red = 0;
610   color.green = 0xffff;
611   
612   gtk_text_buffer_create_tag (buffer, "bg_green",
613                               "background_gdk", &color,
614                               "font", "-*-courier-bold-r-*-*-10-*-*-*-*-*-*-*",
615                               NULL);
616
617   pixbuf = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
618
619   g_assert (pixbuf != NULL);
620
621   i = 0;
622   while (i < 10)
623     {
624       gchar *str;
625
626       gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
627
628       gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
629
630       gtk_text_buffer_get_iter_at_offset (buffer, &iter, 1);
631
632       gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
633
634       str = g_strdup_printf ("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
635                             i);
636
637       gtk_text_buffer_insert (buffer, &iter, str, -1);
638
639       g_free (str);
640
641       gtk_text_buffer_insert (buffer, &iter,
642                               "(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"
643                               /* This is UTF8 stuff, Emacs doesn't
644                                  really know how to display it */
645                               "Spanish (Español) ¡Hola! / French (Français) Bonjour, Salut / German (Deutsch Süd) Grüß Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash)  (ภาษาไทย)  สวัสดีครับ, สวัสดีค่ะ\n",
646                               -1);
647
648       gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
649       gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
650
651       gtk_text_buffer_get_iter_at_offset (buffer, &iter, 4);
652
653       gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
654
655       gtk_text_buffer_get_iter_at_offset (buffer, &iter, 7);
656
657       gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
658
659       gtk_text_buffer_get_iter_at_offset (buffer, &iter, 8);
660
661       gtk_text_buffer_insert_pixbuf (buffer, &iter, pixbuf);
662
663       gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, 0, 8);
664       iter2 = iter;
665       gtk_text_iter_forward_chars (&iter2, 10);
666
667       gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
668
669       gtk_text_iter_forward_chars (&iter, 7);
670       gtk_text_iter_forward_chars (&iter2, 10);
671
672       gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
673
674       gtk_text_iter_forward_chars (&iter, 12);
675       gtk_text_iter_forward_chars (&iter2, 10);
676
677       gtk_text_buffer_apply_tag_by_name (buffer, "bg_green", &iter, &iter2);
678
679       gtk_text_iter_forward_chars (&iter, 10);
680       gtk_text_iter_forward_chars (&iter2, 15);
681
682       gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
683       gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
684
685       gtk_text_iter_forward_chars (&iter, 20);
686       gtk_text_iter_forward_chars (&iter2, 20);
687
688       gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
689       gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
690
691       gtk_text_iter_backward_chars (&iter, 25);
692       gtk_text_iter_forward_chars (&iter2, 5);
693
694       gtk_text_buffer_apply_tag_by_name (buffer, "fg_red", &iter, &iter2);
695       gtk_text_buffer_apply_tag_by_name (buffer, "fg_blue", &iter, &iter2);
696
697       gtk_text_iter_forward_chars (&iter, 15);
698       gtk_text_iter_backward_chars (&iter2, 10);
699
700       gtk_text_buffer_remove_tag_by_name (buffer, "fg_red", &iter, &iter2);
701       gtk_text_buffer_remove_tag_by_name (buffer, "fg_blue", &iter, &iter2);
702
703       ++i;
704     }
705
706   /* Put in tags that are just at the beginning, and just near the end,
707    * and just near the middle.
708    */
709   tag = gtk_text_buffer_create_tag (buffer, "front_tag", NULL);
710   gtk_text_buffer_get_iter_at_offset (buffer, &iter, 3);
711   gtk_text_buffer_get_iter_at_offset (buffer, &iter2, 300);
712
713   gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);  
714   
715   tag = gtk_text_buffer_create_tag (buffer, "end_tag", NULL);
716   gtk_text_buffer_get_end_iter (buffer, &iter2);
717   gtk_text_iter_backward_chars (&iter2, 12);
718   iter = iter2;
719   gtk_text_iter_backward_chars (&iter, 157);
720
721   gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);
722   
723   tag = gtk_text_buffer_create_tag (buffer, "center_tag", NULL);
724   gtk_text_buffer_get_iter_at_offset (buffer, &iter,
725                                       gtk_text_buffer_get_char_count (buffer)/2);
726   gtk_text_iter_backward_chars (&iter, 37);
727   iter2 = iter;
728   gtk_text_iter_forward_chars (&iter2, 57);
729
730   gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);  
731
732   gdk_pixbuf_unref (pixbuf);
733 }