Geometry.c revision a3bd7f05
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#include "ShellP.h"
76#include "ShellI.h"
77
78static void
79ClearRectObjAreas(RectObj r, XWindowChanges *old)
80{
81    Widget pw = _XtWindowedAncestor((Widget) r);
82    int bw2;
83
84    bw2 = old->border_width << 1;
85    XClearArea(XtDisplay(pw), XtWindow(pw),
86               old->x, old->y,
87               (unsigned) (old->width + bw2), (unsigned) (old->height + bw2),
88               TRUE);
89
90    bw2 = r->rectangle.border_width << 1;
91    XClearArea(XtDisplay(pw), XtWindow(pw),
92               (int) r->rectangle.x, (int) r->rectangle.y,
93               (unsigned int) (r->rectangle.width + bw2),
94               (unsigned int) (r->rectangle.height + bw2), TRUE);
95}
96
97/*
98 * Internal function used by XtMakeGeometryRequest and XtSetValues.
99 * Returns more data than the public interface.  Does not convert
100 * XtGeometryDone to XtGeometryYes.
101 *
102 * clear_rect_obj - *** RETURNED ***
103 *                  TRUE if the rect obj has been cleared, false otherwise.
104 */
105
106XtGeometryResult
107_XtMakeGeometryRequest(Widget widget,
108                       XtWidgetGeometry *request,
109                       XtWidgetGeometry *reply,
110                       Boolean *clear_rect_obj)
111{
112    XtWidgetGeometry junk;
113    XtGeometryHandler manager = (XtGeometryHandler) NULL;
114    XtGeometryResult returnCode;
115    Widget parent = widget->core.parent;
116    Boolean managed;
117    Boolean parentRealized = False;
118    Boolean rgm = False;
119    XtConfigureHookDataRec req;
120    Widget hookobj;
121
122    *clear_rect_obj = FALSE;
123
124    CALLGEOTAT(_XtGeoTrace(widget,
125                           "\"%s\" is making a %sgeometry request to its parent \"%s\".\n",
126                           XtName(widget),
127                           ((request->request_mode & XtCWQueryOnly)) ?
128                           "query only " : "",
129                           (XtParent(widget)) ? XtName(XtParent(widget)) :
130                           "Root"));
131    CALLGEOTAT(_XtGeoTab(1));
132
133    if (XtIsShell(widget)) {
134        ShellClassExtension ext;
135
136        LOCK_PROCESS;
137        for (ext = (ShellClassExtension) ((ShellWidgetClass) XtClass(widget))
138             ->shell_class.extension;
139             ext != NULL && ext->record_type != NULLQUARK;
140             ext = (ShellClassExtension) ext->next_extension);
141
142        if (ext != NULL) {
143            if (ext->version == XtShellExtensionVersion
144                && ext->record_size == sizeof(ShellClassExtensionRec)) {
145                manager = ext->root_geometry_manager;
146                rgm = True;
147            }
148            else {
149                String params[1];
150                Cardinal num_params = 1;
151
152                params[0] = XtClass(widget)->core_class.class_name;
153                XtAppErrorMsg(XtWidgetToApplicationContext(widget),
154                              "invalidExtension", "xtMakeGeometryRequest",
155                              XtCXtToolkitError,
156                              "widget class %s has invalid ShellClassExtension record",
157                              params, &num_params);
158            }
159        }
160        else {
161            XtAppErrorMsg(XtWidgetToApplicationContext(widget),
162                          "internalError", "xtMakeGeometryRequest",
163                          XtCXtToolkitError,
164                          "internal error; ShellClassExtension is NULL",
165                          NULL, NULL);
166        }
167        managed = True;
168        parentRealized = TRUE;
169        UNLOCK_PROCESS;
170    }
171    else {                      /* not shell */
172
173        if (parent == NULL) {
174            XtAppErrorMsg(XtWidgetToApplicationContext(widget),
175                          "invalidParent", "xtMakeGeometryRequest",
176                          XtCXtToolkitError,
177                          "non-shell has no parent in XtMakeGeometryRequest",
178                          NULL, NULL);
179        }
180        else {
181            managed = XtIsManaged(widget);
182            parentRealized = XtIsRealized(parent);
183            if (XtIsComposite(parent)) {
184                LOCK_PROCESS;
185                manager = ((CompositeWidgetClass) (parent->core.widget_class))
186                    ->composite_class.geometry_manager;
187                UNLOCK_PROCESS;
188            }
189        }
190    }
191
192#if 0
193    /*
194     * The Xt spec says that these conditions must generate
195     * error messages (not warnings), but many Xt applications
196     * and toolkits (including parts of Xaw, Motif and Netscape)
197     * depend on the previous Xt behaviour.  Thus, these tests
198     * should probably remain disabled.
199     */
200    if (parentRealized && managed) {
201        if (parent && !XtIsComposite(parent)) {
202            /*
203             * This shouldn't ever happen, we only test for this to pass
204             * VSW5.  Normally managing the widget will catch this, but VSW5
205             * does some really screwy stuff to get here.
206             */
207            XtAppErrorMsg(XtWidgetToApplicationContext(widget),
208                          "invalidParent", "xtMakeGeometryRequest",
209                          XtCXtToolkitError,
210                          "XtMakeGeometryRequest - parent not composite",
211                          NULL, NULL);
212        }
213        else if (manager == (XtGeometryHandler) NULL) {
214            XtAppErrorMsg(XtWidgetToApplicationContext(widget),
215                          "invalidGeometryManager", "xtMakeGeometryRequest",
216                          XtCXtToolkitError,
217                          "XtMakeGeometryRequest - parent has no geometry manager",
218                          NULL, NULL);
219        }
220    }
221#else
222    if (!manager)
223        managed = False;
224#endif
225
226    if (widget->core.being_destroyed) {
227        CALLGEOTAT(_XtGeoTab(-1));
228        CALLGEOTAT(_XtGeoTrace(widget,
229                               "It is being destroyed, just return XtGeometryNo.\n"));
230        return XtGeometryNo;
231    }
232
233    /* see if requesting anything to change */
234    req.changeMask = 0;
235    if (request->request_mode & CWStackMode
236        && request->stack_mode != XtSMDontChange) {
237        req.changeMask |= CWStackMode;
238        CALLGEOTAT(_XtGeoTrace(widget, "Asking for a change in StackMode!\n"));
239        if (request->request_mode & CWSibling) {
240            XtCheckSubclass(request->sibling, rectObjClass,
241                            "XtMakeGeometryRequest");
242            req.changeMask |= CWSibling;
243        }
244    }
245    if (request->request_mode & CWX && widget->core.x != request->x) {
246        CALLGEOTAT(_XtGeoTrace(widget,
247                               "Asking for a change in x: from %d to %d.\n",
248                               widget->core.x, request->x));
249        req.changeMask |= CWX;
250    }
251    if (request->request_mode & CWY && widget->core.y != request->y) {
252        CALLGEOTAT(_XtGeoTrace(widget,
253                               "Asking for a change in y: from %d to %d.\n",
254                               widget->core.y, request->y));
255        req.changeMask |= CWY;
256    }
257    if (request->request_mode & CWWidth && widget->core.width != request->width) {
258        CALLGEOTAT(_XtGeoTrace
259                   (widget, "Asking for a change in width: from %d to %d.\n",
260                    widget->core.width, request->width));
261        req.changeMask |= CWWidth;
262    }
263    if (request->request_mode & CWHeight
264        && widget->core.height != request->height) {
265        CALLGEOTAT(_XtGeoTrace(widget,
266                               "Asking for a change in height: from %d to %d.\n",
267                               widget->core.height, request->height));
268        req.changeMask |= CWHeight;
269    }
270    if (request->request_mode & CWBorderWidth
271        && widget->core.border_width != request->border_width) {
272        CALLGEOTAT(_XtGeoTrace(widget,
273                               "Asking for a change in border_width: from %d to %d.\n",
274                               widget->core.border_width,
275                               request->border_width));
276        req.changeMask |= CWBorderWidth;
277    }
278    if (!req.changeMask) {
279        CALLGEOTAT(_XtGeoTrace(widget, "Asking for nothing new,\n"));
280        CALLGEOTAT(_XtGeoTab(-1));
281        CALLGEOTAT(_XtGeoTrace(widget, "just return XtGeometryYes.\n"));
282        return XtGeometryYes;
283    }
284    req.changeMask |= (request->request_mode & XtCWQueryOnly);
285
286    if (!(req.changeMask & XtCWQueryOnly) && XtIsRealized(widget)) {
287        /* keep record of the current geometry so we know what's changed */
288        req.changes.x = widget->core.x;
289        req.changes.y = widget->core.y;
290        req.changes.width = widget->core.width;
291        req.changes.height = widget->core.height;
292        req.changes.border_width = widget->core.border_width;
293    }
294
295    if (!managed || !parentRealized) {
296        CALLGEOTAT(_XtGeoTrace(widget,
297                               "Not Managed or Parent not realized.\n"));
298        /* Don't get parent's manager involved--assume the answer is yes */
299        if (req.changeMask & XtCWQueryOnly) {
300            /* He was just asking, don't change anything, just tell him yes */
301            CALLGEOTAT(_XtGeoTrace(widget, "QueryOnly request\n"));
302            CALLGEOTAT(_XtGeoTab(-1));
303            CALLGEOTAT(_XtGeoTrace(widget, "just return XtGeometryYes.\n"));
304            return XtGeometryYes;
305        }
306        else {
307            CALLGEOTAT(_XtGeoTrace(widget,
308                                   "Copy values from request to widget.\n"));
309            /* copy values from request to widget */
310            if (request->request_mode & CWX)
311                widget->core.x = request->x;
312            if (request->request_mode & CWY)
313                widget->core.y = request->y;
314            if (request->request_mode & CWWidth)
315                widget->core.width = request->width;
316            if (request->request_mode & CWHeight)
317                widget->core.height = request->height;
318            if (request->request_mode & CWBorderWidth)
319                widget->core.border_width = request->border_width;
320            if (!parentRealized) {
321                CALLGEOTAT(_XtGeoTab(-1));
322                CALLGEOTAT(_XtGeoTrace(widget, "and return XtGeometryYes.\n"));
323                return XtGeometryYes;
324            }
325            else
326                returnCode = XtGeometryYes;
327        }
328    }
329    else {
330        /* go ask the widget's geometry manager */
331        CALLGEOTAT(_XtGeoTrace(widget,
332                               "Go ask the parent geometry manager.\n"));
333        if (reply == (XtWidgetGeometry *) NULL) {
334            returnCode = (*manager) (widget, request, &junk);
335        }
336        else {
337            returnCode = (*manager) (widget, request, reply);
338        }
339    }
340
341    /*
342     * If Unrealized, not a XtGeometryYes, or a query-only then we are done.
343     */
344
345    if ((returnCode != XtGeometryYes) ||
346        (req.changeMask & XtCWQueryOnly) || !XtIsRealized(widget)) {
347
348#ifdef XT_GEO_TATTLER
349        switch (returnCode) {
350        case XtGeometryNo:
351            CALLGEOTAT(_XtGeoTab(-1));
352            CALLGEOTAT(_XtGeoTrace(widget, "\"%s\" returns XtGeometryNo.\n",
353                                   (XtParent(widget)) ? XtName(XtParent(widget))
354                                   : "Root"));
355            /* check for no change */
356            break;
357        case XtGeometryDone:
358            CALLGEOTAT(_XtGeoTab(-1));
359            CALLGEOTAT(_XtGeoTrace(widget, "\"%s\" returns XtGeometryDone.\n",
360                                   (XtParent(widget)) ? XtName(XtParent(widget))
361                                   : "Root"));
362            /* check for no change in queryonly */
363            break;
364        case XtGeometryAlmost:
365            CALLGEOTAT(_XtGeoTab(-1));
366            CALLGEOTAT(_XtGeoTrace(widget, "\"%s\" returns XtGeometryAlmost.\n",
367                                   (XtParent(widget)) ? XtName(XtParent(widget))
368                                   : "Root"));
369            CALLGEOTAT(_XtGeoTab(1));
370            CALLGEOTAT(_XtGeoTrace(widget, "Proposal: width %d height %d.\n",
371                                   (reply) ? reply->width : junk.width,
372                                   (reply) ? reply->height : junk.height));
373            CALLGEOTAT(_XtGeoTab(-1));
374
375            /* check for no change */
376            break;
377        case XtGeometryYes:
378            if (req.changeMask & XtCWQueryOnly) {
379                CALLGEOTAT(_XtGeoTrace(widget,
380                                       "QueryOnly specified, no configuration.\n"));
381            }
382            if (!XtIsRealized(widget)) {
383                CALLGEOTAT(_XtGeoTrace(widget,
384                                       "\"%s\" not realized, no configuration.\n",
385                                       XtName(widget)));
386            }
387            CALLGEOTAT(_XtGeoTab(-1));
388            CALLGEOTAT(_XtGeoTrace(widget, "\"%s\" returns XtGeometryYes.\n",
389                                   (XtParent(widget)) ? XtName(XtParent(widget))
390                                   : "Root"));
391            break;
392        }
393#endif
394        return returnCode;
395    }
396
397    CALLGEOTAT(_XtGeoTab(-1));
398    CALLGEOTAT(_XtGeoTrace(widget, "\"%s\" returns XtGeometryYes.\n",
399                           (XtParent(widget)) ? XtName(XtParent(widget)) :
400                           "Root"));
401
402    if (XtIsWidget(widget)) {   /* reconfigure the window (if needed) */
403
404        if (rgm)
405            return returnCode;
406
407        if (req.changes.x != widget->core.x) {
408            req.changeMask |= CWX;
409            req.changes.x = widget->core.x;
410            CALLGEOTAT(_XtGeoTrace(widget,
411                                   "x changing to %d\n", widget->core.x));
412        }
413        if (req.changes.y != widget->core.y) {
414            req.changeMask |= CWY;
415            req.changes.y = widget->core.y;
416            CALLGEOTAT(_XtGeoTrace(widget,
417                                   "y changing to %d\n", widget->core.y));
418        }
419        if (req.changes.width != widget->core.width) {
420            req.changeMask |= CWWidth;
421            req.changes.width = widget->core.width;
422            CALLGEOTAT(_XtGeoTrace(widget,
423                                   "width changing to %d\n",
424                                   widget->core.width));
425        }
426        if (req.changes.height != widget->core.height) {
427            req.changeMask |= CWHeight;
428            req.changes.height = widget->core.height;
429            CALLGEOTAT(_XtGeoTrace(widget,
430                                   "height changing to %d\n",
431                                   widget->core.height));
432        }
433        if (req.changes.border_width != widget->core.border_width) {
434            req.changeMask |= CWBorderWidth;
435            req.changes.border_width = widget->core.border_width;
436            CALLGEOTAT(_XtGeoTrace(widget,
437                                   "border_width changing to %d\n",
438                                   widget->core.border_width));
439        }
440        if (req.changeMask & CWStackMode) {
441            req.changes.stack_mode = request->stack_mode;
442            CALLGEOTAT(_XtGeoTrace(widget, "stack_mode changing\n"));
443            if (req.changeMask & CWSibling) {
444                if (XtIsWidget(request->sibling))
445                    req.changes.sibling = XtWindow(request->sibling);
446                else
447                    req.changeMask =
448                        (XtGeometryMask) (req.changeMask & (unsigned long)
449                                          (~(CWStackMode | CWSibling)));
450            }
451        }
452
453#ifdef XT_GEO_TATTLER
454        if (req.changeMask) {
455            CALLGEOTAT(_XtGeoTrace(widget,
456                                   "XConfigure \"%s\"'s window.\n",
457                                   XtName(widget)));
458        }
459        else {
460            CALLGEOTAT(_XtGeoTrace(widget,
461                                   "No window configuration needed for \"%s\".\n",
462                                   XtName(widget)));
463        }
464#endif
465
466        XConfigureWindow(XtDisplay(widget), XtWindow(widget),
467                         req.changeMask, &req.changes);
468    }
469    else {                      /* RectObj child of realized Widget */
470        *clear_rect_obj = TRUE;
471        CALLGEOTAT(_XtGeoTrace(widget,
472                               "ClearRectObj on \"%s\".\n", XtName(widget)));
473
474        ClearRectObjAreas((RectObj) widget, &req.changes);
475    }
476    hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
477    if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
478        req.type = XtHconfigure;
479        req.widget = widget;
480        XtCallCallbackList(hookobj,
481                           ((HookObject) hookobj)->hooks.confighook_callbacks,
482                           (XtPointer) &req);
483    }
484
485    return returnCode;
486}                               /* _XtMakeGeometryRequest */
487
488/* Public routines */
489
490XtGeometryResult
491XtMakeGeometryRequest(Widget widget,
492                      XtWidgetGeometry *request,
493                      XtWidgetGeometry *reply)
494{
495    Boolean junk;
496    XtGeometryResult r;
497    XtGeometryHookDataRec call_data;
498    Widget hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
499
500    WIDGET_TO_APPCON(widget);
501
502    LOCK_APP(app);
503    if (XtHasCallbacks(hookobj, XtNgeometryHook) == XtCallbackHasSome) {
504        call_data.type = XtHpreGeometry;
505        call_data.widget = widget;
506        call_data.request = request;
507        XtCallCallbackList(hookobj,
508                           ((HookObject) hookobj)->hooks.geometryhook_callbacks,
509                           (XtPointer) &call_data);
510        call_data.result = r =
511            _XtMakeGeometryRequest(widget, request, reply, &junk);
512        call_data.type = XtHpostGeometry;
513        call_data.reply = reply;
514        XtCallCallbackList(hookobj,
515                           ((HookObject) hookobj)->hooks.geometryhook_callbacks,
516                           (XtPointer) &call_data);
517    }
518    else {
519        r = _XtMakeGeometryRequest(widget, request, reply, &junk);
520    }
521    UNLOCK_APP(app);
522
523    return ((r == XtGeometryDone) ? XtGeometryYes : r);
524}
525
526XtGeometryResult
527XtMakeResizeRequest(Widget widget,
528                    _XtDimension width,
529                    _XtDimension height,
530                    Dimension *replyWidth,
531                    Dimension *replyHeight)
532{
533    XtWidgetGeometry request, reply;
534    XtGeometryResult r;
535    XtGeometryHookDataRec call_data;
536    Boolean junk;
537    Widget hookobj = XtHooksOfDisplay(XtDisplayOfObject(widget));
538
539    WIDGET_TO_APPCON(widget);
540
541    LOCK_APP(app);
542    request.request_mode = CWWidth | CWHeight;
543    request.width = (Dimension) width;
544    request.height = (Dimension) height;
545
546    if (XtHasCallbacks(hookobj, XtNgeometryHook) == XtCallbackHasSome) {
547        call_data.type = XtHpreGeometry;
548        call_data.widget = widget;
549        call_data.request = &request;
550        XtCallCallbackList(hookobj,
551                           ((HookObject) hookobj)->hooks.geometryhook_callbacks,
552                           (XtPointer) &call_data);
553        call_data.result = r =
554            _XtMakeGeometryRequest(widget, &request, &reply, &junk);
555        call_data.type = XtHpostGeometry;
556        call_data.reply = &reply;
557        XtCallCallbackList(hookobj,
558                           ((HookObject) hookobj)->hooks.geometryhook_callbacks,
559                           (XtPointer) &call_data);
560    }
561    else {
562        r = _XtMakeGeometryRequest(widget, &request, &reply, &junk);
563    }
564    if (replyWidth != NULL) {
565        if (r == XtGeometryAlmost && reply.request_mode & CWWidth)
566            *replyWidth = reply.width;
567        else
568            *replyWidth = (Dimension) width;
569    }
570    if (replyHeight != NULL) {
571        if (r == XtGeometryAlmost && reply.request_mode & CWHeight)
572            *replyHeight = reply.height;
573        else
574            *replyHeight = (Dimension) height;
575    }
576    UNLOCK_APP(app);
577    return ((r == XtGeometryDone) ? XtGeometryYes : r);
578}                               /* XtMakeResizeRequest */
579
580void
581XtResizeWindow(Widget w)
582{
583    XtConfigureHookDataRec req;
584
585    WIDGET_TO_APPCON(w);
586
587    LOCK_APP(app);
588    if (XtIsRealized(w)) {
589        Widget hookobj;
590
591        req.changes.width = w->core.width;
592        req.changes.height = w->core.height;
593        req.changes.border_width = w->core.border_width;
594        req.changeMask = CWWidth | CWHeight | CWBorderWidth;
595        XConfigureWindow(XtDisplay(w), XtWindow(w),
596                         (unsigned) req.changeMask, &req.changes);
597        hookobj = XtHooksOfDisplay(XtDisplayOfObject(w));
598        if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
599            req.type = XtHconfigure;
600            req.widget = w;
601            XtCallCallbackList(hookobj,
602                               ((HookObject) hookobj)->hooks.
603                               confighook_callbacks, (XtPointer) &req);
604        }
605    }
606    UNLOCK_APP(app);
607}                               /* XtResizeWindow */
608
609void
610XtResizeWidget(Widget w,
611               _XtDimension width,
612               _XtDimension height,
613               _XtDimension borderWidth)
614{
615    XtConfigureWidget(w, w->core.x, w->core.y, width, height, borderWidth);
616}                               /* XtResizeWidget */
617
618void
619XtConfigureWidget(Widget w,
620                  _XtPosition x,
621                  _XtPosition y,
622                  _XtDimension width,
623                  _XtDimension height,
624                  _XtDimension borderWidth)
625{
626    XtConfigureHookDataRec req;
627    XWindowChanges old;
628
629    WIDGET_TO_APPCON(w);
630
631    CALLGEOTAT(_XtGeoTrace(w,
632                           "\"%s\" is being configured by its parent \"%s\"\n",
633                           XtName(w),
634                           (XtParent(w)) ? XtName(XtParent(w)) : "Root"));
635    CALLGEOTAT(_XtGeoTab(1));
636
637    LOCK_APP(app);
638    req.changeMask = 0;
639    if ((old.x = w->core.x) != x) {
640        CALLGEOTAT(_XtGeoTrace(w, "x move from %d to %d\n", w->core.x, x));
641        req.changes.x = w->core.x = (Position) x;
642        req.changeMask |= CWX;
643    }
644
645    if ((old.y = w->core.y) != y) {
646        CALLGEOTAT(_XtGeoTrace(w, "y move from %d to %d\n", w->core.y, y));
647        req.changes.y = w->core.y = (Position) y;
648        req.changeMask |= CWY;
649    }
650
651    if ((old.width = w->core.width) != width) {
652        CALLGEOTAT(_XtGeoTrace(w,
653                               "width move from %d to %d\n", w->core.width,
654                               width));
655        req.changes.width = w->core.width = (Dimension) width;
656        req.changeMask |= CWWidth;
657    }
658
659    if ((old.height = w->core.height) != height) {
660        CALLGEOTAT(_XtGeoTrace(w,
661                               "height move from %d to %d\n", w->core.height,
662                               height));
663        req.changes.height = w->core.height = (Dimension) height;
664        req.changeMask |= CWHeight;
665    }
666
667    if ((old.border_width = w->core.border_width) != borderWidth) {
668        CALLGEOTAT(_XtGeoTrace(w, "border_width move from %d to %d\n",
669                               w->core.border_width, borderWidth));
670        req.changes.border_width = w->core.border_width =
671            (Dimension) borderWidth;
672        req.changeMask |= CWBorderWidth;
673    }
674
675    if (req.changeMask != 0) {
676        Widget hookobj;
677
678        if (XtIsRealized(w)) {
679            if (XtIsWidget(w)) {
680                CALLGEOTAT(_XtGeoTrace(w,
681                                       "XConfigure \"%s\"'s window\n",
682                                       XtName(w)));
683                XConfigureWindow(XtDisplay(w), XtWindow(w), req.changeMask,
684                                 &req.changes);
685            }
686            else {
687                CALLGEOTAT(_XtGeoTrace(w,
688                                       "ClearRectObj called on \"%s\"\n",
689                                       XtName(w)));
690                ClearRectObjAreas((RectObj) w, &old);
691            }
692        }
693        hookobj = XtHooksOfDisplay(XtDisplayOfObject(w));
694        if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
695            req.type = XtHconfigure;
696            req.widget = w;
697            XtCallCallbackList(hookobj,
698                               ((HookObject) hookobj)->hooks.
699                               confighook_callbacks, (XtPointer) &req);
700        }
701        {
702            XtWidgetProc resize;
703
704            LOCK_PROCESS;
705            resize = XtClass(w)->core_class.resize;
706            UNLOCK_PROCESS;
707            if ((req.changeMask & (CWWidth | CWHeight)) &&
708                resize != (XtWidgetProc) NULL) {
709                CALLGEOTAT(_XtGeoTrace(w, "Resize proc is called.\n"));
710                (*resize) (w);
711            }
712        }
713    }
714    else {
715        CALLGEOTAT(_XtGeoTrace(w, "No change in configuration\n"));
716    }
717
718    CALLGEOTAT(_XtGeoTab(-1));
719    UNLOCK_APP(app);
720}                               /* XtConfigureWidget */
721
722void
723XtMoveWidget(Widget w, _XtPosition x, _XtPosition y)
724{
725    XtConfigureWidget(w, x, y, w->core.width, w->core.height,
726                      w->core.border_width);
727}                               /* XtMoveWidget */
728
729void
730XtTranslateCoords(register Widget w,
731                  _XtPosition x,
732                  _XtPosition y,
733                  register Position *rootx, /* return */
734                  register Position *rooty) /* return */
735{
736    Position garbagex, garbagey;
737    XtAppContext app = XtWidgetToApplicationContext(w);
738
739    LOCK_APP(app);
740    if (rootx == NULL)
741        rootx = &garbagex;
742    if (rooty == NULL)
743        rooty = &garbagey;
744
745    *rootx = (Position) x;
746    *rooty = (Position) y;
747
748    for (; w != NULL && !XtIsShell(w); w = w->core.parent) {
749        *rootx = (Position) (*rootx + w->core.x + w->core.border_width);
750        *rooty = (Position) (*rooty + w->core.y + w->core.border_width);
751    }
752
753    if (w == NULL)
754        XtAppWarningMsg(app,
755                        "invalidShell", "xtTranslateCoords", XtCXtToolkitError,
756                        "Widget has no shell ancestor", NULL, NULL);
757    else {
758        Position x2, y2;
759
760        _XtShellGetCoordinates(w, &x2, &y2);
761        *rootx = (Position) (*rootx + x2 + w->core.border_width);
762        *rooty = (Position) (*rooty + y2 + w->core.border_width);
763    }
764    UNLOCK_APP(app);
765}
766
767XtGeometryResult XtQueryGeometry(Widget widget,
768                                 register XtWidgetGeometry *intended, /* parent's changes; may be NULL */
769                                 XtWidgetGeometry *reply) {    /* child's preferred geometry; never NULL */
770    XtWidgetGeometry null_intended;
771    XtGeometryHandler query;
772    XtGeometryResult result;
773
774    WIDGET_TO_APPCON(widget);
775
776    CALLGEOTAT(_XtGeoTrace(widget,
777                           "\"%s\" is asking its preferred geometry to \"%s\".\n",
778                           (XtParent(widget)) ? XtName(XtParent(widget)) :
779                           "Root", XtName(widget)));
780    CALLGEOTAT(_XtGeoTab(1));
781
782    LOCK_APP(app);
783    LOCK_PROCESS;
784    query = XtClass(widget)->core_class.query_geometry;
785    UNLOCK_PROCESS;
786    reply->request_mode = 0;
787    if (query != NULL) {
788        if (intended == NULL) {
789            null_intended.request_mode = 0;
790            intended = &null_intended;
791#ifdef XT_GEO_TATTLER
792            CALLGEOTAT(_XtGeoTrace(widget, "without any constraint.\n"));
793        }
794        else {
795            CALLGEOTAT(_XtGeoTrace(widget,
796                                   "with the following constraints:\n"));
797
798            if (intended->request_mode & CWX) {
799                CALLGEOTAT(_XtGeoTrace(widget, " x = %d\n", intended->x));
800            }
801            if (intended->request_mode & CWY) {
802                CALLGEOTAT(_XtGeoTrace(widget, " y = %d\n", intended->y));
803            }
804            if (intended->request_mode & CWWidth) {
805                CALLGEOTAT(_XtGeoTrace(widget,
806                                       " width = %d\n", intended->width));
807            }
808            if (intended->request_mode & CWHeight) {
809                CALLGEOTAT(_XtGeoTrace(widget,
810                                       " height = %d\n", intended->height));
811            }
812            if (intended->request_mode & CWBorderWidth) {
813                CALLGEOTAT(_XtGeoTrace(widget,
814                                       " border_width = %d\n",
815                                       intended->border_width));
816            }
817#endif
818        }
819
820        result = (*query) (widget, intended, reply);
821    }
822    else {
823        CALLGEOTAT(_XtGeoTrace
824                   (widget,
825                    "\"%s\" has no QueryGeometry proc, return the current state\n",
826                    XtName(widget)));
827
828        result = XtGeometryYes;
829    }
830
831#ifdef XT_GEO_TATTLER
832#define FillIn(mask, field) \
833        if (!(reply->request_mode & mask)) {\
834              reply->field = widget->core.field;\
835              _XtGeoTrace(widget," using core %s = %d.\n","field",\
836                                                       widget->core.field);\
837        } else {\
838              _XtGeoTrace(widget," replied %s = %d\n","field",\
839                                                   reply->field);\
840        }
841#else
842#define FillIn(mask, field) \
843        if (!(reply->request_mode & mask)) reply->field = widget->core.field;
844#endif
845
846    FillIn(CWX, x);
847    FillIn(CWY, y);
848    FillIn(CWWidth, width);
849    FillIn(CWHeight, height);
850    FillIn(CWBorderWidth, border_width);
851
852    CALLGEOTAT(_XtGeoTab(-1));
853#undef FillIn
854
855    if (!(reply->request_mode & CWStackMode))
856        reply->stack_mode = XtSMDontChange;
857    UNLOCK_APP(app);
858    return result;
859}
860