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
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
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
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
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, tmp, 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 | nwidth = (font->max_bounds.width * strlen(s))+leftMargin+rightMargin;
253 | tmp = width-(leftMargin+rightMargin);
254 | if (nwidth < tmp)
255 | nwidth = tmp;
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
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 | }