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 nethack'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 qualifiers from pointer
48 * target type" issued by 'gcc -Wwrite-strings' as used by nethack.
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 * $NHDT-Date: 1455157470 2016/02/11 02:24:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-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
81 #include "config.h" /* #define for const for non __STDC__ compilers */
84 #include "lint.h" /* for nethack's nhStr() macro */
85 #include "winX.h" /* to make sure prototypes match corresponding functions */
87 /* ":" added to both translations below to allow limited redefining of
88 * keysyms before testing for keysym values -- dlc */
89 static const char okay_accelerators
[] = "#override\n\
90 :<Key>Return: set() notify() unset()\n";
92 static const char cancel_accelerators
[] = "#override\n\
93 :<Key>Escape: set() notify() unset()\n\
94 :<Ctrl>[: set() notify() unset()\n"; /* for keyboards w/o an ESC */
96 /* Create a dialog widget. It is just a form widget with
100 * an optional cancel button
103 CreateDialog(Widget parent
, String name
, XtCallbackProc okay_callback
,
104 XtCallbackProc cancel_callback
)
106 Widget form
, prompt
, response
, okay
, cancel
;
109 Dimension owidth
, cwidth
;
114 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
117 form
= XtCreateManagedWidget(name
, formWidgetClass
, parent
,
123 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
124 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
127 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
128 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
129 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
130 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
131 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
132 XtSetArg(args
[num_args
], nhStr(XtNborderWidth
), 0); num_args
++;
133 prompt
= XtCreateManagedWidget("prompt", labelWidgetClass
, form
,
139 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
140 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
143 XtSetArg(args
[num_args
], nhStr(XtNfromVert
), prompt
); num_args
++;
144 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
145 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
146 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
147 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
148 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
149 XtSetArg(args
[num_args
], nhStr(XtNeditType
), XawtextEdit
); num_args
++;
150 XtSetArg(args
[num_args
], nhStr(XtNresize
), XawtextResizeWidth
); num_args
++;
151 XtSetArg(args
[num_args
], nhStr(XtNstring
), ""); num_args
++;
152 response
= XtCreateManagedWidget("response", asciiTextWidgetClass
, form
,
158 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
159 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
162 XtSetArg(args
[num_args
], nhStr(XtNfromVert
), response
); num_args
++;
163 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
164 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
165 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
166 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
167 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
168 XtSetArg(args
[num_args
], nhStr(XtNaccelerators
),
169 XtParseAcceleratorTable(okay_accelerators
)); num_args
++;
170 okay
= XtCreateManagedWidget("okay", commandWidgetClass
, form
,
172 XtAddCallback(okay
, XtNcallback
, okay_callback
, form
);
173 XtSetArg(args
[0], XtNwidth
, &owidth
);
174 XtGetValues(okay
, args
, ONE
);
176 /* Only create cancel button if there is a callback for it. */
177 if (cancel_callback
) {
181 XtSetArg(args
[num_args
], nhStr(XtNforeground
), black
); num_args
++;
182 XtSetArg(args
[num_args
], nhStr(XtNbackground
), white
); num_args
++;
185 XtSetArg(args
[num_args
], nhStr(XtNfromVert
), response
); num_args
++;
186 XtSetArg(args
[num_args
], nhStr(XtNfromHoriz
), okay
); num_args
++;
187 XtSetArg(args
[num_args
], nhStr(XtNtop
), XtChainTop
); num_args
++;
188 XtSetArg(args
[num_args
], nhStr(XtNbottom
), XtChainTop
); num_args
++;
189 XtSetArg(args
[num_args
], nhStr(XtNleft
), XtChainLeft
); num_args
++;
190 XtSetArg(args
[num_args
], nhStr(XtNright
), XtChainLeft
); num_args
++;
191 XtSetArg(args
[num_args
], nhStr(XtNresizable
), True
); num_args
++;
192 XtSetArg(args
[num_args
], nhStr(XtNaccelerators
),
193 XtParseAcceleratorTable(cancel_accelerators
)); num_args
++;
194 cancel
= XtCreateManagedWidget("cancel", commandWidgetClass
, form
,
196 XtAddCallback(cancel
, XtNcallback
, cancel_callback
, form
);
197 XtInstallAccelerators(response
, cancel
);
198 XtSetArg(args
[0], XtNwidth
, &cwidth
);
199 XtGetValues(cancel
, args
, ONE
);
200 /* widen the cancel button */
202 XtSetArg(args
[0], XtNwidth
, cwidth
);
203 XtSetValues(cancel
, args
, ONE
);
205 cwidth
= owidth
+ 25;
207 /* make okay button same width as cancel, or widen it if no cancel */
208 XtSetArg(args
[0], XtNwidth
, cwidth
);
209 XtSetValues(okay
, args
, ONE
);
211 XtInstallAccelerators(response
, okay
);
212 XtSetKeyboardFocus(form
, response
);
218 /* get the prompt from the dialog box. Used a startup time to
219 * save away the initial prompt */
221 GetDialogPrompt(Widget w
)
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(Widget w
, String newprompt
)
241 label
= XtNameToWidget(w
, "prompt");
242 XtSetArg(args
[0], nhStr(XtNlabel
), newprompt
);
243 XtSetValues(label
, args
, ONE
);
246 /* get what the user typed; caller must free the response */
248 GetDialogResponse(Widget w
)
254 response
= XtNameToWidget(w
, "response");
255 XtSetArg(args
[0], nhStr(XtNstring
), &s
);
256 XtGetValues(response
, args
, ONE
);
257 return XtNewString(s
);
260 /* set the default response */
262 SetDialogResponse(Widget w
, String s
, unsigned ln
)
267 Dimension width
, nwidth
, leftMargin
, rightMargin
;
268 unsigned s_len
= strlen(s
);
272 response
= XtNameToWidget(w
, "response");
273 XtSetArg(args
[0], nhStr(XtNfont
), &font
);
274 XtSetArg(args
[1], nhStr(XtNleftMargin
), &leftMargin
);
275 XtSetArg(args
[2], nhStr(XtNrightMargin
), &rightMargin
);
276 XtSetArg(args
[3], nhStr(XtNwidth
), &width
);
277 XtGetValues(response
, args
, FOUR
);
278 /* width includes margins as per Xaw documentation */
279 nwidth
= font
->max_bounds
.width
* (s_len
+ 1) + leftMargin
+ rightMargin
;
283 XtSetArg(args
[0], nhStr(XtNstring
), s
);
284 XtSetArg(args
[1], nhStr(XtNwidth
), nwidth
);
285 XtSetValues(response
, args
, TWO
);
286 XawTextSetInsertionPoint(response
, strlen(s
));
290 /* clear the response */
292 ClearDialogResponse(Widget w
)
297 response
= XtNameToWidget(w
, "response");
298 XtSetArg(args
[0], nhStr(XtNstring
), "");
299 XtSetArg(args
[1], nhStr(XtNwidth
), 100);
300 XtSetValues(response
, args
, TWO
);
304 /* Not a part of the original dialogs.c from ghostview -------------------- */
306 /* position popup window under the cursor */
308 positionpopup(Widget w
, boolean bottom
) /* position y on bottom? */
312 Dimension width
, height
, b_width
;
313 int x
, y
, max_x
, max_y
;
317 unsigned int dummymask
;
318 extern Widget toplevel
;
320 /* following line deals with a race condition w/brain-damaged WM's -dlc */
321 XtUnrealizeWidget(w
);
323 XQueryPointer(XtDisplay(toplevel
), XtWindow(toplevel
), &root
, &child
, &x
,
324 &y
, &dummyx
, &dummyy
, &dummymask
);
326 XtSetArg(args
[num_args
], XtNwidth
, &width
); num_args
++;
327 XtSetArg(args
[num_args
], XtNheight
, &height
); num_args
++;
328 XtSetArg(args
[num_args
], XtNborderWidth
, &b_width
); num_args
++;
329 XtGetValues(w
, args
, num_args
);
331 /* position so that the cursor is center,center or center,bottom */
332 width
+= 2 * b_width
;
333 x
-= ((Position
) width
/ 2);
336 if (x
> (max_x
= (Position
) (XtScreen(w
)->width
- width
)))
340 y
-= (height
+ b_width
- 1);
341 height
+= 2 * b_width
;
343 height
+= 2 * b_width
;
344 y
-= ((Position
) height
/ 2);
348 if (y
> (max_y
= (Position
) (XtScreen(w
)->height
- height
)))
352 XtSetArg(args
[num_args
], XtNx
, x
); num_args
++;
353 XtSetArg(args
[num_args
], XtNy
, y
); num_args
++;
354 XtSetValues(w
, args
, num_args
);
356 /* Some older window managers ignore XtN{x,y}; hint the same values.
357 {x,y} are not used by newer window managers; older ones need them. */
359 hints
= XAllocSizeHints();
360 hints
->flags
= USPosition
;
363 XSetWMNormalHints(XtDisplay(w
), XtWindow(w
), hints
);