NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / win / X11 / dialogs.c
blobea4c6b6c6b8b3fb52b5c662bedb231dfe6c4837f
1 /*
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
13 * implied warranty.
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
36 * to this code.
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 $
60 #ifndef SYSV
61 #define PRESERVE_NO_SYSV /* X11 include files may define SYSV */
62 #endif
64 #include <X11/Intrinsic.h>
65 #include <X11/StringDefs.h>
66 #include <X11/Xos.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
74 #ifdef SYSV
75 #undef SYSV
76 #endif
77 #undef PRESERVE_NO_SYSV
78 #endif
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
93 * a label prompt
94 * a text response
95 * an okay button
96 * an optional cancel button
98 Widget
99 CreateDialog(parent, name, okay_callback, cancel_callback)
100 Widget parent;
101 String name;
102 XtCallbackProc okay_callback;
103 XtCallbackProc cancel_callback;
105 Widget form, prompt, response, okay, cancel;
106 Arg args[20];
107 Cardinal num_args;
108 Dimension owidth, cwidth;
110 num_args = 0;
111 #ifdef SPECIAL_CMAP
112 if (special_cmap) {
113 XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
115 #endif
116 form = XtCreateManagedWidget(name, formWidgetClass, parent,
117 args, num_args);
119 num_args = 0;
120 #ifdef SPECIAL_CMAP
121 if (special_cmap) {
122 XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
123 XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
125 #endif
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,
133 args, num_args);
135 num_args = 0;
136 #ifdef SPECIAL_CMAP
137 if (special_cmap) {
138 XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
139 XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
141 #endif
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,
152 args, num_args);
154 num_args = 0;
155 #ifdef SPECIAL_CMAP
156 if (special_cmap) {
157 XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
158 XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
160 #endif
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,
170 args, num_args);
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) {
177 num_args = 0;
178 #ifdef SPECIAL_CMAP
179 if (special_cmap) {
180 XtSetArg(args[num_args], nhStr(XtNforeground), black); num_args++;
181 XtSetArg(args[num_args], nhStr(XtNbackground), white); num_args++;
183 #endif
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,
194 args, num_args);
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 */
200 cwidth += 25;
201 XtSetArg(args[0], XtNwidth, cwidth);
202 XtSetValues(cancel, args, ONE);
203 } else
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);
213 return form;
216 #if 0
217 /* get the prompt from the dialog box. Used a startup time to
218 * save away the initial prompt */
219 String
220 GetDialogPrompt(w)
221 Widget w;
223 Arg args[1];
224 Widget label;
225 String s;
227 label = XtNameToWidget(w, "prompt");
228 XtSetArg(args[0], nhStr(XtNlabel), &s);
229 XtGetValues(label, args, ONE);
230 return XtNewString(s);
232 #endif
234 /* set the prompt. This is used to put error information in the prompt */
235 void
236 SetDialogPrompt(w, newprompt)
237 Widget w;
238 String newprompt;
240 Arg args[1];
241 Widget label;
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 */
249 String
250 GetDialogResponse(w)
251 Widget w;
253 Arg args[1];
254 Widget response;
255 String s;
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 */
264 void
265 SetDialogResponse(w, s, ln)
266 Widget w;
267 String s;
268 unsigned ln;
270 Arg args[4];
271 Widget response;
272 XFontStruct *font;
273 Dimension width, nwidth, leftMargin, rightMargin;
274 unsigned s_len = strlen(s);
276 if (s_len < ln)
277 s_len = ln;
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;
286 if (nwidth < width)
287 nwidth = width;
289 XtSetArg(args[0], nhStr(XtNstring), s);
290 XtSetArg(args[1], nhStr(XtNwidth), nwidth);
291 XtSetValues(response, args, TWO);
292 XawTextSetInsertionPoint(response, strlen(s));
295 #if 0
296 /* clear the response */
297 void
298 ClearDialogResponse(w)
299 Widget w;
301 Arg args[2];
302 Widget response;
304 response = XtNameToWidget(w, "response");
305 XtSetArg(args[0], nhStr(XtNstring), "");
306 XtSetArg(args[1], nhStr(XtNwidth), 100);
307 XtSetValues(response, args, TWO);
309 #endif
311 /* Not a part of the original dialogs.c from ghostview -------------------- */
313 /* position popup window under the cursor */
314 void
315 positionpopup(w, bottom)
316 Widget w;
317 boolean bottom; /* position y on bottom? */
319 Arg args[3];
320 Cardinal num_args;
321 Dimension width, height, b_width;
322 int x, y, max_x, max_y;
323 Window root, child;
324 XSizeHints *hints;
325 int dummyx, dummyy;
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);
334 num_args = 0;
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);
343 if (x < 0)
344 x = 0;
345 if (x > (max_x = (Position) (XtScreen(w)->width - width)))
346 x = max_x;
348 if (bottom) {
349 y -= (height + b_width - 1);
350 height += 2 * b_width;
351 } else {
352 height += 2 * b_width;
353 y -= ((Position) height / 2);
355 if (y < 0)
356 y = 0;
357 if (y > (max_y = (Position) (XtScreen(w)->height - height)))
358 y = max_y;
360 num_args = 0;
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. */
367 XtRealizeWidget(w);
368 hints = XAllocSizeHints();
369 hints->flags = USPosition;
370 hints->x = x;
371 hints->y = y;
372 XSetWMNormalHints(XtDisplay(w), XtWindow(w), hints);
373 XFree(hints);
376 /*dialogs.c*/