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