Dialog.c revision 5ec34c4c
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 }, 178 /* dialog */ 179 { 180 NULL, /* extension */ 181 } 182}; 183 184WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec; 185 186/* 187 * Implementation 188 */ 189/*ARGSUSED*/ 190static void 191XawDialogInitialize(Widget request _X_UNUSED, Widget cnew, 192 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 193{ 194 DialogWidget dw = (DialogWidget)cnew; 195 Arg arglist[9]; 196 Cardinal arg_cnt = 0; 197 198 XtSetArg(arglist[arg_cnt], XtNborderWidth, 0); arg_cnt++; 199 XtSetArg(arglist[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; 200 201 if (dw->dialog.icon != (Pixmap)0) { 202 XtSetArg(arglist[arg_cnt], XtNbitmap, dw->dialog.icon); arg_cnt++; 203 XtSetArg(arglist[arg_cnt], XtNright, XtChainLeft); arg_cnt++; 204 dw->dialog.iconW = XtCreateManagedWidget("icon", labelWidgetClass, 205 cnew, arglist, arg_cnt); 206 arg_cnt = 2; 207 XtSetArg(arglist[arg_cnt], XtNfromHoriz, dw->dialog.iconW); arg_cnt++; 208 } 209 else 210 dw->dialog.iconW = NULL; 211 212 XtSetArg(arglist[arg_cnt], XtNlabel, dw->dialog.label); arg_cnt++; 213 XtSetArg(arglist[arg_cnt], XtNright, XtChainRight); arg_cnt++; 214 215 dw->dialog.labelW = XtCreateManagedWidget("label", labelWidgetClass, 216 cnew, arglist, arg_cnt); 217 218 if (dw->dialog.iconW != NULL && 219 XtHeight(dw->dialog.labelW) < XtHeight(dw->dialog.iconW)) { 220 XtSetArg(arglist[0], XtNheight, XtHeight(dw->dialog.iconW)); 221 XtSetValues(dw->dialog.labelW, arglist, 1); 222 } 223 if (dw->dialog.value != NULL) 224 CreateDialogValueWidget((Widget)dw); 225 else 226 dw->dialog.valueW = NULL; 227} 228 229/*ARGSUSED*/ 230static void 231XawDialogConstraintInitialize(Widget request _X_UNUSED, Widget cnew, 232 ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED) 233{ 234 DialogWidget dw = (DialogWidget)cnew->core.parent; 235 DialogConstraints constraint = (DialogConstraints)cnew->core.constraints; 236 237 if (!XtIsSubclass(cnew, commandWidgetClass)) /* if not a button */ 238 return; /* then just use defaults */ 239 240 constraint->form.left = constraint->form.right = XtChainLeft; 241 if (dw->dialog.valueW == NULL) 242 constraint->form.vert_base = dw->dialog.labelW; 243 else 244 constraint->form.vert_base = dw->dialog.valueW; 245 246 if (dw->composite.num_children > 1) { 247 WidgetList children = dw->composite.children; 248 Widget *childP; 249 250 for (childP = children + dw->composite.num_children - 1; 251 childP >= children; childP-- ) { 252 if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW) 253 break; 254 if (XtIsManaged(*childP) && 255 XtIsSubclass(*childP, commandWidgetClass)) { 256 constraint->form.horiz_base = *childP; 257 break; 258 } 259 } 260 } 261} 262 263#define ICON 0 264#define LABEL 1 265#define NUM_CHECKS 2 266/*ARGSUSED*/ 267static Boolean 268XawDialogSetValues(Widget current, Widget request _X_UNUSED, Widget cnew, 269 ArgList in_args, Cardinal *in_num_args) 270{ 271 DialogWidget w = (DialogWidget)cnew; 272 DialogWidget old = (DialogWidget)current; 273 Arg args[5]; 274 Cardinal num_args; 275 unsigned int i; 276 Bool checks[NUM_CHECKS]; 277 278 for (i = 0; i < NUM_CHECKS; i++) 279 checks[i] = False; 280 281 for (i = 0; i < *in_num_args; i++) { 282 if (streq(XtNicon, in_args[i].name)) 283 checks[ICON] = True; 284 else if (streq(XtNlabel, in_args[i].name)) 285 checks[LABEL] = True; 286 } 287 288 if (checks[ICON]) { 289 if (w->dialog.icon != 0) { 290 XtSetArg(args[0], XtNbitmap, w->dialog.icon); 291 if (old->dialog.iconW != NULL) 292 XtSetValues(old->dialog.iconW, args, 1); 293 else { 294 XtSetArg(args[1], XtNborderWidth, 0); 295 XtSetArg(args[2], XtNleft, XtChainLeft); 296 XtSetArg(args[3], XtNright, XtChainLeft); 297 w->dialog.iconW = XtCreateWidget("icon", labelWidgetClass, 298 cnew, args, 4); 299 ((DialogConstraints)w->dialog.labelW->core.constraints)-> 300 form.horiz_base = w->dialog.iconW; 301 XtManageChild(w->dialog.iconW); 302 } 303 } 304 else if (old->dialog.icon != 0) { 305 ((DialogConstraints)w->dialog.labelW->core.constraints)-> 306 form.horiz_base = NULL; 307 XtDestroyWidget(old->dialog.iconW); 308 w->dialog.iconW = NULL; 309 } 310 } 311 312 if (checks[LABEL]) { 313 num_args = 0; 314 XtSetArg(args[num_args], XtNlabel, w->dialog.label); num_args++; 315 if (w->dialog.iconW != NULL && 316 XtHeight(w->dialog.labelW) <= XtHeight(w->dialog.iconW)) { 317 XtSetArg(args[num_args], XtNheight, XtHeight(w->dialog.iconW)); 318 num_args++; 319 } 320 XtSetValues(w->dialog.labelW, args, num_args); 321 } 322 323 if (w->dialog.value != old->dialog.value) { 324 if (w->dialog.value == NULL) /* only get here if it 325 wasn't NULL before */ 326 XtDestroyWidget(old->dialog.valueW); 327 else if (old->dialog.value == NULL) { /* create a new value widget */ 328 XtWidth(w) = XtWidth(old); 329 XtHeight(w) = XtHeight(old); 330 CreateDialogValueWidget(cnew); 331 } 332 else { /* Widget ok, just change string */ 333 Arg nargs[1]; 334 335 XtSetArg(nargs[0], XtNstring, w->dialog.value); 336 XtSetValues(w->dialog.valueW, nargs, 1); 337 w->dialog.value = MAGIC_VALUE; 338 } 339 } 340 341 return (False); 342} 343 344/* 345 * Function: 346 * XawDialogGetValuesHook 347 * 348 * Parameters: 349 * w - Dialog Widget 350 * args - argument list 351 * num_args - number of args 352 * 353 * Description: 354 * This is a get values hook routine that gets the values in the dialog. 355 */ 356static void 357XawDialogGetValuesHook(Widget w, ArgList args, Cardinal *num_args) 358{ 359 Arg a[1]; 360 char * s; 361 DialogWidget src = (DialogWidget)w; 362 unsigned int i; 363 364 for (i = 0; i < *num_args; i++) 365 if (streq(args[i].name, XtNvalue)) { 366 XtSetArg(a[0], XtNstring, &s); 367 XtGetValues(src->dialog.valueW, a, 1); 368 *((char **)args[i].value) = s; 369 } 370 else if (streq(args[i].name, XtNlabel)) { 371 XtSetArg(a[0], XtNlabel, &s); 372 XtGetValues(src->dialog.labelW, a, 1); 373 *((char **)args[i].value) = s; 374 } 375} 376 377/* 378 * Function: 379 * CreateDialogValueWidget 380 * 381 * Parameters: 382 * w - dialog widget 383 * 384 * Description: 385 * Creates the dialog widgets value widget. 386 * 387 * Note 388 * Must be called only when w->dialog.value is non-nil 389 */ 390static void 391CreateDialogValueWidget(Widget w) 392{ 393 DialogWidget dw = (DialogWidget)w; 394 Arg arglist[10]; 395 Cardinal num_args = 0; 396 397 XtSetArg(arglist[num_args], XtNstring, dw->dialog.value); num_args++; 398 XtSetArg(arglist[num_args], XtNresizable, True); num_args++; 399 XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); num_args++; 400 XtSetArg(arglist[num_args], XtNfromVert, dw->dialog.labelW); num_args++; 401 XtSetArg(arglist[num_args], XtNleft, XtChainLeft); num_args++; 402 XtSetArg(arglist[num_args], XtNright, XtChainRight); num_args++; 403 404 dw->dialog.valueW = XtCreateWidget("value", asciiTextWidgetClass, 405 w, arglist, num_args); 406 407 /* if the value widget is being added after buttons, 408 * then the buttons need new layout constraints 409 */ 410 if (dw->composite.num_children > 1) { 411 WidgetList children = dw->composite.children; 412 Widget *childP; 413 414 for (childP = children + dw->composite.num_children - 1; 415 childP >= children; childP-- ) { 416 if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW) 417 continue; 418 419 if (XtIsManaged(*childP) && 420 XtIsSubclass(*childP, commandWidgetClass)) { 421 ((DialogConstraints)(*childP)->core.constraints)-> 422 form.vert_base = dw->dialog.valueW; 423 } 424 } 425 } 426 XtManageChild(dw->dialog.valueW); 427 428 /* 429 * Value widget gets the keyboard focus 430 */ 431 XtSetKeyboardFocus(w, dw->dialog.valueW); 432 dw->dialog.value = MAGIC_VALUE; 433} 434 435void 436XawDialogAddButton(Widget dialog, _Xconst char* name, XtCallbackProc function, 437 XtPointer param) 438{ 439 /* 440 * Correct Constraints are all set in ConstraintInitialize() 441 */ 442 Widget button; 443 444 button = XtCreateManagedWidget(name, commandWidgetClass, dialog, NULL, 0); 445 446 if (function != NULL) /* don't add NULL callback func */ 447 XtAddCallback(button, XtNcallback, function, param); 448} 449 450char * 451XawDialogGetValueString(Widget w) 452{ 453 Arg args[1]; 454 char *value; 455 456 XtSetArg(args[0], XtNstring, &value); 457 XtGetValues(((DialogWidget)w)->dialog.valueW, args, 1); 458 459 return(value); 460} 461