1 /* make and manage base dialogs ... subclass off this for others
2  */
3 
4 /*
5 
6     Copyright (C) 1991-2003 The National Gallery
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 along
19     with this program; if not, write to the Free Software Foundation, Inc.,
20     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 
22  */
23 
24 /*
25 
26     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27 
28 */
29 
30 #include "ip.h"
31 
32 /*
33 #define DEBUG
34  */
35 
36 static iWindowClass *parent_class = NULL;
37 
38 /* An OK button: label (can be a stock) plus a callback.
39  */
40 typedef struct {
41 	char *label;
42 	iWindowFn done_cb;
43 } OKButton;
44 
45 static void *
okbutton_free(OKButton * ok)46 okbutton_free( OKButton *ok )
47 {
48 	IM_FREEF( g_free, ok->label );
49 	ok->done_cb = NULL;
50 	IM_FREEF( g_free, ok );
51 
52 	return( NULL );
53 }
54 
55 static OKButton *
okbutton_new(char * label,iWindowFn done_cb)56 okbutton_new( char *label, iWindowFn done_cb )
57 {
58 	OKButton *ok;
59 
60 	ok = g_new( OKButton, 1 );
61 	ok->label = g_strdup( label );
62 	ok->done_cb = done_cb;
63 
64 	return( ok );
65 }
66 
67 /* Handy destroy callback ... just free client.
68  */
69 void
idialog_free_client(iDialog * idlg,void * client)70 idialog_free_client( iDialog *idlg, void *client )
71 {
72 	IM_FREE( client );
73 }
74 
75 /* Notify our parent.
76  */
77 static void
idialog_notify_parent(iDialog * idlg,iWindowResult result)78 idialog_notify_parent( iDialog *idlg, iWindowResult result )
79 {
80 	if( idlg->nfn ) {
81 		iWindowNotifyFn nfn = idlg->nfn;
82 
83 		idlg->nfn = NULL;
84 		nfn( idlg->sys, result );
85 	}
86 }
87 
88 static void *
idialog_set_sensitive(GtkWidget * w,gboolean state)89 idialog_set_sensitive( GtkWidget *w, gboolean state )
90 {
91 	gtk_widget_set_sensitive( w, state );
92 
93 	return( NULL );
94 }
95 
96 /* Set OK sensitivities.
97  */
98 void
idialog_set_ok_button_state(iDialog * idlg,gboolean state)99 idialog_set_ok_button_state( iDialog *idlg, gboolean state )
100 {
101 	slist_map( idlg->ok_but_l,
102 		(SListMapFn) idialog_set_sensitive, GINT_TO_POINTER( state ) );
103 }
104 
105 /* Set all the button sensitivities.
106  */
107 static void
idialog_set_button_state(iDialog * idlg,gboolean state)108 idialog_set_button_state( iDialog *idlg, gboolean state )
109 {
110 	idialog_set_ok_button_state( idlg, state );
111 	if( idlg->but_cancel )
112 		gtk_widget_set_sensitive( idlg->but_cancel, state );
113 	if( idlg->but_help )
114 		gtk_widget_set_sensitive( idlg->but_help, state );
115 }
116 
117 /* Sub-fn of below. Come back from a popdown notify.
118  */
119 static void
idialog_popdown_notify(void * sys,iWindowResult result)120 idialog_popdown_notify( void *sys, iWindowResult result )
121 {
122         iWindowSusp *susp = IWINDOW_SUSP( sys );
123 	iDialog *idlg = IDIALOG( susp->client );
124 
125 	if( result == IWINDOW_YES )
126 		/* If our caller hasn't been notified yet, post off a FALSE.
127 		 */
128 		idialog_notify_parent( idlg, IWINDOW_NO );
129 
130 	/* Pass result on to our suspension (ie. back to iwindow).
131 	 */
132 	iwindow_susp_return( susp, result );
133 
134 	/* Housekeeping.
135 	 */
136 	iwindow_notify_return( IWINDOW( idlg ) );
137 }
138 
139 /* Our popdown callback ... here from iwindow.
140  */
141 static void
idialog_popdown_cb(iWindow * iwnd,void * client,iWindowNotifyFn nfn,void * sys)142 idialog_popdown_cb( iWindow *iwnd, void *client,
143 	iWindowNotifyFn nfn, void *sys )
144 {
145 	iDialog *idlg = IDIALOG( client );
146         iWindowSusp *susp = iwindow_susp_new( NULL, iwnd, idlg, nfn, sys );
147 
148 #ifdef DEBUG
149 	printf( "idialog_popdown_cb: %s\n", IWINDOW( idlg )->title );
150 #endif /*DEBUG*/
151 
152 	/* Trigger user popdown.
153 	 */
154 	iwindow_notify_send( IWINDOW( idlg ),
155 		idlg->popdown_cb, idlg->client, idialog_popdown_notify, susp );
156 }
157 
158 /* Sub-fn of below. Come back from a done notify.
159  */
160 static void
idialog_done_notify(void * sys,iWindowResult result)161 idialog_done_notify( void *sys, iWindowResult result )
162 {
163 	iDialog *idlg = IDIALOG( sys );
164 
165 #ifdef DEBUG
166 	printf( "idialog_done_notify: %s\n", IWINDOW( idlg )->title );
167 #endif /*DEBUG*/
168 
169 	idialog_set_button_state( idlg, TRUE );
170 
171 	/* If all ok, popdown and tell our parent.
172 	 */
173 	if( result == IWINDOW_YES ) {
174 		/* Unless we're pinned up, that is.
175 		 */
176 		if( !(idlg->tog_pin &&
177 			gtk_toggle_button_get_active(
178 				GTK_TOGGLE_BUTTON( idlg->tog_pin ) )) ) {
179 			idialog_notify_parent( idlg, result );
180 			iwindow_kill( IWINDOW( idlg ) );
181 		}
182 	}
183 
184 	/* Alert on failure.
185 	 */
186 	if( result == IWINDOW_ERROR )
187 		iwindow_alert( GTK_WIDGET( idlg ), GTK_MESSAGE_ERROR );
188 
189 	/* Clean up.
190 	 */
191 	iwindow_notify_return( IWINDOW( idlg ) );
192 }
193 
194 /* Make a DONE event happen. Used (for example) by the browse window to force
195  * a done in the enclosing FSB on double click on icon.
196  */
197 void
idialog_done_trigger(iDialog * idlg,int pos)198 idialog_done_trigger( iDialog *idlg, int pos )
199 {
200 	OKButton *ok = (OKButton *) g_slist_nth_data( idlg->ok_disp_l, pos );
201 
202 #ifdef DEBUG
203 	printf( "idialog_done_trigger: %s, %d\n",
204 		IWINDOW( idlg )->title, pos );
205 #endif /*DEBUG*/
206 
207 	/* Trigger user done callback.
208 	 */
209 	g_assert( pos >= 0 );
210 	g_assert( ok->done_cb );
211 	idialog_set_button_state( idlg, FALSE );
212 	iwindow_notify_send( IWINDOW( idlg ),
213 		ok->done_cb, idlg->client, idialog_done_notify, idlg );
214 }
215 
216 /* Sub-fn of below.
217  */
218 static void
idialog_cancel_notify(void * sys,iWindowResult result)219 idialog_cancel_notify( void *sys, iWindowResult result )
220 {
221 	iDialog *idlg = IDIALOG( sys );
222 
223 #ifdef DEBUG
224 	printf( "idialog_cancel_notify: %s\n", IWINDOW( idlg )->title );
225 #endif /*DEBUG*/
226 
227 	idialog_set_button_state( idlg, TRUE );
228 
229 	/* Send cancel message back to parent if our client cancel was OK.
230 	 */
231 	if( result == IWINDOW_YES ) {
232 		idialog_notify_parent( idlg, IWINDOW_NO );
233 		iwindow_kill( IWINDOW( idlg ) );
234 	}
235 
236 	/* Alert on error.
237 	 */
238 	if( result == IWINDOW_ERROR )
239 		iwindow_alert( GTK_WIDGET( idlg ), GTK_MESSAGE_ERROR );
240 
241 	/* Clean up.
242 	 */
243 	iwindow_notify_return( IWINDOW( idlg ) );
244 }
245 
246 static void
idialog_cancel_trigger(iDialog * idlg)247 idialog_cancel_trigger( iDialog *idlg )
248 {
249 #ifdef DEBUG
250         printf( "idialog_cancel_trigger: %s\n", IWINDOW( idlg )->title );
251 #endif /*DEBUG*/
252 
253         /* Trigger user cancel function.
254          */
255 	idialog_set_button_state( idlg, FALSE );
256         iwindow_notify_send( IWINDOW( idlg ),
257 		idlg->cancel_cb, idlg->client, idialog_cancel_notify, idlg );
258 }
259 
260 /* Button callbacks from gtk.
261  */
262 static void
idialog_done_cb(GtkWidget * w,iDialog * idlg)263 idialog_done_cb( GtkWidget *w, iDialog *idlg )
264 {
265 	int pos = g_slist_index( idlg->ok_but_l, w );
266 
267 	g_assert( pos != -1 );
268 
269 	idialog_done_trigger( idlg, pos );
270 }
271 
272 static void
idialog_cancel_cb(GtkWidget * w,iDialog * idlg)273 idialog_cancel_cb( GtkWidget *w, iDialog *idlg )
274 {
275 	idialog_cancel_trigger( idlg );
276 }
277 
278 static void
idialog_help_cb(GtkWidget * w,iDialog * idlg)279 idialog_help_cb( GtkWidget *w, iDialog *idlg )
280 {
281 	if( idlg->help_tag )
282 		box_help( GTK_WIDGET( idlg ), idlg->help_tag );
283 }
284 
285 static void
idialog_destroy(GtkObject * object)286 idialog_destroy( GtkObject *object )
287 {
288 	iDialog *idlg;
289 
290 #ifdef DEBUG
291 	printf( "idialog_destroy\n" );
292 #endif /*DEBUG*/
293 
294 	g_return_if_fail( object != NULL );
295 	g_return_if_fail( IS_IDIALOG( object ) );
296 
297 	idlg = IDIALOG( object );
298 
299 #ifdef DEBUG
300 	printf( "... %s\n", IWINDOW( idlg )->title );
301 #endif /*DEBUG*/
302 
303 	/* My instance destroy stuff.
304 	 */
305 
306 	if( idlg->destroy_cb ) {
307 		idlg->destroy_cb( idlg, idlg->client );
308 		idlg->destroy_cb = NULL;
309 	}
310 
311 	FREESID( idlg->destroy_sid, idlg->iobject );
312 	slist_map( idlg->ok_l, (SListMapFn) okbutton_free, NULL );
313 	IM_FREEF( g_slist_free, idlg->ok_l );
314 	IM_FREEF( g_slist_free, idlg->ok_disp_l );
315 	IM_FREEF( g_slist_free, idlg->ok_but_l );
316 
317 	GTK_OBJECT_CLASS( parent_class )->destroy( object );
318 }
319 
320 static void
idialog_realize(GtkWidget * widget)321 idialog_realize( GtkWidget *widget )
322 {
323 	iDialog *idlg = IDIALOG( widget );
324 
325 #ifdef DEBUG
326 	printf( "idialog_realize: %s\n", IWINDOW( idlg )->title );
327 #endif /*DEBUG*/
328 
329 	GTK_WIDGET_CLASS( parent_class )->realize( widget );
330 
331 	if( idlg->entry )
332 		gtk_widget_grab_focus( GTK_WIDGET( idlg->entry ) );
333 }
334 
335 /* The object we represent has been destroyed, kill us too.
336  */
337 static void
idialog_iobject_destroy(iObject * iobject,iDialog * idlg)338 idialog_iobject_destroy( iObject *iobject, iDialog *idlg )
339 {
340 #ifdef DEBUG
341 	printf( "idialog_iobject_destroy: %s\n", IWINDOW( idlg )->title );
342 #endif /*DEBUG*/
343 
344 	/* This object has gone.
345 	 */
346 	idlg->iobject = NULL;
347 
348 	iwindow_kill( IWINDOW( idlg ) );
349 }
350 
351 static void *
idialog_build_ok(OKButton * ok,iDialog * idlg)352 idialog_build_ok( OKButton *ok, iDialog *idlg )
353 {
354 	GtkWidget *but;
355 
356 	but = build_button( ok->label,
357 		GTK_SIGNAL_FUNC( idialog_done_cb ), idlg );
358 	idlg->ok_disp_l = g_slist_prepend( idlg->ok_disp_l, ok );
359 	idlg->ok_but_l = g_slist_prepend( idlg->ok_but_l, but );
360 	gtk_box_pack_start( GTK_BOX( idlg->bb ), but, TRUE, TRUE, 0 );
361 	gtk_widget_show( but );
362 
363 	return( NULL );
364 }
365 
366 static void *
idialog_build_cancel(iDialog * idlg)367 idialog_build_cancel( iDialog *idlg )
368 {
369 	idlg->but_cancel = build_button( idlg->cancel_text,
370 		GTK_SIGNAL_FUNC( idialog_cancel_cb ), idlg );
371 	gtk_box_pack_start( GTK_BOX( idlg->bb ),
372 		idlg->but_cancel, TRUE, TRUE, 0 );
373 	gtk_widget_show( idlg->but_cancel );
374 
375 	return( NULL );
376 }
377 
378 /* Set a button to be the dialog default. Turn off button_focus for complex
379  * dialogs like file_chooser which have their on focus systems.
380  */
381 static void
idialog_set_default(iDialog * idlg,GtkWidget * widget)382 idialog_set_default( iDialog *idlg, GtkWidget *widget )
383 {
384 	if( idlg->button_focus )
385 		gtk_widget_grab_focus( widget );
386 
387 	GTK_WIDGET_SET_FLAGS( widget, GTK_CAN_DEFAULT );
388 	gtk_window_set_default( GTK_WINDOW( idlg ), widget );
389 }
390 
391 static void
idialog_build(GtkWidget * widget)392 idialog_build( GtkWidget *widget )
393 {
394 	iDialog *idlg = IDIALOG( widget );
395 	iWindow *iwnd = IWINDOW( idlg );
396 
397 #ifdef DEBUG
398 	printf( "idialog_build: %s\n", iwnd->title );
399 #endif /*DEBUG*/
400 
401 	/* Call all builds in superclasses.
402 	 */
403 	if( IWINDOW_CLASS( parent_class )->build )
404 		(*IWINDOW_CLASS( parent_class )->build)( widget );
405 
406 	/* delete_event and destroy handled by our superclass.
407 	 */
408 	iwindow_set_popdown( iwnd, idialog_popdown_cb, idlg );
409 
410         gtk_window_set_modal( GTK_WINDOW( idlg ), idlg->modal );
411 
412         idlg->work = gtk_vbox_new( FALSE, 6 );
413         gtk_container_set_border_width( GTK_CONTAINER( idlg->work ), 12 );
414         gtk_box_pack_start( GTK_BOX( iwnd->work ), idlg->work, TRUE, TRUE, 0 );
415 
416 	if( !idlg->nosep ) {
417 		GtkWidget *sep;
418 
419 		sep = gtk_hseparator_new();
420 		gtk_box_pack_start( GTK_BOX( iwnd->work ),
421 			sep, FALSE, FALSE, 2 );
422 		gtk_widget_show( sep );
423 	}
424 
425 	idlg->hb = gtk_hbox_new( FALSE, 6 );
426         gtk_container_set_border_width( GTK_CONTAINER( idlg->hb ), 12 );
427         gtk_box_pack_start( GTK_BOX( iwnd->work ), idlg->hb, FALSE, FALSE, 0 );
428         gtk_widget_show( idlg->hb );
429 
430 	if( idlg->pinup ) {
431 		idlg->tog_pin = gtk_check_button_new_with_label(
432 			_( "Pin up" ) );
433 		set_tooltip( idlg->tog_pin,
434 			_( "Check this to pin the dialog up" ) );
435                 gtk_box_pack_start( GTK_BOX( idlg->hb ),
436                         idlg->tog_pin, FALSE, FALSE, 0 );
437 		gtk_widget_show( idlg->tog_pin );
438 	}
439 
440         idlg->bb = gtk_hbutton_box_new();
441         gtk_button_box_set_layout( GTK_BUTTON_BOX( idlg->bb ),
442 		GTK_BUTTONBOX_END );
443 	gtk_box_set_spacing( GTK_BOX( idlg->bb ), 6 );
444         gtk_box_pack_end( GTK_BOX( idlg->hb ), idlg->bb, FALSE, FALSE, 0 );
445         gtk_widget_show( idlg->bb );
446 
447 	/* Default button order:
448 	 *
449 	 * Help        OK3 OK2 Cancel OK1
450 	 *
451 	 * win32 button order:
452 	 *
453 	 * OK1 OK2 OK3 Cancel Help
454 	 */
455 
456 #ifdef OS_WIN32
457 
458 	/* OK buttons.
459 	 */
460 	slist_map( idlg->ok_l,
461 		(SListMapFn) idialog_build_ok, idlg );
462 
463         if( idlg->cancel_cb ) {
464 		idialog_build_cancel( idlg );
465 
466 		/* Cancel grabs default if it's the only button. Set focus
467 		 * too; user build can change this later.
468 		 */
469                 if( !idlg->ok_l )
470 			idialog_set_default( idlg, idlg->but_cancel );
471 	}
472 
473         if( idlg->help_tag ) {
474                 idlg->but_help = build_button( GTK_STOCK_HELP,
475 			GTK_SIGNAL_FUNC( idialog_help_cb ), idlg );
476                 gtk_widget_show( idlg->but_help );
477         }
478 
479 #else /*!OS_WIN32*/
480 
481         if( idlg->help_tag ) {
482                 idlg->but_help = build_button( GTK_STOCK_HELP,
483 			GTK_SIGNAL_FUNC( idialog_help_cb ), idlg );
484                 gtk_box_pack_end( GTK_BOX( idlg->bb ),
485                         idlg->but_help, TRUE, TRUE, 0 );
486 		gtk_button_box_set_child_secondary( GTK_BUTTON_BOX( idlg->bb ),
487 			idlg->but_help, TRUE );
488                 gtk_widget_show( idlg->but_help );
489         }
490 
491 	/* Add OK2, 3, etc.
492 	 */
493 	if( idlg->ok_l && idlg->ok_l->next )
494 		slist_map_rev( idlg->ok_l->next,
495 			(SListMapFn) idialog_build_ok, idlg );
496 
497         if( idlg->cancel_cb ) {
498 		idialog_build_cancel( idlg );
499 
500 		/* Cancel grabs default if it's the only button. Set focus
501 		 * too; user build can change this later.
502 		 */
503                 if( !idlg->ok_l )
504 			idialog_set_default( idlg, idlg->but_cancel );
505 	}
506 
507 	/* Make OK1
508 	 */
509 	if( idlg->ok_l ) {
510 		OKButton *ok1 = (OKButton *) idlg->ok_l->data;
511 
512 		idialog_build_ok( ok1, idlg );
513 	}
514 
515 #endif /*lots*/
516 
517 	/* OK1 grabs the default.
518 	 */
519 	if( idlg->ok_but_l )
520 		idialog_set_default( idlg, idlg->ok_but_l->data );
521 
522 	/* Escape triggers cancel, if there is a cancel.
523 	 */
524 	if( idlg->cancel_cb )
525 		gtk_widget_add_accelerator( idlg->but_cancel,
526 			"clicked", iwnd->accel_group, GDK_Escape, 0, 0 );
527 	else {
528 		/* If there's just 1 OK, that gets Esc too.
529 		 */
530 		if( idlg->ok_but_l &&
531 			g_slist_length( idlg->ok_but_l ) == 1 )
532 			gtk_widget_add_accelerator(
533 				GTK_WIDGET( idlg->ok_but_l->data ), "clicked",
534 				iwnd->accel_group, GDK_Escape, 0, 0 );
535 	}
536 
537 	/* F1 triggers help.
538 	 */
539 	if( idlg->but_help )
540 		gtk_widget_add_accelerator(
541 			idlg->but_help,
542 			"clicked", iwnd->accel_group, GDK_F1, 0, 0 );
543 
544 	/* Build user dialog contents.
545 	 */
546 	if( idlg->build )
547 		idlg->build( iwnd, idlg->work,
548 			idlg->build_a, idlg->build_b, idlg->build_c );
549 
550 	if( idlg->iobject )
551 		idlg->destroy_sid = g_signal_connect( idlg->iobject, "destroy",
552 			G_CALLBACK( idialog_iobject_destroy ), idlg );
553 
554         gtk_widget_show( idlg->work );
555 }
556 
557 static void
idialog_class_init(iDialogClass * class)558 idialog_class_init( iDialogClass *class )
559 {
560 	GtkObjectClass *object_class = (GtkObjectClass *) class;
561 	GtkWidgetClass *widget_class = (GtkWidgetClass *) class;
562 	iWindowClass *iwindow_class = (iWindowClass *) class;
563 
564 	parent_class = g_type_class_peek_parent( class );
565 
566 	object_class->destroy = idialog_destroy;
567 
568 	widget_class->realize = idialog_realize;
569 
570 	iwindow_class->build = idialog_build;
571 	iwindow_class->transient = TRUE;
572 
573 	/* Create signals.
574 	 */
575 
576 	/* Init methods.
577 	 */
578 }
579 
580 static void
idialog_init(iDialog * idlg)581 idialog_init( iDialog *idlg )
582 {
583 #ifdef DEBUG
584 	printf( "idialog_init: %s\n", IWINDOW( idlg )->title );
585 #endif /*DEBUG*/
586 
587 	/* Init our instance fields.
588 	 */
589 	idlg->iobject = NULL;
590         idlg->destroy_sid = 0;
591 
592 	idlg->work = NULL;
593 
594 	idlg->ok_l = NULL;
595 	idlg->ok_disp_l = NULL;
596 	idlg->ok_but_l = NULL;
597 
598 	idlg->but_cancel = NULL;
599 	idlg->but_help = NULL;
600 	idlg->tog_pin = NULL;
601 
602 	idlg->entry = NULL;
603 
604 	idlg->modal = FALSE;
605 	idlg->pinup = FALSE;
606 	idlg->nosep = FALSE;
607 	idlg->button_focus = TRUE;
608 
609 	idlg->help_tag = NULL;
610 
611 	idlg->cancel_text = GTK_STOCK_CANCEL;
612 
613 	idlg->cancel_cb = NULL;
614 	idlg->popdown_cb = NULL;
615 	idlg->destroy_cb = NULL;
616 	idlg->client = NULL;
617 
618 	idlg->arg = NULL;
619 
620 	idlg->nfn = iwindow_notify_null;
621 	idlg->sys = NULL;
622 
623 	gtk_window_set_position( GTK_WINDOW( idlg ),
624 		GTK_WIN_POS_CENTER_ON_PARENT );
625 }
626 
627 GtkType
idialog_get_type(void)628 idialog_get_type( void )
629 {
630 	static GtkType type = 0;
631 
632 	if( !type ) {
633 		static const GtkTypeInfo info = {
634 			"iDialog",
635 			sizeof( iDialog ),
636 			sizeof( iDialogClass ),
637 			(GtkClassInitFunc) idialog_class_init,
638 			(GtkObjectInitFunc) idialog_init,
639 			/* reserved_1 */ NULL,
640 			/* reserved_2 */ NULL,
641 			(GtkClassInitFunc) NULL,
642 		};
643 
644 		type = gtk_type_unique( TYPE_IWINDOW, &info );
645 	}
646 
647 	return( type );
648 }
649 
650 GtkWidget *
idialog_new()651 idialog_new()
652 {
653 	iDialog *idlg = gtk_type_new( TYPE_IDIALOG );
654 	GtkWindow *gwnd = GTK_WINDOW( idlg );
655 
656 	/* Init gtk base class.
657 	 */
658 	gwnd->type = GTK_WINDOW_TOPLEVEL;
659 
660 	return( GTK_WIDGET( idlg ) );
661 }
662 
663 void
idialog_set_iobject(iDialog * idlg,iObject * iobject)664 idialog_set_iobject( iDialog *idlg, iObject *iobject )
665 {
666 	idlg->iobject = iobject;
667 }
668 
669 void
idialog_set_pinup(iDialog * idlg,gboolean pinup)670 idialog_set_pinup( iDialog *idlg, gboolean pinup )
671 {
672 	idlg->pinup = pinup;
673 
674 	if( idlg->tog_pin )
675 		gtk_toggle_button_set_active(
676 			GTK_TOGGLE_BUTTON( idlg->tog_pin ), TRUE );
677 }
678 
679 void
idialog_set_modal(iDialog * idlg,gboolean modal)680 idialog_set_modal( iDialog *idlg, gboolean modal )
681 {
682 	idlg->modal = modal;
683 }
684 
685 void
idialog_set_nosep(iDialog * idlg,gboolean nosep)686 idialog_set_nosep( iDialog *idlg, gboolean nosep )
687 {
688 	idlg->nosep = nosep;
689 }
690 
691 void
idialog_set_button_focus(iDialog * idlg,gboolean button_focus)692 idialog_set_button_focus( iDialog *idlg, gboolean button_focus )
693 {
694 	idlg->button_focus = button_focus;
695 }
696 
697 void
idialog_set_help_tag(iDialog * idlg,const char * help_tag)698 idialog_set_help_tag( iDialog *idlg, const char *help_tag )
699 {
700 	IM_SETSTR( idlg->help_tag, help_tag );
701 }
702 
703 void
idialog_set_callbacks(iDialog * idlg,iWindowFn cancel_cb,iWindowFn popdown_cb,iDialogFreeFn destroy_cb,void * client)704 idialog_set_callbacks( iDialog *idlg,
705 	iWindowFn cancel_cb, iWindowFn popdown_cb,
706 	iDialogFreeFn destroy_cb, void *client )
707 {
708 	idlg->cancel_cb = cancel_cb;
709 	idlg->popdown_cb = popdown_cb;
710 	idlg->destroy_cb = destroy_cb;
711 	idlg->client = client;
712 }
713 
714 void
idialog_add_ok(iDialog * idlg,iWindowFn done_cb,const char * fmt,...)715 idialog_add_ok( iDialog *idlg, iWindowFn done_cb, const char *fmt, ... )
716 {
717 	va_list ap;
718 	char buf[1024];
719 
720         va_start( ap, fmt );
721         (void) im_vsnprintf( buf, 1024, fmt, ap );
722         va_end( ap );
723 
724 	/* So the last OK button added is the default one (and at the head of
725 	 * the list). [OK1, OK2, OK3, OK4]
726 	 */
727 	idlg->ok_l = g_slist_prepend( idlg->ok_l,
728 		okbutton_new( buf, done_cb ) );
729 }
730 
731 void
idialog_set_notify(iDialog * idlg,iWindowNotifyFn nfn,void * sys)732 idialog_set_notify( iDialog *idlg, iWindowNotifyFn nfn, void *sys )
733 {
734 	idlg->nfn = nfn;
735 	idlg->sys = sys;
736 }
737 
738 void
idialog_set_build(iDialog * idlg,iWindowBuildFn build,void * build_a,void * build_b,void * build_c)739 idialog_set_build( iDialog *idlg,
740 	iWindowBuildFn build, void *build_a, void *build_b, void *build_c )
741 {
742 	idlg->build = build;
743 	idlg->build_a = build_a;
744 	idlg->build_b = build_b;
745 	idlg->build_c = build_c;
746 }
747 
748 void
idialog_set_cancel_text(iDialog * idlg,const char * cancel_text)749 idialog_set_cancel_text( iDialog *idlg, const char *cancel_text )
750 {
751 	idlg->cancel_text = cancel_text;
752 }
753 
754 void
idialog_set_default_entry(iDialog * idlg,GtkEntry * entry)755 idialog_set_default_entry( iDialog *idlg, GtkEntry *entry )
756 {
757 	gtk_entry_set_activates_default( entry, TRUE );
758 	idlg->entry = entry;
759 }
760 
761 /* Set up an entry inside a dialog ... set tooltip, set start
762  * value, link to OK button in enclosing dialog.
763  */
764 void
idialog_init_entry(iDialog * idlg,GtkWidget * entry,const char * tip,const char * fmt,...)765 idialog_init_entry( iDialog *idlg, GtkWidget *entry,
766 	const char *tip, const char *fmt, ... )
767 {
768 	va_list ap;
769 
770 	va_start( ap, fmt );
771         set_gentryv( entry, fmt, ap );
772 	va_end( ap );
773         set_tooltip( entry, "%s", tip );
774 	idialog_set_default_entry( idlg, GTK_ENTRY( entry ) );
775 }
776