]> Pileus Git - ~andy/gtk/blob - gtk/gtkmain.c
adapt to handle PangoColor
[~andy/gtk] / gtk / gtkmain.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #ifdef GDK_WINDOWING_X11
28 #include <X11/Xlocale.h>        /* so we get the right setlocale */
29 #else
30 #include <locale.h>
31 #endif
32
33 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
34 #include <libintl.h>
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <gmodule.h>
41 #include "gtkdnd.h"
42 #include "gtkcompat.h"
43 #include "gtkmain.h"
44 #include "gtkrc.h"
45 #include "gtkselection.h"
46 #include "gtksignal.h"
47 #include "gtkwidget.h"
48 #include "gtkwindow.h"
49 #include "gtkprivate.h"
50 #include "gdk/gdki18n.h"
51 #include "config.h"
52 #include "gtkdebug.h"
53 #include "gtkintl.h"
54
55 /* Private type definitions
56  */
57 typedef struct _GtkInitFunction          GtkInitFunction;
58 typedef struct _GtkQuitFunction          GtkQuitFunction;
59 typedef struct _GtkClosure               GtkClosure;
60 typedef struct _GtkKeySnooperData        GtkKeySnooperData;
61
62 struct _GtkInitFunction
63 {
64   GtkFunction function;
65   gpointer data;
66 };
67
68 struct _GtkQuitFunction
69 {
70   guint id;
71   guint main_level;
72   GtkCallbackMarshal marshal;
73   GtkFunction function;
74   gpointer data;
75   GtkDestroyNotify destroy;
76 };
77
78 struct _GtkClosure
79 {
80   GtkCallbackMarshal marshal;
81   gpointer data;
82   GtkDestroyNotify destroy;
83 };
84
85 struct _GtkKeySnooperData
86 {
87   GtkKeySnoopFunc func;
88   gpointer func_data;
89   guint id;
90 };
91
92 static void  gtk_exit_func               (void);
93 static gint  gtk_quit_invoke_function    (GtkQuitFunction    *quitf);
94 static void  gtk_quit_destroy            (GtkQuitFunction    *quitf);
95 static gint  gtk_invoke_key_snoopers     (GtkWidget          *grab_widget,
96                                           GdkEvent           *event);
97
98 static void     gtk_destroy_closure      (gpointer            data);
99 static gboolean gtk_invoke_idle_timeout  (gpointer            data);
100 static void     gtk_invoke_input         (gpointer            data,
101                                           gint                source,
102                                           GdkInputCondition   condition);
103
104 #if 0
105 static void  gtk_error                   (gchar              *str);
106 static void  gtk_warning                 (gchar              *str);
107 static void  gtk_message                 (gchar              *str);
108 static void  gtk_print                   (gchar              *str);
109 #endif
110
111 const guint gtk_major_version = GTK_MAJOR_VERSION;
112 const guint gtk_minor_version = GTK_MINOR_VERSION;
113 const guint gtk_micro_version = GTK_MICRO_VERSION;
114 const guint gtk_binary_age = GTK_BINARY_AGE;
115 const guint gtk_interface_age = GTK_INTERFACE_AGE;
116
117 static guint gtk_main_loop_level = 0;
118 static gint gtk_initialized = FALSE;
119 static GList *current_events = NULL;
120
121 static GSList *main_loops = NULL;      /* stack of currently executing main loops */
122
123 static GSList *grabs = NULL;               /* A stack of unique grabs. The grabbing
124                                             *  widget is the first one on the list.
125                                             */
126 static GList *init_functions = NULL;       /* A list of init functions.
127                                             */
128 static GList *quit_functions = NULL;       /* A list of quit functions.
129                                             */
130 static GMemChunk *quit_mem_chunk = NULL;
131
132 static GSList *key_snoopers = NULL;
133
134 static GdkVisual *gtk_visual;              /* The visual to be used in creating new
135                                             *  widgets.
136                                             */
137 static GdkColormap *gtk_colormap;          /* The colormap to be used in creating new
138                                             *  widgets.
139                                             */
140
141 guint gtk_debug_flags = 0;                 /* Global GTK debug flag */
142
143 #ifdef G_ENABLE_DEBUG
144 static const GDebugKey gtk_debug_keys[] = {
145   {"objects", GTK_DEBUG_OBJECTS},
146   {"misc", GTK_DEBUG_MISC},
147   {"signals", GTK_DEBUG_SIGNALS},
148   {"dnd", GTK_DEBUG_DND},
149   {"plugsocket", GTK_DEBUG_PLUGSOCKET},
150   {"text", GTK_DEBUG_TEXT},
151   {"tree", GTK_DEBUG_TREE},
152   {"updates", GTK_DEBUG_UPDATES}
153 };
154
155 static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
156
157 #endif /* G_ENABLE_DEBUG */
158
159 gchar*
160 gtk_check_version (guint required_major,
161                    guint required_minor,
162                    guint required_micro)
163 {
164   if (required_major > GTK_MAJOR_VERSION)
165     return "Gtk+ version too old (major mismatch)";
166   if (required_major < GTK_MAJOR_VERSION)
167     return "Gtk+ version too new (major mismatch)";
168   if (required_minor > GTK_MINOR_VERSION)
169     return "Gtk+ version too old (minor mismatch)";
170   if (required_minor < GTK_MINOR_VERSION)
171     return "Gtk+ version too new (minor mismatch)";
172   if (required_micro < GTK_MICRO_VERSION - GTK_BINARY_AGE)
173     return "Gtk+ version too new (micro mismatch)";
174   if (required_micro > GTK_MICRO_VERSION)
175     return "Gtk+ version too old (micro mismatch)";
176   return NULL;
177 }
178
179 #ifdef __EMX__
180 static gchar *add_dll_suffix(gchar *module_name)
181 {
182     gchar *suffix = strrchr(module_name, '.');
183     
184     if (!suffix || stricmp(suffix, ".dll"))
185     {
186         gchar *old = module_name;
187           
188         module_name = g_strconcat (module_name, ".dll", NULL);
189         g_free (old);
190     }
191     return (module_name);
192 }
193 #endif
194
195 #undef gtk_init_check
196
197 gboolean
198 gtk_init_check (int      *argc,
199                 char   ***argv)
200 {
201   GSList *gtk_modules = NULL;
202   GSList *slist;
203   gchar *env_string = NULL;
204
205   if (gtk_initialized)
206     return TRUE;
207
208 #if     0
209   g_set_error_handler (gtk_error);
210   g_set_warning_handler (gtk_warning);
211   g_set_message_handler (gtk_message);
212   g_set_print_handler (gtk_print);
213 #endif
214   
215   /* Initialize "gdk". We pass along the 'argc' and 'argv'
216    *  parameters as they contain information that GDK uses
217    */
218   if (!gdk_init_check (argc, argv))
219     return FALSE;
220
221   gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
222   
223 #ifdef G_ENABLE_DEBUG
224   env_string = getenv ("GTK_DEBUG");
225   if (env_string != NULL)
226     {
227       gtk_debug_flags = g_parse_debug_string (env_string,
228                                               gtk_debug_keys,
229                                               gtk_ndebug_keys);
230       env_string = NULL;
231     }
232 #endif  /* G_ENABLE_DEBUG */
233
234   env_string = getenv ("GTK_MODULES");
235   if (env_string)
236     {
237       gchar **modules, **as;
238
239 #ifndef __EMX__
240       modules = g_strsplit (env_string, G_SEARCHPATH_SEPARATOR_S, -1);
241 #else
242       modules = g_strsplit (env_string, ";", -1);
243 #endif
244       for (as = modules; *as; as++)
245         {
246           if (**as)
247             gtk_modules = g_slist_prepend (gtk_modules, *as);
248           else
249             g_free (*as);
250         }
251       g_free (modules);
252       env_string = NULL;
253     }
254
255   if (argc && argv)
256     {
257       gint i, j, k;
258       
259       for (i = 1; i < *argc;)
260         {
261           if (strcmp ("--gtk-module", (*argv)[i]) == 0 ||
262               strncmp ("--gtk-module=", (*argv)[i], 13) == 0)
263             {
264               gchar *module_name = (*argv)[i] + 12;
265               
266               if (*module_name == '=')
267                 module_name++;
268               else if (i + 1 < *argc)
269                 {
270                   (*argv)[i] = NULL;
271                   i += 1;
272                   module_name = (*argv)[i];
273                 }
274               (*argv)[i] = NULL;
275
276               if (module_name && *module_name)
277                 gtk_modules = g_slist_prepend (gtk_modules, g_strdup (module_name));
278             }
279           else if (strcmp ("--g-fatal-warnings", (*argv)[i]) == 0)
280             {
281               GLogLevelFlags fatal_mask;
282               
283               fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
284               fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
285               g_log_set_always_fatal (fatal_mask);
286               (*argv)[i] = NULL;
287             }
288 #ifdef G_ENABLE_DEBUG
289           else if ((strcmp ("--gtk-debug", (*argv)[i]) == 0) ||
290                    (strncmp ("--gtk-debug=", (*argv)[i], 12) == 0))
291             {
292               gchar *equal_pos = strchr ((*argv)[i], '=');
293               
294               if (equal_pos != NULL)
295                 {
296                   gtk_debug_flags |= g_parse_debug_string (equal_pos+1,
297                                                            gtk_debug_keys,
298                                                            gtk_ndebug_keys);
299                 }
300               else if ((i + 1) < *argc && (*argv)[i + 1])
301                 {
302                   gtk_debug_flags |= g_parse_debug_string ((*argv)[i+1],
303                                                            gtk_debug_keys,
304                                                            gtk_ndebug_keys);
305                   (*argv)[i] = NULL;
306                   i += 1;
307                 }
308               (*argv)[i] = NULL;
309             }
310           else if ((strcmp ("--gtk-no-debug", (*argv)[i]) == 0) ||
311                    (strncmp ("--gtk-no-debug=", (*argv)[i], 15) == 0))
312             {
313               gchar *equal_pos = strchr ((*argv)[i], '=');
314               
315               if (equal_pos != NULL)
316                 {
317                   gtk_debug_flags &= ~g_parse_debug_string (equal_pos+1,
318                                                             gtk_debug_keys,
319                                                             gtk_ndebug_keys);
320                 }
321               else if ((i + 1) < *argc && (*argv)[i + 1])
322                 {
323                   gtk_debug_flags &= ~g_parse_debug_string ((*argv)[i+1],
324                                                             gtk_debug_keys,
325                                                             gtk_ndebug_keys);
326                   (*argv)[i] = NULL;
327                   i += 1;
328                 }
329               (*argv)[i] = NULL;
330             }
331 #endif /* G_ENABLE_DEBUG */
332           i += 1;
333         }
334       
335       for (i = 1; i < *argc; i++)
336         {
337           for (k = i; k < *argc; k++)
338             if ((*argv)[k] != NULL)
339               break;
340           
341           if (k > i)
342             {
343               k -= i;
344               for (j = i + k; j < *argc; j++)
345                 (*argv)[j-k] = (*argv)[j];
346               *argc -= k;
347             }
348         }
349     }
350
351   if (gtk_debug_flags & GTK_DEBUG_UPDATES)
352     gdk_window_set_debug_updates (TRUE);
353   
354   /* load gtk modules */
355   gtk_modules = g_slist_reverse (gtk_modules);
356   for (slist = gtk_modules; slist; slist = slist->next)
357     {
358       gchar *module_name;
359       GModule *module = NULL;
360       GtkModuleInitFunc modinit_func = NULL;
361       
362       module_name = slist->data;
363       slist->data = NULL;
364 #ifndef __EMX__
365       if (!g_path_is_absolute (module_name))
366         {
367           gchar *old = module_name;
368           
369           module_name = g_module_build_path (NULL, module_name);
370           g_free (old);
371         }
372 #else
373       module_name = add_dll_suffix(module_name);
374 #endif
375       if (g_module_supported ())
376         {
377           module = g_module_open (module_name, G_MODULE_BIND_LAZY);
378           if (module &&
379               g_module_symbol (module, "gtk_module_init", (gpointer*) &modinit_func) &&
380               modinit_func)
381             {
382               if (!g_slist_find (gtk_modules, modinit_func))
383                 {
384                   g_module_make_resident (module);
385                   slist->data = modinit_func;
386                 }
387               else
388                 {
389                   g_module_close (module);
390                   module = NULL;
391                 }
392             }
393         }
394       if (!modinit_func)
395         {
396           g_message ("Failed to load module \"%s\": %s",
397                      module ? g_module_name (module) : module_name,
398                      g_module_error ());
399           if (module)
400             g_module_close (module);
401         }
402       g_free (module_name);
403     }
404
405 #ifdef ENABLE_NLS
406 #  ifndef G_OS_WIN32
407   bindtextdomain(GETTEXT_PACKAGE, GTK_LOCALEDIR);
408 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
409   bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
410 #    endif
411 #  else /* !G_OS_WIN32 */
412   {
413     bindtextdomain (GETTEXT_PACKAGE,
414                     g_win32_get_package_installation_subdirectory (GETTEXT_PACKAGE,
415                                                                    g_strdup_printf ("gtk-%d.%d.dll", GTK_MAJOR_VERSION, GTK_MINOR_VERSION),
416                                                                    "locale"));
417   }
418 #endif
419 #endif  
420
421   {
422   /* Translate to default:RTL if you want your widgets
423    * to be RTL, otherwise translate to default:LTR.
424    * Do *not* translate it to "predefinito:LTR", if it
425    * it isn't default:LTR or default:RTL it will not work 
426    */
427     char *e = _("default:LTR");
428     if (strcmp (e, "default:RTL")==0) {
429       gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
430     } else if (strcmp (e, "default:LTR")) {
431       g_warning ("Whoever translated default:LTR did so wrongly.\n");
432     }
433   }
434
435   /* Initialize the default visual and colormap to be
436    *  used in creating widgets. (We want to use the system
437    *  defaults so as to be nice to the colormap).
438    */
439   gtk_visual = gdk_visual_get_system ();
440   gtk_colormap = gdk_colormap_get_system ();
441
442   gtk_type_init ();
443   gtk_signal_init ();
444   gtk_rc_init ();
445   
446   
447   /* Register an exit function to make sure we are able to cleanup.
448    */
449   g_atexit (gtk_exit_func);
450   
451   /* Set the 'initialized' flag.
452    */
453   gtk_initialized = TRUE;
454
455   /* initialize gtk modules
456    */
457   for (slist = gtk_modules; slist; slist = slist->next)
458     {
459       if (slist->data)
460         {
461           GtkModuleInitFunc modinit;
462           
463           modinit = slist->data;
464           modinit (argc, argv);
465         }
466     }
467   g_slist_free (gtk_modules);
468   
469 #ifndef G_OS_WIN32
470   /* No use warning on Win32, there aren't any non-devel versions anyhow... */
471   g_message (""              "YOU ARE USING THE DEVEL BRANCH 1.3.x OF GTK+ WHICH IS CURRENTLY\n"
472              "                UNDER HEAVY DEVELOPMENT AND FREQUENTLY INTRODUCES INSTABILITIES.\n"
473              "                if you don't know why you are getting this, you probably want to\n"
474              "                use the stable branch which can be retrived from\n"
475              "                ftp://ftp.gtk.org/pub/gtk/v1.2/ or via CVS with\n"
476              "                cvs checkout -r glib-1-2 glib; cvs checkout -r gtk-1-2 gtk+");
477 #endif
478
479   return TRUE;
480 }
481
482 #undef gtk_init
483
484 void
485 gtk_init (int *argc, char ***argv)
486 {
487   if (!gtk_init_check (argc, argv))
488     {
489       g_warning ("cannot open display: %s", gdk_get_display ());
490       exit(1);
491     }
492 }
493
494 #ifdef G_OS_WIN32
495
496 static void
497 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
498 {
499   if (sizeof_GtkWindow != sizeof (GtkWindow))
500     g_error ("Incompatible build!\n"
501              "The code using GTK+ thinks GtkWindow is of different\n"
502              "size than it actually is in this build of GTK+.\n"
503              "On Windows, this probably means that you have compiled\n"
504              "your code with gcc without the -fnative-struct switch.");
505 }
506
507 /* These two functions might get more checks added later, thus pass
508  * in the number of extra args.
509  */
510 void
511 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow)
512 {
513   check_sizeof_GtkWindow (sizeof_GtkWindow);
514   gtk_init (argc, argv);
515 }
516
517 gboolean
518 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow)
519 {
520   check_sizeof_GtkWindow (sizeof_GtkWindow);
521   return gtk_init_check (argc, argv);
522 }
523
524 #endif
525
526 void
527 gtk_exit (gint errorcode)
528 {
529   /* Only if "gtk" has been initialized should we de-initialize.
530    */
531   /* de-initialisation is done by the gtk_exit_funct(),
532    * no need to do this here (Alex J.)
533    */
534   gdk_exit(errorcode);
535 }
536
537 gchar*
538 gtk_set_locale (void)
539 {
540   return gdk_set_locale ();
541 }
542
543 gchar*
544 gtk_get_default_language (void)
545 {
546   gchar *lang;
547   gchar *p;
548   
549   lang = g_strdup (setlocale (LC_CTYPE, NULL));
550   p = strchr (lang, '.');
551   if (p)
552     *p = '\0';
553   p = strchr (lang, '@');
554   if (p)
555     *p = '\0';
556
557   return lang;
558 }
559
560 void
561 gtk_main (void)
562 {
563   GList *tmp_list;
564   GList *functions;
565   GtkInitFunction *init;
566   GMainLoop *loop;
567
568   gtk_main_loop_level++;
569   
570   loop = g_main_new (TRUE);
571   main_loops = g_slist_prepend (main_loops, loop);
572
573   tmp_list = functions = init_functions;
574   init_functions = NULL;
575   
576   while (tmp_list)
577     {
578       init = tmp_list->data;
579       tmp_list = tmp_list->next;
580       
581       (* init->function) (init->data);
582       g_free (init);
583     }
584   g_list_free (functions);
585
586   if (g_main_is_running (main_loops->data))
587     {
588       GDK_THREADS_LEAVE ();
589       g_main_run (loop);
590       GDK_THREADS_ENTER ();
591       gdk_flush ();
592     }
593
594   if (quit_functions)
595     {
596       GList *reinvoke_list = NULL;
597       GtkQuitFunction *quitf;
598
599       while (quit_functions)
600         {
601           quitf = quit_functions->data;
602
603           tmp_list = quit_functions;
604           quit_functions = g_list_remove_link (quit_functions, quit_functions);
605           g_list_free_1 (tmp_list);
606
607           if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
608               gtk_quit_invoke_function (quitf))
609             {
610               reinvoke_list = g_list_prepend (reinvoke_list, quitf);
611             }
612           else
613             {
614               gtk_quit_destroy (quitf);
615             }
616         }
617       if (reinvoke_list)
618         {
619           GList *work;
620           
621           work = g_list_last (reinvoke_list);
622           if (quit_functions)
623             quit_functions->prev = work;
624           work->next = quit_functions;
625           quit_functions = work;
626         }
627
628       gdk_flush ();
629     }
630               
631   main_loops = g_slist_remove (main_loops, loop);
632
633   g_main_destroy (loop);
634
635   gtk_main_loop_level--;
636 }
637
638 guint
639 gtk_main_level (void)
640 {
641   return gtk_main_loop_level;
642 }
643
644 void
645 gtk_main_quit (void)
646 {
647   g_return_if_fail (main_loops != NULL);
648
649   g_main_quit (main_loops->data);
650 }
651
652 gint
653 gtk_events_pending (void)
654 {
655   gboolean result;
656   
657   GDK_THREADS_LEAVE ();  
658   result = g_main_pending();
659   GDK_THREADS_ENTER ();
660
661   return result;
662 }
663
664 gint 
665 gtk_main_iteration (void)
666 {
667   GDK_THREADS_LEAVE ();
668   g_main_iteration (TRUE);
669   GDK_THREADS_ENTER ();
670
671   if (main_loops)
672     return !g_main_is_running (main_loops->data);
673   else
674     return TRUE;
675 }
676
677 gint 
678 gtk_main_iteration_do (gboolean blocking)
679 {
680   GDK_THREADS_LEAVE ();
681   g_main_iteration (blocking);
682   GDK_THREADS_ENTER ();
683
684   if (main_loops)
685     return !g_main_is_running (main_loops->data);
686   else
687     return TRUE;
688 }
689
690 void 
691 gtk_main_do_event (GdkEvent *event)
692 {
693   GtkWidget *event_widget;
694   GtkWidget *grab_widget;
695   GdkEvent *next_event;
696   GList *tmp_list;
697
698   /* If there are any events pending then get the next one.
699    */
700   next_event = gdk_event_peek ();
701   
702   /* Try to compress enter/leave notify events. These event
703    *  pairs occur when the mouse is dragged quickly across
704    *  a window with many buttons (or through a menu). Instead
705    *  of highlighting and de-highlighting each widget that
706    *  is crossed it is better to simply de-highlight the widget
707    *  which contained the mouse initially and highlight the
708    *  widget which ends up containing the mouse.
709    */
710   if (next_event)
711     if (((event->type == GDK_ENTER_NOTIFY) ||
712          (event->type == GDK_LEAVE_NOTIFY)) &&
713         ((next_event->type == GDK_ENTER_NOTIFY) ||
714          (next_event->type == GDK_LEAVE_NOTIFY)) &&
715         (next_event->type != event->type) &&
716         (next_event->any.window == event->any.window))
717       {
718         /* Throw both the peeked copy and the queued copy away 
719          */
720         gdk_event_free (next_event);
721         next_event = gdk_event_get ();
722         gdk_event_free (next_event);
723         
724         return;
725       }
726
727   if (next_event)
728     gdk_event_free (next_event);
729
730   /* Find the widget which got the event. We store the widget
731    *  in the user_data field of GdkWindow's.
732    *  Ignore the event if we don't have a widget for it, except
733    *  for GDK_PROPERTY_NOTIFY events which are handled specialy.
734    *  Though this happens rarely, bogus events can occour
735    *  for e.g. destroyed GdkWindows. 
736    */
737   event_widget = gtk_get_event_widget (event);
738   if (!event_widget)
739     {
740       /* To handle selection INCR transactions, we select
741        * PropertyNotify events on the requestor window and create
742        * a corresponding (fake) GdkWindow so that events get
743        * here. There won't be a widget though, so we have to handle
744            * them specially
745            */
746       if (event->type == GDK_PROPERTY_NOTIFY)
747         gtk_selection_incr_event (event->any.window,
748                                   &event->property);
749       
750       return;
751     }
752   
753   /* Push the event onto a stack of current events for
754    * gtk_current_event_get().
755    */
756   current_events = g_list_prepend (current_events, event);
757   
758   /* If there is a grab in effect...
759    */
760   if (grabs)
761     {
762       grab_widget = grabs->data;
763       
764       /* If the grab widget is an ancestor of the event widget
765        *  then we send the event to the original event widget.
766        *  This is the key to implementing modality.
767        */
768       if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
769           gtk_widget_is_ancestor (event_widget, grab_widget))
770         grab_widget = event_widget;
771     }
772   else
773     {
774       grab_widget = event_widget;
775     }
776
777   /* Not all events get sent to the grabbing widget.
778    * The delete, destroy, expose, focus change and resize
779    *  events still get sent to the event widget because
780    *  1) these events have no meaning for the grabbing widget
781    *  and 2) redirecting these events to the grabbing widget
782    *  could cause the display to be messed up.
783    * 
784    * Drag events are also not redirected, since it isn't
785    *  clear what the semantics of that would be.
786    */
787   switch (event->type)
788     {
789     case GDK_NOTHING:
790       break;
791       
792     case GDK_DELETE:
793       gtk_widget_ref (event_widget);
794       if ((!grabs || gtk_widget_get_toplevel (grabs->data) == event_widget) &&
795           !gtk_widget_event (event_widget, event))
796         gtk_widget_destroy (event_widget);
797       gtk_widget_unref (event_widget);
798       break;
799       
800     case GDK_DESTROY:
801       /* Unexpected GDK_DESTROY from the outside, ignore for
802        * child windows, handle like a GDK_DELETE for toplevels
803        */
804       if (!event_widget->parent)
805         {
806           gtk_widget_ref (event_widget);
807           if (!gtk_widget_event (event_widget, event) &&
808               !GTK_OBJECT_DESTROYED (event_widget))
809             gtk_widget_destroy (event_widget);
810           gtk_widget_unref (event_widget);
811         }
812       break;
813       
814     case GDK_EXPOSE:
815       if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
816         gdk_window_begin_paint_rect (event->any.window, &event->expose.area);
817
818       gtk_widget_event (event_widget, event);
819
820       if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
821         gdk_window_end_paint (event->any.window);
822       break;
823
824     case GDK_PROPERTY_NOTIFY:
825     case GDK_NO_EXPOSE:
826     case GDK_FOCUS_CHANGE:
827     case GDK_CONFIGURE:
828     case GDK_MAP:
829     case GDK_UNMAP:
830     case GDK_SELECTION_CLEAR:
831     case GDK_SELECTION_REQUEST:
832     case GDK_SELECTION_NOTIFY:
833     case GDK_CLIENT_EVENT:
834     case GDK_VISIBILITY_NOTIFY:
835       gtk_widget_event (event_widget, event);
836       break;
837
838     case GDK_SCROLL:
839     case GDK_BUTTON_PRESS:
840     case GDK_2BUTTON_PRESS:
841     case GDK_3BUTTON_PRESS:
842       gtk_propagate_event (grab_widget, event);
843       break;
844
845     case GDK_KEY_PRESS:
846     case GDK_KEY_RELEASE:
847       if (key_snoopers)
848         {
849           if (gtk_invoke_key_snoopers (grab_widget, event))
850             break;
851         }
852       /* else fall through */
853     case GDK_MOTION_NOTIFY:
854     case GDK_BUTTON_RELEASE:
855     case GDK_PROXIMITY_IN:
856     case GDK_PROXIMITY_OUT:
857       gtk_propagate_event (grab_widget, event);
858       break;
859       
860     case GDK_ENTER_NOTIFY:
861       if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
862         {
863           gtk_widget_event (grab_widget, event);
864           if (event_widget == grab_widget)
865             GTK_PRIVATE_SET_FLAG (event_widget, GTK_LEAVE_PENDING);
866         }
867       break;
868       
869     case GDK_LEAVE_NOTIFY:
870       if (GTK_WIDGET_LEAVE_PENDING (event_widget))
871         {
872           GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_LEAVE_PENDING);
873           gtk_widget_event (event_widget, event);
874         }
875       else if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
876         gtk_widget_event (grab_widget, event);
877       break;
878       
879     case GDK_DRAG_STATUS:
880     case GDK_DROP_FINISHED:
881       gtk_drag_source_handle_event (event_widget, event);
882       break;
883     case GDK_DRAG_ENTER:
884     case GDK_DRAG_LEAVE:
885     case GDK_DRAG_MOTION:
886     case GDK_DROP_START:
887       gtk_drag_dest_handle_event (event_widget, event);
888       break;
889     }
890   
891   tmp_list = current_events;
892   current_events = g_list_remove_link (current_events, tmp_list);
893   g_list_free_1 (tmp_list);
894 }
895
896 gint
897 gtk_true (void)
898 {
899   return TRUE;
900 }
901
902 gint
903 gtk_false (void)
904 {
905   return FALSE;
906 }
907
908 void
909 gtk_grab_add (GtkWidget *widget)
910 {
911   g_return_if_fail (widget != NULL);
912   
913   if (!GTK_WIDGET_HAS_GRAB (widget))
914     {
915       GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
916       
917       grabs = g_slist_prepend (grabs, widget);
918       gtk_widget_ref (widget);
919     }
920 }
921
922 GtkWidget*
923 gtk_grab_get_current (void)
924 {
925   if (grabs)
926     return GTK_WIDGET (grabs->data);
927   return NULL;
928 }
929
930 void
931 gtk_grab_remove (GtkWidget *widget)
932 {
933   g_return_if_fail (widget != NULL);
934   
935   if (GTK_WIDGET_HAS_GRAB (widget))
936     {
937       GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
938       
939       grabs = g_slist_remove (grabs, widget);
940       gtk_widget_unref (widget);
941     }
942 }
943
944 void
945 gtk_init_add (GtkFunction function,
946               gpointer    data)
947 {
948   GtkInitFunction *init;
949   
950   init = g_new (GtkInitFunction, 1);
951   init->function = function;
952   init->data = data;
953   
954   init_functions = g_list_prepend (init_functions, init);
955 }
956
957 guint
958 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
959                          gpointer        func_data)
960 {
961   GtkKeySnooperData *data;
962   static guint snooper_id = 1;
963
964   g_return_val_if_fail (snooper != NULL, 0);
965
966   data = g_new (GtkKeySnooperData, 1);
967   data->func = snooper;
968   data->func_data = func_data;
969   data->id = snooper_id++;
970   key_snoopers = g_slist_prepend (key_snoopers, data);
971
972   return data->id;
973 }
974
975 void
976 gtk_key_snooper_remove (guint            snooper_id)
977 {
978   GtkKeySnooperData *data = NULL;
979   GSList *slist;
980
981   slist = key_snoopers;
982   while (slist)
983     {
984       data = slist->data;
985       if (data->id == snooper_id)
986         break;
987
988       slist = slist->next;
989       data = NULL;
990     }
991   if (data)
992     key_snoopers = g_slist_remove (key_snoopers, data);
993 }
994
995 static gint
996 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
997                          GdkEvent  *event)
998 {
999   GSList *slist;
1000   gint return_val = FALSE;
1001
1002   slist = key_snoopers;
1003   while (slist && !return_val)
1004     {
1005       GtkKeySnooperData *data;
1006
1007       data = slist->data;
1008       slist = slist->next;
1009       return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
1010     }
1011
1012   return return_val;
1013 }
1014
1015 guint
1016 gtk_quit_add_full (guint                main_level,
1017                    GtkFunction          function,
1018                    GtkCallbackMarshal   marshal,
1019                    gpointer             data,
1020                    GtkDestroyNotify     destroy)
1021 {
1022   static guint quit_id = 1;
1023   GtkQuitFunction *quitf;
1024   
1025   g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
1026
1027   if (!quit_mem_chunk)
1028     quit_mem_chunk = g_mem_chunk_new ("quit mem chunk", sizeof (GtkQuitFunction),
1029                                       512, G_ALLOC_AND_FREE);
1030   
1031   quitf = g_chunk_new (GtkQuitFunction, quit_mem_chunk);
1032   
1033   quitf->id = quit_id++;
1034   quitf->main_level = main_level;
1035   quitf->function = function;
1036   quitf->marshal = marshal;
1037   quitf->data = data;
1038   quitf->destroy = destroy;
1039
1040   quit_functions = g_list_prepend (quit_functions, quitf);
1041   
1042   return quitf->id;
1043 }
1044
1045 static void
1046 gtk_quit_destroy (GtkQuitFunction *quitf)
1047 {
1048   if (quitf->destroy)
1049     quitf->destroy (quitf->data);
1050   g_mem_chunk_free (quit_mem_chunk, quitf);
1051 }
1052
1053 static gint
1054 gtk_quit_destructor (GtkObject **object_p)
1055 {
1056   if (*object_p)
1057     gtk_object_destroy (*object_p);
1058   g_free (object_p);
1059
1060   return FALSE;
1061 }
1062
1063 void
1064 gtk_quit_add_destroy (guint              main_level,
1065                       GtkObject         *object)
1066 {
1067   GtkObject **object_p;
1068
1069   g_return_if_fail (main_level > 0);
1070   g_return_if_fail (object != NULL);
1071   g_return_if_fail (GTK_IS_OBJECT (object));
1072
1073   object_p = g_new (GtkObject*, 1);
1074   *object_p = object;
1075   gtk_signal_connect (object,
1076                       "destroy",
1077                       GTK_SIGNAL_FUNC (gtk_widget_destroyed),
1078                       object_p);
1079   gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
1080 }
1081
1082 guint
1083 gtk_quit_add (guint       main_level,
1084               GtkFunction function,
1085               gpointer    data)
1086 {
1087   return gtk_quit_add_full (main_level, function, NULL, data, NULL);
1088 }
1089
1090 void
1091 gtk_quit_remove (guint id)
1092 {
1093   GtkQuitFunction *quitf;
1094   GList *tmp_list;
1095   
1096   tmp_list = quit_functions;
1097   while (tmp_list)
1098     {
1099       quitf = tmp_list->data;
1100       
1101       if (quitf->id == id)
1102         {
1103           quit_functions = g_list_remove_link (quit_functions, tmp_list);
1104           g_list_free (tmp_list);
1105           gtk_quit_destroy (quitf);
1106           
1107           return;
1108         }
1109       
1110       tmp_list = tmp_list->next;
1111     }
1112 }
1113
1114 void
1115 gtk_quit_remove_by_data (gpointer data)
1116 {
1117   GtkQuitFunction *quitf;
1118   GList *tmp_list;
1119   
1120   tmp_list = quit_functions;
1121   while (tmp_list)
1122     {
1123       quitf = tmp_list->data;
1124       
1125       if (quitf->data == data)
1126         {
1127           quit_functions = g_list_remove_link (quit_functions, tmp_list);
1128           g_list_free (tmp_list);
1129           gtk_quit_destroy (quitf);
1130
1131           return;
1132         }
1133       
1134       tmp_list = tmp_list->next;
1135     }
1136 }
1137
1138 guint
1139 gtk_timeout_add_full (guint32            interval,
1140                       GtkFunction        function,
1141                       GtkCallbackMarshal marshal,
1142                       gpointer           data,
1143                       GtkDestroyNotify   destroy)
1144 {
1145   if (marshal)
1146     {
1147       GtkClosure *closure;
1148
1149       closure = g_new (GtkClosure, 1);
1150       closure->marshal = marshal;
1151       closure->data = data;
1152       closure->destroy = destroy;
1153
1154       return g_timeout_add_full (0, interval, 
1155                                  gtk_invoke_idle_timeout,
1156                                  closure,
1157                                  gtk_destroy_closure);
1158     }
1159   else
1160     return g_timeout_add_full (0, interval, function, data, destroy);
1161 }
1162
1163 guint
1164 gtk_timeout_add (guint32     interval,
1165                  GtkFunction function,
1166                  gpointer    data)
1167 {
1168   return g_timeout_add_full (0, interval, function, data, NULL);
1169 }
1170
1171 void
1172 gtk_timeout_remove (guint tag)
1173 {
1174   g_source_remove (tag);
1175 }
1176
1177 guint
1178 gtk_idle_add_full (gint                 priority,
1179                    GtkFunction          function,
1180                    GtkCallbackMarshal   marshal,
1181                    gpointer             data,
1182                    GtkDestroyNotify     destroy)
1183 {
1184   if (marshal)
1185     {
1186       GtkClosure *closure;
1187
1188       closure = g_new (GtkClosure, 1);
1189       closure->marshal = marshal;
1190       closure->data = data;
1191       closure->destroy = destroy;
1192
1193       return g_idle_add_full (priority,
1194                               gtk_invoke_idle_timeout,
1195                               closure,
1196                               gtk_destroy_closure);
1197     }
1198   else
1199     return g_idle_add_full (priority, function, data, destroy);
1200 }
1201
1202 guint
1203 gtk_idle_add (GtkFunction function,
1204               gpointer    data)
1205 {
1206   return g_idle_add_full (GTK_PRIORITY_DEFAULT, function, data, NULL);
1207 }
1208
1209 guint       
1210 gtk_idle_add_priority   (gint               priority,
1211                          GtkFunction        function,
1212                          gpointer           data)
1213 {
1214   return g_idle_add_full (priority, function, data, NULL);
1215 }
1216
1217 void
1218 gtk_idle_remove (guint tag)
1219 {
1220   g_source_remove (tag);
1221 }
1222
1223 void
1224 gtk_idle_remove_by_data (gpointer data)
1225 {
1226   if (!g_idle_remove_by_data (data))
1227     g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
1228 }
1229
1230 guint
1231 gtk_input_add_full (gint                source,
1232                     GdkInputCondition   condition,
1233                     GdkInputFunction    function,
1234                     GtkCallbackMarshal  marshal,
1235                     gpointer            data,
1236                     GtkDestroyNotify    destroy)
1237 {
1238   if (marshal)
1239     {
1240       GtkClosure *closure;
1241
1242       closure = g_new (GtkClosure, 1);
1243       closure->marshal = marshal;
1244       closure->data = data;
1245       closure->destroy = destroy;
1246
1247       return gdk_input_add_full (source,
1248                                  condition,
1249                                  (GdkInputFunction) gtk_invoke_input,
1250                                  closure,
1251                                  (GdkDestroyNotify) gtk_destroy_closure);
1252     }
1253   else
1254     return gdk_input_add_full (source, condition, function, data, destroy);
1255 }
1256
1257 void
1258 gtk_input_remove (guint tag)
1259 {
1260   g_source_remove (tag);
1261 }
1262
1263 static void
1264 gtk_destroy_closure (gpointer data)
1265 {
1266   GtkClosure *closure = data;
1267
1268   if (closure->destroy)
1269     (closure->destroy) (closure->data);
1270   g_free (closure);
1271 }
1272
1273 static gboolean
1274 gtk_invoke_idle_timeout (gpointer data)
1275 {
1276   GtkClosure *closure = data;
1277
1278   GtkArg args[1];
1279   gint ret_val = FALSE;
1280   args[0].name = NULL;
1281   args[0].type = GTK_TYPE_BOOL;
1282   args[0].d.pointer_data = &ret_val;
1283   closure->marshal (NULL, closure->data,  0, args);
1284   return ret_val;
1285 }
1286
1287 static void
1288 gtk_invoke_input (gpointer          data,
1289                   gint              source,
1290                   GdkInputCondition condition)
1291 {
1292   GtkClosure *closure = data;
1293
1294   GtkArg args[3];
1295   args[0].type = GTK_TYPE_INT;
1296   args[0].name = NULL;
1297   GTK_VALUE_INT(args[0]) = source;
1298   args[1].type = GTK_TYPE_GDK_INPUT_CONDITION;
1299   args[1].name = NULL;
1300   GTK_VALUE_FLAGS(args[1]) = condition;
1301   args[2].type = GTK_TYPE_NONE;
1302   args[2].name = NULL;
1303
1304   closure->marshal (NULL, closure->data, 2, args);
1305 }
1306
1307 GdkEvent*
1308 gtk_get_current_event (void)
1309 {
1310   if (current_events)
1311     return gdk_event_copy (current_events->data);
1312   else
1313     return NULL;
1314 }
1315
1316 /**
1317  * gtk_get_current_event_time:
1318  * 
1319  * If there is a current event and it has a timestamp, return that
1320  * timestamp, otherwise return %GDK_CURRENT_TIME.
1321  * 
1322  * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
1323  **/
1324 guint32
1325 gtk_get_current_event_time (void)
1326 {
1327   if (current_events)
1328     return gdk_event_get_time (current_events->data);
1329   else
1330     return GDK_CURRENT_TIME;
1331 }
1332
1333 gboolean
1334 gtk_get_current_event_state (GdkModifierType *state)
1335 {
1336   g_return_val_if_fail (state != NULL, FALSE);
1337   
1338   if (current_events)
1339     return gdk_event_get_state (current_events->data, state);
1340   else
1341     {
1342       *state = 0;
1343       return FALSE;
1344     }
1345 }
1346
1347 GtkWidget*
1348 gtk_get_event_widget (GdkEvent *event)
1349 {
1350   GtkWidget *widget;
1351
1352   widget = NULL;
1353   if (event && event->any.window)
1354     gdk_window_get_user_data (event->any.window, (void**) &widget);
1355   
1356   return widget;
1357 }
1358
1359 static void
1360 gtk_exit_func (void)
1361 {
1362   if (gtk_initialized)
1363     {
1364       gtk_initialized = FALSE;
1365     }
1366 }
1367
1368
1369 static gint
1370 gtk_quit_invoke_function (GtkQuitFunction *quitf)
1371 {
1372   if (!quitf->marshal)
1373     return quitf->function (quitf->data);
1374   else
1375     {
1376       GtkArg args[1];
1377       gint ret_val = FALSE;
1378
1379       args[0].name = NULL;
1380       args[0].type = GTK_TYPE_BOOL;
1381       args[0].d.pointer_data = &ret_val;
1382       ((GtkCallbackMarshal) quitf->marshal) (NULL,
1383                                              quitf->data,
1384                                              0, args);
1385       return ret_val;
1386     }
1387 }
1388
1389 void
1390 gtk_propagate_event (GtkWidget *widget,
1391                      GdkEvent  *event)
1392 {
1393   gint handled_event;
1394   
1395   g_return_if_fail (widget != NULL);
1396   g_return_if_fail (GTK_IS_WIDGET (widget));
1397   g_return_if_fail (event != NULL);
1398   
1399   handled_event = FALSE;
1400
1401   if ((event->type == GDK_KEY_PRESS) ||
1402       (event->type == GDK_KEY_RELEASE))
1403     {
1404       /* Only send key events within Window widgets to the Window
1405        *  The Window widget will in turn pass the
1406        *  key event on to the currently focused widget
1407        *  for that window.
1408        */
1409       GtkWidget *window;
1410
1411       window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
1412       if (window)
1413         {
1414           if (GTK_WIDGET_IS_SENSITIVE (window))
1415             gtk_widget_event (window, event);
1416
1417           handled_event = TRUE; /* don't send to widget */
1418         }
1419     }
1420   
1421   /* Other events get propagated up the widget tree
1422    *  so that parents can see the button and motion
1423    *  events of the children.
1424    */
1425   while (!handled_event && widget)
1426     {
1427       GtkWidget *tmp;
1428
1429       gtk_widget_ref (widget);
1430       handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event);
1431       tmp = widget->parent;
1432       gtk_widget_unref (widget);
1433       widget  = tmp;
1434     }
1435 }
1436
1437 #if 0
1438 static void
1439 gtk_error (gchar *str)
1440 {
1441   gtk_print (str);
1442 }
1443
1444 static void
1445 gtk_warning (gchar *str)
1446 {
1447   gtk_print (str);
1448 }
1449
1450 static void
1451 gtk_message (gchar *str)
1452 {
1453   gtk_print (str);
1454 }
1455
1456 static void
1457 gtk_print (gchar *str)
1458 {
1459   static GtkWidget *window = NULL;
1460   static GtkWidget *text;
1461   static int level = 0;
1462   GtkWidget *box1;
1463   GtkWidget *box2;
1464   GtkWidget *table;
1465   GtkWidget *hscrollbar;
1466   GtkWidget *vscrollbar;
1467   GtkWidget *separator;
1468   GtkWidget *button;
1469   
1470   if (level > 0)
1471     {
1472       fputs (str, stdout);
1473       fflush (stdout);
1474       return;
1475     }
1476   
1477   if (!window)
1478     {
1479       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1480       
1481       gtk_signal_connect (GTK_OBJECT (window), "destroy",
1482                           (GtkSignalFunc) gtk_widget_destroyed,
1483                           &window);
1484       
1485       gtk_window_set_title (GTK_WINDOW (window), "Messages");
1486       
1487       box1 = gtk_vbox_new (FALSE, 0);
1488       gtk_container_add (GTK_CONTAINER (window), box1);
1489       gtk_widget_show (box1);
1490       
1491       
1492       box2 = gtk_vbox_new (FALSE, 10);
1493       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1494       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1495       gtk_widget_show (box2);
1496       
1497       
1498       table = gtk_table_new (2, 2, FALSE);
1499       gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
1500       gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
1501       gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
1502       gtk_widget_show (table);
1503       
1504       text = gtk_text_new (NULL, NULL);
1505       gtk_text_set_editable (GTK_TEXT (text), FALSE);
1506       gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
1507       gtk_widget_show (text);
1508       gtk_widget_realize (text);
1509       
1510       hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
1511       gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
1512                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
1513       gtk_widget_show (hscrollbar);
1514       
1515       vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
1516       gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
1517                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1518       gtk_widget_show (vscrollbar);
1519       
1520       separator = gtk_hseparator_new ();
1521       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1522       gtk_widget_show (separator);
1523       
1524       
1525       box2 = gtk_vbox_new (FALSE, 10);
1526       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1527       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
1528       gtk_widget_show (box2);
1529       
1530       
1531       button = gtk_button_new_with_label ("close");
1532       gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1533                                  (GtkSignalFunc) gtk_widget_hide,
1534                                  GTK_OBJECT (window));
1535       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1536       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1537       gtk_widget_grab_default (button);
1538       gtk_widget_show (button);
1539     }
1540   
1541   level += 1;
1542   gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
1543   level -= 1;
1544   
1545   if (!GTK_WIDGET_VISIBLE (window))
1546     gtk_widget_show (window);
1547 }
1548 #endif