summaryrefslogtreecommitdiffstats
path: root/kdbg/winstack.cpp
blob: 1d2d68700c8d1a0d8ffdabc24211be85c785dfa3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
/*
 * 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 "winstack.h"
#include "sourcewnd.h"
#include <ntqbrush.h>
#include <ntqfileinfo.h>
#include <ntqpopupmenu.h>
#include <tdeapplication.h>
#include <tdemainwindow.h>
#include <tdelocale.h>			/* i18n */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mydebug.h"



WinStack::WinStack(TQWidget* parent, const char* name) :
	KTabWidget(parent, name),
	m_pcLine(-1),
	m_valueTip(this),
	m_tipLocation(1,1,10,10),
	m_tabWidth(0)
{
    connect(&m_findDlg.m_buttonForward,
	    SIGNAL(clicked()), SLOT(slotFindForward()));
    connect(&m_findDlg.m_buttonBackward,
	    SIGNAL(clicked()), SLOT(slotFindBackward()));

    connect(this, SIGNAL(setTabWidth(int)), this, SLOT(slotSetTabWidth(int)));
}

WinStack::~WinStack()
{
}

void WinStack::contextMenuEvent(TQContextMenuEvent* e)
{
    // get the context menu from the GUI factory
    TQWidget* top = this;
    do
	top = top->parentWidget();
    while (!top->isTopLevel());
    TDEMainWindow* mw = static_cast<TDEMainWindow*>(top);
    TQPopupMenu* m =
	static_cast<TQPopupMenu*>(mw->factory()->container("popup_files_empty", mw));
    m->exec(e->globalPos());
}


void WinStack::reloadAllFiles()
{
    for (int i = count()-1; i >= 0; i--) {
	windowAt(i)->reloadFile();
    }
}

TQSize WinStack::sizeHint() const
{
    return TQSize(640, 480);
}

void WinStack::activate(const TQString& fileName, int lineNo, const DbgAddr& address)
{
    TQFileInfo fi(fileName);

    if (!fi.isFile()) {
	/*
	 * We didn't find that file. Now check if it is a relative path and
	 * try m_lastOpenDir as prefix.
	 */
	TRACE(fi.filePath() + (" not found, looking in " + m_lastOpenDir));
	if (!fi.isRelative() || m_lastOpenDir.isEmpty()) {
	    return;
	}
	fi.setFile(m_lastOpenDir + "/" + fi.filePath());
	if (!fi.isFile()) {
	    return;
	}
    }
    // if this is not an absolute path name, make it one
    activatePath(fi.absFilePath(), lineNo, address);
}

void WinStack::activateFile(const TQString& fileName)
{
    activatePath(fileName, 0, DbgAddr());
}

bool WinStack::activatePath(TQString pathName, int lineNo, const DbgAddr& address)
{
    // check whether the file is already open
    SourceWindow* fw = 0;
    for (int i = count()-1; i >= 0; i--) {
	if (windowAt(i)->fileName() == pathName) {
	    fw = windowAt(i);
	    break;
	}
    }
    if (fw == 0) {
	// not found, load it
	fw = new SourceWindow(pathName, this, "fileWindow");

	// slurp the file in
	if (!fw->loadFile()) {
	    // read failed
	    delete fw;
	    return false;
	}

	addTab(fw, TQFileInfo(pathName).fileName());
	setTabToolTip(fw, pathName);

	connect(fw, SIGNAL(clickedLeft(const TQString&,int,const DbgAddr&,bool)),
		SIGNAL(toggleBreak(const TQString&,int,const DbgAddr&,bool)));
	connect(fw, SIGNAL(clickedMid(const TQString&,int,const DbgAddr&)),
		SIGNAL(enadisBreak(const TQString&,int,const DbgAddr&)));

	// disassemble code
	connect(fw, SIGNAL(disassemble(const TQString&, int)),
		SIGNAL(disassemble(const TQString&, int)));
	connect(fw, SIGNAL(expanded(int)), SLOT(slotExpandCollapse(int)));
	connect(fw, SIGNAL(collapsed(int)), SLOT(slotExpandCollapse(int)));

	// tab width
	connect(this, SIGNAL(setTabWidth(int)), fw, SLOT(setTabWidth(int)));
	fw->setTabWidth(m_tabWidth);
	fw->setFocusPolicy(TQWidget::WheelFocus);

	// set PC if there is one
	emit newFileLoaded();
	if (m_pcLine >= 0) {
	    setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
	}
    }
    return activateWindow(fw, lineNo, address);
}

