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