Shell.c revision 2265a131
1/* $Xorg: Shell.c,v 1.4 2001/02/09 02:03:58 xorgcvs Exp $ */
2
3/***********************************************************
4Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts
5Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA.
6
7                        All Rights Reserved
8
9Permission to use, copy, modify, and distribute this software and its
10documentation for any purpose and without fee is hereby granted,
11provided that the above copyright notice appear in all copies and that
12both that copyright notice and this permission notice appear in
13supporting documentation, and that the names of Digital or Sun not be
14used in advertising or publicity pertaining to distribution of the
15software without specific, written prior permission.
16
17DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
18ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
19DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
20ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23SOFTWARE.
24
25SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
26INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
27NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
28ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
29ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
30PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
31OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
32THE USE OR PERFORMANCE OF THIS SOFTWARE.
33
34******************************************************************/
35/* $XFree86: xc/lib/Xt/Shell.c,v 3.16tsi Exp $ */
36
37/*
38
39Copyright 1987, 1988, 1994, 1998  The Open Group
40
41Permission to use, copy, modify, distribute, and sell this software and its
42documentation for any purpose is hereby granted without fee, provided that
43the above copyright notice appear in all copies and that both that
44copyright notice and this permission notice appear in supporting
45documentation.
46
47The above copyright notice and this permission notice shall be included in
48all copies or substantial portions of the Software.
49
50THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
53OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
54AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
55CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56
57Except as contained in this notice, the name of The Open Group shall not be
58used in advertising or otherwise to promote the sale, use or other dealings
59in this Software without prior written authorization from The Open Group.
60
61*/
62
63#ifndef DEFAULT_WM_TIMEOUT
64#define DEFAULT_WM_TIMEOUT 5000
65#endif
66
67#ifdef HAVE_CONFIG_H
68#include <config.h>
69#endif
70#include "IntrinsicI.h"
71#include "StringDefs.h"
72#include "Shell.h"
73#include "ShellP.h"
74#include "ShellI.h"
75#include "Vendor.h"
76#include "VendorP.h"
77#include <X11/Xatom.h>
78#include <X11/Xlocale.h>
79#include <X11/ICE/ICElib.h>
80#include <stdio.h>
81#include <stdlib.h>
82
83#ifdef EDITRES
84#include <X11/Xmu/Editres.h>
85#endif
86
87/***************************************************************************
88 *
89 * Note: per the Xt spec, the Shell geometry management assumes in
90 * several places that there is only one managed child.  This is
91 * *not* a bug.  Any subclass that assumes otherwise is broken.
92 *
93 ***************************************************************************/
94
95#define BIGSIZE ((Dimension)32767)
96
97/***************************************************************************
98 *
99 * Default values for resource lists
100 *
101 ***************************************************************************/
102
103#ifdef CRAY
104void _XtShellDepth(Widget, int, XrmValue *);
105void _XtShellColormap(Widget, int, XrmValue *);
106void _XtShellAncestorSensitive(Widget, int, XrmValue *);
107void _XtTitleEncoding(Widget, int, XrmValue *);
108#else
109static void _XtShellDepth(Widget, int, XrmValue *);
110static void _XtShellColormap(Widget, int, XrmValue *);
111static void _XtShellAncestorSensitive(Widget, int, XrmValue *);
112static void _XtTitleEncoding(Widget, int, XrmValue *);
113#endif
114
115/***************************************************************************
116 *
117 * Shell class record
118 *
119 ***************************************************************************/
120
121#define Offset(x)	(XtOffsetOf(ShellRec, x))
122static XtResource shellResources[]=
123{
124	{XtNx, XtCPosition, XtRPosition, sizeof(Position),
125	    Offset(core.x), XtRImmediate, (XtPointer)BIGSIZE},
126	{XtNy, XtCPosition, XtRPosition, sizeof(Position),
127	    Offset(core.y), XtRImmediate, (XtPointer)BIGSIZE},
128	{ XtNdepth, XtCDepth, XtRInt, sizeof(int),
129	    Offset(core.depth), XtRCallProc, (XtPointer) _XtShellDepth},
130	{ XtNcolormap, XtCColormap, XtRColormap, sizeof(Colormap),
131	    Offset(core.colormap), XtRCallProc, (XtPointer) _XtShellColormap},
132	{ XtNancestorSensitive, XtCSensitive, XtRBoolean, sizeof(Boolean),
133	    Offset(core.ancestor_sensitive), XtRCallProc,
134	    (XtPointer) _XtShellAncestorSensitive},
135	{ XtNallowShellResize, XtCAllowShellResize, XtRBoolean,
136	    sizeof(Boolean), Offset(shell.allow_shell_resize),
137	    XtRImmediate, (XtPointer)False},
138	{ XtNgeometry, XtCGeometry, XtRString, sizeof(String),
139	    Offset(shell.geometry), XtRString, (XtPointer)NULL},
140	{ XtNcreatePopupChildProc, XtCCreatePopupChildProc, XtRFunction,
141	    sizeof(XtCreatePopupChildProc), Offset(shell.create_popup_child_proc),
142	    XtRFunction, NULL},
143	{ XtNsaveUnder, XtCSaveUnder, XtRBoolean, sizeof(Boolean),
144	    Offset(shell.save_under), XtRImmediate, (XtPointer)False},
145	{ XtNpopupCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
146	    Offset(shell.popup_callback), XtRCallback, (XtPointer) NULL},
147	{ XtNpopdownCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
148	    Offset(shell.popdown_callback), XtRCallback, (XtPointer) NULL},
149	{ XtNoverrideRedirect, XtCOverrideRedirect,
150	    XtRBoolean, sizeof(Boolean), Offset(shell.override_redirect),
151	    XtRImmediate, (XtPointer)False},
152	{ XtNvisual, XtCVisual, XtRVisual, sizeof(Visual*),
153	    Offset(shell.visual), XtRImmediate, (XtPointer)CopyFromParent}
154};
155
156static void ClassPartInitialize(WidgetClass);
157static void Initialize(Widget, Widget, ArgList, Cardinal *);
158static void Realize(Widget, Mask *, XSetWindowAttributes *);
159static void Resize(Widget);
160static Boolean SetValues(Widget, Widget, Widget, ArgList , Cardinal *);
161static void GetValuesHook(Widget, ArgList, Cardinal*);
162static void ChangeManaged(Widget);
163static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *, XtWidgetGeometry *);
164static XtGeometryResult RootGeometryManager(Widget gw, XtWidgetGeometry *request, XtWidgetGeometry *reply);
165static void Destroy(Widget);
166
167static ShellClassExtensionRec shellClassExtRec = {
168    NULL,
169    NULLQUARK,
170    XtShellExtensionVersion,
171    sizeof(ShellClassExtensionRec),
172    RootGeometryManager
173};
174
175externaldef(shellclassrec) ShellClassRec shellClassRec = {
176  {   /* Core */
177    /* superclass	  */	(WidgetClass) &compositeClassRec,
178    /* class_name	  */	"Shell",
179    /* size		  */	sizeof(ShellRec),
180    /* Class Initializer  */	NULL,
181    /* class_part_initialize*/	ClassPartInitialize,
182    /* Class init'ed ?	  */	FALSE,
183    /* initialize	  */	Initialize,
184    /* initialize_notify  */	NULL,
185    /* realize		  */	Realize,
186    /* actions		  */	NULL,
187    /* num_actions	  */	0,
188    /* resources	  */	shellResources,
189    /* resource_count	  */	XtNumber(shellResources),
190    /* xrm_class	  */	NULLQUARK,
191    /* compress_motion	  */	FALSE,
192    /* compress_exposure  */	TRUE,
193    /* compress_enterleave*/	FALSE,
194    /* visible_interest	  */	FALSE,
195    /* destroy		  */	Destroy,
196    /* resize		  */	Resize,
197    /* expose		  */	NULL,
198    /* set_values	  */	SetValues,
199    /* set_values_hook	  */	NULL,
200    /* set_values_almost  */	XtInheritSetValuesAlmost,
201    /* get_values_hook	  */	GetValuesHook,
202    /* accept_focus	  */	NULL,
203    /* intrinsics version */	XtVersion,
204    /* callback offsets	  */	NULL,
205    /* tm_table		  */	NULL,
206    /* query_geometry	  */	NULL,
207    /* display_accelerator*/	NULL,
208    /* extension	  */	NULL
209  },{ /* Composite */
210    /* geometry_manager	  */	GeometryManager,
211    /* change_managed	  */	ChangeManaged,
212    /* insert_child	  */	XtInheritInsertChild,
213    /* delete_child	  */	XtInheritDeleteChild,
214    /* extension	  */	NULL
215  },{ /* Shell */
216    /* extension	  */	(XtPointer)&shellClassExtRec
217  }
218};
219
220externaldef(shellwidgetclass) WidgetClass shellWidgetClass = (WidgetClass) (&shellClassRec);
221
222/***************************************************************************
223 *
224 * OverrideShell class record
225 *
226 ***************************************************************************/
227
228static XtResource overrideResources[]=
229{
230	{ XtNoverrideRedirect, XtCOverrideRedirect,
231	    XtRBoolean, sizeof(Boolean), Offset(shell.override_redirect),
232	    XtRImmediate, (XtPointer)True},
233	{ XtNsaveUnder, XtCSaveUnder, XtRBoolean, sizeof(Boolean),
234	    Offset(shell.save_under), XtRImmediate, (XtPointer)True},
235};
236
237externaldef(overrideshellclassrec) OverrideShellClassRec overrideShellClassRec = {
238  {
239    /* superclass         */    (WidgetClass) &shellClassRec,
240    /* class_name         */    "OverrideShell",
241    /* size               */    sizeof(OverrideShellRec),
242    /* Class Initializer  */	NULL,
243    /* class_part_initialize*/	NULL,
244    /* Class init'ed ?    */	FALSE,
245    /* initialize         */    NULL,
246    /* initialize_notify    */	NULL,
247    /* realize            */    XtInheritRealize,
248    /* actions            */    NULL,
249    /* num_actions        */    0,
250    /* resources          */    overrideResources,
251    /* resource_count     */	XtNumber(overrideResources),
252    /* xrm_class          */    NULLQUARK,
253    /* compress_motion    */    FALSE,
254    /* compress_exposure  */    TRUE,
255    /* compress_enterleave*/ 	FALSE,
256    /* visible_interest   */    FALSE,
257    /* destroy            */    NULL,
258    /* resize             */    XtInheritResize,
259    /* expose             */    NULL,
260    /* set_values         */    NULL,
261    /* set_values_hook      */	NULL,
262    /* set_values_almost    */	XtInheritSetValuesAlmost,
263    /* get_values_hook      */	NULL,
264    /* accept_focus       */    NULL,
265    /* intrinsics version */	XtVersion,
266    /* callback offsets   */    NULL,
267    /* tm_table		    */  NULL,
268    /* query_geometry	    */  NULL,
269    /* display_accelerator  */  NULL,
270    /* extension	    */  NULL
271  },{
272    /* geometry_manager   */    XtInheritGeometryManager,
273    /* change_managed     */    XtInheritChangeManaged,
274    /* insert_child	  */	XtInheritInsertChild,
275    /* delete_child	  */	XtInheritDeleteChild,
276    /* extension	    */  NULL
277  },{
278    /* extension	    */  NULL
279  },{
280    /* extension	    */  NULL
281  }
282};
283
284externaldef(overrideshellwidgetclass) WidgetClass overrideShellWidgetClass =
285	(WidgetClass) (&overrideShellClassRec);
286
287/***************************************************************************
288 *
289 * WMShell class record
290 *
291 ***************************************************************************/
292
293#undef Offset
294#define Offset(x)	(XtOffsetOf(WMShellRec, x))
295
296static int default_unspecified_shell_int = XtUnspecifiedShellInt;
297/*
298 * Warning, casting XtUnspecifiedShellInt (which is -1) to an (XtPointer)
299 * can result is loss of bits on some machines (i.e. crays)
300 */
301
302static XtResource wmResources[]=
303{
304	{ XtNtitle, XtCTitle, XtRString, sizeof(String),
305	    Offset(wm.title), XtRString, NULL},
306	{ XtNtitleEncoding, XtCTitleEncoding, XtRAtom, sizeof(Atom),
307	    Offset(wm.title_encoding),
308	    XtRCallProc, (XtPointer) _XtTitleEncoding},
309	{ XtNwmTimeout, XtCWmTimeout, XtRInt, sizeof(int),
310	    Offset(wm.wm_timeout), XtRImmediate,(XtPointer)DEFAULT_WM_TIMEOUT},
311	{ XtNwaitForWm, XtCWaitForWm, XtRBoolean, sizeof(Boolean),
312	    Offset(wm.wait_for_wm), XtRImmediate, (XtPointer)True},
313	{ XtNtransient, XtCTransient, XtRBoolean, sizeof(Boolean),
314	    Offset(wm.transient), XtRImmediate, (XtPointer)False},
315/* size_hints minus things stored in core */
316	{ XtNbaseWidth, XtCBaseWidth, XtRInt, sizeof(int),
317	    Offset(wm.base_width),
318	    XtRInt, (XtPointer) &default_unspecified_shell_int},
319	{ XtNbaseHeight, XtCBaseHeight, XtRInt, sizeof(int),
320	    Offset(wm.base_height),
321	    XtRInt, (XtPointer) &default_unspecified_shell_int},
322	{ XtNwinGravity, XtCWinGravity, XtRGravity, sizeof(int),
323	    Offset(wm.win_gravity),
324	    XtRGravity, (XtPointer) &default_unspecified_shell_int},
325	{ XtNminWidth, XtCMinWidth, XtRInt, sizeof(int),
326	    Offset(wm.size_hints.min_width),
327	    XtRInt, (XtPointer) &default_unspecified_shell_int},
328	{ XtNminHeight, XtCMinHeight, XtRInt, sizeof(int),
329	    Offset(wm.size_hints.min_height),
330	    XtRInt, (XtPointer) &default_unspecified_shell_int},
331	{ XtNmaxWidth, XtCMaxWidth, XtRInt, sizeof(int),
332	    Offset(wm.size_hints.max_width),
333	    XtRInt, (XtPointer) &default_unspecified_shell_int},
334	{ XtNmaxHeight, XtCMaxHeight, XtRInt, sizeof(int),
335	    Offset(wm.size_hints.max_height),
336	    XtRInt, (XtPointer) &default_unspecified_shell_int},
337	{ XtNwidthInc, XtCWidthInc, XtRInt, sizeof(int),
338	    Offset(wm.size_hints.width_inc),
339	    XtRInt, (XtPointer) &default_unspecified_shell_int},
340	{ XtNheightInc, XtCHeightInc, XtRInt, sizeof(int),
341	    Offset(wm.size_hints.height_inc),
342	    XtRInt, (XtPointer) &default_unspecified_shell_int},
343	{ XtNminAspectX, XtCMinAspectX, XtRInt, sizeof(int),
344	    Offset(wm.size_hints.min_aspect.x),
345	    XtRInt, (XtPointer) &default_unspecified_shell_int},
346	{ XtNminAspectY, XtCMinAspectY, XtRInt, sizeof(int),
347	    Offset(wm.size_hints.min_aspect.y),
348	    XtRInt, (XtPointer) &default_unspecified_shell_int},
349	{ XtNmaxAspectX, XtCMaxAspectX, XtRInt, sizeof(int),
350	    Offset(wm.size_hints.max_aspect.x),
351	    XtRInt, (XtPointer) &default_unspecified_shell_int},
352	{ XtNmaxAspectY, XtCMaxAspectY, XtRInt, sizeof(int),
353	    Offset(wm.size_hints.max_aspect.y),
354	    XtRInt, (XtPointer) &default_unspecified_shell_int},
355/* wm_hints */
356	{ XtNinput, XtCInput, XtRBool, sizeof(Bool),
357	    Offset(wm.wm_hints.input), XtRImmediate, (XtPointer)False},
358	{ XtNinitialState, XtCInitialState, XtRInitialState, sizeof(int),
359	    Offset(wm.wm_hints.initial_state),
360	    XtRImmediate, (XtPointer)NormalState},
361	{ XtNiconPixmap, XtCIconPixmap, XtRBitmap, sizeof(Pixmap),
362	    Offset(wm.wm_hints.icon_pixmap), XtRPixmap, NULL},
363	{ XtNiconWindow, XtCIconWindow, XtRWindow, sizeof(Window),
364	    Offset(wm.wm_hints.icon_window), XtRWindow,   (XtPointer) NULL},
365	{ XtNiconX, XtCIconX, XtRInt, sizeof(int),
366	    Offset(wm.wm_hints.icon_x),
367	    XtRInt, (XtPointer) &default_unspecified_shell_int},
368	{ XtNiconY, XtCIconY, XtRInt, sizeof(int),
369	    Offset(wm.wm_hints.icon_y),
370	    XtRInt, (XtPointer) &default_unspecified_shell_int},
371	{ XtNiconMask, XtCIconMask, XtRBitmap, sizeof(Pixmap),
372	    Offset(wm.wm_hints.icon_mask), XtRPixmap, NULL},
373	{ XtNwindowGroup, XtCWindowGroup, XtRWindow, sizeof(Window),
374	    Offset(wm.wm_hints.window_group),
375	    XtRImmediate, (XtPointer)XtUnspecifiedWindow},
376	{ XtNclientLeader, XtCClientLeader, XtRWidget, sizeof(Widget),
377	    Offset(wm.client_leader), XtRWidget, NULL},
378	{ XtNwindowRole, XtCWindowRole, XtRString, sizeof(String),
379	    Offset(wm.window_role), XtRString, (XtPointer) NULL},
380	{ XtNurgency, XtCUrgency, XtRBoolean, sizeof(Boolean),
381	    Offset(wm.urgency), XtRImmediate, (XtPointer) False}
382};
383
384static void WMInitialize(Widget, Widget, ArgList, Cardinal *);
385static Boolean WMSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
386static void WMDestroy(Widget);
387
388externaldef(wmshellclassrec) WMShellClassRec wmShellClassRec = {
389  {
390    /* superclass         */    (WidgetClass) &shellClassRec,
391    /* class_name         */    "WMShell",
392    /* size               */    sizeof(WMShellRec),
393    /* Class Initializer  */	NULL,
394    /* class_part_initialize*/	NULL,
395    /* Class init'ed ?    */	FALSE,
396    /* initialize         */    WMInitialize,
397    /* initialize_notify    */	NULL,
398    /* realize            */    XtInheritRealize,
399    /* actions            */    NULL,
400    /* num_actions        */    0,
401    /* resources          */    wmResources,
402    /* resource_count     */	XtNumber(wmResources),
403    /* xrm_class          */    NULLQUARK,
404    /* compress_motion    */    FALSE,
405    /* compress_exposure  */    TRUE,
406    /* compress_enterleave*/	FALSE,
407    /* visible_interest   */    FALSE,
408    /* destroy            */    WMDestroy,
409    /* resize             */    XtInheritResize,
410    /* expose             */    NULL,
411    /* set_values         */    WMSetValues,
412    /* set_values_hook      */	NULL,
413    /* set_values_almost    */	XtInheritSetValuesAlmost,
414    /* get_values_hook      */	NULL,
415    /* accept_focus       */    NULL,
416    /* intrinsics version */	XtVersion,
417    /* callback offsets   */    NULL,
418    /* tm_table		    */  NULL,
419    /* query_geometry	    */  NULL,
420    /* display_accelerator  */  NULL,
421    /* extension	    */  NULL
422  },{
423    /* geometry_manager   */    XtInheritGeometryManager,
424    /* change_managed     */    XtInheritChangeManaged,
425    /* insert_child	  */	XtInheritInsertChild,
426    /* delete_child	  */	XtInheritDeleteChild,
427    /* extension	    */  NULL
428  },{
429    /* extension	    */  NULL
430  },{
431    /* extension	    */  NULL
432  }
433};
434
435externaldef(wmshellwidgetclass) WidgetClass wmShellWidgetClass = (WidgetClass) (&wmShellClassRec);
436
437/***************************************************************************
438 *
439 * TransientShell class record
440 *
441 ***************************************************************************/
442
443#undef Offset
444#define Offset(x)	(XtOffsetOf(TransientShellRec, x))
445
446static XtResource transientResources[]=
447{
448	{ XtNtransient, XtCTransient, XtRBoolean, sizeof(Boolean),
449	    Offset(wm.transient), XtRImmediate, (XtPointer)True},
450	{ XtNtransientFor, XtCTransientFor, XtRWidget, sizeof(Widget),
451	    Offset(transient.transient_for), XtRWidget, NULL},
452	{ XtNsaveUnder, XtCSaveUnder, XtRBoolean, sizeof(Boolean),
453	    Offset(shell.save_under), XtRImmediate, (XtPointer)True},
454};
455
456static void TransientRealize(Widget, Mask *, XSetWindowAttributes *);
457static Boolean TransientSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
458
459externaldef(transientshellclassrec) TransientShellClassRec transientShellClassRec = {
460  {
461    /* superclass	  */	(WidgetClass) &vendorShellClassRec,
462    /* class_name	  */	"TransientShell",
463    /* size		  */	sizeof(TransientShellRec),
464    /* Class Initializer  */	NULL,
465    /* class_part_initialize*/	NULL,
466    /* Class init'ed ?	  */	FALSE,
467    /* initialize	  */	NULL,
468    /* initialize_notify  */	NULL,
469    /* realize		  */	TransientRealize,
470    /* actions		  */	NULL,
471    /* num_actions	  */	0,
472    /* resources	  */	transientResources,
473    /* resource_count	  */	XtNumber(transientResources),
474    /* xrm_class	  */	NULLQUARK,
475    /* compress_motion	  */	FALSE,
476    /* compress_exposure  */	TRUE,
477    /* compress_enterleave*/	FALSE,
478    /* visible_interest	  */	FALSE,
479    /* destroy		  */	NULL,
480    /* resize		  */	XtInheritResize,
481    /* expose		  */	NULL,
482    /* set_values	  */	TransientSetValues,
483    /* set_values_hook	  */	NULL,
484    /* set_values_almost  */	XtInheritSetValuesAlmost,
485    /* get_values_hook	  */	NULL,
486    /* accept_focus	  */	NULL,
487    /* intrinsics version */	XtVersion,
488    /* callback offsets	  */	NULL,
489    /* tm_table		  */	XtInheritTranslations,
490    /* query_geometry	  */	NULL,
491    /* display_accelerator*/	NULL,
492    /* extension	  */	NULL
493  },{
494    /* geometry_manager	  */	XtInheritGeometryManager,
495    /* change_managed	  */	XtInheritChangeManaged,
496    /* insert_child	  */	XtInheritInsertChild,
497    /* delete_child	  */	XtInheritDeleteChild,
498    /* extension	  */	NULL
499  },{
500    /* extension	  */	NULL
501  },{
502    /* extension	  */	NULL
503  },{
504    /* extension	  */	NULL
505  },{
506    /* extension	  */	NULL
507  }
508};
509
510externaldef(transientshellwidgetclass) WidgetClass transientShellWidgetClass =
511	(WidgetClass) (&transientShellClassRec);
512
513/***************************************************************************
514 *
515 * TopLevelShell class record
516 *
517 ***************************************************************************/
518
519#undef Offset
520#define Offset(x)	(XtOffsetOf(TopLevelShellRec, x))
521
522static XtResource topLevelResources[]=
523{
524	{ XtNiconName, XtCIconName, XtRString, sizeof(String),
525	    Offset(topLevel.icon_name), XtRString, (XtPointer) NULL},
526	{ XtNiconNameEncoding, XtCIconNameEncoding, XtRAtom, sizeof(Atom),
527	    Offset(topLevel.icon_name_encoding),
528	    XtRCallProc, (XtPointer) _XtTitleEncoding},
529	{ XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
530	    Offset(topLevel.iconic), XtRImmediate, (XtPointer)False}
531};
532
533static void TopLevelInitialize(Widget, Widget, ArgList, Cardinal *);
534static Boolean TopLevelSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
535static void TopLevelDestroy(Widget);
536
537externaldef(toplevelshellclassrec) TopLevelShellClassRec topLevelShellClassRec = {
538  {
539    /* superclass         */    (WidgetClass) &vendorShellClassRec,
540    /* class_name         */    "TopLevelShell",
541    /* size               */    sizeof(TopLevelShellRec),
542    /* Class Initializer  */	NULL,
543    /* class_part_initialize*/	NULL,
544    /* Class init'ed ?    */	FALSE,
545    /* initialize         */    TopLevelInitialize,
546    /* initialize_notify    */	NULL,
547    /* realize            */    XtInheritRealize,
548    /* actions            */    NULL,
549    /* num_actions        */    0,
550    /* resources          */    topLevelResources,
551    /* resource_count     */	XtNumber(topLevelResources),
552    /* xrm_class          */    NULLQUARK,
553    /* compress_motion    */    FALSE,
554    /* compress_exposure  */    TRUE,
555    /* compress_enterleave*/ 	FALSE,
556    /* visible_interest   */    FALSE,
557    /* destroy            */    TopLevelDestroy,
558    /* resize             */    XtInheritResize,
559    /* expose             */    NULL,
560    /* set_values         */    TopLevelSetValues,
561    /* set_values_hook      */	NULL,
562    /* set_values_almost    */	XtInheritSetValuesAlmost,
563    /* get_values_hook      */	NULL,
564    /* accept_focus       */    NULL,
565    /* intrinsics version */	XtVersion,
566    /* callback offsets   */    NULL,
567    /* tm_table		    */  XtInheritTranslations,
568    /* query_geometry	    */  NULL,
569    /* display_accelerator  */  NULL,
570    /* extension	    */  NULL
571  },{
572    /* geometry_manager   */    XtInheritGeometryManager,
573    /* change_managed     */    XtInheritChangeManaged,
574    /* insert_child	  */	XtInheritInsertChild,
575    /* delete_child	  */	XtInheritDeleteChild,
576    /* extension	    */  NULL
577  },{
578    /* extension	    */  NULL
579  },{
580    /* extension	    */  NULL
581  },{
582    /* extension	    */  NULL
583  },{
584    /* extension	    */  NULL
585  }
586};
587
588externaldef(toplevelshellwidgetclass) WidgetClass topLevelShellWidgetClass =
589	(WidgetClass) (&topLevelShellClassRec);
590
591/***************************************************************************
592 *
593 * ApplicationShell class record
594 *
595 ***************************************************************************/
596
597#undef Offset
598#define Offset(x)	(XtOffsetOf(ApplicationShellRec, x))
599
600static XtResource applicationResources[]=
601{
602    {XtNargc, XtCArgc, XtRInt, sizeof(int),
603	  Offset(application.argc), XtRImmediate, (XtPointer)0},
604    {XtNargv, XtCArgv, XtRStringArray, sizeof(String*),
605	  Offset(application.argv), XtRPointer, (XtPointer) NULL}
606};
607#undef Offset
608
609static void ApplicationInitialize(Widget, Widget, ArgList, Cardinal *);
610static void ApplicationDestroy(Widget);
611static Boolean ApplicationSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
612static void ApplicationShellInsertChild(Widget);
613
614static CompositeClassExtensionRec compositeClassExtension = {
615    /* next_extension	*/	NULL,
616    /* record_type	*/	NULLQUARK,
617    /* version		*/	XtCompositeExtensionVersion,
618    /* record_size	*/	sizeof(CompositeClassExtensionRec),
619    /* accepts_objects	*/	TRUE,
620    /* allows_change_managed_set */ FALSE
621};
622
623
624externaldef(applicationshellclassrec) ApplicationShellClassRec applicationShellClassRec = {
625  {
626    /* superclass         */    (WidgetClass) &topLevelShellClassRec,
627    /* class_name         */    "ApplicationShell",
628    /* size               */    sizeof(ApplicationShellRec),
629    /* Class Initializer  */	NULL,
630    /* class_part_initialize*/	NULL,
631    /* Class init'ed ?    */	FALSE,
632    /* initialize         */    ApplicationInitialize,
633    /* initialize_notify  */	NULL,
634    /* realize            */    XtInheritRealize,
635    /* actions            */    NULL,
636    /* num_actions        */    0,
637    /* resources          */    applicationResources,
638    /* resource_count     */	XtNumber(applicationResources),
639    /* xrm_class          */    NULLQUARK,
640    /* compress_motion    */    FALSE,
641    /* compress_exposure  */    TRUE,
642    /* compress_enterleave*/    FALSE,
643    /* visible_interest   */    FALSE,
644    /* destroy            */    ApplicationDestroy,
645    /* resize             */    XtInheritResize,
646    /* expose             */    NULL,
647    /* set_values         */    ApplicationSetValues,
648    /* set_values_hook    */	NULL,
649    /* set_values_almost  */	XtInheritSetValuesAlmost,
650    /* get_values_hook    */	NULL,
651    /* accept_focus       */    NULL,
652    /* intrinsics version */	XtVersion,
653    /* callback offsets   */    NULL,
654    /* tm_table		  */	XtInheritTranslations,
655    /* query_geometry	  */	NULL,
656    /* display_accelerator*/	NULL,
657    /* extension	  */	NULL
658  },{
659    /* geometry_manager   */    XtInheritGeometryManager,
660    /* change_managed     */    XtInheritChangeManaged,
661    /* insert_child	  */	ApplicationShellInsertChild,
662    /* delete_child	  */	XtInheritDeleteChild,
663    /* extension	  */	(XtPointer)&compositeClassExtension
664  },{
665    /* extension	  */	NULL
666  },{
667    /* extension	  */	NULL
668  },{
669    /* extension	  */	NULL
670  },{
671    /* extension	  */	NULL
672  },{
673    /* extension	  */	NULL
674  }
675};
676
677externaldef(applicationshellwidgetclass) WidgetClass applicationShellWidgetClass =
678	(WidgetClass) (&applicationShellClassRec);
679
680/***************************************************************************
681 *
682 * SessionShell class record
683 *
684 ***************************************************************************/
685
686#undef Offset
687#define Offset(x)	(XtOffsetOf(SessionShellRec, x))
688
689static XtResource sessionResources[]=
690{
691#ifndef XT_NO_SM
692 {XtNconnection, XtCConnection, XtRSmcConn, sizeof(SmcConn),
693       Offset(session.connection), XtRSmcConn, (XtPointer) NULL},
694#endif
695 {XtNsessionID, XtCSessionID, XtRString, sizeof(String),
696       Offset(session.session_id), XtRString, (XtPointer) NULL},
697 {XtNrestartCommand, XtCRestartCommand, XtRCommandArgArray, sizeof(String*),
698       Offset(session.restart_command), XtRPointer, (XtPointer) NULL},
699 {XtNcloneCommand, XtCCloneCommand, XtRCommandArgArray, sizeof(String*),
700       Offset(session.clone_command), XtRPointer, (XtPointer) NULL},
701 {XtNdiscardCommand, XtCDiscardCommand, XtRCommandArgArray, sizeof(String*),
702       Offset(session.discard_command), XtRPointer, (XtPointer) NULL},
703 {XtNresignCommand, XtCResignCommand, XtRCommandArgArray, sizeof(String*),
704       Offset(session.resign_command), XtRPointer, (XtPointer) NULL},
705 {XtNshutdownCommand, XtCShutdownCommand, XtRCommandArgArray, sizeof(String*),
706       Offset(session.shutdown_command), XtRPointer, (XtPointer) NULL},
707 {XtNenvironment, XtCEnvironment, XtREnvironmentArray, sizeof(String*),
708       Offset(session.environment), XtRPointer, (XtPointer) NULL},
709 {XtNcurrentDirectory, XtCCurrentDirectory, XtRDirectoryString, sizeof(String),
710       Offset(session.current_dir), XtRString, (XtPointer) NULL},
711 {XtNprogramPath, XtCProgramPath, XtRString, sizeof(String),
712      Offset(session.program_path), XtRString, (XtPointer) NULL},
713 {XtNrestartStyle, XtCRestartStyle, XtRRestartStyle, sizeof(unsigned char),
714      Offset(session.restart_style), XtRImmediate,
715      (XtPointer) SmRestartIfRunning},
716 {XtNjoinSession, XtCJoinSession, XtRBoolean, sizeof(Boolean),
717       Offset(session.join_session), XtRImmediate, (XtPointer) True},
718 {XtNsaveCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
719       Offset(session.save_callbacks), XtRCallback, (XtPointer) NULL},
720 {XtNinteractCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
721       Offset(session.interact_callbacks), XtRCallback, (XtPointer)NULL},
722 {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
723       Offset(session.cancel_callbacks), XtRCallback, (XtPointer) NULL},
724 {XtNsaveCompleteCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
725       Offset(session.save_complete_callbacks), XtRCallback, (XtPointer) NULL},
726 {XtNdieCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
727       Offset(session.die_callbacks), XtRCallback, (XtPointer) NULL},
728 {XtNerrorCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
729       Offset(session.error_callbacks), XtRCallback, (XtPointer) NULL}
730};
731#undef Offset
732
733static void SessionInitialize(Widget, Widget, ArgList, Cardinal *);
734static void SessionDestroy(Widget);
735static Boolean SessionSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
736
737static CompositeClassExtensionRec sessionCompositeClassExtension = {
738    /* next_extension	*/	NULL,
739    /* record_type	*/	NULLQUARK,
740    /* version		*/	XtCompositeExtensionVersion,
741    /* record_size	*/	sizeof(CompositeClassExtensionRec),
742    /* accepts_objects	*/	TRUE,
743    /* allows_change_managed_set */ FALSE
744};
745
746
747externaldef(sessionshellclassrec) SessionShellClassRec sessionShellClassRec = {
748  {
749    /* superclass         */    (WidgetClass) &applicationShellClassRec,
750    /* class_name         */    "SessionShell",
751    /* size               */    sizeof(SessionShellRec),
752    /* Class Initializer  */	NULL,
753    /* class_part_initialize*/	NULL,
754    /* Class init'ed ?    */	FALSE,
755    /* initialize         */    SessionInitialize,
756    /* initialize_notify  */	NULL,
757    /* realize            */    XtInheritRealize,
758    /* actions            */    NULL,
759    /* num_actions        */    0,
760    /* resources          */    sessionResources,
761    /* resource_count     */	XtNumber(sessionResources),
762    /* xrm_class          */    NULLQUARK,
763    /* compress_motion    */    FALSE,
764    /* compress_exposure  */    TRUE,
765    /* compress_enterleave*/    FALSE,
766    /* visible_interest   */    FALSE,
767    /* destroy            */    SessionDestroy,
768    /* resize             */    XtInheritResize,
769    /* expose             */    NULL,
770    /* set_values         */    SessionSetValues,
771    /* set_values_hook    */	NULL,
772    /* set_values_almost  */	XtInheritSetValuesAlmost,
773    /* get_values_hook    */	NULL,
774    /* accept_focus       */    NULL,
775    /* intrinsics version */	XtVersion,
776    /* callback offsets   */    NULL,
777    /* tm_table		  */	XtInheritTranslations,
778    /* query_geometry	  */	NULL,
779    /* display_accelerator*/	NULL,
780    /* extension	  */	NULL
781  },{
782    /* geometry_manager   */    XtInheritGeometryManager,
783    /* change_managed     */    XtInheritChangeManaged,
784    /* insert_child	  */	XtInheritInsertChild,
785    /* delete_child	  */	XtInheritDeleteChild,
786    /* extension	  */	(XtPointer)&sessionCompositeClassExtension
787  },{
788    /* extension	  */	NULL
789  },{
790    /* extension	  */	NULL
791  },{
792    /* extension	  */	NULL
793  },{
794    /* extension	  */	NULL
795  },{
796    /* extension	  */	NULL
797  },{
798    /* extension          */    NULL
799  }
800};
801
802externaldef(sessionshellwidgetclass) WidgetClass sessionShellWidgetClass =
803	(WidgetClass) (&sessionShellClassRec);
804
805/****************************************************************************
806 * Whew!
807 ****************************************************************************/
808
809static void ComputeWMSizeHints(
810    WMShellWidget w,
811    XSizeHints *hints)
812{
813    register long flags;
814    hints->flags = flags = w->wm.size_hints.flags;
815#define copy(field) hints->field = w->wm.size_hints.field
816    if (flags & (USPosition | PPosition)) {
817	copy(x);
818	copy(y);
819    }
820    if (flags & (USSize | PSize)) {
821	copy(width);
822	copy(height);
823    }
824    if (flags & PMinSize) {
825	copy(min_width);
826	copy(min_height);
827    }
828    if (flags & PMaxSize) {
829	copy(max_width);
830	copy(max_height);
831    }
832    if (flags & PResizeInc) {
833	copy(width_inc);
834	copy(height_inc);
835    }
836    if (flags & PAspect) {
837	copy(min_aspect.x);
838	copy(min_aspect.y);
839	copy(max_aspect.x);
840	copy(max_aspect.y);
841    }
842#undef copy
843#define copy(field) hints->field = w->wm.field
844    if (flags & PBaseSize) {
845	copy(base_width);
846	copy(base_height);
847    }
848    if (flags & PWinGravity)
849	copy(win_gravity);
850#undef copy
851}
852
853static void _SetWMSizeHints(
854    WMShellWidget w)
855{
856    XSizeHints *size_hints = XAllocSizeHints();
857
858    if (size_hints == NULL) _XtAllocError("XAllocSizeHints");
859    ComputeWMSizeHints(w, size_hints);
860    XSetWMNormalHints(XtDisplay((Widget)w), XtWindow((Widget)w), size_hints);
861    XFree((char*)size_hints);
862}
863
864static ShellClassExtension _FindClassExtension(
865    WidgetClass widget_class)
866{
867    ShellClassExtension ext;
868    for (ext = (ShellClassExtension)((ShellWidgetClass)widget_class)
869	       ->shell_class.extension;
870	 ext != NULL && ext->record_type != NULLQUARK;
871	 ext = (ShellClassExtension)ext->next_extension);
872
873    if (ext != NULL) {
874	if (  ext->version == XtShellExtensionVersion
875	      && ext->record_size == sizeof(ShellClassExtensionRec)) {
876	    /* continue */
877	} else {
878	    String params[1];
879	    Cardinal num_params = 1;
880	    params[0] = widget_class->core_class.class_name;
881	    XtErrorMsg( "invalidExtension", "shellClassPartInitialize",
882		        XtCXtToolkitError,
883		 "widget class %s has invalid ShellClassExtension record",
884		 params, &num_params);
885	}
886    }
887    return ext;
888}
889
890static void ClassPartInitialize(WidgetClass widget_class)
891{
892    ShellClassExtension ext = _FindClassExtension(widget_class);
893    if (ext != NULL) {
894	if (ext->root_geometry_manager == XtInheritRootGeometryManager) {
895	    ext->root_geometry_manager =
896		_FindClassExtension(widget_class->core_class.superclass)
897		    ->root_geometry_manager;
898	}
899    } else {
900	/* if not found, spec requires XtInheritRootGeometryManager */
901	XtPointer *extP
902	    = &((ShellWidgetClass)widget_class)->shell_class.extension;
903	ext = XtNew(ShellClassExtensionRec);
904	(void) memmove((char*)ext,
905		       (char*)_FindClassExtension(widget_class->core_class.superclass),
906		       sizeof(ShellClassExtensionRec));
907	ext->next_extension = *extP;
908	*extP = (XtPointer)ext;
909    }
910}
911
912
913static void EventHandler(Widget wid, XtPointer closure, XEvent *event, Boolean *continue_to_dispatch);
914static void _popup_set_prop(ShellWidget);
915
916
917/*ARGSUSED*/
918static void XtCopyDefaultDepth(
919    Widget      widget,
920    int		offset,
921    XrmValue    *value)
922{
923    value->addr = (XPointer)(&DefaultDepthOfScreen(XtScreenOfObject(widget)));
924}
925
926#ifndef CRAY
927static
928#endif
929void _XtShellDepth(
930    Widget widget,
931    int closure,
932    XrmValue *value)
933{
934   if (widget->core.parent == NULL) XtCopyDefaultDepth(widget,closure,value);
935   else _XtCopyFromParent (widget,closure,value);
936}
937
938/*ARGSUSED*/
939static void XtCopyDefaultColormap(
940    Widget      widget,
941    int		offset,
942    XrmValue    *value)
943{
944    value->addr = (XPointer)(&DefaultColormapOfScreen(XtScreenOfObject(widget)));
945}
946
947#ifndef CRAY
948static
949#endif
950void _XtShellColormap(
951    Widget widget,
952    int closure,
953    XrmValue *value)
954{
955   if (widget->core.parent == NULL)
956	   XtCopyDefaultColormap(widget,closure,value);
957   else _XtCopyFromParent (widget,closure,value);
958}
959
960#ifndef CRAY
961static
962#endif
963void _XtShellAncestorSensitive(
964    Widget widget,
965    int closure,
966    XrmValue *value)
967{
968   static Boolean true = True;
969   if (widget->core.parent == NULL) value->addr = (XPointer)(&true);
970   else _XtCopyFromParent (widget,closure,value);
971}
972
973/*ARGSUSED*/
974#ifndef CRAY
975static
976#endif
977void _XtTitleEncoding(
978    Widget widget,
979    int offset,
980    XrmValue *value)
981{
982    static Atom atom;
983    if (XtWidgetToApplicationContext(widget)->langProcRec.proc) atom = None;
984    else atom = XA_STRING;
985    value->addr = (XPointer) &atom;
986}
987
988
989/* ARGSUSED */
990static void Initialize(
991	Widget req,
992	Widget new,
993	ArgList args,		/* unused */
994	Cardinal *num_args)	/* unused */
995{
996	ShellWidget w = (ShellWidget) new;
997
998	w->shell.popped_up = FALSE;
999	w->shell.client_specified =
1000	    _XtShellNotReparented | _XtShellPositionValid;
1001
1002	if (w->core.x == BIGSIZE) {
1003	    w->core.x = 0;
1004	    if (w->core.y == BIGSIZE) w->core.y = 0;
1005	} else {
1006	    if (w->core.y == BIGSIZE) w->core.y = 0;
1007	    else w->shell.client_specified |= _XtShellPPositionOK;
1008	}
1009
1010	XtAddEventHandler(new, (EventMask) StructureNotifyMask,
1011		TRUE, EventHandler, (XtPointer) NULL);
1012
1013#ifdef EDITRES
1014	XtAddEventHandler(new, (EventMask) 0, TRUE,
1015			  _XEditResCheckMessages, NULL);
1016#endif
1017}
1018
1019/* ARGSUSED */
1020static void WMInitialize(
1021	Widget req, Widget new,
1022	ArgList args,		/* unused */
1023	Cardinal *num_args)	/* unused */
1024{
1025	WMShellWidget w = (WMShellWidget) new;
1026	TopLevelShellWidget tls = (TopLevelShellWidget) new;	/* maybe */
1027
1028	if(w->wm.title == NULL) {
1029	    if (XtIsTopLevelShell(new) &&
1030		    tls->topLevel.icon_name != NULL &&
1031		    strlen(tls->topLevel.icon_name) != 0) {
1032		w->wm.title = XtNewString(tls->topLevel.icon_name);
1033	    } else {
1034		w->wm.title = XtNewString(w->core.name);
1035	    }
1036	} else {
1037	    w->wm.title = XtNewString(w->wm.title);
1038	}
1039	w->wm.size_hints.flags = 0;
1040	w->wm.wm_hints.flags = 0;
1041	if (w->wm.window_role)
1042	    w->wm.window_role = XtNewString(w->wm.window_role);
1043}
1044
1045
1046/* ARGSUSED */
1047static void TopLevelInitialize(
1048	Widget req, Widget new,
1049	ArgList args,		/* unused */
1050	Cardinal *num_args)	/* unused */
1051{
1052	TopLevelShellWidget w = (TopLevelShellWidget) new;
1053
1054	if (w->topLevel.icon_name == NULL) {
1055	    w->topLevel.icon_name = XtNewString(w->core.name);
1056	} else {
1057	    w->topLevel.icon_name = XtNewString(w->topLevel.icon_name);
1058	}
1059
1060	if (w->topLevel.iconic)
1061	    w->wm.wm_hints.initial_state = IconicState;
1062}
1063
1064static String *NewArgv(int, String *);
1065static String *NewStringArray(String *);
1066static void FreeStringArray(String *);
1067
1068/* ARGSUSED */
1069static void ApplicationInitialize(
1070    Widget req, Widget new,
1071    ArgList args,		/* unused */
1072    Cardinal *num_args)		/* unused */
1073{
1074    ApplicationShellWidget w = (ApplicationShellWidget)new;
1075
1076    if (w->application.argc > 0)
1077	w->application.argv = NewArgv(w->application.argc,
1078				      w->application.argv);
1079}
1080
1081#define XtSaveInactive 0
1082#define XtSaveActive   1
1083#define XtInteractPending    2
1084#define XtInteractActive     3
1085
1086#define XtCloneCommandMask	(1L<<0)
1087#define XtCurrentDirectoryMask	(1L<<1)
1088#define XtDiscardCommandMask	(1L<<2)
1089#define XtEnvironmentMask	(1L<<3)
1090#define XtProgramMask		(1L<<4)
1091#define XtResignCommandMask	(1L<<5)
1092#define XtRestartCommandMask	(1L<<6)
1093#define XtRestartStyleHintMask	(1L<<7)
1094#define XtShutdownCommandMask	(1L<<8)
1095
1096static void JoinSession(SessionShellWidget);
1097static void SetSessionProperties(SessionShellWidget, Boolean, unsigned long, unsigned long);
1098static void StopManagingSession(SessionShellWidget, SmcConn);
1099
1100typedef struct _XtSaveYourselfRec {
1101    XtSaveYourself next;
1102    int            save_type;
1103    int            interact_style;
1104    Boolean        shutdown;
1105    Boolean        fast;
1106    Boolean        cancel_shutdown;
1107    int		   phase;
1108    int            interact_dialog_type;
1109    Boolean	   request_cancel;
1110    Boolean	   request_next_phase;
1111    Boolean        save_success;
1112    int            save_tokens;
1113    int            interact_tokens;
1114} XtSaveYourselfRec;
1115
1116/* ARGSUSED */
1117static void SessionInitialize(
1118    Widget req, Widget new,
1119    ArgList args,		/* unused */
1120    Cardinal *num_args)		/* unused */
1121{
1122#ifndef XT_NO_SM
1123    SessionShellWidget w = (SessionShellWidget)new;
1124
1125    if (w->session.session_id) w->session.session_id =
1126	XtNewString(w->session.session_id);
1127    if (w->session.restart_command) w->session.restart_command =
1128	NewStringArray(w->session.restart_command);
1129    if (w->session.clone_command) w->session.clone_command =
1130	NewStringArray(w->session.clone_command);
1131    if (w->session.discard_command) w->session.discard_command =
1132	NewStringArray(w->session.discard_command);
1133    if (w->session.resign_command) w->session.resign_command =
1134	NewStringArray(w->session.resign_command);
1135    if (w->session.shutdown_command) w->session.shutdown_command =
1136	NewStringArray(w->session.shutdown_command);
1137    if (w->session.environment) w->session.environment =
1138	NewStringArray(w->session.environment);
1139    if (w->session.current_dir) w->session.current_dir =
1140	XtNewString(w->session.current_dir);
1141    if (w->session.program_path) w->session.program_path =
1142	XtNewString(w->session.program_path);
1143
1144    w->session.checkpoint_state = XtSaveInactive;
1145    w->session.input_id = 0;
1146    w->session.save = NULL;
1147
1148    if ((w->session.join_session) &&
1149	(w->application.argv || w->session.restart_command))
1150	JoinSession(w);
1151
1152    if (w->session.connection)
1153	SetSessionProperties(w, True, 0L, 0L);
1154#endif /* !XT_NO_SM */
1155}
1156
1157static void Resize(
1158    Widget w)
1159{
1160    register ShellWidget sw = (ShellWidget)w;
1161    Widget childwid;
1162    Cardinal i;
1163    for(i = 0; i < sw->composite.num_children; i++) {
1164        if (XtIsManaged(sw->composite.children[i])) {
1165             childwid = sw->composite.children[i];
1166             XtResizeWidget(childwid, sw->core.width, sw->core.height,
1167                           childwid->core.border_width);
1168	     break;		/* can only be one managed child */
1169        }
1170    }
1171}
1172
1173static void GetGeometry(Widget, Widget);
1174
1175static void Realize(
1176	Widget wid,
1177	Mask *vmask,
1178	XSetWindowAttributes *attr)
1179{
1180	ShellWidget w = (ShellWidget) wid;
1181        Mask mask = *vmask;
1182
1183	if (! (w->shell.client_specified & _XtShellGeometryParsed)) {
1184	    /* we'll get here only if there was no child the first
1185	       time we were realized.  If the shell was Unrealized
1186	       and then re-Realized, we probably don't want to
1187	       re-evaluate the defaults anyway.
1188	     */
1189	    GetGeometry(wid, (Widget)NULL);
1190	}
1191	else if (w->core.background_pixmap == XtUnspecifiedPixmap) {
1192	    /* I attempt to inherit my child's background to avoid screen flash
1193	     * if there is latency between when I get resized and when my child
1194	     * is resized.  Background=None is not satisfactory, as I want the
1195	     * user to get immediate feedback on the new dimensions (most
1196	     * particularly in the case of a non-reparenting wm).  It is
1197	     * especially important to have the server clear any old cruft
1198	     * from the display when I am resized larger.
1199	     */
1200	    register Widget *childP = w->composite.children;
1201	    int i;
1202	    for (i = w->composite.num_children; i; i--, childP++) {
1203		if (XtIsWidget(*childP) && XtIsManaged(*childP)) {
1204		    if ((*childP)->core.background_pixmap
1205			    != XtUnspecifiedPixmap) {
1206			mask &= ~(CWBackPixel);
1207			mask |= CWBackPixmap;
1208			attr->background_pixmap =
1209			    w->core.background_pixmap =
1210				(*childP)->core.background_pixmap;
1211		    } else {
1212			attr->background_pixel =
1213			    w->core.background_pixel =
1214				(*childP)->core.background_pixel;
1215		    }
1216		    break;
1217		}
1218	    }
1219	}
1220
1221	if(w->shell.save_under) {
1222		mask |= CWSaveUnder;
1223		attr->save_under = TRUE;
1224	}
1225	if(w->shell.override_redirect) {
1226		mask |= CWOverrideRedirect;
1227		attr->override_redirect = TRUE;
1228	}
1229	if (wid->core.width == 0 || wid->core.height == 0) {
1230	    Cardinal count = 1;
1231	    XtErrorMsg("invalidDimension", "shellRealize", XtCXtToolkitError,
1232		       "Shell widget %s has zero width and/or height",
1233		       &wid->core.name, &count);
1234	}
1235	wid->core.window = XCreateWindow(XtDisplay(wid),
1236		wid->core.screen->root, (int)wid->core.x, (int)wid->core.y,
1237		(unsigned int)wid->core.width, (unsigned int)wid->core.height,
1238		(unsigned int)wid->core.border_width, (int) wid->core.depth,
1239		(unsigned int) InputOutput, w->shell.visual,
1240		mask, attr);
1241
1242	_popup_set_prop(w);
1243}
1244
1245
1246static void _SetTransientForHint(
1247     TransientShellWidget w,
1248     Boolean delete)
1249{
1250    Window window_group;
1251
1252    if (w->wm.transient) {
1253	if (w->transient.transient_for != NULL
1254	    && XtIsRealized(w->transient.transient_for))
1255	    window_group = XtWindow(w->transient.transient_for);
1256	else if ((window_group = w->wm.wm_hints.window_group)
1257		 == XtUnspecifiedWindowGroup) {
1258	    if (delete)
1259		XDeleteProperty( XtDisplay((Widget)w),
1260				 XtWindow((Widget)w),
1261				 XA_WM_TRANSIENT_FOR
1262				);
1263	    return;
1264	}
1265
1266	XSetTransientForHint( XtDisplay((Widget)w),
1267			      XtWindow((Widget)w),
1268			      window_group
1269			     );
1270    }
1271}
1272
1273
1274static void TransientRealize(
1275     Widget w,
1276     Mask *vmask,
1277     XSetWindowAttributes *attr)
1278{
1279    XtRealizeProc realize;
1280
1281    LOCK_PROCESS;
1282    realize =
1283	transientShellWidgetClass->core_class.superclass->core_class.realize;
1284    UNLOCK_PROCESS;
1285    (*realize) (w, vmask, attr);
1286
1287    _SetTransientForHint((TransientShellWidget)w, False);
1288}
1289
1290static Widget GetClientLeader(
1291    Widget w)
1292{
1293    while ((! XtIsWMShell(w) || ! ((WMShellWidget)w)->wm.client_leader)
1294	   && w->core.parent)
1295	w = w->core.parent;
1296
1297    /* ASSERT: w is a WMshell with client_leader set, or w has no parent */
1298
1299    if (XtIsWMShell(w) && ((WMShellWidget)w)->wm.client_leader)
1300	w = ((WMShellWidget)w)->wm.client_leader;
1301    return w;
1302}
1303
1304static void EvaluateWMHints(
1305    WMShellWidget w)
1306{
1307	XWMHints *hintp = &w->wm.wm_hints;
1308
1309	hintp->flags = StateHint | InputHint;
1310
1311	if (hintp->icon_x == XtUnspecifiedShellInt)
1312	    hintp->icon_x = -1;
1313	else
1314	    hintp->flags |= IconPositionHint;
1315
1316	if (hintp->icon_y == XtUnspecifiedShellInt)
1317	    hintp->icon_y = -1;
1318	else
1319	    hintp->flags |= IconPositionHint;
1320
1321	if (hintp->icon_pixmap != None) hintp->flags |= IconPixmapHint;
1322	if (hintp->icon_mask != None)   hintp->flags |= IconMaskHint;
1323	if (hintp->icon_window != None) hintp->flags |= IconWindowHint;
1324
1325	if (hintp->window_group == XtUnspecifiedWindow) {
1326	    if(w->core.parent) {
1327		Widget p;
1328		for (p = w->core.parent; p->core.parent; p = p->core.parent);
1329		if (XtIsRealized(p)) {
1330		    hintp->window_group = XtWindow(p);
1331		    hintp->flags |=  WindowGroupHint;
1332		}
1333	    }
1334	} else if (hintp->window_group != XtUnspecifiedWindowGroup)
1335	    hintp->flags |=  WindowGroupHint;
1336
1337	if (w->wm.urgency) hintp->flags |= XUrgencyHint;
1338}
1339
1340
1341static void EvaluateSizeHints(
1342    WMShellWidget w)
1343{
1344	struct _OldXSizeHints *sizep = &w->wm.size_hints;
1345
1346	sizep->x = w->core.x;
1347	sizep->y = w->core.y;
1348	sizep->width = w->core.width;
1349	sizep->height = w->core.height;
1350
1351	if (sizep->flags & USSize) {
1352	    if (sizep->flags & PSize) sizep->flags &= ~PSize;
1353	} else
1354	    sizep->flags |= PSize;
1355
1356	if (sizep->flags & USPosition) {
1357	    if (sizep->flags & PPosition) sizep->flags &= ~PPosition;
1358	} else if (w->shell.client_specified & _XtShellPPositionOK)
1359	    sizep->flags |= PPosition;
1360
1361	if (sizep->min_aspect.x != XtUnspecifiedShellInt
1362	    || sizep->min_aspect.y != XtUnspecifiedShellInt
1363	    || sizep->max_aspect.x != XtUnspecifiedShellInt
1364	    || sizep->max_aspect.y != XtUnspecifiedShellInt) {
1365	    sizep->flags |= PAspect;
1366	}
1367	if (sizep->flags & PBaseSize
1368	    || w->wm.base_width != XtUnspecifiedShellInt
1369	    || w->wm.base_height != XtUnspecifiedShellInt) {
1370	    sizep->flags |= PBaseSize;
1371	    if (w->wm.base_width == XtUnspecifiedShellInt)
1372		w->wm.base_width = 0;
1373	    if (w->wm.base_height == XtUnspecifiedShellInt)
1374		w->wm.base_height = 0;
1375	}
1376	if (sizep->flags & PResizeInc
1377	    || sizep->width_inc != XtUnspecifiedShellInt
1378	    || sizep->height_inc != XtUnspecifiedShellInt) {
1379	    if (sizep->width_inc < 1) sizep->width_inc = 1;
1380	    if (sizep->height_inc < 1) sizep->height_inc = 1;
1381	    sizep->flags |= PResizeInc;
1382	}
1383	if (sizep->flags & PMaxSize
1384	    || sizep->max_width != XtUnspecifiedShellInt
1385	    || sizep->max_height != XtUnspecifiedShellInt) {
1386	    sizep->flags |= PMaxSize;
1387	    if (sizep->max_width == XtUnspecifiedShellInt)
1388		sizep->max_width = BIGSIZE;
1389	    if (sizep->max_height == XtUnspecifiedShellInt)
1390		sizep->max_height = BIGSIZE;
1391	}
1392	if (sizep->flags & PMinSize
1393	    || sizep->min_width != XtUnspecifiedShellInt
1394	    || sizep->min_height != XtUnspecifiedShellInt) {
1395	    sizep->flags |= PMinSize;
1396	    if (sizep->min_width == XtUnspecifiedShellInt)
1397		sizep->min_width = 1;
1398	    if (sizep->min_height == XtUnspecifiedShellInt)
1399		sizep->min_height = 1;
1400	}
1401}
1402
1403static void _popup_set_prop(
1404	ShellWidget w)
1405{
1406	Widget p;
1407	WMShellWidget wmshell = (WMShellWidget) w;
1408	TopLevelShellWidget tlshell = (TopLevelShellWidget) w;
1409	ApplicationShellWidget appshell = (ApplicationShellWidget) w;
1410	XTextProperty icon_name;
1411	XTextProperty window_name;
1412	char **argv;
1413	int argc;
1414	XSizeHints *size_hints;
1415	Window window_group;
1416	XClassHint classhint;
1417	Boolean copied_iname, copied_wname;
1418
1419	if (!XtIsWMShell((Widget)w) || w->shell.override_redirect) return;
1420
1421	if ((size_hints = XAllocSizeHints()) == NULL)
1422	    _XtAllocError("XAllocSizeHints");
1423
1424	copied_iname = copied_wname = False;
1425        if (wmshell->wm.title_encoding == None &&
1426	    XmbTextListToTextProperty(XtDisplay((Widget)w),
1427				      (char**)&wmshell->wm.title,
1428				      1, XStdICCTextStyle,
1429				      &window_name) >= Success) {
1430	    copied_wname = True;
1431	} else {
1432	    window_name.value = (unsigned char*)wmshell->wm.title;
1433	    window_name.encoding = wmshell->wm.title_encoding ?
1434		wmshell->wm.title_encoding : XA_STRING;
1435	    window_name.format = 8;
1436	    window_name.nitems = strlen((char *)window_name.value);
1437	}
1438
1439	if (XtIsTopLevelShell((Widget)w)) {
1440            if (tlshell->topLevel.icon_name_encoding == None &&
1441		XmbTextListToTextProperty(XtDisplay((Widget)w),
1442					  (char**)&tlshell->topLevel.icon_name,
1443					  1, XStdICCTextStyle,
1444					  &icon_name) >= Success) {
1445		copied_iname = True;
1446	    } else {
1447		icon_name.value = (unsigned char*)tlshell->topLevel.icon_name;
1448		icon_name.encoding = tlshell->topLevel.icon_name_encoding ?
1449		    tlshell->topLevel.icon_name_encoding : XA_STRING;
1450		icon_name.format = 8;
1451		icon_name.nitems = strlen((char *)icon_name.value);
1452	    }
1453	}
1454
1455	EvaluateWMHints(wmshell);
1456	EvaluateSizeHints(wmshell);
1457	ComputeWMSizeHints(wmshell, size_hints);
1458
1459	if (wmshell->wm.transient
1460	    && !XtIsTransientShell((Widget)w)
1461	    && (window_group = wmshell->wm.wm_hints.window_group)
1462	       != XtUnspecifiedWindowGroup) {
1463
1464	    XSetTransientForHint(XtDisplay((Widget)w),
1465				 XtWindow((Widget)w),
1466				 window_group
1467				 );
1468	}
1469
1470	classhint.res_name = w->core.name;
1471	/* For the class, look up to the top of the tree */
1472	for (p = (Widget)w; p->core.parent != NULL; p = p->core.parent);
1473	if (XtIsApplicationShell(p)) {
1474	    classhint.res_class =
1475		((ApplicationShellWidget)p)->application.class;
1476	} else {
1477	    LOCK_PROCESS;
1478	    classhint.res_class = XtClass(p)->core_class.class_name;
1479	    UNLOCK_PROCESS;
1480	}
1481
1482	if (XtIsApplicationShell((Widget)w)
1483	    && (argc = appshell->application.argc) != -1)
1484	    argv = (char**)appshell->application.argv;
1485	else {
1486	    argv = NULL;
1487	    argc = 0;
1488	}
1489
1490	XSetWMProperties(XtDisplay((Widget)w), XtWindow((Widget)w),
1491			 &window_name,
1492			 (XtIsTopLevelShell((Widget)w)) ? &icon_name : NULL,
1493			 argv, argc,
1494			 size_hints,
1495			 &wmshell->wm.wm_hints,
1496			 &classhint);
1497	XFree((char*)size_hints);
1498	if (copied_wname)
1499	    XFree((XPointer)window_name.value);
1500	if (copied_iname)
1501	    XFree((XPointer)icon_name.value);
1502
1503	LOCK_PROCESS;
1504	if (XtWidgetToApplicationContext((Widget)w)->langProcRec.proc) {
1505	    char *locale = setlocale(LC_CTYPE, (char *)NULL);
1506	    if (locale)
1507		XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w),
1508				XInternAtom(XtDisplay((Widget)w),
1509					    "WM_LOCALE_NAME", False),
1510				XA_STRING, 8, PropModeReplace,
1511				(unsigned char *)locale, strlen(locale));
1512	}
1513	UNLOCK_PROCESS;
1514
1515	p = GetClientLeader((Widget)w);
1516	if (XtWindow(p))
1517	    XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w),
1518			    XInternAtom(XtDisplay((Widget)w),
1519					"WM_CLIENT_LEADER", False),
1520			    XA_WINDOW, 32, PropModeReplace,
1521			    (unsigned char *)(&(p->core.window)), 1);
1522#ifndef XT_NO_SM
1523	if (p == (Widget) w) {
1524	    for ( ; p->core.parent != NULL; p = p->core.parent);
1525	    if (XtIsSubclass(p, sessionShellWidgetClass)) {
1526		String sm_client_id =
1527		    ((SessionShellWidget)p)->session.session_id;
1528		if (sm_client_id != NULL) {
1529		    XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w),
1530				    XInternAtom(XtDisplay((Widget)w),
1531						"SM_CLIENT_ID", False),
1532				    XA_STRING, 8, PropModeReplace,
1533				    (unsigned char *) sm_client_id,
1534				    strlen(sm_client_id));
1535		}
1536	    }
1537	}
1538#endif /* !XT_NO_SM */
1539
1540	if (wmshell->wm.window_role)
1541	    XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w),
1542			    XInternAtom(XtDisplay((Widget)w),
1543					"WM_WINDOW_ROLE", False),
1544			    XA_STRING, 8, PropModeReplace,
1545			    (unsigned char *)wmshell->wm.window_role,
1546			    strlen(wmshell->wm.window_role));
1547}
1548
1549/* ARGSUSED */
1550static void EventHandler(
1551	Widget wid,
1552	XtPointer closure,	/* unused */
1553	XEvent *event,
1554        Boolean *continue_to_dispatch) /* unused */
1555{
1556	register ShellWidget w = (ShellWidget) wid;
1557	WMShellWidget wmshell = (WMShellWidget) w;
1558	Boolean  sizechanged = FALSE;
1559
1560	if(w->core.window != event->xany.window) {
1561		XtAppErrorMsg(XtWidgetToApplicationContext(wid),
1562			"invalidWindow","eventHandler",XtCXtToolkitError,
1563                        "Event with wrong window",
1564			(String *)NULL, (Cardinal *)NULL);
1565		return;
1566	}
1567
1568	switch(event->type) {
1569	    case ConfigureNotify:
1570	        if (w->core.window != event->xconfigure.window)
1571		    return;  /* in case of SubstructureNotify */
1572#define NEQ(x)	( w->core.x != event->xconfigure.x )
1573		if( NEQ(width) || NEQ(height) || NEQ(border_width) ) {
1574			sizechanged = TRUE;
1575#undef NEQ
1576			w->core.width = event->xconfigure.width;
1577			w->core.height = event->xconfigure.height;
1578			w->core.border_width = event->xconfigure.border_width;
1579		}
1580		if (event->xany.send_event /* ICCCM compliant synthetic ev */
1581		    /* || w->shell.override_redirect */
1582		    || w->shell.client_specified & _XtShellNotReparented)
1583	        {
1584		    w->core.x = event->xconfigure.x;
1585		    w->core.y = event->xconfigure.y;
1586		    w->shell.client_specified |= _XtShellPositionValid;
1587		}
1588		else w->shell.client_specified &= ~_XtShellPositionValid;
1589		if (XtIsWMShell(wid) && !wmshell->wm.wait_for_wm) {
1590		    /* Consider trusting the wm again */
1591		    register struct _OldXSizeHints *hintp
1592			= &wmshell->wm.size_hints;
1593#define EQ(x) (hintp->x == w->core.x)
1594		    if (EQ(x) && EQ(y) && EQ(width) && EQ(height)) {
1595			wmshell->wm.wait_for_wm = TRUE;
1596		    }
1597#undef EQ
1598		}
1599		break;
1600
1601	      case ReparentNotify:
1602		if (event->xreparent.window == XtWindow(w)) {
1603		   if (event->xreparent.parent !=
1604		       RootWindowOfScreen(XtScreen(w)))
1605		       w->shell.client_specified &=
1606			   ~(_XtShellNotReparented | _XtShellPositionValid);
1607		   else {
1608		       w->core.x = event->xreparent.x;
1609		       w->core.y = event->xreparent.y;
1610		       w->shell.client_specified |=
1611			   (_XtShellNotReparented | _XtShellPositionValid);
1612		   }
1613	        }
1614		return;
1615
1616              case MapNotify:
1617                if (XtIsTopLevelShell(wid)) {
1618                    ((TopLevelShellWidget)wid)->topLevel.iconic = FALSE;
1619                }
1620                return;
1621
1622	      case UnmapNotify:
1623		{
1624		    XtPerDisplayInput	pdi;
1625		    XtDevice		device;
1626		    Widget		p;
1627
1628                    if (XtIsTopLevelShell(wid))
1629                        ((TopLevelShellWidget)wid)->topLevel.iconic = TRUE;
1630
1631		    pdi = _XtGetPerDisplayInput(event->xunmap.display);
1632
1633		    device = &pdi->pointer;
1634		    if (device->grabType == XtPassiveServerGrab) {
1635			p = device->grab.widget;
1636			while (p && !(XtIsShell(p)))
1637			    p = p->core.parent;
1638			if (p == wid)
1639			    device->grabType = XtNoServerGrab;
1640		    }
1641
1642		    device = &pdi->keyboard;
1643		    if (IsEitherPassiveGrab(device->grabType)) {
1644			p = device->grab.widget;
1645			while (p && !(XtIsShell(p)))
1646			    p = p->core.parent;
1647			if (p == wid) {
1648			    device->grabType = XtNoServerGrab;
1649			    pdi->activatingKey = 0;
1650			}
1651		    }
1652
1653		    return;
1654		}
1655	      default:
1656		 return;
1657	}
1658	{
1659	XtWidgetProc resize;
1660
1661	LOCK_PROCESS;
1662	resize = XtClass(wid)->core_class.resize;
1663	UNLOCK_PROCESS;
1664
1665	if (sizechanged && resize) {
1666	    CALLGEOTAT(_XtGeoTrace((Widget)w,
1667			   "Shell \"%s\" is being resized to %d %d.\n",
1668			   XtName(wid), wid->core.width, wid->core.height ));
1669	    (*resize)(wid);
1670	 }
1671	}
1672}
1673
1674static void Destroy(
1675	Widget wid)
1676{
1677	if (XtIsRealized(wid))
1678	    XDestroyWindow( XtDisplay(wid), XtWindow(wid) );
1679}
1680
1681static void WMDestroy(
1682	Widget wid)
1683{
1684	WMShellWidget w = (WMShellWidget) wid;
1685
1686	XtFree((char *) w->wm.title);
1687	XtFree((char *) w->wm.window_role);
1688}
1689
1690static void TopLevelDestroy(
1691	Widget wid)
1692{
1693	TopLevelShellWidget w = (TopLevelShellWidget) wid;
1694
1695	XtFree((char *) w->topLevel.icon_name);
1696}
1697
1698static void ApplicationDestroy(
1699    Widget wid)
1700{
1701    ApplicationShellWidget w = (ApplicationShellWidget) wid;
1702    if (w->application.argc > 0)
1703	FreeStringArray(w->application.argv);
1704}
1705
1706static void SessionDestroy(
1707    Widget wid)
1708{
1709#ifndef XT_NO_SM
1710    SessionShellWidget w = (SessionShellWidget) wid;
1711
1712    StopManagingSession(w, w->session.connection);
1713    XtFree(w->session.session_id);
1714    FreeStringArray(w->session.restart_command);
1715    FreeStringArray(w->session.clone_command);
1716    FreeStringArray(w->session.discard_command);
1717    FreeStringArray(w->session.resign_command);
1718    FreeStringArray(w->session.shutdown_command);
1719    FreeStringArray(w->session.environment);
1720    XtFree(w->session.current_dir);
1721    XtFree(w->session.program_path);
1722#endif /* !XT_NO_SM */
1723}
1724
1725/*
1726 * If the Shell has a width and a height which are zero, and as such
1727 * suspect, and it has not yet been realized then it will grow to
1728 * match the child before parsing the geometry resource.
1729 *
1730 */
1731static void GetGeometry(
1732    Widget W, Widget child)
1733{
1734    register ShellWidget w = (ShellWidget)W;
1735    Boolean is_wmshell = XtIsWMShell(W);
1736    int x, y, width, height, win_gravity = -1, flag;
1737    XSizeHints hints;
1738
1739    if (child != NULL) {
1740	/* we default to our child's size */
1741	if (is_wmshell && (w->core.width == 0 || w->core.height == 0))
1742	    ((WMShellWidget)W)->wm.size_hints.flags |= PSize;
1743	if (w->core.width == 0)	    w->core.width = child->core.width;
1744	if (w->core.height == 0)    w->core.height = child->core.height;
1745    }
1746    if(w->shell.geometry != NULL) {
1747	char def_geom[64];
1748	x = w->core.x;
1749	y = w->core.y;
1750	width = w->core.width;
1751	height = w->core.height;
1752	if (is_wmshell) {
1753	    WMShellPart* wm = &((WMShellWidget)w)->wm;
1754	    EvaluateSizeHints((WMShellWidget)w);
1755	    (void) memmove((char*)&hints, (char*)&wm->size_hints,
1756			   sizeof(struct _OldXSizeHints));
1757	    hints.win_gravity = wm->win_gravity;
1758	    if (wm->size_hints.flags & PBaseSize) {
1759		width -= wm->base_width;
1760		height -= wm->base_height;
1761		hints.base_width = wm->base_width;
1762		hints.base_height = wm->base_height;
1763	    }
1764	    else if (wm->size_hints.flags & PMinSize) {
1765		width -= wm->size_hints.min_width;
1766		height -= wm->size_hints.min_height;
1767	    }
1768	    if (wm->size_hints.flags & PResizeInc) {
1769		width /= wm->size_hints.width_inc;
1770		height /= wm->size_hints.height_inc;
1771	    }
1772	}
1773	else hints.flags = 0;
1774
1775	sprintf( def_geom, "%dx%d+%d+%d", width, height, x, y );
1776	flag = XWMGeometry( XtDisplay(W),
1777			    XScreenNumberOfScreen(XtScreen(W)),
1778			    w->shell.geometry, def_geom,
1779			    (unsigned int)w->core.border_width,
1780			    &hints, &x, &y, &width, &height,
1781			    &win_gravity
1782			   );
1783	if (flag) {
1784	    if (flag & XValue) w->core.x = (Position)x;
1785	    if (flag & YValue) w->core.y = (Position)y;
1786	    if (flag & WidthValue) w->core.width = (Dimension)width;
1787	    if (flag & HeightValue) w->core.height = (Dimension)height;
1788	}
1789	else {
1790	    String params[2];
1791	    Cardinal num_params = 2;
1792	    params[0] = XtName(W);
1793	    params[1] = w->shell.geometry;
1794	    XtAppWarningMsg(XtWidgetToApplicationContext(W),
1795       "badGeometry", "shellRealize", XtCXtToolkitError,
1796       "Shell widget \"%s\" has an invalid geometry specification: \"%s\"",
1797			    params, &num_params);
1798	}
1799    }
1800    else
1801	flag = 0;
1802
1803    if (is_wmshell) {
1804	WMShellWidget wmshell = (WMShellWidget) w;
1805	if (wmshell->wm.win_gravity == XtUnspecifiedShellInt) {
1806	    if (win_gravity != -1)
1807		wmshell->wm.win_gravity = win_gravity;
1808	    else
1809		wmshell->wm.win_gravity = NorthWestGravity;
1810	}
1811	wmshell->wm.size_hints.flags |= PWinGravity;
1812	if ((flag & (XValue|YValue)) == (XValue|YValue))
1813	    wmshell->wm.size_hints.flags |= USPosition;
1814	if ((flag & (WidthValue|HeightValue)) == (WidthValue|HeightValue))
1815	    wmshell->wm.size_hints.flags |= USSize;
1816    }
1817    w->shell.client_specified |= _XtShellGeometryParsed;
1818}
1819
1820
1821static void ChangeManaged(Widget wid)
1822{
1823    ShellWidget w = (ShellWidget) wid;
1824    Widget child = NULL;
1825    Cardinal i;
1826
1827    for (i = 0; i < w->composite.num_children; i++) {
1828	if (XtIsManaged(w->composite.children[i])) {
1829	    child = w->composite.children[i];
1830	    break;		/* there can only be one of them! */
1831	}
1832    }
1833
1834    if (!XtIsRealized (wid))	/* then we're about to be realized... */
1835	GetGeometry(wid, child);
1836
1837    if (child != NULL)
1838	XtConfigureWidget (child, (Position)0, (Position)0,
1839			   w->core.width, w->core.height, (Dimension)0 );
1840}
1841
1842/*
1843 * This is gross, I can't wait to see if the change happened so I will ask
1844 * the window manager to change my size and do the appropriate X work.
1845 * I will then tell the requester that he can.  Care must be taken because
1846 * it is possible that some time in the future the request will be
1847 * asynchronusly denied and the window reverted to it's old size/shape.
1848 */
1849
1850/*ARGSUSED*/
1851static XtGeometryResult GeometryManager(
1852	Widget wid,
1853	XtWidgetGeometry *request,
1854	XtWidgetGeometry *reply)
1855{
1856	ShellWidget shell = (ShellWidget)(wid->core.parent);
1857	XtWidgetGeometry my_request;
1858
1859	if(shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid))
1860		return(XtGeometryNo);
1861
1862	if (request->request_mode & (CWX | CWY))
1863	    return(XtGeometryNo);
1864
1865	my_request.request_mode = (request->request_mode & XtCWQueryOnly);
1866	if (request->request_mode & CWWidth) {
1867	    my_request.width = request->width;
1868	    my_request.request_mode |= CWWidth;
1869	}
1870	if (request->request_mode & CWHeight) {
1871	    my_request.height = request->height;
1872	    my_request.request_mode |= CWHeight;
1873	}
1874	if (request->request_mode & CWBorderWidth) {
1875	    my_request.border_width = request->border_width;
1876	    my_request.request_mode |= CWBorderWidth;
1877	}
1878	if (XtMakeGeometryRequest((Widget)shell, &my_request, NULL)
1879		== XtGeometryYes) {
1880	    /* assert: if (request->request_mode & CWWidth) then
1881	     * 		  shell->core.width == request->width
1882	     * assert: if (request->request_mode & CWHeight) then
1883	     * 		  shell->core.height == request->height
1884	     *
1885	     * so, whatever the WM sized us to (if the Shell requested
1886	     * only one of the two) is now the correct child size
1887	     */
1888
1889	    if (!(request->request_mode & XtCWQueryOnly)) {
1890		wid->core.width = shell->core.width;
1891		wid->core.height = shell->core.height;
1892		if (request->request_mode & CWBorderWidth) {
1893		    wid->core.x = wid->core.y = -request->border_width;
1894		}
1895	    }
1896	    return XtGeometryYes;
1897	} else return XtGeometryNo;
1898}
1899
1900typedef struct {
1901	Widget  w;
1902	unsigned long request_num;
1903	Boolean done;
1904} QueryStruct;
1905
1906static Bool isMine(
1907	Display *dpy,
1908	register XEvent  *event,
1909	char *arg)
1910{
1911	QueryStruct *q = (QueryStruct *) arg;
1912	register Widget w = q->w;
1913
1914	if ( (dpy != XtDisplay(w)) || (event->xany.window != XtWindow(w)) ) {
1915	    return FALSE;
1916	}
1917	if (event->xany.serial >= q->request_num) {
1918	    if (event->type == ConfigureNotify) {
1919		q->done = TRUE;
1920		return TRUE;
1921	    }
1922	}
1923	else if (event->type == ConfigureNotify)
1924	    return TRUE;	/* flush old events */
1925	if (event->type == ReparentNotify
1926		 && event->xreparent.window == XtWindow(w)) {
1927	    /* we might get ahead of this event, so just in case someone
1928	     * asks for coordinates before this event is dispatched...
1929	     */
1930	    register ShellWidget s = (ShellWidget)w;
1931	    if (event->xreparent.parent != RootWindowOfScreen(XtScreen(w)))
1932		s->shell.client_specified &= ~_XtShellNotReparented;
1933	    else
1934		s->shell.client_specified |= _XtShellNotReparented;
1935	}
1936	return FALSE;
1937}
1938
1939static Boolean _wait_for_response(
1940	ShellWidget	w,
1941	XEvent		*event,
1942        unsigned long	request_num)
1943{
1944	XtAppContext app = XtWidgetToApplicationContext((Widget) w);
1945	QueryStruct q;
1946	unsigned long timeout;
1947
1948	if (XtIsWMShell((Widget)w))
1949	    timeout = ((WMShellWidget)w)->wm.wm_timeout;
1950	else
1951	    timeout = DEFAULT_WM_TIMEOUT;
1952
1953	XFlush(XtDisplay(w));
1954	q.w = (Widget) w;
1955	q.request_num = request_num;
1956	q.done = FALSE;
1957
1958	/*
1959	 * look for match event and discard all prior configures
1960	 */
1961	while (XCheckIfEvent(XtDisplay(w),event,isMine,(char*)&q)) {
1962	    if (q.done) return TRUE;
1963	}
1964
1965	while (timeout > 0) {
1966	    if (_XtWaitForSomething (app,
1967				     FALSE, TRUE, TRUE, TRUE,
1968				     TRUE,
1969#ifdef XTHREADS
1970				     FALSE,
1971#endif
1972				     &timeout) != -1) {
1973		while (XCheckIfEvent(XtDisplay(w),event,isMine,(char*)&q)) {
1974		    if (q.done) return TRUE;
1975		}
1976	    }
1977	}
1978	return FALSE;
1979}
1980
1981/*ARGSUSED*/
1982static XtGeometryResult RootGeometryManager(
1983    Widget gw,
1984    XtWidgetGeometry *request, XtWidgetGeometry *reply)
1985{
1986    register ShellWidget w = (ShellWidget)gw;
1987    XWindowChanges values;
1988    unsigned int mask = request->request_mode;
1989    XEvent event;
1990    Boolean wm;
1991    register struct _OldXSizeHints *hintp = NULL;
1992    int oldx, oldy, oldwidth, oldheight, oldborder_width;
1993    unsigned long request_num;
1994
1995    CALLGEOTAT(_XtGeoTab(1));
1996
1997    if (XtIsWMShell(gw)) {
1998	wm = True;
1999	hintp = &((WMShellWidget)w)->wm.size_hints;
2000	/* for draft-ICCCM wm's, need to make sure hints reflect
2001	   (current) reality so client can move and size separately. */
2002  	hintp->x = w->core.x;
2003  	hintp->y = w->core.y;
2004  	hintp->width = w->core.width;
2005   	hintp->height = w->core.height;
2006    } else
2007	wm = False;
2008
2009    oldx = w->core.x;
2010    oldy = w->core.y;
2011    oldwidth = w->core.width;
2012    oldheight = w->core.height;
2013    oldborder_width = w->core.border_width;
2014
2015#define PutBackGeometry() \
2016	{ w->core.x = oldx; \
2017	  w->core.y = oldy; \
2018	  w->core.width = oldwidth; \
2019	  w->core.height = oldheight; \
2020	  w->core.border_width = oldborder_width; }
2021
2022    if (mask & CWX) {
2023	    if (w->core.x == request->x) mask &= ~CWX;
2024	    else {
2025		w->core.x = values.x = request->x;
2026		if (wm) {
2027		    hintp->flags &= ~USPosition;
2028		    hintp->flags |= PPosition;
2029		    hintp->x = values.x;
2030		}
2031	    }
2032    }
2033    if (mask & CWY) {
2034	    if (w->core.y == request->y) mask &= ~CWY;
2035	    else {
2036		w->core.y = values.y = request->y;
2037		if (wm) {
2038		    hintp->flags &= ~USPosition;
2039		    hintp->flags |= PPosition;
2040		    hintp->y = values.y;
2041		}
2042	    }
2043    }
2044    if (mask & CWBorderWidth) {
2045	    if (w->core.border_width == request->border_width) {
2046		    mask &= ~CWBorderWidth;
2047	    } else
2048		w->core.border_width =
2049		    values.border_width =
2050			request->border_width;
2051    }
2052    if (mask & CWWidth) {
2053	    if (w->core.width == request->width) mask &= ~CWWidth;
2054	    else {
2055		w->core.width = values.width = request->width;
2056		if (wm) {
2057		    hintp->flags &= ~USSize;
2058		    hintp->flags |= PSize;
2059		    hintp->width = values.width;
2060		}
2061	    }
2062    }
2063    if (mask & CWHeight) {
2064	    if (w->core.height == request->height) mask &= ~CWHeight;
2065	    else {
2066		w->core.height = values.height = request->height;
2067		if (wm) {
2068		    hintp->flags &= ~USSize;
2069		    hintp->flags |= PSize;
2070		    hintp->height = values.height;
2071		}
2072	    }
2073    }
2074    if (mask & CWStackMode) {
2075	values.stack_mode = request->stack_mode;
2076	if (mask & CWSibling)
2077	    values.sibling = XtWindow(request->sibling);
2078    }
2079
2080    if (!XtIsRealized((Widget)w)) {
2081	CALLGEOTAT(_XtGeoTrace((Widget)w,
2082		      "Shell \"%s\" is not realized, return XtGeometryYes.\n",
2083		       XtName((Widget)w)));
2084    	CALLGEOTAT(_XtGeoTab(-1));
2085	return XtGeometryYes;
2086    }
2087
2088    request_num = NextRequest(XtDisplay(w));
2089
2090    CALLGEOTAT(_XtGeoTrace((Widget)w,"XConfiguring the Shell X window :\n"));
2091    CALLGEOTAT(_XtGeoTab(1));
2092#ifdef XT_GEO_TATTLER
2093    if (mask & CWX) { CALLGEOTAT(_XtGeoTrace((Widget)w,"x = %d\n",values.x));}
2094    if (mask & CWY) { CALLGEOTAT(_XtGeoTrace((Widget)w,"y = %d\n",values.y));}
2095    if (mask & CWWidth) { CALLGEOTAT(_XtGeoTrace((Widget)w,
2096					       "width = %d\n",values.width));}
2097    if (mask & CWHeight) { CALLGEOTAT(_XtGeoTrace((Widget)w,
2098					    "height = %d\n",values.height));}
2099    if (mask & CWBorderWidth) { CALLGEOTAT(_XtGeoTrace((Widget)w,
2100				  "border_width = %d\n",values.border_width));}
2101#endif
2102    CALLGEOTAT(_XtGeoTab(-1));
2103
2104    XConfigureWindow(XtDisplay((Widget)w), XtWindow((Widget)w), mask,&values);
2105
2106    if (wm && !w->shell.override_redirect
2107	&& mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)) {
2108	_SetWMSizeHints((WMShellWidget)w);
2109    }
2110
2111    if (w->shell.override_redirect) {
2112	CALLGEOTAT(_XtGeoTrace((Widget)w,"Shell \"%s\" is override redirect, return XtGeometryYes.\n", XtName((Widget)w)));
2113    	CALLGEOTAT(_XtGeoTab(-1));
2114	return XtGeometryYes;
2115    }
2116
2117
2118    /* If no non-stacking bits are set, there's no way to tell whether
2119       or not this worked, so assume it did */
2120
2121    if (!(mask & ~(CWStackMode | CWSibling))) return XtGeometryYes;
2122
2123    if (wm && ((WMShellWidget)w)->wm.wait_for_wm == FALSE) {
2124	    /* the window manager is sick
2125	     * so I will do the work and
2126	     * say no so if a new WM starts up,
2127	     * or the current one recovers
2128	     * my size requests will be visible
2129	     */
2130	CALLGEOTAT(_XtGeoTrace((Widget)w,"Shell \"%s\" has wait_for_wm == FALSE, return XtGeometryNo.\n",
2131		       XtName((Widget)w)));
2132    	CALLGEOTAT(_XtGeoTab(-1));
2133
2134	PutBackGeometry();
2135	return XtGeometryNo;
2136    }
2137
2138    if (_wait_for_response(w, &event, request_num)) {
2139	/* got an event */
2140	if (event.type == ConfigureNotify) {
2141
2142#define NEQ(x, msk) ((mask & msk) && (values.x != event.xconfigure.x))
2143	    if (NEQ(x, CWX) ||
2144		NEQ(y, CWY) ||
2145		NEQ(width, CWWidth) ||
2146		NEQ(height, CWHeight) ||
2147		NEQ(border_width, CWBorderWidth)) {
2148#ifdef XT_GEO_TATTLER
2149		if (NEQ(x, CWX)) {
2150		    CALLGEOTAT(_XtGeoTrace((Widget)w,
2151					   "received Configure X %d\n",
2152					   event.xconfigure.x));
2153		}
2154		if (NEQ(y, CWY)) {
2155		    CALLGEOTAT(_XtGeoTrace((Widget)w,
2156					   "received Configure Y %d\n",
2157					   event.xconfigure.y));
2158		}
2159		if (NEQ(width, CWWidth)) {
2160		    CALLGEOTAT(_XtGeoTrace((Widget)w,
2161					   "received Configure Width %d\n",
2162					   event.xconfigure.width));
2163		}
2164		if (NEQ(height, CWHeight)) {
2165		    CALLGEOTAT(_XtGeoTrace((Widget)w,
2166					   "received Configure Height %d\n",
2167					   event.xconfigure.height));
2168		}
2169		if (NEQ(border_width, CWBorderWidth)) {
2170		    CALLGEOTAT(_XtGeoTrace((Widget)w,
2171				        "received Configure BorderWidth %d\n",
2172					event.xconfigure.border_width));
2173		}
2174#endif
2175#undef NEQ
2176		XPutBackEvent(XtDisplay(w), &event);
2177		PutBackGeometry();
2178		/*
2179		 * We just potentially re-ordered the event queue
2180		 * w.r.t. ConfigureNotifies with some trepidation.
2181		 * But this is probably a Good Thing because we
2182		 * will know the new true state of the world sooner
2183		 * this way.
2184		 */
2185		CALLGEOTAT(_XtGeoTrace((Widget)w,
2186			   "ConfigureNotify failed, return XtGeometryNo.\n"));
2187		CALLGEOTAT(_XtGeoTab(-1));
2188
2189		return XtGeometryNo;
2190	    }
2191	    else {
2192		w->core.width = event.xconfigure.width;
2193		w->core.height = event.xconfigure.height;
2194		w->core.border_width = event.xconfigure.border_width;
2195		if (event.xany.send_event || /* ICCCM compliant synth */
2196		    w->shell.client_specified & _XtShellNotReparented) {
2197
2198		    w->core.x = event.xconfigure.x;
2199		    w->core.y = event.xconfigure.y;
2200		    w->shell.client_specified |= _XtShellPositionValid;
2201		}
2202		else w->shell.client_specified &= ~_XtShellPositionValid;
2203		CALLGEOTAT(_XtGeoTrace((Widget)w,
2204			 "ConfigureNotify succeed, return XtGeometryYes.\n"));
2205		CALLGEOTAT(_XtGeoTab(-1));
2206		return XtGeometryYes;
2207	    }
2208	} else if (!wm) {
2209	    PutBackGeometry();
2210	    CALLGEOTAT(_XtGeoTrace((Widget)w,
2211				   "Not wm, return XtGeometryNo.\n"));
2212	    CALLGEOTAT(_XtGeoTab(-1));
2213	    return XtGeometryNo;
2214	} else XtAppWarningMsg(XtWidgetToApplicationContext((Widget)w),
2215			       "internalError", "shell", XtCXtToolkitError,
2216			       "Shell's window manager interaction is broken",
2217			       (String *)NULL, (Cardinal *)NULL);
2218    } else if (wm) { /* no event */
2219	((WMShellWidget)w)->wm.wait_for_wm = FALSE; /* timed out; must be broken */
2220    }
2221    PutBackGeometry();
2222#undef PutBackGeometry
2223    CALLGEOTAT(_XtGeoTrace((Widget)w,
2224			   "Timeout passed?, return XtGeometryNo.\n"));
2225    CALLGEOTAT(_XtGeoTab(-1));
2226    return XtGeometryNo;
2227		}
2228
2229/* ARGSUSED */
2230static Boolean SetValues(
2231	Widget old, Widget ref, Widget new,
2232	ArgList args,
2233	Cardinal *num_args)
2234{
2235	ShellWidget nw = (ShellWidget) new;
2236	ShellWidget ow = (ShellWidget) old;
2237	Mask mask = 0;
2238	XSetWindowAttributes attr;
2239
2240	if (!XtIsRealized(new))
2241	    return False;
2242
2243	if (ow->shell.save_under != nw->shell.save_under) {
2244	    mask = CWSaveUnder;
2245	    attr.save_under = nw->shell.save_under;
2246	}
2247
2248	if (ow->shell.override_redirect != nw->shell.override_redirect) {
2249	    mask |= CWOverrideRedirect;
2250	    attr.override_redirect = nw->shell.override_redirect;
2251	}
2252
2253	if (mask) {
2254	    XChangeWindowAttributes(XtDisplay(new),XtWindow(new), mask, &attr);
2255	    if ((mask & CWOverrideRedirect) && !nw->shell.override_redirect)
2256		_popup_set_prop(nw);
2257	}
2258
2259	if (! (ow->shell.client_specified & _XtShellPositionValid)) {
2260	    Cardinal n;
2261
2262	    for (n = *num_args; n; n--, args++) {
2263		if (strcmp(XtNx, args->name) == 0) {
2264		    _XtShellGetCoordinates((Widget)ow, &ow->core.x,
2265							&ow->core.y);
2266		} else if (strcmp(XtNy, args->name) == 0) {
2267		    _XtShellGetCoordinates((Widget)ow, &ow->core.x,
2268							&ow->core.y);
2269		}
2270	    }
2271	}
2272	return FALSE;
2273}
2274
2275/* ARGSUSED */
2276static Boolean WMSetValues(
2277	Widget old, Widget ref, Widget new,
2278	ArgList args,		/* unused */
2279	Cardinal *num_args)	/* unused */
2280{
2281	WMShellWidget nwmshell = (WMShellWidget) new;
2282	WMShellWidget owmshell = (WMShellWidget) old;
2283	Boolean set_prop
2284	    = XtIsRealized(new) && !nwmshell->shell.override_redirect;
2285	Boolean title_changed;
2286
2287	EvaluateSizeHints(nwmshell);
2288
2289#define NEQ(f) (nwmshell->wm.size_hints.f != owmshell->wm.size_hints.f)
2290
2291	if (set_prop
2292	    && (NEQ(flags) || NEQ(min_width) || NEQ(min_height)
2293		|| NEQ(max_width) || NEQ(max_height)
2294		|| NEQ(width_inc) || NEQ(height_inc)
2295		|| NEQ(min_aspect.x) || NEQ(min_aspect.y)
2296		|| NEQ(max_aspect.x) || NEQ(max_aspect.y)
2297#undef NEQ
2298#define NEQ(f) (nwmshell->wm.f != owmshell->wm.f)
2299
2300		|| NEQ(base_width) || NEQ(base_height) || NEQ(win_gravity))) {
2301	    _SetWMSizeHints(nwmshell);
2302	}
2303#undef NEQ
2304
2305	if (nwmshell->wm.title != owmshell->wm.title) {
2306	    XtFree(owmshell->wm.title);
2307	    if (! nwmshell->wm.title) nwmshell->wm.title = "";
2308	    nwmshell->wm.title = XtNewString(nwmshell->wm.title);
2309	    title_changed = True;
2310	} else
2311	    title_changed = False;
2312
2313	if (set_prop
2314	    && (title_changed ||
2315		nwmshell->wm.title_encoding != owmshell->wm.title_encoding)) {
2316
2317	    XTextProperty title;
2318	    Boolean copied = False;
2319
2320            if (nwmshell->wm.title_encoding == None &&
2321		XmbTextListToTextProperty(XtDisplay(new),
2322					  (char**)&nwmshell->wm.title,
2323					  1, XStdICCTextStyle,
2324					  &title) >= Success) {
2325		copied = True;
2326	    } else {
2327		title.value = (unsigned char*)nwmshell->wm.title;
2328		title.encoding = nwmshell->wm.title_encoding ?
2329		    nwmshell->wm.title_encoding : XA_STRING;
2330		title.format = 8;
2331		title.nitems = strlen(nwmshell->wm.title);
2332	    }
2333	    XSetWMName(XtDisplay(new), XtWindow(new), &title);
2334	    if (copied)
2335		XFree((XPointer)title.value);
2336	}
2337
2338	EvaluateWMHints(nwmshell);
2339
2340#define NEQ(f)	(nwmshell->wm.wm_hints.f != owmshell->wm.wm_hints.f)
2341
2342	if (set_prop
2343	    && (NEQ(flags) || NEQ(input) || NEQ(initial_state)
2344		|| NEQ(icon_x) || NEQ(icon_y)
2345		|| NEQ(icon_pixmap) || NEQ(icon_mask) || NEQ(icon_window)
2346		|| NEQ(window_group))) {
2347
2348	    XSetWMHints(XtDisplay(new), XtWindow(new), &nwmshell->wm.wm_hints);
2349	}
2350#undef NEQ
2351
2352 	if (XtIsRealized(new) &&
2353	    nwmshell->wm.transient != owmshell->wm.transient) {
2354 	    if (nwmshell->wm.transient) {
2355		if (!XtIsTransientShell(new) &&
2356		    !nwmshell->shell.override_redirect &&
2357		    nwmshell->wm.wm_hints.window_group !=
2358		       XtUnspecifiedWindowGroup)
2359		    XSetTransientForHint(XtDisplay(new), XtWindow(new),
2360					 nwmshell->wm.wm_hints.window_group);
2361	    }
2362 	    else XDeleteProperty(XtDisplay(new), XtWindow(new),
2363 				 XA_WM_TRANSIENT_FOR);
2364 	}
2365
2366	if (nwmshell->wm.client_leader != owmshell->wm.client_leader
2367	    && XtWindow(new) && !nwmshell->shell.override_redirect) {
2368	    Widget leader = GetClientLeader(new);
2369	    if (XtWindow(leader))
2370		XChangeProperty(XtDisplay(new), XtWindow(new),
2371				XInternAtom(XtDisplay(new),
2372					    "WM_CLIENT_LEADER", False),
2373				XA_WINDOW, 32, PropModeReplace,
2374				(unsigned char *) &(leader->core.window), 1);
2375	}
2376
2377	if (nwmshell->wm.window_role != owmshell->wm.window_role) {
2378	    XtFree(owmshell->wm.window_role);
2379	    if (set_prop && nwmshell->wm.window_role) {
2380		XChangeProperty(XtDisplay(new), XtWindow(new),
2381				XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE",
2382					    False),
2383				XA_STRING, 8, PropModeReplace,
2384				(unsigned char *)nwmshell->wm.window_role,
2385				strlen(nwmshell->wm.window_role));
2386	    } else if (XtIsRealized(new) && ! nwmshell->wm.window_role) {
2387		XDeleteProperty(XtDisplay(new), XtWindow(new),
2388				XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE",
2389					    False));
2390	    }
2391	}
2392
2393	return FALSE;
2394}
2395
2396/*ARGSUSED*/
2397static Boolean TransientSetValues(
2398     Widget oldW, Widget refW, Widget newW,
2399     ArgList args,		/* unused */
2400     Cardinal *num_args)	/* unused */
2401{
2402    TransientShellWidget old = (TransientShellWidget)oldW;
2403    TransientShellWidget new = (TransientShellWidget)newW;
2404
2405    if (XtIsRealized(newW)
2406	&& ((new->wm.transient && !old->wm.transient)
2407	    || ((new->transient.transient_for != old->transient.transient_for)
2408		|| (new->transient.transient_for == NULL
2409		    && (new->wm.wm_hints.window_group
2410			!= old->wm.wm_hints.window_group))))) {
2411
2412	_SetTransientForHint(new, True);
2413    }
2414    return False;
2415}
2416
2417
2418/* ARGSUSED */
2419static Boolean TopLevelSetValues(
2420     Widget oldW, Widget refW, Widget newW,
2421     ArgList args,		/* unused */
2422     Cardinal *num_args)	/* unused */
2423{
2424    TopLevelShellWidget old = (TopLevelShellWidget)oldW;
2425    TopLevelShellWidget new = (TopLevelShellWidget)newW;
2426    Boolean name_changed;
2427
2428    if (old->topLevel.icon_name != new->topLevel.icon_name) {
2429	XtFree((XtPointer)old->topLevel.icon_name);
2430	if (! new->topLevel.icon_name) new->topLevel.icon_name = "";
2431	new->topLevel.icon_name = XtNewString(new->topLevel.icon_name);
2432	name_changed = True;
2433    } else
2434	name_changed = False;
2435
2436    if (XtIsRealized(newW)) {
2437	if (new->topLevel.iconic != old->topLevel.iconic) {
2438	    if (new->topLevel.iconic)
2439		XIconifyWindow(XtDisplay(newW),
2440			       XtWindow(newW),
2441			       XScreenNumberOfScreen(XtScreen(newW))
2442			       );
2443	    else {
2444		Boolean map = new->shell.popped_up;
2445		XtPopup(newW, XtGrabNone);
2446		if (map) XMapWindow(XtDisplay(newW), XtWindow(newW));
2447	    }
2448	}
2449
2450	if (!new->shell.override_redirect &&
2451	    (name_changed ||
2452	     (old->topLevel.icon_name_encoding
2453	      != new->topLevel.icon_name_encoding))) {
2454
2455	    XTextProperty icon_name;
2456	    Boolean copied = False;
2457
2458            if (new->topLevel.icon_name_encoding == None &&
2459		XmbTextListToTextProperty(XtDisplay(newW),
2460					  (char**) &new->topLevel.icon_name,
2461					  1, XStdICCTextStyle,
2462					  &icon_name) >= Success) {
2463		copied = True;
2464	    } else {
2465		icon_name.value = (unsigned char *)new->topLevel.icon_name;
2466		icon_name.encoding = new->topLevel.icon_name_encoding ?
2467		    new->topLevel.icon_name_encoding : XA_STRING;
2468		icon_name.format = 8;
2469		icon_name.nitems = strlen((char *)icon_name.value);
2470	    }
2471	    XSetWMIconName(XtDisplay(newW), XtWindow(newW), &icon_name);
2472	    if (copied)
2473		XFree((XPointer)icon_name.value);
2474	}
2475    }
2476    return False;
2477}
2478
2479static String * NewArgv(
2480    int count,
2481    String *str)  /* do not assume it's terminated by a NULL element */
2482{
2483    Cardinal nbytes = 0;
2484    Cardinal num = 0;
2485    String *newarray, *new;
2486    String *strarray = str;
2487    String sptr;
2488
2489    if (count <= 0 || !str) return NULL;
2490
2491    for (num = count; num--; str++) {
2492	nbytes += strlen(*str);
2493	nbytes++;
2494    }
2495    num = (count+1) * sizeof(String);
2496    new = newarray = (String *) __XtMalloc(num + nbytes);
2497    sptr = ((char *) new) + num;
2498
2499    for (str = strarray; count--; str++) {
2500	*new = sptr;
2501	strcpy(*new, *str);
2502	new++;
2503	sptr = strchr(sptr, '\0');
2504	sptr++;
2505    }
2506    *new = NULL;
2507    return newarray;
2508}
2509
2510
2511/*ARGSUSED*/
2512static Boolean ApplicationSetValues(
2513    Widget current, Widget request, Widget new,
2514    ArgList args,
2515    Cardinal *num_args)
2516{
2517    ApplicationShellWidget nw = (ApplicationShellWidget) new;
2518    ApplicationShellWidget cw = (ApplicationShellWidget) current;
2519
2520    if (cw->application.argc != nw->application.argc ||
2521	cw->application.argv != nw->application.argv) {
2522
2523	if (nw->application.argc > 0)
2524	    nw->application.argv = NewArgv(nw->application.argc,
2525					   nw->application.argv);
2526	if (cw->application.argc > 0)
2527	    FreeStringArray(cw->application.argv);
2528
2529	if (XtIsRealized(new) && !nw->shell.override_redirect) {
2530	    if (nw->application.argc >= 0 && nw->application.argv)
2531		XSetCommand(XtDisplay(new), XtWindow(new),
2532			    nw->application.argv, nw->application.argc);
2533	    else
2534		XDeleteProperty(XtDisplay(new), XtWindow(new), XA_WM_COMMAND);
2535	}
2536    }
2537    return False;
2538}
2539
2540/*ARGSUSED*/
2541static Boolean SessionSetValues(
2542    Widget current, Widget request, Widget new,
2543    ArgList args,
2544    Cardinal *num_args)
2545{
2546#ifndef XT_NO_SM
2547    SessionShellWidget nw = (SessionShellWidget) new;
2548    SessionShellWidget cw = (SessionShellWidget) current;
2549    unsigned long set_mask = 0UL;
2550    unsigned long unset_mask = 0UL;
2551    Boolean initialize = False;
2552
2553    if (cw->session.session_id != nw->session.session_id) {
2554	nw->session.session_id = XtNewString(nw->session.session_id);
2555	XtFree(cw->session.session_id);
2556    }
2557
2558    if (cw->session.clone_command != nw->session.clone_command) {
2559	if (nw->session.clone_command) {
2560	    nw->session.clone_command =
2561		NewStringArray(nw->session.clone_command);
2562	    set_mask |= XtCloneCommandMask;
2563	} else unset_mask |= XtCloneCommandMask;
2564	FreeStringArray(cw->session.clone_command);
2565    }
2566
2567    if (cw->session.current_dir != nw->session.current_dir) {
2568	if (nw->session.current_dir) {
2569	    nw->session.current_dir =
2570		XtNewString(nw->session.current_dir);
2571	    set_mask |= XtCurrentDirectoryMask;
2572	} else unset_mask |= XtCurrentDirectoryMask;
2573	XtFree((char *) cw->session.current_dir);
2574    }
2575
2576    if (cw->session.discard_command != nw->session.discard_command) {
2577	if (nw->session.discard_command) {
2578	    nw->session.discard_command =
2579		NewStringArray(nw->session.discard_command);
2580	    set_mask |=  XtDiscardCommandMask;
2581	} else unset_mask |= XtDiscardCommandMask;
2582	FreeStringArray(cw->session.discard_command);
2583    }
2584
2585    if (cw->session.environment != nw->session.environment) {
2586	if (nw->session.environment) {
2587	    nw->session.environment =
2588		NewStringArray(nw->session.environment);
2589	    set_mask |= XtEnvironmentMask;
2590	} else unset_mask |= XtEnvironmentMask;
2591	FreeStringArray(cw->session.environment);
2592    }
2593
2594    if (cw->session.program_path != nw->session.program_path) {
2595	if (nw->session.program_path) {
2596	    nw->session.program_path =
2597		XtNewString(nw->session.program_path);
2598	    set_mask |= XtProgramMask;
2599	} else unset_mask |= XtProgramMask;
2600	XtFree((char *) cw->session.program_path);
2601    }
2602
2603    if (cw->session.resign_command != nw->session.resign_command) {
2604	if (nw->session.resign_command) {
2605	    nw->session.resign_command =
2606		NewStringArray(nw->session.resign_command);
2607	    set_mask |= XtResignCommandMask;
2608	} else set_mask |= XtResignCommandMask;
2609	FreeStringArray(cw->session.resign_command);
2610    }
2611
2612    if (cw->session.restart_command != nw->session.restart_command) {
2613	if (nw->session.restart_command) {
2614	    nw->session.restart_command =
2615		NewStringArray(nw->session.restart_command);
2616	    set_mask |= XtRestartCommandMask;
2617	} else unset_mask |= XtRestartCommandMask;
2618	FreeStringArray(cw->session.restart_command);
2619    }
2620
2621    if (cw->session.restart_style != nw->session.restart_style)
2622	set_mask |= XtRestartStyleHintMask;
2623
2624    if (cw->session.shutdown_command != nw->session.shutdown_command) {
2625	if (nw->session.shutdown_command) {
2626	    nw->session.shutdown_command =
2627		NewStringArray(nw->session.shutdown_command);
2628	    set_mask |= XtShutdownCommandMask;
2629	} else unset_mask |= XtShutdownCommandMask;
2630	FreeStringArray(cw->session.shutdown_command);
2631    }
2632
2633    if ((!cw->session.join_session && nw->session.join_session) ||
2634	(!cw->session.connection && nw->session.connection)) {
2635	JoinSession(nw);
2636	initialize = True;
2637    }
2638
2639    if (nw->session.connection && (set_mask || unset_mask || initialize))
2640	SetSessionProperties((SessionShellWidget) new, initialize, set_mask, unset_mask);
2641
2642    if ((cw->session.join_session && !nw->session.join_session) ||
2643	(cw->session.connection && !nw->session.connection))
2644	StopManagingSession(nw, nw->session.connection);
2645#endif /* !XT_NO_SM */
2646
2647    if (cw->wm.client_leader != nw->wm.client_leader ||
2648	cw->session.session_id != nw->session.session_id) {
2649	Widget leader;
2650	if (cw->session.session_id) {
2651	    leader = GetClientLeader(current);
2652	    if (XtWindow(leader))
2653		XDeleteProperty(XtDisplay(leader), XtWindow(leader),
2654				XInternAtom(XtDisplay(leader), "SM_CLIENT_ID",
2655					    False));
2656	}
2657	if (nw->session.session_id) {
2658	    leader = GetClientLeader(new);
2659	    if (XtWindow(leader))
2660		XChangeProperty(XtDisplay(leader), XtWindow(leader),
2661				XInternAtom(XtDisplay(leader), "SM_CLIENT_ID",
2662					    False),
2663				XA_STRING, 8, PropModeReplace,
2664				(unsigned char *) nw->session.session_id,
2665				strlen(nw->session.session_id));
2666	}
2667    }
2668    return False;
2669}
2670
2671void _XtShellGetCoordinates(
2672    Widget widget,
2673    Position* x,
2674    Position* y)
2675{
2676    ShellWidget w = (ShellWidget)widget;
2677    if (XtIsRealized(widget) &&
2678	!(w->shell.client_specified & _XtShellPositionValid)) {
2679	int tmpx, tmpy;
2680	Window tmpchild;
2681	(void) XTranslateCoordinates(XtDisplay(w), XtWindow(w),
2682				     RootWindowOfScreen(XtScreen(w)),
2683				     (int) -w->core.border_width,
2684				     (int) -w->core.border_width,
2685				     &tmpx, &tmpy, &tmpchild);
2686	w->core.x = tmpx;
2687	w->core.y = tmpy;
2688	w->shell.client_specified |= _XtShellPositionValid;
2689    }
2690    *x = w->core.x;
2691    *y = w->core.y;
2692}
2693
2694static void GetValuesHook(
2695    Widget	widget,
2696    ArgList	args,
2697    Cardinal*	num_args)
2698{
2699    ShellWidget w = (ShellWidget) widget;
2700
2701    /* x and y resource values may be invalid after a shell resize */
2702    if (XtIsRealized(widget) &&
2703	!(w->shell.client_specified & _XtShellPositionValid)) {
2704	Cardinal	n;
2705	Position	x, y;
2706
2707	for (n = *num_args; n; n--, args++) {
2708	    if (strcmp(XtNx, args->name) == 0) {
2709		_XtShellGetCoordinates(widget, &x, &y);
2710		_XtCopyToArg((char *) &x, &args->value, sizeof(Position));
2711	    } else if (strcmp(XtNy, args->name) == 0) {
2712		_XtShellGetCoordinates(widget, &x, &y);
2713		_XtCopyToArg((char *) &y, &args->value, sizeof(Position));
2714	    }
2715	}
2716    }
2717}
2718
2719static void ApplicationShellInsertChild(
2720    Widget widget)
2721{
2722    if (! XtIsWidget(widget) && XtIsRectObj(widget)) {
2723	XtAppWarningMsg(XtWidgetToApplicationContext(widget),
2724	       "invalidClass", "applicationShellInsertChild", XtCXtToolkitError,
2725	       "ApplicationShell does not accept RectObj children; ignored",
2726	       (String*)NULL, (Cardinal*)NULL);
2727    }
2728    else {
2729	XtWidgetProc insert_child;
2730
2731	LOCK_PROCESS;
2732	insert_child =
2733	    ((CompositeWidgetClass)applicationShellClassRec.core_class.
2734	   superclass)->composite_class.insert_child;
2735	UNLOCK_PROCESS;
2736	(*insert_child) (widget);
2737    }
2738}
2739
2740/**************************************************************************
2741
2742  Session Protocol Participation
2743
2744 *************************************************************************/
2745
2746#define XtSessionCheckpoint	0
2747#define XtSessionInteract	1
2748
2749static void CallSaveCallbacks(SessionShellWidget );
2750static String *EditCommand(String, String *, String *);
2751static Boolean ExamineToken(XtPointer);
2752static void GetIceEvent(XtPointer, int *, XtInputId *);
2753static XtCheckpointToken GetToken(Widget, int);
2754static void XtCallCancelCallbacks(SmcConn, SmPointer);
2755static void XtCallDieCallbacks(SmcConn, SmPointer);
2756static void XtCallSaveCallbacks(SmcConn, SmPointer, int, Bool, int, Bool);
2757static void XtCallSaveCompleteCallbacks(SmcConn, SmPointer);
2758
2759#ifndef XT_NO_SM
2760static void StopManagingSession(
2761    SessionShellWidget w,
2762    SmcConn connection) /* connection to close, if any */
2763{
2764    if (connection)
2765	SmcCloseConnection(connection, 0, NULL);
2766
2767    if (w->session.input_id) {
2768	XtRemoveInput(w->session.input_id);
2769	w->session.input_id = 0;
2770    }
2771    w->session.connection = NULL;
2772}
2773
2774#define XT_MSG_LENGTH 256
2775static void JoinSession(
2776    SessionShellWidget w)
2777{
2778    IceConn ice_conn;
2779    SmcCallbacks smcb;
2780    char * sm_client_id;
2781    unsigned long mask;
2782    static char context;  /* used to guarantee the connection isn't shared */
2783
2784    smcb.save_yourself.callback = XtCallSaveCallbacks;
2785    smcb.die.callback = XtCallDieCallbacks;
2786    smcb.save_complete.callback = XtCallSaveCompleteCallbacks;
2787    smcb.shutdown_cancelled.callback = XtCallCancelCallbacks;
2788    smcb.save_yourself.client_data = smcb.die.client_data =
2789	smcb.save_complete.client_data =
2790	    smcb.shutdown_cancelled.client_data = (SmPointer) w;
2791    mask = SmcSaveYourselfProcMask | SmcDieProcMask |
2792	SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
2793
2794    if (w->session.connection) {
2795	SmcModifyCallbacks(w->session.connection, mask, &smcb);
2796	sm_client_id = SmcClientID(w->session.connection);
2797    } else if (getenv("SESSION_MANAGER")) {
2798	char error_msg[XT_MSG_LENGTH];
2799	error_msg[0] = '\0';
2800	w->session.connection =
2801	    SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor,
2802			      mask, &smcb, w->session.session_id,
2803			      &sm_client_id, XT_MSG_LENGTH, error_msg);
2804	if (error_msg[0]) {
2805	    String params[1];
2806	    Cardinal num_params = 1;
2807	    params[0] = error_msg;
2808	    XtAppWarningMsg(XtWidgetToApplicationContext((Widget) w),
2809			    "sessionManagement", "SmcOpenConnection",
2810			    XtCXtToolkitError,
2811			    "Tried to connect to session manager, %s",
2812			    params, &num_params);
2813	}
2814    }
2815
2816    if (w->session.connection) {
2817	if (w->session.session_id == NULL
2818	    || (strcmp(w->session.session_id, sm_client_id) != 0)) {
2819	    XtFree(w->session.session_id);
2820	    w->session.session_id = XtNewString(sm_client_id);
2821	}
2822	free(sm_client_id);
2823	ice_conn = SmcGetIceConnection(w->session.connection);
2824	w->session.input_id =
2825	    XtAppAddInput(XtWidgetToApplicationContext((Widget)w),
2826			  IceConnectionNumber(ice_conn),
2827			  (XtPointer) XtInputReadMask,
2828			  GetIceEvent, (XtPointer) w);
2829
2830	w->session.restart_command =
2831	    EditCommand(w->session.session_id, w->session.restart_command,
2832			w->application.argv);
2833
2834	if (! w->session.clone_command) w->session.clone_command =
2835	    EditCommand(NULL, NULL, w->session.restart_command);
2836
2837	if (! w->session.program_path)
2838	    w->session.program_path = w->session.restart_command
2839		? XtNewString(w->session.restart_command[0]) : NULL;
2840    }
2841}
2842#undef XT_MSG_LENGTH
2843
2844#endif /* !XT_NO_SM */
2845
2846static String * NewStringArray(String *str)
2847{
2848    Cardinal nbytes = 0;
2849    Cardinal num = 0;
2850    String *newarray, *new;
2851    String *strarray = str;
2852    String sptr;
2853
2854    if (!str) return NULL;
2855
2856    for (num = 0; *str; num++, str++) {
2857	nbytes += strlen(*str);
2858	nbytes++;
2859    }
2860    num = (num + 1) * sizeof(String);
2861    new = newarray = (String *) __XtMalloc(num + nbytes);
2862    sptr = ((char *) new) + num;
2863
2864    for (str = strarray; *str; str++) {
2865	*new = sptr;
2866	strcpy(*new, *str);
2867	new++;
2868	sptr = strchr(sptr, '\0');
2869	sptr++;
2870    }
2871    *new = NULL;
2872    return newarray;
2873}
2874
2875static void FreeStringArray(String *str)
2876{
2877    if (str)
2878	XtFree((char *) str);
2879}
2880
2881
2882#ifndef XT_NO_SM
2883static SmProp * CardPack(
2884    char *name,
2885    XtPointer closure)
2886{
2887    unsigned char *prop = (unsigned char *) closure;
2888    SmProp *p;
2889
2890    p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue));
2891    p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp));
2892    p->num_vals = 1;
2893    p->type = SmCARD8;
2894    p->name = name;
2895    p->vals->length = 1;
2896    p->vals->value = (SmPointer) prop;
2897    return p;
2898}
2899
2900static SmProp * ArrayPack(char *name, XtPointer closure)
2901{
2902    String prop = *(String *) closure;
2903    SmProp *p;
2904
2905    p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue));
2906    p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp));
2907    p->num_vals = 1;
2908    p->type = SmARRAY8;
2909    p->name = name;
2910    p->vals->length = strlen(prop) + 1;
2911    p->vals->value = prop;
2912    return p;
2913}
2914
2915static SmProp * ListPack(
2916    char *name,
2917    XtPointer closure)
2918{
2919    String *prop = *(String **) closure;
2920    SmProp *p;
2921    String *ptr;
2922    SmPropValue *vals;
2923    int n = 0;
2924
2925    for (ptr = prop; *ptr; ptr++)
2926	n++;
2927    p = (SmProp*) __XtMalloc(sizeof(SmProp) + (Cardinal)(n*sizeof(SmPropValue)));
2928    p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp));
2929    p->num_vals = n;
2930    p->type = SmLISTofARRAY8;
2931    p->name = name;
2932    for (ptr = prop, vals = p->vals; *ptr; ptr++, vals++) {
2933	vals->length = strlen(*ptr) + 1;
2934	vals->value = *ptr;
2935    }
2936    return p;
2937}
2938
2939static void FreePacks(
2940    SmProp **props,
2941    int num_props)
2942{
2943    while (--num_props >= 0)
2944	XtFree((char *) props[num_props]);
2945}
2946
2947typedef SmProp* (*PackProc)(char *, XtPointer);
2948
2949typedef struct PropertyRec {
2950    char *	name;
2951    int		offset;
2952    PackProc	proc;
2953} PropertyRec, *PropertyTable;
2954
2955#define Offset(x) (XtOffsetOf(SessionShellRec, x))
2956static PropertyRec propertyTable[] = {
2957  {SmCloneCommand,     Offset(session.clone_command),    ListPack},
2958  {SmCurrentDirectory, Offset(session.current_dir),      ArrayPack},
2959  {SmDiscardCommand,   Offset(session.discard_command),  ListPack},
2960  {SmEnvironment,      Offset(session.environment),      ListPack},
2961  {SmProgram,          Offset(session.program_path),     ArrayPack},
2962  {SmResignCommand,    Offset(session.resign_command),   ListPack},
2963  {SmRestartCommand,   Offset(session.restart_command),  ListPack},
2964  {SmRestartStyleHint, Offset(session.restart_style),    CardPack},
2965  {SmShutdownCommand,  Offset(session.shutdown_command), ListPack}
2966};
2967#undef Offset
2968
2969#define XT_NUM_SM_PROPS 11
2970
2971static void SetSessionProperties(
2972    SessionShellWidget w,
2973    Boolean initialize,
2974    unsigned long set_mask,
2975    unsigned long unset_mask)
2976{
2977    PropertyTable p = propertyTable;
2978    int n;
2979    int num_props = 0;
2980    XtPointer *addr;
2981    unsigned long mask;
2982    SmProp *props[XT_NUM_SM_PROPS];
2983    char *pnames[XT_NUM_SM_PROPS];
2984
2985    if (w->session.connection == NULL)
2986	return;
2987
2988    if (initialize) {
2989	char nam_buf[32];
2990	char pid[12];
2991	String user_name;
2992	String pidp = pid;
2993
2994	/* set all non-NULL session properties, the UserID and the ProcessID */
2995	for (n = XtNumber(propertyTable); n; n--, p++) {
2996	    addr = (XtPointer *) ((char *) w + p->offset);
2997	    if (p->proc == CardPack) {
2998		if (*(unsigned char *)addr)
2999		    props[num_props++] =(*(p->proc))(p->name, (XtPointer)addr);
3000	    }
3001	    else if (* addr)
3002		props[num_props++] = (*(p->proc))(p->name, (XtPointer)addr);
3003
3004	}
3005	user_name = _XtGetUserName(nam_buf, sizeof nam_buf);
3006	if (user_name)
3007	    props[num_props++] = ArrayPack(SmUserID, &user_name);
3008	sprintf(pid, "%ld", (long)getpid());
3009	props[num_props++] = ArrayPack(SmProcessID, &pidp);
3010
3011	if (num_props) {
3012	    SmcSetProperties(w->session.connection, num_props, props);
3013	    FreePacks(props, num_props);
3014	}
3015	return;
3016    }
3017
3018    if (set_mask) {
3019	mask = 1L;
3020	for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1)
3021	    if (mask & set_mask) {
3022		addr = (XtPointer *) ((char *) w + p->offset);
3023		props[num_props++] = (*(p->proc))(p->name, (XtPointer)addr);
3024	    }
3025	SmcSetProperties(w->session.connection, num_props, props);
3026	FreePacks(props, num_props);
3027    }
3028
3029    if (unset_mask) {
3030	mask = 1L;
3031	num_props = 0;
3032	for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1)
3033	    if (mask & unset_mask)
3034		pnames[num_props++] = p->name;
3035	SmcDeleteProperties(w->session.connection, num_props, pnames);
3036    }
3037}
3038
3039/*ARGSUSED*/
3040static void GetIceEvent(
3041    XtPointer	client_data,
3042    int *	source,
3043    XtInputId *	id)
3044{
3045    SessionShellWidget w = (SessionShellWidget) client_data;
3046    IceProcessMessagesStatus status;
3047
3048    status = IceProcessMessages(SmcGetIceConnection(w->session.connection),
3049				NULL, NULL);
3050
3051    if (status == IceProcessMessagesIOError) {
3052	StopManagingSession(w, w->session.connection);
3053	XtCallCallbackList((Widget)w, w->session.error_callbacks,
3054			   (XtPointer) NULL);
3055    }
3056}
3057
3058static void CleanUpSave(
3059    SessionShellWidget w)
3060{
3061    XtSaveYourself next = w->session.save->next;
3062    XtFree((char *)w->session.save);
3063    w->session.save = next;
3064    if (w->session.save)
3065	CallSaveCallbacks(w);
3066}
3067
3068static void CallSaveCallbacks(
3069    SessionShellWidget w)
3070{
3071    XtCheckpointToken token;
3072
3073    if (XtHasCallbacks((Widget) w, XtNsaveCallback) != XtCallbackHasSome) {
3074	/* if the application makes no attempt to save state, report failure */
3075	SmcSaveYourselfDone(w->session.connection, False);
3076	CleanUpSave(w);
3077    } else {
3078	w->session.checkpoint_state = XtSaveActive;
3079	token = GetToken((Widget) w, XtSessionCheckpoint);
3080	_XtCallConditionalCallbackList((Widget)w, w->session.save_callbacks,
3081				       (XtPointer)token, ExamineToken);
3082	XtSessionReturnToken(token);
3083    }
3084}
3085
3086/*ARGSUSED*/
3087static void XtCallSaveCallbacks(
3088    SmcConn	connection,	/* unused */
3089    SmPointer	client_data,
3090    int		save_type,
3091    Bool	shutdown,
3092    int		interact,
3093    Bool	fast)
3094{
3095    SessionShellWidget w = (SessionShellWidget) client_data;
3096    XtSaveYourself save;
3097    XtSaveYourself prev;
3098
3099    save = XtNew(XtSaveYourselfRec);
3100    save->next = NULL;
3101    save->save_type = save_type;
3102    save->interact_style = interact;
3103    save->shutdown = shutdown;
3104    save->fast = fast;
3105    save->cancel_shutdown = False;
3106    save->phase = 1;
3107    save->interact_dialog_type = SmDialogNormal;
3108    save->request_cancel = save->request_next_phase = False;
3109    save->save_success = True;
3110    save->save_tokens = save->interact_tokens = 0;
3111
3112    prev = (XtSaveYourself) &w->session.save;
3113    while (prev->next)
3114	prev = prev->next;
3115    prev->next = save;
3116
3117    if (w->session.checkpoint_state == XtSaveInactive)
3118	CallSaveCallbacks(w);
3119}
3120
3121static void XtInteractPermission(
3122    SmcConn	connection,
3123    SmPointer	data)
3124{
3125    Widget w = (Widget) data;
3126    SessionShellWidget sw = (SessionShellWidget) data;
3127    XtCheckpointToken token;
3128    XtCallbackProc callback;
3129    XtPointer client_data;
3130
3131
3132    _XtPeekCallback(w, sw->session.interact_callbacks, &callback,
3133		    &client_data);
3134    if (callback) {
3135	sw->session.checkpoint_state = XtInteractActive;
3136	token = GetToken(w, XtSessionInteract);
3137    	XtRemoveCallback(w, XtNinteractCallback, callback, client_data);
3138	(*callback)(w, client_data, (XtPointer) token);
3139    } else if (! sw->session.save->cancel_shutdown) {
3140	SmcInteractDone(connection, False);
3141    }
3142}
3143
3144/*ARGSUSED*/
3145static void XtCallSaveCompleteCallbacks(
3146    SmcConn	connection,
3147    SmPointer	client_data)
3148{
3149    SessionShellWidget w =  (SessionShellWidget) client_data;
3150
3151    XtCallCallbackList((Widget)w, w->session.save_complete_callbacks,
3152		       (XtPointer) NULL);
3153}
3154
3155/*ARGSUSED*/
3156static void XtCallNextPhaseCallbacks(
3157    SmcConn	connection,	/* unused */
3158    SmPointer	client_data)
3159{
3160    SessionShellWidget w =  (SessionShellWidget) client_data;
3161    w->session.save->phase = 2;
3162    CallSaveCallbacks(w);
3163}
3164
3165/*ARGSUSED*/
3166static void XtCallDieCallbacks(
3167    SmcConn	connection,	/* unused */
3168    SmPointer	client_data)
3169{
3170    SessionShellWidget w =  (SessionShellWidget) client_data;
3171
3172    StopManagingSession(w, w->session.connection);
3173    XtCallCallbackList((Widget)w, w->session.die_callbacks,
3174		       (XtPointer) NULL);
3175}
3176
3177/*ARGSUSED*/
3178static void XtCallCancelCallbacks(
3179    SmcConn	connection,	/* unused */
3180    SmPointer	client_data)
3181{
3182    SessionShellWidget w = (SessionShellWidget) client_data;
3183    Boolean call_interacts = False;
3184
3185    if (w->session.checkpoint_state != XtSaveInactive) {
3186	w->session.save->cancel_shutdown = True;
3187	call_interacts = (w->session.save->interact_style !=
3188			  SmInteractStyleNone);
3189    }
3190
3191    XtCallCallbackList((Widget)w, w->session.cancel_callbacks,
3192		       (XtPointer) NULL);
3193
3194    if (call_interacts) {
3195	w->session.save->interact_style = SmInteractStyleNone;
3196	XtInteractPermission(w->session.connection, (SmPointer) w);
3197    }
3198
3199    if (w->session.checkpoint_state != XtSaveInactive) {
3200	if (w->session.save->save_tokens == 0 &&
3201	    w->session.checkpoint_state == XtSaveActive) {
3202	    w->session.checkpoint_state = XtSaveInactive;
3203	    SmcSaveYourselfDone(w->session.connection,
3204				w->session.save->save_success);
3205	    CleanUpSave(w);
3206	}
3207    }
3208}
3209
3210static XtCheckpointToken GetToken(
3211    Widget	widget,
3212    int		type)
3213{
3214    SessionShellWidget w = (SessionShellWidget) widget;
3215    XtCheckpointToken token;
3216    XtSaveYourself save = w->session.save;
3217
3218    if (type == XtSessionCheckpoint)
3219	w->session.save->save_tokens++;
3220    else if (type == XtSessionInteract)
3221	w->session.save->interact_tokens++;
3222    else
3223	return (XtCheckpointToken) NULL;
3224
3225    token = (XtCheckpointToken) __XtMalloc(sizeof(XtCheckpointTokenRec));
3226    token->save_type = save->save_type;
3227    token->interact_style = save->interact_style;
3228    token->shutdown = save->shutdown;
3229    token->fast = save->fast;
3230    token->cancel_shutdown = save->cancel_shutdown;
3231    token->phase = save->phase;
3232    token->interact_dialog_type = save->interact_dialog_type;
3233    token->request_cancel = save->request_cancel;
3234    token->request_next_phase = save->request_next_phase;
3235    token->save_success = save->save_success;
3236    token->type = type;
3237    token->widget = widget;
3238    return token;
3239}
3240
3241XtCheckpointToken XtSessionGetToken(Widget widget)
3242{
3243    SessionShellWidget w = (SessionShellWidget) widget;
3244    XtCheckpointToken token = NULL;
3245    WIDGET_TO_APPCON(widget);
3246
3247    LOCK_APP(app);
3248    if (w->session.checkpoint_state)
3249	token = GetToken(widget, XtSessionCheckpoint);
3250
3251    UNLOCK_APP(app);
3252    return token;
3253}
3254
3255static Boolean ExamineToken(
3256    XtPointer	call_data)
3257{
3258    XtCheckpointToken token = (XtCheckpointToken) call_data;
3259    SessionShellWidget w = (SessionShellWidget) token->widget;
3260
3261    if (token->interact_dialog_type == SmDialogError)
3262	w->session.save->interact_dialog_type = SmDialogError;
3263    if (token->request_next_phase)
3264	w->session.save->request_next_phase = True;
3265    if (! token->save_success)
3266	w->session.save->save_success = False;
3267
3268    token->interact_dialog_type = w->session.save->interact_dialog_type;
3269    token->request_next_phase = w->session.save->request_next_phase;
3270    token->save_success = w->session.save->save_success;
3271    token->cancel_shutdown = w->session.save->cancel_shutdown;
3272
3273    return True;
3274}
3275
3276void XtSessionReturnToken(XtCheckpointToken token)
3277{
3278    SessionShellWidget w = (SessionShellWidget) token->widget;
3279    Boolean has_some;
3280    Boolean phase_done;
3281    XtCallbackProc callback;
3282    XtPointer client_data;
3283    WIDGET_TO_APPCON((Widget)w);
3284
3285    LOCK_APP(app);
3286
3287    has_some = (XtHasCallbacks(token->widget, XtNinteractCallback)
3288		== XtCallbackHasSome);
3289
3290    (void) ExamineToken((XtPointer) token);
3291
3292    if (token->type == XtSessionCheckpoint) {
3293	w->session.save->save_tokens--;
3294	if (has_some && w->session.checkpoint_state == XtSaveActive) {
3295	    w->session.checkpoint_state = XtInteractPending;
3296	    SmcInteractRequest(w->session.connection,
3297			       w->session.save->interact_dialog_type,
3298			       XtInteractPermission, (SmPointer) w);
3299	}
3300	XtFree((char*) token);
3301    } else {
3302	if (token->request_cancel)
3303	    w->session.save->request_cancel = True;
3304	token->request_cancel = w->session.save->request_cancel;
3305	if (has_some) {
3306	    _XtPeekCallback((Widget)w, w->session.interact_callbacks,
3307			    &callback, &client_data);
3308	    XtRemoveCallback((Widget)w, XtNinteractCallback,
3309			     callback, client_data);
3310	    (*callback)((Widget)w, client_data, (XtPointer)token);
3311	} else {
3312	    w->session.save->interact_tokens--;
3313	    if (w->session.save->interact_tokens == 0) {
3314		w->session.checkpoint_state = XtSaveActive;
3315		if (! w->session.save->cancel_shutdown)
3316		    SmcInteractDone(w->session.connection,
3317				    w->session.save->request_cancel);
3318	    }
3319	    XtFree((char *) token);
3320	}
3321    }
3322
3323    phase_done = (w->session.save->save_tokens == 0 &&
3324		  w->session.checkpoint_state == XtSaveActive);
3325
3326    if (phase_done) {
3327	if (w->session.save->request_next_phase &&
3328	    w->session.save->phase == 1) {
3329	    SmcRequestSaveYourselfPhase2(w->session.connection,
3330					 XtCallNextPhaseCallbacks,
3331					 (SmPointer)w);
3332	} else {
3333	    w->session.checkpoint_state = XtSaveInactive;
3334	    SmcSaveYourselfDone(w->session.connection,
3335				w->session.save->save_success);
3336	    CleanUpSave(w);
3337	}
3338    }
3339
3340    UNLOCK_APP(app);
3341}
3342
3343static Boolean IsInArray(
3344    String str,
3345    String *sarray)
3346{
3347    if (str == NULL || sarray == NULL)
3348	return False;
3349    for (; *sarray; sarray++) {
3350	if (strcmp(*sarray, str) == 0)
3351	    return True;
3352    }
3353    return False;
3354}
3355
3356static String* EditCommand(
3357    String str,		/* if not NULL, the sm_client_id */
3358    String *src1,	/* first choice */
3359    String *src2)	/* alternate */
3360{
3361    Boolean have;
3362    Boolean want;
3363    int count;
3364    String *sarray;
3365    String *s;
3366    String *new;
3367
3368    want = (str != NULL);
3369    sarray = (src1 ? src1 : src2);
3370    if (! sarray) return NULL;
3371    have = IsInArray("-xtsessionID", sarray);
3372    if ((want && have) || (!want && !have)) {
3373	if (sarray == src1)
3374	    return src1;
3375	else
3376	    return NewStringArray(sarray);
3377    }
3378
3379    count = 0;
3380    for (s = sarray; *s; s++)
3381	count++;
3382
3383    if (want) {
3384	s = new = (String *) __XtMalloc((Cardinal)(count+3) * sizeof(String*));
3385	*s = *sarray;		s++; sarray++;
3386	*s = "-xtsessionID";	s++;
3387	*s = str;		s++;
3388	for (; --count > 0; s++, sarray++)
3389	    *s = *sarray;
3390	*s = (String) NULL;
3391    } else {
3392	if (count < 3)
3393	    return NewStringArray(sarray);
3394	s = new = (String *) __XtMalloc((Cardinal)(count-1) * sizeof(String*));
3395	for (; --count >= 0; sarray++) {
3396	    if (strcmp(*sarray, "-xtsessionID") == 0) {
3397		sarray++;
3398		count--;
3399	    } else {
3400		*s = *sarray;
3401		s++;
3402	    }
3403	}
3404	*s = (String) NULL;
3405    }
3406    s = new;
3407    new = NewStringArray(new);
3408    XtFree((char *)s);
3409    return new;
3410}
3411
3412#endif /* !XT_NO_SM */
3413