~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/sdk/debuggermanager.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
 
3
 * http://www.gnu.org/licenses/lgpl-3.0.html
 
4
 *
 
5
 * $Revision: 10695 $
 
6
 * $Id: debuggermanager.cpp 10695 2016-01-23 19:02:44Z mortenmacfly $
 
7
 * $HeadURL: http://svn.code.sf.net/p/codeblocks/code/branches/release-16.xx/src/sdk/debuggermanager.cpp $
 
8
 */
 
9
 
 
10
#include "sdk_precomp.h"
 
11
#ifndef CB_PRECOMP
 
12
    #include <wx/artprov.h>
 
13
    #include <wx/bmpbuttn.h>
 
14
    #include <wx/combobox.h>
 
15
    #include <wx/filedlg.h>
 
16
    #include <wx/frame.h>
 
17
    #include <wx/menu.h>
 
18
    #include <wx/settings.h>
 
19
    #include <wx/sizer.h>
 
20
    #include <wx/stattext.h>
 
21
    #include <wx/regex.h>
 
22
 
 
23
    #include "cbeditor.h"
 
24
    #include "cbexception.h"
 
25
    #include "cbplugin.h"
 
26
    #include "cbproject.h"
 
27
    #include "compilerfactory.h"
 
28
    #include "configmanager.h"
 
29
    #include "editormanager.h"
 
30
    #include "logmanager.h"
 
31
    #include "projectmanager.h"
 
32
#endif
 
33
 
 
34
#include <algorithm>
 
35
#include <sstream>
 
36
#include <wx/toolbar.h>
 
37
 
 
38
#include "debuggermanager.h"
 
39
 
 
40
#include "annoyingdialog.h"
 
41
#include "cbdebugger_interfaces.h"
 
42
#include "loggers.h"
 
43
#include "manager.h"
 
44
 
 
45
cbWatch::cbWatch() :
 
46
    m_changed(true),
 
47
    m_removed(false),
 
48
    m_expanded(false),
 
49
    m_autoUpdate(true)
 
50
{
 
51
}
 
52
 
 
53
cbWatch::~cbWatch()
 
54
{
 
55
    m_children.clear();
 
56
}
 
57
 
 
58
void cbWatch::AddChild(cb::shared_ptr<cbWatch> parent, cb::shared_ptr<cbWatch> watch)
 
59
{
 
60
    watch->m_parent = parent;
 
61
    parent->m_children.push_back(watch);
 
62
}
 
63
 
 
64
void cbWatch::RemoveChild(int index)
 
65
{
 
66
    std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin();
 
67
    std::advance(it, index);
 
68
    m_children.erase(it);
 
69
}
 
70
 
 
71
inline bool TestIfMarkedForRemoval(cb::shared_ptr<cbWatch> watch)
 
72
{
 
73
    if(watch->IsRemoved())
 
74
        return true;
 
75
    else
 
76
    {
 
77
        watch->RemoveMarkedChildren();
 
78
        return false;
 
79
    }
 
80
}
 
81
 
 
82
bool cbWatch::RemoveMarkedChildren()
 
83
{
 
84
    size_t start_size = m_children.size();
 
85
    std::vector<cb::shared_ptr<cbWatch> >::iterator new_last;
 
86
    new_last = std::remove_if(m_children.begin(), m_children.end(), &TestIfMarkedForRemoval);
 
87
    m_children.erase(new_last, m_children.end());
 
88
 
 
89
    return start_size != m_children.size();
 
90
 
 
91
}
 
92
void cbWatch::RemoveChildren()
 
93
{
 
94
    m_children.clear();
 
95
}
 
96
 
 
97
int cbWatch::GetChildCount() const
 
98
{
 
99
    return m_children.size();
 
100
}
 
101
 
 
102
cb::shared_ptr<cbWatch> cbWatch::GetChild(int index)
 
103
{
 
104
    std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin();
 
105
    std::advance(it, index);
 
106
    return *it;
 
107
}
 
108
 
 
109
cb::shared_ptr<const cbWatch> cbWatch::GetChild(int index) const
 
110
{
 
111
    std::vector<cb::shared_ptr<cbWatch> >::const_iterator it = m_children.begin();
 
112
    std::advance(it, index);
 
113
    return *it;
 
114
}
 
115
 
 
116
cb::shared_ptr<cbWatch> cbWatch::FindChild(const wxString& symbol)
 
117
{
 
118
    for (std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin(); it != m_children.end(); ++it)
 
119
    {
 
120
        wxString s;
 
121
        (*it)->GetSymbol(s);
 
122
        if(s == symbol)
 
123
            return *it;
 
124
    }
 
125
    return cb::shared_ptr<cbWatch>();
 
126
}
 
127
 
 
128
int cbWatch::FindChildIndex(const wxString& symbol) const
 
129
{
 
130
    int index = 0;
 
131
    for (std::vector<cb::shared_ptr<cbWatch> >::const_iterator it = m_children.begin();
 
132
         it != m_children.end();
 
133
         ++it, ++index)
 
134
    {
 
135
        wxString s;
 
136
        (*it)->GetSymbol(s);
 
137
        if(s == symbol)
 
138
            return index;
 
139
    }
 
140
    return -1;
 
141
}
 
142
 
 
143
cb::shared_ptr<const cbWatch> cbWatch::GetParent() const
 
144
{
 
145
    return m_parent.lock();
 
146
}
 
147
 
 
148
cb::shared_ptr<cbWatch> cbWatch::GetParent()
 
149
{
 
150
    return m_parent.lock();
 
151
}
 
152
 
 
153
bool cbWatch::IsRemoved() const
 
154
{
 
155
    return m_removed;
 
156
}
 
157
 
 
158
bool cbWatch::IsChanged() const
 
159
{
 
160
    return m_changed;
 
161
}
 
162
 
 
163
void cbWatch::MarkAsRemoved(bool flag)
 
164
{
 
165
    m_removed = flag;
 
166
}
 
167
 
 
168
void cbWatch::MarkChildsAsRemoved()
 
169
{
 
170
    for(std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin(); it != m_children.end(); ++it)
 
171
        (*it)->MarkAsRemoved(true);
 
172
}
 
173
void cbWatch::MarkAsChanged(bool flag)
 
174
{
 
175
    m_changed = flag;
 
176
}
 
177
 
 
178
void cbWatch::MarkAsChangedRecursive(bool flag)
 
179
{
 
180
    m_changed = flag;
 
181
    for(std::vector<cb::shared_ptr<cbWatch> >::iterator it = m_children.begin(); it != m_children.end(); ++it)
 
182
        (*it)->MarkAsChangedRecursive(flag);
 
183
}
 
184
 
 
185
bool cbWatch::IsExpanded() const
 
186
{
 
187
    return m_expanded;
 
188
}
 
189
 
 
190
void cbWatch::Expand(bool expand)
 
191
{
 
192
    m_expanded = expand;
 
193
}
 
194
 
 
195
bool cbWatch::IsAutoUpdateEnabled() const
 
196
{
 
197
    return m_autoUpdate;
 
198
}
 
199
 
 
200
void cbWatch::AutoUpdate(bool enabled)
 
201
{
 
202
    m_autoUpdate = enabled;
 
203
}
 
204
 
 
205
cb::shared_ptr<cbWatch> DLLIMPORT cbGetRootWatch(cb::shared_ptr<cbWatch> watch)
 