bool WinStack::activateWindow(SourceWindow* fw, int lineNo, const DbgAddr& address)
{
    // make the line visible
    if (lineNo >= 0) {
	fw->scrollTo(lineNo, address);
    }

    showPage(fw);
    fw->setFocus();

    return true;
}

bool WinStack::activeLine(TQString& fileName, int& lineNo)
{
    DbgAddr dummy;
    return activeLine(fileName, lineNo, dummy);
}

bool WinStack::activeLine(TQString& fileName, int& lineNo, DbgAddr& address)
{
    if (activeWindow() == 0) {
	return false;
    }
    
    fileName = activeFileName();
    activeWindow()->activeLine(lineNo, address);
    return true;
}

void WinStack::updateLineItems(const KDebugger* dbg)
{
    for (int i = count()-1; i >= 0; i--) {
	windowAt(i)->updateLineItems(dbg);
    }
}

void WinStack::updatePC(const TQString& fileName, int lineNo, const DbgAddr& address, int frameNo)
{
    if (m_pcLine >= 0) {
	setPC(false, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
    }
    m_pcFile = fileName;
    m_pcLine = lineNo;
    m_pcAddress = address.asString();
    m_pcFrame = frameNo;
    if (lineNo >= 0) {
	setPC(true, fileName, lineNo, address, frameNo);
    }
}

SourceWindow* WinStack::findByFileName(const TQString& fileName) const
{
    for (int i = count()-1; i >= 0; i--) {
	if (windowAt(i)->fileNameMatches(fileName)) {
	    return windowAt(i);
	}
    }
    return 0;
}

void WinStack::setPC(bool set, const TQString& fileName, int lineNo,
		     const DbgAddr& address, int frameNo)
{
    TRACE((set ? "set PC: " : "clear PC: ") + fileName +
	  TQString().sprintf(":%d#%d ", lineNo, frameNo) + address.asString());
    SourceWindow* fw = findByFileName(fileName);
    if (fw)
	fw->setPC(set, lineNo, address, frameNo);
}

SourceWindow* WinStack::windowAt(int i) const
{
    return static_cast<SourceWindow*>(page(i));
}

SourceWindow* WinStack::activeWindow() const
{
    return static_cast<SourceWindow*>(currentPage());
}

TQString WinStack::activeFileName() const
{
    TQString f;
    if (activeWindow() != 0)
	f = activeWindow()->fileName();
    return f;
}

void WinStack::slotFindForward()
{
    if (activeWindow() != 0)
	activeWindow()->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
			     SourceWindow::findForward);
}

void WinStack::slotFindBackward()
{
    if (activeWindow() != 0)
	activeWindow()->find(m_findDlg.searchText(), m_findDlg.caseSensitive(),
			     SourceWindow::findBackward);
}

void WinStack::maybeTip(const TQPoint& p)
{
    SourceWindow* w = activeWindow();
    if (w == 0)
	return;

    // get the word at the point
    TQString word;
    TQRect r;
    if (!w->wordAtPoint(w->mapFrom(this, p), word, r))
	return;

    // must be valid
    assert(!word.isEmpty());
    assert(r.isValid());

    // remember the location
    m_tipLocation = TQRect(w->mapTo(this, r.topLeft()), r.size());

    emit initiateValuePopup(word);
}

void WinStack::slotShowValueTip(const TQString& tipText)
{
    m_valueTip.tip(m_tipLocation, tipText);
}

void WinStack::slotDisassembled(const TQString& fileName, int lineNo,
				const std::list<DisassembledCode>& disass)
{
    SourceWindow* fw = findByFileName(fileName);
    if (fw == 0) {
	// not found: ignore
	return;
    }

    fw->disassembled(lineNo, disass);
}

