1/***********************************************************
2Copyright (c) 1993, Oracle and/or its affiliates.
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    memset(&request, 0, sizeof(request));
543    request.request_mode = CWWidth | CWHeight;
544    request.width = (Dimension) width;
545    request.height = (Dimension) height;
546
547    if (XtHasCallbacks(hookobj, XtNgeometryHook) == XtCallbackHasSome) {
548        call_data.type = XtHpreGeometry;
549        call_data.widget = widget;
550        call_data.request = &request;
551        XtCallCallbackList(hookobj,
552                           ((HookObject) hookobj)->hooks.geometryhook_callbacks,
553                           (XtPointer) &call_data);
554        call_data.result = r =
555            _XtMakeGeometryRequest(widget, &request, &reply, &junk);
556        call_data.type = XtHpostGeometry;
557        call_data.reply = &reply;
558        XtCallCallbackList(hookobj,
559                           ((HookObject) hookobj)->hooks.geometryhook_callbacks,
560                           (XtPointer) &call_data);
561    }
562    else {
563        r = _XtMakeGeometryRequest(widget, &request, &reply, &junk);
564    }
565    if (replyWidth != NULL) {
566        if (r == XtGeometryAlmost && reply.request_mode & CWWidth)
567            *replyWidth = reply.width;
568        else
569            *replyWidth = (Dimension) width;
570    }
571    if (replyHeight != NULL) {
572        if (r == XtGeometryAlmost && reply.request_mode & CWHeight)
573            *replyHeight = reply.height;
574        else
575            *replyHeight = (Dimension) height;
576    }
577    UNLOCK_APP(app);
578    return ((r == XtGeometryDone) ? XtGeometryYes : r);
579}                               /* XtMakeResizeRequest */
580
581void
582XtResizeWindow(Widget w)
583{
584    XtConfigureHookDataRec req;
585
586    WIDGET_TO_APPCON(w);
587
588    LOCK_APP(app);
589    if (XtIsRealized(w)) {
590        Widget hookobj;
591
592        req.changes.width = w->core.width;
593        req.changes.height = w->core.height;
594        req.changes.border_width = w->core.border_width;
595        req.changeMask = CWWidth | CWHeight | CWBorderWidth;
596        XConfigureWindow(XtDisplay(w), XtWindow(w),
597                         (unsigned) req.changeMask, &req.changes);
598        hookobj = XtHooksOfDisplay(XtDisplayOfObject(w));
599        if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
600            req.type = XtHconfigure;
601            req.widget = w;
602            XtCallCallbackList(hookobj,
603                               ((HookObject) hookobj)->hooks.
604                               confighook_callbacks, (XtPointer) &req);
605        }
606    }
607    UNLOCK_APP(app);
608}                               /* XtResizeWindow */
609
610void
611XtResizeWidget(Widget w,
612               _XtDimension width,
613               _XtDimension height,
614               _XtDimension borderWidth)
615{
616    XtConfigureWidget(w, w->core.x, w->core.y, width, height, borderWidth);
617}                               /* XtResizeWidget */
618
619void
620XtConfigureWidget(Widget w,
621                  _XtPosition x,
622                  _XtPosition y,
623                  _XtDimension width,
624                  _XtDimension height,
625                  _XtDimension borderWidth)
626{
627    XtConfigureHookDataRec req;
628    XWindowChanges old;
629
630    WIDGET_TO_APPCON(w);
631
632    CALLGEOTAT(_XtGeoTrace(w,
633                           "\"%s\" is being configured by its parent \"%s\"\n",
634                           XtName(w),
635                           (XtParent(w)) ? XtName(XtParent(w)) : "Root"));
636    CALLGEOTAT(_XtGeoTab(1));
637
638    LOCK_APP(app);
639    req.changeMask = 0;
640    if ((old.x = w->core.x) != x) {
641        CALLGEOTAT(_XtGeoTrace(w, "x move from %d to %d\n", w->core.x, x));
642        req.changes.x = w->core.x = (Position) x;
643        req.changeMask |= CWX;
644    }
645
646    if ((old.y = w->core.y) != y) {
647        CALLGEOTAT(_XtGeoTrace(w, "y move from %d to %d\n", w->core.y, y));
648        req.changes.y = w->core.y = (Position) y;
649        req.changeMask |= CWY;
650    }
651
652    if ((old.width = w->core.width) != width) {
653        CALLGEOTAT(_XtGeoTrace(w,
654                               "width move from %d to %d\n", w->core.width,
655                               width));
656        req.changes.width = w->core.width = (Dimension) width;
657        req.changeMask |= CWWidth;
658    }
659
660    if ((old.height = w->core.height) != height) {
661        CALLGEOTAT(_XtGeoTrace(w,
662                               "height move from %d to %d\n", w->core.height,
663                               height));
664        req.changes.height = w->core.height = (Dimension) height;
665        req.changeMask |= CWHeight;
666    }
667
668    if ((old.border_width = w->core.border_width) != borderWidth) {
669        CALLGEOTAT(_XtGeoTrace(w, "border_width move from %d to %d\n",
670                               w->core.border_width, borderWidth));
671        req.changes.border_width = w->core.border_width =
672            (Dimension) borderWidth;
673        req.changeMask |= CWBorderWidth;
674    }
675
676    if (req.changeMask != 0) {
677        Widget hookobj;
678
679        if (XtIsRealized(w)) {
680            if (XtIsWidget(w)) {
681                CALLGEOTAT(_XtGeoTrace(w,
682                                       "XConfigure \"%s\"'s window\n",
683                                       XtName(w)));
684                XConfigureWindow(XtDisplay(w), XtWindow(w), req.changeMask,
685                                 &req.changes);
686            }
687            else {
688                CALLGEOTAT(_XtGeoTrace(w,
689                                       "ClearRectObj called on \"%s\"\n",
690                                       XtName(w)));
691                ClearRectObjAreas((RectObj) w, &old);
692            }
693        }
694        hookobj = XtHooksOfDisplay(XtDisplayOfObject(w));
695        if (XtHasCallbacks(hookobj, XtNconfigureHook) == XtCallbackHasSome) {
696            req.type = XtHconfigure;
697            req.widget = w;
698            XtCallCallbackList(hookobj,
699                               ((HookObject) hookobj)->hooks.
700                               confighook_callbacks, (XtPointer) &req);
701        }
702        {
703            XtWidgetProc resize;
704
705            LOCK_PROCESS;
706            resize = XtClass(w)->core_class.resize;
707            UNLOCK_PROCESS;
708            if ((req.changeMask & (CWWidth | CWHeight)) &&
709                resize != (XtWidgetProc) NULL) {
710                CALLGEOTAT(_XtGeoTrace(w, "Resize proc is called.\n"));
711                (*resize) (w);
712            }
713        }
714    }
715    else {
716        CALLGEOTAT(_XtGeoTrace(w, "No change in configuration\n"));
717    }
718
719    CALLGEOTAT(_XtGeoTab(-1));
720    UNLOCK_APP(app);
721}                               /* XtConfigureWidget */
722
723void
724XtMoveWidget(Widget w, _XtPosition x, _XtPosition y)
725{
726    XtConfigureWidget(w, x, y, w->core.width, w->core.height,
727                      w->core.border_width);
728}                               /* XtMoveWidget */
729
730void
731XtTranslateCoords(register Widget w,
732                  _XtPosition x,
733                  _XtPosition y,
734                  register Position *rootx, /* return */
735                  register Position *rooty) /* return */
736{
737    Position garbagex, garbagey;
738    XtAppContext app = XtWidgetToApplicationContext(w);
739
740    LOCK_APP(app);
741    if (rootx == NULL)
742        rootx = &garbagex;
743    if (rooty == NULL)
744        rooty = &garbagey;
745
746    *rootx = (Position) x;
747    *rooty = (Position) y;
748
749    for (; w != NULL && !XtIsShell(w); w = w->core.parent) {
750        *rootx = (Position) (*rootx + w->core.x + w->core.border_width);
751        *rooty = (Position) (*rooty + w->core.y + w->core.border_width);
752    }
753
754    if (w == NULL)
755        XtAppWarningMsg(app,
756                        "invalidShell", "xtTranslateCoords", XtCXtToolkitError,
757                        "Widget has no shell ancestor", NULL, NULL);
758    else {
759        Position x2, y2;
760
761        _XtShellGetCoordinates(w, &x2, &y2);
762        *rootx = (Position) (*rootx + x2 + w->core.border_width);
763        *rooty = (Position) (*rooty + y2 + w->core.border_width);
764    }
765    UNLOCK_APP(app);
766}
767
768XtGeometryResult XtQueryGeometry(Widget widget,
769                                 register XtWidgetGeometry *intended, /* parent's changes; may be NULL */
770                                 XtWidgetGeometry *reply) {    /* child's preferred geometry; never NULL */
771    XtWidgetGeometry null_intended;
772    XtGeometryHandler query;
773    XtGeometryResult result;
774
775    WIDGET_TO_APPCON(widget);
776
777    CALLGEOTAT(_XtGeoTrace(widget,
778                           "\"%s\" is asking its preferred geometry to \"%s\".\n",
779                           (XtParent(widget)) ? XtName(XtParent(widget)) :
780                           "Root", XtName(widget)));
781    CALLGEOTAT(_XtGeoTab(1));
782
783    LOCK_APP(app);
784    LOCK_PROCESS;
785    query = XtClass(widget)->core_class.query_geometry;
786    UNLOCK_PROCESS;
787    reply->request_mode = 0;
788    if (query != NULL) {
789        if (intended == NULL) {
790            null_intended.request_mode = 0;
791            intended = &null_intended;
792#ifdef XT_GEO_TATTLER
793            CALLGEOTAT(_XtGeoTrace(widget, "without any constraint.\n"));
794        }
795        else {
796            CALLGEOTAT(_XtGeoTrace(widget,
797                                   "with the following constraints:\n"));
798
799            if (intended->request_mode & CWX) {
800                CALLGEOTAT(_XtGeoTrace(widget, " x = %d\n", intended->x));
801            }
802            if (intended->request_mode & CWY) {
803                CALLGEOTAT(_XtGeoTrace(widget, " y = %d\n", intended->y));
804            }
805            if (intended->request_mode & CWWidth) {
806                CALLGEOTAT(_XtGeoTrace(widget,
807                                       " width = %d\n", intended->width));
808            }
809            if (intended->request_mode & CWHeight) {
810                CALLGEOTAT(_XtGeoTrace(widget,
811                                       " height = %d\n", intended->height));
812            }
813            if (intended->request_mode & CWBorderWidth) {
814                CALLGEOTAT(_XtGeoTrace(widget,
815                                       " border_width = %d\n",
816                                       intended->border_width));
817            }
818#endif
819        }
820
821        result = (*query) (widget, intended, reply);
822    }
823    else {
824        CALLGEOTAT(_XtGeoTrace
825                   (widget,
826                    "\"%s\" has no QueryGeometry proc, return the current state\n",
827                    XtName(widget)));
828
829        result = XtGeometryYes;
830    }
831
832#ifdef XT_GEO_TATTLER
833#define FillIn(mask, field) \
834        if (!(reply->request_mode & mask)) {\
835              reply->field = widget->core.field;\
836              _XtGeoTrace(widget," using core %s = %d.\n","field",\
837                                                       widget->core.field);\
838        } else {\
839              _XtGeoTrace(widget," replied %s = %d\n","field",\
840                                                   reply->field);\
841        }
842#else
843#define FillIn(mask, field) \
844        if (!(reply->request_mode & mask)) reply->field = widget->core.field;
845#endif
846
847    FillIn(CWX, x);
848    FillIn(CWY, y);
849    FillIn(CWWidth, width);
850    FillIn(CWHeight, height);
851    FillIn(CWBorderWidth, border_width);
852
853    CALLGEOTAT(_XtGeoTab(-1));
854#undef FillIn
855
856    if (!(reply->request_mode & CWStackMode))
857        reply->stack_mode = XtSMDontChange;
858    UNLOCK_APP(app);
859    return result;
860}
861