]> Pileus Git - ~andy/gtk/blob - gtk/gtkmain.c
Flip the padding
[~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 #include <config.h>
28
29 #include <glib.h>
30 #include "gdkconfig.h"
31
32 #include <locale.h>
33
34 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
35 #include <libintl.h>
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #include <sys/types.h>          /* For uid_t, gid_t */
45
46 #ifdef G_OS_WIN32
47 #define STRICT
48 #include <windows.h>
49 #undef STRICT
50 #endif
51
52 #include <pango/pango-types.h>  /* For pango_language_from_string */
53
54 #include "gtkintl.h"
55
56 #include "gtkaccelmap.h"
57 #include "gtkbox.h"
58 #include "gtkclipboard.h"
59 #include "gtkdnd.h"
60 #include "gtkversion.h"
61 #include "gtkmain.h"
62 #include "gtkmodules.h"
63 #include "gtkrc.h"
64 #include "gtkselection.h"
65 #include "gtksettings.h"
66 #include "gtkwidget.h"
67 #include "gtkwindow.h"
68 #include "gtkprivate.h"
69 #include "gtkdebug.h"
70 #include "gtkalias.h"
71
72 /* Private type definitions
73  */
74 typedef struct _GtkInitFunction          GtkInitFunction;
75 typedef struct _GtkQuitFunction          GtkQuitFunction;
76 typedef struct _GtkClosure               GtkClosure;
77 typedef struct _GtkKeySnooperData        GtkKeySnooperData;
78
79 struct _GtkInitFunction
80 {
81   GtkFunction function;
82   gpointer data;
83 };
84
85 struct _GtkQuitFunction
86 {
87   guint id;
88   guint main_level;
89   GtkCallbackMarshal marshal;
90   GtkFunction function;
91   gpointer data;
92   GtkDestroyNotify destroy;
93 };
94
95 struct _GtkClosure
96 {
97   GtkCallbackMarshal marshal;
98   gpointer data;
99   GtkDestroyNotify destroy;
100 };
101
102 struct _GtkKeySnooperData
103 {
104   GtkKeySnoopFunc func;
105   gpointer func_data;
106   guint id;
107 };
108
109 static gint  gtk_quit_invoke_function    (GtkQuitFunction    *quitf);
110 static void  gtk_quit_destroy            (GtkQuitFunction    *quitf);
111 static gint  gtk_invoke_key_snoopers     (GtkWidget          *grab_widget,
112                                           GdkEvent           *event);
113
114 static void     gtk_destroy_closure      (gpointer            data);
115 static gboolean gtk_invoke_idle_timeout  (gpointer            data);
116 static void     gtk_invoke_input         (gpointer            data,
117                                           gint                source,
118                                           GdkInputCondition   condition);
119
120 #if 0
121 static void  gtk_error                   (gchar              *str);
122 static void  gtk_warning                 (gchar              *str);
123 static void  gtk_message                 (gchar              *str);
124 static void  gtk_print                   (gchar              *str);
125 #endif
126
127 static GtkWindowGroup *gtk_main_get_window_group (GtkWidget   *widget);
128
129 const guint gtk_major_version = GTK_MAJOR_VERSION;
130 const guint gtk_minor_version = GTK_MINOR_VERSION;
131 const guint gtk_micro_version = GTK_MICRO_VERSION;
132 const guint gtk_binary_age = GTK_BINARY_AGE;
133 const guint gtk_interface_age = GTK_INTERFACE_AGE;
134
135 static guint gtk_main_loop_level = 0;
136 static gint gtk_initialized = FALSE;
137 static GList *current_events = NULL;
138
139 static GSList *main_loops = NULL;      /* stack of currently executing main loops */
140
141 static GList *init_functions = NULL;       /* A list of init functions.
142                                             */
143 static GList *quit_functions = NULL;       /* A list of quit functions.
144                                             */
145 static GMemChunk *quit_mem_chunk = NULL;
146
147 static GSList *key_snoopers = NULL;
148
149 guint gtk_debug_flags = 0;                 /* Global GTK debug flag */
150
151 #ifdef G_ENABLE_DEBUG
152 static const GDebugKey gtk_debug_keys[] = {
153   {"misc", GTK_DEBUG_MISC},
154   {"plugsocket", GTK_DEBUG_PLUGSOCKET},
155   {"text", GTK_DEBUG_TEXT},
156   {"tree", GTK_DEBUG_TREE},
157   {"updates", GTK_DEBUG_UPDATES},
158   {"keybindings", GTK_DEBUG_KEYBINDINGS},
159   {"multihead", GTK_DEBUG_MULTIHEAD},
160   {"modules", GTK_DEBUG_MODULES},
161   {"geometry", GTK_DEBUG_GEOMETRY},
162   {"icontheme", GTK_DEBUG_ICONTHEME}
163 };
164
165 static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
166
167 #endif /* G_ENABLE_DEBUG */
168
169 /**
170  * gtk_check_version:
171  * @required_major: the required major version.
172  * @required_minor: the required major version.
173  * @required_micro: the required major version.
174  * 
175  * Checks that the GTK+ library in use is compatible with the
176  * given version. Generally you would pass in the constants
177  * #GTK_MAJOR_VERSION, #GTK_MINOR_VERSION, #GTK_MICRO_VERSION
178  * as the three arguments to this function; that produces
179  * a check that the library in use is compatible with
180  * the version of GTK+ the application or module was compiled
181  * against.
182  *
183  * Compatibility is defined by two things: first the version
184  * of the running library is newer than the version
185  * @required_major.required_minor.@required_micro. Second
186  * the running library must be binary compatible with the
187  * version @required_major.required_minor.@required_micro
188  * (same major version.)
189  *
190  * This function is primarily for GTK+ modules; the module
191  * can call this function to check that it wasn't loaded
192  * into an incompatible version of GTK+. However, such a
193  * a check isn't completely reliable, since the module may be
194  * linked against an old version of GTK+ and calling the
195  * old version of gtk_check_version(), but still get loaded
196  * into an application using a newer version of GTK+.
197  *
198  * Return value: %NULL if the GTK+ library is compatible with the
199  *   given version, or a string describing the version mismatch.
200  *   The returned string is owned by GTK+ and should not be modified
201  *   or freed.
202  **/
203 gchar*
204 gtk_check_version (guint required_major,
205                    guint required_minor,
206                    guint required_micro)
207 {
208   gint gtk_effective_micro = 100 * GTK_MINOR_VERSION + GTK_MICRO_VERSION;
209   gint required_effective_micro = 100 * required_minor + required_micro;
210
211   if (required_major > GTK_MAJOR_VERSION)
212     return "Gtk+ version too old (major mismatch)";
213   if (required_major < GTK_MAJOR_VERSION)
214     return "Gtk+ version too new (major mismatch)";
215   if (required_effective_micro < gtk_effective_micro - GTK_BINARY_AGE)
216     return "Gtk+ version too new (micro mismatch)";
217   if (required_effective_micro > gtk_effective_micro)
218     return "Gtk+ version too old (micro mismatch)";
219   return NULL;
220 }
221
222 /* This checks to see if the process is running suid or sgid
223  * at the current time. If so, we don't allow GTK+ to be initialized.
224  * This is meant to be a mild check - we only error out if we
225  * can prove the programmer is doing something wrong, not if
226  * they could be doing something wrong. For this reason, we
227  * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE).
228  */
229 static gboolean
230 check_setugid (void)
231 {
232 /* this isn't at all relevant on MS Windows and doesn't compile ... --hb */
233 #ifndef G_OS_WIN32
234   uid_t ruid, euid, suid; /* Real, effective and saved user ID's */
235   gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */
236   
237 #ifdef HAVE_GETRESUID
238   /* These aren't in the header files, so we prototype them here.
239    */
240   int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
241   int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
242
243   if (getresuid (&ruid, &euid, &suid) != 0 ||
244       getresgid (&rgid, &egid, &sgid) != 0)
245 #endif /* HAVE_GETRESUID */
246     {
247       suid = ruid = getuid ();
248       sgid = rgid = getgid ();
249       euid = geteuid ();
250       egid = getegid ();
251     }
252
253   if (ruid != euid || ruid != suid ||
254       rgid != egid || rgid != sgid)
255     {
256       g_warning ("This process is currently running setuid or setgid.\n"
257                  "This is not a supported use of GTK+. You must create a helper\n"
258                  "program instead. For further details, see:\n\n"
259                  "    http://www.gtk.org/setuid.html\n\n"
260                  "Refusing to initialize GTK+.");
261       exit (1);
262     }
263 #endif
264   return TRUE;
265 }
266
267 #ifdef G_OS_WIN32
268
269 G_WIN32_DLLMAIN_FOR_DLL_NAME(static, dll_name)
270
271 const gchar *
272 _gtk_get_datadir (void)
273 {
274   static char *gtk_datadir = NULL;
275   if (gtk_datadir == NULL)
276     gtk_datadir = g_win32_get_package_installation_subdirectory
277       (GETTEXT_PACKAGE, dll_name, "share");
278
279   return gtk_datadir;
280 }
281
282 const gchar *
283 _gtk_get_libdir (void)
284 {
285   static char *gtk_libdir = NULL;
286   if (gtk_libdir == NULL)
287     gtk_libdir = g_win32_get_package_installation_subdirectory
288       (GETTEXT_PACKAGE, dll_name, "lib");
289
290   return gtk_libdir;
291 }
292
293 const gchar *
294 _gtk_get_localedir (void)
295 {
296   static char *gtk_localedir = NULL;
297   if (gtk_localedir == NULL)
298     gtk_localedir = g_win32_get_package_installation_subdirectory
299       (GETTEXT_PACKAGE, dll_name, "lib\\locale");
300
301   return gtk_localedir;
302 }
303
304 const gchar *
305 _gtk_get_sysconfdir (void)
306 {
307   static char *gtk_sysconfdir = NULL;
308   if (gtk_sysconfdir == NULL)
309     gtk_sysconfdir = g_win32_get_package_installation_subdirectory
310       (GETTEXT_PACKAGE, dll_name, "etc");
311
312   return gtk_sysconfdir;
313 }
314
315 const gchar *
316 _gtk_get_data_prefix (void)
317 {
318   static char *gtk_data_prefix = NULL;
319   if (gtk_data_prefix == NULL)
320     gtk_data_prefix = g_win32_get_package_installation_directory
321       (GETTEXT_PACKAGE, dll_name);
322
323   return gtk_data_prefix;
324 }
325
326 #endif /* G_OS_WIN32 */
327
328 static gboolean do_setlocale = TRUE;
329
330 /**
331  * gtk_disable_setlocale:
332  * 
333  * Prevents gtk_init(), gtk_init_check(), gtk_init_with_args() and
334  * gtk_parse_args() from automatically
335  * calling <literal>setlocale (LC_ALL, "")</literal>. You would 
336  * want to use this function if you wanted to set the locale for 
337  * your program to something other than the user's locale, or if 
338  * you wanted to set different values for different locale categories.
339  *
340  * Most programs should not need to call this function.
341  **/
342 void
343 gtk_disable_setlocale (void)
344 {
345   if (gtk_initialized)
346     g_warning ("gtk_disable_setlocale() must be called before gtk_init()");
347     
348   do_setlocale = FALSE;
349 }
350
351 #ifdef G_PLATFORM_WIN32
352 #undef gtk_init_check
353 #endif
354
355 static GString *gtk_modules_string = NULL;
356 static gboolean g_fatal_warnings = FALSE;
357
358 #ifdef G_ENABLE_DEBUG
359 static gboolean
360 gtk_arg_debug_cb (const char *key, const char *value, gpointer user_data)
361 {
362   gtk_debug_flags |= g_parse_debug_string (value,
363                                            gtk_debug_keys,
364                                            gtk_ndebug_keys);
365
366   return TRUE;
367 }
368
369 static gboolean
370 gtk_arg_no_debug_cb (const char *key, const char *value, gpointer user_data)
371 {
372   gtk_debug_flags &= ~g_parse_debug_string (value,
373                                             gtk_debug_keys,
374                                             gtk_ndebug_keys);
375
376   return TRUE;
377 }
378 #endif /* G_ENABLE_DEBUG */
379
380 static gboolean
381 gtk_arg_module_cb (const char *key, const char *value, gpointer user_data)
382 {
383   if (value && *value)
384     {
385       if (gtk_modules_string)
386         g_string_append_c (gtk_modules_string, G_SEARCHPATH_SEPARATOR);
387       else
388         gtk_modules_string = g_string_new (NULL);
389       
390       g_string_append (gtk_modules_string, value);
391     }
392
393   return TRUE;
394 }
395
396 static GOptionEntry gtk_args[] = {
397   { "gtk-module",       0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_module_cb,   
398     /* Description of --gtk-module=MODULES in --help output */ N_("Load additional GTK+ modules"), 
399     /* Placeholder in --gtk-module=MODULES in --help output */ N_("MODULES") },
400   { "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, 
401     /* Description of --g-fatal-warnings in --help output */   N_("Make all warnings fatal"), NULL },
402 #ifdef G_ENABLE_DEBUG
403   { "gtk-debug",        0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_debug_cb,    
404     /* Description of --gtk-debug=FLAGS in --help output */    N_("GTK+ debugging flags to set"), 
405     /* Placeholder in --gtk-debug=FLAGS in --help output */    N_("FLAGS") },
406   { "gtk-no-debug",     0, 0, G_OPTION_ARG_CALLBACK, gtk_arg_no_debug_cb, 
407     /* Description of --gtk-no-debug=FLAGS in --help output */ N_("GTK+ debugging flags to unset"), 
408     /* Placeholder in --gtk-no-debug=FLAGS in --help output */ N_("FLAGS") },
409 #endif 
410   { NULL }
411 };
412
413 static void
414 do_pre_parse_initialization (int    *argc,
415                              char ***argv)
416 {
417   const gchar *env_string;
418   
419 #if     0
420   g_set_error_handler (gtk_error);
421   g_set_warning_handler (gtk_warning);
422   g_set_message_handler (gtk_message);
423   g_set_print_handler (gtk_print);
424 #endif
425
426   if (do_setlocale)
427     {
428       if (!setlocale (LC_ALL, ""))
429         g_warning ("Locale not supported by C library.\n\tUsing the fallback 'C' locale.");
430     }
431
432   gdk_pre_parse_libgtk_only ();
433   gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
434   
435 #ifdef G_ENABLE_DEBUG
436   env_string = g_getenv ("GTK_DEBUG");
437   if (env_string != NULL)
438     {
439       gtk_debug_flags = g_parse_debug_string (env_string,
440                                               gtk_debug_keys,
441                                               gtk_ndebug_keys);
442       env_string = NULL;
443     }
444 #endif  /* G_ENABLE_DEBUG */
445
446   env_string = g_getenv ("GTK_MODULES");
447   if (env_string)
448     gtk_modules_string = g_string_new (env_string);
449 }
450
451 static void
452 do_post_parse_initialization (int    *argc,
453                               char ***argv)
454 {
455   if (gtk_initialized)
456     return;
457
458   if (g_fatal_warnings)
459     {
460       GLogLevelFlags fatal_mask;
461
462       fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
463       fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
464       g_log_set_always_fatal (fatal_mask);
465     }
466
467   if (gtk_debug_flags & GTK_DEBUG_UPDATES)
468     gdk_window_set_debug_updates (TRUE);
469
470   {
471   /* Translate to default:RTL if you want your widgets
472    * to be RTL, otherwise translate to default:LTR.
473    * Do *not* translate it to "predefinito:LTR", if it
474    * it isn't default:LTR or default:RTL it will not work 
475    */
476     char *e = _("default:LTR");
477     if (strcmp (e, "default:RTL")==0) {
478       gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
479     } else if (strcmp (e, "default:LTR")) {
480       g_warning ("Whoever translated default:LTR did so wrongly.\n");
481     }
482   }
483
484   gtk_type_init (0);
485   _gtk_accel_map_init ();  
486   _gtk_rc_init ();
487
488   /* Set the 'initialized' flag.
489    */
490   gtk_initialized = TRUE;
491
492   /* load gtk modules */
493   if (gtk_modules_string)
494     {
495       _gtk_modules_init (argc, argv, gtk_modules_string->str);
496       g_string_free (gtk_modules_string, TRUE);
497     }
498 }
499
500
501 typedef struct
502 {
503   gboolean open_default_display;
504 } OptionGroupInfo;
505
506 static gboolean
507 pre_parse_hook (GOptionContext *context,
508                 GOptionGroup   *group,
509                 gpointer        data,
510                 GError        **error)
511 {
512   do_pre_parse_initialization (NULL, NULL);
513   
514   return TRUE;
515 }
516
517 static gboolean
518 post_parse_hook (GOptionContext *context,
519                  GOptionGroup   *group,
520                  gpointer       data,
521                  GError        **error)
522 {
523   OptionGroupInfo *info = data;
524
525   
526   do_post_parse_initialization (NULL, NULL);
527   
528   if (info->open_default_display)
529     return gdk_display_open_default_libgtk_only () != NULL;
530   else
531     return TRUE;
532 }
533
534
535 /**
536  * gtk_get_option_group:
537  * @open_default_display: whether to open the default display 
538  *    when parsing the commandline arguments
539  * 
540  * Returns a #GOptionGroup for the commandline arguments recognized
541  * by GTK+ and GDK. You should add this group to your #GOptionContext 
542  * with g_option_context_add_group(), if you are using 
543  * g_option_context_parse() to parse your commandline arguments.
544  *
545  * Returns a #GOptionGroup for the commandline arguments recognized
546  *   by GTK+
547  *
548  * Since: 2.6
549  */
550 GOptionGroup *
551 gtk_get_option_group (gboolean open_default_display)
552 {
553   GOptionGroup *group;
554   OptionGroupInfo *info;
555
556   info = g_new0 (OptionGroupInfo, 1);
557   info->open_default_display = open_default_display;
558   
559   group = g_option_group_new ("gtk", _("GTK+ Options"), _("Show GTK+ Options"), info, g_free);
560   g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
561
562   gdk_add_option_entries_libgtk_only (group);
563   g_option_group_add_entries (group, gtk_args);
564   g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
565   
566   return group;
567 }
568
569 static void
570 gettext_initialization (void)
571 {
572 #ifdef ENABLE_NLS
573   bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR);
574   bindtextdomain (GETTEXT_PACKAGE "-properties", GTK_LOCALEDIR);
575 #    ifdef HAVE_BIND_TEXTDOMAIN_CODESET
576   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
577   bind_textdomain_codeset (GETTEXT_PACKAGE "-properties", "UTF-8");
578 #    endif
579 #endif  
580 }
581
582 /**
583  * gtk_init_with_args:
584  * @argc: a pointer to the number of command line arguments.
585  * @argv: a pointer to the array of command line arguments.
586  * @parameter_string: a string which is displayed in
587  *    the first line of <option>--help</option> output, after 
588  *    <literal><replaceable>programname</replaceable> [OPTION...]</literal>
589  * @entries: a %NULL-terminated array of #GOptionEntry<!-- -->s
590  *    describing the options of your program
591  * @translation_domain: a translation domain to use for translating
592  *    the <option>--help</option> output for the options in @entries
593  *    with gettext(), or %NULL
594  * @error: a return location for errors 
595  *
596  * This function does the same work as gtk_init_check(). 
597  * Additionally, it allows you to add your own commandline options, 
598  * and it automatically generates nicely formatted 
599  * <option>--help</option> output. Note that your program will
600  * be terminated after writing out the help output.
601  *
602  * Returns: %TRUE if the GUI has been successfully initialized, 
603  *               %FALSE otherwise.
604  * 
605  * Since: 2.6
606  */
607 gboolean
608 gtk_init_with_args (int            *argc,
609                     char         ***argv,
610                     char           *parameter_string,  
611                     GOptionEntry   *entries,
612                     char           *translation_domain,
613                     GError        **error)
614 {
615   GOptionContext *context;
616   GOptionGroup *gtk_group;
617   gboolean retval;
618
619   if (gtk_initialized)
620     return TRUE;
621
622   if (!check_setugid ())
623     return FALSE;
624
625   gettext_initialization ();
626
627   gtk_group = gtk_get_option_group (TRUE);
628   
629   context = g_option_context_new (parameter_string);
630   g_option_context_add_group (context, gtk_group);
631   
632   if (entries)
633     g_option_context_add_main_entries (context, entries, translation_domain);
634   retval = g_option_context_parse (context, argc, argv, error);
635   
636   g_option_context_free (context);
637
638   return retval;
639 }
640
641
642 /**
643  * gtk_parse_args:
644  * @argc: a pointer to the number of command line arguments.
645  * @argv: a pointer to the array of command line arguments.
646  * 
647  * Parses command line arguments, and initializes global
648  * attributes of GTK+, but does not actually open a connection
649  * to a display. (See gdk_display_open(), gdk_get_display_arg_name())
650  *
651  * Any arguments used by GTK+ or GDK are removed from the array and
652  * @argc and @argv are updated accordingly.
653  *
654  * You shouldn't call this function explicitely if you are using
655  * gtk_init(), or gtk_init_check().
656  *
657  * Return value: %TRUE if initialization succeeded, otherwise %FALSE.
658  **/
659 gboolean
660 gtk_parse_args (int    *argc,
661                 char ***argv)
662 {
663   GOptionContext *option_context;
664   GOptionGroup *gtk_group;
665   
666   if (gtk_initialized)
667     return TRUE;
668
669   if (!check_setugid ())
670     return FALSE;
671
672   gettext_initialization ();
673
674   option_context = g_option_context_new (NULL);
675   g_option_context_set_ignore_unknown_options (option_context, TRUE);
676   g_option_context_set_help_enabled (option_context, FALSE);
677   gtk_group = gtk_get_option_group (FALSE);
678   g_option_context_set_main_group (option_context, gtk_group);
679   g_option_context_parse (option_context, argc, argv, NULL);
680   g_option_context_free (option_context);
681
682   return TRUE;
683 }
684
685 #ifdef G_PLATFORM_WIN32
686 #undef gtk_init_check
687 #endif
688
689 /**
690  * gtk_init_check:
691  * @argc: Address of the <parameter>argc</parameter> parameter of your 
692  *   main() function. Changed if any arguments were handled.
693  * @argv: Address of the <parameter>argv</parameter> parameter of main(). 
694  *   Any parameters understood by gtk_init() are stripped before return.
695  * 
696  * This function does the same work as gtk_init() with only 
697  * a single change: It does not terminate the program if the GUI can't be 
698  * initialized. Instead it returns %FALSE on failure.
699  *
700  * This way the application can fall back to some other means of communication 
701  * with the user - for example a curses or command line interface.
702  * 
703  * Return value: %TRUE if the GUI has been successfully initialized, 
704  *               %FALSE otherwise.
705  **/
706 gboolean
707 gtk_init_check (int      *argc,
708                 char   ***argv)
709 {
710   if (!gtk_parse_args (argc, argv))
711     return FALSE;
712
713   return gdk_display_open_default_libgtk_only () != NULL;
714 }
715
716 #ifdef G_PLATFORM_WIN32
717 #undef gtk_init
718 #endif
719
720 /**
721  * gtk_init:
722  * @argc: Address of the <parameter>argc</parameter> parameter of your 
723  *   main() function. Changed if any arguments were handled.
724  * @argv: Address of the <parameter>argv</parameter> parameter of main(). 
725  *   Any parameters understood by gtk_init() are stripped before return.
726  * 
727  * Call this function before using any other GTK+ functions in your GUI
728  * applications.  It will initialize everything needed to operate the 
729  * toolkit and parses some standard command line options. @argc and 
730  * @argv are adjusted accordingly so your own code will 
731  * never see those standard arguments. 
732  *
733  * Note that there are some alternative ways to initialize GTK+: 
734  * if you are calling gtk_parse_args(), gtk_init_check(), 
735  * gtk_init_with_args() or g_option_context_parse() with 
736  * the option group returned by gtk_get_option_group(), you 
737  * <emphasis>don't</emphasis> have to call gtk_init().
738  *
739  * <note><para>
740  * This function will terminate your program if it was unable to initialize 
741  * the GUI for some reason. If you want your program to fall back to a 
742  * textual interface you want to call gtk_init_check() instead.
743  * </para></note>
744  **/
745 void
746 gtk_init (int *argc, char ***argv)
747 {
748   if (!gtk_init_check (argc, argv))
749     {
750       const char *display_name_arg = gdk_get_display_arg_name ();
751       g_warning ("cannot open display: %s", display_name_arg ? display_name_arg : " ");
752       exit (1);
753     }
754 }
755
756 #ifdef G_PLATFORM_WIN32
757
758 static void
759 check_sizeof_GtkWindow (size_t sizeof_GtkWindow)
760 {
761   if (sizeof_GtkWindow != sizeof (GtkWindow))
762     g_error ("Incompatible build!\n"
763              "The code using GTK+ thinks GtkWindow is of different\n"
764              "size than it actually is in this build of GTK+.\n"
765              "On Windows, this probably means that you have compiled\n"
766              "your code with gcc without the -fnative-struct\n"
767              "(or -mms-bitfields) switch, or that you are using\n"
768              "an unsupported compiler.");
769 }
770
771 /* In GTK+ 2.0 the GtkWindow struct actually is the same size in
772  * gcc-compiled code on Win32 whether compiled with -fnative-struct or
773  * not. Unfortunately this wan't noticed until after GTK+ 2.0.1. So,
774  * from GTK+ 2.0.2 on, check some other struct, too, where the use of
775  * -fnative-struct still matters. GtkBox is one such.
776  */
777 static void
778 check_sizeof_GtkBox (size_t sizeof_GtkBox)
779 {
780   if (sizeof_GtkBox != sizeof (GtkBox))
781     g_error ("Incompatible build!\n"
782              "The code using GTK+ thinks GtkBox is of different\n"
783              "size than it actually is in this build of GTK+.\n"
784              "On Windows, this probably means that you have compiled\n"
785              "your code with gcc without the -fnative-struct\n"
786              "(or -mms-bitfields) switch, or that you are using\n"
787              "an unsupported compiler.");
788 }
789
790 /* These two functions might get more checks added later, thus pass
791  * in the number of extra args.
792  */
793 void
794 gtk_init_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
795 {
796   check_sizeof_GtkWindow (sizeof_GtkWindow);
797   if (num_checks >= 2)
798     check_sizeof_GtkBox (sizeof_GtkBox);
799   gtk_init (argc, argv);
800 }
801
802 gboolean
803 gtk_init_check_abi_check (int *argc, char ***argv, int num_checks, size_t sizeof_GtkWindow, size_t sizeof_GtkBox)
804 {
805   check_sizeof_GtkWindow (sizeof_GtkWindow);
806   if (num_checks >= 2)
807     check_sizeof_GtkBox (sizeof_GtkBox);
808   return gtk_init_check (argc, argv);
809 }
810
811 #endif
812
813 void
814 gtk_exit (gint errorcode)
815 {
816   exit (errorcode);
817 }
818
819
820 /**
821  * gtk_set_locale:
822  *
823  * Initializes internationalization support for GTK+. gtk_init()
824  * automatically does this, so there is typically no point
825  * in calling this function.
826  *
827  * If you are calling this function because you changed the locale
828  * after GTK+ is was initialized, then calling this function
829  * may help a bit. (Note, however, that changing the locale
830  * after GTK+ is initialized may produce inconsistent results and
831  * is not really supported.)
832  * 
833  * In detail - sets the current locale according to the
834  * program environment. This is the same as calling the C library function
835  * <literal>setlocale (LC_ALL, "")</literal> but also takes care of the 
836  * locale specific setup of the windowing system used by GDK.
837  * 
838  * Returns: a string corresponding to the locale set, typically in the
839  * form lang_COUNTRY, where lang is an ISO-639 language code, and
840  * COUNTRY is an ISO-3166 country code. On Unix, this form matches the
841  * result of the setlocale(); it is also used on other machines, such as 
842  * Windows, where the C library returns a different result. The string is 
843  * owned by GTK+ and should not be modified or freed.
844  **/
845 gchar *
846 gtk_set_locale (void)
847 {
848   return gdk_set_locale ();
849 }
850
851 /**
852  * _gtk_get_lc_ctype:
853  *
854  * Return the Unix-style locale string for the language currently in
855  * effect. On Unix systems, this is the return value from
856  * <literal>setlocale(LC_CTYPE, NULL)</literal>, and the user can
857  * affect this through the environment variables LC_ALL, LC_CTYPE or
858  * LANG (checked in that order). The locale strings typically is in
859  * the form lang_COUNTRY, where lang is an ISO-639 language code, and
860  * COUNTRY is an ISO-3166 country code. For instance, sv_FI for
861  * Swedish as written in Finland or pt_BR for Portuguese as written in
862  * Brazil.
863  * 
864  * On Windows, the C library doesn't use any such environment
865  * variables, and setting them won't affect the behaviour of functions
866  * like ctime(). The user sets the locale through the Regional Options 
867  * in the Control Panel. The C library (in the setlocale() function) 
868  * does not use country and language codes, but country and language 
869  * names spelled out in English. 
870  * However, this function does check the above environment
871  * variables, and does return a Unix-style locale string based on
872  * either said environment variables or the thread's current locale.
873  *
874  * Return value: a dynamically allocated string, free with g_free().
875  */
876
877 gchar *
878 _gtk_get_lc_ctype (void)
879 {
880 #ifdef G_OS_WIN32
881   /* Somebody might try to set the locale for this process using the
882    * LANG or LC_ environment variables. The Microsoft C library
883    * doesn't know anything about them. You set the locale in the
884    * Control Panel. Setting these env vars won't have any affect on
885    * locale-dependent C library functions like ctime(). But just for
886    * kicks, do obey LC_ALL, LC_CTYPE and LANG in GTK. (This also makes
887    * it easier to test GTK and Pango in various default languages, you
888    * don't have to clickety-click in the Control Panel, you can simply
889    * start the program with LC_ALL=something on the command line.)
890    */
891   gchar *p;
892
893   p = getenv ("LC_ALL");
894   if (p != NULL)
895     return g_strdup (p);
896
897   p = getenv ("LC_CTYPE");
898   if (p != NULL)
899     return g_strdup (p);
900
901   p = getenv ("LANG");
902   if (p != NULL)
903     return g_strdup (p);
904
905   return g_win32_getlocale ();
906 #else
907   return g_strdup (setlocale (LC_CTYPE, NULL));
908 #endif
909 }
910
911 /**
912  * gtk_get_default_language:
913  *
914  * Returns the #PangoLanguage for the default language currently in
915  * effect. (Note that this can change over the life of an
916  * application.)  The default language is derived from the current
917  * locale. It determines, for example, whether GTK+ uses the
918  * right-to-left or left-to-right text direction. See
919  * _gtk_get_lc_ctype() for notes on behaviour on Windows.
920  * 
921  * Return value: the default language as a #PangoLanguage, must not be
922  * freed
923  **/
924 PangoLanguage *
925 gtk_get_default_language (void)
926 {
927   gchar *lang;
928   PangoLanguage *result;
929   gchar *p;
930   
931   lang = _gtk_get_lc_ctype ();
932   p = strchr (lang, '.');
933   if (p)
934     *p = '\0';
935   p = strchr (lang, '@');
936   if (p)
937     *p = '\0';
938
939   result = pango_language_from_string (lang);
940   g_free (lang);
941   
942   return result;
943 }
944
945 void
946 gtk_main (void)
947 {
948   GList *tmp_list;
949   GList *functions;
950   GtkInitFunction *init;
951   GMainLoop *loop;
952
953   gtk_main_loop_level++;
954   
955   loop = g_main_loop_new (NULL, TRUE);
956   main_loops = g_slist_prepend (main_loops, loop);
957
958   tmp_list = functions = init_functions;
959   init_functions = NULL;
960   
961   while (tmp_list)
962     {
963       init = tmp_list->data;
964       tmp_list = tmp_list->next;
965       
966       (* init->function) (init->data);
967       g_free (init);
968     }
969   g_list_free (functions);
970
971   if (g_main_loop_is_running (main_loops->data))
972     {
973       GDK_THREADS_LEAVE ();
974       g_main_loop_run (loop);
975       GDK_THREADS_ENTER ();
976       gdk_flush ();
977     }
978
979   if (quit_functions)
980     {
981       GList *reinvoke_list = NULL;
982       GtkQuitFunction *quitf;
983
984       while (quit_functions)
985         {
986           quitf = quit_functions->data;
987
988           tmp_list = quit_functions;
989           quit_functions = g_list_remove_link (quit_functions, quit_functions);
990           g_list_free_1 (tmp_list);
991
992           if ((quitf->main_level && quitf->main_level != gtk_main_loop_level) ||
993               gtk_quit_invoke_function (quitf))
994             {
995               reinvoke_list = g_list_prepend (reinvoke_list, quitf);
996             }
997           else
998             {
999               gtk_quit_destroy (quitf);
1000             }
1001         }
1002       if (reinvoke_list)
1003         {
1004           GList *work;
1005           
1006           work = g_list_last (reinvoke_list);
1007           if (quit_functions)
1008             quit_functions->prev = work;
1009           work->next = quit_functions;
1010           quit_functions = work;
1011         }
1012
1013       gdk_flush ();
1014     }
1015     
1016   main_loops = g_slist_remove (main_loops, loop);
1017
1018   g_main_loop_unref (loop);
1019
1020   gtk_main_loop_level--;
1021
1022   /* Try storing all clipboard data we have */
1023   if (gtk_main_loop_level == 0)
1024     _gtk_clipboard_store_all ();
1025 }
1026
1027 guint
1028 gtk_main_level (void)
1029 {
1030   return gtk_main_loop_level;
1031 }
1032
1033 void
1034 gtk_main_quit (void)
1035 {
1036   g_return_if_fail (main_loops != NULL);
1037
1038   g_main_loop_quit (main_loops->data);
1039 }
1040
1041 gboolean
1042 gtk_events_pending (void)
1043 {
1044   gboolean result;
1045   
1046   GDK_THREADS_LEAVE ();  
1047   result = g_main_context_pending (NULL);
1048   GDK_THREADS_ENTER ();
1049
1050   return result;
1051 }
1052
1053 gboolean
1054 gtk_main_iteration (void)
1055 {
1056   GDK_THREADS_LEAVE ();
1057   g_main_context_iteration (NULL, TRUE);
1058   GDK_THREADS_ENTER ();
1059
1060   if (main_loops)
1061     return !g_main_loop_is_running (main_loops->data);
1062   else
1063     return TRUE;
1064 }
1065
1066 gboolean
1067 gtk_main_iteration_do (gboolean blocking)
1068 {
1069   GDK_THREADS_LEAVE ();
1070   g_main_context_iteration (NULL, blocking);
1071   GDK_THREADS_ENTER ();
1072
1073   if (main_loops)
1074     return !g_main_loop_is_running (main_loops->data);
1075   else
1076     return TRUE;
1077 }
1078
1079 /* private libgtk to libgdk interfaces
1080  */
1081 gboolean gdk_pointer_grab_info_libgtk_only  (GdkDisplay *display,
1082                                              GdkWindow **grab_window,
1083                                              gboolean   *owner_events);
1084 gboolean gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
1085                                              GdkWindow **grab_window,
1086                                              gboolean   *owner_events);
1087
1088 static void
1089 rewrite_events_translate (GdkWindow *old_window,
1090                           GdkWindow *new_window,
1091                           gdouble   *x,
1092                           gdouble   *y)
1093 {
1094   gint old_origin_x, old_origin_y;
1095   gint new_origin_x, new_origin_y;
1096
1097   gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y);
1098   gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y);
1099
1100   *x += old_origin_x - new_origin_x;
1101   *y += old_origin_y - new_origin_y;
1102 }
1103
1104 static GdkEvent *
1105 rewrite_event_for_window (GdkEvent  *event,
1106                           GdkWindow *new_window)
1107 {
1108   event = gdk_event_copy (event);
1109
1110   switch (event->type)
1111     {
1112     case GDK_SCROLL:
1113       rewrite_events_translate (event->any.window,
1114                                 new_window,
1115                                 &event->scroll.x, &event->scroll.y);
1116       break;
1117     case GDK_BUTTON_PRESS:
1118     case GDK_2BUTTON_PRESS:
1119     case GDK_3BUTTON_PRESS:
1120     case GDK_BUTTON_RELEASE:
1121       rewrite_events_translate (event->any.window,
1122                                 new_window,
1123                                 &event->button.x, &event->button.y);
1124       break;
1125     case GDK_MOTION_NOTIFY:
1126       rewrite_events_translate (event->any.window,
1127                                 new_window,
1128                                 &event->motion.x, &event->motion.y);
1129       break;
1130     case GDK_KEY_PRESS:
1131     case GDK_KEY_RELEASE:
1132     case GDK_PROXIMITY_IN:
1133     case GDK_PROXIMITY_OUT:
1134       break;
1135
1136     default:
1137       return event;
1138     }
1139
1140   g_object_unref (event->any.window);
1141   event->any.window = g_object_ref (new_window);
1142
1143   return event;
1144 }
1145
1146 /* If there is a pointer or keyboard grab in effect with owner_events = TRUE,
1147  * then what X11 does is deliver the event normally if it was going to this
1148  * client, otherwise, delivers it in terms of the grab window. This function
1149  * rewrites events to the effect that events going to the same window group
1150  * are delivered normally, otherwise, the event is delivered in terms of the
1151  * grab window.
1152  */
1153 static GdkEvent *
1154 rewrite_event_for_grabs (GdkEvent *event)
1155 {
1156   GdkWindow *grab_window;
1157   GtkWidget *event_widget, *grab_widget;
1158   gboolean owner_events;
1159   GdkDisplay *display;
1160
1161   switch (event->type)
1162     {
1163     case GDK_SCROLL:
1164     case GDK_BUTTON_PRESS:
1165     case GDK_2BUTTON_PRESS:
1166     case GDK_3BUTTON_PRESS:
1167     case GDK_BUTTON_RELEASE:
1168     case GDK_MOTION_NOTIFY:
1169     case GDK_PROXIMITY_IN:
1170     case GDK_PROXIMITY_OUT:
1171       display = gdk_drawable_get_display (event->proximity.window);
1172       if (!gdk_pointer_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1173           !owner_events)
1174         return NULL;
1175       break;
1176
1177     case GDK_KEY_PRESS:
1178     case GDK_KEY_RELEASE:
1179       display = gdk_drawable_get_display (event->key.window);
1180       if (!gdk_keyboard_grab_info_libgtk_only (display, &grab_window, &owner_events) ||
1181           !owner_events)
1182         return NULL;
1183       break;
1184
1185     default:
1186       return NULL;
1187     }
1188
1189   event_widget = gtk_get_event_widget (event);
1190   gdk_window_get_user_data (grab_window, (void**) &grab_widget);
1191
1192   if (grab_widget &&
1193       gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget))
1194     return rewrite_event_for_window (event, grab_window);
1195   else
1196     return NULL;
1197 }
1198
1199 void 
1200 gtk_main_do_event (GdkEvent *event)
1201 {
1202   GtkWidget *event_widget;
1203   GtkWidget *grab_widget;
1204   GtkWindowGroup *window_group;
1205   GdkEvent *next_event;
1206   GdkEvent *rewritten_event = NULL;
1207   GList *tmp_list;
1208
1209   /* If there are any events pending then get the next one.
1210    */
1211   next_event = gdk_event_peek ();
1212   
1213   /* Try to compress enter/leave notify events. These event
1214    *  pairs occur when the mouse is dragged quickly across
1215    *  a window with many buttons (or through a menu). Instead
1216    *  of highlighting and de-highlighting each widget that
1217    *  is crossed it is better to simply de-highlight the widget
1218    *  which contained the mouse initially and highlight the
1219    *  widget which ends up containing the mouse.
1220    */
1221   if (next_event)
1222     if (((event->type == GDK_ENTER_NOTIFY) ||
1223          (event->type == GDK_LEAVE_NOTIFY)) &&
1224         ((next_event->type == GDK_ENTER_NOTIFY) ||
1225          (next_event->type == GDK_LEAVE_NOTIFY)) &&
1226         (next_event->type != event->type) &&
1227         (next_event->any.window == event->any.window))
1228       {
1229         /* Throw both the peeked copy and the queued copy away 
1230          */
1231         gdk_event_free (next_event);
1232         next_event = gdk_event_get ();
1233         gdk_event_free (next_event);
1234         
1235         return;
1236       }
1237
1238   if (next_event)
1239     gdk_event_free (next_event);
1240
1241   if (event->type == GDK_SETTING)
1242     {
1243       _gtk_settings_handle_event (&event->setting);
1244       return;
1245     }
1246
1247   if (event->type == GDK_OWNER_CHANGE)
1248     {
1249       _gtk_clipboard_handle_event (&event->owner_change);
1250       return;
1251     }
1252
1253   /* Find the widget which got the event. We store the widget
1254    *  in the user_data field of GdkWindow's.
1255    *  Ignore the event if we don't have a widget for it, except
1256    *  for GDK_PROPERTY_NOTIFY events which are handled specialy.
1257    *  Though this happens rarely, bogus events can occour
1258    *  for e.g. destroyed GdkWindows. 
1259    */
1260   event_widget = gtk_get_event_widget (event);
1261   if (!event_widget)
1262     {
1263       /* To handle selection INCR transactions, we select
1264        * PropertyNotify events on the requestor window and create
1265        * a corresponding (fake) GdkWindow so that events get
1266        * here. There won't be a widget though, so we have to handle
1267            * them specially
1268            */
1269       if (event->type == GDK_PROPERTY_NOTIFY)
1270         _gtk_selection_incr_event (event->any.window,
1271                                    &event->property);
1272
1273       return;
1274     }
1275
1276   /* If pointer or keyboard grabs are in effect, munge the events
1277    * so that each window group looks like a separate app.
1278    */
1279   rewritten_event = rewrite_event_for_grabs (event);
1280   if (rewritten_event)
1281     {
1282       event = rewritten_event;
1283       event_widget = gtk_get_event_widget (event);
1284     }
1285   
1286   window_group = gtk_main_get_window_group (event_widget);
1287
1288   /* Push the event onto a stack of current events for
1289    * gtk_current_event_get().
1290    */
1291   current_events = g_list_prepend (current_events, event);
1292
1293   /* If there is a grab in effect...
1294    */
1295   if (window_group->grabs)
1296     {
1297       grab_widget = window_group->grabs->data;
1298       
1299       /* If the grab widget is an ancestor of the event widget
1300        *  then we send the event to the original event widget.
1301        *  This is the key to implementing modality.
1302        */
1303       if (GTK_WIDGET_IS_SENSITIVE (event_widget) &&
1304           gtk_widget_is_ancestor (event_widget, grab_widget))
1305         grab_widget = event_widget;
1306     }
1307   else
1308     {
1309       grab_widget = event_widget;
1310     }
1311
1312   /* Not all events get sent to the grabbing widget.
1313    * The delete, destroy, expose, focus change and resize
1314    *  events still get sent to the event widget because
1315    *  1) these events have no meaning for the grabbing widget
1316    *  and 2) redirecting these events to the grabbing widget
1317    *  could cause the display to be messed up.
1318    * 
1319    * Drag events are also not redirected, since it isn't
1320    *  clear what the semantics of that would be.
1321    */
1322   switch (event->type)
1323     {
1324     case GDK_NOTHING:
1325       break;
1326       
1327     case GDK_DELETE:
1328       g_object_ref (event_widget);
1329       if ((!window_group->grabs || gtk_widget_get_toplevel (window_group->grabs->data) == event_widget) &&
1330           !gtk_widget_event (event_widget, event))
1331         gtk_widget_destroy (event_widget);
1332       g_object_unref (event_widget);
1333       break;
1334       
1335     case GDK_DESTROY:
1336       /* Unexpected GDK_DESTROY from the outside, ignore for
1337        * child windows, handle like a GDK_DELETE for toplevels
1338        */
1339       if (!event_widget->parent)
1340         {
1341           g_object_ref (event_widget);
1342           if (!gtk_widget_event (event_widget, event) &&
1343               GTK_WIDGET_REALIZED (event_widget))
1344             gtk_widget_destroy (event_widget);
1345           g_object_unref (event_widget);
1346         }
1347       break;
1348       
1349     case GDK_EXPOSE:
1350       if (event->any.window && GTK_WIDGET_DOUBLE_BUFFERED (event_widget))
1351         {
1352           gdk_window_begin_paint_region (event->any.window, event->expose.region);
1353           gtk_widget_send_expose (event_widget, event);
1354           gdk_window_end_paint (event->any.window);
1355         }
1356       else
1357         gtk_widget_send_expose (event_widget, event);
1358       break;
1359
1360     case GDK_PROPERTY_NOTIFY:
1361     case GDK_NO_EXPOSE:
1362     case GDK_FOCUS_CHANGE:
1363     case GDK_CONFIGURE:
1364     case GDK_MAP:
1365     case GDK_UNMAP:
1366     case GDK_SELECTION_CLEAR:
1367     case GDK_SELECTION_REQUEST:
1368     case GDK_SELECTION_NOTIFY:
1369     case GDK_CLIENT_EVENT:
1370     case GDK_VISIBILITY_NOTIFY:
1371     case GDK_WINDOW_STATE:
1372       gtk_widget_event (event_widget, event);
1373       break;
1374
1375     case GDK_SCROLL:
1376     case GDK_BUTTON_PRESS:
1377     case GDK_2BUTTON_PRESS:
1378     case GDK_3BUTTON_PRESS:
1379       gtk_propagate_event (grab_widget, event);
1380       break;
1381
1382     case GDK_KEY_PRESS:
1383     case GDK_KEY_RELEASE:
1384       if (key_snoopers)
1385         {
1386           if (gtk_invoke_key_snoopers (grab_widget, event))
1387             break;
1388         }
1389       /* else fall through */
1390     case GDK_MOTION_NOTIFY:
1391     case GDK_BUTTON_RELEASE:
1392     case GDK_PROXIMITY_IN:
1393     case GDK_PROXIMITY_OUT:
1394       gtk_propagate_event (grab_widget, event);
1395       break;
1396       
1397     case GDK_ENTER_NOTIFY:
1398       if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1399         {
1400           g_object_ref (event_widget);
1401           
1402           gtk_widget_event (grab_widget, event);
1403           if (event_widget == grab_widget)
1404             GTK_PRIVATE_SET_FLAG (event_widget, GTK_LEAVE_PENDING);
1405           
1406           g_object_unref (event_widget);
1407         }
1408       break;
1409       
1410     case GDK_LEAVE_NOTIFY:
1411       if (GTK_WIDGET_LEAVE_PENDING (event_widget))
1412         {
1413           GTK_PRIVATE_UNSET_FLAG (event_widget, GTK_LEAVE_PENDING);
1414           gtk_widget_event (event_widget, event);
1415         }
1416       else if (GTK_WIDGET_IS_SENSITIVE (grab_widget))
1417         gtk_widget_event (grab_widget, event);
1418       break;
1419       
1420     case GDK_DRAG_STATUS:
1421     case GDK_DROP_FINISHED:
1422       _gtk_drag_source_handle_event (event_widget, event);
1423       break;
1424     case GDK_DRAG_ENTER:
1425     case GDK_DRAG_LEAVE:
1426     case GDK_DRAG_MOTION:
1427     case GDK_DROP_START:
1428       _gtk_drag_dest_handle_event (event_widget, event);
1429       break;
1430     default:
1431       g_assert_not_reached ();
1432       break;
1433     }
1434   
1435   tmp_list = current_events;
1436   current_events = g_list_remove_link (current_events, tmp_list);
1437   g_list_free_1 (tmp_list);
1438
1439   if (rewritten_event)
1440     gdk_event_free (rewritten_event);
1441 }
1442
1443 gboolean
1444 gtk_true (void)
1445 {
1446   return TRUE;
1447 }
1448
1449 gboolean
1450 gtk_false (void)
1451 {
1452   return FALSE;
1453 }
1454
1455 static GtkWindowGroup *
1456 gtk_main_get_window_group (GtkWidget   *widget)
1457 {
1458   GtkWidget *toplevel = NULL;
1459
1460   if (widget)
1461     toplevel = gtk_widget_get_toplevel (widget);
1462
1463   if (toplevel && GTK_IS_WINDOW (toplevel))
1464     return _gtk_window_get_group (GTK_WINDOW (toplevel));
1465   else
1466     return _gtk_window_get_group (NULL);
1467 }
1468
1469 typedef struct
1470 {
1471   GtkWidget *old_grab_widget;
1472   GtkWidget *new_grab_widget;
1473 } GrabNotifyInfo;
1474
1475 static gboolean
1476 check_is_grabbed (GtkWidget *widget,
1477                   GtkWidget *grab_widget)
1478 {
1479   if (grab_widget)
1480     return !(widget == grab_widget || gtk_widget_is_ancestor (widget, grab_widget));
1481   else
1482     return FALSE;
1483 }
1484
1485 static void
1486 gtk_grab_notify_foreach (GtkWidget *child,
1487                          gpointer   data)
1488                         
1489 {
1490   GrabNotifyInfo *info = data;
1491   gboolean was_grabbed = check_is_grabbed (child, info->old_grab_widget);
1492   gboolean is_grabbed = check_is_grabbed (child, info->new_grab_widget);
1493
1494   if (was_grabbed != is_grabbed)
1495     {
1496       g_object_ref (child);
1497
1498       _gtk_widget_grab_notify (child, was_grabbed);
1499       
1500       if (GTK_IS_CONTAINER (child))
1501         gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
1502       
1503       g_object_unref (child);
1504     }
1505 }
1506
1507 static void
1508 gtk_grab_notify (GtkWindowGroup *group,
1509                  GtkWidget      *grab_widget,
1510                  gboolean        was_grabbed)
1511 {
1512   GList *toplevels;
1513   GrabNotifyInfo info;
1514
1515   if (was_grabbed)
1516     {
1517       info.old_grab_widget = grab_widget;
1518       info.new_grab_widget = group->grabs ? group->grabs->data : NULL;
1519     }
1520   else
1521     {
1522       info.old_grab_widget = (group->grabs && group->grabs->next) ? group->grabs->next->data : NULL;
1523       info.new_grab_widget = grab_widget;
1524     }
1525
1526   g_object_ref (group);
1527   g_object_ref (grab_widget);
1528
1529   toplevels = gtk_window_list_toplevels ();
1530   g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
1531                             
1532   while (toplevels)
1533     {
1534       GtkWindow *toplevel = toplevels->data;
1535       toplevels = g_list_delete_link (toplevels, toplevels);
1536
1537       if (group == _gtk_window_get_group (toplevel))
1538         gtk_container_foreach (GTK_CONTAINER (toplevel), gtk_grab_notify_foreach, &info);
1539       g_object_unref (toplevel);
1540     }
1541
1542   g_object_unref (group);
1543   g_object_unref (grab_widget);
1544 }
1545
1546 void
1547 gtk_grab_add (GtkWidget *widget)
1548 {
1549   GtkWindowGroup *group;
1550   gboolean was_grabbed;
1551   
1552   g_return_if_fail (widget != NULL);
1553   
1554   if (!GTK_WIDGET_HAS_GRAB (widget) && GTK_WIDGET_IS_SENSITIVE (widget))
1555     {
1556       GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_GRAB);
1557       
1558       group = gtk_main_get_window_group (widget);
1559
1560       was_grabbed = (group->grabs != NULL);
1561       
1562       g_object_ref (widget);
1563       group->grabs = g_slist_prepend (group->grabs, widget);
1564
1565       gtk_grab_notify (group, widget, FALSE);
1566     }
1567 }
1568
1569 GtkWidget*
1570 gtk_grab_get_current (void)
1571 {
1572   GtkWindowGroup *group;
1573
1574   group = gtk_main_get_window_group (NULL);
1575
1576   if (group->grabs)
1577     return GTK_WIDGET (group->grabs->data);
1578   return NULL;
1579 }
1580
1581 void
1582 gtk_grab_remove (GtkWidget *widget)
1583 {
1584   GtkWindowGroup *group;
1585   
1586   g_return_if_fail (widget != NULL);
1587   
1588   if (GTK_WIDGET_HAS_GRAB (widget))
1589     {
1590       GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_GRAB);
1591
1592       group = gtk_main_get_window_group (widget);
1593       group->grabs = g_slist_remove (group->grabs, widget);
1594       
1595       g_object_unref (widget);
1596
1597       gtk_grab_notify (group, widget, TRUE);
1598     }
1599 }
1600
1601 void
1602 gtk_init_add (GtkFunction function,
1603               gpointer    data)
1604 {
1605   GtkInitFunction *init;
1606   
1607   init = g_new (GtkInitFunction, 1);
1608   init->function = function;
1609   init->data = data;
1610   
1611   init_functions = g_list_prepend (init_functions, init);
1612 }
1613
1614 guint
1615 gtk_key_snooper_install (GtkKeySnoopFunc snooper,
1616                          gpointer        func_data)
1617 {
1618   GtkKeySnooperData *data;
1619   static guint snooper_id = 1;
1620
1621   g_return_val_if_fail (snooper != NULL, 0);
1622
1623   data = g_new (GtkKeySnooperData, 1);
1624   data->func = snooper;
1625   data->func_data = func_data;
1626   data->id = snooper_id++;
1627   key_snoopers = g_slist_prepend (key_snoopers, data);
1628
1629   return data->id;
1630 }
1631
1632 void
1633 gtk_key_snooper_remove (guint snooper_id)
1634 {
1635   GtkKeySnooperData *data = NULL;
1636   GSList *slist;
1637
1638   slist = key_snoopers;
1639   while (slist)
1640     {
1641       data = slist->data;
1642       if (data->id == snooper_id)
1643         break;
1644
1645       slist = slist->next;
1646       data = NULL;
1647     }
1648   if (data)
1649     {
1650       key_snoopers = g_slist_remove (key_snoopers, data);
1651       g_free (data);
1652     }
1653 }
1654
1655 static gint
1656 gtk_invoke_key_snoopers (GtkWidget *grab_widget,
1657                          GdkEvent  *event)
1658 {
1659   GSList *slist;
1660   gint return_val = FALSE;
1661
1662   slist = key_snoopers;
1663   while (slist && !return_val)
1664     {
1665       GtkKeySnooperData *data;
1666
1667       data = slist->data;
1668       slist = slist->next;
1669       return_val = (*data->func) (grab_widget, (GdkEventKey*) event, data->func_data);
1670     }
1671
1672   return return_val;
1673 }
1674
1675 guint
1676 gtk_quit_add_full (guint                main_level,
1677                    GtkFunction          function,
1678                    GtkCallbackMarshal   marshal,
1679                    gpointer             data,
1680                    GtkDestroyNotify     destroy)
1681 {
1682   static guint quit_id = 1;
1683   GtkQuitFunction *quitf;
1684   
1685   g_return_val_if_fail ((function != NULL) || (marshal != NULL), 0);
1686
1687   if (!quit_mem_chunk)
1688     quit_mem_chunk = g_mem_chunk_new ("quit mem chunk", sizeof (GtkQuitFunction),
1689                                       512, G_ALLOC_AND_FREE);
1690   
1691   quitf = g_chunk_new (GtkQuitFunction, quit_mem_chunk);
1692   
1693   quitf->id = quit_id++;
1694   quitf->main_level = main_level;
1695   quitf->function = function;
1696   quitf->marshal = marshal;
1697   quitf->data = data;
1698   quitf->destroy = destroy;
1699
1700   quit_functions = g_list_prepend (quit_functions, quitf);
1701   
1702   return quitf->id;
1703 }
1704
1705 static void
1706 gtk_quit_destroy (GtkQuitFunction *quitf)
1707 {
1708   if (quitf->destroy)
1709     quitf->destroy (quitf->data);
1710   g_mem_chunk_free (quit_mem_chunk, quitf);
1711 }
1712
1713 static gint
1714 gtk_quit_destructor (GtkObject **object_p)
1715 {
1716   if (*object_p)
1717     gtk_object_destroy (*object_p);
1718   g_free (object_p);
1719
1720   return FALSE;
1721 }
1722
1723 void
1724 gtk_quit_add_destroy (guint              main_level,
1725                       GtkObject         *object)
1726 {
1727   GtkObject **object_p;
1728
1729   g_return_if_fail (main_level > 0);
1730   g_return_if_fail (GTK_IS_OBJECT (object));
1731
1732   object_p = g_new (GtkObject*, 1);
1733   *object_p = object;
1734   g_signal_connect (object,
1735                     "destroy",
1736                     G_CALLBACK (gtk_widget_destroyed),
1737                     object_p);
1738   gtk_quit_add (main_level, (GtkFunction) gtk_quit_destructor, object_p);
1739 }
1740
1741 guint
1742 gtk_quit_add (guint       main_level,
1743               GtkFunction function,
1744               gpointer    data)
1745 {
1746   return gtk_quit_add_full (main_level, function, NULL, data, NULL);
1747 }
1748
1749 void
1750 gtk_quit_remove (guint id)
1751 {
1752   GtkQuitFunction *quitf;
1753   GList *tmp_list;
1754   
1755   tmp_list = quit_functions;
1756   while (tmp_list)
1757     {
1758       quitf = tmp_list->data;
1759       
1760       if (quitf->id == id)
1761         {
1762           quit_functions = g_list_remove_link (quit_functions, tmp_list);
1763           g_list_free (tmp_list);
1764           gtk_quit_destroy (quitf);
1765           
1766           return;
1767         }
1768       
1769       tmp_list = tmp_list->next;
1770     }
1771 }
1772
1773 void
1774 gtk_quit_remove_by_data (gpointer data)
1775 {
1776   GtkQuitFunction *quitf;
1777   GList *tmp_list;
1778   
1779   tmp_list = quit_functions;
1780   while (tmp_list)
1781     {
1782       quitf = tmp_list->data;
1783       
1784       if (quitf->data == data)
1785         {
1786           quit_functions = g_list_remove_link (quit_functions, tmp_list);
1787           g_list_free (tmp_list);
1788           gtk_quit_destroy (quitf);
1789
1790           return;
1791         }
1792       
1793       tmp_list = tmp_list->next;
1794     }
1795 }
1796
1797 guint
1798 gtk_timeout_add_full (guint32            interval,
1799                       GtkFunction        function,
1800                       GtkCallbackMarshal marshal,
1801                       gpointer           data,
1802                       GtkDestroyNotify   destroy)
1803 {
1804   if (marshal)
1805     {
1806       GtkClosure *closure;
1807
1808       closure = g_new (GtkClosure, 1);
1809       closure->marshal = marshal;
1810       closure->data = data;
1811       closure->destroy = destroy;
1812
1813       return g_timeout_add_full (0, interval, 
1814                                  gtk_invoke_idle_timeout,
1815                                  closure,
1816                                  gtk_destroy_closure);
1817     }
1818   else
1819     return g_timeout_add_full (0, interval, function, data, destroy);
1820 }
1821
1822 guint
1823 gtk_timeout_add (guint32     interval,
1824                  GtkFunction function,
1825                  gpointer    data)
1826 {
1827   return g_timeout_add_full (0, interval, function, data, NULL);
1828 }
1829
1830 void
1831 gtk_timeout_remove (guint tag)
1832 {
1833   g_source_remove (tag);
1834 }
1835
1836 guint
1837 gtk_idle_add_full (gint                 priority,
1838                    GtkFunction          function,
1839                    GtkCallbackMarshal   marshal,
1840                    gpointer             data,
1841                    GtkDestroyNotify     destroy)
1842 {
1843   if (marshal)
1844     {
1845       GtkClosure *closure;
1846
1847       closure = g_new (GtkClosure, 1);
1848       closure->marshal = marshal;
1849       closure->data = data;
1850       closure->destroy = destroy;
1851
1852       return g_idle_add_full (priority,
1853                               gtk_invoke_idle_timeout,
1854                               closure,
1855                               gtk_destroy_closure);
1856     }
1857   else
1858     return g_idle_add_full (priority, function, data, destroy);
1859 }
1860
1861 guint
1862 gtk_idle_add (GtkFunction function,
1863               gpointer    data)
1864 {
1865   return g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, function, data, NULL);
1866 }
1867
1868 guint       
1869 gtk_idle_add_priority (gint        priority,
1870                        GtkFunction function,
1871                        gpointer    data)
1872 {
1873   return g_idle_add_full (priority, function, data, NULL);
1874 }
1875
1876 void
1877 gtk_idle_remove (guint tag)
1878 {
1879   g_source_remove (tag);
1880 }
1881
1882 void
1883 gtk_idle_remove_by_data (gpointer data)
1884 {
1885   if (!g_idle_remove_by_data (data))
1886     g_warning ("gtk_idle_remove_by_data(%p): no such idle", data);
1887 }
1888
1889 guint
1890 gtk_input_add_full (gint                source,
1891                     GdkInputCondition   condition,
1892                     GdkInputFunction    function,
1893                     GtkCallbackMarshal  marshal,
1894                     gpointer            data,
1895                     GtkDestroyNotify    destroy)
1896 {
1897   if (marshal)
1898     {
1899       GtkClosure *closure;
1900
1901       closure = g_new (GtkClosure, 1);
1902       closure->marshal = marshal;
1903       closure->data = data;
1904       closure->destroy = destroy;
1905
1906       return gdk_input_add_full (source,
1907                                  condition,
1908                                  (GdkInputFunction) gtk_invoke_input,
1909                                  closure,
1910                                  (GdkDestroyNotify) gtk_destroy_closure);
1911     }
1912   else
1913     return gdk_input_add_full (source, condition, function, data, destroy);
1914 }
1915
1916 void
1917 gtk_input_remove (guint tag)
1918 {
1919   g_source_remove (tag);
1920 }
1921
1922 static void
1923 gtk_destroy_closure (gpointer data)
1924 {
1925   GtkClosure *closure = data;
1926
1927   if (closure->destroy)
1928     (closure->destroy) (closure->data);
1929   g_free (closure);
1930 }
1931
1932 static gboolean
1933 gtk_invoke_idle_timeout (gpointer data)
1934 {
1935   GtkClosure *closure = data;
1936
1937   GtkArg args[1];
1938   gint ret_val = FALSE;
1939   args[0].name = NULL;
1940   args[0].type = G_TYPE_BOOLEAN;
1941   args[0].d.pointer_data = &ret_val;
1942   closure->marshal (NULL, closure->data,  0, args);
1943   return ret_val;
1944 }
1945
1946 static void
1947 gtk_invoke_input (gpointer          data,
1948                   gint              source,
1949                   GdkInputCondition condition)
1950 {
1951   GtkClosure *closure = data;
1952
1953   GtkArg args[3];
1954   args[0].type = G_TYPE_INT;
1955   args[0].name = NULL;
1956   GTK_VALUE_INT (args[0]) = source;
1957   args[1].type = GDK_TYPE_INPUT_CONDITION;
1958   args[1].name = NULL;
1959   GTK_VALUE_FLAGS (args[1]) = condition;
1960   args[2].type = G_TYPE_NONE;
1961   args[2].name = NULL;
1962
1963   closure->marshal (NULL, closure->data, 2, args);
1964 }
1965
1966 /**
1967  * gtk_get_current_event:
1968  * 
1969  * Obtains a copy of the event currently being processed by GTK+.  For
1970  * example, if you get a "clicked" signal from #GtkButton, the current
1971  * event will be the #GdkEventButton that triggered the "clicked"
1972  * signal. The returned event must be freed with gdk_event_free().
1973  * If there is no current event, the function returns %NULL.
1974  * 
1975  * Return value: a copy of the current event, or %NULL if no current event.
1976  **/
1977 GdkEvent*
1978 gtk_get_current_event (void)
1979 {
1980   if (current_events)
1981     return gdk_event_copy (current_events->data);
1982   else
1983     return NULL;
1984 }
1985
1986 /**
1987  * gtk_get_current_event_time:
1988  * 
1989  * If there is a current event and it has a timestamp, return that
1990  * timestamp, otherwise return %GDK_CURRENT_TIME.
1991  * 
1992  * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
1993  **/
1994 guint32
1995 gtk_get_current_event_time (void)
1996 {
1997   if (current_events)
1998     return gdk_event_get_time (current_events->data);
1999   else
2000     return GDK_CURRENT_TIME;
2001 }
2002
2003 /**
2004  * gtk_get_current_event_state:
2005  * @state: a location to store the state of the current event
2006  * 
2007  * If there is a current event and it has a state field, place
2008  * that state field in @state and return %TRUE, otherwise return
2009  * %FALSE.
2010  * 
2011  * Return value: %TRUE if there was a current event and it had a state field
2012  **/
2013 gboolean
2014 gtk_get_current_event_state (GdkModifierType *state)
2015 {
2016   g_return_val_if_fail (state != NULL, FALSE);
2017   
2018   if (current_events)
2019     return gdk_event_get_state (current_events->data, state);
2020   else
2021     {
2022       *state = 0;
2023       return FALSE;
2024     }
2025 }
2026
2027 /**
2028  * gtk_get_event_widget:
2029  * @event: a #GdkEvent
2030  *
2031  * If @event is %NULL or the event was not associated with any widget,
2032  * returns %NULL, otherwise returns the widget that received the event
2033  * originally.
2034  * 
2035  * Return value: the widget that originally received @event, or %NULL
2036  **/
2037 GtkWidget*
2038 gtk_get_event_widget (GdkEvent *event)
2039 {
2040   GtkWidget *widget;
2041
2042   widget = NULL;
2043   if (event && event->any.window)
2044     gdk_window_get_user_data (event->any.window, (void**) &widget);
2045   
2046   return widget;
2047 }
2048
2049 static gint
2050 gtk_quit_invoke_function (GtkQuitFunction *quitf)
2051 {
2052   if (!quitf->marshal)
2053     return quitf->function (quitf->data);
2054   else
2055     {
2056       GtkArg args[1];
2057       gint ret_val = FALSE;
2058
2059       args[0].name = NULL;
2060       args[0].type = G_TYPE_BOOLEAN;
2061       args[0].d.pointer_data = &ret_val;
2062       ((GtkCallbackMarshal) quitf->marshal) (NULL,
2063                                              quitf->data,
2064                                              0, args);
2065       return ret_val;
2066     }
2067 }
2068
2069 /**
2070  * gtk_propagate_event:
2071  * @widget: a #GtkWidget
2072  * @event: an event
2073  *
2074  * Sends an event to a widget, propagating the event to parent widgets
2075  * if the event remains unhandled. Events received by GTK+ from GDK
2076  * normally begin in gtk_main_do_event(). Depending on the type of
2077  * event, existence of modal dialogs, grabs, etc., the event may be
2078  * propagated; if so, this function is used. gtk_propagate_event()
2079  * calls gtk_widget_event() on each widget it decides to send the
2080  * event to.  So gtk_widget_event() is the lowest-level function; it
2081  * simply emits the "event" and possibly an event-specific signal on a
2082  * widget.  gtk_propagate_event() is a bit higher-level, and
2083  * gtk_main_do_event() is the highest level.
2084  *
2085  * All that said, you most likely don't want to use any of these
2086  * functions; synthesizing events is rarely needed. Consider asking on
2087  * the mailing list for better ways to achieve your goals. For
2088  * example, use gdk_window_invalidate_rect() or
2089  * gtk_widget_queue_draw() instead of making up expose events.
2090  * 
2091  **/
2092 void
2093 gtk_propagate_event (GtkWidget *widget,
2094                      GdkEvent  *event)
2095 {
2096   gint handled_event;
2097   
2098   g_return_if_fail (GTK_IS_WIDGET (widget));
2099   g_return_if_fail (event != NULL);
2100   
2101   handled_event = FALSE;
2102
2103   g_object_ref (widget);
2104       
2105   if ((event->type == GDK_KEY_PRESS) ||
2106       (event->type == GDK_KEY_RELEASE))
2107     {
2108       /* Only send key events within Window widgets to the Window
2109        *  The Window widget will in turn pass the
2110        *  key event on to the currently focused widget
2111        *  for that window.
2112        */
2113       GtkWidget *window;
2114
2115       window = gtk_widget_get_toplevel (widget);
2116       if (window && GTK_IS_WINDOW (window))
2117         {
2118           /* If there is a grab within the window, give the grab widget
2119            * a first crack at the key event
2120            */
2121           if (widget != window && GTK_WIDGET_HAS_GRAB (widget))
2122             handled_event = gtk_widget_event (widget, event);
2123           
2124           if (!handled_event)
2125             {
2126               window = gtk_widget_get_toplevel (widget);
2127               if (window && GTK_IS_WINDOW (window))
2128                 {
2129                   if (GTK_WIDGET_IS_SENSITIVE (window))
2130                     gtk_widget_event (window, event);
2131                 }
2132             }
2133                   
2134           handled_event = TRUE; /* don't send to widget */
2135         }
2136     }
2137   
2138   /* Other events get propagated up the widget tree
2139    *  so that parents can see the button and motion
2140    *  events of the children.
2141    */
2142   if (!handled_event)
2143     {
2144       while (TRUE)
2145         {
2146           GtkWidget *tmp;
2147
2148           /* Scroll events are special cased here because it
2149            * feels wrong when scrolling a GtkViewport, say,
2150            * to have children of the viewport eat the scroll
2151            * event
2152            */
2153           if (!GTK_WIDGET_IS_SENSITIVE (widget))
2154             handled_event = event->type != GDK_SCROLL;
2155           else
2156             handled_event = gtk_widget_event (widget, event);
2157               
2158           tmp = widget->parent;
2159           g_object_unref (widget);
2160
2161           widget = tmp;
2162           
2163           if (!handled_event && widget)
2164             g_object_ref (widget);
2165           else
2166             break;
2167         }
2168     }
2169   else
2170     g_object_unref (widget);
2171 }
2172
2173 #if 0
2174 static void
2175 gtk_error (gchar *str)
2176 {
2177   gtk_print (str);
2178 }
2179
2180 static void
2181 gtk_warning (gchar *str)
2182 {
2183   gtk_print (str);
2184 }
2185
2186 static void
2187 gtk_message (gchar *str)
2188 {
2189   gtk_print (str);
2190 }
2191
2192 static void
2193 gtk_print (gchar *str)
2194 {
2195   static GtkWidget *window = NULL;
2196   static GtkWidget *text;
2197   static int level = 0;
2198   GtkWidget *box1;
2199   GtkWidget *box2;
2200   GtkWidget *table;
2201   GtkWidget *hscrollbar;
2202   GtkWidget *vscrollbar;
2203   GtkWidget *separator;
2204   GtkWidget *button;
2205   
2206   if (level > 0)
2207     {
2208       fputs (str, stdout);
2209       fflush (stdout);
2210       return;
2211     }
2212   
2213   if (!window)
2214     {
2215       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2216       
2217       gtk_signal_connect (GTK_OBJECT (window), "destroy",
2218                           (GtkSignalFunc) gtk_widget_destroyed,
2219                           &window);
2220       
2221       gtk_window_set_title (GTK_WINDOW (window), "Messages");
2222       
2223       box1 = gtk_vbox_new (FALSE, 0);
2224       gtk_container_add (GTK_CONTAINER (window), box1);
2225       gtk_widget_show (box1);
2226       
2227       
2228       box2 = gtk_vbox_new (FALSE, 10);
2229       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2230       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2231       gtk_widget_show (box2);
2232       
2233       
2234       table = gtk_table_new (2, 2, FALSE);
2235       gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
2236       gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
2237       gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
2238       gtk_widget_show (table);
2239       
2240       text = gtk_text_new (NULL, NULL);
2241       gtk_text_set_editable (GTK_TEXT (text), FALSE);
2242       gtk_table_attach_defaults (GTK_TABLE (table), text, 0, 1, 0, 1);
2243       gtk_widget_show (text);
2244       gtk_widget_realize (text);
2245       
2246       hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
2247       gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
2248                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
2249       gtk_widget_show (hscrollbar);
2250       
2251       vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
2252       gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
2253                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
2254       gtk_widget_show (vscrollbar);
2255       
2256       separator = gtk_hseparator_new ();
2257       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2258       gtk_widget_show (separator);
2259       
2260       
2261       box2 = gtk_vbox_new (FALSE, 10);
2262       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2263       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2264       gtk_widget_show (box2);
2265       
2266       
2267       button = gtk_button_new_with_label ("close");
2268       gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2269                                  (GtkSignalFunc) gtk_widget_hide,
2270                                  GTK_OBJECT (window));
2271       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2272       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2273       gtk_widget_grab_default (button);
2274       gtk_widget_show (button);
2275     }
2276   
2277   level += 1;
2278   gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, str, -1);
2279   level -= 1;
2280   
2281   if (!GTK_WIDGET_VISIBLE (window))
2282     gtk_widget_show (window);
2283 }
2284 #endif
2285
2286 gboolean
2287 _gtk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
2288                                   GValue                *return_accu,
2289                                   const GValue          *handler_return,
2290                                   gpointer               dummy)
2291 {
2292   gboolean continue_emission;
2293   gboolean signal_handled;
2294   
2295   signal_handled = g_value_get_boolean (handler_return);
2296   g_value_set_boolean (return_accu, signal_handled);
2297   continue_emission = !signal_handled;
2298   
2299   return continue_emission;
2300 }
2301
2302 #define __GTK_MAIN_C__
2303 #include "gtkaliasdef.c"