1 /*
2 * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3 * http://www.gnu.org/licenses/gpl-3.0.html
4 *
5 * $Revision: 11130 $
6 * $Id: examinememorydlg.cpp 11130 2017-08-06 11:31:43Z fuscated $
7 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/src/examinememorydlg.cpp $
8 */
9
10 #include "sdk.h"
11
12 #ifndef CB_PRECOMP
13 #include <wx/button.h>
14 #include <wx/combobox.h>
15 #include <wx/intl.h>
16 #include <wx/textctrl.h>
17 #include <wx/xrc/xmlres.h>
18
19 #include "cbplugin.h"
20 #endif
21
22 #include "examinememorydlg.h"
23 #include "debuggermanager.h"
24
BEGIN_EVENT_TABLE(ExamineMemoryDlg,wxPanel)25 BEGIN_EVENT_TABLE(ExamineMemoryDlg, wxPanel)
26 EVT_BUTTON(XRCID("btnGo"), ExamineMemoryDlg::OnGo)
27 EVT_COMBOBOX(XRCID("cmbBytes"), ExamineMemoryDlg::OnGo)
28 EVT_TEXT_ENTER(XRCID("txtAddress"), ExamineMemoryDlg::OnGo)
29 END_EVENT_TABLE()
30
31 ExamineMemoryDlg::ExamineMemoryDlg(wxWindow* parent) :
32 m_LastRowStartingAddress(0)
33 {
34 //ctor
35 if (!wxXmlResource::Get()->LoadPanel(this, parent, _T("MemoryDumpPanel")))
36 return;
37 m_pText = XRCCTRL(*this, "txtDump", wxTextCtrl);
38
39 wxFont font(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
40 m_pText->SetFont(font);
41
42 ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
43 int bytes = c->ReadInt(wxT("/common/examine_memory/size_to_show"), 32);
44 wxString strBytes;
45 strBytes << bytes;
46 wxComboBox *combo = XRCCTRL(*this, "cmbBytes", wxComboBox);
47 if (!combo->SetStringSelection(strBytes))
48 combo->SetSelection(1); // Default is 32 bytes
49
50 Clear();
51 }
52
Begin()53 void ExamineMemoryDlg::Begin()
54 {
55 m_pText->Freeze();
56 }
57
End()58 void ExamineMemoryDlg::End()
59 {
60 m_pText->Thaw();
61 }
62
Clear()63 void ExamineMemoryDlg::Clear()
64 {
65 m_pText->Clear();
66 m_LastRowStartingAddress = 0;
67 m_ByteCounter = 0;
68 for (int i = 0; i < 67; ++i)
69 m_LineText[i] = _T(' ');
70 }
71
GetBaseAddress()72 wxString ExamineMemoryDlg::GetBaseAddress()
73 {
74 return XRCCTRL(*this, "txtAddress", wxTextCtrl)->GetValue();
75 }
76
GetBytes()77 int ExamineMemoryDlg::GetBytes()
78 {
79 long a;
80 XRCCTRL(*this, "cmbBytes", wxComboBox)->GetValue().ToLong(&a);
81 return a;
82 }
83
AddError(const wxString & err)84 void ExamineMemoryDlg::AddError(const wxString& err)
85 {
86 m_pText->AppendText(err + _T('\n'));
87 }
88
AddHexByte(const wxString & addr,const wxString & hexbyte)89 void ExamineMemoryDlg::AddHexByte(const wxString& addr, const wxString& hexbyte)
90 {
91 // m_pDbg->Log(_T("AddHexByte(") + addr + _T(", ") + hexbyte + _T(')'));
92 int bcmod = m_ByteCounter % 16;
93
94 if (m_LastRowStartingAddress == 0)
95 {
96 // because we 'll be appending each row *after* we have consumed it
97 // and then "addr" will point to the next row's starting address,
98 // we 'll keep the current row's starting address in "m_LastRowStartingAddress".
99
100 // if it's zero (i.e this is the first row), keep "addr" as starting address for this row.
101 // m_LastRowStartingAddress will be set again when we 've consumed this row...
102 addr.ToULong(&m_LastRowStartingAddress, 16);
103 }
104
105 #define HEX_OFFSET(a) (a*3)
106 #define CHAR_OFFSET(a) (16*3 + 3 + a)
107
108 unsigned long hb;
109 hexbyte.ToULong(&hb, 16);
110 // m_pDbg->Log(wxString::Format(_T("hb=%d, [0]=%c, [1]=%c"), hb, hexbyte[0], hexbyte[1]));
111 // m_pDbg->Log(wxString::Format(_T("HEX_OFFSET(bcmod)=%d, CHAR_OFFSET(bcmod)=%d"), HEX_OFFSET(bcmod), CHAR_OFFSET(bcmod)));
112 m_LineText[HEX_OFFSET(bcmod)] = hexbyte[0];
113 m_LineText[HEX_OFFSET(bcmod) + 1] = hexbyte[1];
114 m_LineText[CHAR_OFFSET(bcmod)] = hb >= 32 ? wxChar(hb) : wxChar(_T('.'));
115 ++m_ByteCounter;
116
117 // flush every 16 bytes
118 if (m_ByteCounter != 0 && m_ByteCounter % 16 == 0)
119 {
120 // filled 16 bytes window; append text and reset accumulator array
121 if (m_ByteCounter != 16) // after the first line,
122 m_pText->AppendText(_T('\n')); // prepend a newline
123 m_LineText[23] = _T('|'); // put a "separator" in the middle (just to ease reading a bit)
124
125 unsigned long a;
126 addr.ToULong(&a, 16);
127 m_pText->AppendText(wxString::Format(_T("0x%lx: %.67s"), m_LastRowStartingAddress, m_LineText));
128 for (int i = 0; i < 67; ++i)
129 m_LineText[i] = _T(' ');
130 // update starting address for next row
131 // add 8 bytes: addr is the start address of the second 8-byte chunk of this line, so next line is +8
132 m_LastRowStartingAddress = a + 8;
133 }
134 }
135
OnGo(cb_unused wxCommandEvent & event)136 void ExamineMemoryDlg::OnGo(cb_unused wxCommandEvent& event)
137 {
138 cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
139
140 // Save the value of the bytes combo box in the config,
141 // so it is the same next time the dialog is used.
142 ConfigManager *c = Manager::Get()->GetConfigManager(wxT("debugger_common"));
143 c->Write(wxT("/common/examine_memory/size_to_show"), GetBytes());
144
145 if (plugin)
146 plugin->RequestUpdate(cbDebuggerPlugin::ExamineMemory);
147 }
148
EnableWindow(bool enable)149 void ExamineMemoryDlg::EnableWindow(bool enable)
150 {
151 Enable(enable);
152 }
153
SetBaseAddress(const wxString & addr)154 void ExamineMemoryDlg::SetBaseAddress(const wxString &addr)
155 {
156 XRCCTRL(*this, "txtAddress", wxTextCtrl)->SetValue(addr);
157
158 cbDebuggerPlugin *plugin = Manager::Get()->GetDebuggerManager()->GetActiveDebugger();
159 if (plugin)
160 plugin->RequestUpdate(cbDebuggerPlugin::ExamineMemory);
161
162 }
163