choose.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /* $Xorg: choose.c,v 1.4 2001/02/09 02:05:59 xorgcvs Exp $ */
  2. /******************************************************************************
  3. Copyright 1993, 1998 The Open Group
  4. Permission to use, copy, modify, distribute, and sell this software and its
  5. documentation for any purpose is hereby granted without fee, provided that
  6. the above copyright notice appear in all copies and that both that
  7. copyright notice and this permission notice appear in supporting
  8. documentation.
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  15. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  16. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  17. Except as contained in this notice, the name of The Open Group shall not be
  18. used in advertising or otherwise to promote the sale, use or other dealings
  19. in this Software without prior written authorization from The Open Group.
  20. ******************************************************************************/
  21. /* $XFree86: xc/programs/xsm/choose.c,v 1.6tsi Exp $ */
  22. #include "xsm.h"
  23. #include "saveutil.h"
  24. #include "lock.h"
  25. #include "choose.h"
  26. #include <sys/types.h>
  27. #include <X11/Shell.h>
  28. #include <X11/Xaw/Form.h>
  29. #include <X11/Xaw/List.h>
  30. #include <X11/Xaw/Command.h>
  31. #ifndef X_NOT_POSIX
  32. #include <dirent.h>
  33. #else
  34. #ifdef SYSV
  35. #include <dirent.h>
  36. #else
  37. #ifdef USG
  38. #include <dirent.h>
  39. #else
  40. #include <sys/dir.h>
  41. #ifndef dirent
  42. #define dirent direct
  43. #endif
  44. #endif
  45. #endif
  46. #endif
  47. static Pixel save_message_foreground;
  48. static Pixel save_message_background;
  49. static int delete_session_phase = 0;
  50. static int break_lock_phase = 0;
  51. static Widget chooseSessionPopup;
  52. static Widget chooseSessionForm;
  53. static Widget chooseSessionLabel;
  54. static Widget chooseSessionListWidget;
  55. static Widget chooseSessionMessageLabel;
  56. static Widget chooseSessionLoadButton;
  57. static Widget chooseSessionDeleteButton;
  58. static Widget chooseSessionBreakLockButton;
  59. static Widget chooseSessionFailSafeButton;
  60. static Widget chooseSessionCancelButton;
  61. int
  62. GetSessionNames(int *count_ret, String **short_names_ret,
  63. String **long_names_ret, Bool **locked_ret)
  64. {
  65. DIR *dir;
  66. struct dirent *entry;
  67. const char *path;
  68. int count;
  69. path = getenv ("SM_SAVE_DIR");
  70. if (!path)
  71. {
  72. path = getenv ("HOME");
  73. if (!path)
  74. path = ".";
  75. }
  76. *count_ret = 0;
  77. *short_names_ret = NULL;
  78. *locked_ret = NULL;
  79. if (long_names_ret)
  80. *long_names_ret = NULL;
  81. if ((dir = opendir (path)) == NULL)
  82. return 0;
  83. count = 0;
  84. while ((entry = readdir (dir)) != NULL)
  85. {
  86. if (strncmp (entry->d_name, ".XSM-", 5) == 0)
  87. count++;
  88. }
  89. if (count == 0 ||
  90. ((*short_names_ret = (String *) XtMalloc (
  91. count * sizeof (String))) == NULL) ||
  92. (long_names_ret && (*long_names_ret =
  93. (String *) XtMalloc (count * sizeof (String))) == NULL) ||
  94. ((*locked_ret = (Bool *) XtMalloc (count * sizeof (Bool))) == NULL))
  95. {
  96. closedir (dir);
  97. if (*short_names_ret)
  98. XtFree ((char *) *short_names_ret);
  99. if (long_names_ret && *long_names_ret)
  100. XtFree ((char *) *long_names_ret);
  101. return 0;
  102. }
  103. rewinddir (dir);
  104. while ((entry = readdir (dir)) != NULL && *count_ret < count)
  105. {
  106. if (strncmp (entry->d_name, ".XSM-", 5) == 0)
  107. {
  108. char *name = (char *) entry->d_name + 5;
  109. char *id = NULL;
  110. Bool locked = CheckSessionLocked (name, long_names_ret!=NULL, &id);
  111. (*short_names_ret)[*count_ret] = XtNewString (name);
  112. (*locked_ret)[*count_ret] = locked;
  113. if (long_names_ret)
  114. {
  115. if (!locked)
  116. {
  117. (*long_names_ret)[*count_ret] =
  118. (*short_names_ret)[*count_ret];
  119. }
  120. else
  121. {
  122. char *host = ((char *) strchr (id, '/')) + 1;
  123. char *colon = (char *) strrchr (host, ':');
  124. char *lockmsg;
  125. /* backtrack over previous colon if there are 2 (DECnet),
  126. but not three (IPv6) */
  127. if ((*(colon - 1) == ':') && (*(colon - 2) != ':'))
  128. colon--;
  129. *colon = '\0';
  130. XtAsprintf (&lockmsg, "%s (locked at %s)", name, host);
  131. (*long_names_ret)[*count_ret] = lockmsg;
  132. *colon = ':';
  133. XtFree (id);
  134. }
  135. }
  136. (*count_ret)++;
  137. }
  138. }
  139. closedir (dir);
  140. return 1;
  141. }
  142. void
  143. FreeSessionNames(int count, String *namesShort, String *namesLong,
  144. Bool *lockFlags)
  145. {
  146. int i;
  147. for (i = 0; i < count; i++)
  148. XtFree ((char *) namesShort[i]);
  149. XtFree ((char *) namesShort);
  150. if (namesLong)
  151. {
  152. for (i = 0; i < count; i++)
  153. if (lockFlags[i])
  154. XtFree ((char *) namesLong[i]);
  155. XtFree ((char *) namesLong);
  156. }
  157. XtFree ((char *) lockFlags);
  158. }
  159. static void
  160. SessionSelected(int number, Bool highlight)
  161. {
  162. if (number >= 0)
  163. {
  164. Bool locked = sessionsLocked[number];
  165. if (highlight)
  166. XawListHighlight (chooseSessionListWidget, number);
  167. XtSetSensitive (chooseSessionLoadButton, !locked);
  168. XtSetSensitive (chooseSessionDeleteButton, !locked);
  169. XtSetSensitive (chooseSessionBreakLockButton, locked);
  170. }
  171. else
  172. {
  173. XtSetSensitive (chooseSessionLoadButton, False);
  174. XtSetSensitive (chooseSessionDeleteButton, False);
  175. XtSetSensitive (chooseSessionBreakLockButton, False);
  176. }
  177. }
  178. static void
  179. AddSessionNames(int count, String *names)
  180. {
  181. int i;
  182. XawListChange (chooseSessionListWidget, names, count, 0, True);
  183. /*
  184. * Highlight the first unlocked session, if any.
  185. */
  186. for (i = 0; i < sessionNameCount; i++)
  187. if (!sessionsLocked[i])
  188. break;
  189. SessionSelected (i < sessionNameCount ? i : -1, True);
  190. }
  191. void
  192. ChooseWindowStructureNotifyXtHandler(Widget w, XtPointer closure,
  193. XEvent *event,
  194. Boolean *continue_to_dispatch)
  195. {
  196. if (event->type == MapNotify)
  197. {
  198. /*
  199. * Set the input focus to the choose window and direct all keyboard
  200. * events to the list widget. This way, the user can make selections
  201. * using the keyboard.
  202. */
  203. XtSetKeyboardFocus (chooseSessionPopup, chooseSessionListWidget);
  204. XSetInputFocus (XtDisplay (topLevel), XtWindow (chooseSessionPopup),
  205. RevertToPointerRoot, CurrentTime);
  206. XSync (XtDisplay (topLevel), 0);
  207. XtRemoveEventHandler (chooseSessionPopup, StructureNotifyMask, False,
  208. ChooseWindowStructureNotifyXtHandler, NULL);
  209. }
  210. }
  211. void
  212. ChooseSession(void)
  213. {
  214. Dimension width, height;
  215. Position x, y;
  216. /*
  217. * Add the session names to the list
  218. */
  219. AddSessionNames (sessionNameCount, sessionNamesLong);
  220. /*
  221. * Center popup containing choice of sessions
  222. */
  223. XtRealizeWidget (chooseSessionPopup);
  224. XtVaGetValues (chooseSessionPopup,
  225. XtNwidth, &width,
  226. XtNheight, &height,
  227. NULL);
  228. x = (Position)(WidthOfScreen (XtScreen (topLevel)) - width) / 2;
  229. y = (Position)(HeightOfScreen (XtScreen (topLevel)) - height) / 3;
  230. XtVaSetValues (chooseSessionPopup,
  231. XtNx, x,
  232. XtNy, y,
  233. NULL);
  234. XtVaSetValues (chooseSessionListWidget,
  235. XtNlongest, width,
  236. NULL);
  237. XtVaSetValues (chooseSessionLabel,
  238. XtNwidth, width,
  239. NULL);
  240. XtVaGetValues (chooseSessionMessageLabel,
  241. XtNforeground, &save_message_foreground,
  242. XtNbackground, &save_message_background,
  243. NULL);
  244. XtVaSetValues (chooseSessionMessageLabel,
  245. XtNwidth, width,
  246. XtNforeground, save_message_background,
  247. NULL);
  248. /*
  249. * Wait for a map notify on the popup, then set input focus.
  250. */
  251. XtAddEventHandler (chooseSessionPopup, StructureNotifyMask, False,
  252. ChooseWindowStructureNotifyXtHandler, NULL);
  253. XtPopup (chooseSessionPopup, XtGrabNone);
  254. }
  255. static void
  256. CheckDeleteCancel (void)
  257. {
  258. if (delete_session_phase > 0)
  259. {
  260. XtVaSetValues (chooseSessionMessageLabel,
  261. XtNforeground, save_message_background,
  262. NULL);
  263. delete_session_phase = 0;
  264. }
  265. }
  266. static void
  267. CheckBreakLockCancel(void)
  268. {
  269. if (break_lock_phase > 0)
  270. {
  271. XtVaSetValues (chooseSessionMessageLabel,
  272. XtNforeground, save_message_background,
  273. NULL);
  274. break_lock_phase = 0;
  275. }
  276. }
  277. static void
  278. ChooseSessionUp(Widget w, XEvent *event, String *params, Cardinal *numParams)
  279. {
  280. XawListReturnStruct *current;
  281. CheckDeleteCancel ();
  282. CheckBreakLockCancel ();
  283. current = XawListShowCurrent (chooseSessionListWidget);
  284. if (current->list_index > 0)
  285. SessionSelected (current->list_index - 1, True);
  286. XtFree ((char *) current);
  287. }
  288. static void
  289. ChooseSessionDown(Widget w, XEvent *event, String *params, Cardinal *numParams)
  290. {
  291. XawListReturnStruct *current;
  292. CheckDeleteCancel ();
  293. CheckBreakLockCancel ();
  294. current = XawListShowCurrent (chooseSessionListWidget);
  295. if (current->list_index < sessionNameCount - 1)
  296. SessionSelected (current->list_index + 1, True);
  297. XtFree ((char *) current);
  298. }
  299. static void
  300. ChooseSessionBtn1Down(Widget w, XEvent *event, String *params,
  301. Cardinal *numParams)
  302. {
  303. XawListReturnStruct *current;
  304. CheckDeleteCancel ();
  305. CheckBreakLockCancel ();
  306. current = XawListShowCurrent (chooseSessionListWidget);
  307. SessionSelected (current->list_index, False /* already highlighted */);
  308. XtFree ((char *) current);
  309. }
  310. static void
  311. ChooseSessionLoadXtProc(Widget w, XtPointer client_data, XtPointer callData)
  312. {
  313. XawListReturnStruct *current;
  314. CheckDeleteCancel ();
  315. CheckBreakLockCancel ();
  316. current = XawListShowCurrent (chooseSessionListWidget);
  317. if (!current || !current->string || *(current->string) == '\0')
  318. {
  319. if (current)
  320. XtFree ((char *) current);
  321. #ifdef XKB
  322. XkbStdBell(XtDisplay(topLevel),XtWindow(topLevel),0,XkbBI_BadValue);
  323. #else
  324. XBell (XtDisplay (topLevel), 0);
  325. #endif
  326. return;
  327. }
  328. /*
  329. * Pop down choice of sessions and start the specified session.
  330. */
  331. XtPopdown (chooseSessionPopup);
  332. if (session_name)
  333. XtFree (session_name);
  334. session_name = XtNewString (current->string);
  335. XtFree ((char *) current);
  336. FreeSessionNames (sessionNameCount,
  337. sessionNamesShort, sessionNamesLong, sessionsLocked);
  338. /*
  339. * Start the session, looking for .XSM-<session name> startup file.
  340. */
  341. if (!StartSession (session_name, False))
  342. UnableToLockSession (session_name);
  343. }
  344. static void
  345. ChooseSessionDeleteXtProc(Widget w, XtPointer client_data, XtPointer callData)
  346. {
  347. XawListReturnStruct *current;
  348. int longest;
  349. char *name;
  350. CheckBreakLockCancel ();
  351. current = XawListShowCurrent (chooseSessionListWidget);
  352. if (!current || !(name = current->string) || *name == '\0')
  353. {
  354. if (current)
  355. XtFree ((char *) current);
  356. #ifdef XKB
  357. XkbStdBell(XtDisplay(w),XtWindow(w),0,XkbBI_BadValue);
  358. #else
  359. XBell (XtDisplay (topLevel), 0);
  360. #endif
  361. return;
  362. }
  363. delete_session_phase++;
  364. if (delete_session_phase == 1)
  365. {
  366. XtVaSetValues (chooseSessionMessageLabel,
  367. XtNforeground, save_message_foreground,
  368. NULL);
  369. #ifdef XKB
  370. XkbStdBell(XtDisplay(w),XtWindow(w),0,XkbBI_BadValue);
  371. #else
  372. XBell (XtDisplay (topLevel), 0);
  373. #endif
  374. }
  375. else
  376. {
  377. XtVaSetValues (chooseSessionMessageLabel,
  378. XtNforeground, save_message_background,
  379. NULL);
  380. if (DeleteSession (name))
  381. {
  382. int i, j;
  383. for (i = 0; i < sessionNameCount; i++)
  384. {
  385. if (strcmp (sessionNamesLong[i], name) == 0)
  386. {
  387. XtFree ((char *) sessionNamesShort[i]);
  388. if (sessionsLocked[i])
  389. XtFree ((char *) sessionNamesLong[i]);
  390. for (j = i; j < sessionNameCount - 1; j++)
  391. {
  392. sessionNamesLong[j] = sessionNamesLong[j + 1];
  393. sessionNamesShort[j] = sessionNamesShort[j + 1];
  394. sessionsLocked[j] = sessionsLocked[j + 1];
  395. }
  396. sessionNameCount--;
  397. break;
  398. }
  399. }
  400. if (sessionNameCount == 0)
  401. {
  402. XtSetSensitive (chooseSessionLoadButton, 0);
  403. XtSetSensitive (chooseSessionDeleteButton, 0);
  404. XtUnmanageChild (chooseSessionListWidget);
  405. }
  406. else
  407. {
  408. XtVaGetValues (chooseSessionListWidget,
  409. XtNlongest, &longest,
  410. NULL);
  411. XawListChange (chooseSessionListWidget,
  412. sessionNamesLong, sessionNameCount, longest, True);
  413. SessionSelected (-1, False);
  414. }
  415. }
  416. delete_session_phase = 0;
  417. }
  418. XtFree ((char *) current);
  419. }
  420. static void
  421. ChooseSessionBreakLockXtProc(Widget w, XtPointer client_data,
  422. XtPointer callData)
  423. {
  424. XawListReturnStruct *current;
  425. char *name;
  426. CheckDeleteCancel ();
  427. current = XawListShowCurrent (chooseSessionListWidget);
  428. if (!current || !(name = current->string) || *name == '\0')
  429. {
  430. if (current)
  431. XtFree ((char *) current);
  432. #ifdef XKB
  433. XkbStdBell(XtDisplay(topLevel),XtWindow(topLevel),0,XkbBI_BadValue);
  434. #else
  435. XBell (XtDisplay (topLevel), 0);
  436. #endif
  437. return;
  438. }
  439. break_lock_phase++;
  440. if (break_lock_phase == 1)
  441. {
  442. XtVaSetValues (chooseSessionMessageLabel,
  443. XtNforeground, save_message_foreground,
  444. NULL);
  445. #ifdef XKB
  446. XkbStdBell(XtDisplay(topLevel),XtWindow(topLevel),0,XkbBI_BadValue);
  447. #else
  448. XBell (XtDisplay (topLevel), 0);
  449. #endif
  450. }
  451. else
  452. {
  453. int longest;
  454. XtVaSetValues (chooseSessionMessageLabel,
  455. XtNforeground, save_message_background,
  456. NULL);
  457. name = sessionNamesShort[current->list_index];
  458. (void) GetLockId (name);
  459. UnlockSession (name);
  460. sessionsLocked[current->list_index] = False;
  461. XtFree ((char *) sessionNamesLong[current->list_index]);
  462. sessionNamesLong[current->list_index] =
  463. sessionNamesShort[current->list_index];
  464. XtVaGetValues (chooseSessionListWidget,
  465. XtNlongest, &longest,
  466. NULL);
  467. XawListChange (chooseSessionListWidget,
  468. sessionNamesLong, sessionNameCount, longest, True);
  469. SessionSelected (current->list_index, True);
  470. break_lock_phase = 0;
  471. }
  472. XtFree ((char *) current);
  473. }
  474. static void
  475. ChooseSessionFailSafeXtProc(Widget w, XtPointer client_data,
  476. XtPointer callData)
  477. {
  478. /*
  479. * Pop down choice of sessions, and start the fail safe session.
  480. */
  481. CheckDeleteCancel ();
  482. CheckBreakLockCancel ();
  483. XtPopdown (chooseSessionPopup);
  484. if (session_name)
  485. XtFree (session_name);
  486. session_name = XtNewString (FAILSAFE_SESSION_NAME);
  487. FreeSessionNames (sessionNameCount,
  488. sessionNamesShort, sessionNamesLong, sessionsLocked);
  489. /*
  490. * We don't need to check return value of StartSession in this case,
  491. * because we are using the default session, and StartSession will
  492. * not try to lock the session at this time. It will try to lock
  493. * it as soon as the user gives the session a name.
  494. */
  495. StartSession (session_name,
  496. True /* Use ~/.xsmstartup if found, else system.xsm */);
  497. }
  498. static void
  499. ChooseSessionCancelXtProc(Widget w, XtPointer client_data, XtPointer callData)
  500. {
  501. if (delete_session_phase > 0 || break_lock_phase > 0)
  502. {
  503. XtVaSetValues (chooseSessionMessageLabel,
  504. XtNforeground, save_message_background,
  505. NULL);
  506. delete_session_phase = 0;
  507. break_lock_phase = 0;
  508. }
  509. else
  510. EndSession (2);
  511. }
  512. void
  513. create_choose_session_popup(void)
  514. {
  515. static XtActionsRec choose_actions[] = {
  516. {"ChooseSessionUp", ChooseSessionUp},
  517. {"ChooseSessionDown", ChooseSessionDown},
  518. {"ChooseSessionBtn1Down", ChooseSessionBtn1Down}
  519. };
  520. /*
  521. * Pop up for choosing session at startup
  522. */
  523. chooseSessionPopup = XtVaCreatePopupShell (
  524. "chooseSessionPopup", transientShellWidgetClass, topLevel,
  525. XtNallowShellResize, True,
  526. NULL);
  527. chooseSessionForm = XtVaCreateManagedWidget (
  528. "chooseSessionForm", formWidgetClass, chooseSessionPopup,
  529. NULL);
  530. chooseSessionLabel = XtVaCreateManagedWidget (
  531. "chooseSessionLabel", labelWidgetClass, chooseSessionForm,
  532. XtNfromHoriz, NULL,
  533. XtNfromVert, NULL,
  534. XtNborderWidth, 0,
  535. XtNresizable, True,
  536. XtNjustify, XtJustifyCenter,
  537. NULL);
  538. chooseSessionListWidget = XtVaCreateManagedWidget (
  539. "chooseSessionListWidget", listWidgetClass, chooseSessionForm,
  540. XtNresizable, True,
  541. XtNdefaultColumns, 1,
  542. XtNforceColumns, True,
  543. XtNfromHoriz, NULL,
  544. XtNfromVert, chooseSessionLabel,
  545. XtNvertDistance, 25,
  546. NULL);
  547. chooseSessionMessageLabel = XtVaCreateManagedWidget (
  548. "chooseSessionMessageLabel", labelWidgetClass, chooseSessionForm,
  549. XtNfromHoriz, NULL,
  550. XtNfromVert, chooseSessionListWidget,
  551. XtNborderWidth, 0,
  552. XtNresizable, True,
  553. XtNjustify, XtJustifyCenter,
  554. NULL);
  555. chooseSessionLoadButton = XtVaCreateManagedWidget (
  556. "chooseSessionLoadButton", commandWidgetClass, chooseSessionForm,
  557. XtNfromHoriz, NULL,
  558. XtNfromVert, chooseSessionMessageLabel,
  559. NULL);
  560. XtAddCallback (chooseSessionLoadButton, XtNcallback,
  561. ChooseSessionLoadXtProc, NULL);
  562. chooseSessionDeleteButton = XtVaCreateManagedWidget (
  563. "chooseSessionDeleteButton", commandWidgetClass, chooseSessionForm,
  564. XtNfromHoriz, chooseSessionLoadButton,
  565. XtNfromVert, chooseSessionMessageLabel,
  566. NULL);
  567. XtAddCallback (chooseSessionDeleteButton, XtNcallback,
  568. ChooseSessionDeleteXtProc, NULL);
  569. chooseSessionBreakLockButton = XtVaCreateManagedWidget (
  570. "chooseSessionBreakLockButton",
  571. commandWidgetClass, chooseSessionForm,
  572. XtNfromHoriz, chooseSessionDeleteButton,
  573. XtNfromVert, chooseSessionMessageLabel,
  574. NULL);
  575. XtAddCallback (chooseSessionBreakLockButton, XtNcallback,
  576. ChooseSessionBreakLockXtProc, NULL);
  577. chooseSessionFailSafeButton = XtVaCreateManagedWidget (
  578. "chooseSessionFailSafeButton", commandWidgetClass, chooseSessionForm,
  579. XtNfromHoriz, chooseSessionBreakLockButton,
  580. XtNfromVert, chooseSessionMessageLabel,
  581. NULL);
  582. XtAddCallback (chooseSessionFailSafeButton, XtNcallback,
  583. ChooseSessionFailSafeXtProc, NULL);
  584. chooseSessionCancelButton = XtVaCreateManagedWidget (
  585. "chooseSessionCancelButton", commandWidgetClass, chooseSessionForm,
  586. XtNfromHoriz, chooseSessionFailSafeButton,
  587. XtNfromVert, chooseSessionMessageLabel,
  588. NULL);
  589. XtAddCallback (chooseSessionCancelButton, XtNcallback,
  590. ChooseSessionCancelXtProc, NULL);
  591. XtAppAddActions (appContext, choose_actions, XtNumber (choose_actions));
  592. XtInstallAllAccelerators (chooseSessionListWidget, chooseSessionPopup);
  593. }