]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Merge branch 'master' into toolpalette
[~andy/gtk] / tests / testgtk.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 #undef GTK_DISABLE_DEPRECATED
28
29 #include "config.h"
30
31 #undef  G_LOG_DOMAIN
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <math.h>
38 #include <time.h>
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #define GTK_ENABLE_BROKEN
44 #include "gtk/gtk.h"
45 #include "gdk/gdk.h"
46 #include "gdk/gdkkeysyms.h"
47
48 #ifdef G_OS_WIN32
49 #define sleep(n) _sleep(n)
50 #endif
51
52 #include "prop-editor.h"
53
54 #include "circles.xbm"
55 #include "test.xpm"
56
57 gboolean
58 file_exists (const char *filename)
59 {
60   struct stat statbuf;
61
62   return stat (filename, &statbuf) == 0;
63 }
64
65 GtkWidget *
66 shape_create_icon (GdkScreen *screen,
67                    char      *xpm_file,
68                    gint       x,
69                    gint       y,
70                    gint       px,
71                    gint       py,
72                    gint       window_type);
73
74 static GtkWidget *
75 build_option_menu (gchar           *items[],
76                    gint             num_items,
77                    gint             history,
78                    void           (*func) (GtkWidget *widget, gpointer data),
79                    gpointer         data);
80
81 /* macro, structure and variables used by tree window demos */
82 #define DEFAULT_NUMBER_OF_ITEM  3
83 #define DEFAULT_RECURSION_LEVEL 3
84
85 struct {
86   GSList* selection_mode_group;
87   GtkWidget* single_button;
88   GtkWidget* browse_button;
89   GtkWidget* multiple_button;
90   GtkWidget* draw_line_button;
91   GtkWidget* view_line_button;
92   GtkWidget* no_root_item_button;
93   GtkWidget* nb_item_spinner;
94   GtkWidget* recursion_spinner;
95 } sTreeSampleSelection;
96
97 typedef struct sTreeButtons {
98   guint nb_item_add;
99   GtkWidget* add_button;
100   GtkWidget* remove_button;
101   GtkWidget* subtree_button;
102 } sTreeButtons;
103 /* end of tree section */
104
105 static GtkWidget *
106 build_option_menu (gchar           *items[],
107                    gint             num_items,
108                    gint             history,
109                    void           (*func)(GtkWidget *widget, gpointer data),
110                    gpointer         data)
111 {
112   GtkWidget *omenu;
113   GtkWidget *menu;
114   GtkWidget *menu_item;
115   GSList *group;
116   gint i;
117
118   omenu = gtk_option_menu_new ();
119   g_signal_connect (omenu, "changed",
120                     G_CALLBACK (func), data);
121       
122   menu = gtk_menu_new ();
123   group = NULL;
124   
125   for (i = 0; i < num_items; i++)
126     {
127       menu_item = gtk_radio_menu_item_new_with_label (group, items[i]);
128       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
129       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
130       if (i == history)
131         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
132       gtk_widget_show (menu_item);
133     }
134
135   gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu);
136   gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), history);
137   
138   return omenu;
139 }
140
141 static void
142 destroy_tooltips (GtkWidget *widget, GtkWindow **window)
143 {
144   GtkTooltips *tt = g_object_get_data (G_OBJECT (*window), "tooltips");
145   g_object_unref (tt);
146   *window = NULL;
147 }
148
149
150 /*
151  * Windows with an alpha channel
152  */
153
154
155 static gboolean
156 on_alpha_window_expose (GtkWidget      *widget,
157                         GdkEventExpose *expose)
158 {
159   cairo_t *cr;
160   cairo_pattern_t *pattern;
161   int radius;
162
163   cr = gdk_cairo_create (widget->window);
164
165   radius = MIN (widget->allocation.width, widget->allocation.height) / 2;
166   pattern = cairo_pattern_create_radial (widget->allocation.width / 2,
167                                          widget->allocation.height / 2,
168                                          0.0,
169                                          widget->allocation.width / 2,
170                                          widget->allocation.height / 2,
171                                          radius * 1.33);
172
173   if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)) &&
174       gtk_widget_is_composited (widget))
175     cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
176   else
177     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
178     
179   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
180   cairo_paint (cr);
181   
182   cairo_pattern_add_color_stop_rgba (pattern, 0.0,
183                                      1.0, 0.75, 0.0, 1.0); /* solid orange */
184   cairo_pattern_add_color_stop_rgba (pattern, 1.0,
185                                      1.0, 0.75, 0.0, 0.0); /* transparent orange */
186
187   cairo_set_source (cr, pattern);
188   cairo_pattern_destroy (pattern);
189   
190   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
191   cairo_paint (cr);
192
193   cairo_destroy (cr);
194
195   return FALSE;
196 }
197
198 static GtkWidget *
199 build_alpha_widgets (void)
200 {
201   GtkWidget *table;
202   GtkWidget *radio_button;
203   GtkWidget *hbox;
204   GtkWidget *label;
205   GtkWidget *entry;
206
207   table = gtk_table_new (1, 1, FALSE);
208
209   radio_button = gtk_radio_button_new_with_label (NULL, "Red");
210   gtk_table_attach (GTK_TABLE (table),
211                     radio_button,
212                     0, 1,                  0, 1,
213                     GTK_EXPAND | GTK_FILL, 0,
214                     0,                     0);
215
216   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
217   gtk_table_attach (GTK_TABLE (table),
218                     radio_button,
219                     0, 1,                  1, 2,
220                     GTK_EXPAND | GTK_FILL, 0,
221                     0,                     0);
222
223   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
224   gtk_table_attach (GTK_TABLE (table),
225                     radio_button,
226                     0, 1,                  2, 3,
227                     GTK_EXPAND | GTK_FILL, 0,
228                     0,                     0);
229
230   gtk_table_attach (GTK_TABLE (table),
231                     gtk_check_button_new_with_label ("Sedentary"),
232                     1, 2,                  0, 1,
233                     GTK_EXPAND | GTK_FILL, 0,
234                     0,                     0);
235   gtk_table_attach (GTK_TABLE (table),
236                     gtk_check_button_new_with_label ("Nocturnal"),
237                     1, 2,                  1, 2,
238                     GTK_EXPAND | GTK_FILL, 0,
239                     0,                     0);
240   gtk_table_attach (GTK_TABLE (table),
241                     gtk_check_button_new_with_label ("Compulsive"),
242                     1, 2,                  2, 3,
243                     GTK_EXPAND | GTK_FILL, 0,
244                     0,                     0);
245
246   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
247   gtk_table_attach (GTK_TABLE (table),
248                     radio_button,
249                     0, 1,                  1, 2,
250                     GTK_EXPAND | GTK_FILL, 0,
251                     0,                     0);
252
253   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
254   gtk_table_attach (GTK_TABLE (table),
255                     radio_button,
256                     0, 1,                  2, 3,
257                     GTK_EXPAND | GTK_FILL, 0,
258                     0,                     0);
259   
260   hbox = gtk_hbox_new (FALSE, 0);
261   label = gtk_label_new (NULL);
262   gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
263   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
264   entry = gtk_entry_new ();
265   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
266   gtk_table_attach (GTK_TABLE (table),
267                     hbox,
268                     0, 1,                  3, 4,
269                     GTK_EXPAND | GTK_FILL, 0,
270                     0,                     0);
271   
272   return table;
273 }
274
275 static gboolean
276 on_alpha_drawing_expose (GtkWidget      *widget,
277                          GdkEventExpose *expose)
278 {
279   int x = widget->allocation.x;
280   int y = widget->allocation.y;
281   int width = widget->allocation.width;
282   int height = widget->allocation.height;
283   GdkPixbuf *pixbuf;
284   guchar *buffer;
285   guchar *p;
286   int i, j;
287
288   buffer = g_malloc (64 * 64 * 4);
289   
290   gdk_draw_rectangle (widget->window, widget->style->black_gc, FALSE,
291                       x,         y,
292                       width - 1, height - 1);
293
294   p = buffer;
295   for (i = 0; i < 64; i++) {
296     for (j = 0; j < 64; j++) {
297       *(p++) = i * 4 + 3;
298       *(p++) = 0;
299       *(p++) = j + 4 + 3;
300       *(p++) = MIN (255, ((32 - i) * (32 - i) + (32 - j) * (32 - j)) / 8);
301     }
302   }
303   p++;
304
305   gdk_draw_rgb_32_image (widget->window, widget->style->black_gc,
306                          x + 18, y + (height - 64) /2,
307                          64, 64, GDK_RGB_DITHER_NORMAL, buffer, 64 * 4);
308
309   pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, TRUE,
310                                      8, 64, 64, 4 * 64, NULL, NULL);
311
312   gdk_draw_pixbuf (widget->window, widget->style->black_gc, pixbuf,
313                    0, 0, x + width - 18 - 64, y + (height - 64) /2,
314                    64, 64, GDK_RGB_DITHER_NORMAL, 0, 0);
315
316   g_object_unref (pixbuf);
317
318   g_free (buffer);
319   
320   return FALSE;
321 }
322
323 static GtkWidget *
324 build_alpha_drawing ()
325 {
326   GtkWidget *hbox;
327
328   hbox = gtk_hbox_new (FALSE, 0);
329   gtk_widget_set_size_request (hbox, 100, 100);
330
331   g_signal_connect (hbox, "expose-event",
332                     G_CALLBACK (on_alpha_drawing_expose), NULL);
333
334   return hbox;
335 }
336
337 static void
338 on_alpha_screen_changed (GtkWidget *widget,
339                          GdkScreen *old_screen,
340                          GtkWidget *label)
341 {
342   GdkScreen *screen = gtk_widget_get_screen (widget);
343   GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
344
345   if (!colormap)
346     {
347       colormap = gdk_screen_get_rgb_colormap (screen);
348       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
349     }
350   else
351     {
352       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
353     }
354
355   gtk_widget_set_colormap (widget, colormap);
356 }
357
358 static void
359 on_composited_changed (GtkWidget *window,
360                       GtkLabel *label)
361 {
362   gboolean is_composited = gtk_widget_is_composited (window);
363
364   if (is_composited)
365     gtk_label_set_text (label, "Composited");
366   else
367     gtk_label_set_text (label, "Not composited");
368 }
369
370 void
371 create_alpha_window (GtkWidget *widget)
372 {
373   static GtkWidget *window;
374
375   if (!window)
376     {
377       GtkWidget *vbox;
378       GtkWidget *label;
379       
380       window = gtk_dialog_new_with_buttons ("Alpha Window",
381                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
382                                             GTK_STOCK_CLOSE, 0,
383                                             NULL);
384
385       gtk_widget_set_app_paintable (window, TRUE);
386       g_signal_connect (window, "expose-event",
387                         G_CALLBACK (on_alpha_window_expose), NULL);
388       
389       vbox = gtk_vbox_new (FALSE, 8);
390       gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
391       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
392                           TRUE, TRUE, 0);
393
394       label = gtk_label_new (NULL);
395       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
396       on_alpha_screen_changed (window, NULL, label);
397       g_signal_connect (window, "screen-changed",
398                         G_CALLBACK (on_alpha_screen_changed), label);
399       
400       label = gtk_label_new (NULL);
401       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
402       on_composited_changed (window, GTK_LABEL (label));
403       g_signal_connect (window, "composited_changed", G_CALLBACK (on_composited_changed), label);
404       
405       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
406       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0);
407
408       g_signal_connect (window, "destroy",
409                         G_CALLBACK (gtk_widget_destroyed),
410                         &window);
411       
412       g_signal_connect (window, "response",
413                         G_CALLBACK (gtk_widget_destroy),
414                         NULL); 
415     }
416
417   if (!GTK_WIDGET_VISIBLE (window))
418     gtk_widget_show_all (window);
419   else
420     gtk_widget_destroy (window);
421 }
422
423 /*
424  * Composited non-toplevel window
425  */
426
427 /* The expose event handler for the event box.
428  *
429  * This function simply draws a transparency onto a widget on the area
430  * for which it receives expose events.  This is intended to give the
431  * event box a "transparent" background.
432  *
433  * In order for this to work properly, the widget must have an RGBA
434  * colourmap.  The widget should also be set as app-paintable since it
435  * doesn't make sense for GTK to draw a background if we are drawing it
436  * (and because GTK might actually replace our transparency with its
437  * default background colour).
438  */
439 static gboolean
440 transparent_expose (GtkWidget *widget,
441                     GdkEventExpose *event)
442 {
443   cairo_t *cr;
444
445   cr = gdk_cairo_create (widget->window);
446   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
447   gdk_cairo_region (cr, event->region);
448   cairo_fill (cr);
449   cairo_destroy (cr);
450
451   return FALSE;
452 }
453
454 /* The expose event handler for the window.
455  *
456  * This function performs the actual compositing of the event box onto
457  * the already-existing background of the window at 50% normal opacity.
458  *
459  * In this case we do not want app-paintable to be set on the widget
460  * since we want it to draw its own (red) background.  Because of this,
461  * however, we must ensure that we use g_signal_register_after so that
462  * this handler is called after the red has been drawn.  If it was
463  * called before then GTK would just blindly paint over our work.
464  */
465 static gboolean
466 window_expose_event (GtkWidget *widget,
467                      GdkEventExpose *event)
468 {
469   GdkRegion *region;
470   GtkWidget *child;
471   cairo_t *cr;
472
473   /* get our child (in this case, the event box) */ 
474   child = gtk_bin_get_child (GTK_BIN (widget));
475
476   /* create a cairo context to draw to the window */
477   cr = gdk_cairo_create (widget->window);
478
479   /* the source data is the (composited) event box */
480   gdk_cairo_set_source_pixmap (cr, child->window,
481                                child->allocation.x,
482                                child->allocation.y);
483
484   /* draw no more than our expose event intersects our child */
485   region = gdk_region_rectangle (&child->allocation);
486   gdk_region_intersect (region, event->region);
487   gdk_cairo_region (cr, region);
488   cairo_clip (cr);
489
490   /* composite, with a 50% opacity */
491   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
492   cairo_paint_with_alpha (cr, 0.5);
493
494   /* we're done */
495   cairo_destroy (cr);
496
497   return FALSE;
498 }
499
500 void
501 create_composited_window (GtkWidget *widget)
502 {
503   static GtkWidget *window;
504
505   if (!window)
506     {
507       GtkWidget *event, *button;
508       GdkScreen *screen;
509       GdkColormap *rgba;
510       GdkColor red;
511
512       /* make the widgets */
513       button = gtk_button_new_with_label ("A Button");
514       event = gtk_event_box_new ();
515       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
516
517       g_signal_connect (window, "destroy",
518                         G_CALLBACK (gtk_widget_destroyed),
519                         &window);
520
521       /* put a red background on the window */
522       gdk_color_parse ("red", &red);
523       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &red);
524
525       /* set the colourmap for the event box.
526        * must be done before the event box is realised.
527        */
528       screen = gtk_widget_get_screen (event);
529       rgba = gdk_screen_get_rgba_colormap (screen);
530       gtk_widget_set_colormap (event, rgba);
531
532       /* set our event box to have a fully-transparent background
533        * drawn on it.  currently there is no way to simply tell gtk
534        * that "transparency" is the background colour for a widget.
535        */
536       gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
537       g_signal_connect (event, "expose-event",
538                         G_CALLBACK (transparent_expose), NULL);
539
540       /* put them inside one another */
541       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
542       gtk_container_add (GTK_CONTAINER (window), event);
543       gtk_container_add (GTK_CONTAINER (event), button);
544
545       /* realise and show everything */
546       gtk_widget_realize (button);
547
548       /* set the event box GdkWindow to be composited.
549        * obviously must be performed after event box is realised.
550        */
551       gdk_window_set_composited (event->window, TRUE);
552
553       /* set up the compositing handler.
554        * note that we do _after so that the normal (red) background is drawn
555        * by gtk before our compositing occurs.
556        */
557       g_signal_connect_after (window, "expose-event",
558                               G_CALLBACK (window_expose_event), NULL);
559     }
560
561   if (!GTK_WIDGET_VISIBLE (window))
562     gtk_widget_show_all (window);
563   else
564     gtk_widget_destroy (window);
565 }
566
567 /*
568  * Big windows and guffaw scrolling
569  */
570
571 static gboolean
572 pattern_expose (GtkWidget      *widget,
573                 GdkEventExpose *event,
574                 gpointer        data)
575 {
576   GdkColor *color;
577   GdkWindow *window = event->window;
578
579   color = g_object_get_data (G_OBJECT (window), "pattern-color");
580   if (color)
581     {
582       GdkGC *tmp_gc = gdk_gc_new (window);
583       gdk_gc_set_rgb_fg_color (tmp_gc, color);
584
585       gdk_draw_rectangle (window, tmp_gc, TRUE,
586                           event->area.x, event->area.y,
587                           event->area.width, event->area.height);
588
589       g_object_unref (tmp_gc);
590     }
591
592   return FALSE;
593 }
594
595 static void
596 pattern_set_bg (GtkWidget   *widget,
597                 GdkWindow   *child,
598                 gint         level)
599 {
600   static const GdkColor colors[] = {
601     { 0, 0x4444, 0x4444, 0xffff },
602     { 0, 0x8888, 0x8888, 0xffff },
603     { 0, 0xaaaa, 0xaaaa, 0xffff }
604   };
605     
606   g_object_set_data (G_OBJECT (child), "pattern-color", (gpointer) &colors[level]);
607   gdk_window_set_user_data (child, widget);
608 }
609
610 static void
611 create_pattern (GtkWidget   *widget,
612                 GdkWindow   *parent,
613                 gint         level,
614                 gint         width,
615                 gint         height)
616 {
617   gint h = 1;
618   gint i = 0;
619     
620   GdkWindow *child;
621
622   while (2 * h <= height)
623     {
624       gint w = 1;
625       gint j = 0;
626       
627       while (2 * w <= width)
628         {
629           if ((i + j) % 2 == 0)
630             {
631               gint x = w  - 1;
632               gint y = h - 1;
633               
634               GdkWindowAttr attributes;
635
636               attributes.window_type = GDK_WINDOW_CHILD;
637               attributes.x = x;
638               attributes.y = y;
639               attributes.width = w;
640               attributes.height = h;
641               attributes.wclass = GDK_INPUT_OUTPUT;
642               attributes.event_mask = GDK_EXPOSURE_MASK;
643               attributes.visual = gtk_widget_get_visual (widget);
644               attributes.colormap = gtk_widget_get_colormap (widget);
645               
646               child = gdk_window_new (parent, &attributes,
647                                       GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
648
649               pattern_set_bg (widget, child, level);
650
651               if (level < 2)
652                 create_pattern (widget, child, level + 1, w, h);
653
654               gdk_window_show (child);
655             }
656           j++;
657           w *= 2;
658         }
659       i++;
660       h *= 2;
661     }
662 }
663
664 #define PATTERN_SIZE (1 << 18)
665
666 static void
667 pattern_hadj_changed (GtkAdjustment *adj,
668                       GtkWidget     *darea)
669 {
670   gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
671   gint new_value = adj->value;
672
673   if (GTK_WIDGET_REALIZED (darea))
674     {
675       gdk_window_scroll (darea->window, *old_value - new_value, 0);
676       *old_value = new_value;
677     }
678 }
679
680 static void
681 pattern_vadj_changed (GtkAdjustment *adj,
682                       GtkWidget *darea)
683 {
684   gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
685   gint new_value = adj->value;
686
687   if (GTK_WIDGET_REALIZED (darea))
688     {
689       gdk_window_scroll (darea->window, 0, *old_value - new_value);
690       *old_value = new_value;
691     }
692 }
693
694 static void
695 pattern_realize (GtkWidget *widget,
696                  gpointer   data)
697 {
698   pattern_set_bg (widget, widget->window, 0);
699   create_pattern (widget, widget->window, 1, PATTERN_SIZE, PATTERN_SIZE);
700 }
701
702 static void 
703 create_big_windows (GtkWidget *widget)
704 {
705   static GtkWidget *window = NULL;
706   GtkWidget *darea, *table, *scrollbar;
707   GtkWidget *eventbox;
708   GtkAdjustment *hadj;
709   GtkAdjustment *vadj;
710   static gint current_x;
711   static gint current_y;
712  
713   if (!window)
714     {
715       current_x = 0;
716       current_y = 0;
717       
718       window = gtk_dialog_new_with_buttons ("Big Windows",
719                                             NULL, 0,
720                                             GTK_STOCK_CLOSE,
721                                             GTK_RESPONSE_NONE,
722                                             NULL);
723  
724       gtk_window_set_screen (GTK_WINDOW (window),
725                              gtk_widget_get_screen (widget));
726
727       gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
728
729       g_signal_connect (window, "destroy",
730                         G_CALLBACK (gtk_widget_destroyed),
731                         &window);
732
733       g_signal_connect (window, "response",
734                         G_CALLBACK (gtk_widget_destroy),
735                         NULL);
736
737       table = gtk_table_new (2, 2, FALSE);
738       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
739                           table, TRUE, TRUE, 0);
740
741       darea = gtk_drawing_area_new ();
742
743       hadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
744       g_signal_connect (hadj, "value_changed",
745                         G_CALLBACK (pattern_hadj_changed), darea);
746       g_object_set_data (G_OBJECT (hadj), "old-value", &current_x);
747       
748       vadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
749       g_signal_connect (vadj, "value_changed",
750                         G_CALLBACK (pattern_vadj_changed), darea);
751       g_object_set_data (G_OBJECT (vadj), "old-value", &current_y);
752       
753       g_signal_connect (darea, "realize",
754                         G_CALLBACK (pattern_realize),
755                         NULL);
756       g_signal_connect (darea, "expose_event",
757                         G_CALLBACK (pattern_expose),
758                         NULL);
759
760       eventbox = gtk_event_box_new ();
761       gtk_table_attach (GTK_TABLE (table), eventbox,
762                         0, 1,                  0, 1,
763                         GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
764                         0,                     0);
765
766       gtk_container_add (GTK_CONTAINER (eventbox), darea);
767
768       scrollbar = gtk_hscrollbar_new (hadj);
769       gtk_table_attach (GTK_TABLE (table), scrollbar,
770                         0, 1,                  1, 2,
771                         GTK_FILL | GTK_EXPAND, GTK_FILL,
772                         0,                     0);
773
774       scrollbar = gtk_vscrollbar_new (vadj);
775       gtk_table_attach (GTK_TABLE (table), scrollbar,
776                         1, 2,                  0, 1,
777                         GTK_FILL,              GTK_EXPAND | GTK_FILL,
778                         0,                     0);
779
780     }
781
782   if (!GTK_WIDGET_VISIBLE (window))
783     gtk_widget_show_all (window);
784   else
785     gtk_widget_hide (window);
786 }
787
788 /*
789  * GtkButton
790  */
791
792 static void
793 button_window (GtkWidget *widget,
794                GtkWidget *button)
795 {
796   if (!GTK_WIDGET_VISIBLE (button))
797     gtk_widget_show (button);
798   else
799     gtk_widget_hide (button);
800 }
801
802 static void
803 create_buttons (GtkWidget *widget)
804 {
805   static GtkWidget *window = NULL;
806   GtkWidget *box1;
807   GtkWidget *box2;
808   GtkWidget *table;
809   GtkWidget *button[10];
810   GtkWidget *separator;
811
812   if (!window)
813     {
814       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
815       gtk_window_set_screen (GTK_WINDOW (window),
816                              gtk_widget_get_screen (widget));
817
818       g_signal_connect (window, "destroy",
819                         G_CALLBACK (gtk_widget_destroyed),
820                         &window);
821
822       gtk_window_set_title (GTK_WINDOW (window), "GtkButton");
823       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
824
825       box1 = gtk_vbox_new (FALSE, 0);
826       gtk_container_add (GTK_CONTAINER (window), box1);
827
828       table = gtk_table_new (3, 3, FALSE);
829       gtk_table_set_row_spacings (GTK_TABLE (table), 5);
830       gtk_table_set_col_spacings (GTK_TABLE (table), 5);
831       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
832       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
833
834       button[0] = gtk_button_new_with_label ("button1");
835       button[1] = gtk_button_new_with_mnemonic ("_button2");
836       button[2] = gtk_button_new_with_mnemonic ("_button3");
837       button[3] = gtk_button_new_from_stock (GTK_STOCK_OK);
838       button[4] = gtk_button_new_with_label ("button5");
839       button[5] = gtk_button_new_with_label ("button6");
840       button[6] = gtk_button_new_with_label ("button7");
841       button[7] = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
842       button[8] = gtk_button_new_with_label ("button9");
843       
844       g_signal_connect (button[0], "clicked",
845                         G_CALLBACK (button_window),
846                         button[1]);
847
848       gtk_table_attach (GTK_TABLE (table), button[0], 0, 1, 0, 1,
849                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
850
851       g_signal_connect (button[1], "clicked",
852                         G_CALLBACK (button_window),
853                         button[2]);
854
855       gtk_table_attach (GTK_TABLE (table), button[1], 1, 2, 1, 2,
856                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
857
858       g_signal_connect (button[2], "clicked",
859                         G_CALLBACK (button_window),
860                         button[3]);
861       gtk_table_attach (GTK_TABLE (table), button[2], 2, 3, 2, 3,
862                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
863
864       g_signal_connect (button[3], "clicked",
865                         G_CALLBACK (button_window),
866                         button[4]);
867       gtk_table_attach (GTK_TABLE (table), button[3], 0, 1, 2, 3,
868                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
869
870       g_signal_connect (button[4], "clicked",
871                         G_CALLBACK (button_window),
872                         button[5]);
873       gtk_table_attach (GTK_TABLE (table), button[4], 2, 3, 0, 1,
874                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
875
876       g_signal_connect (button[5], "clicked",
877                         G_CALLBACK (button_window),
878                         button[6]);
879       gtk_table_attach (GTK_TABLE (table), button[5], 1, 2, 2, 3,
880                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
881
882       g_signal_connect (button[6], "clicked",
883                         G_CALLBACK (button_window),
884                         button[7]);
885       gtk_table_attach (GTK_TABLE (table), button[6], 1, 2, 0, 1,
886                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
887
888       g_signal_connect (button[7], "clicked",
889                         G_CALLBACK (button_window),
890                         button[8]);
891       gtk_table_attach (GTK_TABLE (table), button[7], 2, 3, 1, 2,
892                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
893
894       g_signal_connect (button[8], "clicked",
895                         G_CALLBACK (button_window),
896                         button[0]);
897       gtk_table_attach (GTK_TABLE (table), button[8], 0, 1, 1, 2,
898                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
899
900       separator = gtk_hseparator_new ();
901       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
902
903       box2 = gtk_vbox_new (FALSE, 10);
904       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
905       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
906
907       button[9] = gtk_button_new_with_label ("close");
908       g_signal_connect_swapped (button[9], "clicked",
909                                 G_CALLBACK (gtk_widget_destroy),
910                                 window);
911       gtk_box_pack_start (GTK_BOX (box2), button[9], TRUE, TRUE, 0);
912       GTK_WIDGET_SET_FLAGS (button[9], GTK_CAN_DEFAULT);
913       gtk_widget_grab_default (button[9]);
914     }
915
916   if (!GTK_WIDGET_VISIBLE (window))
917     gtk_widget_show_all (window);
918   else
919     gtk_widget_destroy (window);
920 }
921
922 /*
923  * GtkToggleButton
924  */
925
926 static void
927 create_toggle_buttons (GtkWidget *widget)
928 {
929   static GtkWidget *window = NULL;
930   GtkWidget *box1;
931   GtkWidget *box2;
932   GtkWidget *button;
933   GtkWidget *separator;
934
935   if (!window)
936     {
937       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
938       gtk_window_set_screen (GTK_WINDOW (window),
939                              gtk_widget_get_screen (widget));
940
941       g_signal_connect (window, "destroy",
942                         G_CALLBACK (gtk_widget_destroyed),
943                         &window);
944
945       gtk_window_set_title (GTK_WINDOW (window), "GtkToggleButton");
946       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
947
948       box1 = gtk_vbox_new (FALSE, 0);
949       gtk_container_add (GTK_CONTAINER (window), box1);
950
951       box2 = gtk_vbox_new (FALSE, 10);
952       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
953       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
954
955       button = gtk_toggle_button_new_with_label ("button1");
956       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
957
958       button = gtk_toggle_button_new_with_label ("button2");
959       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
960
961       button = gtk_toggle_button_new_with_label ("button3");
962       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
963
964       button = gtk_toggle_button_new_with_label ("inconsistent");
965       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
966       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
967       
968       separator = gtk_hseparator_new ();
969       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
970
971       box2 = gtk_vbox_new (FALSE, 10);
972       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
973       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
974
975       button = gtk_button_new_with_label ("close");
976       g_signal_connect_swapped (button, "clicked",
977                                 G_CALLBACK (gtk_widget_destroy),
978                                 window);
979       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
980       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
981       gtk_widget_grab_default (button);
982     }
983
984   if (!GTK_WIDGET_VISIBLE (window))
985     gtk_widget_show_all (window);
986   else
987     gtk_widget_destroy (window);
988 }
989
990 static GtkWidget *
991 create_widget_grid (GType widget_type)
992 {
993   GtkWidget *table;
994   GtkWidget *group_widget = NULL;
995   gint i, j;
996   
997   table = gtk_table_new (FALSE, 3, 3);
998   
999   for (i = 0; i < 5; i++)
1000     {
1001       for (j = 0; j < 5; j++)
1002         {
1003           GtkWidget *widget;
1004           char *tmp;
1005           
1006           if (i == 0 && j == 0)
1007             {
1008               widget = NULL;
1009             }
1010           else if (i == 0)
1011             {
1012               tmp = g_strdup_printf ("%d", j);
1013               widget = gtk_label_new (tmp);
1014               g_free (tmp);
1015             }
1016           else if (j == 0)
1017             {
1018               tmp = g_strdup_printf ("%c", 'A' + i - 1);
1019               widget = gtk_label_new (tmp);
1020               g_free (tmp);
1021             }
1022           else
1023             {
1024               widget = g_object_new (widget_type, NULL);
1025               
1026               if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON))
1027                 {
1028                   if (!group_widget)
1029                     group_widget = widget;
1030                   else
1031                     g_object_set (widget, "group", group_widget, NULL);
1032                 }
1033             }
1034           
1035           if (widget)
1036             gtk_table_attach (GTK_TABLE (table), widget,
1037                               i, i + 1, j, j + 1,
1038                               0,        0,
1039                               0,        0);
1040         }
1041     }
1042
1043   return table;
1044 }
1045
1046 /*
1047  * GtkCheckButton
1048  */
1049
1050 static void
1051 create_check_buttons (GtkWidget *widget)
1052 {
1053   static GtkWidget *window = NULL;
1054   GtkWidget *box1;
1055   GtkWidget *box2;
1056   GtkWidget *button;
1057   GtkWidget *separator;
1058   GtkWidget *table;
1059   
1060   if (!window)
1061     {
1062       window = gtk_dialog_new_with_buttons ("Check Buttons",
1063                                             NULL, 0,
1064                                             GTK_STOCK_CLOSE,
1065                                             GTK_RESPONSE_NONE,
1066                                             NULL);
1067
1068       gtk_window_set_screen (GTK_WINDOW (window), 
1069                              gtk_widget_get_screen (widget));
1070
1071       g_signal_connect (window, "destroy",
1072                         G_CALLBACK (gtk_widget_destroyed),
1073                         &window);
1074       g_signal_connect (window, "response",
1075                         G_CALLBACK (gtk_widget_destroy),
1076                         NULL);
1077
1078       box1 = GTK_DIALOG (window)->vbox;
1079       
1080       box2 = gtk_vbox_new (FALSE, 10);
1081       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1082       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1083
1084       button = gtk_check_button_new_with_mnemonic ("_button1");
1085       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1086
1087       button = gtk_check_button_new_with_label ("button2");
1088       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1089
1090       button = gtk_check_button_new_with_label ("button3");
1091       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1092
1093       button = gtk_check_button_new_with_label ("inconsistent");
1094       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1095       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1096
1097       separator = gtk_hseparator_new ();
1098       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1099
1100       table = create_widget_grid (GTK_TYPE_CHECK_BUTTON);
1101       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1102       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1103     }
1104
1105   if (!GTK_WIDGET_VISIBLE (window))
1106     gtk_widget_show_all (window);
1107   else
1108     gtk_widget_destroy (window);
1109 }
1110
1111 /*
1112  * GtkRadioButton
1113  */
1114
1115 static void
1116 create_radio_buttons (GtkWidget *widget)
1117 {
1118   static GtkWidget *window = NULL;
1119   GtkWidget *box1;
1120   GtkWidget *box2;
1121   GtkWidget *button;
1122   GtkWidget *separator;
1123   GtkWidget *table;
1124
1125   if (!window)
1126     {
1127       window = gtk_dialog_new_with_buttons ("Radio Buttons",
1128                                             NULL, 0,
1129                                             GTK_STOCK_CLOSE,
1130                                             GTK_RESPONSE_NONE,
1131                                             NULL);
1132
1133       gtk_window_set_screen (GTK_WINDOW (window),
1134                              gtk_widget_get_screen (widget));
1135
1136       g_signal_connect (window, "destroy",
1137                         G_CALLBACK (gtk_widget_destroyed),
1138                         &window);
1139       g_signal_connect (window, "response",
1140                         G_CALLBACK (gtk_widget_destroy),
1141                         NULL);
1142
1143       box1 = GTK_DIALOG (window)->vbox;
1144
1145       box2 = gtk_vbox_new (FALSE, 10);
1146       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1147       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1148
1149       button = gtk_radio_button_new_with_label (NULL, "button1");
1150       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1151
1152       button = gtk_radio_button_new_with_label (
1153                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1154                  "button2");
1155       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1156       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1157
1158       button = gtk_radio_button_new_with_label (
1159                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1160                  "button3");
1161       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1162
1163       button = gtk_radio_button_new_with_label (
1164                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1165                  "inconsistent");
1166       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1167       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1168       
1169       separator = gtk_hseparator_new ();
1170       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1171
1172       box2 = gtk_vbox_new (FALSE, 10);
1173       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1174       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1175
1176       button = gtk_radio_button_new_with_label (NULL, "button4");
1177       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1178       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1179
1180       button = gtk_radio_button_new_with_label (
1181                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1182                  "button5");
1183       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1184       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1185       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1186
1187       button = gtk_radio_button_new_with_label (
1188                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1189                  "button6");
1190       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1191       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1192
1193       separator = gtk_hseparator_new ();
1194       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1195
1196       table = create_widget_grid (GTK_TYPE_RADIO_BUTTON);
1197       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1198       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1199     }
1200
1201   if (!GTK_WIDGET_VISIBLE (window))
1202     gtk_widget_show_all (window);
1203   else
1204     gtk_widget_destroy (window);
1205 }
1206
1207 /*
1208  * GtkButtonBox
1209  */
1210
1211 static GtkWidget *
1212 create_bbox (gint  horizontal,
1213              char* title, 
1214              gint  spacing,
1215              gint  child_w,
1216              gint  child_h,
1217              gint  layout)
1218 {
1219   GtkWidget *frame;
1220   GtkWidget *bbox;
1221   GtkWidget *button;
1222         
1223   frame = gtk_frame_new (title);
1224
1225   if (horizontal)
1226     bbox = gtk_hbutton_box_new ();
1227   else
1228     bbox = gtk_vbutton_box_new ();
1229
1230   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
1231   gtk_container_add (GTK_CONTAINER (frame), bbox);
1232
1233   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
1234   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
1235   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
1236   
1237   button = gtk_button_new_with_label ("OK");
1238   gtk_container_add (GTK_CONTAINER (bbox), button);
1239   
1240   button = gtk_button_new_with_label ("Cancel");
1241   gtk_container_add (GTK_CONTAINER (bbox), button);
1242   
1243   button = gtk_button_new_with_label ("Help");
1244   gtk_container_add (GTK_CONTAINER (bbox), button);
1245
1246   return frame;
1247 }
1248
1249 static void
1250 create_button_box (GtkWidget *widget)
1251 {
1252   static GtkWidget* window = NULL;
1253   GtkWidget *main_vbox;
1254   GtkWidget *vbox;
1255   GtkWidget *hbox;
1256   GtkWidget *frame_horz;
1257   GtkWidget *frame_vert;
1258
1259   if (!window)
1260   {
1261     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1262     gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (widget));
1263     gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
1264     
1265     g_signal_connect (window, "destroy",
1266                       G_CALLBACK (gtk_widget_destroyed),
1267                       &window);
1268
1269     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1270
1271     main_vbox = gtk_vbox_new (FALSE, 0);
1272     gtk_container_add (GTK_CONTAINER (window), main_vbox);
1273     
1274     frame_horz = gtk_frame_new ("Horizontal Button Boxes");
1275     gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
1276     
1277     vbox = gtk_vbox_new (FALSE, 0);
1278     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1279     gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
1280     
1281     gtk_box_pack_start (GTK_BOX (vbox), 
1282                         create_bbox (TRUE, "Spread", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
1283                         TRUE, TRUE, 0);
1284     
1285     gtk_box_pack_start (GTK_BOX (vbox), 
1286                         create_bbox (TRUE, "Edge", 40, 85, 20, GTK_BUTTONBOX_EDGE),
1287                         TRUE, TRUE, 5);
1288     
1289     gtk_box_pack_start (GTK_BOX (vbox), 
1290                         create_bbox (TRUE, "Start", 40, 85, 20, GTK_BUTTONBOX_START),
1291                         TRUE, TRUE, 5);
1292     
1293     gtk_box_pack_start (GTK_BOX (vbox), 
1294                         create_bbox (TRUE, "End", 40, 85, 20, GTK_BUTTONBOX_END),
1295                         TRUE, TRUE, 5);
1296     
1297     gtk_box_pack_start (GTK_BOX (vbox),
1298                         create_bbox (TRUE, "Center", 40, 85, 20, GTK_BUTTONBOX_CENTER),
1299                         TRUE, TRUE, 5);
1300     
1301     frame_vert = gtk_frame_new ("Vertical Button Boxes");
1302     gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
1303     
1304     hbox = gtk_hbox_new (FALSE, 0);
1305     gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
1306     gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
1307
1308     gtk_box_pack_start (GTK_BOX (hbox), 
1309                         create_bbox (FALSE, "Spread", 30, 85, 20, GTK_BUTTONBOX_SPREAD),
1310                         TRUE, TRUE, 0);
1311     
1312     gtk_box_pack_start (GTK_BOX (hbox), 
1313                         create_bbox (FALSE, "Edge", 30, 85, 20, GTK_BUTTONBOX_EDGE),
1314                         TRUE, TRUE, 5);
1315     
1316     gtk_box_pack_start (GTK_BOX (hbox), 
1317                         create_bbox (FALSE, "Start", 30, 85, 20, GTK_BUTTONBOX_START),
1318                         TRUE, TRUE, 5);
1319     
1320     gtk_box_pack_start (GTK_BOX (hbox), 
1321                         create_bbox (FALSE, "End", 30, 85, 20, GTK_BUTTONBOX_END),
1322                         TRUE, TRUE, 5);
1323     
1324     gtk_box_pack_start (GTK_BOX (hbox),
1325                         create_bbox (FALSE, "Center", 30, 85, 20, GTK_BUTTONBOX_CENTER),
1326                         TRUE, TRUE, 5);
1327   }
1328
1329   if (!GTK_WIDGET_VISIBLE (window))
1330     gtk_widget_show_all (window);
1331   else
1332     gtk_widget_destroy (window);
1333 }
1334
1335 /*
1336  * GtkToolBar
1337  */
1338
1339 static GtkWidget*
1340 new_pixmap (char      *filename,
1341             GdkWindow *window,
1342             GdkColor  *background)
1343 {
1344   GtkWidget *wpixmap;
1345   GdkPixmap *pixmap;
1346   GdkBitmap *mask;
1347
1348   if (strcmp (filename, "test.xpm") == 0 ||
1349       !file_exists (filename))
1350     {
1351       pixmap = gdk_pixmap_create_from_xpm_d (window, &mask,
1352                                              background,
1353                                              openfile);
1354     }
1355   else
1356     pixmap = gdk_pixmap_create_from_xpm (window, &mask,
1357                                          background,
1358                                          filename);
1359   
1360   wpixmap = gtk_image_new_from_pixmap (pixmap, mask);
1361
1362   return wpixmap;
1363 }
1364
1365
1366 static void
1367 set_toolbar_small_stock (GtkWidget *widget,
1368                          gpointer   data)
1369 {
1370   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_SMALL_TOOLBAR);
1371 }
1372
1373 static void
1374 set_toolbar_large_stock (GtkWidget *widget,
1375                          gpointer   data)
1376 {
1377   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_LARGE_TOOLBAR);
1378 }
1379
1380 static void
1381 set_toolbar_horizontal (GtkWidget *widget,
1382                         gpointer   data)
1383 {
1384   gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_HORIZONTAL);
1385 }
1386
1387 static void
1388 set_toolbar_vertical (GtkWidget *widget,
1389                       gpointer   data)
1390 {
1391   gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_VERTICAL);
1392 }
1393
1394 static void
1395 set_toolbar_icons (GtkWidget *widget,
1396                    gpointer   data)
1397 {
1398   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
1399 }
1400
1401 static void
1402 set_toolbar_text (GtkWidget *widget,
1403                   gpointer   data)
1404 {
1405   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
1406 }
1407
1408 static void
1409 set_toolbar_both (GtkWidget *widget,
1410                   gpointer   data)
1411 {
1412   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
1413 }
1414
1415 static void
1416 set_toolbar_both_horiz (GtkWidget *widget,
1417                         gpointer   data)
1418 {
1419   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH_HORIZ);
1420 }
1421
1422 static void
1423 set_toolbar_enable (GtkWidget *widget,
1424                     gpointer   data)
1425 {
1426   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), TRUE);
1427 }
1428
1429 static void
1430 set_toolbar_disable (GtkWidget *widget,
1431                      gpointer   data)
1432 {
1433   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), FALSE);
1434 }
1435
1436 static void
1437 create_toolbar (GtkWidget *widget)
1438 {
1439   static GtkWidget *window = NULL;
1440   GtkWidget *toolbar;
1441   GtkWidget *entry;
1442
1443   if (!window)
1444     {
1445       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1446       gtk_window_set_screen (GTK_WINDOW (window),
1447                              gtk_widget_get_screen (widget));
1448       
1449       gtk_window_set_title (GTK_WINDOW (window), "Toolbar test");
1450
1451       g_signal_connect (window, "destroy",
1452                         G_CALLBACK (gtk_widget_destroyed),
1453                         &window);
1454
1455       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1456       gtk_widget_realize (window);
1457
1458       toolbar = gtk_toolbar_new ();
1459
1460       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
1461                                 GTK_STOCK_NEW,
1462                                 "Stock icon: New", "Toolbar/New",
1463                                 G_CALLBACK (set_toolbar_small_stock), toolbar, -1);
1464       
1465       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
1466                                 GTK_STOCK_OPEN,
1467                                 "Stock icon: Open", "Toolbar/Open",
1468                                 G_CALLBACK (set_toolbar_large_stock), toolbar, -1);
1469       
1470       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1471                                "Horizontal", "Horizontal toolbar layout", "Toolbar/Horizontal",
1472                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1473                                G_CALLBACK (set_toolbar_horizontal), toolbar);
1474       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1475                                "Vertical", "Vertical toolbar layout", "Toolbar/Vertical",
1476                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1477                                G_CALLBACK (set_toolbar_vertical), toolbar);
1478
1479       gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
1480
1481       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1482                                "Icons", "Only show toolbar icons", "Toolbar/IconsOnly",
1483                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1484                                G_CALLBACK (set_toolbar_icons), toolbar);
1485       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1486                                "Text", "Only show toolbar text", "Toolbar/TextOnly",
1487                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1488                                G_CALLBACK (set_toolbar_text), toolbar);
1489       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1490                                "Both", "Show toolbar icons and text", "Toolbar/Both",
1491                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1492                                G_CALLBACK (set_toolbar_both), toolbar);
1493       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1494                                "Both (horizontal)",
1495                                "Show toolbar icons and text in a horizontal fashion",
1496                                "Toolbar/BothHoriz",
1497                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1498                                G_CALLBACK (set_toolbar_both_horiz), toolbar);
1499                                
1500       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1501
1502       entry = gtk_entry_new ();
1503
1504       gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), entry, "This is an unusable GtkEntry ;)", "Hey don't click me!!!");
1505
1506       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1507
1508
1509       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1510
1511       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1512                                "Enable", "Enable tooltips", NULL,
1513                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1514                                G_CALLBACK (set_toolbar_enable), toolbar);
1515       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1516                                "Disable", "Disable tooltips", NULL,
1517                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1518                                G_CALLBACK (set_toolbar_disable), toolbar);
1519
1520       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1521
1522       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1523                                "Frobate", "Frobate tooltip", NULL,
1524                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1525                                NULL, toolbar);
1526       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1527                                "Baz", "Baz tooltip", NULL,
1528                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1529                                NULL, toolbar);
1530
1531       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1532       
1533       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1534                                "Blah", "Blah tooltip", NULL,
1535                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1536                                NULL, toolbar);
1537       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1538                                "Bar", "Bar tooltip", NULL,
1539                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1540                                NULL, toolbar);
1541
1542       gtk_container_add (GTK_CONTAINER (window), toolbar);
1543
1544       gtk_widget_set_size_request (toolbar, 200, -1);
1545     }
1546
1547   if (!GTK_WIDGET_VISIBLE (window))
1548     gtk_widget_show_all (window);
1549   else
1550     gtk_widget_destroy (window);
1551 }
1552
1553 static GtkWidget*
1554 make_toolbar (GtkWidget *window)
1555 {
1556   GtkWidget *toolbar;
1557
1558   if (!GTK_WIDGET_REALIZED (window))
1559     gtk_widget_realize (window);
1560
1561   toolbar = gtk_toolbar_new ();
1562
1563   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1564                            "Horizontal", "Horizontal toolbar layout", NULL,
1565                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1566                            G_CALLBACK (set_toolbar_horizontal), toolbar);
1567   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1568                            "Vertical", "Vertical toolbar layout", NULL,
1569                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1570                            G_CALLBACK (set_toolbar_vertical), toolbar);
1571
1572   gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
1573
1574   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1575                            "Icons", "Only show toolbar icons", NULL,
1576                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1577                            G_CALLBACK (set_toolbar_icons), toolbar);
1578   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1579                            "Text", "Only show toolbar text", NULL,
1580                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1581                            G_CALLBACK (set_toolbar_text), toolbar);
1582   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1583                            "Both", "Show toolbar icons and text", NULL,
1584                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1585                            G_CALLBACK (set_toolbar_both), toolbar);
1586
1587   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1588
1589   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1590                            "Woot", "Woot woot woot", NULL,
1591                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1592                            NULL, toolbar);
1593   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1594                            "Blah", "Blah blah blah", "Toolbar/Big",
1595                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1596                            NULL, toolbar);
1597
1598   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1599
1600   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1601                            "Enable", "Enable tooltips", NULL,
1602                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1603                            G_CALLBACK (set_toolbar_enable), toolbar);
1604   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1605                            "Disable", "Disable tooltips", NULL,
1606                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1607                            G_CALLBACK (set_toolbar_disable), toolbar);
1608
1609   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1610   
1611   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1612                            "Hoo", "Hoo tooltip", NULL,
1613                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1614                            NULL, toolbar);
1615   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1616                            "Woo", "Woo tooltip", NULL,
1617                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1618                            NULL, toolbar);
1619
1620   return toolbar;
1621 }
1622
1623 /*
1624  * GtkStatusBar
1625  */
1626
1627 static guint statusbar_counter = 1;
1628
1629 static void
1630 statusbar_push (GtkWidget *button,
1631                 GtkStatusbar *statusbar)
1632 {
1633   gchar text[1024];
1634
1635   sprintf (text, "something %d", statusbar_counter++);
1636
1637   gtk_statusbar_push (statusbar, 1, text);
1638 }
1639
1640 static void
1641 statusbar_push_long (GtkWidget *button,
1642                      GtkStatusbar *statusbar)
1643 {
1644   gchar text[1024];
1645
1646   sprintf (text, "Just because a system has menu choices written with English words, phrases or sentences, that is no guarantee, that it is comprehensible. Individual words may not be familiar to some users (for example, \"repaginate\"), and two menu items may appear to satisfy the users's needs, whereas only one does (for example, \"put away\" or \"eject\").");
1647
1648   gtk_statusbar_push (statusbar, 1, text);
1649 }
1650
1651 static void
1652 statusbar_pop (GtkWidget *button,
1653                GtkStatusbar *statusbar)
1654 {
1655   gtk_statusbar_pop (statusbar, 1);
1656 }
1657
1658 static void
1659 statusbar_steal (GtkWidget *button,
1660                  GtkStatusbar *statusbar)
1661 {
1662   gtk_statusbar_remove (statusbar, 1, 4);
1663 }
1664
1665 static void
1666 statusbar_popped (GtkStatusbar  *statusbar,
1667                   guint          context_id,
1668                   const gchar   *text)
1669 {
1670   if (!statusbar->messages)
1671     statusbar_counter = 1;
1672 }
1673
1674 static void
1675 statusbar_contexts (GtkStatusbar *statusbar)
1676 {
1677   gchar *string;
1678
1679   string = "any context";
1680   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1681            string,
1682            gtk_statusbar_get_context_id (statusbar, string));
1683   
1684   string = "idle messages";
1685   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1686            string,
1687            gtk_statusbar_get_context_id (statusbar, string));
1688   
1689   string = "some text";
1690   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1691            string,
1692            gtk_statusbar_get_context_id (statusbar, string));
1693
1694   string = "hit the mouse";
1695   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1696            string,
1697            gtk_statusbar_get_context_id (statusbar, string));
1698
1699   string = "hit the mouse2";
1700   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1701            string,
1702            gtk_statusbar_get_context_id (statusbar, string));
1703 }
1704
1705 static void
1706 create_statusbar (GtkWidget *widget)
1707 {
1708   static GtkWidget *window = NULL;
1709   GtkWidget *box1;
1710   GtkWidget *box2;
1711   GtkWidget *button;
1712   GtkWidget *separator;
1713   GtkWidget *statusbar;
1714
1715   if (!window)
1716     {
1717       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1718       gtk_window_set_screen (GTK_WINDOW (window),
1719                              gtk_widget_get_screen (widget));
1720
1721       g_signal_connect (window, "destroy",
1722                         G_CALLBACK (gtk_widget_destroyed),
1723                         &window);
1724
1725       gtk_window_set_title (GTK_WINDOW (window), "statusbar");
1726       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1727
1728       box1 = gtk_vbox_new (FALSE, 0);
1729       gtk_container_add (GTK_CONTAINER (window), box1);
1730
1731       box2 = gtk_vbox_new (FALSE, 10);
1732       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1733       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1734
1735       statusbar = gtk_statusbar_new ();
1736       gtk_box_pack_end (GTK_BOX (box1), statusbar, TRUE, TRUE, 0);
1737       g_signal_connect (statusbar,
1738                         "text_popped",
1739                         G_CALLBACK (statusbar_popped),
1740                         NULL);
1741
1742       button = g_object_new (gtk_button_get_type (),
1743                                "label", "push something",
1744                                "visible", TRUE,
1745                                "parent", box2,
1746                                NULL);
1747       g_object_connect (button,
1748                         "signal::clicked", statusbar_push, statusbar,
1749                         NULL);
1750
1751       button = g_object_connect (g_object_new (gtk_button_get_type (),
1752                                                  "label", "pop",
1753                                                  "visible", TRUE,
1754                                                  "parent", box2,
1755                                                  NULL),
1756                                  "signal_after::clicked", statusbar_pop, statusbar,
1757                                  NULL);
1758
1759       button = g_object_connect (g_object_new (gtk_button_get_type (),
1760                                                  "label", "steal #4",
1761                                                  "visible", TRUE,
1762                                                  "parent", box2,
1763                                                  NULL),
1764                                  "signal_after::clicked", statusbar_steal, statusbar,
1765                                  NULL);
1766
1767       button = g_object_connect (g_object_new (gtk_button_get_type (),
1768                                                  "label", "test contexts",
1769                                                  "visible", TRUE,
1770                                                  "parent", box2,
1771                                                  NULL),
1772                                  "swapped_signal_after::clicked", statusbar_contexts, statusbar,
1773                                  NULL);
1774
1775       button = g_object_connect (g_object_new (gtk_button_get_type (),
1776                                                  "label", "push something long",
1777                                                  "visible", TRUE,
1778                                                  "parent", box2,
1779                                                  NULL),
1780                                  "signal_after::clicked", statusbar_push_long, statusbar,
1781                                  NULL);
1782       
1783       separator = gtk_hseparator_new ();
1784       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1785
1786       box2 = gtk_vbox_new (FALSE, 10);
1787       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1788       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
1789
1790       button = gtk_button_new_with_label ("close");
1791       g_signal_connect_swapped (button, "clicked",
1792                                 G_CALLBACK (gtk_widget_destroy),
1793                                 window);
1794       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1795       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1796       gtk_widget_grab_default (button);
1797     }
1798
1799   if (!GTK_WIDGET_VISIBLE (window))
1800     gtk_widget_show_all (window);
1801   else
1802     gtk_widget_destroy (window);
1803 }
1804
1805 /*
1806  * GtkTree
1807  */
1808
1809 static void
1810 cb_tree_destroy_event(GtkWidget* w)
1811 {
1812   sTreeButtons* tree_buttons;
1813
1814   /* free buttons structure associate at this tree */
1815   tree_buttons = g_object_get_data (G_OBJECT (w), "user_data");
1816   g_free (tree_buttons);
1817 }
1818
1819 static void
1820 cb_add_new_item(GtkWidget* w, GtkTree* tree)
1821 {
1822   sTreeButtons* tree_buttons;
1823   GList* selected_list;
1824   GtkWidget* selected_item;
1825   GtkWidget* subtree;
1826   GtkWidget* item_new;
1827   char buffer[255];
1828
1829   tree_buttons = g_object_get_data (G_OBJECT (tree), "user_data");
1830
1831   selected_list = GTK_TREE_SELECTION_OLD(tree);
1832
1833   if(selected_list == NULL)
1834     {
1835       /* there is no item in tree */
1836       subtree = GTK_WIDGET(tree);
1837     }
1838   else
1839     {
1840       /* list can have only one element */
1841       selected_item = GTK_WIDGET(selected_list->data);
1842       
1843       subtree = GTK_TREE_ITEM_SUBTREE(selected_item);
1844
1845       if(subtree == NULL)
1846         {
1847           /* current selected item have not subtree ... create it */
1848           subtree = gtk_tree_new();
1849           gtk_tree_item_set_subtree(GTK_TREE_ITEM(selected_item), 
1850                                     subtree);
1851         }
1852     }
1853
1854   /* at this point, we know which subtree will be used to add new item */
1855   /* create a new item */
1856   sprintf(buffer, "item add %d", tree_buttons->nb_item_add);
1857   item_new = gtk_tree_item_new_with_label(buffer);
1858   gtk_tree_append(GTK_TREE(subtree), item_new);
1859   gtk_widget_show(item_new);
1860
1861   tree_buttons->nb_item_add++;
1862 }
1863
1864 static void
1865 cb_remove_item(GtkWidget*w, GtkTree* tree)
1866 {
1867   GList* selected_list;
1868   GList* clear_list;
1869   
1870   selected_list = GTK_TREE_SELECTION_OLD(tree);
1871
1872   clear_list = NULL;
1873     
1874   while (selected_list) 
1875     {
1876       clear_list = g_list_prepend (clear_list, selected_list->data);
1877       selected_list = selected_list->next;
1878     }
1879   
1880   clear_list = g_list_reverse (clear_list);
1881   gtk_tree_remove_items(tree, clear_list);
1882
1883   g_list_free (clear_list);
1884 }
1885
1886 static void
1887 cb_remove_subtree(GtkWidget*w, GtkTree* tree)
1888 {
1889   GList* selected_list;
1890   GtkTreeItem *item;
1891   
1892   selected_list = GTK_TREE_SELECTION_OLD(tree);
1893
1894   if (selected_list)
1895     {
1896       item = GTK_TREE_ITEM (selected_list->data);
1897       if (item->subtree)
1898         gtk_tree_item_remove_subtree (item);
1899     }
1900 }
1901
1902 static void
1903 cb_tree_changed(GtkTree* tree)
1904 {
1905   sTreeButtons* tree_buttons;
1906   GList* selected_list;
1907   guint nb_selected;
1908
1909   tree_buttons = g_object_get_data (G_OBJECT (tree), "user_data");
1910
1911   selected_list = GTK_TREE_SELECTION_OLD(tree);
1912   nb_selected = g_list_length(selected_list);
1913
1914   if(nb_selected == 0) 
1915     {
1916       if(tree->children == NULL)
1917         gtk_widget_set_sensitive(tree_buttons->add_button, TRUE);
1918       else
1919         gtk_widget_set_sensitive(tree_buttons->add_button, FALSE);
1920       gtk_widget_set_sensitive(tree_buttons->remove_button, FALSE);
1921       gtk_widget_set_sensitive(tree_buttons->subtree_button, FALSE);
1922     } 
1923   else 
1924     {
1925       gtk_widget_set_sensitive(tree_buttons->remove_button, TRUE);
1926       gtk_widget_set_sensitive(tree_buttons->add_button, (nb_selected == 1));
1927       gtk_widget_set_sensitive(tree_buttons->subtree_button, (nb_selected == 1));
1928     }  
1929 }
1930
1931 static void 
1932 create_subtree(GtkWidget* item, guint level, guint nb_item_max, guint recursion_level_max)
1933 {
1934   GtkWidget* item_subtree;
1935   GtkWidget* item_new;
1936   guint nb_item;
1937   char buffer[255];
1938   int no_root_item;
1939
1940   if(level == recursion_level_max) return;
1941
1942   if(level == -1)
1943     {
1944       /* query with no root item */
1945       level = 0;
1946       item_subtree = item;
1947       no_root_item = 1;
1948     }
1949   else
1950     {
1951       /* query with no root item */
1952       /* create subtree and associate it with current item */
1953       item_subtree = gtk_tree_new();
1954       no_root_item = 0;
1955     }
1956   
1957   for(nb_item = 0; nb_item < nb_item_max; nb_item++)
1958     {
1959       sprintf(buffer, "item %d-%d", level, nb_item);
1960       item_new = gtk_tree_item_new_with_label(buffer);
1961       gtk_tree_append(GTK_TREE(item_subtree), item_new);
1962       create_subtree(item_new, level+1, nb_item_max, recursion_level_max);
1963       gtk_widget_show(item_new);
1964     }
1965
1966   if(!no_root_item)
1967     gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), item_subtree);
1968 }
1969
1970 static void
1971 create_tree_sample(GdkScreen *screen, guint selection_mode, 
1972                    guint draw_line, guint view_line, guint no_root_item,
1973                    guint nb_item_max, guint recursion_level_max) 
1974 {
1975   GtkWidget* window;
1976   GtkWidget* box1;
1977   GtkWidget* box2;
1978   GtkWidget* separator;
1979   GtkWidget* button;
1980   GtkWidget* scrolled_win;
1981   GtkWidget* root_tree;
1982   GtkWidget* root_item;
1983   sTreeButtons* tree_buttons;
1984
1985   /* create tree buttons struct */
1986   if ((tree_buttons = g_malloc (sizeof (sTreeButtons))) == NULL)
1987     {
1988       g_error("can't allocate memory for tree structure !\n");
1989       return;
1990     }
1991   tree_buttons->nb_item_add = 0;
1992
1993   /* create top level window */
1994   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1995   gtk_window_set_screen (GTK_WINDOW (window), screen);
1996   gtk_window_set_title(GTK_WINDOW(window), "Tree Sample");
1997   g_signal_connect (window, "destroy",
1998                     G_CALLBACK (cb_tree_destroy_event), NULL);
1999   g_object_set_data (G_OBJECT (window), "user_data", tree_buttons);
2000
2001   box1 = gtk_vbox_new(FALSE, 0);
2002   gtk_container_add(GTK_CONTAINER(window), box1);
2003   gtk_widget_show(box1);
2004
2005   /* create tree box */
2006   box2 = gtk_vbox_new(FALSE, 0);
2007   gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 0);
2008   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2009   gtk_widget_show(box2);
2010
2011   /* create scrolled window */
2012   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
2013   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
2014                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2015   gtk_box_pack_start (GTK_BOX (box2), scrolled_win, TRUE, TRUE, 0);
2016   gtk_widget_set_size_request (scrolled_win, 200, 200);
2017   gtk_widget_show (scrolled_win);
2018   
2019   /* create root tree widget */
2020   root_tree = gtk_tree_new();
2021   g_signal_connect (root_tree, "selection_changed",
2022                     G_CALLBACK (cb_tree_changed),
2023                     NULL);
2024   g_object_set_data (G_OBJECT (root_tree), "user_data", tree_buttons);
2025   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), root_tree);
2026   gtk_tree_set_selection_mode(GTK_TREE(root_tree), selection_mode);
2027   gtk_tree_set_view_lines(GTK_TREE(root_tree), draw_line);
2028   gtk_tree_set_view_mode(GTK_TREE(root_tree), !view_line);
2029   gtk_widget_show(root_tree);
2030
2031   if ( no_root_item )
2032     {
2033       /* set root tree to subtree function with root item variable */
2034       root_item = GTK_WIDGET(root_tree);
2035     }
2036   else
2037     {
2038       /* create root tree item widget */
2039       root_item = gtk_tree_item_new_with_label("root item");
2040       gtk_tree_append(GTK_TREE(root_tree), root_item);
2041       gtk_widget_show(root_item);
2042      }
2043   create_subtree(root_item, -no_root_item, nb_item_max, recursion_level_max);
2044
2045   box2 = gtk_vbox_new(FALSE, 0);
2046   gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2047   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2048   gtk_widget_show(box2);
2049
2050   button = gtk_button_new_with_label("Add Item");
2051   gtk_widget_set_sensitive(button, FALSE);
2052   g_signal_connect (button, "clicked",
2053                     G_CALLBACK (cb_add_new_item),
2054                     root_tree);
2055   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2056   gtk_widget_show(button);
2057   tree_buttons->add_button = button;
2058
2059   button = gtk_button_new_with_label("Remove Item(s)");
2060   gtk_widget_set_sensitive(button, FALSE);
2061   g_signal_connect (button, "clicked",
2062                     G_CALLBACK (cb_remove_item),
2063                     root_tree);
2064   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2065   gtk_widget_show(button);
2066   tree_buttons->remove_button = button;
2067
2068   button = gtk_button_new_with_label("Remove Subtree");
2069   gtk_widget_set_sensitive(button, FALSE);
2070   g_signal_connect (button, "clicked",
2071                     G_CALLBACK (cb_remove_subtree),
2072                     root_tree);
2073   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2074   gtk_widget_show(button);
2075   tree_buttons->subtree_button = button;
2076
2077   /* create separator */
2078   separator = gtk_hseparator_new();
2079   gtk_box_pack_start(GTK_BOX(box1), separator, FALSE, FALSE, 0);
2080   gtk_widget_show(separator);
2081
2082   /* create button box */
2083   box2 = gtk_vbox_new(FALSE, 0);
2084   gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2085   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2086   gtk_widget_show(box2);
2087
2088   button = gtk_button_new_with_label("Close");
2089   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2090   g_signal_connect_swapped (button, "clicked",
2091                             G_CALLBACK (gtk_widget_destroy),
2092                             window);
2093   gtk_widget_show(button);
2094
2095   gtk_widget_show(window);
2096 }
2097
2098 static void
2099 cb_create_tree(GtkWidget* w)
2100 {
2101   guint selection_mode = GTK_SELECTION_SINGLE;
2102   guint view_line;
2103   guint draw_line;
2104   guint no_root_item;
2105   guint nb_item;
2106   guint recursion_level;
2107
2108   /* get selection mode choice */
2109   if(GTK_TOGGLE_BUTTON(sTreeSampleSelection.single_button)->active)
2110     selection_mode = GTK_SELECTION_SINGLE;
2111   else
2112     if(GTK_TOGGLE_BUTTON(sTreeSampleSelection.browse_button)->active)
2113       selection_mode = GTK_SELECTION_BROWSE;
2114     else
2115       selection_mode = GTK_SELECTION_MULTIPLE;
2116
2117   /* get options choice */
2118   draw_line = GTK_TOGGLE_BUTTON(sTreeSampleSelection.draw_line_button)->active;
2119   view_line = GTK_TOGGLE_BUTTON(sTreeSampleSelection.view_line_button)->active;
2120   no_root_item = GTK_TOGGLE_BUTTON(sTreeSampleSelection.no_root_item_button)->active;
2121     
2122   /* get levels */
2123   nb_item = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sTreeSampleSelection.nb_item_spinner));
2124   recursion_level = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sTreeSampleSelection.recursion_spinner));
2125
2126   if (pow (nb_item, recursion_level) > 10000)
2127     {
2128       g_print ("%g total items? That will take a very long time. Try less\n",
2129                pow (nb_item, recursion_level));
2130       return;
2131     }
2132
2133   create_tree_sample(gtk_widget_get_screen (w),
2134                      selection_mode, draw_line, 
2135                      view_line, no_root_item, nb_item, recursion_level);
2136 }
2137
2138 void 
2139 create_tree_mode_window(GtkWidget *widget)
2140 {
2141   static GtkWidget* window;
2142   GtkWidget* box1;
2143   GtkWidget* box2;
2144   GtkWidget* box3;
2145   GtkWidget* box4;
2146   GtkWidget* box5;
2147   GtkWidget* button;
2148   GtkWidget* frame;
2149   GtkWidget* separator;
2150   GtkWidget* label;
2151   GtkWidget* spinner;
2152   GtkAdjustment *adj;
2153
2154   if (!window)
2155     {
2156       /* create toplevel window  */
2157       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2158       gtk_window_set_screen (GTK_WINDOW (window),
2159                              gtk_widget_get_screen (widget));
2160       gtk_window_set_title(GTK_WINDOW(window), "Set Tree Parameters");
2161       g_signal_connect (window, "destroy",
2162                         G_CALLBACK (gtk_widget_destroyed),
2163                         &window);
2164       box1 = gtk_vbox_new(FALSE, 0);
2165       gtk_container_add(GTK_CONTAINER(window), box1);
2166
2167       /* create upper box - selection box */
2168       box2 = gtk_vbox_new(FALSE, 5);
2169       gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 0);
2170       gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2171
2172       box3 = gtk_hbox_new(FALSE, 5);
2173       gtk_box_pack_start(GTK_BOX(box2), box3, TRUE, TRUE, 0);
2174
2175       /* create selection mode frame */
2176       frame = gtk_frame_new("Selection Mode");
2177       gtk_box_pack_start(GTK_BOX(box3), frame, TRUE, TRUE, 0);
2178
2179       box4 = gtk_vbox_new(FALSE, 0);
2180       gtk_container_add(GTK_CONTAINER(frame), box4);
2181       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2182
2183       /* create radio button */  
2184       button = gtk_radio_button_new_with_label(NULL, "SINGLE");
2185       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2186       sTreeSampleSelection.single_button = button;
2187
2188       button = gtk_radio_button_new_with_label(gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
2189                                                "BROWSE");
2190       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2191       sTreeSampleSelection.browse_button = button;
2192
2193       button = gtk_radio_button_new_with_label(gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
2194                                                "MULTIPLE");
2195       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2196       sTreeSampleSelection.multiple_button = button;
2197
2198       sTreeSampleSelection.selection_mode_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
2199
2200       /* create option mode frame */
2201       frame = gtk_frame_new("Options");
2202       gtk_box_pack_start(GTK_BOX(box3), frame, TRUE, TRUE, 0);
2203
2204       box4 = gtk_vbox_new(FALSE, 0);
2205       gtk_container_add(GTK_CONTAINER(frame), box4);
2206       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2207
2208       /* create check button */
2209       button = gtk_check_button_new_with_label("Draw line");
2210       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2211       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
2212       sTreeSampleSelection.draw_line_button = button;
2213   
2214       button = gtk_check_button_new_with_label("View Line mode");
2215       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2216       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
2217       sTreeSampleSelection.view_line_button = button;
2218   
2219       button = gtk_check_button_new_with_label("Without Root item");
2220       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2221       sTreeSampleSelection.no_root_item_button = button;
2222
2223       /* create recursion parameter */
2224       frame = gtk_frame_new("Size Parameters");
2225       gtk_box_pack_start(GTK_BOX(box2), frame, TRUE, TRUE, 0);
2226
2227       box4 = gtk_hbox_new(FALSE, 5);
2228       gtk_container_add(GTK_CONTAINER(frame), box4);
2229       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2230
2231       /* create number of item spin button */
2232       box5 = gtk_hbox_new(FALSE, 5);
2233       gtk_box_pack_start(GTK_BOX(box4), box5, FALSE, FALSE, 0);
2234
2235       label = gtk_label_new("Number of items : ");
2236       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2237       gtk_box_pack_start (GTK_BOX (box5), label, FALSE, TRUE, 0);
2238
2239       adj = (GtkAdjustment *) gtk_adjustment_new (DEFAULT_NUMBER_OF_ITEM, 1.0, 255.0, 1.0,
2240                                                   5.0, 0.0);
2241       spinner = gtk_spin_button_new (adj, 0, 0);
2242       gtk_box_pack_start (GTK_BOX (box5), spinner, FALSE, TRUE, 0);
2243       sTreeSampleSelection.nb_item_spinner = spinner;
2244   
2245       /* create recursion level spin button */
2246       box5 = gtk_hbox_new(FALSE, 5);
2247       gtk_box_pack_start(GTK_BOX(box4), box5, FALSE, FALSE, 0);
2248
2249       label = gtk_label_new("Depth : ");
2250       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2251       gtk_box_pack_start (GTK_BOX (box5), label, FALSE, TRUE, 0);
2252
2253       adj = (GtkAdjustment *) gtk_adjustment_new (DEFAULT_RECURSION_LEVEL, 0.0, 255.0, 1.0,
2254                                                   5.0, 0.0);
2255       spinner = gtk_spin_button_new (adj, 0, 0);
2256       gtk_box_pack_start (GTK_BOX (box5), spinner, FALSE, TRUE, 0);
2257       sTreeSampleSelection.recursion_spinner = spinner;
2258   
2259       /* create horizontal separator */
2260       separator = gtk_hseparator_new();
2261       gtk_box_pack_start(GTK_BOX(box1), separator, FALSE, FALSE, 0);
2262
2263       /* create bottom button box */
2264       box2 = gtk_hbox_new(TRUE, 10);
2265       gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2266       gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2267
2268       button = gtk_button_new_with_label("Create Tree");
2269       gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2270       g_signal_connect (button, "clicked",
2271                         G_CALLBACK (cb_create_tree), NULL);
2272
2273       button = gtk_button_new_with_label("Close");
2274       gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2275       g_signal_connect_swapped (button, "clicked",
2276                                 G_CALLBACK (gtk_widget_destroy),
2277                                 window);
2278     }
2279   if (!GTK_WIDGET_VISIBLE (window))
2280     gtk_widget_show_all (window);
2281   else
2282     gtk_widget_destroy (window);
2283 }
2284
2285 /*
2286  * Gridded geometry
2287  */
2288 #define GRID_SIZE 20
2289 #define DEFAULT_GEOMETRY "10x10"
2290
2291 static gboolean
2292 gridded_geometry_expose (GtkWidget      *widget,
2293                          GdkEventExpose *event)
2294 {
2295   int i, j;
2296
2297   gdk_draw_rectangle (widget->window, widget->style->base_gc[widget->state], TRUE,
2298                       0, 0, widget->allocation.width, widget->allocation.height);
2299   
2300   for (i = 0 ; i * GRID_SIZE < widget->allocation.width; i++)
2301     for (j = 0 ; j * GRID_SIZE < widget->allocation.height; j++)
2302       {
2303         if ((i + j) % 2 == 0)
2304           gdk_draw_rectangle (widget->window, widget->style->text_gc[widget->state], TRUE,
2305                               i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
2306       }
2307
2308   return FALSE;
2309 }
2310
2311 static void
2312 gridded_geometry_subresponse (GtkDialog *dialog,
2313                               gint       response_id,
2314                               gchar     *geometry_string)
2315 {
2316   if (response_id == GTK_RESPONSE_NONE)
2317     {
2318       gtk_widget_destroy (GTK_WIDGET (dialog));
2319     }
2320   else
2321     {
2322       if (!gtk_window_parse_geometry (GTK_WINDOW (dialog), geometry_string))
2323         {
2324           g_print ("Can't parse geometry string %s\n", geometry_string);
2325           gtk_window_parse_geometry (GTK_WINDOW (dialog), DEFAULT_GEOMETRY);
2326         }
2327     }
2328 }
2329
2330 static void
2331 gridded_geometry_response (GtkDialog *dialog,
2332                            gint       response_id,
2333                            GtkEntry  *entry)
2334 {
2335   if (response_id == GTK_RESPONSE_NONE)
2336     {
2337       gtk_widget_destroy (GTK_WIDGET (dialog));
2338     }
2339   else
2340     {
2341       gchar *geometry_string = g_strdup (gtk_entry_get_text (entry));
2342       gchar *title = g_strdup_printf ("Gridded window at: %s", geometry_string);
2343       GtkWidget *window;
2344       GtkWidget *drawing_area;
2345       GtkWidget *box;
2346       GdkGeometry geometry;
2347       
2348       window = gtk_dialog_new_with_buttons (title,
2349                                             NULL, 0,
2350                                             "Reset", 1,
2351                                             GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
2352                                             NULL);
2353
2354       gtk_window_set_screen (GTK_WINDOW (window), 
2355                              gtk_widget_get_screen (GTK_WIDGET (dialog)));
2356       g_free (title);
2357       g_signal_connect (window, "response",
2358                         G_CALLBACK (gridded_geometry_subresponse), geometry_string);
2359
2360       box = gtk_vbox_new (FALSE, 0);
2361       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), box, TRUE, TRUE, 0);
2362       
2363       gtk_container_set_border_width (GTK_CONTAINER (box), 7);
2364       
2365       drawing_area = gtk_drawing_area_new ();
2366       g_signal_connect (drawing_area, "expose_event",
2367                         G_CALLBACK (gridded_geometry_expose), NULL);
2368       gtk_box_pack_start (GTK_BOX (box), drawing_area, TRUE, TRUE, 0);
2369
2370       /* Gross hack to work around bug 68668... if we set the size request
2371        * large enough, then  the current
2372        *
2373        *   request_of_window - request_of_geometry_widget
2374        *
2375        * method of getting the base size works more or less works.
2376        */
2377       gtk_widget_set_size_request (drawing_area, 2000, 2000);
2378
2379       geometry.base_width = 0;
2380       geometry.base_height = 0;
2381       geometry.min_width = 2 * GRID_SIZE;
2382       geometry.min_height = 2 * GRID_SIZE;
2383       geometry.width_inc = GRID_SIZE;
2384       geometry.height_inc = GRID_SIZE;
2385
2386       gtk_window_set_geometry_hints (GTK_WINDOW (window), drawing_area,
2387                                      &geometry,
2388                                      GDK_HINT_BASE_SIZE | GDK_HINT_MIN_SIZE | GDK_HINT_RESIZE_INC);
2389
2390       if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry_string))
2391         {
2392           g_print ("Can't parse geometry string %s\n", geometry_string);
2393           gtk_window_parse_geometry (GTK_WINDOW (window), DEFAULT_GEOMETRY);
2394         }
2395
2396       gtk_widget_show_all (window);
2397     }
2398 }
2399
2400 static void 
2401 create_gridded_geometry (GtkWidget *widget)
2402 {
2403   static GtkWidget *window = NULL;
2404   gpointer window_ptr;
2405   GtkWidget *entry;
2406   GtkWidget *label;
2407
2408   if (!window)
2409     {
2410       window = gtk_dialog_new_with_buttons ("Gridded Geometry",
2411                                             NULL, 0,
2412                                             "Create", 1,
2413                                             GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
2414                                             NULL);
2415       
2416       gtk_window_set_screen (GTK_WINDOW (window),
2417                              gtk_widget_get_screen (widget));
2418
2419       label = gtk_label_new ("Geometry string:");
2420       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, FALSE, FALSE, 0);
2421
2422       entry = gtk_entry_new ();
2423       gtk_entry_set_text (GTK_ENTRY (entry), DEFAULT_GEOMETRY);
2424       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), entry, FALSE, FALSE, 0);
2425
2426       g_signal_connect (window, "response",
2427                         G_CALLBACK (gridded_geometry_response), entry);
2428       window_ptr = &window;
2429       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
2430
2431       gtk_widget_show_all (window);
2432     }
2433   else
2434     gtk_widget_destroy (window);
2435 }
2436
2437 /*
2438  * GtkHandleBox
2439  */
2440
2441 static void
2442 handle_box_child_signal (GtkHandleBox *hb,
2443                          GtkWidget    *child,
2444                          const gchar  *action)
2445 {
2446   printf ("%s: child <%s> %sed\n",
2447           g_type_name (G_OBJECT_TYPE (hb)),
2448           g_type_name (G_OBJECT_TYPE (child)),
2449           action);
2450 }
2451
2452 static void
2453 create_handle_box (GtkWidget *widget)
2454 {
2455   static GtkWidget* window = NULL;
2456   GtkWidget *handle_box;
2457   GtkWidget *handle_box2;
2458   GtkWidget *vbox;
2459   GtkWidget *hbox;
2460   GtkWidget *toolbar;
2461   GtkWidget *label;
2462   GtkWidget *separator;
2463
2464   if (!window)
2465   {
2466     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2467     
2468     gtk_window_set_screen (GTK_WINDOW (window),
2469                            gtk_widget_get_screen (widget));
2470     gtk_window_set_modal (GTK_WINDOW (window), FALSE);
2471     gtk_window_set_title (GTK_WINDOW (window),
2472                           "Handle Box Test");
2473     gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
2474     
2475     g_signal_connect (window, "destroy",
2476                       G_CALLBACK (gtk_widget_destroyed),
2477                       &window);
2478     
2479     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
2480
2481     vbox = gtk_vbox_new (FALSE, 0);
2482     gtk_container_add (GTK_CONTAINER (window), vbox);
2483     gtk_widget_show (vbox);
2484
2485     label = gtk_label_new ("Above");
2486     gtk_container_add (GTK_CONTAINER (vbox), label);
2487     gtk_widget_show (label);
2488
2489     separator = gtk_hseparator_new ();
2490     gtk_container_add (GTK_CONTAINER (vbox), separator);
2491     gtk_widget_show (separator);
2492     
2493     hbox = gtk_hbox_new (FALSE, 10);
2494     gtk_container_add (GTK_CONTAINER (vbox), hbox);
2495     gtk_widget_show (hbox);
2496
2497     separator = gtk_hseparator_new ();
2498     gtk_container_add (GTK_CONTAINER (vbox), separator);
2499     gtk_widget_show (separator);
2500
2501     label = gtk_label_new ("Below");
2502     gtk_container_add (GTK_CONTAINER (vbox), label);
2503     gtk_widget_show (label);
2504
2505     handle_box = gtk_handle_box_new ();
2506     gtk_box_pack_start (GTK_BOX (hbox), handle_box, FALSE, FALSE, 0);
2507     g_signal_connect (handle_box,
2508                       "child_attached",
2509                       G_CALLBACK (handle_box_child_signal),
2510                       "attached");
2511     g_signal_connect (handle_box,
2512                       "child_detached",
2513                       G_CALLBACK (handle_box_child_signal),
2514                       "detached");
2515     gtk_widget_show (handle_box);
2516
2517     toolbar = make_toolbar (window);
2518     
2519     gtk_container_add (GTK_CONTAINER (handle_box), toolbar);
2520     gtk_widget_show (toolbar);
2521
2522     handle_box = gtk_handle_box_new ();
2523     gtk_box_pack_start (GTK_BOX (hbox), handle_box, FALSE, FALSE, 0);
2524     g_signal_connect (handle_box,
2525                       "child_attached",
2526                       G_CALLBACK (handle_box_child_signal),
2527                       "attached");
2528     g_signal_connect (handle_box,
2529                       "child_detached",
2530                       G_CALLBACK (handle_box_child_signal),
2531                       "detached");
2532     gtk_widget_show (handle_box);
2533
2534     handle_box2 = gtk_handle_box_new ();
2535     gtk_container_add (GTK_CONTAINER (handle_box), handle_box2);
2536     g_signal_connect (handle_box2,
2537                       "child_attached",
2538                       G_CALLBACK (handle_box_child_signal),
2539                       "attached");
2540     g_signal_connect (handle_box2,
2541                       "child_detached",
2542                       G_CALLBACK (handle_box_child_signal),
2543                       "detached");
2544     gtk_widget_show (handle_box2);
2545
2546     hbox = g_object_new (GTK_TYPE_HBOX, "visible", 1, "parent", handle_box2, NULL);
2547     label = gtk_label_new ("Fooo!");
2548     gtk_container_add (GTK_CONTAINER (hbox), label);
2549     gtk_widget_show (label);
2550     g_object_new (GTK_TYPE_ARROW, "visible", 1, "parent", hbox, NULL);
2551   }
2552
2553   if (!GTK_WIDGET_VISIBLE (window))
2554     gtk_widget_show (window);
2555   else
2556     gtk_widget_destroy (window);
2557 }
2558
2559 /*
2560  * Test for getting an image from a drawable
2561  */
2562
2563 struct GetImageData
2564 {
2565   GtkWidget *src;
2566   GtkWidget *snap;
2567   GtkWidget *sw;
2568 };
2569
2570 static void
2571 take_snapshot (GtkWidget *button,
2572                gpointer data)
2573 {
2574   struct GetImageData *gid = data;
2575   GdkRectangle visible;
2576   int width_fraction;
2577   int height_fraction;
2578   GdkGC *gc;
2579   GdkGC *black_gc;
2580   GdkColor color = { 0, 30000, 0, 0 };
2581   GdkRectangle target;
2582   GdkImage *shot;
2583   
2584   /* Do some begin_paint_rect on some random rects, draw some
2585    * distinctive stuff into those rects, then take the snapshot.
2586    * figure out whether any rects were overlapped and report to
2587    * user.
2588    */
2589
2590   visible = gid->sw->allocation;
2591
2592   visible.x = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (gid->sw))->value;
2593   visible.y = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (gid->sw))->value;
2594   
2595   width_fraction = visible.width / 4;
2596   height_fraction = visible.height / 4;
2597
2598   gc = gdk_gc_new (gid->src->window);
2599   black_gc = gid->src->style->black_gc;
2600   
2601   gdk_gc_set_rgb_fg_color (gc, &color);
2602
2603     
2604   target.x = visible.x + width_fraction;
2605   target.y = visible.y + height_fraction * 3;
2606   target.width = width_fraction;
2607   target.height = height_fraction / 2;
2608   
2609   gdk_window_begin_paint_rect (gid->src->window,
2610                                &target);
2611
2612   gdk_draw_rectangle (gid->src->window,
2613                       gc,
2614                       TRUE,
2615                       target.x, target.y,
2616                       target.width, target.height);
2617
2618   gdk_draw_rectangle (gid->src->window,
2619                       black_gc,
2620                       FALSE,
2621                       target.x + 10, target.y + 10,
2622                       target.width - 20, target.height - 20);
2623   
2624   target.x = visible.x + width_fraction;
2625   target.y = visible.y + height_fraction;
2626   target.width = width_fraction;
2627   target.height = height_fraction;
2628   
2629   gdk_window_begin_paint_rect (gid->src->window,
2630                                &target);
2631
2632   gdk_draw_rectangle (gid->src->window,
2633                       gc,
2634                       TRUE,
2635                       target.x, target.y,
2636                       target.width, target.height);
2637
2638   gdk_draw_rectangle (gid->src->window,
2639                       black_gc,
2640                       FALSE,
2641                       target.x + 10, target.y + 10,
2642                       target.width - 20, target.height - 20);
2643   
2644   target.x = visible.x + width_fraction * 3;
2645   target.y = visible.y + height_fraction;
2646   target.width = width_fraction / 2;
2647   target.height = height_fraction;
2648   
2649   gdk_window_begin_paint_rect (gid->src->window,
2650                                &target);
2651
2652   gdk_draw_rectangle (gid->src->window,
2653                       gc,
2654                       TRUE,
2655                       target.x, target.y,
2656                       target.width, target.height);
2657
2658   gdk_draw_rectangle (gid->src->window,
2659                       black_gc,
2660                       FALSE,
2661                       target.x + 10, target.y + 10,
2662                       target.width - 20, target.height - 20);
2663   
2664   target.x = visible.x + width_fraction * 2;
2665   target.y = visible.y + height_fraction * 2;
2666   target.width = width_fraction / 4;
2667   target.height = height_fraction / 4;
2668   
2669   gdk_window_begin_paint_rect (gid->src->window,
2670                                &target);
2671
2672   gdk_draw_rectangle (gid->src->window,
2673                       gc,
2674                       TRUE,
2675                       target.x, target.y,
2676                       target.width, target.height);
2677
2678   gdk_draw_rectangle (gid->src->window,
2679                       black_gc,
2680                       FALSE,
2681                       target.x + 10, target.y + 10,
2682                       target.width - 20, target.height - 20);  
2683
2684   target.x += target.width / 2;
2685   target.y += target.width / 2;
2686   
2687   gdk_window_begin_paint_rect (gid->src->window,
2688                                &target);
2689
2690   gdk_draw_rectangle (gid->src->window,
2691                       gc,
2692                       TRUE,
2693                       target.x, target.y,
2694                       target.width, target.height);
2695
2696   gdk_draw_rectangle (gid->src->window,
2697                       black_gc,
2698                       FALSE,
2699                       target.x + 10, target.y + 10,
2700                       target.width - 20, target.height - 20);
2701   
2702   /* Screen shot area */
2703
2704   target.x = visible.x + width_fraction * 1.5;
2705   target.y = visible.y + height_fraction * 1.5;
2706   target.width = width_fraction * 2;
2707   target.height = height_fraction * 2;  
2708
2709   shot = gdk_drawable_get_image (gid->src->window,
2710                                  target.x, target.y,
2711                                  target.width, target.height);
2712
2713   gtk_image_set_from_image (GTK_IMAGE (gid->snap),
2714                             shot, NULL);
2715
2716   g_object_unref (shot);
2717   
2718   gdk_window_end_paint (gid->src->window);
2719   gdk_window_end_paint (gid->src->window);
2720   gdk_window_end_paint (gid->src->window);
2721   gdk_window_end_paint (gid->src->window);
2722   gdk_window_end_paint (gid->src->window);
2723
2724   gdk_draw_rectangle (gid->src->window,
2725                       gid->src->style->black_gc,
2726                       FALSE,
2727                       target.x, target.y,
2728                       target.width, target.height);
2729   
2730   g_object_unref (gc);
2731 }
2732
2733 static gint
2734 image_source_expose (GtkWidget *da,
2735                      GdkEventExpose *event,
2736                      gpointer data)
2737 {
2738   int x = event->area.x;
2739   GdkColor red = { 0, 65535, 0, 0 };
2740   GdkColor green = { 0, 0, 65535, 0 };
2741   GdkColor blue = { 0, 0, 0, 65535 };
2742   GdkGC *gc;
2743
2744   gc = gdk_gc_new (event->window);
2745   
2746   while (x < (event->area.x + event->area.width))
2747     {
2748       switch (x % 7)
2749         {
2750         case 0:
2751         case 1:
2752         case 2:
2753           gdk_gc_set_rgb_fg_color (gc, &red);
2754           break;
2755
2756         case 3:
2757         case 4:
2758         case 5:
2759           gdk_gc_set_rgb_fg_color (gc, &green);
2760           break;
2761
2762         case 6:
2763         case 7:
2764         case 8:
2765           gdk_gc_set_rgb_fg_color (gc, &blue);
2766           break;
2767
2768         default:
2769           g_assert_not_reached ();
2770           break;
2771         }
2772
2773       gdk_draw_line (event->window,
2774                      gc,
2775                      x, event->area.y,
2776                      x, event->area.y + event->area.height);
2777       
2778       ++x;
2779     }
2780
2781   g_object_unref (gc);
2782   
2783   return TRUE;
2784 }
2785
2786 static void
2787 create_get_image (GtkWidget *widget)
2788 {
2789   static GtkWidget *window = NULL;
2790
2791   if (window)
2792     gtk_widget_destroy (window);
2793   else
2794     {
2795       GtkWidget *sw;
2796       GtkWidget *src;
2797       GtkWidget *snap;
2798       GtkWidget *hbox;
2799       GtkWidget *vbox;
2800       GtkWidget *button;
2801       struct GetImageData *gid;
2802
2803       gid = g_new (struct GetImageData, 1);
2804       
2805       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2806       
2807       gtk_window_set_screen (GTK_WINDOW (window),
2808                              gtk_widget_get_screen (widget));
2809
2810       g_signal_connect (window,
2811                         "destroy",
2812                         G_CALLBACK (gtk_widget_destroyed),
2813                         &window);
2814
2815       g_object_set_data_full (G_OBJECT (window),
2816                               "testgtk-get-image-data",
2817                               gid,
2818                               g_free);
2819       
2820       hbox = gtk_hbox_new (FALSE, 0);
2821       
2822       gtk_container_add (GTK_CONTAINER (window), hbox);
2823       
2824       sw = gtk_scrolled_window_new (NULL, NULL);
2825       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2826                                       GTK_POLICY_AUTOMATIC,
2827                                       GTK_POLICY_AUTOMATIC);
2828
2829       gid->sw = sw;
2830
2831       gtk_widget_set_size_request (sw, 400, 400);
2832       
2833       src = gtk_drawing_area_new ();
2834       gtk_widget_set_size_request (src, 10000, 10000);
2835
2836       g_signal_connect (src,
2837                         "expose_event",
2838                         G_CALLBACK (image_source_expose),
2839                         gid);
2840       
2841       gid->src = src;
2842       
2843       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw),
2844                                              src);
2845       
2846       gtk_box_pack_start (GTK_BOX (hbox),
2847                           sw, TRUE, TRUE, 0);
2848
2849
2850       vbox = gtk_vbox_new (FALSE, 3);
2851
2852       snap = g_object_new (GTK_TYPE_IMAGE, NULL);
2853
2854       gid->snap = snap;
2855
2856       sw = gtk_scrolled_window_new (NULL, NULL);
2857       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2858                                       GTK_POLICY_AUTOMATIC,
2859                                       GTK_POLICY_AUTOMATIC);
2860       gtk_widget_set_size_request (sw, 300, 300);
2861       
2862       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), snap);
2863
2864       gtk_box_pack_end (GTK_BOX (vbox), sw, FALSE, FALSE, 5);
2865
2866       button = gtk_button_new_with_label ("Get image from drawable");
2867
2868       g_signal_connect (button,
2869                         "clicked",
2870                         G_CALLBACK (take_snapshot),
2871                         gid);
2872       
2873       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2874
2875       gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2876       
2877       gtk_widget_show_all (window);
2878     }
2879 }
2880
2881 /* 
2882  * Label Demo
2883  */
2884 static void
2885 sensitivity_toggled (GtkWidget *toggle,
2886                      GtkWidget *widget)
2887 {
2888   gtk_widget_set_sensitive (widget,  GTK_TOGGLE_BUTTON (toggle)->active);  
2889 }
2890
2891 static GtkWidget*
2892 create_sensitivity_control (GtkWidget *widget)
2893 {
2894   GtkWidget *button;
2895
2896   button = gtk_toggle_button_new_with_label ("Sensitive");  
2897
2898   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2899                                 GTK_WIDGET_IS_SENSITIVE (widget));
2900   
2901   g_signal_connect (button,
2902                     "toggled",
2903                     G_CALLBACK (sensitivity_toggled),
2904                     widget);
2905   
2906   gtk_widget_show_all (button);
2907
2908   return button;
2909 }
2910
2911 static void
2912 set_selectable_recursive (GtkWidget *widget,
2913                           gboolean   setting)
2914 {
2915   if (GTK_IS_CONTAINER (widget))
2916     {
2917       GList *children;
2918       GList *tmp;
2919       
2920       children = gtk_container_get_children (GTK_CONTAINER (widget));
2921       tmp = children;
2922       while (tmp)
2923         {
2924           set_selectable_recursive (tmp->data, setting);
2925
2926           tmp = tmp->next;
2927         }
2928       g_list_free (children);
2929     }
2930   else if (GTK_IS_LABEL (widget))
2931     {
2932       gtk_label_set_selectable (GTK_LABEL (widget), setting);
2933     }
2934 }
2935
2936 static void
2937 selectable_toggled (GtkWidget *toggle,
2938                     GtkWidget *widget)
2939 {
2940   set_selectable_recursive (widget,
2941                             GTK_TOGGLE_BUTTON (toggle)->active);
2942 }
2943
2944 static GtkWidget*
2945 create_selectable_control (GtkWidget *widget)
2946 {
2947   GtkWidget *button;
2948
2949   button = gtk_toggle_button_new_with_label ("Selectable");  
2950
2951   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2952                                 FALSE);
2953   
2954   g_signal_connect (button,
2955                     "toggled",
2956                     G_CALLBACK (selectable_toggled),
2957                     widget);
2958   
2959   gtk_widget_show_all (button);
2960
2961   return button;
2962 }
2963
2964 static void
2965 dialog_response (GtkWidget *dialog, gint response_id, GtkLabel *label)
2966 {
2967   const gchar *text;
2968
2969   gtk_widget_destroy (dialog);
2970
2971   text = "Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
2972          "as hyperlinks, which can be clicked\n"
2973          "or activated via <a href=\"keynav\">keynav</a>.\n"
2974          "The links remain the same.";
2975   gtk_label_set_markup (label, text);
2976 }
2977
2978 static gboolean
2979 activate_link (GtkWidget *label, const gchar *uri, gpointer data)
2980 {
2981   if (g_strcmp0 (uri, "keynav") == 0)
2982     {
2983       GtkWidget *dialog;
2984
2985       dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (gtk_widget_get_toplevel (label)),
2986                                        GTK_DIALOG_DESTROY_WITH_PARENT,
2987                                        GTK_MESSAGE_INFO,
2988                                        GTK_BUTTONS_OK,
2989                                        "The term <i>keynav</i> is a shorthand for "
2990                                        "keyboard navigation and refers to the process of using a program "
2991                                        "(exclusively) via keyboard input.");
2992
2993       gtk_window_present (GTK_WINDOW (dialog));
2994
2995       g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), label);
2996
2997       return TRUE;
2998     }
2999
3000   return FALSE;
3001 }
3002
3003 void create_labels (GtkWidget *widget)
3004 {
3005   static GtkWidget *window = NULL;
3006   GtkWidget *hbox;
3007   GtkWidget *vbox;
3008   GtkWidget *frame;
3009   GtkWidget *label;
3010   GtkWidget *button;
3011
3012   if (!window)
3013     {
3014       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3015
3016       gtk_window_set_screen (GTK_WINDOW (window),
3017                              gtk_widget_get_screen (widget));
3018
3019       g_signal_connect (window, "destroy",
3020                         G_CALLBACK (gtk_widget_destroyed),
3021                         &window);
3022
3023       gtk_window_set_title (GTK_WINDOW (window), "Label");
3024
3025       vbox = gtk_vbox_new (FALSE, 5);
3026       
3027       hbox = gtk_hbox_new (FALSE, 5);
3028       gtk_container_add (GTK_CONTAINER (window), vbox);
3029
3030       gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
3031
3032       button = create_sensitivity_control (hbox);
3033
3034       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3035
3036       button = create_selectable_control (hbox);
3037
3038       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3039       
3040       vbox = gtk_vbox_new (FALSE, 5);
3041       
3042       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3043       gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3044
3045       frame = gtk_frame_new ("Normal Label");
3046       label = gtk_label_new ("This is a Normal label");
3047       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
3048       gtk_container_add (GTK_CONTAINER (frame), label);
3049       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3050
3051       frame = gtk_frame_new ("Multi-line Label");
3052       label = gtk_label_new ("This is a Multi-line label.\nSecond line\nThird line");
3053       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
3054       gtk_container_add (GTK_CONTAINER (frame), label);
3055       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3056
3057       frame = gtk_frame_new ("Left Justified Label");
3058       label = gtk_label_new ("This is a Left-Justified\nMulti-line label.\nThird      line");
3059       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
3060       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3061       gtk_container_add (GTK_CONTAINER (frame), label);
3062       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3063
3064       frame = gtk_frame_new ("Right Justified Label");
3065       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
3066       label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\nFourth line, (j/k)");
3067       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3068       gtk_container_add (GTK_CONTAINER (frame), label);
3069       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3070
3071       frame = gtk_frame_new ("Internationalized Label");
3072       label = gtk_label_new (NULL);
3073       gtk_label_set_markup (GTK_LABEL (label),
3074                             "French (Fran\303\247ais) Bonjour, Salut\n"
3075                             "Korean (\355\225\234\352\270\200)   \354\225\210\353\205\225\355\225\230\354\204\270\354\232\224, \354\225\210\353\205\225\355\225\230\354\213\255\353\213\210\352\271\214\n"
3076                             "Russian (\320\240\321\203\321\201\321\201\320\272\320\270\320\271) \320\227\320\264\321\200\320\260\320\262\321\201\321\202\320\262\321\203\320\271\321\202\320\265!\n"
3077                             "Chinese (Simplified) <span lang=\"zh-cn\">\345\205\203\346\260\224 \345\274\200\345\217\221</span>\n"
3078                             "Chinese (Traditional) <span lang=\"zh-tw\">\345\205\203\346\260\243        \351\226\213\347\231\274</span>\n"
3079                             "Japanese <span lang=\"ja\">\345\205\203\346\260\227        \351\226\213\347\231\272</span>");
3080       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3081       gtk_container_add (GTK_CONTAINER (frame), label);
3082       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3083
3084       frame = gtk_frame_new ("Bidirection Label");
3085       label = gtk_label_new ("\342\200\217Arabic        \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205\n"
3086                              "\342\200\217Hebrew        \327\251\327\234\327\225\327\235");
3087       gtk_container_add (GTK_CONTAINER (frame), label);
3088       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3089
3090       frame = gtk_frame_new ("Links in a label");
3091       label = gtk_label_new ("Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
3092                              "as hyperlinks, which can be clicked\n"
3093                              "or activated via <a href=\"keynav\">keynav</a>");
3094       gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
3095       gtk_container_add (GTK_CONTAINER (frame), label);
3096       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3097       g_signal_connect (label, "activate-link", G_CALLBACK (activate_link), NULL);
3098
3099       vbox = gtk_vbox_new (FALSE, 5);
3100       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3101       frame = gtk_frame_new ("Line wrapped label");
3102       label = gtk_label_new ("This is an example of a line-wrapped label.  It should not be taking "\
3103                              "up the entire             "/* big space to test spacing */\
3104                              "width allocated to it, but automatically wraps the words to fit.  "\
3105                              "The time has come, for all good men, to come to the aid of their party.  "\
3106                              "The sixth sheik's six sheep's sick.\n"\
3107                              "     It supports multiple paragraphs correctly, and  correctly   adds "\
3108                              "many          extra  spaces. ");
3109
3110       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3111       gtk_container_add (GTK_CONTAINER (frame), label);
3112       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3113
3114       frame = gtk_frame_new ("Filled, wrapped label");
3115       label = gtk_label_new ("This is an example of a line-wrapped, filled label.  It should be taking "\
3116                              "up the entire              width allocated to it.  Here is a seneance to prove "\
3117                              "my point.  Here is another sentence. "\
3118                              "Here comes the sun, do de do de do.\n"\
3119                              "    This is a new paragraph.\n"\
3120                              "    This is another newer, longer, better paragraph.  It is coming to an end, "\
3121                              "unfortunately.");
3122       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3123       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3124       gtk_container_add (GTK_CONTAINER (frame), label);
3125       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3126
3127       frame = gtk_frame_new ("Underlined label");
3128       label = gtk_label_new ("This label is underlined!\n"
3129                              "This one is underlined (\343\201\223\343\202\223\343\201\253\343\201\241\343\201\257) in quite a funky fashion");
3130       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3131       gtk_label_set_pattern (GTK_LABEL (label), "_________________________ _ _________ _ _____ _ __ __  ___ ____ _____");
3132       gtk_container_add (GTK_CONTAINER (frame), label);
3133       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3134
3135       frame = gtk_frame_new ("Markup label");
3136       label = gtk_label_new (NULL);
3137
3138       /* There's also a gtk_label_set_markup() without accel if you
3139        * don't have an accelerator key
3140        */
3141       gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
3142                                           "This <span foreground=\"blue\" background=\"orange\">label</span> has "
3143                                           "<b>markup</b> _such as "
3144                                           "<big><i>Big Italics</i></big>\n"
3145                                           "<tt>Monospace font</tt>\n"
3146                                           "<u>Underline!</u>\n"
3147                                           "foo\n"
3148                                           "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
3149                                           "and nothing on this line,\n"
3150                                           "or this.\n"
3151                                           "or this either\n"
3152                                           "or even on this one\n"
3153                                           "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
3154                                           "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
3155                                           "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
3156
3157       g_assert (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)) == GDK_s);
3158       
3159       gtk_container_add (GTK_CONTAINER (frame), label);
3160       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3161     }
3162   
3163   if (!GTK_WIDGET_VISIBLE (window))
3164     gtk_widget_show_all (window);
3165   else
3166     gtk_widget_destroy (window);
3167 }
3168
3169 static void
3170 on_angle_scale_changed (GtkRange *range,
3171                         GtkLabel *label)
3172 {
3173   gtk_label_set_angle (GTK_LABEL (label), gtk_range_get_value (range));
3174 }
3175
3176 static void
3177 create_rotated_label (GtkWidget *widget)
3178 {
3179   static GtkWidget *window = NULL;
3180   GtkWidget *vbox;
3181   GtkWidget *hscale;
3182   GtkWidget *label;  
3183   GtkWidget *scale_label;  
3184   GtkWidget *scale_hbox;  
3185
3186   if (!window)
3187     {
3188       window = gtk_dialog_new_with_buttons ("Rotated Label",
3189                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
3190                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
3191                                             NULL);
3192
3193       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
3194
3195       gtk_window_set_screen (GTK_WINDOW (window),
3196                              gtk_widget_get_screen (widget));
3197
3198       g_signal_connect (window, "response",
3199                         G_CALLBACK (gtk_object_destroy), NULL);
3200       g_signal_connect (window, "destroy",
3201                         G_CALLBACK (gtk_widget_destroyed), &window);
3202
3203       vbox = gtk_vbox_new (FALSE, 5);
3204       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0);
3205       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3206
3207       label = gtk_label_new (NULL);
3208       gtk_label_set_markup (GTK_LABEL (label), "Hello World\n<i>Rotate</i> <span underline='single' foreground='blue'>me</span>");
3209       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3210
3211       scale_hbox = gtk_hbox_new (FALSE, 0);
3212       gtk_box_pack_start (GTK_BOX (vbox), scale_hbox, FALSE, FALSE, 0);
3213       
3214       scale_label = gtk_label_new (NULL);
3215       gtk_label_set_markup (GTK_LABEL (scale_label), "<i>Angle: </i>");
3216       gtk_box_pack_start (GTK_BOX (scale_hbox), scale_label, FALSE, FALSE, 0);
3217
3218       hscale = gtk_hscale_new_with_range (0, 360, 5);
3219       g_signal_connect (hscale, "value-changed",
3220                         G_CALLBACK (on_angle_scale_changed), label);
3221       
3222       gtk_range_set_value (GTK_RANGE (hscale), 45);
3223       gtk_widget_set_usize (hscale, 200, -1);
3224       gtk_box_pack_start (GTK_BOX (scale_hbox), hscale, TRUE, TRUE, 0);
3225     }
3226   
3227   if (!GTK_WIDGET_VISIBLE (window))
3228     gtk_widget_show_all (window);
3229   else
3230     gtk_widget_destroy (window);
3231 }
3232
3233 #define DEFAULT_TEXT_RADIUS 200
3234
3235 static void
3236 on_rotated_text_unrealize (GtkWidget *widget)
3237 {
3238   g_object_set_data (G_OBJECT (widget), "text-gc", NULL);
3239 }
3240
3241 static gboolean
3242 on_rotated_text_expose (GtkWidget      *widget,
3243                         GdkEventExpose *event,
3244                         GdkPixbuf      *tile_pixbuf)
3245 {
3246   static const gchar *words[] = { "The", "grand", "old", "Duke", "of", "York",
3247                                   "had", "10,000", "men" };
3248   PangoRenderer *renderer;
3249   GdkGC *gc;
3250   int n_words;
3251   int i;
3252   double radius;
3253   PangoMatrix matrix = PANGO_MATRIX_INIT;
3254   PangoLayout *layout;
3255   PangoContext *context;
3256   PangoFontDescription *desc;
3257
3258   gc = g_object_get_data (G_OBJECT (widget), "text-gc");
3259   if (!gc)
3260     {
3261       static GdkColor black = { 0, 0, 0, 0 };
3262       
3263       gc = gdk_gc_new (widget->window);
3264       gdk_gc_set_rgb_fg_color (gc, &black);
3265       
3266       if (tile_pixbuf)
3267         {
3268           GdkPixmap *tile;
3269           
3270           gint width = gdk_pixbuf_get_width (tile_pixbuf);
3271           gint height = gdk_pixbuf_get_height (tile_pixbuf);
3272           
3273           tile = gdk_pixmap_new (widget->window, width, height, -1);
3274           gdk_draw_pixbuf (tile, gc, tile_pixbuf,
3275                            0, 0, 0, 0, width, height,
3276                            GDK_RGB_DITHER_NORMAL, 0, 0);
3277
3278           gdk_gc_set_tile (gc, tile);
3279           gdk_gc_set_fill (gc, GDK_TILED);
3280
3281           g_object_unref (tile);
3282         }
3283
3284       g_object_set_data_full (G_OBJECT (widget), "text-gc", gc, (GDestroyNotify)g_object_unref);
3285     }
3286
3287   renderer = gdk_pango_renderer_get_default (gtk_widget_get_screen (widget));
3288   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), widget->window);
3289   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), gc);
3290
3291   radius = MIN (widget->allocation.width, widget->allocation.height) / 2.;
3292
3293   pango_matrix_translate (&matrix,
3294                           radius + (widget->allocation.width - 2 * radius) / 2,
3295                           radius + (widget->allocation.height - 2 * radius) / 2);
3296   pango_matrix_scale (&matrix, radius / DEFAULT_TEXT_RADIUS, radius / DEFAULT_TEXT_RADIUS);
3297
3298   context = gtk_widget_get_pango_context (widget);
3299   layout = pango_layout_new (context);
3300   desc = pango_font_description_from_string ("Sans Bold 30");
3301   pango_layout_set_font_description (layout, desc);
3302   pango_font_description_free (desc);
3303     
3304   n_words = G_N_ELEMENTS (words);
3305   for (i = 0; i < n_words; i++)
3306     {
3307       PangoMatrix rotated_matrix = matrix;
3308       int width, height;
3309       
3310       pango_matrix_rotate (&rotated_matrix, - (360. * i) / n_words);
3311
3312       pango_context_set_matrix (context, &rotated_matrix);
3313       pango_layout_context_changed (layout);
3314       pango_layout_set_text (layout, words[i], -1);
3315       
3316       pango_layout_get_size (layout, &width, &height);
3317
3318       pango_renderer_draw_layout (renderer, layout,
3319                                   - width / 2, - DEFAULT_TEXT_RADIUS * PANGO_SCALE);
3320     }
3321
3322   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), NULL);
3323   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), NULL);
3324   
3325   g_object_unref (layout);
3326
3327   return FALSE;
3328 }
3329
3330 static void
3331 create_rotated_text (GtkWidget *widget)
3332 {
3333   static GtkWidget *window = NULL;
3334
3335   if (!window)
3336     {
3337       const GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
3338       GtkRequisition requisition;
3339       GtkWidget *drawing_area;
3340       GdkPixbuf *tile_pixbuf;
3341
3342       window = gtk_dialog_new_with_buttons ("Rotated Text",
3343                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
3344                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
3345                                             NULL);
3346
3347       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
3348
3349       gtk_window_set_screen (GTK_WINDOW (window),
3350                              gtk_widget_get_screen (widget));
3351
3352       g_signal_connect (window, "response",
3353                         G_CALLBACK (gtk_object_destroy), NULL);
3354       g_signal_connect (window, "destroy",
3355                         G_CALLBACK (gtk_widget_destroyed), &window);
3356
3357       drawing_area = gtk_drawing_area_new ();
3358       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), drawing_area, TRUE, TRUE, 0);
3359       gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &white);
3360
3361       tile_pixbuf = gdk_pixbuf_new_from_file ("marble.xpm", NULL);
3362       
3363       g_signal_connect (drawing_area, "expose-event",
3364                         G_CALLBACK (on_rotated_text_expose), tile_pixbuf);
3365       g_signal_connect (drawing_area, "unrealize",
3366                         G_CALLBACK (on_rotated_text_unrealize), NULL);
3367
3368       gtk_widget_show_all (GTK_BIN (window)->child);
3369       
3370       gtk_widget_set_size_request (drawing_area, DEFAULT_TEXT_RADIUS * 2, DEFAULT_TEXT_RADIUS * 2);
3371       gtk_widget_size_request (window, &requisition);
3372       gtk_widget_set_size_request (drawing_area, -1, -1);
3373       gtk_window_resize (GTK_WINDOW (window), requisition.width, requisition.height);
3374     }
3375   
3376   if (!GTK_WIDGET_VISIBLE (window))
3377     gtk_widget_show (window);
3378   else
3379     gtk_widget_destroy (window);
3380 }
3381
3382 /*
3383  * Reparent demo
3384  */
3385
3386 static void
3387 reparent_label (GtkWidget *widget,
3388                 GtkWidget *new_parent)
3389 {
3390   GtkWidget *label;
3391
3392   label = g_object_get_data (G_OBJECT (widget), "user_data");
3393
3394   gtk_widget_reparent (label, new_parent);
3395 }
3396
3397 static void
3398 set_parent_signal (GtkWidget *child,
3399                    GtkWidget *old_parent,
3400                    gpointer   func_data)
3401 {
3402   g_message ("set_parent for \"%s\": new parent: \"%s\", old parent: \"%s\", data: %d\n",
3403              g_type_name (G_OBJECT_TYPE (child)),
3404              child->parent ? g_type_name (G_OBJECT_TYPE (child->parent)) : "NULL",
3405              old_parent ? g_type_name (G_OBJECT_TYPE (old_parent)) : "NULL",
3406              GPOINTER_TO_INT (func_data));
3407 }
3408
3409 static void
3410 create_reparent (GtkWidget *widget)
3411 {
3412   static GtkWidget *window = NULL;
3413   GtkWidget *box1;
3414   GtkWidget *box2;
3415   GtkWidget *box3;
3416   GtkWidget *frame;
3417   GtkWidget *button;
3418   GtkWidget *label;
3419   GtkWidget *separator;
3420   GtkWidget *event_box;
3421
3422   if (!window)
3423     {
3424       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3425
3426       gtk_window_set_screen (GTK_WINDOW (window),
3427                              gtk_widget_get_screen (widget));
3428
3429       g_signal_connect (window, "destroy",
3430                         G_CALLBACK (gtk_widget_destroyed),
3431                         &window);
3432
3433       gtk_window_set_title (GTK_WINDOW (window), "reparent");
3434       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3435
3436       box1 = gtk_vbox_new (FALSE, 0);
3437       gtk_container_add (GTK_CONTAINER (window), box1);
3438
3439       box2 = gtk_hbox_new (FALSE, 5);
3440       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3441       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3442
3443       label = gtk_label_new ("Hello World");
3444
3445       frame = gtk_frame_new ("Frame 1");
3446       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
3447
3448       box3 = gtk_vbox_new (FALSE, 5);
3449       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
3450       gtk_container_add (GTK_CONTAINER (frame), box3);
3451
3452       button = gtk_button_new_with_label ("switch");
3453       g_object_set_data (G_OBJECT (button), "user_data", label);
3454       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
3455
3456       event_box = gtk_event_box_new ();
3457       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
3458       gtk_container_add (GTK_CONTAINER (event_box), label);
3459                          
3460       g_signal_connect (button, "clicked",
3461                         G_CALLBACK (reparent_label),
3462                         event_box);
3463       
3464       g_signal_connect (label, "parent_set",
3465                         G_CALLBACK (set_parent_signal),
3466                         GINT_TO_POINTER (42));
3467
3468       frame = gtk_frame_new ("Frame 2");
3469       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
3470
3471       box3 = gtk_vbox_new (FALSE, 5);
3472       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
3473       gtk_container_add (GTK_CONTAINER (frame), box3);
3474
3475       button = gtk_button_new_with_label ("switch");
3476       g_object_set_data (G_OBJECT (button), "user_data", label);
3477       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
3478       
3479       event_box = gtk_event_box_new ();
3480       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
3481
3482       g_signal_connect (button, "clicked",
3483                         G_CALLBACK (reparent_label),
3484                         event_box);
3485
3486       separator = gtk_hseparator_new ();
3487       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3488
3489       box2 = gtk_vbox_new (FALSE, 10);
3490       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3491       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3492
3493       button = gtk_button_new_with_label ("close");
3494       g_signal_connect_swapped (button, "clicked",
3495                                 G_CALLBACK (gtk_widget_destroy), window);
3496       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3497       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3498       gtk_widget_grab_default (button);
3499     }
3500
3501   if (!GTK_WIDGET_VISIBLE (window))
3502     gtk_widget_show_all (window);
3503   else
3504     gtk_widget_destroy (window);
3505 }
3506
3507 /*
3508  * Resize Grips
3509  */
3510 static gboolean
3511 grippy_button_press (GtkWidget *area, GdkEventButton *event, GdkWindowEdge edge)
3512 {
3513   if (event->type == GDK_BUTTON_PRESS) 
3514     {
3515       if (event->button == 1)
3516         gtk_window_begin_resize_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), edge,
3517                                       event->button, event->x_root, event->y_root,
3518                                       event->time);
3519       else if (event->button == 2)
3520         gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), 
3521                                     event->button, event->x_root, event->y_root,
3522                                     event->time);
3523     }
3524   return TRUE;
3525 }
3526
3527 static gboolean
3528 grippy_expose (GtkWidget *area, GdkEventExpose *event, GdkWindowEdge edge)
3529 {
3530   gtk_paint_resize_grip (area->style,
3531                          area->window,
3532                          GTK_WIDGET_STATE (area),
3533                          &event->area,
3534                          area,
3535                          "statusbar",
3536                          edge,
3537                          0, 0,
3538                          area->allocation.width,
3539                          area->allocation.height);
3540
3541   return TRUE;
3542 }
3543
3544 static void
3545 create_resize_grips (GtkWidget *widget)
3546 {
3547   static GtkWidget *window = NULL;
3548   GtkWidget *area;
3549   GtkWidget *hbox, *vbox;
3550   if (!window)
3551     {
3552       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3553
3554       gtk_window_set_screen (GTK_WINDOW (window),
3555                              gtk_widget_get_screen (widget));
3556
3557       gtk_window_set_title (GTK_WINDOW (window), "resize grips");
3558       
3559       g_signal_connect (window, "destroy",
3560                         G_CALLBACK (gtk_widget_destroyed),
3561                         &window);
3562
3563       vbox = gtk_vbox_new (FALSE, 0);
3564       gtk_container_add (GTK_CONTAINER (window), vbox);
3565       
3566       hbox = gtk_hbox_new (FALSE, 0);
3567       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3568
3569       /* North west */
3570       area = gtk_drawing_area_new ();
3571       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3572       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3573       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3574                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3575       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3576                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3577       
3578       /* North */
3579       area = gtk_drawing_area_new ();
3580       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3581       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3582       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3583                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3584       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3585                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3586
3587       /* North east */
3588       area = gtk_drawing_area_new ();
3589       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3590       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3591       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3592                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3593       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3594                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3595
3596       hbox = gtk_hbox_new (FALSE, 0);
3597       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3598
3599       /* West */
3600       area = gtk_drawing_area_new ();
3601       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3602       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3603       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3604                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3605       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3606                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3607
3608       /* Middle */
3609       area = gtk_drawing_area_new ();
3610       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3611
3612       /* East */
3613       area = gtk_drawing_area_new ();
3614       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3615       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3616       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3617                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3618       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3619                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3620
3621
3622       hbox = gtk_hbox_new (FALSE, 0);
3623       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3624
3625       /* South west */
3626       area = gtk_drawing_area_new ();
3627       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3628       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3629       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3630                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3631       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3632                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3633       /* South */
3634       area = gtk_drawing_area_new ();
3635       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3636       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3637       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3638                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3639       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3640                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3641       
3642       /* South east */
3643       area = gtk_drawing_area_new ();
3644       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3645       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3646       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3647                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3648       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3649                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3650     }
3651
3652   if (!GTK_WIDGET_VISIBLE (window))
3653     gtk_widget_show_all (window);
3654   else
3655     gtk_widget_destroy (window);
3656 }
3657
3658 /*
3659  * Saved Position
3660  */
3661 gint upositionx = 0;
3662 gint upositiony = 0;
3663
3664 static gint
3665 uposition_configure (GtkWidget *window)
3666 {
3667   GtkLabel *lx;
3668   GtkLabel *ly;
3669   gchar buffer[64];
3670
3671   lx = g_object_get_data (G_OBJECT (window), "x");
3672   ly = g_object_get_data (G_OBJECT (window), "y");
3673
3674   gdk_window_get_root_origin (window->window, &upositionx, &upositiony);
3675   sprintf (buffer, "%d", upositionx);
3676   gtk_label_set_text (lx, buffer);
3677   sprintf (buffer, "%d", upositiony);
3678   gtk_label_set_text (ly, buffer);
3679
3680   return FALSE;
3681 }
3682
3683 static void
3684 uposition_stop_configure (GtkToggleButton *toggle,
3685                           GtkObject       *window)
3686 {
3687   if (toggle->active)
3688     g_signal_handlers_block_by_func (window, G_CALLBACK (uposition_configure), NULL);
3689   else
3690     g_signal_handlers_unblock_by_func (window, G_CALLBACK (uposition_configure), NULL);
3691 }
3692
3693 static void
3694 create_saved_position (GtkWidget *widget)
3695 {
3696   static GtkWidget *window = NULL;
3697
3698   if (!window)
3699     {
3700       GtkWidget *hbox;
3701       GtkWidget *main_vbox;
3702       GtkWidget *vbox;
3703       GtkWidget *x_label;
3704       GtkWidget *y_label;
3705       GtkWidget *button;
3706       GtkWidget *label;
3707       GtkWidget *any;
3708
3709       window = g_object_connect (g_object_new (GTK_TYPE_WINDOW,
3710                                                  "type", GTK_WINDOW_TOPLEVEL,
3711                                                  "title", "Saved Position",
3712                                                  NULL),
3713                                  "signal::configure_event", uposition_configure, NULL,
3714                                  NULL);
3715
3716       gtk_window_move (GTK_WINDOW (window), upositionx, upositiony);
3717
3718       gtk_window_set_screen (GTK_WINDOW (window),
3719                              gtk_widget_get_screen (widget));
3720       
3721
3722       g_signal_connect (window, "destroy",
3723                         G_CALLBACK (gtk_widget_destroyed),
3724                         &window);
3725
3726       main_vbox = gtk_vbox_new (FALSE, 5);
3727       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
3728       gtk_container_add (GTK_CONTAINER (window), main_vbox);
3729
3730       vbox =
3731         g_object_new (gtk_vbox_get_type (),
3732                         "GtkBox::homogeneous", FALSE,
3733                         "GtkBox::spacing", 5,
3734                         "GtkContainer::border_width", 10,
3735                         "GtkWidget::parent", main_vbox,
3736                         "GtkWidget::visible", TRUE,
3737                         "child", g_object_connect (g_object_new (GTK_TYPE_TOGGLE_BUTTON,
3738                                                                    "label", "Stop Events",
3739                                                                    "active", FALSE,
3740                                                                    "visible", TRUE,
3741                                                                    NULL),
3742                                                    "signal::clicked", uposition_stop_configure, window,
3743                                                    NULL),
3744                         NULL);
3745
3746       hbox = gtk_hbox_new (FALSE, 0);
3747       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3748       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3749
3750       label = gtk_label_new ("X Origin : ");
3751       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3752       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3753
3754       x_label = gtk_label_new ("");
3755       gtk_box_pack_start (GTK_BOX (hbox), x_label, TRUE, TRUE, 0);
3756       g_object_set_data (G_OBJECT (window), "x", x_label);
3757
3758       hbox = gtk_hbox_new (FALSE, 0);
3759       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3760       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3761
3762       label = gtk_label_new ("Y Origin : ");
3763       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3764       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3765
3766       y_label = gtk_label_new ("");
3767       gtk_box_pack_start (GTK_BOX (hbox), y_label, TRUE, TRUE, 0);
3768       g_object_set_data (G_OBJECT (window), "y", y_label);
3769
3770       any =
3771         g_object_new (gtk_hseparator_get_type (),
3772                         "GtkWidget::visible", TRUE,
3773                         NULL);
3774       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
3775
3776       hbox = gtk_hbox_new (FALSE, 0);
3777       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
3778       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
3779
3780       button = gtk_button_new_with_label ("Close");
3781       g_signal_connect_swapped (button, "clicked",
3782                                 G_CALLBACK (gtk_widget_destroy),
3783                                 window);
3784       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
3785       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3786       gtk_widget_grab_default (button);
3787       
3788       gtk_widget_show_all (window);
3789     }
3790   else
3791     gtk_widget_destroy (window);
3792 }
3793
3794 /*
3795  * GtkPixmap
3796  */
3797
3798 static void
3799 create_pixmap (GtkWidget *widget)
3800 {
3801   static GtkWidget *window = NULL;
3802   GtkWidget *box1;
3803   GtkWidget *box2;
3804   GtkWidget *box3;
3805   GtkWidget *button;
3806   GtkWidget *label;
3807   GtkWidget *separator;
3808   GtkWidget *pixmapwid;
3809
3810   if (!window)
3811     {
3812       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3813
3814       gtk_window_set_screen (GTK_WINDOW (window),
3815                              gtk_widget_get_screen (widget));
3816
3817       g_signal_connect (window, "destroy",
3818                         G_CALLBACK (gtk_widget_destroyed),
3819                         &window);
3820
3821       gtk_window_set_title (GTK_WINDOW (window), "GtkPixmap");
3822       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3823       gtk_widget_realize(window);
3824
3825       box1 = gtk_vbox_new (FALSE, 0);
3826       gtk_container_add (GTK_CONTAINER (window), box1);
3827
3828       box2 = gtk_vbox_new (FALSE, 10);
3829       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3830       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3831
3832       button = gtk_button_new ();
3833       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3834
3835       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3836
3837       label = gtk_label_new ("Pixmap\ntest");
3838       box3 = gtk_hbox_new (FALSE, 0);
3839       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3840       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3841       gtk_container_add (GTK_CONTAINER (box3), label);
3842       gtk_container_add (GTK_CONTAINER (button), box3);
3843
3844       button = gtk_button_new ();
3845       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3846       
3847       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3848
3849       label = gtk_label_new ("Pixmap\ntest");
3850       box3 = gtk_hbox_new (FALSE, 0);
3851       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3852       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3853       gtk_container_add (GTK_CONTAINER (box3), label);
3854       gtk_container_add (GTK_CONTAINER (button), box3);
3855
3856       gtk_widget_set_sensitive (button, FALSE);
3857       
3858       separator = gtk_hseparator_new ();
3859       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3860
3861       box2 = gtk_vbox_new (FALSE, 10);
3862       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3863       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3864
3865       button = gtk_button_new_with_label ("close");
3866       g_signal_connect_swapped (button, "clicked",
3867                                 G_CALLBACK (gtk_widget_destroy),
3868                                 window);
3869       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3870       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3871       gtk_widget_grab_default (button);
3872     }
3873
3874   if (!GTK_WIDGET_VISIBLE (window))
3875     gtk_widget_show_all (window);
3876   else
3877     gtk_widget_destroy (window);
3878 }
3879
3880 static void
3881 tips_query_widget_entered (GtkTipsQuery   *tips_query,
3882                            GtkWidget      *widget,
3883                            const gchar    *tip_text,
3884                            const gchar    *tip_private,
3885                            GtkWidget      *toggle)
3886 {
3887   if (GTK_TOGGLE_BUTTON (toggle)->active)
3888     {
3889       gtk_label_set_text (GTK_LABEL (tips_query), tip_text ? "There is a Tip!" : "There is no Tip!");
3890       /* don't let GtkTipsQuery reset its label */
3891       g_signal_stop_emission_by_name (tips_query, "widget_entered");
3892     }
3893 }
3894
3895 static gint
3896 tips_query_widget_selected (GtkWidget      *tips_query,
3897                             GtkWidget      *widget,
3898                             const gchar    *tip_text,
3899                             const gchar    *tip_private,
3900                             GdkEventButton *event,
3901                             gpointer        func_data)
3902 {
3903   if (widget)
3904     g_print ("Help \"%s\" requested for <%s>\n",
3905              tip_private ? tip_private : "None",
3906              g_type_name (G_OBJECT_TYPE (widget)));
3907   return TRUE;
3908 }
3909
3910 static void
3911 create_tooltips (GtkWidget *widget)
3912 {
3913   static GtkWidget *window = NULL;
3914   GtkWidget *box1;
3915   GtkWidget *box2;
3916   GtkWidget *box3;
3917   GtkWidget *button;
3918   GtkWidget *toggle;
3919   GtkWidget *frame;
3920   GtkWidget *tips_query;
3921   GtkWidget *separator;
3922   GtkTooltips *tooltips;
3923
3924   if (!window)
3925     {
3926       window =
3927         g_object_new (gtk_window_get_type (),
3928                         "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
3929                         "GtkContainer::border_width", 0,
3930                         "GtkWindow::title", "Tooltips",
3931                         "GtkWindow::allow_shrink", TRUE,
3932                         "GtkWindow::allow_grow", FALSE,
3933                         NULL);
3934
3935       gtk_window_set_screen (GTK_WINDOW (window),
3936                              gtk_widget_get_screen (widget));
3937
3938       g_signal_connect (window, "destroy",
3939                         G_CALLBACK (destroy_tooltips),
3940                         &window);
3941
3942       tooltips=gtk_tooltips_new();
3943       g_object_ref (tooltips);
3944       gtk_object_sink (GTK_OBJECT (tooltips));
3945       g_object_set_data (G_OBJECT (window), "tooltips", tooltips);
3946       
3947       box1 = gtk_vbox_new (FALSE, 0);
3948       gtk_container_add (GTK_CONTAINER (window), box1);
3949
3950       box2 = gtk_vbox_new (FALSE, 10);
3951       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3952       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3953
3954       button = gtk_toggle_button_new_with_label ("button1");
3955       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3956
3957       gtk_tooltips_set_tip (tooltips,
3958                             button,
3959                             "This is button 1",
3960                             "ContextHelp/buttons/1");
3961
3962       button = gtk_toggle_button_new_with_label ("button2");
3963       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3964
3965       gtk_tooltips_set_tip (tooltips,
3966                             button,
3967                             "This is button 2. This is also a really long tooltip which probably won't fit on a single line and will therefore need to be wrapped. Hopefully the wrapping will work correctly.",
3968                             "ContextHelp/buttons/2_long");
3969
3970       toggle = gtk_toggle_button_new_with_label ("Override TipsQuery Label");
3971       gtk_box_pack_start (GTK_BOX (box2), toggle, TRUE, TRUE, 0);
3972
3973       gtk_tooltips_set_tip (tooltips,
3974                             toggle,
3975                             "Toggle TipsQuery view.",
3976                             "Hi msw! ;)");
3977
3978       box3 =
3979         g_object_new (gtk_vbox_get_type (),
3980                         "homogeneous", FALSE,
3981                         "spacing", 5,
3982                         "border_width", 5,
3983                         "visible", TRUE,
3984                         NULL);
3985
3986       tips_query = gtk_tips_query_new ();
3987
3988       button =
3989         g_object_new (gtk_button_get_type (),
3990                         "label", "[?]",
3991                         "visible", TRUE,
3992                         "parent", box3,
3993                         NULL);
3994       g_object_connect (button,
3995                         "swapped_signal::clicked", gtk_tips_query_start_query, tips_query,
3996                         NULL);
3997       gtk_box_set_child_packing (GTK_BOX (box3), button, FALSE, FALSE, 0, GTK_PACK_START);
3998       gtk_tooltips_set_tip (tooltips,
3999                             button,
4000                             "Start the Tooltips Inspector",
4001                             "ContextHelp/buttons/?");
4002       
4003       
4004       g_object_set (g_object_connect (tips_query,
4005                                       "signal::widget_entered", tips_query_widget_entered, toggle,
4006                                       "signal::widget_selected", tips_query_widget_selected, NULL,
4007                                       NULL),
4008                     "visible", TRUE,
4009                     "parent", box3,
4010                     "caller", button,
4011                     NULL);
4012       
4013       frame = g_object_new (gtk_frame_get_type (),
4014                               "label", "ToolTips Inspector",
4015                               "label_xalign", (double) 0.5,
4016                               "border_width", 0,
4017                               "visible", TRUE,
4018                               "parent", box2,
4019                               "child", box3,
4020                               NULL);
4021       gtk_box_set_child_packing (GTK_BOX (box2), frame, TRUE, TRUE, 10, GTK_PACK_START);
4022
4023       separator = gtk_hseparator_new ();
4024       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4025
4026       box2 = gtk_vbox_new (FALSE, 10);
4027       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4028       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4029
4030       button = gtk_button_new_with_label ("close");
4031       g_signal_connect_swapped (button, "clicked",
4032                                 G_CALLBACK (gtk_widget_destroy),
4033                                 window);
4034       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4035       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4036       gtk_widget_grab_default (button);
4037
4038       gtk_tooltips_set_tip (tooltips, button, "Push this button to close window", "ContextHelp/buttons/Close");
4039     }
4040
4041   if (!GTK_WIDGET_VISIBLE (window))
4042     gtk_widget_show_all (window);
4043   else
4044     gtk_widget_destroy (window);
4045 }
4046
4047 /*
4048  * GtkImage
4049  */
4050
4051 static void
4052 pack_image (GtkWidget *box,
4053             const gchar *text,
4054             GtkWidget *image)
4055 {
4056   gtk_box_pack_start (GTK_BOX (box),
4057                       gtk_label_new (text),
4058                       FALSE, FALSE, 0);
4059
4060   gtk_box_pack_start (GTK_BOX (box),
4061                       image,
4062                       TRUE, TRUE, 0);  
4063 }
4064
4065 static void
4066 create_image (GtkWidget *widget)
4067 {
4068   static GtkWidget *window = NULL;
4069
4070   if (window == NULL)
4071     {
4072       GtkWidget *vbox;
4073       GdkPixmap *pixmap;
4074       GdkBitmap *mask;
4075         
4076       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4077       
4078       gtk_window_set_screen (GTK_WINDOW (window),
4079                              gtk_widget_get_screen (widget));
4080
4081       /* this is bogus for testing drawing when allocation < request,
4082        * don't copy into real code
4083        */
4084       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
4085       
4086       g_signal_connect (window, "destroy",
4087                         G_CALLBACK (gtk_widget_destroyed),
4088                         &window);
4089
4090       vbox = gtk_vbox_new (FALSE, 5);
4091
4092       gtk_container_add (GTK_CONTAINER (window), vbox);
4093
4094       pack_image (vbox, "Stock Warning Dialog",
4095                   gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
4096                                             GTK_ICON_SIZE_DIALOG));
4097
4098       pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
4099                                                       gtk_widget_get_colormap (window),
4100                                                       &mask,
4101                                                       NULL,
4102                                                       openfile);
4103       
4104       pack_image (vbox, "Pixmap",
4105                   gtk_image_new_from_pixmap (pixmap, mask));
4106     }
4107
4108   if (!GTK_WIDGET_VISIBLE (window))
4109     gtk_widget_show_all (window);
4110   else
4111     gtk_widget_destroy (window);
4112 }
4113      
4114 /*
4115  * Menu demo
4116  */
4117
4118 static GtkWidget*
4119 create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
4120 {
4121   GtkWidget *menu;
4122   GtkWidget *menuitem;
4123   GtkWidget *image;
4124   GSList *group;
4125   char buf[32];
4126   int i, j;
4127
4128   if (depth < 1)
4129     return NULL;
4130
4131   menu = gtk_menu_new ();
4132   gtk_menu_set_screen (GTK_MENU (menu), screen);
4133
4134   group = NULL;
4135
4136   if (tearoff)
4137     {
4138       menuitem = gtk_tearoff_menu_item_new ();
4139       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4140       gtk_widget_show (menuitem);
4141     }
4142
4143   image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
4144                                     GTK_ICON_SIZE_MENU);
4145   gtk_widget_show (image);
4146   menuitem = gtk_image_menu_item_new_with_label ("Image item");
4147   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4148   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4149   gtk_widget_show (menuitem);
4150   
4151   for (i = 0, j = 1; i < length; i++, j++)
4152     {
4153       sprintf (buf, "item %2d - %d", depth, j);
4154
4155       menuitem = gtk_radio_menu_item_new_with_label (group, buf);
4156       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
4157
4158 #if 0
4159       if (depth % 2)
4160         gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
4161 #endif
4162
4163       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4164       gtk_widget_show (menuitem);
4165       if (i == 3)
4166         gtk_widget_set_sensitive (menuitem, FALSE);
4167
4168       if (i == 5)
4169         gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (menuitem),
4170                                               TRUE);
4171
4172       if (i < 5)
4173         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), 
4174                                    create_menu (screen, depth - 1, 5,  TRUE));
4175     }
4176
4177   return menu;
4178 }
4179
4180 static GtkWidget*
4181 create_table_menu (GdkScreen *screen, gint cols, gint rows, gboolean tearoff)
4182 {
4183   GtkWidget *menu;
4184   GtkWidget *menuitem;
4185   GtkWidget *submenu;
4186   GtkWidget *image;
4187   char buf[32];
4188   int i, j;
4189
4190   menu = gtk_menu_new ();
4191   gtk_menu_set_screen (GTK_MENU (menu), screen);
4192
4193   j = 0;
4194   if (tearoff)
4195     {
4196       menuitem = gtk_tearoff_menu_item_new ();
4197       gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4198       gtk_widget_show (menuitem);
4199       j++;
4200     }
4201   
4202   menuitem = gtk_menu_item_new_with_label ("items");
4203   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4204
4205   submenu = gtk_menu_new ();
4206   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4207   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4208   gtk_widget_show (menuitem);
4209   j++;
4210
4211   /* now fill the items submenu */
4212   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4213                                     GTK_ICON_SIZE_MENU);
4214   gtk_widget_show (image);
4215   menuitem = gtk_image_menu_item_new_with_label ("Image");
4216   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4217   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4218   gtk_widget_show (menuitem);
4219
4220   menuitem = gtk_menu_item_new_with_label ("x");
4221   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 0, 1);
4222   gtk_widget_show (menuitem);
4223
4224   menuitem = gtk_menu_item_new_with_label ("x");
4225   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 2);
4226   gtk_widget_show (menuitem);
4227   
4228   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4229                                     GTK_ICON_SIZE_MENU);
4230   gtk_widget_show (image);
4231   menuitem = gtk_image_menu_item_new_with_label ("Image");
4232   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4233   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
4234   gtk_widget_show (menuitem);
4235
4236   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
4237   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 2, 3);
4238   gtk_widget_show (menuitem);
4239
4240   menuitem = gtk_menu_item_new_with_label ("x");
4241   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 2, 3);
4242   gtk_widget_show (menuitem);
4243
4244   menuitem = gtk_menu_item_new_with_label ("x");
4245   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 3, 4);
4246   gtk_widget_show (menuitem);
4247   
4248   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
4249   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 3, 4);
4250   gtk_widget_show (menuitem);
4251
4252   menuitem = gtk_check_menu_item_new_with_label ("Check");
4253   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 4, 5);
4254   gtk_widget_show (menuitem);
4255
4256   menuitem = gtk_menu_item_new_with_label ("x");
4257   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 4, 5);
4258   gtk_widget_show (menuitem);
4259
4260   menuitem = gtk_menu_item_new_with_label ("x");
4261   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 5, 6);
4262   gtk_widget_show (menuitem);
4263   
4264   menuitem = gtk_check_menu_item_new_with_label ("Check");
4265   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 5, 6);
4266   gtk_widget_show (menuitem);
4267
4268   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
4269   gtk_widget_show (menuitem);
4270   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 8);
4271
4272   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
4273   gtk_widget_show (menuitem);
4274   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 2);
4275
4276   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
4277   gtk_widget_show (menuitem);
4278   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 0);
4279
4280   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
4281   gtk_widget_show (menuitem);
4282   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, -1);
4283   
4284   /* end of items submenu */
4285
4286   menuitem = gtk_menu_item_new_with_label ("spanning");
4287   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4288
4289   submenu = gtk_menu_new ();
4290   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4291   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4292   gtk_widget_show (menuitem);
4293   j++;
4294
4295   /* now fill the spanning submenu */
4296   menuitem = gtk_menu_item_new_with_label ("a");
4297   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 2, 0, 1);
4298   gtk_widget_show (menuitem);
4299
4300   menuitem = gtk_menu_item_new_with_label ("b");
4301   gtk_menu_attach (GTK_MENU (submenu), menuitem, 2, 3, 0, 2);
4302   gtk_widget_show (menuitem);
4303
4304   menuitem = gtk_menu_item_new_with_label ("c");
4305   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 3);
4306   gtk_widget_show (menuitem);
4307
4308   menuitem = gtk_menu_item_new_with_label ("d");
4309   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
4310   gtk_widget_show (menuitem);
4311
4312   menuitem = gtk_menu_item_new_with_label ("e");
4313   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 3, 2, 3);
4314   gtk_widget_show (menuitem);
4315   /* end of spanning submenu */
4316   
4317   menuitem = gtk_menu_item_new_with_label ("left");
4318   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, 1, j, j + 1);
4319   submenu = gtk_menu_new ();
4320   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4321   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4322   gtk_widget_show (menuitem);
4323
4324   menuitem = gtk_menu_item_new_with_label ("Empty");
4325   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4326   submenu = gtk_menu_new ();
4327   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4328   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4329   gtk_widget_show (menuitem);
4330
4331   menuitem = gtk_menu_item_new_with_label ("right");
4332   gtk_menu_attach (GTK_MENU (menu), menuitem, 1, 2, j, j + 1);
4333   submenu = gtk_menu_new ();
4334   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4335   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4336   gtk_widget_show (menuitem);
4337
4338   menuitem = gtk_menu_item_new_with_label ("Empty");
4339   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4340   gtk_widget_show (menuitem);
4341
4342   j++;
4343
4344   for (; j < rows; j++)
4345       for (i = 0; i < cols; i++)
4346       {
4347         sprintf (buf, "(%d %d)", i, j);
4348         menuitem = gtk_menu_item_new_with_label (buf);
4349         gtk_menu_attach (GTK_MENU (menu), menuitem, i, i + 1, j, j + 1);
4350         gtk_widget_show (menuitem);
4351       }
4352   
4353   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
4354   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 8);
4355   gtk_widget_show (menuitem);
4356   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
4357   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 2);
4358   gtk_widget_show (menuitem);
4359   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
4360   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 0);
4361   gtk_widget_show (menuitem);
4362   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
4363   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1);
4364   gtk_widget_show (menuitem);
4365   
4366   return menu;
4367 }
4368
4369 static void
4370 create_menus (GtkWidget *widget)
4371 {
4372   static GtkWidget *window = NULL;
4373   GtkWidget *box1;
4374   GtkWidget *box2;
4375   GtkWidget *button;
4376   GtkWidget *optionmenu;
4377   GtkWidget *separator;
4378   
4379   if (!window)
4380     {
4381       GtkWidget *menubar;
4382       GtkWidget *menu;
4383       GtkWidget *menuitem;
4384       GtkAccelGroup *accel_group;
4385       GtkWidget *image;
4386       GdkScreen *screen = gtk_widget_get_screen (widget);
4387       
4388       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4389
4390       gtk_window_set_screen (GTK_WINDOW (window), screen);
4391       
4392       g_signal_connect (window, "destroy",
4393                         G_CALLBACK (gtk_widget_destroyed),
4394                         &window);
4395       g_signal_connect (window, "delete-event",
4396                         G_CALLBACK (gtk_true),
4397                         NULL);
4398       
4399       accel_group = gtk_accel_group_new ();
4400       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4401
4402       gtk_window_set_title (GTK_WINDOW (window), "menus");
4403       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4404       
4405       
4406       box1 = gtk_vbox_new (FALSE, 0);
4407       gtk_container_add (GTK_CONTAINER (window), box1);
4408       gtk_widget_show (box1);
4409       
4410       menubar = gtk_menu_bar_new ();
4411       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
4412       gtk_widget_show (menubar);
4413       
4414       menu = create_menu (screen, 2, 50, TRUE);
4415       
4416       menuitem = gtk_menu_item_new_with_label ("test\nline2");
4417       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4418       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4419       gtk_widget_show (menuitem);
4420
4421       menu = create_table_menu (screen, 2, 50, TRUE);
4422       
4423       menuitem = gtk_menu_item_new_with_label ("table");
4424       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4425       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4426       gtk_widget_show (menuitem);
4427       
4428       menuitem = gtk_menu_item_new_with_label ("foo");
4429       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 3, 5, TRUE));
4430       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4431       gtk_widget_show (menuitem);
4432
4433       image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4434                                         GTK_ICON_SIZE_MENU);
4435       gtk_widget_show (image);
4436       menuitem = gtk_image_menu_item_new_with_label ("Help");
4437       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4438       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 4, 5, TRUE));
4439       gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
4440       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4441       gtk_widget_show (menuitem);
4442       
4443       menubar = gtk_menu_bar_new ();
4444       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
4445       gtk_widget_show (menubar);
4446       
4447       menu = create_menu (screen, 2, 10, TRUE);
4448       
4449       menuitem = gtk_menu_item_new_with_label ("Second menu bar");
4450       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4451       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4452       gtk_widget_show (menuitem);
4453       
4454       box2 = gtk_vbox_new (FALSE, 10);
4455       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4456       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
4457       gtk_widget_show (box2);
4458       
4459       menu = create_menu (screen, 1, 5, FALSE);
4460       gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);
4461
4462       menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
4463       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4464       gtk_widget_show (menuitem);
4465       
4466       menuitem = gtk_check_menu_item_new_with_label ("Accelerate Me");
4467       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4468       gtk_widget_show (menuitem);
4469       gtk_widget_add_accelerator (menuitem,
4470                                   "activate",
4471                                   accel_group,
4472                                   GDK_F1,
4473                                   0,
4474                                   GTK_ACCEL_VISIBLE);
4475       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
4476       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4477       gtk_widget_show (menuitem);
4478       gtk_widget_add_accelerator (menuitem,
4479                                   "activate",
4480                                   accel_group,
4481                                   GDK_F2,
4482                                   0,
4483                                   GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4484       menuitem = gtk_check_menu_item_new_with_label ("Accelerators Frozen");
4485       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4486       gtk_widget_show (menuitem);
4487       gtk_widget_add_accelerator (menuitem,
4488                                   "activate",
4489                                   accel_group,
4490                                   GDK_F2,
4491                                   0,
4492                                   GTK_ACCEL_VISIBLE);
4493       gtk_widget_add_accelerator (menuitem,
4494                                   "activate",
4495                                   accel_group,
4496                                   GDK_F3,
4497                                   0,
4498                                   GTK_ACCEL_VISIBLE);
4499       
4500       optionmenu = gtk_option_menu_new ();
4501       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
4502       gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), 3);
4503       gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
4504       gtk_widget_show (optionmenu);
4505
4506       separator = gtk_hseparator_new ();
4507       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4508       gtk_widget_show (separator);
4509
4510       box2 = gtk_vbox_new (FALSE, 10);
4511       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4512       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4513       gtk_widget_show (box2);
4514
4515       button = gtk_button_new_with_label ("close");
4516       g_signal_connect_swapped (button, "clicked",
4517                                 G_CALLBACK (gtk_widget_destroy),
4518                                 window);
4519       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4520       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4521       gtk_widget_grab_default (button);
4522       gtk_widget_show (button);
4523     }
4524
4525   if (!GTK_WIDGET_VISIBLE (window))
4526     gtk_widget_show (window);
4527   else
4528     gtk_widget_destroy (window);
4529 }
4530
4531 static void
4532 gtk_ifactory_cb (gpointer             callback_data,
4533                  guint                callback_action,
4534                  GtkWidget           *widget)
4535 {
4536   g_message ("ItemFactory: activated \"%s\"", gtk_item_factory_path_from_widget (widget));
4537 }
4538
4539 /* GdkPixbuf RGBA C-Source image dump */
4540
4541 static const guint8 apple[] = 
4542 { ""
4543   /* Pixbuf magic (0x47646b50) */
4544   "GdkP"
4545   /* length: header (24) + pixel_data (2304) */
4546   "\0\0\11\30"
4547   /* pixdata_type (0x1010002) */
4548   "\1\1\0\2"
4549   /* rowstride (96) */
4550   "\0\0\0`"
4551   /* width (24) */
4552   "\0\0\0\30"
4553   /* height (24) */
4554   "\0\0\0\30"
4555   /* pixel_data: */
4556   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4557   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4558   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4559   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4560   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4561   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4562   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\26\24"
4563   "\17\11\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4564   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`m"
4565   "[pn{a\344hv_\345_k[`\0\0\0\0\0\0\0\0\0\0\0\0D>/\305\0\0\0_\0\0\0\0\0"
4566   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4567   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`l[Blza\373s\202d\354w\206g\372p~c"
4568   "\374`l[y\0\0\0\0[S\77/\27\25\17\335\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0"
4569   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4570   "\0\0\0\0\0\0`l\\\20iw_\356y\211h\373x\207g\364~\216i\364u\204e\366gt"
4571   "_\374^jX\241A;-_\0\0\0~\0\0\0\0SM4)SM21B9&\22\320\270\204\1\320\270\204"
4572   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0eq"
4573   "]\212r\200c\366v\205f\371jx_\323_kY\232_kZH^jY\26]iW\211@G9\272:6%j\220"
4574   "\211]\320\221\211`\377\212\203Z\377~xP\377mkE\331]^;|/0\37\21\0\0\0\0"
4575   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ly`\40p~b\360lz`\353^kY\246["
4576   "eT<\216\200Z\203\227\211_\354\234\217c\377\232\217b\362\232\220c\337"
4577   "\243\233k\377\252\241p\377\250\236p\377\241\225h\377\231\214_\377\210"
4578   "\202U\377srI\377[]:\355KO0U\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0i"
4579   "v^\200`lY\211^jY\"\0\0\0\0\221\204\\\273\250\233r\377\302\267\224\377"
4580   "\311\300\237\377\272\256\204\377\271\256\177\377\271\257\200\377\267"
4581   "\260\177\377\260\251x\377\250\236l\377\242\225e\377\226\213]\377~zP\377"
4582   "ff@\377QT5\377LR2d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0]iW(\0\0\0\0\0\0\0"
4583   "\0\213\203[v\253\240t\377\334\326\301\377\344\340\317\377\321\312\253"
4584   "\377\303\271\217\377\300\270\213\377\277\267\210\377\272\264\203\377"
4585   "\261\255z\377\250\242n\377\243\232h\377\232\220`\377\210\202V\377nnE"
4586   "\377SW6\377RX6\364Za<\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0b]@\20"
4587   "\234\222e\362\304\274\232\377\337\333\306\377\332\325\273\377\311\302"
4588   "\232\377\312\303\236\377\301\273\216\377\300\271\212\377\270\264\200"
4589   "\377\256\253v\377\246\243n\377\236\232h\377\230\220`\377\213\203V\377"
4590   "wvL\377X]:\377KR0\377NU5v\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\212"
4591   "\203Zl\242\234l\377\321\315\260\377\331\324\271\377\320\313\251\377\307"
4592   "\301\232\377\303\276\224\377\300\272\214\377\274\267\206\377\264\260"
4593   "|\377\253\251s\377\244\243n\377\232\230e\377\223\216^\377\207\200U\377"
4594   "ttJ\377[_<\377HO/\377GN0\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4595   "\210\204Y\240\245\237o\377\316\310\253\377\310\303\237\377\304\300\230"
4596   "\377\303\277\225\377\277\272\216\377\274\270\210\377\266\263\200\377"
4597   "\256\254v\377\247\246p\377\237\236j\377\227\226d\377\215\212[\377\203"
4598   "\177T\377qsH\377X]8\377FN.\377DK-\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4599   "\0\0\0\0\207\204X\257\244\240o\377\300\275\231\377\301\275\226\377\274"
4600   "\270\213\377\274\270\214\377\267\264\205\377\264\262\200\377\260\256"
4601   "z\377\251\251s\377\243\244n\377\231\232g\377\220\222`\377\210\211Y\377"
4602   "|}Q\377hlC\377PU3\377CK,\377DL/Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4603   "\0\0\205\204X\220\232\230h\377\261\260\204\377\266\264\212\377\261\260"
4604   "\201\377\263\260\200\377\260\257}\377\256\256x\377\253\254t\377\244\246"
4605   "o\377\233\236i\377\221\224b\377\211\214\\\377\202\204V\377txM\377]b>"
4606   "\377HP0\377@H+\373CJ-\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0xxO>"
4607   "\215\215_\377\237\237r\377\247\247x\377\247\247t\377\252\252w\377\252"
4608   "\252u\377\252\253t\377\243\246o\377\235\240j\377\223\230c\377\213\217"
4609   "]\377\201\206V\377x}P\377gkD\377RY5\377BI,\377AI,\262\0\0\0\0\0\0\0\0"
4610   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\202\205W\312\216\220`\377\230"
4611   "\232g\377\234\236i\377\236\241l\377\241\244n\377\240\244m\377\232\237"
4612   "i\377\223\230c\377\212\221]\377\200\210W\377v|P\377jnG\377Za>\377HP2"
4613   "\377=D)\377HQ1:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4614   "\0wzQ6\177\201U\371\206\211Z\377\216\222`\377\220\225a\377\220\225b\377"
4615   "\220\226a\377\213\221_\377\204\213Z\377{\203R\377ryN\377iqH\377^fA\377"
4616   "R[;\377BJ-\3778@'\317\0\0\0>\0\0\0\36\0\0\0\7\0\0\0\0\0\0\0\0\0\0\0\0"
4617   "\0\0\0\0\0\0\0\0\0\0\0\0ptJTw|Q\371z\177R\377}\202T\377|\203T\377z\200"
4618   "R\377v|O\377pwL\377jpF\377dlB\377`hB\377Yb@\377LT6\377<C*\377\11\12\6"
4619   "\376\0\0\0\347\0\0\0\262\0\0\0Y\0\0\0\32\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4620   "\0\0\0\0\0\0\0\0\0\0\\`=UgnE\370hnG\377gmE\377djB\377]d>\377[c<\377Y"
4621   "b<\377Zc>\377V_>\377OW8\377BK/\377\16\20\12\377\0\0\0\377\0\0\0\377\0"
4622   "\0\0\374\0\0\0\320\0\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4623   "\0\1\0\0\0\40\22\24\15\260@D+\377W`;\377OV5\377.3\36\377.3\37\377IP0"
4624   "\377RZ7\377PZ8\3776=&\377\14\15\10\377\0\0\0\377\0\0\0\377\0\0\0\377"
4625   "\0\0\0\347\0\0\0\217\0\0\0""4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4626   "\0\0\0\0\0\0\0\20\0\0\0P\0\0\0\252\7\10\5\346\7\7\5\375\0\0\0\377\0\0"
4627   "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\374\0"
4628   "\0\0\336\0\0\0\254\0\0\0i\0\0\0""2\0\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0"
4629   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11\0\0\0\40\0\0\0D\0\0\0m\0\0\0"
4630   "\226\0\0\0\234\0\0\0\234\0\0\0\244\0\0\0\246\0\0\0\232\0\0\0\202\0\0"
4631   "\0i\0\0\0T\0\0\0,\0\0\0\15\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4632   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\6\0\0\0"
4633   "\16\0\0\0\22\0\0\0\24\0\0\0\23\0\0\0\17\0\0\0\14\0\0\0\13\0\0\0\10\0"
4634   "\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
4635
4636
4637 static void
4638 dump_accels (gpointer             callback_data,
4639              guint                callback_action,
4640              GtkWidget           *widget)
4641 {
4642   gtk_accel_map_save_fd (1 /* stdout */);
4643 }
4644     
4645 static GtkItemFactoryEntry menu_items[] =
4646 {
4647   { "/_File",                  NULL,         NULL,                  0, "<Branch>" },
4648   { "/File/tearoff1",          NULL,         gtk_ifactory_cb,       0, "<Tearoff>" },
4649   { "/File/_New",              NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_NEW },
4650   { "/File/_Open",             NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_OPEN },
4651   { "/File/_Save",             NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
4652   { "/File/Save _As...",       "<control>A", gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
4653   { "/File/_Dump \"_Accels\"",  NULL,        dump_accels,           0 },
4654   { "/File/\\/Test__Escaping/And\\/\n\tWei\\\\rdly",
4655                                 NULL,        gtk_ifactory_cb,       0 },
4656   { "/File/sep1",        NULL,               gtk_ifactory_cb,       0, "<Separator>" },
4657   { "/File/_Quit",       NULL,               gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_QUIT },
4658
4659   { "/_Preferences",                    NULL, 0,               0, "<Branch>" },
4660   { "/_Preferences/_Color",             NULL, 0,               0, "<Branch>" },
4661   { "/_Preferences/Color/_Red",         NULL, gtk_ifactory_cb, 0, "<RadioItem>" },
4662   { "/_Preferences/Color/_Green",       NULL, gtk_ifactory_cb, 0, "/Preferences/Color/Red" },
4663   { "/_Preferences/Color/_Blue",        NULL, gtk_ifactory_cb, 0, "/Preferences/Color/Red" },
4664   { "/_Preferences/_Shape",             NULL, 0,               0, "<Branch>" },
4665   { "/_Preferences/Shape/_Square",      NULL, gtk_ifactory_cb, 0, "<RadioItem>" },
4666   { "/_Preferences/Shape/_Rectangle",   NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Square" },
4667   { "/_Preferences/Shape/_Oval",        NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Rectangle" },
4668   { "/_Preferences/Shape/_Rectangle",   NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Square" },
4669   { "/_Preferences/Shape/_Oval",        NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Rectangle" },
4670   { "/_Preferences/Shape/_Image",       NULL, gtk_ifactory_cb, 0, "<ImageItem>", apple },
4671   { "/_Preferences/Coffee",                  NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4672   { "/_Preferences/Toast",                   NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4673   { "/_Preferences/Marshmallow Froot Loops", NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4674
4675   /* For testing deletion of menus */
4676   { "/_Preferences/Should_NotAppear",          NULL, 0,               0, "<Branch>" },
4677   { "/Preferences/ShouldNotAppear/SubItem1",   NULL, gtk_ifactory_cb, 0 },
4678   { "/Preferences/ShouldNotAppear/SubItem2",   NULL, gtk_ifactory_cb, 0 },
4679
4680   { "/_Help",            NULL,         0,                     0, "<LastBranch>" },
4681   { "/Help/_Help",       NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_HELP},
4682   { "/Help/_About",      NULL,         gtk_ifactory_cb,       0 },
4683 };
4684
4685
4686 static int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
4687
4688 static void
4689 create_item_factory (GtkWidget *widget)
4690 {
4691   static GtkWidget *window = NULL;
4692   
4693   if (!window)
4694     {
4695       GtkWidget *box1;
4696       GtkWidget *box2;
4697       GtkWidget *separator;
4698       GtkWidget *label;
4699       GtkWidget *button;
4700       GtkAccelGroup *accel_group;
4701       GtkItemFactory *item_factory;
4702       GtkTooltips *tooltips;
4703       
4704       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4705       
4706       gtk_window_set_screen (GTK_WINDOW (window),
4707                              gtk_widget_get_screen (widget));
4708       
4709       g_signal_connect (window, "destroy",
4710                         G_CALLBACK(gtk_widget_destroyed),
4711                         &window);
4712       g_signal_connect (window, "delete-event",
4713                         G_CALLBACK (gtk_true),
4714                         NULL);
4715       
4716       accel_group = gtk_accel_group_new ();
4717       item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
4718       g_object_set_data_full (G_OBJECT (window),
4719                               "<main>",
4720                               item_factory,
4721                               g_object_unref);
4722       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4723       gtk_window_set_title (GTK_WINDOW (window), "Item Factory");
4724       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4725       gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
4726
4727       /* preselect /Preferences/Shape/Oval over the other radios
4728        */
4729       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4730                                                                                       "/Preferences/Shape/Oval")),
4731                                       TRUE);
4732
4733       /* preselect /Preferences/Coffee
4734        */
4735       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4736                                                                                       "/Preferences/Coffee")),
4737                                       TRUE);
4738
4739       /* preselect /Preferences/Marshmallow Froot Loops and set it insensitive
4740        */
4741       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4742                                                                                       "/Preferences/Marshmallow Froot Loops")),
4743                                       TRUE);
4744       gtk_widget_set_sensitive (GTK_WIDGET (gtk_item_factory_get_item (item_factory,
4745                                                                        "/Preferences/Marshmallow Froot Loops")),
4746                                 FALSE);
4747        
4748       /* Test how tooltips (ugh) work on menu items
4749        */
4750       tooltips = gtk_tooltips_new ();
4751       g_object_ref (tooltips);
4752       gtk_object_sink (GTK_OBJECT (tooltips));
4753       g_object_set_data_full (G_OBJECT (window), "testgtk-tooltips",
4754                               tooltips, (GDestroyNotify)g_object_unref);
4755       
4756       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/New"),
4757                             "Create a new file", NULL);
4758       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/Open"),
4759                             "Open a file", NULL);
4760       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/Save"),
4761                             "Safe file", NULL);
4762       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/Preferences/Color"),
4763                             "Modify color", NULL);
4764
4765       box1 = gtk_vbox_new (FALSE, 0);
4766       gtk_container_add (GTK_CONTAINER (window), box1);
4767       
4768       gtk_box_pack_start (GTK_BOX (box1),
4769                           gtk_item_factory_get_widget (item_factory, "<main>"),
4770                           FALSE, FALSE, 0);
4771
4772       label = gtk_label_new ("Type\n<alt>\nto start");
4773       gtk_widget_set_size_request (label, 200, 200);
4774       gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
4775       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
4776
4777
4778       separator = gtk_hseparator_new ();
4779       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4780
4781
4782       box2 = gtk_vbox_new (FALSE, 10);
4783       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4784       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4785
4786       button = gtk_button_new_with_label ("close");
4787       g_signal_connect_swapped (button, "clicked",
4788                                 G_CALLBACK (gtk_widget_destroy),
4789                                 window);
4790       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4791       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4792       gtk_widget_grab_default (button);
4793
4794       gtk_item_factory_delete_item (item_factory, "/Preferences/ShouldNotAppear");
4795       
4796       gtk_widget_show_all (window);
4797     }
4798   else
4799     gtk_widget_destroy (window);
4800 }
4801
4802 static GtkWidget *
4803 accel_button_new (GtkAccelGroup *accel_group,
4804                   const gchar   *text,
4805                   const gchar   *accel)
4806 {
4807   guint keyval;
4808   GdkModifierType modifiers;
4809   GtkWidget *button;
4810   GtkWidget *label;
4811
4812   gtk_accelerator_parse (accel, &keyval, &modifiers);
4813   g_assert (keyval);
4814
4815   button = gtk_button_new ();
4816   gtk_widget_add_accelerator (button, "activate", accel_group,
4817                               keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4818
4819   label = gtk_accel_label_new (text);
4820   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
4821   gtk_widget_show (label);
4822   
4823   gtk_container_add (GTK_CONTAINER (button), label);
4824
4825   return button;
4826 }
4827
4828 static void
4829 create_key_lookup (GtkWidget *widget)
4830 {
4831   static GtkWidget *window = NULL;
4832   gpointer window_ptr;
4833
4834   if (!window)
4835     {
4836       GtkAccelGroup *accel_group = gtk_accel_group_new ();
4837       GtkWidget *button;
4838       
4839       window = gtk_dialog_new_with_buttons ("Key Lookup", NULL, 0,
4840                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
4841                                             NULL);
4842
4843       gtk_window_set_screen (GTK_WINDOW (window),
4844                              gtk_widget_get_screen (widget));
4845
4846       /* We have to expand it so the accel labels will draw their labels
4847        */
4848       gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
4849       
4850       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4851       
4852       button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
4853       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4854       button = gtk_button_new_with_mnemonic ("Button 2 (_A)");
4855       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4856       button = gtk_button_new_with_mnemonic ("Button 3 (_\321\204)");
4857       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4858       button = gtk_button_new_with_mnemonic ("Button 4 (_\320\244)");
4859       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4860       button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
4861       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4862       button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
4863       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4864       button = accel_button_new (accel_group, "Button 8", "<Alt>d");
4865       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4866       button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
4867       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4868       button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
4869       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4870       button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
4871       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4872       button = accel_button_new (accel_group, "Button 12", "<Super>a");
4873       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4874       button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
4875       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4876       button = accel_button_new (accel_group, "Button 14", "<Meta>a");
4877       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4878       button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
4879       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4880
4881       window_ptr = &window;
4882       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
4883       g_signal_connect (window, "response", G_CALLBACK (gtk_object_destroy), NULL);
4884
4885       gtk_widget_show_all (window);
4886     }
4887   else
4888     gtk_widget_destroy (window);
4889 }
4890
4891
4892 /*
4893  create_modal_window
4894  */
4895
4896 static gboolean
4897 cmw_destroy_cb(GtkWidget *widget)
4898 {
4899   /* This is needed to get out of gtk_main */
4900   gtk_main_quit ();
4901
4902   return FALSE;
4903 }
4904
4905 static void
4906 cmw_color (GtkWidget *widget, GtkWidget *parent)
4907 {
4908     GtkWidget *csd;
4909
4910     csd = gtk_color_selection_dialog_new ("This is a modal color selection dialog");
4911
4912     gtk_window_set_screen (GTK_WINDOW (csd), gtk_widget_get_screen (parent));
4913
4914     gtk_color_selection_set_has_palette (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (csd)->colorsel),
4915                                          TRUE);
4916     
4917     /* Set as modal */
4918     gtk_window_set_modal (GTK_WINDOW(csd),TRUE);
4919
4920     /* And mark it as a transient dialog */
4921     gtk_window_set_transient_for (GTK_WINDOW (csd), GTK_WINDOW (parent));
4922     
4923     g_signal_connect (csd, "destroy",
4924                       G_CALLBACK (cmw_destroy_cb), NULL);
4925
4926     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->ok_button,
4927                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4928     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->cancel_button,
4929                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4930     
4931     /* wait until destroy calls gtk_main_quit */
4932     gtk_widget_show (csd);    
4933     gtk_main ();
4934 }
4935
4936 static void
4937 cmw_file (GtkWidget *widget, GtkWidget *parent)
4938 {
4939     GtkWidget *fs;
4940
4941     fs = gtk_file_selection_new("This is a modal file selection dialog");
4942
4943     gtk_window_set_screen (GTK_WINDOW (fs), gtk_widget_get_screen (parent));
4944
4945     /* Set as modal */
4946     gtk_window_set_modal (GTK_WINDOW(fs),TRUE);
4947
4948     /* And mark it as a transient dialog */
4949     gtk_window_set_transient_for (GTK_WINDOW (fs), GTK_WINDOW (parent));
4950
4951     g_signal_connect (fs, "destroy",
4952                       G_CALLBACK (cmw_destroy_cb), NULL);
4953
4954     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->ok_button,
4955                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4956     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->cancel_button,
4957                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4958     
4959     /* wait until destroy calls gtk_main_quit */
4960     gtk_widget_show (fs);
4961     
4962     gtk_main();
4963 }
4964
4965
4966 static void
4967 create_modal_window (GtkWidget *widget)
4968 {
4969   GtkWidget *window = NULL;
4970   GtkWidget *box1,*box2;
4971   GtkWidget *frame1;
4972   GtkWidget *btnColor,*btnFile,*btnClose;
4973
4974   /* Create modal window (Here you can use any window descendent )*/
4975   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4976   gtk_window_set_screen (GTK_WINDOW (window),
4977                          gtk_widget_get_screen (widget));
4978
4979   gtk_window_set_title (GTK_WINDOW(window),"This window is modal");
4980
4981   /* Set window as modal */
4982   gtk_window_set_modal (GTK_WINDOW(window),TRUE);
4983
4984   /* Create widgets */
4985   box1 = gtk_vbox_new (FALSE,5);
4986   frame1 = gtk_frame_new ("Standard dialogs in modal form");
4987   box2 = gtk_vbox_new (TRUE,5);
4988   btnColor = gtk_button_new_with_label ("Color");
4989   btnFile = gtk_button_new_with_label ("File Selection");
4990   btnClose = gtk_button_new_with_label ("Close");
4991
4992   /* Init widgets */
4993   gtk_container_set_border_width (GTK_CONTAINER (box1), 3);
4994   gtk_container_set_border_width (GTK_CONTAINER (box2), 3);
4995     
4996   /* Pack widgets */
4997   gtk_container_add (GTK_CONTAINER (window), box1);
4998   gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4);
4999   gtk_container_add (GTK_CONTAINER (frame1), box2);
5000   gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4);
5001   gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4);
5002   gtk_box_pack_start (GTK_BOX (box1), gtk_hseparator_new (), FALSE, FALSE, 4);
5003   gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4);
5004    
5005   /* connect signals */
5006   g_signal_connect_swapped (btnClose, "clicked",
5007                             G_CALLBACK (gtk_widget_destroy), window);
5008
5009   g_signal_connect (window, "destroy",
5010                     G_CALLBACK (cmw_destroy_cb), NULL);
5011   
5012   g_signal_connect (btnColor, "clicked",
5013                     G_CALLBACK (cmw_color), window);
5014   g_signal_connect (btnFile, "clicked",
5015                     G_CALLBACK (cmw_file), window);
5016
5017   /* Show widgets */
5018   gtk_widget_show_all (window);
5019
5020   /* wait until dialog get destroyed */
5021   gtk_main();
5022 }
5023
5024 /*
5025  * GtkMessageDialog
5026  */
5027
5028 static void
5029 make_message_dialog (GdkScreen *screen,
5030                      GtkWidget **dialog,
5031                      GtkMessageType  type,
5032                      GtkButtonsType  buttons,
5033                      guint           default_response)
5034 {
5035   if (*dialog)
5036     {
5037       gtk_widget_destroy (*dialog);
5038
5039       return;
5040     }
5041
5042   *dialog = gtk_message_dialog_new (NULL, 0, type, buttons,
5043                                     "This is a message dialog; it can wrap long lines. This is a long line. La la la. Look this line is wrapped. Blah blah blah blah blah blah. (Note: testgtk has a nonstandard gtkrc that changes some of the message dialog icons.)");
5044
5045   gtk_window_set_screen (GTK_WINDOW (*dialog), screen);
5046
5047   g_signal_connect_swapped (*dialog,
5048                             "response",
5049                             G_CALLBACK (gtk_widget_destroy),
5050                             *dialog);
5051   
5052   g_signal_connect (*dialog,
5053                     "destroy",
5054                     G_CALLBACK (gtk_widget_destroyed),
5055                     dialog);
5056
5057   gtk_dialog_set_default_response (GTK_DIALOG (*dialog), default_response);
5058
5059   gtk_widget_show (*dialog);
5060 }
5061
5062 static void
5063 create_message_dialog (GtkWidget *widget)
5064 {
5065   static GtkWidget *info = NULL;
5066   static GtkWidget *warning = NULL;
5067   static GtkWidget *error = NULL;
5068   static GtkWidget *question = NULL;
5069   GdkScreen *screen = gtk_widget_get_screen (widget);
5070
5071   make_message_dialog (screen, &info, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, GTK_RESPONSE_OK);
5072   make_message_dialog (screen, &warning, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE);
5073   make_message_dialog (screen, &error, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK);
5074   make_message_dialog (screen, &question, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, GTK_RESPONSE_NO);
5075 }
5076
5077 /*
5078  * GtkScrolledWindow
5079  */
5080
5081 static GtkWidget *sw_parent = NULL;
5082 static GtkWidget *sw_float_parent;
5083 static guint sw_destroyed_handler = 0;
5084
5085 static gboolean
5086 scrolled_windows_delete_cb (GtkWidget *widget, GdkEventAny *event, GtkWidget *scrollwin)
5087 {
5088   gtk_widget_reparent (scrollwin, sw_parent);
5089   
5090   g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
5091   sw_float_parent = NULL;
5092   sw_parent = NULL;
5093   sw_destroyed_handler = 0;
5094
5095   return FALSE;
5096 }
5097
5098 static void
5099 scrolled_windows_destroy_cb (GtkWidget *widget, GtkWidget *scrollwin)
5100 {
5101   gtk_widget_destroy (sw_float_parent);
5102
5103   sw_float_parent = NULL;
5104   sw_parent = NULL;
5105   sw_destroyed_handler = 0;
5106 }
5107
5108 static void
5109 scrolled_windows_remove (GtkWidget *widget, GtkWidget *scrollwin)
5110 {
5111   if (sw_parent)
5112     {
5113       gtk_widget_reparent (scrollwin, sw_parent);
5114       gtk_widget_destroy (sw_float_parent);
5115
5116       g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
5117       sw_float_parent = NULL;
5118       sw_parent = NULL;
5119       sw_destroyed_handler = 0;
5120     }
5121   else
5122     {
5123       sw_parent = scrollwin->parent;
5124       sw_float_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5125       gtk_window_set_screen (GTK_WINDOW (sw_float_parent),
5126                              gtk_widget_get_screen (widget));
5127       
5128       gtk_window_set_default_size (GTK_WINDOW (sw_float_parent), 200, 200);
5129       
5130       gtk_widget_reparent (scrollwin, sw_float_parent);
5131       gtk_widget_show (sw_float_parent);
5132
5133       sw_destroyed_handler =
5134         g_signal_connect (sw_parent, "destroy",
5135                           G_CALLBACK (scrolled_windows_destroy_cb), scrollwin);
5136       g_signal_connect (sw_float_parent, "delete_event",
5137                         G_CALLBACK (scrolled_windows_delete_cb), scrollwin);
5138     }
5139 }
5140
5141 static void
5142 create_scrolled_windows (GtkWidget *widget)
5143 {
5144   static GtkWidget *window;
5145   GtkWidget *scrolled_window;
5146   GtkWidget *table;
5147   GtkWidget *button;
5148   char buffer[32];
5149   int i, j;
5150
5151   if (!window)
5152     {
5153       window = gtk_dialog_new ();
5154
5155       gtk_window_set_screen (GTK_WINDOW (window),
5156                              gtk_widget_get_screen (widget));
5157
5158       g_signal_connect (window, "destroy",
5159                         G_CALLBACK (gtk_widget_destroyed),
5160                         &window);
5161
5162       gtk_window_set_title (GTK_WINDOW (window), "dialog");
5163       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5164
5165
5166       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
5167       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
5168       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
5169                                       GTK_POLICY_AUTOMATIC,
5170                                       GTK_POLICY_AUTOMATIC);
5171       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5172                           scrolled_window, TRUE, TRUE, 0);
5173       gtk_widget_show (scrolled_window);
5174
5175       table = gtk_table_new (20, 20, FALSE);
5176       gtk_table_set_row_spacings (GTK_TABLE (table), 10);
5177       gtk_table_set_col_spacings (GTK_TABLE (table), 10);
5178       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
5179       gtk_container_set_focus_hadjustment (GTK_CONTAINER (table),
5180                                            gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
5181       gtk_container_set_focus_vadjustment (GTK_CONTAINER (table),
5182                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
5183       gtk_widget_show (table);
5184
5185       for (i = 0; i < 20; i++)
5186         for (j = 0; j < 20; j++)
5187           {
5188             sprintf (buffer, "button (%d,%d)\n", i, j);
5189             button = gtk_toggle_button_new_with_label (buffer);
5190             gtk_table_attach_defaults (GTK_TABLE (table), button,
5191                                        i, i+1, j, j+1);
5192             gtk_widget_show (button);
5193           }
5194
5195
5196       button = gtk_button_new_with_label ("Close");
5197       g_signal_connect_swapped (button, "clicked",
5198                                 G_CALLBACK (gtk_widget_destroy),
5199                                 window);
5200       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5201       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5202                           button, TRUE, TRUE, 0);
5203       gtk_widget_grab_default (button);
5204       gtk_widget_show (button);
5205
5206       button = gtk_button_new_with_label ("Reparent Out");
5207       g_signal_connect (button, "clicked",
5208                         G_CALLBACK (scrolled_windows_remove),
5209                         scrolled_window);
5210       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5211       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5212                           button, TRUE, TRUE, 0);
5213       gtk_widget_grab_default (button);
5214       gtk_widget_show (button);
5215
5216       gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
5217     }
5218
5219   if (!GTK_WIDGET_VISIBLE (window))
5220     gtk_widget_show (window);
5221   else
5222     gtk_widget_destroy (window);
5223 }
5224
5225 /*
5226  * GtkEntry
5227  */
5228
5229 static void
5230 entry_toggle_frame (GtkWidget *checkbutton,
5231                     GtkWidget *entry)
5232 {
5233    gtk_entry_set_has_frame (GTK_ENTRY(entry),
5234                             GTK_TOGGLE_BUTTON(checkbutton)->active);
5235 }
5236
5237 static void
5238 entry_toggle_sensitive (GtkWidget *checkbutton,
5239                         GtkWidget *entry)
5240 {
5241    gtk_widget_set_sensitive (entry, GTK_TOGGLE_BUTTON(checkbutton)->active);
5242 }
5243
5244 static gboolean
5245 entry_progress_timeout (gpointer data)
5246 {
5247   if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "progress-pulse")))
5248     {
5249       gtk_entry_progress_pulse (GTK_ENTRY (data));
5250     }
5251   else
5252     {
5253       gdouble fraction;
5254
5255       fraction = gtk_entry_get_progress_fraction (GTK_ENTRY (data));
5256
5257       fraction += 0.05;
5258       if (fraction > 1.0001)
5259         fraction = 0.0;
5260
5261       gtk_entry_set_progress_fraction (GTK_ENTRY (data), fraction);
5262     }
5263
5264   return TRUE;
5265 }
5266
5267 static void
5268 entry_remove_timeout (gpointer data)
5269 {
5270   g_source_remove (GPOINTER_TO_UINT (data));
5271 }
5272
5273 static void
5274 entry_toggle_progress (GtkWidget *checkbutton,
5275                        GtkWidget *entry)
5276 {
5277   if (GTK_TOGGLE_BUTTON (checkbutton)->active)
5278     {
5279       guint timeout = gdk_threads_add_timeout (100,
5280                                                entry_progress_timeout,
5281                                                entry);
5282       g_object_set_data_full (G_OBJECT (entry), "timeout-id",
5283                               GUINT_TO_POINTER (timeout),
5284                               entry_remove_timeout);
5285     }
5286   else
5287     {
5288       g_object_set_data (G_OBJECT (entry), "timeout-id",
5289                          GUINT_TO_POINTER (0));
5290
5291       gtk_entry_set_progress_fraction (GTK_ENTRY (entry), 0.0);
5292     }
5293 }
5294
5295 static void
5296 entry_toggle_pulse (GtkWidget *checkbutton,
5297                     GtkWidget *entry)
5298 {
5299   g_object_set_data (G_OBJECT (entry), "progress-pulse",
5300                      GUINT_TO_POINTER ((guint) GTK_TOGGLE_BUTTON (checkbutton)->active));
5301 }
5302
5303 static void
5304 entry_props_clicked (GtkWidget *button,
5305                      GObject   *entry)
5306 {
5307   GtkWidget *window = create_prop_editor (entry, 0);
5308
5309   gtk_window_set_title (GTK_WINDOW (window), "Entry Properties");
5310 }
5311
5312 static void
5313 create_entry (GtkWidget *widget)
5314 {
5315   static GtkWidget *window = NULL;
5316   GtkWidget *box1;
5317   GtkWidget *box2;
5318   GtkWidget *hbox;
5319   GtkWidget *has_frame_check;
5320   GtkWidget *sensitive_check;
5321   GtkWidget *progress_check;
5322   GtkWidget *entry, *cb;
5323   GtkWidget *button;
5324   GtkWidget *separator;
5325   GList *cbitems = NULL;
5326
5327   if (!window)
5328     {
5329       cbitems = g_list_append(cbitems, "item0");
5330       cbitems = g_list_append(cbitems, "item1 item1");
5331       cbitems = g_list_append(cbitems, "item2 item2 item2");
5332       cbitems = g_list_append(cbitems, "item3 item3 item3 item3");
5333       cbitems = g_list_append(cbitems, "item4 item4 item4 item4 item4");
5334       cbitems = g_list_append(cbitems, "item5 item5 item5 item5 item5 item5");
5335       cbitems = g_list_append(cbitems, "item6 item6 item6 item6 item6");
5336       cbitems = g_list_append(cbitems, "item7 item7 item7 item7");
5337       cbitems = g_list_append(cbitems, "item8 item8 item8");
5338       cbitems = g_list_append(cbitems, "item9 item9");
5339
5340       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5341       gtk_window_set_screen (GTK_WINDOW (window),
5342                              gtk_widget_get_screen (widget));
5343
5344       g_signal_connect (window, "destroy",
5345                         G_CALLBACK (gtk_widget_destroyed),
5346                         &window);
5347
5348       gtk_window_set_title (GTK_WINDOW (window), "entry");
5349       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5350
5351
5352       box1 = gtk_vbox_new (FALSE, 0);
5353       gtk_container_add (GTK_CONTAINER (window), box1);
5354
5355
5356       box2 = gtk_vbox_new (FALSE, 10);
5357       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5358       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
5359
5360       hbox = gtk_hbox_new (FALSE, 5);
5361       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
5362       
5363       entry = gtk_entry_new ();
5364       gtk_entry_set_text (GTK_ENTRY (entry), "hello world \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205");
5365       gtk_editable_select_region (GTK_EDITABLE (entry), 0, 5);
5366       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
5367
5368       button = gtk_button_new_with_mnemonic ("_Props");
5369       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
5370       g_signal_connect (button, "clicked",
5371                         G_CALLBACK (entry_props_clicked),
5372                         entry);
5373
5374       cb = gtk_combo_new ();
5375       gtk_combo_set_popdown_strings (GTK_COMBO (cb), cbitems);
5376       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO(cb)->entry), "hello world \n\n\n foo");
5377       gtk_editable_select_region (GTK_EDITABLE (GTK_COMBO(cb)->entry),
5378                                   0, -1);
5379       gtk_box_pack_start (GTK_BOX (box2), cb, TRUE, TRUE, 0);
5380
5381       sensitive_check = gtk_check_button_new_with_label("Sensitive");
5382       gtk_box_pack_start (GTK_BOX (box2), sensitive_check, FALSE, TRUE, 0);
5383       g_signal_connect (sensitive_check, "toggled",
5384                         G_CALLBACK (entry_toggle_sensitive), entry);
5385       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sensitive_check), TRUE);
5386
5387       has_frame_check = gtk_check_button_new_with_label("Has Frame");
5388       gtk_box_pack_start (GTK_BOX (box2), has_frame_check, FALSE, TRUE, 0);
5389       g_signal_connect (has_frame_check, "toggled",
5390                         G_CALLBACK (entry_toggle_frame), entry);
5391       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (has_frame_check), TRUE);
5392
5393       progress_check = gtk_check_button_new_with_label("Show Progress");
5394       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
5395       g_signal_connect (progress_check, "toggled",
5396                         G_CALLBACK (entry_toggle_progress), entry);
5397
5398       progress_check = gtk_check_button_new_with_label("Pulse Progress");
5399       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
5400       g_signal_connect (progress_check, "toggled",
5401                         G_CALLBACK (entry_toggle_pulse), entry);
5402
5403       separator = gtk_hseparator_new ();
5404       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5405
5406       box2 = gtk_vbox_new (FALSE, 10);
5407       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5408       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5409
5410       button = gtk_button_new_with_label ("close");
5411       g_signal_connect_swapped (button, "clicked",
5412                                 G_CALLBACK (gtk_widget_destroy),
5413                                 window);
5414       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5415       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5416       gtk_widget_grab_default (button);
5417     }
5418
5419   if (!GTK_WIDGET_VISIBLE (window))
5420     gtk_widget_show_all (window);
5421   else
5422     gtk_widget_destroy (window);
5423 }
5424
5425 static void
5426 create_expander (GtkWidget *widget)
5427 {
5428   GtkWidget *box1;
5429   GtkWidget *expander;
5430   GtkWidget *hidden;
5431   static GtkWidget *window = NULL;
5432
5433   if (!window)
5434     {
5435       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5436       gtk_window_set_screen (GTK_WINDOW (window),
5437                              gtk_widget_get_screen (widget));
5438       
5439       g_signal_connect (window, "destroy",
5440                         G_CALLBACK (gtk_widget_destroyed),
5441                         &window);
5442       
5443       gtk_window_set_title (GTK_WINDOW (window), "expander");
5444       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5445       
5446       box1 = gtk_vbox_new (FALSE, 0);
5447       gtk_container_add (GTK_CONTAINER (window), box1);
5448       
5449       expander = gtk_expander_new ("The Hidden");
5450       
5451       gtk_box_pack_start (GTK_BOX (box1), expander, TRUE, TRUE, 0);
5452       
5453       hidden = gtk_label_new ("Revealed!");
5454       
5455       gtk_container_add (GTK_CONTAINER (expander), hidden);
5456     }
5457   
5458   if (!GTK_WIDGET_VISIBLE (window))
5459     gtk_widget_show_all (window);
5460   else
5461     gtk_widget_destroy (window);
5462 }
5463
5464
5465 /* GtkEventBox */
5466
5467
5468 static void
5469 event_box_label_pressed (GtkWidget        *widget,
5470                          GdkEventButton   *event,
5471                          gpointer user_data)
5472 {
5473   g_print ("clicked on event box\n");
5474 }
5475
5476 static void
5477 event_box_button_clicked (GtkWidget *widget,
5478                           GtkWidget *button,
5479                           gpointer user_data)
5480 {
5481   g_print ("pushed button\n");
5482 }
5483
5484 static void
5485 event_box_toggle_visible_window (GtkWidget *checkbutton,
5486                                  GtkEventBox *event_box)
5487 {
5488   gtk_event_box_set_visible_window (event_box,
5489                                     GTK_TOGGLE_BUTTON(checkbutton)->active);
5490 }
5491
5492 static void
5493 event_box_toggle_above_child (GtkWidget *checkbutton,
5494                               GtkEventBox *event_box)
5495 {
5496   gtk_event_box_set_above_child (event_box,
5497                                  GTK_TOGGLE_BUTTON(checkbutton)->active);
5498 }
5499
5500 static void
5501 create_event_box (GtkWidget *widget)
5502 {
5503   static GtkWidget *window = NULL;
5504   GtkWidget *box1;
5505   GtkWidget *box2;
5506   GtkWidget *hbox;
5507   GtkWidget *vbox;
5508   GtkWidget *button;
5509   GtkWidget *separator;
5510   GtkWidget *event_box;
5511   GtkWidget *label;
5512   GtkWidget *visible_window_check;
5513   GtkWidget *above_child_check;
5514   GdkColor color;
5515
5516   if (!window)
5517     {
5518       color.red = 0;
5519       color.blue = 65535;
5520       color.green = 0;
5521       
5522       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5523       gtk_window_set_screen (GTK_WINDOW (window),
5524                              gtk_widget_get_screen (widget));
5525
5526       g_signal_connect (window, "destroy",
5527                         G_CALLBACK (gtk_widget_destroyed),
5528                         &window);
5529
5530       gtk_window_set_title (GTK_WINDOW (window), "event box");
5531       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5532
5533       box1 = gtk_vbox_new (FALSE, 0);
5534       gtk_container_add (GTK_CONTAINER (window), box1);
5535       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &color);
5536
5537       hbox = gtk_hbox_new (FALSE, 0);
5538       gtk_box_pack_start (GTK_BOX (box1), hbox, TRUE, FALSE, 0);
5539       
5540       event_box = gtk_event_box_new ();
5541       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, FALSE, 0);
5542
5543       vbox = gtk_vbox_new (FALSE, 0);
5544       gtk_container_add (GTK_CONTAINER (event_box), vbox);
5545       g_signal_connect (event_box, "button_press_event",
5546                         G_CALLBACK (event_box_label_pressed),
5547                         NULL);
5548       
5549       label = gtk_label_new ("Click on this label");
5550       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);
5551
5552       button = gtk_button_new_with_label ("button in eventbox");
5553       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, FALSE, 0);
5554       g_signal_connect (button, "clicked",
5555                         G_CALLBACK (event_box_button_clicked),
5556                         NULL);
5557       
5558
5559       visible_window_check = gtk_check_button_new_with_label("Visible Window");
5560       gtk_box_pack_start (GTK_BOX (box1), visible_window_check, FALSE, TRUE, 0);
5561       g_signal_connect (visible_window_check, "toggled",
5562                         G_CALLBACK (event_box_toggle_visible_window), event_box);
5563       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (visible_window_check), FALSE);
5564       
5565       above_child_check = gtk_check_button_new_with_label("Above Child");
5566       gtk_box_pack_start (GTK_BOX (box1), above_child_check, FALSE, TRUE, 0);
5567       g_signal_connect (above_child_check, "toggled",
5568                         G_CALLBACK (event_box_toggle_above_child), event_box);
5569       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (above_child_check), FALSE);
5570       
5571       separator = gtk_hseparator_new ();
5572       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5573
5574       box2 = gtk_vbox_new (FALSE, 10);
5575       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5576       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5577
5578       button = gtk_button_new_with_label ("close");
5579       g_signal_connect_swapped (button, "clicked",
5580                                 G_CALLBACK (gtk_widget_destroy),
5581                                 window);
5582       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5583       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5584       gtk_widget_grab_default (button);
5585     }
5586
5587   if (!GTK_WIDGET_VISIBLE (window))
5588     gtk_widget_show_all (window);
5589   else
5590     gtk_widget_destroy (window);
5591 }
5592
5593
5594 /*
5595  * GtkSizeGroup
5596  */
5597
5598 #define SIZE_GROUP_INITIAL_SIZE 50
5599
5600 static void
5601 size_group_hsize_changed (GtkSpinButton *spin_button,
5602                           GtkWidget     *button)
5603 {
5604   gtk_widget_set_size_request (GTK_BIN (button)->child,
5605                                gtk_spin_button_get_value_as_int (spin_button),
5606                                -1);
5607 }
5608
5609 static void
5610 size_group_vsize_changed (GtkSpinButton *spin_button,
5611                           GtkWidget     *button)
5612 {
5613   gtk_widget_set_size_request (GTK_BIN (button)->child,
5614                                -1,
5615                                gtk_spin_button_get_value_as_int (spin_button));
5616 }
5617
5618 static GtkWidget *
5619 create_size_group_window (GdkScreen    *screen,
5620                           GtkSizeGroup *master_size_group)
5621 {
5622   GtkWidget *window;
5623   GtkWidget *table;
5624   GtkWidget *main_button;
5625   GtkWidget *button;
5626   GtkWidget *spin_button;
5627   GtkWidget *hbox;
5628   GtkSizeGroup *hgroup1;
5629   GtkSizeGroup *hgroup2;
5630   GtkSizeGroup *vgroup1;
5631   GtkSizeGroup *vgroup2;
5632
5633   window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
5634                                         NULL, 0,
5635                                         GTK_STOCK_CLOSE,
5636                                         GTK_RESPONSE_NONE,
5637                                         NULL);
5638
5639   gtk_window_set_screen (GTK_WINDOW (window), screen);
5640
5641   gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
5642
5643   g_signal_connect (window, "response",
5644                     G_CALLBACK (gtk_widget_destroy),
5645                     NULL);
5646
5647   table = gtk_table_new (2, 2, FALSE);
5648   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table, TRUE, TRUE, 0);
5649
5650   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
5651   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
5652   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
5653   gtk_widget_set_size_request (table, 250, 250);
5654
5655   hgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
5656   hgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
5657   vgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
5658   vgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
5659
5660   main_button = gtk_button_new_with_label ("X");
5661   
5662   gtk_table_attach (GTK_TABLE (table), main_button,
5663                     0, 1,       0, 1,
5664                     GTK_EXPAND, GTK_EXPAND,
5665                     0,          0);
5666   gtk_size_group_add_widget (master_size_group, main_button);
5667   gtk_size_group_add_widget (hgroup1, main_button);
5668   gtk_size_group_add_widget (vgroup1, main_button);
5669   gtk_widget_set_size_request (GTK_BIN (main_button)->child,
5670                                SIZE_GROUP_INITIAL_SIZE,
5671                                SIZE_GROUP_INITIAL_SIZE);
5672
5673   button = gtk_button_new ();
5674   gtk_table_attach (GTK_TABLE (table), button,
5675                     1, 2,       0, 1,
5676                     GTK_EXPAND, GTK_EXPAND,
5677                     0,          0);
5678   gtk_size_group_add_widget (vgroup1, button);
5679   gtk_size_group_add_widget (vgroup2, button);
5680
5681   button = gtk_button_new ();
5682   gtk_table_attach (GTK_TABLE (table), button,
5683                     0, 1,       1, 2,
5684                     GTK_EXPAND, GTK_EXPAND,
5685                     0,          0);
5686   gtk_size_group_add_widget (hgroup1, button);
5687   gtk_size_group_add_widget (hgroup2, button);
5688
5689   button = gtk_button_new ();
5690   gtk_table_attach (GTK_TABLE (table), button,
5691                     1, 2,       1, 2,
5692                     GTK_EXPAND, GTK_EXPAND,
5693                     0,          0);
5694   gtk_size_group_add_widget (hgroup2, button);
5695   gtk_size_group_add_widget (vgroup2, button);
5696
5697   g_object_unref (hgroup1);
5698   g_object_unref (hgroup2);
5699   g_object_unref (vgroup1);
5700   g_object_unref (vgroup2);
5701   
5702   hbox = gtk_hbox_new (FALSE, 5);
5703   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox, FALSE, FALSE, 0);
5704   
5705   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
5706   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
5707   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
5708   g_signal_connect (spin_button, "value_changed",
5709                     G_CALLBACK (size_group_hsize_changed), main_button);
5710
5711   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
5712   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
5713   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
5714   g_signal_connect (spin_button, "value_changed",
5715                     G_CALLBACK (size_group_vsize_changed), main_button);
5716
5717   return window;
5718 }
5719
5720 static void
5721 create_size_groups (GtkWidget *widget)
5722 {
5723   static GtkWidget *window1 = NULL;
5724   static GtkWidget *window2 = NULL;
5725   static GtkSizeGroup *master_size_group;
5726
5727   if (!master_size_group)
5728     master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
5729
5730   if (!window1)
5731     {
5732       window1 = create_size_group_window (gtk_widget_get_screen (widget),
5733                                           master_size_group);
5734
5735       g_signal_connect (window1, "destroy",
5736                         G_CALLBACK (gtk_widget_destroyed),
5737                         &window1);
5738     }
5739
5740   if (!window2)
5741     {
5742       window2 = create_size_group_window (gtk_widget_get_screen (widget),
5743                                           master_size_group);
5744
5745       g_signal_connect (window2, "destroy",
5746                         G_CALLBACK (gtk_widget_destroyed),
5747                         &window2);
5748     }
5749
5750   if (GTK_WIDGET_VISIBLE (window1) && GTK_WIDGET_VISIBLE (window2))
5751     {
5752       gtk_widget_destroy (window1);
5753       gtk_widget_destroy (window2);
5754     }
5755   else
5756     {
5757       if (!GTK_WIDGET_VISIBLE (window1))
5758         gtk_widget_show_all (window1);
5759       if (!GTK_WIDGET_VISIBLE (window2))
5760         gtk_widget_show_all (window2);
5761     }
5762 }
5763
5764 /*
5765  * GtkSpinButton
5766  */
5767
5768 static GtkWidget *spinner1;
5769
5770 static void
5771 toggle_snap (GtkWidget *widget, GtkSpinButton *spin)
5772 {
5773   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5774 }
5775
5776 static void
5777 toggle_numeric (GtkWidget *widget, GtkSpinButton *spin)
5778 {
5779   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5780 }
5781
5782 static void
5783 change_digits (GtkWidget *widget, GtkSpinButton *spin)
5784 {
5785   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5786                               gtk_spin_button_get_value_as_int (spin));
5787 }
5788
5789 static void
5790 get_value (GtkWidget *widget, gpointer data)
5791 {
5792   gchar buf[32];
5793   GtkLabel *label;
5794   GtkSpinButton *spin;
5795
5796   spin = GTK_SPIN_BUTTON (spinner1);
5797   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
5798   if (GPOINTER_TO_INT (data) == 1)
5799     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5800   else
5801     sprintf (buf, "%0.*f", spin->digits, gtk_spin_button_get_value (spin));
5802   gtk_label_set_text (label, buf);
5803 }
5804
5805 static void
5806 get_spin_value (GtkWidget *widget, gpointer data)
5807 {
5808   gchar *buffer;
5809   GtkLabel *label;
5810   GtkSpinButton *spin;
5811
5812   spin = GTK_SPIN_BUTTON (widget);
5813   label = GTK_LABEL (data);
5814
5815   buffer = g_strdup_printf ("%0.*f", spin->digits,
5816                             gtk_spin_button_get_value (spin));
5817   gtk_label_set_text (label, buffer);
5818
5819   g_free (buffer);
5820 }
5821
5822 static gint
5823 spin_button_time_output_func (GtkSpinButton *spin_button)
5824 {
5825   static gchar buf[6];
5826   gdouble hours;
5827   gdouble minutes;
5828
5829   hours = spin_button->adjustment->value / 60.0;
5830   minutes = (fabs(floor (hours) - hours) < 1e-5) ? 0.0 : 30;
5831   sprintf (buf, "%02.0f:%02.0f", floor (hours), minutes);
5832   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5833     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5834   return TRUE;
5835 }
5836
5837 static gint
5838 spin_button_month_input_func (GtkSpinButton *spin_button,
5839                               gdouble       *new_val)
5840 {
5841   gint i;
5842   static gchar *month[12] = { "January", "February", "March", "April",
5843                               "May", "June", "July", "August",
5844                               "September", "October", "November", "December" };
5845   gchar *tmp1, *tmp2;
5846   gboolean found = FALSE;
5847
5848   for (i = 1; i <= 12; i++)
5849     {
5850       tmp1 = g_ascii_strup (month[i - 1], -1);
5851       tmp2 = g_ascii_strup (gtk_entry_get_text (GTK_ENTRY (spin_button)), -1);
5852       if (strstr (tmp1, tmp2) == tmp1)
5853         found = TRUE;
5854       g_free (tmp1);
5855       g_free (tmp2);
5856       if (found)
5857         break;
5858     }
5859   if (!found)
5860     {
5861       *new_val = 0.0;
5862       return GTK_INPUT_ERROR;
5863     }
5864   *new_val = (gdouble) i;
5865   return TRUE;
5866 }
5867
5868 static gint
5869 spin_button_month_output_func (GtkSpinButton *spin_button)
5870 {
5871   gint i;
5872   static gchar *month[12] = { "January", "February", "March", "April",
5873                               "May", "June", "July", "August", "September",
5874                               "October", "November", "December" };
5875
5876   for (i = 1; i <= 12; i++)
5877     if (fabs (spin_button->adjustment->value - (double)i) < 1e-5)
5878       {
5879         if (strcmp (month[i-1], gtk_entry_get_text (GTK_ENTRY (spin_button))))
5880           gtk_entry_set_text (GTK_ENTRY (spin_button), month[i-1]);
5881       }
5882   return TRUE;
5883 }
5884
5885 static gint
5886 spin_button_hex_input_func (GtkSpinButton *spin_button,
5887                             gdouble       *new_val)
5888 {
5889   const gchar *buf;
5890   gchar *err;
5891   gdouble res;
5892
5893   buf = gtk_entry_get_text (GTK_ENTRY (spin_button));
5894   res = strtol(buf, &err, 16);
5895   *new_val = res;
5896   if (*err)
5897     return GTK_INPUT_ERROR;
5898   else
5899     return TRUE;
5900 }
5901
5902 static gint
5903 spin_button_hex_output_func (GtkSpinButton *spin_button)
5904 {
5905   static gchar buf[7];
5906   gint val;
5907
5908   val = (gint) spin_button->adjustment->value;
5909   if (fabs (val) < 1e-5)
5910     sprintf (buf, "0x00");
5911   else
5912     sprintf (buf, "0x%.2X", val);
5913   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5914     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5915   return TRUE;
5916 }
5917
5918 static void
5919 create_spins (GtkWidget *widget)
5920 {
5921   static GtkWidget *window = NULL;
5922   GtkWidget *frame;
5923   GtkWidget *hbox;
5924   GtkWidget *main_vbox;
5925   GtkWidget *vbox;
5926   GtkWidget *vbox2;
5927   GtkWidget *spinner2;
5928   GtkWidget *spinner;
5929   GtkWidget *button;
5930   GtkWidget *label;
5931   GtkWidget *val_label;
5932   GtkAdjustment *adj;
5933
5934   if (!window)
5935     {
5936       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5937       gtk_window_set_screen (GTK_WINDOW (window),
5938                              gtk_widget_get_screen (widget));
5939       
5940       g_signal_connect (window, "destroy",
5941                         G_CALLBACK (gtk_widget_destroyed),
5942                         &window);
5943       
5944       gtk_window_set_title (GTK_WINDOW (window), "GtkSpinButton");
5945       
5946       main_vbox = gtk_vbox_new (FALSE, 5);
5947       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5948       gtk_container_add (GTK_CONTAINER (window), main_vbox);
5949       
5950       frame = gtk_frame_new ("Not accelerated");
5951       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5952       
5953       vbox = gtk_vbox_new (FALSE, 0);
5954       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5955       gtk_container_add (GTK_CONTAINER (frame), vbox);
5956       
5957       /* Time, month, hex spinners */
5958       
5959       hbox = gtk_hbox_new (FALSE, 0);
5960       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5961       
5962       vbox2 = gtk_vbox_new (FALSE, 0);
5963       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5964       
5965       label = gtk_label_new ("Time :");
5966       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5967       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5968       
5969       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 1410, 30, 60, 0);
5970       spinner = gtk_spin_button_new (adj, 0, 0);
5971       gtk_editable_set_editable (GTK_EDITABLE (spinner), FALSE);
5972       g_signal_connect (spinner,
5973                         "output",
5974                         G_CALLBACK (spin_button_time_output_func),
5975                         NULL);
5976       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5977       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 5);
5978       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5979
5980       vbox2 = gtk_vbox_new (FALSE, 0);
5981       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5982       
5983       label = gtk_label_new ("Month :");
5984       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5985       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5986       
5987       adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5988                                                   5.0, 0.0);
5989       spinner = gtk_spin_button_new (adj, 0, 0);
5990       gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinner),
5991                                          GTK_UPDATE_IF_VALID);
5992       g_signal_connect (spinner,
5993                         "input",
5994                         G_CALLBACK (spin_button_month_input_func),
5995                         NULL);
5996       g_signal_connect (spinner,
5997                         "output",
5998                         G_CALLBACK (spin_button_month_output_func),
5999                         NULL);
6000       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
6001       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 9);
6002       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
6003       
6004       vbox2 = gtk_vbox_new (FALSE, 0);
6005       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
6006
6007       label = gtk_label_new ("Hex :");
6008       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6009       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
6010
6011       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 255, 1, 16, 0);
6012       spinner = gtk_spin_button_new (adj, 0, 0);
6013       gtk_editable_set_editable (GTK_EDITABLE (spinner), TRUE);
6014       g_signal_connect (spinner,
6015                         "input",
6016                         G_CALLBACK (spin_button_hex_input_func),
6017                         NULL);
6018       g_signal_connect (spinner,
6019                         "output",
6020                         G_CALLBACK (spin_button_hex_output_func),
6021                         NULL);
6022       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
6023       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 4);
6024       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
6025
6026       frame = gtk_frame_new ("Accelerated");
6027       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
6028   
6029       vbox = gtk_vbox_new (FALSE, 0);
6030       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
6031       gtk_container_add (GTK_CONTAINER (frame), vbox);
6032       
6033       hbox = gtk_hbox_new (FALSE, 0);
6034       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6035       
6036       vbox2 = gtk_vbox_new (FALSE, 0);
6037       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
6038       
6039       label = gtk_label_new ("Value :");
6040       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6041       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
6042
6043       adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
6044                                                   0.5, 100.0, 0.0);
6045       spinner1 = gtk_spin_button_new (adj, 1.0, 2);
6046       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
6047       gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
6048
6049       vbox2 = gtk_vbox_new (FALSE, 0);
6050       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
6051
6052       label = gtk_label_new ("Digits :");
6053       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6054       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
6055
6056       adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 15, 1, 1, 0);
6057       spinner2 = gtk_spin_button_new (adj, 0.0, 0);
6058       g_signal_connect (adj, "value_changed",
6059                         G_CALLBACK (change_digits),
6060                         spinner2);
6061       gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
6062
6063       hbox = gtk_hbox_new (FALSE, 0);
6064       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
6065
6066       button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
6067       g_signal_connect (button, "clicked",
6068                         G_CALLBACK (toggle_snap),
6069                         spinner1);
6070       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
6071       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6072
6073       button = gtk_check_button_new_with_label ("Numeric only input mode");
6074       g_signal_connect (button, "clicked",
6075                         G_CALLBACK (toggle_numeric),
6076                         spinner1);
6077       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
6078       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6079
6080       val_label = gtk_label_new ("");
6081
6082       hbox = gtk_hbox_new (FALSE, 0);
6083       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6084
6085       button = gtk_button_new_with_label ("Value as Int");
6086       g_object_set_data (G_OBJECT (button), "user_data", val_label);
6087       g_signal_connect (button, "clicked",
6088                         G_CALLBACK (get_value),
6089                         GINT_TO_POINTER (1));
6090       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6091
6092       button = gtk_button_new_with_label ("Value as Float");
6093       g_object_set_data (G_OBJECT (button), "user_data", val_label);
6094       g_signal_connect (button, "clicked",
6095                         G_CALLBACK (get_value),
6096                         GINT_TO_POINTER (2));
6097       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6098
6099       gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
6100       gtk_label_set_text (GTK_LABEL (val_label), "0");
6101
6102       frame = gtk_frame_new ("Using Convenience Constructor");
6103       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
6104   
6105       hbox = gtk_hbox_new (FALSE, 0);
6106       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6107       gtk_container_add (GTK_CONTAINER (frame), hbox);
6108       
6109       val_label = gtk_label_new ("0.0");
6110
6111       spinner = gtk_spin_button_new_with_range (0.0, 10.0, 0.009);
6112       gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 0.0);
6113       g_signal_connect (spinner, "value_changed",
6114                         G_CALLBACK (get_spin_value), val_label);
6115       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 5);
6116       gtk_box_pack_start (GTK_BOX (hbox), val_label, TRUE, TRUE, 5);
6117
6118       hbox = gtk_hbox_new (FALSE, 0);
6119       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
6120   
6121       button = gtk_button_new_with_label ("Close");
6122       g_signal_connect_swapped (button, "clicked",
6123                                 G_CALLBACK (gtk_widget_destroy),
6124                                 window);
6125       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6126     }
6127
6128   if (!GTK_WIDGET_VISIBLE (window))
6129     gtk_widget_show_all (window);
6130   else
6131     gtk_widget_destroy (window);
6132 }
6133
6134
6135 /*
6136  * Cursors
6137  */
6138
6139 static gint
6140 cursor_expose_event (GtkWidget *widget,
6141                      GdkEvent  *event,
6142                      gpointer   user_data)
6143 {
6144   GtkDrawingArea *darea;
6145   GdkDrawable *drawable;
6146   GdkGC *black_gc;
6147   GdkGC *gray_gc;
6148   GdkGC *white_gc;
6149   guint max_width;
6150   guint max_height;
6151
6152   g_return_val_if_fail (widget != NULL, TRUE);
6153   g_return_val_if_fail (GTK_IS_DRAWING_AREA (widget), TRUE);
6154
6155   darea = GTK_DRAWING_AREA (widget);
6156   drawable = widget->window;
6157   white_gc = widget->style->white_gc;
6158   gray_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
6159   black_gc = widget->style->black_gc;
6160   max_width = widget->allocation.width;
6161   max_height = widget->allocation.height;
6162
6163   gdk_draw_rectangle (drawable, white_gc,
6164                       TRUE,
6165                       0,
6166                       0,
6167                       max_width,
6168                       max_height / 2);
6169
6170   gdk_draw_rectangle (drawable, black_gc,
6171                       TRUE,
6172                       0,
6173                       max_height / 2,
6174                       max_width,
6175                       max_height / 2);
6176
6177   gdk_draw_rectangle (drawable, gray_gc,
6178                       TRUE,
6179                       max_width / 3,
6180                       max_height / 3,
6181                       max_width / 3,
6182                       max_height / 3);
6183
6184   return TRUE;
6185 }
6186
6187 static void
6188 set_cursor (GtkWidget *spinner,
6189             GtkWidget *widget)
6190 {
6191   guint c;
6192   GdkCursor *cursor;
6193   GtkWidget *label;
6194   GEnumClass *class;
6195   GEnumValue *vals;
6196
6197   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
6198   c &= 0xfe;
6199
6200   label = g_object_get_data (G_OBJECT (spinner), "user_data");
6201   
6202   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
6203   vals = class->values;
6204
6205   while (vals && vals->value != c)
6206     vals++;
6207   if (vals)
6208     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
6209   else
6210     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
6211
6212   g_type_class_unref (class);
6213
6214   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
6215   gdk_window_set_cursor (widget->window, cursor);
6216   gdk_cursor_unref (cursor);
6217 }
6218
6219 static gint
6220 cursor_event (GtkWidget          *widget,
6221               GdkEvent           *event,
6222               GtkSpinButton      *spinner)
6223 {
6224   if ((event->type == GDK_BUTTON_PRESS) &&
6225       ((event->button.button == 1) ||
6226        (event->button.button == 3)))
6227     {
6228       gtk_spin_button_spin (spinner, event->button.button == 1 ?
6229                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
6230       return TRUE;
6231     }
6232
6233   return FALSE;
6234 }
6235
6236 #ifdef GDK_WINDOWING_X11
6237 #include "x11/gdkx.h"
6238
6239 static void
6240 change_cursor_theme (GtkWidget *widget,
6241                      gpointer   data)
6242 {
6243   const gchar *theme;
6244   gint size;
6245   GList *children;
6246
6247   children = gtk_container_get_children (GTK_CONTAINER (data));
6248
6249   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
6250   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
6251
6252   g_list_free (children);
6253
6254   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
6255                                     theme, size);
6256 }
6257 #endif
6258
6259
6260 static void
6261 create_cursors (GtkWidget *widget)
6262 {
6263   static GtkWidget *window = NULL;
6264   GtkWidget *frame;
6265   GtkWidget *hbox;
6266   GtkWidget *main_vbox;
6267   GtkWidget *vbox;
6268   GtkWidget *darea;
6269   GtkWidget *spinner;
6270   GtkWidget *button;
6271   GtkWidget *label;
6272   GtkWidget *any;
6273   GtkAdjustment *adj;
6274   GtkWidget *entry;
6275   GtkWidget *size;  
6276
6277   if (!window)
6278     {
6279       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6280       gtk_window_set_screen (GTK_WINDOW (window), 
6281                              gtk_widget_get_screen (widget));
6282       
6283       g_signal_connect (window, "destroy",
6284                         G_CALLBACK (gtk_widget_destroyed),
6285                         &window);
6286       
6287       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
6288       
6289       main_vbox = gtk_vbox_new (FALSE, 5);
6290       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
6291       gtk_container_add (GTK_CONTAINER (window), main_vbox);
6292
6293       vbox =
6294         g_object_new (gtk_vbox_get_type (),
6295                         "GtkBox::homogeneous", FALSE,
6296                         "GtkBox::spacing", 5,
6297                         "GtkContainer::border_width", 10,
6298                         "GtkWidget::parent", main_vbox,
6299                         "GtkWidget::visible", TRUE,
6300                         NULL);
6301
6302 #ifdef GDK_WINDOWING_X11
6303       hbox = gtk_hbox_new (FALSE, 0);
6304       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6305       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6306
6307       label = gtk_label_new ("Cursor Theme : ");
6308       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6309       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6310
6311       entry = gtk_entry_new ();
6312       gtk_entry_set_text (GTK_ENTRY (entry), "default");
6313       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
6314
6315       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
6316       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
6317       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
6318       
6319       g_signal_connect (entry, "changed", 
6320                         G_CALLBACK (change_cursor_theme), hbox);
6321       g_signal_connect (size, "changed", 
6322                         G_CALLBACK (change_cursor_theme), hbox);
6323 #endif
6324
6325       hbox = gtk_hbox_new (FALSE, 0);
6326       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6327       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6328
6329       label = gtk_label_new ("Cursor Value : ");
6330       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6331       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6332       
6333       adj = (GtkAdjustment *) gtk_adjustment_new (0,
6334                                                   0, 152,
6335                                                   2,
6336                                                   10, 0);
6337       spinner = gtk_spin_button_new (adj, 0, 0);
6338       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
6339
6340       frame =
6341         g_object_new (gtk_frame_get_type (),
6342                         "GtkFrame::shadow", GTK_SHADOW_ETCHED_IN,
6343                         "GtkFrame::label_xalign", 0.5,
6344                         "GtkFrame::label", "Cursor Area",
6345                         "GtkContainer::border_width", 10,
6346                         "GtkWidget::parent", vbox,
6347                         "GtkWidget::visible", TRUE,
6348                         NULL);
6349
6350       darea = gtk_drawing_area_new ();
6351       gtk_widget_set_size_request (darea, 80, 80);
6352       gtk_container_add (GTK_CONTAINER (frame), darea);
6353       g_signal_connect (darea,
6354                         "expose_event",
6355                         G_CALLBACK (cursor_expose_event),
6356                         NULL);
6357       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
6358       g_signal_connect (darea,
6359                         "button_press_event",
6360                         G_CALLBACK (cursor_event),
6361                         spinner);
6362       gtk_widget_show (darea);
6363
6364       g_signal_connect (spinner, "changed",
6365                         G_CALLBACK (set_cursor),
6366                         darea);
6367
6368       label = g_object_new (GTK_TYPE_LABEL,
6369                               "visible", TRUE,
6370                               "label", "XXX",
6371                               "parent", vbox,
6372                               NULL);
6373       gtk_container_child_set (GTK_CONTAINER (vbox), label,
6374                                "expand", FALSE,
6375                                NULL);
6376       g_object_set_data (G_OBJECT (spinner), "user_data", label);
6377
6378       any =
6379         g_object_new (gtk_hseparator_get_type (),
6380                         "GtkWidget::visible", TRUE,
6381                         NULL);
6382       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
6383   
6384       hbox = gtk_hbox_new (FALSE, 0);
6385       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6386       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
6387
6388       button = gtk_button_new_with_label ("Close");
6389       g_signal_connect_swapped (button, "clicked",
6390                                 G_CALLBACK (gtk_widget_destroy),
6391                                 window);
6392       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6393
6394       gtk_widget_show_all (window);
6395
6396       set_cursor (spinner, darea);
6397     }
6398   else
6399     gtk_widget_destroy (window);
6400 }
6401
6402 /*
6403  * GtkList
6404  */
6405
6406 static void
6407 list_add (GtkWidget *widget,
6408           GtkWidget *list)
6409 {
6410   static int i = 1;
6411   gchar buffer[64];
6412   GtkWidget *list_item;
6413   GtkContainer *container;
6414
6415   container = GTK_CONTAINER (list);
6416
6417   sprintf (buffer, "added item %d", i++);
6418   list_item = gtk_list_item_new_with_label (buffer);
6419   gtk_widget_show (list_item);
6420
6421   gtk_container_add (container, list_item);
6422 }
6423
6424 static void
6425 list_remove (GtkWidget *widget,
6426              GtkList   *list)
6427 {
6428   GList *clear_list = NULL;
6429   GList *sel_row = NULL;
6430   GList *work = NULL;
6431
6432   if (list->selection_mode == GTK_SELECTION_EXTENDED)
6433     {
6434       GtkWidget *item;
6435
6436       item = GTK_CONTAINER (list)->focus_child;
6437       if (!item && list->selection)
6438         item = list->selection->data;
6439
6440       if (item)
6441         {
6442           work = g_list_find (list->children, item);
6443           for (sel_row = work; sel_row; sel_row = sel_row->next)
6444             if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6445               break;
6446
6447           if (!sel_row)
6448             {
6449               for (sel_row = work; sel_row; sel_row = sel_row->prev)
6450                 if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6451                   break;
6452             }
6453         }
6454     }
6455
6456   for (work = list->selection; work; work = work->next)
6457     clear_list = g_list_prepend (clear_list, work->data);
6458
6459   clear_list = g_list_reverse (clear_list);
6460   gtk_list_remove_items (GTK_LIST (list), clear_list);
6461   g_list_free (clear_list);
6462
6463   if (list->selection_mode == GTK_SELECTION_EXTENDED && sel_row)
6464     gtk_list_select_child (list, GTK_WIDGET(sel_row->data));
6465 }
6466
6467 static void
6468 list_clear (GtkWidget *widget,
6469             GtkWidget *list)
6470 {
6471   gtk_list_clear_items (GTK_LIST (list), 0, -1);
6472 }
6473
6474 static gchar *selection_mode_items[] =
6475 {
6476   "Single",
6477   "Browse",
6478   "Multiple"
6479 };
6480
6481 static const GtkSelectionMode selection_modes[] = {
6482   GTK_SELECTION_SINGLE,
6483   GTK_SELECTION_BROWSE,
6484   GTK_SELECTION_MULTIPLE
6485 };
6486
6487 static GtkWidget *list_omenu;
6488
6489 static void 
6490 list_toggle_sel_mode (GtkWidget *widget, gpointer data)
6491 {
6492   GtkList *list;
6493   gint i;
6494
6495   list = GTK_LIST (data);
6496
6497   if (!GTK_WIDGET_MAPPED (widget))
6498     return;
6499
6500   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6501
6502   gtk_list_set_selection_mode (list, selection_modes[i]);
6503 }
6504
6505 static void
6506 create_list (GtkWidget *widget)
6507 {
6508   static GtkWidget *window = NULL;
6509
6510   if (!window)
6511     {
6512       GtkWidget *cbox;
6513       GtkWidget *vbox;
6514       GtkWidget *hbox;
6515       GtkWidget *label;
6516       GtkWidget *scrolled_win;
6517       GtkWidget *list;
6518       GtkWidget *button;
6519       GtkWidget *separator;
6520       FILE *infile;
6521
6522       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6523
6524       gtk_window_set_screen (GTK_WINDOW (window),
6525                              gtk_widget_get_screen (widget));
6526
6527       g_signal_connect (window, "destroy",
6528                         G_CALLBACK (gtk_widget_destroyed),
6529                         &window);
6530
6531       gtk_window_set_title (GTK_WINDOW (window), "list");
6532       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6533
6534       vbox = gtk_vbox_new (FALSE, 0);
6535       gtk_container_add (GTK_CONTAINER (window), vbox);
6536
6537       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
6538       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
6539       gtk_widget_set_size_request (scrolled_win, -1, 300);
6540       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
6541       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
6542                                       GTK_POLICY_AUTOMATIC,
6543                                       GTK_POLICY_AUTOMATIC);
6544
6545       list = gtk_list_new ();
6546       gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
6547       gtk_scrolled_window_add_with_viewport
6548         (GTK_SCROLLED_WINDOW (scrolled_win), list);
6549       gtk_container_set_focus_vadjustment
6550         (GTK_CONTAINER (list),
6551          gtk_scrolled_window_get_vadjustment
6552          (GTK_SCROLLED_WINDOW (scrolled_win)));
6553       gtk_container_set_focus_hadjustment
6554         (GTK_CONTAINER (list),
6555          gtk_scrolled_window_get_hadjustment
6556          (GTK_SCROLLED_WINDOW (scrolled_win)));
6557
6558       if ((infile = fopen("../gtk/gtkenums.h", "r")))
6559         {
6560           char buffer[256];
6561           char *pos;
6562           GtkWidget *item;
6563
6564           while (fgets (buffer, 256, infile))
6565             {
6566               if ((pos = strchr (buffer, '\n')))
6567                 *pos = 0;
6568               item = gtk_list_item_new_with_label (buffer);
6569               gtk_container_add (GTK_CONTAINER (list), item);
6570             }
6571           
6572           fclose (infile);
6573         }
6574
6575
6576       hbox = gtk_hbox_new (TRUE, 5);
6577       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6578       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6579
6580       button = gtk_button_new_with_label ("Insert Row");
6581       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6582       g_signal_connect (button, "clicked",
6583                         G_CALLBACK (list_add),
6584                         list);
6585
6586       button = gtk_button_new_with_label ("Clear List");
6587       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6588       g_signal_connect (button, "clicked",
6589                         G_CALLBACK (list_clear),
6590                         list);
6591
6592       button = gtk_button_new_with_label ("Remove Selection");
6593       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6594       g_signal_connect (button, "clicked",
6595                         G_CALLBACK (list_remove),
6596                         list);
6597
6598       cbox = gtk_hbox_new (FALSE, 0);
6599       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6600
6601       hbox = gtk_hbox_new (FALSE, 5);
6602       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6603       gtk_box_pack_start (GTK_BOX (cbox), hbox, TRUE, FALSE, 0);
6604
6605       label = gtk_label_new ("Selection Mode :");
6606       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6607
6608       list_omenu = build_option_menu (selection_mode_items, 3, 3, 
6609                                       list_toggle_sel_mode,
6610                                       list);
6611       gtk_box_pack_start (GTK_BOX (hbox), list_omenu, FALSE, TRUE, 0);
6612
6613       separator = gtk_hseparator_new ();
6614       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
6615
6616       cbox = gtk_hbox_new (FALSE, 0);
6617       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6618
6619       button = gtk_button_new_with_label ("close");
6620       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
6621       gtk_box_pack_start (GTK_BOX (cbox), button, TRUE, TRUE, 0);
6622       g_signal_connect_swapped (button, "clicked",
6623                                 G_CALLBACK (gtk_widget_destroy),
6624                                 window);
6625
6626       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6627       gtk_widget_grab_default (button);
6628     }
6629
6630   if (!GTK_WIDGET_VISIBLE (window))
6631     gtk_widget_show_all (window);
6632   else
6633     gtk_widget_destroy (window);
6634 }
6635
6636 /*
6637  * GtkCList
6638  */
6639
6640 static char * book_open_xpm[] = {
6641 "16 16 4 1",
6642 "       c None s None",
6643 ".      c black",
6644 "X      c #808080",
6645 "o      c white",
6646 "                ",
6647 "  ..            ",
6648 " .Xo.    ...    ",
6649 " .Xoo. ..oo.    ",
6650 " .Xooo.Xooo...  ",
6651 " .Xooo.oooo.X.  ",
6652 " .Xooo.Xooo.X.  ",
6653 " .Xooo.oooo.X.  ",
6654 " .Xooo.Xooo.X.  ",
6655 " .Xooo.oooo.X.  ",
6656 "  .Xoo.Xoo..X.  ",
6657 "   .Xo.o..ooX.  ",
6658 "    .X..XXXXX.  ",
6659 "    ..X.......  ",
6660 "     ..         ",
6661 "                "};
6662
6663 static char * book_closed_xpm[] = {
6664 "16 16 6 1",
6665 "       c None s None",
6666 ".      c black",
6667 "X      c red",
6668 "o      c yellow",
6669 "O      c #808080",
6670 "#      c white",
6671 "                ",
6672 "       ..       ",
6673 "     ..XX.      ",
6674 "   ..XXXXX.     ",
6675 " ..XXXXXXXX.    ",
6676 ".ooXXXXXXXXX.   ",
6677 "..ooXXXXXXXXX.  ",
6678 ".X.ooXXXXXXXXX. ",
6679 ".XX.ooXXXXXX..  ",
6680 " .XX.ooXXX..#O  ",
6681 "  .XX.oo..##OO. ",
6682 "   .XX..##OO..  ",
6683 "    .X.#OO..    ",
6684 "     ..O..      ",
6685 "      ..        ",
6686 "                "};
6687
6688 static char * mini_page_xpm[] = {
6689 "16 16 4 1",
6690 "       c None s None",
6691 ".      c black",
6692 "X      c white",
6693 "o      c #808080",
6694 "                ",
6695 "   .......      ",
6696 "   .XXXXX..     ",
6697 "   .XoooX.X.    ",
6698 "   .XXXXX....   ",
6699 "   .XooooXoo.o  ",
6700 "   .XXXXXXXX.o  ",
6701 "   .XooooooX.o  ",
6702 "   .XXXXXXXX.o  ",
6703 "   .XooooooX.o  ",
6704 "   .XXXXXXXX.o  ",
6705 "   .XooooooX.o  ",
6706 "   .XXXXXXXX.o  ",
6707 "   ..........o  ",
6708 "    oooooooooo  ",
6709 "                "};
6710
6711 static char * gtk_mini_xpm[] = {
6712 "15 20 17 1",
6713 "       c None",
6714 ".      c #14121F",
6715 "+      c #278828",
6716 "@      c #9B3334",
6717 "#      c #284C72",
6718 "$      c #24692A",
6719 "%      c #69282E",
6720 "&      c #37C539",
6721 "*      c #1D2F4D",
6722 "=      c #6D7076",
6723 "-      c #7D8482",
6724 ";      c #E24A49",
6725 ">      c #515357",
6726 ",      c #9B9C9B",
6727 "'      c #2FA232",
6728 ")      c #3CE23D",
6729 "!      c #3B6CCB",
6730 "               ",
6731 "      ***>     ",
6732 "    >.*!!!*    ",
6733 "   ***....#*=  ",
6734 "  *!*.!!!**!!# ",
6735 " .!!#*!#*!!!!# ",
6736 " @%#!.##.*!!$& ",
6737 " @;%*!*.#!#')) ",
6738 " @;;@%!!*$&)'' ",
6739 " @%.%@%$'&)$+' ",
6740 " @;...@$'*'*)+ ",
6741 " @;%..@$+*.')$ ",
6742 " @;%%;;$+..$)# ",
6743 " @;%%;@$$$'.$# ",
6744 " %;@@;;$$+))&* ",
6745 "  %;;;@+$&)&*  ",
6746 "   %;;@'))+>   ",
6747 "    %;@'&#     ",
6748 "     >%$$      ",
6749 "      >=       "};
6750
6751 #define TESTGTK_CLIST_COLUMNS 12
6752 static gint clist_rows = 0;
6753 static GtkWidget *clist_omenu;
6754
6755 static void
6756 add1000_clist (GtkWidget *widget, gpointer data)
6757 {
6758   gint i, row;
6759   char text[TESTGTK_CLIST_COLUMNS][50];
6760   char *texts[TESTGTK_CLIST_COLUMNS];
6761   GdkBitmap *mask;
6762   GdkPixmap *pixmap;
6763   GtkCList  *clist;
6764
6765   clist = GTK_CLIST (data);
6766
6767   pixmap = gdk_pixmap_create_from_xpm_d (clist->clist_window,
6768                                          &mask, 
6769                                          &GTK_WIDGET (data)->style->white,
6770                                          gtk_mini_xpm);
6771
6772   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6773     {
6774       texts[i] = text[i];
6775       sprintf (text[i], "Column %d", i);
6776     }
6777   
6778   texts[3] = NULL;
6779   sprintf (text[1], "Right");
6780   sprintf (text[2], "Center");
6781   
6782   gtk_clist_freeze (GTK_CLIST (data));
6783   for (i = 0; i < 1000; i++)
6784     {
6785       sprintf (text[0], "CListRow %d", rand() % 10000);
6786       row = gtk_clist_append (clist, texts);
6787       gtk_clist_set_pixtext (clist, row, 3, "gtk+", 5, pixmap, mask);
6788     }
6789
6790   gtk_clist_thaw (GTK_CLIST (data));
6791
6792   g_object_unref (pixmap);
6793   g_object_unref (mask);
6794 }
6795
6796 static void
6797 add10000_clist (GtkWidget *widget, gpointer data)
6798 {
6799   gint i;
6800   char text[TESTGTK_CLIST_COLUMNS][50];
6801   char *texts[TESTGTK_CLIST_COLUMNS];
6802
6803   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6804     {
6805       texts[i] = text[i];
6806       sprintf (text[i], "Column %d", i);
6807     }
6808   
6809   sprintf (text[1], "Right");
6810   sprintf (text[2], "Center");
6811   
6812   gtk_clist_freeze (GTK_CLIST (data));
6813   for (i = 0; i < 10000; i++)
6814     {
6815       sprintf (text[0], "CListRow %d", rand() % 10000);
6816       gtk_clist_append (GTK_CLIST (data), texts);
6817     }
6818   gtk_clist_thaw (GTK_CLIST (data));
6819 }
6820
6821 void
6822 clear_clist (GtkWidget *widget, gpointer data)
6823 {
6824   gtk_clist_clear (GTK_CLIST (data));
6825   clist_rows = 0;
6826 }
6827
6828 void clist_remove_selection (GtkWidget *widget, GtkCList *clist)
6829 {
6830   gtk_clist_freeze (clist);
6831
6832   while (clist->selection)
6833     {
6834       gint row;
6835
6836       clist_rows--;
6837       row = GPOINTER_TO_INT (clist->selection->data);
6838
6839       gtk_clist_remove (clist, row);
6840
6841       if (clist->selection_mode == GTK_SELECTION_BROWSE)
6842         break;
6843     }
6844
6845   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
6846       clist->focus_row >= 0)
6847     gtk_clist_select_row (clist, clist->focus_row, -1);
6848
6849   gtk_clist_thaw (clist);
6850 }
6851
6852 void toggle_title_buttons (GtkWidget *widget, GtkCList *clist)
6853 {
6854   if (GTK_TOGGLE_BUTTON (widget)->active)
6855     gtk_clist_column_titles_show (clist);
6856   else
6857     gtk_clist_column_titles_hide (clist);
6858 }
6859
6860 void toggle_reorderable (GtkWidget *widget, GtkCList *clist)
6861 {
6862   gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active);
6863 }
6864
6865 static void
6866 insert_row_clist (GtkWidget *widget, gpointer data)
6867 {
6868   static char *text[] =
6869   {
6870     "This", "is an", "inserted", "row.",
6871     "This", "is an", "inserted", "row.",
6872     "This", "is an", "inserted", "row."
6873   };
6874
6875   static GtkStyle *style1 = NULL;
6876   static GtkStyle *style2 = NULL;
6877   static GtkStyle *style3 = NULL;
6878   gint row;
6879   
6880   if (GTK_CLIST (data)->focus_row >= 0)
6881     row = gtk_clist_insert (GTK_CLIST (data), GTK_CLIST (data)->focus_row,
6882                             text);
6883   else
6884     row = gtk_clist_prepend (GTK_CLIST (data), text);
6885
6886   if (!style1)
6887     {
6888       GdkColor col1 = { 0, 0, 56000, 0};
6889       GdkColor col2 = { 0, 32000, 0, 56000};
6890
6891       style1 = gtk_style_copy (GTK_WIDGET (data)->style);
6892       style1->base[GTK_STATE_NORMAL] = col1;
6893       style1->base[GTK_STATE_SELECTED] = col2;
6894
6895       style2 = gtk_style_copy (GTK_WIDGET (data)->style);
6896       style2->fg[GTK_STATE_NORMAL] = col1;
6897       style2->fg[GTK_STATE_SELECTED] = col2;
6898
6899       style3 = gtk_style_copy (GTK_WIDGET (data)->style);
6900       style3->fg[GTK_STATE_NORMAL] = col1;
6901       style3->base[GTK_STATE_NORMAL] = col2;
6902       pango_font_description_free (style3->font_desc);
6903       style3->font_desc = pango_font_description_from_string ("courier 12");
6904     }
6905
6906   gtk_clist_set_cell_style (GTK_CLIST (data), row, 3, style1);
6907   gtk_clist_set_cell_style (GTK_CLIST (data), row, 4, style2);
6908   gtk_clist_set_cell_style (GTK_CLIST (data), row, 0, style3);
6909
6910   clist_rows++;
6911 }
6912
6913 static void
6914 clist_warning_test (GtkWidget *button,
6915                     GtkWidget *clist)
6916 {
6917   GtkWidget *child;
6918   static gboolean add_remove = FALSE;
6919
6920   add_remove = !add_remove;
6921
6922   child = gtk_label_new ("Test");
6923   g_object_ref (child);
6924   gtk_object_sink (GTK_OBJECT (child));
6925
6926   if (add_remove)
6927     gtk_container_add (GTK_CONTAINER (clist), child);
6928   else
6929     {
6930       child->parent = clist;
6931       gtk_container_remove (GTK_CONTAINER (clist), child);
6932       child->parent = NULL;
6933     }
6934
6935   gtk_widget_destroy (child);
6936   g_object_unref (child);
6937 }
6938
6939 static void
6940 undo_selection (GtkWidget *button, GtkCList *clist)
6941 {
6942   gtk_clist_undo_selection (clist);
6943 }
6944
6945 static void 
6946 clist_toggle_sel_mode (GtkWidget *widget, gpointer data)
6947 {
6948   GtkCList *clist;
6949   gint i;
6950
6951   clist = GTK_CLIST (data);
6952
6953   if (!GTK_WIDGET_MAPPED (widget))
6954     return;
6955
6956   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6957
6958   gtk_clist_set_selection_mode (clist, selection_modes[i]);
6959 }
6960
6961 static void 
6962 clist_click_column (GtkCList *clist, gint column, gpointer data)
6963 {
6964   if (column == 4)
6965     gtk_clist_set_column_visibility (clist, column, FALSE);
6966   else if (column == clist->sort_column)
6967     {
6968       if (clist->sort_type == GTK_SORT_ASCENDING)
6969         clist->sort_type = GTK_SORT_DESCENDING;
6970       else
6971         clist->sort_type = GTK_SORT_ASCENDING;
6972     }
6973   else
6974     gtk_clist_set_sort_column (clist, column);
6975
6976   gtk_clist_sort (clist);
6977 }
6978
6979 static void
6980 create_clist (GtkWidget *widget)
6981 {
6982   gint i;
6983   static GtkWidget *window = NULL;
6984
6985   static char *titles[] =
6986   {
6987     "auto resize", "not resizeable", "max width 100", "min width 50",
6988     "hide column", "Title 5", "Title 6", "Title 7",
6989     "Title 8",  "Title 9",  "Title 10", "Title 11"
6990   };
6991
6992   char text[TESTGTK_CLIST_COLUMNS][50];
6993   char *texts[TESTGTK_CLIST_COLUMNS];
6994
6995   GtkWidget *vbox;
6996   GtkWidget *hbox;
6997   GtkWidget *clist;
6998   GtkWidget *button;
6999   GtkWidget *separator;
7000   GtkWidget *scrolled_win;
7001   GtkWidget *check;
7002
7003   GtkWidget *undo_button;
7004   GtkWidget *label;
7005
7006   GtkStyle *style;
7007   GdkColor red_col = { 0, 56000, 0, 0};
7008   GdkColor light_green_col = { 0, 0, 56000, 32000};
7009
7010   if (!window)
7011     {
7012       clist_rows = 0;
7013       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7014       gtk_window_set_screen (GTK_WINDOW (window), 
7015                              gtk_widget_get_screen (widget));
7016
7017       g_signal_connect (window, "destroy",
7018                         G_CALLBACK (gtk_widget_destroyed), &window);
7019
7020       gtk_window_set_title (GTK_WINDOW (window), "clist");
7021       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7022
7023       vbox = gtk_vbox_new (FALSE, 0);
7024       gtk_container_add (GTK_CONTAINER (window), vbox);
7025
7026       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7027       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
7028       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7029                                       GTK_POLICY_AUTOMATIC, 
7030                                       GTK_POLICY_AUTOMATIC);
7031
7032       /* create GtkCList here so we have a pointer to throw at the 
7033        * button callbacks -- more is done with it later */
7034       clist = gtk_clist_new_with_titles (TESTGTK_CLIST_COLUMNS, titles);
7035       gtk_container_add (GTK_CONTAINER (scrolled_win), clist);
7036       g_signal_connect (clist, "click_column",
7037                         G_CALLBACK (clist_click_column), NULL);
7038
7039       /* control buttons */
7040       hbox = gtk_hbox_new (FALSE, 5);
7041       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7042       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7043
7044       button = gtk_button_new_with_label ("Insert Row");
7045       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7046       g_signal_connect (button, "clicked",
7047                         G_CALLBACK (insert_row_clist), clist);
7048
7049       button = gtk_button_new_with_label ("Add 1,000 Rows With Pixmaps");
7050       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7051       g_signal_connect (button, "clicked",
7052                         G_CALLBACK (add1000_clist), clist);
7053
7054       button = gtk_button_new_with_label ("Add 10,000 Rows");
7055       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7056       g_signal_connect (button, "clicked",
7057                         G_CALLBACK (add10000_clist), clist);
7058
7059       /* second layer of buttons */
7060       hbox = gtk_hbox_new (FALSE, 5);
7061       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7062       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7063
7064       button = gtk_button_new_with_label ("Clear List");
7065       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7066       g_signal_connect (button, "clicked",
7067                         G_CALLBACK (clear_clist), clist);
7068
7069       button = gtk_button_new_with_label ("Remove Selection");
7070       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7071       g_signal_connect (button, "clicked",
7072                         G_CALLBACK (clist_remove_selection), clist);
7073
7074       undo_button = gtk_button_new_with_label ("Undo Selection");
7075       gtk_box_pack_start (GTK_BOX (hbox), undo_button, TRUE, TRUE, 0);
7076       g_signal_connect (undo_button, "clicked",
7077                         G_CALLBACK (undo_selection), clist);
7078
7079       button = gtk_button_new_with_label ("Warning Test");
7080       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7081       g_signal_connect (button, "clicked",
7082                         G_CALLBACK (clist_warning_test), clist);
7083
7084       /* third layer of buttons */
7085       hbox = gtk_hbox_new (FALSE, 5);
7086       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7087       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7088
7089       check = gtk_check_button_new_with_label ("Show Title Buttons");
7090       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7091       g_signal_connect (check, "clicked",
7092                         G_CALLBACK (toggle_title_buttons), clist);
7093       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7094
7095       check = gtk_check_button_new_with_label ("Reorderable");
7096       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7097       g_signal_connect (check, "clicked",
7098                         G_CALLBACK (toggle_reorderable), clist);
7099       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7100
7101       label = gtk_label_new ("Selection Mode :");
7102       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7103
7104       clist_omenu = build_option_menu (selection_mode_items, 3, 3, 
7105                                        clist_toggle_sel_mode,
7106                                        clist);
7107       gtk_box_pack_start (GTK_BOX (hbox), clist_omenu, FALSE, TRUE, 0);
7108
7109       /* 
7110        * the rest of the clist configuration
7111        */
7112
7113       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7114       gtk_clist_set_row_height (GTK_CLIST (clist), 18);
7115       gtk_widget_set_size_request (clist, -1, 300);
7116
7117       for (i = 1; i < TESTGTK_CLIST_COLUMNS; i++)
7118         gtk_clist_set_column_width (GTK_CLIST (clist), i, 80);
7119
7120       gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
7121       gtk_clist_set_column_resizeable (GTK_CLIST (clist), 1, FALSE);
7122       gtk_clist_set_column_max_width (GTK_CLIST (clist), 2, 100);
7123       gtk_clist_set_column_min_width (GTK_CLIST (clist), 3, 50);
7124       gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
7125       gtk_clist_set_column_justification (GTK_CLIST (clist), 1,
7126                                           GTK_JUSTIFY_RIGHT);
7127       gtk_clist_set_column_justification (GTK_CLIST (clist), 2,
7128                                           GTK_JUSTIFY_CENTER);
7129       
7130       for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
7131         {
7132           texts[i] = text[i];
7133           sprintf (text[i], "Column %d", i);
7134         }
7135
7136       sprintf (text[1], "Right");
7137       sprintf (text[2], "Center");
7138
7139       style = gtk_style_new ();
7140       style->fg[GTK_STATE_NORMAL] = red_col;
7141       style->base[GTK_STATE_NORMAL] = light_green_col;
7142
7143       pango_font_description_set_size (style->font_desc, 14 * PANGO_SCALE);
7144       pango_font_description_set_weight (style->font_desc, PANGO_WEIGHT_BOLD);
7145
7146       for (i = 0; i < 10; i++)
7147         {
7148           sprintf (text[0], "CListRow %d", clist_rows++);
7149           gtk_clist_append (GTK_CLIST (clist), texts);
7150
7151           switch (i % 4)
7152             {
7153             case 2:
7154               gtk_clist_set_row_style (GTK_CLIST (clist), i, style);
7155               break;
7156             default:
7157               gtk_clist_set_cell_style (GTK_CLIST (clist), i, i % 4, style);
7158               break;
7159             }
7160         }
7161
7162       g_object_unref (style);
7163       
7164       separator = gtk_hseparator_new ();
7165       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
7166
7167       hbox = gtk_hbox_new (FALSE, 0);
7168       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7169
7170       button = gtk_button_new_with_label ("close");
7171       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
7172       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7173       g_signal_connect_swapped (button, "clicked",
7174                                 G_CALLBACK (gtk_widget_destroy),
7175                                 window);
7176
7177       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7178       gtk_widget_grab_default (button);
7179     }
7180
7181   if (!GTK_WIDGET_VISIBLE (window))
7182     gtk_widget_show_all (window);
7183   else
7184     {
7185       clist_rows = 0;
7186       gtk_widget_destroy (window);
7187     }
7188 }
7189
7190 /*
7191  * GtkCTree
7192  */
7193
7194 typedef struct 
7195 {
7196   GdkPixmap *pixmap1;
7197   GdkPixmap *pixmap2;
7198   GdkPixmap *pixmap3;
7199   GdkBitmap *mask1;
7200   GdkBitmap *mask2;
7201   GdkBitmap *mask3;
7202 } CTreePixmaps;
7203
7204 static gint books = 0;
7205 static gint pages = 0;
7206
7207 static GtkWidget *book_label;
7208 static GtkWidget *page_label;
7209 static GtkWidget *sel_label;
7210 static GtkWidget *vis_label;
7211 static GtkWidget *omenu1;
7212 static GtkWidget *omenu2;
7213 static GtkWidget *omenu3;
7214 static GtkWidget *omenu4;
7215 static GtkWidget *spin1;
7216 static GtkWidget *spin2;
7217 static GtkWidget *spin3;
7218 static gint line_style;
7219
7220
7221 static CTreePixmaps *
7222 get_ctree_pixmaps (GtkCTree *ctree)
7223 {
7224   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (ctree));
7225   CTreePixmaps *pixmaps = g_object_get_data (G_OBJECT (screen), "ctree-pixmaps");
7226
7227   if (!pixmaps)
7228     {
7229       GdkColormap *colormap = gdk_screen_get_rgb_colormap (screen);
7230       pixmaps = g_new (CTreePixmaps, 1);
7231       
7232       pixmaps->pixmap1 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7233                                                                 &pixmaps->mask1, 
7234                                                                 NULL, book_closed_xpm);
7235       pixmaps->pixmap2 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7236                                                                 &pixmaps->mask2, 
7237                                                                 NULL, book_open_xpm);
7238       pixmaps->pixmap3 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7239                                                                 &pixmaps->mask3,
7240                                                                 NULL, mini_page_xpm);
7241       
7242       g_object_set_data (G_OBJECT (screen), "ctree-pixmaps", pixmaps);
7243     }
7244
7245   return pixmaps;
7246 }
7247
7248 void after_press (GtkCTree *ctree, gpointer data)
7249 {
7250   char buf[80];
7251
7252   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
7253   gtk_label_set_text (GTK_LABEL (sel_label), buf);
7254
7255   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
7256   gtk_label_set_text (GTK_LABEL (vis_label), buf);
7257
7258   sprintf (buf, "%d", books);
7259   gtk_label_set_text (GTK_LABEL (book_label), buf);
7260
7261   sprintf (buf, "%d", pages);
7262   gtk_label_set_text (GTK_LABEL (page_label), buf);
7263 }
7264
7265 void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent, 
7266                  GtkCTreeNode *sibling, gpointer data)
7267 {
7268   char *source;
7269   char *target1;
7270   char *target2;
7271
7272   gtk_ctree_get_node_info (ctree, child, &source, 
7273                            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7274   if (parent)
7275     gtk_ctree_get_node_info (ctree, parent, &target1, 
7276                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7277   if (sibling)
7278     gtk_ctree_get_node_info (ctree, sibling, &target2, 
7279                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7280
7281   g_print ("Moving \"%s\" to \"%s\" with sibling \"%s\".\n", source,
7282            (parent) ? target1 : "nil", (sibling) ? target2 : "nil");
7283 }
7284
7285 void count_items (GtkCTree *ctree, GtkCTreeNode *list)
7286 {
7287   if (GTK_CTREE_ROW (list)->is_leaf)
7288     pages--;
7289   else
7290     books--;
7291 }
7292
7293 void expand_all (GtkWidget *widget, GtkCTree *ctree)
7294 {
7295   gtk_ctree_expand_recursive (ctree, NULL);
7296   after_press (ctree, NULL);
7297 }
7298
7299 void collapse_all (GtkWidget *widget, GtkCTree *ctree)
7300 {
7301   gtk_ctree_collapse_recursive (ctree, NULL);
7302   after_press (ctree, NULL);
7303 }
7304
7305 void select_all (GtkWidget *widget, GtkCTree *ctree)
7306 {
7307   gtk_ctree_select_recursive (ctree, NULL);
7308   after_press (ctree, NULL);
7309 }
7310
7311 void change_style (GtkWidget *widget, GtkCTree *ctree)
7312 {
7313   static GtkStyle *style1 = NULL;
7314   static GtkStyle *style2 = NULL;
7315
7316   GtkCTreeNode *node;
7317   GdkColor green_col = { 0, 0, 56000, 0};
7318   GdkColor purple_col = { 0, 32000, 0, 56000};
7319
7320   if (GTK_CLIST (ctree)->focus_row >= 0)
7321     node = GTK_CTREE_NODE
7322       (g_list_nth (GTK_CLIST (ctree)->row_list,GTK_CLIST (ctree)->focus_row));
7323   else
7324     node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
7325
7326   if (!node)
7327     return;
7328
7329   if (!style1)
7330     {
7331       style1 = gtk_style_new ();
7332       style1->base[GTK_STATE_NORMAL] = green_col;
7333       style1->fg[GTK_STATE_SELECTED] = purple_col;
7334
7335       style2 = gtk_style_new ();
7336       style2->base[GTK_STATE_SELECTED] = purple_col;
7337       style2->fg[GTK_STATE_NORMAL] = green_col;
7338       style2->base[GTK_STATE_NORMAL] = purple_col;
7339       pango_font_description_free (style2->font_desc);
7340       style2->font_desc = pango_font_description_from_string ("courier 30");
7341     }
7342
7343   gtk_ctree_node_set_cell_style (ctree, node, 1, style1);
7344   gtk_ctree_node_set_cell_style (ctree, node, 0, style2);
7345
7346   if (GTK_CTREE_ROW (node)->children)
7347     gtk_ctree_node_set_row_style (ctree, GTK_CTREE_ROW (node)->children,
7348                                   style2);
7349 }
7350
7351 void unselect_all (GtkWidget *widget, GtkCTree *ctree)
7352 {
7353   gtk_ctree_unselect_recursive (ctree, NULL);
7354   after_press (ctree, NULL);
7355 }
7356
7357 void remove_selection (GtkWidget *widget, GtkCTree *ctree)
7358 {
7359   GtkCList *clist;
7360   GtkCTreeNode *node;
7361
7362   clist = GTK_CLIST (ctree);
7363
7364   gtk_clist_freeze (clist);
7365
7366   while (clist->selection)
7367     {
7368       node = clist->selection->data;
7369
7370       if (GTK_CTREE_ROW (node)->is_leaf)
7371         pages--;
7372       else
7373         gtk_ctree_post_recursive (ctree, node,
7374                                   (GtkCTreeFunc) count_items, NULL);
7375
7376       gtk_ctree_remove_node (ctree, node);
7377
7378       if (clist->selection_mode == GTK_SELECTION_BROWSE)
7379         break;
7380     }
7381
7382   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
7383       clist->focus_row >= 0)
7384     {
7385       node = gtk_ctree_node_nth (ctree, clist->focus_row);
7386
7387       if (node)
7388         gtk_ctree_select (ctree, node);
7389     }
7390     
7391   gtk_clist_thaw (clist);
7392   after_press (ctree, NULL);
7393 }
7394
7395 struct _ExportStruct {
7396   gchar *tree;
7397   gchar *info;
7398   gboolean is_leaf;
7399 };
7400
7401 typedef struct _ExportStruct ExportStruct;
7402
7403 gboolean
7404 gnode2ctree (GtkCTree   *ctree,
7405              guint       depth,
7406              GNode        *gnode,
7407              GtkCTreeNode *cnode,
7408              gpointer    data)
7409 {
7410   ExportStruct *es;
7411   GdkPixmap *pixmap_closed;
7412   GdkBitmap *mask_closed;
7413   GdkPixmap *pixmap_opened;
7414   GdkBitmap *mask_opened;
7415   CTreePixmaps *pixmaps;
7416
7417   if (!cnode || !gnode || (!(es = gnode->data)))
7418     return FALSE;
7419
7420   pixmaps = get_ctree_pixmaps (ctree);
7421
7422   if (es->is_leaf)
7423     {
7424       pixmap_closed = pixmaps->pixmap3;
7425       mask_closed = pixmaps->mask3;
7426       pixmap_opened = NULL;
7427       mask_opened = NULL;
7428     }
7429   else
7430     {
7431       pixmap_closed = pixmaps->pixmap1;
7432       mask_closed = pixmaps->mask1;
7433       pixmap_opened = pixmaps->pixmap2;
7434       mask_opened = pixmaps->mask2;
7435     }
7436
7437   gtk_ctree_set_node_info (ctree, cnode, es->tree, 2, pixmap_closed,
7438                            mask_closed, pixmap_opened, mask_opened,
7439                            es->is_leaf, (depth < 3));
7440   gtk_ctree_node_set_text (ctree, cnode, 1, es->info);
7441   g_free (es);
7442   gnode->data = NULL;
7443
7444   return TRUE;
7445 }
7446
7447 gboolean
7448 ctree2gnode (GtkCTree   *ctree,
7449              guint       depth,
7450              GNode        *gnode,
7451              GtkCTreeNode *cnode,
7452              gpointer    data)
7453 {
7454   ExportStruct *es;
7455
7456   if (!cnode || !gnode)
7457     return FALSE;
7458   
7459   es = g_new (ExportStruct, 1);
7460   gnode->data = es;
7461   es->is_leaf = GTK_CTREE_ROW (cnode)->is_leaf;
7462   es->tree = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[0])->text;
7463   es->info = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[1])->text;
7464   return TRUE;
7465 }
7466
7467 void export_ctree (GtkWidget *widget, GtkCTree *ctree)
7468 {
7469   char *title[] = { "Tree" , "Info" };
7470   static GtkWidget *export_window = NULL;
7471   static GtkCTree *export_ctree;
7472   GtkWidget *vbox;
7473   GtkWidget *scrolled_win;
7474   GtkWidget *button;
7475   GtkWidget *sep;
7476   GNode *gnode;
7477   GtkCTreeNode *node;
7478
7479   if (!export_window)
7480     {
7481       export_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7482
7483       gtk_window_set_screen (GTK_WINDOW (export_window),
7484                              gtk_widget_get_screen (widget));
7485   
7486       g_signal_connect (export_window, "destroy",
7487                         G_CALLBACK (gtk_widget_destroyed),
7488                         &export_window);
7489
7490       gtk_window_set_title (GTK_WINDOW (export_window), "exported ctree");
7491       gtk_container_set_border_width (GTK_CONTAINER (export_window), 5);
7492
7493       vbox = gtk_vbox_new (FALSE, 0);
7494       gtk_container_add (GTK_CONTAINER (export_window), vbox);
7495       
7496       button = gtk_button_new_with_label ("Close");
7497       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, TRUE, 0);
7498
7499       g_signal_connect_swapped (button, "clicked",
7500                                 G_CALLBACK (gtk_widget_destroy),
7501                                 export_window);
7502
7503       sep = gtk_hseparator_new ();
7504       gtk_box_pack_end (GTK_BOX (vbox), sep, FALSE, TRUE, 10);
7505
7506       export_ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7507       gtk_ctree_set_line_style (export_ctree, GTK_CTREE_LINES_DOTTED);
7508
7509       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7510       gtk_container_add (GTK_CONTAINER (scrolled_win),
7511                          GTK_WIDGET (export_ctree));
7512       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7513                                       GTK_POLICY_AUTOMATIC,
7514                                       GTK_POLICY_AUTOMATIC);
7515       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7516       gtk_clist_set_selection_mode (GTK_CLIST (export_ctree),
7517                                     GTK_SELECTION_EXTENDED);
7518       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 0, 200);
7519       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 1, 200);
7520       gtk_widget_set_size_request (GTK_WIDGET (export_ctree), 300, 200);
7521     }
7522
7523   if (!GTK_WIDGET_VISIBLE (export_window))
7524     gtk_widget_show_all (export_window);
7525       
7526   gtk_clist_clear (GTK_CLIST (export_ctree));
7527
7528   node = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list,
7529                                      GTK_CLIST (ctree)->focus_row));
7530   if (!node)
7531     return;
7532
7533   gnode = gtk_ctree_export_to_gnode (ctree, NULL, NULL, node,
7534                                      ctree2gnode, NULL);
7535   if (gnode)
7536     {
7537       gtk_ctree_insert_gnode (export_ctree, NULL, NULL, gnode,
7538                               gnode2ctree, NULL);
7539       g_node_destroy (gnode);
7540     }
7541 }
7542
7543 void change_indent (GtkWidget *widget, GtkCTree *ctree)
7544 {
7545   gtk_ctree_set_indent (ctree, GTK_ADJUSTMENT (widget)->value);
7546 }
7547
7548 void change_spacing (GtkWidget *widget, GtkCTree *ctree)
7549 {
7550   gtk_ctree_set_spacing (ctree, GTK_ADJUSTMENT (widget)->value);
7551 }
7552
7553 void change_row_height (GtkWidget *widget, GtkCList *clist)
7554 {
7555   gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value);
7556 }
7557
7558 void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data)
7559 {
7560   GtkStyle *style = NULL;
7561   
7562   if (!node)
7563     return;
7564   
7565   if (ctree->line_style != GTK_CTREE_LINES_TABBED)
7566     {
7567       if (!GTK_CTREE_ROW (node)->is_leaf)
7568         style = GTK_CTREE_ROW (node)->row.data;
7569       else if (GTK_CTREE_ROW (node)->parent)
7570         style = GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->row.data;
7571     }
7572
7573   gtk_ctree_node_set_row_style (ctree, node, style);
7574 }
7575
7576 void 
7577 ctree_toggle_line_style (GtkWidget *widget, gpointer data)
7578 {
7579   GtkCTree *ctree;
7580   gint i;
7581
7582   ctree = GTK_CTREE (data);
7583
7584   if (!GTK_WIDGET_MAPPED (widget))
7585     return;
7586
7587   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7588
7589   if ((ctree->line_style == GTK_CTREE_LINES_TABBED && 
7590        ((GtkCTreeLineStyle) i) != GTK_CTREE_LINES_TABBED) ||
7591       (ctree->line_style != GTK_CTREE_LINES_TABBED && 
7592        ((GtkCTreeLineStyle) i) == GTK_CTREE_LINES_TABBED))
7593     gtk_ctree_pre_recursive (ctree, NULL, set_background, NULL);
7594   gtk_ctree_set_line_style (ctree, i);
7595   line_style = i;
7596 }
7597
7598 void 
7599 ctree_toggle_expander_style (GtkWidget *widget, gpointer data)
7600 {
7601   GtkCTree *ctree;
7602   gint i;
7603
7604   ctree = GTK_CTREE (data);
7605
7606   if (!GTK_WIDGET_MAPPED (widget))
7607     return;
7608   
7609   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7610   
7611   gtk_ctree_set_expander_style (ctree, (GtkCTreeExpanderStyle) i);
7612 }
7613
7614 void 
7615 ctree_toggle_justify (GtkWidget *widget, gpointer data)
7616 {
7617   GtkCTree *ctree;
7618   gint i;
7619
7620   ctree = GTK_CTREE (data);
7621
7622   if (!GTK_WIDGET_MAPPED (widget))
7623     return;
7624
7625   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7626
7627   gtk_clist_set_column_justification (GTK_CLIST (ctree), ctree->tree_column, 
7628                                       (GtkJustification) i);
7629 }
7630
7631 void 
7632 ctree_toggle_sel_mode (GtkWidget *widget, gpointer data)
7633 {
7634   GtkCTree *ctree;
7635   gint i;
7636
7637   ctree = GTK_CTREE (data);
7638
7639   if (!GTK_WIDGET_MAPPED (widget))
7640     return;
7641
7642   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7643
7644   gtk_clist_set_selection_mode (GTK_CLIST (ctree), selection_modes[i]);
7645   after_press (ctree, NULL);
7646 }
7647     
7648 void build_recursive (GtkCTree *ctree, gint cur_depth, gint depth, 
7649                       gint num_books, gint num_pages, GtkCTreeNode *parent)
7650 {
7651   gchar *text[2];
7652   gchar buf1[60];
7653   gchar buf2[60];
7654   GtkCTreeNode *sibling;
7655   CTreePixmaps *pixmaps;
7656   gint i;
7657
7658   text[0] = buf1;
7659   text[1] = buf2;
7660   sibling = NULL;
7661
7662   pixmaps = get_ctree_pixmaps (ctree);
7663
7664   for (i = num_pages + num_books; i > num_books; i--)
7665     {
7666       pages++;
7667       sprintf (buf1, "Page %02d", (gint) rand() % 100);
7668       sprintf (buf2, "Item %d-%d", cur_depth, i);
7669       sibling = gtk_ctree_insert_node (ctree, parent, sibling, text, 5,
7670                                        pixmaps->pixmap3, pixmaps->mask3, NULL, NULL,
7671                                        TRUE, FALSE);
7672
7673       if (parent && ctree->line_style == GTK_CTREE_LINES_TABBED)
7674         gtk_ctree_node_set_row_style (ctree, sibling,
7675                                       GTK_CTREE_ROW (parent)->row.style);
7676     }
7677
7678   if (cur_depth == depth)
7679     return;
7680
7681   for (i = num_books; i > 0; i--)
7682     {
7683       GtkStyle *style;
7684
7685       books++;
7686       sprintf (buf1, "Book %02d", (gint) rand() % 100);
7687       sprintf (buf2, "Item %d-%d", cur_depth, i);
7688       sibling = gtk_ctree_insert_node (ctree, parent, sibling, text, 5,
7689                                        pixmaps->pixmap1, pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2,
7690                                        FALSE, FALSE);
7691
7692       style = gtk_style_new ();
7693       switch (cur_depth % 3)
7694         {
7695         case 0:
7696           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7697           style->base[GTK_STATE_NORMAL].green = 0;
7698           style->base[GTK_STATE_NORMAL].blue  = 65535 - ((i * 10000) % 65535);
7699           break;
7700         case 1:
7701           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7702           style->base[GTK_STATE_NORMAL].green = 65535 - ((i * 10000) % 65535);
7703           style->base[GTK_STATE_NORMAL].blue  = 0;
7704           break;
7705         default:
7706           style->base[GTK_STATE_NORMAL].red   = 65535 - ((i * 10000) % 65535);
7707           style->base[GTK_STATE_NORMAL].green = 0;
7708           style->base[GTK_STATE_NORMAL].blue  = 10000 * (cur_depth % 6);
7709           break;
7710         }
7711       gtk_ctree_node_set_row_data_full (ctree, sibling, style,
7712                                         (GDestroyNotify) g_object_unref);
7713
7714       if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7715         gtk_ctree_node_set_row_style (ctree, sibling, style);
7716
7717       build_recursive (ctree, cur_depth + 1, depth, num_books, num_pages,
7718                        sibling);
7719     }
7720 }
7721
7722 void rebuild_tree (GtkWidget *widget, GtkCTree *ctree)
7723 {
7724   gchar *text [2];
7725   gchar label1[] = "Root";
7726   gchar label2[] = "";
7727   GtkCTreeNode *parent;
7728   GtkStyle *style;
7729   guint b, d, p, n;
7730   CTreePixmaps *pixmaps;
7731
7732   pixmaps = get_ctree_pixmaps (ctree);
7733
7734   text[0] = label1;
7735   text[1] = label2;
7736   
7737   d = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1)); 
7738   b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7739   p = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin3));
7740
7741   n = ((pow (b, d) - 1) / (b - 1)) * (p + 1);
7742
7743   if (n > 100000)
7744     {
7745       g_print ("%d total items? Try less\n",n);
7746       return;
7747     }
7748
7749   gtk_clist_freeze (GTK_CLIST (ctree));
7750   gtk_clist_clear (GTK_CLIST (ctree));
7751
7752   books = 1;
7753   pages = 0;
7754
7755   parent = gtk_ctree_insert_node (ctree, NULL, NULL, text, 5, pixmaps->pixmap1,
7756                                   pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2, FALSE, TRUE);
7757
7758   style = gtk_style_new ();
7759   style->base[GTK_STATE_NORMAL].red   = 0;
7760   style->base[GTK_STATE_NORMAL].green = 45000;
7761   style->base[GTK_STATE_NORMAL].blue  = 55000;
7762   gtk_ctree_node_set_row_data_full (ctree, parent, style,
7763                                     (GDestroyNotify) g_object_unref);
7764
7765   if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7766     gtk_ctree_node_set_row_style (ctree, parent, style);
7767
7768   build_recursive (ctree, 1, d, b, p, parent);
7769   gtk_clist_thaw (GTK_CLIST (ctree));
7770   after_press (ctree, NULL);
7771 }
7772
7773 static void 
7774 ctree_click_column (GtkCTree *ctree, gint column, gpointer data)
7775 {
7776   GtkCList *clist;
7777
7778   clist = GTK_CLIST (ctree);
7779
7780   if (column == clist->sort_column)
7781     {
7782       if (clist->sort_type == GTK_SORT_ASCENDING)
7783         clist->sort_type = GTK_SORT_DESCENDING;
7784       else
7785         clist->sort_type = GTK_SORT_ASCENDING;
7786     }
7787   else
7788     gtk_clist_set_sort_column (clist, column);
7789
7790   gtk_ctree_sort_recursive (ctree, NULL);
7791 }
7792
7793 void create_ctree (GtkWidget *widget)
7794 {
7795   static GtkWidget *window = NULL;
7796   GtkTooltips *tooltips;
7797   GtkCTree *ctree;
7798   GtkWidget *scrolled_win;
7799   GtkWidget *vbox;
7800   GtkWidget *bbox;
7801   GtkWidget *mbox;
7802   GtkWidget *hbox;
7803   GtkWidget *hbox2;
7804   GtkWidget *frame;
7805   GtkWidget *label;
7806   GtkWidget *button;
7807   GtkWidget *check;
7808   GtkAdjustment *adj;
7809   GtkWidget *spinner;
7810
7811   char *title[] = { "Tree" , "Info" };
7812   char buf[80];
7813
7814   static gchar *items1[] =
7815   {
7816     "No lines",
7817     "Solid",
7818     "Dotted",
7819     "Tabbed"
7820   };
7821
7822   static gchar *items2[] =
7823   {
7824     "None",
7825     "Square",
7826     "Triangle",
7827     "Circular"
7828   };
7829
7830   static gchar *items3[] =
7831   {
7832     "Left",
7833     "Right"
7834   };
7835   
7836   if (!window)
7837     {
7838       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7839       gtk_window_set_screen (GTK_WINDOW (window), 
7840                              gtk_widget_get_screen (widget));
7841
7842       g_signal_connect (window, "destroy",
7843                         G_CALLBACK (gtk_widget_destroyed),
7844                         &window);
7845
7846       gtk_window_set_title (GTK_WINDOW (window), "GtkCTree");
7847       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7848
7849       tooltips = gtk_tooltips_new ();
7850       g_object_ref (tooltips);
7851       gtk_object_sink (GTK_OBJECT (tooltips));
7852
7853       g_object_set_data_full (G_OBJECT (window), "tooltips", tooltips,
7854                               g_object_unref);
7855
7856       vbox = gtk_vbox_new (FALSE, 0);
7857       gtk_container_add (GTK_CONTAINER (window), vbox);
7858
7859       hbox = gtk_hbox_new (FALSE, 5);
7860       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7861       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7862       
7863       label = gtk_label_new ("Depth :");
7864       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7865       
7866       adj = (GtkAdjustment *) gtk_adjustment_new (4, 1, 10, 1, 5, 0);
7867       spin1 = gtk_spin_button_new (adj, 0, 0);
7868       gtk_box_pack_start (GTK_BOX (hbox), spin1, FALSE, TRUE, 5);
7869   
7870       label = gtk_label_new ("Books :");
7871       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7872       
7873       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
7874       spin2 = gtk_spin_button_new (adj, 0, 0);
7875       gtk_box_pack_start (GTK_BOX (hbox), spin2, FALSE, TRUE, 5);
7876
7877       label = gtk_label_new ("Pages :");
7878       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7879       
7880       adj = (GtkAdjustment *) gtk_adjustment_new (5, 1, 20, 1, 5, 0);
7881       spin3 = gtk_spin_button_new (adj, 0, 0);
7882       gtk_box_pack_start (GTK_BOX (hbox), spin3, FALSE, TRUE, 5);
7883
7884       button = gtk_button_new_with_label ("Close");
7885       gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7886
7887       g_signal_connect_swapped (button, "clicked",
7888                                 G_CALLBACK (gtk_widget_destroy),
7889                                 window);
7890
7891       button = gtk_button_new_with_label ("Rebuild Tree");
7892       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7893
7894       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7895       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
7896       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7897                                       GTK_POLICY_AUTOMATIC,
7898                                       GTK_POLICY_ALWAYS);
7899       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7900
7901       ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7902       gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree));
7903
7904       gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
7905       gtk_clist_set_column_width (GTK_CLIST (ctree), 1, 200);
7906       gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_EXTENDED);
7907       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
7908       line_style = GTK_CTREE_LINES_DOTTED;
7909
7910       g_signal_connect (button, "clicked",
7911                         G_CALLBACK (rebuild_tree), ctree);
7912       g_signal_connect (ctree, "click_column",
7913                         G_CALLBACK (ctree_click_column), NULL);
7914
7915       g_signal_connect_after (ctree, "button_press_event",
7916                               G_CALLBACK (after_press), NULL);
7917       g_signal_connect_after (ctree, "button_release_event",
7918                               G_CALLBACK (after_press), NULL);
7919       g_signal_connect_after (ctree, "tree_move",
7920                               G_CALLBACK (after_move), NULL);
7921       g_signal_connect_after (ctree, "end_selection",
7922                               G_CALLBACK (after_press), NULL);
7923       g_signal_connect_after (ctree, "toggle_focus_row",
7924                               G_CALLBACK (after_press), NULL);
7925       g_signal_connect_after (ctree, "select_all",
7926                               G_CALLBACK (after_press), NULL);
7927       g_signal_connect_after (ctree, "unselect_all",
7928                               G_CALLBACK (after_press), NULL);
7929       g_signal_connect_after (ctree, "scroll_vertical",
7930                               G_CALLBACK (after_press), NULL);
7931
7932       bbox = gtk_hbox_new (FALSE, 5);
7933       gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7934       gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0);
7935
7936       mbox = gtk_vbox_new (TRUE, 5);
7937       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7938
7939       label = gtk_label_new ("Row Height :");
7940       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7941
7942       label = gtk_label_new ("Indent :");
7943       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7944
7945       label = gtk_label_new ("Spacing :");
7946       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7947
7948       mbox = gtk_vbox_new (TRUE, 5);
7949       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7950
7951       adj = (GtkAdjustment *) gtk_adjustment_new (20, 12, 100, 1, 10, 0);
7952       spinner = gtk_spin_button_new (adj, 0, 0);
7953       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7954       gtk_tooltips_set_tip (tooltips, spinner,
7955                             "Row height of list items", NULL);
7956       g_signal_connect (adj, "value_changed",
7957                         G_CALLBACK (change_row_height), ctree);
7958       gtk_clist_set_row_height ( GTK_CLIST (ctree), adj->value);
7959
7960       adj = (GtkAdjustment *) gtk_adjustment_new (20, 0, 60, 1, 10, 0);
7961       spinner = gtk_spin_button_new (adj, 0, 0);
7962       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7963       gtk_tooltips_set_tip (tooltips, spinner, "Tree Indentation.", NULL);
7964       g_signal_connect (adj, "value_changed",
7965                         G_CALLBACK (change_indent), ctree);
7966
7967       adj = (GtkAdjustment *) gtk_adjustment_new (5, 0, 60, 1, 10, 0);
7968       spinner = gtk_spin_button_new (adj, 0, 0);
7969       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7970       gtk_tooltips_set_tip (tooltips, spinner, "Tree Spacing.", NULL);
7971       g_signal_connect (adj, "value_changed",
7972                         G_CALLBACK (change_spacing), ctree);
7973
7974       mbox = gtk_vbox_new (TRUE, 5);
7975       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7976
7977       hbox = gtk_hbox_new (FALSE, 5);
7978       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7979
7980       button = gtk_button_new_with_label ("Expand All");
7981       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7982       g_signal_connect (button, "clicked",
7983                         G_CALLBACK (expand_all), ctree);
7984
7985       button = gtk_button_new_with_label ("Collapse All");
7986       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7987       g_signal_connect (button, "clicked",
7988                         G_CALLBACK (collapse_all), ctree);
7989
7990       button = gtk_button_new_with_label ("Change Style");
7991       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7992       g_signal_connect (button, "clicked",
7993                         G_CALLBACK (change_style), ctree);
7994
7995       button = gtk_button_new_with_label ("Export Tree");
7996       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7997       g_signal_connect (button, "clicked",
7998                         G_CALLBACK (export_ctree), ctree);
7999
8000       hbox = gtk_hbox_new (FALSE, 5);
8001       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
8002
8003       button = gtk_button_new_with_label ("Select All");
8004       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
8005       g_signal_connect (button, "clicked",
8006                         G_CALLBACK (select_all), ctree);
8007
8008       button = gtk_button_new_with_label ("Unselect All");
8009       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
8010       g_signal_connect (button, "clicked",
8011                         G_CALLBACK (unselect_all), ctree);
8012
8013       button = gtk_button_new_with_label ("Remove Selection");
8014       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
8015       g_signal_connect (button, "clicked",
8016                         G_CALLBACK (remove_selection), ctree);
8017
8018       check = gtk_check_button_new_with_label ("Reorderable");
8019       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
8020       gtk_tooltips_set_tip (tooltips, check,
8021                             "Tree items can be reordered by dragging.", NULL);
8022       g_signal_connect (check, "clicked",
8023                         G_CALLBACK (toggle_reorderable), ctree);
8024       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
8025
8026       hbox = gtk_hbox_new (TRUE, 5);
8027       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
8028
8029       omenu1 = build_option_menu (items1, 4, 2, 
8030                                   ctree_toggle_line_style,
8031                                   ctree);
8032       gtk_box_pack_start (GTK_BOX (hbox), omenu1, FALSE, TRUE, 0);
8033       gtk_tooltips_set_tip (tooltips, omenu1, "The tree's line style.", NULL);
8034
8035       omenu2 = build_option_menu (items2, 4, 1, 
8036                                   ctree_toggle_expander_style,
8037                                   ctree);
8038       gtk_box_pack_start (GTK_BOX (hbox), omenu2, FALSE, TRUE, 0);
8039       gtk_tooltips_set_tip (tooltips, omenu2, "The tree's expander style.",
8040                             NULL);
8041
8042       omenu3 = build_option_menu (items3, 2, 0, 
8043                                   ctree_toggle_justify, ctree);
8044       gtk_box_pack_start (GTK_BOX (hbox), omenu3, FALSE, TRUE, 0);
8045       gtk_tooltips_set_tip (tooltips, omenu3, "The tree's justification.",
8046                             NULL);
8047
8048       omenu4 = build_option_menu (selection_mode_items, 3, 3, 
8049                                   ctree_toggle_sel_mode, ctree);
8050       gtk_box_pack_start (GTK_BOX (hbox), omenu4, FALSE, TRUE, 0);
8051       gtk_tooltips_set_tip (tooltips, omenu4, "The list's selection mode.",
8052                             NULL);
8053
8054       gtk_widget_realize (window);
8055       
8056       gtk_widget_set_size_request (GTK_WIDGET (ctree), -1, 300);
8057
8058       frame = gtk_frame_new (NULL);
8059       gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
8060       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
8061       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8062
8063       hbox = gtk_hbox_new (TRUE, 2);
8064       gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
8065       gtk_container_add (GTK_CONTAINER (frame), hbox);
8066
8067       frame = gtk_frame_new (NULL);
8068       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8069       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8070
8071       hbox2 = gtk_hbox_new (FALSE, 0);
8072       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8073       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8074
8075       label = gtk_label_new ("Books :");
8076       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8077
8078       sprintf (buf, "%d", books);
8079       book_label = gtk_label_new (buf);
8080       gtk_box_pack_end (GTK_BOX (hbox2), book_label, FALSE, TRUE, 5);
8081
8082       frame = gtk_frame_new (NULL);
8083       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8084       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8085
8086       hbox2 = gtk_hbox_new (FALSE, 0);
8087       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8088       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8089
8090       label = gtk_label_new ("Pages :");
8091       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8092
8093       sprintf (buf, "%d", pages);
8094       page_label = gtk_label_new (buf);
8095       gtk_box_pack_end (GTK_BOX (hbox2), page_label, FALSE, TRUE, 5);
8096
8097       frame = gtk_frame_new (NULL);
8098       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8099       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8100
8101       hbox2 = gtk_hbox_new (FALSE, 0);
8102       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8103       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8104
8105       label = gtk_label_new ("Selected :");
8106       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8107
8108       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
8109       sel_label = gtk_label_new (buf);
8110       gtk_box_pack_end (GTK_BOX (hbox2), sel_label, FALSE, TRUE, 5);
8111
8112       frame = gtk_frame_new (NULL);
8113       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8114       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8115
8116       hbox2 = gtk_hbox_new (FALSE, 0);
8117       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8118       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8119
8120       label = gtk_label_new ("Visible :");
8121       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8122
8123       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
8124       vis_label = gtk_label_new (buf);
8125       gtk_box_pack_end (GTK_BOX (hbox2), vis_label, FALSE, TRUE, 5);
8126
8127       rebuild_tree (NULL, ctree);
8128     }
8129
8130   if (!GTK_WIDGET_VISIBLE (window))
8131     gtk_widget_show_all (window);
8132   else
8133     gtk_widget_destroy (window);
8134 }
8135
8136 /*
8137  * GtkColorSelection
8138  */
8139
8140 void
8141 color_selection_ok (GtkWidget               *w,
8142                     GtkColorSelectionDialog *cs)
8143 {
8144   GtkColorSelection *colorsel;
8145   gdouble color[4];
8146
8147   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8148
8149   gtk_color_selection_get_color(colorsel,color);
8150   gtk_color_selection_set_color(colorsel,color);
8151 }
8152
8153 void
8154 color_selection_changed (GtkWidget *w,
8155                          GtkColorSelectionDialog *cs)
8156 {
8157   GtkColorSelection *colorsel;
8158   gdouble color[4];
8159
8160   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8161   gtk_color_selection_get_color(colorsel,color);
8162 }
8163
8164 #if 0 /* unused */
8165 static void
8166 opacity_toggled_cb (GtkWidget *w,
8167                     GtkColorSelectionDialog *cs)
8168 {
8169   GtkColorSelection *colorsel;
8170
8171   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8172   gtk_color_selection_set_has_opacity_control (colorsel,
8173                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8174 }
8175
8176 static void
8177 palette_toggled_cb (GtkWidget *w,
8178                     GtkColorSelectionDialog *cs)
8179 {
8180   GtkColorSelection *colorsel;
8181
8182   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8183   gtk_color_selection_set_has_palette (colorsel,
8184                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8185 }
8186 #endif
8187
8188 void
8189 create_color_selection (GtkWidget *widget)
8190 {
8191   static GtkWidget *window = NULL;
8192
8193   if (!window)
8194     {
8195       GtkWidget *picker;
8196       GtkWidget *hbox;
8197       GtkWidget *label;
8198       
8199       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8200       gtk_window_set_screen (GTK_WINDOW (window), 
8201                              gtk_widget_get_screen (widget));
8202                              
8203       g_signal_connect (window, "destroy",
8204                         G_CALLBACK (gtk_widget_destroyed),
8205                         &window);
8206
8207       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
8208       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8209
8210       hbox = gtk_hbox_new (FALSE, 8);
8211       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8212       gtk_container_add (GTK_CONTAINER (window), hbox);
8213       
8214       label = gtk_label_new ("Pick a color");
8215       gtk_container_add (GTK_CONTAINER (hbox), label);
8216
8217       picker = gtk_color_button_new ();
8218       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
8219       gtk_container_add (GTK_CONTAINER (hbox), picker);
8220     }
8221
8222   if (!GTK_WIDGET_VISIBLE (window))
8223     gtk_widget_show_all (window);
8224   else
8225     gtk_widget_destroy (window);
8226 }
8227
8228 /*
8229  * GtkFileSelection
8230  */
8231
8232 void
8233 show_fileops (GtkWidget        *widget,
8234               GtkFileSelection *fs)
8235 {
8236   gboolean show_ops;
8237
8238   show_ops = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8239
8240   if (show_ops)
8241     gtk_file_selection_show_fileop_buttons (fs);
8242   else
8243     gtk_file_selection_hide_fileop_buttons (fs);
8244 }
8245
8246 void
8247 select_multiple (GtkWidget        *widget,
8248                  GtkFileSelection *fs)
8249 {
8250   gboolean select_multiple;
8251
8252   select_multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8253   gtk_file_selection_set_select_multiple (fs, select_multiple);
8254 }
8255
8256 void
8257 file_selection_ok (GtkFileSelection *fs)
8258 {
8259   int i;
8260   gchar **selections;
8261
8262   selections = gtk_file_selection_get_selections (fs);
8263
8264   for (i = 0; selections[i] != NULL; i++)
8265     g_print ("%s\n", selections[i]);
8266
8267   g_strfreev (selections);
8268
8269   gtk_widget_destroy (GTK_WIDGET (fs));
8270 }
8271
8272 void
8273 create_file_selection (GtkWidget *widget)
8274 {
8275   static GtkWidget *window = NULL;
8276   GtkWidget *button;
8277
8278   if (!window)
8279     {
8280       window = gtk_file_selection_new ("file selection dialog");
8281       gtk_window_set_screen (GTK_WINDOW (window),
8282                              gtk_widget_get_screen (widget));
8283
8284       gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (window));
8285
8286       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
8287
8288       g_signal_connect (window, "destroy",
8289                         G_CALLBACK (gtk_widget_destroyed),
8290                         &window);
8291
8292       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->ok_button,
8293                                 "clicked",
8294                                 G_CALLBACK (file_selection_ok),
8295                                 window);
8296       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->cancel_button,
8297                                 "clicked",
8298                                 G_CALLBACK (gtk_widget_destroy),
8299                                 window);
8300       
8301       button = gtk_check_button_new_with_label ("Show Fileops");
8302       g_signal_connect (button, "toggled",
8303                         G_CALLBACK (show_fileops),
8304                         window);
8305       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8306                           button, FALSE, FALSE, 0);
8307       gtk_widget_show (button);
8308
8309       button = gtk_check_button_new_with_label ("Select Multiple");
8310       g_signal_connect (button, "clicked",
8311                         G_CALLBACK (select_multiple),
8312                         window);
8313       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8314                           button, FALSE, FALSE, 0);
8315       gtk_widget_show (button);
8316     }
8317   
8318   if (!GTK_WIDGET_VISIBLE (window))
8319     gtk_widget_show (window);
8320   else
8321     gtk_widget_destroy (window);
8322 }
8323
8324 void
8325 flipping_toggled_cb (GtkWidget *widget, gpointer data)
8326 {
8327   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8328   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
8329
8330   gtk_widget_set_default_direction (new_direction);
8331 }
8332
8333 static void
8334 orientable_toggle_orientation (GtkOrientable *orientable)
8335 {
8336   GtkOrientation orientation;
8337
8338   orientation = gtk_orientable_get_orientation (orientable);
8339   gtk_orientable_set_orientation (orientable,
8340                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
8341                                   GTK_ORIENTATION_VERTICAL :
8342                                   GTK_ORIENTATION_HORIZONTAL);
8343
8344   if (GTK_IS_CONTAINER (orientable))
8345     {
8346       GList *children;
8347       GList *child;
8348
8349       children = gtk_container_get_children (GTK_CONTAINER (orientable));
8350
8351       for (child = children; child; child = child->next)
8352         {
8353           if (GTK_IS_ORIENTABLE (child->data))
8354             orientable_toggle_orientation (child->data);
8355         }
8356
8357       g_list_free (children);
8358     }
8359 }
8360
8361 void
8362 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
8363 {
8364   orientable_toggle_orientation (GTK_ORIENTABLE (GTK_DIALOG (gtk_widget_get_toplevel (widget))->vbox));
8365 }
8366
8367 static void
8368 set_direction_recurse (GtkWidget *widget,
8369                        gpointer   data)
8370 {
8371   GtkTextDirection *dir = data;
8372   
8373   gtk_widget_set_direction (widget, *dir);
8374   if (GTK_IS_CONTAINER (widget))
8375     gtk_container_foreach (GTK_CONTAINER (widget),
8376                            set_direction_recurse,
8377                            data);
8378 }
8379
8380 static GtkWidget *
8381 create_forward_back (const char       *title,
8382                      GtkTextDirection  text_dir)
8383 {
8384   GtkWidget *frame = gtk_frame_new (title);
8385   GtkWidget *bbox = gtk_hbutton_box_new ();
8386   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
8387   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
8388
8389   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
8390   
8391   gtk_container_add (GTK_CONTAINER (frame), bbox);
8392   gtk_container_add (GTK_CONTAINER (bbox), back_button);
8393   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
8394
8395   set_direction_recurse (frame, &text_dir);
8396
8397   return frame;
8398 }
8399
8400 void
8401 create_flipping (GtkWidget *widget)
8402 {
8403   static GtkWidget *window = NULL;
8404   GtkWidget *check_button, *button;
8405
8406   if (!window)
8407     {
8408       window = gtk_dialog_new ();
8409
8410       gtk_window_set_screen (GTK_WINDOW (window),
8411                              gtk_widget_get_screen (widget));
8412
8413       g_signal_connect (window, "destroy",
8414                         G_CALLBACK (gtk_widget_destroyed),
8415                         &window);
8416
8417       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
8418
8419       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
8420       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8421       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
8422                           check_button, TRUE, TRUE, 0);
8423
8424       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
8425         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
8426
8427       g_signal_connect (check_button, "toggled",
8428                         G_CALLBACK (flipping_toggled_cb), NULL);
8429
8430       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
8431       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8432       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8433                           check_button, TRUE, TRUE, 0);
8434
8435       g_signal_connect (check_button, "toggled",
8436                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
8437
8438       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8439                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
8440                           TRUE, TRUE, 0);
8441
8442       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8443                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
8444                           TRUE, TRUE, 0);
8445
8446       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8447                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
8448                           TRUE, TRUE, 0);
8449
8450       button = gtk_button_new_with_label ("Close");
8451       g_signal_connect_swapped (button, "clicked",
8452                                 G_CALLBACK (gtk_widget_destroy), window);
8453       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
8454                           button, TRUE, TRUE, 0);
8455     }
8456   
8457   if (!GTK_WIDGET_VISIBLE (window))
8458     gtk_widget_show_all (window);
8459   else
8460     gtk_widget_destroy (window);
8461 }
8462
8463 /*
8464  * Focus test
8465  */
8466
8467 static GtkWidget*
8468 make_focus_table (GList **list)
8469 {
8470   GtkWidget *table;
8471   gint i, j;
8472   
8473   table = gtk_table_new (5, 5, FALSE);
8474
8475   i = 0;
8476   j = 0;
8477
8478   while (i < 5)
8479     {
8480       j = 0;
8481       while (j < 5)
8482         {
8483           GtkWidget *widget;
8484           
8485           if ((i + j) % 2)
8486             widget = gtk_entry_new ();
8487           else
8488             widget = gtk_button_new_with_label ("Foo");
8489
8490           *list = g_list_prepend (*list, widget);
8491           
8492           gtk_table_attach (GTK_TABLE (table),
8493                             widget,
8494                             i, i + 1,
8495                             j, j + 1,
8496                             GTK_EXPAND | GTK_FILL,
8497                             GTK_EXPAND | GTK_FILL,
8498                             5, 5);
8499           
8500           ++j;
8501         }
8502
8503       ++i;
8504     }
8505
8506   *list = g_list_reverse (*list);
8507   
8508   return table;
8509 }
8510
8511 static void
8512 create_focus (GtkWidget *widget)
8513 {
8514   static GtkWidget *window = NULL;
8515   
8516   if (!window)
8517     {
8518       GtkWidget *table;
8519       GtkWidget *frame;
8520       GList *list = NULL;
8521       
8522       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
8523                                             NULL, 0,
8524                                             GTK_STOCK_CLOSE,
8525                                             GTK_RESPONSE_NONE,
8526                                             NULL);
8527
8528       gtk_window_set_screen (GTK_WINDOW (window),
8529                              gtk_widget_get_screen (widget));
8530
8531       g_signal_connect (window, "destroy",
8532                         G_CALLBACK (gtk_widget_destroyed),
8533                         &window);
8534
8535       g_signal_connect (window, "response",
8536                         G_CALLBACK (gtk_widget_destroy),
8537                         NULL);
8538       
8539       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
8540
8541       frame = gtk_frame_new ("Weird tab focus chain");
8542
8543       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8544                           frame, TRUE, TRUE, 0);
8545       
8546       table = make_focus_table (&list);
8547
8548       gtk_container_add (GTK_CONTAINER (frame), table);
8549
8550       gtk_container_set_focus_chain (GTK_CONTAINER (table),
8551                                      list);
8552
8553       g_list_free (list);
8554       
8555       frame = gtk_frame_new ("Default tab focus chain");
8556
8557       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8558                           frame, TRUE, TRUE, 0);
8559
8560       list = NULL;
8561       table = make_focus_table (&list);
8562
8563       g_list_free (list);
8564       
8565       gtk_container_add (GTK_CONTAINER (frame), table);      
8566     }
8567   
8568   if (!GTK_WIDGET_VISIBLE (window))
8569     gtk_widget_show_all (window);
8570   else
8571     gtk_widget_destroy (window);
8572 }
8573
8574 /*
8575  * GtkFontSelection
8576  */
8577
8578 void
8579 font_selection_ok (GtkWidget              *w,
8580                    GtkFontSelectionDialog *fs)
8581 {
8582   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
8583
8584   g_print ("%s\n", s);
8585   g_free (s);
8586   gtk_widget_destroy (GTK_WIDGET (fs));
8587 }
8588
8589 void
8590 create_font_selection (GtkWidget *widget)
8591 {
8592   static GtkWidget *window = NULL;
8593
8594   if (!window)
8595     {
8596       GtkWidget *picker;
8597       GtkWidget *hbox;
8598       GtkWidget *label;
8599       
8600       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8601       gtk_window_set_screen (GTK_WINDOW (window),
8602                              gtk_widget_get_screen (widget));
8603
8604       g_signal_connect (window, "destroy",
8605                         G_CALLBACK (gtk_widget_destroyed),
8606                         &window);
8607
8608       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
8609       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8610
8611       hbox = gtk_hbox_new (FALSE, 8);
8612       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8613       gtk_container_add (GTK_CONTAINER (window), hbox);
8614       
8615       label = gtk_label_new ("Pick a font");
8616       gtk_container_add (GTK_CONTAINER (hbox), label);
8617
8618       picker = gtk_font_button_new ();
8619       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
8620       gtk_container_add (GTK_CONTAINER (hbox), picker);
8621     }
8622   
8623   if (!GTK_WIDGET_VISIBLE (window))
8624     gtk_widget_show_all (window);
8625   else
8626     gtk_widget_destroy (window);
8627 }
8628
8629 /*
8630  * GtkDialog
8631  */
8632
8633 static GtkWidget *dialog_window = NULL;
8634
8635 static void
8636 label_toggle (GtkWidget  *widget,
8637               GtkWidget **label)
8638 {
8639   if (!(*label))
8640     {
8641       *label = gtk_label_new ("Dialog Test");
8642       g_signal_connect (*label,
8643                         "destroy",
8644                         G_CALLBACK (gtk_widget_destroyed),
8645                         label);
8646       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
8647       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8648                           *label, TRUE, TRUE, 0);
8649       gtk_widget_show (*label);
8650     }
8651   else
8652     gtk_widget_destroy (*label);
8653 }
8654
8655 #define RESPONSE_TOGGLE_SEPARATOR 1
8656
8657 static void
8658 print_response (GtkWidget *dialog,
8659                 gint       response_id,
8660                 gpointer   data)
8661 {
8662   g_print ("response signal received (%d)\n", response_id);
8663
8664   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
8665     {
8666       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
8667                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
8668     }
8669 }
8670
8671 static void
8672 create_dialog (GtkWidget *widget)
8673 {
8674   static GtkWidget *label;
8675   GtkWidget *button;
8676
8677   if (!dialog_window)
8678     {
8679       /* This is a terrible example; it's much simpler to create
8680        * dialogs than this. Don't use testgtk for example code,
8681        * use gtk-demo ;-)
8682        */
8683       
8684       dialog_window = gtk_dialog_new ();
8685       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8686                              gtk_widget_get_screen (widget));
8687
8688       g_signal_connect (dialog_window,
8689                         "response",
8690                         G_CALLBACK (print_response),
8691                         NULL);
8692       
8693       g_signal_connect (dialog_window, "destroy",
8694                         G_CALLBACK (gtk_widget_destroyed),
8695                         &dialog_window);
8696
8697       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
8698       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8699
8700       button = gtk_button_new_with_label ("OK");
8701       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8702       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
8703                           button, TRUE, TRUE, 0);
8704       gtk_widget_grab_default (button);
8705       gtk_widget_show (button);
8706
8707       button = gtk_button_new_with_label ("Toggle");
8708       g_signal_connect (button, "clicked",
8709                         G_CALLBACK (label_toggle),
8710                         &label);
8711       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8712       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8713                           button, TRUE, TRUE, 0);
8714       gtk_widget_show (button);
8715
8716       label = NULL;
8717       
8718       button = gtk_button_new_with_label ("Separator");
8719
8720       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8721
8722       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
8723                                     button,
8724                                     RESPONSE_TOGGLE_SEPARATOR);
8725       gtk_widget_show (button);
8726     }
8727
8728   if (!GTK_WIDGET_VISIBLE (dialog_window))
8729     gtk_widget_show (dialog_window);
8730   else
8731     gtk_widget_destroy (dialog_window);
8732 }
8733
8734 /* Display & Screen test 
8735  */
8736
8737 typedef struct 
8738
8739   GtkEntry *entry;
8740   GtkWidget *radio_dpy;
8741   GtkWidget *toplevel; 
8742   GtkWidget *dialog_window;
8743   GList *valid_display_list;
8744 } ScreenDisplaySelection;
8745
8746 static gint
8747 display_name_cmp (gconstpointer a,
8748                   gconstpointer b)
8749 {
8750   return g_ascii_strcasecmp (a,b);
8751 }
8752
8753 static void
8754 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
8755 {
8756   char *display_name;
8757   GdkDisplay *display = gtk_widget_get_display (widget);
8758   GtkWidget *dialog;
8759   GdkScreen *new_screen = NULL;
8760   GdkScreen *current_screen = gtk_widget_get_screen (widget);
8761   
8762   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
8763     {
8764       display_name = g_strdup (gtk_entry_get_text (data->entry));
8765       display = gdk_display_open (display_name);
8766       
8767       if (!display)
8768         {
8769           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
8770                                            GTK_DIALOG_DESTROY_WITH_PARENT,
8771                                            GTK_MESSAGE_ERROR,
8772                                            GTK_BUTTONS_OK,
8773                                            "The display :\n%s\ncannot be opened",
8774                                            display_name);
8775           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
8776           gtk_widget_show (dialog);
8777           g_signal_connect (dialog, "response",
8778                             G_CALLBACK (gtk_widget_destroy),
8779                             NULL);
8780         }
8781       else
8782         {
8783           if (!g_list_find_custom (data->valid_display_list, 
8784                                    display_name,
8785                                    display_name_cmp))
8786             data->valid_display_list = g_list_append (data->valid_display_list,
8787                                                       display_name);
8788           
8789           new_screen = gdk_display_get_default_screen (display);
8790         }
8791     }
8792   else
8793     {
8794       gint number_of_screens = gdk_display_get_n_screens (display);
8795       gint screen_num = gdk_screen_get_number (current_screen);
8796       if ((screen_num +1) < number_of_screens)
8797         new_screen = gdk_display_get_screen (display, screen_num + 1);
8798       else
8799         new_screen = gdk_display_get_screen (display, 0);
8800     }
8801   
8802   if (new_screen) 
8803     {
8804       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
8805       gtk_widget_destroy (data->dialog_window);
8806     }
8807 }
8808
8809 void
8810 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
8811 {
8812   gtk_widget_destroy (data);
8813 }
8814
8815 void
8816 create_display_screen (GtkWidget *widget)
8817 {
8818   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
8819   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
8820   GtkWidget *bbox;
8821   ScreenDisplaySelection *scr_dpy_data;
8822   GdkScreen *screen = gtk_widget_get_screen (widget);
8823   static GList *valid_display_list = NULL;
8824   
8825   GdkDisplay *display = gdk_screen_get_display (screen);
8826
8827   window = g_object_new (gtk_window_get_type (),
8828                            "screen", screen,
8829                            "user_data", NULL,
8830                            "type", GTK_WINDOW_TOPLEVEL,
8831                            "title",
8832                            "Screen or Display selection",
8833                            "border_width", 10, NULL);
8834   g_signal_connect (window, "destroy", 
8835                     G_CALLBACK (gtk_widget_destroy), NULL);
8836
8837   vbox = gtk_vbox_new (FALSE, 3);
8838   gtk_container_add (GTK_CONTAINER (window), vbox);
8839   
8840   frame = gtk_frame_new ("Select screen or display");
8841   gtk_container_add (GTK_CONTAINER (vbox), frame);
8842   
8843   table = gtk_table_new (2, 2, TRUE);
8844   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
8845   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
8846
8847   gtk_container_add (GTK_CONTAINER (frame), table);
8848
8849   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
8850   if (gdk_display_get_n_screens(display) > 1)
8851     radio_scr = gtk_radio_button_new_with_label 
8852     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
8853   else
8854     {    
8855       radio_scr = gtk_radio_button_new_with_label 
8856         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
8857          "only one screen on the current display");
8858       gtk_widget_set_sensitive (radio_scr, FALSE);
8859     }
8860   combo_dpy = gtk_combo_new ();
8861   if (!valid_display_list)
8862     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
8863     
8864   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
8865     
8866   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
8867                       "<hostname>:<X Server Num>.<Screen Num>");
8868
8869   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
8870   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
8871   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
8872
8873   bbox = gtk_hbutton_box_new ();
8874   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
8875   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
8876   
8877   gtk_container_add (GTK_CONTAINER (vbox), bbox);
8878
8879   gtk_container_add (GTK_CONTAINER (bbox), applyb);
8880   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
8881
8882   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
8883
8884   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
8885   scr_dpy_data->radio_dpy = radio_dpy;
8886   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
8887   scr_dpy_data->dialog_window = window;
8888   scr_dpy_data->valid_display_list = valid_display_list;
8889
8890   g_signal_connect (cancelb, "clicked", 
8891                     G_CALLBACK (screen_display_destroy_diag), window);
8892   g_signal_connect (applyb, "clicked", 
8893                     G_CALLBACK (screen_display_check), scr_dpy_data);
8894   gtk_widget_show_all (window);
8895 }
8896
8897 /* Event Watcher
8898  */
8899 static gboolean event_watcher_enter_id = 0;
8900 static gboolean event_watcher_leave_id = 0;
8901
8902 static gboolean
8903 event_watcher (GSignalInvocationHint *ihint,
8904                guint                  n_param_values,
8905                const GValue          *param_values,
8906                gpointer               data)
8907 {
8908   g_print ("Watch: \"%s\" emitted for %s\n",
8909            g_signal_name (ihint->signal_id),
8910            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
8911
8912   return TRUE;
8913 }
8914
8915 static void
8916 event_watcher_down (void)
8917 {
8918   if (event_watcher_enter_id)
8919     {
8920       guint signal_id;
8921
8922       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8923       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
8924       event_watcher_enter_id = 0;
8925       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8926       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
8927       event_watcher_leave_id = 0;
8928     }
8929 }
8930
8931 static void
8932 event_watcher_toggle (void)
8933 {
8934   if (event_watcher_enter_id)
8935     event_watcher_down ();
8936   else
8937     {
8938       guint signal_id;
8939
8940       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8941       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8942       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8943       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8944     }
8945 }
8946
8947 static void
8948 create_event_watcher (GtkWidget *widget)
8949 {
8950   GtkWidget *button;
8951
8952   if (!dialog_window)
8953     {
8954       dialog_window = gtk_dialog_new ();
8955       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8956                              gtk_widget_get_screen (widget));
8957
8958       g_signal_connect (dialog_window, "destroy",
8959                         G_CALLBACK (gtk_widget_destroyed),
8960                         &dialog_window);
8961       g_signal_connect (dialog_window, "destroy",
8962                         G_CALLBACK (event_watcher_down),
8963                         NULL);
8964
8965       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
8966       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8967       gtk_widget_set_size_request (dialog_window, 200, 110);
8968
8969       button = gtk_toggle_button_new_with_label ("Activate Watch");
8970       g_signal_connect (button, "clicked",
8971                         G_CALLBACK (event_watcher_toggle),
8972                         NULL);
8973       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
8974       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8975                           button, TRUE, TRUE, 0);
8976       gtk_widget_show (button);
8977
8978       button = gtk_button_new_with_label ("Close");
8979       g_signal_connect_swapped (button, "clicked",
8980                                 G_CALLBACK (gtk_widget_destroy),
8981                                 dialog_window);
8982       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8983       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8984                           button, TRUE, TRUE, 0);
8985       gtk_widget_grab_default (button);
8986       gtk_widget_show (button);
8987     }
8988
8989   if (!GTK_WIDGET_VISIBLE (dialog_window))
8990     gtk_widget_show (dialog_window);
8991   else
8992     gtk_widget_destroy (dialog_window);
8993 }
8994
8995 /*
8996  * GtkRange
8997  */
8998
8999 static gchar*
9000 reformat_value (GtkScale *scale,
9001                 gdouble   value)
9002 {
9003   return g_strdup_printf ("-->%0.*g<--",
9004                           gtk_scale_get_digits (scale), value);
9005 }
9006
9007 static void
9008 create_range_controls (GtkWidget *widget)
9009 {
9010   static GtkWidget *window = NULL;
9011   GtkWidget *box1;
9012   GtkWidget *box2;
9013   GtkWidget *button;
9014   GtkWidget *scrollbar;
9015   GtkWidget *scale;
9016   GtkWidget *separator;
9017   GtkObject *adjustment;
9018   GtkWidget *hbox;
9019
9020   if (!window)
9021     {
9022       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9023
9024       gtk_window_set_screen (GTK_WINDOW (window),
9025                              gtk_widget_get_screen (widget));
9026
9027       g_signal_connect (window, "destroy",
9028                         G_CALLBACK (gtk_widget_destroyed),
9029                         &window);
9030
9031       gtk_window_set_title (GTK_WINDOW (window), "range controls");
9032       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9033
9034
9035       box1 = gtk_vbox_new (FALSE, 0);
9036       gtk_container_add (GTK_CONTAINER (window), box1);
9037       gtk_widget_show (box1);
9038
9039
9040       box2 = gtk_vbox_new (FALSE, 10);
9041       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9042       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9043       gtk_widget_show (box2);
9044
9045
9046       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
9047
9048       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
9049       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
9050       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
9051       gtk_scale_set_digits (GTK_SCALE (scale), 1);
9052       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9053       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
9054       gtk_widget_show (scale);
9055
9056       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
9057       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
9058                                    GTK_UPDATE_CONTINUOUS);
9059       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
9060       gtk_widget_show (scrollbar);
9061
9062       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
9063       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9064       g_signal_connect (scale,
9065                         "format_value",
9066                         G_CALLBACK (reformat_value),
9067                         NULL);
9068       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
9069       gtk_widget_show (scale);
9070       
9071       hbox = gtk_hbox_new (FALSE, 0);
9072
9073       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9074       gtk_widget_set_size_request (scale, -1, 200);
9075       gtk_scale_set_digits (GTK_SCALE (scale), 2);
9076       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9077       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9078       gtk_widget_show (scale);
9079
9080       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9081       gtk_widget_set_size_request (scale, -1, 200);
9082       gtk_scale_set_digits (GTK_SCALE (scale), 2);
9083       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9084       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
9085       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9086       gtk_widget_show (scale);
9087
9088       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9089       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9090       g_signal_connect (scale,
9091                         "format_value",
9092                         G_CALLBACK (reformat_value),
9093                         NULL);
9094       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9095       gtk_widget_show (scale);
9096
9097       
9098       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
9099       gtk_widget_show (hbox);
9100       
9101       separator = gtk_hseparator_new ();
9102       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9103       gtk_widget_show (separator);
9104
9105
9106       box2 = gtk_vbox_new (FALSE, 10);
9107       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9108       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9109       gtk_widget_show (box2);
9110
9111
9112       button = gtk_button_new_with_label ("close");
9113       g_signal_connect_swapped (button, "clicked",
9114                                 G_CALLBACK (gtk_widget_destroy),
9115                                 window);
9116       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9117       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9118       gtk_widget_grab_default (button);
9119       gtk_widget_show (button);
9120     }
9121
9122   if (!GTK_WIDGET_VISIBLE (window))
9123     gtk_widget_show (window);
9124   else
9125     gtk_widget_destroy (window);
9126 }
9127
9128 /*
9129  * GtkRulers
9130  */
9131
9132 void
9133 create_rulers (GtkWidget *widget)
9134 {
9135   static GtkWidget *window = NULL;
9136   GtkWidget *table;
9137   GtkWidget *ruler;
9138
9139   if (!window)
9140     {
9141       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9142
9143       gtk_window_set_screen (GTK_WINDOW (window),
9144                              gtk_widget_get_screen (widget));
9145
9146       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9147
9148       g_signal_connect (window, "destroy",
9149                         G_CALLBACK (gtk_widget_destroyed),
9150                         &window);
9151
9152       gtk_window_set_title (GTK_WINDOW (window), "rulers");
9153       gtk_widget_set_size_request (window, 300, 300);
9154       gtk_widget_set_events (window, 
9155                              GDK_POINTER_MOTION_MASK 
9156                              | GDK_POINTER_MOTION_HINT_MASK);
9157       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9158
9159       table = gtk_table_new (2, 2, FALSE);
9160       gtk_container_add (GTK_CONTAINER (window), table);
9161       gtk_widget_show (table);
9162
9163       ruler = gtk_hruler_new ();
9164       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
9165       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
9166
9167       g_signal_connect_swapped (window, 
9168                                 "motion_notify_event",
9169                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9170                                 ruler);
9171       
9172       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
9173                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
9174       gtk_widget_show (ruler);
9175
9176
9177       ruler = gtk_vruler_new ();
9178       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
9179
9180       g_signal_connect_swapped (window, 
9181                                 "motion_notify_event",
9182                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9183                                 ruler);
9184       
9185       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
9186                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
9187       gtk_widget_show (ruler);
9188     }
9189
9190   if (!GTK_WIDGET_VISIBLE (window))
9191     gtk_widget_show (window);
9192   else
9193     gtk_widget_destroy (window);
9194 }
9195
9196 static void
9197 text_toggle_editable (GtkWidget *checkbutton,
9198                        GtkWidget *text)
9199 {
9200    gtk_text_set_editable(GTK_TEXT(text),
9201                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9202 }
9203
9204 static void
9205 text_toggle_word_wrap (GtkWidget *checkbutton,
9206                        GtkWidget *text)
9207 {
9208    gtk_text_set_word_wrap(GTK_TEXT(text),
9209                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9210 }
9211
9212 struct {
9213   GdkColor color;
9214   gchar *name;
9215 } text_colors[] = {
9216  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
9217  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
9218  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
9219  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
9220  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
9221  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
9222  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
9223  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
9224 };
9225
9226 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
9227
9228 /*
9229  * GtkText
9230  */
9231 void
9232 text_insert_random (GtkWidget *w, GtkText *text)
9233 {
9234   int i;
9235   char c;
9236    for (i=0; i<10; i++)
9237     {
9238       c = 'A' + rand() % ('Z' - 'A');
9239       gtk_text_set_point (text, rand() % gtk_text_get_length (text));
9240       gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
9241     }
9242 }
9243
9244 void
9245 create_text (GtkWidget *widget)
9246 {
9247   int i, j;
9248
9249   static GtkWidget *window = NULL;
9250   GtkWidget *box1;
9251   GtkWidget *box2;
9252   GtkWidget *hbox;
9253   GtkWidget *button;
9254   GtkWidget *check;
9255   GtkWidget *separator;
9256   GtkWidget *scrolled_window;
9257   GtkWidget *text;
9258
9259   FILE *infile;
9260
9261   if (!window)
9262     {
9263       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9264       gtk_window_set_screen (GTK_WINDOW (window),
9265                              gtk_widget_get_screen (widget));
9266
9267       gtk_widget_set_name (window, "text window");
9268       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9269       gtk_widget_set_size_request (window, 500, 500);
9270
9271       g_signal_connect (window, "destroy",
9272                         G_CALLBACK (gtk_widget_destroyed),
9273                         &window);
9274
9275       gtk_window_set_title (GTK_WINDOW (window), "test");
9276       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9277
9278
9279       box1 = gtk_vbox_new (FALSE, 0);
9280       gtk_container_add (GTK_CONTAINER (window), box1);
9281       gtk_widget_show (box1);
9282
9283
9284       box2 = gtk_vbox_new (FALSE, 10);
9285       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9286       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9287       gtk_widget_show (box2);
9288
9289
9290       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9291       gtk_box_pack_start (GTK_BOX (box2), scrolled_window, TRUE, TRUE, 0);
9292       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9293                                       GTK_POLICY_NEVER,
9294                                       GTK_POLICY_ALWAYS);
9295       gtk_widget_show (scrolled_window);
9296
9297       text = gtk_text_new (NULL, NULL);
9298       gtk_text_set_editable (GTK_TEXT (text), TRUE);
9299       gtk_container_add (GTK_CONTAINER (scrolled_window), text);
9300       gtk_widget_grab_focus (text);
9301       gtk_widget_show (text);
9302
9303
9304       gtk_text_freeze (GTK_TEXT (text));
9305
9306       for (i=0; i<ntext_colors; i++)
9307         {
9308           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 
9309                            text_colors[i].name, -1);
9310           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\t", -1);
9311
9312           for (j=0; j<ntext_colors; j++)
9313             {
9314               gtk_text_insert (GTK_TEXT (text), NULL,
9315                                &text_colors[j].color, &text_colors[i].color,
9316                                "XYZ", -1);
9317             }
9318           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
9319         }
9320
9321       infile = fopen("testgtk.c", "r");
9322       
9323       if (infile)
9324         {
9325           char *buffer;
9326           int nbytes_read, nbytes_alloc;
9327           
9328           nbytes_read = 0;
9329           nbytes_alloc = 1024;
9330           buffer = g_new (char, nbytes_alloc);
9331           while (1)
9332             {
9333               int len;
9334               if (nbytes_alloc < nbytes_read + 1024)
9335                 {
9336                   nbytes_alloc *= 2;
9337                   buffer = g_realloc (buffer, nbytes_alloc);
9338                 }
9339               len = fread (buffer + nbytes_read, 1, 1024, infile);
9340               nbytes_read += len;
9341               if (len < 1024)
9342                 break;
9343             }
9344           
9345           gtk_text_insert (GTK_TEXT (text), NULL, NULL,
9346                            NULL, buffer, nbytes_read);
9347           g_free(buffer);
9348           fclose (infile);
9349         }
9350       
9351       gtk_text_thaw (GTK_TEXT (text));
9352
9353       hbox = gtk_hbutton_box_new ();
9354       gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9355       gtk_widget_show (hbox);
9356
9357       check = gtk_check_button_new_with_label("Editable");
9358       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9359       g_signal_connect (check, "toggled",
9360                         G_CALLBACK (text_toggle_editable), text);
9361       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9362       gtk_widget_show (check);
9363
9364       check = gtk_check_button_new_with_label("Wrap Words");
9365       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9366       g_signal_connect (check, "toggled",
9367                         G_CALLBACK (text_toggle_word_wrap), text);
9368       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9369       gtk_widget_show (check);
9370
9371       separator = gtk_hseparator_new ();
9372       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9373       gtk_widget_show (separator);
9374
9375
9376       box2 = gtk_vbox_new (FALSE, 10);
9377       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9378       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9379       gtk_widget_show (box2);
9380
9381
9382       button = gtk_button_new_with_label ("insert random");
9383       g_signal_connect (button, "clicked",
9384                         G_CALLBACK (text_insert_random),
9385                         text);
9386       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9387       gtk_widget_show (button);
9388
9389       button = gtk_button_new_with_label ("close");
9390       g_signal_connect_swapped (button, "clicked",
9391                                 G_CALLBACK (gtk_widget_destroy),
9392                                 window);
9393       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9394       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9395       gtk_widget_grab_default (button);
9396       gtk_widget_show (button);
9397     }
9398
9399   if (!GTK_WIDGET_VISIBLE (window))
9400     gtk_widget_show (window);
9401   else
9402     gtk_widget_destroy (window);
9403 }
9404
9405 /*
9406  * GtkNotebook
9407  */
9408
9409 GdkPixbuf *book_open;
9410 GdkPixbuf *book_closed;
9411 GtkWidget *sample_notebook;
9412
9413 static void
9414 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
9415 {
9416   GtkWidget *page_widget;
9417   GtkWidget *pixwid;
9418
9419   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
9420
9421   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
9422   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9423   
9424   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
9425   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9426 }
9427
9428 static void
9429 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
9430 {
9431   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
9432   gint old_page_num = gtk_notebook_get_current_page (notebook);
9433  
9434   if (page_num == old_page_num)
9435     return;
9436
9437   set_page_image (notebook, page_num, book_open);
9438
9439   if (old_page_num != -1)
9440     set_page_image (notebook, old_page_num, book_closed);
9441 }
9442
9443 static void
9444 tab_fill (GtkToggleButton *button, GtkWidget *child)
9445 {
9446   gboolean expand;
9447   GtkPackType pack_type;
9448
9449   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9450                                         &expand, NULL, &pack_type);
9451   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9452                                       expand, button->active, pack_type);
9453 }
9454
9455 static void
9456 tab_expand (GtkToggleButton *button, GtkWidget *child)
9457 {
9458   gboolean fill;
9459   GtkPackType pack_type;
9460
9461   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9462                                         NULL, &fill, &pack_type);
9463   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9464                                       button->active, fill, pack_type);
9465 }
9466
9467 static void
9468 tab_pack (GtkToggleButton *button, GtkWidget *child)
9469           
9470
9471   gboolean expand;
9472   gboolean fill;
9473
9474   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9475                                         &expand, &fill, NULL);
9476   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9477                                       expand, fill, button->active);
9478 }
9479
9480 static void
9481 create_pages (GtkNotebook *notebook, gint start, gint end)
9482 {
9483   GtkWidget *child = NULL;
9484   GtkWidget *button;
9485   GtkWidget *label;
9486   GtkWidget *hbox;
9487   GtkWidget *vbox;
9488   GtkWidget *label_box;
9489   GtkWidget *menu_box;
9490   GtkWidget *pixwid;
9491   gint i;
9492   char buffer[32];
9493   char accel_buffer[32];
9494
9495   for (i = start; i <= end; i++)
9496     {
9497       sprintf (buffer, "Page %d", i);
9498       sprintf (accel_buffer, "Page _%d", i);
9499
9500       child = gtk_frame_new (buffer);
9501       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
9502
9503       vbox = gtk_vbox_new (TRUE,0);
9504       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9505       gtk_container_add (GTK_CONTAINER (child), vbox);
9506
9507       hbox = gtk_hbox_new (TRUE,0);
9508       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
9509
9510       button = gtk_check_button_new_with_label ("Fill Tab");
9511       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9512       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
9513       g_signal_connect (button, "toggled",
9514                         G_CALLBACK (tab_fill), child);
9515
9516       button = gtk_check_button_new_with_label ("Expand Tab");
9517       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9518       g_signal_connect (button, "toggled",
9519                         G_CALLBACK (tab_expand), child);
9520
9521       button = gtk_check_button_new_with_label ("Pack end");
9522       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9523       g_signal_connect (button, "toggled",
9524                         G_CALLBACK (tab_pack), child);
9525
9526       button = gtk_button_new_with_label ("Hide Page");
9527       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
9528       g_signal_connect_swapped (button, "clicked",
9529                                 G_CALLBACK (gtk_widget_hide),
9530                                 child);
9531
9532       gtk_widget_show_all (child);
9533
9534       label_box = gtk_hbox_new (FALSE, 0);
9535       pixwid = gtk_image_new_from_pixbuf (book_closed);
9536       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
9537                            
9538       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
9539       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9540       label = gtk_label_new_with_mnemonic (accel_buffer);
9541       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
9542       gtk_widget_show_all (label_box);
9543       
9544                                        
9545       menu_box = gtk_hbox_new (FALSE, 0);
9546       pixwid = gtk_image_new_from_pixbuf (book_closed);
9547       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
9548       
9549       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
9550       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9551       label = gtk_label_new (buffer);
9552       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
9553       gtk_widget_show_all (menu_box);
9554
9555       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
9556     }
9557 }
9558
9559 static void
9560 rotate_notebook (GtkButton   *button,
9561                  GtkNotebook *notebook)
9562 {
9563   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
9564 }
9565
9566 static void
9567 show_all_pages (GtkButton   *button,
9568                 GtkNotebook *notebook)
9569 {  
9570   gtk_container_foreach (GTK_CONTAINER (notebook),
9571                          (GtkCallback) gtk_widget_show, NULL);
9572 }
9573
9574 static void
9575 notebook_type_changed (GtkWidget *optionmenu,
9576                        gpointer   data)
9577 {
9578   GtkNotebook *notebook;
9579   gint i, c;
9580
9581   enum {
9582     STANDARD,
9583     NOTABS,
9584     BORDERLESS,
9585     SCROLLABLE
9586   };
9587
9588   notebook = GTK_NOTEBOOK (data);
9589
9590   c = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
9591
9592   switch (c)
9593     {
9594     case STANDARD:
9595       /* standard notebook */
9596       gtk_notebook_set_show_tabs (notebook, TRUE);
9597       gtk_notebook_set_show_border (notebook, TRUE);
9598       gtk_notebook_set_scrollable (notebook, FALSE);
9599       break;
9600
9601     case NOTABS:
9602       /* notabs notebook */
9603       gtk_notebook_set_show_tabs (notebook, FALSE);
9604       gtk_notebook_set_show_border (notebook, TRUE);
9605       break;
9606
9607     case BORDERLESS:
9608       /* borderless */
9609       gtk_notebook_set_show_tabs (notebook, FALSE);
9610       gtk_notebook_set_show_border (notebook, FALSE);
9611       break;
9612
9613     case SCROLLABLE:  
9614       /* scrollable */
9615       gtk_notebook_set_show_tabs (notebook, TRUE);
9616       gtk_notebook_set_show_border (notebook, TRUE);
9617       gtk_notebook_set_scrollable (notebook, TRUE);
9618       if (g_list_length (notebook->children) == 5)
9619         create_pages (notebook, 6, 15);
9620       
9621       return;
9622       break;
9623     }
9624   
9625   if (g_list_length (notebook->children) == 15)
9626     for (i = 0; i < 10; i++)
9627       gtk_notebook_remove_page (notebook, 5);
9628 }
9629
9630 static void
9631 notebook_popup (GtkToggleButton *button,
9632                 GtkNotebook     *notebook)
9633 {
9634   if (button->active)
9635     gtk_notebook_popup_enable (notebook);
9636   else
9637     gtk_notebook_popup_disable (notebook);
9638 }
9639
9640 static void
9641 notebook_homogeneous (GtkToggleButton *button,
9642                       GtkNotebook     *notebook)
9643 {
9644   g_object_set (notebook, "homogeneous", button->active, NULL);
9645 }
9646
9647 static void
9648 create_notebook (GtkWidget *widget)
9649 {
9650   static GtkWidget *window = NULL;
9651   GtkWidget *box1;
9652   GtkWidget *box2;
9653   GtkWidget *button;
9654   GtkWidget *separator;
9655   GtkWidget *omenu;
9656   GtkWidget *label;
9657
9658   static gchar *items[] =
9659   {
9660     "Standard",
9661     "No tabs",
9662     "Borderless",
9663     "Scrollable"
9664   };
9665   
9666   if (!window)
9667     {
9668       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9669       gtk_window_set_screen (GTK_WINDOW (window),
9670                              gtk_widget_get_screen (widget));
9671
9672       g_signal_connect (window, "destroy",
9673                         G_CALLBACK (gtk_widget_destroyed),
9674                         &window);
9675
9676       gtk_window_set_title (GTK_WINDOW (window), "notebook");
9677       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9678
9679       box1 = gtk_vbox_new (FALSE, 0);
9680       gtk_container_add (GTK_CONTAINER (window), box1);
9681
9682       sample_notebook = gtk_notebook_new ();
9683       g_signal_connect (sample_notebook, "switch_page",
9684                         G_CALLBACK (page_switch), NULL);
9685       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
9686       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
9687       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
9688
9689       gtk_widget_realize (sample_notebook);
9690
9691       if (!book_open)
9692         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
9693                                                   
9694       if (!book_closed)
9695         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
9696
9697       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
9698
9699       separator = gtk_hseparator_new ();
9700       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
9701       
9702       box2 = gtk_hbox_new (FALSE, 5);
9703       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9704       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9705
9706       button = gtk_check_button_new_with_label ("popup menu");
9707       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9708       g_signal_connect (button, "clicked",
9709                         G_CALLBACK (notebook_popup),
9710                         sample_notebook);
9711
9712       button = gtk_check_button_new_with_label ("homogeneous tabs");
9713       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9714       g_signal_connect (button, "clicked",
9715                         G_CALLBACK (notebook_homogeneous),
9716                         sample_notebook);
9717
9718       box2 = gtk_hbox_new (FALSE, 5);
9719       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9720       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9721
9722       label = gtk_label_new ("Notebook Style :");
9723       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
9724
9725       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
9726                                  notebook_type_changed,
9727                                  sample_notebook);
9728       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
9729
9730       button = gtk_button_new_with_label ("Show all Pages");
9731       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
9732       g_signal_connect (button, "clicked",
9733                         G_CALLBACK (show_all_pages), sample_notebook);
9734
9735       box2 = gtk_hbox_new (TRUE, 10);
9736       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9737       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9738
9739       button = gtk_button_new_with_label ("prev");
9740       g_signal_connect_swapped (button, "clicked",
9741                                 G_CALLBACK (gtk_notebook_prev_page),
9742                                 sample_notebook);
9743       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9744
9745       button = gtk_button_new_with_label ("next");
9746       g_signal_connect_swapped (button, "clicked",
9747                                 G_CALLBACK (gtk_notebook_next_page),
9748                                 sample_notebook);
9749       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9750
9751       button = gtk_button_new_with_label ("rotate");
9752       g_signal_connect (button, "clicked",
9753                         G_CALLBACK (rotate_notebook), sample_notebook);
9754       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9755
9756       separator = gtk_hseparator_new ();
9757       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
9758
9759       button = gtk_button_new_with_label ("close");
9760       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
9761       g_signal_connect_swapped (button, "clicked",
9762                                 G_CALLBACK (gtk_widget_destroy),
9763                                 window);
9764       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
9765       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9766       gtk_widget_grab_default (button);
9767     }
9768
9769   if (!GTK_WIDGET_VISIBLE (window))
9770     gtk_widget_show_all (window);
9771   else
9772     gtk_widget_destroy (window);
9773 }
9774
9775 /*
9776  * GtkPanes
9777  */
9778
9779 void
9780 toggle_resize (GtkWidget *widget, GtkWidget *child)
9781 {
9782   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9783   GValue value = { 0, };
9784   g_value_init (&value, G_TYPE_BOOLEAN);
9785   gtk_container_child_get_property (container, child, "resize", &value);
9786   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9787   gtk_container_child_set_property (container, child, "resize", &value);
9788 }
9789
9790 void
9791 toggle_shrink (GtkWidget *widget, GtkWidget *child)
9792 {
9793   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9794   GValue value = { 0, };
9795   g_value_init (&value, G_TYPE_BOOLEAN);
9796   gtk_container_child_get_property (container, child, "shrink", &value);
9797   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9798   gtk_container_child_set_property (container, child, "shrink", &value);
9799 }
9800
9801 static void
9802 paned_props_clicked (GtkWidget *button,
9803                      GObject   *paned)
9804 {
9805   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
9806   
9807   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
9808 }
9809
9810 GtkWidget *
9811 create_pane_options (GtkPaned    *paned,
9812                      const gchar *frame_label,
9813                      const gchar *label1,
9814                      const gchar *label2)
9815 {
9816   GtkWidget *frame;
9817   GtkWidget *table;
9818   GtkWidget *label;
9819   GtkWidget *button;
9820   GtkWidget *check_button;
9821   
9822   frame = gtk_frame_new (frame_label);
9823   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
9824   
9825   table = gtk_table_new (4, 2, 4);
9826   gtk_container_add (GTK_CONTAINER (frame), table);
9827   
9828   label = gtk_label_new (label1);
9829   gtk_table_attach_defaults (GTK_TABLE (table), label,
9830                              0, 1, 0, 1);
9831   
9832   check_button = gtk_check_button_new_with_label ("Resize");
9833   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9834                              0, 1, 1, 2);
9835   g_signal_connect (check_button, "toggled",
9836                     G_CALLBACK (toggle_resize),
9837                     paned->child1);
9838   
9839   check_button = gtk_check_button_new_with_label ("Shrink");
9840   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9841                              0, 1, 2, 3);
9842   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9843                                TRUE);
9844   g_signal_connect (check_button, "toggled",
9845                     G_CALLBACK (toggle_shrink),
9846                     paned->child1);
9847   
9848   label = gtk_label_new (label2);
9849   gtk_table_attach_defaults (GTK_TABLE (table), label,
9850                              1, 2, 0, 1);
9851   
9852   check_button = gtk_check_button_new_with_label ("Resize");
9853   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9854                              1, 2, 1, 2);
9855   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9856                                TRUE);
9857   g_signal_connect (check_button, "toggled",
9858                     G_CALLBACK (toggle_resize),
9859                     paned->child2);
9860   
9861   check_button = gtk_check_button_new_with_label ("Shrink");
9862   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9863                              1, 2, 2, 3);
9864   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9865                                TRUE);
9866   g_signal_connect (check_button, "toggled",
9867                     G_CALLBACK (toggle_shrink),
9868                     paned->child2);
9869
9870   button = gtk_button_new_with_mnemonic ("_Properties");
9871   gtk_table_attach_defaults (GTK_TABLE (table), button,
9872                              0, 2, 3, 4);
9873   g_signal_connect (button, "clicked",
9874                     G_CALLBACK (paned_props_clicked),
9875                     paned);
9876
9877   return frame;
9878 }
9879
9880 void
9881 create_panes (GtkWidget *widget)
9882 {
9883   static GtkWidget *window = NULL;
9884   GtkWidget *frame;
9885   GtkWidget *hpaned;
9886   GtkWidget *vpaned;
9887   GtkWidget *button;
9888   GtkWidget *vbox;
9889
9890   if (!window)
9891     {
9892       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9893
9894       gtk_window_set_screen (GTK_WINDOW (window),
9895                              gtk_widget_get_screen (widget));
9896       
9897       g_signal_connect (window, "destroy",
9898                         G_CALLBACK (gtk_widget_destroyed),
9899                         &window);
9900
9901       gtk_window_set_title (GTK_WINDOW (window), "Panes");
9902       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9903
9904       vbox = gtk_vbox_new (FALSE, 0);
9905       gtk_container_add (GTK_CONTAINER (window), vbox);
9906       
9907       vpaned = gtk_vpaned_new ();
9908       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
9909       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
9910
9911       hpaned = gtk_hpaned_new ();
9912       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
9913
9914       frame = gtk_frame_new (NULL);
9915       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9916       gtk_widget_set_size_request (frame, 60, 60);
9917       gtk_paned_add1 (GTK_PANED (hpaned), frame);
9918       
9919       button = gtk_button_new_with_label ("Hi there");
9920       gtk_container_add (GTK_CONTAINER(frame), button);
9921
9922       frame = gtk_frame_new (NULL);
9923       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9924       gtk_widget_set_size_request (frame, 80, 60);
9925       gtk_paned_add2 (GTK_PANED (hpaned), frame);
9926
9927       frame = gtk_frame_new (NULL);
9928       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9929       gtk_widget_set_size_request (frame, 60, 80);
9930       gtk_paned_add2 (GTK_PANED (vpaned), frame);
9931
9932       /* Now create toggle buttons to control sizing */
9933
9934       gtk_box_pack_start (GTK_BOX (vbox),
9935                           create_pane_options (GTK_PANED (hpaned),
9936                                                "Horizontal",
9937                                                "Left",
9938                                                "Right"),
9939                           FALSE, FALSE, 0);
9940
9941       gtk_box_pack_start (GTK_BOX (vbox),
9942                           create_pane_options (GTK_PANED (vpaned),
9943                                                "Vertical",
9944                                                "Top",
9945                                                "Bottom"),
9946                           FALSE, FALSE, 0);
9947
9948       gtk_widget_show_all (vbox);
9949     }
9950
9951   if (!GTK_WIDGET_VISIBLE (window))
9952     gtk_widget_show (window);
9953   else
9954     gtk_widget_destroy (window);
9955 }
9956
9957 /*
9958  * Paned keyboard navigation
9959  */
9960
9961 static GtkWidget*
9962 paned_keyboard_window1 (GtkWidget *widget)
9963 {
9964   GtkWidget *window1;
9965   GtkWidget *hpaned1;
9966   GtkWidget *frame1;
9967   GtkWidget *vbox1;
9968   GtkWidget *button7;
9969   GtkWidget *button8;
9970   GtkWidget *button9;
9971   GtkWidget *vpaned1;
9972   GtkWidget *frame2;
9973   GtkWidget *frame5;
9974   GtkWidget *hbox1;
9975   GtkWidget *button5;
9976   GtkWidget *button6;
9977   GtkWidget *frame3;
9978   GtkWidget *frame4;
9979   GtkWidget *table1;
9980   GtkWidget *button1;
9981   GtkWidget *button2;
9982   GtkWidget *button3;
9983   GtkWidget *button4;
9984
9985   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9986   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
9987   gtk_window_set_screen (GTK_WINDOW (window1), 
9988                          gtk_widget_get_screen (widget));
9989
9990   hpaned1 = gtk_hpaned_new ();
9991   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
9992
9993   frame1 = gtk_frame_new (NULL);
9994   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
9995   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
9996
9997   vbox1 = gtk_vbox_new (FALSE, 0);
9998   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
9999
10000   button7 = gtk_button_new_with_label ("button7");
10001   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
10002
10003   button8 = gtk_button_new_with_label ("button8");
10004   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
10005
10006   button9 = gtk_button_new_with_label ("button9");
10007   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
10008
10009   vpaned1 = gtk_vpaned_new ();
10010   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
10011
10012   frame2 = gtk_frame_new (NULL);
10013   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
10014   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
10015
10016   frame5 = gtk_frame_new (NULL);
10017   gtk_container_add (GTK_CONTAINER (frame2), frame5);
10018
10019   hbox1 = gtk_hbox_new (FALSE, 0);
10020   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
10021
10022   button5 = gtk_button_new_with_label ("button5");
10023   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
10024
10025   button6 = gtk_button_new_with_label ("button6");
10026   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
10027
10028   frame3 = gtk_frame_new (NULL);
10029   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
10030   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
10031
10032   frame4 = gtk_frame_new ("Buttons");
10033   gtk_container_add (GTK_CONTAINER (frame3), frame4);
10034   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
10035
10036   table1 = gtk_table_new (2, 2, FALSE);
10037   gtk_container_add (GTK_CONTAINER (frame4), table1);
10038   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
10039
10040   button1 = gtk_button_new_with_label ("button1");
10041   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
10042                     (GtkAttachOptions) (GTK_FILL),
10043                     (GtkAttachOptions) (0), 0, 0);
10044
10045   button2 = gtk_button_new_with_label ("button2");
10046   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
10047                     (GtkAttachOptions) (GTK_FILL),
10048                     (GtkAttachOptions) (0), 0, 0);
10049
10050   button3 = gtk_button_new_with_label ("button3");
10051   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
10052                     (GtkAttachOptions) (GTK_FILL),
10053                     (GtkAttachOptions) (0), 0, 0);
10054
10055   button4 = gtk_button_new_with_label ("button4");
10056   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
10057                     (GtkAttachOptions) (GTK_FILL),
10058                     (GtkAttachOptions) (0), 0, 0);
10059
10060   return window1;
10061 }
10062
10063 static GtkWidget*
10064 paned_keyboard_window2 (GtkWidget *widget)
10065 {
10066   GtkWidget *window2;
10067   GtkWidget *hpaned2;
10068   GtkWidget *frame6;
10069   GtkWidget *button13;
10070   GtkWidget *hbox2;
10071   GtkWidget *vpaned2;
10072   GtkWidget *frame7;
10073   GtkWidget *button12;
10074   GtkWidget *frame8;
10075   GtkWidget *button11;
10076   GtkWidget *button10;
10077
10078   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10079   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
10080
10081   gtk_window_set_screen (GTK_WINDOW (window2), 
10082                          gtk_widget_get_screen (widget));
10083
10084   hpaned2 = gtk_hpaned_new ();
10085   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
10086
10087   frame6 = gtk_frame_new (NULL);
10088   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
10089   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
10090
10091   button13 = gtk_button_new_with_label ("button13");
10092   gtk_container_add (GTK_CONTAINER (frame6), button13);
10093
10094   hbox2 = gtk_hbox_new (FALSE, 0);
10095   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
10096
10097   vpaned2 = gtk_vpaned_new ();
10098   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
10099
10100   frame7 = gtk_frame_new (NULL);
10101   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
10102   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
10103
10104   button12 = gtk_button_new_with_label ("button12");
10105   gtk_container_add (GTK_CONTAINER (frame7), button12);
10106
10107   frame8 = gtk_frame_new (NULL);
10108   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
10109   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
10110
10111   button11 = gtk_button_new_with_label ("button11");
10112   gtk_container_add (GTK_CONTAINER (frame8), button11);
10113
10114   button10 = gtk_button_new_with_label ("button10");
10115   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
10116
10117   return window2;
10118 }
10119
10120 static GtkWidget*
10121 paned_keyboard_window3 (GtkWidget *widget)
10122 {
10123   GtkWidget *window3;
10124   GtkWidget *vbox2;
10125   GtkWidget *label1;
10126   GtkWidget *hpaned3;
10127   GtkWidget *frame9;
10128   GtkWidget *button14;
10129   GtkWidget *hpaned4;
10130   GtkWidget *frame10;
10131   GtkWidget *button15;
10132   GtkWidget *hpaned5;
10133   GtkWidget *frame11;
10134   GtkWidget *button16;
10135   GtkWidget *frame12;
10136   GtkWidget *button17;
10137
10138   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10139   g_object_set_data (G_OBJECT (window3), "window3", window3);
10140   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
10141
10142   gtk_window_set_screen (GTK_WINDOW (window3), 
10143                          gtk_widget_get_screen (widget));
10144   
10145
10146   vbox2 = gtk_vbox_new (FALSE, 0);
10147   gtk_container_add (GTK_CONTAINER (window3), vbox2);
10148
10149   label1 = gtk_label_new ("Three panes nested inside each other");
10150   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
10151
10152   hpaned3 = gtk_hpaned_new ();
10153   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
10154
10155   frame9 = gtk_frame_new (NULL);
10156   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
10157   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
10158
10159   button14 = gtk_button_new_with_label ("button14");
10160   gtk_container_add (GTK_CONTAINER (frame9), button14);
10161
10162   hpaned4 = gtk_hpaned_new ();
10163   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
10164
10165   frame10 = gtk_frame_new (NULL);
10166   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
10167   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
10168
10169   button15 = gtk_button_new_with_label ("button15");
10170   gtk_container_add (GTK_CONTAINER (frame10), button15);
10171
10172   hpaned5 = gtk_hpaned_new ();
10173   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
10174
10175   frame11 = gtk_frame_new (NULL);
10176   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
10177   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
10178
10179   button16 = gtk_button_new_with_label ("button16");
10180   gtk_container_add (GTK_CONTAINER (frame11), button16);
10181
10182   frame12 = gtk_frame_new (NULL);
10183   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
10184   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
10185
10186   button17 = gtk_button_new_with_label ("button17");
10187   gtk_container_add (GTK_CONTAINER (frame12), button17);
10188
10189   return window3;
10190 }
10191
10192 static GtkWidget*
10193 paned_keyboard_window4 (GtkWidget *widget)
10194 {
10195   GtkWidget *window4;
10196   GtkWidget *vbox3;
10197   GtkWidget *label2;
10198   GtkWidget *hpaned6;
10199   GtkWidget *vpaned3;
10200   GtkWidget *button19;
10201   GtkWidget *button18;
10202   GtkWidget *hbox3;
10203   GtkWidget *vpaned4;
10204   GtkWidget *button21;
10205   GtkWidget *button20;
10206   GtkWidget *vpaned5;
10207   GtkWidget *button23;
10208   GtkWidget *button22;
10209   GtkWidget *vpaned6;
10210   GtkWidget *button25;
10211   GtkWidget *button24;
10212
10213   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10214   g_object_set_data (G_OBJECT (window4), "window4", window4);
10215   gtk_window_set_title (GTK_WINDOW (window4), "window4");
10216
10217   gtk_window_set_screen (GTK_WINDOW (window4), 
10218                          gtk_widget_get_screen (widget));
10219
10220   vbox3 = gtk_vbox_new (FALSE, 0);
10221   gtk_container_add (GTK_CONTAINER (window4), vbox3);
10222
10223   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
10224   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
10225   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
10226
10227   hpaned6 = gtk_hpaned_new ();
10228   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
10229
10230   vpaned3 = gtk_vpaned_new ();
10231   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
10232
10233   button19 = gtk_button_new_with_label ("button19");
10234   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
10235
10236   button18 = gtk_button_new_with_label ("button18");
10237   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
10238
10239   hbox3 = gtk_hbox_new (FALSE, 0);
10240   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
10241
10242   vpaned4 = gtk_vpaned_new ();
10243   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
10244
10245   button21 = gtk_button_new_with_label ("button21");
10246   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
10247
10248   button20 = gtk_button_new_with_label ("button20");
10249   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
10250
10251   vpaned5 = gtk_vpaned_new ();
10252   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
10253
10254   button23 = gtk_button_new_with_label ("button23");
10255   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
10256
10257   button22 = gtk_button_new_with_label ("button22");
10258   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
10259
10260   vpaned6 = gtk_vpaned_new ();
10261   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
10262
10263   button25 = gtk_button_new_with_label ("button25");
10264   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
10265
10266   button24 = gtk_button_new_with_label ("button24");
10267   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
10268
10269   return window4;
10270 }
10271
10272 static void
10273 create_paned_keyboard_navigation (GtkWidget *widget)
10274 {
10275   static GtkWidget *window1 = NULL;
10276   static GtkWidget *window2 = NULL;
10277   static GtkWidget *window3 = NULL;
10278   static GtkWidget *window4 = NULL;
10279
10280   if (window1 && 
10281      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
10282     {
10283       gtk_widget_destroy (window1);
10284       gtk_widget_destroy (window2);
10285       gtk_widget_destroy (window3);
10286       gtk_widget_destroy (window4);
10287     }
10288   
10289   if (!window1)
10290     {
10291       window1 = paned_keyboard_window1 (widget);
10292       g_signal_connect (window1, "destroy",
10293                         G_CALLBACK (gtk_widget_destroyed),
10294                         &window1);
10295     }
10296
10297   if (!window2)
10298     {
10299       window2 = paned_keyboard_window2 (widget);
10300       g_signal_connect (window2, "destroy",
10301                         G_CALLBACK (gtk_widget_destroyed),
10302                         &window2);
10303     }
10304
10305   if (!window3)
10306     {
10307       window3 = paned_keyboard_window3 (widget);
10308       g_signal_connect (window3, "destroy",
10309                         G_CALLBACK (gtk_widget_destroyed),
10310                         &window3);
10311     }
10312
10313   if (!window4)
10314     {
10315       window4 = paned_keyboard_window4 (widget);
10316       g_signal_connect (window4, "destroy",
10317                         G_CALLBACK (gtk_widget_destroyed),
10318                         &window4);
10319     }
10320
10321   if (GTK_WIDGET_VISIBLE (window1))
10322     gtk_widget_destroy (GTK_WIDGET (window1));
10323   else
10324     gtk_widget_show_all (GTK_WIDGET (window1));
10325
10326   if (GTK_WIDGET_VISIBLE (window2))
10327     gtk_widget_destroy (GTK_WIDGET (window2));
10328   else
10329     gtk_widget_show_all (GTK_WIDGET (window2));
10330
10331   if (GTK_WIDGET_VISIBLE (window3))
10332     gtk_widget_destroy (GTK_WIDGET (window3));
10333   else
10334     gtk_widget_show_all (GTK_WIDGET (window3));
10335
10336   if (GTK_WIDGET_VISIBLE (window4))
10337     gtk_widget_destroy (GTK_WIDGET (window4));
10338   else
10339     gtk_widget_show_all (GTK_WIDGET (window4));
10340 }
10341
10342
10343 /*
10344  * Shaped Windows
10345  */
10346
10347 typedef struct _cursoroffset {gint x,y;} CursorOffset;
10348
10349 static void
10350 shape_pressed (GtkWidget *widget, GdkEventButton *event)
10351 {
10352   CursorOffset *p;
10353
10354   /* ignore double and triple click */
10355   if (event->type != GDK_BUTTON_PRESS)
10356     return;
10357
10358   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10359   p->x = (int) event->x;
10360   p->y = (int) event->y;
10361
10362   gtk_grab_add (widget);
10363   gdk_pointer_grab (widget->window, TRUE,
10364                     GDK_BUTTON_RELEASE_MASK |
10365                     GDK_BUTTON_MOTION_MASK |
10366                     GDK_POINTER_MOTION_HINT_MASK,
10367                     NULL, NULL, 0);
10368 }
10369
10370 static void
10371 shape_released (GtkWidget *widget)
10372 {
10373   gtk_grab_remove (widget);
10374   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10375                               GDK_CURRENT_TIME);
10376 }
10377
10378 static void
10379 shape_motion (GtkWidget      *widget, 
10380               GdkEventMotion *event)
10381 {
10382   gint xp, yp;
10383   CursorOffset * p;
10384   GdkModifierType mask;
10385
10386   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10387
10388   /*
10389    * Can't use event->x / event->y here 
10390    * because I need absolute coordinates.
10391    */
10392   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
10393   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
10394 }
10395
10396 GtkWidget *
10397 shape_create_icon (GdkScreen *screen,
10398                    char      *xpm_file,
10399                    gint       x,
10400                    gint       y,
10401                    gint       px,
10402                    gint       py,
10403                    gint       window_type)
10404 {
10405   GtkWidget *window;
10406   GtkWidget *pixmap;
10407   GtkWidget *fixed;
10408   CursorOffset* icon_pos;
10409   GdkGC* gc;
10410   GdkBitmap *gdk_pixmap_mask;
10411   GdkPixmap *gdk_pixmap;
10412   GtkStyle *style;
10413
10414   style = gtk_widget_get_default_style ();
10415   gc = style->black_gc; 
10416
10417   /*
10418    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
10419    */
10420   window = gtk_window_new (window_type);
10421   gtk_window_set_screen (GTK_WINDOW (window), screen);
10422   
10423   fixed = gtk_fixed_new ();
10424   gtk_widget_set_size_request (fixed, 100, 100);
10425   gtk_container_add (GTK_CONTAINER (window), fixed);
10426   gtk_widget_show (fixed);
10427   
10428   gtk_widget_set_events (window, 
10429                          gtk_widget_get_events (window) |
10430                          GDK_BUTTON_MOTION_MASK |
10431                          GDK_POINTER_MOTION_HINT_MASK |
10432                          GDK_BUTTON_PRESS_MASK);
10433
10434   gtk_widget_realize (window);
10435   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
10436                                            &style->bg[GTK_STATE_NORMAL],
10437                                            xpm_file);
10438
10439   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
10440   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
10441   gtk_widget_show (pixmap);
10442   
10443   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
10444   
10445   g_object_unref (gdk_pixmap_mask);
10446   g_object_unref (gdk_pixmap);
10447
10448   g_signal_connect (window, "button_press_event",
10449                     G_CALLBACK (shape_pressed), NULL);
10450   g_signal_connect (window, "button_release_event",
10451                     G_CALLBACK (shape_released), NULL);
10452   g_signal_connect (window, "motion_notify_event",
10453                     G_CALLBACK (shape_motion), NULL);
10454
10455   icon_pos = g_new (CursorOffset, 1);
10456   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
10457
10458   gtk_widget_set_uposition (window, x, y);
10459   gtk_widget_show (window);
10460   
10461   return window;
10462 }
10463
10464 void 
10465 create_shapes (GtkWidget *widget)
10466 {
10467   /* Variables used by the Drag/Drop and Shape Window demos */
10468   static GtkWidget *modeller = NULL;
10469   static GtkWidget *sheets = NULL;
10470   static GtkWidget *rings = NULL;
10471   static GtkWidget *with_region = NULL;
10472   GdkScreen *screen = gtk_widget_get_screen (widget);
10473   
10474   if (!(file_exists ("Modeller.xpm") &&
10475         file_exists ("FilesQueue.xpm") &&
10476         file_exists ("3DRings.xpm")))
10477     return;
10478   
10479
10480   if (!modeller)
10481     {
10482       modeller = shape_create_icon (screen, "Modeller.xpm",
10483                                     440, 140, 0,0, GTK_WINDOW_POPUP);
10484
10485       g_signal_connect (modeller, "destroy",
10486                         G_CALLBACK (gtk_widget_destroyed),
10487                         &modeller);
10488     }
10489   else
10490     gtk_widget_destroy (modeller);
10491
10492   if (!sheets)
10493     {
10494       sheets = shape_create_icon (screen, "FilesQueue.xpm",
10495                                   580, 170, 0,0, GTK_WINDOW_POPUP);
10496
10497       g_signal_connect (sheets, "destroy",
10498                         G_CALLBACK (gtk_widget_destroyed),
10499                         &sheets);
10500
10501     }
10502   else
10503     gtk_widget_destroy (sheets);
10504
10505   if (!rings)
10506     {
10507       rings = shape_create_icon (screen, "3DRings.xpm",
10508                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10509
10510       g_signal_connect (rings, "destroy",
10511                         G_CALLBACK (gtk_widget_destroyed),
10512                         &rings);
10513     }
10514   else
10515     gtk_widget_destroy (rings);
10516
10517   if (!with_region)
10518     {
10519       GdkRegion *region;
10520       gint x, y;
10521       
10522       with_region = shape_create_icon (screen, "3DRings.xpm",
10523                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10524
10525       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
10526       
10527       g_signal_connect (with_region, "destroy",
10528                         G_CALLBACK (gtk_widget_destroyed),
10529                         &with_region);
10530
10531       /* reset shape from mask to a region */
10532       x = 0;
10533       y = 0;
10534       region = gdk_region_new ();
10535
10536       while (x < 460)
10537         {
10538           while (y < 270)
10539             {
10540               GdkRectangle rect;
10541               rect.x = x;
10542               rect.y = y;
10543               rect.width = 10;
10544               rect.height = 10;
10545
10546               gdk_region_union_with_rect (region, &rect);
10547               
10548               y += 20;
10549             }
10550           y = 0;
10551           x += 20;
10552         }
10553
10554       gdk_window_shape_combine_region (with_region->window,
10555                                        region,
10556                                        0, 0);
10557     }
10558   else
10559     gtk_widget_destroy (with_region);
10560 }
10561
10562 /*
10563  * WM Hints demo
10564  */
10565
10566 void
10567 create_wmhints (GtkWidget *widget)
10568 {
10569   static GtkWidget *window = NULL;
10570   GtkWidget *label;
10571   GtkWidget *separator;
10572   GtkWidget *button;
10573   GtkWidget *box1;
10574   GtkWidget *box2;
10575
10576   GdkBitmap *circles;
10577
10578   if (!window)
10579     {
10580       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10581
10582       gtk_window_set_screen (GTK_WINDOW (window),
10583                              gtk_widget_get_screen (widget));
10584       
10585       g_signal_connect (window, "destroy",
10586                         G_CALLBACK (gtk_widget_destroyed),
10587                         &window);
10588
10589       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
10590       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10591
10592       gtk_widget_realize (window);
10593       
10594       circles = gdk_bitmap_create_from_data (window->window,
10595                                              (gchar *) circles_bits,
10596                                              circles_width,
10597                                              circles_height);
10598       gdk_window_set_icon (window->window, NULL,
10599                            circles, circles);
10600       
10601       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
10602   
10603       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
10604       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
10605       
10606       box1 = gtk_vbox_new (FALSE, 0);
10607       gtk_container_add (GTK_CONTAINER (window), box1);
10608       gtk_widget_show (box1);
10609
10610       label = gtk_label_new ("Try iconizing me!");
10611       gtk_widget_set_size_request (label, 150, 50);
10612       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
10613       gtk_widget_show (label);
10614
10615
10616       separator = gtk_hseparator_new ();
10617       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10618       gtk_widget_show (separator);
10619
10620
10621       box2 = gtk_vbox_new (FALSE, 10);
10622       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10623       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10624       gtk_widget_show (box2);
10625
10626
10627       button = gtk_button_new_with_label ("close");
10628
10629       g_signal_connect_swapped (button, "clicked",
10630                                 G_CALLBACK (gtk_widget_destroy),
10631                                 window);
10632
10633       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10634       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10635       gtk_widget_grab_default (button);
10636       gtk_widget_show (button);
10637     }
10638
10639   if (!GTK_WIDGET_VISIBLE (window))
10640     gtk_widget_show (window);
10641   else
10642     gtk_widget_destroy (window);
10643 }
10644
10645
10646 /*
10647  * Window state tracking
10648  */
10649
10650 static gint
10651 window_state_callback (GtkWidget *widget,
10652                        GdkEventWindowState *event,
10653                        gpointer data)
10654 {
10655   GtkWidget *label = data;
10656   gchar *msg;
10657
10658   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
10659                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
10660                      "withdrawn" : "not withdrawn", ", ",
10661                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
10662                      "iconified" : "not iconified", ", ",
10663                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
10664                      "sticky" : "not sticky", ", ",
10665                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
10666                      "maximized" : "not maximized", ", ",
10667                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
10668                      "fullscreen" : "not fullscreen",
10669                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
10670                      "above" : "not above", ", ",
10671                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
10672                      "below" : "not below", ", ",
10673                      NULL);
10674   
10675   gtk_label_set_text (GTK_LABEL (label), msg);
10676
10677   g_free (msg);
10678
10679   return FALSE;
10680 }
10681
10682 static GtkWidget*
10683 tracking_label (GtkWidget *window)
10684 {
10685   GtkWidget *label;
10686   GtkWidget *hbox;
10687   GtkWidget *button;
10688
10689   hbox = gtk_hbox_new (FALSE, 5);
10690
10691   g_signal_connect_object (hbox,
10692                            "destroy",
10693                            G_CALLBACK (gtk_widget_destroy),
10694                            window,
10695                            G_CONNECT_SWAPPED);
10696   
10697   label = gtk_label_new ("<no window state events received>");
10698   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
10699   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
10700   
10701   g_signal_connect (window,
10702                     "window_state_event",
10703                     G_CALLBACK (window_state_callback),
10704                     label);
10705
10706   button = gtk_button_new_with_label ("Deiconify");
10707   g_signal_connect_object (button,
10708                            "clicked",
10709                            G_CALLBACK (gtk_window_deiconify),
10710                            window,
10711                            G_CONNECT_SWAPPED);
10712   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10713
10714   button = gtk_button_new_with_label ("Iconify");
10715   g_signal_connect_object (button,
10716                            "clicked",
10717                            G_CALLBACK (gtk_window_iconify),
10718                            window,
10719                            G_CONNECT_SWAPPED);
10720   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10721
10722   button = gtk_button_new_with_label ("Fullscreen");
10723   g_signal_connect_object (button,
10724                            "clicked",
10725                            G_CALLBACK (gtk_window_fullscreen),
10726                            window,
10727                            G_CONNECT_SWAPPED);
10728   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10729
10730   button = gtk_button_new_with_label ("Unfullscreen");
10731   g_signal_connect_object (button,
10732                            "clicked",
10733                            G_CALLBACK (gtk_window_unfullscreen),
10734                            window,
10735                            G_CONNECT_SWAPPED);
10736   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10737   
10738   button = gtk_button_new_with_label ("Present");
10739   g_signal_connect_object (button,
10740                            "clicked",
10741                            G_CALLBACK (gtk_window_present),
10742                            window,
10743                            G_CONNECT_SWAPPED);
10744   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10745
10746   button = gtk_button_new_with_label ("Show");
10747   g_signal_connect_object (button,
10748                            "clicked",
10749                            G_CALLBACK (gtk_widget_show),
10750                            window,
10751                            G_CONNECT_SWAPPED);
10752   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10753   
10754   gtk_widget_show_all (hbox);
10755   
10756   return hbox;
10757 }
10758
10759 void
10760 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
10761 {
10762   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10763
10764   gtk_window_set_keep_above (GTK_WINDOW (data),
10765                              gtk_toggle_button_get_active (togglebutton));
10766
10767   if (gtk_toggle_button_get_active (togglebutton))
10768     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10769 }
10770
10771 void
10772 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
10773 {
10774   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10775
10776   gtk_window_set_keep_below (GTK_WINDOW (data),
10777                              gtk_toggle_button_get_active (togglebutton));
10778
10779   if (gtk_toggle_button_get_active (togglebutton))
10780     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10781 }
10782
10783
10784 static GtkWidget*
10785 get_state_controls (GtkWidget *window)
10786 {
10787   GtkWidget *vbox;
10788   GtkWidget *button;
10789   GtkWidget *button_above;
10790   GtkWidget *button_below;
10791
10792   vbox = gtk_vbox_new (FALSE, 0);
10793   
10794   button = gtk_button_new_with_label ("Stick");
10795   g_signal_connect_object (button,
10796                            "clicked",
10797                            G_CALLBACK (gtk_window_stick),
10798                            window,
10799                            G_CONNECT_SWAPPED);
10800   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10801
10802   button = gtk_button_new_with_label ("Unstick");
10803   g_signal_connect_object (button,
10804                            "clicked",
10805                            G_CALLBACK (gtk_window_unstick),
10806                            window,
10807                            G_CONNECT_SWAPPED);
10808   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10809   
10810   button = gtk_button_new_with_label ("Maximize");
10811   g_signal_connect_object (button,
10812                            "clicked",
10813                            G_CALLBACK (gtk_window_maximize),
10814                            window,
10815                            G_CONNECT_SWAPPED);
10816   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10817
10818   button = gtk_button_new_with_label ("Unmaximize");
10819   g_signal_connect_object (button,
10820                            "clicked",
10821                            G_CALLBACK (gtk_window_unmaximize),
10822                            window,
10823                            G_CONNECT_SWAPPED);
10824   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10825
10826   button = gtk_button_new_with_label ("Iconify");
10827   g_signal_connect_object (button,
10828                            "clicked",
10829                            G_CALLBACK (gtk_window_iconify),
10830                            window,
10831                            G_CONNECT_SWAPPED);
10832   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10833
10834   button = gtk_button_new_with_label ("Fullscreen");
10835   g_signal_connect_object (button,
10836                            "clicked",
10837                            G_CALLBACK (gtk_window_fullscreen),
10838                            window,
10839                            G_CONNECT_SWAPPED);
10840   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10841
10842   button = gtk_button_new_with_label ("Unfullscreen");
10843   g_signal_connect_object (button,
10844                            "clicked",
10845                            G_CALLBACK (gtk_window_unfullscreen),
10846                            window,
10847                            G_CONNECT_SWAPPED);
10848   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10849
10850   button_above = gtk_toggle_button_new_with_label ("Keep above");
10851   g_signal_connect (button_above,
10852                     "toggled",
10853                     G_CALLBACK (keep_window_above),
10854                     window);
10855   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
10856
10857   button_below = gtk_toggle_button_new_with_label ("Keep below");
10858   g_signal_connect (button_below,
10859                     "toggled",
10860                     G_CALLBACK (keep_window_below),
10861                     window);
10862   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
10863
10864   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
10865   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
10866
10867   button = gtk_button_new_with_label ("Hide (withdraw)");
10868   g_signal_connect_object (button,
10869                            "clicked",
10870                            G_CALLBACK (gtk_widget_hide),
10871                            window,
10872                            G_CONNECT_SWAPPED);
10873   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10874   
10875   gtk_widget_show_all (vbox);
10876
10877   return vbox;
10878 }
10879
10880 void
10881 create_window_states (GtkWidget *widget)
10882 {
10883   static GtkWidget *window = NULL;
10884   GtkWidget *label;
10885   GtkWidget *box1;
10886   GtkWidget *iconified;
10887   GtkWidget *normal;
10888   GtkWidget *controls;
10889
10890   if (!window)
10891     {
10892       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10893       gtk_window_set_screen (GTK_WINDOW (window),
10894                              gtk_widget_get_screen (widget));
10895
10896       g_signal_connect (window, "destroy",
10897                         G_CALLBACK (gtk_widget_destroyed),
10898                         &window);
10899
10900       gtk_window_set_title (GTK_WINDOW (window), "Window states");
10901       
10902       box1 = gtk_vbox_new (FALSE, 0);
10903       gtk_container_add (GTK_CONTAINER (window), box1);
10904
10905       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10906
10907       gtk_window_set_screen (GTK_WINDOW (iconified),
10908                              gtk_widget_get_screen (widget));
10909       
10910       g_signal_connect_object (iconified, "destroy",
10911                                G_CALLBACK (gtk_widget_destroy),
10912                                window,
10913                                G_CONNECT_SWAPPED);
10914       gtk_window_iconify (GTK_WINDOW (iconified));
10915       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
10916       controls = get_state_controls (iconified);
10917       gtk_container_add (GTK_CONTAINER (iconified), controls);
10918       
10919       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10920
10921       gtk_window_set_screen (GTK_WINDOW (normal),
10922                              gtk_widget_get_screen (widget));
10923       
10924       g_signal_connect_object (normal, "destroy",
10925                                G_CALLBACK (gtk_widget_destroy),
10926                                window,
10927                                G_CONNECT_SWAPPED);
10928       
10929       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
10930       controls = get_state_controls (normal);
10931       gtk_container_add (GTK_CONTAINER (normal), controls);
10932       
10933       label = tracking_label (iconified);
10934       gtk_container_add (GTK_CONTAINER (box1), label);
10935
10936       label = tracking_label (normal);
10937       gtk_container_add (GTK_CONTAINER (box1), label);
10938
10939       gtk_widget_show_all (iconified);
10940       gtk_widget_show_all (normal);
10941       gtk_widget_show_all (box1);
10942     }
10943
10944   if (!GTK_WIDGET_VISIBLE (window))
10945     gtk_widget_show (window);
10946   else
10947     gtk_widget_destroy (window);
10948 }
10949
10950 /*
10951  * Window sizing
10952  */
10953
10954 static gint
10955 configure_event_callback (GtkWidget *widget,
10956                           GdkEventConfigure *event,
10957                           gpointer data)
10958 {
10959   GtkWidget *label = data;
10960   gchar *msg;
10961   gint x, y;
10962   
10963   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
10964   
10965   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
10966                          "position: %d, %d",
10967                          event->x, event->y, event->width, event->height,
10968                          x, y);
10969   
10970   gtk_label_set_text (GTK_LABEL (label), msg);
10971
10972   g_free (msg);
10973
10974   return FALSE;
10975 }
10976
10977 static void
10978 get_ints (GtkWidget *window,
10979           gint      *a,
10980           gint      *b)
10981 {
10982   GtkWidget *spin1;
10983   GtkWidget *spin2;
10984
10985   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
10986   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
10987
10988   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
10989   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
10990 }
10991
10992 static void
10993 set_size_callback (GtkWidget *widget,
10994                    gpointer   data)
10995 {
10996   gint w, h;
10997   
10998   get_ints (data, &w, &h);
10999
11000   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
11001 }
11002
11003 static void
11004 unset_default_size_callback (GtkWidget *widget,
11005                              gpointer   data)
11006 {
11007   gtk_window_set_default_size (g_object_get_data (data, "target"),
11008                                -1, -1);
11009 }
11010
11011 static void
11012 set_default_size_callback (GtkWidget *widget,
11013                            gpointer   data)
11014 {
11015   gint w, h;
11016   
11017   get_ints (data, &w, &h);
11018
11019   gtk_window_set_default_size (g_object_get_data (data, "target"),
11020                                w, h);
11021 }
11022
11023 static void
11024 unset_size_request_callback (GtkWidget *widget,
11025                              gpointer   data)
11026 {
11027   gtk_widget_set_size_request (g_object_get_data (data, "target"),
11028                                -1, -1);
11029 }
11030
11031 static void
11032 set_size_request_callback (GtkWidget *widget,
11033                            gpointer   data)
11034 {
11035   gint w, h;
11036   
11037   get_ints (data, &w, &h);
11038
11039   gtk_widget_set_size_request (g_object_get_data (data, "target"),
11040                                w, h);
11041 }
11042
11043 static void
11044 set_location_callback (GtkWidget *widget,
11045                        gpointer   data)
11046 {
11047   gint x, y;
11048   
11049   get_ints (data, &x, &y);
11050
11051   gtk_window_move (g_object_get_data (data, "target"), x, y);
11052 }
11053
11054 static void
11055 move_to_position_callback (GtkWidget *widget,
11056                            gpointer   data)
11057 {
11058   gint x, y;
11059   GtkWindow *window;
11060
11061   window = g_object_get_data (data, "target");
11062   
11063   gtk_window_get_position (window, &x, &y);
11064
11065   gtk_window_move (window, x, y);
11066 }
11067
11068 static void
11069 set_geometry_callback (GtkWidget *entry,
11070                        gpointer   data)
11071 {
11072   gchar *text;
11073   GtkWindow *target;
11074
11075   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
11076   
11077   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
11078
11079   if (!gtk_window_parse_geometry (target, text))
11080     g_print ("Bad geometry string '%s'\n", text);
11081
11082   g_free (text);
11083 }
11084
11085 static void
11086 allow_shrink_callback (GtkWidget *widget,
11087                        gpointer   data)
11088 {
11089   g_object_set (g_object_get_data (data, "target"),
11090                 "allow_shrink",
11091                 GTK_TOGGLE_BUTTON (widget)->active,
11092                 NULL);
11093 }
11094
11095 static void
11096 allow_grow_callback (GtkWidget *widget,
11097                      gpointer   data)
11098 {
11099   g_object_set (g_object_get_data (data, "target"),
11100                 "allow_grow",
11101                 GTK_TOGGLE_BUTTON (widget)->active,
11102                 NULL);
11103 }
11104
11105 static void
11106 gravity_selected (GtkWidget *widget,
11107                   gpointer   data)
11108 {
11109   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
11110                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
11111 }
11112
11113 static void
11114 pos_selected (GtkWidget *widget,
11115               gpointer   data)
11116 {
11117   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
11118                            gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
11119 }
11120
11121 static void
11122 move_gravity_window_to_current_position (GtkWidget *widget,
11123                                          gpointer   data)
11124 {
11125   gint x, y;
11126   GtkWindow *window;
11127
11128   window = GTK_WINDOW (data);    
11129   
11130   gtk_window_get_position (window, &x, &y);
11131
11132   gtk_window_move (window, x, y);
11133 }
11134
11135 static void
11136 get_screen_corner (GtkWindow *window,
11137                    gint      *x,
11138                    gint      *y)
11139 {
11140   int w, h;
11141   GdkScreen * screen = gtk_window_get_screen (window);
11142   
11143   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
11144
11145   switch (gtk_window_get_gravity (window))
11146     {
11147     case GDK_GRAVITY_SOUTH_EAST:
11148       *x = gdk_screen_get_width (screen) - w;
11149       *y = gdk_screen_get_height (screen) - h;
11150       break;
11151
11152     case GDK_GRAVITY_NORTH_EAST:
11153       *x = gdk_screen_get_width (screen) - w;
11154       *y = 0;
11155       break;
11156
11157     case GDK_GRAVITY_SOUTH_WEST:
11158       *x = 0;
11159       *y = gdk_screen_get_height (screen) - h;
11160       break;
11161
11162     case GDK_GRAVITY_NORTH_WEST:
11163       *x = 0;
11164       *y = 0;
11165       break;
11166       
11167     case GDK_GRAVITY_SOUTH:
11168       *x = (gdk_screen_get_width (screen) - w) / 2;
11169       *y = gdk_screen_get_height (screen) - h;
11170       break;
11171
11172     case GDK_GRAVITY_NORTH:
11173       *x = (gdk_screen_get_width (screen) - w) / 2;
11174       *y = 0;
11175       break;
11176
11177     case GDK_GRAVITY_WEST:
11178       *x = 0;
11179       *y = (gdk_screen_get_height (screen) - h) / 2;
11180       break;
11181
11182     case GDK_GRAVITY_EAST:
11183       *x = gdk_screen_get_width (screen) - w;
11184       *y = (gdk_screen_get_height (screen) - h) / 2;
11185       break;
11186
11187     case GDK_GRAVITY_CENTER:
11188       *x = (gdk_screen_get_width (screen) - w) / 2;
11189       *y = (gdk_screen_get_height (screen) - h) / 2;
11190       break;
11191
11192     case GDK_GRAVITY_STATIC:
11193       /* pick some random numbers */
11194       *x = 350;
11195       *y = 350;
11196       break;
11197
11198     default:
11199       g_assert_not_reached ();
11200       break;
11201     }
11202 }
11203
11204 static void
11205 move_gravity_window_to_starting_position (GtkWidget *widget,
11206                                           gpointer   data)
11207 {
11208   gint x, y;
11209   GtkWindow *window;
11210
11211   window = GTK_WINDOW (data);    
11212   
11213   get_screen_corner (window,
11214                      &x, &y);
11215   
11216   gtk_window_move (window, x, y);
11217 }
11218
11219 static GtkWidget*
11220 make_gravity_window (GtkWidget   *destroy_with,
11221                      GdkGravity   gravity,
11222                      const gchar *title)
11223 {
11224   GtkWidget *window;
11225   GtkWidget *button;
11226   GtkWidget *vbox;
11227   int x, y;
11228   
11229   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11230
11231   gtk_window_set_screen (GTK_WINDOW (window),
11232                          gtk_widget_get_screen (destroy_with));
11233
11234   vbox = gtk_vbox_new (FALSE, 0);
11235   gtk_widget_show (vbox);
11236   
11237   gtk_container_add (GTK_CONTAINER (window), vbox);
11238   gtk_window_set_title (GTK_WINDOW (window), title);
11239   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
11240
11241   g_signal_connect_object (destroy_with,
11242                            "destroy",
11243                            G_CALLBACK (gtk_widget_destroy),
11244                            window,
11245                            G_CONNECT_SWAPPED);
11246
11247   
11248   button = gtk_button_new_with_mnemonic ("_Move to current position");
11249
11250   g_signal_connect (button, "clicked",
11251                     G_CALLBACK (move_gravity_window_to_current_position),
11252                     window);
11253
11254   gtk_container_add (GTK_CONTAINER (vbox), button);
11255   gtk_widget_show (button);
11256
11257   button = gtk_button_new_with_mnemonic ("Move to _starting position");
11258
11259   g_signal_connect (button, "clicked",
11260                     G_CALLBACK (move_gravity_window_to_starting_position),
11261                     window);
11262
11263   gtk_container_add (GTK_CONTAINER (vbox), button);
11264   gtk_widget_show (button);
11265   
11266   /* Pretend this is the result of --geometry.
11267    * DO NOT COPY THIS CODE unless you are setting --geometry results,
11268    * and in that case you probably should just use gtk_window_parse_geometry().
11269    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
11270    * you are parsing --geometry or equivalent.
11271    */
11272   gtk_window_set_geometry_hints (GTK_WINDOW (window),
11273                                  NULL, NULL,
11274                                  GDK_HINT_USER_POS);
11275
11276   gtk_window_set_default_size (GTK_WINDOW (window),
11277                                200, 200);
11278
11279   get_screen_corner (GTK_WINDOW (window), &x, &y);
11280   
11281   gtk_window_move (GTK_WINDOW (window),
11282                    x, y);
11283   
11284   return window;
11285 }
11286
11287 static void
11288 do_gravity_test (GtkWidget *widget,
11289                  gpointer   data)
11290 {
11291   GtkWidget *destroy_with = data;
11292   GtkWidget *window;
11293   
11294   /* We put a window at each gravity point on the screen. */
11295   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
11296                                 "NorthWest");
11297   gtk_widget_show (window);
11298   
11299   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
11300                                 "SouthEast");
11301   gtk_widget_show (window);
11302
11303   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
11304                                 "NorthEast");
11305   gtk_widget_show (window);
11306
11307   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
11308                                 "SouthWest");
11309   gtk_widget_show (window);
11310
11311   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
11312                                 "South");
11313   gtk_widget_show (window);
11314
11315   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
11316                                 "North");
11317   gtk_widget_show (window);
11318
11319   
11320   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
11321                                 "West");
11322   gtk_widget_show (window);
11323
11324     
11325   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
11326                                 "East");
11327   gtk_widget_show (window);
11328
11329   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
11330                                 "Center");
11331   gtk_widget_show (window);
11332
11333   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
11334                                 "Static");
11335   gtk_widget_show (window);
11336 }
11337
11338 static GtkWidget*
11339 window_controls (GtkWidget *window)
11340 {
11341   GtkWidget *control_window;
11342   GtkWidget *label;
11343   GtkWidget *vbox;
11344   GtkWidget *button;
11345   GtkWidget *spin;
11346   GtkAdjustment *adj;
11347   GtkWidget *entry;
11348   GtkWidget *om;
11349   GtkWidget *menu;
11350   gint i;
11351   
11352   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11353
11354   gtk_window_set_screen (GTK_WINDOW (control_window),
11355                          gtk_widget_get_screen (window));
11356
11357   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
11358   
11359   g_object_set_data (G_OBJECT (control_window),
11360                      "target",
11361                      window);
11362   
11363   g_signal_connect_object (control_window,
11364                            "destroy",
11365                            G_CALLBACK (gtk_widget_destroy),
11366                            window,
11367                            G_CONNECT_SWAPPED);
11368
11369   vbox = gtk_vbox_new (FALSE, 5);
11370   
11371   gtk_container_add (GTK_CONTAINER (control_window), vbox);
11372   
11373   label = gtk_label_new ("<no configure events>");
11374   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11375   
11376   g_signal_connect (window,
11377                     "configure_event",
11378                     G_CALLBACK (configure_event_callback),
11379                     label);
11380
11381   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11382                                               5.0, 0.0);
11383   spin = gtk_spin_button_new (adj, 0, 0);
11384
11385   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11386
11387   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
11388
11389   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11390                                               5.0, 0.0);
11391   spin = gtk_spin_button_new (adj, 0, 0);
11392
11393   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11394
11395   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
11396
11397   entry = gtk_entry_new ();
11398   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11399
11400   g_signal_connect (entry, "changed",
11401                     G_CALLBACK (set_geometry_callback),
11402                     control_window);
11403
11404   button = gtk_button_new_with_label ("Show gravity test windows");
11405   g_signal_connect_swapped (button,
11406                             "clicked",
11407                             G_CALLBACK (do_gravity_test),
11408                             control_window);
11409   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11410
11411   button = gtk_button_new_with_label ("Reshow with initial size");
11412   g_signal_connect_object (button,
11413                            "clicked",
11414                            G_CALLBACK (gtk_window_reshow_with_initial_size),
11415                            window,
11416                            G_CONNECT_SWAPPED);
11417   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11418   
11419   button = gtk_button_new_with_label ("Queue resize");
11420   g_signal_connect_object (button,
11421                            "clicked",
11422                            G_CALLBACK (gtk_widget_queue_resize),
11423                            window,
11424                            G_CONNECT_SWAPPED);
11425   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11426   
11427   button = gtk_button_new_with_label ("Resize");
11428   g_signal_connect (button,
11429                     "clicked",
11430                     G_CALLBACK (set_size_callback),
11431                     control_window);
11432   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11433
11434   button = gtk_button_new_with_label ("Set default size");
11435   g_signal_connect (button,
11436                     "clicked",
11437                     G_CALLBACK (set_default_size_callback),
11438                     control_window);
11439   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11440
11441   button = gtk_button_new_with_label ("Unset default size");
11442   g_signal_connect (button,
11443                     "clicked",
11444                     G_CALLBACK (unset_default_size_callback),
11445                     control_window);
11446   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11447   
11448   button = gtk_button_new_with_label ("Set size request");
11449   g_signal_connect (button,
11450                     "clicked",
11451                     G_CALLBACK (set_size_request_callback),
11452                     control_window);
11453   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11454
11455   button = gtk_button_new_with_label ("Unset size request");
11456   g_signal_connect (button,
11457                     "clicked",
11458                     G_CALLBACK (unset_size_request_callback),
11459                     control_window);
11460   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11461   
11462   button = gtk_button_new_with_label ("Move");
11463   g_signal_connect (button,
11464                     "clicked",
11465                     G_CALLBACK (set_location_callback),
11466                     control_window);
11467   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11468
11469   button = gtk_button_new_with_label ("Move to current position");
11470   g_signal_connect (button,
11471                     "clicked",
11472                     G_CALLBACK (move_to_position_callback),
11473                     control_window);
11474   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11475   
11476   button = gtk_check_button_new_with_label ("Allow shrink");
11477   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
11478   g_signal_connect (button,
11479                     "toggled",
11480                     G_CALLBACK (allow_shrink_callback),
11481                     control_window);
11482   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11483
11484   button = gtk_check_button_new_with_label ("Allow grow");
11485   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
11486   g_signal_connect (button,
11487                     "toggled",
11488                     G_CALLBACK (allow_grow_callback),
11489                     control_window);
11490   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11491   
11492   button = gtk_button_new_with_mnemonic ("_Show");
11493   g_signal_connect_object (button,
11494                            "clicked",
11495                            G_CALLBACK (gtk_widget_show),
11496                            window,
11497                            G_CONNECT_SWAPPED);
11498   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11499
11500   button = gtk_button_new_with_mnemonic ("_Hide");
11501   g_signal_connect_object (button,
11502                            "clicked",
11503                            G_CALLBACK (gtk_widget_hide),
11504                            window,
11505                            G_CONNECT_SWAPPED);
11506   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11507   
11508   menu = gtk_menu_new ();
11509   
11510   i = 0;
11511   while (i < 10)
11512     {
11513       GtkWidget *mi;
11514       static gchar *names[] = {
11515         "GDK_GRAVITY_NORTH_WEST",
11516         "GDK_GRAVITY_NORTH",
11517         "GDK_GRAVITY_NORTH_EAST",
11518         "GDK_GRAVITY_WEST",
11519         "GDK_GRAVITY_CENTER",
11520         "GDK_GRAVITY_EAST",
11521         "GDK_GRAVITY_SOUTH_WEST",
11522         "GDK_GRAVITY_SOUTH",
11523         "GDK_GRAVITY_SOUTH_EAST",
11524         "GDK_GRAVITY_STATIC",
11525         NULL
11526       };
11527
11528       g_assert (names[i]);
11529       
11530       mi = gtk_menu_item_new_with_label (names[i]);
11531
11532       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11533
11534       ++i;
11535     }
11536   
11537   gtk_widget_show_all (menu);
11538   
11539   om = gtk_option_menu_new ();
11540   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11541   
11542
11543   g_signal_connect (om,
11544                     "changed",
11545                     G_CALLBACK (gravity_selected),
11546                     control_window);
11547
11548   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11549
11550
11551   menu = gtk_menu_new ();
11552   
11553   i = 0;
11554   while (i < 5)
11555     {
11556       GtkWidget *mi;
11557       static gchar *names[] = {
11558         "GTK_WIN_POS_NONE",
11559         "GTK_WIN_POS_CENTER",
11560         "GTK_WIN_POS_MOUSE",
11561         "GTK_WIN_POS_CENTER_ALWAYS",
11562         "GTK_WIN_POS_CENTER_ON_PARENT",
11563         NULL
11564       };
11565
11566       g_assert (names[i]);
11567       
11568       mi = gtk_menu_item_new_with_label (names[i]);
11569
11570       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11571
11572       ++i;
11573     }
11574   
11575   gtk_widget_show_all (menu);
11576   
11577   om = gtk_option_menu_new ();
11578   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11579   
11580
11581   g_signal_connect (om,
11582                     "changed",
11583                     G_CALLBACK (pos_selected),
11584                     control_window);
11585
11586   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11587   
11588   gtk_widget_show_all (vbox);
11589   
11590   return control_window;
11591 }
11592
11593 void
11594 create_window_sizing (GtkWidget *widget)
11595 {
11596   static GtkWidget *window = NULL;
11597   static GtkWidget *target_window = NULL;
11598
11599   if (!target_window)
11600     {
11601       GtkWidget *label;
11602       
11603       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11604       gtk_window_set_screen (GTK_WINDOW (target_window),
11605                              gtk_widget_get_screen (widget));
11606       label = gtk_label_new (NULL);
11607       gtk_label_set_markup (GTK_LABEL (label), "<span foreground=\"purple\"><big>Window being resized</big></span>\nBlah blah blah blah\nblah blah blah\nblah blah blah blah blah");
11608       gtk_container_add (GTK_CONTAINER (target_window), label);
11609       gtk_widget_show (label);
11610       
11611       g_signal_connect (target_window, "destroy",
11612                         G_CALLBACK (gtk_widget_destroyed),
11613                         &target_window);
11614
11615       window = window_controls (target_window);
11616       
11617       g_signal_connect (window, "destroy",
11618                         G_CALLBACK (gtk_widget_destroyed),
11619                         &window);
11620       
11621       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
11622     }
11623
11624   /* don't show target window by default, we want to allow testing
11625    * of behavior on first show.
11626    */
11627   
11628   if (!GTK_WIDGET_VISIBLE (window))
11629     gtk_widget_show (window);
11630   else
11631     gtk_widget_destroy (window);
11632 }
11633
11634 /*
11635  * GtkProgressBar
11636  */
11637
11638 typedef struct _ProgressData {
11639   GtkWidget *window;
11640   GtkWidget *pbar;
11641   GtkWidget *block_spin;
11642   GtkWidget *x_align_spin;
11643   GtkWidget *y_align_spin;
11644   GtkWidget *step_spin;
11645   GtkWidget *act_blocks_spin;
11646   GtkWidget *label;
11647   GtkWidget *omenu1;
11648   GtkWidget *elmenu;
11649   GtkWidget *omenu2;
11650   GtkWidget *entry;
11651   int timer;
11652 } ProgressData;
11653
11654 gint
11655 progress_timeout (gpointer data)
11656 {
11657   gdouble new_val;
11658   GtkAdjustment *adj;
11659
11660   adj = GTK_PROGRESS (data)->adjustment;
11661
11662   new_val = adj->value + 1;
11663   if (new_val > adj->upper)
11664     new_val = adj->lower;
11665
11666   gtk_progress_set_value (GTK_PROGRESS (data), new_val);
11667
11668   return TRUE;
11669 }
11670
11671 static void
11672 destroy_progress (GtkWidget     *widget,
11673                   ProgressData **pdata)
11674 {
11675   gtk_timeout_remove ((*pdata)->timer);
11676   (*pdata)->timer = 0;
11677   (*pdata)->window = NULL;
11678   g_free (*pdata);
11679   *pdata = NULL;
11680 }
11681
11682 static void
11683 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
11684 {
11685   ProgressData *pdata;
11686   gint i;
11687
11688   pdata = (ProgressData *) data;
11689
11690   if (!GTK_WIDGET_MAPPED (widget))
11691     return;
11692
11693   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11694
11695   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
11696                                     (GtkProgressBarOrientation) i);
11697 }
11698
11699 static void
11700 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
11701 {
11702   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
11703                               GTK_TOGGLE_BUTTON (widget)->active);
11704   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
11705   gtk_widget_set_sensitive (pdata->x_align_spin,
11706                             GTK_TOGGLE_BUTTON (widget)->active);
11707   gtk_widget_set_sensitive (pdata->y_align_spin,
11708                             GTK_TOGGLE_BUTTON (widget)->active);
11709 }
11710
11711 static void
11712 progressbar_toggle_ellipsize (GtkWidget *widget,
11713                               gpointer   data)
11714 {
11715   ProgressData *pdata = data;
11716   if (GTK_WIDGET_DRAWABLE (widget))
11717     {
11718       gint i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11719       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
11720     }
11721 }
11722
11723 static void
11724 progressbar_toggle_bar_style (GtkWidget *widget, gpointer data)
11725 {
11726   ProgressData *pdata;
11727   gint i;
11728
11729   pdata = (ProgressData *) data;
11730
11731   if (!GTK_WIDGET_MAPPED (widget))
11732     return;
11733
11734   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11735
11736   if (i == 1)
11737     gtk_widget_set_sensitive (pdata->block_spin, TRUE);
11738   else
11739     gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11740   
11741   gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
11742                                   (GtkProgressBarStyle) i);
11743 }
11744
11745 static void
11746 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
11747 {
11748   char buf[20];
11749
11750   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
11751     sprintf (buf, "???");
11752   else
11753     sprintf (buf, "%.0f%%", 100 *
11754              gtk_progress_get_current_percentage (GTK_PROGRESS (pdata->pbar)));
11755   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
11756 }
11757
11758 static void
11759 adjust_blocks (GtkAdjustment *adj, ProgressData *pdata)
11760 {
11761   gtk_progress_set_percentage (GTK_PROGRESS (pdata->pbar), 0);
11762   gtk_progress_bar_set_discrete_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11763      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->block_spin)));
11764 }
11765
11766 static void
11767 adjust_step (GtkAdjustment *adj, ProgressData *pdata)
11768 {
11769   gtk_progress_bar_set_activity_step (GTK_PROGRESS_BAR (pdata->pbar),
11770      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->step_spin)));
11771 }
11772
11773 static void
11774 adjust_act_blocks (GtkAdjustment *adj, ProgressData *pdata)
11775 {
11776   gtk_progress_bar_set_activity_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11777                gtk_spin_button_get_value_as_int 
11778                       (GTK_SPIN_BUTTON (pdata->act_blocks_spin)));
11779 }
11780
11781 static void
11782 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
11783 {
11784   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
11785          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
11786          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
11787 }
11788
11789 static void
11790 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
11791 {
11792   gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
11793                                   GTK_TOGGLE_BUTTON (widget)->active);
11794   gtk_widget_set_sensitive (pdata->step_spin, 
11795                             GTK_TOGGLE_BUTTON (widget)->active);
11796   gtk_widget_set_sensitive (pdata->act_blocks_spin, 
11797                             GTK_TOGGLE_BUTTON (widget)->active);
11798 }
11799
11800 static void
11801 entry_changed (GtkWidget *widget, ProgressData *pdata)
11802 {
11803   gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11804                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
11805 }
11806
11807 void
11808 create_progress_bar (GtkWidget *widget)
11809 {
11810   GtkWidget *button;
11811   GtkWidget *vbox;
11812   GtkWidget *vbox2;
11813   GtkWidget *hbox;
11814   GtkWidget *check;
11815   GtkWidget *frame;
11816   GtkWidget *tab;
11817   GtkWidget *label;
11818   GtkWidget *align;
11819   GtkAdjustment *adj;
11820   static ProgressData *pdata = NULL;
11821
11822   static gchar *items1[] =
11823   {
11824     "Left-Right",
11825     "Right-Left",
11826     "Bottom-Top",
11827     "Top-Bottom"
11828   };
11829
11830   static gchar *items2[] =
11831   {
11832     "Continuous",
11833     "Discrete"
11834   };
11835
11836   static char *ellipsize_items[] = {
11837     "None",     // PANGO_ELLIPSIZE_NONE,
11838     "Start",    // PANGO_ELLIPSIZE_START,
11839     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
11840     "End",      // PANGO_ELLIPSIZE_END
11841   };
11842   
11843   if (!pdata)
11844     pdata = g_new0 (ProgressData, 1);
11845
11846   if (!pdata->window)
11847     {
11848       pdata->window = gtk_dialog_new ();
11849
11850       gtk_window_set_screen (GTK_WINDOW (pdata->window),
11851                              gtk_widget_get_screen (widget));
11852
11853       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
11854
11855       g_signal_connect (pdata->window, "destroy",
11856                         G_CALLBACK (destroy_progress),
11857                         &pdata);
11858
11859       pdata->timer = 0;
11860
11861       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
11862       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
11863
11864       vbox = gtk_vbox_new (FALSE, 5);
11865       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
11866       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
11867                           vbox, FALSE, TRUE, 0);
11868
11869       frame = gtk_frame_new ("Progress");
11870       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11871
11872       vbox2 = gtk_vbox_new (FALSE, 5);
11873       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11874
11875       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11876       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11877
11878       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
11879       g_signal_connect (adj, "value_changed",
11880                         G_CALLBACK (progress_value_changed), pdata);
11881
11882       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
11883                                     "adjustment", adj,
11884                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
11885                                     NULL);
11886       gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11887                                       "%v from [%l,%u] (=%p%%)");
11888       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
11889       pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
11890
11891       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11892       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11893
11894       hbox = gtk_hbox_new (FALSE, 5);
11895       gtk_container_add (GTK_CONTAINER (align), hbox);
11896       label = gtk_label_new ("Label updated by user :"); 
11897       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11898       pdata->label = gtk_label_new ("");
11899       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
11900
11901       frame = gtk_frame_new ("Options");
11902       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11903
11904       vbox2 = gtk_vbox_new (FALSE, 5);
11905       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11906
11907       tab = gtk_table_new (7, 2, FALSE);
11908       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
11909
11910       label = gtk_label_new ("Orientation :");
11911       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
11912                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11913                         5, 5);
11914       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11915
11916       pdata->omenu1 = build_option_menu (items1, 4, 0,
11917                                          progressbar_toggle_orientation,
11918                                          pdata);
11919       hbox = gtk_hbox_new (FALSE, 0);
11920       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
11921                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11922                         5, 5);
11923       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
11924       
11925       check = gtk_check_button_new_with_label ("Show text");
11926       g_signal_connect (check, "clicked",
11927                         G_CALLBACK (toggle_show_text),
11928                         pdata);
11929       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
11930                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11931                         5, 5);
11932
11933       hbox = gtk_hbox_new (FALSE, 0);
11934       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
11935                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11936                         5, 5);
11937
11938       label = gtk_label_new ("Format : ");
11939       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11940
11941       pdata->entry = gtk_entry_new ();
11942       g_signal_connect (pdata->entry, "changed",
11943                         G_CALLBACK (entry_changed),
11944                         pdata);
11945       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
11946       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
11947       gtk_widget_set_size_request (pdata->entry, 100, -1);
11948       gtk_widget_set_sensitive (pdata->entry, FALSE);
11949
11950       label = gtk_label_new ("Text align :");
11951       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
11952                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11953                         5, 5);
11954       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11955
11956       hbox = gtk_hbox_new (FALSE, 0);
11957       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
11958                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11959                         5, 5);
11960
11961       label = gtk_label_new ("x :");
11962       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11963       
11964       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11965       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
11966       g_signal_connect (adj, "value_changed",
11967                         G_CALLBACK (adjust_align), pdata);
11968       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
11969       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
11970
11971       label = gtk_label_new ("y :");
11972       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11973
11974       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11975       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
11976       g_signal_connect (adj, "value_changed",
11977                         G_CALLBACK (adjust_align), pdata);
11978       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
11979       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
11980
11981       label = gtk_label_new ("Ellipsize text :");
11982       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
11983                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11984                         5, 5);
11985       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11986       pdata->elmenu = build_option_menu (ellipsize_items,
11987                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
11988                                          2, // PANGO_ELLIPSIZE_MIDDLE
11989                                          progressbar_toggle_ellipsize,
11990                                          pdata);
11991       hbox = gtk_hbox_new (FALSE, 0);
11992       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
11993                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11994                         5, 5);
11995       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
11996
11997       label = gtk_label_new ("Bar Style :");
11998       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 13, 14,
11999                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12000                         5, 5);
12001       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
12002
12003       pdata->omenu2 = build_option_menu (items2, 2, 0,
12004                                          progressbar_toggle_bar_style,
12005                                          pdata);
12006       hbox = gtk_hbox_new (FALSE, 0);
12007       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 13, 14,
12008                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12009                         5, 5);
12010       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu2, TRUE, TRUE, 0);
12011
12012       label = gtk_label_new ("Block count :");
12013       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 14, 15,
12014                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12015                         5, 5);
12016       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
12017
12018       hbox = gtk_hbox_new (FALSE, 0);
12019       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 14, 15,
12020                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12021                         5, 5);
12022       adj = (GtkAdjustment *) gtk_adjustment_new (10, 2, 20, 1, 5, 0);
12023       pdata->block_spin = gtk_spin_button_new (adj, 0, 0);
12024       g_signal_connect (adj, "value_changed",
12025                         G_CALLBACK (adjust_blocks), pdata);
12026       gtk_box_pack_start (GTK_BOX (hbox), pdata->block_spin, FALSE, TRUE, 0);
12027       gtk_widget_set_sensitive (pdata->block_spin, FALSE);
12028
12029       check = gtk_check_button_new_with_label ("Activity mode");
12030       g_signal_connect (check, "clicked",
12031                         G_CALLBACK (toggle_activity_mode), pdata);
12032       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
12033                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12034                         5, 5);
12035
12036       hbox = gtk_hbox_new (FALSE, 0);
12037       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 15, 16,
12038                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12039                         5, 5);
12040       label = gtk_label_new ("Step size : ");
12041       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
12042       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
12043       pdata->step_spin = gtk_spin_button_new (adj, 0, 0);
12044       g_signal_connect (adj, "value_changed",
12045                         G_CALLBACK (adjust_step), pdata);
12046       gtk_box_pack_start (GTK_BOX (hbox), pdata->step_spin, FALSE, TRUE, 0);
12047       gtk_widget_set_sensitive (pdata->step_spin, FALSE);
12048
12049       hbox = gtk_hbox_new (FALSE, 0);
12050       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 16, 17,
12051                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12052                         5, 5);
12053       label = gtk_label_new ("Blocks :     ");
12054       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
12055       adj = (GtkAdjustment *) gtk_adjustment_new (5, 2, 10, 1, 5, 0);
12056       pdata->act_blocks_spin = gtk_spin_button_new (adj, 0, 0);
12057       g_signal_connect (adj, "value_changed",
12058                         G_CALLBACK (adjust_act_blocks), pdata);
12059       gtk_box_pack_start (GTK_BOX (hbox), pdata->act_blocks_spin, FALSE, TRUE,
12060                           0);
12061       gtk_widget_set_sensitive (pdata->act_blocks_spin, FALSE);
12062
12063       button = gtk_button_new_with_label ("close");
12064       g_signal_connect_swapped (button, "clicked",
12065                                 G_CALLBACK (gtk_widget_destroy),
12066                                 pdata->window);
12067       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12068       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
12069                           button, TRUE, TRUE, 0);
12070       gtk_widget_grab_default (button);
12071     }
12072
12073   if (!GTK_WIDGET_VISIBLE (pdata->window))
12074     gtk_widget_show_all (pdata->window);
12075   else
12076     gtk_widget_destroy (pdata->window);
12077 }
12078
12079 /*
12080  * Properties
12081  */
12082
12083 typedef struct {
12084   int x;
12085   int y;
12086   gboolean found;
12087   gboolean first;
12088   GtkWidget *res_widget;
12089 } FindWidgetData;
12090
12091 static void
12092 find_widget (GtkWidget *widget, FindWidgetData *data)
12093 {
12094   GtkAllocation new_allocation;
12095   gint x_offset = 0;
12096   gint y_offset = 0;
12097
12098   new_allocation = widget->allocation;
12099
12100   if (data->found || !GTK_WIDGET_MAPPED (widget))
12101     return;
12102
12103   /* Note that in the following code, we only count the
12104    * position as being inside a WINDOW widget if it is inside
12105    * widget->window; points that are outside of widget->window
12106    * but within the allocation are not counted. This is consistent
12107    * with the way we highlight drag targets.
12108    */
12109   if (!GTK_WIDGET_NO_WINDOW (widget))
12110     {
12111       new_allocation.x = 0;
12112       new_allocation.y = 0;
12113     }
12114   
12115   if (widget->parent && !data->first)
12116     {
12117       GdkWindow *window = widget->window;
12118       while (window != widget->parent->window)
12119         {
12120           gint tx, ty, twidth, theight;
12121           gdk_drawable_get_size (window, &twidth, &theight);
12122
12123           if (new_allocation.x < 0)
12124             {
12125               new_allocation.width += new_allocation.x;
12126               new_allocation.x = 0;
12127             }
12128           if (new_allocation.y < 0)
12129             {
12130               new_allocation.height += new_allocation.y;
12131               new_allocation.y = 0;
12132             }
12133           if (new_allocation.x + new_allocation.width > twidth)
12134             new_allocation.width = twidth - new_allocation.x;
12135           if (new_allocation.y + new_allocation.height > theight)
12136             new_allocation.height = theight - new_allocation.y;
12137
12138           gdk_window_get_position (window, &tx, &ty);
12139           new_allocation.x += tx;
12140           x_offset += tx;
12141           new_allocation.y += ty;
12142           y_offset += ty;
12143           
12144           window = gdk_window_get_parent (window);
12145         }
12146     }
12147
12148   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
12149       (data->x < new_allocation.x + new_allocation.width) && 
12150       (data->y < new_allocation.y + new_allocation.height))
12151     {
12152       /* First, check if the drag is in a valid drop site in
12153        * one of our children 
12154        */
12155       if (GTK_IS_CONTAINER (widget))
12156         {
12157           FindWidgetData new_data = *data;
12158           
12159           new_data.x -= x_offset;
12160           new_data.y -= y_offset;
12161           new_data.found = FALSE;
12162           new_data.first = FALSE;
12163           
12164           gtk_container_forall (GTK_CONTAINER (widget),
12165                                 (GtkCallback)find_widget,
12166                                 &new_data);
12167           
12168           data->found = new_data.found;
12169           if (data->found)
12170             data->res_widget = new_data.res_widget;
12171         }
12172
12173       /* If not, and this widget is registered as a drop site, check to
12174        * emit "drag_motion" to check if we are actually in
12175        * a drop site.
12176        */
12177       if (!data->found)
12178         {
12179           data->found = TRUE;
12180           data->res_widget = widget;
12181         }
12182     }
12183 }
12184
12185 static GtkWidget *
12186 find_widget_at_pointer (GdkDisplay *display)
12187 {
12188   GtkWidget *widget = NULL;
12189   GdkWindow *pointer_window;
12190   gint x, y;
12191   FindWidgetData data;
12192  
12193  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
12194  
12195  if (pointer_window)
12196    {
12197      gpointer widget_ptr;
12198
12199      gdk_window_get_user_data (pointer_window, &widget_ptr);
12200      widget = widget_ptr;
12201    }
12202
12203  if (widget)
12204    {
12205      gdk_window_get_pointer (widget->window,
12206                              &x, &y, NULL);
12207      
12208      data.x = x;
12209      data.y = y;
12210      data.found = FALSE;
12211      data.first = TRUE;
12212
12213      find_widget (widget, &data);
12214      if (data.found)
12215        return data.res_widget;
12216      return widget;
12217    }
12218  return NULL;
12219 }
12220
12221 struct PropertiesData {
12222   GtkWidget **window;
12223   GdkCursor *cursor;
12224   gboolean in_query;
12225   gint handler;
12226 };
12227
12228 static void
12229 destroy_properties (GtkWidget             *widget,
12230                     struct PropertiesData *data)
12231 {
12232   if (data->window)
12233     {
12234       *data->window = NULL;
12235       data->window = NULL;
12236     }
12237
12238   if (data->cursor)
12239     {
12240       gdk_cursor_unref (data->cursor);
12241       data->cursor = NULL;
12242     }
12243
12244   if (data->handler)
12245     {
12246       g_signal_handler_disconnect (widget, data->handler);
12247       data->handler = 0;
12248     }
12249
12250   g_free (data);
12251 }
12252
12253 static gint
12254 property_query_event (GtkWidget        *widget,
12255                       GdkEvent         *event,
12256                       struct PropertiesData *data)
12257 {
12258   GtkWidget *res_widget = NULL;
12259
12260   if (!data->in_query)
12261     return FALSE;
12262   
12263   if (event->type == GDK_BUTTON_RELEASE)
12264     {
12265       gtk_grab_remove (widget);
12266       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12267                                   GDK_CURRENT_TIME);
12268       
12269       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12270       if (res_widget)
12271         {
12272           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
12273                              gtk_widget_get_screen (widget));
12274           create_prop_editor (G_OBJECT (res_widget), 0);
12275         }
12276
12277       data->in_query = FALSE;
12278     }
12279   return FALSE;
12280 }
12281
12282
12283 static void
12284 query_properties (GtkButton *button,
12285                   struct PropertiesData *data)
12286 {
12287   gint failure;
12288
12289   g_signal_connect (button, "event",
12290                     G_CALLBACK (property_query_event), data);
12291
12292
12293   if (!data->cursor)
12294     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12295                                                GDK_TARGET);
12296   
12297   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12298                               TRUE,
12299                               GDK_BUTTON_RELEASE_MASK,
12300                               NULL,
12301                               data->cursor,
12302                               GDK_CURRENT_TIME);
12303
12304   gtk_grab_add (GTK_WIDGET (button));
12305
12306   data->in_query = TRUE;
12307 }
12308
12309 static void
12310 create_properties (GtkWidget *widget)
12311 {
12312   static GtkWidget *window = NULL;
12313   GtkWidget *button;
12314   GtkWidget *vbox;
12315   GtkWidget *label;
12316   struct PropertiesData *data;
12317
12318   data = g_new (struct PropertiesData, 1);
12319   data->window = &window;
12320   data->in_query = FALSE;
12321   data->cursor = NULL;
12322   data->handler = 0;
12323
12324   if (!window)
12325     {
12326       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12327
12328       gtk_window_set_screen (GTK_WINDOW (window),
12329                              gtk_widget_get_screen (widget));      
12330
12331       data->handler = g_signal_connect (window, "destroy",
12332                                         G_CALLBACK (destroy_properties),
12333                                         data);
12334
12335       gtk_window_set_title (GTK_WINDOW (window), "test properties");
12336       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12337
12338       vbox = gtk_vbox_new (FALSE, 1);
12339       gtk_container_add (GTK_CONTAINER (window), vbox);
12340             
12341       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
12342       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
12343       
12344       button = gtk_button_new_with_label ("Query properties");
12345       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12346       g_signal_connect (button, "clicked",
12347                         G_CALLBACK (query_properties),
12348                         data);
12349     }
12350
12351   if (!GTK_WIDGET_VISIBLE (window))
12352     gtk_widget_show_all (window);
12353   else
12354     gtk_widget_destroy (window);
12355   
12356 }
12357
12358 struct SnapshotData {
12359   GtkWidget *toplevel_button;
12360   GtkWidget **window;
12361   GdkCursor *cursor;
12362   gboolean in_query;
12363   gboolean is_toplevel;
12364   gint handler;
12365 };
12366
12367 static void
12368 destroy_snapshot_data (GtkWidget             *widget,
12369                        struct SnapshotData *data)
12370 {
12371   if (*data->window)
12372     *data->window = NULL;
12373   
12374   if (data->cursor)
12375     {
12376       gdk_cursor_unref (data->cursor);
12377       data->cursor = NULL;
12378     }
12379
12380   if (data->handler)
12381     {
12382       g_signal_handler_disconnect (widget, data->handler);
12383       data->handler = 0;
12384     }
12385
12386   g_free (data);
12387 }
12388
12389 static gint
12390 snapshot_widget_event (GtkWidget               *widget,
12391                        GdkEvent        *event,
12392                        struct SnapshotData *data)
12393 {
12394   GtkWidget *res_widget = NULL;
12395
12396   if (!data->in_query)
12397     return FALSE;
12398   
12399   if (event->type == GDK_BUTTON_RELEASE)
12400     {
12401       gtk_grab_remove (widget);
12402       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12403                                   GDK_CURRENT_TIME);
12404       
12405       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12406       if (data->is_toplevel && res_widget)
12407         res_widget = gtk_widget_get_toplevel (res_widget);
12408       if (res_widget)
12409         {
12410           GdkPixmap *pixmap;
12411           GtkWidget *window, *image;
12412
12413           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12414           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
12415           gtk_widget_realize (window);
12416           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
12417             {
12418               /* this branch is needed to convert ARGB -> RGB */
12419               int width, height;
12420               GdkPixbuf *pixbuf;
12421               gdk_drawable_get_size (pixmap, &width, &height);
12422               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
12423                                                      gtk_widget_get_colormap (res_widget),
12424                                                      0, 0,
12425                                                      0, 0,
12426                                                      width, height);
12427               image = gtk_image_new_from_pixbuf (pixbuf);
12428               g_object_unref (pixbuf);
12429             }
12430           else
12431             image = gtk_image_new_from_pixmap (pixmap, NULL);
12432           gtk_container_add (GTK_CONTAINER (window), image);
12433           g_object_unref (pixmap);
12434           gtk_widget_show_all (window);
12435         }
12436
12437       data->in_query = FALSE;
12438     }
12439   return FALSE;
12440 }
12441
12442
12443 static void
12444 snapshot_widget (GtkButton *button,
12445                  struct SnapshotData *data)
12446 {
12447   gint failure;
12448
12449   g_signal_connect (button, "event",
12450                     G_CALLBACK (snapshot_widget_event), data);
12451
12452   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
12453   
12454   if (!data->cursor)
12455     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12456                                                GDK_TARGET);
12457   
12458   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12459                               TRUE,
12460                               GDK_BUTTON_RELEASE_MASK,
12461                               NULL,
12462                               data->cursor,
12463                               GDK_CURRENT_TIME);
12464
12465   gtk_grab_add (GTK_WIDGET (button));
12466
12467   data->in_query = TRUE;
12468 }
12469
12470 static void
12471 create_snapshot (GtkWidget *widget)
12472 {
12473   static GtkWidget *window = NULL;
12474   GtkWidget *button;
12475   GtkWidget *vbox;
12476   struct SnapshotData *data;
12477
12478   data = g_new (struct SnapshotData, 1);
12479   data->window = &window;
12480   data->in_query = FALSE;
12481   data->cursor = NULL;
12482   data->handler = 0;
12483
12484   if (!window)
12485     {
12486       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12487
12488       gtk_window_set_screen (GTK_WINDOW (window),
12489                              gtk_widget_get_screen (widget));      
12490
12491       data->handler = g_signal_connect (window, "destroy",
12492                                         G_CALLBACK (destroy_snapshot_data),
12493                                         data);
12494
12495       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
12496       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12497
12498       vbox = gtk_vbox_new (FALSE, 1);
12499       gtk_container_add (GTK_CONTAINER (window), vbox);
12500             
12501       button = gtk_button_new_with_label ("Snapshot widget");
12502       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12503       g_signal_connect (button, "clicked",
12504                         G_CALLBACK (snapshot_widget),
12505                         data);
12506       
12507       button = gtk_button_new_with_label ("Snapshot toplevel");
12508       data->toplevel_button = button;
12509       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12510       g_signal_connect (button, "clicked",
12511                         G_CALLBACK (snapshot_widget),
12512                         data);
12513     }
12514
12515   if (!GTK_WIDGET_VISIBLE (window))
12516     gtk_widget_show_all (window);
12517   else
12518     gtk_widget_destroy (window);
12519   
12520 }
12521
12522
12523
12524 /*
12525  * Color Preview
12526  */
12527
12528 static int color_idle = 0;
12529
12530 gint
12531 color_idle_func (GtkWidget *preview)
12532 {
12533   static int count = 1;
12534   guchar buf[768];
12535   int i, j, k;
12536
12537   for (i = 0; i < 256; i++)
12538     {
12539       for (j = 0, k = 0; j < 256; j++)
12540         {
12541           buf[k+0] = i + count;
12542           buf[k+1] = 0;
12543           buf[k+2] = j + count;
12544           k += 3;
12545         }
12546
12547       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12548     }
12549
12550   count += 1;
12551
12552   gtk_widget_queue_draw (preview);
12553   gdk_window_process_updates (preview->window, TRUE);
12554
12555   return TRUE;
12556 }
12557
12558 static void
12559 color_preview_destroy (GtkWidget  *widget,
12560                        GtkWidget **window)
12561 {
12562   gtk_idle_remove (color_idle);
12563   color_idle = 0;
12564
12565   *window = NULL;
12566 }
12567
12568 void
12569 create_color_preview (GtkWidget *widget)
12570 {
12571   static GtkWidget *window = NULL;
12572   GtkWidget *preview;
12573   guchar buf[768];
12574   int i, j, k;
12575
12576   if (!window)
12577     {
12578       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12579       
12580       gtk_window_set_screen (GTK_WINDOW (window),
12581                              gtk_widget_get_screen (widget));
12582
12583       g_signal_connect (window, "destroy",
12584                         G_CALLBACK (color_preview_destroy),
12585                         &window);
12586
12587       gtk_window_set_title (GTK_WINDOW (window), "test");
12588       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12589
12590       preview = gtk_preview_new (GTK_PREVIEW_COLOR);
12591       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12592       gtk_container_add (GTK_CONTAINER (window), preview);
12593
12594       for (i = 0; i < 256; i++)
12595         {
12596           for (j = 0, k = 0; j < 256; j++)
12597             {
12598               buf[k+0] = i;
12599               buf[k+1] = 0;
12600               buf[k+2] = j;
12601               k += 3;
12602             }
12603
12604           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12605         }
12606
12607       color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
12608     }
12609
12610   if (!GTK_WIDGET_VISIBLE (window))
12611     gtk_widget_show_all (window);
12612   else
12613     gtk_widget_destroy (window);
12614 }
12615
12616 /*
12617  * Gray Preview
12618  */
12619
12620 static int gray_idle = 0;
12621
12622 gint
12623 gray_idle_func (GtkWidget *preview)
12624 {
12625   static int count = 1;
12626   guchar buf[256];
12627   int i, j;
12628
12629   for (i = 0; i < 256; i++)
12630     {
12631       for (j = 0; j < 256; j++)
12632         buf[j] = i + j + count;
12633
12634       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12635     }
12636
12637   count += 1;
12638
12639   gtk_widget_draw (preview, NULL);
12640
12641   return TRUE;
12642 }
12643
12644 static void
12645 gray_preview_destroy (GtkWidget  *widget,
12646                       GtkWidget **window)
12647 {
12648   gtk_idle_remove (gray_idle);
12649   gray_idle = 0;
12650
12651   *window = NULL;
12652 }
12653
12654 void
12655 create_gray_preview (GtkWidget *widget)
12656 {
12657   static GtkWidget *window = NULL;
12658   GtkWidget *preview;
12659   guchar buf[256];
12660   int i, j;
12661
12662   if (!window)
12663     {
12664       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12665
12666       gtk_window_set_screen (GTK_WINDOW (window),
12667                              gtk_widget_get_screen (widget));
12668
12669       g_signal_connect (window, "destroy",
12670                         G_CALLBACK (gray_preview_destroy),
12671                         &window);
12672
12673       gtk_window_set_title (GTK_WINDOW (window), "test");
12674       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12675
12676       preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
12677       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12678       gtk_container_add (GTK_CONTAINER (window), preview);
12679
12680       for (i = 0; i < 256; i++)
12681         {
12682           for (j = 0; j < 256; j++)
12683             buf[j] = i + j;
12684
12685           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12686         }
12687
12688       gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
12689     }
12690
12691   if (!GTK_WIDGET_VISIBLE (window))
12692     gtk_widget_show_all (window);
12693   else
12694     gtk_widget_destroy (window);
12695 }
12696
12697
12698 /*
12699  * Selection Test
12700  */
12701
12702 void
12703 selection_test_received (GtkWidget *list, GtkSelectionData *data)
12704 {
12705   GdkAtom *atoms;
12706   GtkWidget *list_item;
12707   GList *item_list;
12708   int i, l;
12709
12710   if (data->length < 0)
12711     {
12712       g_print ("Selection retrieval failed\n");
12713       return;
12714     }
12715   if (data->type != GDK_SELECTION_TYPE_ATOM)
12716     {
12717       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
12718       return;
12719     }
12720
12721   /* Clear out any current list items */
12722
12723   gtk_list_clear_items (GTK_LIST(list), 0, -1);
12724
12725   /* Add new items to list */
12726
12727   atoms = (GdkAtom *)data->data;
12728
12729   item_list = NULL;
12730   l = data->length / sizeof (GdkAtom);
12731   for (i = 0; i < l; i++)
12732     {
12733       char *name;
12734       name = gdk_atom_name (atoms[i]);
12735       if (name != NULL)
12736         {
12737           list_item = gtk_list_item_new_with_label (name);
12738           g_free (name);
12739         }
12740       else
12741         list_item = gtk_list_item_new_with_label ("(bad atom)");
12742
12743       gtk_widget_show (list_item);
12744       item_list = g_list_append (item_list, list_item);
12745     }
12746
12747   gtk_list_append_items (GTK_LIST (list), item_list);
12748
12749   return;
12750 }
12751
12752 void
12753 selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
12754 {
12755   static GdkAtom targets_atom = GDK_NONE;
12756
12757   if (targets_atom == GDK_NONE)
12758     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
12759
12760   gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
12761                          GDK_CURRENT_TIME);
12762 }
12763
12764 void
12765 create_selection_test (GtkWidget *widget)
12766 {
12767   static GtkWidget *window = NULL;
12768   GtkWidget *button;
12769   GtkWidget *vbox;
12770   GtkWidget *scrolled_win;
12771   GtkWidget *list;
12772   GtkWidget *label;
12773
12774   if (!window)
12775     {
12776       window = gtk_dialog_new ();
12777       
12778       gtk_window_set_screen (GTK_WINDOW (window),
12779                              gtk_widget_get_screen (widget));
12780
12781       g_signal_connect (window, "destroy",
12782                         G_CALLBACK (gtk_widget_destroyed),
12783                         &window);
12784
12785       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
12786       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12787
12788       /* Create the list */
12789
12790       vbox = gtk_vbox_new (FALSE, 5);
12791       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
12792       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
12793                           TRUE, TRUE, 0);
12794
12795       label = gtk_label_new ("Gets available targets for current selection");
12796       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12797
12798       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
12799       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
12800                                       GTK_POLICY_AUTOMATIC, 
12801                                       GTK_POLICY_AUTOMATIC);
12802       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
12803       gtk_widget_set_size_request (scrolled_win, 100, 200);
12804
12805       list = gtk_list_new ();
12806       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
12807
12808       g_signal_connect (list, "selection_received",
12809                         G_CALLBACK (selection_test_received), NULL);
12810
12811       /* .. And create some buttons */
12812       button = gtk_button_new_with_label ("Get Targets");
12813       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12814                           button, TRUE, TRUE, 0);
12815
12816       g_signal_connect (button, "clicked",
12817                         G_CALLBACK (selection_test_get_targets), list);
12818
12819       button = gtk_button_new_with_label ("Quit");
12820       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12821                           button, TRUE, TRUE, 0);
12822
12823       g_signal_connect_swapped (button, "clicked",
12824                                 G_CALLBACK (gtk_widget_destroy),
12825                                 window);
12826     }
12827
12828   if (!GTK_WIDGET_VISIBLE (window))
12829     gtk_widget_show_all (window);
12830   else
12831     gtk_widget_destroy (window);
12832 }
12833
12834 /*
12835  * Gamma Curve
12836  */
12837
12838 void
12839 create_gamma_curve (GtkWidget *widget)
12840 {
12841   static GtkWidget *window = NULL, *curve;
12842   static int count = 0;
12843   gfloat vec[256];
12844   gint max;
12845   gint i;
12846   
12847   if (!window)
12848     {
12849       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12850       gtk_window_set_screen (GTK_WINDOW (window),
12851                              gtk_widget_get_screen (widget));
12852
12853       gtk_window_set_title (GTK_WINDOW (window), "test");
12854       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12855
12856       g_signal_connect (window, "destroy",
12857                         G_CALLBACK(gtk_widget_destroyed),
12858                         &window);
12859
12860       curve = gtk_gamma_curve_new ();
12861       gtk_container_add (GTK_CONTAINER (window), curve);
12862       gtk_widget_show (curve);
12863     }
12864
12865   max = 127 + (count % 2)*128;
12866   gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12867                        0, max, 0, max);
12868   for (i = 0; i < max; ++i)
12869     vec[i] = (127 / sqrt (max)) * sqrt (i);
12870   gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12871                         max, vec);
12872
12873   if (!GTK_WIDGET_VISIBLE (window))
12874     gtk_widget_show (window);
12875   else if (count % 4 == 3)
12876     {
12877       gtk_widget_destroy (window);
12878       window = NULL;
12879     }
12880
12881   ++count;
12882 }
12883
12884 /*
12885  * Test scrolling
12886  */
12887
12888 static int scroll_test_pos = 0.0;
12889
12890 static gint
12891 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
12892                     GtkAdjustment *adj)
12893 {
12894   gint i,j;
12895   gint imin, imax, jmin, jmax;
12896   
12897   imin = (event->area.x) / 10;
12898   imax = (event->area.x + event->area.width + 9) / 10;
12899
12900   jmin = ((int)adj->value + event->area.y) / 10;
12901   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
12902
12903   gdk_window_clear_area (widget->window,
12904                          event->area.x, event->area.y,
12905                          event->area.width, event->area.height);
12906
12907   for (i=imin; i<imax; i++)
12908     for (j=jmin; j<jmax; j++)
12909       if ((i+j) % 2)
12910         gdk_draw_rectangle (widget->window, 
12911                             widget->style->black_gc,
12912                             TRUE,
12913                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
12914
12915   return TRUE;
12916 }
12917
12918 static gint
12919 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
12920                     GtkAdjustment *adj)
12921 {
12922   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
12923                                     -adj->page_increment / 2:
12924                                     adj->page_increment / 2);
12925   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
12926   gtk_adjustment_set_value (adj, new_value);  
12927   
12928   return TRUE;
12929 }
12930
12931 static void
12932 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
12933                        GtkAdjustment *adj)
12934 {
12935   adj->page_increment = 0.9 * widget->allocation.height;
12936   adj->page_size = widget->allocation.height;
12937
12938   g_signal_emit_by_name (adj, "changed");
12939 }
12940
12941 static void
12942 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
12943 {
12944   /* gint source_min = (int)adj->value - scroll_test_pos; */
12945   gint dy;
12946
12947   dy = scroll_test_pos - (int)adj->value;
12948   scroll_test_pos = adj->value;
12949
12950   if (!GTK_WIDGET_DRAWABLE (widget))
12951     return;
12952   gdk_window_scroll (widget->window, 0, dy);
12953   gdk_window_process_updates (widget->window, FALSE);
12954 }
12955
12956
12957 void
12958 create_scroll_test (GtkWidget *widget)
12959 {
12960   static GtkWidget *window = NULL;
12961   GtkWidget *hbox;
12962   GtkWidget *drawing_area;
12963   GtkWidget *scrollbar;
12964   GtkWidget *button;
12965   GtkAdjustment *adj;
12966   GdkGeometry geometry;
12967   GdkWindowHints geometry_mask;
12968
12969   if (!window)
12970     {
12971       window = gtk_dialog_new ();
12972
12973       gtk_window_set_screen (GTK_WINDOW (window),
12974                              gtk_widget_get_screen (widget));
12975
12976       g_signal_connect (window, "destroy",
12977                         G_CALLBACK (gtk_widget_destroyed),
12978                         &window);
12979
12980       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
12981       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12982
12983       hbox = gtk_hbox_new (FALSE, 0);
12984       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
12985                           TRUE, TRUE, 0);
12986       gtk_widget_show (hbox);
12987
12988       drawing_area = gtk_drawing_area_new ();
12989       gtk_widget_set_size_request (drawing_area, 200, 200);
12990       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
12991       gtk_widget_show (drawing_area);
12992
12993       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
12994
12995       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
12996       scroll_test_pos = 0.0;
12997
12998       scrollbar = gtk_vscrollbar_new (adj);
12999       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
13000       gtk_widget_show (scrollbar);
13001
13002       g_signal_connect (drawing_area, "expose_event",
13003                         G_CALLBACK (scroll_test_expose), adj);
13004       g_signal_connect (drawing_area, "configure_event",
13005                         G_CALLBACK (scroll_test_configure), adj);
13006       g_signal_connect (drawing_area, "scroll_event",
13007                         G_CALLBACK (scroll_test_scroll), adj);
13008       
13009       g_signal_connect (adj, "value_changed",
13010                         G_CALLBACK (scroll_test_adjustment_changed),
13011                         drawing_area);
13012       
13013       /* .. And create some buttons */
13014
13015       button = gtk_button_new_with_label ("Quit");
13016       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
13017                           button, TRUE, TRUE, 0);
13018
13019       g_signal_connect_swapped (button, "clicked",
13020                                 G_CALLBACK (gtk_widget_destroy),
13021                                 window);
13022       gtk_widget_show (button);
13023
13024       /* Set up gridded geometry */
13025
13026       geometry_mask = GDK_HINT_MIN_SIZE | 
13027                        GDK_HINT_BASE_SIZE | 
13028                        GDK_HINT_RESIZE_INC;
13029
13030       geometry.min_width = 20;
13031       geometry.min_height = 20;
13032       geometry.base_width = 0;
13033       geometry.base_height = 0;
13034       geometry.width_inc = 10;
13035       geometry.height_inc = 10;
13036       
13037       gtk_window_set_geometry_hints (GTK_WINDOW (window),
13038                                drawing_area, &geometry, geometry_mask);
13039     }
13040
13041   if (!GTK_WIDGET_VISIBLE (window))
13042     gtk_widget_show (window);
13043   else
13044     gtk_widget_destroy (window);
13045 }
13046
13047 /*
13048  * Timeout Test
13049  */
13050
13051 static int timer = 0;
13052
13053 gint
13054 timeout_test (GtkWidget *label)
13055 {
13056   static int count = 0;
13057   static char buffer[32];
13058
13059   sprintf (buffer, "count: %d", ++count);
13060   gtk_label_set_text (GTK_LABEL (label), buffer);
13061
13062   return TRUE;
13063 }
13064
13065 void
13066 start_timeout_test (GtkWidget *widget,
13067                     GtkWidget *label)
13068 {
13069   if (!timer)
13070     {
13071       timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
13072     }
13073 }
13074
13075 void
13076 stop_timeout_test (GtkWidget *widget,
13077                    gpointer   data)
13078 {
13079   if (timer)
13080     {
13081       gtk_timeout_remove (timer);
13082       timer = 0;
13083     }
13084 }
13085
13086 void
13087 destroy_timeout_test (GtkWidget  *widget,
13088                       GtkWidget **window)
13089 {
13090   stop_timeout_test (NULL, NULL);
13091
13092   *window = NULL;
13093 }
13094
13095 void
13096 create_timeout_test (GtkWidget *widget)
13097 {
13098   static GtkWidget *window = NULL;
13099   GtkWidget *button;
13100   GtkWidget *label;
13101
13102   if (!window)
13103     {
13104       window = gtk_dialog_new ();
13105
13106       gtk_window_set_screen (GTK_WINDOW (window),
13107                              gtk_widget_get_screen (widget));
13108
13109       g_signal_connect (window, "destroy",
13110                         G_CALLBACK (destroy_timeout_test),
13111                         &window);
13112
13113       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
13114       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13115
13116       label = gtk_label_new ("count: 0");
13117       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13118       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13119                           label, TRUE, TRUE, 0);
13120       gtk_widget_show (label);
13121
13122       button = gtk_button_new_with_label ("close");
13123       g_signal_connect_swapped (button, "clicked",
13124                                 G_CALLBACK (gtk_widget_destroy),
13125                                 window);
13126       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13127       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13128                           button, TRUE, TRUE, 0);
13129       gtk_widget_grab_default (button);
13130       gtk_widget_show (button);
13131
13132       button = gtk_button_new_with_label ("start");
13133       g_signal_connect (button, "clicked",
13134                         G_CALLBACK(start_timeout_test),
13135                         label);
13136       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13137       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13138                           button, TRUE, TRUE, 0);
13139       gtk_widget_show (button);
13140
13141       button = gtk_button_new_with_label ("stop");
13142       g_signal_connect (button, "clicked",
13143                         G_CALLBACK (stop_timeout_test),
13144                         NULL);
13145       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13146       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13147                           button, TRUE, TRUE, 0);
13148       gtk_widget_show (button);
13149     }
13150
13151   if (!GTK_WIDGET_VISIBLE (window))
13152     gtk_widget_show (window);
13153   else
13154     gtk_widget_destroy (window);
13155 }
13156
13157 /*
13158  * Idle Test
13159  */
13160
13161 static int idle_id = 0;
13162
13163 static gint
13164 idle_test (GtkWidget *label)
13165 {
13166   static int count = 0;
13167   static char buffer[32];
13168
13169   sprintf (buffer, "count: %d", ++count);
13170   gtk_label_set_text (GTK_LABEL (label), buffer);
13171
13172   return TRUE;
13173 }
13174
13175 static void
13176 start_idle_test (GtkWidget *widget,
13177                  GtkWidget *label)
13178 {
13179   if (!idle_id)
13180     {
13181       idle_id = gtk_idle_add ((GtkFunction) idle_test, label);
13182     }
13183 }
13184
13185 static void
13186 stop_idle_test (GtkWidget *widget,
13187                 gpointer   data)
13188 {
13189   if (idle_id)
13190     {
13191       gtk_idle_remove (idle_id);
13192       idle_id = 0;
13193     }
13194 }
13195
13196 static void
13197 destroy_idle_test (GtkWidget  *widget,
13198                    GtkWidget **window)
13199 {
13200   stop_idle_test (NULL, NULL);
13201
13202   *window = NULL;
13203 }
13204
13205 static void
13206 toggle_idle_container (GObject *button,
13207                        GtkContainer *container)
13208 {
13209   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
13210 }
13211
13212 static void
13213 create_idle_test (GtkWidget *widget)
13214 {
13215   static GtkWidget *window = NULL;
13216   GtkWidget *button;
13217   GtkWidget *label;
13218   GtkWidget *container;
13219
13220   if (!window)
13221     {
13222       GtkWidget *button2;
13223       GtkWidget *frame;
13224       GtkWidget *box;
13225
13226       window = gtk_dialog_new ();
13227
13228       gtk_window_set_screen (GTK_WINDOW (window),
13229                              gtk_widget_get_screen (widget));
13230
13231       g_signal_connect (window, "destroy",
13232                         G_CALLBACK (destroy_idle_test),
13233                         &window);
13234
13235       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
13236       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13237
13238       label = gtk_label_new ("count: 0");
13239       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13240       gtk_widget_show (label);
13241       
13242       container =
13243         g_object_new (GTK_TYPE_HBOX,
13244                         "visible", TRUE,
13245                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
13246                          * "GtkWidget::visible", TRUE,
13247                          */
13248                          "child", label,
13249                         /* NULL), */
13250                         NULL);
13251       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13252                           container, TRUE, TRUE, 0);
13253
13254       frame =
13255         g_object_new (GTK_TYPE_FRAME,
13256                         "border_width", 5,
13257                         "label", "Label Container",
13258                         "visible", TRUE,
13259                         "parent", GTK_DIALOG (window)->vbox,
13260                         NULL);
13261       box =
13262         g_object_new (GTK_TYPE_VBOX,
13263                         "visible", TRUE,
13264                         "parent", frame,
13265                         NULL);
13266       button =
13267         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
13268                                           "label", "Resize-Parent",
13269                                           "user_data", (void*)GTK_RESIZE_PARENT,
13270                                           "visible", TRUE,
13271                                           "parent", box,
13272                                           NULL),
13273                           "signal::clicked", toggle_idle_container, container,
13274                           NULL);
13275       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
13276                                "label", "Resize-Queue",
13277                                "user_data", (void*)GTK_RESIZE_QUEUE,
13278                                "group", button,
13279                                "visible", TRUE,
13280                                "parent", box,
13281                                NULL);
13282       g_object_connect (button,
13283                         "signal::clicked", toggle_idle_container, container,
13284                         NULL);
13285       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
13286                                 "label", "Resize-Immediate",
13287                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
13288                                 NULL);
13289       g_object_connect (button2,
13290                         "signal::clicked", toggle_idle_container, container,
13291                         NULL);
13292       g_object_set (button2,
13293                     "group", button,
13294                     "visible", TRUE,
13295                     "parent", box,
13296                     NULL);
13297
13298       button = gtk_button_new_with_label ("close");
13299       g_signal_connect_swapped (button, "clicked",
13300                                 G_CALLBACK (gtk_widget_destroy),
13301                                 window);
13302       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13303       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13304                           button, TRUE, TRUE, 0);
13305       gtk_widget_grab_default (button);
13306       gtk_widget_show (button);
13307
13308       button = gtk_button_new_with_label ("start");
13309       g_signal_connect (button, "clicked",
13310                         G_CALLBACK (start_idle_test),
13311                         label);
13312       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13313       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13314                           button, TRUE, TRUE, 0);
13315       gtk_widget_show (button);
13316
13317       button = gtk_button_new_with_label ("stop");
13318       g_signal_connect (button, "clicked",
13319                         G_CALLBACK (stop_idle_test),
13320                         NULL);
13321       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13322       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13323                           button, TRUE, TRUE, 0);
13324       gtk_widget_show (button);
13325     }
13326
13327   if (!GTK_WIDGET_VISIBLE (window))
13328     gtk_widget_show (window);
13329   else
13330     gtk_widget_destroy (window);
13331 }
13332
13333 /*
13334  * rc file test
13335  */
13336
13337 void
13338 reload_all_rc_files (void)
13339 {
13340   static GdkAtom atom_rcfiles = GDK_NONE;
13341
13342   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
13343   int i;
13344   
13345   if (!atom_rcfiles)
13346     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
13347
13348   for(i = 0; i < 5; i++)
13349     send_event->client.data.l[i] = 0;
13350   send_event->client.data_format = 32;
13351   send_event->client.message_type = atom_rcfiles;
13352   gdk_event_send_clientmessage_toall (send_event);
13353
13354   gdk_event_free (send_event);
13355 }
13356
13357 void
13358 create_rc_file (GtkWidget *widget)
13359 {
13360   static GtkWidget *window = NULL;
13361   GtkWidget *button;
13362   GtkWidget *frame;
13363   GtkWidget *vbox;
13364   GtkWidget *label;
13365
13366   if (!window)
13367     {
13368       window = gtk_dialog_new ();
13369
13370       gtk_window_set_screen (GTK_WINDOW (window),
13371                              gtk_widget_get_screen (widget));
13372
13373       g_signal_connect (window, "destroy",
13374                         G_CALLBACK (gtk_widget_destroyed),
13375                         &window);
13376
13377       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
13378       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
13379
13380       vbox = gtk_vbox_new (FALSE, 0);
13381       gtk_container_add (GTK_CONTAINER (frame), vbox);
13382       
13383       label = gtk_label_new ("This label should be red");
13384       gtk_widget_set_name (label, "testgtk-red-label");
13385       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13386
13387       label = gtk_label_new ("This label should be green");
13388       gtk_widget_set_name (label, "testgtk-green-label");
13389       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13390
13391       label = gtk_label_new ("This label should be blue");
13392       gtk_widget_set_name (label, "testgtk-blue-label");
13393       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13394
13395       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
13396       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13397
13398       button = gtk_button_new_with_label ("Reload");
13399       g_signal_connect (button, "clicked",
13400                         G_CALLBACK (gtk_rc_reparse_all), NULL);
13401       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13402       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13403                           button, TRUE, TRUE, 0);
13404       gtk_widget_grab_default (button);
13405
13406       button = gtk_button_new_with_label ("Reload All");
13407       g_signal_connect (button, "clicked",
13408                         G_CALLBACK (reload_all_rc_files), NULL);
13409       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13410       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13411                           button, TRUE, TRUE, 0);
13412
13413       button = gtk_button_new_with_label ("Close");
13414       g_signal_connect_swapped (button, "clicked",
13415                                 G_CALLBACK (gtk_widget_destroy),
13416                                 window);
13417       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13418       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13419                           button, TRUE, TRUE, 0);
13420     }
13421
13422   if (!GTK_WIDGET_VISIBLE (window))
13423     gtk_widget_show_all (window);
13424   else
13425     gtk_widget_destroy (window);
13426 }
13427
13428 /*
13429  * Test of recursive mainloop
13430  */
13431
13432 void
13433 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
13434 {
13435   *window = NULL;
13436   gtk_main_quit ();
13437 }
13438
13439 void
13440 create_mainloop (GtkWidget *widget)
13441 {
13442   static GtkWidget *window = NULL;
13443   GtkWidget *label;
13444   GtkWidget *button;
13445
13446   if (!window)
13447     {
13448       window = gtk_dialog_new ();
13449
13450       gtk_window_set_screen (GTK_WINDOW (window),
13451                              gtk_widget_get_screen (widget));
13452
13453       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
13454
13455       g_signal_connect (window, "destroy",
13456                         G_CALLBACK (mainloop_destroyed),
13457                         &window);
13458
13459       label = gtk_label_new ("In recursive main loop...");
13460       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
13461
13462       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
13463                           TRUE, TRUE, 0);
13464       gtk_widget_show (label);
13465
13466       button = gtk_button_new_with_label ("Leave");
13467       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
13468                           FALSE, TRUE, 0);
13469
13470       g_signal_connect_swapped (button, "clicked",
13471                                 G_CALLBACK (gtk_widget_destroy),
13472                                 window);
13473
13474       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13475       gtk_widget_grab_default (button);
13476
13477       gtk_widget_show (button);
13478     }
13479
13480   if (!GTK_WIDGET_VISIBLE (window))
13481     {
13482       gtk_widget_show (window);
13483
13484       g_print ("create_mainloop: start\n");
13485       gtk_main ();
13486       g_print ("create_mainloop: done\n");
13487     }
13488   else
13489     gtk_widget_destroy (window);
13490 }
13491
13492 gboolean
13493 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
13494 {
13495   GtkLayout *layout;
13496
13497   gint i,j;
13498   gint imin, imax, jmin, jmax;
13499
13500   layout = GTK_LAYOUT (widget);
13501
13502   if (event->window != layout->bin_window)
13503     return FALSE;
13504   
13505   imin = (event->area.x) / 10;
13506   imax = (event->area.x + event->area.width + 9) / 10;
13507
13508   jmin = (event->area.y) / 10;
13509   jmax = (event->area.y + event->area.height + 9) / 10;
13510
13511   for (i=imin; i<imax; i++)
13512     for (j=jmin; j<jmax; j++)
13513       if ((i+j) % 2)
13514         gdk_draw_rectangle (layout->bin_window,
13515                             widget->style->black_gc,
13516                             TRUE,
13517                             10*i, 10*j, 
13518                             1+i%10, 1+j%10);
13519   
13520   return FALSE;
13521 }
13522
13523 void create_layout (GtkWidget *widget)
13524 {
13525   static GtkWidget *window = NULL;
13526   GtkWidget *layout;
13527   GtkWidget *scrolledwindow;
13528   GtkWidget *button;
13529
13530   if (!window)
13531     {
13532       gchar buf[16];
13533
13534       gint i, j;
13535       
13536       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13537       gtk_window_set_screen (GTK_WINDOW (window),
13538                              gtk_widget_get_screen (widget));
13539
13540       g_signal_connect (window, "destroy",
13541                         G_CALLBACK (gtk_widget_destroyed),
13542                         &window);
13543
13544       gtk_window_set_title (GTK_WINDOW (window), "Layout");
13545       gtk_widget_set_size_request (window, 200, 200);
13546
13547       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
13548       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
13549                                            GTK_SHADOW_IN);
13550       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
13551                                          GTK_CORNER_TOP_RIGHT);
13552
13553       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
13554       
13555       layout = gtk_layout_new (NULL, NULL);
13556       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
13557
13558       /* We set step sizes here since GtkLayout does not set
13559        * them itself.
13560        */
13561       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
13562       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
13563       
13564       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
13565       g_signal_connect (layout, "expose_event",
13566                         G_CALLBACK (layout_expose_handler), NULL);
13567       
13568       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
13569       
13570       for (i=0 ; i < 16 ; i++)
13571         for (j=0 ; j < 16 ; j++)
13572           {
13573             sprintf(buf, "Button %d, %d", i, j);
13574             if ((i + j) % 2)
13575               button = gtk_button_new_with_label (buf);
13576             else
13577               button = gtk_label_new (buf);
13578
13579             gtk_layout_put (GTK_LAYOUT (layout), button,
13580                             j*100, i*100);
13581           }
13582
13583       for (i=16; i < 1280; i++)
13584         {
13585           sprintf(buf, "Button %d, %d", i, 0);
13586           if (i % 2)
13587             button = gtk_button_new_with_label (buf);
13588           else
13589             button = gtk_label_new (buf);
13590
13591           gtk_layout_put (GTK_LAYOUT (layout), button,
13592                           0, i*100);
13593         }
13594     }
13595
13596   if (!GTK_WIDGET_VISIBLE (window))
13597     gtk_widget_show_all (window);
13598   else
13599     gtk_widget_destroy (window);
13600 }
13601
13602 void
13603 create_styles (GtkWidget *widget)
13604 {
13605   static GtkWidget *window = NULL;
13606   GtkWidget *label;
13607   GtkWidget *button;
13608   GtkWidget *entry;
13609   GtkWidget *vbox;
13610   static GdkColor red =    { 0, 0xffff, 0,      0      };
13611   static GdkColor green =  { 0, 0,      0xffff, 0      };
13612   static GdkColor blue =   { 0, 0,      0,      0xffff };
13613   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
13614   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
13615   PangoFontDescription *font_desc;
13616
13617   GtkRcStyle *rc_style;
13618
13619   if (!window)
13620     {
13621       window = gtk_dialog_new ();
13622       gtk_window_set_screen (GTK_WINDOW (window),
13623                              gtk_widget_get_screen (widget));
13624      
13625       g_signal_connect (window, "destroy",
13626                         G_CALLBACK (gtk_widget_destroyed),
13627                         &window);
13628
13629       
13630       button = gtk_button_new_with_label ("Close");
13631       g_signal_connect_swapped (button, "clicked",
13632                                 G_CALLBACK (gtk_widget_destroy),
13633                                 window);
13634       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13635       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13636                           button, TRUE, TRUE, 0);
13637       gtk_widget_show (button);
13638
13639       vbox = gtk_vbox_new (FALSE, 5);
13640       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
13641       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
13642       
13643       label = gtk_label_new ("Font:");
13644       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13645       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13646
13647       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
13648
13649       button = gtk_button_new_with_label ("Some Text");
13650       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
13651       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13652
13653       label = gtk_label_new ("Foreground:");
13654       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13655       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13656
13657       button = gtk_button_new_with_label ("Some Text");
13658       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
13659       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13660
13661       label = gtk_label_new ("Background:");
13662       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13663       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13664
13665       button = gtk_button_new_with_label ("Some Text");
13666       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
13667       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13668
13669       label = gtk_label_new ("Text:");
13670       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13671       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13672
13673       entry = gtk_entry_new ();
13674       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13675       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
13676       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13677
13678       label = gtk_label_new ("Base:");
13679       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13680       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13681
13682       entry = gtk_entry_new ();
13683       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13684       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
13685       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13686
13687       label = gtk_label_new ("Cursor:");
13688       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13689       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13690
13691       entry = gtk_entry_new ();
13692       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13693       gtk_widget_modify_cursor (entry, &red, &red);
13694       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13695
13696       label = gtk_label_new ("Multiple:");
13697       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13698       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13699
13700       button = gtk_button_new_with_label ("Some Text");
13701
13702       rc_style = gtk_rc_style_new ();
13703
13704       rc_style->font_desc = pango_font_description_copy (font_desc);
13705       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
13706       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
13707       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
13708       rc_style->fg[GTK_STATE_NORMAL] = yellow;
13709       rc_style->bg[GTK_STATE_NORMAL] = blue;
13710       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
13711       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
13712       rc_style->fg[GTK_STATE_ACTIVE] = red;
13713       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
13714       rc_style->xthickness = 5;
13715       rc_style->ythickness = 5;
13716
13717       gtk_widget_modify_style (button, rc_style);
13718       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
13719
13720       g_object_unref (rc_style);
13721       
13722       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13723     }
13724   
13725   if (!GTK_WIDGET_VISIBLE (window))
13726     gtk_widget_show_all (window);
13727   else
13728     gtk_widget_destroy (window);
13729 }
13730
13731 /*
13732  * Main Window and Exit
13733  */
13734
13735 void
13736 do_exit (GtkWidget *widget, GtkWidget *window)
13737 {
13738   gtk_widget_destroy (window);
13739   gtk_main_quit ();
13740 }
13741
13742 struct {
13743   char *label;
13744   void (*func) (GtkWidget *widget);
13745   gboolean do_not_benchmark;
13746 } buttons[] =
13747 {
13748   { "alpha window", create_alpha_window },
13749   { "big windows", create_big_windows },
13750   { "button box", create_button_box },
13751   { "buttons", create_buttons },
13752   { "check buttons", create_check_buttons },
13753   { "clist", create_clist},
13754   { "color selection", create_color_selection },
13755   { "composited window", create_composited_window },
13756   { "ctree", create_ctree },
13757   { "cursors", create_cursors },
13758   { "dialog", create_dialog },
13759   { "display & screen", create_display_screen, TRUE },
13760   { "entry", create_entry },
13761   { "event box", create_event_box },
13762   { "event watcher", create_event_watcher },
13763   { "expander", create_expander },
13764   { "file selection", create_file_selection },
13765   { "flipping", create_flipping },
13766   { "focus", create_focus },
13767   { "font selection", create_font_selection },
13768   { "gamma curve", create_gamma_curve, TRUE },
13769   { "gridded geometry", create_gridded_geometry },
13770   { "handle box", create_handle_box },
13771   { "image from drawable", create_get_image },
13772   { "image", create_image },
13773   { "item factory", create_item_factory },
13774   { "key lookup", create_key_lookup },
13775   { "labels", create_labels },
13776   { "layout", create_layout },
13777   { "list", create_list },
13778   { "menus", create_menus },
13779   { "message dialog", create_message_dialog },
13780   { "modal window", create_modal_window, TRUE },
13781   { "notebook", create_notebook },
13782   { "panes", create_panes },
13783   { "paned keyboard", create_paned_keyboard_navigation },
13784   { "pixmap", create_pixmap },
13785   { "preview color", create_color_preview, TRUE },
13786   { "preview gray", create_gray_preview, TRUE },
13787   { "progress bar", create_progress_bar },
13788   { "properties", create_properties },
13789   { "radio buttons", create_radio_buttons },
13790   { "range controls", create_range_controls },
13791   { "rc file", create_rc_file },
13792   { "reparent", create_reparent },
13793   { "resize grips", create_resize_grips },
13794   { "rotated label", create_rotated_label },
13795   { "rotated text", create_rotated_text },
13796   { "rulers", create_rulers },
13797   { "saved position", create_saved_position },
13798   { "scrolled windows", create_scrolled_windows },
13799   { "shapes", create_shapes },
13800   { "size groups", create_size_groups },
13801   { "snapshot", create_snapshot },
13802   { "spinbutton", create_spins },
13803   { "statusbar", create_statusbar },
13804   { "styles", create_styles },
13805   { "test idle", create_idle_test },
13806   { "test mainloop", create_mainloop, TRUE },
13807   { "test scrolling", create_scroll_test },
13808   { "test selection", create_selection_test },
13809   { "test timeout", create_timeout_test },
13810   { "text", create_text },
13811   { "toggle buttons", create_toggle_buttons },
13812   { "toolbar", create_toolbar },
13813   { "tooltips", create_tooltips },
13814   { "tree", create_tree_mode_window},
13815   { "WM hints", create_wmhints },
13816   { "window sizing", create_window_sizing },
13817   { "window states", create_window_states }
13818 };
13819 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
13820
13821 void
13822 create_main_window (void)
13823 {
13824   GtkWidget *window;
13825   GtkWidget *box1;
13826   GtkWidget *box2;
13827   GtkWidget *scrolled_window;
13828   GtkWidget *button;
13829   GtkWidget *label;
13830   gchar buffer[64];
13831   GtkWidget *separator;
13832   GdkGeometry geometry;
13833   int i;
13834
13835   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13836   gtk_widget_set_name (window, "main window");
13837   gtk_widget_set_uposition (window, 50, 20);
13838   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
13839
13840   geometry.min_width = -1;
13841   geometry.min_height = -1;
13842   geometry.max_width = -1;
13843   geometry.max_height = G_MAXSHORT;
13844   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
13845                                  &geometry,
13846                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
13847
13848   g_signal_connect (window, "destroy",
13849                     G_CALLBACK (gtk_main_quit),
13850                     NULL);
13851   g_signal_connect (window, "delete-event",
13852                     G_CALLBACK (gtk_false),
13853                     NULL);
13854
13855   box1 = gtk_vbox_new (FALSE, 0);
13856   gtk_container_add (GTK_CONTAINER (window), box1);
13857
13858   if (gtk_micro_version > 0)
13859     sprintf (buffer,
13860              "Gtk+ v%d.%d.%d",
13861              gtk_major_version,
13862              gtk_minor_version,
13863              gtk_micro_version);
13864   else
13865     sprintf (buffer,
13866              "Gtk+ v%d.%d",
13867              gtk_major_version,
13868              gtk_minor_version);
13869
13870   label = gtk_label_new (buffer);
13871   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
13872   gtk_widget_set_name (label, "testgtk-version-label");
13873
13874   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
13875   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
13876   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
13877                                   GTK_POLICY_NEVER, 
13878                                   GTK_POLICY_AUTOMATIC);
13879   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
13880
13881   box2 = gtk_vbox_new (FALSE, 0);
13882   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13883   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
13884   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
13885                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
13886   gtk_widget_show (box2);
13887
13888   for (i = 0; i < nbuttons; i++)
13889     {
13890       button = gtk_button_new_with_label (buttons[i].label);
13891       if (buttons[i].func)
13892         g_signal_connect (button, 
13893                           "clicked", 
13894                           G_CALLBACK(buttons[i].func),
13895                           NULL);
13896       else
13897         gtk_widget_set_sensitive (button, FALSE);
13898       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13899     }
13900
13901   separator = gtk_hseparator_new ();
13902   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
13903
13904   box2 = gtk_vbox_new (FALSE, 10);
13905   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13906   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
13907
13908   button = gtk_button_new_with_mnemonic ("_Close");
13909   g_signal_connect (button, "clicked",
13910                     G_CALLBACK (do_exit),
13911                     window);
13912   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13913   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13914   gtk_widget_grab_default (button);
13915
13916   gtk_widget_show_all (window);
13917 }
13918
13919 static void
13920 test_init (void)
13921 {
13922   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
13923                    G_FILE_TEST_EXISTS))
13924     {
13925       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
13926       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
13927     }
13928 }
13929
13930 static char *
13931 pad (const char *str, int to)
13932 {
13933   static char buf[256];
13934   int len = strlen (str);
13935   int i;
13936
13937   for (i = 0; i < to; i++)
13938     buf[i] = ' ';
13939
13940   buf[to] = '\0';
13941
13942   memcpy (buf, str, len);
13943
13944   return buf;
13945 }
13946
13947 static void
13948 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
13949 {
13950   fn (widget); /* on */
13951   while (g_main_context_iteration (NULL, FALSE));
13952   fn (widget); /* off */
13953   while (g_main_context_iteration (NULL, FALSE));
13954 }
13955
13956 void
13957 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
13958 {
13959   GTimeVal tv0, tv1;
13960   double dt_first;
13961   double dt;
13962   int n;
13963   static gboolean printed_headers = FALSE;
13964
13965   if (!printed_headers) {
13966     g_print ("Test                 Iters      First      Other\n");
13967     g_print ("-------------------- ----- ---------- ----------\n");
13968     printed_headers = TRUE;
13969   }
13970
13971   g_get_current_time (&tv0);
13972   bench_iteration (widget, fn); 
13973   g_get_current_time (&tv1);
13974
13975   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13976         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13977
13978   g_get_current_time (&tv0);
13979   for (n = 0; n < num - 1; n++)
13980     bench_iteration (widget, fn); 
13981   g_get_current_time (&tv1);
13982   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13983         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13984
13985   g_print ("%s %5d ", pad (name, 20), num);
13986   if (num > 1)
13987     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
13988   else
13989     g_print ("%10.1f\n", dt_first);
13990 }
13991
13992 void
13993 do_bench (char* what, int num)
13994 {
13995   int i;
13996   GtkWidget *widget;
13997   void (* fn) (GtkWidget *widget);
13998   fn = NULL;
13999   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14000
14001   if (g_ascii_strcasecmp (what, "ALL") == 0)
14002     {
14003       for (i = 0; i < nbuttons; i++)
14004         {
14005           if (!buttons[i].do_not_benchmark)
14006             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
14007         }
14008
14009       return;
14010     }
14011   else
14012     {
14013       for (i = 0; i < nbuttons; i++)
14014         {
14015           if (strcmp (buttons[i].label, what) == 0)
14016             {
14017               fn = buttons[i].func;
14018               break;
14019             }
14020         }
14021       
14022       if (!fn)
14023         g_print ("Can't bench: \"%s\" not found.\n", what);
14024       else
14025         do_real_bench (widget, fn, buttons[i].label, num);
14026     }
14027 }
14028
14029 void 
14030 usage (void)
14031 {
14032   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
14033   exit (1);
14034 }
14035
14036 int
14037 main (int argc, char *argv[])
14038 {
14039   GtkBindingSet *binding_set;
14040   int i;
14041   gboolean done_benchmarks = FALSE;
14042
14043   srand (time (NULL));
14044
14045   test_init ();
14046
14047   /* Check to see if we are being run from the correct
14048    * directory.
14049    */
14050   if (file_exists ("testgtkrc"))
14051     gtk_rc_add_default_file ("testgtkrc");
14052   else if (file_exists ("tests/testgtkrc"))
14053     gtk_rc_add_default_file ("tests/testgtkrc");
14054   else
14055     g_warning ("Couldn't find file \"testgtkrc\".");
14056
14057   g_set_application_name ("GTK+ Test Program");
14058
14059   gtk_init (&argc, &argv);
14060
14061   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
14062                                         GDK_CONTROL_MASK |
14063                                         GDK_MOD1_MASK | 
14064                                         GDK_META_MASK |
14065                                         GDK_SUPER_MASK |
14066                                         GDK_HYPER_MASK |
14067                                         GDK_MOD4_MASK);
14068   /*  benchmarking
14069    */
14070   for (i = 1; i < argc; i++)
14071     {
14072       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
14073         {
14074           int num = 1;
14075           char *nextarg;
14076           char *what;
14077           char *count;
14078           
14079           nextarg = strchr (argv[i], '=');
14080           if (nextarg)
14081             nextarg++;
14082           else
14083             {
14084               i++;
14085               if (i == argc)
14086                 usage ();
14087               nextarg = argv[i];
14088             }
14089
14090           count = strchr (nextarg, ':');
14091           if (count)
14092             {
14093               what = g_strndup (nextarg, count - nextarg);
14094               count++;
14095               num = atoi (count);
14096               if (num <= 0)
14097                 usage ();
14098             }
14099           else
14100             what = g_strdup (nextarg);
14101
14102           do_bench (what, num ? num : 1);
14103           done_benchmarks = TRUE;
14104         }
14105       else
14106         usage ();
14107     }
14108   if (done_benchmarks)
14109     return 0;
14110
14111   /* bindings test
14112    */
14113   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
14114   gtk_binding_entry_add_signal (binding_set,
14115                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
14116                                 "debug_msg",
14117                                 1,
14118                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
14119   
14120   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
14121    * changes
14122    */
14123
14124   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
14125                        "   fg[NORMAL] = \"#ff0000\"\n"
14126                        "   font = \"Sans 18\"\n"
14127                        "}\n"
14128                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
14129   
14130   create_main_window ();
14131
14132   gtk_main ();
14133
14134   if (1)
14135     {
14136       while (g_main_context_pending (NULL))
14137         g_main_context_iteration (NULL, FALSE);
14138 #if 0
14139       sleep (1);
14140       while (g_main_context_pending (NULL))
14141         g_main_context_iteration (NULL, FALSE);
14142 #endif
14143     }
14144   return 0;
14145 }