1 /* $XConsortium: Dialog.c,v 1.48 94/04/17 20:12:02 kaleb Exp $ */
2
3 /***********************************************************
4
5 Copyright (c) 1987, 1988, 1994 X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
27
28
29 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
30
31 All Rights Reserved
32
33 Permission to use, copy, modify, and distribute this software and its
34 documentation for any purpose and without fee is hereby granted,
35 provided that the above copyright notice appear in all copies and that
36 both that copyright notice and this permission notice appear in
37 supporting documentation, and that the name of Digital not be
38 used in advertising or publicity pertaining to distribution of the
39 software without specific, written prior permission.
40
41 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
42 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
43 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
44 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
45 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
46 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 SOFTWARE.
48
49 ******************************************************************/
50
51 /* NOTE: THIS IS NOT A WIDGET! Rather, this is an interface to a widget.
52 It implements policy, and gives a (hopefully) easier-to-use interface
53 than just directly making your own form. */
54
55
56 #include <X11/IntrinsicP.h>
57 #include <X11/Xos.h>
58 #include <X11/StringDefs.h>
59 #include <X11/Xmu/Misc.h>
60
61 #include <X11/Xaw3d/XawInit.h>
62 #include <X11/Xaw3d/AsciiText.h>
63 #include <X11/Xaw3d/Command.h>
64 #include <X11/Xaw3d/Label.h>
65 #include <X11/Xaw3d/DialogP.h>
66 #include <X11/Xaw3d/Cardinals.h>
67
68 /*
69 * After we have set the string in the value widget we set the
70 * string to a magic value. So that when a SetValues request is made
71 * on the dialog value we will notice it, and reset the string.
72 */
73
74 #define MAGIC_VALUE ((char *) 3)
75
76 #define streq(a,b) (strcmp( (a), (b) ) == 0)
77
78 static XtResource resources[] = {
79 {XtNlabel, XtCLabel, XtRString, sizeof(String),
80 XtOffsetOf(DialogRec, dialog.label), XtRString, NULL},
81 {XtNvalue, XtCValue, XtRString, sizeof(String),
82 XtOffsetOf(DialogRec, dialog.value), XtRString, NULL},
83 {XtNicon, XtCIcon, XtRBitmap, sizeof(Pixmap),
84 XtOffsetOf(DialogRec, dialog.icon), XtRImmediate, 0},
85 };
86
87 static void Initialize(), ConstraintInitialize(), CreateDialogValueWidget(),
88 GetValuesHook();
89
90 static Boolean SetValues();
91
92 DialogClassRec dialogClassRec = {
93 { /* core_class fields */
94 /* superclass */ (WidgetClass) &formClassRec,
95 /* class_name */ "Dialog",
96 /* widget_size */ sizeof(DialogRec),
97 /* class_initialize */ XawInitializeWidgetSet,
98 /* class_part init */ NULL,
99 /* class_inited */ FALSE,
100 /* initialize */ Initialize,
101 /* initialize_hook */ NULL,
102 /* realize */ XtInheritRealize,
103 /* actions */ NULL,
104 /* num_actions */ 0,
105 /* resources */ resources,
106 /* num_resources */ XtNumber(resources),
107 /* xrm_class */ NULLQUARK,
108 /* compress_motion */ TRUE,
109 /* compress_exposure */ TRUE,
110 /* compress_enterleave*/ TRUE,
111 /* visible_interest */ FALSE,
112 /* destroy */ NULL,
113 /* resize */ XtInheritResize,
114 /* expose */ XtInheritExpose,
115 /* set_values */ SetValues,
116 /* set_values_hook */ NULL,
117 /* set_values_almost */ XtInheritSetValuesAlmost,
118 /* get_values_hook */ GetValuesHook,
119 /* accept_focus */ NULL,
120 /* version */ XtVersion,
121 /* callback_private */ NULL,
122 /* tm_table */ NULL,
123 /* query_geometry */ XtInheritQueryGeometry,
124 /* display_accelerator*/ XtInheritDisplayAccelerator,
125 /* extension */ NULL
126 },
127 { /* composite_class fields */
128 /* geometry_manager */ XtInheritGeometryManager,
129 /* change_managed */ XtInheritChangeManaged,
130 /* insert_child */ XtInheritInsertChild,
131 /* delete_child */ XtInheritDeleteChild,
132 /* extension */ NULL
133 },
134 { /* constraint_class fields */
135 /* subresourses */ NULL,
136 /* subresource_count */ 0,
137 /* constraint_size */ sizeof(DialogConstraintsRec),
138 /* initialize */ ConstraintInitialize,
139 /* destroy */ NULL,
140 /* set_values */ NULL,
141 /* extension */ NULL
142 },
143 { /* form_class fields */
144 /* layout */ XtInheritLayout
145 },
146 { /* dialog_class fields */
147 /* empty */ 0
148 }
149 };
150
151 WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec;
152
153 /* ARGSUSED */
Initialize(request,new,args,num_args)154 static void Initialize(request, new, args, num_args)
155 Widget request, new;
156 ArgList args;
157 Cardinal *num_args;
158 {
159 DialogWidget dw = (DialogWidget)new;
160 Arg arglist[9];
161 Cardinal arg_cnt = 0;
162
163 XtSetArg(arglist[arg_cnt], XtNborderWidth, 0); arg_cnt++;
164 XtSetArg(arglist[arg_cnt], XtNleft, XtChainLeft); arg_cnt++;
165
166 if (dw->dialog.icon != (Pixmap)0) {
167 XtSetArg(arglist[arg_cnt], XtNbitmap, dw->dialog.icon); arg_cnt++;
168 XtSetArg(arglist[arg_cnt], XtNright, XtChainLeft); arg_cnt++;
169 dw->dialog.iconW =
170 XtCreateManagedWidget( "icon", labelWidgetClass,
171 new, arglist, arg_cnt );
172 arg_cnt = 2;
173 XtSetArg(arglist[arg_cnt], XtNfromHoriz, dw->dialog.iconW);arg_cnt++;
174 } else dw->dialog.iconW = (Widget)NULL;
175
176 XtSetArg(arglist[arg_cnt], XtNlabel, dw->dialog.label); arg_cnt++;
177 XtSetArg(arglist[arg_cnt], XtNright, XtChainRight); arg_cnt++;
178
179 dw->dialog.labelW = XtCreateManagedWidget( "label", labelWidgetClass,
180 new, arglist, arg_cnt);
181
182 if (dw->dialog.iconW != (Widget)NULL &&
183 (dw->dialog.labelW->core.height < dw->dialog.iconW->core.height)) {
184 XtSetArg( arglist[0], XtNheight, dw->dialog.iconW->core.height );
185 XtSetValues( dw->dialog.labelW, arglist, ONE );
186 }
187 if (dw->dialog.value != NULL)
188 CreateDialogValueWidget( (Widget) dw);
189 else
190 dw->dialog.valueW = NULL;
191 }
192
193 /* ARGSUSED */
ConstraintInitialize(request,new,args,num_args)194 static void ConstraintInitialize(request, new, args, num_args)
195 Widget request, new;
196 ArgList args;
197 Cardinal *num_args;
198 {
199 DialogWidget dw = (DialogWidget)new->core.parent;
200 DialogConstraints constraint = (DialogConstraints)new->core.constraints;
201
202 if (!XtIsSubclass(new, commandWidgetClass)) /* if not a button */
203 return; /* then just use defaults */
204
205 constraint->form.left = constraint->form.right = XtChainLeft;
206 if (dw->dialog.valueW == NULL)
207 constraint->form.vert_base = dw->dialog.labelW;
208 else
209 constraint->form.vert_base = dw->dialog.valueW;
210
211 if (dw->composite.num_children > 1) {
212 WidgetList children = dw->composite.children;
213 Widget *childP;
214 for (childP = children + dw->composite.num_children - 1;
215 childP >= children; childP-- ) {
216 if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW)
217 break;
218 if (XtIsManaged(*childP) &&
219 XtIsSubclass(*childP, commandWidgetClass)) {
220 constraint->form.horiz_base = *childP;
221 break;
222 }
223 }
224 }
225 }
226
227 #define ICON 0
228 #define LABEL 1
229 #define NUM_CHECKS 2
230
231 /* ARGSUSED */
SetValues(current,request,new,in_args,in_num_args)232 static Boolean SetValues(current, request, new, in_args, in_num_args)
233 Widget current, request, new;
234 ArgList in_args;
235 Cardinal *in_num_args;
236 {
237 DialogWidget w = (DialogWidget)new;
238 DialogWidget old = (DialogWidget)current;
239 Arg args[5];
240 Cardinal num_args;
241 int i;
242 Boolean checks[NUM_CHECKS];
243
244 for (i = 0; i < NUM_CHECKS; i++)
245 checks[i] = FALSE;
246
247 for (i = 0; i < *in_num_args; i++) {
248 if (streq(XtNicon, in_args[i].name))
249 checks[ICON] = TRUE;
250 if (streq(XtNlabel, in_args[i].name))
251 checks[LABEL] = TRUE;
252 }
253
254 if (checks[ICON]) {
255 if (w->dialog.icon != (Pixmap)0) {
256 XtSetArg( args[0], XtNbitmap, w->dialog.icon );
257 if (old->dialog.iconW != (Widget)NULL) {
258 XtSetValues( old->dialog.iconW, args, ONE );
259 } else {
260 XtSetArg( args[1], XtNborderWidth, 0);
261 XtSetArg( args[2], XtNleft, XtChainLeft);
262 XtSetArg( args[3], XtNright, XtChainLeft);
263 w->dialog.iconW =
264 XtCreateWidget( "icon", labelWidgetClass,
265 new, args, FOUR );
266 ((DialogConstraints)w->dialog.labelW->core.constraints)->
267 form.horiz_base = w->dialog.iconW;
268 XtManageChild(w->dialog.iconW);
269 }
270 } else if (old->dialog.icon != (Pixmap)0) {
271 ((DialogConstraints)w->dialog.labelW->core.constraints)->
272 form.horiz_base = (Widget)NULL;
273 XtDestroyWidget(old->dialog.iconW);
274 w->dialog.iconW = (Widget)NULL;
275 }
276 }
277
278 if ( checks[LABEL] ) {
279 num_args = 0;
280 XtSetArg( args[num_args], XtNlabel, w->dialog.label ); num_args++;
281 if (w->dialog.iconW != (Widget)NULL &&
282 (w->dialog.labelW->core.height <= w->dialog.iconW->core.height)) {
283 XtSetArg(args[num_args], XtNheight, w->dialog.iconW->core.height);
284 num_args++;
285 }
286 XtSetValues( w->dialog.labelW, args, num_args );
287 }
288
289 if ( w->dialog.value != old->dialog.value ) {
290 if (w->dialog.value == NULL) /* only get here if it
291 wasn't NULL before. */
292 XtDestroyWidget(old->dialog.valueW);
293 else if (old->dialog.value == NULL) { /* create a new value widget. */
294 w->core.width = old->core.width;
295 w->core.height = old->core.height;
296 #ifdef notdef
297 /* this would be correct if Form had the same semantics on Resize
298 * as on MakeGeometryRequest. Unfortunately, Form botched it, so
299 * any subclasses will currently have to deal with the fact that
300 * we're about to change our real size.
301 */
302 w->form.resize_in_layout = False;
303 CreateDialogValueWidget( (Widget) w);
304 w->core.width = w->form.preferred_width;
305 w->core.height = w->form.preferred_height;
306 w->form.resize_in_layout = True;
307 #else /*notdef*/
308 CreateDialogValueWidget( (Widget) w);
309 #endif /*notdef*/
310 }
311 else { /* Widget ok, just change string. */
312 Arg args[1];
313 XtSetArg(args[0], XtNstring, w->dialog.value);
314 XtSetValues(w->dialog.valueW, args, ONE);
315 w->dialog.value = MAGIC_VALUE;
316 }
317 }
318 return False;
319 }
320
321 /* Function Name: GetValuesHook
322 * Description: This is a get values hook routine that gets the
323 * values in the dialog.
324 * Arguments: w - the Text Widget.
325 * args - the argument list.
326 * num_args - the number of args.
327 * Returns: none.
328 */
329
330 static void
GetValuesHook(w,args,num_args)331 GetValuesHook(w, args, num_args)
332 Widget w;
333 ArgList args;
334 Cardinal * num_args;
335 {
336 Arg a[1];
337 String s;
338 DialogWidget src = (DialogWidget) w;
339 int i;
340
341 for (i=0; i < *num_args; i++)
342 if (streq(args[i].name, XtNvalue)) {
343 XtSetArg(a[0], XtNstring, &s);
344 XtGetValues(src->dialog.valueW, a, 1);
345 *((char **) args[i].value) = s;
346 }
347 }
348
349
350 /* Function Name: CreateDialogValueWidget
351 * Description: Creates the dialog widgets value widget.
352 * Arguments: w - the dialog widget.
353 * Returns: none.
354 *
355 * must be called only when w->dialog.value is non-nil.
356 */
357
358 static void
CreateDialogValueWidget(w)359 CreateDialogValueWidget(w)
360 Widget w;
361 {
362 DialogWidget dw = (DialogWidget) w;
363 Arg arglist[10];
364 Cardinal num_args = 0;
365
366 #ifdef notdef
367 XtSetArg(arglist[num_args], XtNwidth,
368 dw->dialog.labelW->core.width); num_args++; /* ||| hack */
369 #endif /*notdef*/
370 XtSetArg(arglist[num_args], XtNstring, dw->dialog.value); num_args++;
371 XtSetArg(arglist[num_args], XtNresizable, True); num_args++;
372 XtSetArg(arglist[num_args], XtNresize, XawtextResizeBoth); num_args++;
373 XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); num_args++;
374 XtSetArg(arglist[num_args], XtNfromVert, dw->dialog.labelW); num_args++;
375 XtSetArg(arglist[num_args], XtNleft, XtChainLeft); num_args++;
376 XtSetArg(arglist[num_args], XtNright, XtChainRight); num_args++;
377
378 dw->dialog.valueW = XtCreateWidget("value", asciiTextWidgetClass,
379 w, arglist, num_args);
380
381 /* if the value widget is being added after buttons,
382 * then the buttons need new layout constraints.
383 */
384 if (dw->composite.num_children > 1) {
385 WidgetList children = dw->composite.children;
386 Widget *childP;
387 for (childP = children + dw->composite.num_children - 1;
388 childP >= children; childP-- ) {
389 if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW)
390 continue;
391 if (XtIsManaged(*childP) &&
392 XtIsSubclass(*childP, commandWidgetClass)) {
393 ((DialogConstraints)(*childP)->core.constraints)->
394 form.vert_base = dw->dialog.valueW;
395 }
396 }
397 }
398 XtManageChild(dw->dialog.valueW);
399
400 /*
401 * Value widget gets the keyboard focus.
402 */
403
404 XtSetKeyboardFocus(w, dw->dialog.valueW);
405 dw->dialog.value = MAGIC_VALUE;
406 }
407
408
409 void
410 #if NeedFunctionPrototypes
XawDialogAddButton(Widget dialog,_Xconst char * name,XtCallbackProc function,XtPointer param)411 XawDialogAddButton(Widget dialog, _Xconst char* name, XtCallbackProc function,
412 XtPointer param)
413 #else
414 XawDialogAddButton(dialog, name, function, param)
415 Widget dialog;
416 String name;
417 XtCallbackProc function;
418 XtPointer param;
419 #endif
420 {
421 /*
422 * Correct Constraints are all set in ConstraintInitialize().
423 */
424 Widget button;
425
426 button = XtCreateManagedWidget( name, commandWidgetClass, dialog,
427 (ArgList)NULL, (Cardinal)0 );
428
429 if (function != NULL) /* don't add NULL callback func. */
430 XtAddCallback(button, XtNcallback, function, param);
431 }
432
433
434 char *
435 #if NeedFunctionPrototypes
XawDialogGetValueString(Widget w)436 XawDialogGetValueString(Widget w)
437 #else
438 XawDialogGetValueString(w)
439 Widget w;
440 #endif
441 {
442 Arg args[1];
443 char * value;
444
445 XtSetArg(args[0], XtNstring, &value);
446 XtGetValues( ((DialogWidget)w)->dialog.valueW, args, ONE);
447 return(value);
448 }
449