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