Home | History | Annotate | Line # | Download | only in dist
      1 /* $Xorg: save.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */
      2 /******************************************************************************
      3 
      4 Copyright 1993, 1998  The Open Group
      5 
      6 Permission to use, copy, modify, distribute, and sell this software and its
      7 documentation for any purpose is hereby granted without fee, provided that
      8 the above copyright notice appear in all copies and that both that
      9 copyright notice and this permission notice appear in supporting
     10 documentation.
     11 
     12 The above copyright notice and this permission notice shall be included in
     13 all copies or substantial portions of the 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 THE
     18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall not be
     23 used in advertising or otherwise to promote the sale, use or other dealings
     24 in this Software without prior written authorization from The Open Group.
     25 ******************************************************************************/
     26 /* $XFree86: xc/programs/xsm/save.c,v 3.3 2001/01/17 23:46:30 dawes Exp $ */
     27 
     28 #include "xsm.h"
     29 #include "save.h"
     30 #include "saveutil.h"
     31 #include "popup.h"
     32 #include "info.h"
     33 #include "lock.h"
     34 #include "choose.h"
     35 
     36 #include <X11/Shell.h>
     37 #include <X11/Xaw/Form.h>
     38 #include <X11/Xaw/List.h>
     39 #include <X11/Xaw/Command.h>
     40 #include <X11/Xaw/Toggle.h>
     41 #include <X11/Xaw/AsciiText.h>
     42 
     43 
     44 static Widget savePopup;
     46 static Widget   saveForm;
     47 static Widget	   saveMessageLabel;
     48 static Widget	   saveName;
     49 static Widget	   saveTypeLabel;
     50 static Widget	   saveTypeGlobal;
     51 static Widget	   saveTypeLocal;
     52 static Widget	   saveTypeBoth;
     53 static Widget	   interactStyleLabel;
     54 static Widget	   interactStyleNone;
     55 static Widget	   interactStyleErrors;
     56 static Widget	   interactStyleAny;
     57 static Widget	   saveOkButton;
     58 static Widget     helpSaveButton;
     59 static Widget	   saveCancelButton;
     60 static Widget helpPopup;
     61 static Widget   helpForm;
     62 static Widget     helpSaveText;
     63 static Widget     helpSaveOkButton;
     64 static Widget nameInUsePopup;
     65 static Widget   nameInUseForm;
     66 static Widget	   nameInUseLabel;
     67 static Widget     nameInUseOverwriteButton;
     68 static Widget	   nameInUseCancelButton;
     69 static Widget badSavePopup;
     70 static Widget   badSaveForm;
     71 static Widget	   badSaveLabel;
     72 static Widget     badSaveOkButton;
     73 static Widget	   badSaveCancelButton;
     74 static Widget     badSaveListWidget;
     75 
     76 static int saveTypeData[] = {
     77 	SmSaveLocal,
     78 	SmSaveGlobal,
     79 	SmSaveBoth
     80 };
     81 
     82 static int interactStyleData[] = {
     83 	SmInteractStyleNone,
     84 	SmInteractStyleErrors,
     85 	SmInteractStyleAny
     86 };
     87 
     88 static String *failedNames = NULL;
     89 static int numFailedNames = 0;
     90 
     91 static Bool help_visible = False;
     92 
     93 static String name_in_use = NULL;
     94 static Bool name_locked = False;
     95 
     96 
     97 
     98 static void
    100 MakeCurrentSession(String new_name, Bool name_changed)
    101 {
    102     char title[256];
    103     List *cl;
    104 
    105     if (session_name)
    106     {
    107 	/*
    108 	 * In the old session, for any client that was not restarted by the
    109 	 * session manager (previous ID was NULL), if we did not issue a
    110 	 * checkpoint to this client after the initial startup, remove the
    111 	 * client's checkpoint file using the discard command.
    112 	 */
    113 
    114 	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
    115 	{
    116 	    ClientRec *client = (ClientRec *) cl->thing;
    117 
    118 	    if (!client->restarted &&
    119 		!client->userIssuedCheckpoint &&
    120 		client->discardCommand)
    121 	    {
    122 		execute_system_command (client->discardCommand);
    123 		XtFree (client->discardCommand);
    124 		client->discardCommand = NULL;
    125 	    }
    126 	}
    127 
    128 	/*
    129 	 * Unlock the old session.
    130 	 */
    131 
    132 	if (!need_to_name_session)
    133 	    UnlockSession (session_name);
    134     }
    135 
    136     if (name_changed)
    137     {
    138 	if (session_name)
    139 	    XtFree (session_name);
    140 
    141 	session_name = XtNewString (new_name);
    142     }
    143 
    144     LockSession (session_name, True);
    145 
    146     snprintf (title, sizeof(title), "xsm: %s", session_name);
    147 
    148     XtVaSetValues (topLevel,
    149 	XtNtitle, title,
    150 	NULL);
    151 
    152     set_session_save_file_name (session_name);
    153 
    154 
    155     /*
    156      * For each client, set the DiscardCommand ptr to NULL.
    157      * This is so when we do a checkpoint with the new session
    158      * name, we don't wipe out the checkpoint files needed by
    159      * the previous session.  We also set the userIssuedCheckpoint
    160      * flag to false for each client in the new session.
    161      */
    162 
    163     for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
    164     {
    165 	ClientRec *client = (ClientRec *) cl->thing;
    166 
    167 	client->userIssuedCheckpoint = False;
    168 
    169 	if (client->discardCommand)
    170 	{
    171 	    XtFree (client->discardCommand);
    172 	    client->discardCommand = NULL;
    173 	}
    174     }
    175 
    176     need_to_name_session = False;
    177 }
    178 
    179 
    180 
    181 
    182 #define NAME_OK     0
    184 #define NAME_EMPTY  1
    185 #define NAME_EXISTS 2
    186 #define NAME_LOCKED 3
    187 
    188 static int
    189 GetSaveName(String *nameRet)
    190 {
    191     String new_name = NULL;
    192     Bool name_changed;
    193 
    194     /*
    195      * Get the name of the session for the save
    196      */
    197 
    198     XtVaGetValues (saveName,
    199 	XtNstring, &new_name,
    200 	NULL);
    201 
    202     *nameRet = new_name;
    203 
    204     if (!new_name || *new_name == '\0')
    205 	return (NAME_EMPTY);
    206 
    207     /*
    208      * See if this is a new session.  If not return.
    209      */
    210 
    211     name_changed = !session_name ||
    212 	(session_name && strcmp (session_name, new_name) != 0);
    213 
    214     if (!need_to_name_session && !name_changed)
    215 	return (NAME_OK);
    216 
    217 
    218     /*
    219      * Make sure the session name is unique.
    220      */
    221 
    222     if (GetSessionNames (&sessionNameCount,
    223 	&sessionNamesShort, NULL, &sessionsLocked))
    224     {
    225 	int i, no_good = 0, locked = 0;
    226 
    227 	for (i = 0; i < sessionNameCount; i++)
    228 	    if (strcmp (new_name, sessionNamesShort[i]) == 0)
    229 	    {
    230 		no_good = 1;
    231 		locked = sessionsLocked[i];
    232 		break;
    233 	    }
    234 
    235 	FreeSessionNames (sessionNameCount,
    236 	    sessionNamesShort, NULL, sessionsLocked);
    237 
    238 	if (no_good)
    239 	    return (locked ? NAME_LOCKED : NAME_EXISTS);
    240     }
    241 
    242     MakeCurrentSession (new_name, name_changed);
    243 
    244     return (NAME_OK);
    245 }
    246 
    247 
    248 static void
    250 GetSaveOptions(int *saveType, int *interactStyle, Bool *fast)
    251 {
    252     XtPointer	ptr;
    253 
    254     if (help_visible)
    255     {
    256 	XtPopdown (helpPopup);
    257 	help_visible = 0;
    258     }
    259 
    260     ptr = XawToggleGetCurrent (saveTypeLocal /* just 1 of the group */);
    261     *saveType = *((int *) ptr);
    262 
    263     ptr = XawToggleGetCurrent (interactStyleNone /* just 1 of the group */);
    264     *interactStyle = *((int *) ptr);
    265 
    266     *fast = False;
    267 }
    268 
    269 
    270 
    271 void
    273 DoSave(int saveType, int interactStyle, Bool fast)
    274 {
    275     ClientRec	*client;
    276     List	*cl;
    277     const char	*_saveType;
    278     const char	*_shutdown;
    279     const char	*_interactStyle;
    280 
    281     if (saveType == SmSaveLocal)
    282 	_saveType = "Local";
    283     else if (saveType == SmSaveGlobal)
    284 	_saveType = "Global";
    285     else
    286 	_saveType = "Both";
    287 
    288     if (wantShutdown)
    289 	_shutdown = "True";
    290     else
    291 	_shutdown = "False";
    292 
    293     if (interactStyle == SmInteractStyleNone)
    294 	_interactStyle = "None";
    295     else if (interactStyle == SmInteractStyleErrors)
    296 	_interactStyle = "Errors";
    297     else
    298 	_interactStyle = "Any";
    299 
    300     SetSaveSensitivity (False);
    301 
    302     saveInProgress = True;
    303 
    304     shutdownCancelled = False;
    305     phase2InProgress = False;
    306 
    307     if (ListCount (RunningList) == 0)
    308 	FinishUpSave ();
    309 
    310     for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
    311     {
    312 	client = (ClientRec *) cl->thing;
    313 
    314 	SmsSaveYourself (client->smsConn,
    315 	    saveType, wantShutdown, interactStyle, fast);
    316 
    317 	ListAddLast (WaitForSaveDoneList, (char *) client);
    318 
    319 	client->userIssuedCheckpoint = True;
    320 	client->receivedDiscardCommand = False;
    321 
    322 	if (verbose)
    323 	{
    324 	    printf ("Client Id = %s, sent SAVE YOURSELF [", client->clientId);
    325 	    printf ("Save Type = %s, Shutdown = %s, ", _saveType, _shutdown);
    326 	    printf ("Interact Style = %s, Fast = False]\n", _interactStyle);
    327 	}
    328     }
    329 
    330     if (verbose)
    331     {
    332 	printf ("\n");
    333 	printf ("Sent SAVE YOURSELF to all clients.  Waiting for\n");
    334 	printf ("SAVE YOURSELF DONE, INTERACT REQUEST, or\n");
    335 	printf ("SAVE YOURSELF PHASE 2 REQUEST from each client.\n");
    336 	printf ("\n");
    337     }
    338 }
    339 
    340 
    341 
    342 static void
    344 SaveOkAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
    345 {
    346     XtCallCallbacks (saveOkButton, XtNcallback, NULL);
    347 }
    348 
    349 
    350 
    351 static void
    353 DelSaveWinAction(Widget w, XEvent *event, String *params, Cardinal *num_params)
    354 {
    355     XtCallCallbacks (saveCancelButton, XtNcallback, NULL);
    356 }
    357 
    358 
    359 
    360 static void
    362 DelNameInUseWinAction(Widget w, XEvent *event, String *params,
    363 		      Cardinal *num_params)
    364 {
    365     XtCallCallbacks (nameInUseCancelButton, XtNcallback, NULL);
    366 }
    367 
    368 
    369 
    370 static void
    372 DelBadSaveWinAction(Widget w, XEvent *event, String *params,
    373 		    Cardinal *num_params)
    374 {
    375     if (XtIsManaged (badSaveCancelButton))
    376 	XtCallCallbacks (badSaveCancelButton, XtNcallback, NULL);
    377     else
    378 	XtCallCallbacks (badSaveOkButton, XtNcallback, NULL);
    379 }
    380 
    381 
    382 
    383 static void
    385 DelSaveHelpWinAction(Widget w, XEvent *event, String *params,
    386 		     Cardinal *num_params)
    387 {
    388     XtCallCallbacks (helpSaveOkButton, XtNcallback, NULL);
    389 }
    390 
    391 
    392 
    393 static void
    395 SaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData)
    396 {
    397     String name = NULL;
    398     char label[256];
    399     int	status;
    400     static int first_time = 1;
    401     int saveType;
    402     int interactStyle;
    403     Bool fast;
    404 
    405     if ((status = GetSaveName (&name)) != NAME_OK)
    406     {
    407 #ifdef XKB
    408 	XkbStdBell(XtDisplay(topLevel),XtWindow(topLevel),0,XkbBI_BadValue);
    409 #else
    410 	XBell (XtDisplay (topLevel), 0);
    411 #endif
    412 
    413 	if (status == NAME_EXISTS || status == NAME_LOCKED)
    414 	{
    415 	    name_in_use = name;
    416 
    417 	    if (status == NAME_LOCKED)
    418 	    {
    419 		name_locked = True;
    420 
    421 		snprintf (label, sizeof(label), "Another session by the name '%s' is active.\nChoose another name for the session.", name);
    422 
    423 		XtUnmanageChild (nameInUseOverwriteButton);
    424 
    425 		XtVaSetValues (nameInUseCancelButton,
    426 		    XtNlabel, "OK",
    427 		    XtNfromHoriz, NULL,
    428 		    NULL);
    429 	    }
    430 	    else
    431 	    {
    432 		name_locked = False;
    433 
    434 		snprintf (label, sizeof(label), "Another session by the name '%s' already exists.\nWould you like to overwrite it?", name);
    435 
    436 		XtManageChild (nameInUseOverwriteButton);
    437 
    438 		XtVaSetValues (nameInUseCancelButton,
    439 		    XtNlabel, "Cancel",
    440 		    XtNfromHoriz, nameInUseOverwriteButton,
    441 		    NULL);
    442 	    }
    443 
    444 	    XtVaSetValues (nameInUseLabel,
    445 		XtNlabel, label,
    446 		NULL);
    447 
    448 	    XtPopdown (savePopup);
    449 
    450 	    PopupPopup (mainWindow, nameInUsePopup,
    451 		True, first_time, 25, 100, "DelNameInUseWinAction()");
    452 
    453 	    if (first_time)
    454 		first_time = 0;
    455 	}
    456 
    457 	return;
    458     }
    459 
    460     GetSaveOptions (&saveType, &interactStyle, &fast);
    461     DoSave (saveType, interactStyle, fast);
    462 }
    463 
    464 
    465 
    466 void
    468 LetClientInteract(List *cl)
    469 {
    470     ClientRec *client = (ClientRec *) cl->thing;
    471 
    472     SmsInteract (client->smsConn);
    473 
    474     ListSearchAndFreeOne (WaitForInteractList, (char *) client);
    475 
    476     if (verbose)
    477     {
    478 	printf ("Client Id = %s, sent INTERACT\n", client->clientId);
    479     }
    480 }
    481 
    482 
    483 
    484 void
    485 StartPhase2(void)
    486 {
    487     List *cl;
    488 
    489     if (verbose)
    490     {
    491 	printf ("\n");
    492 	printf ("Starting PHASE 2 of SAVE YOURSELF\n");
    493 	printf ("\n");
    494     }
    495 
    496     for (cl = ListFirst (WaitForPhase2List); cl; cl = ListNext (cl))
    497     {
    498 	ClientRec *client = (ClientRec *) cl->thing;
    499 
    500 	SmsSaveYourselfPhase2 (client->smsConn);
    501 
    502 	if (verbose)
    503 	{
    504 	    printf ("Client Id = %s, sent SAVE YOURSELF PHASE 2",
    505 		client->clientId);
    506 	}
    507     }
    508 
    509     ListFreeAllButHead (WaitForPhase2List);
    510 
    511     phase2InProgress = True;
    512 }
    513 
    514 
    515 void
    516 FinishUpSave(void)
    517 {
    518     ClientRec	*client;
    519     List	*cl;
    520 
    521     if (verbose)
    522     {
    523 	printf ("\n");
    524 	printf ("All clients issued SAVE YOURSELF DONE\n");
    525 	printf ("\n");
    526     }
    527 
    528     saveInProgress = False;
    529     phase2InProgress = False;
    530 
    531     /*
    532      * Now execute discard commands
    533      */
    534 
    535     for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
    536     {
    537 	client = (ClientRec *) cl->thing;
    538 
    539 	if (!client->receivedDiscardCommand)
    540 	    continue;
    541 
    542 	if (client->discardCommand)
    543 	{
    544 	    execute_system_command (client->discardCommand);
    545 	    XtFree (client->discardCommand);
    546 	    client->discardCommand = NULL;
    547 	}
    548 
    549 	if (client->saveDiscardCommand)
    550 	{
    551 	    client->discardCommand = client->saveDiscardCommand;
    552 	    client->saveDiscardCommand = NULL;
    553 	}
    554     }
    555 
    556 
    557     /*
    558      * Write the save file
    559      */
    560 
    561     WriteSave (sm_id);
    562 
    563 
    564     if (wantShutdown && shutdownCancelled)
    565     {
    566 	shutdownCancelled = False;
    567     }
    568     else if (wantShutdown)
    569     {
    570 	if (ListCount (RunningList) == 0)
    571 	    EndSession (0);
    572 
    573 	shutdownInProgress = True;
    574 
    575 	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
    576 	{
    577 	    client = (ClientRec *) cl->thing;
    578 
    579 	    SmsDie (client->smsConn);
    580 
    581 	    if (verbose)
    582 	    {
    583 		printf ("Client Id = %s, sent DIE\n", client->clientId);
    584 	    }
    585 	}
    586     }
    587     else
    588     {
    589 	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
    590 	{
    591 	    client = (ClientRec *) cl->thing;
    592 
    593 	    SmsSaveComplete (client->smsConn);
    594 
    595 	    if (verbose)
    596 	    {
    597 		printf ("Client Id = %s, sent SAVE COMPLETE\n",
    598 		    client->clientId);
    599 	    }
    600 	}
    601     }
    602 
    603     if (!shutdownInProgress)
    604     {
    605 	XtPopdown (savePopup);
    606 	SetAllSensitive (1);
    607 	if (checkpoint_from_signal)
    608 	    checkpoint_from_signal = False;
    609     }
    610 }
    611 
    612 
    613 
    614 static void
    616 SaveCancelXtProc(Widget w, XtPointer client_data, XtPointer callData)
    617 {
    618     XtPopdown (savePopup);
    619 
    620     if (help_visible)
    621     {
    622 	XtPopdown (helpPopup);
    623 	help_visible = 0;
    624     }
    625 
    626     SetAllSensitive (1);
    627 }
    628 
    629 
    630 
    631 /*
    633  * Add toggle button
    634  */
    635 
    636 static Widget
    637 AddToggle(String widgetName, Widget parent, int state, Widget radioGroup,
    638 	  XtPointer radioData,  Widget fromHoriz, Widget fromVert)
    639 {
    640     Widget toggle;
    641 
    642     toggle = XtVaCreateManagedWidget (
    643 	widgetName, toggleWidgetClass, parent,
    644         XtNstate, state,
    645         XtNradioGroup, radioGroup,
    646         XtNradioData, radioData,
    647         XtNfromHoriz, fromHoriz,
    648         XtNfromVert, fromVert,
    649         NULL);
    650 
    651     return (toggle);
    652 }
    653 
    654 
    655 
    656 void
    658 SetSaveSensitivity(Bool on)
    659 {
    660     XtSetSensitive (savePopup, on);
    661 
    662 #if 0
    663     /*
    664      * When we turn of sensitivity in the save dialog, we want to keep
    665      * the cancel button sensitive (so the user can cancel in case of
    666      * a problem).  Unfortunately, we can not turn off the sensitivity on
    667      * the save popup, and then just turn on sensitivity for the cancel
    668      * button.  We must do each widget individually.
    669      */
    670 
    671     XtSetSensitive (saveTypeLabel, on);
    672     XtSetSensitive (saveTypeGlobal, on);
    673     XtSetSensitive (saveTypeLocal, on);
    674     XtSetSensitive (saveTypeBoth, on);
    675     XtSetSensitive (interactStyleLabel, on);
    676     XtSetSensitive (interactStyleNone, on);
    677     XtSetSensitive (interactStyleErrors, on);
    678     XtSetSensitive (interactStyleAny, on);
    679     XtSetSensitive (saveOkButton, on);
    680 #endif
    681 }
    682 
    683 
    684 
    685 void
    687 SavePopupStructureNotifyXtHandler(Widget w, XtPointer closure, XEvent *event,
    688 				  Boolean *continue_to_dispatch)
    689 {
    690     if (event->type == MapNotify)
    691     {
    692 	/*
    693 	 * Now that the Save Dialog is back up, we can do the save.
    694 	 */
    695 
    696 	int saveType;
    697 	int interactStyle;
    698 	Bool fast;
    699 
    700 	if (name_locked)
    701 	{
    702 	    /* Force shutdown */
    703 	}
    704 
    705 	DeleteSession (name_in_use);
    706 
    707 	MakeCurrentSession (name_in_use, True);
    708 
    709 	name_in_use = NULL;
    710 
    711 	GetSaveOptions (&saveType, &interactStyle, &fast);
    712 	DoSave (saveType, interactStyle, fast);
    713 
    714 	XtRemoveEventHandler (savePopup, StructureNotifyMask, False,
    715 	    SavePopupStructureNotifyXtHandler, NULL);
    716     }
    717 }
    718 
    719 
    720 
    721 static void
    723 NameInUseOverwriteXtProc(Widget w, XtPointer client_data, XtPointer callData)
    724 {
    725     if (name_locked)
    726     {
    727 	/* force shutdown not implemented yet */
    728 
    729 	return;
    730     }
    731 
    732     XtPopdown (nameInUsePopup);
    733 
    734     /*
    735      * We want to popup the Save dialog again.  In order to avoid a race
    736      * condition with the BadSave handler trying to pop down the Save Dialog,
    737      * we wait for the MapNotify on the Save dialog, and then do the save.
    738      */
    739 
    740     XtAddEventHandler (savePopup, StructureNotifyMask, False,
    741 	SavePopupStructureNotifyXtHandler, NULL);
    742 
    743     XtPopup (savePopup, XtGrabNone);
    744 }
    745 
    746 
    747 
    748 static void
    750 NameInUseCancelXtProc(Widget w, XtPointer client_data, XtPointer callData)
    751 {
    752     XtPopdown (nameInUsePopup);
    753     XtPopup (savePopup, XtGrabNone);
    754 
    755     name_in_use = NULL;
    756 }
    757 
    758 
    759 
    760 static void
    762 BadSaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData)
    763 {
    764     ListFreeAllButHead (FailedSaveList);
    765     XtPopdown (badSavePopup);
    766     FinishUpSave ();
    767 }
    768 
    769 
    770 
    771 static void
    773 BadSaveCancelXtProc(Widget w, XtPointer client_data, XtPointer callData)
    774 {
    775     ListFreeAllButHead (FailedSaveList);
    776     XtPopdown (badSavePopup);
    777 
    778     if (wantShutdown)
    779     {
    780 	List *cl;
    781 
    782 	shutdownCancelled = True;
    783 
    784 	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
    785 	{
    786 	    ClientRec *client = (ClientRec *) cl->thing;
    787 
    788 	    SmsShutdownCancelled (client->smsConn);
    789 
    790 	    if (verbose)
    791 	    {
    792 		printf ("Client Id = %s, sent SHUTDOWN CANCELLED\n",
    793 			client->clientId);
    794 	    }
    795 	}
    796     }
    797 
    798     FinishUpSave ();
    799 }
    800 
    801 
    802 
    803 static void
    805 BadSaveListXtProc(Widget w, XtPointer client_data, XtPointer callData)
    806 {
    807 
    808 }
    809 
    810 
    811 
    812 static void
    814 HelpSaveXtProc(Widget w, XtPointer client_data, XtPointer callData)
    815 {
    816     static int first_time = 1;
    817 
    818     if (help_visible)
    819     {
    820 	/* Make sure it is visible */
    821 
    822 	XMapRaised (XtDisplay (topLevel), XtWindow (helpPopup));
    823     }
    824     else
    825     {
    826 	PopupPopup (savePopup, helpPopup,
    827 	    True, first_time, 50, 50, "DelSaveHelpWinAction()");
    828 
    829 	help_visible = 1;
    830 
    831 	if (first_time)
    832 	    first_time = 0;
    833     }
    834 }
    835 
    836 
    837 
    838 static void
    840 HelpSaveOkXtProc(Widget w, XtPointer client_data, XtPointer callData)
    841 {
    842     XtPopdown (helpPopup);
    843     help_visible = 0;
    844 }
    845 
    846 
    847 
    848 void
    850 create_save_popup(void)
    851 
    852 {
    853     XtTranslations translations;
    854 
    855     static XtActionsRec actions[] = {
    856         {"SaveOkAction", SaveOkAction},
    857         {"DelSaveWinAction", DelSaveWinAction},
    858 	{"DelNameInUseWinAction", DelNameInUseWinAction},
    859 	{"DelBadSaveWinAction", DelBadSaveWinAction},
    860 	{"DelSaveHelpWinAction", DelSaveHelpWinAction}
    861     };
    862 
    863 
    864     /*
    865      * Pop up for Save Yourself button.
    866      */
    867 
    868     savePopup = XtVaCreatePopupShell (
    869 	"savePopup", transientShellWidgetClass, topLevel,
    870 	XtNallowShellResize, True,
    871 	NULL);
    872 
    873     saveForm = XtCreateManagedWidget (
    874 	"saveForm", formWidgetClass, savePopup, NULL, 0);
    875 
    876     saveMessageLabel = XtVaCreateManagedWidget (
    877 	"saveMessageLabel", labelWidgetClass, saveForm,
    878         XtNfromHoriz, NULL,
    879         XtNfromVert, NULL,
    880         XtNborderWidth, 0,
    881 	NULL);
    882 
    883     saveName = XtVaCreateManagedWidget (
    884 	"saveName", asciiTextWidgetClass, saveForm,
    885         XtNfromVert, NULL,
    886 	XtNeditType, XawtextEdit,
    887 	XtNresizable, True,
    888 	XtNresize, XawtextResizeWidth,
    889 	NULL);
    890 
    891     saveTypeLabel = XtVaCreateManagedWidget (
    892 	"saveTypeLabel", labelWidgetClass, saveForm,
    893         XtNfromHoriz, NULL,
    894         XtNfromVert, saveMessageLabel,
    895         XtNborderWidth, 0,
    896         XtNvertDistance, 20,
    897 	NULL);
    898 
    899     saveTypeLocal = AddToggle (
    900 	"saveTypeLocal", 			/* widgetName */
    901 	saveForm,				/* parent */
    902 	0,					/* state */
    903         NULL,					/* radioGroup */
    904         (XtPointer) &saveTypeData[0],		/* radioData */
    905         saveTypeLabel,				/* fromHoriz */
    906         saveMessageLabel			/* fromVert */
    907     );
    908 
    909     saveTypeGlobal = AddToggle (
    910 	"saveTypeGlobal", 			/* widgetName */
    911 	saveForm,				/* parent */
    912 	0,					/* state */
    913         saveTypeLocal,				/* radioGroup */
    914         (XtPointer) &saveTypeData[1],		/* radioData */
    915         saveTypeLocal,				/* fromHoriz */
    916         saveMessageLabel			/* fromVert */
    917     );
    918 
    919     saveTypeBoth = AddToggle (
    920 	"saveTypeBoth", 			/* widgetName */
    921 	saveForm,				/* parent */
    922 	1,					/* state */
    923         saveTypeLocal,				/* radioGroup */
    924         (XtPointer) &saveTypeData[2],		/* radioData */
    925         saveTypeGlobal,				/* fromHoriz */
    926         saveMessageLabel			/* fromVert */
    927     );
    928 
    929 
    930     XtVaSetValues (saveName, XtNfromHoriz, saveTypeLabel, NULL);
    931     XtVaSetValues (saveTypeLocal, XtNvertDistance, 20, NULL);
    932     XtVaSetValues (saveTypeGlobal, XtNvertDistance, 20, NULL);
    933     XtVaSetValues (saveTypeBoth, XtNvertDistance, 20, NULL);
    934 
    935     interactStyleLabel = XtVaCreateManagedWidget (
    936 	"interactStyleLabel", labelWidgetClass, saveForm,
    937         XtNfromHoriz, NULL,
    938         XtNfromVert, saveTypeLabel,
    939         XtNborderWidth, 0,
    940 	NULL);
    941 
    942     interactStyleNone = AddToggle (
    943 	"interactStyleNone", 			/* widgetName */
    944 	saveForm,				/* parent */
    945 	0,					/* state */
    946         NULL,					/* radioGroup */
    947         (XtPointer) &interactStyleData[0],	/* radioData */
    948         saveTypeLabel,				/* fromHoriz */
    949         saveTypeLabel				/* fromVert */
    950     );
    951 
    952     interactStyleErrors = AddToggle (
    953 	"interactStyleErrors", 			/* widgetName */
    954 	saveForm,				/* parent */
    955 	0,					/* state */
    956         interactStyleNone,			/* radioGroup */
    957         (XtPointer) &interactStyleData[1],	/* radioData */
    958         interactStyleNone,			/* fromHoriz */
    959         saveTypeLabel				/* fromVert */
    960     );
    961 
    962     interactStyleAny = AddToggle (
    963 	"interactStyleAny", 			/* widgetName */
    964 	saveForm,				/* parent */
    965 	1,					/* state */
    966         interactStyleNone,			/* radioGroup */
    967         (XtPointer) &interactStyleData[2],	/* radioData */
    968         interactStyleErrors,			/* fromHoriz */
    969         saveTypeLabel				/* fromVert */
    970     );
    971 
    972 
    973     saveOkButton = XtVaCreateManagedWidget (
    974 	"saveOkButton",	commandWidgetClass, saveForm,
    975         XtNfromHoriz, NULL,
    976         XtNfromVert, interactStyleLabel,
    977         XtNvertDistance, 20,
    978 	XtNresizable, True,
    979         NULL);
    980 
    981     XtAddCallback (saveOkButton, XtNcallback, SaveOkXtProc, NULL);
    982 
    983 
    984     helpSaveButton = XtVaCreateManagedWidget (
    985 	"helpSaveButton", commandWidgetClass, saveForm,
    986         XtNfromHoriz, saveOkButton,
    987         XtNfromVert, interactStyleLabel,
    988         XtNvertDistance, 20,
    989 	NULL);
    990 
    991     XtAddCallback (helpSaveButton, XtNcallback, HelpSaveXtProc, NULL);
    992 
    993 
    994     saveCancelButton = XtVaCreateManagedWidget (
    995 	"saveCancelButton", commandWidgetClass, saveForm,
    996         XtNfromHoriz, helpSaveButton,
    997         XtNfromVert, interactStyleLabel,
    998         XtNvertDistance, 20,
    999         NULL);
   1000 
   1001     XtAddCallback (saveCancelButton, XtNcallback, SaveCancelXtProc, NULL);
   1002 
   1003     XtSetKeyboardFocus (saveForm, saveName);
   1004 
   1005     XtAppAddActions (appContext, actions, XtNumber (actions));
   1006 
   1007     translations = XtParseTranslationTable
   1008 	("<Key>Return: SaveOkAction()\n");
   1009     XtOverrideTranslations(saveName, translations);
   1010 
   1011     XtInstallAllAccelerators (saveForm, saveForm);
   1012 
   1013 
   1014     /*
   1015      * Pop up when user tries to save the session under an
   1016      * already used name.
   1017      */
   1018 
   1019     nameInUsePopup = XtVaCreatePopupShell (
   1020 	"nameInUsePopup", transientShellWidgetClass, topLevel,
   1021 	XtNallowShellResize, True,
   1022 	NULL);
   1023 
   1024 
   1025     nameInUseForm = XtVaCreateManagedWidget (
   1026 	"nameInUseForm", formWidgetClass, nameInUsePopup,
   1027 	NULL);
   1028 
   1029     nameInUseLabel = XtVaCreateManagedWidget (
   1030 	"nameInUseLabel", labelWidgetClass, nameInUseForm,
   1031 	XtNresizable, True,
   1032         XtNfromHoriz, NULL,
   1033         XtNfromVert, NULL,
   1034         XtNborderWidth, 0,
   1035 	XtNtop, XawChainTop,
   1036 	XtNbottom, XawChainTop,
   1037 	NULL);
   1038 
   1039     nameInUseOverwriteButton = XtVaCreateManagedWidget (
   1040 	"nameInUseOverwriteButton", commandWidgetClass, nameInUseForm,
   1041         XtNfromHoriz, NULL,
   1042         XtNfromVert, nameInUseLabel,
   1043 	XtNtop, XawChainBottom,
   1044 	XtNbottom, XawChainBottom,
   1045         NULL);
   1046 
   1047     XtAddCallback (nameInUseOverwriteButton, XtNcallback,
   1048 	NameInUseOverwriteXtProc, NULL);
   1049 
   1050 
   1051     nameInUseCancelButton = XtVaCreateManagedWidget (
   1052 	"nameInUseCancelButton", commandWidgetClass, nameInUseForm,
   1053 	XtNresizable, True,
   1054         XtNfromHoriz, nameInUseOverwriteButton,
   1055         XtNfromVert, nameInUseLabel,
   1056 	XtNtop, XawChainBottom,
   1057 	XtNbottom, XawChainBottom,
   1058         NULL);
   1059 
   1060     XtAddCallback (nameInUseCancelButton, XtNcallback,
   1061 	NameInUseCancelXtProc, NULL);
   1062 
   1063 
   1064     /*
   1065      * Pop up for help.
   1066      */
   1067 
   1068     helpPopup = XtVaCreatePopupShell (
   1069 	"helpPopup", transientShellWidgetClass, topLevel,
   1070 	NULL);
   1071 
   1072 
   1073     helpForm = XtVaCreateManagedWidget (
   1074 	"helpForm", formWidgetClass, helpPopup,
   1075 	NULL);
   1076 
   1077     helpSaveText = XtVaCreateManagedWidget (
   1078 	"helpSaveText", labelWidgetClass, helpForm,
   1079         XtNfromHoriz, NULL,
   1080         XtNfromVert, NULL,
   1081 	XtNtop, XawChainTop,
   1082 	XtNbottom, XawChainTop,
   1083 	NULL);
   1084 
   1085     helpSaveOkButton = XtVaCreateManagedWidget (
   1086 	"helpSaveOkButton", commandWidgetClass, helpForm,
   1087         XtNfromHoriz, NULL,
   1088         XtNfromVert, helpSaveText,
   1089 	XtNtop, XawChainBottom,
   1090 	XtNbottom, XawChainBottom,
   1091         XtNvertDistance, 20,
   1092         NULL);
   1093 
   1094     XtAddCallback (helpSaveOkButton, XtNcallback,
   1095 	HelpSaveOkXtProc, NULL);
   1096 
   1097 
   1098     /*
   1099      * Pop up when not all clients returned SaveSuccess
   1100      */
   1101 
   1102     badSavePopup = XtVaCreatePopupShell (
   1103 	"badSavePopup", transientShellWidgetClass, topLevel,
   1104 	XtNallowShellResize, True,
   1105 	NULL);
   1106 
   1107 
   1108     badSaveForm = XtVaCreateManagedWidget (
   1109 	"badSaveForm", formWidgetClass, badSavePopup,
   1110 	NULL);
   1111 
   1112     badSaveLabel = XtVaCreateManagedWidget (
   1113 	"badSaveLabel", labelWidgetClass, badSaveForm,
   1114         XtNfromHoriz, NULL,
   1115         XtNfromVert, NULL,
   1116         XtNborderWidth, 0,
   1117 	XtNtop, XawChainTop,
   1118 	XtNbottom, XawChainTop,
   1119 	NULL);
   1120 
   1121     badSaveListWidget = XtVaCreateManagedWidget (
   1122 	"badSaveListWidget", listWidgetClass, badSaveForm,
   1123 	XtNresizable, True,
   1124         XtNdefaultColumns, 1,
   1125 	XtNforceColumns, True,
   1126         XtNfromHoriz, NULL,
   1127         XtNfromVert, badSaveLabel,
   1128 	XtNtop, XawChainTop,
   1129 	XtNbottom, XawChainBottom,
   1130 	NULL);
   1131 
   1132     XtAddCallback (badSaveListWidget, XtNcallback, BadSaveListXtProc, NULL);
   1133 
   1134     badSaveOkButton = XtVaCreateManagedWidget (
   1135 	"badSaveOkButton", commandWidgetClass, badSaveForm,
   1136         XtNfromHoriz, NULL,
   1137         XtNfromVert, badSaveListWidget,
   1138 	XtNtop, XawChainBottom,
   1139 	XtNbottom, XawChainBottom,
   1140         NULL);
   1141 
   1142     XtAddCallback (badSaveOkButton, XtNcallback, BadSaveOkXtProc, NULL);
   1143 
   1144 
   1145     badSaveCancelButton = XtVaCreateManagedWidget (
   1146 	"badSaveCancelButton", commandWidgetClass, badSaveForm,
   1147         XtNfromHoriz, badSaveOkButton,
   1148         XtNfromVert, badSaveListWidget,
   1149 	XtNtop, XawChainBottom,
   1150 	XtNbottom, XawChainBottom,
   1151         NULL);
   1152 
   1153     XtAddCallback (badSaveCancelButton, XtNcallback, BadSaveCancelXtProc, NULL);
   1154 
   1155     XtInstallAllAccelerators (badSaveForm, badSaveForm);
   1156 }
   1157 
   1158 
   1159 
   1160 void
   1162 PopupSaveDialog(void)
   1163 
   1164 {
   1165     static int first_time = 1;
   1166 
   1167     XtSetSensitive (mainWindow, 0);
   1168     XtSetSensitive (clientInfoPopup, 0);
   1169     XtSetSensitive (clientPropPopup, 0);
   1170 
   1171     XawToggleSetCurrent (saveTypeBoth,
   1172 	(XtPointer) &saveTypeData[2]);
   1173     XawToggleSetCurrent (interactStyleAny,
   1174 	(XtPointer) &interactStyleData[2]);
   1175 
   1176     XtVaSetValues (savePopup,
   1177 	XtNtitle, wantShutdown ? "Shutdown" : "Checkpoint",
   1178 	NULL);
   1179 
   1180     XtVaSetValues (saveName,
   1181 	XtNstring, need_to_name_session ? "" : session_name,
   1182 	NULL);
   1183 
   1184     XtVaSetValues (saveOkButton,
   1185 	XtNlabel, wantShutdown ? "Shutdown" : "Checkpoint",
   1186 	NULL);
   1187 
   1188     PopupPopup (mainWindow, savePopup,
   1189 	True, first_time, 25, 100, "DelSaveWinAction()");
   1190 
   1191     if (first_time)
   1192 	first_time = 0;
   1193 }
   1194 
   1195 
   1196 
   1197 
   1198 void
   1200 CheckPointXtProc(Widget w, XtPointer client_data, XtPointer callData)
   1201 {
   1202     wantShutdown = False;
   1203     PopupSaveDialog ();
   1204 }
   1205 
   1206 
   1207 
   1208 
   1209 void
   1211 ShutdownSaveXtProc(Widget w, XtPointer client_data, XtPointer callData)
   1212 {
   1213     wantShutdown = True;
   1214     PopupSaveDialog ();
   1215 }
   1216 
   1217 
   1218 
   1219 void
   1221 PopupBadSave(void)
   1222 
   1223 {
   1224     ClientRec *client;
   1225     char *progName, *hostname, *tmp1, *tmp2;
   1226     char *clientInfo;
   1227     int maxlen1, maxlen2;
   1228     char extraBuf1[80], extraBuf2[80];
   1229     char *restart_service_prop;
   1230     List *cl, *pl;
   1231     int i, k;
   1232     static int first_time = 1;
   1233 
   1234     if (failedNames)
   1235     {
   1236 	/*
   1237 	 * Free the previous list of names.  Xaw doesn't make a copy of
   1238 	 * our list, so we need to keep it around.
   1239 	 */
   1240 
   1241 	for (i = 0; i < numFailedNames; i++)
   1242 	    XtFree ((char *) failedNames[i]);
   1243 
   1244 	XtFree ((char *) failedNames);
   1245 
   1246 	failedNames = NULL;
   1247     }
   1248 
   1249     maxlen1 = maxlen2 = 0;
   1250     numFailedNames = 0;
   1251 
   1252     for (cl = ListFirst (FailedSaveList); cl; cl = ListNext (cl))
   1253     {
   1254 	client = (ClientRec *) cl->thing;
   1255 
   1256 	progName = NULL;
   1257 	restart_service_prop = NULL;
   1258 
   1259 	for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
   1260 	{
   1261 	    Prop *pprop = (Prop *) pl->thing;
   1262 	    List *vl = ListFirst (pprop->values);
   1263 	    PropValue *pval = (PropValue *) vl->thing;
   1264 
   1265 	    if (strcmp (pprop->name, SmProgram) == 0)
   1266 	    {
   1267 		progName = GetProgramName ((char *) pval->value);
   1268 
   1269 		if ((int) strlen (progName) > maxlen1)
   1270 		    maxlen1 = strlen (progName);
   1271 	    }
   1272 	    else if (strcmp (pprop->name, "_XC_RestartService") == 0)
   1273 	    {
   1274 		restart_service_prop = (char *) pval->value;
   1275 	    }
   1276 	}
   1277 
   1278 	if (!progName)
   1279 	    continue;
   1280 
   1281 	if (restart_service_prop)
   1282 	    tmp1 = restart_service_prop;
   1283 	else if (client->clientHostname)
   1284 	    tmp1 = client->clientHostname;
   1285 	else
   1286 	    continue;
   1287 
   1288 	if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL)
   1289 	    hostname = tmp1;
   1290 	else
   1291 	    hostname = tmp2 + 1;
   1292 
   1293 	if ((int) strlen (hostname) > maxlen2)
   1294 	    maxlen2 = strlen (hostname);
   1295 
   1296 	numFailedNames++;
   1297     }
   1298 
   1299     failedNames = (String *) XtMalloc (
   1300 	numFailedNames * sizeof (String));
   1301 
   1302     i = 0;
   1303     for (cl = ListFirst (FailedSaveList); cl; cl = ListNext (cl))
   1304     {
   1305 	ClientRec *client = (ClientRec *) cl->thing;
   1306 	int extra1, extra2;
   1307 
   1308 	progName = NULL;
   1309 	restart_service_prop = NULL;
   1310 
   1311 	for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
   1312 	{
   1313 	    Prop *pprop = (Prop *) pl->thing;
   1314 	    List *vl = ListFirst (pprop->values);
   1315 	    PropValue *pval = (PropValue *) vl->thing;
   1316 
   1317 	    if (strcmp (pprop->name, SmProgram) == 0)
   1318 	    {
   1319 		progName = GetProgramName ((char *) pval->value);
   1320 	    }
   1321 	    else if (strcmp (pprop->name, "_XC_RestartService") == 0)
   1322 	    {
   1323 		restart_service_prop = (char *) pval->value;
   1324 	    }
   1325 	}
   1326 
   1327 	if (!progName)
   1328 	    continue;
   1329 
   1330 	if (restart_service_prop)
   1331 	    tmp1 = restart_service_prop;
   1332 	else if (client->clientHostname)
   1333 	    tmp1 = client->clientHostname;
   1334 	else
   1335 	    continue;
   1336 
   1337 	if ((tmp2 = (char *) strchr (tmp1, '/')) == NULL)
   1338 	    hostname = tmp1;
   1339 	else
   1340 	    hostname = tmp2 + 1;
   1341 
   1342 	extra1 = maxlen1 - strlen (progName) + 5;
   1343 	extra2 = maxlen2 - strlen (hostname);
   1344 
   1345 	for (k = 0; k < extra1; k++)
   1346 	    extraBuf1[k] = ' ';
   1347 	extraBuf1[extra1] = '\0';
   1348 
   1349 	for (k = 0; k < extra2; k++)
   1350 	    extraBuf2[k] = ' ';
   1351 	extraBuf2[extra2] = '\0';
   1352 
   1353 	XtAsprintf (&clientInfo, "%s%s (%s%s)", progName, extraBuf1,
   1354 	    hostname, extraBuf2);
   1355 
   1356 	failedNames[i++] = clientInfo;
   1357 
   1358 	if (client->freeAfterBadSavePopup)
   1359 	{
   1360 	    FreeClient (client, True /* free props */);
   1361 	}
   1362     }
   1363 
   1364     XawListChange (badSaveListWidget,
   1365 	failedNames, numFailedNames, 0, True);
   1366 
   1367     XtPopdown (savePopup);
   1368 
   1369     if (wantShutdown && !shutdownCancelled)
   1370 	XtManageChild (badSaveCancelButton);
   1371     else
   1372 	XtUnmanageChild (badSaveCancelButton);
   1373 
   1374     PopupPopup (mainWindow, badSavePopup,
   1375 	True, first_time, 25, 100, "DelBadSaveWinAction()");
   1376 
   1377     if (first_time)
   1378 	first_time = 0;
   1379 }
   1380 
   1381 
   1382 
   1383 void
   1385 ShutdownDontSaveXtProc(Widget w, XtPointer client_data, XtPointer callData)
   1386 {
   1387     List	*cl;
   1388     ClientRec 	*client;
   1389 
   1390     if (ListCount (RunningList) == 0)
   1391 	EndSession (0);
   1392 
   1393     /*
   1394      * For any client that was not restarted by the session
   1395      * manager (previous ID was NULL), if we did not issue a
   1396      * checkpoint to this client, remove the client's checkpoint
   1397      * file using the discard command.
   1398      */
   1399 
   1400     for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
   1401     {
   1402 	client = (ClientRec *) cl->thing;
   1403 
   1404 	if (!client->restarted &&
   1405 	    !client->userIssuedCheckpoint &&
   1406 	    client->discardCommand)
   1407 	{
   1408 	    execute_system_command (client->discardCommand);
   1409 	    XtFree (client->discardCommand);
   1410 	    client->discardCommand = NULL;
   1411 	}
   1412     }
   1413 
   1414     shutdownInProgress = True;
   1415 
   1416     for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
   1417     {
   1418 	client = (ClientRec *) cl->thing;
   1419 
   1420 	SmsDie (client->smsConn);
   1421 
   1422 	if (verbose)
   1423 	{
   1424 	    printf ("Client Id = %s, sent DIE\n", client->clientId);
   1425 	}
   1426     }
   1427 }
   1428