void WinStack::slotExpandCollapse(int)
{
    // update line items after expanding or collapsing disassembled code

    // HACK: we know that this will result in updateLineItems
    // should be done more cleanly with a separate signal
    emit newFileLoaded();

    if (m_pcLine >= 0) {
	setPC(true, m_pcFile, m_pcLine, DbgAddr(m_pcAddress), m_pcFrame);
    }
}


void WinStack::slotSetTabWidth(int numChars)
{
    m_tabWidth = numChars;
}

void WinStack::slotFileReload()
{
    if (activeWindow() != 0) {
	TRACE("reloading one file");
	activeWindow()->reloadFile();
    }
}

void WinStack::slotViewFind()
{
    if (m_findDlg.isVisible()) {
	m_findDlg.done(0);
    } else {
	m_findDlg.show();
    }
}

void WinStack::slotBrkptSet()
{
    TQString file;
    int lineNo;
    DbgAddr address;
    if (activeLine(file, lineNo, address))
	emit toggleBreak(file, lineNo, address, false);
}

void WinStack::slotBrkptSetTemp()
{
    TQString file;
    int lineNo;
    DbgAddr address;
    if (activeLine(file, lineNo, address))
	emit toggleBreak(file, lineNo, address, true);
}

void WinStack::slotBrkptEnable()
{
    TQString file;
    int lineNo;
    DbgAddr address;
    if (activeLine(file, lineNo, address))
	emit enadisBreak(file, lineNo, address);
}

void WinStack::slotMoveProgramCounter()
{
    TQString file;
    int lineNo;
    DbgAddr address;
    if (activeLine(file, lineNo, address))
	emit moveProgramCounter(file, lineNo, address);
}

void WinStack::slotClose()
{
    TQWidget* w = activeWindow();
    if (!w)
	return;

    removePage(w);
    delete w;
}


ValueTip::ValueTip(WinStack* parent) :
	TQToolTip(parent)
{
}

void ValueTip::maybeTip(const TQPoint& p)
{
    WinStack* w = static_cast<WinStack*>(parentWidget());
    w->maybeTip(p);
}


FindDialog::FindDialog() :
	TQDialog(0, "find", false),
	m_searchText(this, "text"),
	m_caseCheck(this, "case"),
	m_buttonForward(this, "forward"),
	m_buttonBackward(this, "backward"),
	m_buttonClose(this, "close"),
	m_layout(this, 8),
	m_buttons(4)
{
    setCaption(TQString(kapp->caption()) + i18n(": Search"));

    m_searchText.setMinimumSize(330, 24);
    m_searchText.setMaxLength(10000);
    m_searchText.setFrame(true);

    m_caseCheck.setText(i18n("&Case sensitive"));
    m_caseCheck.setChecked(true);
    m_buttonForward.setText(i18n("&Forward"));
    m_buttonForward.setDefault(true);
    m_buttonBackward.setText(i18n("&Backward"));
    m_buttonClose.setText(i18n("Close"));

    m_caseCheck.setMinimumSize(330, 24);

    // get maximum size of buttons
    TQSize maxSize(80,30);
    maxSize.expandedTo(m_buttonForward.sizeHint());
    maxSize.expandedTo(m_buttonBackward.sizeHint());
    maxSize.expandedTo(m_buttonClose.sizeHint());

    m_buttonForward.setMinimumSize(maxSize);
    m_buttonBackward.setMinimumSize(maxSize);
    m_buttonClose.setMinimumSize(maxSize);

    connect(&m_buttonClose, SIGNAL(clicked()), SLOT(reject()));

    m_layout.addWidget(&m_searchText);
    m_layout.addWidget(&m_caseCheck);
    m_layout.addLayout(&m_buttons);
    m_layout.addStretch(10);
    m_buttons.addWidget(&m_buttonForward);
    m_buttons.addStretch(10);
    m_buttons.addWidget(&m_buttonBackward);
    m_buttons.addStretch(10);
    m_buttons.addWidget(&m_buttonClose);

    m_layout.activate();

    m_searchText.setFocus();
    resize( 350, 120 );
}

FindDialog::~FindDialog()
{
}

void FindDialog::closeEvent(TQCloseEvent* ev)
{
    TQDialog::closeEvent(ev);
    emit closed();
}

void FindDialog::done(int result)
{
    TQDialog::done(result);
    emit closed();
}

#include "winstack.moc"