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