You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kdbg/kdbg/memwindow.cpp

317 lines
8.6 KiB

/*
* Copyright Johannes Sixt
* This file is licensed under the GNU General Public License Version 2.
* See the file COPYING in the toplevel directory of the source directory.
*/
#include "memwindow.h"
#include <tqheader.h>
#include <tdelocale.h>
#include <tdeconfigbase.h>
#include "debugger.h"
class MemoryViewItem : public TQListViewItem
{
public:
MemoryViewItem(TQListView* parent, TQListViewItem* insertAfter, TQString raw, TQString cooked)
: TQListViewItem(parent, insertAfter, raw, cooked) {}
void setChanged(uint pos, bool b) { m_changed[pos] = b; }
protected:
virtual void paintCell(TQPainter* p, const TQColorGroup& cg,
int column, int width, int alignment);
bool m_changed[8];
};
void MemoryViewItem::paintCell(TQPainter* p, const TQColorGroup& cg,
int column, int width, int alignment)
{
if( column > 0 && m_changed[column - 1] ) {
TQColorGroup newcg = cg;
newcg.setColor(TQColorGroup::Text, red);
TQListViewItem::paintCell(p, newcg, column, width, alignment);
} else {
TQListViewItem::paintCell(p, cg, column, width, alignment);
}
}
MemoryWindow::MemoryWindow(TQWidget* parent, const char* name) :
TQWidget(parent, name),
m_debugger(0),
m_expression(true, this, "expression"),
m_memory(this, "memory"),
m_layout(this, 0, 2),
m_format(MDTword | MDThex)
{
TQSize minSize = m_expression.sizeHint();
m_expression.setMinimumSize(minSize);
m_expression.setInsertionPolicy(TQComboBox::NoInsertion);
m_expression.setMaxCount(15);
m_memory.addColumn(i18n("Address"), 80);
m_memory.setSorting(-1); /* don't sort */
m_memory.setAllColumnsShowFocus(true);
m_memory.header()->setClickEnabled(false);
// create layout
m_layout.addWidget(&m_expression, 0);
m_layout.addWidget(&m_memory, 10);
m_layout.activate();
connect(&m_expression, SIGNAL(activated(const TQString&)),
this, SLOT(slotNewExpression(const TQString&)));
// the popup menu
m_popup.insertItem(i18n("B&ytes"), MDTbyte);
m_popup.insertItem(i18n("Halfwords (&2 Bytes)"), MDThalfword);
m_popup.insertItem(i18n("Words (&4 Bytes)"), MDTword);
m_popup.insertItem(i18n("Giantwords (&8 Bytes)"), MDTgiantword);
m_popup.insertSeparator();
m_popup.insertItem(i18n("He&xadecimal"), MDThex);
m_popup.insertItem(i18n("Signed &decimal"), MDTsigned);
m_popup.insertItem(i18n("&Unsigned decimal"), MDTunsigned);
m_popup.insertItem(i18n("&Octal"), MDToctal);
m_popup.insertItem(i18n("&Binary"), MDTbinary);
m_popup.insertItem(i18n("&Addresses"), MDTaddress);
m_popup.insertItem(i18n("&Character"), MDTchar);
m_popup.insertItem(i18n("&Floatingpoint"), MDTfloat);
m_popup.insertItem(i18n("&Strings"), MDTstring);
m_popup.insertItem(i18n("&Instructions"), MDTinsn);
connect(&m_popup, SIGNAL(activated(int)), this, SLOT(slotTypeChange(int)));
/*
* Handle right mouse button. Signal righteButtonClicked cannot be
* used, because it works only over items, not over the blank window.
*/
m_memory.viewport()->installEventFilter(this);
}
MemoryWindow::~MemoryWindow()
{
}
bool MemoryWindow::eventFilter(TQObject*, TQEvent* ev)
{
if (ev->type() == TQEvent::MouseButtonRelease) {
handlePopup(static_cast<TQMouseEvent*>(ev));
return true;
}
return false;
}
void MemoryWindow::handlePopup(TQMouseEvent* ev)
{
if (ev->button() == RightButton)
{
// show popup menu
if (m_popup.isVisible())
{
m_popup.hide();
}
else
{
m_popup.popup(mapToGlobal(ev->pos()));
}
return;
}
}
void MemoryWindow::slotNewExpression(const TQString& newText)
{
TQString text = newText.simplifyWhiteSpace();
// see if the string is in the list
// (note: must count downwards because of removeItem!)
for (int i = m_expression.count()-1; i >= 0; i--)
{
if (m_expression.text(i) == text) {
// yes it is!
// look up the format that was used last time for this expr
TQMap<TQString,unsigned>::iterator pFormat = m_formatCache.find(text);
if (pFormat != m_formatCache.end()) {
m_format = *pFormat;
m_debugger->setMemoryFormat(m_format);
}
// remove this text, will be inserted at the top
m_expression.removeItem(i);
}
}
m_expression.insertItem(text, 0);
if (!text.isEmpty()) {
m_formatCache[text] = m_format;
}
displayNewExpression(text);
}
void MemoryWindow::displayNewExpression(const TQString& expr)
{
m_debugger->setMemoryExpression(expr);
m_expression.setEditText(expr);
// clear memory dump if no dump wanted
if (expr.isEmpty()) {
m_memory.clear();
m_old_memory.clear();
}
}
void MemoryWindow::slotTypeChange(int id)
{
m_old_memory.clear();
// compute new type
if (id & MDTsizemask)
m_format = (m_format & ~MDTsizemask) | id;
if (id & MDTformatmask)
m_format = (m_format & ~MDTformatmask) | id;
m_debugger->setMemoryFormat(m_format);
// change the format in the cache
TQString expr = m_expression.currentText();
m_formatCache[expr.simplifyWhiteSpace()] = m_format;
// force redisplay
displayNewExpression(expr);
}
void MemoryWindow::slotNewMemoryDump(const TQString& msg, const std::list<MemoryDump>& memdump)
{
m_memory.clear();
if (!msg.isEmpty()) {
new TQListViewItem(&m_memory, TQString(), msg);
return;
}
MemoryViewItem* after = 0;
std::list<MemoryDump>::const_iterator md = memdump.begin();
// remove all columns, except the address column
for(int k = m_memory.columns() - 1; k > 0; k--)
m_memory.removeColumn(k);
//add the needed columns
TQStringList sl = TQStringList::split( "\t", md->dump );
for (uint i = 0; i < sl.count(); i++)
m_memory.addColumn("", -1);
TQMap<TQString,TQString> tmpMap;
for (; md != memdump.end(); ++md)
{
TQString addr = md->address.asString() + " " + md->address.fnoffs;
TQStringList sl = TQStringList::split( "\t", md->dump );
// save memory
tmpMap[addr] = md->dump;
after = new MemoryViewItem(&m_memory, after, addr, "");
TQStringList tmplist;
TQMap<TQString,TQString>::Iterator pos = m_old_memory.find( addr );
if( pos != m_old_memory.end() )
tmplist = TQStringList::split( "\t", pos.data() );
for (uint i = 0; i < sl.count(); i++)
{
after->setText( i+1, *sl.at(i) );
bool changed =
tmplist.count() > 0 &&
*sl.at(i) != *tmplist.at(i);
after->setChanged(i, changed);
}
}
m_old_memory.clear();
m_old_memory = tmpMap;
}
static const char MemoryGroup[] = "Memory";
static const char NumExprs[] = "NumExprs";
static const char ExpressionFmt[] = "Expression%d";
static const char FormatFmt[] = "Format%d";
static const char ColumnWidths[] = "ColumnWidths";
void MemoryWindow::saveProgramSpecific(TDEConfigBase* config)
{
TDEConfigGroupSaver s(config, MemoryGroup);
int numEntries = m_expression.count();
config->writeEntry(NumExprs, numEntries);
TQString exprEntry;
TQString fmtEntry;
for (int i = 0; i < numEntries;) {
TQString text = m_expression.text(i);
i++; /* entries are counted 1-based */
exprEntry.sprintf(ExpressionFmt, i);
fmtEntry.sprintf(FormatFmt, i);
config->writeEntry(exprEntry, text);
TQMap<TQString,unsigned>::iterator pFormat = m_formatCache.find(text);
unsigned fmt = pFormat != m_formatCache.end() ? *pFormat : MDTword | MDThex;
config->writeEntry(fmtEntry, fmt);
}
// column widths
TQStrList widths;
TQString wStr;
for (int i = 0; i < 2; i++) {
int w = m_memory.columnWidth(i);
wStr.setNum(w);
widths.append(wStr.latin1());
}
config->writeEntry(ColumnWidths, widths);
}
void MemoryWindow::restoreProgramSpecific(TDEConfigBase* config)
{
TDEConfigGroupSaver s(config, MemoryGroup);
int numEntries = config->readNumEntry(NumExprs, 0);
m_expression.clear();
TQString exprEntry;
TQString fmtEntry;
// entries are counted 1-based
for (int i = 1; i <= numEntries; i++) {
exprEntry.sprintf(ExpressionFmt, i);
fmtEntry.sprintf(FormatFmt, i);
TQString expr = config->readEntry(exprEntry);
unsigned fmt = config->readNumEntry(fmtEntry, MDTword | MDThex);
m_expression.insertItem(expr);
m_formatCache[expr] = fmt & (MDTsizemask | MDTformatmask);
}
// initialize with top expression
if (numEntries > 0) {
m_expression.setCurrentItem(0);
TQString expr = m_expression.text(0);
m_format = m_formatCache[expr];
m_debugger->setMemoryFormat(m_format);
displayNewExpression(expr);
}
// column widths
TQStrList widths;
int n = config->readListEntry(ColumnWidths, widths);
if (n > 2)
n = 2;
for (int i = 0; i < n; i++) {
TQString wStr = widths.at(i);
bool ok;
int w = wStr.toInt(&ok);
if (ok)
m_memory.setColumnWidth(i, w);
}
}
#include "memwindow.moc"