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 / post.C < prev    next >
C/C++ Source or Header  |  1998-12-02  |  11KB  |  417 lines

  1. // $Id: post.C,v 1.49 1998/12/02 13:44:20 zeller Exp $ -*- C++ -*-
  2. // Elementary DDD dialogs
  3.  
  4. // Copyright (C) 1996 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. char post_rcsid[] = 
  30.     "$Id: post.C,v 1.49 1998/12/02 13:44:20 zeller Exp $";
  31.  
  32. #ifdef __GNUG__
  33. #pragma implementation
  34. #endif
  35.  
  36. #include "post.h"
  37.  
  38. #include "AppData.h"
  39. #include "Command.h"
  40. #include "Delay.h"
  41. #include "GDBAgent.h"
  42. #include "HelpCB.h"
  43. #include "TimeOut.h"
  44. #include "assert.h"
  45. #include "charsets.h"
  46. #include "cmdtty.h"
  47. #include "ddd.h"
  48. #include "exit.h"
  49. #include "findParent.h"
  50. #include "session.h"
  51. #include "string-fun.h"
  52. #include "verify.h"
  53. #include "wm.h"
  54.  
  55. #include <Xm/Xm.h>
  56. #include <Xm/AtomMgr.h>
  57. #include <Xm/MessageB.h>
  58. #include <Xm/Protocols.h>
  59.  
  60. #include <signal.h>
  61. #include <unistd.h>
  62. #include <stdlib.h>
  63.  
  64. extern "C" {
  65. #include <sys/types.h>
  66. #include <sys/wait.h>
  67. }
  68.  
  69.  
  70.  
  71. //=============================================================================
  72. // Dialogs
  73. //=============================================================================
  74.  
  75. //-----------------------------------------------------------------------------
  76. // Yes/No dialogs
  77. //-----------------------------------------------------------------------------
  78.  
  79. static Widget yn_dialog;
  80.  
  81. // Issue CLIENT_DATA as command and unmanage YN_DIALOG.
  82. void YnCB(Widget dialog, 
  83.       XtPointer client_data, 
  84.       XtPointer call_data)
  85. {
  86.     gdbCommandCB(dialog, client_data, call_data);
  87.     unpost_gdb_yn();
  88. }
  89.  
  90. Widget post_gdb_yn(string question, Widget w)
  91. {
  92.     strip_trailing_space(question);
  93.     if (question == "")
  94.     return 0;
  95.  
  96.     Arg args[10];
  97.     int arg;
  98.  
  99.     arg = 0;
  100.     MString mquestion = rm(question);
  101.     XtSetArg(args[arg], XmNmessageString, mquestion.xmstring()); arg++;
  102.  
  103.     if (yn_dialog == 0)
  104.     {
  105.     XtSetArg(args[arg], XmNdeleteResponse, XmDO_NOTHING); arg++;
  106.     yn_dialog = verify(XmCreateQuestionDialog(find_shell(w),
  107.                           "yn_dialog", args, arg));
  108.     Delay::register_shell(yn_dialog);
  109.     XtAddCallback (yn_dialog, XmNokCallback,     YnCB, (void *)"yes");
  110.     XtAddCallback (yn_dialog, XmNcancelCallback, YnCB, (void *)"no");
  111.     XtAddCallback (yn_dialog, XmNhelpCallback,   ImmediateHelpCB, 0);
  112.  
  113.     // If the dialog is closed, assume `no'.
  114.     Atom WM_DELETE_WINDOW =
  115.         XmInternAtom(XtDisplay(yn_dialog), "WM_DELETE_WINDOW", False);
  116.     XmAddWMProtocolCallback(XtParent(yn_dialog), WM_DELETE_WINDOW, 
  117.                 YnCB, (caddr_t)"no");
  118.     }
  119.     else
  120.     {
  121.     XtSetValues(yn_dialog, args, arg);
  122.     }
  123.  
  124.     manage_and_raise(yn_dialog);
  125.     return yn_dialog;
  126. }
  127.  
  128. void unpost_gdb_yn()
  129. {
  130.     if (yn_dialog)
  131.     XtUnmanageChild(yn_dialog);
  132. }
  133.  
  134.  
  135. //-----------------------------------------------------------------------------
  136. // GDB is busy
  137. //-----------------------------------------------------------------------------
  138.  
  139. static Widget busy_dialog = 0;
  140.  
  141. Widget post_gdb_busy(Widget w)
  142. {
  143.     if (ddd_is_exiting)
  144.     return 0;
  145.  
  146.     if (busy_dialog == 0)
  147.     {
  148.     busy_dialog = 
  149.         verify(XmCreateWorkingDialog(find_shell(w), "busy_dialog", 
  150.                      NULL, 0));
  151.     Delay::register_shell(busy_dialog);
  152.     XtUnmanageChild(XmMessageBoxGetChild(busy_dialog, 
  153.                          XmDIALOG_CANCEL_BUTTON));
  154.     XtAddCallback(busy_dialog, XmNhelpCallback, ImmediateHelpCB, NULL);
  155.     }
  156.  
  157.     manage_and_raise(busy_dialog);
  158.     return busy_dialog;
  159. }
  160.  
  161. void unpost_gdb_busy()
  162. {
  163.     if (busy_dialog)
  164.     XtUnmanageChild(busy_dialog);
  165. }
  166.  
  167.  
  168. //-----------------------------------------------------------------------------
  169. // GDB terminated abnormally
  170. //-----------------------------------------------------------------------------
  171.  
  172. Widget post_gdb_died(string reason, int state, Widget w)
  173. {
  174.     strip_trailing_space(reason);
  175.  
  176.     int exit_state = EXIT_FAILURE;
  177.     if (WIFEXITED(((state))))
  178.     exit_state = WEXITSTATUS(((state)));
  179.  
  180.     bool exited = (exit_state == EXIT_SUCCESS || reason.contains("Exit 0"));
  181.  
  182.     if (gdb_initialized && gdb_is_exiting && exited)
  183.     {
  184.     // Exit was expected
  185.     _DDDExitCB(find_shell(w), XtPointer(EXIT_SUCCESS), 0);
  186.     return 0;
  187.     }
  188.  
  189.     if (ddd_is_exiting)
  190.     {
  191.     // GDB would not die
  192.     cerr << reason << "\n";
  193.     return 0;
  194.     }
  195.  
  196.     Arg args[10];
  197.     int arg;
  198.  
  199.     Widget dialog = 0;
  200.     Widget shell = find_shell(w);
  201.     if (gdb_initialized)
  202.     {
  203.     String name;
  204.     MString msg;
  205.  
  206.     if (gdb->has_exec_files() && exited)
  207.     {
  208.         // In GDB, DBX, and XDB, a sudden exit is probably an error.
  209.         msg = rm(gdb->title() + " suddenly exited.");
  210.         name = "exited_dialog";
  211.     }
  212.     else if (exited)
  213.     {
  214.         // In Perl, PYDB, and JDB, the debugger dies with the program.
  215.         _gdb_out("\n" + reason + "\n");
  216.  
  217.         msg = rm("The program terminated (" + reason + ")");
  218.         name = "done_dialog";
  219.     }
  220.     else
  221.     {
  222.         _gdb_out("\n" + reason + "\n");
  223.  
  224.         // Abnormal exits are always errors.
  225.         msg = rm(gdb->title() + " terminated abnormally (" + reason + ")");
  226.         name = "terminated_dialog";
  227.     }
  228.  
  229.     arg = 0;
  230.     XtSetArg(args[arg], XmNmessageString, msg.xmstring()); arg++;
  231.     if (exited)
  232.         dialog = verify(XmCreateWarningDialog(shell, name, args, arg));
  233.     else
  234.         dialog = verify(XmCreateErrorDialog(shell, name, args, arg));
  235.  
  236.     XtAddCallback(dialog, XmNhelpCallback,   ImmediateHelpCB, NULL);
  237.     XtAddCallback(dialog, XmNokCallback,     RestartDebuggerCB, NULL);
  238.     XtAddCallback(dialog, XmNcancelCallback, 
  239.               DDDExitCB, XtPointer(exit_state));
  240.     }
  241.     else
  242.     {
  243.     arg = 0;
  244.     MString msg = rm(gdb->title() + " could not be started.");
  245.     XtSetArg(args[arg], XmNmessageString, msg.xmstring()); arg++;
  246.     dialog = verify(XmCreateErrorDialog(shell, "no_debugger_dialog", 
  247.                         args, arg));
  248.     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
  249.     XtAddCallback(dialog, XmNhelpCallback, ImmediateHelpCB, NULL);
  250.     XtAddCallback(dialog, XmNokCallback, DDDExitCB, XtPointer(exit_state));
  251.     }
  252.  
  253.     Delay::register_shell(dialog);
  254.     manage_and_raise(dialog);
  255.     return dialog;
  256. }
  257.  
  258.  
  259. //-----------------------------------------------------------------------------
  260. // GDB issued a message
  261. //-----------------------------------------------------------------------------
  262.  
  263. struct PostInfo {
  264.     string text;
  265.     bool prompt;
  266.  
  267.     PostInfo(const string& t, bool p)
  268.     : text(t), prompt(p)
  269.     {}
  270. };
  271.  
  272. static void GDBOutCB(XtPointer client_data, XtIntervalId *)
  273. {
  274.     PostInfo *info = (PostInfo *)client_data;
  275.     if (info->text != "")
  276.     {
  277.     gdb_out("\r" + info->text + "\n");
  278.     if (info->prompt)
  279.         prompt();
  280.     }
  281.  
  282.     delete info;
  283. }
  284.  
  285. Widget post_gdb_message(string text, bool prompt, Widget w)
  286. {
  287.     strip_trailing_space(text);
  288.     if (text == NO_GDB_ANSWER || text == "")
  289.     return 0;
  290.  
  291.     if (ddd_is_exiting)
  292.     {
  293.     if (text != "")
  294.         cerr << ddd_NAME << ": " << text << "\n";
  295.     return 0;
  296.     }
  297.  
  298.     if (gdb->isReadyWithPrompt())
  299.     {
  300.     // We don't output this immediately, because we might be in a
  301.     // private input state (private_gdb_input or tty_gdb_input
  302.     // might be set)
  303.     PostInfo *info = new PostInfo(text, prompt);
  304.     XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 0,
  305.             GDBOutCB, XtPointer(info));
  306.     return 0;
  307.     }
  308.  
  309.     Arg args[10];
  310.     int arg = 0;
  311.  
  312.     MString mtext = rm(text);
  313.     XtSetArg(args[arg], XmNmessageString, mtext.xmstring()); arg++;
  314.  
  315.     static Widget gdb_message_dialog = 0;
  316.     if (gdb_message_dialog == 0)
  317.     {
  318.     gdb_message_dialog = 
  319.         verify(XmCreateWarningDialog(find_shell(w), "gdb_message_dialog",
  320.                      args, arg));
  321.     Delay::register_shell(gdb_message_dialog);
  322.     XtUnmanageChild(XmMessageBoxGetChild(gdb_message_dialog, 
  323.                          XmDIALOG_CANCEL_BUTTON));
  324.     XtAddCallback(gdb_message_dialog, XmNhelpCallback, 
  325.               ImmediateHelpCB, NULL);
  326.     }
  327.     else
  328.     {
  329.     XtSetValues(gdb_message_dialog, args, arg);
  330.     }
  331.  
  332.     manage_and_raise(gdb_message_dialog);
  333.     return gdb_message_dialog;
  334. }
  335.  
  336.  
  337. //-----------------------------------------------------------------------------
  338. // DDD errors
  339. //-----------------------------------------------------------------------------
  340.  
  341. Widget post_error(string text, String name, Widget w)
  342. {
  343.     strip_trailing_space(text);
  344.     if (ddd_is_exiting)
  345.     {
  346.     cerr << ddd_NAME << ": " << text << "\n";
  347.     return 0;
  348.     }
  349.  
  350. #if 0
  351.     if (status_w && !text.contains('\n'))
  352.     {
  353.     set_status(text);
  354.     return 0;
  355.     }
  356. #endif
  357.  
  358.     if (name == 0)
  359.     name = "ddd_error";
  360.  
  361.     Arg args[10];
  362.     int arg = 0;
  363.  
  364.     MString mtext = rm(text);
  365.     XtSetArg(args[arg], XmNmessageString, mtext.xmstring()); arg++;
  366.  
  367.     Widget ddd_error = 
  368.     verify(XmCreateErrorDialog(find_shell(w), name, args, arg));
  369.     Delay::register_shell(ddd_error);
  370.     XtUnmanageChild(XmMessageBoxGetChild(ddd_error, XmDIALOG_CANCEL_BUTTON));
  371.     XtAddCallback(ddd_error, XmNhelpCallback, ImmediateHelpCB, NULL);
  372.  
  373.     manage_and_raise(ddd_error);
  374.     return ddd_error;
  375. }
  376.  
  377.  
  378. //-----------------------------------------------------------------------------
  379. // DDD warnings
  380. //-----------------------------------------------------------------------------
  381.  
  382. Widget post_warning(string text, String name, Widget w)
  383. {
  384.     strip_trailing_space(text);
  385.     if (ddd_is_exiting)
  386.     {
  387.     cerr << ddd_NAME << ": warning: " << text << "\n";
  388.     return 0;
  389.     }
  390.  
  391. #if 0
  392.     if (status_w && !text.contains('\n'))
  393.     {
  394.     set_status(text);
  395.     return 0;
  396.     }
  397. #endif
  398.  
  399.     if (name == 0)
  400.     name = "ddd_warning";
  401.  
  402.     Arg args[10];
  403.     int arg = 0;
  404.  
  405.     MString mtext = rm(text);
  406.     XtSetArg(args[arg], XmNmessageString, mtext.xmstring()); arg++;
  407.  
  408.     Widget ddd_warning = 
  409.     verify(XmCreateWarningDialog(find_shell(w), name, args, arg));
  410.     Delay::register_shell(ddd_warning);
  411.     XtUnmanageChild(XmMessageBoxGetChild(ddd_warning, XmDIALOG_CANCEL_BUTTON));
  412.     XtAddCallback(ddd_warning, XmNhelpCallback, ImmediateHelpCB, NULL);
  413.  
  414.     manage_and_raise(ddd_warning);
  415.     return ddd_warning;
  416. }
  417.