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