206
{
 
207
    cb::shared_ptr<cbWatch> root = watch;
 
208
    while (root)
 
209
    {
 
210
        cb::shared_ptr<cbWatch> parent = root->GetParent();
 
211
        if (!parent)
 
212
            break;
 
213
        root = parent;
 
214
    }
 
215
    return root;
 
216
}
 
217
 
 
218
cbStackFrame::cbStackFrame() :
 
219
    m_valid(false)
 
220
{
 
221
}
 
222
 
 
223
void cbStackFrame::SetNumber(int number)
 
224
{
 
225
    m_number = number;
 
226
}
 
227
 
 
228
void cbStackFrame::SetAddress(uint64_t address)
 
229
{
 
230
    m_address = address;
 
231
}
 
232
 
 
233
void cbStackFrame::SetSymbol(const wxString& symbol)
 
234
{
 
235
    m_symbol = symbol;
 
236
}
 
237
 
 
238
void cbStackFrame::SetFile(const wxString& filename, const wxString &line)
 
239
{
 
240
    m_file = filename;
 
241
    m_line = line;
 
242
}
 
243
 
 
244
void cbStackFrame::MakeValid(bool flag)
 
245
{
 
246
    m_valid = flag;
 
247
}
 
248
 
 
249
int cbStackFrame::GetNumber() const
 
250
{
 
251
    return m_number;
 
252
}
 
253
 
 
254
uint64_t cbStackFrame::GetAddress() const
 
255
{
 
256
    return m_address;
 
257
}
 
258
 
 
259
wxString cbStackFrame::GetAddressAsString() const
 
260
{
 
261
    if(m_address!=0)
 
262
        return cbDebuggerAddressToString(m_address);
 
263
    else
 
264
        return wxEmptyString;
 
265
}
 
266
 
 
267
const wxString& cbStackFrame::GetSymbol() const
 
268
{
 
269
    return m_symbol;
 
270
}
 
271
 
 
272
const wxString& cbStackFrame::GetFilename() const
 
273
{
 
274
    return m_file;
 
275
}
 
276
 
 
277
const wxString& cbStackFrame::GetLine() const
 
278
{
 
279
    return m_line;
 
280
}
 
281
 
 
282
bool cbStackFrame::IsValid() const
 
283
{
 
284
    return m_valid;
 
285
}
 
286
 
 
287
cbThread::cbThread()
 
288
{
 
289
}
 
290
 
 
291
cbThread::cbThread(bool active, int number, const wxString& info)
 
292
{
 
293
    m_active = active;
 
294
    m_number = number;
 
295
    m_info = info;
 
296
}
 
297
 
 
298
bool cbThread::IsActive() const
 
299
{
 
300
    return m_active;
 
301
}
 
302
 
 
303
int cbThread::GetNumber() const
 
304
{
 
305
    return m_number;
 
306
}
 
307
 
 
308
const wxString& cbThread::GetInfo() const
 
309
{
 
310
    return m_info;
 
311
}
 
312
 
 
313
cbDebuggerConfiguration::cbDebuggerConfiguration(const ConfigManagerWrapper &config) :
 
314
    m_config(config),
 
315
    m_menuId(wxID_ANY)
 
316
{
 
317
}
 
318
 
 
319
cbDebuggerConfiguration::cbDebuggerConfiguration(const cbDebuggerConfiguration &o) :
 
320
    m_config(o.m_config),
 
321
    m_name(o.m_name)
 
322
{
 
323
}
 
324
 
 
325
void cbDebuggerConfiguration::SetName(const wxString &name)
 
326
{
 
327
    m_name = name;
 
328
}
 
329
const wxString& cbDebuggerConfiguration::GetName() const
 
330
{
 
331
    return m_name;
 
332
}
 
333
 
 
334
const ConfigManagerWrapper& cbDebuggerConfiguration::GetConfig() const
 
335
{
 
336
    return m_config;
 
337
}
 
338
 
 
339
void cbDebuggerConfiguration::SetConfig(const ConfigManagerWrapper &config)
 
340
{
 
341
    m_config = config;
 
342
}
 
343
 
 
344
void cbDebuggerConfiguration::SetMenuId(long id)
 
345
{
 
346
    m_menuId = id;
 
347
}
 
348
 
 
349
long cbDebuggerConfiguration::GetMenuId() const
 
350
{
 
351
    return m_menuId;
 
352
}
 
353
 
 
354
bool cbDebuggerCommonConfig::GetFlag(Flags flag)
 
355
{
 
356
    ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
357
    switch (flag)
 
358
    {
 
359
        case AutoBuild:
 
360
            return c->ReadBool(wxT("/common/auto_build"), true);
 
361
        case AutoSwitchFrame:
 
362
            return c->ReadBool(wxT("/common/auto_switch_frame"), true);
 
363
        case ShowDebuggersLog:
 
364
            return c->ReadBool(wxT("/common/debug_log"), false);
 
365
        case JumpOnDoubleClick:
 
366
            return c->ReadBool(wxT("/common/jump_on_double_click"), false);
 
367
        case RequireCtrlForTooltips:
 
368
            return c->ReadBool(wxT("/common/require_ctrl_for_tooltips"), false);
 
369
        case ShowTemporaryBreakpoints:
 
370
            return c->ReadBool(wxT("/common/show_temporary_breakpoints"), false);
 
371
        default:
 
372
            return false;
 
373
    }
 
374
}
 
375
 
 
376
void cbDebuggerCommonConfig::SetFlag(Flags flag, bool value)
 
377
{
 
378
    ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
379
    switch (flag)
 
380
    {
 
381
        case AutoBuild:
 
382
            c->Write(wxT("/common/auto_build"), value);
 
383
            break;
 
384
        case AutoSwitchFrame:
 
385
            c->Write(wxT("/common/auto_switch_frame"), value);
 
386
            break;
 
387
        case ShowDebuggersLog:
 
388
            c->Write(wxT("/common/debug_log"), value);
 
389
            break;
 
390
        case JumpOnDoubleClick:
 
391
            c->Write(wxT("/common/jump_on_double_click"), value);
 
392
            break;
 
393
        case RequireCtrlForTooltips:
 
394
            c->Write(wxT("/common/require_ctrl_for_tooltips"), value);
 
395
            break;
 
396
        case ShowTemporaryBreakpoints:
 
397
            c->Write(wxT("/common/show_temporary_breakpoints"), value);
 
398
        default:
 
399
            ;
 
400
    }
 
401
}
 
402
 
 
403
wxString cbDebuggerCommonConfig::GetValueTooltipFont()
 
404
{
 
405
    wxFont system = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
 
406
    system.SetPointSize(std::max(system.GetPointSize() - 3, 7));
 
407
    wxString defaultFont = system.GetNativeFontInfo()->ToString();
 
408
 
 
409
    ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
410
    wxString configFont = c->Read(wxT("/common/tooltip_font"));
 
411
 
 
412
    return configFont.empty() ? defaultFont : configFont;
 
413
}
 
414
 
 
415
void cbDebuggerCommonConfig::SetValueTooltipFont(const wxString &font)
 
416
{
 
417
    const wxString &oldFont = GetValueTooltipFont();
 
418
 
 
419
    if (font != oldFont && !font.empty())
 
420
    {
 
421
        ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
422
        c->Write(wxT("/common/tooltip_font"), font);
 
423
    }
 
424
}
 
