3 // Copyright by Johannes Sixt
4 // This file is under GPL, the GNU General Public Licence
9 #include <kconfigbase.h>
11 #include "dbgdriver.h" /* memory dump formats */
14 class MemoryViewItem
: public QListViewItem
17 MemoryViewItem(QListView
* parent
, QListViewItem
* insertAfter
, QString raw
, QString cooked
)
18 : QListViewItem(parent
, insertAfter
, raw
, cooked
), m_changed(8) {}
20 void setChanged(uint pos
, bool b
) { m_changed
[pos
] = b
; }
23 virtual void paintCell(QPainter
* p
, const QColorGroup
& cg
,
24 int column
, int width
, int alignment
);
26 QArray
<bool> m_changed
;
29 void MemoryViewItem::paintCell(QPainter
* p
, const QColorGroup
& cg
,
30 int column
, int width
, int alignment
)
32 if( column
> 0 && m_changed
[column
- 1] ) {
33 QColorGroup newcg
= cg
;
34 newcg
.setColor(QColorGroup::Text
, red
);
35 QListViewItem::paintCell(p
, newcg
, column
, width
, alignment
);
37 QListViewItem::paintCell(p
, cg
, column
, width
, alignment
);
42 MemoryWindow::MemoryWindow(QWidget
* parent
, const char* name
) :
43 QWidget(parent
, name
),
45 m_expression(true, this, "expression"),
46 m_memory(this, "memory"),
48 m_format(MDTword
| MDThex
)
50 QSize minSize
= m_expression
.sizeHint();
51 m_expression
.setMinimumSize(minSize
);
52 m_expression
.setInsertionPolicy(QComboBox::NoInsertion
);
53 m_expression
.setMaxCount(15);
55 m_memory
.addColumn(i18n("Address"), 80);
57 m_memory
.setSorting(-1); /* don't sort */
58 m_memory
.setAllColumnsShowFocus(true);
59 m_memory
.header()->setClickEnabled(false);
62 m_layout
.addWidget(&m_expression
, 0);
63 m_layout
.addWidget(&m_memory
, 10);
66 connect(&m_expression
, SIGNAL(activated(const QString
&)),
67 this, SLOT(slotNewExpression(const QString
&)));
70 m_popup
.insertItem(i18n("B&ytes"), MDTbyte
);
71 m_popup
.insertItem(i18n("Halfwords (&2 Bytes)"), MDThalfword
);
72 m_popup
.insertItem(i18n("Words (&4 Bytes)"), MDTword
);
73 m_popup
.insertItem(i18n("Giantwords (&8 Bytes)"), MDTgiantword
);
74 m_popup
.insertSeparator();
75 m_popup
.insertItem(i18n("He&xadecimal"), MDThex
);
76 m_popup
.insertItem(i18n("Signed &decimal"), MDTsigned
);
77 m_popup
.insertItem(i18n("&Unsigned decimal"), MDTunsigned
);
78 m_popup
.insertItem(i18n("&Octal"), MDToctal
);
79 m_popup
.insertItem(i18n("&Binary"), MDTbinary
);
80 m_popup
.insertItem(i18n("&Addresses"), MDTaddress
);
81 m_popup
.insertItem(i18n("&Character"), MDTchar
);
82 m_popup
.insertItem(i18n("&Floatingpoint"), MDTfloat
);
83 m_popup
.insertItem(i18n("&Strings"), MDTstring
);
84 m_popup
.insertItem(i18n("&Instructions"), MDTinsn
);
85 connect(&m_popup
, SIGNAL(activated(int)), this, SLOT(slotTypeChange(int)));
88 * Handle right mouse button. Signal righteButtonClicked cannot be
89 * used, because it works only over items, not over the blank window.
91 m_memory
.viewport()->installEventFilter(this);
93 m_formatCache
.setAutoDelete(true);
96 MemoryWindow::~MemoryWindow()
100 bool MemoryWindow::eventFilter(QObject
*, QEvent
* ev
)
102 if (ev
->type() == QEvent::MouseButtonRelease
) {
103 handlePopup(static_cast<QMouseEvent
*>(ev
));
109 void MemoryWindow::handlePopup(QMouseEvent
* ev
)
111 if (ev
->button() == RightButton
)
114 if (m_popup
.isVisible())
120 m_popup
.popup(mapToGlobal(ev
->pos()));
126 void MemoryWindow::slotNewExpression(const QString
& newText
)
128 QString text
= newText
.simplifyWhiteSpace();
130 // see if the string is in the list
131 // (note: must count downwards because of removeItem!)
132 for (int i
= m_expression
.count()-1; i
>= 0; i
--)
134 if (m_expression
.text(i
) == text
) {
136 // look up the format that was used last time for this expr
137 unsigned* pFormat
= m_formatCache
[text
];
140 m_debugger
->setMemoryFormat(m_format
);
142 // remove this text, will be inserted at the top
143 m_expression
.removeItem(i
);
146 m_expression
.insertItem(text
, 0);
148 if (text
.isEmpty()) {
149 // if format was not in the cache, insert it
150 if (m_formatCache
[text
] == 0) {
151 m_formatCache
.insert(text
, new unsigned(m_format
));
156 displayNewExpression(text
);
159 void MemoryWindow::displayNewExpression(const QString
& expr
)
161 m_debugger
->setMemoryExpression(expr
);
162 m_expression
.setEditText(expr
);
164 // clear memory dump if no dump wanted
165 if (expr
.isEmpty()) {
167 m_old_memory
.clear();
171 void MemoryWindow::slotTypeChange(int id
)
173 m_old_memory
.clear();
176 if (id
& MDTsizemask
)
177 m_format
= (m_format
& ~MDTsizemask
) | id
;
178 if (id
& MDTformatmask
)
179 m_format
= (m_format
& ~MDTformatmask
) | id
;
180 m_debugger
->setMemoryFormat(m_format
);
182 // change the format in the cache
183 QString expr
= m_expression
.currentText();
184 expr
= expr
.simplifyWhiteSpace();
185 unsigned* pFormat
= m_formatCache
[expr
];
190 displayNewExpression(expr
);
193 void MemoryWindow::slotNewMemoryDump(const QString
& msg
, QList
<MemoryDump
>& memdump
)
196 if (!msg
.isEmpty()) {
197 new QListViewItem(&m_memory
, QString(), msg
);
201 MemoryViewItem
* after
= 0;
202 MemoryDump
* md
= memdump
.first();
204 // remove all columns, except the address column
205 for(int k
= m_memory
.columns() - 1; k
> 0; k
--)
206 m_memory
.removeColumn(k
);
208 //add the needed columns
209 QStringList sl
= QStringList::split( "\t", md
->dump
);
210 for (uint i
= 0; i
< sl
.count(); i
++)
211 m_memory
.addColumn("", -1);
213 QMap
<QString
,QString
> tmpMap
;
215 for (; md
!= 0; md
= memdump
.next())
217 QString addr
= md
->address
.asString() + " " + md
->address
.fnoffs
;
218 QStringList sl
= QStringList::split( "\t", md
->dump
);
221 tmpMap
[addr
] = md
->dump
;
223 after
= new MemoryViewItem(&m_memory
, after
, addr
, "");
226 QMap
<QString
,QString
>::Iterator pos
= m_old_memory
.find( addr
);
228 if( pos
!= m_old_memory
.end() )
229 tmplist
= QStringList::split( "\t", pos
.data() );
231 for (uint i
= 0; i
< sl
.count(); i
++)
233 after
->setText( i
+1, *sl
.at(i
) );
236 tmplist
.count() > 0 &&
237 *sl
.at(i
) != *tmplist
.at(i
);
238 after
->setChanged(i
, changed
);
242 m_old_memory
.clear();
243 m_old_memory
= tmpMap
;
246 static const char MemoryGroup
[] = "Memory";
247 static const char NumExprs
[] = "NumExprs";
248 static const char ExpressionFmt
[] = "Expression%d";
249 static const char FormatFmt
[] = "Format%d";
250 static const char ColumnWidths
[] = "ColumnWidths";
252 void MemoryWindow::saveProgramSpecific(KConfigBase
* config
)
254 KConfigGroupSaver
s(config
, MemoryGroup
);
256 int numEntries
= m_expression
.count();
257 config
->writeEntry(NumExprs
, numEntries
);
260 for (int i
= 0; i
< numEntries
;) {
261 QString text
= m_expression
.text(i
);
262 i
++; /* entries are counted 1-based */
263 exprEntry
.sprintf(ExpressionFmt
, i
);
264 fmtEntry
.sprintf(FormatFmt
, i
);
265 config
->writeEntry(exprEntry
, text
);
266 unsigned* pFormat
= m_formatCache
[text
];
267 unsigned fmt
= pFormat
!= 0 ? *pFormat
: MDTword
| MDThex
;
268 config
->writeEntry(fmtEntry
, fmt
);
274 for (int i
= 0; i
< 2; i
++) {
275 int w
= m_memory
.columnWidth(i
);
279 config
->writeEntry(ColumnWidths
, widths
);
282 void MemoryWindow::restoreProgramSpecific(KConfigBase
* config
)
284 KConfigGroupSaver
s(config
, MemoryGroup
);
286 int numEntries
= config
->readNumEntry(NumExprs
, 0);
287 m_expression
.clear();
291 // entries are counted 1-based
292 for (int i
= 1; i
<= numEntries
; i
++) {
293 exprEntry
.sprintf(ExpressionFmt
, i
);
294 fmtEntry
.sprintf(FormatFmt
, i
);
295 QString expr
= config
->readEntry(exprEntry
);
296 unsigned fmt
= config
->readNumEntry(fmtEntry
, MDTword
| MDThex
);
297 m_expression
.insertItem(expr
);
298 m_formatCache
.replace(expr
, new unsigned(fmt
& (MDTsizemask
| MDTformatmask
)));
301 // initialize with top expression
302 if (numEntries
> 0) {
303 m_expression
.setCurrentItem(0);
304 QString expr
= m_expression
.text(0);
305 m_format
= *m_formatCache
[expr
];
306 m_debugger
->setMemoryFormat(m_format
);
307 displayNewExpression(expr
);
312 int n
= config
->readListEntry(ColumnWidths
, widths
);
315 for (int i
= 0; i
< n
; i
++) {
316 QString wStr
= widths
.at(i
);
318 int w
= wStr
.toInt(&ok
);
320 m_memory
.setColumnWidth(i
, w
);
325 #include "memwindow.moc"