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 / DispNode.C < prev    next >
C/C++ Source or Header  |  1998-10-25  |  10KB  |  462 lines

  1. // $Id: DispNode.C,v 1.50 1998/10/25 20:29:03 zeller Exp $
  2. // Store information about a single display espression
  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 DispNode_rcsid[] =
  31.     "$Id: DispNode.C,v 1.50 1998/10/25 20:29:03 zeller Exp $";
  32.  
  33. #ifdef __GNUG__
  34. #pragma implementation
  35. #endif
  36.  
  37.  
  38. //-----------------------------------------------------------------------------
  39. // A DispNode keeps all information about a single data display
  40. //-----------------------------------------------------------------------------
  41.  
  42. #include "DispNode.h"
  43.  
  44. #include "cook.h"
  45. #include "AppData.h"
  46. #include "CompositeB.h"
  47. #include "DispValue.h"
  48. #include "DispBox.h"
  49. #include "AliasGE.h"
  50.  
  51. #ifndef KEEP_CLUSTERED_DISPLAYS
  52. #define KEEP_CLUSTERED_DISPLAYS 0
  53. #endif
  54.  
  55. DEFINE_TYPE_INFO_1(DispNode, BoxGraphNode)
  56.  
  57. // Data
  58. HandlerList DispNode::handlers(DispNode_NTypes);
  59.  
  60. int DispNode::tics = 0;
  61.  
  62. // Constructor
  63. DispNode::DispNode (int disp_nr,
  64.             const string& name,
  65.             const string& scope,
  66.             const string& val,
  67.             bool pl)
  68.     : BoxGraphNode(),
  69.       mydisp_nr(disp_nr),
  70.       myname(name),
  71.       myaddr(""),
  72.       myscope(scope),
  73.       mydepends_on(""),
  74.       myactive(true),
  75.       saved_node_hidden(false),
  76.       mydeferred(false),
  77.       myclustered(false),
  78.       myplotted(pl),
  79.       myconstant(false),
  80.       disp_value(0),
  81.       myselected_value(0),
  82.       disp_box(0),
  83.       mylast_change(++tics),
  84.       mylast_refresh(++tics),
  85.       alias_of(0)
  86. {
  87.     if (val != "")
  88.     {
  89.     string v = val;
  90.     disp_value = DispValue::parse(v, myname);
  91.     set_addr(disp_value->addr());
  92.     }
  93.  
  94.     if (plotted() && value() != 0)
  95.     {
  96.     // No need to show all detail; it is plotted, anyway
  97.     value()->collapse();
  98.     }
  99.     
  100.     // Create new box from DISP_VALUE
  101.     disp_box = new DispBox (mydisp_nr, myname, disp_value);
  102.  
  103.     // Set the box
  104.     setBox(disp_box->box());
  105. }
  106.  
  107. // Destructor
  108. DispNode::~DispNode()
  109. {
  110.     if (disp_value != 0)
  111.     {
  112.     disp_value->unlink();
  113.     disp_value = 0;
  114.     }
  115.  
  116.     delete disp_box;
  117. }
  118.  
  119. // User-defined displays (status displays)
  120.  
  121. // Return user command from S
  122. string user_command(const string& s)
  123. {
  124.     if (is_user_command(s))
  125.     return _unquote(s);
  126.     else
  127.     return "";
  128. }
  129.  
  130. // Add event handler
  131. void DispNode::addHandler (unsigned    type,
  132.                HandlerProc proc,
  133.                void*       client_data)
  134. {
  135.     DispNode::handlers.add(type, proc, client_data);
  136. }
  137.  
  138. // Remove event handler
  139. void DispNode::removeHandler (unsigned    type,
  140.                   HandlerProc proc,
  141.                   void        *client_data)
  142. {
  143.     DispNode::handlers.remove(type, proc, client_data);
  144. }
  145.  
  146.  
  147. // Update with VALUE;  return false if value is unchanged
  148. bool DispNode::update(string& value)
  149. {
  150.     bool changed = false;
  151.     bool inited  = false;
  152.  
  153.     if (disabled()) 
  154.     { 
  155.     // Display has been enabled (automatically)
  156.     enable();
  157.     changed = true;
  158.     }
  159.  
  160.     if (disp_value == 0)
  161.     { 
  162.     // We have not read a value yet
  163.     disp_value = DispValue::parse(value, myname);
  164.     set_addr(disp_value->addr());
  165.     changed = true;
  166.     }
  167.     else
  168.     {
  169.     // Update existing value
  170.     disp_value = disp_value->update(value, changed, inited);
  171.     if (disp_value->addr() != "" && addr() != disp_value->addr())
  172.     {
  173.         set_addr(disp_value->addr());
  174.         changed = true;
  175.     }
  176.     }
  177.  
  178.     if (inited)
  179.     {
  180.     // We were reinitialized: disable old selection
  181.     select(0);
  182.     }
  183.     
  184.     if (changed)
  185.     {
  186.     disp_box->set_value(disp_value);
  187.  
  188.     // Set new box
  189.     setBox(disp_box->box());
  190.     }
  191.  
  192.     if (changed || inited)
  193.     {
  194.     // mylast_change = ++tics;
  195.     mylast_refresh = ++tics;
  196. #if 0
  197.     clog << "Display " << disp_nr() << " changed"
  198.          << " (" << mylast_change << ")\n";
  199. #endif
  200.     }
  201.  
  202.     return changed;
  203. }
  204.  
  205.  
  206. // Re-create box from current disp_value
  207. void DispNode::refresh()
  208. {
  209.     disp_box->set_value(disp_value);
  210.     setBox(disp_box->box());
  211.     select(selected_value());
  212.     refresh_plot_state();
  213.  
  214.     mylast_refresh = ++tics;
  215. }
  216.  
  217. // In BOX, find outermost TagBox for given DispValue DV
  218. TagBox *DispNode::findTagBox(const Box *box, DispValue *dv)
  219. {
  220.     TagBox *tb = ptr_cast(TagBox, (Box *)box);
  221.     if (tb && tb->__data() == (void *)dv)
  222.     return tb;
  223.  
  224.     HatBox *hb = ptr_cast(HatBox, (Box *)box);
  225.     if (hb)
  226.     return findTagBox(hb->box(), dv);
  227.  
  228.     CompositeBox *cb = ptr_cast(CompositeBox, (Box *)box);
  229.     if (cb)
  230.     {
  231.     for (int i = 0; i < cb->nchildren(); i++)
  232.     {
  233.         Box *child = (*cb)[i];
  234.         TagBox *tb = findTagBox(child, dv);
  235.         if (tb)
  236.         return tb;
  237.     }
  238.     }
  239.  
  240.     return 0;
  241. }
  242.  
  243. // Highlights the box related to the display value DV
  244. void DispNode::select(DispValue *dv)
  245. {
  246.     TagBox *tb = 0;
  247.     if (dv != 0)
  248.     tb = findTagBox(box(), dv);
  249.  
  250.     setHighlight(tb);
  251.     myselected_value = dv;
  252. }
  253.  
  254. // Copy selection state from SRC
  255. void DispNode::copy_selection_state(const DispNode& src)
  256. {
  257.     if (value() != 0 && src.value() != 0 && src.selected_value() != 0)
  258.     {
  259.     const DispValue *descendant = 0;
  260.     bool eq = value()->structurally_equal(src.value(), 
  261.                           src.selected_value(),
  262.                           descendant);
  263.     if (eq)
  264.         select((DispValue *)descendant);
  265.     return;
  266.     }
  267.  
  268.     // Don't care - just select it all
  269.     select(0);
  270. }
  271.  
  272. // Set up plot state
  273. void DispNode::refresh_plot_state() const
  274. {
  275.     if (value() == 0)
  276.     return;
  277.  
  278.     if (disabled())
  279.     value()->set_plot_state("Disabled");
  280.     else if (!active())
  281.     value()->set_plot_state("Not active");
  282.     else
  283.     value()->set_plot_state();
  284. }
  285.  
  286. // Disable display
  287. void DispNode::disable()
  288. {
  289.     if (value() == 0 || disabled())
  290.     return;
  291.  
  292.     value()->enabled() = false;
  293.     handlers.call(DispNode_Disabled, this, (void *)true);
  294.     refresh();
  295. }
  296.  
  297. // Enable display
  298. void DispNode::enable()
  299. {
  300.     if (value() == 0 || enabled())
  301.     return;
  302.  
  303.     value()->enabled() = true;
  304.     handlers.call(DispNode_Disabled, this, (void *)false);
  305.     refresh();
  306. }
  307.  
  308. // Hide display
  309. void DispNode::make_inactive()
  310. {
  311.     if (active())
  312.     {
  313.     if (!clustered())
  314.     {
  315.         saved_node_hidden = hidden();
  316.         hidden() = true;
  317.     }
  318.     myactive = false;
  319.  
  320.     mylast_refresh = ++tics;
  321.  
  322.     refresh_plot_state();
  323.     }
  324.  
  325.     // Unselect it
  326.     selected() = false;
  327. }
  328.  
  329. // Show display
  330. void DispNode::make_active()
  331. {
  332.     if (!active())
  333.     {
  334.     myactive = true;
  335.     if (!clustered())
  336.         hidden() = saved_node_hidden;
  337.  
  338.     mylast_refresh = ++tics;
  339.  
  340.     refresh_plot_state();
  341.     }
  342. }
  343.  
  344. // Cluster display into TARGET
  345. void DispNode::cluster(int target)
  346. {
  347.     if (target != 0)
  348.     {
  349.     if (clustered() == 0)
  350.         saved_node_hidden = hidden();
  351.  
  352. #if KEEP_CLUSTERED_DISPLAYS
  353.     // Don't hide clustered displays
  354. #else
  355.     hidden() = true;
  356. #endif
  357.     }
  358.     else // target == 0
  359.     {
  360.     if (clustered() != 0)
  361.         hidden() = saved_node_hidden;
  362.     }
  363.  
  364.     // Set new target
  365.     myclustered = target;
  366.  
  367.     // Unselect it
  368.     selected() = false;
  369.  
  370.     // Mark as changed
  371.     mylast_refresh = ++tics;
  372. }
  373.  
  374. // Update address with NEW_ADDR
  375. void DispNode::set_addr(const string& new_addr)
  376. {
  377.     if (myaddr != new_addr)
  378.     {
  379.     myaddr = new_addr;
  380.     // mylast_change = ++tics;
  381. #if 0
  382.     clog << "Display " << disp_nr() << " changed"
  383.          << " (" << mylast_change << ")\n";
  384. #endif
  385.     }
  386. }
  387.  
  388. // Return `true' if this expression can be aliased.
  389. bool DispNode::alias_ok() const
  390. {
  391.     // We avoid merging displays that are derived from other displays,
  392.     // such as `/FMT EXPR' or `(TYPE) EXPR'.
  393.     return !is_user_command()
  394.     && !name().contains('/', 0) 
  395.     && !name().contains('(', 0);
  396. }
  397.  
  398. // Toggle titles.  Return true if changed.
  399. bool DispNode::set_title(bool set)
  400. {
  401.     bool changed = false;
  402.     if (set && !disp_box->have_title())
  403.     {
  404.     // Add title
  405.     disp_box->set_title(mydisp_nr, myname);
  406.     changed = true;
  407.     }
  408.     else if (!set && disp_box->have_title())
  409.     {
  410.     // Remove title
  411.     disp_box->set_title(mydisp_nr, "");
  412.     changed = true;
  413.     }
  414.  
  415.     if (changed)
  416.     {
  417.     // Set value again
  418.     disp_box->set_value(disp_value);
  419.  
  420.     // Show new box
  421.     setBox(disp_box->box());
  422.     }
  423.  
  424.     return changed;
  425. }
  426.  
  427. // Duplication
  428. DispNode::DispNode(const DispNode& node)
  429.     : BoxGraphNode(node),
  430.       mydisp_nr(node.disp_nr()),
  431.       myname(node.name()),
  432.       myaddr(node.addr()),
  433.       myscope(node.scope()),
  434.       mydepends_on(node.mydepends_on),
  435.       myactive(node.active()),
  436.       saved_node_hidden(node.saved_node_hidden),
  437.       mydeferred(node.deferred()),
  438.       myclustered(node.clustered()),
  439.       myplotted(node.plotted()),
  440.       myconstant(node.constant()),
  441.       disp_value(node.value() ? node.value()->dup() : 0),
  442.       myselected_value(0),
  443.       disp_box(node.disp_box ? node.disp_box->dup() : 0),
  444.       mylast_change(node.last_change()),
  445.       mylast_refresh(node.last_refresh()),
  446.       alias_of(node.alias_of)
  447. {
  448.     setBox(disp_box->box());
  449.     copy_selection_state(node);
  450. }
  451.  
  452. // Plotting
  453.  
  454. // Print plots to FILENAME
  455. void DispNode::print_plots(const string& filename, const GraphGC& gc) const
  456. {
  457.     if (gc.printSelectedNodesOnly && selected_value() != 0)
  458.     selected_value()->print_plots(filename, *gc.printGC);
  459.     else if (value() != 0)
  460.     value()->print_plots(filename, *gc.printGC);
  461. }
  462.