425
 
 
426
cbDebuggerCommonConfig::Perspective cbDebuggerCommonConfig::GetPerspective()
 
427
{
 
428
    ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
429
    int v = c->ReadInt(wxT("/common/perspective"), static_cast<int>(OnePerDebuggerConfig));
 
430
    if (v < OnlyOne || v > OnePerDebuggerConfig)
 
431
        return OnePerDebuggerConfig;
 
432
    return static_cast<Perspective>(v);
 
433
}
 
434
 
 
435
void cbDebuggerCommonConfig::SetPerspective(int perspective)
 
436
{
 
437
    ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
438
    if (perspective < OnlyOne || perspective > OnePerDebuggerConfig)
 
439
        perspective = OnePerDebuggerConfig;
 
440
    c->Write(wxT("/common/perspective"), perspective);
 
441
}
 
442
 
 
443
wxString cbDetectDebuggerExecutable(const wxString &exeName)
 
444
{
 
445
    wxString exeExt(platform::windows ? wxT(".exe") : wxEmptyString);
 
446
    wxString exePath = cbFindFileInPATH(exeName);
 
447
    wxChar sep = wxFileName::GetPathSeparator();
 
448
 
 
449
    if (exePath.empty())
 
450
    {
 
451
        if (!platform::windows)
 
452
            exePath = wxT("/usr/bin/") + exeName + exeExt;
 
453
        else
 
454
        {
 
455
            const wxString &cbInstallFolder = ConfigManager::GetExecutableFolder();
 
456
            if (wxFileExists(cbInstallFolder + sep + wxT("MINGW") + sep + wxT("bin") + sep + exeName + exeExt))
 
457
                exePath = cbInstallFolder + sep + wxT("MINGW") + sep + wxT("bin");
 
458
            else
 
459
            {
 
460
                exePath = wxT("C:\\MinGW\\bin");
 
461
                if (!wxDirExists(exePath))
 
462
                    exePath = wxT("C:\\MinGW32\\bin");
 
463
            }
 
464
        }
 
465
    }
 
466
    if (!wxDirExists(exePath))
 
467
        return wxEmptyString;
 
468
    return exePath + wxFileName::GetPathSeparator() + exeName + exeExt;
 
469
}
 
470
 
 
471
uint64_t cbDebuggerStringToAddress(const wxString &address)
 
472
{
 
473
    if (address.empty())
 
474
        return 0;
 
475
    std::istringstream s(address.utf8_str().data());
 
476
    uint64_t result;
 
477
    s >> std::hex >> result;
 
478
    return (s.fail() ? 0 : result);
 
479
}
 
480
 
 
481
wxString cbDebuggerAddressToString(uint64_t address)
 
482
{
 
483
    std::stringstream s;
 
484
    s << "0x" << std::hex << address;
 
485
    return wxString(s.str().c_str(), wxConvUTF8);
 
486
}
 
487
 
 
488
class DebugTextCtrlLogger : public TextCtrlLogger
 
489
{
 
490
public:
 
491
    DebugTextCtrlLogger(bool fixedPitchFont, bool debugLog) :
 
492
        TextCtrlLogger(fixedPitchFont),
 
493
        m_panel(nullptr),
 
494
        m_debugLog(debugLog)
 
495
    {
 
496
    }
 
497
 
 
498
    wxWindow* CreateTextCtrl(wxWindow *parent)
 
499
    {
 
500
        return TextCtrlLogger::CreateControl(parent);
 
501
    }
 
502
 
 
503
    virtual wxWindow* CreateControl(wxWindow* parent);
 
504
 
 
505
private:
 
506
    wxPanel *m_panel;
 
507
    bool    m_debugLog;
 
508
};
 
509
 
 
510
class DebugLogPanel : public wxPanel
 
511
{
 
512
public:
 
513
    DebugLogPanel(wxWindow *parent, DebugTextCtrlLogger *text_control_logger, bool debug_log) :
 
514
        wxPanel(parent),
 
515
        m_text_control_logger(text_control_logger),
 
516
        m_debug_log(debug_log)
 
517
    {
 
518
        int idDebug_LogEntryControl = wxNewId();
 
519
        int idDebug_ExecuteButton = wxNewId();
 
520
        int idDebug_ClearButton = wxNewId();
 
521
        int idDebug_LoadButton = wxNewId();
 
522
 
 
523
        wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
 
524
        wxBoxSizer *control_sizer = new wxBoxSizer(wxHORIZONTAL);
 
525
 
 
526
        wxWindow *text_control = text_control_logger->CreateTextCtrl(this);
 
527
        sizer->Add(text_control, wxEXPAND, wxEXPAND | wxALL , 0);
 
528
        sizer->Add(control_sizer, 0, wxEXPAND | wxALL, 0);
 
529
 
 
530
        wxStaticText *label = new wxStaticText(this, wxID_ANY, _T("Command:"),
 
531
                                               wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
 
532
 
 
533
        m_command_entry = new wxComboBox(this, idDebug_LogEntryControl, wxEmptyString,
 
534
                                         wxDefaultPosition, wxDefaultSize, 0, nullptr,
 
535
                                         wxCB_DROPDOWN | wxTE_PROCESS_ENTER);
 
536
 
 
537
        wxBitmap execute_bitmap = wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_EXECUTABLE_FILE")),
 
538
                                                           wxART_BUTTON);
 
539
        wxBitmap clear_bitmap = wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_DELETE")),wxART_BUTTON);
 
540
        wxBitmap file_open_bitmap =wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(_T("wxART_FILE_OPEN")),
 
541
                                                            wxART_BUTTON);
 
542
 
 
543
        wxBitmapButton *button_execute;
 
544
        button_execute = new wxBitmapButton(this, idDebug_ExecuteButton, execute_bitmap, wxDefaultPosition,
 
545
                                            wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator,
 
546
                                            _T("idDebug_ExecuteButton"));
 
547
        button_execute->SetToolTip(_("Execute current command"));
 
548
 
 
549
        wxBitmapButton *button_load = new wxBitmapButton(this, idDebug_LoadButton, file_open_bitmap, wxDefaultPosition,
 
550
                                                         wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator,
 
551
                                                         _T("idDebug_LoadButton"));
 
552
        button_load->SetDefault();
 
553
        button_load->SetToolTip(_("Load from file"));
 
554
 
 
555
        wxBitmapButton *button_clear = new wxBitmapButton(this, idDebug_ClearButton, clear_bitmap, wxDefaultPosition,
 
556
                                                          wxDefaultSize, wxBU_AUTODRAW, wxDefaultValidator,
 
557
                                                          _T("idDebug_ClearButton"));
 
558
        button_clear->SetDefault();
 
559
        button_clear->SetToolTip(_("Clear output window"));
 
560
 
 
561
        control_sizer->Add(label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 2);
 
562
        control_sizer->Add(m_command_entry, wxEXPAND, wxEXPAND | wxALL, 2);
 
563
        control_sizer->Add(button_execute, 0, wxEXPAND | wxALL, 0);
 
564
        control_sizer->Add(button_load, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0);
 
565
        control_sizer->Add(button_clear, 0, wxALL|wxALIGN_CENTER_VERTICAL, 0);
 
566
 
 
567
        SetSizer(sizer);
 
568
 
 
569
        Connect(idDebug_LogEntryControl,
 
570
                wxEVT_COMMAND_TEXT_ENTER,
 
571
                wxObjectEventFunction(&DebugLogPanel::OnEntryCommand));
 
572
        Connect(idDebug_ExecuteButton,
 
573
                wxEVT_COMMAND_BUTTON_CLICKED,
 
574
                wxObjectEventFunction(&DebugLogPanel::OnEntryCommand));
 
575
        Connect(idDebug_ClearButton,
 
576
                wxEVT_COMMAND_BUTTON_CLICKED,
 
577
                wxObjectEventFunction(&DebugLogPanel::OnClearLog));
 
578
        Connect(idDebug_LoadButton,
 
579
                wxEVT_COMMAND_BUTTON_CLICKED,
 
580
                wxObjectEventFunction(&DebugLogPanel::OnLoadFile));
 
581
 
 
582
        // UpdateUI events
 
583
        Connect(idDebug_ExecuteButton,
 
584
                wxEVT_UPDATE_UI,
 
585
                wxObjectEventFunction(&DebugLogPanel::OnUpdateUI));
 
586
        Connect(idDebug_LoadButton,
 
587
                wxEVT_UPDATE_UI,
 
588
                wxObjectEventFunction(&DebugLogPanel::OnUpdateUI));
 
589
        Connect(idDebug_LogEntryControl,
 
590
                wxEVT_UPDATE_UI,
 
591
                wxObjectEventFunction(&DebugLogPanel::OnUpdateUI));
 
592
    }
 
