Dialog.c revision 775e7de9
1/* $Xorg: Dialog.c,v 1.4 2001/02/09 02:03:43 xorgcvs Exp $ */
2
3/***********************************************************
4
5Copyright 1987, 1988, 1994, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from The Open Group.
26
27
28Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
29
30                        All Rights Reserved
31
32Permission to use, copy, modify, and distribute this software and its
33documentation for any purpose and without fee is hereby granted,
34provided that the above copyright notice appear in all copies and that
35both that copyright notice and this permission notice appear in
36supporting documentation, and that the name of Digital not be
37used in advertising or publicity pertaining to distribution of the
38software without specific, written prior permission.
39
40DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
41ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
42DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
43ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
44WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
45ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46SOFTWARE.
47
48******************************************************************/
49/* $XFree86: xc/lib/Xaw/Dialog.c,v 1.7 2001/01/17 19:42:26 dawes Exp $ */
50
51#ifdef HAVE_CONFIG_H
52#include <config.h>
53#endif
54#include <X11/IntrinsicP.h>
55#include <X11/StringDefs.h>
56#include <X11/Xos.h>
57#include <X11/Xmu/Misc.h>
58#include <X11/Xaw/AsciiText.h>
59#include <X11/Xaw/Cardinals.h>
60#include <X11/Xaw/Command.h>
61#include <X11/Xaw/Label.h>
62#include <X11/Xaw/DialogP.h>
63#include <X11/Xaw/XawInit.h>
64#include "Private.h"
65
66/*
67 * After we have set the string in the value widget we set the
68 * string to a magic value.  So that when a SetValues request is made
69 * on the dialog value we will notice it, and reset the string
70 */
71#define MAGIC_VALUE	((char *)3)
72
73#define streq(a,b)	(strcmp((a), (b)) == 0)
74
75/*
76 * Class Methods
77 */
78static void XawDialogConstraintInitialize(Widget, Widget,
79					  ArgList, Cardinal*);
80static void XawDialogGetValuesHook(Widget, ArgList, Cardinal*);
81static void XawDialogInitialize(Widget, Widget, ArgList, Cardinal*);
82static Boolean XawDialogSetValues(Widget, Widget, Widget,
83				  ArgList, Cardinal*);
84
85/*
86 * Prototypes
87 */
88static void CreateDialogValueWidget(Widget);
89
90/*
91 * Initialization
92 */
93static XtResource resources[] = {
94  {
95    XtNlabel,
96    XtCLabel,
97    XtRString,
98    sizeof(String),
99    XtOffsetOf(DialogRec, dialog.label),
100    XtRString,
101    NULL
102  },
103  {
104    XtNvalue,
105    XtCValue,
106    XtRString,
107    sizeof(String),
108    XtOffsetOf(DialogRec, dialog.value),
109    XtRString,
110    NULL
111  },
112  {
113    XtNicon,
114    XtCIcon,
115    XtRBitmap,
116    sizeof(Pixmap),
117    XtOffsetOf(DialogRec, dialog.icon),
118    XtRImmediate,
119    NULL
120  },
121};
122
123DialogClassRec dialogClassRec = {
124  /* core */
125  {
126    (WidgetClass)&formClassRec,		/* superclass */
127    "Dialog",				/* class_name */
128    sizeof(DialogRec),			/* widget_size */
129    XawInitializeWidgetSet,		/* class_initialize */
130    NULL,				/* class_part init */
131    False,				/* class_inited */
132    XawDialogInitialize,		/* initialize */
133    NULL,				/* initialize_hook */
134    XtInheritRealize,			/* realize */
135    NULL,				/* actions */
136    0,					/* num_actions */
137    resources,				/* resources */
138    XtNumber(resources),		/* num_resources */
139    NULLQUARK,				/* xrm_class */
140    True,				/* compress_motion */
141    True,				/* compress_exposure */
142    True,				/* compress_enterleave */
143    False,				/* visible_interest */
144    NULL,				/* destroy */
145    XtInheritResize,			/* resize */
146    XtInheritExpose,			/* expose */
147    XawDialogSetValues,			/* set_values */
148    NULL,				/* set_values_hook */
149    XtInheritSetValuesAlmost,		/* set_values_almost */
150    XawDialogGetValuesHook,		/* get_values_hook */
151    NULL,				/* accept_focus */
152    XtVersion,				/* version */
153    NULL,				/* callback_private */
154    NULL,				/* tm_table */
155    XtInheritQueryGeometry,		/* query_geometry */
156    XtInheritDisplayAccelerator,	/* display_accelerator */
157    NULL,				/* extension */
158  },
159  /* composite */
160  {
161    XtInheritGeometryManager,		/* geometry_manager */
162    XtInheritChangeManaged,		/* change_managed */
163    XtInheritInsertChild,		/* insert_child */
164    XtInheritDeleteChild,		/* delete_child */
165    NULL,				/* extension */
166  },
167  /* constraint */
168  {
169    NULL,				/* subresourses */
170    0,					/* subresource_count */
171    sizeof(DialogConstraintsRec),	/* constraint_size */
172    XawDialogConstraintInitialize,	/* initialize */
173    NULL,				/* destroy */
174    NULL,				/* set_values */
175    NULL,				/* extension */
176  },
177  /* form */
178  {
179    XtInheritLayout,			/* layout */
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, Widget cnew,
195		    ArgList args, Cardinal *num_args)
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, Widget cnew,
235			      ArgList args, Cardinal *num_args)
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, 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    Cardinal num_args;
278    unsigned int i;
279    Bool checks[NUM_CHECKS];
280
281    for (i = 0; i < NUM_CHECKS; i++)
282	checks[i] = False;
283
284    for (i = 0; i < *in_num_args; i++) {
285	if (streq(XtNicon, in_args[i].name))
286	    checks[ICON] = True;
287	else if (streq(XtNlabel, in_args[i].name))
288	    checks[LABEL] = True;
289    }
290
291    if (checks[ICON]) {
292	if (w->dialog.icon != 0) {
293	    XtSetArg(args[0], XtNbitmap, w->dialog.icon);
294	    if (old->dialog.iconW != NULL)
295		XtSetValues(old->dialog.iconW, args, 1);
296	    else {
297		XtSetArg(args[1], XtNborderWidth, 0);
298		XtSetArg(args[2], XtNleft, XtChainLeft);
299		XtSetArg(args[3], XtNright, XtChainLeft);
300		w->dialog.iconW = XtCreateWidget("icon", labelWidgetClass,
301						 cnew, args, 4);
302		((DialogConstraints)w->dialog.labelW->core.constraints)->
303		    form.horiz_base = w->dialog.iconW;
304		XtManageChild(w->dialog.iconW);
305	    }
306	}
307	else if (old->dialog.icon != 0) {
308	    ((DialogConstraints)w->dialog.labelW->core.constraints)->
309		form.horiz_base = NULL;
310	    XtDestroyWidget(old->dialog.iconW);
311	    w->dialog.iconW = NULL;
312	}
313    }
314
315    if (checks[LABEL]) {
316	num_args = 0;
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    String s;
364    DialogWidget src = (DialogWidget)w;
365    unsigned int 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 * Function:
382 *	CreateDialogValueWidget
383 *
384 * Parameters:
385 *	w - dialog widget
386 *
387 * Description:
388 *	Creates the dialog widgets value widget.
389 *
390 * Note
391 *	Must be called only when w->dialog.value is non-nil
392 */
393static void
394CreateDialogValueWidget(Widget w)
395{
396    DialogWidget dw = (DialogWidget)w;
397    Arg arglist[10];
398    Cardinal num_args = 0;
399
400    XtSetArg(arglist[num_args], XtNstring, dw->dialog.value);     num_args++;
401    XtSetArg(arglist[num_args], XtNresizable, True);              num_args++;
402    XtSetArg(arglist[num_args], XtNeditType, XawtextEdit);        num_args++;
403    XtSetArg(arglist[num_args], XtNfromVert, dw->dialog.labelW);  num_args++;
404    XtSetArg(arglist[num_args], XtNleft, XtChainLeft);            num_args++;
405    XtSetArg(arglist[num_args], XtNright, XtChainRight);          num_args++;
406
407    dw->dialog.valueW = XtCreateWidget("value", asciiTextWidgetClass,
408				       w, arglist, num_args);
409
410    /* if the value widget is being added after buttons,
411     * then the buttons need new layout constraints
412     */
413    if (dw->composite.num_children > 1) {
414	WidgetList children = dw->composite.children;
415	Widget *childP;
416
417        for (childP = children + dw->composite.num_children - 1;
418	     childP >= children; childP-- ) {
419	    if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW)
420		continue;
421
422	    if (XtIsManaged(*childP) &&
423	        XtIsSubclass(*childP, commandWidgetClass)) {
424		((DialogConstraints)(*childP)->core.constraints)->
425		    form.vert_base = dw->dialog.valueW;
426	    }
427	}
428    }
429    XtManageChild(dw->dialog.valueW);
430
431    /*
432     * Value widget gets the keyboard focus
433     */
434    XtSetKeyboardFocus(w, dw->dialog.valueW);
435    dw->dialog.value = MAGIC_VALUE;
436}
437
438void
439XawDialogAddButton(Widget dialog, _Xconst char* name, XtCallbackProc function,
440		   XtPointer param)
441{
442    /*
443     * Correct Constraints are all set in ConstraintInitialize()
444     */
445    Widget button;
446
447    button = XtCreateManagedWidget(name, commandWidgetClass, dialog, NULL, 0);
448
449    if (function != NULL)	/* don't add NULL callback func */
450	XtAddCallback(button, XtNcallback, function, param);
451}
452
453char *
454XawDialogGetValueString(Widget w)
455{
456    Arg args[1];
457    char *value;
458
459    XtSetArg(args[0], XtNstring, &value);
460    XtGetValues(((DialogWidget)w)->dialog.valueW, args, 1);
461
462    return(value);
463}
464