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