593
 
 
594
    void OnEntryCommand(cb_unused wxCommandEvent& event)
 
595
    {
 
596
        assert(m_command_entry);
 
597
        wxString cmd = m_command_entry->GetValue();
 
598
        cmd.Trim(false);
 
599
        cmd.Trim(true);
 
600
 
 
601
        if (cmd.IsEmpty())
 
602
            return;
 
603
        cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
 
604
        if (plugin)
 
605
        {
 
606
            plugin->SendCommand(cmd, m_debug_log);
 
607
 
 
608
            //If it already exists in the list, remove it and add it back at the end
 
609
            int index = m_command_entry->FindString(cmd);
 
610
            if (index != wxNOT_FOUND)
 
611
                m_command_entry->Delete(index);
 
612
            m_command_entry->Append(cmd);
 
613
 
 
614
            m_command_entry->SetValue(wxEmptyString);
 
615
        }
 
616
    }
 
617
 
 
618
    void OnClearLog(cb_unused wxCommandEvent& event)
 
619
    {
 
620
        assert(m_command_entry);
 
621
        assert(m_text_control_logger);
 
622
        m_text_control_logger->Clear();
 
623
        m_command_entry->SetFocus();
 
624
    }
 
625
 
 
626
    void OnLoadFile(cb_unused wxCommandEvent& event)
 
627
    {
 
628
        cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
 
629
        if (!plugin)
 
630
            return;
 
631
 
 
632
        ConfigManager* manager = Manager::Get()->GetConfigManager(_T("app"));
 
633
        wxString path = manager->Read(_T("/file_dialogs/file_run_dbg_script/directory"), wxEmptyString);
 
634
 
 
635
        wxFileDialog dialog(this, _("Load script"), path, wxEmptyString,
 
636
                            _T("Debugger script files (*.gdb)|*.gdb"), wxFD_OPEN | compatibility::wxHideReadonly);
 
637
 
 
638
        if (dialog.ShowModal() == wxID_OK)
 
639
        {
 
640
            manager->Write(_T("/file_dialogs/file_run_dbg_script/directory"), dialog.GetDirectory());
 
641
 
 
642
            plugin->SendCommand(_T("source ") + dialog.GetPath(), m_debug_log);
 
643
        }
 
644
    }
 
645
 
 
646
    void OnUpdateUI(wxUpdateUIEvent &event)
 
647
    {
 
648
        cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
 
649
        event.Enable(plugin && plugin->IsRunning() && plugin->IsStopped());
 
650
    }
 
651
private:
 
652
    DebugTextCtrlLogger *m_text_control_logger;
 
653
    wxComboBox  *m_command_entry;
 
654
    bool m_debug_log;
 
655
};
 
656
 
 
657
wxWindow* DebugTextCtrlLogger::CreateControl(wxWindow* parent)
 
658
{
 
659
    if(!m_panel)
 
660
        m_panel = new DebugLogPanel(parent, this, m_debugLog);
 
661
 
 
662
    return m_panel;
 
663
}
 
664
 
 
665
template<> DebuggerManager* Mgr<DebuggerManager>::instance = nullptr;
 
666
template<> bool  Mgr<DebuggerManager>::isShutdown = false;
 
667
 
 
668
inline void ReadActiveDebuggerConfig(wxString &name, int &configIndex)
 
669
{
 
670
    ConfigManager &config = *Manager::Get()->GetConfigManager(_T("debugger_common"));
 
671
    name = config.Read(wxT("active_debugger"), wxEmptyString);
 
672
    if (name.empty())
 
673
        configIndex = -1;
 
674
    else
 
675
        configIndex = std::max(0, config.ReadInt(wxT("active_debugger_config"), 0));
 
676
}
 
677
 
 
678
inline void WriteActiveDebuggerConfig(const wxString &name, int configIndex)
 
679
{
 
680
    ConfigManager &configMgr = *Manager::Get()->GetConfigManager(_T("debugger_common"));
 
681
    configMgr.Write(wxT("active_debugger"), name);
 
682
    configMgr.Write(wxT("active_debugger_config"), configIndex);
 
683
}
 
684
 
 
685
cbDebuggerConfiguration* DebuggerManager::PluginData::GetConfiguration(int index)
 
686
{
 
687
    if (m_configurations.empty())
 
688
        cbAssert(false);
 
689
    if (index >= static_cast<int>(m_configurations.size()))
 
690
        return nullptr;
 
691
    else
 
692
        return m_configurations[index];
 
693
}
 
694
 
 
695
DebuggerManager::DebuggerManager() :
 
696
    m_interfaceFactory(nullptr),
 
697
    m_activeDebugger(nullptr),
 
698
    m_menuHandler(nullptr),
 
699
    m_backtraceDialog(nullptr),
 
700
    m_breakPointsDialog(nullptr),
 
701
    m_cpuRegistersDialog(nullptr),
 
702
    m_disassemblyDialog(nullptr),
 
703
    m_examineMemoryDialog(nullptr),
 
704
    m_threadsDialog(nullptr),
 
705
    m_watchesDialog(nullptr),
 
706
    m_logger(nullptr),
 
707
    m_loggerIndex(-1),
 
708
    m_isDisassemblyMixedMode(false),
 
709
    m_useTargetsDefault(false)
 
710
{
 
711
    typedef cbEventFunctor<DebuggerManager, CodeBlocksEvent> Event;
 
712
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_ACTIVATE,        new Event(this, &DebuggerManager::OnProjectActivated));
 
713
    // connect with cbEVT_PROJECT_OPEN, too (see here: http://forums.codeblocks.org/index.php/topic,17260.msg118431.html#msg118431)
 
714
    Manager::Get()->RegisterEventSink(cbEVT_PROJECT_OPEN,            new Event(this, &DebuggerManager::OnProjectActivated));
 
