OSDN Git Service

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