1 /*
2 |  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
3 |  Part of the gtkpod project.
4 |
5 |  URL: http://www.gtkpod.org/
6 |  URL: http://gtkpod.sourceforge.net/
7 |
8 |  This program is free software; you can redistribute it and/or modify
9 |  it under the terms of the GNU General Public License as published by
10 |  the Free Software Foundation; either version 2 of the License, or
11 |  (at your option) any later version.
12 |
13 |  This program is distributed in the hope that it will be useful,
14 |  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 |  GNU General Public License for more details.
17 |
18 |  You should have received a copy of the GNU General Public License
19 |  along with this program; if not, write to the Free Software
20 |  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 |
22 |  iTunes and iPod are trademarks of Apple
23 |
24 |  This product is not supported/written/published by Apple!
25 |
26 |  $Id$
27 */
28 
29 #ifdef HAVE_CONFIG_H
30 #  include <config.h>
31 #endif
32 
33 #include <string.h>
34 #include "misc.h"
35 #include "confirmation.h"
36 #include "prefs.h"
37 
38 
39 static GHashTable *id_hash = NULL;
40 
41 typedef struct {
42     GtkWidget *window;
43     GladeXML *window_xml;
44     gboolean  scrolled;
45     gchar *option1_key;
46     gboolean option1_invert;
47     gchar *option2_key;
48     gboolean option2_invert;
49     gchar *confirm_again_key;
50     ConfHandler ok_handler;
51     ConfHandler apply_handler;
52     ConfHandler cancel_handler;
53     gpointer user_data1;
54     gpointer user_data2;
55 } ConfData;
56 
57 
58 
59 /* cleanup hash, store window size */
cleanup(gpointer id)60 static void cleanup (gpointer id)
61 {
62     ConfData *cd;
63 
64     cd = g_hash_table_lookup (id_hash, id);
65     if (cd)
66     {
67 	gint defx, defy;
68 	gtk_window_get_size (GTK_WINDOW (cd->window), &defx, &defy);
69 	if (cd->scrolled)
70 	{
71 		prefs_set_int("size_conf_sw.x", defx);
72 		prefs_set_int("size_conf_sw.y", defy);
73 	}
74 	else
75 	{
76 		prefs_set_int("size_conf.x", defx);
77 		prefs_set_int("size_conf.y", defy);
78 	}
79 
80 	gtk_widget_destroy (cd->window);
81 	g_free (cd->option1_key);
82 	g_free (cd->option2_key);
83 	g_free (cd->confirm_again_key);
84 
85 	g_hash_table_remove (id_hash, id);
86     }
87 }
88 
89 
on_ok_clicked(GtkWidget * w,gpointer id)90 static void on_ok_clicked (GtkWidget *w, gpointer id)
91 {
92     ConfData *cd;
93 
94     cd = g_hash_table_lookup (id_hash, id);
95     if (cd)
96     {
97 	gtk_widget_set_sensitive (cd->window, FALSE);
98 	if (cd->ok_handler)
99 	    cd->ok_handler (cd->user_data1, cd->user_data2);
100 	cleanup (id);
101     }
102 }
103 
on_apply_clicked(GtkWidget * w,gpointer id)104 static void on_apply_clicked (GtkWidget *w, gpointer id)
105 {
106     ConfData *cd;
107 
108     cd = g_hash_table_lookup (id_hash, id);
109     if (cd)
110     {
111 	gtk_widget_set_sensitive (cd->window, FALSE);
112 	if (cd->apply_handler)
113 	    cd->apply_handler (cd->user_data1, cd->user_data2);
114 	gtk_widget_set_sensitive (cd->window, TRUE);
115     }
116 }
117 
on_cancel_clicked(GtkWidget * w,gpointer id)118 static void on_cancel_clicked (GtkWidget *w, gpointer id)
119 {
120     ConfData *cd;
121 
122     cd = g_hash_table_lookup (id_hash, id);
123     if (cd)
124     {
125 	gtk_widget_set_sensitive (cd->window, FALSE);
126 	if (cd->cancel_handler)
127 	    cd->cancel_handler (cd->user_data1, cd->user_data2);
128 	cleanup (id);
129     }
130 }
131 
132 
133 /* Handler to be used when the button should be displayed, but no
134    action is required */
CONF_NULL_HANDLER(gpointer d1,gpointer d2)135 void CONF_NULL_HANDLER (gpointer d1, gpointer d2)
136 {
137     return;
138 }
139 
140 
on_never_again_toggled(GtkToggleButton * t,gpointer id)141 static void on_never_again_toggled (GtkToggleButton *t, gpointer id)
142 {
143     ConfData *cd;
144 
145     cd = g_hash_table_lookup (id_hash, id);
146     if (cd)
147     {
148 	if (cd->confirm_again_key)
149 	    prefs_set_int(cd->confirm_again_key, !gtk_toggle_button_get_active(t));
150     }
151 }
152 
on_option1_toggled(GtkToggleButton * t,gpointer id)153 static void on_option1_toggled (GtkToggleButton *t, gpointer id)
154 {
155     ConfData *cd;
156 
157     cd = g_hash_table_lookup (id_hash, id);
158     if (cd)
159     {
160 	if (cd->option1_key)
161 	{
162 	    gboolean state = gtk_toggle_button_get_active(t);
163 	    if (cd->option1_invert)  prefs_set_int (cd->option1_key, !state);
164 	    else                     prefs_set_int (cd->option1_key, state);
165 	}
166     }
167 }
168 
on_option2_toggled(GtkToggleButton * t,gpointer id)169 static void on_option2_toggled (GtkToggleButton *t, gpointer id)
170 {
171     ConfData *cd;
172 
173     cd = g_hash_table_lookup (id_hash, id);
174     if (cd)
175     {
176 	if (cd->option2_key)
177 	{
178 	    gboolean state = gtk_toggle_button_get_active(t);
179 	    if (cd->option2_invert)  prefs_set_int (cd->option2_key, !state);
180 	    else                     prefs_set_int (cd->option2_key, state);
181 	}
182     }
183 }
184 
on_response(GtkWidget * w,gint response,gpointer id)185 static void on_response (GtkWidget *w, gint response, gpointer id)
186 {
187     ConfData *cd;
188 /*     printf ("r: %d, i: %d\n", response, id); */
189     cd = g_hash_table_lookup (id_hash, id);
190     if (cd)
191     {
192 	switch (response)
193 	{
194 	case GTK_RESPONSE_OK:
195 	    on_ok_clicked (w, id);
196 	    break;
197 	case GTK_RESPONSE_NONE:
198 	case GTK_RESPONSE_CANCEL:
199 	case GTK_RESPONSE_DELETE_EVENT:
200 	    on_cancel_clicked (w, id);
201 	    break;
202 	case GTK_RESPONSE_APPLY:
203 	    on_apply_clicked (w, id);
204 	    break;
205 	default:
206 	    g_warning ("Programming error: resonse '%d' received in on_response()\n", response);
207 	    on_cancel_clicked (w, id);
208 	    break;
209 	}
210     }
211 }
212 
confirm_append_text(GladeXML * xml,const gchar * text)213 static void confirm_append_text (GladeXML *xml, const gchar *text)
214 {
215 	int i;
216 	gchar **strings = g_strsplit (text, "\n", 0);
217 	GtkTreeIter iter;
218 	GtkAdjustment *adjustment;
219 	GtkWidget *w = gtkpod_xml_get_widget (xml, "tree");
220 	GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (w)));
221 
222 	for (i = 0; strings[i]; i++)
223 	{
224 		if (strings[i][0])
225 		{
226 			gtk_list_store_append (store, &iter);
227 			gtk_list_store_set (store, &iter, 0, strings[i], -1);
228 		}
229 	}
230 
231 	w = gtkpod_xml_get_widget (xml, "scroller");
232 	adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (w));
233 	gtk_adjustment_set_value (adjustment, adjustment->upper - adjustment->page_size);
234 
235 	g_strfreev (strings);
236 }
237 
238 /* gtkpod_confirmation(): open a confirmation window with the
239    information given. If "OK" is clicked, ok_handler() is called,
240    otherwise cancel_handler() is called, each with the parameters
241    "user_data1" and "user_data2". Use "NULL" if you want to
242    omit a parameter. If "confirm_again" is FALSE, ok_handler() is called
243    directly.
244 
245    @id:    an ID: only one window with a given positive id can be
246            open. Use negative ID if you don't care how many windows
247 	   are open at the same time (e.g. because they are modal).
248 	   With positive IDs @text is added to an already open window
249            with the same ID.
250    @modal: should the window be modal (i.e. block the program)?
251    @title: title of the window
252    @label: the text at the top of the window
253    @text:  the text displayed in a scrolled window
254    @option_text: text for the option checkbox (or NULL)
255    @option_state: initial state of the option + a flag indicating
256            whether the handler should be called with the inverse state
257            of the toggle button: CONF_STATE_TRUE, CONF_STATE_FALSE,
258 	   CONF_STATE_INVERT_TRUE, CONF_STATE_INVERT_FALSE
259    @option_key: prefs key for the option (is set to the state of the
260            toggle box)
261    @confirm_again:    state of the "confirm again" flag
262    @confirm_again_key: prefs key for the 'never show this dialog
263            again' toggle box (is set to the inverted current state
264 	   of the toggle box)
265    @ok_handler:     function to be called when the OK button is pressed
266    @apply_handler:  function to be called when the Apply button is pressed
267    @cancel_handler: function to be called when the cancel button is pressed
268 	   Note: in modal windows, the ok_, apply_, and cancel_handlers
269 	   must be set to CONF_NULL_HANDLER if the button is to be shown.
270    @user_data1:     first argument to be passed to the ConfHandler
271    @user_data1:     second argument to be passed to the ConfHandler
272 
273    Pass NULL as "handler" if you want the corresponding button to be
274    hidden.
275 
276    Pass CONF_NULL_HANDLER if you want the corresponding button to be
277    shown, but don't want to specify a handler.
278 
279    Return value:
280 
281    non-modal dialogs:
282 
283      GTK_RESPONSE_REJECT: no window was opened because another window
284      with the same ID is already open. Text was appended.
285 
286      GTK_RESPONSE_ACCEPT: either a window was opened, or ok_handler()
287      was called directly.
288 
289    modal dialogs:
290 
291      GTK_RESPONSE_REJECT: no window was opened because another window
292      with the same ID is already open. Text was appended.
293 
294      GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, GTK_RESPONSE_APPLY:
295      OK/CANCEL/APPLY pressed. If the window is closed by the user,
296      GTK_RESPONSE_CANCEL will be returned.
297  */
298 
gtkpod_confirmation(gint id,gboolean modal,const gchar * title,const gchar * label,const gchar * text,const gchar * option1_text,CONF_STATE option1_state,const gchar * option1_key,const gchar * option2_text,CONF_STATE option2_state,const gchar * option2_key,gboolean confirm_again,const gchar * confirm_again_key,ConfHandler ok_handler,ConfHandler apply_handler,ConfHandler cancel_handler,gpointer user_data1,gpointer user_data2)299 GtkResponseType gtkpod_confirmation (gint id,
300 				     gboolean modal,
301 				     const gchar *title,
302 				     const gchar *label,
303 				     const gchar *text,
304 				     const gchar *option1_text,
305 				     CONF_STATE option1_state,
306 				     const gchar *option1_key,
307 				     const gchar *option2_text,
308 				     CONF_STATE option2_state,
309 				     const gchar *option2_key,
310 				     gboolean confirm_again,
311 				     const gchar *confirm_again_key,
312 				     ConfHandler ok_handler,
313 				     ConfHandler apply_handler,
314 				     ConfHandler cancel_handler,
315 				     gpointer user_data1,
316 				     gpointer user_data2)
317 {
318     GtkWidget *window, *w;
319     ConfData *cd;
320     gint defx, defy;
321     GladeXML *confirm_xml;
322     GtkListStore *store;
323     GtkTreeViewColumn *column;
324     GtkCellRenderer *renderer;
325     gchar *full_label;
326 
327     if (id_hash == NULL)
328     {  /* initialize hash table to store IDs */
329 	id_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal,
330 							  NULL, g_free);
331     }
332 
333     if (id >= 0)
334     {
335 	if ((cd = g_hash_table_lookup (id_hash, GINT_TO_POINTER(id))))
336 	{ /* window with same ID already open -- add @text and return */
337 	    if (text && *text && cd->window)
338 	    {
339 		confirm_append_text (cd->window_xml, text);
340 	    }
341 	    return GTK_RESPONSE_REJECT;
342 	}
343     }
344     else /* find free ID */
345     {
346 	id = 0;
347 
348 	do
349 	{
350 	    --id;
351 	    cd = g_hash_table_lookup (id_hash, GINT_TO_POINTER(id));
352 	} while (cd != NULL);
353     }
354 
355     if (!confirm_again)
356     {
357 	/* This question was supposed to be asked "never again" ("don't
358 	   confirm again" -- so we just call the ok_handler */
359 	if (ok_handler && !modal)
360 	    ok_handler (user_data1, user_data2);
361 
362 	if (!modal)
363 	    return GTK_RESPONSE_ACCEPT;
364 
365 	return GTK_RESPONSE_OK;
366     }
367 
368     /* window = create_confirm_dialog (); */
369     confirm_xml = gtkpod_xml_new (xml_file, "confirm_dialog");
370     window = gtkpod_xml_get_widget (confirm_xml, "confirm_dialog");
371     glade_xml_signal_autoconnect (confirm_xml);
372 
373     /* insert ID into hash table */
374     cd = g_new0 (ConfData, 1);
375     cd->window = window;
376     cd->window_xml = confirm_xml;
377     cd->option1_key = g_strdup(option1_key);
378     cd->option2_key = g_strdup(option2_key);
379     cd->confirm_again_key = g_strdup(confirm_again_key);
380     cd->ok_handler = ok_handler;
381     cd->apply_handler = apply_handler;
382     cd->cancel_handler = cancel_handler;
383     cd->user_data1 = user_data1;
384     cd->user_data2 = user_data2;
385     g_hash_table_insert (id_hash, GINT_TO_POINTER(id), cd);
386 
387     full_label = g_markup_printf_escaped ("<span weight='bold' size='larger'>%s</span>\n\n%s",
388 					  title ? title : _("Confirmation"), label ? label : "");
389 
390     /* Set label */
391     w = gtkpod_xml_get_widget (confirm_xml, "label");
392     gtk_label_set_markup (GTK_LABEL(w), full_label);
393     g_free (full_label);
394 
395     /* Set text */
396     w = gtkpod_xml_get_widget (confirm_xml, "tree");
397     store = gtk_list_store_new (1, G_TYPE_STRING);
398     gtk_tree_view_set_model (GTK_TREE_VIEW (w), GTK_TREE_MODEL (store));
399     g_object_unref (store);
400 
401     column = gtk_tree_view_column_new ();
402     renderer = gtk_cell_renderer_text_new ();
403 
404 /*
405     gint mode, width;
406 
407     g_object_get (G_OBJECT (renderer),
408 		  "wrap-mode", &mode,
409 		  "wrap-width", &width,
410 		  NULL);
411 
412     printf ("wrap-mode: %d wrap-width:%d\n", mode, width);
413 */
414 
415     /* I have no idea why 400, but neither 1000 nor 0 result in the
416        right behavior... */
417     g_object_set (G_OBJECT (renderer),
418 		  "wrap-mode", PANGO_WRAP_WORD_CHAR,
419 		  "wrap-width", 400,
420 		  NULL);
421 
422     gtk_tree_view_column_pack_start (column, renderer, TRUE);
423     gtk_tree_view_column_set_attributes (column, renderer, "text", 0, NULL);
424     g_object_set_data (G_OBJECT (w), "renderer", renderer);
425 
426     gtk_tree_view_append_column (GTK_TREE_VIEW (w), column);
427 
428     if (text)
429     {
430 		confirm_append_text (cd->window_xml, text);
431 		cd->scrolled = TRUE;
432 		defx = prefs_get_int("size_conf_sw.x");
433 		defy = prefs_get_int("size_conf_sw.y");
434     }
435     else
436     {
437 		/* no text -> hide widget */
438 		if ((w = gtkpod_xml_get_widget (confirm_xml, "scroller")))
439 			gtk_widget_hide (w);
440 
441 		cd->scrolled = FALSE;
442 		defx = prefs_get_int("size_conf.x");
443 		defy = prefs_get_int("size_conf.y");
444     }
445 
446     gtk_widget_set_size_request (GTK_WIDGET (window), defx, defy);
447 
448     /* Set "Option 1" checkbox */
449     w = gtkpod_xml_get_widget (confirm_xml, "option_vbox");
450 
451     if (w && option1_key && option1_text)
452     {
453 	gboolean state, invert;
454 	GtkWidget *option1_button =
455 	    gtk_check_button_new_with_mnemonic (option1_text);
456 
457 	state = ((option1_state==CONF_STATE_INVERT_TRUE) || (option1_state==CONF_STATE_TRUE));
458 	invert = ((option1_state==CONF_STATE_INVERT_FALSE) || (option1_state==CONF_STATE_INVERT_TRUE));
459 	cd->option1_invert = invert;
460 
461 	gtk_widget_show (option1_button);
462 	gtk_box_pack_start (GTK_BOX (w), option1_button, FALSE, FALSE, 0);
463 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(option1_button),
464 				     state);
465 	g_signal_connect ((gpointer)option1_button,
466 			  "toggled",
467 			  G_CALLBACK (on_option1_toggled),
468 			  GINT_TO_POINTER(id));
469     }
470 
471     /* Set "Option 2" checkbox */
472     w = gtkpod_xml_get_widget (confirm_xml, "option_vbox");
473     if (w && option2_key && option2_text)
474     {
475 	gboolean state, invert;
476 	GtkWidget *option2_button =
477 	    gtk_check_button_new_with_mnemonic (option2_text);
478 
479 	state = ((option2_state==CONF_STATE_INVERT_TRUE) || (option2_state==CONF_STATE_TRUE));
480 	invert = ((option2_state==CONF_STATE_INVERT_FALSE) || (option2_state==CONF_STATE_INVERT_TRUE));
481 	cd->option2_invert = invert;
482 
483 	gtk_widget_show (option2_button);
484 	gtk_box_pack_start (GTK_BOX (w), option2_button, FALSE, FALSE, 0);
485 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(option2_button),
486 				     state);
487 	g_signal_connect ((gpointer)option2_button,
488 			  "toggled",
489 			  G_CALLBACK (on_option2_toggled),
490 			  GINT_TO_POINTER(id));
491     }
492 
493     /* Set "Never Again" checkbox */
494     w = gtkpod_xml_get_widget (confirm_xml, "never_again");
495 
496     if (w && confirm_again_key)
497     {
498 	/* connect signal */
499 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
500 				     !confirm_again);
501 	g_signal_connect ((gpointer)w,
502 			  "toggled",
503 			  G_CALLBACK (on_never_again_toggled),
504 			  GINT_TO_POINTER(id));
505     }
506     else if (w)
507     {
508 	/* hide "never again" button */
509 	gtk_widget_hide (w);
510     }
511 
512     /* Hide and set "default" button that can be activated by pressing
513        ENTER in the window (usually OK)*/
514     /* Hide or default CANCEL button */
515     if ((w = gtkpod_xml_get_widget (confirm_xml, "cancel")))
516     {
517 	GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
518 	gtk_widget_grab_default (w);
519 
520 	if (!cancel_handler)
521 	    gtk_widget_hide (w);
522     }
523 
524     /* Hide or default APPLY button */
525     if ((w = gtkpod_xml_get_widget (confirm_xml, "apply")))
526     {
527 	GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
528 	gtk_widget_grab_default (w);
529 
530 	if (!apply_handler)
531 	    gtk_widget_hide (w);
532     }
533 
534     /* Hide or default OK button */
535     if ((w = gtkpod_xml_get_widget (confirm_xml, "ok")))
536     {
537 	GTK_WIDGET_SET_FLAGS (w, GTK_CAN_DEFAULT);
538 	gtk_widget_grab_default (w);
539 
540 	if (!ok_handler)
541 	    gtk_widget_hide (w);
542     }
543 
544     /* Connect Close window */
545     g_signal_connect (GTK_OBJECT (window),
546 		      "delete_event",
547 		      G_CALLBACK (on_cancel_clicked),
548 		      GINT_TO_POINTER(id));
549 
550     if (modal)
551     {
552 	/* use gtk_dialog_run() to block the application */
553 	gint response = gtk_dialog_run (GTK_DIALOG (window));
554 	/* cleanup hash, store window size */
555 	cleanup (GINT_TO_POINTER(id));
556 
557 	switch (response)
558 	{
559 	case GTK_RESPONSE_OK:
560 	case GTK_RESPONSE_APPLY:
561 	    return response;
562 	default:
563 	    return GTK_RESPONSE_CANCEL;
564 	}
565     }
566     else
567     {
568 	/* Make sure we catch the response */
569 	g_signal_connect (GTK_OBJECT (window),
570 			  "response",
571 			  G_CALLBACK (on_response),
572 			  GINT_TO_POINTER(id));
573 	gtk_widget_show (window);
574 
575 	return GTK_RESPONSE_ACCEPT;
576     }
577 }
578 
on_confirm_tree_size_allocate(GtkWidget * sender,GtkAllocation * allocation,gpointer e)579 G_MODULE_EXPORT void on_confirm_tree_size_allocate (GtkWidget *sender, GtkAllocation *allocation, gpointer e)
580 {
581     GtkCellRenderer *renderer = GTK_CELL_RENDERER (g_object_get_data (G_OBJECT (sender), "renderer"));
582     g_object_set (renderer, "wrap-width", allocation->width, NULL);
583 }
584 
gtkpod_confirmation_simple(GtkWindow * parent,GtkMessageType icon,const gchar * primary_text,const gchar * secondary_text,const gchar * accept_button_text)585 gint gtkpod_confirmation_simple (GtkWindow *parent,
586 				 GtkMessageType icon,
587 				 const gchar *primary_text,
588 				 const gchar *secondary_text,
589 				 const gchar *accept_button_text)
590 {
591     return gtkpod_confirmation_hig(parent, icon, primary_text, secondary_text,
592 				   accept_button_text, NULL, NULL, NULL);
593 }
594 
gtkpod_confirmation_hig(GtkWindow * parent,GtkMessageType icon,const gchar * primary_text,const gchar * secondary_text,const gchar * accept_button_text,const gchar * cancel_button_text,const gchar * third_button_text,const gchar * help_context)595 gint gtkpod_confirmation_hig (GtkWindow *parent,
596 			      GtkMessageType icon,
597 			      const gchar *primary_text,
598 			      const gchar *secondary_text,
599 			      const gchar *accept_button_text,
600 			      const gchar *cancel_button_text,
601 			      const gchar *third_button_text,
602 			      const gchar *help_context)
603 {
604     gint result;
605 
606     GtkWidget *dialog =
607 	gtk_message_dialog_new(parent,
608 			       GTK_DIALOG_MODAL,
609 			       icon,
610 			       GTK_BUTTONS_NONE,
611 			       "%s",
612 			       primary_text);
613 
614     gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG(dialog),
615 						"%s",
616 						secondary_text);
617 
618     if(third_button_text)
619 	gtk_dialog_add_button(GTK_DIALOG(dialog), third_button_text, GTK_RESPONSE_APPLY);
620 
621     gtk_dialog_add_buttons(GTK_DIALOG(dialog),
622 			   cancel_button_text ? cancel_button_text : GTK_STOCK_CANCEL,
623 			   GTK_RESPONSE_CANCEL,
624 			   accept_button_text ? accept_button_text : GTK_STOCK_OK,
625 			   GTK_RESPONSE_OK,
626 			   NULL);
627 
628     result = gtk_dialog_run(GTK_DIALOG(dialog));
629     gtk_widget_destroy(dialog);
630 
631     switch (result)
632     {
633     case GTK_RESPONSE_OK:
634     case GTK_RESPONSE_APPLY:
635 	return result;
636     default:
637 	return GTK_RESPONSE_CANCEL;
638     };
639 }
640