2 * Copyright 1991 University of Wisconsin-Madison
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that 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
9 * not 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
15 * THE UNIVERSITY OF WISCONSIN-MADISON DISCLAIMS ALL WARRANTIES WITH REGARD
16 * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF WISCONSIN-MADISON BE LIABLE
18 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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
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.
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
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.
43 * Modified 5/2015, anonymous.
44 * + Include anethack's lint.h to get nhStr() macro.
45 * + Use nhStr() on string literals (or macros from <X11/StringDefs.h>
46 * that hide string literals) to cast away implicit 'const' in order
47 * to suppress "warning: assignment discards qualifers from pointer
48 * target type" issued by 'gcc -Wwrite-strings' as used by anethack.
49 * (For this file, always the second parameter to XtSetArg().)
51 * Modified 1/2016, Pat Rankin.
52 * + Added minimum width argument to SetDialogResponse() so that the
53 * text entry widget can be forced to wider than the default response.
54 * + Make 'okay' button same width as 'cancel', and both wider than
55 * default by a small arbitrary amount.
57 * $ANH-Date: 1455157470 2016/02/11 02:24:30 $ $ANH-Branch: aNetHack-3.6.0 $:$ANH-Revision: 1.9 $
61 #define PRESERVE_NO_SYSV /* X11 include files may define SYSV */
64 #include <X11/Intrinsic.h>
65 #include <X11/StringDefs.h>
67 #include <X11/Xaw/Cardinals.h>
68 #include <X11/Xaw/Form.h>
69 #include <X11/Xaw/Label.h>
70 #include <X11/Xaw/AsciiText.h>
71 #include <X11/Xaw/Command.h>
73 #ifdef PRESERVE_NO_SYSV
77 #undef PRESERVE_NO_SYSV
80 #include "config.h" /* #define for const for non __STDC__ compilers */
81 #include "lint.h" /* for anethack's nhStr() macro */
83 /* ":" added to both translations below to allow limited redefining of
84 * keysyms before testing for keysym values -- dlc */
85 static const char okay_accelerators
[] = "#override\n\
86 :<Key>Return: set() notify() unset()\n";
88 static const char cancel_accelerators
[] = "#override\n\
89 :<Key>Escape: set() notify() unset()\n\
90 :<Ctrl>[: set() notify() unset()\n"; /* for keyboards w/o an ESC */
92 /* Create a dialog widget. It is just a form widget with
96 * an optional cancel button
99 CreateDialog(parent
, name
, okay_callback
, cancel_callback
)
102 XtCallbackProc okay_callback
;
103 XtCallbackProc cancel_callback
;
105 Widget form
, prompt
, response
, okay
, cancel
;
108 Dimension owidth
, cwidth
;
113 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
116 form
= XtCreateManagedWidget(name
, formWidgetClass
, parent
,
122 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
123 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
126 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
127 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
128 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
129 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
130 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
131 XtSetArg(args
[num_args
], nhStr(XtNborderWidth
), 0); num_args
++;
132 prompt
= XtCreateManagedWidget("prompt", labelWidgetClass
, form
,
138 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
139 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
142 XtSetArg(args
[num_args
], nhStr(XtNfromVert
), prompt
); num_args
++;
143 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
144 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
145 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
146 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
147 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
148 XtSetArg(args
[num_args
], nhStr(XtNeditType
), XawtextEdit
); num_args
++;
149 XtSetArg(args
[num_args
], nhStr(XtNresize
), XawtextResizeWidth
); num_args
++;
150 XtSetArg(args
[num_args
], nhStr(XtNstring
), ""); num_args
++;
151 response
= XtCreateManagedWidget("response", asciiTextWidgetClass
, form
,
157 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
158 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
161 XtSetArg(args
[num_args
], nhStr(XtNfromVert
), response
); num_args
++;
162 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
163 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
164 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
165 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
166 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
167 XtSetArg(args
[num_args
], nhStr(XtNaccelerators
),
168 XtParseAcceleratorTable(okay_accelerators
)); num_args
++;
169 okay
= XtCreateManagedWidget("okay", commandWidgetClass
, form
,
171 XtAddCallback(okay
, XtNcallback
, okay_callback
, form
);
172 XtSetArg(args
[0], XtNwidth
, &owidth
);
173 XtGetValues(okay
, args
, ONE
);
175 /* Only create cancel button if there is a callback for it. */
176 if (cancel_callback
) {
180 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
181 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
184 XtSetArg(args
[num_args
], nhStr(XtNfromVert
), response
); num_args
++;
185 XtSetArg(args
[num_args
], nhStr(XtNfromHoriz
), okay
); num_args
++;
186 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
187 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
188 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
189 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
190 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
191 XtSetArg(args
[num_args
], nhStr(XtNaccelerators
),
192 XtParseAcceleratorTable(cancel_accelerators
)); num_args
++;
193 cancel
= XtCreateManagedWidget("cancel", commandWidgetClass
, form
,
195 XtAddCallback(cancel
, XtNcallback
, cancel_callback
, form
);
196 XtInstallAccelerators(response
, cancel
);
197 XtSetArg(args
[0], XtNwidth
, &cwidth
);
198 XtGetValues(cancel
, args
, ONE
);
199 /* widen the cancel button */
201 XtSetArg(args
[0], XtNwidth
, cwidth
);
202 XtSetValues(cancel
, args
, ONE
);
204 cwidth
= owidth
+ 25;
206 /* make okay button same width as cancel, or widen it if no cancel */
207 XtSetArg(args
[0], XtNwidth
, cwidth
);
208 XtSetValues(okay
, args
, ONE
);
210 XtInstallAccelerators(response
, okay
);
211 XtSetKeyboardFocus(form
, response
);
217 /* get the prompt from the dialog box. Used a startup time to
218 * save away the initial prompt */
227 label
= XtNameToWidget(w
, "prompt");
228 XtSetArg(args
[0], nhStr(XtNlabel
), &s
);
229 XtGetValues(label
, args
, ONE
);
230 return XtNewString(s
);
234 /* set the prompt. This is used to put error information in the prompt */
236 SetDialogPrompt(w
, newprompt
)
243 label
= XtNameToWidget(w
, "prompt");
244 XtSetArg(args
[0], nhStr(XtNlabel
), newprompt
);
245 XtSetValues(label
, args
, ONE
);
248 /* get what the user typed; caller must free the response */
257 response
= XtNameToWidget(w
, "response");
258 XtSetArg(args
[0], nhStr(XtNstring
), &s
);
259 XtGetValues(response
, args
, ONE
);
260 return XtNewString(s
);
263 /* set the default reponse */
265 SetDialogResponse(w
, s
, ln
)
273 Dimension width
, nwidth
, leftMargin
, rightMargin
;
274 unsigned s_len
= strlen(s
);
278 response
= XtNameToWidget(w
, "response");
279 XtSetArg(args
[0], nhStr(XtNfont
), &font
);
280 XtSetArg(args
[1], nhStr(XtNleftMargin
), &leftMargin
);
281 XtSetArg(args
[2], nhStr(XtNrightMargin
), &rightMargin
);
282 XtSetArg(args
[3], nhStr(XtNwidth
), &width
);
283 XtGetValues(response
, args
, FOUR
);
284 /* width includes margins as per Xaw documentation */
285 nwidth
= font
->max_bounds
.width
* (s_len
+ 1) + leftMargin
+ rightMargin
;
289 XtSetArg(args
[0], nhStr(XtNstring
), s
);
290 XtSetArg(args
[1], nhStr(XtNwidth
), nwidth
);
291 XtSetValues(response
, args
, TWO
);
292 XawTextSetInsertionPoint(response
, strlen(s
));
296 /* clear the response */
298 ClearDialogResponse(w
)
304 response
= XtNameToWidget(w
, "response");
305 XtSetArg(args
[0], nhStr(XtNstring
), "");
306 XtSetArg(args
[1], nhStr(XtNwidth
), 100);
307 XtSetValues(response
, args
, TWO
);
311 /* Not a part of the original dialogs.c from ghostview -------------------- */
313 /* position popup window under the cursor */
315 positionpopup(w
, bottom
)
317 boolean bottom
; /* position y on bottom? */
321 Dimension width
, height
, b_width
;
322 int x
, y
, max_x
, max_y
;
326 unsigned int dummymask
;
327 extern Widget toplevel
;
329 /* following line deals with a race condition w/brain-damaged WM's -dlc */
330 XtUnrealizeWidget(w
);
332 XQueryPointer(XtDisplay(toplevel
), XtWindow(toplevel
), &root
, &child
, &x
,
333 &y
, &dummyx
, &dummyy
, &dummymask
);
335 XtSetArg(args
[num_args
], XtNwidth
, &width
); num_args
++;
336 XtSetArg(args
[num_args
], XtNheight
, &height
); num_args
++;
337 XtSetArg(args
[num_args
], XtNborderWidth
, &b_width
); num_args
++;
338 XtGetValues(w
, args
, num_args
);
340 /* position so that the cursor is center,center or center,bottom */
341 width
+= 2 * b_width
;
342 x
-= ((Position
) width
/ 2);
345 if (x
> (max_x
= (Position
) (XtScreen(w
)->width
- width
)))
349 y
-= (height
+ b_width
- 1);
350 height
+= 2 * b_width
;
352 height
+= 2 * b_width
;
353 y
-= ((Position
) height
/ 2);
357 if (y
> (max_y
= (Position
) (XtScreen(w
)->height
- height
)))
361 XtSetArg(args
[num_args
], XtNx
, x
); num_args
++;
362 XtSetArg(args
[num_args
], XtNy
, y
); num_args
++;
363 XtSetValues(w
, args
, num_args
);
365 /* Some older window managers ignore XtN{x,y}; hint the same values.
366 {x,y} are not used by newer window managers; older ones need them. */
368 hints
= XAllocSizeHints();
369 hints
->flags
= USPosition
;
372 XSetWMNormalHints(XtDisplay(w
), XtWindow(w
), hints
);