1 /*
2 * Copyright 1991 University of Wisconsin-Madison
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the University of Wisconsin-Madison not
9 * be used in advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission. The University of
11 * Wisconsin-Madison makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *
15 * THE UNIVERSITY OF WISCONSIN-MADISON DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN-MADISON BE LIABLE FOR
18 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Author: Tim Theisen Department of Computer Sciences
24 * tim@cs.wisc.edu University of Wisconsin-Madison
25 * uwvax!tim 1210 West Dayton Street
26 * (608)262-0438 Madison, WI 53706
27 *
28 *
29 * Modified 12/91 by Dean Luick. Tim graciously donated this piece of code
30 * from his program ghostview, an X11 front end for ghostscript.
31 *
32 * + Make the cancel button optional.
33 * + Put an #ifdef SPECIAL_CMAP around code to fix a colormap bug.
34 * We don't need it here.
35 * + Add the function positionpopup() from another part of ghostview
36 * to this code.
37 *
38 * Modified 2/93, Various.
39 * + Added workaround for SYSV include problem.
40 * + Changed the default width response text widget to be as wide as the
41 * window itself. Suggestion from David E. Wexelblat, dwex@goblin.org.
42 */
43
44 #ifndef SYSV
45 #define PRESERVE_NO_SYSV /* X11 include files may define SYSV */
46 #endif
47
48 #include <X11/Intrinsic.h>
49 #include <X11/StringDefs.h>
50 #include <X11/Xos.h>
51 #include <X11/Xaw/Cardinals.h>
52 #include <X11/Xaw/Form.h>
53 #include <X11/Xaw/Label.h>
54 #include <X11/Xaw/AsciiText.h>
55 #include <X11/Xaw/Command.h>
56
57 #ifdef PRESERVE_NO_SYSV
58 # ifdef SYSV
59 # undef SYSV
60 # endif
61 # undef PRESERVE_NO_SYSV
62 #endif
63
64 #include "config.h" /* #define for const for non __STDC__ compilers */
65
66 /* ":" added to both translations below to allow limited redefining of
67 * keysyms before testing for keysym values -- dlc */
68 static const char okay_accelerators[] =
69 "#override\n\
70 :<Key>Return: set() notify() unset()\n";
71
72 static const char cancel_accelerators[] =
73 "#override\n\
74 :<Key>Escape: set() notify() unset()\n\
75 :<Ctrl>[: set() notify() unset()\n"; /* for keyboards w/o an ESC */
76
77
78 /* Create a dialog widget. It is just a form widget with
79 * a label prompt
80 * a text response
81 * an okay button
82 * an optional cancel button
83 */
84 Widget
CreateDialog(parent,name,okay_callback,cancel_callback)85 CreateDialog(parent, name, okay_callback, cancel_callback)
86 Widget parent;
87 String name;
88 XtCallbackProc okay_callback;
89 XtCallbackProc cancel_callback;
90 {
91 Widget form, prompt, response, okay, cancel;
92 Arg args[20];
93 Cardinal num_args;
94
95 num_args = 0;
96 #ifdef SPECIAL_CMAP
97 if (special_cmap) {
98 XtSetArg(args[num_args], XtNbackground, white); num_args++;
99 }
100 #endif
101 form = XtCreateManagedWidget(name, formWidgetClass, parent, args, num_args);
102
103 num_args = 0;
104 #ifdef SPECIAL_CMAP
105 if (special_cmap) {
106 XtSetArg(args[num_args], XtNforeground, black); num_args++;
107 XtSetArg(args[num_args], XtNbackground, white); num_args++;
108 }
109 #endif
110 XtSetArg(args[num_args], XtNtop, XtChainTop); num_args++;
111 XtSetArg(args[num_args], XtNbottom, XtChainTop); num_args++;
112 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
113 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
114 XtSetArg(args[num_args], XtNresizable, True); num_args++;
115 XtSetArg(args[num_args], XtNborderWidth, 0); num_args++;
116 prompt = XtCreateManagedWidget("prompt", labelWidgetClass,
117 form, args, num_args);
118
119 num_args = 0;
120 #ifdef SPECIAL_CMAP
121 if (special_cmap) {
122 XtSetArg(args[num_args], XtNforeground, black); num_args++;
123 XtSetArg(args[num_args], XtNbackground, white); num_args++;
124 }
125 #endif
126 XtSetArg(args[num_args], XtNfromVert, prompt); num_args++;
127 XtSetArg(args[num_args], XtNtop, XtChainTop); num_args++;
128 XtSetArg(args[num_args], XtNbottom, XtChainTop); num_args++;
129 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
130 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
131 XtSetArg(args[num_args], XtNresizable, True); num_args++;
132 XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++;
133 XtSetArg(args[num_args], XtNresize, XawtextResizeWidth); num_args++;
134 XtSetArg(args[num_args], XtNstring, ""); num_args++;
135 response = XtCreateManagedWidget("response", asciiTextWidgetClass,
136 form, args, num_args);
137
138 num_args = 0;
139 #ifdef SPECIAL_CMAP
140 if (special_cmap) {
141 XtSetArg(args[num_args], XtNforeground, black); num_args++;
142 XtSetArg(args[num_args], XtNbackground, white); num_args++;
143 }
144 #endif
145 XtSetArg(args[num_args], XtNfromVert, response); num_args++;
146 XtSetArg(args[num_args], XtNtop, XtChainTop); num_args++;
147 XtSetArg(args[num_args], XtNbottom, XtChainTop); num_args++;
148 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
149 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
150 XtSetArg(args[num_args], XtNresizable, True); num_args++;
151 XtSetArg(args[num_args], XtNaccelerators,
152 XtParseAcceleratorTable(okay_accelerators)); num_args++;
153 okay = XtCreateManagedWidget("okay", commandWidgetClass,
154 form, args, num_args);
155 XtAddCallback(okay, XtNcallback, okay_callback, form);
156
157 /* Only create cancel button if there is a callback for it. */
158 if (cancel_callback) {
159 num_args = 0;
160 #ifdef SPECIAL_CMAP
161 if (special_cmap) {
162 XtSetArg(args[num_args], XtNforeground, black); num_args++;
163 XtSetArg(args[num_args], XtNbackground, white); num_args++;
164 }
165 #endif
166 XtSetArg(args[num_args], XtNfromVert, response); num_args++;
167 XtSetArg(args[num_args], XtNfromHoriz, okay); num_args++;
168 XtSetArg(args[num_args], XtNtop, XtChainTop); num_args++;
169 XtSetArg(args[num_args], XtNbottom, XtChainTop); num_args++;
170 XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++;
171 XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++;
172 XtSetArg(args[num_args], XtNresizable, True); num_args++;
173 XtSetArg(args[num_args], XtNaccelerators,
174 XtParseAcceleratorTable(cancel_accelerators)); num_args++;
175 cancel = XtCreateManagedWidget("cancel", commandWidgetClass,
176 form, args, num_args);
177 XtAddCallback(cancel, XtNcallback, cancel_callback, form);
178 XtInstallAccelerators(response, cancel);
179 }
180
181 XtInstallAccelerators(response, okay);
182 XtSetKeyboardFocus(form, response);
183
184 return form;
185 }
186
187 #if 0
188 /* get the prompt from the dialog box. Used a startup time to
189 * save away the initial prompt */
190 String
191 GetDialogPrompt(w)
192 Widget w;
193 {
194 Arg args[1];
195 Widget label;
196 String s;
197
198 label = XtNameToWidget(w, "prompt");
199 XtSetArg(args[0], XtNlabel, &s);
200 XtGetValues(label, args, ONE);
201 return XtNewString(s);
202 }
203 #endif
204
205 /* set the prompt. This is used to put error information in the prompt */
206 void
SetDialogPrompt(w,newprompt)207 SetDialogPrompt(w, newprompt)
208 Widget w;
209 String newprompt;
210 {
211 Arg args[1];
212 Widget label;
213
214 label = XtNameToWidget(w, "prompt");
215 XtSetArg(args[0], XtNlabel, newprompt);
216 XtSetValues(label, args, ONE);
217 }
218
219 /* get what the user typed; caller must free the response */
220 String
GetDialogResponse(w)221 GetDialogResponse(w)
222 Widget w;
223 {
224 Arg args[1];
225 Widget response;
226 String s;
227
228 response = XtNameToWidget(w, "response");
229 XtSetArg(args[0], XtNstring, &s);
230 XtGetValues(response, args, ONE);
231 return XtNewString(s);
232 }
233
234 #define max(a,b) (((a) > (b)) ? (a) : (b))
235 /* set the default reponse */
236 void
SetDialogResponse(w,s)237 SetDialogResponse(w, s)
238 Widget w;
239 String s;
240 {
241 Arg args[4];
242 Widget response;
243 XFontStruct *font;
244 Dimension width, nwidth, leftMargin, rightMargin;
245
246 response = XtNameToWidget(w, "response");
247 XtSetArg(args[0], XtNfont, &font);
248 XtSetArg(args[1], XtNleftMargin, &leftMargin);
249 XtSetArg(args[2], XtNrightMargin, &rightMargin);
250 XtSetArg(args[3], XtNwidth, &width);
251 XtGetValues(response, args, FOUR);
252 /* width includes margins as per Xaw documentation */
253 nwidth = (font->max_bounds.width * strlen(s))+leftMargin+rightMargin;
254 if (nwidth < width)
255 nwidth = width;
256
257 XtSetArg(args[0], XtNstring, s);
258 XtSetArg(args[1], XtNwidth, nwidth);
259 XtSetValues(response, args, TWO);
260 XawTextSetInsertionPoint(response, strlen(s));
261 }
262
263 #if 0
264 /* clear the response */
265 void
266 ClearDialogResponse(w)
267 Widget w;
268 {
269 Arg args[2];
270 Widget response;
271
272 response = XtNameToWidget(w, "response");
273 XtSetArg(args[0], XtNstring, "");
274 XtSetArg(args[1], XtNwidth, 100);
275 XtSetValues(response, args, TWO);
276 }
277 #endif
278
279
280 /* Not a part of the original dialogs.c from ghostview --------------------- */
281
282 /* position popup window under the cursor */
283 void
positionpopup(w,bottom)284 positionpopup(w, bottom)
285 Widget w;
286 boolean bottom; /* position y on bottom? */
287 {
288 Arg args[3];
289 Cardinal num_args;
290 Dimension width, height, b_width;
291 int x, y, max_x, max_y;
292 Window root, child;
293 XSizeHints *hints;
294 int dummyx, dummyy;
295 unsigned int dummymask;
296 extern Widget toplevel;
297
298 /* following line deals with a race condition w/brain-damaged WM's -dlc */
299 XtUnrealizeWidget(w);
300
301 XQueryPointer(XtDisplay(toplevel), XtWindow(toplevel), &root, &child,
302 &x, &y, &dummyx, &dummyy, &dummymask);
303 num_args = 0;
304 XtSetArg(args[num_args], XtNwidth, &width); num_args++;
305 XtSetArg(args[num_args], XtNheight, &height); num_args++;
306 XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++;
307 XtGetValues(w, args, num_args);
308
309 /* position so that the cursor is center,center or center,bottom */
310 width += 2 * b_width;
311 x -= ( (Position) width/2 );
312 if (x < 0) x = 0;
313 if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x;
314
315 if (bottom) {
316 y -= (height+b_width-1);
317 height += 2 * b_width;
318 } else {
319 height += 2 * b_width;
320 y -= ( (Position) height/2 );
321 }
322 if (y < 0) y = 0;
323 if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y;
324
325
326 num_args = 0;
327 XtSetArg(args[num_args], XtNx, x); num_args++;
328 XtSetArg(args[num_args], XtNy, y); num_args++;
329 XtSetValues(w, args, num_args);
330
331 /* Some older window managers ignore XtN{x,y}; hint the same values */
332 /* The {x,y} are not used by newer window managers; older ones need them */
333 XtRealizeWidget(w);
334 hints = XAllocSizeHints();
335 hints->flags = USPosition;
336 hints->x = x;
337 hints->y = y;
338 XSetWMNormalHints(XtDisplay(w), XtWindow(w), hints);
339 XFree(hints);
340 }
341