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