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