home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / ddd.C < prev    next >
C/C++ Source or Header  |  1998-12-06  |  230KB  |  7,504 lines

  1. // $Id: ddd.C,v 1.566.4.1 1998/12/06 15:36:20 zeller Exp $
  2. // DDD main program (and much more)
  3.  
  4. // Copyright (C) 1995-1998 Technische Universitaet Braunschweig, Germany.
  5. // Written by Dorothea Luetkehaus <luetke@ips.cs.tu-bs.de>
  6. // and Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  7. // 
  8. // This file is part of DDD.
  9. // 
  10. // DDD is free software; you can redistribute it and/or
  11. // modify it under the terms of the GNU General Public
  12. // License as published by the Free Software Foundation; either
  13. // version 2 of the License, or (at your option) any later version.
  14. // 
  15. // DDD is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18. // See the GNU General Public License for more details.
  19. // 
  20. // You should have received a copy of the GNU General Public
  21. // License along with DDD -- see the file COPYING.
  22. // If not, write to the Free Software Foundation, Inc.,
  23. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24. // 
  25. // DDD is the data display debugger.
  26. // For details, see the DDD World-Wide-Web page, 
  27. // `http://www.cs.tu-bs.de/softech/ddd/',
  28. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  29.  
  30. char ddd_rcsid[] =
  31.     "$Id: ddd.C,v 1.566.4.1 1998/12/06 15:36:20 zeller Exp $";
  32.  
  33. // Introduction to DDD
  34. // ===================
  35. //
  36. // :bug: n.  An unwanted and unintended property of a program or
  37. // piece of hardware, esp. one that causes it to malfunction.
  38. // Antonym of {feature}.  Examples: "There's a bug in the editor: 
  39. // it writes things out backwards."  "The system crashed because of  
  40. // a hardware bug."  "Fred is a winner, but he has a few bugs"
  41. // (i.e., Fred is a good guy, but he has a few personality problems).
  42. //
  43. // Historical note: Admiral Grace Hopper (an early computing pioneer  
  44. // better known for inventing {COBOL}) liked to tell a story in  
  45. // which a technician solved a {glitch} in the Harvard Mark II
  46. // machine by pulling an actual insect out from between the contacts
  47. // of one of its relays, and she subsequently promulgated {bug} in
  48. // its hackish sense as a joke about the incident (though, as she was
  49. // careful to admit, she was not there when it happened).  For many
  50. // years the logbook associated with the incident and the actual bug 
  51. // in question (a moth) sat in a display case at the Naval Surface
  52. // Warfare Center (NSWC).  The entire story, with a picture of the 
  53. // logbook and the moth taped into it, is recorded in the "Annals
  54. // of the History of Computing", Vol. 3, No. 3 (July 1981),
  55. // pp. 285--286.
  56. //
  57. // The text of the log entry (from September 9, 1947), reads "1545
  58. // Relay #70 Panel F (moth) in relay.  First actual case of bug being
  59. //  found".  This wording establishes that the term was already
  60. // in use at the time in its current specific sense -- and Hopper
  61. // herself reports that the term `bug' was regularly applied to
  62. // problems in radar electronics during WWII.
  63. //
  64. // Indeed, the use of `bug' to mean an industrial defect was already  
  65. // established in Thomas Edison's time, and a more specific and rather
  66. // modern use can be found in an electrical handbook from 1896 
  67. // ("Hawkin's New Catechism of Electricity", Theo. Audel & Co.)
  68. // which says: "The term `bug' is used to a limited extent to
  69. // designate any fault or trouble in the connections or working of 
  70. // electric apparatus."  It further notes that the term is "said to  
  71. // have originated in quadruplex telegraphy and have been transferred
  72. // to all electric apparatus."
  73. //
  74. // The latter observation may explain a common folk etymology of the 
  75. // term; that it came from telephone company usage, in which "bugs in
  76. // a telephone cable" were blamed for noisy lines.  Though this
  77. // derivation seems to be mistaken, it may well be a distorted memory
  78. // of a joke first current among *telegraph* operators more than
  79. // a century ago!
  80. //
  81. // Actually, use of `bug' in the general sense of a disruptive event
  82. // goes back to Shakespeare!  In the first edition of Samuel Johnson's
  83. // dictionary one meaning of `bug' is "A frightful object; a 
  84. // walking spectre"; this is traced to `bugbear', a Welsh term for
  85. // a variety of mythological monster which (to complete the circle)
  86. // has recently been reintroduced into the popular lexicon through 
  87. // fantasy role-playing games.
  88. //
  89. // In any case, in jargon the word almost never refers to insects.
  90. // Here is a plausible conversation that never actually happened:
  91. //
  92. // "There is a bug in this ant farm!"
  93. //
  94. // "What do you mean?  I don't see any ants in it."
  95. //
  96. // "That's the bug."
  97. //
  98. // A careful discussion of the etymological issues can be found in a
  99. // paper by Fred R. Shapiro, 1987, "Entomology of the Computer Bug: 
  100. // History and Folklore", American Speech 62(4):376-378.
  101. //
  102. // [There has been a widespread myth that the original bug was moved
  103. // to the Smithsonian, and an earlier version of this entry so 
  104. // asserted.  A correspondent who thought to check discovered that the
  105. // bug was not there.  While investigating this in late 1990, your 
  106. // editor discovered that the NSWC still had the bug, but had 
  107. // unsuccessfully tried to get the Smithsonian to accept it -- and
  108. // that the present curator of their History of American Technology
  109. // Museum didn't know this and agreed that it would make a worthwhile
  110. // exhibit.  It was moved to the Smithsonian in mid-1991, but due to 
  111. // space and money constraints has not yet been exhibited.  Thus, the
  112. // process of investigating the original-computer-bug bug fixed it in
  113. // an entirely unexpected way, by making the myth true!  -- ESR]
  114.  
  115.  
  116.  
  117. //-----------------------------------------------------------------------------
  118. // Name conventions used:
  119. // ...CB : Callback function,
  120. // ...DCB: Dialog callback function,
  121. // ...CD : Create a dialog
  122. // ...Act: Action procedure
  123. // ...HP : Handler procedure (see `HandlerL.h' for details)
  124. //-----------------------------------------------------------------------------
  125.  
  126. #ifdef __GNUG__
  127. #pragma implementation
  128. #endif
  129.  
  130. #include "config.h"
  131. // #include "MemCheckD.h"
  132.  
  133. //-----------------------------------------------------------------------------
  134. // Includes
  135. //-----------------------------------------------------------------------------
  136.  
  137. #include "ddd.h"
  138.  
  139. // Motif stuff
  140. #include <Xm/Xm.h>
  141. #include <Xm/AtomMgr.h>
  142. #include <Xm/CutPaste.h>
  143. #include <Xm/DrawingA.h>
  144. #include <Xm/MainW.h>
  145. #include <Xm/PanedW.h>
  146. #include <Xm/Label.h>
  147. #include <Xm/LabelG.h>
  148. #include <Xm/Frame.h>
  149. #include <Xm/Text.h>
  150. #include <Xm/MessageB.h>
  151. #include <Xm/RowColumn.h>    // XmCreateWorkArea()
  152. #include <Xm/Protocols.h>
  153. #include <Xm/SelectioB.h>
  154. #include <Xm/DialogS.h>
  155. #include <Xm/Form.h>
  156. #include <Xm/TextF.h>
  157. #include <Xm/ToggleB.h>
  158. #include <Xm/PushB.h>
  159. #include <Xm/ArrowB.h>
  160. #include <Xm/MwmUtil.h>
  161. #include <X11/Shell.h>
  162.  
  163. #if XmVersion >= 1002
  164. #include <Xm/Display.h>
  165. #include <Xm/DragDrop.h>
  166. #include <Xm/RepType.h>        // XmRepTypeInstallTearOffModelConverter()
  167. #endif
  168.  
  169. #if HAVE_X11_XMU_EDITRES_H
  170. #include <X11/Xmu/Editres.h>
  171. #endif
  172.  
  173. #include <X11/IntrinsicP.h>    // LessTif hacks
  174. #include "Sash.h"
  175. #include "LessTifH.h"
  176.  
  177. // ANSI C++ doesn't like the XtIsRealized() macro
  178. #ifdef XtIsRealized
  179. #undef XtIsRealized
  180. #endif
  181.  
  182. // Lots of DDD stuff
  183. #include "AgentM.h"
  184. #include "AppData.h"
  185. #include "ArgField.h"
  186. #include "DataDisp.h"
  187. #include "DestroyCB.h"
  188. #include "DispGraph.h"
  189. #include "DispGraph.h"
  190. #include "DispBox.h"
  191. #include "DispValue.h"
  192. #include "ExitCB.h"
  193. #include "GraphEdit.h"
  194. #include "GDBAgent.h"
  195. #include "HistoryD.h"
  196. #include "LabelH.h"
  197. #include "MakeMenu.h"
  198. #include "PlotAgent.h"
  199. #include "SourceView.h"
  200. #include "Swallower.h"
  201. #include "TimeOut.h"
  202. #include "UndoBuffer.h"
  203. #include "VSEFlags.h"
  204. #include "XErrorB.h"
  205. #include "args.h"
  206. #include "assert.h"
  207. #include "bool.h"
  208. #include "buttons.h"
  209. #include "charsets.h"
  210. #include "cmdtty.h"
  211. #include "comm-manag.h"
  212. #include "Command.h"
  213. #include "complete.h"
  214. #include "converters.h"
  215. #include "cook.h"
  216. #include "data.h"
  217. #include "dbx-lookup.h"
  218. #include "deref.h"
  219. #include "disp-read.h"
  220. #include "editing.h"
  221. #include "environ.h"
  222. #include "examine.h"
  223. #include "exectty.h"
  224. #include "exit.h"
  225. #include "expired.h"
  226. #include "file.h"
  227. #include "filetype.h"
  228. #include "findParent.h"
  229. #include "fonts.h"
  230. #include "frame.h"
  231. #include "gdbinit.h"
  232. #include "getrlimit.h"
  233. #include "history.h"
  234. #include "home.h"
  235. #include "host.h"
  236. #include "hostname.h"
  237. #include "logo.h"
  238. #include "logplayer.h"
  239. #include "longName.h"
  240. #include "mainloop.h"
  241. #include "options.h"
  242. #include "post.h"
  243. #include "print.h"
  244. #include "question.h"
  245. #include "regexps.h"
  246. #include "resources.h"
  247. #include "sashes.h"
  248. #include "select.h"
  249. #include "selection.h"
  250. #include "session.h"
  251. #include "settings.h"
  252. #include "shell.h"
  253. #include "shorten.h"
  254. #include "show.h"
  255. #include "simpleMenu.h"
  256. #include "source.h"
  257. #include "status.h"
  258. #include "strclass.h"
  259. #include "string-fun.h"
  260. #include "tictactoe.h"
  261. #include "tips.h"
  262. #include "toolbar.h"
  263. #include "ungrab.h"
  264. #include "verify.h"
  265. #include "version.h"
  266. #include "windows.h"
  267. #include "wm.h"
  268. #include "xconfig.h"
  269.  
  270. // Standard stuff
  271. #include <stdlib.h>
  272. #include <iostream.h>
  273. #include <fstream.h>
  274. #include <time.h>
  275. #include <signal.h>
  276.  
  277. #include <limits.h>
  278. #ifndef ARG_MAX
  279. #define ARG_MAX 4096
  280. #endif
  281.  
  282. #if HAVE_EXCEPTIONS && HAVE_EXCEPTION
  283. #include <exception>
  284. #endif
  285.  
  286.  
  287. //-----------------------------------------------------------------------------
  288. // Forward function decls
  289. //-----------------------------------------------------------------------------
  290.  
  291. // Callbacks
  292. static void gdb_readyHP        (Agent *, void *, void *);
  293. static void gdb_strangeHP      (Agent *, void *, void *);
  294. static void gdb_recordingHP    (Agent *, void *, void *);
  295. static void gdb_panicHP        (Agent *, void *, void *);
  296. static void gdb_echo_detectedHP(Agent *, void *, void *);
  297. static void language_changedHP (Agent *, void *, void *);
  298. static void report_languageHP  (Agent *, void *, void *);
  299. static void source_argHP       (void *, void *, void *call_data);
  300.  
  301. // Warning proc
  302. static void ddd_xt_warning(String message);
  303.  
  304. // Getting ready
  305. static void WhenReady            (Widget, XtPointer, XtPointer);
  306.  
  307. // Cut and Paste
  308. static void gdbCutSelectionCB    (Widget, XtPointer, XtPointer);
  309. static void gdbCopySelectionCB   (Widget, XtPointer, XtPointer);
  310. static void gdbPasteClipboardCB  (Widget, XtPointer, XtPointer);
  311. static void gdbDeleteSelectionCB (Widget, XtPointer, XtPointer);
  312. static void gdbClearAllCB        (Widget, XtPointer, XtPointer);
  313. static void gdbSelectAllCB       (Widget, XtPointer, XtPointer);
  314. static void gdbUnselectAllCB     (Widget, XtPointer, XtPointer);
  315.  
  316. // Update menus
  317. static void gdbUpdateEditCB      (Widget, XtPointer, XtPointer);
  318. static void gdbUpdateFileCB      (Widget, XtPointer, XtPointer);
  319. static void gdbUpdateViewCB      (Widget, XtPointer, XtPointer);
  320. static void gdbUpdateViewsCB     (Widget, XtPointer, XtPointer);
  321. static void gdbUpdateAllMenus();
  322.  
  323. // Preferences
  324. static void make_preferences (Widget parent);
  325. static void dddPopupPreferencesCB (Widget, XtPointer, XtPointer);
  326.  
  327. // Synchronize `():' fields
  328. static void sync_args(ArgField *a1, ArgField *a2);
  329.  
  330. // Return true if user interaction events are pending
  331. static bool pending_interaction();
  332.  
  333. // Create status line
  334. static void create_status(Widget parent);
  335.  
  336. // Status LED
  337. static void blink(bool set);
  338. static void ToggleBlinkCB(Widget, XtPointer client_data, XtPointer call_data);
  339. static void DisableBlinkHP(Agent *, void *, void *);
  340.  
  341. // GDB Status
  342. static void ReportStartHP(Agent *, void *, void *);
  343. static void ReportDeathHP(Agent *, void *, void *);
  344.  
  345. // Status history
  346. static void PopupStatusHistoryCB(Widget, XtPointer, XtPointer);
  347. static void PopdownStatusHistoryCB(Widget, XtPointer, XtPointer);
  348.  
  349. // Argument callback
  350. static void ActivateCB(Widget, XtPointer client_data, XtPointer call_data);
  351.  
  352. // Drag and drop
  353. static void CheckDragCB(Widget, XtPointer client_data, XtPointer call_data);
  354.  
  355. // Verify whether buttons are active
  356. static void verify_buttons(MMDesc *items);
  357.  
  358. // Setup shortcut menu
  359. static void set_shortcut_menu(DataDisp *data_disp, string expressions);
  360. static void set_shortcut_menu(DataDisp *data_disp);
  361.  
  362. // Fix the size of the status line
  363. static void fix_status_size();
  364.  
  365. // Setup new shell
  366. static void setup_new_shell(Widget w);
  367.  
  368. // Check if window manager decorates transients
  369. static void start_have_decorated_transients(Widget parent);
  370. static bool have_decorated_transients();
  371.  
  372. // Set `Settings' title
  373. static void set_settings_title(Widget w);
  374.  
  375. // Set Cut/Copy/Paste bindings for MENU to STYLE
  376. static void set_cut_copy_paste_bindings(MMDesc *menu, BindingStyle style);
  377.  
  378. // Set Select All bindings for MENU to STYLE
  379. static void set_select_all_bindings(MMDesc *menu, BindingStyle style);
  380.  
  381. // Popup DDD splash screen upon start-up.
  382. static void SetSplashScreenCB(Widget, XtPointer, XtPointer);
  383. static void popup_splash_screen(Widget parent, string color_key);
  384. static void popdown_splash_screen(XtPointer data = 0, XtIntervalId *id = 0);
  385.  
  386. // Read in database from FILENAME.  Upon version mismatch, ignore some
  387. // resources such as window sizes.
  388. static XrmDatabase GetFileDatabase(char *filename);
  389.  
  390. // Lock `~/.ddd'
  391. static bool lock_ddd(Widget parent, LockInfo& info);
  392.  
  393. // Various setups
  394. static void setup_version_info();
  395. static void setup_environment();
  396. static void setup_command_tool();
  397. static void setup_options(int& argc, char *argv[],
  398.               StringArray& saved_options, string& gdb_name,
  399.               bool& no_windows);
  400. static void setup_tty();
  401. static void setup_ddd_version_warnings();
  402. static void setup_motif_version_warnings();
  403. static void setup_auto_command_prefix();
  404. static void setup_core_limit();
  405. static void setup_options();
  406. static void setup_cut_copy_paste_bindings(XrmDatabase db);
  407. static void setup_select_all_bindings(XrmDatabase db);
  408. static void setup_show(XrmDatabase db, char *app_name, char *gdb_name);
  409.  
  410. // Help hooks
  411. static void PreHelpOnContext(Widget w, XtPointer, XtPointer);
  412. static void PostHelpOnItem(Widget item);
  413.  
  414. // Log player stuff
  415. static void check_log(const string& logname, DebuggerType& type);
  416.  
  417. // Add current selection as argument
  418. static void add_arg_from_selection(Widget toplevel, int& argc, char **&argv);
  419.  
  420. #if XmVersion < 2000
  421. static void toggleOverstrikeAct (Widget, XEvent*, String*, Cardinal*) {}
  422. #endif
  423.  
  424.  
  425. //-----------------------------------------------------------------------------
  426. // Xt Stuff
  427. //-----------------------------------------------------------------------------
  428.  
  429. static char ON[]  = "on";
  430. static char OFF[] = "off";
  431.  
  432. // Options
  433. // Note: we support both the GDB '--OPTION' and the X '-OPTION' convention.
  434. static XrmOptionDescRec options[] = {
  435. { "--session",              XtNsession,              XrmoptionSepArg, NULL },
  436. { "-session",               XtNsession,              XrmoptionSepArg, NULL },
  437.  
  438. { "-xtsessionID",           XtNsession,              XrmoptionSepArg, NULL },
  439.  
  440. { "--debugger",             XtNdebuggerCommand,      XrmoptionSepArg, NULL },
  441. { "-debugger",              XtNdebuggerCommand,      XrmoptionSepArg, NULL },
  442.  
  443. { "--automatic-debugger",   XtNautoDebugger,         XrmoptionNoArg,  ON },
  444. { "-automatic-debugger",    XtNautoDebugger,         XrmoptionNoArg,  ON },
  445.  
  446. { "--gdb",                  XtNdebugger,             XrmoptionNoArg,  "gdb" },
  447. { "-gdb",                   XtNdebugger,             XrmoptionNoArg,  "gdb" },
  448.  
  449. { "--dbx",                  XtNdebugger,             XrmoptionNoArg,  "dbx" },
  450. { "-dbx",                   XtNdebugger,             XrmoptionNoArg,  "dbx" },
  451.  
  452. { "--xdb",                  XtNdebugger,             XrmoptionNoArg,  "xdb" },
  453. { "-xdb",                   XtNdebugger,             XrmoptionNoArg,  "xdb" },
  454.  
  455. { "--jdb",                  XtNdebugger,             XrmoptionNoArg,  "jdb" },
  456. { "-jdb",                   XtNdebugger,             XrmoptionNoArg,  "jdb" },
  457.  
  458. { "--pydb",                 XtNdebugger,             XrmoptionNoArg,  "pydb" },
  459. { "-pydb",                  XtNdebugger,             XrmoptionNoArg,  "pydb" },
  460.  
  461. { "--perl",                 XtNdebugger,             XrmoptionNoArg,  "perl" },
  462. { "-perl",                  XtNdebugger,             XrmoptionNoArg,  "perl" },
  463.  
  464. { "--trace",                XtNtrace,                XrmoptionNoArg,  ON },
  465. { "-trace",                 XtNtrace,                XrmoptionNoArg,  ON },
  466.  
  467. { "--play-log",            XtNplayLog,              XrmoptionSepArg, NULL },
  468. { "-play-log",            XtNplayLog,              XrmoptionSepArg, NULL },
  469.  
  470. { "--font",                 XtNdefaultFont,          XrmoptionSepArg, NULL },
  471. { "-font",                  XtNdefaultFont,          XrmoptionSepArg, NULL },
  472. { "-fn",                    XtNdefaultFont,          XrmoptionSepArg, NULL },
  473.  
  474. { "--fontsize",             XtCFontSize,             XrmoptionSepArg, NULL },
  475. { "-fontsize",              XtCFontSize,             XrmoptionSepArg, NULL },
  476.  
  477. { "--vsl-library",          XtNvslLibrary,           XrmoptionSepArg, NULL },
  478. { "-vsl-library",           XtNvslLibrary,           XrmoptionSepArg, NULL },
  479.  
  480. { "--vsl-path",             XtNvslPath,              XrmoptionSepArg, NULL },
  481. { "-vsl-path",              XtNvslPath,              XrmoptionSepArg, NULL },
  482.  
  483. { "--separate",             XtCSeparate,             XrmoptionNoArg, ON },
  484. { "-separate",              XtCSeparate,             XrmoptionNoArg, ON },
  485. { "--separate-windows",     XtCSeparate,             XrmoptionNoArg, ON },
  486. { "-separate-windows",      XtCSeparate,             XrmoptionNoArg, ON },
  487.  
  488. { "--separate-source-window", XtNseparateSourceWindow, XrmoptionNoArg, ON },
  489. { "-separate-source-window",  XtNseparateSourceWindow, XrmoptionNoArg, ON },
  490.  
  491. { "--separate-data-window", XtNseparateDataWindow,   XrmoptionNoArg, ON },
  492. { "-separate-data-window",  XtNseparateDataWindow,   XrmoptionNoArg, ON },
  493.  
  494. { "--attach",               XtCSeparate,             XrmoptionNoArg, OFF },
  495. { "-attach",                XtCSeparate,             XrmoptionNoArg, OFF },
  496. { "--attach-windows",       XtCSeparate,             XrmoptionNoArg, OFF },
  497. { "-attach-windows",        XtCSeparate,             XrmoptionNoArg, OFF },
  498.  
  499. { "--attach-source-window", XtNseparateSourceWindow, XrmoptionNoArg, OFF },
  500. { "-attach-source-window",  XtNseparateSourceWindow, XrmoptionNoArg, OFF },
  501.  
  502. { "--attach-data-window",   XtNseparateDataWindow,   XrmoptionNoArg, OFF },
  503. { "-attach-data-window",    XtNseparateDataWindow,   XrmoptionNoArg, OFF },
  504.  
  505. { "--exec-window",          XtNseparateExecWindow,   XrmoptionNoArg, ON },
  506. { "-exec-window",           XtNseparateExecWindow,   XrmoptionNoArg, ON },
  507.  
  508. { "--no-exec-window",       XtNseparateExecWindow,   XrmoptionNoArg, OFF },
  509. { "-no-exec-window",        XtNseparateExecWindow,   XrmoptionNoArg, OFF },
  510.  
  511. { "--source-window",        XtNopenSourceWindow,     XrmoptionNoArg, ON },
  512. { "-source-window",         XtNopenSourceWindow,     XrmoptionNoArg, ON },
  513.  
  514. { "--no-source-window",     XtNopenSourceWindow,     XrmoptionNoArg, OFF },
  515. { "-no-source-window",      XtNopenSourceWindow,     XrmoptionNoArg, OFF },
  516.  
  517. { "--data-window",          XtNopenDataWindow,       XrmoptionNoArg, ON },
  518. { "-data-window",           XtNopenDataWindow,       XrmoptionNoArg, ON },
  519.  
  520. { "--no-data-window",       XtNopenDataWindow,       XrmoptionNoArg, OFF },
  521. { "-no-data-window",        XtNopenDataWindow,       XrmoptionNoArg, OFF },
  522.  
  523. { "--debugger-console",     XtNopenDebuggerConsole,  XrmoptionNoArg, ON },
  524. { "-debugger-console",      XtNopenDebuggerConsole,  XrmoptionNoArg, ON },
  525.  
  526. { "--no-debugger-console",  XtNopenDebuggerConsole,  XrmoptionNoArg, OFF },
  527. { "-no-debugger-console",   XtNopenDebuggerConsole,  XrmoptionNoArg, OFF },
  528.  
  529. { "--button-tips",          XtNbuttonTips,           XrmoptionNoArg, ON },
  530. { "-button-tips",           XtNbuttonTips,           XrmoptionNoArg, ON },
  531.  
  532. { "--no-button-tips",       XtNbuttonTips,           XrmoptionNoArg, OFF },
  533. { "-no-button-tips",        XtNbuttonTips,           XrmoptionNoArg, OFF },
  534.  
  535. { "--value-tips",           XtNvalueTips,            XrmoptionNoArg, ON },
  536. { "-value-tips",            XtNvalueTips,            XrmoptionNoArg, ON },
  537.  
  538. { "--no-value-tips",        XtNvalueTips,            XrmoptionNoArg, OFF },
  539. { "-no-value-tips",         XtNvalueTips,            XrmoptionNoArg, OFF },
  540.  
  541. { "--status-at-bottom",     XtNstatusAtBottom,       XrmoptionNoArg, ON },
  542. { "-status-at-bottom",      XtNstatusAtBottom,       XrmoptionNoArg, ON },
  543.  
  544. { "--status-at-top",        XtNstatusAtBottom,       XrmoptionNoArg, OFF },
  545. { "-status-at-top",         XtNstatusAtBottom,       XrmoptionNoArg, OFF },
  546.  
  547. { "--toolbars-at-bottom",   XtNtoolbarsAtBottom,     XrmoptionNoArg, ON },
  548. { "-toolbars-at-bottom",    XtNtoolbarsAtBottom,     XrmoptionNoArg, ON },
  549.  
  550. { "--toolbars-at-top",      XtNtoolbarsAtBottom,     XrmoptionNoArg, OFF },
  551. { "-toolbars-at-top",       XtNtoolbarsAtBottom,     XrmoptionNoArg, OFF },
  552.  
  553. { "--panned-graph-editor",  XtNpannedGraphEditor,    XrmoptionNoArg, ON },
  554. { "-panned-graph-editor",   XtNpannedGraphEditor,    XrmoptionNoArg, ON },
  555.  
  556. { "--scrolled-graph-editor", XtNpannedGraphEditor,   XrmoptionNoArg, OFF },
  557. { "-scrolled-graph-editor", XtNpannedGraphEditor,    XrmoptionNoArg, OFF },
  558.  
  559. { "--sync-debugger",        XtNsynchronousDebugger,  XrmoptionNoArg, ON },
  560. { "-sync-debugger",         XtNsynchronousDebugger,  XrmoptionNoArg, ON },
  561.  
  562. { "--disassemble",          XtNdisassemble,          XrmoptionNoArg, ON },
  563. { "-disassemble",           XtNdisassemble,          XrmoptionNoArg, ON },
  564.  
  565. { "--no-disassemble",       XtNdisassemble,          XrmoptionNoArg, OFF },
  566. { "-no-disassemble",        XtNdisassemble,          XrmoptionNoArg, OFF },
  567.  
  568. { "--glyphs",               XtNdisplayGlyphs,        XrmoptionNoArg, ON },
  569. { "-glyphs",                XtNdisplayGlyphs,        XrmoptionNoArg, ON },
  570.  
  571. { "--no-glyphs",            XtNdisplayGlyphs,        XrmoptionNoArg, OFF },
  572. { "-no-glyphs",             XtNdisplayGlyphs,        XrmoptionNoArg, OFF },
  573.  
  574. { "--host",                 XtNdebuggerHost,         XrmoptionSepArg, NULL },
  575. { "-host",                  XtNdebuggerHost,         XrmoptionSepArg, NULL },
  576.  
  577. { "--rhost",                XtNdebuggerRHost,        XrmoptionSepArg, NULL },
  578. { "-rhost",                 XtNdebuggerRHost,        XrmoptionSepArg, NULL },
  579.  
  580. { "--login",                XtNdebuggerHostLogin,    XrmoptionSepArg, NULL },
  581. { "-login",                 XtNdebuggerHostLogin,    XrmoptionSepArg, NULL },
  582. { "-l",                     XtNdebuggerHostLogin,    XrmoptionSepArg, NULL },
  583.  
  584. { "--tty",                  XtNttyMode,              XrmoptionNoArg, ON },
  585. { "-tty",                   XtNttyMode,              XrmoptionNoArg, ON },
  586. { "-t",                     XtNttyMode,              XrmoptionNoArg, ON },
  587.  
  588. { "--fullname",             XtCTTYMode,              XrmoptionNoArg, ON },
  589. { "-fullname",              XtCTTYMode,              XrmoptionNoArg, ON },
  590. { "-f",                     XtCTTYMode,              XrmoptionNoArg, ON },
  591.  
  592. { "--version",              XtNshowVersion,          XrmoptionNoArg, ON },
  593. { "-version",               XtNshowVersion,          XrmoptionNoArg, ON },
  594. { "-v",                     XtNshowVersion,          XrmoptionNoArg, ON },
  595.  
  596. { "--configuration",        XtNshowConfiguration,    XrmoptionNoArg, ON },
  597. { "-configuration",         XtNshowConfiguration,    XrmoptionNoArg, ON },
  598.  
  599. { "--manual",               XtNshowManual,           XrmoptionNoArg, ON },
  600. { "-manual",                XtNshowManual,           XrmoptionNoArg, ON },
  601.  
  602. { "--maintenance",          XtNmaintenance,          XrmoptionNoArg, ON },
  603. { "-maintenance",           XtNmaintenance,          XrmoptionNoArg, ON },
  604.  
  605. { "--no-maintenance",       XtNmaintenance,          XrmoptionNoArg, OFF },
  606. { "-no-maintenance",        XtNmaintenance,          XrmoptionNoArg, OFF },
  607.  
  608. { "--license",              XtNshowLicense,          XrmoptionNoArg, ON },
  609. { "-license",               XtNshowLicense,          XrmoptionNoArg, ON },
  610.  
  611. { "--news",                 XtNshowNews,             XrmoptionNoArg, ON },
  612. { "-news",                  XtNshowNews,             XrmoptionNoArg, ON },
  613.  
  614. { "--fonts",                XtNshowFonts,            XrmoptionNoArg, ON },
  615. { "-fonts",                 XtNshowFonts,            XrmoptionNoArg, ON },
  616.  
  617. { "--check-configuration",  XtNcheckConfiguration,   XrmoptionNoArg, ON },
  618. { "-check-configuration",   XtNcheckConfiguration,   XrmoptionNoArg, ON },
  619.  
  620. { "--lesstif-hacks",        XtNlessTifVersion,       XrmoptionNoArg, "999" },
  621. { "-lesstif-hacks",         XtNlessTifVersion,       XrmoptionNoArg, "999" },
  622.  
  623. { "--no-lesstif-hacks",     XtNlessTifVersion,       XrmoptionNoArg, "1000" },
  624. { "-no-lesstif-hacks",      XtNlessTifVersion,       XrmoptionNoArg, "1000" },
  625.  
  626. { "--lesstif-version",      XtNlessTifVersion,       XrmoptionSepArg, NULL },
  627. { "-lesstif-version",       XtNlessTifVersion,       XrmoptionSepArg, NULL },
  628.  
  629. { "--help",                 XtNshowInvocation,       XrmoptionNoArg, ON },
  630. { "-help",                  XtNshowInvocation,       XrmoptionNoArg, ON },
  631. { "-h",                     XtNshowInvocation,       XrmoptionNoArg, ON },
  632. { "--?",                    XtNshowInvocation,       XrmoptionNoArg, ON },
  633. { "-?",                     XtNshowInvocation,       XrmoptionNoArg, ON },
  634.  
  635. };
  636.  
  637. // Actions
  638. static XtActionsRec actions [] = {
  639.     {"gdb-control",            controlAct},
  640.     {"gdb-interrupt",          interruptAct},
  641.     {"gdb-command",            commandAct},
  642.     {"gdb-process",            processAct},
  643.     {"gdb-delete-or-control",  delete_or_controlAct},
  644.     {"gdb-prev-history",       prev_historyAct},
  645.     {"gdb-previous-history",   prev_historyAct},
  646.     {"gdb-next-history",       next_historyAct},
  647.     {"gdb-beginning-of-line",  beginning_of_lineAct},
  648.     {"gdb-end-of-line",        end_of_lineAct},
  649.     {"gdb-forward-character",  forward_characterAct},
  650.     {"gdb-backward-character", backward_characterAct},
  651.     {"gdb-set-line",           set_lineAct},
  652.     {"gdb-complete-command",   complete_commandAct},
  653.     {"gdb-complete-arg",       complete_argAct},
  654.     {"gdb-complete-tab",       complete_tabAct},
  655.     {"gdb-insert-source-arg",  insert_source_argAct},
  656.     {"gdb-insert-graph-arg",   insert_graph_argAct},
  657.     {"gdb-isearch-prev",       isearch_prevAct},
  658.     {"gdb-isearch-next",       isearch_nextAct},
  659.     {"gdb-isearch-exit",       isearch_exitAct},
  660.     {"gdb-popup-menu",         popupAct},
  661.     {"ddd-next-tab-group",     next_tab_groupAct},
  662.     {"ddd-prev-tab-group",     prev_tab_groupAct},
  663.     {"ddd-previous-tab-group", prev_tab_groupAct},
  664.     {"ddd-get-focus",          get_focusAct},
  665.     {"ddd-select-all",         select_allAct},
  666. #if XmVersion < 2000
  667.     {"toggle-overstrike",      toggleOverstrikeAct},
  668. #endif
  669. };
  670.  
  671.  
  672. //-----------------------------------------------------------------------------
  673. // Menus
  674. //-----------------------------------------------------------------------------
  675.  
  676. struct RecentItems {
  677.     enum RecentItem { R1, R2, R3, R4, R5, R6, R7, R8, R9 };
  678. };
  679.  
  680. #define RECENT_MENU \
  681. { \
  682.     { "r1", MMPush, { gdbOpenRecentCB, XtPointer(1) }, 0, 0, 0, 0 }, \
  683.     { "r2", MMPush, { gdbOpenRecentCB, XtPointer(2) }, 0, 0, 0, 0 }, \
  684.     { "r3", MMPush, { gdbOpenRecentCB, XtPointer(3) }, 0, 0, 0, 0 }, \
  685.     { "r4", MMPush, { gdbOpenRecentCB, XtPointer(4) }, 0, 0, 0, 0 }, \
  686.     { "r5", MMPush, { gdbOpenRecentCB, XtPointer(5) }, 0, 0, 0, 0 }, \
  687.     { "r6", MMPush, { gdbOpenRecentCB, XtPointer(6) }, 0, 0, 0, 0 }, \
  688.     { "r7", MMPush, { gdbOpenRecentCB, XtPointer(7) }, 0, 0, 0, 0 }, \
  689.     { "r8", MMPush, { gdbOpenRecentCB, XtPointer(8) }, 0, 0, 0, 0 }, \
  690.     { "r9", MMPush, { gdbOpenRecentCB, XtPointer(9) }, 0, 0, 0, 0 }, \
  691.     MMEnd \
  692. }
  693.  
  694. static MMDesc command_recent_menu[] = RECENT_MENU;
  695. static MMDesc source_recent_menu[]  = RECENT_MENU;
  696. static MMDesc data_recent_menu[]    = RECENT_MENU;
  697.  
  698. struct FileItems {
  699.     enum FileItem { OpenFile, OpenClass, Recent, OpenCore, OpenSource, Sep1,
  700.             OpenSession, SaveSession, Sep2,
  701.             Attach, Detach, Sep3,
  702.             Print, PrintAgain, Sep4,
  703.             CD, Sep5,
  704.             Make, MakeAgain, Sep6,
  705.             Close, Restart, Exit
  706.     };
  707. };
  708.  
  709. #define FILE_MENU(recent_menu) \
  710. { \
  711.     { "open_file",     MMPush, \
  712.         { WhenReady, XtPointer(gdbOpenFileCB) }, 0, 0, 0, 0 }, \
  713.     { "open_class",    MMPush | MMUnmanaged, \
  714.         { WhenReady, XtPointer(gdbOpenClassCB) }, 0, 0, 0, 0 }, \
  715.     { "recent",        MMMenu, MMNoCB, recent_menu, 0, 0, 0 }, \
  716.     { "open_core",     MMPush, \
  717.         { WhenReady, XtPointer(gdbOpenCoreCB) }, 0, 0, 0, 0}, \
  718.     { "open_source",   MMPush, { gdbLookupSourceCB, 0 }, 0, 0, 0, 0 }, \
  719.     MMSep, \
  720.     { "open_session",  MMPush, \
  721.         { WhenReady, XtPointer(OpenSessionCB) }, 0, 0, 0, 0 }, \
  722.     { "save_session",  MMPush, \
  723.         { WhenReady, XtPointer(SaveSessionAsCB) }, 0, 0, 0, 0 }, \
  724.     MMSep, \
  725.     { "attach",        MMPush, \
  726.         { WhenReady, XtPointer(gdbOpenProcessCB) }, 0, 0, 0, 0 }, \
  727.     { "detach",        MMPush, \
  728.         { gdbCommandCB, "detach" }, 0, 0, 0, 0 }, \
  729.     MMSep, \
  730.     { "print",         MMPush, { PrintGraphCB, XtPointer(0) }, 0, 0, 0, 0 }, \
  731.     { "printAgain",    MMPush | MMUnmanaged, \
  732.      { PrintAgainCB, XtPointer(1) }, 0, 0, 0, 0 }, \
  733.     { "separator",     MMSeparator | MMUnmanaged, MMNoCB, 0, 0, 0, 0 }, \
  734.     { "cd",            MMPush, \
  735.         { WhenReady, XtPointer(gdbChangeDirectoryCB) }, 0, 0, 0, 0 }, \
  736.     { "separator",     MMSeparator | MMUnmanaged, MMNoCB, 0, 0, 0, 0 }, \
  737.     { "make",          MMPush, \
  738.         { WhenReady, XtPointer(gdbMakeCB) }, 0, 0, 0, 0 }, \
  739.     { "makeAgain",     MMPush | MMUnmanaged, \
  740.         { WhenReady, XtPointer(gdbMakeAgainCB) }, 0, 0, 0, 0 }, \
  741.     MMSep, \
  742.     { "close",         MMPush, { DDDCloseCB, 0 }, 0, 0, 0, 0 }, \
  743.     { "restart",       MMPush, { DDDRestartCB, 0 }, 0, 0, 0, 0 }, \
  744.     { "exit",          MMPush, \
  745.         { DDDExitCB, XtPointer(EXIT_SUCCESS) }, 0, 0, 0, 0 }, \
  746.     MMEnd \
  747. }
  748.  
  749. static MMDesc command_file_menu[] = FILE_MENU(command_recent_menu);
  750. static MMDesc source_file_menu[]  = FILE_MENU(source_recent_menu);
  751. static MMDesc data_file_menu[]    = FILE_MENU(data_recent_menu);
  752.  
  753.  
  754. struct ProgramItems {
  755.     enum ProgramItem { Run, RunAgain, Sep1,
  756.                SeparateExecWindow, Sep2,
  757.                Step, Stepi, Next, Nexti, Until, Finish, Sep3,
  758.                Cont, Signal0, Sep4,
  759.                Kill, Break, Quit
  760.     };
  761. };
  762.  
  763. #define PROGRAM_MENU(w) \
  764. { \
  765.     { "run",         MMPush, { gdbRunCB, 0 }, 0, 0, 0, 0 }, \
  766.     { "run_again",   MMPush, { gdbCommandCB, "run" }, 0, 0, 0, 0 }, \
  767.     MMSep, \
  768.     { "separateExecWindow",  MMToggle, \
  769.     { dddToggleSeparateExecWindowCB, 0 }, 0, &(w), 0, 0 }, \
  770.     MMSep, \
  771.     { "step",        MMPush, { gdbCommandCB, "step" }, 0, 0, 0, 0 }, \
  772.     { "stepi",       MMPush, { gdbCommandCB, "stepi" }, 0, 0, 0, 0 }, \
  773.     { "next",        MMPush, { gdbCommandCB, "next" }, 0, 0, 0, 0 }, \
  774.     { "nexti",       MMPush, { gdbCommandCB, "nexti" }, 0, 0, 0, 0}, \
  775.     { "until",       MMPush, { gdbCommandCB, "until" }, 0, 0, 0, 0}, \
  776.     { "finish",      MMPush, { gdbCommandCB, "finish" }, 0, 0, 0, 0}, \
  777.     MMSep, \
  778.     { "cont",        MMPush, { gdbCommandCB, "cont" }, 0, 0, 0, 0}, \
  779.     { "signal0",     MMPush, { gdbCommandCB, "signal 0" }, 0, 0, 0, 0}, \
  780.     MMSep, \
  781.     { "kill",        MMPush, { gdbCommandCB, "kill" }, 0, 0, 0, 0}, \
  782.     { "break",       MMPush, { gdbCommandCB, "\003" }, 0, 0, 0, 0}, \
  783.     { "quit",        MMPush, { gdbCommandCB, "\034" }, 0, 0, 0, 0}, \
  784.     MMEnd \
  785. }
  786.  
  787. static Widget command_separate_exec_window_w;
  788. static Widget source_separate_exec_window_w;
  789. static Widget data_separate_exec_window_w;
  790.  
  791. static MMDesc command_program_menu[]
  792.     = PROGRAM_MENU(command_separate_exec_window_w);
  793. static MMDesc source_program_menu[]
  794.     = PROGRAM_MENU(source_separate_exec_window_w);
  795. static MMDesc data_program_menu[]
  796.     = PROGRAM_MENU(data_separate_exec_window_w);
  797.  
  798. enum DDDWindow { OtherWindow = -1,
  799.          ToolWindow  = 0, 
  800.          ExecWindow, 
  801.          Sep,
  802.          GDBWindow, 
  803.          SourceWindow,
  804.          DataWindow, 
  805.          CodeWindow,
  806.          CommonWindow };
  807.  
  808. #define VIEW_MENU \
  809. { \
  810.     { "tool",    MMPush,   { gdbOpenToolWindowCB, 0 }, 0, 0, 0, 0}, \
  811.     { "exec",    MMPush,   { gdbOpenExecWindowCB, 0 }, 0, 0, 0, 0}, \
  812.     MMSep, \
  813.     { "console", MMPush,   { gdbOpenCommandWindowCB, 0 }, 0, 0, 0, 0}, \
  814.     { "source",  MMPush,   { gdbOpenSourceWindowCB, 0 }, 0, 0, 0, 0}, \
  815.     { "data",    MMPush,   { gdbOpenDataWindowCB, 0 }, 0, 0, 0, 0}, \
  816.     { "code",    MMToggle | MMUnmanaged, \
  817.         { gdbToggleCodeWindowCB, 0 }, 0, 0, 0, 0}, \
  818.     MMEnd \
  819. }
  820.  
  821. static MMDesc command_view_menu[] = VIEW_MENU;
  822. static MMDesc source_view_menu[]  = VIEW_MENU;
  823. static MMDesc data_view_menu[]    = VIEW_MENU;
  824.  
  825. static MMDesc views_menu[] = 
  826. {
  827.     { "tool",    MMPush,   { gdbOpenToolWindowCB, 0 }, 0, 0, 0, 0},
  828.     { "exec",    MMPush,   { gdbOpenExecWindowCB, 0 }, 0, 0, 0, 0},
  829.     MMSep,
  830.     { "console", MMToggle, { gdbToggleCommandWindowCB, 0 }, 0, 0, 0, 0},
  831.     { "source",  MMToggle, { gdbToggleSourceWindowCB, 0 }, 0, 0, 0, 0},
  832.     { "data",    MMToggle, { gdbToggleDataWindowCB, 0 }, 0, 0, 0, 0},
  833.     { "code",    MMToggle, { gdbToggleCodeWindowCB, 0 }, 0, 0, 0, 0},
  834.     MMEnd
  835. };
  836.  
  837. struct EditItems {
  838.     enum EditItem { 
  839.     Undo, Redo, Sep1,
  840.     Cut, Copy, Paste, ClearAll, Delete, Sep2, 
  841.     SelectAll, Sep3,
  842.     Preferences, Settings, Sep4,
  843.     SaveOptions
  844.     };
  845. };
  846.  
  847. #define EDIT_MENU(win) \
  848. { \
  849.     { "undo",        MMPush,  { gdbUndoCB, 0 }, 0, 0, 0, 0}, \
  850.     { "redo",        MMPush,  { gdbRedoCB, 0 }, 0, 0, 0, 0}, \
  851.     MMSep, \
  852.     { "cut",         MMPush,  \
  853.       { gdbCutSelectionCB,    XtPointer(win) }, 0, 0, 0, 0}, \
  854.     { "copy",        MMPush,  \
  855.       { gdbCopySelectionCB,   XtPointer(win) }, 0, 0, 0, 0}, \
  856.     { "paste",       MMPush,  \
  857.       { gdbPasteClipboardCB,  XtPointer(win) }, 0, 0, 0, 0}, \
  858.     { "clearAll",    MMPush,  \
  859.       { gdbClearAllCB,        XtPointer(win) }, 0, 0, 0, 0}, \
  860.     { "delete",      MMPush,  \
  861.       { gdbDeleteSelectionCB, XtPointer(win) }, 0, 0, 0, 0}, \
  862.     MMSep, \
  863.     { "selectAll",   MMPush,  \
  864.       { gdbSelectAllCB,       XtPointer(win) }, 0, 0, 0, 0}, \
  865.     MMSep, \
  866.     { "preferences", MMPush,  \
  867.       { dddPopupPreferencesCB, 0 }, 0, 0, 0, 0}, \
  868.     { "settings",    MMPush,  \
  869.       { WhenReady, XtPointer(dddPopupSettingsCB) }, 0, 0, 0, 0}, \
  870.     MMSep, \
  871.     { "saveOptions", MMPush,  \
  872.       { DDDSaveOptionsCB, XtPointer(SAVE_DEFAULT) }, 0, 0, 0, 0}, \
  873.     MMEnd \
  874. }
  875.  
  876. static MMDesc command_edit_menu[] = EDIT_MENU(GDBWindow);
  877. static MMDesc source_edit_menu[]  = EDIT_MENU(SourceWindow);
  878. static MMDesc data_edit_menu[]    = EDIT_MENU(DataWindow);
  879.  
  880. static Widget complete_w;
  881. static Widget define_w;
  882.  
  883. static MMDesc command_menu[] =
  884. {
  885.     { "history",  MMPush, { gdbHistoryCB, 0 }, 0, 0, 0, 0},
  886.     MMSep,
  887.     { "prev",     MMPush, { gdbPrevCB, 0 }, 0, 0, 0, 0},
  888.     { "next",     MMPush, { gdbNextCB, 0 }, 0, 0, 0, 0},
  889.     MMSep,
  890.     { "isearch_prev", MMPush, { gdbISearchPrevCB, 0 }, 0, 0, 0, 0},
  891.     { "isearch_next", MMPush, { gdbISearchNextCB, 0 }, 0, 0, 0, 0},
  892.     { "isearch_exit", MMPush, { gdbISearchExitCB, 0 }, 0, 0, 0, 0},
  893.     MMSep,
  894.     { "complete", MMPush, { WhenReady, XtPointer(gdbCompleteCB) }, 
  895.       NULL, &complete_w, 0, 0 },
  896.     { "apply",    MMPush, { WhenReady, XtPointer(gdbApplyCB) }, 0, 0, 0, 0},
  897.     MMSep,
  898.     { "clear_line",   MMPush, { gdbClearCB, 0 }, 0, 0, 0, 0},
  899.     { "clear_window", MMPush, { gdbClearWindowCB, 0 }, 0, 0, 0, 0},
  900.     MMSep,
  901.     { "define",   MMPush, { dddDefineCommandCB, 0 }, NULL, &define_w, 0, 0 },
  902.     { "buttons",  MMPush, { dddEditButtonsCB, 0 }, 0, 0, 0, 0},
  903.     MMEnd
  904. };
  905.  
  906. static Widget stack_w;
  907. static Widget registers_w;
  908. static Widget threads_w;
  909. static Widget signals_w;
  910.  
  911. static MMDesc stack_menu[] =
  912. {
  913.     { "stack",      MMPush,  { WhenReady, 
  914.                    XtPointer(SourceView::ViewStackFramesCB) },
  915.       NULL, &stack_w, 0, 0 },
  916.     { "registers",  MMPush,  { WhenReady, 
  917.                    XtPointer(SourceView::ViewRegistersCB) },
  918.       NULL, ®isters_w, 0, 0 },
  919.     { "threads",    MMPush,  { WhenReady,
  920.                    XtPointer(SourceView::ViewThreadsCB) },
  921.       NULL, &threads_w, 0, 0 },
  922.     { "signals",    MMPush,  { WhenReady,
  923.                    XtPointer(dddPopupSignalsCB) },
  924.       NULL, &signals_w, 0, 0 },
  925.     MMSep,
  926.     { "up",         MMPush,  { gdbCommandCB, "up" }, 0, 0, 0, 0},
  927.     { "down",       MMPush,  { gdbCommandCB, "down" }, 0, 0, 0, 0},
  928.     MMEnd
  929. };
  930.  
  931. static Widget lookup_w;
  932. static Widget find_forward_w;
  933. static Widget find_backward_w;
  934. static Widget find_words_only_w;
  935. static Widget find_case_sensitive_w;
  936. static Widget disassemble_w;
  937. static Widget edit_source_w;
  938. static Widget reload_source_w;
  939. static Widget line_numbers1_w;
  940.  
  941. static MMDesc source_menu[] =
  942. {
  943.     { "breakpoints", MMPush, { SourceView::EditBreakpointsCB, 0 }, 0, 0, 0, 0},
  944.     MMSep,
  945.     {"lookup",        MMPush, { gdbLookupCB, 0 },
  946.       NULL, &lookup_w, 0, 0 },
  947.     { "findForward",  MMPush, { gdbFindCB, XtPointer(SourceView::forward) },
  948.       NULL, &find_forward_w, 0, 0 },
  949.     { "findBackward", MMPush, { gdbFindCB, XtPointer(SourceView::backward) },
  950.       NULL, &find_backward_w, 0, 0 },
  951.     MMSep,
  952.     { "findWordsOnly",       MMToggle, { sourceToggleFindWordsOnlyCB, 0 }, 
  953.       NULL, &find_words_only_w, 0, 0 },
  954.     { "findCaseSensitive",   MMToggle, { sourceToggleFindCaseSensitiveCB, 0 }, 
  955.       NULL, &find_case_sensitive_w, 0, 0 },
  956.     MMSep,
  957.     { "lineNumbers",         MMToggle, { sourceToggleDisplayLineNumbersCB, 0 },
  958.       NULL, &line_numbers1_w, 0, 0 },
  959.     { "disassemble",         MMToggle,  { gdbToggleCodeWindowCB, 0 },
  960.       NULL, &disassemble_w, 0, 0 },
  961.     MMSep,
  962.     { "edit",       MMPush,  
  963.       { gdbEditSourceCB, 0 }, 0, &edit_source_w, 0, 0 },
  964.     { "reload",     MMPush,  
  965.       { gdbReloadSourceCB, 0 }, 0, &reload_source_w, 0, 0},
  966.     MMEnd
  967. };
  968.  
  969.  
  970. // Preferences
  971.  
  972. // General preferences
  973.  
  974. static Widget button_tips_w;
  975. static Widget button_docs_w;
  976. static MMDesc button_menu [] = 
  977. {
  978.     { "tips",  MMToggle, { dddToggleButtonTipsCB, 0 }, 0, &button_tips_w, 0,0},
  979.     { "docs",  MMToggle, { dddToggleButtonDocsCB, 0 }, 0, &button_docs_w, 0,0},
  980.     MMEnd
  981. };
  982.  
  983. static Widget value_tips_w;
  984. static Widget value_docs_w;
  985. static MMDesc value_menu [] = 
  986. {
  987.     { "tips",  MMToggle, { dddToggleValueTipsCB, 0 }, 0, &value_tips_w, 0, 0 },
  988.     { "docs",  MMToggle, { dddToggleValueDocsCB, 0 }, 0, &value_docs_w, 0, 0 },
  989.     MMEnd
  990. };
  991.  
  992. static Widget set_global_completion_w;
  993. static Widget set_console_completion_w;
  994. static MMDesc completion_menu [] = 
  995. {
  996.     { "inAllWindows", MMToggle, 
  997.       { dddSetGlobalTabCompletionCB, XtPointer(True) }, 
  998.       NULL, &set_global_completion_w, 0, 0 },
  999.     { "inConsole", MMToggle, { dddSetGlobalTabCompletionCB, XtPointer(False) },
  1000.       NULL, &set_console_completion_w, 0, 0 },
  1001.     MMEnd
  1002. };
  1003.  
  1004. static Widget max_undo_size_w;
  1005. static MMDesc undo_menu [] =
  1006. {
  1007.     { "size", MMTextField | MMUnmanagedLabel, { dddSetUndoBufferSizeCB, 0 }, 
  1008.       NULL, &max_undo_size_w, 0, 0 },
  1009.     { "kbytes", MMLabel, MMNoCB, NULL, 0, 0, 0 },
  1010.     { "clear", MMPush, { dddClearUndoBufferCB, 0 }, NULL, 0, 0, 0 },
  1011.     MMEnd
  1012. };
  1013.  
  1014. static Widget group_iconify_w;
  1015. static Widget uniconify_when_ready_w;
  1016. static Widget suppress_warnings_w;
  1017. static Widget warn_if_locked_w;
  1018. static Widget check_grabs_w;
  1019.  
  1020. static MMDesc general_preferences_menu[] = 
  1021. {
  1022.     { "buttonHints",         MMButtonPanel, MMNoCB, button_menu, 0, 0, 0 },
  1023.     { "valueHints",          MMButtonPanel, MMNoCB, value_menu, 0, 0, 0 },
  1024.     { "tabCompletion",       MMRadioPanel,  MMNoCB, completion_menu, 0, 0, 0 },
  1025.     { "groupIconify",        MMToggle, { dddToggleGroupIconifyCB, 0 },
  1026.       NULL, &group_iconify_w, 0, 0 },
  1027.     { "uniconifyWhenReady",  MMToggle, { dddToggleUniconifyWhenReadyCB, 0 },
  1028.       NULL, &uniconify_when_ready_w, 0, 0 },
  1029.     { "suppressWarnings",    MMToggle, { dddToggleSuppressWarningsCB, 0 },
  1030.       NULL, &suppress_warnings_w, 0, 0 },
  1031.     { "warnIfLocked",        MMToggle, { dddToggleWarnIfLockedCB, 0 }, 
  1032.       NULL, &warn_if_locked_w, 0, 0 },
  1033.     { "checkGrabs",          MMToggle, { dddToggleCheckGrabsCB, 0 },
  1034.       NULL, &check_grabs_w, 0, 0 },
  1035.     { "undoSize",            MMPanel,  MMNoCB, undo_menu, 0, 0, 0 },
  1036.     MMEnd
  1037. };
  1038.  
  1039.  
  1040. // Source preferences
  1041. static Widget set_display_glyphs_w;
  1042. static Widget set_display_text_w;
  1043. static MMDesc glyph_menu[] =
  1044. {
  1045.     { "asGlyphs", MMToggle, { sourceSetDisplayGlyphsCB, XtPointer(True) },
  1046.       NULL, &set_display_glyphs_w, 0, 0 },
  1047.     { "asText", MMToggle, { sourceSetDisplayGlyphsCB, XtPointer(False) },
  1048.       NULL, &set_display_text_w, 0, 0 },
  1049.     MMEnd
  1050. };
  1051.  
  1052. static Widget set_tool_buttons_in_toolbar_w;
  1053. static Widget set_tool_buttons_in_command_tool_w;
  1054. static MMDesc tool_buttons_menu [] = 
  1055. {
  1056.     { "commandTool",  MMToggle, { dddSetToolBarCB, XtPointer(False) },
  1057.       NULL, &set_tool_buttons_in_command_tool_w, 0, 0 },
  1058.     { "sourceWindow", MMToggle, { dddSetToolBarCB, XtPointer(True) },
  1059.       NULL, &set_tool_buttons_in_toolbar_w, 0, 0 },
  1060.     MMEnd
  1061. };
  1062.  
  1063. static Widget set_refer_path_w;
  1064. static Widget set_refer_base_w;
  1065. static MMDesc refer_menu[] =
  1066. {
  1067.     { "byPath", MMToggle, { sourceSetUseSourcePathCB, XtPointer(True) },
  1068.       NULL, &set_refer_path_w, 0, 0 },
  1069.     { "byBase", MMToggle, { sourceSetUseSourcePathCB, XtPointer(False) },
  1070.       NULL, &set_refer_base_w, 0, 0 },
  1071.     MMEnd
  1072. };
  1073.  
  1074. static Widget words_only_w;
  1075. static Widget case_sensitive_w;
  1076. static MMDesc find_preferences_menu[] =
  1077. {
  1078.     { "wordsOnly", MMToggle, { sourceToggleFindWordsOnlyCB, 0 }, 
  1079.       NULL, &words_only_w, 0, 0 },
  1080.     { "caseSensitive", MMToggle, { sourceToggleFindCaseSensitiveCB, 0 }, 
  1081.       NULL, &case_sensitive_w, 0, 0 },
  1082.     MMEnd
  1083. };
  1084.  
  1085. static Widget cache_source_files_w;
  1086. static Widget cache_machine_code_w;
  1087. static MMDesc cache_menu[] =
  1088. {
  1089.     { "cacheSource", MMToggle, { sourceToggleCacheSourceFilesCB, 0 }, 
  1090.       NULL, &cache_source_files_w, 0, 0 },
  1091.     { "cacheCode", MMToggle, { sourceToggleCacheMachineCodeCB, 0 }, 
  1092.       NULL, &cache_machine_code_w, 0, 0 },
  1093.     MMEnd
  1094. };
  1095.  
  1096. static Widget tab_width_w;
  1097. static Widget source_indent_w;
  1098. static Widget code_indent_w;
  1099. static MMDesc scales_menu[] = 
  1100. {
  1101.     { "tabWidth", MMScale, 
  1102.       { sourceSetTabWidthCB, 0 }, NULL, &tab_width_w, 0, 0 },
  1103.     { "sourceIndent", MMScale, 
  1104.       { sourceSetSourceIndentCB, 0 }, NULL, &source_indent_w, 0, 0 },
  1105.     { "codeIndent", MMScale, 
  1106.       { sourceSetCodeIndentCB, 0 }, NULL, &code_indent_w, 0, 0 },
  1107.     MMEnd
  1108. };
  1109.  
  1110.  
  1111. static Widget line_numbers2_w;
  1112. static Widget refer_sources_w;
  1113. static MMDesc source_preferences_menu[] = 
  1114. {
  1115.     { "showExecPos",  MMRadioPanel, MMNoCB, glyph_menu, 0, 0, 0 },
  1116.     { "toolButtons",  MMRadioPanel,  MMNoCB, tool_buttons_menu, 0, 0, 0 },
  1117.     { "referSources", MMRadioPanel, MMNoCB, refer_menu, &refer_sources_w, 0,0},
  1118.     { "find",         MMButtonPanel, MMNoCB, find_preferences_menu, 0, 0, 0 },
  1119.     { "cache",        MMButtonPanel, MMNoCB, cache_menu, 0, 0, 0 },
  1120.     { "lineNumbers",  MMToggle,
  1121.       { sourceToggleDisplayLineNumbersCB, 0 }, 0, 
  1122.       &line_numbers2_w, 0, 0 },
  1123.     { "scales",       MMPanel | MMUnmanagedLabel, 
  1124.                   MMNoCB, scales_menu, 0, 0, 0 },
  1125.     MMEnd
  1126. };
  1127.  
  1128.  
  1129. // Data preferences
  1130.  
  1131. static Widget graph_detect_aliases_w;
  1132. static Widget graph_cluster_displays_w;
  1133. static Widget graph_align_2d_arrays_w;
  1134. static Widget graph_show_hints_w;
  1135. static Widget graph_show_annotations_w;
  1136. static Widget graph_show_dependent_titles_w;
  1137. static Widget graph_auto_close_w;
  1138. static Widget graph_compact_layout_w;
  1139. static Widget graph_auto_layout_w;
  1140. static Widget graph_snap_to_grid_w;
  1141. static Widget graph_grid_size_w;
  1142.  
  1143. static MMDesc show_menu[] = 
  1144. {
  1145.     { "hints", MMToggle, { graphToggleShowHintsCB, 0 },
  1146.       NULL, &graph_show_hints_w, 0, 0 },
  1147.     { "annotations", MMToggle, { graphToggleShowAnnotationsCB, 0 },
  1148.       NULL, &graph_show_annotations_w, 0, 0 },
  1149.     { "dependentTitles", MMToggle, { graphToggleShowDependentTitlesCB, 0 },
  1150.       NULL, &graph_show_dependent_titles_w, 0, 0 },
  1151.     MMEnd
  1152. };
  1153.  
  1154. static MMDesc layout_menu[] =
  1155. {
  1156.     { "compact", MMToggle,  { graphToggleCompactLayoutCB, 0 },
  1157.       NULL, &graph_compact_layout_w, 0, 0 },
  1158.     { "auto",    MMToggle,  { graphToggleAutoLayoutCB, 0 },
  1159.       NULL, &graph_auto_layout_w, 0, 0 },
  1160.     MMEnd
  1161. };
  1162.  
  1163. static MMDesc data_preferences_menu[] = 
  1164. {
  1165.     { "show",          MMPanel, MMNoCB, show_menu, 0, 0, 0 },
  1166.     { "layout",        MMPanel, MMNoCB, layout_menu, 0, 0, 0 },
  1167.     { "detectAliases", MMToggle, { graphToggleDetectAliasesCB, 0 },
  1168.       NULL, &graph_detect_aliases_w, 0, 0 },
  1169.     { "clusterDisplays", MMToggle, { graphToggleClusterDisplaysCB, 0 },
  1170.       NULL, &graph_cluster_displays_w, 0, 0 }, 
  1171.     { "align2dArrays", MMToggle,  { graphToggleAlign2dArraysCB, 0 },
  1172.       NULL, &graph_align_2d_arrays_w, 0, 0 },
  1173.     { "autoClose",     MMToggle,  { graphToggleAutoCloseCB, 0 },
  1174.       NULL, &graph_auto_close_w, 0, 0 },
  1175.     { "snapToGrid",    MMToggle,  { graphToggleSnapToGridCB, 0 },
  1176.       NULL, &graph_snap_to_grid_w, 0, 0 },
  1177.     { "gridSize",      MMScale,   { graphSetGridSizeCB, 0 },
  1178.       NULL, &graph_grid_size_w, 0, 0 },
  1179.     MMEnd
  1180. };
  1181.  
  1182.  
  1183. // Startup preferences
  1184. static Widget set_separate_windows_w;
  1185. static Widget set_attached_windows_w;
  1186. static MMDesc window_mode_menu [] = 
  1187. {
  1188.     { "attached",  MMToggle, { dddSetSeparateWindowsCB, XtPointer(1) },
  1189.       NULL, &set_attached_windows_w, 0, 0 },
  1190.     { "separate",  MMToggle, { dddSetSeparateWindowsCB, XtPointer(0) },
  1191.       NULL, &set_separate_windows_w, 0, 0 },
  1192.     MMEnd
  1193. };
  1194.  
  1195. static Widget set_button_images_w;
  1196. static Widget set_button_captions_w;
  1197. static Widget set_flat_buttons_w;
  1198. static Widget set_color_buttons_w;
  1199. static Widget set_toolbars_at_bottom_w;
  1200. static MMDesc button_appearance_menu [] = 
  1201. {
  1202.     { "images",   MMToggle, { dddToggleButtonImagesCB, 0 },
  1203.       NULL, &set_button_images_w, 0, 0 },
  1204.     { "captions", MMToggle, { dddToggleButtonCaptionsCB, 0 },
  1205.       NULL, &set_button_captions_w, 0, 0 },
  1206.     { "flat", MMToggle, { dddToggleFlatButtonsCB, 0 },
  1207.       NULL, &set_flat_buttons_w, 0, 0 },
  1208.     { "color", MMToggle, { dddToggleColorButtonsCB, 0 },
  1209.       NULL, &set_color_buttons_w, 0, 0 },
  1210.     { "bottom", MMToggle, { dddToggleToolbarsAtBottomCB, 0 },
  1211.       NULL, &set_toolbars_at_bottom_w, 0, 0 },
  1212.     MMEnd
  1213. };
  1214.  
  1215. static Widget set_focus_pointer_w;
  1216. static Widget set_focus_explicit_w;
  1217. static MMDesc keyboard_focus_menu [] = 
  1218. {
  1219.     { "pointer",  MMToggle, { dddSetKeyboardFocusPolicyCB, 
  1220.                 XtPointer(XmPOINTER) },
  1221.       NULL, &set_focus_pointer_w, 0, 0 },
  1222.     { "explicit", MMToggle, { dddSetKeyboardFocusPolicyCB, 
  1223.                 XtPointer(XmEXPLICIT) },
  1224.       NULL, &set_focus_explicit_w, 0, 0 },
  1225.     MMEnd
  1226. };
  1227.  
  1228. static Widget set_scrolling_panner_w;
  1229. static Widget set_scrolling_scrollbars_w;
  1230. static MMDesc data_scrolling_menu [] = 
  1231. {
  1232.     { "panner", MMToggle,     { dddSetPannerCB, XtPointer(True) },
  1233.       NULL, &set_scrolling_panner_w, 0, 0 },
  1234.     { "scrollbars", MMToggle, { dddSetPannerCB, XtPointer(False) },
  1235.       NULL, &set_scrolling_scrollbars_w, 0, 0 },
  1236.     MMEnd
  1237. };
  1238.  
  1239. static Widget set_debugger_gdb_w;
  1240. static Widget set_debugger_dbx_w;
  1241. static Widget set_debugger_xdb_w;
  1242. static Widget set_debugger_jdb_w;
  1243. static Widget set_debugger_pydb_w;
  1244. static Widget set_debugger_perl_w;
  1245. static MMDesc debugger_menu [] = 
  1246. {
  1247.     { "gdb", MMToggle, { dddSetDebuggerCB, XtPointer(GDB) },
  1248.       NULL, &set_debugger_gdb_w, 0, 0 },
  1249.     { "dbx", MMToggle, { dddSetDebuggerCB, XtPointer(DBX) },
  1250.       NULL, &set_debugger_dbx_w, 0, 0 },
  1251.     { "xdb", MMToggle, { dddSetDebuggerCB, XtPointer(XDB) },
  1252.       NULL, &set_debugger_xdb_w, 0, 0 },
  1253.     { "jdb", MMToggle, { dddSetDebuggerCB, XtPointer(JDB) },
  1254.       NULL, &set_debugger_jdb_w, 0, 0 },
  1255.     { "pydb", MMToggle, { dddSetDebuggerCB, XtPointer(PYDB) },
  1256.       NULL, &set_debugger_pydb_w, 0, 0 },
  1257.     { "perl", MMToggle, { dddSetDebuggerCB, XtPointer(PERL) },
  1258.       NULL, &set_debugger_perl_w, 0, 0 },
  1259.     MMEnd
  1260. };
  1261.  
  1262. static Widget auto_debugger_w;
  1263. static MMDesc auto_debugger_menu [] =
  1264. {
  1265.     { "automatic", MMToggle, { dddToggleAutoDebuggerCB, 0 },
  1266.       NULL, &auto_debugger_w, 0, 0 },
  1267.     MMEnd
  1268. };
  1269.  
  1270. static Widget startup_tips_w;
  1271. static Widget splash_screen_w;
  1272.  
  1273. static MMDesc startup_menu [] =
  1274. {
  1275.     { "splashScreen", MMToggle, { SetSplashScreenCB, 0 }, 
  1276.       NULL, &splash_screen_w, 0, 0 },
  1277.     { "startupTips",  MMToggle, { SetStartupTipsCB, 0 },  
  1278.       NULL, &startup_tips_w, 0, 0 },
  1279.     MMEnd
  1280. };
  1281.  
  1282. static Widget cut_copy_paste_kde_w;
  1283. static Widget cut_copy_paste_motif_w;
  1284.  
  1285. static MMDesc cut_copy_paste_menu [] =
  1286. {
  1287.     { "kde",    MMToggle, { dddSetCutCopyPasteBindingsCB, 
  1288.                 XtPointer(KDEBindings) }, 
  1289.       NULL, &cut_copy_paste_kde_w, 0, 0 },
  1290.     { "motif",  MMToggle, { dddSetCutCopyPasteBindingsCB, 
  1291.                 XtPointer(MotifBindings) },
  1292.       NULL, &cut_copy_paste_motif_w, 0, 0 },
  1293.     MMEnd
  1294. };
  1295.  
  1296. static Widget select_all_kde_w;
  1297. static Widget select_all_motif_w;
  1298.  
  1299. static MMDesc select_all_menu [] =
  1300. {
  1301.     { "kde",    MMToggle, { dddSetSelectAllBindingsCB, 
  1302.                 XtPointer(KDEBindings) }, 
  1303.       NULL, &select_all_kde_w, 0, 0 },
  1304.     { "motif",  MMToggle, { dddSetSelectAllBindingsCB, 
  1305.                 XtPointer(MotifBindings) },
  1306.       NULL, &select_all_motif_w, 0, 0 },
  1307.     MMEnd
  1308. };
  1309.  
  1310. static MMDesc startup_preferences_menu [] =
  1311. {
  1312.     { "windows",         MMRadioPanel,  MMNoCB, window_mode_menu, 0, 0, 0 },
  1313.     { "cutCopyPaste",    MMRadioPanel,  MMNoCB, cut_copy_paste_menu, 0, 0, 0 },
  1314.     { "selectAll",       MMRadioPanel,  MMNoCB, select_all_menu, 0, 0, 0 },
  1315.     { "buttons",         MMButtonPanel, MMNoCB, 
  1316.                                         button_appearance_menu, 0, 0, 0 },
  1317.     { "keyboardFocus",   MMRadioPanel,  MMNoCB, keyboard_focus_menu, 0, 0, 0 },
  1318.     { "dataScrolling",   MMRadioPanel,  MMNoCB, data_scrolling_menu, 0, 0, 0 },
  1319.     { "autoDebugger",    MMButtonPanel, MMNoCB,
  1320.                                         auto_debugger_menu, 0, 0, 0 },
  1321.     { "debugger",        MMRadioPanel,  MMNoCB,
  1322.                           debugger_menu, 0, 0, 0 },
  1323.     { "startupWindows",  MMButtonPanel, MMNoCB, startup_menu, 0, 0, 0 },
  1324.     MMEnd
  1325. };
  1326.  
  1327.  
  1328. static Widget font_names[4];
  1329. static Widget font_sizes[4];
  1330.  
  1331. #define FONT_MENU(font) \
  1332. { \
  1333.     { "name",   MMTextField | MMUnmanagedLabel, \
  1334.     { SetFontNameCB, XtPointer(font) }, NULL, \
  1335.     &font_names[int(font)], 0, 0 }, \
  1336.     { "size",   MMTextField, \
  1337.     { SetFontSizeCB, XtPointer(font) }, NULL, \
  1338.     &font_sizes[int(font)], 0, 0 }, \
  1339.     { "browse", MMPush, { BrowseFontCB, XtPointer(font) }, 0, 0, 0, 0 }, \
  1340.     MMEnd \
  1341. }
  1342.  
  1343. static MMDesc default_font_menu        [] = FONT_MENU(DefaultDDDFont);
  1344. static MMDesc variable_width_font_menu [] = FONT_MENU(VariableWidthDDDFont);
  1345. static MMDesc fixed_width_font_menu    [] = FONT_MENU(FixedWidthDDDFont);
  1346.  
  1347. static MMDesc font_preferences_menu [] =
  1348. {
  1349.     { "default",         MMPanel,  MMNoCB, default_font_menu, 0, 0, 0 },
  1350.     { "variableWidth",   MMPanel,  MMNoCB, variable_width_font_menu, 0, 0, 0 },
  1351.     { "fixedWidth",      MMPanel,  MMNoCB, fixed_width_font_menu, 0, 0, 0 },
  1352.     MMEnd
  1353. };
  1354.  
  1355.  
  1356. static Widget extern_plot_window_w;
  1357. static Widget builtin_plot_window_w;
  1358.  
  1359. static MMDesc plot_window_menu [] =
  1360. {
  1361.     { "extern", MMToggle, { dddSetBuiltinPlotWindowCB, XtPointer(false) },
  1362.       NULL, &extern_plot_window_w, 0, 0},
  1363.     { "builtin", MMToggle, { dddSetBuiltinPlotWindowCB, XtPointer(true) },
  1364.       NULL, &builtin_plot_window_w, 0, 0},
  1365.     MMEnd
  1366. };
  1367.  
  1368. static Widget edit_command_w;
  1369. static Widget get_core_command_w;
  1370. static Widget ps_command_w;
  1371. static Widget term_command_w;
  1372. static Widget uncompress_command_w;
  1373. static Widget www_command_w;
  1374. static Widget plot_command_w;
  1375.  
  1376. static MMDesc helpers_preferences_menu [] =
  1377. {
  1378.     { "edit",       MMTextField, { dddSetEditCommandCB, 0 }, 
  1379.       NULL, &edit_command_w, 0, 0},
  1380.     { "get_core",   MMTextField, { dddSetGetCoreCommandCB, 0 }, 
  1381.       NULL, &get_core_command_w, 0, 0},
  1382.     { "ps",         MMTextField, { dddSetPSCommandCB, 0 },
  1383.       NULL, &ps_command_w, 0, 0},
  1384.     { "term",       MMTextField, { dddSetTermCommandCB, 0 },
  1385.       NULL, &term_command_w, 0, 0},
  1386.     { "uncompress", MMTextField, { dddSetUncompressCommandCB, 0 },
  1387.       NULL, &uncompress_command_w, 0, 0},
  1388.     { "www",        MMTextField, { dddSetWWWCommandCB, 0 },
  1389.       NULL, &www_command_w, 0, 0},
  1390.     { "plot",       MMTextField, { dddSetPlotCommandCB, 0 }, 
  1391.       NULL, &plot_command_w, 0, 0},
  1392.     { "plot_window", MMRadioPanel, MMNoCB, plot_window_menu, 0, 0, 0 },
  1393.     MMEnd
  1394. };
  1395.  
  1396.  
  1397. // Data
  1398. static Widget print_w            = 0;
  1399. static Widget display_w          = 0;
  1400. static Widget examine_w          = 0;
  1401. static Widget locals_w           = 0;
  1402. static Widget args_w             = 0;
  1403. static Widget detect_aliases_w   = 0;
  1404. static Widget infos_w            = 0;
  1405. static Widget align_w            = 0;
  1406. static Widget edit_watchpoints_w = 0;
  1407.  
  1408. static MMDesc data_menu[] = 
  1409. {
  1410.     { "displays",    MMPush,    { DataDisp::EditDisplaysCB, 0 }, 0, 0, 0, 0},
  1411.     { "watchpoints", MMPush,   { SourceView::EditBreakpointsCB, 0 }, 
  1412.                                  NULL, &edit_watchpoints_w, 0, 0 },
  1413.     { "examine",     MMPush,  { gdbExamineCB, 0 }, NULL, &examine_w, 0, 0},
  1414.     MMSep,
  1415.     { "print",       MMPush,  { gdbPrintCB, 0   }, NULL, &print_w, 0, 0 },
  1416.     { "display",     MMPush,  { gdbDisplayCB, 0 }, NULL, &display_w, 0, 0 },
  1417.     MMSep,
  1418.     { "detectAliases", MMToggle, { graphToggleDetectAliasesCB, 0 },
  1419.       NULL, &detect_aliases_w, 0, 0 },
  1420.     MMSep,
  1421.     { "info locals", MMToggle,  { graphToggleLocalsCB, 0 }, 
  1422.       NULL, &locals_w, 0, 0 },
  1423.     { "info args",   MMToggle,  { graphToggleArgsCB, 0 }, 
  1424.       NULL, &args_w, 0, 0 },
  1425.     { "infos",       MMPush,    { WhenReady, XtPointer(dddPopupInfosCB) }, 
  1426.       NULL, &infos_w, 0, 0 },
  1427.     MMSep,
  1428.     { "align",      MMPush,    { graphAlignCB, 0  }, NULL, &align_w, 0, 0 },
  1429.     { "rotate",     MMPush,    { graphRotateCB, 0 }, 0, 0, 0, 0},
  1430.     { "layout",     MMPush,    { graphLayoutCB, 0 }, 0, 0, 0, 0},
  1431.     MMSep,
  1432.     { "refresh",    MMPush,    { DataDisp::refreshCB, 0 }, 0, 0, 0, 0},
  1433.     MMEnd
  1434. };
  1435.  
  1436.  
  1437. // Maintenance
  1438. static Widget crash_debug_w     = 0;
  1439. static Widget crash_dump_core_w = 0;
  1440. static Widget crash_nothing_w   = 0;
  1441.  
  1442. static MMDesc crash_menu[] = 
  1443. {
  1444.     { "debug",         MMToggle, { dddSetCrashCB, XtPointer(2) }, 0,
  1445.       &crash_debug_w, 0, 0 },
  1446.     { "dumpCore",      MMToggle, { dddSetCrashCB, XtPointer(1) }, 0,
  1447.       &crash_dump_core_w, 0, 0 },
  1448.     { "nothing",       MMToggle, { dddSetCrashCB, XtPointer(0) }, 0,
  1449.       &crash_nothing_w, 0, 0 },
  1450.     MMEnd
  1451. };
  1452.  
  1453. static Widget debug_ddd_w       = 0;
  1454. static Widget dump_core_w       = 0;
  1455.  
  1456. static MMDesc maintenance_menu[] = 
  1457. {
  1458.     { "debug",         MMPush, { DDDDebugCB, 0 }, 0, &debug_ddd_w, 0, 0 },
  1459.     { "dumpCore",      MMPush, { DDDDumpCoreCB, 0 }, 0, &dump_core_w, 0, 0 },
  1460.     { "tictactoe",     MMPush, { TicTacToeCB, 0 }, 0, 0, 0, 0 },
  1461.     MMSep,
  1462.     { "crash",         MMRadioMenu, MMNoCB, crash_menu, 0, 0, 0 },
  1463.     MMSep,
  1464.     { "remove",        MMPush, { dddClearMaintenanceCB, 0 }, 0, 0, 0, 0 },
  1465.     MMEnd
  1466. };
  1467.  
  1468. static Widget maintenance_w = 0;
  1469.  
  1470. // Menu Bar for DDD command window
  1471. static MMDesc command_menubar[] = 
  1472. {
  1473.     { "file",     MMMenu,          { gdbUpdateFileCB, command_file_menu }, 
  1474.                                    command_file_menu, 0, 0, 0 },
  1475.     { "edit",     MMMenu,          { gdbUpdateEditCB, XtPointer(GDBWindow) }, 
  1476.                                    command_edit_menu, 0, 0, 0 },
  1477.     { "view",    MMMenu,          { gdbUpdateViewCB, command_view_menu }, 
  1478.                          command_view_menu, 0, 0, 0 },
  1479.     { "program",  MMMenu,          MMNoCB, command_program_menu, 0, 0, 0 },
  1480.     { "commands", MMMenu,          MMNoCB, command_menu, 0, 0, 0  },
  1481.     { "maintenance", MMMenu | MMUnmanaged, MMNoCB, maintenance_menu, 
  1482.       &maintenance_w, 0, 0  },
  1483.     { "help",     MMMenu | MMHelp, MMNoCB, simple_help_menu, 0, 0, 0  },
  1484.     MMEnd
  1485. };
  1486.  
  1487. // Menu Bar for DDD source view
  1488. static MMDesc source_menubar[] = 
  1489. {
  1490.     { "file",    MMMenu,          { gdbUpdateFileCB, source_file_menu }, 
  1491.                                   source_file_menu, 0, 0, 0  },
  1492.     { "edit",    MMMenu,          { gdbUpdateEditCB, XtPointer(SourceWindow) },
  1493.                                   source_edit_menu, 0, 0, 0  },
  1494.     { "view",    MMMenu,          { gdbUpdateViewCB, source_view_menu },
  1495.                   source_view_menu, 0, 0, 0  },
  1496.     { "program", MMMenu,          MMNoCB, source_program_menu, 0, 0, 0  },
  1497.     { "stack",   MMMenu,          MMNoCB, stack_menu, 0, 0, 0  },
  1498.     { "source",  MMMenu,          MMNoCB, source_menu, 0, 0, 0  },
  1499.     { "help",    MMMenu | MMHelp, MMNoCB, simple_help_menu, 0, 0, 0  },
  1500.     MMEnd
  1501. };
  1502.  
  1503. // Menu Bar for DDD data window
  1504. static MMDesc data_menubar[] = 
  1505. {
  1506.     { "file",    MMMenu,          { gdbUpdateFileCB, data_file_menu }, 
  1507.                                   data_file_menu, 0, 0, 0  },
  1508.     { "edit",    MMMenu,          { gdbUpdateEditCB, XtPointer(DataWindow) },
  1509.                                   data_edit_menu, 0, 0, 0  },
  1510.     { "view",    MMMenu,          { gdbUpdateViewCB, data_view_menu }, 
  1511.                         data_view_menu, 0, 0, 0  },
  1512.     { "program", MMMenu,          MMNoCB, data_program_menu, 0, 0, 0  },
  1513.     { "data",    MMMenu,          MMNoCB, data_menu, 0, 0, 0  },
  1514.     { "help",    MMMenu | MMHelp, MMNoCB, simple_help_menu, 0, 0, 0  },
  1515.     MMEnd
  1516. };
  1517.  
  1518. // Menu Bar for common DDD data/command window
  1519. static MMDesc common_menubar[] = 
  1520. {
  1521.     { "file",       MMMenu,       { gdbUpdateFileCB, command_file_menu }, 
  1522.                                   command_file_menu, 0, 0, 0  },
  1523.     { "edit",       MMMenu,       { gdbUpdateEditCB, XtPointer(CommonWindow) },
  1524.                                   command_edit_menu, 0, 0, 0  },
  1525.     { "views",      MMMenu,       { gdbUpdateViewsCB, views_menu }, 
  1526.                                   views_menu, 0, 0, 0  },
  1527.     { "program",    MMMenu,       MMNoCB, command_program_menu, 0, 0, 0  },
  1528.     { "commands",   MMMenu,       MMNoCB, command_menu, 0, 0, 0  },
  1529.     { "stack",      MMMenu,       MMNoCB, stack_menu, 0, 0, 0  },
  1530.     { "source",     MMMenu,       MMNoCB, source_menu, 0, 0, 0  },
  1531.     { "data",       MMMenu,       MMNoCB, data_menu, 0, 0, 0  },
  1532.     { "maintenance", MMMenu | MMUnmanaged, MMNoCB, maintenance_menu, 
  1533.       &maintenance_w, 0, 0  },
  1534.     { "help", MMMenu | MMHelp,    MMNoCB, simple_help_menu, 0, 0, 0  },
  1535.     MMEnd
  1536. };
  1537.  
  1538. struct PrintItems {
  1539.     enum ArgCmd { PrintRef, Whatis };
  1540. };
  1541.  
  1542. static Widget print_examine_w = 0;
  1543.  
  1544. static MMDesc print_menu[] =
  1545. {
  1546.     { "printRef",        MMPush, { gdbPrintRefCB, 0 }, 0, 0, 0, 0 },
  1547.     { "whatis",          MMPush, { gdbWhatisCB, 0 }, 0, 0, 0, 0 },
  1548.     { "examine",         MMPush, 
  1549.       { gdbExamineCB, 0 }, NULL, &print_examine_w, 0, 0 },
  1550.     MMEnd
  1551. };
  1552.  
  1553. struct DispItems {
  1554.     enum ArgCmd { DispRef };
  1555. };
  1556.  
  1557. static MMDesc display_menu[] =
  1558. {
  1559.     { "dispRef",        MMPush, { gdbDispRefCB, 0 }, 0, 0, 0, 0 },
  1560.     MMEnd
  1561. };
  1562.  
  1563. struct WatchItems {
  1564.     enum ArgCmd { Properties, Enable, Sep, CWatch, RWatch, AWatch };
  1565. };
  1566.  
  1567. static MMDesc watch_menu[] =
  1568. {
  1569.     { "watchProperties",  MMPush, 
  1570.       { gdbEditWatchpointPropertiesCB, 0 }, 0, 0, 0, 0},
  1571.     { "enableWatch",      MMPush, 
  1572.       { gdbToggleEnableWatchpointCB, 0 }, 0, 0, 0, 0},
  1573.     MMSep,
  1574.     { "cwatch",       MMPush, 
  1575.       { gdbWatchCB, XtPointer(WATCH_CHANGE) }, 0, 0, 0, 0 },
  1576.     { "rwatch",       MMPush, 
  1577.       { gdbWatchCB, XtPointer(WATCH_READ)   }, 0, 0, 0, 0 },
  1578.     { "awatch",       MMPush, 
  1579.       { gdbWatchCB, XtPointer(WATCH_ACCESS) }, 0, 0, 0, 0 },
  1580.  
  1581.     // It would be nice to have an `unwatch' command here, for
  1582.     // recording commands.  Unfortunately, GDB needs a watchpoint
  1583.     // number for deleting watchpoints.
  1584. #if 0    
  1585.     MMSep,
  1586.     { "unwatch",      MMPush, { gdbUnwatchCB, 0 }, 0, 0, 0, 0},
  1587. #endif
  1588.     MMEnd
  1589. };
  1590.  
  1591. struct BreakItems {
  1592.     enum ArgCmd { TempBreak, RegexBreak, Properties, Enable, Sep1,
  1593.           ContUntil, SetPC, Sep2, ClearAt2 };
  1594. };
  1595.  
  1596. static MMDesc break_menu[] = 
  1597. {
  1598.     { "tempBreakAt",     MMPush, { gdbTempBreakAtCB, 0 }, 0, 0, 0, 0},
  1599.     { "regexBreakAt",    MMPush, { gdbRegexBreakAtCB, 0 }, 0, 0, 0, 0},
  1600.     { "breakProperties", MMPush, 
  1601.       { gdbEditBreakpointPropertiesCB, 0 }, 0, 0, 0, 0},
  1602.     { "enableBreak",     MMPush, 
  1603.       { gdbToggleEnableBreakpointCB, 0 }, 0, 0, 0, 0},
  1604.     MMSep,
  1605.     { "contUntil",       MMPush, { gdbContUntilCB, 0 }, 0, 0, 0, 0},
  1606.     { "setPC",           MMPush, { gdbSetPCCB, 0 }, 0, 0, 0, 0},
  1607.     MMSep,
  1608.     { "clearAt2",        MMPush, { gdbClearAtCB, 0 }, 0, 0, 0, 0},
  1609.     MMEnd
  1610. };
  1611.  
  1612. struct FindItems {
  1613.     enum ArgCmd { FindForward, FindBackward };
  1614. };
  1615.  
  1616. static MMDesc find_menu[] = 
  1617. {
  1618.     { "findForward",  MMPush, 
  1619.       { gdbFindCB, XtPointer(SourceView::forward) }, 0, 0, 0, 0},
  1620.     { "findBackward", MMPush, 
  1621.       { gdbFindCB, XtPointer(SourceView::backward) }, 0, 0, 0, 0},
  1622.     MMEnd
  1623. };
  1624.  
  1625. struct ArgItems {
  1626.     enum ArgCmd { Lookup, Find, Break, Watch, Print, Display };
  1627. };
  1628.  
  1629. static MMDesc arg_cmd_area[] = 
  1630. {
  1631.     {"lookup",        MMPush,  
  1632.      { gdbLookupCB, 0 }, 0, 0, 0, 0},
  1633.     {"find",          MMPush | MMInsensitive, 
  1634.      { gdbFindAgainCB, 0 }, find_menu, 0, 0, 0 },
  1635.     {"breakAt",       MMPush,  { gdbToggleBreakCB, 0 }, break_menu, 0, 0, 0 },
  1636.     {"watch",         MMPush,  { gdbToggleWatchCB, XtPointer(WATCH_CHANGE) }, 
  1637.                                  watch_menu, 0, 0, 0 },
  1638.     {"print",         MMPush,  { gdbPrintCB, 0 }, print_menu, 0, 0, 0 },
  1639.     {"display",       MMPush,  { gdbDisplayCB, 0 }, display_menu, 0, 0, 0 },
  1640.     MMEnd
  1641. };
  1642.  
  1643.  
  1644. //-----------------------------------------------------------------------------
  1645. // Global variables
  1646. //-----------------------------------------------------------------------------
  1647.  
  1648. // All communication with GDB passes through this variable
  1649. GDBAgent*     gdb = 0;
  1650.  
  1651. // Data display
  1652. DataDisp*     data_disp;
  1653.  
  1654. // Source display
  1655. SourceView*   source_view;
  1656.  
  1657. // Argument field
  1658. ArgField*     source_arg;
  1659.  
  1660. // Argument toolbar
  1661. static Widget arg_cmd_w;
  1662.  
  1663. // GDB input/output widget
  1664. Widget gdb_w;
  1665.  
  1666. // GDB status line
  1667. Widget status_w;
  1668.  
  1669. // GDB activity led
  1670. static Widget led_w;
  1671.  
  1672. // Last output position
  1673. XmTextPosition promptPosition;
  1674.  
  1675. // Last message position
  1676. XmTextPosition messagePosition;
  1677.  
  1678. // Buttons
  1679. static Widget console_buttons_w;
  1680. static Widget source_buttons_w;
  1681. static Widget data_buttons_w;
  1682. static Widget command_toolbar_w;
  1683.  
  1684. // Strings to be ignored in GDB output
  1685. string gdb_out_ignore = "";
  1686.  
  1687. // Command management
  1688. bool private_gdb_output;   // true if output is running
  1689. bool private_gdb_input;    // true if input is running
  1690.  
  1691. // true, if initial gdb prompt appeared
  1692. bool gdb_initialized;
  1693.  
  1694. // The Xt Warning handler
  1695. static XtErrorHandler ddd_original_xt_warning_handler;
  1696.  
  1697. // Initial delays
  1698. static StatusMsg *init_delay = 0;
  1699. static Delay *setup_delay = 0;
  1700.  
  1701. // Events to note for window visibility
  1702. const int STRUCTURE_MASK = StructureNotifyMask | VisibilityChangeMask;
  1703.  
  1704. // The atom for the delete-window protocol
  1705. static Atom WM_DELETE_WINDOW;
  1706.  
  1707. // Message handling
  1708. static MString version_warnings;
  1709.  
  1710.  
  1711. //-----------------------------------------------------------------------------
  1712. // DDD main program
  1713. //-----------------------------------------------------------------------------
  1714.  
  1715. int main(int argc, char *argv[])
  1716. {
  1717.     // As this is a C++ program, execution does not begin here.  At
  1718.     // this point, all global data objects already have been properly
  1719.     // initialized.
  1720.  
  1721.     // Save environment for restart.
  1722.     register_argv(argv);
  1723.     register_environ();
  1724.  
  1725.     // This one is required for error messages
  1726.     char *program_name = (char *)(argc > 0 ? argv[0] : ddd_NAME);
  1727.  
  1728.     // Install signal handlers
  1729.  
  1730.     // On some systems (notably HP-UX), GDB has trouble finding what
  1731.     // function invoked the signal handler.  Hence, if the environment
  1732.     // variable DDD_NO_SIGNAL_HANDLERS is set, we do not install
  1733.     // signal handlers, causing DDD to report signals immediately.
  1734.  
  1735.     if (getenv(DDD_NAME "_NO_SIGNAL_HANDLERS") == 0)
  1736.     {
  1737.     ddd_install_signal();             // Cleanup upon termination
  1738.     ddd_install_fatal(program_name); // Fatal error
  1739.     }
  1740.  
  1741.     // Check if we are to run without windows
  1742.     bool no_windows = false;
  1743.  
  1744.     // Don't run DDD setuid.  DDD invokes shell commands and even
  1745.     // shell scripts, such that all known problems of setuid shell
  1746.     // scripts apply.
  1747.     if (geteuid() != getuid())
  1748.     no_windows = true;
  1749.  
  1750.     // Check for special options:
  1751.     // `--nw'   - no windows (GDB)
  1752.     // `-L'     - no windows (XDB)
  1753.     // `--PLAY' - logplayer mode (DDD)
  1754.     // and options that would otherwise be eaten by Xt
  1755.     StringArray saved_options;
  1756.     string gdb_name = "";
  1757.     setup_options(argc, argv, saved_options, gdb_name, no_windows);
  1758.  
  1759.     // If we don't want windows, just start GDB.
  1760.     if (no_windows)
  1761.     {
  1762.     argv[0] = gdb_name;
  1763.     execvp(gdb_name, argv);
  1764.     perror(gdb_name);
  1765.     return EXIT_FAILURE;
  1766.     }
  1767.  
  1768.     // Initialize X toolkit
  1769.     Arg args[10];
  1770.     int arg = 0;
  1771.  
  1772.     // Install X error handlers
  1773.     ddd_install_x_fatal();
  1774.     ddd_install_x_error();
  1775.  
  1776.     ostrstream messages;
  1777.  
  1778.     // Set up a `~/.ddd/' directory hierarchy
  1779.     create_session_dir(DEFAULT_SESSION, messages);
  1780.  
  1781.     // Read ~/.ddd/init resources
  1782.     XrmDatabase dddinit = 
  1783.     GetFileDatabase(session_state_file(DEFAULT_SESSION));
  1784.     if (dddinit == 0)
  1785.     dddinit = XrmGetStringDatabase("");
  1786.  
  1787.     // Read ~/.ddd/tips resources
  1788.     XrmDatabase dddtips =
  1789.     GetFileDatabase(session_tips_file());
  1790.     if (dddtips != 0)
  1791.     XrmMergeDatabases(dddtips, &dddinit);
  1792.  
  1793.     // Let command-line arguments override ~/.ddd/init
  1794.     XrmParseCommand(&dddinit, options, XtNumber(options), 
  1795.             DDD_CLASS_NAME, &argc, argv);
  1796.  
  1797.     String session_id = 0;
  1798.     if (session_id == 0)
  1799.     {
  1800.     // Determine session
  1801.     char *session_rtype = 0;
  1802.     XrmValue session_value;
  1803.  
  1804.     string Nsession   = string(DDD_CLASS_NAME ".") + XtNsession;
  1805.     string CSessionID = string(DDD_CLASS_NAME ".") + XtCSessionID;
  1806. #if XtSpecificationRelease >= 6
  1807.     string NsessionID = string(DDD_CLASS_NAME ".") + XtNsessionID;
  1808. #endif
  1809.  
  1810.     // Try resource or option
  1811.     if (
  1812. #if XtSpecificationRelease >= 6
  1813.         XrmGetResource(dddinit, NsessionID, CSessionID,
  1814.                &session_rtype, &session_value) ||
  1815. #endif
  1816.         XrmGetResource(dddinit, Nsession, CSessionID,
  1817.                &session_rtype, &session_value))
  1818.     {
  1819.         if (session_value.addr != 0)
  1820.         {
  1821.         static string id((char *)session_value.addr, 
  1822.                  session_value.size);
  1823.         session_id = id;
  1824.         }
  1825.     }
  1826.  
  1827.     if (session_id == 0)
  1828.     {
  1829.         // Try `=FILE' hack: if the last or second-to-last arg is
  1830.         // `=FILE', replace it by FILE and use FILE as session id.
  1831.         for (int i = argc - 1; i >= 1 && i >= argc - 2; i--)
  1832.         {
  1833.         if (argv[i][0] == '=')
  1834.         {
  1835.             // Delete '='
  1836.             int j = 0;
  1837.             while ((argv[i][j] = argv[i][j + 1]))
  1838.             j++;
  1839.             
  1840.             session_id = (char *)SourceView::basename(argv[i]);
  1841.             session_value.addr = session_id;
  1842.             session_value.size = strlen(session_id) + 1;
  1843.             XrmPutResource(&dddinit, Nsession, XtRString, 
  1844.                    &session_value);
  1845.         }
  1846.         }
  1847.     }
  1848.     }
  1849.  
  1850.     if (restart_session() != "")
  1851.     {
  1852.     // A session is given in $DDD_SESSION: override everything.
  1853.     XrmDatabase session_db = 
  1854.         GetFileDatabase(session_state_file(restart_session()));
  1855.     if (session_db != 0)
  1856.         XrmMergeDatabases(session_db, &dddinit);
  1857.     }
  1858.     else if (session_id != 0)
  1859.     {
  1860.     // Merge in session resources; these override `~/.ddd/init' as
  1861.     // well as the command-line options.
  1862.     XrmDatabase session_db = 
  1863.         GetFileDatabase(session_state_file(session_id));
  1864.     if (session_db != 0)
  1865.         XrmMergeDatabases(session_db, &dddinit);
  1866.     }
  1867.  
  1868.     // Register own converters.  This must be done here to install the
  1869.     // String -> Cardinal converter.
  1870.     registerOwnConverters();
  1871.  
  1872.     // Handle `--version', `--help', etc.  We do this here, since we
  1873.     // might want to use them even without X access.
  1874.     setup_show(dddinit, (char *)SourceView::basename(argv[0]), gdb_name);
  1875.  
  1876.     // From this point on, we'll be running under X.
  1877.  
  1878.     // Open X connection and create top-level application shell
  1879.     XtAppContext app_context;
  1880.     arg = 0;
  1881.     XtSetArg(args[arg], XmNdeleteResponse, XmDO_NOTHING); arg++;
  1882.  
  1883. #if XtSpecificationRelease >= 6
  1884.     if (session_id)
  1885.     {
  1886.     XtSetArg(args[arg], XtNsessionID, session_id); arg++;
  1887.     }
  1888.  
  1889.     Widget toplevel =
  1890.     XtOpenApplication(&app_context, DDD_CLASS_NAME,
  1891.               XrmOptionDescList(0), 0,
  1892.               &argc, argv, ddd_fallback_resources,
  1893.               sessionShellWidgetClass,
  1894.               args, arg);
  1895.  
  1896.     XtAddCallback(toplevel, XtNsaveCallback, SaveSmSessionCB, XtPointer(0));
  1897.     XtAddCallback(toplevel, XtNdieCallback, ShutdownSmSessionCB, XtPointer(0));
  1898. #else
  1899.     Widget toplevel = 
  1900.     XtAppInitialize(&app_context, DDD_CLASS_NAME,
  1901.             XrmOptionDescList(0), 0, 
  1902.             &argc, argv, ddd_fallback_resources, args, arg);
  1903. #endif
  1904.     ddd_install_xt_error(app_context);
  1905.  
  1906.     // Check Motif version.  We can do this only now after the first
  1907.     // Motif widget has been created.
  1908.     setup_motif_version_warnings();
  1909.  
  1910.     // Merge ~/.ddd/init resources into application shell
  1911.     XrmDatabase target = XtDatabase(XtDisplay(toplevel));
  1912.     XrmMergeDatabases(dddinit, &target);
  1913.  
  1914.     // Setup top-level actions; this must be done before reading
  1915.     // application defaults.
  1916.     XtAppAddActions(app_context, actions, XtNumber(actions));
  1917.  
  1918.     // Register string -> OnOff converter; this must be done before
  1919.     // reading application defaults.
  1920.     XtSetTypeConverter(XmRString, XtROnOff, CvtStringToOnOff,
  1921.                NULL, 0, XtCacheAll, 
  1922.                XtDestructor(NULL));
  1923.  
  1924.     // Get application resources into APP_DATA
  1925.     XtVaGetApplicationResources(toplevel, (XtPointer)&app_data,
  1926.                 ddd_resources, ddd_resources_size,
  1927.                 NULL);
  1928.  
  1929.  
  1930. #if XtSpecificationRelease >= 6
  1931.     // Synchronize SESSION_ID and APP_DATA.session
  1932.     session_id = 0;
  1933.     XtVaGetValues(toplevel, XtNsessionID, &session_id, NULL);
  1934.     if (session_id != 0)
  1935.     app_data.session = session_id;
  1936. #endif
  1937.  
  1938.     if (app_data.session == 0)
  1939.     app_data.session = DEFAULT_SESSION;
  1940.     if (restart_session() != "")
  1941.     {
  1942.     static string s;
  1943.     s = restart_session();
  1944.     app_data.session = s;
  1945.     }
  1946.     session_id = app_data.session;
  1947.  
  1948.     // From this point on, APP_DATA is valid.
  1949.  
  1950. #ifdef SIGCHLD
  1951.     if (app_data.poll_child_status)
  1952.     {
  1953.     // In POLL_CHILD_STATUS mode, we ignore SIGCHLD signals and
  1954.     // poll the child process state explicitly, as in DDD 3.0 and
  1955.     // earlier.  Advantage: DDD does not depend on correct
  1956.     // asynchronous signal handling.  Disadvantage: somewhat
  1957.     // slower due to explicit polling.
  1958.     signal(SIGCHLD, SignalProc(SIG_DFL));
  1959.     }
  1960. #endif
  1961.  
  1962.     // Setup label hack
  1963.     arg = 0;
  1964.     XtCreateWidget("label_hack", xmLabelHackWidgetClass, toplevel, args, arg);
  1965.  
  1966.     // Set key bindings
  1967.     setup_cut_copy_paste_bindings(XtDatabase(XtDisplay(toplevel)));
  1968.     setup_select_all_bindings(XtDatabase(XtDisplay(toplevel)));
  1969.  
  1970.     // Handle `--version', `--help', etc.  once more, in case the user
  1971.     // gave appropriate X resources.  Somewhat paranoid.
  1972.     setup_show(XtDatabase(XtDisplay(toplevel)), XtName(toplevel), gdb_name);
  1973.  
  1974.     // Define font macros
  1975.     setup_fonts(app_data, XtDatabase(XtDisplay(toplevel)));
  1976.     if (app_data.show_fonts)
  1977.     return EXIT_SUCCESS;
  1978.  
  1979.     // Create new session dir if needed
  1980.     create_session_dir(app_data.session, messages);
  1981.  
  1982.     // Create a new auto_command_prefix if needed
  1983.     setup_auto_command_prefix();
  1984.  
  1985.     // Forward messages found so far into cerr
  1986.     {
  1987.     string msg(messages);
  1988.     cerr << msg;
  1989.     }
  1990.  
  1991.     // Set up VSL resources
  1992.     if (VSEFlags::parse_vsl(argc, argv))
  1993.     {
  1994.     // Show VSL usage...
  1995.     cout << VSEFlags::explain(true);
  1996.     return EXIT_FAILURE;
  1997.     }
  1998.  
  1999.     // All remaining args are passed to the inferior debugger.
  2000.     if (argc == 1 && app_data.open_selection)
  2001.     {
  2002.     // No args given - try to get one from current selection
  2003.     add_arg_from_selection(toplevel, argc, argv);
  2004.     }
  2005.  
  2006.     // Check the X configuration
  2007.     if (app_data.check_configuration)
  2008.     {
  2009.     if (check_x_configuration(toplevel, true))
  2010.         return EXIT_FAILURE;
  2011.     else
  2012.         return EXIT_SUCCESS;
  2013.     }
  2014.  
  2015.     // If needed, fix the X configuration silently
  2016.     check_x_configuration(toplevel, false);
  2017.  
  2018.     // Set up warning handler
  2019.     ddd_original_xt_warning_handler =
  2020.     XtAppSetWarningHandler(app_context, ddd_xt_warning);
  2021.  
  2022.     // Determine debugger type
  2023.     DebuggerType debugger_type = DebuggerType(-1);
  2024.  
  2025.     if (debugger_type == DebuggerType(-1) && gdb_name != "")
  2026.     {
  2027.     // Use given debugger
  2028.     get_debugger_type(gdb_name, debugger_type);
  2029.     }
  2030.  
  2031.     if (debugger_type == DebuggerType(-1) && !app_data.auto_debugger)
  2032.     {
  2033.     // Use debugger from args or app_defaults
  2034.     get_debugger_type(app_data.debugger, debugger_type);
  2035.     }
  2036.  
  2037.     if (debugger_type == DebuggerType(-1))
  2038.     {
  2039.     // Guess debugger type from args
  2040.     bool sure;
  2041.     debugger_type = guess_debugger_type(argc, argv, sure);
  2042.  
  2043.     if (!app_data.auto_debugger)
  2044.     {
  2045.         cerr << "Unknown debugger type " << quote(app_data.debugger)
  2046.          << ", using " << quote(default_debugger(debugger_type))
  2047.          << "instead\n";
  2048.     }
  2049.     }
  2050.  
  2051.     if (app_data.debugger_command[0] == '\0')
  2052.     {
  2053.     if (gdb_name != "")
  2054.         app_data.debugger_command = gdb_name;
  2055.     else
  2056.         app_data.debugger_command = default_debugger(debugger_type);
  2057.     }
  2058.  
  2059.     // Set host specification
  2060.     if (app_data.debugger_rhost && app_data.debugger_rhost[0] != '\0')
  2061.     gdb_host = app_data.debugger_rhost;
  2062.     else if (app_data.debugger_host && app_data.debugger_host[0] != '\0')
  2063.     gdb_host = app_data.debugger_host;
  2064.     else
  2065.     gdb_host = "";
  2066.  
  2067.     if (gdb_host.contains('@') && string(app_data.debugger_host_login) == "")
  2068.     {
  2069.     static string new_login = gdb_host.before('@');
  2070.     app_data.debugger_host_login = new_login;
  2071.     gdb_host = gdb_host.after('@');
  2072.     }
  2073.  
  2074.     if (gdb_host == "" && string(app_data.debugger_host_login) != "")
  2075.     {
  2076.     cerr << argv[0] << ": --login requires --rhost or --host\n";
  2077.     return EXIT_FAILURE;
  2078.     }
  2079.  
  2080.     // Check for `--play-log'
  2081.     if (app_data.play_log != NULL)
  2082.     {
  2083.     // Invoke self with `--PLAY LOGFILE' as inferior
  2084.     app_data.debugger_command = argv[0];
  2085.  
  2086.     if (!remote_gdb())
  2087.     {
  2088.         // Override debugger type from log
  2089.         check_log(app_data.play_log, debugger_type);
  2090.     }
  2091.  
  2092.     // Don't overwrite existing log files
  2093.     app_data.trace = true;
  2094.     }
  2095.  
  2096.     // Create a `~/.ddd/log' file for this session; 
  2097.     // log invocation and configuration
  2098.     init_dddlog();
  2099.  
  2100.     // Warn for incompatible `Ddd' and `~/.ddd/init' files
  2101.     setup_ddd_version_warnings();
  2102.  
  2103.     // Global variables: Set LessTif version
  2104.     lesstif_version = app_data.lesstif_version;
  2105.  
  2106.     // Global variables: Set maximum lengths
  2107.     max_value_tip_length              = app_data.max_value_tip_length;
  2108.     max_value_doc_length              = app_data.max_value_doc_length;
  2109.     DispBox::max_display_title_length = app_data.max_display_title_length;
  2110.     SourceView::max_popup_expr_length = app_data.max_popup_expr_length;
  2111.  
  2112.     // Global variables: Setup data display
  2113.     DataDisp::bump_displays           = app_data.bump_displays;
  2114.     DispValue::expand_repeated_values = app_data.expand_repeated_values;
  2115.     DispGraph::hide_inactive_displays = app_data.hide_inactive_displays;
  2116.  
  2117.     // Global variables: Setup plot settings
  2118.     PlotAgent::plot_2d_settings = app_data.plot_2d_settings;
  2119.     PlotAgent::plot_3d_settings = app_data.plot_3d_settings;
  2120.  
  2121.     // Global variables: Set delays for button and value tips
  2122.     help_button_tip_delay = app_data.button_tip_delay;
  2123.     help_value_tip_delay  = app_data.value_tip_delay;
  2124.     help_button_doc_delay = app_data.button_doc_delay;
  2125.     help_value_doc_delay  = app_data.value_doc_delay;
  2126.     help_clear_doc_delay  = app_data.clear_doc_delay;
  2127.     help_clear_tip_delay  = app_data.clear_tip_delay;
  2128.  
  2129. #if XmVersion >= 2000
  2130.     // Setup drag and drop callback
  2131.     Widget display_w = verify(XmGetXmDisplay(XtDisplay(toplevel)));
  2132.     if (XmIsDisplay(display_w))
  2133.     {
  2134.     XtAddCallback(display_w, XmNdragStartCallback,
  2135.               CheckDragCB, NULL);
  2136.     }
  2137. #else
  2138.     CheckDragCB(0, 0, 0);        // Use it
  2139. #endif
  2140.  
  2141.     // Re-register own converters.  Motif may have overridden some of
  2142.     // these, so register them again.
  2143.     registerOwnConverters();
  2144.  
  2145.     // Show splash screen
  2146.     Boolean iconic;
  2147.     XtVaGetValues(toplevel, XmNiconic, &iconic, NULL);
  2148.     if (app_data.splash_screen && !iconic && restart_session() == "")
  2149.     popup_splash_screen(toplevel, app_data.splash_screen_color_key);
  2150.  
  2151.     // Re-register own converters.  Motif has overridden some of
  2152.     // these, so register them again.
  2153.     registerOwnConverters();
  2154.  
  2155.     // Install special Motif converters
  2156. #if XmVersion >= 1002
  2157.     XmRepTypeInstallTearOffModelConverter();
  2158. #endif
  2159.  
  2160.     // Lock `~/.ddd/'.
  2161.     LockInfo lock_info;
  2162.     bool lock_ok = lock_ddd(toplevel, lock_info);
  2163.     if (!lock_ok)
  2164.     {
  2165.     // A minimal warning.
  2166.     messages << "Another " DDD_NAME " is running (pid "
  2167.          << lock_info.pid;
  2168.     if (lock_info.hostname != fullhostname())
  2169.         messages << ", host " << cook(lock_info.hostname);
  2170.     if (lock_info.display != XDisplayString(XtDisplay(toplevel)))
  2171.         messages << ", display " << cook(lock_info.display);
  2172.     messages << ")\n";
  2173.     }
  2174.  
  2175.     // Put saved options back again
  2176.     int i;
  2177.     for (i = argc + saved_options.size() - 1; i > saved_options.size(); i--)
  2178.     argv[i] = argv[i - saved_options.size()];
  2179.     for (i = saved_options.size() - 1; i >= 0; i--)
  2180.     argv[i + 1] = saved_options[i];
  2181.     argc += saved_options.size();
  2182.     argv[argc] = 0;
  2183.  
  2184.     // Create GDB interface
  2185.     gdb = new_gdb(debugger_type, app_data, app_context, argc, argv);
  2186.     defineConversionMacro("GDB", gdb->title());
  2187.  
  2188.     // Set up GDB handlers
  2189.     gdb->addHandler(ReadyForQuestion, gdb_readyHP);
  2190.     gdb->addHandler(InputEOF,         gdb_eofHP);
  2191.     gdb->addHandler(ErrorEOF,         gdb_eofHP);
  2192.     gdb->addHandler(Started,          ReportStartHP);
  2193.     gdb->addHandler(Died,             gdb_diedHP);
  2194.     gdb->addHandler(Died,             DisableBlinkHP);
  2195.     gdb->addHandler(Died,             ReportDeathHP);
  2196.     gdb->addHandler(LanguageChanged,  DataDisp::language_changedHP);
  2197.     gdb->addHandler(LanguageChanged,  language_changedHP);
  2198.     gdb->addHandler(LanguageChanged,  report_languageHP);
  2199.     gdb->addHandler(ReplyRequired,    gdb_selectHP);
  2200.     gdb->addHandler(Panic,            gdb_panicHP);
  2201.     gdb->addHandler(Strange,          gdb_strangeHP);
  2202.     gdb->addHandler(Recording,        gdb_recordingHP);
  2203.     gdb->addHandler(EchoDetected,     gdb_echo_detectedHP);
  2204.  
  2205.     // Set default history file (never read, only overwritten)
  2206.     set_gdb_history_file(gdb->history_file());
  2207.  
  2208.     // Setup shell creation
  2209.     Delay::shell_registered = setup_new_shell;
  2210.  
  2211.     // Create command shell
  2212.  
  2213.     // Use original arguments
  2214.     char **original_argv = saved_argv();
  2215.     int original_argc = 0;
  2216.     while (original_argv[original_argc] != 0)
  2217.     original_argc++;
  2218.  
  2219.     arg = 0;
  2220.     XtSetArg(args[arg], XmNdeleteResponse, XmDO_NOTHING); arg++;
  2221.     XtSetArg(args[arg], XmNargc,           original_argc); arg++;
  2222.     XtSetArg(args[arg], XmNargv,           original_argv); arg++;
  2223.  
  2224.     if (!app_data.separate_source_window && !app_data.separate_data_window)
  2225.     {
  2226.     // One single window - use command shell as top-level shell
  2227.     command_shell = 
  2228.         verify(XtAppCreateShell(NULL, DDD_CLASS_NAME,
  2229.                     applicationShellWidgetClass,
  2230.                     XtDisplay(toplevel), args, arg));
  2231.  
  2232.     // From now on, use the command shell as parent
  2233.     toplevel = command_shell;
  2234.     }
  2235.     else
  2236.     {
  2237.     // Separate windows - make command shell a popup shell.  
  2238.     // The toplevel window is never realized.
  2239.     command_shell =
  2240.         verify(XtCreatePopupShell("command_shell",
  2241.                       applicationShellWidgetClass,
  2242.                       toplevel, args, arg));
  2243.     }
  2244.     WM_DELETE_WINDOW =
  2245.     XmInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", False);
  2246.     XmAddWMProtocolCallback(command_shell, WM_DELETE_WINDOW, DDDCloseCB, 0);
  2247.  
  2248.     // From this point on, we have a true top-level window.
  2249.  
  2250.     // Create main window
  2251.     arg = 0;
  2252.     Widget main_window = XmCreateMainWindow(command_shell, "main_window",
  2253.                         args, arg);
  2254.     XtManageChild(main_window);
  2255.  
  2256.     // Re-register own converters to override Motif converters.
  2257.     registerOwnConverters();
  2258.  
  2259.     // Create menu bar
  2260.     MMDesc *menubar = common_menubar;
  2261.     if (app_data.separate_data_window && app_data.separate_source_window)
  2262.     menubar = command_menubar;
  2263.  
  2264.     Widget menubar_w = MMcreateMenuBar(main_window, "menubar", menubar);
  2265.     MMaddCallbacks(menubar);
  2266.     MMaddHelpCallback(menubar, ImmediateHelpCB);
  2267.     verify_buttons(menubar);
  2268.     register_menu_shell(menubar);
  2269.  
  2270.     // Create Paned Window
  2271.     arg = 0;
  2272.     XtSetArg(args[arg], XmNborderWidth,     0); arg++;
  2273.     XtSetArg(args[arg], XmNmarginWidth,     0); arg++;
  2274.     XtSetArg(args[arg], XmNshadowThickness, 0); arg++;
  2275.     Widget paned_work_w = verify(XmCreatePanedWindow(main_window,
  2276.                              "paned_work_w",
  2277.                              args, arg));
  2278.     XtManageChild(paned_work_w);
  2279.  
  2280.     // Status line
  2281.     if (!app_data.separate_source_window && !app_data.status_at_bottom)
  2282.     create_status(paned_work_w);
  2283.  
  2284.     // Toolbar label type
  2285.     unsigned char label_type = XmSTRING;
  2286.     if (app_data.button_captions || app_data.button_images)
  2287.     label_type = XmPIXMAP;
  2288.  
  2289.     // Common toolbar
  2290.     if (!app_data.button_captions && !app_data.button_images)
  2291.     app_data.common_toolbar = false;
  2292.  
  2293.     Widget arg_label = 0;
  2294.     if (!app_data.separate_source_window &&
  2295.     !app_data.separate_data_window &&
  2296.     app_data.common_toolbar)
  2297.     {
  2298.     arg_cmd_area[ArgItems::Display].type |= MMUnmanaged;
  2299.     arg_cmd_w = create_toolbar(paned_work_w, "common",
  2300.                    arg_cmd_area, DataDisp::graph_cmd_area,
  2301.                    arg_label, source_arg, XmPIXMAP);
  2302.  
  2303.     DataDisp::graph_cmd_w = arg_cmd_w;
  2304.  
  2305.     if (command_toolbar_w == 0)
  2306.     {
  2307.         command_toolbar_w = make_buttons(paned_work_w, 
  2308.                          "command_toolbar", 
  2309.                          app_data.tool_buttons);
  2310.     }
  2311.     }
  2312.     
  2313.     // Install icons if not already done
  2314.     install_icons(command_shell, 
  2315.           app_data.button_color_key,
  2316.           app_data.active_button_color_key);
  2317.  
  2318.     // Data window
  2319.     Widget data_disp_parent = paned_work_w;
  2320.     Widget data_menubar_w = 0;
  2321.     Widget data_main_window_w = 0;
  2322.     if (app_data.separate_data_window)
  2323.     {
  2324.     arg = 0;
  2325.     XtSetArg(args[arg], XmNdeleteResponse, XmDO_NOTHING); arg++;
  2326.     data_disp_shell =
  2327.         verify(XtCreatePopupShell("data_disp_shell",
  2328.                       topLevelShellWidgetClass,
  2329.                       toplevel, args, arg));
  2330.     XmAddWMProtocolCallback(data_disp_shell, WM_DELETE_WINDOW, 
  2331.                 DDDCloseCB, 0);
  2332.  
  2333.     arg = 0;
  2334.     data_main_window_w = XmCreateMainWindow(data_disp_shell, 
  2335.                         "data_main_window",
  2336.                         args, arg);
  2337.     XtManageChild(data_main_window_w);
  2338.  
  2339.     // Add menu bar
  2340.     data_menubar_w = 
  2341.         MMcreateMenuBar (data_main_window_w, "menubar", data_menubar);
  2342.     MMaddCallbacks(data_menubar);
  2343.     MMaddHelpCallback(menubar, ImmediateHelpCB);
  2344.     verify_buttons(data_menubar);
  2345.     register_menu_shell(data_menubar);
  2346.  
  2347.     arg = 0;
  2348.     XtSetArg(args[arg], XmNborderWidth,     0); arg++;
  2349.     XtSetArg(args[arg], XmNmarginWidth,     0); arg++;
  2350.     XtSetArg(args[arg], XmNshadowThickness, 0); arg++;
  2351.     data_disp_parent = verify(XmCreatePanedWindow(data_main_window_w,
  2352.                               "data_paned_work_w",
  2353.                               args, arg));
  2354.     XtManageChild(data_disp_parent);
  2355.     }
  2356.  
  2357.     // Create data display
  2358.     data_disp = new DataDisp(data_disp_parent, data_buttons_w);
  2359.  
  2360.     if (app_data.separate_data_window)
  2361.     {
  2362.     // More values for main window
  2363.     XtVaSetValues (data_main_window_w,
  2364.                XmNmenuBar,    data_menubar_w,
  2365.                XmNworkWindow, data_disp_parent,
  2366.                NULL);
  2367.     }
  2368.  
  2369.     if (data_buttons_w == 0)
  2370.     data_buttons_w = make_buttons(data_disp_parent, "data_buttons", 
  2371.                       app_data.data_buttons);
  2372.  
  2373.     // Source window
  2374.     Widget source_view_parent = paned_work_w;
  2375.     Widget source_menubar_w = 0;
  2376.     Widget source_main_window_w = 0;
  2377.     if (app_data.separate_source_window)
  2378.     {
  2379.     arg = 0;
  2380.     XtSetArg(args[arg], XmNdeleteResponse, XmDO_NOTHING); arg++;
  2381.     source_view_shell = 
  2382.         verify(XtCreatePopupShell("source_view_shell",
  2383.                       topLevelShellWidgetClass,
  2384.                       toplevel, args, arg));
  2385.     XmAddWMProtocolCallback(source_view_shell, WM_DELETE_WINDOW, 
  2386.                 DDDCloseCB, 0);
  2387.  
  2388.     arg = 0;
  2389.     source_main_window_w = XmCreateMainWindow(source_view_shell,
  2390.                           "source_main_window",
  2391.                           args, arg);
  2392.     XtManageChild(source_main_window_w);
  2393.  
  2394.     // Add menu bar
  2395.     source_menubar_w = 
  2396.         MMcreateMenuBar (source_main_window_w, "menubar", source_menubar);
  2397.     MMaddCallbacks(source_menubar);
  2398.     MMaddHelpCallback(menubar, ImmediateHelpCB);
  2399.     verify_buttons(source_menubar);
  2400.     register_menu_shell(source_menubar);
  2401.  
  2402.     // Add source window
  2403.     arg = 0;
  2404.     XtSetArg(args[arg], XmNborderWidth,     0); arg++;
  2405.     XtSetArg(args[arg], XmNmarginWidth,     0); arg++;
  2406.     XtSetArg(args[arg], XmNshadowThickness, 0); arg++;
  2407.     source_view_parent = 
  2408.         verify(XmCreatePanedWindow(source_main_window_w, 
  2409.                        "source_paned_work_w", args, arg));
  2410.     XtManageChild(source_view_parent);
  2411.  
  2412.     // Status line
  2413.     if (!app_data.status_at_bottom)
  2414.         create_status(source_view_parent);
  2415.     }
  2416.  
  2417.     // Add toolbar
  2418.     if (arg_cmd_w == 0 && !app_data.toolbars_at_bottom)
  2419.     {
  2420.     arg_cmd_w = create_toolbar(source_view_parent, "source",
  2421.                    arg_cmd_area, 0, arg_label, source_arg,
  2422.                    label_type);
  2423.     }
  2424.  
  2425.     if (command_toolbar_w == 0 && !app_data.toolbars_at_bottom)
  2426.     {
  2427.     command_toolbar_w = make_buttons(source_view_parent, 
  2428.                      "command_toolbar", 
  2429.                      app_data.tool_buttons);
  2430.     }
  2431.  
  2432.     if (source_buttons_w == 0 && !app_data.toolbars_at_bottom)
  2433.     {
  2434.     source_buttons_w = make_buttons(source_view_parent, 
  2435.                     "source_buttons", 
  2436.                     app_data.source_buttons);
  2437.     }
  2438.  
  2439.     source_view = new SourceView(source_view_parent);
  2440.     source_view->set_max_glyphs(app_data.max_glyphs);
  2441.     source_view->cache_glyph_images = app_data.cache_glyph_images;
  2442.  
  2443.     if (app_data.separate_source_window)
  2444.     {
  2445.     // More values for main window
  2446.     XtVaSetValues (source_main_window_w,
  2447.                XmNmenuBar,    source_menubar_w,
  2448.                XmNworkWindow, source_view_parent,
  2449.                NULL);
  2450.     }
  2451.  
  2452.     // Source toolbar
  2453.     if (arg_cmd_w == 0)
  2454.     arg_cmd_w = create_toolbar(source_view_parent, "source",
  2455.                    arg_cmd_area, 0, arg_label, source_arg,
  2456.                    label_type);
  2457.     XtAddCallback(arg_label, XmNactivateCallback, 
  2458.           ClearTextFieldCB, source_arg->text());
  2459.  
  2460.     if (DataDisp::graph_cmd_w == arg_cmd_w)
  2461.     {
  2462.     // Common toolbar
  2463.     XtAddCallback(arg_label, XmNactivateCallback, 
  2464.               DataDisp::SelectionLostCB, XtPointer(0));
  2465.     }
  2466.  
  2467.     XtAddCallback(source_arg->text(), XmNactivateCallback, 
  2468.           ActivateCB, 
  2469.           XtPointer(arg_cmd_area[ArgItems::Lookup].widget));
  2470.     sync_args(source_arg, data_disp->graph_arg);
  2471.  
  2472.     if (data_disp->graph_arg != 0)
  2473.     XtAddCallback(data_disp->graph_arg->text(), XmNactivateCallback, 
  2474.               ActivateCB, 
  2475.               XtPointer(data_disp->graph_cmd_area[0].widget));
  2476.  
  2477.     if (command_toolbar_w == 0)
  2478.     {
  2479.     command_toolbar_w = make_buttons(source_view_parent, 
  2480.                      "command_toolbar", 
  2481.                      app_data.tool_buttons);
  2482.     }
  2483.     if (command_toolbar_w != 0)
  2484.     XtUnmanageChild(command_toolbar_w);
  2485.  
  2486.     if (source_buttons_w == 0)
  2487.     source_buttons_w = make_buttons(source_view_parent, "source_buttons", 
  2488.                     app_data.source_buttons);
  2489.  
  2490.     // Status line
  2491.     if (app_data.separate_source_window && app_data.status_at_bottom)
  2492.     create_status(source_view_parent);
  2493.  
  2494.     // Debugger console
  2495.     if (console_buttons_w == 0 && !app_data.toolbars_at_bottom)
  2496.     console_buttons_w = make_buttons(paned_work_w, "console_buttons", 
  2497.                      app_data.console_buttons);
  2498.  
  2499.     arg = 0;
  2500.     gdb_w = verify(XmCreateScrolledText(paned_work_w, "gdb_w", args, arg));
  2501.  
  2502.     XtAddCallback (gdb_w,
  2503.            XmNmodifyVerifyCallback,
  2504.            gdbModifyCB,
  2505.            NULL);
  2506.     XtAddCallback (gdb_w,
  2507.            XmNmotionVerifyCallback,
  2508.            gdbMotionCB,
  2509.            NULL);
  2510.     XtAddCallback (gdb_w,
  2511.            XmNvalueChangedCallback,
  2512.            gdbChangeCB,
  2513.            NULL);
  2514.     XtManageChild (gdb_w);
  2515.  
  2516.     if (!app_data.separate_source_window || !app_data.separate_data_window)
  2517.     {
  2518.     // Don't resize the debugger console when resizing the main
  2519.     // window - resize source and/or data windows instead
  2520.     XtVaSetValues(XtParent(gdb_w), XmNskipAdjust, True, NULL);
  2521.     }
  2522.  
  2523.     // Set up the scrolled window
  2524.     XtVaSetValues(XtParent(gdb_w),
  2525.           XmNspacing,         0,
  2526.           XmNborderWidth,     0,
  2527.           XmNshadowThickness, 0,
  2528.           NULL);
  2529.  
  2530.     // Give the ScrolledWindow the size specified for the debugger console
  2531.     set_scrolled_window_size(gdb_w);
  2532.  
  2533. #if 0
  2534.     // Don't edit the text until the first prompt appears.
  2535.     XmTextSetEditable(gdb_w, false);
  2536. #endif
  2537.  
  2538.     if (console_buttons_w == 0)
  2539.     console_buttons_w = make_buttons(paned_work_w, "console_buttons", 
  2540.                      app_data.console_buttons);
  2541.  
  2542.     // Status line
  2543.     if (app_data.status_at_bottom && !app_data.separate_source_window)
  2544.     create_status(source_view_parent);
  2545.  
  2546.     // Paned Window is done
  2547.     XtManageChild (paned_work_w);
  2548.  
  2549.     // More values for main window
  2550.     XtVaSetValues (main_window,
  2551.            XmNmenuBar,    menubar_w,
  2552.            XmNworkWindow, paned_work_w,
  2553.            NULL);
  2554.  
  2555.     // All main widgets (except shells) are created at this point.
  2556.     
  2557.     // Load history for current session
  2558.     load_history(session_history_file(app_data.session));
  2559.  
  2560.     // Tie arg fields to history
  2561.     tie_combo_box_to_history(source_arg->text(), arg_history_filter);
  2562.     if (data_disp->graph_arg != 0)
  2563.     tie_combo_box_to_history(data_disp->graph_arg->text(), 
  2564.                  arg_history_filter);
  2565.  
  2566.     // Tie `recent files' to history
  2567.     tie_menu_to_recent_files(command_recent_menu);
  2568.     tie_menu_to_recent_files(source_recent_menu);
  2569.     tie_menu_to_recent_files(data_recent_menu);
  2570.  
  2571.     // Setup environment.
  2572.     setup_environment();
  2573.  
  2574.     // Setup handlers
  2575.     source_arg->addHandler (Changed, source_argHP);
  2576.     source_arg->callHandlers();
  2577.  
  2578.     // Setup insertion position
  2579.     promptPosition = messagePosition = XmTextGetLastPosition(gdb_w);
  2580.     XmTextSetInsertionPosition(gdb_w, messagePosition);
  2581.  
  2582.     // Setup help hooks
  2583.     PreHelpOnContextHook = PreHelpOnContext;
  2584.     PostHelpOnItemHook   = PostHelpOnItem;
  2585.  
  2586.     // Setup version info
  2587.     setup_version_info();
  2588.  
  2589.     // Customize `settings' title.
  2590.     set_settings_title(command_edit_menu[EditItems::Settings].widget);
  2591.     set_settings_title(source_edit_menu[EditItems::Settings].widget);
  2592.     set_settings_title(data_edit_menu[EditItems::Settings].widget);
  2593.  
  2594.     // Close windows explicitly requested
  2595.     if (!app_data.data_window && 
  2596.     (!app_data.full_name_mode || !app_data.tty_mode))
  2597.     {
  2598.     // We don't want the data window (unless in full name mode,
  2599.     // where we always open a data window - because otherwise, no
  2600.     // window would remain and we'd be gone).
  2601.     gdbCloseDataWindowCB(gdb_w, 0, 0);
  2602.     }
  2603.  
  2604.     if (!app_data.source_window || app_data.full_name_mode)
  2605.     {
  2606.     // We don't need the source window, since we're invoked by Emacs.
  2607.     gdbCloseSourceWindowCB(gdb_w, 0, 0);
  2608.  
  2609.     if (!app_data.disassemble)
  2610.         gdbCloseToolWindowCB(gdb_w, 0, 0);
  2611.     }
  2612.  
  2613.     if (!app_data.disassemble)
  2614.     {
  2615.     // We don't disassemble.
  2616.     gdbCloseCodeWindowCB(gdb_w, 0, 0);
  2617.     }
  2618.  
  2619.     if ((!app_data.debugger_console || app_data.tty_mode) &&
  2620.     (!app_data.separate_source_window || !app_data.separate_data_window))
  2621.     {
  2622.     // We don't need the debugger console, since we have a TTY.
  2623.     gdbCloseCommandWindowCB(gdb_w, 0, 0);
  2624.     }
  2625.  
  2626.     if (data_disp_shell != 0)
  2627.     {
  2628.     // Set width of the separate data window
  2629.     Dimension max_width = 0;
  2630.     get_paned_window_width(paned_work_w, max_width);
  2631.     get_paned_window_width(source_view_parent, max_width);
  2632.     set_paned_window_size(data_disp_parent, max_width);
  2633.     set_main_window_size(data_main_window_w);
  2634.     }
  2635.  
  2636.     // Popdown the splash screen before it eats up all colors
  2637.     popdown_splash_screen();
  2638.  
  2639.     // Realize all top-level widgets
  2640.     XtRealizeWidget(command_shell);
  2641.     Delay::register_shell(command_shell);
  2642.  
  2643.     if (data_disp_shell)
  2644.     {
  2645.     XtRealizeWidget(data_disp_shell);
  2646.     Delay::register_shell(data_disp_shell);
  2647.     }
  2648.  
  2649.     if (source_view_shell)
  2650.     {
  2651.     XtRealizeWidget(source_view_shell);
  2652.     Delay::register_shell(source_view_shell);
  2653.     }
  2654.  
  2655.     // Create initial delay
  2656.     if (app_data.session == DEFAULT_SESSION)
  2657.     {
  2658.     setup_delay = new Delay;
  2659.     init_delay  = new StatusMsg("Starting " + gdb->title());
  2660.     unlock_status();    // We still want to see the messages
  2661.     }
  2662.     else
  2663.     {
  2664.     init_delay = new StatusDelay("Opening session " 
  2665.                      + quote(app_data.session));
  2666.     }
  2667.  
  2668.     if (app_data.decorate_tool == Auto)
  2669.     {
  2670.     // Check for decorated transient windows.  We can do this only
  2671.     // after the command shell has been realized, because
  2672.     // otherwise the init shell might always be decorated.
  2673.     start_have_decorated_transients(command_shell);
  2674.     }
  2675.  
  2676.     // Remove unnecessary sashes
  2677.     untraverse_sashes(source_view_parent);
  2678.  
  2679.     // The sash in the source view is kept, as it separates source and
  2680.     // assembler code windows.
  2681. #if 0
  2682.     if (source_view_shell)
  2683.        unmanage_sashes(source_view_parent);
  2684. #endif
  2685.  
  2686.     untraverse_sashes(data_disp_parent);
  2687.     if (data_disp_shell)
  2688.     unmanage_sashes(data_disp_parent);
  2689.  
  2690.     untraverse_sashes(paned_work_w);
  2691.     if (source_view_shell && data_disp_shell)
  2692.     unmanage_sashes(paned_work_w);
  2693.  
  2694.     // Create subshells.  We do this after the main window has been
  2695.     // realized, since LessTif won't make the shells transient otherwise.
  2696.     source_view->create_shells();
  2697.     data_disp->create_shells();
  2698.     set_shortcut_menu(data_disp);
  2699.  
  2700.     // Create preference panels
  2701.     make_preferences(paned_work_w);
  2702.  
  2703.     // Save option states
  2704.     save_option_state();
  2705.  
  2706.     // Setup option states
  2707.     setup_options();
  2708.     update_options();
  2709.  
  2710.     // Setup info buttons
  2711.  
  2712.     // Our info routines require that the widgets be named after the
  2713.     // info command.  Ugly hack.
  2714.     strcpy(XtName(locals_w), gdb->info_locals_command());
  2715.     strcpy(XtName(args_w),   gdb->info_args_command());
  2716.  
  2717.     if (gdb->info_locals_command() != gdb->info_args_command())
  2718.     {
  2719.     register_info_button(locals_w);
  2720.     register_info_button(args_w);
  2721.     }
  2722.     else
  2723.     {
  2724.     register_info_button(locals_w);
  2725.     XtUnmanageChild(args_w);
  2726.     }
  2727.     update_infos();
  2728.  
  2729.     // Startup shells
  2730.     XtVaGetValues(toplevel, XmNiconic, &iconic, NULL);
  2731.     if (iconic)
  2732.     {
  2733.     // Startup command shell iconified; others follow as needed
  2734.     initial_popup_shell(command_shell);
  2735.     }
  2736.     else if ((!app_data.debugger_console || app_data.tty_mode) && 
  2737.          app_data.separate_source_window &&
  2738.          app_data.separate_data_window)
  2739.     {
  2740.     // Debugger console is closed: wait for source to pop up
  2741.     }
  2742.     else if (!app_data.tty_mode)
  2743.     {
  2744.     // Popup the command shell only; other shells follow as needed
  2745.     initial_popup_shell(command_shell);
  2746.     }
  2747.     else
  2748.     {
  2749.     // TTY mode: all shells follow as needed.
  2750.     }
  2751.  
  2752.     // Trace positions and visibility of all DDD windows
  2753.     if (command_shell)
  2754.     XtAddEventHandler(command_shell, STRUCTURE_MASK, False,
  2755.               StructureNotifyEH, XtPointer(0));
  2756.     if (source_view_shell)
  2757.     XtAddEventHandler(source_view_shell, STRUCTURE_MASK, False,
  2758.               StructureNotifyEH, XtPointer(0));
  2759.     if (data_disp_shell)
  2760.     XtAddEventHandler(data_disp_shell, STRUCTURE_MASK, False,
  2761.               StructureNotifyEH, XtPointer(0));
  2762.  
  2763. #if 0
  2764.     // Wait for the command shell to be mapped, such that we don't
  2765.     // lose debugger output.  This also decreases system load on
  2766.     // single-processor machines since DDD is idle when the debugger
  2767.     // starts.
  2768.     wait_until_mapped(command_shell);
  2769. #endif
  2770.  
  2771.     // Create command tool
  2772.     if (app_data.tool_buttons && strlen(app_data.tool_buttons) > 0)
  2773.     setup_command_tool();
  2774.  
  2775.     // Setup TTY interface
  2776.     setup_tty();
  2777.  
  2778.     // Raise core limit if needed; required for getting session info.
  2779.     // Note: this must be done before starting GDB.
  2780.     setup_core_limit();
  2781.  
  2782.     // Start debugger
  2783.     start_gdb();
  2784.     gdb_tty = gdb->slave_tty();
  2785.  
  2786.     if (!emptyCommandQueue())
  2787.     {
  2788.     // GDB startup leaves us with pending graph commands.  We
  2789.     // should better initialize the VSL library right now.
  2790.     DispBox::init_vsllib();
  2791.     }
  2792.  
  2793.     // Make sure we see all messages accumulated so far
  2794.     {
  2795.     string msg(messages);
  2796.     while (msg != "")
  2797.     {
  2798.         string line = msg.before('\n');
  2799.         set_status(line);
  2800.         msg = msg.after('\n');
  2801.     }
  2802.     }
  2803.  
  2804.     // Enter main event loop
  2805.     ddd_main_loop();
  2806.  
  2807.     return EXIT_SUCCESS;    // Never reached
  2808. }
  2809.  
  2810.  
  2811.  
  2812. //-----------------------------------------------------------------------------
  2813. // Process next X Event
  2814. //-----------------------------------------------------------------------------
  2815.  
  2816. void process_next_event()
  2817. {
  2818. #if HAVE_EXCEPTIONS
  2819.     try {
  2820. #endif
  2821.  
  2822.     if (app_data.poll_child_status)
  2823.     {
  2824.     // Check if GDB is still running
  2825.     gdb->running();
  2826.  
  2827.     // Check if the command TTY is still open
  2828.     tty_running();
  2829.     }
  2830.     else
  2831.     {
  2832. #if !ASYNC_CHILD_STATUS_CHANGE
  2833.     // Process pending child status changes
  2834.     Agent::runningAgents.commit();
  2835. #endif
  2836.     }
  2837.  
  2838.     // Check if the separate TTY is still running
  2839.     exec_tty_running();
  2840.  
  2841.     // Check for emergencies
  2842.     process_emergencies();
  2843.  
  2844.     // Restart blinker
  2845.     blink(gdb->recording() || !gdb->isReadyWithPrompt());
  2846.  
  2847.     // Get X event
  2848.     XtAppContext app_context = XtWidgetToApplicationContext(command_shell);
  2849.  
  2850.     XEvent event;
  2851.     XtAppNextEvent(app_context, &event);
  2852.  
  2853.     // Check for window creation.
  2854.     SwallowerCheckEvents();
  2855.  
  2856.     // Check for grabs.
  2857.     switch (event.type)
  2858.     {
  2859.     case MotionNotify:
  2860.     case ButtonPress:
  2861.     case ButtonRelease:
  2862.     case EnterNotify:
  2863.     case LeaveNotify:
  2864.     case KeyPress:
  2865.     case KeyRelease:
  2866.  
  2867.     // User interaction - the pointer cannot be grabbed,
  2868.     // since we receive input events.
  2869.     check_grabs(false);
  2870.     break;
  2871.  
  2872.     default:
  2873.     break;
  2874.     }
  2875.  
  2876.     // Dispatch event.
  2877.     XtDispatchEvent(&event);
  2878.  
  2879.     // Update tear-off menus.
  2880.     gdbUpdateAllMenus();
  2881.  
  2882. #if HAVE_EXCEPTIONS
  2883.     }
  2884. #if HAVE_EXCEPTION && HAVE_STD_EXCEPTIONS && HAVE_TYPEINFO
  2885.     // Standard library exception: get its type and diagnostics.
  2886.     catch (const exception& err)
  2887.     {
  2888.     ddd_show_exception(typeid(err).name(), err.what());
  2889.     }
  2890. #endif // HAVE_EXCEPTION && HAVE_STD_EXCEPTIONS && HAVE_TYPEINFO
  2891.     catch (...)
  2892.     {
  2893.     // Handle non-standard C++ exceptions
  2894.     ddd_show_exception();
  2895.     }
  2896. #endif // HAVE_EXCEPTIONS
  2897. }
  2898.  
  2899. void process_pending_events()
  2900. {
  2901.     if (command_shell == 0)
  2902.     return;
  2903.  
  2904.     XtAppContext app_context = XtWidgetToApplicationContext(command_shell);
  2905.     while (XtAppPending(app_context) & XtIMXEvent)
  2906.     process_next_event();
  2907. }
  2908.  
  2909.  
  2910. //-----------------------------------------------------------------------------
  2911. // Check if interaction events (key or mouse) are pending
  2912. //-----------------------------------------------------------------------------
  2913.  
  2914. static bool pending_interaction()
  2915. {
  2916.     XEvent event;
  2917.     const long mask = KeyPressMask | ButtonMotionMask | ButtonPressMask;
  2918.     Bool pending = XCheckMaskEvent(XtDisplay(command_shell), mask, &event);
  2919.     if (pending)
  2920.     XPutBackEvent(XtDisplay(command_shell), &event);
  2921.     return pending;
  2922. }
  2923.  
  2924. //-----------------------------------------------------------------------------
  2925. // Check this version; give warnings if needed (no license, beta expired, etc.)
  2926. //-----------------------------------------------------------------------------
  2927.  
  2928. static void ddd_check_version()
  2929. {
  2930.     static bool checked = false;
  2931.  
  2932.     if (checked)
  2933.     return;
  2934.     checked = true;
  2935.  
  2936.     if (restart_session() != "")
  2937.     return; // We told the user in the previous DDD instance
  2938.  
  2939.     // Tell user once more about version mismatches
  2940.     if (!version_warnings.isEmpty())
  2941.     {
  2942.     Arg args[10];
  2943.     int arg = 0;
  2944.  
  2945.     XtSetArg(args[arg], XmNmessageString, 
  2946.          version_warnings.xmstring()); arg++;
  2947.     Widget warning = 
  2948.         verify(XmCreateWarningDialog(command_shell, "bad_version_warning",
  2949.                      args, arg));
  2950.     Delay::register_shell(warning);
  2951.     XtUnmanageChild(XmMessageBoxGetChild(warning, XmDIALOG_CANCEL_BUTTON));
  2952.     XtAddCallback(warning, XmNhelpCallback, ImmediateHelpCB, NULL);
  2953.  
  2954.     manage_and_raise(warning);
  2955.     }
  2956.  
  2957.     if (app_data.dddinit_version == 0 ||
  2958.     string(app_data.dddinit_version) != DDD_VERSION)
  2959.     {
  2960.     // We have no ~/.ddd/init file or an old one: show version info
  2961.     HelpOnVersionCB(command_shell, 0, 0);
  2962.  
  2963.     // We have no ~/.ddd/init file: create a simple one
  2964.     if (app_data.dddinit_version == 0)
  2965.     {
  2966.         static string session = app_data.session;
  2967.         app_data.session = DEFAULT_SESSION;
  2968.         save_options(CREATE_OPTIONS);
  2969.         app_data.session = session;
  2970.     }
  2971.     }
  2972.  
  2973.     // Check for expired versions
  2974.     if (ddd_expired())
  2975.     {
  2976.     ostrstream msg;
  2977.     msg << "This " DDD_NAME " version (" DDD_VERSION ") has expired since "
  2978.         << ddd_expiration_date() << ".\n"
  2979.         << "Please upgrade to the recent " DDD_NAME " version.";
  2980.  
  2981.     post_warning(string(msg), "expired_warning");
  2982.     }
  2983.  
  2984.     if (app_data.startup_tips)
  2985.     TipOfTheDayCB(gdb_w);
  2986. }
  2987.  
  2988. // Read in database from FILENAME.  Upon version mismatch, ignore some
  2989. // resources such as window sizes.
  2990. XrmDatabase GetFileDatabase(char *filename)
  2991. {
  2992.     string version_found = "";
  2993.  
  2994.     string tempfile = tmpnam(0);
  2995.     ofstream os(tempfile);
  2996.     ifstream is(filename);
  2997.  
  2998. #if 0
  2999.     clog << "Copying " << filename << " to " << tempfile << "\n";
  3000. #endif
  3001.  
  3002.     // Resources to ignore upon copying
  3003.     static char *do_not_copy[] = 
  3004.     { 
  3005.     XmNwidth, XmNheight,                  // Shell sizes
  3006.     XmNcolumns, XmNrows,                  // Text window sizes
  3007.     XtNtoolRightOffset, XtNtoolTopOffset, // Command tool offset
  3008.     XtNshowHints,                      // Show edge hints
  3009.     };
  3010.  
  3011.     bool version_mismatch = false;
  3012.     while (is)
  3013.     {
  3014.     char _line[ARG_MAX];
  3015.     _line[0] = '\0';
  3016.     is.getline(_line, sizeof(_line));
  3017.     string line = _line;
  3018.  
  3019.     bool copy = true;
  3020.     if (line.contains('!', 0))
  3021.     {
  3022.         // Comment -- proceed
  3023.     }
  3024.     else
  3025.     {
  3026.         if (line.contains(XtNdddinitVersion ":"))
  3027.         {
  3028.         version_found = line.after(":");
  3029.         strip_space(version_found);
  3030.  
  3031.         if (version_found != DDD_VERSION)
  3032.             version_mismatch = true;
  3033.         }
  3034.  
  3035. #define XtNdisplayShortcuts "displayShortcuts"
  3036.  
  3037.         if (line.contains(XtNdisplayShortcuts ":"))
  3038.         {
  3039.         line.gsub(XtNdisplayShortcuts ":", XtNgdbDisplayShortcuts ":");
  3040.         }
  3041.  
  3042.         for (int i = 0; copy && i < int(XtNumber(do_not_copy)); i++)
  3043.         {
  3044.         string res = string(".") + do_not_copy[i] + ":";
  3045.         if (line.contains(res) && version_mismatch)
  3046.         {
  3047. #if 0
  3048.             cerr << "Warning: ignoring " << line 
  3049.              << " in " << filename << "\n";
  3050. #endif
  3051.             copy = false;
  3052.         }
  3053.         }
  3054.     }
  3055.  
  3056.     if (copy)
  3057.         os << line << '\n';
  3058.     }
  3059.  
  3060.     // Flush them all
  3061.     os.close();
  3062.     is.close();
  3063.  
  3064.     if (version_mismatch)
  3065.     {
  3066.     // Read database from filtered file
  3067.     XrmDatabase db = XrmGetFileDatabase(tempfile);
  3068.     unlink(tempfile);
  3069.     return db;
  3070.     }
  3071.     else
  3072.     {
  3073.     // No version mismatch - read from original file
  3074.     unlink(tempfile);
  3075.     return XrmGetFileDatabase(filename);
  3076.     }
  3077. }
  3078.  
  3079.  
  3080.  
  3081. //-----------------------------------------------------------------------------
  3082. // Install DDD log
  3083. //-----------------------------------------------------------------------------
  3084.  
  3085. static ostrstream devnull;
  3086. ostream *_dddlog = &devnull;
  3087.  
  3088. void init_dddlog()
  3089. {
  3090.     if (_dddlog != &devnull)
  3091.     return;            // Already initialized
  3092.  
  3093.     if (app_data.trace)
  3094.     {
  3095.     _dddlog = &clog;
  3096.     }
  3097.     else
  3098.     {
  3099.     static ofstream log(session_log_file());
  3100.     _dddlog = &log;
  3101.     }
  3102.  
  3103.     show_configuration(dddlog);
  3104.  
  3105.     dddlog << "$ ";
  3106.     for (int i = 0; saved_argv()[i] != 0; i++)
  3107.     dddlog << " " << cook(saved_argv()[i]);
  3108.     dddlog << '\n';
  3109.  
  3110.     dddlog.flush();
  3111. }
  3112.  
  3113. //-----------------------------------------------------------------------------
  3114. // Install button tips
  3115. //-----------------------------------------------------------------------------
  3116.  
  3117. static void install_button_tips()
  3118. {
  3119.     const WidgetArray& shells = Delay::shells();
  3120.     for (int i = 0; i < shells.size(); i++)
  3121.     {
  3122.     Widget shell = shells[i];
  3123.     while (shell && !XmIsVendorShell(shell) && !XmIsMenuShell(shell))
  3124.         shell = XtParent(shell);
  3125.     if (shell)
  3126.         InstallButtonTips(shell);
  3127.     }
  3128. }
  3129.  
  3130. void register_menu_shell(MMDesc *items)
  3131. {
  3132.     if (items == 0)
  3133.     return;
  3134.  
  3135.     // Register shell of this menu
  3136.     Widget shell = items[0].widget;
  3137.     while (shell && !XtIsShell(shell))
  3138.     shell = XtParent(shell);
  3139.     if (shell)
  3140.     Delay::register_shell(shell);
  3141.  
  3142.     // Register shells of submenus
  3143.     for (int i = 0; items[i].widget != 0; i++)
  3144.     register_menu_shell(items[i].items);
  3145. }
  3146.  
  3147.  
  3148. //-----------------------------------------------------------------------------
  3149. // Verify buttons
  3150. //-----------------------------------------------------------------------------
  3151.  
  3152. static void verify_button(MMDesc *item, XtPointer)
  3153. {
  3154.     verify_button(item->widget);
  3155. }
  3156.  
  3157. static void verify_buttons(MMDesc *items)
  3158. {
  3159.     MMonItems(items, verify_button);
  3160. }
  3161.  
  3162. //-----------------------------------------------------------------------------
  3163. // Create DataDisp shortcut menu
  3164. //-----------------------------------------------------------------------------
  3165.  
  3166. static void set_shortcut_menu(DataDisp *data_disp, string exprs)
  3167. {
  3168.     int newlines = exprs.freq('\n') + 1;
  3169.     string *items = new string[newlines];
  3170.     split(exprs, items, newlines, '\n');
  3171.  
  3172.     StringArray items_s;
  3173.     StringArray labels_s;
  3174.     for (int i = 0; i < newlines; i++)
  3175.     {
  3176.     string item  = items[i];
  3177.     string label = "";
  3178.  
  3179.     if (item.contains(app_data.label_delimiter))
  3180.     {
  3181.         label = item.after(app_data.label_delimiter);
  3182.         item  = item.before(app_data.label_delimiter);
  3183.     }
  3184.  
  3185.     strip_space(item);
  3186.     strip_space(label);
  3187.  
  3188.     if (item == "")
  3189.         continue;
  3190.  
  3191.     items_s  += item;
  3192.     labels_s += label;
  3193.     }
  3194.  
  3195.     data_disp->set_shortcut_menu(items_s, labels_s);
  3196.  
  3197.     delete[] items;
  3198. }
  3199.  
  3200. static void set_shortcut_menu(DataDisp *data_disp)
  3201. {
  3202.     string display_shortcuts;
  3203.     switch (gdb->type())
  3204.     {
  3205.     case GDB:  display_shortcuts = app_data.gdb_display_shortcuts;  break;
  3206.     case DBX:  display_shortcuts = app_data.dbx_display_shortcuts;  break;
  3207.     case XDB:  display_shortcuts = app_data.xdb_display_shortcuts;  break;
  3208.     case JDB:  display_shortcuts = app_data.jdb_display_shortcuts;  break;
  3209.     case PYDB: display_shortcuts = app_data.pydb_display_shortcuts; break;
  3210.     case PERL: display_shortcuts = app_data.perl_display_shortcuts; break;
  3211.     }
  3212.     set_shortcut_menu(data_disp, display_shortcuts);
  3213. }
  3214.  
  3215. //-----------------------------------------------------------------------------
  3216. // Fix size of status line
  3217. //-----------------------------------------------------------------------------
  3218.  
  3219. static void fix_status_size()
  3220. {
  3221.     if (!app_data.status_at_bottom)
  3222.     return;
  3223.  
  3224.     Widget status_form = XtParent(status_w);
  3225.     if (!XtIsRealized(status_form))
  3226.     return;
  3227.  
  3228.     Dimension pane_maximum, height;
  3229.     XtVaGetValues(status_form,
  3230.           XmNpaneMaximum, &pane_maximum, 
  3231.           XmNheight, &height,
  3232.           NULL);
  3233.  
  3234.     if (height <= pane_maximum)
  3235.     return;
  3236.  
  3237.     XtVaSetValues(status_form,
  3238.           XmNallowResize, True,
  3239.           XmNheight, pane_maximum,
  3240.           XmNallowResize, False,
  3241.           NULL);
  3242.  
  3243.     if (lesstif_version <= 79)
  3244.     {
  3245.     // For LessTif 0.79 and earlier, simulate a drag of the lowest
  3246.     // sash to the bottom.  Ugly LessTif hack.
  3247.  
  3248.     // Find the children of the paned window
  3249.     Widget paned = XtParent(status_form);
  3250.     WidgetList children;
  3251.     Cardinal num_children = 0;
  3252.     
  3253.     XtVaGetValues(paned, 
  3254.               XmNchildren, &children,
  3255.               XmNnumChildren, &num_children,
  3256.               NULL);
  3257.  
  3258.     // The sash controlling the status line is the lowest of all
  3259.     Widget sash = 0;
  3260.     for (Cardinal i = 0; i < num_children; i++)
  3261.     {
  3262.         Widget child = children[i];
  3263.  
  3264.         if (XmIsSash(child) && XtIsRealized(child) && XtIsManaged(child))
  3265.         {
  3266.         Position sash_y  = 0;
  3267.         Position child_y = 1;
  3268.  
  3269.         if (sash != 0)
  3270.         {
  3271.             XtVaGetValues(sash,  XmNy, &sash_y, NULL);
  3272.             XtVaGetValues(child, XmNy, &child_y, NULL);
  3273.         }
  3274.  
  3275.         if (child_y > sash_y)
  3276.             sash = child;
  3277.         }
  3278.     }
  3279.  
  3280.     if (sash != 0 && XtIsRealized(sash))
  3281.     {
  3282.         // Simulate a vertical drag of MOVEMENT pixels
  3283.         const Dimension movement = 
  3284.         max(height, HeightOfScreen(XtScreen(sash)));
  3285.  
  3286.         // Press button 1 ...
  3287.         XEvent event;
  3288.         event.type                = ButtonPress;
  3289.         event.xbutton.serial      = 0;
  3290.         event.xbutton.display     = XtDisplay(sash);
  3291.         event.xbutton.window      = XtWindow(sash);
  3292.         event.xbutton.root        = RootWindowOfScreen(XtScreen(sash));
  3293.         event.xbutton.subwindow   = None;
  3294.         event.xbutton.time        = 
  3295.         XtLastTimestampProcessed(XtDisplay(sash));
  3296.         event.xbutton.x           = 0;
  3297.         event.xbutton.y           = 0;
  3298.         event.xbutton.x_root      = 0;
  3299.         event.xbutton.y_root      = 0;
  3300.         event.xbutton.state       = Button1Mask;
  3301.         event.xbutton.button      = Button1;
  3302.         event.xbutton.same_screen = True;
  3303.         XtDispatchEvent(&event);
  3304.  
  3305.         // ... move down ...
  3306.         for (Dimension y = 0; y < movement; y += 5)
  3307.         {
  3308.         event.type                = MotionNotify;
  3309.         event.xmotion.serial      = 0;
  3310.         event.xmotion.display     = XtDisplay(sash);
  3311.         event.xmotion.window      = XtWindow(sash);
  3312.         event.xmotion.root        = 
  3313.             RootWindowOfScreen(XtScreen(sash));
  3314.         event.xmotion.subwindow   = None;
  3315.         event.xmotion.time        = 
  3316.             XtLastTimestampProcessed(XtDisplay(sash));
  3317.         event.xmotion.x           = 0;
  3318.         event.xmotion.y           = y;
  3319.         event.xmotion.x_root      = 0;
  3320.         event.xmotion.y_root      = y;
  3321.         event.xmotion.state       = Button1Mask;
  3322.         event.xmotion.is_hint     = NotifyNormal;
  3323.         event.xmotion.same_screen = True;
  3324.         XtDispatchEvent(&event);
  3325.         }
  3326.  
  3327.         // ... until target position is reached ...
  3328.         event.type                = MotionNotify;
  3329.         event.xmotion.serial      = 0;
  3330.         event.xmotion.display     = XtDisplay(sash);
  3331.         event.xmotion.window      = XtWindow(sash);
  3332.         event.xmotion.root        = RootWindowOfScreen(XtScreen(sash));
  3333.         event.xmotion.subwindow   = None;
  3334.         event.xmotion.time        = 
  3335.         XtLastTimestampProcessed(XtDisplay(sash));
  3336.         event.xmotion.x           = 0;
  3337.         event.xmotion.y           = movement;
  3338.         event.xmotion.x_root      = 0;
  3339.         event.xmotion.y_root      = movement;
  3340.         event.xmotion.state       = Button1Mask;
  3341.         event.xmotion.is_hint     = NotifyNormal;
  3342.         event.xmotion.same_screen = True;
  3343.         XtDispatchEvent(&event);
  3344.  
  3345.         // ... and release button1 again.
  3346.         event.type                = ButtonRelease;
  3347.         event.xbutton.serial      = 0;
  3348.         event.xbutton.display     = XtDisplay(sash);
  3349.         event.xbutton.window      = XtWindow(sash);
  3350.         event.xbutton.root        = RootWindowOfScreen(XtScreen(sash));
  3351.         event.xbutton.subwindow   = None;
  3352.         event.xbutton.time        = 
  3353.         XtLastTimestampProcessed(XtDisplay(sash));
  3354.         event.xbutton.x           = 0;
  3355.         event.xbutton.y           = movement;
  3356.         event.xbutton.x_root      = 0;
  3357.         event.xbutton.y_root      = movement;
  3358.         event.xbutton.state       = Button1Mask;
  3359.         event.xbutton.button      = Button1;
  3360.         event.xbutton.same_screen = True;
  3361.         XtDispatchEvent(&event);
  3362.     }
  3363.     }
  3364. }
  3365.  
  3366.  
  3367. //---------------------------------------------------------------------------
  3368. // Locking stuff
  3369. //---------------------------------------------------------------------------
  3370.  
  3371. static bool continue_despite_lock = false;
  3372. static int lock_dialog_x = -1;
  3373. static int lock_dialog_y = -1;
  3374.  
  3375. static void ContinueDespiteLockCB(Widget, XtPointer, XtPointer)
  3376. {
  3377.     continue_despite_lock = true;
  3378. }
  3379.  
  3380. static void TryLock(XtPointer client_data, XtIntervalId *)
  3381. {
  3382.     Widget w = (Widget)client_data;
  3383.  
  3384.     LockInfo info;
  3385.     bool lock_ok = lock_session_dir(XtDisplay(w), DEFAULT_SESSION, info);
  3386.  
  3387.     if (lock_ok)
  3388.     {
  3389.     continue_despite_lock = true;
  3390.     return;
  3391.     }
  3392.  
  3393.     XtAppAddTimeOut(XtWidgetToApplicationContext(w), 500, 
  3394.             TryLock, client_data);
  3395. }
  3396.  
  3397. #if XmVersion >= 1002
  3398. static void KillLockerCB(Widget w, XtPointer client_data, XtPointer)
  3399. {
  3400.     static int attempts_to_kill = 0;
  3401.  
  3402.     LockInfo *info = (LockInfo *)client_data;
  3403.  
  3404.     kill(info->pid, SIGHUP);
  3405.  
  3406.     if (attempts_to_kill++ == 0)
  3407.     {
  3408.     // Try locking again until successful
  3409.     TryLock(XtPointer(w), 0);
  3410.     }
  3411. }
  3412. #endif
  3413.  
  3414. static bool lock_ddd(Widget parent, LockInfo& info)
  3415. {
  3416.     bool lock_ok = lock_session_dir(XtDisplay(parent), DEFAULT_SESSION, info);
  3417.     if (lock_ok)
  3418.     return true;
  3419.  
  3420.     if (!app_data.warn_if_locked)
  3421.     return false;
  3422.  
  3423.     bool on_local_host = (info.hostname == fullhostname());
  3424.  
  3425.     string lock_file = session_lock_file(DEFAULT_SESSION);
  3426.     
  3427.     MString msg = rm(DDD_NAME " has detected a ") 
  3428.     + tt(lock_file) + rm(" file.") + cr()
  3429.     + cr()
  3430.     + rm("This may indicate that another user is running "
  3431.          DDD_NAME) + cr()
  3432.     + rm("using your ")
  3433.     + tt(session_state_dir() + "/") + rm(" files.") + cr()
  3434.     + rm(DDD_NAME " appears to be running under process ID ") 
  3435.     + tt(itostring(info.pid));
  3436.  
  3437.     if (!on_local_host)
  3438.     msg += cr() + rm("on host ") + tt(info.hostname);
  3439.  
  3440.     msg += rm(".") 
  3441.     + cr()
  3442.     + rm("You may continue to use " DDD_NAME ", but your "
  3443.          "saved " DDD_NAME " state may be") + cr()
  3444.     + rm("overwritten by the other " DDD_NAME " instance.") + cr()
  3445.     + cr();
  3446.  
  3447. #if XmVersion >= 1002
  3448.     if (on_local_host)
  3449.     msg += rm("You can kill the other " DDD_NAME " instance now.") + cr();
  3450. #endif
  3451.  
  3452.     msg += rm("Otherwise, make sure that you are not running "
  3453.           "another " DDD_NAME " and ") + cr()
  3454.     + rm("delete the ") + tt(lock_file) + rm(" file.") + cr()
  3455.     + cr()
  3456.     + rm("To continue despite the other " DDD_NAME " instance, ")
  3457.     + rm("click on ") + bf("Continue") + rm(".") + cr();
  3458. #if XmVersion >= 1002
  3459.     if (on_local_host)
  3460.     msg += rm("To kill the other " DDD_NAME " instance and continue, ")
  3461.         + rm("click on ") + bf("Kill") + rm(".") + cr();
  3462. #endif
  3463.  
  3464.     msg += rm("To exit this " DDD_NAME " instance, click on ") 
  3465.     + bf("Exit") + rm(".");
  3466.     
  3467.     Arg args[10];
  3468.     int arg = 0;
  3469.     
  3470.     XtSetArg(args[arg], XmNautoUnmanage, False); arg++;
  3471.     XtSetArg(args[arg], XmNmessageString, msg.xmstring()); arg++;
  3472.     XtSetArg(args[arg], XmNdialogStyle, 
  3473.          XmDIALOG_FULL_APPLICATION_MODAL); arg++;
  3474.  
  3475.     string geometry;
  3476.     if (lock_dialog_x >= 0 && lock_dialog_y >= 0)
  3477.     {
  3478.     ostrstream os;
  3479.     os << "+" << lock_dialog_x << "+" << lock_dialog_y;
  3480.     geometry = string(os);
  3481.     XtSetArg(args[arg], XmNgeometry, geometry.chars()); arg++;
  3482.     XtSetArg(args[arg], XmNx, lock_dialog_x); arg++;
  3483.     XtSetArg(args[arg], XmNy, lock_dialog_y); arg++;
  3484.     }
  3485.  
  3486.     Widget lock_dialog =
  3487.     verify(XmCreateQuestionDialog(parent, "lock_dialog", args, arg));
  3488.     Delay::register_shell(lock_dialog);
  3489.  
  3490. #if XmVersion >= 1002
  3491.     Widget kill = verify(XmCreatePushButton(lock_dialog, "kill", 0, 0));
  3492.     XtManageChild(kill);
  3493.     XtAddCallback(kill, XmNactivateCallback,
  3494.           KillLockerCB, XtPointer(&info));
  3495.     set_sensitive(kill, on_local_host);
  3496. #endif
  3497.  
  3498.     XtAddCallback(lock_dialog, XmNhelpCallback,
  3499.           ImmediateHelpCB, NULL);
  3500.     XtAddCallback(lock_dialog, XmNokCallback,
  3501.           ContinueDespiteLockCB, NULL);
  3502.     XtAddCallback(lock_dialog, XmNcancelCallback, ExitCB, 
  3503.           XtPointer(EXIT_FAILURE));
  3504.  
  3505.     if (geometry != "")
  3506.     {
  3507.     Widget shell = lock_dialog;
  3508.     while (!XmIsDialogShell(shell))
  3509.         shell = XtParent(shell);
  3510.  
  3511.     arg = 0;
  3512.     XtSetArg(args[arg], XmNgeometry, geometry.chars()); arg++;
  3513.     XtSetArg(args[arg], XmNx, lock_dialog_x); arg++;
  3514.     XtSetArg(args[arg], XmNy, lock_dialog_y); arg++;
  3515.     XtSetValues(shell, args, arg);
  3516.     }
  3517.  
  3518.     continue_despite_lock = false;
  3519.     manage_and_raise(lock_dialog);
  3520.  
  3521.     while (!continue_despite_lock)
  3522.     XtAppProcessEvent(XtWidgetToApplicationContext(lock_dialog), XtIMAll);
  3523.  
  3524.     XtDestroyWidget(lock_dialog);
  3525.  
  3526.     // Try locking once more
  3527.     return lock_session_dir(XtDisplay(parent), DEFAULT_SESSION, info);
  3528. }
  3529.  
  3530.  
  3531. //-----------------------------------------------------------------------------
  3532. // Setup
  3533. //-----------------------------------------------------------------------------
  3534.  
  3535. static Boolean session_setup_done(XtPointer)
  3536. {
  3537.     if (emptyCommandQueue() && gdb->isReadyWithPrompt())
  3538.     {
  3539.     // Delete initialization delay, if any
  3540.     delete init_delay;
  3541.     init_delay = 0;
  3542.  
  3543.     // Say hello
  3544.     set_status_mstring(rm("Welcome to " DDD_NAME " " DDD_VERSION 
  3545.                   " \"" DDD_NICKNAME "\""
  3546.                   " (" DDD_HOST ")"));
  3547.  
  3548.     if (app_data.initial_session != 0)
  3549.     {
  3550.         set_session(app_data.initial_session);
  3551.         app_data.initial_session = 0;
  3552.     }
  3553.  
  3554.     // From now on, verify the state file for changes
  3555.     check_options_file();
  3556.  
  3557.     return True;        // Remove from the list of work procs
  3558.     }
  3559.  
  3560.     return False;        // Get called again
  3561. }
  3562.  
  3563. Boolean ddd_setup_done(XtPointer)
  3564. {
  3565.     // Delete setup delay, if any
  3566.     delete setup_delay;
  3567.     setup_delay = 0;
  3568.  
  3569.     if (emptyCommandQueue() && gdb->isReadyWithPrompt())
  3570.     {
  3571.     // Some WMs have trouble with early decorations.  Just re-decorate.
  3572.     setup_new_shell(command_shell);
  3573.     setup_new_shell(data_disp_shell);
  3574.     setup_new_shell(source_view_shell);
  3575.  
  3576.     ddd_check_version();
  3577.     install_button_tips();
  3578.     fix_status_size();
  3579.  
  3580.     if (running_shells() == 0)
  3581.     {
  3582.         // We have no shell (yet).  Be sure to popup at least one shell.
  3583.         if (app_data.source_window)
  3584.         gdbOpenSourceWindowCB(gdb_w, 0, 0);
  3585.         else if (app_data.data_window)
  3586.         gdbOpenDataWindowCB(gdb_w, 0, 0);
  3587.         else
  3588.         gdbOpenCommandWindowCB(gdb_w, 0, 0);
  3589.     }
  3590.  
  3591.     main_loop_entered = true;
  3592.  
  3593.     DispBox::init_vsllib(process_pending_events);
  3594.     DataDisp::refresh_graph_edit();
  3595.  
  3596.     if (init_delay != 0 || app_data.initial_session != 0)
  3597.     {
  3598.         // Restoring session may still take time
  3599.         XtAppAddWorkProc(XtWidgetToApplicationContext(command_shell),
  3600.                  session_setup_done, 0);
  3601.     }
  3602.     return True;        // Remove from the list of work procs
  3603.     }
  3604.  
  3605.     return False;        // Keep on processing the command queue
  3606. }
  3607.  
  3608.  
  3609.  
  3610. //-----------------------------------------------------------------------------
  3611. // Activate argument field
  3612. //-----------------------------------------------------------------------------
  3613.  
  3614. static void ActivateCB(Widget, XtPointer client_data, XtPointer call_data)
  3615. {
  3616.     XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *)call_data;
  3617.     
  3618.     Widget button = Widget(client_data);
  3619.     XtCallActionProc(button, "ArmAndActivate", cbs->event, (String *)0, 0);
  3620. }
  3621.  
  3622. //-----------------------------------------------------------------------------
  3623. // Drag and drop
  3624. //-----------------------------------------------------------------------------
  3625.  
  3626. static void CheckDragCB(Widget, XtPointer, XtPointer call_data)
  3627. {
  3628.     if (call_data == 0)        // Use it
  3629.     return;
  3630.  
  3631.     // Some Linux Motif implementations have trouble dragging pixmaps.
  3632.     // Disable this, such that we don't get drowned in bug reports.
  3633. #if XmVersion >= 2000 && defined(__linux__)
  3634.     XmDragStartCallbackStruct *cbs = (XmDragStartCallbackStruct *)call_data;
  3635.     Widget w = cbs->widget;
  3636.     // clog << "Dragging from " << longName(w) << "\n";
  3637.  
  3638.     if (XtIsSubclass(w, xmLabelWidgetClass) 
  3639.     || XtIsSubclass(w, xmLabelGadgetClass))
  3640.     {
  3641.     unsigned char label_type = XmSTRING;
  3642.     XtVaGetValues(w, XmNlabelType, &label_type, NULL);
  3643.     if (label_type == XmPIXMAP)
  3644.         cbs->doit = False;
  3645.     }
  3646. #endif // XmNdragStartCallback
  3647. }
  3648.  
  3649.  
  3650. //-----------------------------------------------------------------------------
  3651. // Context help
  3652. //-----------------------------------------------------------------------------
  3653.  
  3654. static StatusMsg *context_help_msg = 0;
  3655.  
  3656. static void PreHelpOnContext(Widget w, XtPointer, XtPointer)
  3657. {
  3658.     delete context_help_msg;
  3659.     context_help_msg = 
  3660.     new StatusMsg("Please click on the item you want information for");
  3661.  
  3662.     XFlush(XtDisplay(w));
  3663. }
  3664.  
  3665. static void PostHelpOnItem(Widget item)
  3666. {
  3667.     if (item != 0)
  3668.     {
  3669.     if (context_help_msg != 0)
  3670.         context_help_msg->outcome = longName(item);
  3671.     }
  3672.  
  3673.     delete context_help_msg;
  3674.     context_help_msg = 0;
  3675. }
  3676.  
  3677.  
  3678. //-----------------------------------------------------------------------------
  3679. // Option handling
  3680. //-----------------------------------------------------------------------------
  3681.  
  3682. static void set_toggle(Widget w, unsigned char new_state, bool notify = false)
  3683. {
  3684.     if (w == 0)
  3685.     return;
  3686.  
  3687.     assert(XmIsToggleButton(w));
  3688.  
  3689. #if XmVersion < 2000
  3690.     Boolean old_state;
  3691. #else
  3692.     unsigned char old_state;
  3693. #endif
  3694.     XtVaGetValues(w, XmNset, &old_state, NULL);
  3695.  
  3696.     if (old_state != new_state)
  3697.     {
  3698.     if (notify)
  3699.         XmToggleButtonSetState(w, new_state, True);
  3700.     else
  3701.         XtVaSetValues(w, XmNset, new_state, NULL);
  3702.     }
  3703. }
  3704.  
  3705. inline void notify_set_toggle(Widget w, Boolean new_state)
  3706. {
  3707.     set_toggle(w, new_state, true);
  3708. }
  3709.  
  3710. inline void set_string(Widget w, String value)
  3711. {
  3712.     if (w == 0)
  3713.     return;
  3714.  
  3715.     XtVaSetValues(w, 
  3716.           XmNvalue, value,
  3717.           XmNcursorPosition, 0,
  3718.           NULL);
  3719. }
  3720.  
  3721. static void set_string_int(Widget w, int value)
  3722. {
  3723.     string v = itostring(value);
  3724.     set_string(w, (String)v);
  3725. }
  3726.  
  3727. static bool have_cmd(const string& cmd)
  3728. {
  3729.     return cmd_file(cmd).contains('/', 0);
  3730. }
  3731.  
  3732. // Reflect state in option menus
  3733. void update_options()
  3734. {
  3735.     set_toggle(find_words_only_w, app_data.find_words_only);
  3736.     set_toggle(words_only_w, app_data.find_words_only);
  3737.  
  3738.     set_toggle(find_case_sensitive_w, app_data.find_case_sensitive);
  3739.     set_toggle(case_sensitive_w, app_data.find_case_sensitive);
  3740.  
  3741.     set_toggle(disassemble_w, app_data.disassemble);
  3742.  
  3743.     bool separate_exec_window = 
  3744.     app_data.separate_exec_window && gdb->has_redirection();
  3745.     set_toggle(command_separate_exec_window_w, separate_exec_window);
  3746.     set_toggle(source_separate_exec_window_w,  separate_exec_window);
  3747.     set_toggle(data_separate_exec_window_w,    separate_exec_window);
  3748.  
  3749.     set_toggle(button_tips_w,            app_data.button_tips); 
  3750.     set_toggle(value_tips_w,             app_data.value_tips); 
  3751.     set_toggle(button_docs_w,            app_data.button_docs); 
  3752.     set_toggle(value_docs_w,             app_data.value_docs); 
  3753.     set_toggle(set_global_completion_w,  app_data.global_tab_completion);
  3754.     set_toggle(set_console_completion_w, !app_data.global_tab_completion);
  3755.     set_toggle(group_iconify_w,          app_data.group_iconify);
  3756.     set_toggle(uniconify_when_ready_w,   app_data.uniconify_when_ready);
  3757.     set_toggle(check_grabs_w,        app_data.check_grabs);
  3758.     set_toggle(suppress_warnings_w,      app_data.suppress_warnings);
  3759.     set_toggle(warn_if_locked_w,         app_data.warn_if_locked);
  3760.  
  3761.     set_toggle(builtin_plot_window_w,
  3762.            string(app_data.plot_term_type) == "xlib");
  3763.     set_toggle(extern_plot_window_w,
  3764.            string(app_data.plot_term_type) == "x11");
  3765.  
  3766.     set_toggle(cache_source_files_w,     app_data.cache_source_files);
  3767.     set_toggle(cache_machine_code_w,     app_data.cache_machine_code);
  3768.     set_toggle(set_display_glyphs_w,     app_data.display_glyphs);
  3769.     set_toggle(set_display_text_w,       !app_data.display_glyphs);
  3770.     set_toggle(set_refer_path_w,         app_data.use_source_path);
  3771.     set_toggle(set_refer_base_w,         !app_data.use_source_path);
  3772.     set_toggle(line_numbers1_w,          app_data.display_line_numbers);
  3773.     set_toggle(line_numbers2_w,          app_data.display_line_numbers);
  3774.  
  3775.     if (tab_width_w != 0)
  3776.     {
  3777.     XtVaSetValues(tab_width_w,     XmNvalue, app_data.tab_width,     NULL);
  3778.     XtVaSetValues(source_indent_w, XmNvalue, app_data.indent_source, NULL);
  3779.     XtVaSetValues(code_indent_w,   XmNvalue, app_data.indent_code,   NULL);
  3780.     }
  3781.  
  3782.     set_toggle(led_w, app_data.blink_while_busy);
  3783.  
  3784.     Boolean show_grid, snap_to_grid, show_hints, auto_layout, show_annotations;
  3785.     LayoutMode layout_mode;
  3786.     Dimension grid_width, grid_height;
  3787.  
  3788.     XtVaGetValues(data_disp->graph_edit, 
  3789.            XtNshowGrid,   &show_grid,
  3790.            XtNsnapToGrid, &snap_to_grid,
  3791.           XtNshowHints,  &show_hints,
  3792.           XtNshowAnnotations, &show_annotations,
  3793.           XtNautoLayout, &auto_layout,
  3794.           XtNlayoutMode, &layout_mode,
  3795.           XtNgridWidth,  &grid_width,
  3796.           XtNgridHeight, &grid_height,
  3797.           NULL);
  3798.  
  3799.     set_toggle(detect_aliases_w, app_data.detect_aliases);
  3800.     set_toggle(graph_detect_aliases_w, app_data.detect_aliases);
  3801.     set_toggle(graph_cluster_displays_w, app_data.cluster_displays);
  3802.     set_toggle(graph_align_2d_arrays_w, app_data.align_2d_arrays);
  3803.  
  3804.     if (graph_snap_to_grid_w != 0)
  3805.     {
  3806.     if (!show_grid && XtIsSensitive(graph_snap_to_grid_w))
  3807.     {
  3808.         // Grid has been disabled - disable `snap to grid' as well
  3809.         XtVaSetValues(data_disp->graph_edit, XtNsnapToGrid, False, NULL);
  3810.     }
  3811.     else if (show_grid && !XtIsSensitive(graph_snap_to_grid_w))
  3812.     {
  3813.         // Grid has been re-enabled - restore `snap to grid' setting
  3814.         XtVaSetValues(data_disp->graph_edit, XtNsnapToGrid, 
  3815.               XmToggleButtonGetState(graph_snap_to_grid_w), NULL);
  3816.     }
  3817.     else
  3818.     {
  3819.         set_toggle(graph_snap_to_grid_w, snap_to_grid);
  3820.     }
  3821.     }
  3822.  
  3823.     set_sensitive(graph_snap_to_grid_w, show_grid);
  3824.     set_sensitive(align_w, show_grid);
  3825.  
  3826.     set_toggle(graph_show_hints_w, show_hints);
  3827.     set_toggle(graph_show_annotations_w, show_annotations);
  3828.     set_toggle(graph_auto_layout_w, auto_layout);
  3829.     set_toggle(graph_compact_layout_w, layout_mode == CompactLayoutMode);
  3830.     set_toggle(graph_auto_close_w, app_data.auto_close_data_window);
  3831.     set_toggle(graph_show_dependent_titles_w,
  3832.            app_data.show_dependent_display_titles);
  3833.  
  3834.     if (graph_grid_size_w != 0)
  3835.     XtVaSetValues(graph_grid_size_w, XmNvalue, show_grid ? grid_width : 0, 
  3836.               NULL);
  3837.  
  3838.  
  3839.     unsigned char policy = '\0';
  3840.     XtVaGetValues(command_shell, XmNkeyboardFocusPolicy, &policy, NULL);
  3841.     set_toggle(set_focus_pointer_w,        policy == XmPOINTER);
  3842.     set_toggle(set_focus_explicit_w,       policy == XmEXPLICIT);
  3843.  
  3844.     set_toggle(set_scrolling_panner_w,     app_data.panned_graph_editor);
  3845.     set_toggle(set_scrolling_scrollbars_w, !app_data.panned_graph_editor);
  3846.  
  3847.     set_toggle(set_button_images_w,        app_data.button_images);
  3848.     set_toggle(set_button_captions_w,      app_data.button_captions);
  3849.  
  3850.     set_toggle(set_flat_buttons_w,         app_data.flat_toolbar_buttons);
  3851.     set_sensitive(set_flat_buttons_w,
  3852.           app_data.button_images || app_data.button_captions);
  3853.  
  3854.     string button_color_key        = app_data.button_color_key;
  3855.     string active_button_color_key = app_data.active_button_color_key;
  3856. #if XmVersion < 2000
  3857.     set_toggle(set_color_buttons_w, button_color_key == 'c');
  3858. #else
  3859.     if (button_color_key == 'c' && active_button_color_key == 'c')
  3860.     set_toggle(set_color_buttons_w, XmSET);
  3861.     else if (button_color_key == active_button_color_key)
  3862.     set_toggle(set_color_buttons_w, XmUNSET);
  3863.     else
  3864.     set_toggle(set_color_buttons_w, XmINDETERMINATE);
  3865. #endif
  3866.     set_sensitive(set_color_buttons_w, app_data.button_images);
  3867.  
  3868.     Boolean separate = 
  3869.     app_data.separate_data_window || app_data.separate_source_window;
  3870.  
  3871.     set_toggle(set_toolbars_at_bottom_w, app_data.toolbars_at_bottom);
  3872.     set_sensitive(set_toolbars_at_bottom_w, separate ||
  3873.           !app_data.button_images && !app_data.button_captions);
  3874.  
  3875.     set_toggle(set_tool_buttons_in_toolbar_w,      app_data.command_toolbar);
  3876.     set_toggle(set_tool_buttons_in_command_tool_w, !app_data.command_toolbar);
  3877.  
  3878.     set_toggle(set_separate_windows_w, separate);
  3879.     set_toggle(set_attached_windows_w, !separate);
  3880.  
  3881.     DebuggerType debugger_type = DebuggerType(-1);
  3882.     get_debugger_type(app_data.debugger, debugger_type);
  3883.  
  3884.     set_toggle(set_debugger_gdb_w,  debugger_type == GDB);
  3885.     set_toggle(set_debugger_dbx_w,  debugger_type == DBX);
  3886.     set_toggle(set_debugger_xdb_w,  debugger_type == XDB);
  3887.     set_toggle(set_debugger_jdb_w,  debugger_type == JDB);
  3888.     set_toggle(set_debugger_pydb_w, debugger_type == PYDB);
  3889.     set_toggle(set_debugger_perl_w, debugger_type == PERL);
  3890.     set_toggle(auto_debugger_w, app_data.auto_debugger);
  3891.  
  3892.     set_toggle(splash_screen_w, app_data.splash_screen);
  3893.     set_toggle(startup_tips_w,  app_data.startup_tips);
  3894.  
  3895.     if (app_data.cache_source_files != source_view->cache_source_files)
  3896.     {
  3897.     source_view->cache_source_files = app_data.cache_source_files;
  3898.     if (!app_data.cache_source_files)
  3899.         source_view->clear_file_cache();
  3900.     }
  3901.  
  3902.     if (app_data.cache_machine_code != source_view->cache_machine_code)
  3903.     {
  3904.     source_view->cache_machine_code = app_data.cache_machine_code;
  3905.     if (!app_data.cache_machine_code)
  3906.         source_view->clear_code_cache();
  3907.     }
  3908.  
  3909.     source_view->set_display_line_numbers(app_data.display_line_numbers);
  3910.     source_view->set_display_glyphs(app_data.display_glyphs);
  3911.     source_view->set_disassemble(gdb->type() == GDB && app_data.disassemble);
  3912.     source_view->set_all_registers(app_data.all_registers);
  3913.     source_view->set_tab_width(app_data.tab_width);
  3914.     source_view->set_indent(app_data.indent_source, app_data.indent_code);
  3915.  
  3916.     source_view->line_indent_amount   = app_data.line_number_width;
  3917.     source_view->script_indent_amount = app_data.indent_script;
  3918.     source_view->lines_above_cursor   = app_data.lines_above_cursor;
  3919.     source_view->lines_below_cursor   = app_data.lines_below_cursor;
  3920.  
  3921.     source_view->max_breakpoint_number = app_data.max_breakpoint_number;
  3922.     data_disp->max_display_number      = app_data.max_display_number;
  3923.  
  3924.     data_disp->set_detect_aliases(app_data.detect_aliases);
  3925.     data_disp->set_cluster_displays(app_data.cluster_displays);
  3926.  
  3927.     if (DispBox::align_2d_arrays != app_data.align_2d_arrays)
  3928.     {
  3929.     DispBox::align_2d_arrays = app_data.align_2d_arrays;
  3930.     // data_disp->refresh_display();
  3931.     }
  3932.  
  3933.     if (app_data.command_toolbar && 
  3934.     command_toolbar_w != 0 && !XtIsManaged(command_toolbar_w))
  3935.     {
  3936.     if (app_data.source_window)
  3937.         XtManageChild(command_toolbar_w);
  3938.     gdbCloseToolWindowCB(command_shell, 0, 0);
  3939.     }
  3940.     else if (!app_data.command_toolbar && 
  3941.          command_toolbar_w != 0 && XtIsManaged(command_toolbar_w))
  3942.     {
  3943.     XtUnmanageChild(command_toolbar_w);
  3944.     if (app_data.source_window)
  3945.         gdbOpenToolWindowCB(command_shell, 0, 0);
  3946.     }
  3947.  
  3948.     EnableButtonTips(app_data.button_tips);
  3949.     EnableButtonDocs(app_data.button_docs);
  3950.     EnableTextTips(app_data.value_tips);
  3951.     EnableTextDocs(app_data.value_docs);
  3952.  
  3953.     set_string(edit_command_w,       app_data.edit_command);
  3954.     set_string(plot_command_w,       app_data.plot_command);
  3955.     set_string(get_core_command_w,   app_data.get_core_command);
  3956.     set_string(ps_command_w,         app_data.ps_command);
  3957.     set_string(term_command_w,       app_data.term_command);
  3958.     set_string(uncompress_command_w, app_data.uncompress_command);
  3959.     set_string(www_command_w,        app_data.www_command);
  3960.  
  3961.     // Set `find' label
  3962.     Widget find_label_ref = 0;
  3963.     char *icon = 0;
  3964.     switch (current_find_direction())
  3965.     {
  3966.     case SourceView::forward:
  3967.     find_label_ref = find_menu[FindItems::FindForward].widget;
  3968.     icon = FIND_FORWARD_ICON;
  3969.     break;
  3970.     
  3971.     case SourceView::backward:
  3972.     find_label_ref = find_menu[FindItems::FindBackward].widget;
  3973.     icon = FIND_BACKWARD_ICON;
  3974.     break;
  3975.     }
  3976.     XmString label;
  3977.     XtVaGetValues(find_label_ref, XmNlabelString, &label, NULL);
  3978.     MString new_label(label, true);
  3979.     XmStringFree(label);
  3980.  
  3981.     set_label(arg_cmd_area[ArgItems::Find].widget, new_label, icon);
  3982.  
  3983.     // Font stuff
  3984.     if (font_names[DefaultDDDFont] != 0)
  3985.     {
  3986.     set_string(font_names[DefaultDDDFont], app_data.default_font);
  3987.     set_string(font_names[VariableWidthDDDFont], 
  3988.            app_data.variable_width_font);
  3989.     set_string(font_names[FixedWidthDDDFont], app_data.fixed_width_font);
  3990.  
  3991.     set_string_int(font_sizes[DefaultDDDFont], 
  3992.                app_data.default_font_size);
  3993.     set_string_int(font_sizes[VariableWidthDDDFont],
  3994.                app_data.variable_width_font_size);
  3995.     set_string_int(font_sizes[FixedWidthDDDFont], 
  3996.                app_data.fixed_width_font_size);
  3997.     }
  3998.  
  3999.     // Key Bindings
  4000.     BindingStyle cut_copy_paste_style = app_data.cut_copy_paste_bindings;
  4001.     set_toggle(cut_copy_paste_kde_w,   cut_copy_paste_style == KDEBindings);
  4002.     set_toggle(cut_copy_paste_motif_w, cut_copy_paste_style == MotifBindings);
  4003.  
  4004.     set_cut_copy_paste_bindings(command_edit_menu, cut_copy_paste_style);
  4005.     set_cut_copy_paste_bindings(source_edit_menu,  cut_copy_paste_style);
  4006.     set_cut_copy_paste_bindings(data_edit_menu,    cut_copy_paste_style);
  4007.  
  4008.     BindingStyle select_all_style = app_data.select_all_bindings;
  4009.     set_toggle(select_all_kde_w,   select_all_style == KDEBindings);
  4010.     set_toggle(select_all_motif_w, select_all_style == MotifBindings);
  4011.  
  4012.     set_select_all_bindings(command_edit_menu, select_all_style);
  4013.     set_select_all_bindings(source_edit_menu,  select_all_style);
  4014.     set_select_all_bindings(data_edit_menu,    select_all_style);
  4015.  
  4016.     // Maintenance
  4017.     manage_child(maintenance_w, app_data.maintenance);
  4018.  
  4019.     set_toggle(crash_debug_w,
  4020.            app_data.dump_core && app_data.debug_core_dumps);
  4021.     set_toggle(crash_dump_core_w, 
  4022.            app_data.dump_core && !app_data.debug_core_dumps);
  4023.     set_toggle(crash_nothing_w, !app_data.dump_core);
  4024.  
  4025.     // Check for source toolbar
  4026.     Widget arg_cmd_w = XtParent(source_arg->top());
  4027.     if (data_disp->graph_cmd_w == arg_cmd_w)
  4028.     {
  4029.     // Don't close the common toolbar
  4030.     }
  4031.     else
  4032.     {
  4033.     if (XtIsManaged(source_view->source_form()) ||
  4034.         XtIsManaged(source_view->code_form()))
  4035.         manage_paned_child(arg_cmd_w);
  4036.     else
  4037.         unmanage_paned_child(arg_cmd_w);
  4038.     }
  4039.  
  4040.     // Setup undo buffer size
  4041.     UndoBuffer::max_history_depth = app_data.max_undo_depth;
  4042.     UndoBuffer::max_history_size  = app_data.max_undo_size;
  4043.  
  4044.     set_string_int(max_undo_size_w, app_data.max_undo_size / 1000);
  4045.  
  4046.     update_reset_preferences();
  4047.     fix_status_size();
  4048. }
  4049.  
  4050.  
  4051. static void set_settings_title(Widget w)
  4052. {
  4053.     if (w != 0)
  4054.     {
  4055.     MString settings_title(gdb->title() + " Settings...");
  4056.     XtVaSetValues(w, XmNlabelString, settings_title.xmstring(), NULL);
  4057.     }
  4058. }
  4059.  
  4060.  
  4061.  
  4062. //-----------------------------------------------------------------------------
  4063. // Preferences
  4064. //-----------------------------------------------------------------------------
  4065.  
  4066. // Original application resources
  4067. static bool          option_state_saved = false;
  4068. static AppData       initial_app_data;
  4069. static Boolean       initial_show_grid;
  4070. static Boolean       initial_show_hints;
  4071. static Boolean       initial_show_annotations;
  4072. static Boolean       initial_snap_to_grid;
  4073. static Boolean       initial_auto_layout;
  4074. static Dimension     initial_grid_width;
  4075. static Dimension     initial_grid_height;
  4076. static LayoutMode    initial_layout_mode;
  4077. static unsigned char initial_focus_policy;
  4078.  
  4079. static Widget preferences_dialog;
  4080. static Widget reset_preferences_w;
  4081. static Widget current_panel;
  4082.  
  4083. void save_option_state()
  4084. {
  4085.     initial_app_data = app_data;
  4086.  
  4087.     // Make sure the helper command strings are really duplicated
  4088.     static string edit_command;
  4089.     edit_command = initial_app_data.edit_command;
  4090.     initial_app_data.edit_command = edit_command;
  4091.  
  4092.     static string plot_command;
  4093.     plot_command = initial_app_data.plot_command;
  4094.     initial_app_data.plot_command = plot_command;
  4095.  
  4096.     static string get_core_command;
  4097.     get_core_command = initial_app_data.get_core_command;
  4098.     initial_app_data.get_core_command = get_core_command;
  4099.  
  4100.     static string ps_command;
  4101.     ps_command = initial_app_data.ps_command;
  4102.     initial_app_data.ps_command = ps_command;
  4103.  
  4104.     static string term_command;
  4105.     term_command = initial_app_data.term_command;
  4106.     initial_app_data.term_command = term_command;
  4107.  
  4108.     static string uncompress_command;
  4109.     uncompress_command = initial_app_data.uncompress_command;
  4110.     initial_app_data.uncompress_command = uncompress_command;
  4111.  
  4112.     static string www_command;
  4113.     www_command = initial_app_data.www_command;
  4114.     initial_app_data.www_command = www_command;
  4115.  
  4116.     // Fetch data display resources
  4117.     XtVaGetValues(data_disp->graph_edit, 
  4118.           XtNshowGrid,        &initial_show_grid,
  4119.           XtNshowAnnotations, &initial_show_annotations,
  4120.           XtNshowHints,       &initial_show_hints,
  4121.           XtNsnapToGrid,      &initial_snap_to_grid,
  4122.           XtNlayoutMode,      &initial_layout_mode, 
  4123.           XtNautoLayout,      &initial_auto_layout,
  4124.           XtNgridWidth,       &initial_grid_width,
  4125.           XtNgridHeight,      &initial_grid_height,
  4126.           NULL);
  4127.  
  4128.     XtVaGetValues(command_shell,
  4129.           XmNkeyboardFocusPolicy, &initial_focus_policy, NULL);
  4130.  
  4131.     Widget paned_work_w = XtParent(XtParent(gdb_w));
  4132.     save_preferred_paned_sizes(paned_work_w);
  4133.  
  4134.     option_state_saved = true;
  4135.     update_reset_preferences();
  4136. }
  4137.  
  4138. static void ResetGeneralPreferencesCB(Widget, XtPointer, XtPointer)
  4139. {
  4140.     notify_set_toggle(button_tips_w, initial_app_data.button_tips);
  4141.     notify_set_toggle(button_docs_w, initial_app_data.button_docs);
  4142.     notify_set_toggle(value_tips_w,  initial_app_data.value_tips);
  4143.     notify_set_toggle(value_docs_w,  initial_app_data.value_docs);
  4144.     notify_set_toggle(set_global_completion_w, 
  4145.            initial_app_data.global_tab_completion);
  4146.  
  4147.     set_string_int(max_undo_size_w, initial_app_data.max_undo_size / 1000);
  4148.     app_data.max_undo_size = initial_app_data.max_undo_size;
  4149.  
  4150.     notify_set_toggle(set_console_completion_w, 
  4151.            !initial_app_data.global_tab_completion);
  4152.     notify_set_toggle(group_iconify_w, initial_app_data.group_iconify);
  4153.     notify_set_toggle(uniconify_when_ready_w, 
  4154.               initial_app_data.uniconify_when_ready);
  4155.     notify_set_toggle(suppress_warnings_w, initial_app_data.suppress_warnings);
  4156.     notify_set_toggle(warn_if_locked_w, initial_app_data.warn_if_locked);
  4157.     notify_set_toggle(check_grabs_w, 
  4158.               initial_app_data.check_grabs);
  4159. }
  4160.  
  4161. static bool general_preferences_changed()
  4162. {
  4163.     if (app_data.button_tips != initial_app_data.button_tips)
  4164.     return true;
  4165.  
  4166.     if (app_data.button_docs != initial_app_data.button_docs)
  4167.     return true;
  4168.  
  4169.     if (app_data.value_tips != initial_app_data.value_tips)
  4170.     return true;
  4171.  
  4172.     if (app_data.value_docs != initial_app_data.value_docs)
  4173.     return true;
  4174.  
  4175.     if (app_data.max_undo_size != initial_app_data.max_undo_size)
  4176.     return true;
  4177.  
  4178.     if (app_data.global_tab_completion != 
  4179.     initial_app_data.global_tab_completion)
  4180.     return true;
  4181.  
  4182.     if (app_data.group_iconify != initial_app_data.group_iconify)
  4183.     return true;
  4184.  
  4185.     if (app_data.uniconify_when_ready != initial_app_data.uniconify_when_ready)
  4186.     return true;
  4187.  
  4188.     if (app_data.suppress_warnings != initial_app_data.suppress_warnings)
  4189.     return true;
  4190.  
  4191.     if (app_data.warn_if_locked != initial_app_data.warn_if_locked)
  4192.     return true;
  4193.  
  4194.     if (app_data.check_grabs != initial_app_data.check_grabs)
  4195.     return true;
  4196.  
  4197.     return false;
  4198. }
  4199.  
  4200. static void ResetSourcePreferencesCB(Widget, XtPointer, XtPointer)
  4201. {
  4202.     notify_set_toggle(set_display_glyphs_w, initial_app_data.display_glyphs);
  4203.     notify_set_toggle(set_display_glyphs_w, !initial_app_data.display_glyphs);
  4204.  
  4205.     notify_set_toggle(set_tool_buttons_in_toolbar_w, 
  4206.               initial_app_data.command_toolbar);
  4207.     notify_set_toggle(set_tool_buttons_in_command_tool_w, 
  4208.               !initial_app_data.command_toolbar);
  4209.  
  4210.     notify_set_toggle(set_refer_path_w, initial_app_data.use_source_path);
  4211.     notify_set_toggle(set_refer_base_w, !initial_app_data.use_source_path);
  4212.  
  4213.     notify_set_toggle(words_only_w, initial_app_data.find_words_only);
  4214.     notify_set_toggle(case_sensitive_w, initial_app_data.find_case_sensitive);
  4215.  
  4216.     notify_set_toggle(cache_source_files_w, 
  4217.               initial_app_data.cache_source_files);
  4218.     notify_set_toggle(cache_machine_code_w, 
  4219.               initial_app_data.cache_machine_code);
  4220.  
  4221.     notify_set_toggle(line_numbers1_w, 
  4222.               initial_app_data.display_line_numbers);
  4223.     notify_set_toggle(line_numbers2_w, 
  4224.               initial_app_data.display_line_numbers);
  4225.  
  4226.     if (app_data.tab_width != initial_app_data.tab_width)
  4227.     {
  4228.     app_data.tab_width = initial_app_data.tab_width;
  4229.     update_options();
  4230.     }
  4231.     if (app_data.indent_source != initial_app_data.indent_source)
  4232.     {
  4233.     app_data.indent_source = initial_app_data.indent_source;
  4234.     update_options();
  4235.     }
  4236.     if (app_data.indent_code != initial_app_data.indent_code)
  4237.     {
  4238.     app_data.indent_code = initial_app_data.indent_code;
  4239.     update_options();
  4240.     }
  4241. }
  4242.  
  4243. static bool source_preferences_changed()
  4244. {
  4245.     if (app_data.display_glyphs != initial_app_data.display_glyphs)
  4246.     return true;
  4247.  
  4248.     if (app_data.command_toolbar != initial_app_data.command_toolbar)
  4249.     return true;
  4250.  
  4251.     if (app_data.use_source_path != initial_app_data.use_source_path)
  4252.     return true;
  4253.  
  4254.     if (app_data.find_words_only != initial_app_data.find_words_only)
  4255.     return true;
  4256.  
  4257.     if (app_data.find_case_sensitive != initial_app_data.find_case_sensitive)
  4258.     return true;
  4259.  
  4260.     if (app_data.cache_source_files != initial_app_data.cache_source_files)
  4261.     return true;
  4262.  
  4263.     if (app_data.cache_machine_code != initial_app_data.cache_machine_code)
  4264.     return true;
  4265.  
  4266.     if (app_data.tab_width != initial_app_data.tab_width)
  4267.     return true;
  4268.  
  4269.     if (app_data.indent_source != initial_app_data.indent_source)
  4270.     return true;
  4271.  
  4272.     if (app_data.indent_code != initial_app_data.indent_code)
  4273.     return true;
  4274.  
  4275.     if (app_data.display_line_numbers != initial_app_data.display_line_numbers)
  4276.     return true;
  4277.  
  4278.     return false;
  4279. }
  4280.  
  4281. static void ResetDataPreferencesCB(Widget, XtPointer, XtPointer)
  4282. {
  4283.     notify_set_toggle(detect_aliases_w, initial_app_data.detect_aliases);
  4284.     notify_set_toggle(graph_detect_aliases_w, initial_app_data.detect_aliases);
  4285.     notify_set_toggle(graph_cluster_displays_w, 
  4286.               initial_app_data.cluster_displays);
  4287.     notify_set_toggle(graph_align_2d_arrays_w, 
  4288.               initial_app_data.align_2d_arrays);
  4289.     notify_set_toggle(graph_show_hints_w, initial_show_hints);
  4290.     notify_set_toggle(graph_show_dependent_titles_w, 
  4291.               initial_app_data.show_dependent_display_titles);
  4292.     notify_set_toggle(graph_auto_close_w,
  4293.               initial_app_data.auto_close_data_window);
  4294.  
  4295.     Boolean show_hints, show_annotations;
  4296.  
  4297.     XtVaGetValues(data_disp->graph_edit, 
  4298.           XtNshowHints,       &show_hints,
  4299.           XtNshowAnnotations, &show_annotations,
  4300.           NULL);
  4301.  
  4302.     if (show_hints  != initial_show_hints ||
  4303.     show_annotations != initial_show_annotations)
  4304.     {
  4305.     XtVaSetValues(data_disp->graph_edit,
  4306.               XtNshowHints,       initial_show_hints,
  4307.               XtNshowAnnotations, initial_show_annotations,
  4308.               NULL);
  4309.               
  4310.     update_options();
  4311.     }
  4312.  
  4313.     notify_set_toggle(graph_compact_layout_w, 
  4314.            initial_layout_mode == CompactLayoutMode);
  4315.     notify_set_toggle(graph_auto_layout_w, initial_auto_layout);
  4316.     notify_set_toggle(graph_snap_to_grid_w, initial_snap_to_grid);
  4317.  
  4318.     Dimension grid_width, grid_height;
  4319.     Boolean show_grid;
  4320.     XtVaGetValues(data_disp->graph_edit, 
  4321.           XtNgridWidth,  &grid_width,
  4322.           XtNgridHeight, &grid_height,
  4323.           XtNshowGrid,   &show_grid,
  4324.           NULL);
  4325.  
  4326.     if (grid_width  != initial_grid_width || 
  4327.     grid_height != initial_grid_height ||
  4328.     show_grid   != initial_show_grid)
  4329.     {
  4330.     XtVaSetValues(data_disp->graph_edit,
  4331.               XtNgridWidth,  initial_grid_width,
  4332.               XtNgridHeight, initial_grid_height,
  4333.               XtNshowGrid,   initial_show_grid,
  4334.               NULL);
  4335.               
  4336.     update_options();
  4337.     }
  4338. }
  4339.  
  4340. static bool data_preferences_changed()
  4341. {
  4342.     Boolean show_hints, show_annotations;
  4343.     XtVaGetValues(data_disp->graph_edit, 
  4344.           XtNshowHints,       &show_hints,
  4345.           XtNshowAnnotations, &show_annotations,
  4346.           NULL);
  4347.  
  4348.     if (app_data.detect_aliases != initial_app_data.detect_aliases)
  4349.     return true;
  4350.  
  4351.     if (app_data.cluster_displays != initial_app_data.cluster_displays)
  4352.     return true;
  4353.  
  4354.     if (app_data.align_2d_arrays != initial_app_data.align_2d_arrays)
  4355.     return true;
  4356.  
  4357.     if (app_data.auto_close_data_window != 
  4358.     initial_app_data.auto_close_data_window)
  4359.     return true;
  4360.  
  4361.     if (show_hints   != initial_show_hints)
  4362.     return true;
  4363.  
  4364.     if (show_annotations != initial_show_annotations)
  4365.     return true;
  4366.  
  4367.     if (app_data.show_dependent_display_titles != 
  4368.     initial_app_data.show_dependent_display_titles)
  4369.     return true;
  4370.     Boolean show_grid, snap_to_grid, auto_layout;
  4371.     LayoutMode layout_mode;
  4372.     Dimension grid_width, grid_height;
  4373.  
  4374.     XtVaGetValues(data_disp->graph_edit, 
  4375.           XtNshowGrid,   &show_grid,
  4376.           XtNsnapToGrid, &snap_to_grid,
  4377.           XtNlayoutMode, &layout_mode, 
  4378.           XtNautoLayout, &auto_layout,
  4379.           XtNgridWidth,  &grid_width,
  4380.           XtNgridHeight, &grid_height,
  4381.           NULL);
  4382.  
  4383.     if (show_grid    != initial_show_grid)
  4384.     return true;
  4385.  
  4386.     if (snap_to_grid != initial_snap_to_grid)
  4387.     return true;
  4388.  
  4389.     if (layout_mode  != initial_layout_mode )
  4390.     return true;
  4391.  
  4392.     if (auto_layout  != initial_auto_layout)
  4393.     return true;
  4394.  
  4395.     if (grid_width   != initial_grid_width)
  4396.     return true;
  4397.  
  4398.     if (grid_height  != initial_grid_height)
  4399.     return true;
  4400.  
  4401.     return false;
  4402. }
  4403.  
  4404. static void ResetStartupPreferencesCB(Widget, XtPointer, XtPointer)
  4405. {
  4406.     Boolean separate = initial_app_data.separate_data_window 
  4407.     || initial_app_data.separate_source_window;
  4408.  
  4409.     notify_set_toggle(set_separate_windows_w, separate);
  4410.     notify_set_toggle(set_attached_windows_w, !separate);
  4411.  
  4412.     notify_set_toggle(set_button_captions_w, initial_app_data.button_captions);
  4413.     notify_set_toggle(set_button_images_w,   initial_app_data.button_images);
  4414.     notify_set_toggle(set_flat_buttons_w,    
  4415.               initial_app_data.flat_toolbar_buttons);
  4416.  
  4417.     string button_color_key        = initial_app_data.button_color_key;
  4418.     string active_button_color_key = initial_app_data.active_button_color_key;
  4419. #if XmVersion < 2000
  4420.     notify_set_toggle(set_color_buttons_w, button_color_key == 'c');
  4421. #else
  4422.     if (button_color_key == 'c' && active_button_color_key == 'c')
  4423.     notify_set_toggle(set_color_buttons_w, XmSET);
  4424.     else if (button_color_key == active_button_color_key)
  4425.     notify_set_toggle(set_color_buttons_w, XmUNSET);
  4426.     else
  4427.     notify_set_toggle(set_color_buttons_w, XmINDETERMINATE);
  4428. #endif
  4429.     notify_set_toggle(set_toolbars_at_bottom_w, 
  4430.               initial_app_data.toolbars_at_bottom);
  4431.  
  4432.     notify_set_toggle(set_focus_pointer_w, 
  4433.               initial_focus_policy == XmPOINTER);
  4434.     notify_set_toggle(set_focus_explicit_w,
  4435.               initial_focus_policy == XmEXPLICIT);
  4436.  
  4437.     notify_set_toggle(set_scrolling_panner_w, 
  4438.            initial_app_data.panned_graph_editor);
  4439.     notify_set_toggle(set_scrolling_scrollbars_w, 
  4440.            !initial_app_data.panned_graph_editor);
  4441.  
  4442.     DebuggerType debugger_type;
  4443.     bool type_ok = get_debugger_type(initial_app_data.debugger, debugger_type);
  4444.     notify_set_toggle(set_debugger_gdb_w,  type_ok && debugger_type == GDB);
  4445.     notify_set_toggle(set_debugger_dbx_w,  type_ok && debugger_type == DBX);
  4446.     notify_set_toggle(set_debugger_xdb_w,  type_ok && debugger_type == XDB);
  4447.     notify_set_toggle(set_debugger_jdb_w,  type_ok && debugger_type == JDB);
  4448.     notify_set_toggle(set_debugger_pydb_w, type_ok && debugger_type == PYDB);
  4449.     notify_set_toggle(set_debugger_perl_w, type_ok && debugger_type == PERL);
  4450.     notify_set_toggle(auto_debugger_w,
  4451.               !type_ok || initial_app_data.auto_debugger);
  4452.  
  4453.     BindingStyle cut_copy_paste_style = 
  4454.     initial_app_data.cut_copy_paste_bindings;
  4455.     notify_set_toggle(cut_copy_paste_kde_w,   
  4456.               cut_copy_paste_style == KDEBindings);
  4457.     notify_set_toggle(cut_copy_paste_motif_w, 
  4458.               cut_copy_paste_style == MotifBindings);
  4459.  
  4460.     BindingStyle select_all_style = 
  4461.     initial_app_data.select_all_bindings;
  4462.     notify_set_toggle(select_all_kde_w,   
  4463.               select_all_style == KDEBindings);
  4464.     notify_set_toggle(select_all_motif_w, 
  4465.               select_all_style == MotifBindings);
  4466.  
  4467.     notify_set_toggle(splash_screen_w, initial_app_data.splash_screen);
  4468.     notify_set_toggle(startup_tips_w,  initial_app_data.startup_tips);
  4469. }
  4470.  
  4471.  
  4472. static bool startup_preferences_changed()
  4473. {
  4474.  
  4475.     // Christoph L. Spiel <Christoph_Spiel@physik.tu-muenchen.de>
  4476.     // reports that his g++-2.7.2.3 chokes on large `||' expressions.
  4477.     // Hence, instead of `return A || B || C', we say `if A return
  4478.     // true; if B return true; if C return true; return false;'.
  4479.  
  4480.     if (app_data.startup_tips != initial_app_data.startup_tips)
  4481.     return true;
  4482.  
  4483.     if (app_data.cut_copy_paste_bindings !=
  4484.     initial_app_data.cut_copy_paste_bindings)
  4485.     return true;
  4486.  
  4487.     if (app_data.select_all_bindings != initial_app_data.select_all_bindings)
  4488.     return true;
  4489.  
  4490.     if (app_data.splash_screen != initial_app_data.splash_screen)
  4491.     return true;
  4492.  
  4493.     Boolean initial_separate = (initial_app_data.separate_data_window ||
  4494.                 initial_app_data.separate_source_window);
  4495.     Boolean separate = (app_data.separate_data_window || 
  4496.             app_data.separate_source_window);
  4497.     if (separate != initial_separate)
  4498.     return true;
  4499.  
  4500.     if (app_data.button_images != initial_app_data.button_images)
  4501.     return true;
  4502.  
  4503.     if (app_data.button_captions != initial_app_data.button_captions)
  4504.     return true;
  4505.  
  4506.     if (app_data.flat_toolbar_buttons != initial_app_data.flat_toolbar_buttons)
  4507.     return true;
  4508.  
  4509.     if (app_data.toolbars_at_bottom != initial_app_data.toolbars_at_bottom)
  4510.     return true;
  4511.  
  4512.     if (string(app_data.button_color_key) !=
  4513.     string(initial_app_data.button_color_key))
  4514.     return true;
  4515.  
  4516.     if (string(app_data.active_button_color_key) !=
  4517.     string(initial_app_data.active_button_color_key))
  4518.     return true;
  4519.  
  4520.     unsigned char focus_policy;
  4521.     XtVaGetValues(command_shell, XmNkeyboardFocusPolicy, &focus_policy, NULL);
  4522.     if (focus_policy != initial_focus_policy)
  4523.     return true;
  4524.  
  4525.     if (app_data.panned_graph_editor != initial_app_data.panned_graph_editor)
  4526.     return true;
  4527.  
  4528.     if (app_data.auto_debugger != initial_app_data.auto_debugger)
  4529.     return true;
  4530.  
  4531.     if (string(app_data.debugger) != string(initial_app_data.debugger))
  4532.     return true;
  4533.  
  4534.     return false;
  4535. }
  4536.  
  4537. static void ResetFontPreferencesCB(Widget, XtPointer, XtPointer)
  4538. {
  4539.     set_font(DefaultDDDFont,       initial_app_data.default_font);
  4540.     set_font(VariableWidthDDDFont, initial_app_data.variable_width_font);
  4541.     set_font(FixedWidthDDDFont,    initial_app_data.fixed_width_font);
  4542.  
  4543.     app_data.default_font_size = 
  4544.     initial_app_data.default_font_size;
  4545.     app_data.variable_width_font_size = 
  4546.     initial_app_data.variable_width_font_size;
  4547.     app_data.fixed_width_font_size = 
  4548.     initial_app_data.fixed_width_font_size;
  4549.  
  4550.     update_options();
  4551. }
  4552.  
  4553.  
  4554. static bool font_preferences_changed()
  4555. {
  4556.     if (string(app_data.default_font) != string(initial_app_data.default_font))
  4557.     return true;
  4558.  
  4559.     if (string(app_data.variable_width_font) != 
  4560.     string(initial_app_data.variable_width_font))
  4561.     return true;
  4562.  
  4563.     if (string(app_data.fixed_width_font) != 
  4564.     string(initial_app_data.fixed_width_font))
  4565.     return true;
  4566.  
  4567.     if (app_data.default_font_size != initial_app_data.default_font_size)
  4568.     return true;
  4569.  
  4570.     if (app_data.variable_width_font_size != 
  4571.     initial_app_data.variable_width_font_size)
  4572.     return true;
  4573.  
  4574.     if (app_data.fixed_width_font_size != 
  4575.     initial_app_data.fixed_width_font_size)
  4576.     return true;
  4577.  
  4578.     return false;
  4579. }
  4580.  
  4581. static void ResetHelpersPreferencesCB(Widget, XtPointer, XtPointer)
  4582. {
  4583.     set_string(edit_command_w,       initial_app_data.edit_command);
  4584.     set_string(get_core_command_w,   initial_app_data.get_core_command);
  4585.     set_string(ps_command_w,         initial_app_data.ps_command);
  4586.     set_string(term_command_w,       initial_app_data.term_command);
  4587.     set_string(uncompress_command_w, initial_app_data.uncompress_command);
  4588.     set_string(www_command_w,        initial_app_data.www_command);
  4589.     set_string(plot_command_w,       initial_app_data.plot_command);
  4590.  
  4591.     notify_set_toggle(builtin_plot_window_w, 
  4592.               string(initial_app_data.plot_term_type) == "xlib");
  4593. }
  4594.  
  4595. static bool helpers_preferences_changed()
  4596. {
  4597.     if (string(app_data.edit_command) != string(initial_app_data.edit_command))
  4598.     return true;
  4599.  
  4600.     if (string(app_data.plot_command) != string(initial_app_data.plot_command))
  4601.     return true;
  4602.  
  4603.     if (string(app_data.get_core_command) != 
  4604.     string(initial_app_data.get_core_command))
  4605.     return true;
  4606.  
  4607.     if (string(app_data.ps_command) != string(initial_app_data.ps_command))
  4608.     return true;
  4609.  
  4610.     if (string(app_data.term_command) != string(initial_app_data.term_command))
  4611.     return true;
  4612.  
  4613.     if (string(app_data.uncompress_command) != 
  4614.     string(initial_app_data.uncompress_command))
  4615.     return true;
  4616.  
  4617.     if (string(app_data.www_command) != string(initial_app_data.www_command))
  4618.     return true;
  4619.  
  4620.     if (string(app_data.plot_term_type) != 
  4621.     string(initial_app_data.plot_term_type))
  4622.     return true;
  4623.  
  4624.     return false;
  4625. }
  4626.  
  4627.  
  4628. static void ResetPreferencesCB(Widget w, XtPointer client_data, 
  4629.                      XtPointer call_data)
  4630. {
  4631.     Widget panel = (Widget)client_data;
  4632.     string panel_name = XtName(panel);
  4633.  
  4634.     if (panel_name == "general")
  4635.     ResetGeneralPreferencesCB(w, client_data, call_data);
  4636.     else if (panel_name == "source")
  4637.     ResetSourcePreferencesCB(w, client_data, call_data);
  4638.     else if (panel_name == "data")
  4639.     ResetDataPreferencesCB(w, client_data, call_data);
  4640.     else if (panel_name == "startup")
  4641.     ResetStartupPreferencesCB(w, client_data, call_data);
  4642.     else if (panel_name == "fonts")
  4643.     ResetFontPreferencesCB(w, client_data, call_data);
  4644.     else if (panel_name == "helpers")
  4645.     ResetHelpersPreferencesCB(w, client_data, call_data);
  4646. }
  4647.  
  4648. void update_reset_preferences()
  4649. {
  4650.     if (current_panel != 0 && reset_preferences_w != 0 && option_state_saved)
  4651.     {
  4652.     string panel_name = XtName(current_panel);
  4653.  
  4654.     bool sensitive = false;
  4655.  
  4656.     if (panel_name == "general")
  4657.         sensitive = general_preferences_changed();
  4658.     else if (panel_name == "source")
  4659.         sensitive = source_preferences_changed();
  4660.     else if (panel_name == "data")
  4661.         sensitive = data_preferences_changed();
  4662.     else if (panel_name == "startup")
  4663.         sensitive = startup_preferences_changed();
  4664.     else if (panel_name == "fonts")
  4665.         sensitive = font_preferences_changed();
  4666.     else if (panel_name == "helpers")
  4667.         sensitive = helpers_preferences_changed();
  4668.  
  4669.     set_sensitive(reset_preferences_w, sensitive);
  4670.     }
  4671.  
  4672.     if (gdb_initialized)
  4673.     check_options_file();
  4674. }
  4675.  
  4676. static void ChangePanelCB(Widget, XtPointer client_data, XtPointer call_data)
  4677. {
  4678.     Widget panel = (Widget)client_data;
  4679.     XmToggleButtonCallbackStruct *cbs = 
  4680.     (XmToggleButtonCallbackStruct *)call_data;
  4681.  
  4682.     if (cbs->set)
  4683.     {
  4684.     // Manage this child
  4685.     XtManageChild(panel);
  4686.     XtAddCallback(preferences_dialog, XmNhelpCallback,
  4687.               HelpOnThisCB, XtPointer(panel));
  4688.     XtAddCallback(reset_preferences_w, XmNactivateCallback,
  4689.               ResetPreferencesCB, XtPointer(panel));
  4690.     current_panel = panel;
  4691.  
  4692.     update_reset_preferences();
  4693.  
  4694.     // Unmanage all other children
  4695.     WidgetList children;
  4696.     Cardinal num_children;
  4697.     XtVaGetValues(XtParent(panel), 
  4698.               XmNchildren, &children,
  4699.               XmNnumChildren, &num_children,
  4700.               NULL);
  4701.  
  4702.     for (Cardinal i = 0; i < num_children; i++)
  4703.     {
  4704.         Widget child = children[i];
  4705.         if (child != panel)
  4706.         {
  4707.         XtUnmanageChild(child);
  4708.         XtRemoveCallback(preferences_dialog, XmNhelpCallback,
  4709.                  HelpOnThisCB, XtPointer(child));
  4710.         XtRemoveCallback(reset_preferences_w, XmNactivateCallback,
  4711.                  ResetPreferencesCB, XtPointer(child));
  4712.         }
  4713.     }
  4714.     }
  4715. }
  4716.  
  4717. static Widget add_panel(Widget parent, Widget buttons, 
  4718.             String name, MMDesc items[],
  4719.             Dimension& max_width, Dimension& max_height,
  4720.             bool set = false)
  4721. {
  4722.     Arg args[10];
  4723.     int arg;
  4724.  
  4725.     // Add two rows
  4726.     arg = 0;
  4727.     XtSetArg(args[arg], XmNmarginWidth,  0); arg++;
  4728.     XtSetArg(args[arg], XmNmarginHeight, 0); arg++;
  4729.     XtSetArg(args[arg], XmNborderWidth,  0); arg++;
  4730.     Widget form = verify(XmCreateRowColumn(parent, name, args, arg));
  4731.     XtManageChild(form);
  4732.  
  4733.     // Add panel
  4734.     Widget panel = MMcreatePanel(form, "panel", items);
  4735.     MMadjustPanel(items);
  4736.     MMaddCallbacks(items);
  4737.     MMaddHelpCallback(items, ImmediateHelpCB);
  4738.     XtManageChild(panel);
  4739.     register_menu_shell(items);
  4740.  
  4741.     // Fetch panel geometry
  4742.     XtWidgetGeometry size;
  4743.     size.request_mode = CWHeight | CWWidth;
  4744.     XtQueryGeometry(form, NULL, &size);
  4745.     max_width  = max(max_width,  size.width);
  4746.     max_height = max(max_height, size.height);
  4747.  
  4748.     // Add button
  4749.     arg = 0;
  4750.     Widget button = verify(XmCreateToggleButton(buttons, name, args, arg));
  4751.     XtManageChild(button);
  4752.  
  4753.     XtAddCallback(button, XmNvalueChangedCallback, ChangePanelCB, 
  4754.           XtPointer(form));
  4755.  
  4756.     XmToggleButtonSetState(button, Boolean(set), False);
  4757.  
  4758.     if (set)
  4759.     {
  4760.     XmToggleButtonCallbackStruct cbs;
  4761.     cbs.set = set;
  4762.     ChangePanelCB(button, XtPointer(form), &cbs);
  4763.     }
  4764.  
  4765.     return button;
  4766. }
  4767.  
  4768. static void OfferRestartCB(Widget dialog, XtPointer, XtPointer)
  4769. {
  4770.     if (startup_preferences_changed() || font_preferences_changed())
  4771.     {
  4772.     static Widget restart_dialog = 0;
  4773.     if (restart_dialog == 0)
  4774.     {
  4775.         restart_dialog = 
  4776.         verify(XmCreateQuestionDialog(find_shell(dialog), 
  4777.                           "restart_dialog", 0, 0));
  4778.         Delay::register_shell(restart_dialog);
  4779.         XtAddCallback(restart_dialog, XmNokCallback,
  4780.               DDDRestartCB, 0);
  4781.         XtAddCallback(restart_dialog, XmNhelpCallback,
  4782.               ImmediateHelpCB, 0);
  4783.     }
  4784.     manage_and_raise(restart_dialog);
  4785.     }
  4786. }
  4787.  
  4788. // Create preferences dialog
  4789. static void make_preferences(Widget parent)
  4790. {
  4791.     Arg args[10];
  4792.     int arg;
  4793.  
  4794.     arg = 0;
  4795.     preferences_dialog = 
  4796.     verify(XmCreatePromptDialog(parent, "preferences", args, arg));
  4797.     Delay::register_shell(preferences_dialog);
  4798.     XtVaSetValues(preferences_dialog, XmNdefaultButton, Widget(0), NULL);
  4799.     XtAddCallback(preferences_dialog, XmNunmapCallback, OfferRestartCB, NULL);
  4800.  
  4801.     if (lesstif_version <= 79)
  4802.     XtUnmanageChild(XmSelectionBoxGetChild(preferences_dialog,
  4803.                            XmDIALOG_APPLY_BUTTON));
  4804.  
  4805.     // Remove old prompt
  4806.     Widget text = XmSelectionBoxGetChild(preferences_dialog, XmDIALOG_TEXT);
  4807.     XtUnmanageChild(text);
  4808.     Widget old_label = 
  4809.     XmSelectionBoxGetChild(preferences_dialog, XmDIALOG_SELECTION_LABEL);
  4810.     XtUnmanageChild(old_label);
  4811.  
  4812.     // Use cancel button to reset settings
  4813.     reset_preferences_w = 
  4814.         XmSelectionBoxGetChild(preferences_dialog, XmDIALOG_CANCEL_BUTTON);
  4815.     XtRemoveAllCallbacks(reset_preferences_w, XmNactivateCallback);
  4816.  
  4817.     arg = 0;
  4818.     XtSetArg(args[arg], XmNmarginWidth,  0); arg++;
  4819.     XtSetArg(args[arg], XmNmarginHeight, 0); arg++;
  4820.     XtSetArg(args[arg], XmNborderWidth,  0); arg++;
  4821.     Widget box =
  4822.     verify(XmCreateRowColumn(preferences_dialog, "box", args, arg));
  4823.     XtManageChild(box);
  4824.  
  4825.     arg = 0;
  4826.     Widget buttons =
  4827.     verify(XmCreateRadioBox(box, "buttons", args, arg));
  4828.     XtManageChild(buttons);
  4829.  
  4830.     arg = 0;
  4831.     Widget frame = verify(XmCreateFrame(box, "frame", args, arg));
  4832.     XtManageChild(frame);
  4833.  
  4834.     arg = 0;
  4835.     XtSetArg(args[arg], XmNmarginWidth,  0); arg++;
  4836.     XtSetArg(args[arg], XmNmarginHeight, 0); arg++;
  4837.     XtSetArg(args[arg], XmNborderWidth,  0); arg++;
  4838.     Widget change =
  4839.     verify(XmCreateRowColumn(frame, "change", args, arg));
  4840.     XtManageChild(change);
  4841.  
  4842.     Dimension max_width  = 0;
  4843.     Dimension max_height = 0;
  4844.  
  4845.     Widget general_button =
  4846.     add_panel(change, buttons, "general", general_preferences_menu, 
  4847.           max_width, max_height, false);
  4848.     add_panel(change, buttons, "source",  source_preferences_menu, 
  4849.           max_width, max_height, false);
  4850.     add_panel(change, buttons, "data",    data_preferences_menu, 
  4851.           max_width, max_height, false);
  4852.     add_panel(change, buttons, "startup", startup_preferences_menu, 
  4853.           max_width, max_height, false);
  4854.     add_panel(change, buttons, "fonts", font_preferences_menu,
  4855.           max_width, max_height, false);
  4856.     add_panel(change, buttons, "helpers", helpers_preferences_menu, 
  4857.           max_width, max_height, false);
  4858.  
  4859.     XtVaSetValues(change,
  4860.           XmNwidth, max_width,
  4861.           XmNheight, max_height,
  4862.           XmNresizeWidth, False,
  4863.           XmNresizeHeight, False,
  4864.           NULL);
  4865.  
  4866.     XmToggleButtonSetState(general_button, True, True);
  4867. }
  4868.  
  4869. // Popup Preference Panel
  4870. static void dddPopupPreferencesCB (Widget, XtPointer, XtPointer)
  4871. {
  4872.     manage_and_raise(preferences_dialog);
  4873.     check_options_file();
  4874. }
  4875.  
  4876.  
  4877. //-----------------------------------------------------------------------------
  4878. // Create status line
  4879. //-----------------------------------------------------------------------------
  4880.  
  4881. static void create_status(Widget parent)
  4882. {
  4883.     Arg args[15];
  4884.     int arg = 0;
  4885.     XtSetArg(args[arg], XmNresizePolicy, XmRESIZE_ANY); arg++;
  4886.     Widget status_form = 
  4887.     verify(XmCreateForm(parent, "status_form", args, arg));
  4888.     XtManageChild(status_form);
  4889.  
  4890.     // Create LED
  4891.     arg = 0;
  4892.     XtSetArg(args[arg], XmNtopAttachment,      XmATTACH_FORM); arg++;
  4893.     XtSetArg(args[arg], XmNbottomAttachment,   XmATTACH_FORM); arg++;
  4894.     XtSetArg(args[arg], XmNrightAttachment,    XmATTACH_FORM); arg++;
  4895.     XtSetArg(args[arg], XmNresizable,          False); arg++;
  4896.     XtSetArg(args[arg], XmNfillOnSelect,       True); arg++;
  4897.     XtSetArg(args[arg], XmNset,                True); arg++;
  4898.  
  4899.     MString spaces("   ");
  4900.     if (lesstif_version < 1000)
  4901.     {
  4902.     XtSetArg(args[arg], XmNlabelString, spaces.xmstring()); arg++;
  4903.     }
  4904.  
  4905.     led_w = verify(XmCreateToggleButton(status_form, "led", args, arg));
  4906.     XtManageChild(led_w);
  4907.  
  4908.     XtAddCallback(led_w, XmNvalueChangedCallback, ToggleBlinkCB, XtPointer(0));
  4909.  
  4910.     Pixel arrow_foreground;
  4911.     XtVaGetValues(status_form, XmNbackground, &arrow_foreground, 0);
  4912.  
  4913.     // Create `Get more status messages' button
  4914.     arg = 0;
  4915.     XtSetArg(args[arg], XmNtopAttachment,    XmATTACH_FORM); arg++;
  4916.     XtSetArg(args[arg], XmNbottomAttachment, XmATTACH_FORM); arg++;
  4917.     XtSetArg(args[arg], XmNleftAttachment,   XmATTACH_FORM); arg++;
  4918.     XtSetArg(args[arg], XmNresizable,        False); arg++;
  4919.     XtSetArg(args[arg], XmNshadowThickness,  0); arg++;
  4920.     XtSetArg(args[arg], XmNforeground,       arrow_foreground); arg++;
  4921.     XtSetArg(args[arg], XmNarrowDirection, 
  4922.          (app_data.status_at_bottom ? XmARROW_UP : XmARROW_DOWN)); arg++;
  4923.     Widget arrow_w = 
  4924.     verify(XmCreateArrowButton(status_form, "arrow", args, arg));
  4925.     XtManageChild(arrow_w);
  4926.  
  4927.     // Give some `dummy' status message.  Some Motif versions limit
  4928.     // the size of the status window to the length of the very first
  4929.     // message, so we give some huge string at the beginning.
  4930.     MString short_msg = rm("Hello, world!");
  4931.     MString long_msg = short_msg + rm(replicate(' ', 90));
  4932.  
  4933.     arg = 0;
  4934.     XtSetArg(args[arg], XmNlabelString,      long_msg.xmstring()); arg++;
  4935.     XtSetArg(args[arg], XmNtopAttachment,    XmATTACH_FORM); arg++;
  4936.     XtSetArg(args[arg], XmNbottomAttachment, XmATTACH_FORM); arg++;
  4937.     XtSetArg(args[arg], XmNleftAttachment,   XmATTACH_WIDGET); arg++;
  4938.     XtSetArg(args[arg], XmNleftWidget,       arrow_w); arg++;
  4939.     XtSetArg(args[arg], XmNrightAttachment,  XmATTACH_WIDGET); arg++;
  4940.     XtSetArg(args[arg], XmNrightWidget,      led_w); arg++;
  4941.     XtSetArg(args[arg], XmNresizable,        False); arg++;
  4942.     XtSetArg(args[arg], XmNrecomputeSize,    False); arg++;
  4943.     XtSetArg(args[arg], XmNshadowThickness,  0); arg++;
  4944.     status_w = verify(XmCreatePushButton(status_form, "status", args, arg));
  4945.     XtManageChild(status_w);
  4946.  
  4947.     // Initialize status history
  4948.     status_history_size = app_data.status_history_size;
  4949.     (void) status_history(parent);
  4950.     set_status("");
  4951.     set_status_mstring(short_msg);
  4952.  
  4953.     XtAddCallback(status_w, XmNarmCallback, 
  4954.           PopupStatusHistoryCB, XtPointer(0));
  4955.     XtAddCallback(status_w, XmNdisarmCallback, 
  4956.           PopdownStatusHistoryCB, XtPointer(0));
  4957.  
  4958.     XtAddCallback(arrow_w, XmNarmCallback, 
  4959.           PopupStatusHistoryCB, XtPointer(0));
  4960.     XtAddCallback(arrow_w, XmNdisarmCallback, 
  4961.           PopdownStatusHistoryCB, XtPointer(0));
  4962.  
  4963.     XtWidgetGeometry size;
  4964.     size.request_mode = CWHeight;
  4965.     XtQueryGeometry(status_w, NULL, &size);
  4966.  
  4967.     if (lesstif_version < 1000)
  4968.     XtVaSetValues(led_w, XmNindicatorSize, size.height - 4, NULL);
  4969.     else
  4970.     XtVaSetValues(led_w, XmNindicatorSize, size.height - 1, NULL);
  4971.  
  4972.     XtVaSetValues(arrow_w,
  4973.           XmNheight, size.height - 2,
  4974.           XmNwidth,  size.height - 2,
  4975.           NULL);
  4976.     XtVaSetValues(status_form,
  4977.           XmNpaneMaximum, size.height,
  4978.           XmNpaneMinimum, size.height,
  4979.           NULL);
  4980.  
  4981.     set_toggle(led_w, app_data.blink_while_busy);
  4982.     blink(true);
  4983. }
  4984.  
  4985.  
  4986. //-----------------------------------------------------------------------------
  4987. // Handle Status LED
  4988. //-----------------------------------------------------------------------------
  4989.  
  4990. static bool blinker_active        = false; // True iff status LED is active
  4991. static XtIntervalId blink_timer   = 0;     // Timer for blinking
  4992.  
  4993. static void BlinkCB(XtPointer client_data, XtIntervalId *id)
  4994. {
  4995.     (void) id;            // use it
  4996.     assert(*id == blink_timer);
  4997.     blink_timer = 0;
  4998.  
  4999.     static bool have_led_colors = false;
  5000.     static Pixel led_select_color;
  5001.     static Pixel led_background_color;
  5002.  
  5003.     if (!have_led_colors)
  5004.     {
  5005.     XtVaGetValues(led_w,
  5006.               XmNbackground, &led_background_color,
  5007.               XmNselectColor, &led_select_color,
  5008.               NULL);
  5009.     have_led_colors = true;
  5010.     }
  5011.  
  5012.     bool set = bool(long(client_data));
  5013.     if (set)
  5014.     XtVaSetValues(led_w, XmNselectColor, led_select_color, NULL);
  5015.     else
  5016.     XtVaSetValues(led_w, XmNselectColor, led_background_color, NULL);
  5017.  
  5018.     XFlush(XtDisplay(led_w));
  5019.     XmUpdateDisplay(led_w);
  5020.  
  5021.     if ((blinker_active || set) && app_data.busy_blink_rate > 0)
  5022.     {
  5023.     blink_timer = XtAppAddTimeOut(XtWidgetToApplicationContext(led_w),
  5024.                       app_data.busy_blink_rate, BlinkCB,
  5025.                       XtPointer(int(!set)));
  5026.     }
  5027. }
  5028.  
  5029. // Enable or disable blinking
  5030. static void blink(bool set)
  5031. {
  5032.     blinker_active = set;
  5033.  
  5034.     if (!XmToggleButtonGetState(led_w))
  5035.     return;            // Button is not active
  5036.  
  5037.     if (blink_timer == 0)
  5038.     {
  5039.     if (blinker_active)
  5040.     {
  5041.         // Restart blink timer
  5042.         BlinkCB(XtPointer(int(true)), &blink_timer);
  5043.     }
  5044.     }
  5045. }
  5046.  
  5047. static void DisableBlinkHP(Agent *, void *, void *)
  5048. {
  5049.     // GDB has died -- disable status LED
  5050.     XmToggleButtonSetState(led_w, False, False);
  5051. }
  5052.  
  5053. static void ToggleBlinkCB(Widget, XtPointer, XtPointer call_data)
  5054. {
  5055.     XmToggleButtonCallbackStruct *info = 
  5056.     (XmToggleButtonCallbackStruct *)call_data;
  5057.     string debugger_status_indicator =
  5058.     "Debugger status indicator ";
  5059.  
  5060.     app_data.blink_while_busy = info->set;
  5061.  
  5062.     if (info->set)
  5063.     set_status(debugger_status_indicator + "enabled.");
  5064.     else
  5065.     set_status(debugger_status_indicator + "disabled.");
  5066.  
  5067.     // Restart blinker
  5068.     blink(blinker_active);
  5069. }
  5070.  
  5071. //-----------------------------------------------------------------------------
  5072. // Handle Status History
  5073. //-----------------------------------------------------------------------------
  5074.  
  5075. const Dimension y_popup_offset = 5;
  5076.  
  5077. static Widget history_shell = 0;
  5078. static void PopupStatusHistoryCB(Widget w, XtPointer client_data, 
  5079.                  XtPointer call_data)
  5080. {
  5081.     (void) call_data;        // Use it
  5082.     (void) client_data;        // Use it
  5083.  
  5084.     history_shell = status_history(w);
  5085.  
  5086.     Position shell_x, shell_y;
  5087.     XtTranslateCoords(find_shell(status_w), 0, 0, &shell_x, &shell_y);
  5088.  
  5089.     Position status_x, status_y;
  5090.     XtTranslateCoords(status_w, 0, 0, &status_x, &status_y);
  5091.  
  5092.     XtWidgetGeometry size;
  5093.     size.request_mode = CWHeight;
  5094.     Position x, y;
  5095.     if (app_data.status_at_bottom)
  5096.     {
  5097.     XtQueryGeometry(history_shell, NULL, &size);
  5098.  
  5099.     x = shell_x;
  5100.     y = status_y - size.height - y_popup_offset;
  5101.     }
  5102.     else
  5103.     {
  5104.     XtQueryGeometry(status_w, NULL, &size);
  5105.  
  5106.     x = shell_x;
  5107.     y = status_y + size.height + y_popup_offset;
  5108.     }
  5109.  
  5110.     XtVaSetValues(history_shell, XmNx, x, XmNy, y, XtPointer(0));
  5111.     XtPopup(history_shell, XtGrabNone);
  5112. }
  5113.  
  5114. static void PopdownStatusHistoryCB(Widget, XtPointer, XtPointer)
  5115. {
  5116.     if (history_shell != 0)
  5117.     XtPopdown(history_shell);
  5118. }
  5119.  
  5120.  
  5121.  
  5122. //-----------------------------------------------------------------------------
  5123. // Helpers
  5124. //-----------------------------------------------------------------------------
  5125.  
  5126. void update_arg_buttons()
  5127. {
  5128.     string arg = source_arg->get_string();
  5129.  
  5130.     bool can_find = (arg != "") && !is_file_pos(arg) && 
  5131.     source_view->have_source();
  5132.     set_sensitive(arg_cmd_area[ArgItems::Find].widget, can_find);
  5133.     set_sensitive(find_forward_w, can_find);
  5134.     set_sensitive(find_backward_w, can_find);
  5135.  
  5136.     bool undoing = undo_buffer.showing_earlier_state();
  5137.     bool can_print = (arg != "") && !is_file_pos(arg) && !undoing;
  5138.     set_sensitive(arg_cmd_area[ArgItems::Print].widget, can_print);
  5139.     set_sensitive(arg_cmd_area[ArgItems::Display].widget, can_print);
  5140.     set_sensitive(print_w,   can_print);
  5141.     set_sensitive(display_w, can_print);
  5142.  
  5143.     set_sensitive(edit_source_w,   source_view->have_source());
  5144.     set_sensitive(reload_source_w, source_view->have_source());
  5145.  
  5146.     bool can_watch = can_print && gdb->has_watch_command();
  5147.     set_sensitive(arg_cmd_area[ArgItems::Watch].widget, can_watch);
  5148.  
  5149.     bool have_watch = have_watchpoint_at_arg();
  5150.  
  5151.     manage_child(watch_menu[WatchItems::Properties].widget, have_watch);
  5152.     manage_child(watch_menu[WatchItems::Enable].widget,     have_watch);
  5153.     manage_child(watch_menu[WatchItems::Sep].widget,        have_watch);
  5154.  
  5155.     set_sensitive(watch_menu[WatchItems::CWatch].widget, 
  5156.           can_watch && 
  5157.           (gdb->has_watch_command() & WATCH_CHANGE) == WATCH_CHANGE);
  5158.     set_sensitive(watch_menu[WatchItems::RWatch].widget,
  5159.           can_watch &&
  5160.           (gdb->has_watch_command() & WATCH_READ) == WATCH_READ);
  5161.     set_sensitive(watch_menu[WatchItems::AWatch].widget,
  5162.           can_watch &&
  5163.           (gdb->has_watch_command() & WATCH_ACCESS) == WATCH_ACCESS);
  5164.     if (have_watch)
  5165.     {
  5166.     set_label(arg_cmd_area[ArgItems::Watch].widget, 
  5167.           "Unwatch ()", UNWATCH_ICON);
  5168.     }
  5169.     else
  5170.     {
  5171.     set_label(arg_cmd_area[ArgItems::Watch].widget, 
  5172.           "Watch ()", WATCH_ICON);
  5173.     }
  5174.  
  5175.     bool watch_enabled = have_enabled_watchpoint_at_arg();
  5176.     if (watch_enabled)
  5177.     set_label(watch_menu[WatchItems::Enable].widget, 
  5178.           "Disable Watchpoint on ()");
  5179.     else
  5180.     set_label(watch_menu[WatchItems::Enable].widget, 
  5181.           "Enable Watchpoint at ()");
  5182.  
  5183.  
  5184.     bool have_break = have_breakpoint_at_arg();
  5185.  
  5186.     manage_child(break_menu[BreakItems::TempBreak].widget,   !have_break);
  5187.     manage_child(break_menu[BreakItems::RegexBreak].widget,  !have_break);
  5188.     manage_child(break_menu[BreakItems::ContUntil].widget,   !have_break);
  5189.     manage_child(break_menu[BreakItems::Sep2].widget,        !have_break);
  5190.     manage_child(break_menu[BreakItems::ClearAt2].widget,    !have_break);
  5191.  
  5192.     manage_child(break_menu[BreakItems::Properties].widget,  have_break);
  5193.     manage_child(break_menu[BreakItems::Enable].widget,      have_break);
  5194.  
  5195.     if (have_break)
  5196.     {
  5197.     set_label(arg_cmd_area[ArgItems::Break].widget, 
  5198.           "Clear at ()", CLEAR_AT_ICON);
  5199.     }
  5200.     else
  5201.     {
  5202.     set_label(arg_cmd_area[ArgItems::Break].widget, 
  5203.           "Break at ()", BREAK_AT_ICON);
  5204.     }
  5205.  
  5206.     bool break_enabled = have_enabled_breakpoint_at_arg();
  5207.     if (break_enabled)
  5208.     set_label(break_menu[BreakItems::Enable].widget, 
  5209.           "Disable Breakpoint at ()");
  5210.     else
  5211.     set_label(break_menu[BreakItems::Enable].widget, 
  5212.           "Enable Breakpoint at ()");
  5213.  
  5214.     set_sensitive(break_menu[BreakItems::ClearAt2].widget,
  5215.           gdb->recording() || have_breakpoint_at_arg());
  5216.     set_sensitive(break_menu[BreakItems::Enable].widget,
  5217.           gdb->can_enable());
  5218.     set_sensitive(break_menu[BreakItems::SetPC].widget,
  5219.           gdb->has_jump_command() || gdb->has_assign_command());
  5220.     set_sensitive(break_menu[BreakItems::RegexBreak].widget,
  5221.           gdb->type() == GDB);
  5222.  
  5223.     MString print_ref_label("Print " + deref(arg, "()"));
  5224.     XtVaSetValues(print_menu[PrintItems::PrintRef].widget,
  5225.           XmNlabelString, print_ref_label.xmstring(),
  5226.           NULL);
  5227.  
  5228.     MString disp_ref_label("Display " + deref(arg, "()"));
  5229.     XtVaSetValues(display_menu[DispItems::DispRef].widget,
  5230.           XmNlabelString, disp_ref_label.xmstring(),
  5231.           NULL);
  5232.  
  5233.     set_sensitive(stack_w,     !undoing);
  5234.     set_sensitive(registers_w, gdb->has_regs_command() && !undoing);
  5235.     set_sensitive(threads_w,   (gdb->type() == GDB || gdb->type() == JDB) &&
  5236.                         !undoing);
  5237.     set_sensitive(infos_w,     (gdb->type() == GDB || gdb->type() == PYDB) &&
  5238.                         !undoing);
  5239. }
  5240.  
  5241. // Arg changed - re-label buttons
  5242. static void source_argHP(void *, void *, void *)
  5243. {
  5244.     update_arg_buttons();
  5245.     data_disp->refresh_args();
  5246.     data_disp->language_changedHP(gdb, 0, 0);
  5247. }
  5248.  
  5249. // Language changed - re-label buttons
  5250. static void language_changedHP(Agent *, void *, void *)
  5251. {
  5252.     update_arg_buttons();
  5253. }
  5254.  
  5255.  
  5256. // Language changed - report it
  5257. static ostream& operator<< (ostream& os, ProgramLanguage lang)
  5258. {
  5259.     switch (lang)
  5260.     {
  5261.     case LANGUAGE_C:       os << "c/c++";         break;
  5262.     case LANGUAGE_JAVA:    os << "java";          break;
  5263.     case LANGUAGE_PASCAL:  os << "pascal/modula"; break;
  5264.     case LANGUAGE_ADA:     os << "ada";           break;
  5265.     case LANGUAGE_PYTHON:  os << "python";        break;
  5266.     case LANGUAGE_PERL:    os << "perl";          break;
  5267.     case LANGUAGE_CHILL:   os << "chill";         break;
  5268.     case LANGUAGE_FORTRAN: os << "fortran";       break;
  5269.     case LANGUAGE_OTHER:   os << "(unknown)";     break;
  5270.     }
  5271.  
  5272.     return os;
  5273. }
  5274.  
  5275. static void report_languageHP(Agent *, void *, void *)
  5276. {
  5277.     ostrstream os;
  5278.     os << "Current language: " << gdb->program_language();
  5279.     set_status(string(os));
  5280. }
  5281.  
  5282.  
  5283. void update_user_buttons()
  5284. {
  5285.     set_buttons(data_buttons_w,    app_data.data_buttons);
  5286.     set_buttons(source_buttons_w,  app_data.source_buttons);
  5287.     set_buttons(console_buttons_w, app_data.console_buttons);
  5288.     set_shortcut_menu(data_disp);
  5289. }
  5290.  
  5291.  
  5292. //-----------------------------------------------------------------------------
  5293. // Handlers
  5294. //-----------------------------------------------------------------------------
  5295.  
  5296. static void gdb_readyHP(Agent *, void *, void *call_data)
  5297. {
  5298.     bool gdb_ready = bool(long(call_data));
  5299.     if (gdb_ready)
  5300.     {
  5301.     if (!gdb_initialized)
  5302.     {
  5303.         gdb_initialized = true;
  5304.         XmTextSetEditable(gdb_w, true);
  5305.     }
  5306.  
  5307.     // Process next pending command as soon as we return
  5308.     if (!emptyCommandQueue())
  5309.         XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 0, 
  5310.                 processCommandQueue, XtPointer(0));
  5311.  
  5312.     // Check for mouse pointer grabs
  5313.     check_grabs(true);
  5314.  
  5315.     // Completion is done
  5316.     clear_completion_delay();
  5317.  
  5318.     // Selection is done
  5319.     if (gdb_selection_dialog != 0)
  5320.         XtUnmanageChild(gdb_selection_dialog);
  5321.  
  5322.     // We don't exit and we don't restart
  5323.     ddd_is_exiting = ddd_is_restarting = false;
  5324.  
  5325.     if (app_data.uniconify_when_ready && userInteractionSeen())
  5326.     {
  5327.         // Uniconify the command shell.  If `iconify all windows
  5328.         // at once' is set, this also uniconifies the other windows.
  5329.         uniconify_shell(command_shell);
  5330.     }
  5331.     }
  5332.  
  5333.     // Some stuff that must be executed every other time
  5334.     fix_status_size();
  5335. }
  5336.  
  5337.  
  5338. struct WhenReadyInfo {
  5339.     MString message;
  5340.     XtCallbackProc proc;
  5341.     XtPointer client_data;
  5342.     XmPushButtonCallbackStruct cbs;
  5343.     XEvent event;
  5344.  
  5345.     WhenReadyInfo(MString msg, XtCallbackProc p,
  5346.           XtPointer cl_data,
  5347.           const XmPushButtonCallbackStruct& c)
  5348.     : message(msg),
  5349.       proc(p),
  5350.       client_data(cl_data),
  5351.       cbs(c)
  5352.     {
  5353.     // Copy event
  5354.     if (c.event == 0)
  5355.     {
  5356.         // This happens with old LessTif versions
  5357.     }
  5358.     else
  5359.     {
  5360.         memcpy(cbs.event, c.event, sizeof(cbs.event));
  5361.         cbs.event = &event;
  5362.     }
  5363.     }
  5364. };
  5365.  
  5366. static void DoneCB(const string& /* answer */, void *qu_data)
  5367. {
  5368.     WhenReadyInfo *info = (WhenReadyInfo *)qu_data;
  5369.     set_status_mstring(info->message + rm("done."));
  5370.  
  5371.     (*info->proc)(gdb_w, info->client_data, XtPointer(&info->cbs));
  5372.     delete info;
  5373. }
  5374.  
  5375. // Execute command in (XtCallbackProc)CLIENT_DATA as soon as GDB gets ready
  5376. static void WhenReady(Widget w, XtPointer client_data, XtPointer call_data)
  5377. {
  5378.     XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data;
  5379.     if (cbs == 0)
  5380.     return;        // This happens with old LessTif versions
  5381.  
  5382.     XtCallbackProc proc = (XtCallbackProc)client_data;
  5383.     XtPointer user_client_data = 0; // No way to pass extra values here
  5384.  
  5385.     if (gdb->isReadyWithPrompt())
  5386.     {
  5387.     // GDB is ready: do command now
  5388.     proc(w, user_client_data, call_data);
  5389.     return;
  5390.     }
  5391.  
  5392.     // Execute command as soon as GDB gets ready
  5393.     XmString label = 0;
  5394.     XtVaGetValues(w, XmNlabelString, &label, NULL);
  5395.     MString _action(label, true);
  5396.     XmStringFree(label);
  5397.     string action = _action.str();
  5398.     if (action.contains("...", -1))
  5399.     action = action.before("...");
  5400.  
  5401.     MString msg = rm(action + ": waiting until " + gdb->title() 
  5402.              + " gets ready...");
  5403.     WhenReadyInfo *info = new WhenReadyInfo(msg, proc, user_client_data, *cbs);
  5404.  
  5405.     // We don't want to lock the status, hence we use an ordinary
  5406.     // `set_status' call instead of the StatusMsg class.
  5407.     set_status_mstring(msg);
  5408.  
  5409.     Command c(gdb->nop_command(XtName(w)));
  5410.     c.origin   = w;
  5411.     c.callback = DoneCB;
  5412.     c.data     = (void *)info;
  5413.     c.verbose  = false;
  5414.     c.prompt   = false;
  5415.     c.check    = false;
  5416.     c.priority = COMMAND_PRIORITY_USER;
  5417.  
  5418.     gdb_command(c);
  5419. }
  5420.  
  5421.  
  5422. //-----------------------------------------------------------------------------
  5423. // I/O warnings
  5424. //-----------------------------------------------------------------------------
  5425.  
  5426. static void gdb_msgHP(Agent *source, void *call_data, char *name)
  5427. {
  5428.     if (source->pid() == 0)
  5429.     {
  5430.     // We're the child.  Don't use the parent's X display.
  5431.         return;
  5432.     }
  5433.  
  5434.     string msg = (char *)call_data;
  5435.     string path = source->path();
  5436.     GDBAgent *gdb = ptr_cast(GDBAgent, source);
  5437.     if (gdb != 0)
  5438.     path = downcase(gdb->title());
  5439.     post_error(path + ": " + msg, name);
  5440. }
  5441.  
  5442. static void gdb_panicHP(Agent *source, void *, void *call_data)
  5443. {
  5444.     gdb_msgHP(source, call_data, "gdb_io_error");
  5445. }
  5446.  
  5447. static void gdb_strangeHP(Agent *source, void *, void *call_data)
  5448. {
  5449.     gdb_msgHP(source, call_data, "gdb_io_warning");
  5450. }
  5451.  
  5452. static void gdb_echo_detectedHP(Agent *, void *, void *call_data)
  5453. {
  5454.     static bool last_echoing = false;
  5455.  
  5456.     bool echoing = bool(long(call_data));
  5457.     if (echoing != last_echoing)
  5458.     {
  5459.     if (echoing)
  5460.     {
  5461.         // Here is a subtle warning.
  5462.         set_status(gdb->title() + " is running in echo mode.");
  5463.  
  5464.         // Attempt to disable echo mode explicitly via stty command.
  5465.         gdb_command(gdb->shell_command("stty -echo -onlcr"), 0, 0, 0, 
  5466.             false, false, COMMAND_PRIORITY_AGAIN);
  5467.     }
  5468.     else
  5469.     {
  5470.         // Tell the user everything is fine.
  5471.         set_status(gdb->title() + " is no longer running in echo mode.");
  5472.     }
  5473.  
  5474.     last_echoing = echoing;
  5475.     }
  5476. }
  5477.  
  5478. static void gdb_recordingHP(Agent *, void *, void *call_data)
  5479. {
  5480.     static StatusMsg *recording_msg = 0;
  5481.     bool recording = bool(long(call_data));
  5482.  
  5483.     delete recording_msg;
  5484.     recording_msg = 0;
  5485.  
  5486.     if (recording && emptyCommandQueue())
  5487.     recording_msg = new StatusMsg("Recording commands");
  5488.  
  5489.     // Recording state affects toolbar button sensitivity
  5490.     update_arg_buttons();
  5491.     data_disp->refresh_args();
  5492.  
  5493.     // Recording state affects Undo/Redo buttons
  5494.     refresh_buttons();
  5495.     gdbUpdateAllMenus();
  5496. }
  5497.  
  5498.  
  5499.  
  5500. //-----------------------------------------------------------------------------
  5501. // Output
  5502. //-----------------------------------------------------------------------------
  5503.  
  5504. // Return index of first control character; -1 if not found
  5505. static int index_control(const string& text)
  5506. {
  5507.     for (unsigned i = 0; i < text.length(); i++)
  5508.     {
  5509.     switch (text[i])
  5510.     {
  5511.     case '\0':        // NUL
  5512.     case '\001':        // SOH
  5513.     case '\002':        // STX
  5514.     case '\003':        // ETX
  5515.     case '\004':        // EOT
  5516.     case '\005':        // ENQ
  5517.     case '\006':        // ACK
  5518.     case '\007':        // BEL
  5519.     case '\010':        // BS
  5520.     case '\011':        // HT
  5521.      // case '\012':        // NL
  5522.     case '\013':        // VT
  5523.     case '\014':        // NP
  5524.     case '\015':        // CR
  5525.     case '\016':        // SO
  5526.     case '\017':        // SI
  5527.     case '\020':        // DLE
  5528.     case '\021':        // DC1
  5529.     case '\022':        // DC2
  5530.     case '\023':        // DC3
  5531.     case '\024':        // DC4
  5532.     case '\025':        // NAK
  5533.     case '\026':        // SYN
  5534.     case '\027':        // ETB
  5535.     case '\030':        // CAN
  5536.     case '\031':        // EM
  5537.     case '\032':        // SUB
  5538.     case '\033':        // ESC
  5539.     case '\034':        // FS
  5540.     case '\035':        // GS
  5541.     case '\036':        // RS
  5542.     case '\037':        // US
  5543.     case '\177':        // DEL
  5544.         return i;
  5545.     }
  5546.     }
  5547.  
  5548.     return -1;
  5549. }
  5550.  
  5551. // Process control character
  5552. static void gdb_ctrl(char ctrl)
  5553. {
  5554.     switch (ctrl)
  5555.     {
  5556.     case '\t':
  5557.     case '\r':
  5558.     {
  5559.     String s = XmTextGetString(gdb_w);
  5560.     string message = s;
  5561.     XtFree(s);
  5562.  
  5563.     XmTextPosition startOfLine = min(promptPosition, message.length());
  5564.     while (startOfLine - 1 >= 0 && message[startOfLine - 1] != '\n')
  5565.         startOfLine--;
  5566.  
  5567.     switch (ctrl)
  5568.     {
  5569.     case '\t':
  5570.     {
  5571.         // Go to next tab position
  5572.         const int TAB_WIDTH = 8;
  5573.         int column = promptPosition - startOfLine;
  5574.         int spaces = TAB_WIDTH - column % TAB_WIDTH;
  5575.         string spacing = replicate(' ', spaces);
  5576.     
  5577.         XmTextInsert(gdb_w, promptPosition, (String)spacing);
  5578.         promptPosition += spacing.length();
  5579.     }
  5580.     break;
  5581.         
  5582.     case '\r':
  5583.     {
  5584.         // Erase last line
  5585.         XmTextReplace(gdb_w, startOfLine, promptPosition, "");
  5586.         promptPosition = startOfLine;
  5587.     }
  5588.     break;
  5589.     }
  5590.     break;
  5591.     }
  5592.  
  5593.     case '\b':
  5594.     {
  5595.     // Erase last character
  5596.     XmTextReplace(gdb_w, promptPosition - 1, promptPosition, "");
  5597.     promptPosition--;
  5598.     }
  5599.     break;
  5600.  
  5601.     case '\n':
  5602.     {
  5603.     string c = ctrl;
  5604.     XmTextInsert(gdb_w, promptPosition, (String)c);
  5605.     promptPosition += c.length();
  5606.  
  5607.     // Flush output
  5608.     XmTextShowPosition(gdb_w, promptPosition);
  5609.     }
  5610.     break;
  5611.  
  5612.     default:
  5613.     {
  5614.     // Issue control character
  5615.     string c;
  5616.     if (ctrl < ' ')
  5617.         c = string("^") + char('@' + ctrl);
  5618.     else
  5619.         c = "^?";
  5620.     XmTextInsert(gdb_w, promptPosition, (String)c);
  5621.     promptPosition += c.length();
  5622.     }
  5623.     break;
  5624.     }
  5625.  
  5626.     // XmTextShowPosition(gdb_w, promptPosition);
  5627. }
  5628.  
  5629.  
  5630. // Append TEXT to GDB output
  5631. void _gdb_out(const string& txt)
  5632. {
  5633.     if (txt == "")
  5634.     return;
  5635.     if (private_gdb_output)
  5636.     return;
  5637.  
  5638.     string text(txt);
  5639.     string buffered = buffered_gdb_output();
  5640.     if (buffered != "")
  5641.     text.prepend(buffered);
  5642.  
  5643.     gdb_input_at_prompt = gdb->ends_with_prompt(text);
  5644.     if (gdb_input_at_prompt)
  5645.     debuggee_running = false;
  5646.  
  5647.     if (promptPosition == 0)
  5648.     promptPosition = XmTextGetLastPosition(gdb_w);
  5649.  
  5650.     private_gdb_output = true;
  5651.  
  5652.     // Don't care for strings to be ignored
  5653.     static string empty;
  5654.     if (gdb_out_ignore != "")
  5655.     text.gsub(gdb_out_ignore, empty);
  5656.  
  5657.     // Pass TEXT to various functions
  5658.     set_buttons_from_gdb(console_buttons_w, text);
  5659.     set_buttons_from_gdb(source_buttons_w, text);
  5660.     set_buttons_from_gdb(data_buttons_w, text);
  5661.     set_buttons_from_gdb(command_toolbar_w, text);
  5662.     set_status_from_gdb(text);
  5663.     set_tty_from_gdb(text);
  5664.  
  5665.     // Output TEXT on TTY
  5666.     tty_out(text);
  5667.  
  5668.     // Output TEXT in debugger console
  5669.     bool line_buffered = app_data.line_buffered_console;
  5670.     static bool cr_pending = false;
  5671.     do {
  5672.     char ctrl      = '\0';
  5673.     bool have_ctrl = false;
  5674.  
  5675.     if (pending_interaction())
  5676.     {
  5677.         process_emergencies();
  5678.         line_buffered = false;
  5679.     }
  5680.  
  5681.     string block = text;
  5682.  
  5683.     int i = -1;
  5684.     if (line_buffered)
  5685.         i = block.index('\n');
  5686.     if (i < 0)
  5687.         i = index_control(block);
  5688.  
  5689.     if (i >= 0)
  5690.     {
  5691.         ctrl      = block[i];
  5692.         have_ctrl = true;
  5693.         block     = block.before(i);
  5694.         text      = text.after(i);
  5695.     }
  5696.     else
  5697.     {
  5698.         // All done
  5699.         text = "";
  5700.     }
  5701.  
  5702.     if (block.length() > 0)
  5703.     {
  5704.         if (cr_pending)
  5705.         {
  5706.         gdb_ctrl('\r');
  5707.         cr_pending = false;
  5708.         }
  5709.  
  5710.         XmTextInsert(gdb_w, promptPosition, (String)block);
  5711.         promptPosition += block.length();
  5712.         // XmTextShowPosition(gdb_w, promptPosition);
  5713.     }
  5714.  
  5715.     if (have_ctrl)
  5716.     {
  5717.         if (ctrl == '\r')
  5718.         {
  5719.         // Don't output CR immediately, but wait for the next
  5720.         // character.  If it's a NL, ignore the CR.
  5721.         cr_pending = true;
  5722.         }
  5723.         else
  5724.         {
  5725.         if (cr_pending)
  5726.         {
  5727.             if (ctrl == '\n')
  5728.             {
  5729.             // Ignore CR followed by NL
  5730.             }
  5731.             else
  5732.             {
  5733.             gdb_ctrl('\r');
  5734.             }
  5735.             cr_pending = false;
  5736.         }
  5737.         gdb_ctrl(ctrl);
  5738.         }
  5739.     }
  5740.     } while (text != "");
  5741.  
  5742.     XmTextPosition lastPos = XmTextGetLastPosition(gdb_w);
  5743.     XmTextSetInsertionPosition(gdb_w, lastPos);
  5744.     XmTextShowPosition(gdb_w, lastPos);
  5745.  
  5746.     private_gdb_output = false;
  5747. }
  5748.  
  5749.  
  5750. void gdb_out(const string& text)
  5751. {
  5752.     if (private_gdb_input)
  5753.     return;
  5754.  
  5755.     _gdb_out(text);
  5756. }
  5757.  
  5758.  
  5759.  
  5760.  
  5761. //-----------------------------------------------------------------------------
  5762. // Cut/Copy/Paste
  5763. //-----------------------------------------------------------------------------
  5764.  
  5765. static DDDWindow ddd_window(XtPointer client_data)
  5766. {
  5767.     if (source_view_shell == 0 && data_disp_shell == 0)
  5768.     return CommonWindow;
  5769.     else
  5770.     return DDDWindow(long(client_data));
  5771. }
  5772.  
  5773. static void gdbCutSelectionCB(Widget w, XtPointer client_data, 
  5774.                   XtPointer call_data)
  5775. {
  5776.     XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data;
  5777.     Time tm = time(cbs->event);
  5778.  
  5779.     DDDWindow win = ddd_window(client_data);
  5780.     Boolean success = False;
  5781.     Widget dest = XmGetDestination(XtDisplay(w));
  5782.  
  5783.     // Try data arg
  5784.     if (!success && (win == DataWindow || win == CommonWindow))
  5785.     {
  5786.     if (data_disp->have_selection())
  5787.     {
  5788.         success = XmTextCopy(DataDisp::graph_selection_w, tm);
  5789.         if (success)
  5790.         DataDisp::deleteCB(w, client_data, call_data);
  5791.     }
  5792.     }
  5793.  
  5794.     // Try destination window
  5795.     if (!success && dest != 0 && XmIsText(dest))
  5796.     success = XmTextCut(dest, tm);
  5797.     if (!success && dest != 0 && XmIsTextField(dest))
  5798.     success = XmTextFieldCut(dest, tm);
  5799.  
  5800.     // Try debugger console
  5801.     if (!success && (win == GDBWindow || win == CommonWindow))
  5802.     success = XmTextCut(gdb_w, tm);
  5803.  
  5804.     // Try source arg
  5805.     if (!success && (win == SourceWindow || win == CommonWindow))
  5806.     success = XmTextFieldCut(source_arg->text(), tm);
  5807.  
  5808.     if (success)
  5809.     gdbUnselectAllCB(w, client_data, call_data);
  5810. }
  5811.  
  5812. static void gdbCopySelectionCB(Widget w, XtPointer client_data, 
  5813.                    XtPointer call_data)
  5814. {
  5815.     XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data;
  5816.     Time tm = time(cbs->event);
  5817.     
  5818.     DDDWindow win = ddd_window(client_data);
  5819.     Boolean success = False;
  5820.     Widget dest = XmGetDestination(XtDisplay(w));
  5821.  
  5822.     // Try data arg
  5823.     if (!success && (win == DataWindow || win == CommonWindow))
  5824.     if (data_disp->have_selection())
  5825.     {
  5826.         success = XmTextCopy(DataDisp::graph_selection_w, tm);
  5827.     }
  5828.  
  5829.     // Try destination window
  5830.     if (!success && dest != 0 && XmIsText(dest))
  5831.     success = XmTextCopy(dest, tm);
  5832.     if (!success && dest != 0 && XmIsTextField(dest))
  5833.     success = XmTextFieldCopy(dest, tm);
  5834.  
  5835.     // Try debugger console
  5836.     if (!success && (win == GDBWindow || win == CommonWindow))
  5837.     success = XmTextCopy(gdb_w, tm);
  5838.  
  5839.     // Try source arg
  5840.     if (!success && (win == SourceWindow || win == CommonWindow))
  5841.     success = XmTextFieldCopy(source_arg->text(), tm);
  5842.  
  5843.     // Try source
  5844.     if (!success && (win == SourceWindow || win == CommonWindow))
  5845.     success = XmTextCopy(source_view->source(), tm);
  5846.  
  5847.     // Try code
  5848.     if (!success && (win == SourceWindow || win == CommonWindow))
  5849.     success = XmTextCopy(source_view->code(), tm);
  5850. }
  5851.  
  5852. static void gdbPasteClipboardCB(Widget w, XtPointer client_data, XtPointer)
  5853. {
  5854.     DDDWindow win = ddd_window(client_data);
  5855.  
  5856.     // Try destination window
  5857.     bool success = false;
  5858.     Widget dest = XmGetDestination(XtDisplay(w));
  5859.     if (dest != 0)
  5860.     {
  5861.     if (dest == DataDisp::graph_selection_w)
  5862.     {
  5863.         // Don't paste into graph selection; paste into GDB
  5864.         // console instead
  5865.         dest = gdb_w;
  5866.     }
  5867.  
  5868.     if (!success && XmIsText(dest))
  5869.         success = XmTextPaste(dest);
  5870.     if (!success && XmIsTextField(dest))
  5871.         success = XmTextFieldPaste(dest);
  5872.     }
  5873.     if (success)
  5874.     return;
  5875.  
  5876.     switch (win)
  5877.     {
  5878.     case ToolWindow:
  5879.     // Cannot paste into command tool
  5880.     break;
  5881.  
  5882.     case GDBWindow:
  5883.     case CommonWindow:
  5884.     case DataWindow:
  5885.     XmTextPaste(gdb_w);
  5886.     break;
  5887.  
  5888.     case SourceWindow:
  5889.     XmTextFieldPaste(source_arg->text());
  5890.     break;
  5891.  
  5892.     default:
  5893.     // Cannot paste into exec window
  5894.     break;
  5895.     }
  5896. }
  5897.  
  5898. static void gdbUnselectAllCB(Widget w, XtPointer client_data,
  5899.                  XtPointer call_data)
  5900. {
  5901.     XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data;
  5902.     Time tm = time(cbs->event);
  5903.  
  5904.     XmTextClearSelection(gdb_w, tm);
  5905.     XmTextFieldClearSelection(source_arg->text(), tm);
  5906.     XmTextClearSelection(source_view->source(), tm);
  5907.     XmTextClearSelection(source_view->code(), tm);
  5908.  
  5909.     if (data_disp->graph_arg != 0)
  5910.     XmTextFieldClearSelection(data_disp->graph_arg->text(), tm);
  5911.     if (data_disp->graph_selection_w != 0)
  5912.     XmTextClearSelection(data_disp->graph_selection_w, tm);
  5913.  
  5914.     DataDisp::unselectAllCB(w, client_data, call_data);
  5915. }
  5916.  
  5917. static void gdbClearAllCB(Widget w, XtPointer client_data, XtPointer call_data)
  5918. {
  5919.     gdbUnselectAllCB(w, client_data, call_data);
  5920.     source_arg->set_string("");
  5921.     gdbClearCB(w, client_data, call_data);
  5922. }
  5923.  
  5924. static void gdbSelectAllCB(Widget w, XtPointer client_data, 
  5925.                XtPointer call_data)
  5926. {
  5927.     DDDWindow win = ddd_window(client_data);
  5928.  
  5929.     XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data;
  5930.     Time tm = time(cbs->event);
  5931.  
  5932.     bool success = false;
  5933.     Widget dest = XmGetDestination(XtDisplay(w));
  5934.     if (dest != 0)
  5935.     {
  5936.     if (!success && dest == DataDisp::graph_selection_w)
  5937.     {
  5938.         DataDisp::selectAllCB(w, client_data, call_data);
  5939.         success = true;
  5940.     }
  5941.     if (!success && XmIsText(dest))
  5942.     {
  5943.         XmTextSetSelection(dest, 0, XmTextGetLastPosition(dest), tm);
  5944.         success = true;
  5945.     }
  5946.     if (!success && XmIsTextField(dest))
  5947.     {
  5948.         XmTextFieldSetSelection(dest, 0, 
  5949.                     XmTextFieldGetLastPosition(dest), tm);
  5950.         success = true;
  5951.     }
  5952.     }
  5953.     if (success)
  5954.     return;
  5955.  
  5956.     switch (win)
  5957.     {
  5958.     case SourceWindow:
  5959.     case CommonWindow:
  5960.     {
  5961.     Widget w = source_arg->text();
  5962.     XmTextFieldSetSelection(w, 0, XmTextFieldGetLastPosition(w), tm);
  5963.     break;
  5964.     }
  5965.  
  5966.     case DataWindow:
  5967.     DataDisp::selectAllCB(w, client_data, call_data);
  5968.     break;
  5969.  
  5970.     case GDBWindow:
  5971.     XmTextSetSelection(gdb_w, promptPosition, 
  5972.                XmTextGetLastPosition(gdb_w), tm);
  5973.     break;
  5974.  
  5975.     default:
  5976.     break;
  5977.     }
  5978. }
  5979.  
  5980.  
  5981. static void gdbDeleteSelectionCB(Widget w, XtPointer client_data, 
  5982.                  XtPointer call_data)
  5983. {
  5984.     DDDWindow win = ddd_window(client_data);
  5985.     Boolean success = False;
  5986.     Widget dest = XmGetDestination(XtDisplay(w));
  5987.  
  5988.     // Try data display
  5989.     if (!success && dest == DataDisp::graph_selection_w)
  5990.     {
  5991.     if (data_disp->have_selection())
  5992.     {
  5993.         DataDisp::deleteCB(w, client_data, call_data);
  5994.         success = true;
  5995.     }
  5996.     }
  5997.  
  5998.     // Try destination window
  5999.     if (!success && dest != 0 && XmIsText(dest))
  6000.     success = XmTextRemove(dest);
  6001.     if (!success && dest != 0 && XmIsTextField(dest))
  6002.     success = XmTextFieldRemove(dest);
  6003.  
  6004.     // Try debugger console
  6005.     if (!success && (win == GDBWindow || win == CommonWindow))
  6006.     success = XmTextRemove(gdb_w);
  6007.  
  6008.     // Try source arg
  6009.     if (!success && (win == SourceWindow || win == CommonWindow))
  6010.     success = XmTextFieldRemove(source_arg->text());
  6011.  
  6012.     // Try data display
  6013.     if (!success && (win == DataWindow || win == CommonWindow))
  6014.     {
  6015.     if (data_disp->have_selection())
  6016.     {
  6017.         DataDisp::deleteCB(w, client_data, call_data);
  6018.         success = true;
  6019.     }
  6020.     }
  6021.  
  6022.     if (success)
  6023.     gdbUnselectAllCB(w, client_data, call_data);
  6024. }
  6025.  
  6026. // Update cut/copy/paste bindings
  6027. static void set_cut_copy_paste_bindings(MMDesc *menu, BindingStyle style)
  6028. {
  6029.     if (menu == 0 || menu[0].widget == 0)
  6030.     return;
  6031.  
  6032. #ifdef LESSTIF_VERSION
  6033.     // This only works in Lesstif.
  6034.     switch (style)
  6035.     {
  6036.     case KDEBindings:
  6037.     {
  6038.     MString cut("Ctrl+X");
  6039.     MString copy("Ctrl+C");
  6040.     MString paste("Ctrl+V");
  6041.  
  6042.     XtVaSetValues(menu[EditItems::Cut].widget,
  6043.               XmNaccelerator, "~Shift Ctrl<Key>X",
  6044.               XmNacceleratorText, cut.xmstring(),
  6045.               NULL);
  6046.     XtVaSetValues(menu[EditItems::Copy].widget,
  6047.               XmNaccelerator, "~Shift Ctrl<Key>C",
  6048.               XmNacceleratorText, copy.xmstring(),
  6049.               NULL);
  6050.     XtVaSetValues(menu[EditItems::Paste].widget,
  6051.               XmNaccelerator, "~Shift Ctrl<Key>V",
  6052.               XmNacceleratorText, paste.xmstring(),
  6053.               NULL);
  6054.     break;
  6055.     }
  6056.  
  6057.     case MotifBindings:
  6058.     {
  6059.     MString cut("Shift+Del");
  6060.     MString copy("Ctrl+Ins");
  6061.     MString paste("Shift+Ins");
  6062.  
  6063.     XtVaSetValues(menu[EditItems::Cut].widget,
  6064.               XmNaccelerator, "~Ctrl Shift<Key>Delete",
  6065.               XmNacceleratorText, cut.xmstring(),
  6066.               NULL);
  6067.     XtVaSetValues(menu[EditItems::Copy].widget,
  6068.               XmNaccelerator, "~Shift Ctrl<Key>Insert",
  6069.               XmNacceleratorText, copy.xmstring(),
  6070.               NULL);
  6071.     XtVaSetValues(menu[EditItems::Paste].widget,
  6072.               XmNaccelerator, "~Ctrl Shift<Key>Insert",
  6073.               XmNacceleratorText, paste.xmstring(),
  6074.               NULL);
  6075.     break;
  6076.     }
  6077.     }
  6078. #else
  6079.     (void) style;
  6080. #endif
  6081. }
  6082.  
  6083. static void setup_cut_copy_paste_bindings(XrmDatabase db)
  6084. {
  6085.     // Stupid OSF/Motif won't change the accelerators once created.
  6086.     // Set resources explicitly.
  6087.     String resources = 0;
  6088.     switch (app_data.cut_copy_paste_bindings)
  6089.     {
  6090.     case KDEBindings:
  6091.     resources =
  6092.         "*editMenu.cut.acceleratorText: Ctrl+X\n"
  6093.         "*editMenu.copy.acceleratorText: Ctrl+C\n"
  6094.         "*editMenu.paste.acceleratorText: Ctrl+V\n"
  6095.         "*editMenu.cut.accelerator: ~Shift Ctrl<Key>X\n"
  6096.         "*editMenu.copy.accelerator: ~Shift Ctrl<Key>C\n"
  6097.         "*editMenu.paste.accelerator: ~Shift Ctrl<Key>V\n";
  6098.     break;
  6099.  
  6100.     case MotifBindings:
  6101.     resources =
  6102.         "*editMenu.cut.acceleratorText: Shift+Del\n"
  6103.         "*editMenu.copy.acceleratorText: Ctrl+Ins\n"
  6104.         "*editMenu.paste.acceleratorText: Shift+Ins\n"
  6105.         "*editMenu.cut.accelerator: ~Ctrl Shift<Key>Delete\n"
  6106.         "*editMenu.copy.accelerator: ~Shift Ctrl<Key>Insert\n"
  6107.         "*editMenu.paste.accelerator: ~Ctrl Shift<Key>Insert\n";
  6108.     break;
  6109.     }
  6110.  
  6111.     XrmDatabase bindings = XrmGetStringDatabase(resources);
  6112.     assert(bindings != 0);
  6113.     XrmMergeDatabases(bindings, &db);
  6114. }
  6115.  
  6116.  
  6117. // Update select all bindings
  6118. static void set_select_all_bindings(MMDesc *menu, BindingStyle style)
  6119. {
  6120.     if (menu == 0 || menu[0].widget == 0)
  6121.     return;
  6122.  
  6123.     switch (style)
  6124.     {
  6125.     case KDEBindings:
  6126.     {
  6127.     MString select_all("Ctrl+A");
  6128.  
  6129.     XtVaSetValues(menu[EditItems::SelectAll].widget,
  6130.               XmNacceleratorText, select_all.xmstring(),
  6131.               NULL);
  6132.     break;
  6133.     }
  6134.  
  6135.     case MotifBindings:
  6136.     {
  6137.     MString select_all("Shift+Ctrl+A");
  6138.  
  6139.     XtVaSetValues(menu[EditItems::SelectAll].widget,
  6140.               XmNacceleratorText, select_all.xmstring(),
  6141.               NULL);
  6142.     break;
  6143.     }
  6144.     }
  6145. }
  6146.  
  6147. static void setup_select_all_bindings(XrmDatabase db)
  6148. {
  6149.     // Stupid OSF/Motif won't change the accelerators once created.
  6150.     // Set resources explicitly.
  6151.     String resources = 0;
  6152.     switch (app_data.select_all_bindings)
  6153.     {
  6154.     case KDEBindings:
  6155.     resources =
  6156.         "*editMenu.selectAll.acceleratorText: Ctrl+A\n";
  6157.     break;
  6158.  
  6159.     case MotifBindings:
  6160.     resources =
  6161.         "*editMenu.selectAll.acceleratorText: Shift+Ctrl+A\n";
  6162.     break;
  6163.     }
  6164.  
  6165.     XrmDatabase bindings = XrmGetStringDatabase(resources);
  6166.     assert(bindings != 0);
  6167.     XrmMergeDatabases(bindings, &db);
  6168. }
  6169.  
  6170.  
  6171. //-----------------------------------------------------------------------------
  6172. // Update menu entries
  6173. //-----------------------------------------------------------------------------
  6174.  
  6175. static int _mapped_menus = 0;
  6176.  
  6177. static int mapped_menus()
  6178. {
  6179.     if (lesstif_version < 1000)
  6180.     {
  6181.     // LessTif does not issue a XmCR_MAP callback when mapping
  6182.     // RowColumn menus.  Hence, assume we have a mapped menu.
  6183.     return 1;
  6184.     }
  6185.  
  6186.     return _mapped_menus;
  6187. }
  6188.  
  6189. static void count_mapped_menus(Widget, XtPointer, XtPointer call_data)
  6190. {
  6191.     XmRowColumnCallbackStruct *cbs = (XmRowColumnCallbackStruct *)call_data;
  6192.     if (cbs == 0)
  6193.     return;
  6194.  
  6195.     switch (cbs->reason)
  6196.     {
  6197.     case XmCR_MAP:
  6198.     _mapped_menus++;
  6199.     break;
  6200.  
  6201.     case XmCR_UNMAP:
  6202.     _mapped_menus--;
  6203.     break;
  6204.  
  6205. #if XmVersion >= 1002
  6206.     case XmCR_TEAR_OFF_ACTIVATE:
  6207.     _mapped_menus++;
  6208.     break;
  6209.  
  6210.     case XmCR_TEAR_OFF_DEACTIVATE:
  6211.     _mapped_menus--;
  6212.     break;
  6213. #endif
  6214.  
  6215.     default:
  6216.     break;
  6217.     }
  6218.  
  6219.     // clog << _mapped_menus << " mapped menus\n";
  6220. }
  6221.  
  6222. static void gdbUpdateEditCB(Widget w, XtPointer client_data, 
  6223.                 XtPointer call_data)
  6224. {
  6225.     DDDWindow win = ddd_window(client_data);
  6226.  
  6227.     // Fetch menu
  6228.     MMDesc *menu = 0;
  6229.     switch (win)
  6230.     {
  6231.     case GDBWindow:
  6232.     case CommonWindow:
  6233.     menu = command_edit_menu;
  6234.     break;
  6235.  
  6236.     case SourceWindow:
  6237.     menu = source_edit_menu;
  6238.     break;
  6239.  
  6240.     case DataWindow:
  6241.     menu = data_edit_menu;
  6242.     break;
  6243.  
  6244.     default:
  6245.     break;
  6246.     }
  6247.  
  6248.     if (menu == 0 || menu[0].widget == 0)
  6249.     return;
  6250.  
  6251.     count_mapped_menus(w, client_data, call_data);
  6252.  
  6253.     // Reset undo/redo actions
  6254.     string undo_action = undo_buffer.undo_action();
  6255.     string redo_action = undo_buffer.redo_action();
  6256.  
  6257.     if (undo_action == NO_GDB_ANSWER)
  6258.     {
  6259.     set_label(menu[EditItems::Undo].widget, "Undo");
  6260.     set_sensitive(menu[EditItems::Undo].widget, False);
  6261.     }
  6262.     else
  6263.     {
  6264.     MString label("Undo " + undo_action);
  6265.     set_label(menu[EditItems::Undo].widget, label);
  6266.     set_sensitive(menu[EditItems::Undo].widget, True);
  6267.     }
  6268.  
  6269.     if (redo_action == NO_GDB_ANSWER)
  6270.     {
  6271.     set_label(menu[EditItems::Redo].widget, "Redo");
  6272.     set_sensitive(menu[EditItems::Redo].widget, False);
  6273.     }
  6274.     else
  6275.     {
  6276.     MString label("Redo " + redo_action);
  6277.     set_label(menu[EditItems::Redo].widget, label);
  6278.     set_sensitive(menu[EditItems::Redo].widget, True);
  6279.     }
  6280.  
  6281.  
  6282.     // Check if we have something to cut
  6283.     XmTextPosition start, end;
  6284.     bool can_cut = false;
  6285.     Widget dest  = XmGetDestination(XtDisplay(w));
  6286.  
  6287.     // Try destination window
  6288.     if (!can_cut && dest != 0 && XmIsText(dest))
  6289.     can_cut = XmTextGetSelectionPosition(dest, &start, &end);
  6290.     if (!can_cut && dest != 0 && XmIsTextField(dest))
  6291.     can_cut = XmTextFieldGetSelectionPosition(dest, &start, &end);
  6292.  
  6293.     // Try debugger console
  6294.     if (!can_cut && (win == GDBWindow || win == CommonWindow))
  6295.     can_cut = XmTextGetSelectionPosition(gdb_w, &start, &end);
  6296.  
  6297.     // Try source arg
  6298.     if (!can_cut && (win == SourceWindow || win == CommonWindow))
  6299.     can_cut = XmTextFieldGetSelectionPosition(source_arg->text(), 
  6300.                           &start, &end);
  6301.  
  6302.     // Try data display
  6303.     if (!can_cut && (win == DataWindow || win == CommonWindow))
  6304.     can_cut = data_disp->have_selection();
  6305.  
  6306.     // Check if we have something to copy
  6307.     bool can_copy = can_cut;
  6308.  
  6309.     // Try source
  6310.     if (!can_copy && (win == SourceWindow || win == CommonWindow))
  6311.     can_copy = XmTextGetSelectionPosition(source_view->source(),
  6312.                           &start, &end);
  6313.  
  6314.     // Try code
  6315.     if (!can_copy && (win == SourceWindow || win == CommonWindow))
  6316.     can_copy = XmTextGetSelectionPosition(source_view->code(),
  6317.                           &start, &end);
  6318.  
  6319.     // There is always something to paste
  6320.     bool can_paste = true;
  6321.     set_sensitive(menu[EditItems::Cut].widget,    can_cut);
  6322.     set_sensitive(menu[EditItems::Copy].widget,   can_copy);
  6323.     set_sensitive(menu[EditItems::Paste].widget,  can_paste);
  6324.     set_sensitive(menu[EditItems::Delete].widget, can_cut);
  6325. }
  6326.  
  6327. static void gdbUpdateFileCB(Widget w, XtPointer client_data, 
  6328.                 XtPointer call_data)
  6329. {
  6330.     MMDesc *file_menu = (MMDesc *)client_data;
  6331.     if (file_menu == 0 || file_menu[0].widget == 0)
  6332.     return;
  6333.  
  6334.     count_mapped_menus(w, client_data, call_data);
  6335.  
  6336.     // Check whether we can print something
  6337.     Graph *graph = graphEditGetGraph(data_disp->graph_edit);
  6338.     Boolean can_print = (graph->firstNode() != 0);
  6339.     set_sensitive(file_menu[FileItems::Print].widget,      can_print);
  6340.     set_sensitive(file_menu[FileItems::PrintAgain].widget, can_print);
  6341.  
  6342.     // Check whether we can close something
  6343.     Boolean can_close = (running_shells() > 1);
  6344.     set_sensitive(file_menu[FileItems::Close].widget, can_close);
  6345.  
  6346. #if 0
  6347.     // If we have only one window, remove the `Close' item
  6348.     Boolean one_window = 
  6349.     !app_data.separate_source_window && !app_data.separate_data_window;
  6350.     manage_child(file_menu[FileItems::Close].widget, !one_window);
  6351. #endif
  6352. }
  6353.  
  6354. static void gdbUpdateViewCB(Widget w, XtPointer client_data, 
  6355.                 XtPointer call_data)
  6356. {
  6357.     MMDesc *view_menu = (MMDesc *)client_data;
  6358.     if (view_menu == 0 || view_menu[0].widget == 0)
  6359.     return;
  6360.  
  6361.     count_mapped_menus(w, client_data, call_data);
  6362.  
  6363.     set_sensitive(view_menu[CodeWindow].widget, gdb->type() == GDB);
  6364.     set_sensitive(view_menu[ExecWindow].widget, gdb->has_redirection());
  6365. }
  6366.  
  6367. static void gdbUpdateViewsCB(Widget w, XtPointer client_data, 
  6368.                  XtPointer call_data)
  6369. {
  6370.     gdbUpdateViewCB(w, client_data, call_data);
  6371.  
  6372.     MMDesc *view_menu = (MMDesc *)client_data;
  6373.     if (view_menu == 0 || view_menu[0].widget == 0)
  6374.     return;
  6375.  
  6376.     set_toggle(view_menu[DataWindow].widget,   have_data_window());
  6377.     set_toggle(view_menu[SourceWindow].widget, have_source_window());
  6378.     set_toggle(view_menu[CodeWindow].widget,   app_data.disassemble);
  6379.     set_toggle(view_menu[GDBWindow].widget,    have_command_window());
  6380. }
  6381.  
  6382. void update_edit_menus()
  6383. {
  6384.     if (gdb_w == 0)
  6385.     return;
  6386.  
  6387.     XtPointer call_data = 0;
  6388.  
  6389.     gdbUpdateEditCB(gdb_w, XtPointer(GDBWindow),    call_data);
  6390.     gdbUpdateEditCB(gdb_w, XtPointer(SourceWindow), call_data);
  6391.     gdbUpdateEditCB(gdb_w, XtPointer(DataWindow),   call_data);
  6392. }
  6393.  
  6394. // In case we have tear-off menus, all these menus must be updated at
  6395. // all times.
  6396. static void gdbUpdateAllMenus()
  6397. {
  6398.     if (mapped_menus() == 0)
  6399.     return;            // No mapped menu
  6400.  
  6401.     update_edit_menus();
  6402.  
  6403.     XtPointer call_data = 0;
  6404.  
  6405.     gdbUpdateFileCB(gdb_w, XtPointer(command_file_menu), call_data);
  6406.     gdbUpdateFileCB(gdb_w, XtPointer(source_file_menu),  call_data);
  6407.     gdbUpdateFileCB(gdb_w, XtPointer(data_file_menu),    call_data);
  6408.  
  6409.     gdbUpdateViewsCB(gdb_w, XtPointer(views_menu),       call_data);
  6410.  
  6411.     gdbUpdateViewCB(gdb_w, XtPointer(command_view_menu), call_data);
  6412.     gdbUpdateViewCB(gdb_w, XtPointer(source_view_menu),  call_data);
  6413.     gdbUpdateViewCB(gdb_w, XtPointer(data_view_menu),    call_data);
  6414. }
  6415.  
  6416. //-----------------------------------------------------------------------------
  6417. // Configure new shell
  6418. //-----------------------------------------------------------------------------
  6419.  
  6420. static void setup_new_shell(Widget w)
  6421. {
  6422.     if (w == 0)
  6423.     return;
  6424.  
  6425.     Widget shell = findShellParent(w);
  6426.     if (shell == 0 && XtIsWidget(w) && XtIsShell(w))
  6427.     shell = w;
  6428.     if (shell == 0)
  6429.     return;
  6430.  
  6431. #if HAVE_X11_XMU_EDITRES_H
  6432.     // Make the shell handle EditRes messages
  6433.     XtRemoveEventHandler(shell, EventMask(0), true,
  6434.              XtEventHandler(_XEditResCheckMessages), NULL);
  6435.     XtAddEventHandler(shell, EventMask(0), true,
  6436.               XtEventHandler(_XEditResCheckMessages), NULL);
  6437. #endif
  6438.  
  6439.     // Use DDD logo as icon of the new shell
  6440.     if (shell != 0 && XtIsRealized(shell))
  6441.     wm_set_icon(shell, iconlogo(w), iconmask(w));
  6442. }
  6443.  
  6444. //-----------------------------------------------------------------------------
  6445. // Misc functions
  6446. //-----------------------------------------------------------------------------
  6447.  
  6448. // Xt Warning handler
  6449. static void ddd_xt_warning(String message)
  6450. {
  6451.     if (!app_data.suppress_warnings)
  6452.     {
  6453.     ddd_original_xt_warning_handler(message);
  6454.  
  6455.     static bool informed = false;
  6456.  
  6457.     if (!informed)
  6458.     {
  6459.         cerr << "(Annoyed?  "
  6460.         "Try 'Edit->Preferences->General->Suppress X Warnings'!)\n";
  6461.         informed = true;
  6462.     }
  6463.     }
  6464.  
  6465.     // With auto-raised menus, Motif may fail to ungrab the pointer
  6466.     // due to the interference with DDD auto-raise.  In this case,
  6467.     // Motif issues a warning that it cannot grab the pointer (and
  6468.     // leaves the pointer *grabbed*).  Hence, ungrab it explictly.
  6469.     if (gdb_initialized)
  6470.     {
  6471.     XUngrabPointer(XtDisplay(gdb_w), CurrentTime);
  6472.     XFlush(XtDisplay(gdb_w));
  6473.     }
  6474. }
  6475.  
  6476.  
  6477.  
  6478.  
  6479. //-----------------------------------------------------------------------------
  6480. // Decoration
  6481. //-----------------------------------------------------------------------------
  6482.  
  6483. static Widget init_label, init_shell;
  6484.  
  6485. // Return a transient position on SCREEN (for command tool etc.) in POS_X/POS_Y
  6486. static void get_transient_pos(Screen *screen, Position& pos_x, Position& pos_y)
  6487. {
  6488.     (void) screen;        // Use it
  6489. #if 0
  6490.     // Use lower right corner.
  6491.     pos_x = WidthOfScreen(screen) - 1;
  6492.     pos_y = HeightOfScreen(screen) - 1;
  6493. #else
  6494.     // This loses on some window managers; upper left corner is safer.
  6495.     pos_x = 0;
  6496.     pos_y = 0;
  6497. #endif
  6498. }
  6499.  
  6500. // Check if window manager decorates transients
  6501. static void start_have_decorated_transients(Widget parent)
  6502. {
  6503.     Position pos_x, pos_y;
  6504.     get_transient_pos(XtScreen(parent), pos_x, pos_y);
  6505.  
  6506.     ostrstream os;
  6507.     os << "+" << pos_x << "+" << pos_y;
  6508.     string geometry(os);
  6509.  
  6510.     Arg args[10];
  6511.     int arg = 0;
  6512.     XtSetArg(args[arg], XmNgeometry, geometry.chars()); arg++;
  6513.     XtSetArg(args[arg], XmNx, pos_x);                   arg++;
  6514.     XtSetArg(args[arg], XmNy, pos_y);                   arg++;
  6515.     init_shell = verify(XmCreateDialogShell(parent, "init_shell", args, arg));
  6516.  
  6517.     arg = 0;
  6518.     MString label(DDD_NAME " " DDD_VERSION);
  6519.     XtSetArg(args[arg], XmNlabelString, label.xmstring()); arg++;
  6520.     init_label = verify(XmCreateLabel(init_shell, ddd_NAME, args, arg));
  6521.     XtManageChild(init_label);
  6522.  
  6523.     wait_until_mapped(init_label, init_shell);
  6524.     XmUpdateDisplay(init_label);
  6525. }
  6526.  
  6527. static bool have_decorated_transients()
  6528. {
  6529.     if (init_label == 0 || init_shell == 0)
  6530.     start_have_decorated_transients(command_shell);
  6531.  
  6532.     XWindowAttributes shell_attributes;
  6533.     XGetWindowAttributes(XtDisplay(init_shell), XtWindow(init_shell), 
  6534.              &shell_attributes);
  6535.  
  6536. #if 0
  6537.     clog << "shell window: " << XtWindow(init_shell)
  6538.      << ", size: " << BoxPoint(shell_attributes.width, 
  6539.                        shell_attributes.height) << "\n";
  6540. #endif
  6541.  
  6542.     // Wait up to 5 seconds until WM has decorated the init shell.
  6543.     // Problem: If we have no WM or a non-decorating WM, this delays
  6544.     // DDD for 5 seconds; this can be avoided by using an explicit
  6545.     // `decorateTool' resource value.
  6546.     Window frame_window = 0;
  6547.     for (int trial = 1; trial < 5; trial++)
  6548.     {
  6549.     frame_window = frame(XtDisplay(init_shell), XtWindow(init_shell));
  6550.     if (frame_window != XtWindow(init_shell))
  6551.         break;
  6552.     XSync(XtDisplay(init_label), False);
  6553.     sleep(1);
  6554.     }
  6555.  
  6556.     XWindowAttributes frame_attributes;
  6557.     XGetWindowAttributes(XtDisplay(init_shell), frame_window,
  6558.              &frame_attributes);
  6559.  
  6560. #if 0
  6561.     clog << "frame window: " << frame_window 
  6562.      << ", size: " << BoxPoint(frame_attributes.width, 
  6563.                        frame_attributes.height) << "\n";
  6564. #endif
  6565.  
  6566.     XtUnmapWidget(init_shell);
  6567.     DestroyWhenIdle(init_shell);
  6568.  
  6569.     // If the border supplied by the window manager border is more
  6570.     // than 5 pixels higher than wider, assume we have some kind of
  6571.     // title bar - the shell is decorated.
  6572.     int border_height = frame_attributes.height - shell_attributes.height;
  6573.     int border_width  = frame_attributes.width  - shell_attributes.width;
  6574.  
  6575.     return border_height - border_width > 5;
  6576. }
  6577.  
  6578.  
  6579. //-----------------------------------------------------------------------------
  6580. // Splash Screen
  6581. //-----------------------------------------------------------------------------
  6582.  
  6583. static Widget splash_shell  = 0;
  6584. static Pixmap splash_pixmap = None;
  6585. static _Delay *splash_delay = 0;
  6586.  
  6587. static void popdown_splash_screen(XtPointer data, XtIntervalId *id)
  6588. {
  6589.     (void) id;            // use it
  6590.  
  6591.     if (data != 0)
  6592.     {
  6593.     XtIntervalId *timer = (XtIntervalId *)data;
  6594.     assert(*timer == *id);
  6595.     *timer = 0;
  6596.     }
  6597.     
  6598.     if (splash_shell != 0)
  6599.     {
  6600.     if (splash_pixmap != None)
  6601.         XFreePixmap(XtDisplay(splash_shell), splash_pixmap);
  6602.  
  6603.     popdown_shell(splash_shell);
  6604.     DestroyWhenIdle(splash_shell);
  6605.     splash_shell = 0;
  6606.  
  6607.     delete splash_delay;
  6608.     splash_delay = 0;
  6609.     }
  6610. }
  6611.  
  6612. static void popup_splash_screen(Widget parent, string color_key)
  6613. {
  6614.     popdown_splash_screen();
  6615.  
  6616.     XErrorBlocker blocker(XtDisplay(parent));
  6617.  
  6618.     Arg args[10];
  6619.     int arg = 0;
  6620.     XtSetArg(args[arg], XmNallowShellResize, True); arg++;
  6621.     XtSetArg(args[arg], XmNborderWidth, 0); arg++;
  6622.     splash_shell = verify(XtCreatePopupShell("splash_shell", 
  6623.                          overrideShellWidgetClass, 
  6624.                          parent, args, arg));
  6625.  
  6626.     arg = 0;
  6627.     XtSetArg(args[arg], XmNborderWidth, 0);  arg++;
  6628.     XtSetArg(args[arg], XmNmarginWidth, 0);  arg++;
  6629.     XtSetArg(args[arg], XmNmarginHeight, 0); arg++;
  6630.     Widget splash = 
  6631.     verify(XmCreateDrawingArea(splash_shell, "splash", args, arg));
  6632.     XtManageChild(splash);
  6633.  
  6634.     Dimension width, height;
  6635.     splash_pixmap = dddsplash(splash, color_key, width, height);
  6636.  
  6637.     if (blocker.error_occurred())
  6638.     splash_pixmap = None;
  6639.  
  6640.     if (splash_pixmap == None)
  6641.     return;
  6642.  
  6643.     XtVaSetValues(splash,
  6644.           XmNbackgroundPixmap, splash_pixmap,
  6645.           XmNwidth, width,
  6646.           XmNheight, height,
  6647.           NULL);
  6648.  
  6649.     int x = (WidthOfScreen(XtScreen(splash_shell)) - width) / 2;
  6650.     int y = (HeightOfScreen(XtScreen(splash_shell)) - height) / 2;
  6651.  
  6652.     XtVaSetValues(splash_shell, XmNx, x, XmNy, y, NULL);
  6653.  
  6654.     // Place lock warning on top of startup splash
  6655.     lock_dialog_x = x + 20;
  6656.     lock_dialog_y = y + 20;
  6657.  
  6658.     XtRealizeWidget(splash_shell);
  6659.  
  6660.     splash_delay = new _Delay(splash_shell);
  6661.  
  6662.     popup_shell(splash_shell);
  6663.     wait_until_mapped(splash, splash_shell);
  6664. }
  6665.  
  6666. static void SetSplashScreenCB(Widget, XtPointer, XtPointer call_data)
  6667. {
  6668.     XmToggleButtonCallbackStruct *info = 
  6669.     (XmToggleButtonCallbackStruct *)call_data;
  6670.  
  6671.     app_data.splash_screen = info->set;
  6672.  
  6673.     update_options();
  6674. }
  6675.  
  6676.  
  6677. //-----------------------------------------------------------------------------
  6678. // GDB status
  6679. //-----------------------------------------------------------------------------
  6680.  
  6681. static StatusMsg *running_msg = 0;
  6682.  
  6683. static void ReportStartHP(Agent *agent, void *, void *)
  6684. {
  6685.     GDBAgent *gdb = ptr_cast(GDBAgent, agent);
  6686.     if (gdb == 0)
  6687.     return;
  6688.  
  6689.     if (running_msg != 0)
  6690.     delete running_msg;
  6691.  
  6692.     running_msg = new StatusMsg("Running " + gdb->title() + 
  6693.                 " (pid " + itostring(gdb->pid()) + 
  6694.                 ", tty " + gdb->slave_tty() + ")");
  6695.     unlock_status();
  6696. }
  6697.  
  6698. static void ReportDeathHP(Agent *agent, void *, void *call_data)
  6699. {
  6700.     GDBAgent *gdb = ptr_cast(GDBAgent, agent);
  6701.     if (gdb == 0)
  6702.     return;
  6703.  
  6704.     char *reason = (char *)call_data;
  6705.     if (gdb != 0 && running_msg != 0)
  6706.     {
  6707.     running_msg->outcome = reason;
  6708.     delete running_msg;
  6709.     running_msg = 0;
  6710.     }
  6711. }
  6712.  
  6713.  
  6714. //-----------------------------------------------------------------------------
  6715. // Emergency
  6716. //-----------------------------------------------------------------------------
  6717.  
  6718. static Bool is_emergency(Display *, XEvent *event, char *)
  6719. {
  6720.     switch (event->type)
  6721.     {
  6722.     case KeyPress:
  6723.     {
  6724.     char buffer[1024];
  6725.     KeySym keysym;
  6726.  
  6727.     int len = XLookupString(&event->xkey, buffer, sizeof buffer, 
  6728.                 &keysym, NULL);
  6729.     if (len == 1)
  6730.     {
  6731.         char c = buffer[0];
  6732.         if (c== '\003' || c == '\007' || c == '\033' || c == '\034')
  6733.         {
  6734.         // Interrupt: ^C, ^G, ^\, or ESC found in queue
  6735.         return True;
  6736.         }
  6737.     }
  6738.     }
  6739.     }
  6740.  
  6741.     return False;
  6742. }
  6743.  
  6744. bool process_emergencies()
  6745. {
  6746.     XEvent event;
  6747.     if (XCheckIfEvent(XtDisplay(gdb_w), &event, is_emergency, 0))
  6748.     {
  6749.     // Emergency: process this event immediately
  6750.     XtDispatchEvent(&event);
  6751.     return true;
  6752.     }
  6753.  
  6754.     return false;
  6755. }
  6756.  
  6757.  
  6758. //----------------------------------------------------------------------------
  6759. // Synchronize argument fields
  6760. //----------------------------------------------------------------------------
  6761.  
  6762. static void SyncArgHP(void *src, void *client_data, void *)
  6763. {
  6764.     ArgField *source = (ArgField *)src;
  6765.     ArgField *target = (ArgField *)client_data;
  6766.  
  6767.     target->removeHandler(Changed, SyncArgHP, (void *)source);
  6768.     target->set_string(source->get_string());
  6769.     target->addHandler(Changed, SyncArgHP, (void *)source);
  6770. }
  6771.  
  6772. static void sync_args(ArgField *source, ArgField *target)
  6773. {
  6774.     if (source == 0 || target == 0)
  6775.     return;
  6776.  
  6777.     target->set_string(source->get_string());
  6778.  
  6779.     source->addHandler(Changed, SyncArgHP, (void *)target);
  6780.     target->addHandler(Changed, SyncArgHP, (void *)source);
  6781. }
  6782.  
  6783.  
  6784.  
  6785.  
  6786. //-----------------------------------------------------------------------------
  6787. // Log player stuff
  6788. //-----------------------------------------------------------------------------
  6789.  
  6790. static void check_log(const string& logname, DebuggerType& type)
  6791. {
  6792.     ifstream log(logname);
  6793.     if (log.bad())
  6794.     {
  6795.     (void) fopen(logname, "r");
  6796.     perror(logname);
  6797.     exit(EXIT_FAILURE);
  6798.     }
  6799.  
  6800.     while (log)
  6801.     {
  6802.     char buffer[1024];
  6803.     log.getline(buffer, sizeof buffer);
  6804.     string log_line(buffer);
  6805.  
  6806.     if (log_line.contains("+  ", 0))
  6807.     {
  6808.         get_debugger_type(log_line, type);
  6809.         return;
  6810.     }
  6811.     }
  6812. }
  6813.  
  6814.  
  6815. //-----------------------------------------------------------------------------
  6816. // `Show' options
  6817. //-----------------------------------------------------------------------------
  6818.  
  6819. // Return true iff resource is defined and set
  6820. static string resource_value(XrmDatabase db, string app_name, char *res_name)
  6821. {
  6822.     string str_name  = app_name + "." + res_name;
  6823.     string str_class = string(DDD_CLASS_NAME) + "." + res_name;
  6824.  
  6825.     char *type;
  6826.     XrmValue xrmvalue;
  6827.     Bool success = XrmGetResource(db, str_name, str_class, &type, &xrmvalue);
  6828.     if (!success)
  6829.     return "";        // Resource not found
  6830.  
  6831.     char *str = (char *)xrmvalue.addr;
  6832.     int len   = xrmvalue.size - 1; // includes the final `\0'
  6833.     return string(str, len);
  6834. }
  6835.  
  6836. static bool is_set(string value)
  6837. {
  6838.     value.downcase();
  6839.  
  6840.     if (value == "on" || value == "true" || value == "yes")
  6841.     return true;
  6842.     else if (value == "off" || value == "false" || value == "no")
  6843.     return false;
  6844.  
  6845.     // Illegal value
  6846.     return false;
  6847. }
  6848.  
  6849. inline bool have_set_resource(XrmDatabase db, char *app_name, char *res_name)
  6850. {
  6851.     return is_set(resource_value(db, app_name, res_name));
  6852. }
  6853.  
  6854. static void setup_show(XrmDatabase db, char *app_name, char *gdb_name)
  6855. {
  6856.     // Check for `--version', `--help', `--news', etc.  This may be
  6857.     // invoked before we have connected to an X display, so check
  6858.     // APP_DATA as well as the resource database (initialized from the
  6859.     // command line).
  6860.  
  6861.     bool cont = true;
  6862.     if (app_data.show_version || 
  6863.     have_set_resource(db, app_name, XtNshowVersion))
  6864.     {
  6865.     show_version(cout);
  6866.     cont = false;
  6867.     }
  6868.     if (app_data.show_invocation ||
  6869.     have_set_resource(db, app_name, XtNshowInvocation))
  6870.     {
  6871.     show_invocation(gdb_name, cout);
  6872.     cont = false;
  6873.     }
  6874.     if (app_data.show_configuration ||
  6875.     have_set_resource(db, app_name, XtNshowConfiguration))
  6876.     {
  6877.     show_configuration(cout);
  6878.     cont = false;
  6879.     }
  6880.     if (app_data.show_news ||
  6881.     have_set_resource(db, app_name, XtNshowNews))
  6882.     {
  6883.     show(ddd_news);
  6884.     cont = false;
  6885.     }
  6886.     if (app_data.show_license ||
  6887.     have_set_resource(db, app_name, XtNshowLicense))
  6888.     {
  6889.     show(ddd_license);
  6890.     cont = false;
  6891.     }
  6892.     if (app_data.show_manual ||
  6893.     have_set_resource(db, app_name, XtNshowManual))
  6894.     {
  6895.     show(ddd_man);
  6896.     cont = false;
  6897.     }
  6898.     if (!cont)
  6899.     exit(EXIT_SUCCESS);
  6900. }
  6901.  
  6902.  
  6903. //-----------------------------------------------------------------------------
  6904. // Various setups
  6905. //-----------------------------------------------------------------------------
  6906.  
  6907. // This text is shown in `About DDD', appended to the value of the
  6908. // `helpOnVersionString' resource.
  6909. static void setup_version_info()
  6910. {
  6911.     ostrstream os;
  6912.     show_configuration(os);
  6913.     string cinfo(os);
  6914.  
  6915.     cinfo.gsub("(C)", "\251");
  6916.  
  6917.     // Set e-mail address in @tt; the remainder in @rm
  6918.     int cinfo_lt = cinfo.index('<', -1);
  6919.     int cinfo_gt = cinfo.index('>', -1);
  6920.     if (cinfo_lt >= 0 && cinfo_gt >= 0)
  6921.     {
  6922.     helpOnVersionExtraText = rm(cinfo.before(cinfo_lt));
  6923.      helpOnVersionExtraText += cr();    // place e-mail on separate line
  6924.     helpOnVersionExtraText += rm(cinfo(cinfo_lt, 1));
  6925.     helpOnVersionExtraText += 
  6926.         tt(cinfo(cinfo_lt + 1, cinfo_gt - cinfo_lt - 1));
  6927.     helpOnVersionExtraText += rm(cinfo.from(cinfo_gt));
  6928.     }
  6929.     else
  6930.     {
  6931.     helpOnVersionExtraText = rm(cinfo);
  6932.     }
  6933.  
  6934.     string expires = ddd_expiration_date();
  6935.     if (expires != "")
  6936.     {
  6937.     // Add expiration date
  6938.     string expired_msg = DDD_NAME " " DDD_VERSION " ";
  6939.     if (ddd_expired())
  6940.         expired_msg += "has expired since " + expires;
  6941.     else
  6942.         expired_msg += "expires " + expires;
  6943.  
  6944.     helpOnVersionExtraText += rm(expired_msg + ".") + cr();
  6945.     }
  6946.  
  6947.     helpOnVersionExtraText += cr() 
  6948.     + rm(DDD_NAME " is ") + sl("free software")
  6949.     + rm(" and you are welcome to distribute copies of it") + cr()
  6950.     + rm("under certain conditions; select ")
  6951.     + bf("Help") + MString("\256", CHARSET_SYMBOL) 
  6952.     + bf(DDD_NAME " License") + rm(" to see the") + cr()
  6953.     + rm("conditions.  There is ") + sl("absolutely no warranty") 
  6954.     + rm(" for " DDD_NAME "; see the ") + cr()
  6955.     + rm(DDD_NAME " License for details.") + cr();
  6956.  
  6957.     helpOnVersionExtraText += cr()
  6958.     + rm("If you find " DDD_NAME " useful, please send "
  6959.          "us a picture postcard:") + cr()
  6960.     + cr()
  6961.     + rm("    Technische Universit\344t Braunschweig") + cr()
  6962.     + rm("    Abteilung Softwaretechnologie") + cr()
  6963.     + rm("    B\374ltenweg 88") + cr()
  6964.     + rm("    D-38092 Braunschweig") + cr()
  6965.     + rm("    GERMANY") + cr();
  6966.  
  6967.     string log = session_log_file();
  6968.     if (log.contains(gethome(), 0))
  6969.     log = "~" + log.after(gethome());
  6970.  
  6971.     helpOnVersionExtraText += cr()
  6972.     + rm("Send bug reports to <")
  6973.     + tt(ddd_NAME "-bugs@ips.cs.tu-bs.de") + rm(">.") + cr()
  6974.     + rm("Always include the ") + tt(log) + rm(" file;")
  6975.     + rm(" see the " DDD_NAME " manual for details.") + cr()
  6976.     + rm("Send comments and suggestions to <")
  6977.     + tt(ddd_NAME "@ips.cs.tu-bs.de") + rm(">.") + cr();
  6978.  
  6979.     helpOnVersionExtraText += cr()
  6980.     + rm(DDD_NAME " WWW page: ") + tt(app_data.www_page) + cr()
  6981.     + rm(DDD_NAME " discussions: <")
  6982.     + tt(ddd_NAME "-users-request@ips.cs.tu-bs.de") + rm(">") + cr()
  6983.     + rm(DDD_NAME " announcements: <")
  6984.     + tt(ddd_NAME "-announce-request@ips.cs.tu-bs.de") + rm(">");
  6985. }
  6986.  
  6987.  
  6988. // Add current selection as argument
  6989. static void add_arg_from_selection(Widget toplevel, int& argc, char **&argv)
  6990. {
  6991.     assert(argc == 1);
  6992.  
  6993.     static string selection;
  6994.  
  6995.     for (int i = 0; i < 3; i++)
  6996.     {
  6997.     switch (i)
  6998.     {
  6999.     case 0:
  7000.         selection = current_primary(toplevel);
  7001.         break;
  7002.  
  7003.     case 1:
  7004.         selection = current_cut_buffer(toplevel);
  7005.         break;
  7006.  
  7007.     case 2:
  7008.         selection = current_clipboard(toplevel);
  7009.         break;
  7010.     }
  7011.  
  7012.     strip_space(selection);
  7013.  
  7014.     // Simple hack to handle URLs
  7015.     if (selection.contains("file://", 0))
  7016.     {
  7017.         selection = selection.after("//");
  7018.         selection = selection.from("/");
  7019.     }
  7020.     else if (selection.contains("file:", 0))
  7021.         selection = selection.after(':');
  7022.  
  7023.     if (selection == "")
  7024.         continue;            // No selection
  7025.  
  7026.     const int new_argc = 2;
  7027.     static char *new_argv[new_argc + 1];
  7028.     new_argv[0] = argv[0];
  7029.     new_argv[1] = selection;
  7030.     new_argv[2] = 0;
  7031.  
  7032.     bool sure;
  7033.     (void) guess_debugger_type(new_argc, new_argv, sure);
  7034.     if (sure)
  7035.     {
  7036.         // Selection is valid for some debugger.  Go for it.
  7037.         argc = new_argc;
  7038.         argv = new_argv;
  7039.         return;
  7040.     }
  7041.     }
  7042. }
  7043.  
  7044. static void setup_environment()
  7045. {
  7046.     // Set the type of the execution tty.
  7047.     switch (gdb->type())
  7048.     {
  7049.     case GDB:
  7050.     case DBX:
  7051.     case PERL:
  7052.     // The debugger console has few capabilities.
  7053.     // When starting the execution TTY, we set the correct type.
  7054.     put_environment("TERM", "dumb");
  7055.     break;
  7056.  
  7057.     case XDB:
  7058.     case JDB:
  7059.     case PYDB:
  7060.     // In these debuggers, we have no means to set the TTY type
  7061.     // afterwards.  Set the execution TTY type right now.
  7062.     put_environment("TERM", app_data.term_type);
  7063.     break;
  7064.     }
  7065.  
  7066.     // Don't let TERMCAP settings override our TERM settings.
  7067.     put_environment("TERMCAP", "");
  7068.  
  7069.     // This avoids zillions of problems with debuggers that pipe
  7070.     // their output through `more', `less', and likewise.
  7071.     put_environment("PAGER", "cat");
  7072.  
  7073.     // Let the debugger know that we're here
  7074.     put_environment(DDD_NAME, ddd_NAME "-" DDD_VERSION "-" DDD_HOST);
  7075. }
  7076.  
  7077. static void setup_command_tool()
  7078. {
  7079.     // It is preferable to realize the command tool as a DialogShell,
  7080.     // since this will cause it to stay on top of other DDD windows.
  7081.     // Unfortunately, some window managers do not decorate transient
  7082.     // windows such as DialogShells.  In this case, use a TopLevel
  7083.     // shell instead and rely on the DDD auto-raise mechanisms defined
  7084.     // in `windows.C'.
  7085.     //
  7086.     // Nobody ever honors all this work.  -AZ
  7087.  
  7088.     bool use_transient_tool_shell = true;
  7089.     switch (app_data.decorate_tool)
  7090.     {
  7091.     case On:
  7092.     use_transient_tool_shell = false;
  7093.     break;
  7094.     case Off:
  7095.     use_transient_tool_shell = true;
  7096.     break;
  7097.     case Auto:
  7098.     use_transient_tool_shell = have_decorated_transients();
  7099.     break;
  7100.     }
  7101.  
  7102.     Widget tool_shell_parent = 
  7103.     source_view_shell ? source_view_shell : command_shell;
  7104.  
  7105.     Arg args[10];
  7106.     int arg = 0;
  7107.  
  7108.     XtSetArg(args[arg], XmNdeleteResponse, XmDO_NOTHING); arg++;
  7109.     XtSetArg(args[arg], XmNallowShellResize, False);      arg++;
  7110.     XtSetArg(args[arg], XmNmwmDecorations,
  7111.          MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MENU); arg++;
  7112.     XtSetArg(args[arg], XmNmwmFunctions, 
  7113.          MWM_FUNC_MOVE | MWM_FUNC_CLOSE); arg++;
  7114.  
  7115.     if (use_transient_tool_shell)
  7116.     {
  7117.     tool_shell = 
  7118.         verify(XmCreateDialogShell(tool_shell_parent, 
  7119.                        "tool_shell", args, arg));
  7120.     }
  7121.     else
  7122.     {
  7123.     tool_shell = 
  7124.         verify(XtCreateWidget("tool_shell", vendorShellWidgetClass,
  7125.                   tool_shell_parent, args, arg));
  7126.     }
  7127.  
  7128.     XmAddWMProtocolCallback(tool_shell, WM_DELETE_WINDOW, 
  7129.                 gdbCloseToolWindowCB, 0);
  7130.  
  7131.     arg = 0;
  7132.     tool_buttons_w = 
  7133.     verify(XmCreateForm(tool_shell, "tool_buttons", args, arg));
  7134.     set_buttons(tool_buttons_w, app_data.tool_buttons, false);
  7135.  
  7136.     Delay::register_shell(tool_shell);
  7137.     XtAddEventHandler(tool_shell, STRUCTURE_MASK, False,
  7138.               StructureNotifyEH, XtPointer(0));
  7139.  
  7140. #if XmVersion >= 1002
  7141. #define FIXED_COMMAND_TOOL 1
  7142. #endif
  7143.  
  7144. #if FIXED_COMMAND_TOOL
  7145.     // Some FVWM flavors have trouble in finding the `best' window size.
  7146.     // Determine `best' size for tool shell.
  7147.     XtWidgetGeometry size;
  7148.     size.request_mode = CWHeight | CWWidth;
  7149.     XtQueryGeometry(tool_buttons_w, NULL, &size);
  7150. #endif
  7151.  
  7152.     // Set shell geometry
  7153.     Position pos_x, pos_y;
  7154.     get_transient_pos(XtScreen(tool_shell_parent), pos_x, pos_y);
  7155.  
  7156.     ostrstream os;
  7157. #if FIXED_COMMAND_TOOL
  7158.     os << size.width << "x" << size.height;
  7159. #endif
  7160.     os << "+" << pos_x << "+" << pos_y;
  7161.     string geometry(os);
  7162.  
  7163.     XtSetArg(args[arg], XmNgeometry, geometry.chars()); arg++;
  7164.     XtSetArg(args[arg], XmNx, pos_x);                   arg++;
  7165.     XtSetArg(args[arg], XmNy, pos_y);                   arg++;
  7166.  
  7167. #if FIXED_COMMAND_TOOL
  7168.     // Some FVWM flavors have trouble in finding the `best' window size.
  7169.     XtSetArg(args[arg], XmNmaxWidth,  size.width);      arg++;
  7170.     XtSetArg(args[arg], XmNmaxHeight, size.height);     arg++;
  7171.     XtSetArg(args[arg], XmNminWidth,  size.width);      arg++;
  7172.     XtSetArg(args[arg], XmNminHeight, size.height);     arg++;
  7173. #endif
  7174.  
  7175.     XtSetValues(tool_shell, args, arg);
  7176. }
  7177.  
  7178. static void setup_options(int& argc, char *argv[],
  7179.               StringArray& saved_options, string& gdb_name,
  7180.               bool& no_windows)
  7181. {
  7182.     int gdb_option_pos = -1;
  7183.     int gdb_option_offset = 2;
  7184.     int i;
  7185.     for (i = 1; i < argc; i++)
  7186.     {
  7187.     string arg = string(argv[i]);
  7188.  
  7189.     if (arg == "--")
  7190.         break;        // End of options
  7191.  
  7192.     if ((arg == "--debugger" || arg == "-debugger") && i < argc - 1)
  7193.     {
  7194.         gdb_name = argv[i + 1];
  7195.         gdb_option_pos    = i;
  7196.         gdb_option_offset = 2;
  7197.     }
  7198.  
  7199.     if (arg == "--dbx" || arg == "-dbx" 
  7200.         || arg == "--gdb" || arg == "-gdb"
  7201.         || arg == "--xdb" || arg == "-xdb"
  7202.         || arg == "--jdb" || arg == "-jdb"
  7203.         || arg == "--pydb" || arg == "-pydb"
  7204.         || arg == "--perl" || arg == "-perl")
  7205.     {
  7206.         gdb_name = arg.after('-', -1);
  7207.         gdb_option_pos    = i;
  7208.         gdb_option_offset = 1;
  7209.     }
  7210.  
  7211.     if (arg == "--nw" || arg == "-nw" || arg == "-L")
  7212.     {
  7213.         if (gdb_option_pos >= 0)
  7214.         {
  7215.         // Strip `--debugger NAME'/`--dbx'/`--gdb', etc.
  7216.         for (int j = gdb_option_pos; 
  7217.              j <= argc - gdb_option_offset; j++)
  7218.         {
  7219.             argv[j] = argv[j + gdb_option_offset];
  7220.         }
  7221.         argc -= gdb_option_offset;
  7222.         i    -= gdb_option_offset;
  7223.         }
  7224.  
  7225.         // Strip `--nw'/`-L'
  7226.         for (int j = i; j <= argc - 1; j++)
  7227.         argv[j] = argv[j + 1];
  7228.         argc -= 1;
  7229.         i    -= 1;
  7230.  
  7231.         no_windows = true;
  7232.     }
  7233.  
  7234.     if (arg == "--PLAY")
  7235.     {
  7236.         // Switch into logplayer mode
  7237.         string logname;
  7238.         if (i < argc - 1)
  7239.         logname = argv[i + 1];
  7240.         else
  7241.         logname = session_log_file();
  7242.  
  7243.         logplayer(logname);
  7244.     }
  7245.  
  7246.     if (!no_windows)
  7247.     {
  7248.         // Save some one-letter options that would be eaten by Xt:
  7249.         // -b BPS  - Set the line speed to BPS (GDB)
  7250.         // -c FILE - use FILE as a core dump to examine (GDB)
  7251.         // -d DIR  - Add DIR to the path of search files (GDB, XDB)
  7252.         // -e FILE - use FILE as executable file to execute (GDB)
  7253.         // -e FILE - Redirect stderr to FILE (XDB)
  7254.         // -i FILE - Redirect stdin to FILE (XDB)
  7255.         // -I DIR  - Add DIR to the path of search files (DBX)
  7256.         // -o FILE - Redirect stdout to FILE (XDB)
  7257.         // -p FILE - Specify a playback FILE (XDB)
  7258.         // -P PID  - Specify a process id PID (DBX, XDB)
  7259.         // -r FILE - Specify a record FILE (XDB)
  7260.         // -R FILE - Specify a restore state FILE (XDB)
  7261.         // -s FILE - read symbol table (GDB)
  7262.         // -s FILE - execute commands from FILE (DBX)
  7263.         // -x FILE - execute commands from FILE (GDB)
  7264.  
  7265.         // Note: the following options are used by DDD:
  7266.         // -h       - Help
  7267.         // -l LOGIN - Login as LOGIN
  7268.         // -v       - Show version
  7269.         // -?       - Help
  7270.         // -t       - Use TTY mode
  7271.         // -f       - Use fullname mode
  7272. #if RUNTIME_REGEX
  7273.         static regex rxoptions("-[bcdeiIopPrRsx]");
  7274. #endif
  7275.         if (i < argc - 1 && arg.matches(rxoptions))
  7276.         {
  7277.         saved_options += arg;
  7278.         saved_options += string(argv[i + 1]);
  7279.  
  7280.         for (int j = i; j <= argc - 2; j++)
  7281.             argv[j] = argv[j + 2];
  7282.         argc -= 2;
  7283.         i    -= 2;
  7284.         }
  7285.     }
  7286.     }
  7287. }
  7288.  
  7289. static void setup_tty()
  7290. {
  7291.     if (app_data.tty_mode)
  7292.     {
  7293.     init_command_tty();
  7294.  
  7295.     // Issue init msg (using 7-bit characters)
  7296.     string init_msg = XmTextGetString(gdb_w);
  7297.     init_msg.gsub("\344", "ae");
  7298.     init_msg.gsub("\366", "oe");
  7299.     init_msg.gsub("\374", "ue");
  7300.     init_msg.gsub("\337", "ss");
  7301.     init_msg.gsub("\251", "(C)");
  7302.     tty_out(init_msg);
  7303.     }
  7304. }
  7305.  
  7306. static void setup_ddd_version_warnings()
  7307. {
  7308.     // Check for app-defaults
  7309.     if (app_data.app_defaults_version == 0)
  7310.     {
  7311.     cerr << "Error: No `" DDD_CLASS_NAME "' application defaults file\n"
  7312.         "To resolve this problem, you can:\n"
  7313.         "* install the `" DDD_CLASS_NAME "' file in the X "
  7314.         "application defaults directory, or\n"
  7315.         "* set the `" DDD_CLASS_NAME "' location "
  7316.         "in the XAPPLRESDIR environment variable, or\n"
  7317.         "* recompile " DDD_NAME " with builtin app-defaults file;\n"
  7318.         "  see the `--enable-builtin-app-defaults' option for details.\n";
  7319.  
  7320.     exit(EXIT_FAILURE);
  7321.     }
  7322.     else if (string(app_data.app_defaults_version) != DDD_VERSION)
  7323.     {
  7324.     cerr << "Warning: using `" DDD_CLASS_NAME "' app-defaults file"
  7325.          << " for " DDD_NAME " " << app_data.app_defaults_version 
  7326.          << " (this is " DDD_NAME " " DDD_VERSION ")\n"
  7327.          << "Continue at own risk.\n";
  7328.  
  7329.     if (!version_warnings.isEmpty())
  7330.         version_warnings += cr();
  7331.  
  7332.     version_warnings += rm("Using `") + tt(DDD_CLASS_NAME)
  7333.         + rm("' app-defaults file for " DDD_NAME " ")
  7334.         + rm(app_data.app_defaults_version)
  7335.         + rm(" (this is " DDD_NAME " " DDD_VERSION ")");
  7336.     }
  7337.  
  7338.     // Check for ~/.ddd/init
  7339.     if (app_data.dddinit_version && 
  7340.     string(app_data.dddinit_version) != DDD_VERSION)
  7341.     {
  7342.     cerr << "Warning: using "
  7343.          << quote(session_state_file(app_data.session))
  7344.          << " file for " DDD_NAME " " << app_data.dddinit_version
  7345.          << "\n(this is " DDD_NAME " " DDD_VERSION ")."
  7346.          << "  Please save options.\n";
  7347.  
  7348.     if (!version_warnings.isEmpty())
  7349.         version_warnings += cr();
  7350.  
  7351.     version_warnings += rm("Using `")
  7352.         + tt(cook(session_state_file(app_data.session)))
  7353.         + rm("' file for " DDD_NAME " ")
  7354.         + rm(app_data.dddinit_version) + cr()
  7355.         + rm("(this is " DDD_NAME " " DDD_VERSION ").  "
  7356.          "Please save options.");
  7357.     }
  7358. }
  7359.  
  7360. static void setup_motif_version_warnings()
  7361. {
  7362.     // Version warnings
  7363.     bool risky = false;
  7364.  
  7365. #if HAVE_XMUSEVERSION
  7366.     if (xmUseVersion != XmVersion)
  7367.     {
  7368.     cerr << "Warning: This " DDD_NAME " requires a Motif "
  7369.          << XmVersion / 1000 << "." << XmVersion % 1000 
  7370.          << " library (using Motif "
  7371.          << xmUseVersion / 1000 << "." << xmUseVersion % 1000 
  7372.          << ")\n";
  7373.  
  7374.     risky = true;
  7375.     }
  7376. #endif
  7377.  
  7378.     if (risky)
  7379.     cerr << "Continue at own risk.\n";
  7380. }
  7381.  
  7382. static void setup_auto_command_prefix()
  7383. {
  7384.     if (app_data.auto_command_prefix == 0)
  7385.     app_data.auto_command_prefix = "";
  7386.     static string prefix = app_data.auto_command_prefix;
  7387.  
  7388.     if (prefix.length() < 3)
  7389.     {
  7390.     // No prefix or insufficient prefix -- generate a new one
  7391.     ostrstream key;
  7392.     key << ddd_NAME << "-" << getpid() << "-" 
  7393.         << (long)time((time_t *)0) << ": ";
  7394.     prefix = key;
  7395.     }
  7396.  
  7397.     app_data.auto_command_prefix = prefix;
  7398. }
  7399.  
  7400. // All options that remain fixed for a session go here.
  7401. static void setup_options()
  7402. {
  7403.     set_sensitive(disassemble_w, gdb->type() == GDB);
  7404.     set_sensitive(code_indent_w, gdb->type() == GDB);
  7405.     set_sensitive(examine_w,            gdb->has_examine_command());
  7406.     set_sensitive(print_examine_w,      gdb->has_examine_command());
  7407.     set_sensitive(cache_machine_code_w, gdb->type() == GDB);
  7408.  
  7409.     set_sensitive(set_refer_base_w, gdb->type() != GDB);
  7410.     set_sensitive(set_refer_path_w, gdb->type() != GDB);
  7411.     set_sensitive(refer_sources_w,  gdb->type() != GDB);
  7412.  
  7413.     set_sensitive(edit_watchpoints_w, gdb->has_watch_command());
  7414.  
  7415.     set_sensitive(command_separate_exec_window_w, gdb->has_redirection());
  7416.     set_sensitive(source_separate_exec_window_w,  gdb->has_redirection());
  7417.     set_sensitive(data_separate_exec_window_w,    gdb->has_redirection());
  7418.  
  7419.     bool have_core = gdb->has_core_files();
  7420.     set_sensitive(command_file_menu[FileItems::OpenCore].widget,    have_core);
  7421.     set_sensitive(source_file_menu[FileItems::OpenCore].widget,     have_core);
  7422.     set_sensitive(data_file_menu[FileItems::OpenCore].widget,       have_core);
  7423.  
  7424.     bool have_exec = gdb->has_exec_files() || gdb->type() == PERL;
  7425.     manage_child(command_file_menu[FileItems::OpenFile].widget,     have_exec);
  7426.     manage_child(source_file_menu[FileItems::OpenFile].widget,      have_exec);
  7427.     manage_child(data_file_menu[FileItems::OpenFile].widget,        have_exec);
  7428.  
  7429.     bool have_classes = gdb->has_classes();
  7430.     manage_child(command_file_menu[FileItems::OpenClass].widget, have_classes);
  7431.     manage_child(source_file_menu[FileItems::OpenClass].widget,  have_classes);
  7432.     manage_child(data_file_menu[FileItems::OpenClass].widget,    have_classes);
  7433.  
  7434.     bool have_attach = gdb->has_processes();
  7435.     set_sensitive(command_file_menu[FileItems::Attach].widget,    have_attach);
  7436.     set_sensitive(source_file_menu[FileItems::Attach].widget,     have_attach);
  7437.     set_sensitive(data_file_menu[FileItems::Attach].widget,       have_attach);
  7438.  
  7439.     bool have_detach = gdb->has_processes();
  7440.     set_sensitive(command_file_menu[FileItems::Detach].widget,    have_detach);
  7441.     set_sensitive(source_file_menu[FileItems::Detach].widget,     have_detach);
  7442.     set_sensitive(data_file_menu[FileItems::Detach].widget,       have_detach);
  7443.  
  7444.     bool have_make = gdb->has_make_command() || gdb->has_shell_command();
  7445.     set_sensitive(command_file_menu[FileItems::Make].widget,        have_make);
  7446.     set_sensitive(source_file_menu[FileItems::Make].widget,         have_make);
  7447.     set_sensitive(data_file_menu[FileItems::Make].widget,           have_make);
  7448.  
  7449.     set_sensitive(command_file_menu[FileItems::MakeAgain].widget,   have_make);
  7450.     set_sensitive(source_file_menu[FileItems::MakeAgain].widget,    have_make);
  7451.     set_sensitive(data_file_menu[FileItems::MakeAgain].widget,      have_make);
  7452.  
  7453.     bool have_cd = gdb->has_cd_command();
  7454.     set_sensitive(command_file_menu[FileItems::CD].widget,            have_cd);
  7455.     set_sensitive(source_file_menu[FileItems::CD].widget,             have_cd);
  7456.     set_sensitive(data_file_menu[FileItems::CD].widget,               have_cd);
  7457.  
  7458.     bool have_settings = (gdb->type() != XDB && gdb->type() != PYDB);
  7459.     set_sensitive(command_edit_menu[EditItems::Settings].widget,have_settings);
  7460.     set_sensitive(source_edit_menu[EditItems::Settings].widget, have_settings);
  7461.     set_sensitive(data_edit_menu[EditItems::Settings].widget,   have_settings);
  7462.  
  7463.     set_sensitive(complete_w,  gdb->type() == GDB);
  7464.     set_sensitive(define_w,    gdb->type() == GDB);
  7465.     set_sensitive(signals_w,   gdb->type() == GDB);
  7466.  
  7467.     set_sensitive(set_debugger_gdb_w,  have_cmd("gdb"));
  7468.     set_sensitive(set_debugger_dbx_w,  have_cmd("dbx"));
  7469.     set_sensitive(set_debugger_xdb_w,  have_cmd("xdb"));
  7470.     set_sensitive(set_debugger_jdb_w,  have_cmd("jdb"));
  7471.     set_sensitive(set_debugger_pydb_w, have_cmd("pydb"));
  7472.     set_sensitive(set_debugger_perl_w, have_cmd("perl"));
  7473. }
  7474.  
  7475. static void setup_core_limit()
  7476. {
  7477. #if HAVE_GETRLIMIT && HAVE_SETRLIMIT && defined(RLIMIT_CORE)
  7478.     struct rlimit limit;
  7479.     limit.rlim_cur = 1;
  7480.     limit.rlim_max = 1;
  7481.  
  7482.     getrlimit(RLIMIT_CORE, &limit);
  7483.     if (limit.rlim_max > limit.rlim_cur && limit.rlim_max > 0)
  7484.     {
  7485.     string msg;
  7486.  
  7487.     if (limit.rlim_cur <= 0)
  7488.         msg = "Enabling core dumps";
  7489.     else
  7490.         msg = "Raising core file size limit from "
  7491.         + itostring(limit.rlim_cur) + " to "
  7492.         + itostring(limit.rlim_max) + " bytes";
  7493.  
  7494.     StatusDelay delay(msg);
  7495.  
  7496.     limit.rlim_cur = limit.rlim_max;
  7497.     if (setrlimit(RLIMIT_CORE, &limit))
  7498.         delay.outcome = strerror(errno);
  7499.     }
  7500.     else if (limit.rlim_cur <= 0)
  7501.     set_status("Warning: core dumps are disabled");
  7502. #endif // HAVE_GETRLIMIT ...
  7503. }
  7504.