1/*
2
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29/*
30 * Author:  Davor Matic, MIT X Consortium
31 */
32
33#ifdef HAVE_CONFIG_H
34# include "config.h"
35#endif
36
37#include <X11/Intrinsic.h>
38#include <X11/StringDefs.h>
39#include <X11/Shell.h>
40#include <X11/Xaw/Dialog.h>
41#include <X11/Xaw/Command.h>
42#include <X11/Xmu/CharSet.h>
43
44#include "Dialog.h"
45
46#define min(x, y)                     (((x) < (y)) ? (x) : (y))
47#define max(x, y)                     (((x) > (y)) ? (x) : (y))
48
49
50static void SetDialogButton(Widget w, XEvent *event,
51			    String *argv, Cardinal *argc);
52
53static XtActionsRec actions_table[] = {
54  {"set-dialog-button", SetDialogButton},
55};
56
57static DialogButton dialog_buttons[] = {
58    {"yes", Yes},
59    {"no", No},
60    {"maybe", Maybe},
61    {"okay", Okay},
62    {"abort", Abort},
63    {"cancel", Cancel},
64    {"retry", Retry},
65};
66
67static unsigned long selected;
68
69/* ARGSUSED */
70static void
71SetSelected(Widget w, XtPointer clientData, XtPointer callData) /* ARGSUSED */
72{
73    String name = (String)clientData;
74    int i;
75
76    for (i = 0; i < XtNumber(dialog_buttons); i++)
77	if (!strcmp(dialog_buttons[i].name, name))
78	    selected |= dialog_buttons[i].flag;
79}
80
81/* ARGSUSED */
82static void
83SetDialogButton(Widget w,	/* not used */
84		XEvent *event,	/* not used */
85		String *argv,
86		Cardinal *argc)
87{
88  char button_name[80];
89  XtPointer dummy = NULL;
90  int i;
91
92  for (i = 0; i < *argc; i++) {
93    XmuCopyISOLatin1Lowered (button_name, argv[i]);
94    SetSelected(w, button_name, dummy);
95  }
96}
97
98static Boolean firstTime = True;
99
100Dialog
101CreateDialog(Widget top_widget, String name, unsigned long options)
102{
103    int i;
104    Dialog popup;
105
106    popup = (Dialog) XtMalloc(sizeof(_Dialog));
107
108    if (popup) {
109        if (firstTime) {
110	  XtAddActions(actions_table, XtNumber(actions_table));
111	  firstTime = False;
112	}
113	popup->top_widget = top_widget;
114	popup->shell_widget = XtCreatePopupShell(name,
115						 transientShellWidgetClass,
116						 top_widget, NULL, 0);
117	popup->dialog_widget = XtCreateManagedWidget("dialog",
118						     dialogWidgetClass,
119						     popup->shell_widget,
120						     NULL, 0);
121	for (i = 0; i < XtNumber(dialog_buttons); i++)
122	    if (options & dialog_buttons[i].flag)
123		XawDialogAddButton(popup->dialog_widget,
124				   dialog_buttons[i].name,
125				   SetSelected, dialog_buttons[i].name);
126	popup->options = options;
127	return popup;
128    }
129    else
130	return NULL;
131}
132
133void
134PopdownDialog(Dialog popup, _XtString *answer)
135{
136    if (answer)
137	*answer = XawDialogGetValueString(popup->dialog_widget);
138
139    XtPopdown(popup->shell_widget);
140}
141
142unsigned long
143PopupDialog(Dialog popup, String message, String suggestion,
144	    _XtString *answer, XtGrabKind grab)
145{
146  Position popup_x, popup_y, top_x, top_y;
147  Dimension popup_width, popup_height, top_width, top_height, border_width;
148  int n;
149  Arg wargs[4];
150
151  n = 0;
152  XtSetArg(wargs[n], XtNlabel, message); n++;
153  XtSetArg(wargs[n], XtNvalue, suggestion); n++;
154  XtSetValues(popup->dialog_widget, wargs, n);
155
156  XtRealizeWidget(popup->shell_widget);
157
158  n = 0;
159  XtSetArg(wargs[n], XtNx, &top_x); n++;
160  XtSetArg(wargs[n], XtNy, &top_y); n++;
161  XtSetArg(wargs[n], XtNwidth, &top_width); n++;
162  XtSetArg(wargs[n], XtNheight, &top_height); n++;
163  XtGetValues(popup->top_widget, wargs, n);
164
165  n = 0;
166  XtSetArg(wargs[n], XtNwidth, &popup_width); n++;
167  XtSetArg(wargs[n], XtNheight, &popup_height); n++;
168  XtSetArg(wargs[n], XtNborderWidth, &border_width); n++;
169  XtGetValues(popup->shell_widget, wargs, n);
170
171  popup_x = max(0,
172	min(top_x + ((Position)top_width - (Position)popup_width) / 2,
173	    (Position)DisplayWidth(XtDisplay(popup->shell_widget),
174		   DefaultScreen(XtDisplay(popup->shell_widget))) -
175	    (Position)popup_width - 2 * (Position)border_width));
176  popup_y = max(0,
177	min(top_y + ((Position)top_height - (Position)popup_height) / 2,
178	    (Position)DisplayHeight(XtDisplay(popup->shell_widget),
179		    DefaultScreen(XtDisplay(popup->shell_widget))) -
180	    (Position)popup_height - 2 * (Position)border_width));
181  n = 0;
182  XtSetArg(wargs[n], XtNx, popup_x); n++;
183  XtSetArg(wargs[n], XtNy, popup_y); n++;
184  XtSetValues(popup->shell_widget, wargs, n);
185
186  selected = None;
187
188  XtPopup(popup->shell_widget, grab);
189  XWarpPointer(XtDisplay(popup->shell_widget),
190	       XtWindow(popup->top_widget),
191	       XtWindow(popup->shell_widget),
192	       0, 0, top_width, top_height,
193	       popup_width / 2, popup_height / 2);
194
195  while ((selected & popup->options) == None) {
196      XEvent event;
197      XtNextEvent(&event);
198      XtDispatchEvent(&event);
199  }
200
201  PopdownDialog(popup, answer);
202
203  return (selected & popup->options);
204}
205