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 >
Wrap
C/C++ Source or Header
|
1998-10-25
|
10KB
|
462 lines
// $Id: DispNode.C,v 1.50 1998/10/25 20:29:03 zeller Exp $
// Store information about a single display espression
// Copyright (C) 1995-1998 Technische Universitaet Braunschweig, Germany.
// Written by Dorothea Luetkehaus <luetke@ips.cs.tu-bs.de>
// and Andreas Zeller <zeller@ips.cs.tu-bs.de>
//
// This file is part of DDD.
//
// DDD is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// DDD is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with DDD -- see the file COPYING.
// If not, write to the Free Software Foundation, Inc.,
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// DDD is the data display debugger.
// For details, see the DDD World-Wide-Web page,
// `http://www.cs.tu-bs.de/softech/ddd/',
// or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
char DispNode_rcsid[] =
"$Id: DispNode.C,v 1.50 1998/10/25 20:29:03 zeller Exp $";
#ifdef __GNUG__
#pragma implementation
#endif
//-----------------------------------------------------------------------------
// A DispNode keeps all information about a single data display
//-----------------------------------------------------------------------------
#include "DispNode.h"
#include "cook.h"
#include "AppData.h"
#include "CompositeB.h"
#include "DispValue.h"
#include "DispBox.h"
#include "AliasGE.h"
#ifndef KEEP_CLUSTERED_DISPLAYS
#define KEEP_CLUSTERED_DISPLAYS 0
#endif
DEFINE_TYPE_INFO_1(DispNode, BoxGraphNode)
// Data
HandlerList DispNode::handlers(DispNode_NTypes);
int DispNode::tics = 0;
// Constructor
DispNode::DispNode (int disp_nr,
const string& name,
const string& scope,
const string& val,
bool pl)
: BoxGraphNode(),
mydisp_nr(disp_nr),
myname(name),
myaddr(""),
myscope(scope),
mydepends_on(""),
myactive(true),
saved_node_hidden(false),
mydeferred(false),
myclustered(false),
myplotted(pl),
myconstant(false),
disp_value(0),
myselected_value(0),
disp_box(0),
mylast_change(++tics),
mylast_refresh(++tics),
alias_of(0)
{
if (val != "")
{
string v = val;
disp_value = DispValue::parse(v, myname);
set_addr(disp_value->addr());
}
if (plotted() && value() != 0)
{
// No need to show all detail; it is plotted, anyway
value()->collapse();
}
// Create new box from DISP_VALUE
disp_box = new DispBox (mydisp_nr, myname, disp_value);
// Set the box
setBox(disp_box->box());
}
// Destructor
DispNode::~DispNode()
{
if (disp_value != 0)
{
disp_value->unlink();
disp_value = 0;
}
delete disp_box;
}
// User-defined displays (status displays)
// Return user command from S
string user_command(const string& s)
{
if (is_user_command(s))
return _unquote(s);
else
return "";
}
// Add event handler
void DispNode::addHandler (unsigned type,
HandlerProc proc,
void* client_data)
{
DispNode::handlers.add(type, proc, client_data);
}
// Remove event handler
void DispNode::removeHandler (unsigned type,
HandlerProc proc,
void *client_data)
{
DispNode::handlers.remove(type, proc, client_data);
}
// Update with VALUE; return false if value is unchanged
bool DispNode::update(string& value)
{
bool changed = false;
bool inited = false;
if (disabled())
{
// Display has been enabled (automatically)
enable();
changed = true;
}
if (disp_value == 0)
{
// We have not read a value yet
disp_value = DispValue::parse(value, myname);
set_addr(disp_value->addr());
changed = true;
}
else
{
// Update existing value
disp_value = disp_value->update(value, changed, inited);
if (disp_value->addr() != "" && addr() != disp_value->addr())
{
set_addr(disp_value->addr());
changed = true;
}
}
if (inited)
{
// We were reinitialized: disable old selection
select(0);
}
if (changed)
{
disp_box->set_value(disp_value);
// Set new box
setBox(disp_box->box());
}
if (changed || inited)
{
// mylast_change = ++tics;
mylast_refresh = ++tics;
#if 0
clog << "Display " << disp_nr() << " changed"
<< " (" << mylast_change << ")\n";
#endif
}
return changed;
}
// Re-create box from current disp_value
void DispNode::refresh()
{
disp_box->set_value(disp_value);
setBox(disp_box->box());
select(selected_value());
refresh_plot_state();
mylast_refresh = ++tics;
}
// In BOX, find outermost TagBox for given DispValue DV
TagBox *DispNode::findTagBox(const Box *box, DispValue *dv)
{
TagBox *tb = ptr_cast(TagBox, (Box *)box);
if (tb && tb->__data() == (void *)dv)
return tb;
HatBox *hb = ptr_cast(HatBox, (Box *)box);
if (hb)
return findTagBox(hb->box(), dv);
CompositeBox *cb = ptr_cast(CompositeBox, (Box *)box);
if (cb)
{
for (int i = 0; i < cb->nchildren(); i++)
{
Box *child = (*cb)[i];
TagBox *tb = findTagBox(child, dv);
if (tb)
return tb;
}
}
return 0;
}
// Highlights the box related to the display value DV
void DispNode::select(DispValue *dv)
{
TagBox *tb = 0;
if (dv != 0)
tb = findTagBox(box(), dv);
setHighlight(tb);
myselected_value = dv;
}
// Copy selection state from SRC
void DispNode::copy_selection_state(const DispNode& src)
{
if (value() != 0 && src.value() != 0 && src.selected_value() != 0)
{
const DispValue *descendant = 0;
bool eq = value()->structurally_equal(src.value(),
src.selected_value(),
descendant);
if (eq)
select((DispValue *)descendant);
return;
}
// Don't care - just select it all
select(0);
}
// Set up plot state
void DispNode::refresh_plot_state() const
{
if (value() == 0)
return;
if (disabled())
value()->set_plot_state("Disabled");
else if (!active())
value()->set_plot_state("Not active");
else
value()->set_plot_state();
}
// Disable display
void DispNode::disable()
{
if (value() == 0 || disabled())
return;
value()->enabled() = false;
handlers.call(DispNode_Disabled, this, (void *)true);
refresh();
}
// Enable display
void DispNode::enable()
{
if (value() == 0 || enabled())
return;
value()->enabled() = true;
handlers.call(DispNode_Disabled, this, (void *)false);
refresh();
}
// Hide display
void DispNode::make_inactive()
{
if (active())
{
if (!clustered())
{
saved_node_hidden = hidden();
hidden() = true;
}
myactive = false;
mylast_refresh = ++tics;
refresh_plot_state();
}
// Unselect it
selected() = false;
}
// Show display
void DispNode::make_active()
{
if (!active())
{
myactive = true;
if (!clustered())
hidden() = saved_node_hidden;
mylast_refresh = ++tics;
refresh_plot_state();
}
}
// Cluster display into TARGET
void DispNode::cluster(int target)
{
if (target != 0)
{
if (clustered() == 0)
saved_node_hidden = hidden();
#if KEEP_CLUSTERED_DISPLAYS
// Don't hide clustered displays
#else
hidden() = true;
#endif
}
else // target == 0
{
if (clustered() != 0)
hidden() = saved_node_hidden;
}
// Set new target
myclustered = target;
// Unselect it
selected() = false;
// Mark as changed
mylast_refresh = ++tics;
}
// Update address with NEW_ADDR
void DispNode::set_addr(const string& new_addr)
{
if (myaddr != new_addr)
{
myaddr = new_addr;
// mylast_change = ++tics;
#if 0
clog << "Display " << disp_nr() << " changed"
<< " (" << mylast_change << ")\n";
#endif
}
}
// Return `true' if this expression can be aliased.
bool DispNode::alias_ok() const
{
// We avoid merging displays that are derived from other displays,
// such as `/FMT EXPR' or `(TYPE) EXPR'.
return !is_user_command()
&& !name().contains('/', 0)
&& !name().contains('(', 0);
}
// Toggle titles. Return true if changed.
bool DispNode::set_title(bool set)
{
bool changed = false;
if (set && !disp_box->have_title())
{
// Add title
disp_box->set_title(mydisp_nr, myname);
changed = true;
}
else if (!set && disp_box->have_title())
{
// Remove title
disp_box->set_title(mydisp_nr, "");
changed = true;
}
if (changed)
{
// Set value again
disp_box->set_value(disp_value);
// Show new box
setBox(disp_box->box());
}
return changed;
}
// Duplication
DispNode::DispNode(const DispNode& node)
: BoxGraphNode(node),
mydisp_nr(node.disp_nr()),
myname(node.name()),
myaddr(node.addr()),
myscope(node.scope()),
mydepends_on(node.mydepends_on),
myactive(node.active()),
saved_node_hidden(node.saved_node_hidden),
mydeferred(node.deferred()),
myclustered(node.clustered()),
myplotted(node.plotted()),
myconstant(node.constant()),
disp_value(node.value() ? node.value()->dup() : 0),
myselected_value(0),
disp_box(node.disp_box ? node.disp_box->dup() : 0),
mylast_change(node.last_change()),
mylast_refresh(node.last_refresh()),
alias_of(node.alias_of)
{
setBox(disp_box->box());
copy_selection_state(node);
}
// Plotting
// Print plots to FILENAME
void DispNode::print_plots(const string& filename, const GraphGC& gc) const
{
if (gc.printSelectedNodesOnly && selected_value() != 0)
selected_value()->print_plots(filename, *gc.printGC);
else if (value() != 0)
value()->print_plots(filename, *gc.printGC);
}