715
    Manager::Get()->RegisterEventSink(cbEVT_BUILDTARGET_SELECTED,    new Event(this, &DebuggerManager::OnTargetSelected));
 
716
    Manager::Get()->RegisterEventSink(cbEVT_SETTINGS_CHANGED,        new Event(this, &DebuggerManager::OnSettingsChanged));
 
717
    Manager::Get()->RegisterEventSink(cbEVT_PLUGIN_LOADING_COMPLETE, new Event(this, &DebuggerManager::OnPluginLoadingComplete));
 
718
 
 
719
    wxString activeDebuggerName;
 
720
    int activeConfig;
 
721
    ReadActiveDebuggerConfig(activeDebuggerName, activeConfig);
 
722
    if (activeDebuggerName.empty() && activeConfig == -1)
 
723
        m_useTargetsDefault = true;
 
724
}
 
725
 
 
726
DebuggerManager::~DebuggerManager()
 
727
{
 
728
    for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
 
729
        it->second.ClearConfigurations();
 
730
 
 
731
    Manager::Get()->RemoveAllEventSinksFor(this);
 
732
    delete m_interfaceFactory;
 
733
}
 
734
 
 
735
bool DebuggerManager::RegisterDebugger(cbDebuggerPlugin *plugin)
 
736
{
 
737
    RegisteredPlugins::iterator it = m_registered.find(plugin);
 
738
    if (it != m_registered.end())
 
739
        return false;
 
740
    const wxString &guiName=plugin->GetGUIName();
 
741
    const wxString &settingsName=plugin->GetSettingsName();
 
742
 
 
743
    wxRegEx regExSettingsName(wxT("^[a-z_][a-z0-9_]+$"));
 
744
    if (!regExSettingsName.Matches(settingsName))
 
745
    {
 
746
        wxString s;
 
747
        s = wxString::Format(_("The settings name for the debugger plugin \"%s\" - \"%s\" contains invalid characters"),
 
748
                             guiName.c_str(), settingsName.c_str());
 
749
        Manager::Get()->GetLogManager()->LogError(s);
 
750
        return false;
 
751
    }
 
752
 
 
753
    int normalIndex = -1;
 
754
    GetLogger(normalIndex);
 
755
    plugin->SetupLog(normalIndex);
 
756
 
 
757
    PluginData data;
 
758
 
 
759
    m_registered[plugin] = data;
 
760
    it = m_registered.find(plugin);
 
761
    ProcessSettings(it);
 
762
 
 
763
    // There should be at least one configuration for every plugin.
 
764
    // If this is not the case, something is wrong and should be fixed.
 
765
    cbAssert(!it->second.GetConfigurations().empty());
 
766
 
 
767
    wxString activeDebuggerName;
 
768
    int activeConfig;
 
769
    ReadActiveDebuggerConfig(activeDebuggerName, activeConfig);
 
770
 
 
771
    if (activeDebuggerName == settingsName)
 
772
    {
 
773
        if (activeConfig > static_cast<int>(it->second.GetConfigurations().size()))
 
774
            activeConfig = 0;
 
775
 
 
776
        m_activeDebugger = plugin;
 
777
        m_activeDebugger->SetActiveConfig(activeConfig);
 
778
 
 
779
        m_menuHandler->SetActiveDebugger(m_activeDebugger);
 
780
    }
 
781
 
 
782
    CreateWindows();
 
783
    m_menuHandler->RebuildMenus();
 
784
 
 
785
    return true;
 
786
}
 
787
 
 
788
bool DebuggerManager::UnregisterDebugger(cbDebuggerPlugin *plugin)
 
789
{
 
790
    RegisteredPlugins::iterator it = m_registered.find(plugin);
 
791
    if(it == m_registered.end())
 
792
        return false;
 
793
 
 
794
    it->second.ClearConfigurations();
 
795
    m_registered.erase(it);
 
796
    if (plugin == m_activeDebugger)
 
797
    {
 
798
        if (m_registered.empty())
 
799
            m_activeDebugger = nullptr;
 
800
        else
 
801
            m_activeDebugger = m_registered.begin()->first;
 
802
        m_menuHandler->SetActiveDebugger(m_activeDebugger);
 
803
    }
 
804
    if (!Manager::IsAppShuttingDown())
 
805
    {
 
806
        m_menuHandler->RebuildMenus();
 
807
        RefreshUI();
 
808
    }
 
809
 
 
810
    if (m_registered.empty())
 
811
    {
 
812
        DestoryWindows();
 
813
 
 
814
        if (Manager::Get()->GetLogManager())
 
815
            Manager::Get()->GetDebuggerManager()->HideLogger();
 
816
    }
 
817
 
 
818
    return true;
 
819
}
 
820
 
 
821
void DebuggerManager::ProcessSettings(RegisteredPlugins::iterator it)
 
822
{
 
823
    cbDebuggerPlugin *plugin = it->first;
 
824
    PluginData &data = it->second;
 
825
    ConfigManager *config = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
826
    wxString path = wxT("/sets/") + plugin->GetSettingsName();
 
827
    wxArrayString configs = config->EnumerateSubPaths(path);
 
828
    configs.Sort();
 
829
 
 
830
    if (configs.empty())
 
831
    {
 
832
        config->Write(path + wxT("/conf1/name"), wxString(wxT("Default")));
 
833
        configs = config->EnumerateSubPaths(path);
 
834
        configs.Sort();
 
835
    }
 
836
 
 
837
    data.ClearConfigurations();
 
838
    data.m_lastConfigID = -1;
 
839
 
 
840
    for (size_t jj = 0; jj < configs.Count(); ++jj)
 
841
    {
 
842
        wxString configPath = path + wxT("/") + configs[jj];
 
843
        wxString name = config->Read(configPath + wxT("/name"));
 
844
 
 
845
        cbDebuggerConfiguration *pluginConfig;
 
846
        pluginConfig = plugin->LoadConfig(ConfigManagerWrapper(wxT("debugger_common"), configPath + wxT("/values")));
 
847
        if (pluginConfig)
 
848
        {
 
849
            pluginConfig->SetName(name);
 
850
            data.GetConfigurations().push_back(pluginConfig);
 
851
        }
 
852
    }
 
853
}
 
854
 
 
855
ConfigManagerWrapper DebuggerManager::NewConfig(cbDebuggerPlugin *plugin, cb_unused const wxString& name)
 
856
{
 
857
    RegisteredPlugins::iterator it = m_registered.find(plugin);
 
858
    if (it == m_registered.end())
 
859
        return ConfigManagerWrapper();
 
860
 
 
861
    wxString path = wxT("/sets/") + it->first->GetSettingsName();
 
862
 
 
863
    if (it->second.m_lastConfigID == -1)
 
864
    {
 
865
        ConfigManager *config = Manager::Get()->GetConfigManager(wxT("debugger_common"));
 
866
        wxArrayString configs = config->EnumerateSubPaths(path);
 
867
        for (size_t ii = 0; ii < configs.GetCount(); ++ii)
 
868
        {
 
869
            long id;
 
870
            if (configs[ii].Remove(0, 4).ToLong(&id))
 
871
                it->second.m_lastConfigID = std::max<long>(it->second.m_lastConfigID, id);
 
872
        }
 
873
    }
 
874
 
 
875
    path << wxT("/conf") << ++it->second.m_lastConfigID;
 
876
 
 
877
    return ConfigManagerWrapper(wxT("debugger_common"), path +  wxT("/values"));
 
878
}
 
