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