SetValues.c revision 0568f49b
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the "Software"), 6to deal in the Software without restriction, including without limitation 7the rights to use, copy, modify, merge, publish, distribute, sublicense, 8and/or sell copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice (including the next 12paragraph) shall be included in all copies or substantial portions of the 13Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21DEALINGS IN THE SOFTWARE. 22 23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24 25 All Rights Reserved 26 27Permission to use, copy, modify, and distribute this software and its 28documentation for any purpose and without fee is hereby granted, 29provided that the above copyright notice appear in all copies and that 30both that copyright notice and this permission notice appear in 31supporting documentation, and that the name of Digital not be 32used in advertising or publicity pertaining to distribution of the 33software without specific, written prior permission. 34 35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41SOFTWARE. 42 43******************************************************************/ 44 45/* 46 47Copyright 1987, 1988, 1994, 1998 The Open Group 48 49Permission to use, copy, modify, distribute, and sell this software and its 50documentation for any purpose is hereby granted without fee, provided that 51the above copyright notice appear in all copies and that both that 52copyright notice and this permission notice appear in supporting 53documentation. 54 55The above copyright notice and this permission notice shall be included in 56all copies or substantial portions of the Software. 57 58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 65Except as contained in this notice, the name of The Open Group shall not be 66used in advertising or otherwise to promote the sale, use or other dealings 67in this Software without prior written authorization from The Open Group. 68 69*/ 70 71#ifdef HAVE_CONFIG_H 72#include <config.h> 73#endif 74#include "IntrinsicI.h" 75 76/* 77 * XtSetValues(), XtSetSubvalues() 78 */ 79 80 81static void SetValues( 82 char* base, /* Base address to write values to */ 83 XrmResourceList* res, /* The current resource values. */ 84 register Cardinal num_resources, /* number of items in resources */ 85 ArgList args, /* The resource values to set */ 86 Cardinal num_args) /* number of items in arg list */ 87{ 88 register ArgList arg; 89 register Cardinal i; 90 register XrmName argName; 91 register XrmResourceList* xrmres; 92 93 /* Resource lists are assumed to be in compiled form already via the 94 initial XtGetResources, XtGetSubresources calls */ 95 96 for (arg = args ; num_args != 0; num_args--, arg++) { 97 argName = StringToName(arg->name); 98 for (xrmres = res, i = 0; i < num_resources; i++, xrmres++) { 99 if (argName == (*xrmres)->xrm_name) { 100 _XtCopyFromArg(arg->value, 101 base - (*xrmres)->xrm_offset - 1, 102 (*xrmres)->xrm_size); 103 break; 104 } 105 } 106 } 107} /* SetValues */ 108 109static Boolean CallSetValues ( 110 WidgetClass class, 111 Widget current, 112 Widget request, 113 Widget new, 114 ArgList args, 115 Cardinal num_args) 116{ 117 Boolean redisplay = FALSE; 118 WidgetClass superclass; 119 XtArgsFunc set_values_hook; 120 XtSetValuesFunc set_values; 121 122 LOCK_PROCESS; 123 superclass = class->core_class.superclass; 124 UNLOCK_PROCESS; 125 if (superclass) 126 redisplay = 127 CallSetValues(superclass, current, request, new, args, num_args); 128 129 LOCK_PROCESS; 130 set_values = class->core_class.set_values; 131 UNLOCK_PROCESS; 132 if (set_values) 133 redisplay |= (*set_values) (current, request, new, args, &num_args); 134 135 LOCK_PROCESS; 136 set_values_hook = class->core_class.set_values_hook; 137 UNLOCK_PROCESS; 138 if (set_values_hook) 139 redisplay |= (*set_values_hook) (new, args, &num_args); 140 return (redisplay); 141} 142 143static Boolean 144CallConstraintSetValues ( 145 ConstraintWidgetClass class, 146 Widget current, 147 Widget request, 148 Widget new, 149 ArgList args, 150 Cardinal num_args) 151{ 152 Boolean redisplay = FALSE; 153 XtSetValuesFunc set_values; 154 155 if ((WidgetClass)class != constraintWidgetClass) { 156 ConstraintWidgetClass superclass; 157 158 if (class == NULL) { 159 XtAppErrorMsg(XtWidgetToApplicationContext(current), 160 "invalidClass","constraintSetValue",XtCXtToolkitError, 161 "Subclass of Constraint required in CallConstraintSetValues", 162 NULL, NULL); 163 } else { 164 LOCK_PROCESS; 165 superclass = (ConstraintWidgetClass) class->core_class.superclass; 166 UNLOCK_PROCESS; 167 redisplay = 168 CallConstraintSetValues(superclass, 169 current, request, new, args, num_args); 170 } 171 } 172 LOCK_PROCESS; 173 set_values = class ? class->constraint_class.set_values : NULL; 174 UNLOCK_PROCESS; 175 if (set_values) 176 redisplay |= (*set_values) (current, request, new, args, &num_args); 177 return (redisplay); 178} 179 180void XtSetSubvalues( 181 XtPointer base, /* Base address to write values to */ 182 register XtResourceList resources, /* The current resource values. */ 183 register Cardinal num_resources, /* number of items in resources */ 184 ArgList args, /* The resource values to set */ 185 Cardinal num_args) /* number of items in arg list */ 186{ 187 register XrmResourceList* xrmres; 188 xrmres = _XtCreateIndirectionTable (resources, num_resources); 189 SetValues((char*)base,xrmres,num_resources, args, num_args); 190 XtFree((char *)xrmres); 191} 192 193 194void XtSetValues( 195 register Widget w, 196 ArgList args, 197 Cardinal num_args) 198{ 199 register Widget oldw, reqw; 200 /* need to use strictest alignment rules possible in next two decls. */ 201 double oldwCache[100], reqwCache[100]; 202 double oldcCache[20], reqcCache[20]; 203 Cardinal widgetSize, constraintSize; 204 Boolean redisplay, cleared_rect_obj = False; 205 XtGeometryResult result; 206 XtWidgetGeometry geoReq, geoReply; 207 WidgetClass wc; 208 ConstraintWidgetClass cwc = NULL; 209 Boolean hasConstraints; 210 XtAppContext app = XtWidgetToApplicationContext(w); 211 Widget hookobj = XtHooksOfDisplay(XtDisplayOfObject(w)); 212 213 LOCK_APP(app); 214 wc = XtClass(w); 215 if ((args == NULL) && (num_args != 0)) { 216 XtAppErrorMsg(app, 217 "invalidArgCount","xtSetValues",XtCXtToolkitError, 218 "Argument count > 0 on NULL argument list in XtSetValues", 219 NULL, NULL); 220 } 221 222 /* Allocate and copy current widget into old widget */ 223 224 LOCK_PROCESS; 225 widgetSize = wc->core_class.widget_size; 226 UNLOCK_PROCESS; 227 oldw = (Widget) XtStackAlloc(widgetSize, oldwCache); 228 reqw = (Widget) XtStackAlloc (widgetSize, reqwCache); 229 (void) memmove((char *) oldw, (char *) w, (size_t) widgetSize); 230 231 /* Set resource values */ 232 233 LOCK_PROCESS; 234 SetValues((char*)w, (XrmResourceList *) wc->core_class.resources, 235 wc->core_class.num_resources, args, num_args); 236 UNLOCK_PROCESS; 237 238 (void) memmove ((char *) reqw, (char *) w, (size_t) widgetSize); 239 240 hasConstraints = (XtParent(w) != NULL && !XtIsShell(w) && XtIsConstraint(XtParent(w))); 241 242 /* Some widget sets apparently do ugly things by freeing the 243 * constraints on some children, thus the extra test here */ 244 if (hasConstraints) { 245 cwc = (ConstraintWidgetClass) XtClass(w->core.parent); 246 if (w->core.constraints) { 247 LOCK_PROCESS; 248 constraintSize = cwc->constraint_class.constraint_size; 249 UNLOCK_PROCESS; 250 } else constraintSize = 0; 251 } else constraintSize = 0; 252 253 if (constraintSize) { 254 /* Allocate and copy current constraints into oldw */ 255 oldw->core.constraints = XtStackAlloc(constraintSize, oldcCache); 256 reqw->core.constraints = XtStackAlloc(constraintSize, reqcCache); 257 (void) memmove((char *) oldw->core.constraints, 258 (char *) w->core.constraints, (size_t) constraintSize); 259 260 /* Set constraint values */ 261 LOCK_PROCESS; 262 SetValues((char*)w->core.constraints, 263 (XrmResourceList *)(cwc->constraint_class.resources), 264 cwc->constraint_class.num_resources, args, num_args); 265 UNLOCK_PROCESS; 266 (void) memmove((char *) reqw->core.constraints, 267 (char *) w->core.constraints, (size_t) constraintSize); 268 } 269 270 /* Inform widget of changes, then inform parent of changes */ 271 redisplay = CallSetValues (wc, oldw, reqw, w, args, num_args); 272 if (hasConstraints) { 273 redisplay |= CallConstraintSetValues(cwc, oldw, reqw, w, args, num_args); 274 } 275 276 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 277 XtChangeHookDataRec call_data; 278 XtChangeHookSetValuesDataRec set_val; 279 280 set_val.old = oldw; 281 set_val.req = reqw; 282 set_val.args = args; 283 set_val.num_args = num_args; 284 call_data.type = XtHsetValues; 285 call_data.widget = w; 286 call_data.event_data = (XtPointer) &set_val; 287 XtCallCallbackList(hookobj, 288 ((HookObject)hookobj)->hooks.changehook_callbacks, 289 (XtPointer)&call_data); 290 } 291 292 if (XtIsRectObj(w)) { 293 /* Now perform geometry request if needed */ 294 geoReq.request_mode = 0; 295 if (oldw->core.x != w->core.x) { 296 geoReq.x = w->core.x; 297 w->core.x = oldw->core.x; 298 geoReq.request_mode |= CWX; 299 } 300 if (oldw->core.y != w->core.y) { 301 geoReq.y = w->core.y; 302 w->core.y = oldw->core.y; 303 geoReq.request_mode |= CWY; 304 } 305 if (oldw->core.width != w->core.width) { 306 geoReq.width = w->core.width; 307 w->core.width = oldw->core.width; 308 geoReq.request_mode |= CWWidth; 309 } 310 if (oldw->core.height != w->core.height) { 311 geoReq.height = w->core.height; 312 w->core.height = oldw->core.height; 313 geoReq.request_mode |= CWHeight; 314 } 315 if (oldw->core.border_width != w->core.border_width) { 316 geoReq.border_width = w->core.border_width; 317 w->core.border_width = oldw->core.border_width; 318 geoReq.request_mode |= CWBorderWidth; 319 } 320 321 if (geoReq.request_mode != 0) { 322 /* Pass on any requests for unchanged geometry values */ 323 if (geoReq.request_mode != 324 (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)) { 325 for ( ; num_args != 0; num_args--, args++) { 326 if (! (geoReq.request_mode & CWX) && 327 strcmp(XtNx, args->name) == 0) { 328 geoReq.x = w->core.x; 329 geoReq.request_mode |= CWX; 330 } else if (! (geoReq.request_mode & CWY) && 331 strcmp(XtNy, args->name) == 0) { 332 geoReq.y = w->core.y; 333 geoReq.request_mode |= CWY; 334 } else if (! (geoReq.request_mode & CWWidth) && 335 strcmp(XtNwidth, args->name) == 0) { 336 geoReq.width = w->core.width; 337 geoReq.request_mode |= CWWidth; 338 } else if (! (geoReq.request_mode & CWHeight) && 339 strcmp(XtNheight, args->name) == 0) { 340 geoReq.height = w->core.height; 341 geoReq.request_mode |= CWHeight; 342 } else if (! (geoReq.request_mode & CWBorderWidth) && 343 strcmp(XtNborderWidth, args->name) == 0) { 344 geoReq.border_width = w->core.border_width; 345 geoReq.request_mode |= CWBorderWidth; 346 } 347 } 348 } 349 CALLGEOTAT(_XtGeoTrace(w, 350 "\nXtSetValues sees some geometry changes for \"%s\".\n", 351 XtName(w))); 352 CALLGEOTAT(_XtGeoTab(1)); 353 do { 354 XtGeometryHookDataRec call_data; 355 XtAlmostProc set_values_almost; 356 357 if (XtHasCallbacks(hookobj, XtNgeometryHook) == XtCallbackHasSome) { 358 call_data.type = XtHpreGeometry; 359 call_data.widget = w; 360 call_data.request = &geoReq; 361 XtCallCallbackList(hookobj, 362 ((HookObject)hookobj)->hooks.geometryhook_callbacks, 363 (XtPointer)&call_data); 364 call_data.result = result = 365 _XtMakeGeometryRequest(w, &geoReq, &geoReply, 366 &cleared_rect_obj); 367 call_data.type = XtHpostGeometry; 368 call_data.reply = &geoReply; 369 XtCallCallbackList(hookobj, 370 ((HookObject)hookobj)->hooks.geometryhook_callbacks, 371 (XtPointer)&call_data); 372 } else { 373 result = _XtMakeGeometryRequest(w, &geoReq, &geoReply, 374 &cleared_rect_obj); 375 } 376 if (result == XtGeometryYes || result == XtGeometryDone) 377 break; 378 379 /* An Almost or No reply. Call widget and let it munge 380 request, reply */ 381 LOCK_PROCESS; 382 set_values_almost = wc->core_class.set_values_almost; 383 UNLOCK_PROCESS; 384 if (set_values_almost == NULL) { 385 XtAppWarningMsg(app, 386 "invalidProcedure","set_values_almost", 387 XtCXtToolkitError, 388 "set_values_almost procedure shouldn't be NULL", 389 NULL, NULL); 390 break; 391 } 392 if (result == XtGeometryNo) geoReply.request_mode = 0; 393 CALLGEOTAT(_XtGeoTrace(w,"calling SetValuesAlmost.\n")); 394 (*set_values_almost) (oldw, w, &geoReq, &geoReply); 395 } while (geoReq.request_mode != 0); 396 /* call resize proc if we changed size and parent 397 * didn't already invoke resize */ 398 { 399 XtWidgetProc resize; 400 LOCK_PROCESS; 401 resize = wc->core_class.resize; 402 UNLOCK_PROCESS; 403 if ((w->core.width != oldw->core.width || 404 w->core.height != oldw->core.height) 405 && result != XtGeometryDone 406 && resize != (XtWidgetProc) NULL) { 407 CALLGEOTAT(_XtGeoTrace(w, 408 "XtSetValues calls \"%s\"'s resize proc.\n", 409 XtName(w))); 410 (*resize)(w); 411 } 412 } 413 CALLGEOTAT(_XtGeoTab(-1)); 414 } 415 /* Redisplay if needed. No point in clearing if the window is 416 * about to disappear, as the Expose event will just go straight 417 * to the bit bucket. */ 418 if (XtIsWidget(w)) { 419 /* widgets can distinguish between redisplay and resize, since 420 the server will cause an expose on resize */ 421 if (redisplay && XtIsRealized(w) && !w->core.being_destroyed) { 422 CALLGEOTAT(_XtGeoTrace(w, 423 "XtSetValues calls ClearArea on \"%s\".\n", 424 XtName(w))); 425 XClearArea (XtDisplay(w), XtWindow(w), 0, 0, 0, 0, TRUE); 426 } 427 } else { /*non-window object */ 428 if (redisplay && ! cleared_rect_obj ) { 429 Widget pw = _XtWindowedAncestor(w); 430 if (XtIsRealized(pw) && !pw->core.being_destroyed) { 431 RectObj r = (RectObj)w; 432 int bw2 = r->rectangle.border_width << 1; 433 CALLGEOTAT(_XtGeoTrace(w, 434 "XtSetValues calls ClearArea on \"%s\"'s parent \"%s\".\n", 435 XtName(w),XtName(pw))); 436 XClearArea (XtDisplay (pw), XtWindow (pw), 437 r->rectangle.x, r->rectangle.y, 438 (unsigned) (r->rectangle.width + bw2), 439 (unsigned) (r->rectangle.height + bw2), TRUE); 440 } 441 } 442 } 443 } 444 445 446 /* Free dynamic storage */ 447 if (constraintSize) { 448 XtStackFree(oldw->core.constraints, oldcCache); 449 XtStackFree(reqw->core.constraints, reqcCache); 450 } 451 XtStackFree((XtPointer)oldw, oldwCache); 452 XtStackFree((XtPointer)reqw, reqwCache); 453 UNLOCK_APP(app); 454} /* XtSetValues */ 455