879
 
 
880
void DebuggerManager::RebuildAllConfigs()
 
881
{
 
882
    for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
 
883
        ProcessSettings(it);
 
884
    m_menuHandler->RebuildMenus();
 
885
}
 
886
 
 
887
wxMenu* DebuggerManager::GetMenu()
 
888
{
 
889
    wxMenuBar *menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
 
890
    cbAssert(menuBar);
 
891
    wxMenu *menu = NULL;
 
892
 
 
893
    int menu_pos = menuBar->FindMenu(_("&Debug"));
 
894
 
 
895
    if(menu_pos != wxNOT_FOUND)
 
896
        menu = menuBar->GetMenu(menu_pos);
 
897
 
 
898
    if (!menu)
 
899
    {
 
900
        menu = Manager::Get()->LoadMenu(_T("debugger_menu"),true);
 
901
 
 
902
        // ok, now, where do we insert?
 
903
        // three possibilities here:
 
904
        // a) locate "Compile" menu and insert after it
 
905
        // b) locate "Project" menu and insert after it
 
906
        // c) if not found (?), insert at pos 5
 
907
        int finalPos = 5;
 
908
        int projcompMenuPos = menuBar->FindMenu(_("&Build"));
 
909
        if (projcompMenuPos == wxNOT_FOUND)
 
910
            projcompMenuPos = menuBar->FindMenu(_("&Compile"));
 
911
 
 
912
        if (projcompMenuPos != wxNOT_FOUND)
 
913
            finalPos = projcompMenuPos + 1;
 
914
        else
 
915
        {
 
916
            projcompMenuPos = menuBar->FindMenu(_("&Project"));
 
917
            if (projcompMenuPos != wxNOT_FOUND)
 
918
                finalPos = projcompMenuPos + 1;
 
919
        }
 
920
        menuBar->Insert(finalPos, menu, _("&Debug"));
 
921
 
 
922
        m_menuHandler->RebuildMenus();
 
923
    }
 
924
    return menu;
 
925
}
 
926
 
 
927
bool DebuggerManager::HasMenu() const
 
928
{
 
929
    wxMenuBar *menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
 
930
    cbAssert(menuBar);
 
931
    int menu_pos = menuBar->FindMenu(_("&Debug"));
 
932
    return menu_pos != wxNOT_FOUND;
 
933
}
 
934
 
 
935
void DebuggerManager::BuildContextMenu(wxMenu &menu, const wxString& word_at_caret, bool is_running)
 
936
{
 
937
    m_menuHandler->BuildContextMenu(menu, word_at_caret, is_running);
 
938
}
 
939
 
 
940
TextCtrlLogger* DebuggerManager::GetLogger(int &index)
 
941
{
 
942
    LogManager* msgMan = Manager::Get()->GetLogManager();
 
943
 
 
944
    if (!m_logger)
 
945
    {
 
946
        m_logger = new DebugTextCtrlLogger(true, false);
 
947
        m_loggerIndex = msgMan->SetLog(m_logger);
 
948
        LogSlot &slot = msgMan->Slot(m_loggerIndex);
 
949
        slot.title = _("Debugger");
 
950
        // set log image
 
951
        wxString prefix = ConfigManager::GetDataFolder() + _T("/images/");
 
952
        wxBitmap* bmp = new wxBitmap(cbLoadBitmap(prefix + _T("misc_16x16.png"), wxBITMAP_TYPE_PNG));
 
953
        slot.icon = bmp;
 
954
 
 
955
        CodeBlocksLogEvent evtAdd(cbEVT_ADD_LOG_WINDOW, m_logger, slot.title, slot.icon);
 
956
        Manager::Get()->ProcessEvent(evtAdd);
 
957
    }
 
958
 
 
959
    index = m_loggerIndex;
 
960
    return m_logger;
 
961
}
 
962
 
 
963
TextCtrlLogger* DebuggerManager::GetLogger()
 
964
{
 
965
    int index;
 
966
    return GetLogger(index);
 
967
}
 
968
 
 
969
void DebuggerManager::HideLogger()
 
970
{
 
971
 
 
972
    CodeBlocksLogEvent evt(cbEVT_REMOVE_LOG_WINDOW, m_logger);
 
973
    Manager::Get()->ProcessEvent(evt);
 
974
    m_logger = nullptr;
 
975
    m_loggerIndex = -1;
 
976
}
 
977
 
 
978
void DebuggerManager::SetInterfaceFactory(cbDebugInterfaceFactory *factory)
 
979
{
 
980
    cbAssert(!m_interfaceFactory);
 
981
    m_interfaceFactory = factory;
 
982
 
 
983
    CreateWindows();
 
984
 
 
985
    m_backtraceDialog->EnableWindow(false);
 
986
    m_cpuRegistersDialog->EnableWindow(false);
 
987
    m_disassemblyDialog->EnableWindow(false);
 
988
    m_examineMemoryDialog->EnableWindow(false);
 
989
    m_threadsDialog->EnableWindow(false);
 
990
}
 
991
 
 
992
void DebuggerManager::CreateWindows()
 
993
{
 
994
    if (!m_backtraceDialog)
 
995
        m_backtraceDialog = m_interfaceFactory->CreateBacktrace();
 
996
    if (!m_breakPointsDialog)
 
997
        m_breakPointsDialog = m_interfaceFactory->CreateBreapoints();
 
998
    if (!m_cpuRegistersDialog)
 
999
        m_cpuRegistersDialog = m_interfaceFactory->CreateCPURegisters();
 
1000
    if (!m_disassemblyDialog)
 
1001
        m_disassemblyDialog = m_interfaceFactory->CreateDisassembly();
 
1002
    if (!m_examineMemoryDialog)
 
1003
        m_examineMemoryDialog = m_interfaceFactory->CreateMemory();
 
1004
    if (!m_threadsDialog)
 
1005
        m_threadsDialog = m_interfaceFactory->CreateThreads();
 
1006
    if (!m_watchesDialog)
 
1007
        m_watchesDialog = m_interfaceFactory->CreateWatches();
 
1008
}
 
1009
 
 
1010
void DebuggerManager::DestoryWindows()
 
1011
{
 
1012
    m_interfaceFactory->DeleteBacktrace(m_backtraceDialog);
 
1013
    m_backtraceDialog = nullptr;
 
1014
 
 
1015
    m_interfaceFactory->DeleteBreakpoints(m_breakPointsDialog);
 
1016
    m_breakPointsDialog = nullptr;
 
1017
 
 
1018
    m_interfaceFactory->DeleteCPURegisters(m_cpuRegistersDialog);
 
1019
    m_cpuRegistersDialog = nullptr;
 
1020
 
 
1021
    m_interfaceFactory->DeleteDisassembly(m_disassemblyDialog);
 
1022
    m_disassemblyDialog = nullptr;
 
1023
 
 
1024
    m_interfaceFactory->DeleteMemory(m_examineMemoryDialog);
 
1025
    m_examineMemoryDialog = nullptr;
 
1026
 
 
1027
    m_interfaceFactory->DeleteThreads(m_threadsDialog);
 
1028
    m_threadsDialog = nullptr;
 
1029
 
 
1030
    m_interfaceFactory->DeleteWatches(m_watchesDialog);
 
1031
    m_watchesDialog = nullptr;
 
1032
}
 
