-fpermissive to allow GCC to compile old C++
[oweals/cde.git] / cde / programs / dtmail / MotifApp / DialogManager.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: DialogManager.C /main/5 1996/04/21 19:32:05 drk $ */
24 /*
25  *+SNOTICE
26  *
27  *      $XConsortium: DialogManager.C /main/5 1996/04/21 19:32:05 drk $
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *      
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement bertween
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35  *      Sun's specific written approval.  This documment and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  *+ENOTICE
42  */
43
44 ///////////////////////////////////////////////////////////////////////////////
45 //////////////////////////////////////////////////////////////////////////////
46 //         This example code is from the book:
47 //
48 //           Object-Oriented Programming with C++ and OSF/Motif
49 //         by
50 //           Douglas Young
51 //           Prentice Hall, 1992
52 //           ISBN 0-13-630252-1 
53 //
54 //         Copyright 1991 by Prentice Hall
55 //         All Rights Reserved
56 //
57 //  Permission to use, copy, modify, and distribute this software for 
58 //  any purpose except publication and without fee is hereby granted, provided 
59 //  that the above copyright notice appear in all copies of the software.
60 ///////////////////////////////////////////////////////////////////////////////
61 //////////////////////////////////////////////////////////////////////////////
62
63
64 //////////////////////////////////////////////////////////
65 // DialogManager.C: Support cached dialog widgets
66 //////////////////////////////////////////////////////////
67 #include "DialogManager.h"
68 #include "Application.h"
69 #include <Xm/MessageB.h>
70 #include <assert.h>
71
72 #include <nl_types.h>
73 extern nl_catd catd;
74
75 #include "NLS.hh"
76
77 DialogManager::DialogManager ( char   *name ): UIComponent ( name )
78 {
79     // Empty
80 }
81
82 Widget DialogManager::getDialog()
83 {
84     Widget newDialog = NULL;
85     
86     // If the permanent widget exists and is not in use,
87     // just return it
88     
89     if ( _w && !XtIsManaged ( _w ) )
90         return _w;
91     
92     // Get a widget from the derived class
93     
94     newDialog = createDialog ( theApplication->baseWidget() ) ;
95     
96     // If this is a temporary dialog, install callbacks to 
97     // destroy it when the user pops it down.
98     
99     if ( _w )
100     {
101         XtAddCallback ( newDialog, 
102                        XmNokCallback, 
103                        &DialogManager::destroyTmpDialogCallback,
104                        (XtPointer) this );
105         
106         XtAddCallback ( newDialog, 
107                        XmNcancelCallback, 
108                        &DialogManager::destroyTmpDialogCallback,
109                        (XtPointer) this );
110     }
111     else                 // If this is the first dialog to be 
112         _w = newDialog;  // created, save it to be used again.
113     
114     return newDialog;
115 }
116
117 Widget DialogManager::getDialog(
118     Widget w
119 )
120 {
121     Widget newDialog = NULL;
122     
123     // If the permanent widget exists and is not in use,
124     // just return it
125     
126     if ( _w && !XtIsManaged ( _w ) )
127         return _w;
128     
129     // Get a widget from the derived class
130     // Parent the dialog to the widget passed in
131     
132     newDialog = createDialog (w);
133     
134     // If this is a temporary dialog, install callbacks to 
135     // destroy it when the user pops it down.
136     
137     if ( _w )
138     {
139         XtAddCallback ( newDialog, 
140                        XmNokCallback, 
141                        &DialogManager::destroyTmpDialogCallback,
142                        (XtPointer) this );
143         
144         XtAddCallback ( newDialog, 
145                        XmNcancelCallback, 
146                        &DialogManager::destroyTmpDialogCallback,
147                        (XtPointer) this );
148     }
149     else                 // If this is the first dialog to be 
150         _w = newDialog;  // created, save it to be used again.
151     
152     return newDialog;
153 }
154
155 void DialogManager::destroyTmpDialogCallback ( Widget     w, 
156                                               XtPointer,
157                                               XtPointer clientData)
158 {
159     XtDestroyWidget ( w );
160
161     // We must set the wiget handle to NULL to prevent multiple
162     // destroys.
163     ((DialogManager *)clientData)->_w = NULL;
164 }
165
166 Widget DialogManager::post (char          *title,
167                             char          *text,
168                             Widget         wid,
169                             void          *clientData,
170                             DialogCallback ok,
171                             DialogCallback cancel,
172                             DialogCallback help)
173 {
174     // Get a dialog widget from the cache
175     
176     Widget dialog = getDialog(wid);
177     
178     // Make sure the dialog exists, and that it is an XmMessageBox
179     // or subclass, since the callbacks assume this widget type
180     
181     assert ( dialog != NULL );
182 //    assert ( XtIsSubclass ( dialog, xmMessageBoxWidgetClass ) );
183         
184         // Convert the text string to a compound string and 
185         // specify this to be the message displayed in the dialog.
186         
187     XmString titleStr = XmStringCreateLocalized (title);
188     XmString xmstr = XmStringCreateLocalized ( text );
189     XtVaSetValues ( dialog, 
190                     XmNmessageString, xmstr,
191                     XmNdialogTitle, titleStr,
192                     NULL );
193     XmStringFree ( xmstr );
194     XmStringFree ( titleStr );
195     
196     // Create an object to carry the additional data needed
197     // to cache the dialogs.
198     
199     DialogCallbackData *dcb = new DialogCallbackData( this, 
200                                                      clientData,
201                                                      ok, cancel, 
202                                                      help );
203     // Install callback function for each button 
204     // support by Motif dialogs. If there is no help callback
205     // unmanage the corresponding button instead, if possible.
206
207     if ( ok )
208       XtAddCallback ( dialog, 
209                       XmNokCallback, 
210                       &DialogManager::okCallback,
211                       (XtPointer) dcb );
212     else
213       {
214         Widget w = XmMessageBoxGetChild ( dialog,
215                                           XmDIALOG_OK_BUTTON );
216         XtUnmanageChild ( w );
217       }
218
219
220     if ( cancel )
221       XtAddCallback ( dialog, 
222                       XmNcancelCallback, 
223                       &DialogManager::cancelCallback,
224                       (XtPointer) dcb );
225     else
226       {
227         Widget w = XmMessageBoxGetChild ( dialog,
228                                           XmDIALOG_CANCEL_BUTTON );
229         XtUnmanageChild ( w );
230       }
231     
232     
233     if ( help )     
234         XtAddCallback ( dialog, 
235                        XmNhelpCallback, 
236                        &DialogManager::helpCallback,
237                        (XtPointer) dcb );
238     else
239     {
240         Widget w = XmMessageBoxGetChild ( dialog,
241                                          XmDIALOG_HELP_BUTTON );
242         XtUnmanageChild ( w );
243     }
244     
245     // Post the dialog.
246     
247     XtManageChild ( dialog );
248
249     
250     return dialog;
251 }
252
253 Widget DialogManager::post (char          *title,
254                             char          *text,
255                             void          *clientData,
256                             DialogCallback ok,
257                             DialogCallback cancel,
258                             DialogCallback help)
259 {
260     // Get a dialog widget from the cache
261     
262     Widget dialog = getDialog();
263     
264     // Make sure the dialog exists, and that it is an XmMessageBox
265     // or subclass, since the callbacks assume this widget type
266     
267     assert ( dialog != NULL );
268 //    assert ( XtIsSubclass ( dialog, xmMessageBoxWidgetClass ) );
269         
270         // Convert the text string to a compound string and 
271         // specify this to be the message displayed in the dialog.
272         
273     XmString titleStr = XmStringCreateLocalized (title);
274     XmString xmstr = XmStringCreateLocalized ( text );
275     XtVaSetValues ( dialog, 
276                     XmNmessageString, xmstr,
277                     XmNdialogTitle, titleStr,
278                     NULL );
279     XmStringFree ( xmstr );
280     XmStringFree ( titleStr );
281     
282     // Create an object to carry the additional data needed
283     // to cache the dialogs.
284     
285     DialogCallbackData *dcb = new DialogCallbackData( this, 
286                                                      clientData,
287                                                      ok, cancel, 
288                                                      help );
289     // Install callback function for each button 
290     // support by Motif dialogs. If there is no help callback
291     // unmanage the corresponding button instead, if possible.
292
293     if ( ok )
294       XtAddCallback ( dialog, 
295                       XmNokCallback, 
296                       &DialogManager::okCallback,
297                       (XtPointer) dcb );
298     else
299       {
300         Widget w = XmMessageBoxGetChild ( dialog,
301                                           XmDIALOG_OK_BUTTON );
302         XtUnmanageChild ( w );
303       }
304
305
306     if ( cancel )
307       XtAddCallback ( dialog, 
308                       XmNcancelCallback, 
309                       &DialogManager::cancelCallback,
310                       (XtPointer) dcb );
311     else
312       {
313         Widget w = XmMessageBoxGetChild ( dialog,
314                                           XmDIALOG_CANCEL_BUTTON );
315         XtUnmanageChild ( w );
316       }
317     
318     
319     if ( help )     
320         XtAddCallback ( dialog, 
321                        XmNhelpCallback, 
322                        &DialogManager::helpCallback,
323                        (XtPointer) dcb );
324     else
325     {
326         Widget w = XmMessageBoxGetChild ( dialog,
327                                          XmDIALOG_HELP_BUTTON );
328         XtUnmanageChild ( w );
329     }
330     
331     // Post the dialog.
332     
333     XtManageChild ( dialog );
334
335     
336     return dialog;
337 }
338
339 void DialogManager::okCallback ( Widget    w, 
340                                 XtPointer clientData,
341                                 XtPointer )
342 {
343     DialogCallbackData *dcd = (DialogCallbackData *) clientData;
344     DialogManager      *obj = (DialogManager *) dcd->dialogManager();
345     DialogCallback      callback;
346     
347     // If caller specified an ok callback, call the function
348     
349     if ( ( callback = dcd->ok() ) != NULL )
350         ( *callback )( dcd->clientData() );
351     
352     // Reset for the next time
353     
354     obj->cleanup ( w, dcd );
355 }
356
357 void DialogManager::cancelCallback ( Widget    w, 
358                                     XtPointer clientData,
359                                     XtPointer )
360 {
361     DialogCallbackData *dcd = (DialogCallbackData *) clientData;
362     DialogManager      *obj = (DialogManager *) dcd->dialogManager();
363     DialogCallback      callback;
364     
365     if ( ( callback = dcd->cancel() ) != NULL )
366         ( *callback )( dcd->clientData() );
367     
368     obj->cleanup ( w, dcd );
369 }
370
371 void DialogManager::helpCallback ( Widget    w, 
372                                   XtPointer clientData,
373                                   XtPointer )
374 {
375     DialogCallbackData *dcd = (DialogCallbackData *) clientData;
376     DialogManager      *obj = (DialogManager *) dcd->dialogManager();
377     DialogCallback      callback;
378     
379     if ( ( callback = dcd->help() ) != NULL )
380         ( *callback )( dcd->clientData() );
381     
382     obj->cleanup ( w, dcd );
383 }
384
385 void DialogManager::cleanup ( Widget w, DialogCallbackData *dcd )
386 {
387     // Remove all callbacks to avoid having duplicate 
388     // callback functions installed.
389     
390     XtRemoveCallback ( w, 
391                       XmNokCallback, 
392                       &DialogManager::okCallback,
393                       (XtPointer) dcd );
394     
395     XtRemoveCallback ( w, 
396                       XmNcancelCallback, 
397                       &DialogManager::cancelCallback,
398                       (XtPointer) dcd );
399     
400     XtRemoveCallback ( w, 
401                       XmNhelpCallback, 
402                       &DialogManager::helpCallback,
403                       (XtPointer) dcd );
404     
405     // Delete the DialogCallbackData instance for this posting
406     
407     delete dcd;
408 }
409
410 void
411 DialogManager::forceUpdate( Widget w )
412 {
413   Widget diashell, topshell;
414   Window diawindow, topwindow;
415
416   Display               *dpy;
417   XWindowAttributes     xwa;
418   XEvent                event;
419   if ( !w )
420     return;
421   XtAppContext cxt=XtWidgetToApplicationContext( w );
422   for (diashell=w;!XtIsShell(diashell);diashell=XtParent(diashell));
423   for ( topshell=diashell;XtIsTopLevelShell( topshell );
424         topshell = XtParent( topshell ) );
425
426 //  if (XtIsRealized(diashell) && XtIsRealized(topshell)){
427     dpy=XtDisplay(diashell);
428     diawindow=XtWindow(diashell);
429     topwindow=XtWindow(topshell);
430     while ( XGetWindowAttributes(dpy,diawindow,&xwa) && 
431             xwa.map_state != IsViewable && XEventsQueued(dpy,QueuedAlready)){
432 //      if ( XGetWindowAttributes( dpy, topwindow, &xwa ) &&
433 //         xwa.map_state != IsViewable )
434 //        break;
435       XtAppNextEvent( cxt, &event );
436       XtDispatchEvent( &event );
437     }
438 //  }
439   XmUpdateDisplay(topshell);
440 }
441
442
443
444 // Added this extra functionality
445
446 void
447 my_okCallback( int *data )
448 {
449     *data=1;
450 }
451
452 void
453 my_cancelCallback( int *data )
454 {
455     *data=2;
456 }
457
458 int
459 DialogManager::post_and_return(
460         char *title_str, 
461         char *text_str,
462         Widget wid
463 )
464 {
465     int answer = 0;
466     XmString okLabel, cancelLabel;
467
468     // They may have been set via the overloaded post_and_return()
469     // method before. Reset them to their default values...
470
471     okLabel = XmStringCreateLocalized(GETMSG(catd, 1, 2, "OK"));
472     cancelLabel = XmStringCreateLocalized(GETMSG(catd, 1, 3, "Cancel"));
473
474     Widget dlg = this->getDialog(wid);
475
476     // Make sure the dialog exists, and that it is an XmMessageBox
477     // or subclass, since the callbacks assume this widget type
478     
479     assert ( dlg != NULL );
480
481     XtVaSetValues(dlg,
482                   XmNokLabelString, okLabel,
483                   XmNcancelLabelString, cancelLabel,
484                   NULL);
485
486     Widget dialog =
487         this->post(title_str,
488                    text_str,
489                    wid,
490                    (void *) &answer,
491                    ( DialogCallback ) &my_okCallback,
492                    ( DialogCallback ) &my_cancelCallback);
493
494     forceUpdate( dialog );
495     while ( answer==0 ) 
496         XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
497
498     // Process just one more event to pop down dialog.
499     XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
500
501     return(answer);
502
503 }
504
505 int
506 DialogManager::post_and_return(
507         char *title_str, 
508         char *text_str,
509         char *okLabelString,
510         Widget wid
511 )
512 {
513     int answer = 0;
514     XmString okLabel;
515
516     okLabel = XmStringCreateLocalized(okLabelString);
517
518     Widget dlg = this->getDialog(wid);
519
520     // Make sure the dialog exists, and that it is an XmMessageBox
521     // or subclass, since the callbacks assume this widget type
522     
523     assert ( dlg != NULL );
524
525     XtVaSetValues(dlg,
526                   XmNokLabelString, okLabel,
527                   NULL);
528
529     Widget dialog = this->post(title_str,
530                                text_str,
531                                wid,
532                                (void *) &answer,
533                                ( DialogCallback ) &my_okCallback);
534
535     forceUpdate( dialog );
536     while ( answer==0 ) 
537         XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
538
539     // Process just one more event to pop down dialog.
540     XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
541
542     return(answer);
543
544 }
545
546 int
547 DialogManager::post_and_return(
548         char *title_str, 
549         char *text_str,
550         char *okLabelString,
551         char *cancelLabelString,
552         Widget wid
553
554 )
555 {
556     int answer = 0;
557     XmString okLabel, cancelLabel;
558
559     okLabel = XmStringCreateLocalized(okLabelString);
560     cancelLabel = XmStringCreateLocalized(cancelLabelString);
561
562     Widget dlg = this->getDialog(wid);
563
564     // Make sure the dialog exists, and that it is an XmMessageBox
565     // or subclass, since the callbacks assume this widget type
566     
567     assert ( dlg != NULL );
568
569     XtVaSetValues(dlg,
570                   XmNokLabelString, okLabel,
571                   XmNcancelLabelString, cancelLabel,
572                   NULL);
573
574     Widget dialog = this->post(title_str,
575                                text_str,
576                                wid,
577                                (void *) &answer,
578                                ( DialogCallback ) &my_okCallback,
579                                ( DialogCallback ) &my_cancelCallback);
580
581     forceUpdate( dialog );
582     while ( answer==0 ) 
583         XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
584
585     // Process just one more event to pop down dialog.
586     XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll );
587
588     return(answer);
589
590 }
591
592
593