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.
317 lines
8.6 KiB
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"
|