1033
 
 
1034
cbDebugInterfaceFactory* DebuggerManager::GetInterfaceFactory()
 
1035
{
 
1036
    return m_interfaceFactory;
 
1037
}
 
1038
 
 
1039
void DebuggerManager::SetMenuHandler(cbDebuggerMenuHandler *handler)
 
1040
{
 
1041
    m_menuHandler = handler;
 
1042
}
 
1043
 
 
1044
cbDebuggerMenuHandler* DebuggerManager::GetMenuHandler()
 
1045
{
 
1046
    return m_menuHandler;
 
1047
}
 
1048
 
 
1049
cbBacktraceDlg* DebuggerManager::GetBacktraceDialog()
 
1050
{
 
1051
    return m_backtraceDialog;
 
1052
}
 
1053
 
 
1054
cbBreakpointsDlg* DebuggerManager::GetBreakpointDialog()
 
1055
{
 
1056
    return m_breakPointsDialog;
 
1057
}
 
1058
 
 
1059
cbCPURegistersDlg* DebuggerManager::GetCPURegistersDialog()
 
1060
{
 
1061
    return m_cpuRegistersDialog;
 
1062
}
 
1063
 
 
1064
cbDisassemblyDlg* DebuggerManager::GetDisassemblyDialog()
 
1065
{
 
1066
    return m_disassemblyDialog;
 
1067
}
 
1068
 
 
1069
cbExamineMemoryDlg* DebuggerManager::GetExamineMemoryDialog()
 
1070
{
 
1071
    return m_examineMemoryDialog;
 
1072
}
 
1073
 
 
1074
cbThreadsDlg* DebuggerManager::GetThreadsDialog()
 
1075
{
 
1076
    return m_threadsDialog;
 
1077
}
 
1078
 
 
1079
cbWatchesDlg* DebuggerManager::GetWatchesDialog()
 
1080
{
 
1081
    return m_watchesDialog;
 
1082
}
 
1083
 
 
1084
bool DebuggerManager::ShowBacktraceDialog()
 
1085
{
 
1086
    cbBacktraceDlg *dialog = GetBacktraceDialog();
 
1087
 
 
1088
    if (!IsWindowReallyShown(dialog->GetWindow()))
 
1089
    {
 
1090
        // show the backtrace window
 
1091
        CodeBlocksDockEvent evt(cbEVT_SHOW_DOCK_WINDOW);
 
1092
        evt.pWindow = dialog->GetWindow();
 
1093
        Manager::Get()->ProcessEvent(evt);
 
1094
        return true;
 
1095
    }
 
1096
    else
 
1097
        return false;
 
1098
}
 
1099
 
 
1100
bool DebuggerManager::UpdateBacktrace()
 
1101
{
 
1102
    return m_backtraceDialog && IsWindowReallyShown(m_backtraceDialog->GetWindow());
 
1103
}
 
1104
 
 
1105
bool DebuggerManager::UpdateCPURegisters()
 
1106
{
 
1107
    return m_cpuRegistersDialog && IsWindowReallyShown(m_cpuRegistersDialog->GetWindow());
 
1108
}
 
1109
 
 
1110
bool DebuggerManager::UpdateDisassembly()
 
1111
{
 
1112
    return m_disassemblyDialog && IsWindowReallyShown(m_disassemblyDialog->GetWindow());
 
1113
}
 
1114
 
 
1115
bool DebuggerManager::UpdateExamineMemory()
 
1116
{
 
1117
    return m_examineMemoryDialog && IsWindowReallyShown(m_examineMemoryDialog->GetWindow());
 
1118
}
 
1119
 
 
1120
bool DebuggerManager::UpdateThreads()
 
1121
{
 
1122
    return m_threadsDialog && IsWindowReallyShown(m_threadsDialog->GetWindow());
 
1123
}
 
1124
 
 
1125
cbDebuggerPlugin* DebuggerManager::GetDebuggerHavingWatch(cb::shared_ptr<cbWatch> watch)
 
1126
{
 
1127
    watch = cbGetRootWatch(watch);
 
1128
    for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
 
1129
    {
 
1130
        if (it->first->HasWatch(watch))
 
1131
            return it->first;
 
1132
    }
 
1133
    return NULL;
 
1134
}
 
1135
 
 
1136
bool DebuggerManager::ShowValueTooltip(const cb::shared_ptr<cbWatch> &watch, const wxRect &rect)
 
1137
{
 
1138
    return m_interfaceFactory->ShowValueTooltip(watch, rect);
 
1139
}
 
1140
 
 
1141
DebuggerManager::RegisteredPlugins const & DebuggerManager::GetAllDebuggers() const
 
1142
{
 
1143
    return m_registered;
 
1144
}
 
1145
DebuggerManager::RegisteredPlugins & DebuggerManager::GetAllDebuggers()
 
1146
{
 
1147
    return m_registered;
 
1148
}
 
1149
cbDebuggerPlugin* DebuggerManager::GetActiveDebugger()
 
1150
{
 
1151
    return m_activeDebugger;
 
1152
}
 
1153
 
 
1154
inline void RefreshBreakpoints(cb_unused const cbDebuggerPlugin* plugin)
 
1155
{
 
1156
    EditorManager *editorManager = Manager::Get()->GetEditorManager();
 
1157
    int count = editorManager->GetEditorsCount();
 
1158
    for (int ii = 0; ii < count; ++ii)
 
1159
    {
 
1160
        EditorBase *editor = editorManager->GetEditor(ii);
 
1161
        if (!editor->IsBuiltinEditor())
 
1162
            continue;
 
1163
        editor->RefreshBreakpointMarkers();
 
1164
    }
 
1165
}
 
1166
 
 
1167
void DebuggerManager::SetActiveDebugger(cbDebuggerPlugin* activeDebugger, ConfigurationVector::const_iterator config)
 
1168
{
 
1169
    RegisteredPlugins::const_iterator it = m_registered.find(activeDebugger);
 
1170
    cbAssert(it != m_registered.end());
 
1171
 
 
1172
    m_useTargetsDefault = false;
 
1173
    m_activeDebugger = activeDebugger;
 
1174
    int index = std::distance(it->second.GetConfigurations().begin(), config);
 
1175
    m_activeDebugger->SetActiveConfig(index);
 
1176
 
 
1177
    WriteActiveDebuggerConfig(it->first->GetSettingsName(), index);
 
1178
    RefreshUI();
 
1179
}
 
1180
 
 
1181
void DebuggerManager::RefreshUI()
 
1182
{
 
1183
    m_menuHandler->SetActiveDebugger(m_activeDebugger);
 
1184
    m_menuHandler->RebuildMenus();
 
1185
    RefreshBreakpoints(m_activeDebugger);
 
1186
 
 
1187
    if (m_activeDebugger)
 
1188
    {
 
1189
        if (m_backtraceDialog)
 
1190
            m_backtraceDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::Callstack));
 
1191
        if (m_cpuRegistersDialog)
 
1192
            m_cpuRegistersDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::CPURegisters));
 
1193
        if (m_disassemblyDialog)
 
1194
            m_disassemblyDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::Disassembly));
 
1195
        if (m_examineMemoryDialog)
 
