192 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* testrichtext.c
 | |
|  * Copyright (C) 2006 Imendio AB
 | |
|  * Authors: Michael Natterer, Tim Janik
 | |
|  *
 | |
|  * This library is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Lesser General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This library is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General Public
 | |
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 | |
|  */
 | |
| 
 | |
| #include <string.h>
 | |
| #include <gtk/gtk.h>
 | |
| 
 | |
| static guint32 quick_rand32_accu = 2147483563;
 | |
| 
 | |
| static inline guint32
 | |
| quick_rand32 (void)
 | |
| {
 | |
|   quick_rand32_accu = 1664525 * quick_rand32_accu + 1013904223;
 | |
|   return quick_rand32_accu;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| delete_event (GtkWidget   *widget,
 | |
|               GdkEventAny *event,
 | |
|               gpointer     user_data)
 | |
| {
 | |
|   gtk_main_quit ();
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| text_tag_enqueue (GtkTextTag *tag,
 | |
|                   gpointer    data)
 | |
| {
 | |
|   GSList **slist_p = data;
 | |
|   *slist_p = g_slist_prepend (*slist_p, tag);
 | |
| }
 | |
| 
 | |
| static const gchar *example_text =
 | |
| "vkndsk vfds vkfds vkdsv fdlksnvkfdvnkfdvnkdsnvs\n"
 | |
| "kmvofdmvfdsvkv fdskvnkfdv nnd.mckfdvnknsknvdnvs"
 | |
| "fdlvmfdsvlkfdsmvnskdnvfdsnvf sbskjnvlknfd cvdvnd"
 | |
| "mvlfdsv vfdkjv m, ds vkfdks v df,v j kfds v d\n"
 | |
| "vnfdskv kjvnfv  cfdkvndfnvcm fd,vk kdsf vj d\n"
 | |
| "KLJHkjh kjh klhjKLJH Kjh kjl h34kj h34kj3h klj 23 "
 | |
| "kjlkjlhsdjk 34kljh klj hklj 23k4jkjkjh234kjh 52kj "
 | |
| "2h34 sdaf ukklj kjl32l jkkjl 23j jkl ljk23 jkl\n"
 | |
| "hjhjhj2hj23jh jh jk jk2h3 hj kjj jk jh21 jhhj32.";
 | |
| 
 | |
| static GdkAtom
 | |
| setup_buffer (GtkTextBuffer *buffer)
 | |
| {
 | |
|   const guint tlen = strlen (example_text);
 | |
|   const guint tcount = 17;
 | |
|   GtkTextTag **tags;
 | |
|   GtkTextTagTable *ttable = gtk_text_buffer_get_tag_table (buffer);
 | |
|   GSList *node, *slist = NULL;
 | |
|   GdkAtom atom;
 | |
|   guint i;
 | |
| 
 | |
|   tags = g_malloc (sizeof (GtkTextTag *) * tcount);
 | |
| 
 | |
|   /* cleanup */
 | |
|   gtk_text_buffer_set_text (buffer, "", 0);
 | |
|   gtk_text_tag_table_foreach (ttable, text_tag_enqueue, &slist);
 | |
|   for (node = slist; node; node = node->next)
 | |
|     gtk_text_tag_table_remove (ttable, node->data);
 | |
|   g_slist_free (slist);
 | |
| 
 | |
|   /* create new tags */
 | |
|   for (i = 0; i < tcount; i++)
 | |
|     {
 | |
|       char *s = g_strdup_printf ("tag%u", i);
 | |
|       tags[i] = gtk_text_buffer_create_tag (buffer, s,
 | |
|                                             "weight", quick_rand32() >> 31 ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
 | |
|                                             "style", quick_rand32() >> 31 ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL,
 | |
|                                             "underline", quick_rand32() >> 31,
 | |
|                                             NULL);
 | |
|       g_free (s);
 | |
|     }
 | |
| 
 | |
|   /* assign text and tags */
 | |
|   gtk_text_buffer_set_text (buffer, example_text, -1);
 | |
|   for (i = 0; i < tcount * 5; i++)
 | |
|     {
 | |
|       gint a = quick_rand32() % tlen, b = quick_rand32() % tlen;
 | |
|       GtkTextIter start, end;
 | |
|       gtk_text_buffer_get_iter_at_offset (buffer, &start, MIN (a, b));
 | |
|       gtk_text_buffer_get_iter_at_offset (buffer, &end,   MAX (a, b));
 | |
|       gtk_text_buffer_apply_tag (buffer, tags[i % tcount], &start, &end);
 | |
|     }
 | |
| 
 | |
|   /* return serialization format */
 | |
|   atom = gtk_text_buffer_register_deserialize_tagset (buffer, NULL);
 | |
|   gtk_text_buffer_deserialize_set_can_create_tags (buffer, atom, TRUE);
 | |
| 
 | |
|   g_free (tags);
 | |
| 
 | |
|   return atom;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| test_serialize_deserialize (GtkTextBuffer *buffer,
 | |
|                             GdkAtom        atom,
 | |
|                             GError       **error)
 | |
| {
 | |
|   GtkTextIter  start, end;
 | |
|   guint8      *spew;
 | |
|   gsize        spew_length;
 | |
|   gboolean     success;
 | |
| 
 | |
|   gtk_text_buffer_get_bounds (buffer, &start, &end);
 | |
| 
 | |
|   spew = gtk_text_buffer_serialize (buffer, buffer, atom,
 | |
|                                     &start, &end, &spew_length);
 | |
| 
 | |
|   success = gtk_text_buffer_deserialize (buffer, buffer, atom, &end,
 | |
|                                          spew, spew_length, error);
 | |
| 
 | |
|   g_free (spew);
 | |
| 
 | |
|   return success;
 | |
| }
 | |
| 
 | |
| gint
 | |
| main (gint   argc,
 | |
|       gchar *argv[])
 | |
| {
 | |
|   GtkWidget     *window;
 | |
|   GtkWidget     *sw;
 | |
|   GtkWidget     *view;
 | |
|   GtkTextBuffer *buffer;
 | |
|   GdkAtom        atom;
 | |
|   guint          i, broken = 0;
 | |
| 
 | |
|   gtk_init (&argc, &argv);
 | |
| 
 | |
|   /* initialize random numbers, disable this for deterministic testing */
 | |
|   if (1)        
 | |
|     quick_rand32_accu = g_random_int();
 | |
| 
 | |
|   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 | |
|   gtk_widget_set_size_request (window, 400, 300);
 | |
| 
 | |
|   sw = gtk_scrolled_window_new (NULL, NULL);
 | |
|   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
 | |
|                                        GTK_SHADOW_IN);
 | |
|   gtk_container_set_border_width (GTK_CONTAINER (sw), 12);
 | |
|   gtk_container_add (GTK_CONTAINER (window), sw);
 | |
| 
 | |
|   g_signal_connect (window, "delete-event",
 | |
|                     G_CALLBACK (delete_event),
 | |
|                     NULL);
 | |
| 
 | |
|   buffer = gtk_text_buffer_new (NULL);
 | |
|   view = gtk_text_view_new_with_buffer (buffer);
 | |
|   g_object_unref (buffer);
 | |
| 
 | |
|   gtk_container_add (GTK_CONTAINER (sw), view);
 | |
| 
 | |
|   gtk_widget_show_all (window);
 | |
|   if (0)
 | |
|     gtk_main ();
 | |
| 
 | |
|   for (i = 0; i < 250; i++)
 | |
|     {
 | |
|       GError *error = NULL;
 | |
|       g_printerr ("creating randomly tagged text buffer with accu=0x%x...\n", quick_rand32_accu);
 | |
|       atom = setup_buffer (buffer);
 | |
|       if (test_serialize_deserialize (buffer, atom, &error))
 | |
|         g_printerr ("ok.\n");
 | |
|       else
 | |
|         {
 | |
|           g_printerr ("FAIL: serialization/deserialization failed:\n  %s\n", error->message);
 | |
|           broken += 1;
 | |
|         }
 | |
|       g_clear_error (&error);
 | |
|     }
 | |
| 
 | |
|   return broken > 0;
 | |
| }
 | 
