Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtprintinfo / libUI / MotifUI / Dialog.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: Dialog.C /main/3 1996/01/19 15:09:18 lehors $ */
24 /*                                                                      *
25  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
26  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
27  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
28  * (c) Copyright 1993, 1994 Novell, Inc.                                *
29  */
30
31 #include "Dialog.h"
32 #include "Prompt.h"
33 #include "Button.h"
34
35 #include <Xm/MessageB.h>
36 #include <Xm/Form.h>
37 #include <Xm/PushB.h>
38 #include <Xm/FileSB.h>
39 #include <Xm/AtomMgr.h>
40 #include <Xm/Protocols.h>
41 #include <Xm/MwmUtil.h>
42
43 #include <Xm/BulletinBP.h>
44
45 // Constructor for a generic dialog
46 Dialog::Dialog(MotifUI *parent, char *title, DialogType dialog_type,
47                boolean has_resize_controls, DialogCallback help_callback, 
48                void * help_callback_data, DialogCallback apply_callback, 
49                void * apply_callback_data, DialogCallback reset_callback, 
50                void * reset_callback_data, ValidationCallback CB,
51                void * validation_data)
52         : MotifUI(parent, title, NULL)
53 {
54    Arg args[10];
55    int n;
56    XmString xm_string = StringCreate(title);
57
58    _validation_callback = CB;
59    _validation_callback_data = validation_data;
60    _help_callback = help_callback;
61    _help_callback_data = help_callback_data;
62    _apply_callback = apply_callback;
63    _apply_callback_data = apply_callback_data;
64    _reset_callback = reset_callback;
65    _reset_callback_data = reset_callback_data;
66    _cancel_button = NULL;
67    _cancel_widget = NULL;
68
69    n = 0;
70    if (has_resize_controls == false)
71     {
72       long mwmDecorations;
73       mwmDecorations = (MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MENU);
74       XtSetArg(args[n], XmNmwmDecorations, mwmDecorations); n++;
75     }
76    XtSetArg(args[n], XmNdialogTitle, xm_string); n++;
77    XtSetArg(args[n], XmNmarginHeight, 5); n++;
78    XtSetArg(args[n], XmNmarginWidth, 5); n++;
79    XtSetArg(args[n], XmNallowShellResize, true); n++;
80    XtSetArg(args[n], XmNautoUnmanage, false); n++;
81    switch (_dialog_type = dialog_type)
82     {
83      default:
84      case MODELESS:
85      case INFORMATION:
86      case ERROR:
87      case WORK_IN_PROGRESS:
88        XtSetArg(args[n], XmNdialogStyle, XmDIALOG_MODELESS); n++;
89        _dialog_type = MODELESS;
90        break;
91      case MODAL:
92      case FILE_SELECTION:
93      case QUESTION:
94      case WARNING:
95      case PROMPT_DIALOG:
96      case MODAL_WORK_IN_PROGRESS:
97      case MODAL_ERROR:
98      case MODAL_INFORMATION:
99        XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
100        _dialog_type = MODAL;
101        break;
102     };
103
104    if (parent->UIClass() == APPLICATION)
105     {
106       XtSetArg(args[n], XmNdialogType, XmDIALOG_TEMPLATE); n++;
107       _w = XmCreateMessageBox(parent->InnerWidget(), title, args, n);
108       XtManageChild(_w);
109     }
110    else
111       _w = XmCreateTemplateDialog(parent->InnerWidget(), title, args, n);
112
113    _clientArea = XtVaCreateManagedWidget("form", xmFormWidgetClass, _w, NULL);
114
115    StringFree(xm_string);
116    XmAddWMProtocolCallback(XtParent(_w), 
117       XmInternAtom(display, "WM_DELETE_WINDOW", False), 
118       &Dialog::CloseCB, (XtPointer) this);
119    InstallHelpCB();
120 }
121
122 // Constructor for info, error, work-in-progress
123 Dialog::Dialog(MotifUI *parent, char *title, char *message, 
124                DialogType dialog_type, char *ok_label, char *cancel_label, 
125                char *help_label, DialogCallback help,
126                void * help_callback_data, char * /*icon*/)
127         : MotifUI(parent, title, NULL)
128 {
129    Arg args[15];
130    long mwmDecorations;
131    mwmDecorations = (MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MENU);
132
133    XmString xm_string = StringCreate(title);
134    XmString xm_message = StringCreate(message);
135    XmString ok_string = StringCreate(ok_label);
136    XmString cancel_string = StringCreate(cancel_label);
137    XmString help_string = StringCreate(help_label);
138
139    XtSetArg(args[0], XmNdialogTitle, xm_string);
140    XtSetArg(args[1], XmNmarginHeight, 5);
141    XtSetArg(args[2], XmNmarginWidth, 5);
142    XtSetArg(args[3], XmNallowShellResize, true);
143    XtSetArg(args[4], XmNautoUnmanage, false);
144    XtSetArg(args[5], XmNmessageString, xm_message);
145    XtSetArg(args[6], XmNmwmDecorations, mwmDecorations);
146    XtSetArg(args[7], XmNokLabelString, ok_string);
147    XtSetArg(args[8], XmNcancelLabelString, cancel_string);
148    XtSetArg(args[9], XmNhelpLabelString, help_string);
149    _help_callback = help;
150    _help_callback_data = help_callback_data;
151    _apply_callback = NULL;
152    _apply_callback_data = NULL;
153    _reset_callback = NULL;
154    _reset_callback_data = NULL;
155    switch (_dialog_type = dialog_type)
156     {
157      case INFORMATION:
158        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_MODELESS);
159        _w = XmCreateInformationDialog(parent->InnerWidget(), title, args, 11);
160        break;
161
162      case QUESTION:
163        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
164        _w = XmCreateQuestionDialog(parent->InnerWidget(), title, args, 11);
165        break;
166      case WARNING:
167        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
168        _w = XmCreateWarningDialog(parent->InnerWidget(), title, args, 11);
169        break;
170
171      case ERROR:
172        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_MODELESS);
173        _w = XmCreateErrorDialog(parent->InnerWidget(), title, args, 11);
174        break;
175
176      case WORK_IN_PROGRESS:
177        mwmDecorations = (MWM_DECOR_BORDER | MWM_DECOR_TITLE);
178        XtSetArg(args[6], XmNmwmDecorations, mwmDecorations);
179        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_MODELESS);
180        _w = XmCreateWorkingDialog(parent->InnerWidget(), title, args, 11);
181        break;
182
183      case MODAL_WORK_IN_PROGRESS:
184        mwmDecorations = (MWM_DECOR_BORDER | MWM_DECOR_TITLE);
185        XtSetArg(args[6], XmNmwmDecorations, mwmDecorations);
186        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
187        _w = XmCreateWorkingDialog(parent->InnerWidget(), title, args, 11);
188        break;
189
190      case MODAL_ERROR:
191        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
192        _w = XmCreateErrorDialog(parent->InnerWidget(), title, args, 11);
193        break;
194
195      case MODAL_INFORMATION:
196        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
197        _w = XmCreateInformationDialog(parent->InnerWidget(), title, args, 11);
198        break;
199
200      case MODAL:
201        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
202        _w = XmCreateMessageDialog(parent->InnerWidget(), title, args, 11);
203        break;
204
205      default:
206        _dialog_type = MODELESS;
207        XtSetArg(args[10], XmNdialogStyle, XmDIALOG_MODELESS);
208        _w = XmCreateMessageDialog(parent->InnerWidget(), title, args, 11);
209        break;
210     }
211
212    if (_dialog_type == QUESTION || _dialog_type == WARNING)
213       XtAddCallback(_w, XmNcancelCallback, &Dialog::DialogCB, (XtPointer) this);
214    else
215       XtUnmanageChild(XmMessageBoxGetChild(_w, XmDIALOG_CANCEL_BUTTON));
216    if (help)
217       XtAddCallback(_w, XmNhelpCallback, &Dialog::DialogCB, (XtPointer) this);
218    else
219       XtUnmanageChild(XmMessageBoxGetChild(_w, XmDIALOG_HELP_BUTTON));
220    if (_dialog_type == WORK_IN_PROGRESS ||
221        _dialog_type == MODAL_WORK_IN_PROGRESS)
222       XtUnmanageChild(XmMessageBoxGetChild(_w, XmDIALOG_OK_BUTTON));
223    else
224       XtAddCallback(_w, XmNokCallback, &Dialog::DialogCB, (XtPointer) this);
225    XmAddWMProtocolCallback(XtParent(_w), 
226       XmInternAtom(display, "WM_DELETE_WINDOW", False), 
227       &Dialog::CloseCB, (XtPointer) this);
228    InstallHelpCB();
229    StringFree(xm_string);
230    StringFree(xm_message);
231    StringFree(cancel_string);
232    StringFree(ok_string);
233    StringFree(help_string);
234    _clientArea = _w;
235 }
236
237 // Constructor for prompt
238 Dialog::Dialog(MotifUI *parent, char *title, char *caption, boolean editable,
239                PromptType prompt_type, char *default_value,
240                boolean echo_input, ValidationCallback validation_callback, 
241                void * validation_callback_data, DialogCallback help_callback,
242                void * help_callback_data, DialogCallback apply_callback, 
243                void * apply_callback_data, DialogCallback reset_callback, 
244                void * reset_callback_data, char *message, char *icon)
245         : MotifUI(parent, title, NULL)
246 {
247    Arg      args[8];
248    int      n;
249    XmString xm_string = StringCreate(title);
250    XmString xm_message;
251    Pixmap   pixmap;
252
253    _dialog_type = PROMPT_DIALOG;
254    _validation_callback = validation_callback;
255    _validation_callback_data = validation_callback_data;
256    _help_callback = help_callback;
257    _help_callback_data = help_callback_data;
258    _apply_callback = apply_callback;
259    _apply_callback_data = apply_callback_data;
260    _reset_callback = reset_callback;
261    _reset_callback_data = reset_callback_data;
262    n = 0;
263    XtSetArg(args[n], XmNdialogTitle, xm_string); n++;
264    XtSetArg(args[n], XmNmarginHeight, 5); n++;
265    XtSetArg(args[n], XmNmarginWidth, 5); n++;
266    XtSetArg(args[n], XmNallowShellResize, true); n++;
267    XtSetArg(args[n], XmNautoUnmanage, false); n++;
268    XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
269    if (message && *message)
270     {
271       xm_message = StringCreate(message);
272       XtSetArg(args[n], XmNmessageString, xm_message); n++;
273       if (icon && *icon)
274        {
275          pixmap = 0;
276          // XtSetArg(args[n], XmNsymbolPixmap, pixmap); n++;
277        }
278     }
279
280    _w = XmCreateMessageDialog(parent->InnerWidget(), title, args, n);
281    StringFree(xm_string);
282    if (xm_message && *message)
283        StringFree(xm_message);
284    if (help_callback)
285     {
286       XtAddCallback(_w, XmNhelpCallback, &Dialog::DialogCB, (XtPointer) this);
287     }
288    else
289     {
290       XtUnmanageChild(XmMessageBoxGetChild(_w, XmDIALOG_HELP_BUTTON));
291     }
292    _prompt = new Prompt(this, caption, editable, prompt_type, default_value,
293                         validation_callback, validation_callback_data,
294                         echo_input);
295    XmAddWMProtocolCallback(XtParent(_w), 
296       XmInternAtom(display, "WM_DELETE_WINDOW", False), 
297       &Dialog::CloseCB, (XtPointer) this);
298    InstallHelpCB();
299 }
300
301 // Constructor for file selection
302 Dialog::Dialog(MotifUI *parent, char *title, char *base_directory, 
303                char *search_pattern, DialogType dialog_type,
304                DialogCallback help, void * /*help_callback_data*/)
305         : MotifUI(parent, title, NULL)
306 {
307    Arg args[9];
308    XmString title_string = StringCreate(title);
309    XmString directory_string = StringCreate(base_directory);
310    XmString pattern_string = StringCreate(search_pattern);
311
312    XtSetArg(args[0], XmNdialogTitle, title_string);
313    XtSetArg(args[1], XmNmarginHeight, 5);
314    XtSetArg(args[2], XmNmarginWidth, 5);
315    XtSetArg(args[3], XmNallowShellResize, true);
316    XtSetArg(args[4], XmNautoUnmanage, false);
317    XtSetArg(args[5], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
318    switch (_dialog_type = dialog_type)
319     {
320      default:
321      case FILE_SELECTION:
322        _dialog_type = FILE_SELECTION;
323        XtSetArg(args[6], XmNfileTypeMask, XmFILE_REGULAR);
324        break;
325      case DIRECTORY_SELECTION:
326        XtSetArg(args[6], XmNfileTypeMask, XmFILE_DIRECTORY);
327        break;
328      case FILE_DIRECTORY_SELECTION:
329        XtSetArg(args[6], XmNfileTypeMask, XmFILE_ANY_TYPE);
330        break;
331     }
332    XtSetArg(args[7], XmNdirectory, directory_string);
333    XtSetArg(args[8], XmNpattern, pattern_string);
334
335    _w = XmCreateFileSelectionDialog(parent->InnerWidget(), title, args, 9);
336    StringFree(title_string);
337    StringFree(directory_string);
338    StringFree(pattern_string);
339    if (help)
340     {
341       _help_callback_data = _help_callback_data;
342       XtAddCallback(_w, XmNhelpCallback, &Dialog::DialogCB, (XtPointer) this);
343     }
344    else
345     {
346       XtUnmanageChild(XmMessageBoxGetChild(_w, XmDIALOG_HELP_BUTTON));
347     }
348    XmAddWMProtocolCallback(XtParent(_w), 
349       XmInternAtom(display, "WM_DELETE_WINDOW", False), 
350       &Dialog::CloseCB, (XtPointer) this);
351    InstallHelpCB();
352 }
353
354 Dialog::~Dialog()
355 {
356    // Empty
357 }
358
359 void Dialog::DefaultButton(MotifUI *button)
360 {
361    XtVaSetValues(_w, XmNdefaultButton, button->BaseWidget(), NULL);
362 }
363
364 void Dialog::CancelButtonCB(Widget, XtPointer client_data, XtPointer)
365 {
366    Dialog *obj = (Dialog *)client_data;
367    if (obj->_cancel_button)
368     {
369        XtCallCallbacks(obj->_cancel_button->BaseWidget(), XmNactivateCallback,
370                        obj->_cancel_button);
371     }
372 }
373
374 void Dialog::CancelButton(MotifUI *button)
375 {
376    if (!_cancel_widget)
377     {
378       _cancel_widget = XtVaCreateWidget("cancel_button",
379                                         xmPushButtonWidgetClass, _w, NULL);
380       XtAddCallback(_cancel_widget, XmNactivateCallback, CancelButtonCB, this);
381       BB_CancelButton(_w) = _cancel_widget;
382     }
383    _cancel_button = (Button *)button;
384 }
385
386 void Dialog::Width(int w)
387 {
388    XtVaSetValues(XtParent(_w), XmNallowShellResize, true, NULL);
389    MotifUI::Width(w);
390    XtVaSetValues(XtParent(_w), XmNallowShellResize, false, NULL);
391 }
392
393 void Dialog::Height(int w)
394 {
395    XtVaSetValues(XtParent(_w), XmNallowShellResize, true, NULL);
396    MotifUI::Height(w);
397    XtVaSetValues(XtParent(_w), XmNallowShellResize, false, NULL);
398 }
399
400 void Dialog::WidthHeight(int w, int h)
401 {
402    XtVaSetValues(XtParent(_w), XmNallowShellResize, true, NULL);
403    MotifUI::WidthHeight(w, h);
404    XtVaSetValues(XtParent(_w), XmNallowShellResize, false, NULL);
405 }
406
407 boolean Dialog::SetName(char *name)
408 {
409    XmString xm_message = StringCreate(name);
410    XtVaSetValues(_w, XmNmessageString, xm_message, NULL);
411    StringFree(xm_message);
412    return true;
413 }
414
415 boolean Dialog::SetVisiblity(boolean flag)
416 {
417    MotifUI::SetVisiblity(flag);
418    if (flag == false)
419       return true;
420
421    boolean is_modal;
422    switch (_dialog_type)
423     {
424      case MODELESS:
425      case INFORMATION:
426      case ERROR:
427      case WORK_IN_PROGRESS:
428        is_modal = false;
429        break;
430      default:
431        is_modal = true;
432     }
433
434    ToFront();
435    XtVaSetValues(XtParent(_w), XmNallowShellResize, False, NULL);
436    if (is_modal)
437     {
438       _status = -1;
439       while (_status == -1 || XtAppPending(appContext))
440          XtAppProcessEvent(appContext, XtIMAll);
441       if (_status)
442          _rc = true;
443       else
444          _rc = false;
445     }
446    return true;
447 }
448
449 const boolean Dialog::Answer(char **string)
450 {
451    if (_rc)
452     {
453       if (_dialog_type == PROMPT_DIALOG ||
454           _dialog_type == FILE_SELECTION ||
455           _dialog_type == DIRECTORY_SELECTION ||
456           _dialog_type == FILE_DIRECTORY_SELECTION)
457        {
458          *string = STRDUP(_string);
459        }
460     }
461    else
462       *string = NULL;
463      
464    return _rc;
465 }
466
467 void Dialog::OK()
468 {
469    if (Apply() == true)
470     {
471       Visible(false);
472       _rc = true;
473       _status = 1;
474     }
475    if (_dialog_type != PROMPT_DIALOG &&
476        _dialog_type != QUESTION &&
477        _dialog_type != WARNING)
478       delete this;
479 }
480
481 void Dialog::Cancel()
482 {
483    Reset();
484    Visible(false);
485    _rc = false;
486    _status = 0;
487    if (_dialog_type != PROMPT_DIALOG &&
488        _dialog_type != QUESTION &&
489        _dialog_type != WARNING)
490       delete this;
491 }
492
493 boolean Dialog::Apply()
494 {
495    boolean rc = true;
496
497    if (_dialog_type == PROMPT_DIALOG)
498     {
499       _string = _prompt->Value();
500       if (_validation_callback)
501          rc = (*_validation_callback)(_validation_callback_data, _string);
502       else
503          rc = true;
504       if (rc == true)
505        {
506          if (_apply_callback)
507             (*_apply_callback)(_apply_callback_data);
508          _prompt->DefaultValue(_string);
509        }
510     }
511    return rc;
512 }
513
514 void Dialog::Reset()
515 {
516    if (_reset_callback)
517       (*_reset_callback)(_reset_callback_data);
518    if (_dialog_type == PROMPT_DIALOG)
519       _prompt->Reset();
520 }
521
522 void Dialog::Help()
523 {
524    if (_help_callback)
525       (*_help_callback)(_help_callback_data);
526 }
527
528 void Dialog::CloseCB()
529 {
530    Cancel();
531 }
532
533 void Dialog::CloseCB(Widget, XtPointer client_data, XtPointer /*call_data*/)
534 {
535    Dialog *dialog = (Dialog *) client_data;
536    dialog->CloseCB();
537 }
538
539 void Dialog::DialogCB(Widget, XtPointer client_data, XtPointer call_data)
540 {
541    XmFileSelectionBoxCallbackStruct *cb;
542    Dialog *dialog = (Dialog *) client_data;
543
544    cb = (XmFileSelectionBoxCallbackStruct *) call_data;
545    switch (cb->reason)
546    {
547       case XmCR_HELP: dialog->Help(); break;
548       case XmCR_OK:
549          if (dialog->_dialog_type == FILE_SELECTION ||
550              dialog->_dialog_type == DIRECTORY_SELECTION ||
551              dialog->_dialog_type == FILE_DIRECTORY_SELECTION)
552             dialog->_string = dialog->StringExtract(cb->value);
553          dialog->OK();
554          break;
555       case XmCR_CANCEL: dialog->Cancel(); break;
556       default: break;
557    }
558 }
559
560 void Dialog::ResetCB(void *data)
561 {
562    Dialog *dialog = (Dialog *) data;
563
564    dialog->Reset();
565 }
566
567 void Dialog::ApplyCB(void *data)
568 {
569    Dialog *dialog = (Dialog *) data;
570
571    dialog->Apply();
572 }