1196
            m_examineMemoryDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::ExamineMemory));
 
1197
        if (m_threadsDialog)
 
1198
            m_threadsDialog->EnableWindow(m_activeDebugger->SupportsFeature(cbDebuggerFeature::Threads));
 
1199
    }
 
1200
    if (m_watchesDialog)
 
1201
        m_watchesDialog->RefreshUI();
 
1202
    if (m_breakPointsDialog)
 
1203
        m_breakPointsDialog->Reload();
 
1204
}
 
1205
 
 
1206
bool DebuggerManager::IsActiveDebuggerTargetsDefault() const
 
1207
{
 
1208
    return m_activeDebugger && m_useTargetsDefault;
 
1209
}
 
1210
 
 
1211
void DebuggerManager::SetTargetsDefaultAsActiveDebugger()
 
1212
{
 
1213
    m_activeDebugger = nullptr;
 
1214
    m_menuHandler->SetActiveDebugger(nullptr);
 
1215
    FindTargetsDebugger();
 
1216
}
 
1217
 
 
1218
void DebuggerManager::FindTargetsDebugger()
 
1219
{
 
1220
    if (Manager::Get()->GetProjectManager()->IsLoadingOrClosing())
 
1221
        return;
 
1222
 
 
1223
    m_activeDebugger = nullptr;
 
1224
    m_menuHandler->SetActiveDebugger(nullptr);
 
1225
 
 
1226
    if (m_registered.empty())
 
1227
    {
 
1228
        m_menuHandler->MarkActiveTargetAsValid(false);
 
1229
        return;
 
1230
    }
 
1231
 
 
1232
    ProjectManager* projectMgr = Manager::Get()->GetProjectManager();
 
1233
    LogManager* log = Manager::Get()->GetLogManager();
 
1234
    cbProject* project = projectMgr->GetActiveProject();
 
1235
    ProjectBuildTarget *target = nullptr;
 
1236
    if (project)
 
1237
    {
 
1238
        const wxString &targetName = project->GetActiveBuildTarget();
 
1239
        if (project->BuildTargetValid(targetName))
 
1240
            target = project->GetBuildTarget(targetName);
 
1241
    }
 
1242
 
 
1243
 
 
1244
    Compiler *compiler = nullptr;
 
1245
    if (!target)
 
1246
    {
 
1247
        if (project)
 
1248
            compiler = CompilerFactory::GetCompiler(project->GetCompilerID());
 
1249
        if (!compiler)
 
1250
            compiler = CompilerFactory::GetDefaultCompiler();
 
1251
        if (!compiler)
 
1252
        {
 
1253
            log->LogError(_("Can't get the compiler for the active target, nor the project, nor the default one!"));
 
1254
            m_menuHandler->MarkActiveTargetAsValid(false);
 
1255
            return;
 
1256
        }
 
1257
    }
 
1258
    else
 
1259
    {
 
1260
        compiler = CompilerFactory::GetCompiler(target->GetCompilerID());
 
1261
        if (!compiler)
 
1262
        {
 
1263
            log->LogError(wxString::Format(_("Current target '%s' doesn't have valid compiler!"),
 
1264
                                           target->GetTitle().c_str()));
 
1265
            m_menuHandler->MarkActiveTargetAsValid(false);
 
1266
            return;
 
1267
        }
 
1268
    }
 
1269
    wxString dbgString = compiler->GetPrograms().DBGconfig;
 
1270
    wxString::size_type pos = dbgString.find(wxT(':'));
 
1271
 
 
1272
    wxString name, config;
 
1273
    if (pos != wxString::npos)
 
1274
    {
 
1275
        name = dbgString.substr(0, pos);
 
1276
        config = dbgString.substr(pos + 1, dbgString.length() - pos - 1);
 
1277
    }
 
1278
 
 
1279
    if (name.empty() || config.empty())
 
1280
    {
 
1281
        log->LogError(wxString::Format(_("Current compiler '%s' doesn't have correctly defined debugger!"),
 
1282
                                       compiler->GetName().c_str()));
 
1283
        m_menuHandler->MarkActiveTargetAsValid(false);
 
1284
        return;
 
1285
    }
 
1286
 
 
1287
    for (RegisteredPlugins::iterator it = m_registered.begin(); it != m_registered.end(); ++it)
 
1288
    {
 
1289
        PluginData &data = it->second;
 
1290
        if (it->first->GetSettingsName() == name)
 
1291
        {
 
1292
            ConfigurationVector &configs = data.GetConfigurations();
 
1293
            int index = 0;
 
1294
            for (ConfigurationVector::iterator itConf = configs.begin(); itConf != configs.end(); ++itConf, ++index)
 
1295
            {
 
1296
                if ((*itConf)->GetName() == config)
 
1297
                {
 
1298
                    m_activeDebugger = it->first;
 
1299
                    m_activeDebugger->SetActiveConfig(index);
 
1300
                    m_useTargetsDefault = true;
 
1301
 
 
1302
                    WriteActiveDebuggerConfig(wxEmptyString, -1);
 
1303
                    RefreshUI();
 
1304
                    m_menuHandler->MarkActiveTargetAsValid(true);
 
1305
                    return;
 
1306
                }
 
1307
            }
 
1308
        }
 
1309
    }
 
1310
 
 
1311
    wxString targetTitle(target ? target->GetTitle() : wxT("<nullptr>"));
 
1312
    log->LogError(wxString::Format(_("Can't find the debugger config: '%s:%s' for the current target '%s'!"),
 
1313
                                   name.c_str(), config.c_str(),
 
1314
                                   targetTitle.c_str()));
 
1315
    m_menuHandler->MarkActiveTargetAsValid(false);
 
1316
}
 
1317
 
 
1318
bool DebuggerManager::IsDisassemblyMixedMode()
 
1319
{
 
1320
    return m_isDisassemblyMixedMode;
 
1321
}
 
1322
 
 
1323
void DebuggerManager::SetDisassemblyMixedMode(bool mixed)
 
1324
{
 
1325
    m_isDisassemblyMixedMode = mixed;
 
1326
}
 
1327
 
 
1328
void DebuggerManager::OnProjectActivated(cb_unused CodeBlocksEvent& event)
 
1329
{
 
1330
    if (m_useTargetsDefault)
 
1331
        FindTargetsDebugger();
 
1332
}
 
1333
 
 
1334
void DebuggerManager::OnTargetSelected(cb_unused CodeBlocksEvent& event)
 
1335
{
 
1336
    if (m_useTargetsDefault)
 
1337
        FindTargetsDebugger();
 
1338
}
 
1339
 
 
1340
void DebuggerManager::OnSettingsChanged(CodeBlocksEvent& event)
 
1341
{
 
1342
    if (event.GetInt() == cbSettingsType::Compiler || event.GetInt() == cbSettingsType::Debugger)
 
1343
    {
 
1344
        if (m_useTargetsDefault)
 
1345
            FindTargetsDebugger();
 
1346
    }
 
1347
}
 
1348
 
 
1349
void DebuggerManager::OnPluginLoadingComplete(cb_unused CodeBlocksEvent& event)
 
1350
{
 
1351
    RefreshUI();
 
1352
    if (!m_activeDebugger)
 
1353
    {
 
1354
        m_useTargetsDefault = true;
 
1355
        FindTargetsDebugger();
 
1356
    }
 
1357
}