1 /*
2 * This file is part of HexEditor plugin for Code::Blocks Studio
3 * Copyright (C) 2008-2009 Bartlomiej Swiecki
4 *
5 * HexEditor plugin is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * HexEditor pluging is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with HexEditor. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * $Revision: 11221 $
19 * $Id: HexEditPanel.cpp 11221 2017-10-31 07:56:15Z fuscated $
20 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/plugins/contrib/HexEditor/HexEditPanel.cpp $
21 */
22 #include <sdk.h>
23
24 #ifndef CB_PRECOMP
25 #include <wx/dcclient.h>
26 #include <wx/filedlg.h>
27 #include <wx/filename.h>
28 #include <wx/sizer.h>
29 #include <wx/choicdlg.h>
30
31 #include <manager.h>
32 #include <editormanager.h>
33 #include <configmanager.h>
34 #include <logmanager.h>
35 #include <globals.h>
36 #include "prep.h"
37 #endif // CB_PRECOMP
38
39 #include <wx/dcbuffer.h>
40 #include <wx/numdlg.h>
41
42 #include "HexEditPanel.h"
43 #include "ExpressionTester.h"
44 #include "SelectStoredExpressionDlg.h"
45 #include "ExpressionExecutor.h"
46 #include "ExpressionParser.h"
47 #include "CharacterView.h"
48 #include "DigitView.h"
49 #include "HexEditLineBuffer.h"
50
51 #include "ExpressionTestCases.h"
52 #include "FileContentDisk.h"
53 #include "TestCasesDlg.h"
54 #include "SearchDialog.h"
55
56 //(*InternalHeaders(HexEditPanel)
57 #include <wx/string.h>
58 #include <wx/intl.h>
59 //*)
60
61
62 namespace
63 {
NWD(int a,int b)64 inline int NWD( int a, int b )
65 {
66 while ( b )
67 {
68 int c = a % b;
69 a = b;
70 b = c;
71 }
72 return a;
73 }
74 }
75
76 //(*IdInit(HexEditPanel)
77 const long HexEditPanel::ID_STATICTEXT1 = wxNewId();
78 const long HexEditPanel::ID_BUTTON10 = wxNewId();
79 const long HexEditPanel::ID_BUTTON9 = wxNewId();
80 const long HexEditPanel::ID_STATICLINE2 = wxNewId();
81 const long HexEditPanel::ID_BUTTON7 = wxNewId();
82 const long HexEditPanel::ID_BUTTON4 = wxNewId();
83 const long HexEditPanel::ID_BUTTON6 = wxNewId();
84 const long HexEditPanel::ID_BUTTON5 = wxNewId();
85 const long HexEditPanel::ID_STATICLINE1 = wxNewId();
86 const long HexEditPanel::ID_BUTTON1 = wxNewId();
87 const long HexEditPanel::ID_BUTTON8 = wxNewId();
88 const long HexEditPanel::ID_CHECKBOX1 = wxNewId();
89 const long HexEditPanel::ID_PANEL1 = wxNewId();
90 const long HexEditPanel::ID_SCROLLBAR1 = wxNewId();
91 const long HexEditPanel::ID_STATICTEXT2 = wxNewId();
92 const long HexEditPanel::ID_STATICTEXT3 = wxNewId();
93 const long HexEditPanel::ID_STATICTEXT4 = wxNewId();
94 const long HexEditPanel::ID_STATICTEXT5 = wxNewId();
95 const long HexEditPanel::ID_STATICTEXT6 = wxNewId();
96 const long HexEditPanel::ID_STATICTEXT7 = wxNewId();
97 const long HexEditPanel::ID_STATICTEXT8 = wxNewId();
98 const long HexEditPanel::ID_STATICTEXT9 = wxNewId();
99 const long HexEditPanel::ID_STATICTEXT10 = wxNewId();
100 const long HexEditPanel::ID_STATICTEXT11 = wxNewId();
101 const long HexEditPanel::ID_STATICTEXT12 = wxNewId();
102 const long HexEditPanel::ID_STATICTEXT13 = wxNewId();
103 const long HexEditPanel::ID_STATICTEXT14 = wxNewId();
104 const long HexEditPanel::ID_TEXTCTRL1 = wxNewId();
105 const long HexEditPanel::ID_BUTTON3 = wxNewId();
106 const long HexEditPanel::ID_BUTTON2 = wxNewId();
107 const long HexEditPanel::ID_STATICTEXT15 = wxNewId();
108 const long HexEditPanel::ID_TIMER1 = wxNewId();
109 const long HexEditPanel::ID_MENUITEM2 = wxNewId();
110 const long HexEditPanel::ID_MENUITEM1 = wxNewId();
111 const long HexEditPanel::ID_MENUITEM3 = wxNewId();
112 const long HexEditPanel::ID_MENUITEM4 = wxNewId();
113 const long HexEditPanel::ID_MENUITEM5 = wxNewId();
114 const long HexEditPanel::ID_MENUITEM6 = wxNewId();
115 const long HexEditPanel::ID_MENUITEM7 = wxNewId();
116 const long HexEditPanel::ID_MENUITEM8 = wxNewId();
117 const long HexEditPanel::ID_MENUITEM9 = wxNewId();
118 const long HexEditPanel::ID_MENUITEM11 = wxNewId();
119 const long HexEditPanel::ID_MENUITEM12 = wxNewId();
120 const long HexEditPanel::ID_MENUITEM13 = wxNewId();
121 const long HexEditPanel::ID_MENUITEM14 = wxNewId();
122 const long HexEditPanel::ID_MENUITEM15 = wxNewId();
123 const long HexEditPanel::ID_MENUITEM16 = wxNewId();
124 const long HexEditPanel::ID_MENUITEM17 = wxNewId();
125 const long HexEditPanel::ID_MENUITEM18 = wxNewId();
126 const long HexEditPanel::ID_MENUITEM32 = wxNewId();
127 const long HexEditPanel::ID_MENUITEM10 = wxNewId();
128 const long HexEditPanel::ID_MENUITEM20 = wxNewId();
129 const long HexEditPanel::ID_MENUITEM21 = wxNewId();
130 const long HexEditPanel::ID_MENUITEM22 = wxNewId();
131 const long HexEditPanel::ID_MENUITEM23 = wxNewId();
132 const long HexEditPanel::ID_MENUITEM24 = wxNewId();
133 const long HexEditPanel::ID_MENUITEM25 = wxNewId();
134 const long HexEditPanel::ID_MENUITEM26 = wxNewId();
135 const long HexEditPanel::ID_MENUITEM27 = wxNewId();
136 const long HexEditPanel::ID_MENUITEM19 = wxNewId();
137 const long HexEditPanel::ID_MENUITEM29 = wxNewId();
138 const long HexEditPanel::ID_MENUITEM30 = wxNewId();
139 const long HexEditPanel::ID_MENUITEM31 = wxNewId();
140 const long HexEditPanel::ID_MENUITEM33 = wxNewId();
141 const long HexEditPanel::ID_MENUITEM28 = wxNewId();
142 //*)
143
144 BEGIN_EVENT_TABLE(HexEditPanel,EditorBase)
145 //(*EventTable(HexEditPanel)
146 //*)
147 END_EVENT_TABLE()
148
149 HexEditPanel::EditorsSet HexEditPanel::m_AllEditors;
150
HexEditPanel(const wxString & fileName,const wxString & title)151 HexEditPanel::HexEditPanel( const wxString& fileName, const wxString& title )
152 : EditorBase( (wxWindow*)Manager::Get()->GetEditorManager()->GetNotebook(), fileName )
153 , m_FileName( fileName )
154 , m_Content( 0 )
155 , m_DrawFont( 0 )
156 , m_Current( 0 )
157 , m_MouseDown( false )
158 , m_ColsMode( CM_ANY )
159 {
160 /*
161 --- Begin of comment which prevents calling Create() --
162
163 //(*Initialize(HexEditPanel)
164 Create(parent, wxID_ANY, wxDefaultPosition, wxSize(79,51), wxTAB_TRAVERSAL, _T("wxID_ANY"));
165
166 --- End of comment which prevents calling Create() --
167 */
168
169 BoxSizer1 = new wxBoxSizer(wxVERTICAL);
170 BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
171 m_Status = new wxStaticText(this, ID_STATICTEXT1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
172 BoxSizer3->Add(m_Status, 1, wxALL|wxEXPAND, 5);
173 Button6 = new wxButton(this, ID_BUTTON10, _("Goto"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON10"));
174 BoxSizer3->Add(Button6, 0, wxALIGN_CENTER_VERTICAL, 5);
175 Button5 = new wxButton(this, ID_BUTTON9, _("Search"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON9"));
176 BoxSizer3->Add(Button5, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
177 StaticLine2 = new wxStaticLine(this, ID_STATICLINE2, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL, _T("ID_STATICLINE2"));
178 BoxSizer3->Add(StaticLine2, 0, wxALL|wxEXPAND, 5);
179 m_ColsModeBtn = new wxButton(this, ID_BUTTON7, _("Cols"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON7"));
180 BoxSizer3->Add(m_ColsModeBtn, 0, wxALIGN_CENTER_VERTICAL, 5);
181 m_DigitBits = new wxButton(this, ID_BUTTON4, _("Hex"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON4"));
182 BoxSizer3->Add(m_DigitBits, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
183 m_BlockSize = new wxButton(this, ID_BUTTON6, _("1B"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON6"));
184 BoxSizer3->Add(m_BlockSize, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
185 m_Endianess = new wxButton(this, ID_BUTTON5, _("BE"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON5"));
186 BoxSizer3->Add(m_Endianess, 0, wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
187 StaticLine1 = new wxStaticLine(this, ID_STATICLINE1, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL, _T("ID_STATICLINE1"));
188 BoxSizer3->Add(StaticLine1, 0, wxALL|wxEXPAND, 5);
189 Button1 = new wxButton(this, ID_BUTTON1, _("Calc"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON1"));
190 BoxSizer3->Add(Button1, 0, wxALIGN_CENTER_VERTICAL, 5);
191 Button4 = new wxButton(this, ID_BUTTON8, _("Test"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON8"));
192 BoxSizer3->Add(Button4, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
193 CheckBox1 = new wxCheckBox(this, ID_CHECKBOX1, _("Value preview"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_CHECKBOX1"));
194 CheckBox1->SetValue(true);
195 BoxSizer3->Add(CheckBox1, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5);
196 BoxSizer1->Add(BoxSizer3, 0, wxEXPAND, 5);
197 BoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
198 m_DrawArea = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS|wxFULL_REPAINT_ON_RESIZE, _T("ID_PANEL1"));
199 BoxSizer2->Add(m_DrawArea, 1, wxEXPAND, 5);
200 m_ContentScroll = new wxScrollBar(this, ID_SCROLLBAR1, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL, wxDefaultValidator, _T("ID_SCROLLBAR1"));
201 m_ContentScroll->SetScrollbar(0, 1, 1, 1);
202 BoxSizer2->Add(m_ContentScroll, 0, wxEXPAND, 0);
203 BoxSizer1->Add(BoxSizer2, 1, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 5);
204 PreviewSizer = new wxBoxSizer(wxVERTICAL);
205 FlexGridSizer1 = new wxFlexGridSizer(0, 8, 5, 5);
206 FlexGridSizer1->AddGrowableCol(1);
207 FlexGridSizer1->AddGrowableCol(4);
208 FlexGridSizer1->AddGrowableCol(7);
209 StaticText1 = new wxStaticText(this, ID_STATICTEXT2, _("Byte:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT2"));
210 FlexGridSizer1->Add(StaticText1, 1, wxEXPAND, 5);
211 m_ByteVal = new wxStaticText(this, ID_STATICTEXT3, _("-9999999999"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT3"));
212 FlexGridSizer1->Add(m_ByteVal, 1, wxEXPAND, 5);
213 FlexGridSizer1->Add(5,5,1, wxALIGN_CENTER_VERTICAL, 5);
214 StaticText3 = new wxStaticText(this, ID_STATICTEXT4, _("Word:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT4"));
215 FlexGridSizer1->Add(StaticText3, 1, wxEXPAND, 5);
216 m_WordVal = new wxStaticText(this, ID_STATICTEXT5, _("-9999999999"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT5"));
217 FlexGridSizer1->Add(m_WordVal, 1, wxEXPAND, 5);
218 FlexGridSizer1->Add(5,5,1, wxALIGN_CENTER_VERTICAL, 5);
219 StaticText2 = new wxStaticText(this, ID_STATICTEXT6, _("Dword:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT6"));
220 FlexGridSizer1->Add(StaticText2, 1, wxEXPAND, 5);
221 m_DwordVal = new wxStaticText(this, ID_STATICTEXT7, _("-9999999999"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT7"));
222 FlexGridSizer1->Add(m_DwordVal, 1, wxEXPAND, 5);
223 StaticText4 = new wxStaticText(this, ID_STATICTEXT8, _("Float:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT8"));
224 FlexGridSizer1->Add(StaticText4, 1, wxEXPAND, 5);
225 m_FloatVal = new wxStaticText(this, ID_STATICTEXT9, _("-9999999999"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT9"));
226 FlexGridSizer1->Add(m_FloatVal, 1, wxEXPAND, 5);
227 FlexGridSizer1->Add(5,5,1, wxALIGN_CENTER_VERTICAL, 5);
228 StaticText6 = new wxStaticText(this, ID_STATICTEXT10, _("Double:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT10"));
229 FlexGridSizer1->Add(StaticText6, 1, wxEXPAND, 5);
230 m_DoubleVal = new wxStaticText(this, ID_STATICTEXT11, _("-9999999999"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT11"));
231 FlexGridSizer1->Add(m_DoubleVal, 1, wxEXPAND, 5);
232 FlexGridSizer1->Add(5,5,1, wxALIGN_CENTER_VERTICAL, 5);
233 StaticText8 = new wxStaticText(this, ID_STATICTEXT12, _("L-Double:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT12"));
234 FlexGridSizer1->Add(StaticText8, 1, wxEXPAND, 5);
235 m_LDoubleVal = new wxStaticText(this, ID_STATICTEXT13, _("-9999999999"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT13"));
236 FlexGridSizer1->Add(m_LDoubleVal, 1, wxEXPAND, 5);
237 PreviewSizer->Add(FlexGridSizer1, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 5);
238 BoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
239 StaticText5 = new wxStaticText(this, ID_STATICTEXT14, _("Expression:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT14"));
240 BoxSizer4->Add(StaticText5, 0, wxALIGN_CENTER_VERTICAL, 5);
241 m_Expression = new wxTextCtrl(this, ID_TEXTCTRL1, _("byte[ @ ]"), wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER, wxDefaultValidator, _T("ID_TEXTCTRL1"));
242 BoxSizer4->Add(m_Expression, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
243 Button3 = new wxButton(this, ID_BUTTON3, _("v"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON3"));
244 BoxSizer4->Add(Button3, 0, wxRIGHT|wxEXPAND, 5);
245 Button2 = new wxButton(this, ID_BUTTON2, _("\?"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT, wxDefaultValidator, _T("ID_BUTTON2"));
246 BoxSizer4->Add(Button2, 0, wxRIGHT|wxEXPAND, 5);
247 m_ExpressionVal = new wxStaticText(this, ID_STATICTEXT15, _("-9999999999"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT15"));
248 BoxSizer4->Add(m_ExpressionVal, 1, wxLEFT|wxALIGN_CENTER_VERTICAL, 5);
249 PreviewSizer->Add(BoxSizer4, 0, wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND, 5);
250 BoxSizer1->Add(PreviewSizer, 0, wxEXPAND, 5);
251 SetSizer(BoxSizer1);
252 ReparseTimer.SetOwner(this, ID_TIMER1);
253 MenuItem2 = new wxMenuItem((&m_BaseMenu), ID_MENUITEM2, _("Bin"), wxEmptyString, wxITEM_NORMAL);
254 m_BaseMenu.Append(MenuItem2);
255 MenuItem1 = new wxMenuItem((&m_BaseMenu), ID_MENUITEM1, _("Hex"), wxEmptyString, wxITEM_NORMAL);
256 m_BaseMenu.Append(MenuItem1);
257 MenuItem3 = new wxMenuItem((&m_EndianessMenu), ID_MENUITEM3, _("Big Endian"), wxEmptyString, wxITEM_NORMAL);
258 m_EndianessMenu.Append(MenuItem3);
259 MenuItem4 = new wxMenuItem((&m_EndianessMenu), ID_MENUITEM4, _("Little Endian"), wxEmptyString, wxITEM_NORMAL);
260 m_EndianessMenu.Append(MenuItem4);
261 MenuItem5 = new wxMenuItem((&m_BlockSizeMenu), ID_MENUITEM5, _("1 Byte"), wxEmptyString, wxITEM_NORMAL);
262 m_BlockSizeMenu.Append(MenuItem5);
263 MenuItem6 = new wxMenuItem((&m_BlockSizeMenu), ID_MENUITEM6, _("2 Bytes"), wxEmptyString, wxITEM_NORMAL);
264 m_BlockSizeMenu.Append(MenuItem6);
265 MenuItem7 = new wxMenuItem((&m_BlockSizeMenu), ID_MENUITEM7, _("4 Bytes"), wxEmptyString, wxITEM_NORMAL);
266 m_BlockSizeMenu.Append(MenuItem7);
267 MenuItem8 = new wxMenuItem((&m_BlockSizeMenu), ID_MENUITEM8, _("8 Bytes"), wxEmptyString, wxITEM_NORMAL);
268 m_BlockSizeMenu.Append(MenuItem8);
269 MenuItem9 = new wxMenuItem((&m_ColsModeMenu), ID_MENUITEM9, _("Any"), wxEmptyString, wxITEM_NORMAL);
270 m_ColsModeMenu.Append(MenuItem9);
271 MenuItem10 = new wxMenu();
272 MenuItem11 = new wxMenuItem(MenuItem10, ID_MENUITEM11, _("1"), wxEmptyString, wxITEM_NORMAL);
273 MenuItem10->Append(MenuItem11);
274 MenuItem12 = new wxMenuItem(MenuItem10, ID_MENUITEM12, _("2"), wxEmptyString, wxITEM_NORMAL);
275 MenuItem10->Append(MenuItem12);
276 MenuItem13 = new wxMenuItem(MenuItem10, ID_MENUITEM13, _("3"), wxEmptyString, wxITEM_NORMAL);
277 MenuItem10->Append(MenuItem13);
278 MenuItem14 = new wxMenuItem(MenuItem10, ID_MENUITEM14, _("4"), wxEmptyString, wxITEM_NORMAL);
279 MenuItem10->Append(MenuItem14);
280 MenuItem15 = new wxMenuItem(MenuItem10, ID_MENUITEM15, _("5"), wxEmptyString, wxITEM_NORMAL);
281 MenuItem10->Append(MenuItem15);
282 MenuItem16 = new wxMenuItem(MenuItem10, ID_MENUITEM16, _("6"), wxEmptyString, wxITEM_NORMAL);
283 MenuItem10->Append(MenuItem16);
284 MenuItem17 = new wxMenuItem(MenuItem10, ID_MENUITEM17, _("7"), wxEmptyString, wxITEM_NORMAL);
285 MenuItem10->Append(MenuItem17);
286 MenuItem18 = new wxMenuItem(MenuItem10, ID_MENUITEM18, _("8"), wxEmptyString, wxITEM_NORMAL);
287 MenuItem10->Append(MenuItem18);
288 MenuItem10->AppendSeparator();
289 MenuItem32 = new wxMenuItem(MenuItem10, ID_MENUITEM32, _("Other"), wxEmptyString, wxITEM_NORMAL);
290 MenuItem10->Append(MenuItem32);
291 m_ColsModeMenu.Append(ID_MENUITEM10, _("Exactly"), MenuItem10, wxEmptyString);
292 MenuItem19 = new wxMenu();
293 MenuItem20 = new wxMenuItem(MenuItem19, ID_MENUITEM20, _("2"), wxEmptyString, wxITEM_NORMAL);
294 MenuItem19->Append(MenuItem20);
295 MenuItem21 = new wxMenuItem(MenuItem19, ID_MENUITEM21, _("3"), wxEmptyString, wxITEM_NORMAL);
296 MenuItem19->Append(MenuItem21);
297 MenuItem22 = new wxMenuItem(MenuItem19, ID_MENUITEM22, _("4"), wxEmptyString, wxITEM_NORMAL);
298 MenuItem19->Append(MenuItem22);
299 MenuItem23 = new wxMenuItem(MenuItem19, ID_MENUITEM23, _("5"), wxEmptyString, wxITEM_NORMAL);
300 MenuItem19->Append(MenuItem23);
301 MenuItem24 = new wxMenuItem(MenuItem19, ID_MENUITEM24, _("6"), wxEmptyString, wxITEM_NORMAL);
302 MenuItem19->Append(MenuItem24);
303 MenuItem25 = new wxMenuItem(MenuItem19, ID_MENUITEM25, _("7"), wxEmptyString, wxITEM_NORMAL);
304 MenuItem19->Append(MenuItem25);
305 MenuItem26 = new wxMenuItem(MenuItem19, ID_MENUITEM26, _("8"), wxEmptyString, wxITEM_NORMAL);
306 MenuItem19->Append(MenuItem26);
307 MenuItem19->AppendSeparator();
308 MenuItem27 = new wxMenuItem(MenuItem19, ID_MENUITEM27, _("Other"), wxEmptyString, wxITEM_NORMAL);
309 MenuItem19->Append(MenuItem27);
310 m_ColsModeMenu.Append(ID_MENUITEM19, _("Multiple of"), MenuItem19, wxEmptyString);
311 MenuItem28 = new wxMenu();
312 MenuItem29 = new wxMenuItem(MenuItem28, ID_MENUITEM29, _("2"), wxEmptyString, wxITEM_NORMAL);
313 MenuItem28->Append(MenuItem29);
314 MenuItem30 = new wxMenuItem(MenuItem28, ID_MENUITEM30, _("4"), wxEmptyString, wxITEM_NORMAL);
315 MenuItem28->Append(MenuItem30);
316 MenuItem31 = new wxMenuItem(MenuItem28, ID_MENUITEM31, _("8"), wxEmptyString, wxITEM_NORMAL);
317 MenuItem28->Append(MenuItem31);
318 MenuItem28->AppendSeparator();
319 MenuItem33 = new wxMenuItem(MenuItem28, ID_MENUITEM33, _("Other"), wxEmptyString, wxITEM_NORMAL);
320 MenuItem28->Append(MenuItem33);
321 m_ColsModeMenu.Append(ID_MENUITEM28, _("Power of"), MenuItem28, wxEmptyString);
322 SetSizer(BoxSizer1);
323 Layout();
324
325 Connect(ID_BUTTON10,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnButton6Click);
326 Connect(ID_BUTTON9,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnButton5Click);
327 Connect(ID_BUTTON7,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::Onm_ColsModeClick);
328 Connect(ID_BUTTON4,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnButton4Click);
329 Connect(ID_BUTTON6,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::Onm_BlockSizeClick);
330 Connect(ID_BUTTON5,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::Onm_EndianessClick);
331 Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnButton1Click);
332 Connect(ID_BUTTON8,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnButton4Click1);
333 Connect(ID_CHECKBOX1,wxEVT_COMMAND_CHECKBOX_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnCheckBox1Click);
334 m_DrawArea->Connect(wxEVT_PAINT,(wxObjectEventFunction)&HexEditPanel::OnContentPaint,0,this);
335 m_DrawArea->Connect(wxEVT_ERASE_BACKGROUND,(wxObjectEventFunction)&HexEditPanel::OnDrawAreaEraseBackground,0,this);
336 m_DrawArea->Connect(wxEVT_KEY_DOWN,(wxObjectEventFunction)&HexEditPanel::OnSpecialKeyDown,0,this);
337 m_DrawArea->Connect(wxEVT_CHAR,(wxObjectEventFunction)&HexEditPanel::OnDrawAreaKeyDown,0,this);
338 m_DrawArea->Connect(wxEVT_LEFT_DOWN,(wxObjectEventFunction)&HexEditPanel::OnDrawAreaLeftDown,0,this);
339 m_DrawArea->Connect(wxEVT_LEFT_UP,(wxObjectEventFunction)&HexEditPanel::OnDrawAreaLeftUp,0,this);
340 m_DrawArea->Connect(wxEVT_MOTION,(wxObjectEventFunction)&HexEditPanel::OnDrawAreaMouseMove,0,this);
341 m_DrawArea->Connect(wxEVT_LEAVE_WINDOW,(wxObjectEventFunction)&HexEditPanel::OnDrawAreaLeftUp,0,this);
342 m_DrawArea->Connect(wxEVT_MOUSEWHEEL,(wxObjectEventFunction)&HexEditPanel::OnContentMouseWheel,0,this);
343 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_TOP,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
344 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_BOTTOM,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
345 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_LINEUP,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
346 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_LINEDOWN,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
347 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_PAGEUP,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
348 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_PAGEDOWN,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
349 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_THUMBTRACK,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
350 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_THUMBRELEASE,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
351 Connect(ID_SCROLLBAR1,wxEVT_SCROLL_CHANGED,(wxObjectEventFunction)&HexEditPanel::OnContentScroll);
352 Connect(ID_TEXTCTRL1,wxEVT_COMMAND_TEXT_UPDATED,(wxObjectEventFunction)&HexEditPanel::Onm_ExpressionText);
353 Connect(ID_TEXTCTRL1,wxEVT_COMMAND_TEXT_ENTER,(wxObjectEventFunction)&HexEditPanel::OnExpressionTextEnter);
354 Connect(ID_BUTTON3,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnButton3Click1);
355 Connect(ID_BUTTON2,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&HexEditPanel::OnButton2Click);
356 Connect(ID_TIMER1,wxEVT_TIMER,(wxObjectEventFunction)&HexEditPanel::OnReparseTimerTrigger);
357 Connect(ID_MENUITEM2,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetBaseBin);
358 Connect(ID_MENUITEM1,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetBaseHex);
359 Connect(ID_MENUITEM3,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetEndianessBig);
360 Connect(ID_MENUITEM4,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetEndianessLittle);
361 Connect(ID_MENUITEM5,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetBlockSize1);
362 Connect(ID_MENUITEM6,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetBlockSize2);
363 Connect(ID_MENUITEM7,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetBlockSize4);
364 Connect(ID_MENUITEM8,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetBlockSize8);
365 Connect(ID_MENUITEM9,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul1);
366 Connect(ID_MENUITEM11,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue1);
367 Connect(ID_MENUITEM12,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue2);
368 Connect(ID_MENUITEM13,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue3);
369 Connect(ID_MENUITEM14,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue4);
370 Connect(ID_MENUITEM15,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue5);
371 Connect(ID_MENUITEM16,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue6);
372 Connect(ID_MENUITEM17,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue7);
373 Connect(ID_MENUITEM18,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValue8);
374 Connect(ID_MENUITEM32,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsValueOther);
375 Connect(ID_MENUITEM20,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul2);
376 Connect(ID_MENUITEM21,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul3);
377 Connect(ID_MENUITEM22,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul4);
378 Connect(ID_MENUITEM23,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul5);
379 Connect(ID_MENUITEM24,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul6);
380 Connect(ID_MENUITEM25,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul7);
381 Connect(ID_MENUITEM26,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMul8);
382 Connect(ID_MENUITEM27,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsMulOther);
383 Connect(ID_MENUITEM29,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsPower2);
384 Connect(ID_MENUITEM30,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsPower4);
385 Connect(ID_MENUITEM31,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsPower8);
386 Connect(ID_MENUITEM33,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&HexEditPanel::OnSetColsPowerOther);
387 //*)
388
389 // We connect these events manually
390 m_DrawArea->Connect( wxEVT_SIZE, (wxObjectEventFunction)&HexEditPanel::OnContentSize, 0, this );
391 m_DrawArea->SetBackgroundStyle( wxBG_STYLE_CUSTOM );
392 Connect( wxEVT_SET_FOCUS, (wxObjectEventFunction)&HexEditPanel::OnForwardFocus );
393
394 m_ActiveView = 0;
395 m_LastScrollPos = 0;
396 m_LastScrollUnits = 0;
397 m_LinesPerScrollUnit = 1;
398 CreateViews();
399 m_NeedRecalc = true;
400
401 ReparseExpression();
402 SetFontSize( 8 );
403 ReadContent();
404
405 if ( m_Content && m_Content->GetSize() > 0x40000000ULL )
406 {
407 // Because of the filesize we have to map scroll units
408 // to some number of lines
409 m_LinesPerScrollUnit = m_Content->GetSize() / 0x20000000ULL;
410 }
411
412 RefreshStatus();
413
414 m_Current = 0;
415 PropagateOffsetChange();
416
417 m_DrawArea->SetFocus();
418
419 ((wxWindow*)Manager::Get()->GetEditorManager()->GetNotebook())->Layout();
420
421 m_Shortname = title;
422 SetTitle( m_Shortname );
423
424 m_AllEditors.insert( this );
425
426 }
427
CreateViews()428 void HexEditPanel::CreateViews()
429 {
430 for ( int i=0; i<MAX_VIEWS; ++i )
431 {
432 m_Views[ i ] = 0;
433 }
434
435 m_Views[ VIEW_DIGIT ] = m_DigitView = new DigitView( this );
436 m_Views[ VIEW_CHARS ] = new CharacterView( this );
437 ActivateView( m_Views[ 0 ] );
438 }
439
ActivateView(HexEditViewBase * view)440 void HexEditPanel::ActivateView( HexEditViewBase* view )
441 {
442 if ( view == m_ActiveView ) return;
443
444 if ( m_ActiveView )
445 {
446 m_ActiveView->SetActive( false );
447 }
448
449 m_ActiveView = view;
450 view->SetActive( true );
451 }
452
453
~HexEditPanel()454 HexEditPanel::~HexEditPanel()
455 {
456 for ( int i=0; i<MAX_VIEWS; ++i )
457 {
458 delete m_Views[ i ];
459 m_Views[ i ] = 0;
460 }
461
462 m_AllEditors.erase( this );
463
464 delete m_DrawFont;
465 m_DrawFont = 0;
466
467 delete m_Content;
468 m_Content = 0;
469
470 //(*Destroy(HexEditPanel)
471 //*)
472 }
473
SetFontSize(int size)474 void HexEditPanel::SetFontSize( int size )
475 {
476 delete m_DrawFont;
477 m_DrawFont = wxFont::New( size, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString, wxFONTENCODING_DEFAULT );
478 }
479
ReadContent()480 void HexEditPanel::ReadContent()
481 {
482 if ( m_Content ) delete m_Content;
483
484 m_Content = FileContentBase::BuildInstance( m_FileName );
485 if ( !m_Content )
486 {
487 m_ErrorString = _("Could not open the file (note that HexEditor may not be able to open big files)");
488 return;
489 }
490
491 if ( !m_Content->ReadFile( m_FileName ) )
492 {
493 delete m_Content;
494 m_Content = 0;
495 m_ErrorString = _("Could not read the file");
496 return;
497 }
498 }
499
RecalculateCoefs(wxDC & dc)500 void HexEditPanel::RecalculateCoefs(wxDC &dc)
501 {
502 if (!m_NeedRecalc)
503 return;
504 m_NeedRecalc = false;
505 dc.GetTextExtent( _T("0123456789ABCDEF"), &m_FontX, &m_FontY, NULL, NULL, m_DrawFont );
506 m_FontX /= 16;
507
508 // Calculate number of rows and columns in characters
509 wxSize size = m_DrawArea->GetClientSize();
510 m_Cols = size.GetWidth() / m_FontX;
511 m_Lines = size.GetHeight() / m_FontY;
512
513 // Calculate number of bytes in one line
514 double avgByteCharacters = 0.0;
515 int cumulativeBlockSize = 1;
516 for ( int i=0; i<MAX_VIEWS; ++i )
517 {
518 int blockLength;
519 int blockBytes;
520 int spacing;
521 m_Views[ i ]->GetBlockSizes( blockLength, blockBytes, spacing );
522
523 avgByteCharacters += ( (double)( blockLength + spacing ) ) / (double)blockBytes;
524 cumulativeBlockSize = cumulativeBlockSize * blockBytes / NWD( cumulativeBlockSize, blockBytes );
525 }
526
527 int colsLeftForViews =
528 m_Cols
529 - 8 // Offset
530 - 1 // ':' after offset
531 - 2 * MAX_VIEWS // spacing between views
532 - 2; // right margin
533
534 int maxByteInLine = (int)( colsLeftForViews / avgByteCharacters );
535
536 // Now we need to find such number of bytes to be multiple of cumulativeBlockSize
537 // and try not to cross maxByteInLine
538
539 // Additionally we try to match required columns count,
540 // this is a little bit naive approach but will work in generic way
541 int maxColumns = std::max( (int)(maxByteInLine / cumulativeBlockSize), 1 );
542 for ( int i=maxColumns;; i-- )
543 {
544 if ( i<1 )
545 {
546 for ( i=maxColumns+1; i<0x1000; ++i )
547 {
548 if ( MatchColumnsCount( i ) )
549 {
550 maxColumns = i;
551 break;
552 }
553 }
554 break;
555 }
556
557 if ( MatchColumnsCount( i ) )
558 {
559 maxColumns = i;
560 break;
561 }
562 }
563
564 m_ColsCount = maxColumns;
565 m_LineBytes = maxColumns * cumulativeBlockSize;
566
567 // Calculate column positions
568 for ( int i=0; i<MAX_VIEWS; ++i )
569 {
570 int blockLength;
571 int blockBytes;
572 int spacing;
573 m_Views[ i ]->GetBlockSizes( blockLength, blockBytes, spacing );
574 m_ViewsCols[ i ] = ( ( m_LineBytes + blockBytes - 1 ) / blockBytes ) * ( blockLength + spacing );
575 }
576
577 // Adjust scroll bar
578 OffsetT contentSize = m_Content ? m_Content->GetSize() : 0;
579
580 int totalLines = ( contentSize + m_LineBytes - 1 ) / m_LineBytes;
581 int totalUnits = ( totalLines + m_LinesPerScrollUnit - 1 ) / m_LinesPerScrollUnit;
582 int thumbLines = ( m_Lines + m_LinesPerScrollUnit - 1 ) / m_LinesPerScrollUnit;
583
584 m_ContentScroll->SetScrollbar(
585 m_ContentScroll->GetThumbPosition(),
586 thumbLines,
587 totalUnits,
588 thumbLines );
589 }
590
OnContentPaint(wxPaintEvent &)591 void HexEditPanel::OnContentPaint( wxPaintEvent& /*event*/ )
592 {
593 wxAutoBufferedPaintDC dc( m_DrawArea );
594 RecalculateCoefs( dc );
595 dc.SetBrush( GetBackgroundColour() );
596 dc.SetPen ( GetBackgroundColour() );
597 dc.DrawRectangle( GetClientRect() );
598
599 if ( !m_Content ) return;
600
601 dc.SetFont( *m_DrawFont );
602
603 OffsetT startOffs = DetectStartOffset();
604
605 HexEditLineBuffer buff( m_Cols );
606 char* content = new char[ m_Cols ];
607
608 wxColour backgrounds[ stCount ] =
609 {
610 GetBackgroundColour(),
611 wxColour( 0x70, 0x70, 0x70 ),
612 wxColour( 0xA0, 0xA0, 0xFF ),
613 wxColour( 0x80, 0x80, 0xFF ),
614 };
615
616 wxColour foregrounds[ stCount ] =
617 {
618 *wxBLACK,
619 *wxWHITE,
620 *wxWHITE,
621 *wxBLACK,
622 };
623
624
625 for ( OffsetT j = 0; j < m_Lines; ++j )
626 {
627 buff.Reset();
628
629 // Calculate offsets
630 OffsetT offs = startOffs + j * m_LineBytes;
631 OffsetT offsMax = offs + m_LineBytes;
632
633 // Add offset to view buffer
634 for ( size_t i=8; i-->0; )
635 {
636 buff.PutChar( "0123456789ABCDEF"[ ( offs >> ( i << 2 ) ) & 0xF ] );
637 }
638 buff.PutChar(':');
639
640 // Clamp offsets to content size
641 offs = wxMin( offs, m_Content->GetSize() );
642 offsMax = wxMin( offsMax, m_Content->GetSize() );
643
644 if ( offs == offsMax ) continue;
645
646 // Invoking views
647 m_Content->Read( content, offs, offsMax - offs );
648 for ( int i=0; i<MAX_VIEWS; ++i )
649 {
650 buff.PutString(" ");
651 m_Views[ i ]->PutLine( offs, buff, content, offsMax - offs );
652 }
653
654 buff.Draw( dc, 0, j * m_FontY, m_FontX, m_FontY, foregrounds, backgrounds );
655 }
656
657 delete[] content;
658 }
659
OnContentScroll(wxScrollEvent &)660 void HexEditPanel::OnContentScroll( wxScrollEvent& /*event*/ )
661 {
662 if ( !m_Content || !m_Content->GetSize() )
663 {
664 return;
665 }
666
667 if ( m_ContentScroll->GetThumbPosition() == 0 )
668 {
669 DetectStartOffset();
670 m_LastScrollPos = 0;
671 }
672 else if ( m_ContentScroll->GetThumbPosition() >= m_ContentScroll->GetRange() - m_ContentScroll->GetThumbSize() )
673 {
674 DetectStartOffset();
675 int totalLines = m_Content->GetSize() / m_LineBytes;
676 m_LastScrollPos = totalLines - m_Lines + 1;
677 }
678
679 ClampCursorToVisibleArea();
680 m_DrawArea->Refresh();
681 RefreshStatus();
682 m_DrawArea->SetFocus();
683 }
684
OnContentScrollTop(wxScrollEvent & event)685 void HexEditPanel::OnContentScrollTop(wxScrollEvent& event)
686 {
687 if ( !m_Content || !m_Content->GetSize() )
688 {
689 return;
690 }
691
692 m_LastScrollPos = 0;
693
694 LogManager::Get()->DebugLog( _T("Top") );
695
696 OnContentScroll( event );
697 }
698
OnContentScrollBottom(wxScrollEvent & event)699 void HexEditPanel::OnContentScrollBottom(wxScrollEvent& event)
700 {
701 if ( !m_Content || !m_Content->GetSize() )
702 {
703 return;
704 }
705
706 int totalLines = m_Content->GetSize() / m_LineBytes;
707 m_LastScrollPos = totalLines - m_Lines + 1;
708
709 LogManager::Get()->DebugLog( _T("Top") );
710
711 OnContentScroll( event );
712 }
713
OnContentSize(wxSizeEvent & event)714 void HexEditPanel::OnContentSize( wxSizeEvent& event )
715 {
716 m_NeedRecalc = true;
717 EnsureCarretVisible();
718 RefreshStatus();
719 event.Skip();
720 }
721
DetectStartOffset()722 FileContentBase::OffsetT HexEditPanel::DetectStartOffset()
723 {
724 if ( !m_Content ) return 0;
725
726 int currentUnits = m_ContentScroll->GetThumbPosition();
727
728 if ( currentUnits < m_LastScrollUnits )
729 {
730 FileContentBase::OffsetT diff = ( m_LastScrollUnits - currentUnits ) * m_LinesPerScrollUnit;
731 if ( m_LastScrollPos < diff )
732 {
733 m_LastScrollPos = 0;
734 }
735 else
736 {
737 m_LastScrollPos -= diff;
738 }
739 }
740 else if ( currentUnits > m_LastScrollUnits )
741 {
742 m_LastScrollPos += ( currentUnits - m_LastScrollUnits ) * m_LinesPerScrollUnit;
743 FileContentBase::OffsetT maxScrollPos = ( m_Content->GetSize() + m_LineBytes - 1 ) / m_LineBytes;
744 if ( m_LastScrollPos >= maxScrollPos )
745 {
746 m_LastScrollPos = maxScrollPos-1;
747 }
748 }
749
750 m_LastScrollUnits = currentUnits;
751
752 return m_LastScrollPos * m_LineBytes;
753 }
754
OnContentMouseWheel(wxMouseEvent & event)755 void HexEditPanel::OnContentMouseWheel(wxMouseEvent& event)
756 {
757 m_ContentScroll->SetThumbPosition(
758 m_ContentScroll->GetThumbPosition() -
759 2 * event.GetWheelRotation() / event.GetWheelDelta() );
760 ClampCursorToVisibleArea();
761 m_DrawArea->Refresh();
762 RefreshStatus();
763 }
764
RefreshStatus()765 void HexEditPanel::RefreshStatus()
766 {
767 if ( !m_Content )
768 {
769 m_Status->SetLabel( m_ErrorString );
770 return;
771 }
772
773 FileContentBase::OffsetT size = m_Content->GetSize();
774
775 if ( !size )
776 {
777 m_Status->SetLabel( _("File is empty") );
778 }
779 else
780 {
781 unsigned long long current_pos = m_Current + 1; // OffsetT = unsigned long long
782 m_Status->SetLabel( F( _("Position: %llX / %llX ( %lld%% )"), current_pos, size, ( current_pos * 100 / (size) ) ) );
783 }
784
785 FileContentBase::OffsetT left = size - m_Current;
786
787 if ( left >= sizeof( char ) )
788 {
789 char val;
790 m_Content->Read( &val, m_Current, sizeof(val) );
791 m_ByteVal->SetLabel( wxString::Format(_T("%d"),(int)val) );
792 }
793 else
794 {
795 m_ByteVal->SetLabel( _T("-") );
796 }
797
798 if ( left >= sizeof( short ) )
799 {
800 short val;
801 m_Content->Read( &val, m_Current, sizeof(val) );
802 m_WordVal->SetLabel( wxString::Format(_T("%d"),(int)val) );
803 }
804 else
805 {
806 m_WordVal->SetLabel( _T("-") );
807 }
808
809 if ( left >= sizeof( int ) )
810 {
811 int val;
812 m_Content->Read( &val, m_Current, sizeof(val) );
813 m_DwordVal->SetLabel( wxString::Format(_T("%d"),(int)val) );
814 }
815 else
816 {
817 m_DwordVal->SetLabel( _T("-") );
818 }
819
820 if ( left >= sizeof( float ) )
821 {
822 float val;
823 m_Content->Read( &val, m_Current, sizeof(val) );
824 m_FloatVal->SetLabel( wxString::Format(_T("%g"), val) );
825 }
826 else
827 {
828 m_FloatVal->SetLabel( _T("-") );
829 }
830
831 if ( left >= sizeof( double ) )
832 {
833 double val;
834 m_Content->Read( &val, m_Current, sizeof(val) );
835 m_DoubleVal->SetLabel( wxString::Format(_T("%g"), val) );
836 }
837 else
838 {
839 m_DoubleVal->SetLabel( _T("-") );
840 }
841
842 if ( left >= sizeof( long double ) )
843 {
844 long double val;
845 m_Content->Read( &val, m_Current, sizeof(val) );
846 if ( platform::windows )
847 {
848 // MinGW has broken support for long double
849 m_LDoubleVal->SetLabel( wxString::Format(_T("%g"), (double)val) );
850 }
851 else
852 {
853 m_LDoubleVal->SetLabel( wxString::Format(_T("%Lg"), val) );
854 }
855 }
856 else
857 {
858 m_LDoubleVal->SetLabel( _T("-") );
859 }
860
861 if ( m_ExpressionError.IsEmpty() )
862 {
863
864 Expression::Executor executor;
865
866 wxStopWatch sw;
867 if ( !executor.Execute( m_ExpressionCode, m_Content, m_Current ) )
868 {
869 m_ExpressionVal->SetLabel( executor.ErrorDesc() );
870 }
871 else
872 {
873 // LogManager::Get()->DebugLog( F( _T("HEExpr Calculate: %d"), (int)sw.Time() ) );
874 unsigned long long uintLoc;
875 long long sint;
876 long double flt;
877
878 if ( executor.GetResult( uintLoc ) )
879 {
880 m_ExpressionVal->SetLabel( wxString::Format( _T("%llu"), uintLoc) );
881 }
882 else if ( executor.GetResult( sint ) )
883 {
884 m_ExpressionVal->SetLabel( wxString::Format( _T("%lld"), sint ) );
885 }
886 else if ( executor.GetResult( flt ) )
887 {
888 m_ExpressionVal->SetLabel( wxString::Format( _T("%g"), (double)flt ) );
889 }
890 else
891 {
892 m_ExpressionVal->SetLabel( _T("Error") );
893 }
894 }
895 }
896 else
897 {
898 m_ExpressionVal->SetLabel( m_ExpressionError );
899 }
900
901
902 if ( m_DigitView )
903 {
904 switch ( m_DigitView->GetDigitBits() )
905 {
906 case 1: m_DigitBits->SetLabel( _("Bin") ); break;
907 case 4: m_DigitBits->SetLabel( _("Hex") ); break;
908 default: m_DigitBits->SetLabel( wxString::Format( _("%d bits") , m_DigitView->GetDigitBits() ) );
909 }
910
911 if ( m_DigitView->GetLittleEndian() )
912 m_Endianess->SetLabel( _("LE") );
913 else
914 m_Endianess->SetLabel( _("BE") );
915
916 m_BlockSize->SetLabel( wxString::Format( _("%dB"), m_DigitView->GetBlockBytes() ) );
917
918 switch ( m_ColsMode )
919 {
920 case CM_SPECIFIED: m_ColsModeBtn->SetLabel( wxString::Format( _("Cols: %d"), m_ColsValue ) ); break;
921 case CM_MULT: m_ColsModeBtn->SetLabel( wxString::Format( _("Cols: %d ( n * %d )"), m_ColsCount, m_ColsValue ) ); break;
922 case CM_POWER: m_ColsModeBtn->SetLabel( wxString::Format( _("Cols: %d ( n ^ %d )"), m_ColsCount, m_ColsValue ) ); break;
923 default: m_ColsModeBtn->SetLabel( wxString::Format( _("Cols: %d ( Any )"), m_ColsCount ) );
924 }
925 }
926 }
927
OnDrawAreaKeyDown(wxKeyEvent & event)928 void HexEditPanel::OnDrawAreaKeyDown(wxKeyEvent& event)
929 {
930 if ( !m_Content || !m_Content->GetSize() ) return;
931
932 m_ViewNotifyContentChange = false;
933 m_ViewNotifyOffsetChange = false;
934
935 switch ( event.GetKeyCode() )
936 {
937 case WXK_LEFT:
938 {
939 m_ActiveView->MoveLeft();
940 break;
941 }
942
943 case WXK_RIGHT:
944 {
945 m_ActiveView->MoveRight();
946 break;
947 }
948
949 case WXK_UP:
950 {
951 m_ActiveView->MoveUp();
952 break;
953 }
954
955 case WXK_DOWN:
956 {
957 m_ActiveView->MoveDown();
958 break;
959 }
960
961 case WXK_PAGEDOWN:
962 {
963 for ( unsigned int i=0; i<m_Lines/2; i++ )
964 {
965 m_ActiveView->MoveDown();
966 }
967 break;
968 }
969
970 case WXK_PAGEUP:
971 {
972 for ( unsigned int i=0; i<m_Lines/2; i++ )
973 {
974 m_ActiveView->MoveUp();
975 }
976 break;
977 }
978
979 case WXK_TAB:
980 {
981 m_ActiveView->SetActive( false );
982 int newViewId = -1;
983 for ( int i=0; i<MAX_VIEWS; ++i )
984 {
985 if ( m_ActiveView == m_Views[ i ] )
986 {
987 newViewId = ( i + 1 ) % MAX_VIEWS;
988 break;
989 }
990 }
991 if ( newViewId < 0 ) newViewId = 0;
992 m_ActiveView = m_Views[ newViewId ];
993 m_ActiveView->SetActive( true );
994 m_ViewNotifyContentChange = true;
995 break;
996 }
997
998 case WXK_HOME:
999 {
1000 m_Current = 0;
1001 m_ViewNotifyOffsetChange = true;
1002 break;
1003 }
1004
1005 case WXK_END:
1006 {
1007
1008 m_Current = m_Content->GetSize()-1;
1009 m_ViewNotifyOffsetChange = true;
1010 break;
1011 }
1012
1013 case WXK_INSERT:
1014 {
1015 // Insert empty byte at current position
1016 FileContentBase::ExtraUndoData data(
1017 m_ActiveView,
1018 m_Current, m_ActiveView->GetCurrentPositionFlags(),
1019 m_Current, m_ActiveView->GetCurrentPositionFlags() );
1020 m_Content->Add( data, m_Current, 1, 0 );
1021 m_ViewNotifyContentChange = true;
1022 break;
1023 }
1024
1025 case WXK_DELETE:
1026 {
1027 FileContentBase::ExtraUndoData data(
1028 m_ActiveView,
1029 m_Current, m_ActiveView->GetCurrentPositionFlags(),
1030 m_Current, m_ActiveView->GetCurrentPositionFlags() );
1031 m_Content->Remove( data, m_Current, 1 );
1032 m_ViewNotifyContentChange = true;
1033 break;
1034 }
1035
1036 default:
1037 {
1038 m_ActiveView->PutChar( event.GetUnicodeKey() );
1039 break;
1040 }
1041 }
1042
1043 if ( m_ViewNotifyOffsetChange )
1044 {
1045 EnsureCarretVisible();
1046 PropagateOffsetChange();
1047 RefreshStatus();
1048 m_ViewNotifyContentChange = true;
1049 }
1050
1051 if ( m_ViewNotifyContentChange )
1052 {
1053 m_DrawArea->Refresh();
1054 UpdateModified();
1055 }
1056 }
1057
EnsureCarretVisible()1058 void HexEditPanel::EnsureCarretVisible()
1059 {
1060 FileContentBase::OffsetT line = m_Current / m_LineBytes;
1061 FileContentBase::OffsetT startLine = DetectStartOffset() / m_LineBytes;
1062 FileContentBase::OffsetT endLine = startLine + m_Lines;
1063
1064 if ( line < startLine )
1065 {
1066 m_LastScrollPos = line;
1067 m_LastScrollUnits = line / m_LinesPerScrollUnit;
1068
1069 m_ContentScroll->SetThumbPosition( m_LastScrollUnits );
1070 m_DrawArea->Refresh();
1071 }
1072 else if ( line >= endLine )
1073 {
1074 line = line - m_Lines + 1;
1075
1076 m_LastScrollPos = line;
1077 m_LastScrollUnits = line / m_LinesPerScrollUnit;
1078
1079 m_ContentScroll->SetThumbPosition( m_LastScrollUnits );
1080 m_DrawArea->Refresh();
1081 }
1082 }
1083
ClampCursorToVisibleArea()1084 void HexEditPanel::ClampCursorToVisibleArea()
1085 {
1086 FileContentBase::OffsetT startOffs = DetectStartOffset();
1087 FileContentBase::OffsetT endOffs = startOffs + m_LineBytes * m_Lines;
1088
1089 bool changed = false;
1090
1091 if ( m_Current < startOffs )
1092 {
1093 m_Current = startOffs + ( m_Current % m_LineBytes );
1094 changed = true;
1095 }
1096 else if ( m_Current >= endOffs )
1097 {
1098 m_Current = endOffs - m_LineBytes + ( m_Current % m_LineBytes );
1099 changed = true;
1100 }
1101
1102 if ( m_Current >= m_Content->GetSize() )
1103 {
1104 m_Current = m_Content->GetSize() - 1;
1105 changed = true;
1106 }
1107
1108 if ( changed )
1109 {
1110 PropagateOffsetChange();
1111 }
1112 }
1113
PropagateOffsetChange(int flagsForCurrentView)1114 void HexEditPanel::PropagateOffsetChange( int flagsForCurrentView )
1115 {
1116 if ( !m_Content ) return;
1117
1118 OffsetT startOffs = DetectStartOffset();
1119
1120 OffsetT blockStart = m_Current;
1121 OffsetT blockEnd = m_Current + 1;
1122
1123 // First let's calculate block size
1124 for ( int i=0; i<MAX_VIEWS && m_Views[ i ]; ++i )
1125 {
1126 OffsetT thisBlockStart = blockStart;
1127 OffsetT thisBlockEnd = blockEnd;
1128 m_Views[i]->CalculateBlockSize( startOffs, m_Current, thisBlockStart, thisBlockEnd );
1129 blockStart = wxMin( blockStart, thisBlockStart );
1130 blockEnd = wxMax( blockEnd, thisBlockEnd );
1131 }
1132
1133 // Next we can propagate the offset
1134 for ( int i=0; i<MAX_VIEWS && m_Views[ i ]; ++i )
1135 {
1136 m_Views[i]->JumpToOffset( startOffs, m_Current, blockStart, blockEnd, ( m_Views[ i ] == m_ActiveView ) ? flagsForCurrentView : -1 );
1137 }
1138 }
1139
OnDrawAreaEraseBackground(wxEraseEvent &)1140 void HexEditPanel::OnDrawAreaEraseBackground(wxEraseEvent& /*event*/)
1141 {
1142 }
1143
OnForwardFocus(wxFocusEvent &)1144 void HexEditPanel::OnForwardFocus(wxFocusEvent& /*event*/)
1145 {
1146 m_DrawArea->SetFocus();
1147 }
1148
Save()1149 bool HexEditPanel::Save()
1150 {
1151 bool ret = m_Content->WriteFile( GetFilename() );
1152 UpdateModified();
1153 return ret;
1154 }
1155
SaveAs()1156 bool HexEditPanel::SaveAs()
1157 {
1158 wxFileName fname;
1159 fname.Assign(GetFilename());
1160 ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("app"));
1161
1162 wxString Path = fname.GetPath();
1163
1164 if(mgr && Path.IsEmpty())
1165 Path = mgr->Read(_T("/file_dialogs/save_file_as/directory"), Path);
1166
1167 wxFileDialog dlg(Manager::Get()->GetAppWindow(),
1168 _("Save file"),
1169 Path,
1170 fname.GetFullName(),
1171 _T("*.*"),//m_filecontent->GetWildcard(),
1172 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1173
1174 if (dlg.ShowModal() != wxID_OK) // cancelled out
1175 {
1176 UpdateModified();
1177 return false;
1178 }
1179
1180 SetFilename(dlg.GetPath());
1181 return Save();
1182 }
1183
GetModified() const1184 bool HexEditPanel::GetModified() const
1185 {
1186 return m_Content ? m_Content->Modified() : false;
1187 }
1188
SetModified(bool modified)1189 void HexEditPanel::SetModified( bool modified )
1190 {
1191 if ( m_Content ) m_Content->SetModified( modified );
1192 }
1193
UpdateModified()1194 void HexEditPanel::UpdateModified()
1195 {
1196 if ( GetModified() )
1197 {
1198 SetTitle( _T("*") + GetShortName() );
1199 }
1200 else
1201 {
1202 SetTitle( GetShortName() );
1203 }
1204 }
1205
SetFilename(const wxString & filename)1206 void HexEditPanel::SetFilename(const wxString& filename)
1207 {
1208 EditorBase::SetFilename(filename);
1209 //m_Filename = filename; done by EditorBase::SetFilename
1210 wxFileName fname;
1211 fname.Assign(m_Filename);
1212 m_Shortname = fname.GetFullName();
1213 }
1214
OnDrawAreaLeftDown(wxMouseEvent & event)1215 void HexEditPanel::OnDrawAreaLeftDown(wxMouseEvent& event)
1216 {
1217 if ( !m_Content ) return;
1218
1219 m_DrawArea->SetFocus();
1220
1221 // First we need to detect what the user has clicked on
1222 int line = event.GetY() / m_FontY;
1223 int column = event.GetX() / m_FontX;
1224
1225 // Just to prevent some weird situation
1226 line = wxMin( line, (int)m_Lines - 1 );
1227 column = wxMin( column, (int)m_Cols - 1 );
1228 line = wxMax( line, 0 );
1229 column = wxMax( column, 0 );
1230
1231 // Detect what has been pressed
1232
1233 if ( !m_MouseDown )
1234 {
1235 if ( column < 9 )
1236 {
1237 // Offset pressed
1238 return;
1239 }
1240 }
1241 column -= 9;
1242
1243 int viewId = -1;
1244
1245 for ( int i=0; i<MAX_VIEWS; ++i )
1246 {
1247 column -= 2;
1248
1249 if ( !m_MouseDown )
1250 {
1251 if ( column < 0 ) break;
1252
1253 if ( column < (int)m_ViewsCols[ i ] )
1254 {
1255 // Clicked on the area of i-th view
1256 ActivateView( m_Views[ i ] );
1257
1258 viewId = i;
1259 break;
1260 }
1261 }
1262 else if ( m_Views[ i ] == m_ActiveView )
1263 {
1264 viewId = i;
1265 break;
1266 }
1267
1268 column -= m_ViewsCols[ i ];
1269 }
1270
1271 if ( viewId >= 0 )
1272 {
1273 m_MouseDown = true;
1274
1275 column = wxMax( column, 0 );
1276 column = wxMin( column, (int)m_ViewsCols[ viewId ] );
1277
1278 int positionFlags;
1279 int lineOffset = m_Views[ viewId ]->GetOffsetFromColumn( column, positionFlags );
1280 lineOffset = wxMin( lineOffset, (int)m_LineBytes - 1 );
1281 lineOffset = wxMax( lineOffset, 0 );
1282
1283 OffsetT newCurrent = DetectStartOffset() + m_LineBytes * line + lineOffset;
1284
1285 if ( newCurrent < m_Content->GetSize() )
1286 {
1287 if ( ( newCurrent != m_Current ) || ( positionFlags != m_Views[ viewId ]->GetCurrentPositionFlags() ) )
1288 {
1289 m_Current = newCurrent;
1290 PropagateOffsetChange( positionFlags );
1291 RefreshStatus();
1292 EnsureCarretVisible();
1293 m_DrawArea->Refresh();
1294 }
1295 }
1296 }
1297 else
1298 {
1299 m_MouseDown = false;
1300 // Clicked somewhere after all views
1301 }
1302 }
1303
OnDrawAreaLeftUp(wxMouseEvent &)1304 void HexEditPanel::OnDrawAreaLeftUp(wxMouseEvent& /*event*/)
1305 {
1306 m_MouseDown = false;
1307 }
1308
OnDrawAreaMouseMove(wxMouseEvent & event)1309 void HexEditPanel::OnDrawAreaMouseMove(wxMouseEvent& event)
1310 {
1311 if ( m_MouseDown )
1312 {
1313 OnDrawAreaLeftDown( event );
1314 }
1315 }
1316
OnCheckBox1Click(wxCommandEvent &)1317 void HexEditPanel::OnCheckBox1Click(wxCommandEvent& /*event*/)
1318 {
1319 if ( !m_Content ) return;
1320 BoxSizer1->Show( PreviewSizer, CheckBox1->GetValue() );
1321 m_DrawArea->SetFocus();
1322 Layout();
1323 }
1324
CanUndo() const1325 bool HexEditPanel::CanUndo() const
1326 {
1327 return m_Content ? m_Content->CanUndo() : false;
1328 }
1329
CanRedo() const1330 bool HexEditPanel::CanRedo() const
1331 {
1332 return m_Content ? m_Content->CanRedo() : false;
1333 }
1334
Undo()1335 void HexEditPanel::Undo()
1336 {
1337 if ( m_Content )
1338 {
1339 const FileContentBase::ExtraUndoData* extraData = m_Content->Undo();
1340 if ( extraData )
1341 {
1342 m_Current = extraData->m_PosBefore;
1343 ActivateView( extraData->m_View );
1344 PropagateOffsetChange( extraData->m_PosBeforeF );
1345 }
1346 RefreshStatus();
1347 EnsureCarretVisible();
1348 m_DrawArea->Refresh();
1349 UpdateModified();
1350 }
1351 }
1352
Redo()1353 void HexEditPanel::Redo()
1354 {
1355 if ( m_Content )
1356 {
1357 const FileContentBase::ExtraUndoData* extraData = m_Content->Redo();
1358 if ( extraData )
1359 {
1360 m_Current = extraData->m_PosAfter;
1361 ActivateView( extraData->m_View );
1362 PropagateOffsetChange( extraData->m_PosAfterF );
1363 }
1364 RefreshStatus();
1365 EnsureCarretVisible();
1366 m_DrawArea->Refresh();
1367 UpdateModified();
1368 }
1369 }
1370
OnSpecialKeyDown(wxKeyEvent & event)1371 void HexEditPanel::OnSpecialKeyDown(wxKeyEvent& event)
1372 {
1373 // LogManager::Get()->DebugLog(
1374 // F(
1375 // _T("HexEditPanel::OnSpecialKeyDown: %d (%c%c%c)"),
1376 // (int)event.GetKeyCode(),
1377 // event.ControlDown() ? 'C':'c',
1378 // event.AltDown() ? 'A':'a',
1379 // event.CmdDown() ? 'M':'m' ) );
1380
1381 if ( event.ControlDown() && !event.AltDown() )
1382 {
1383 switch ( event.GetKeyCode() )
1384 {
1385 case 'G': ProcessGoto(); return;
1386 case 'F': ProcessSearch(); return;
1387 default: break;
1388 }
1389 }
1390
1391 event.Skip();
1392 }
1393
IsHexEditor(EditorBase * editor)1394 bool HexEditPanel::IsHexEditor( EditorBase* editor )
1395 {
1396 return m_AllEditors.find( editor ) != m_AllEditors.end();
1397 }
1398
CloseAllEditors()1399 void HexEditPanel::CloseAllEditors()
1400 {
1401 EditorsSet s = m_AllEditors;
1402 for ( EditorsSet::iterator i = s.begin(); i != s.end(); ++i )
1403 {
1404 EditorManager::Get()->QueryClose( *i );
1405 (*i)->Close();
1406 }
1407
1408 assert( m_AllEditors.empty() );
1409 }
1410
ProcessGoto()1411 void HexEditPanel::ProcessGoto()
1412 {
1413 if ( !m_Content ) return;
1414 if ( !m_Content->GetSize() ) return;
1415
1416
1417 OffsetT offset;
1418 wxString str = wxString::Format( _T("%lld"), m_Current );
1419 for ( ;; )
1420 {
1421 str = cbGetTextFromUser(
1422 _("Enter offset\n"
1423 "\n"
1424 "Available forms are:\n"
1425 " * Decimal ( 100 )\n"
1426 " * Hexadecimal ( 1AB, 0x1AB, 1ABh )\n"
1427 " * Offset from current ( +100, -100, +0x1AB )"),
1428 _("Goto offset"),
1429 str );
1430
1431 if ( str.IsEmpty() ) return;
1432 str.Trim( true ).Trim( false );
1433
1434 // Decided to parse manually since wxString::ToULongLong does not work everywhere
1435
1436 const wxChar* ptr = str.c_str();
1437 bool relativePlus = false;
1438 bool relativeMinus = false;
1439 bool canBeDec = true;
1440 bool canBeHex = true;
1441
1442 OffsetT dec = 0;
1443 OffsetT hex = 0;
1444
1445 if ( *ptr == _T('+') )
1446 {
1447 relativePlus = true;
1448 ptr++;
1449 }
1450 else if ( *ptr == _T('-') )
1451 {
1452 relativeMinus = true;
1453 ptr++;
1454 }
1455
1456 while ( wxIsspace( *ptr ) ) ptr++;
1457
1458 if ( ptr[0] == _T('0') && wxToupper(ptr[1]) == _T('X') )
1459 {
1460 canBeDec = false;
1461 ptr += 2;
1462 }
1463
1464 while ( *ptr )
1465 {
1466 int digitVal = wxString( _T("0123456789ABCDEF") ).Find( wxToupper( *ptr++ ) );
1467
1468 if ( digitVal == wxNOT_FOUND )
1469 {
1470 canBeDec = false;
1471 canBeHex = false;
1472 break;
1473 }
1474
1475 if ( digitVal >= 10 ) canBeDec = false;
1476
1477 dec = dec * 10 + digitVal;
1478 hex = hex * 0x10 + digitVal;
1479
1480 if ( wxToupper(ptr[0]) == _T('H') && !ptr[1] )
1481 {
1482 canBeDec = false;
1483 break;
1484 }
1485 }
1486
1487 if ( canBeDec || canBeHex )
1488 {
1489 OffsetT val = canBeDec ? dec : hex;
1490 OffsetT max = m_Content->GetSize() - 1;
1491 if ( relativePlus )
1492 {
1493 offset = m_Current + val < max ? m_Current + val : max;
1494 }
1495 else if ( relativeMinus )
1496 {
1497 offset = m_Current > val ? m_Current - val : 0;
1498 }
1499 else
1500 {
1501 offset = wxMin( max, val );
1502 }
1503 break;
1504 }
1505
1506 cbMessageBox( _("Invalid offset !!!.\n") );
1507 }
1508
1509 m_Current = offset;
1510 PropagateOffsetChange();
1511 RefreshStatus();
1512 EnsureCarretVisible();
1513 m_DrawArea->Refresh();
1514 }
1515
ProcessSearch()1516 void HexEditPanel::ProcessSearch()
1517 {
1518 if ( !m_Content ) return;
1519 if ( !m_Content->GetSize() ) return;
1520
1521 SearchDialog dlg( this, m_Content, m_Current );
1522 if ( dlg.ShowModal() == wxID_OK )
1523 {
1524 m_Current = dlg.GetOffset();
1525 PropagateOffsetChange();
1526 RefreshStatus();
1527 EnsureCarretVisible();
1528 m_DrawArea->Refresh();
1529 }
1530
1531 m_DrawArea->SetFocus();
1532 }
1533
OnButton1Click(wxCommandEvent &)1534 void HexEditPanel::OnButton1Click(wxCommandEvent& /*event*/)
1535 {
1536 ExpressionTester( 0, m_Content, m_Current).ShowModal();
1537 }
1538
ReparseExpression()1539 void HexEditPanel::ReparseExpression()
1540 {
1541 Expression::Parser parser;
1542 if ( !parser.Parse( m_Expression->GetValue(), m_ExpressionCode ) )
1543 {
1544 int pos;
1545 m_ExpressionError = parser.ParseErrorDesc( pos );
1546 }
1547 else
1548 {
1549 m_ExpressionError.Clear();
1550 }
1551 }
1552
OnReparseTimerTrigger(wxTimerEvent &)1553 void HexEditPanel::OnReparseTimerTrigger(wxTimerEvent& /*event*/)
1554 {
1555 ReparseExpression();
1556 RefreshStatus();
1557 }
1558
Onm_ExpressionText(wxCommandEvent &)1559 void HexEditPanel::Onm_ExpressionText(wxCommandEvent& /*event*/)
1560 {
1561 ReparseTimer.Start( 1000, wxTIMER_ONE_SHOT );
1562 }
1563
OnButton2Click(wxCommandEvent &)1564 void HexEditPanel::OnButton2Click(wxCommandEvent& /*event*/)
1565 {
1566 cbMessageBox( Expression::Parser::GetHelpString() );
1567 }
1568
OnExpressionTextEnter(wxCommandEvent &)1569 void HexEditPanel::OnExpressionTextEnter(wxCommandEvent& /*event*/)
1570 {
1571 ReparseExpression();
1572 RefreshStatus();
1573 ReparseTimer.Stop();
1574 }
1575
OnButton3Click1(wxCommandEvent & event)1576 void HexEditPanel::OnButton3Click1(wxCommandEvent& event)
1577 {
1578 SelectStoredExpressionDlg dlg( this, m_Expression->GetValue() );
1579 if ( dlg.ShowModal() == wxID_OK )
1580 {
1581 m_Expression->SetValue( dlg.GetExpression() );
1582 OnExpressionTextEnter(event);
1583 }
1584 }
1585
OnButton4Click(wxCommandEvent &)1586 void HexEditPanel::OnButton4Click(wxCommandEvent& /*event*/)
1587 {
1588 PopupMenu( &m_BaseMenu );
1589 }
1590
OnSetBaseHex(wxCommandEvent &)1591 void HexEditPanel::OnSetBaseHex(wxCommandEvent& /*event*/)
1592 {
1593 m_DigitView->SetDigitBits( 4 );
1594 DisplayChanged();
1595 }
1596
OnSetBaseBin(wxCommandEvent &)1597 void HexEditPanel::OnSetBaseBin(wxCommandEvent& /*event*/)
1598 {
1599 m_DigitView->SetDigitBits( 1 );
1600 DisplayChanged();
1601 }
1602
DisplayChanged()1603 void HexEditPanel::DisplayChanged()
1604 {
1605 m_NeedRecalc = true;
1606 RefreshStatus();
1607 EnsureCarretVisible();
1608 m_DrawArea->Refresh();
1609 m_DrawArea->SetFocus();
1610 }
1611
Onm_EndianessClick(wxCommandEvent &)1612 void HexEditPanel::Onm_EndianessClick(wxCommandEvent& /*event*/)
1613 {
1614 PopupMenu( &m_EndianessMenu );
1615 }
1616
OnSetEndianessBig(wxCommandEvent &)1617 void HexEditPanel::OnSetEndianessBig(wxCommandEvent& /*event*/)
1618 {
1619 m_DigitView->SetLittleEndian( false );
1620 DisplayChanged();
1621 }
1622
OnSetEndianessLittle(wxCommandEvent &)1623 void HexEditPanel::OnSetEndianessLittle(wxCommandEvent& /*event*/)
1624 {
1625 m_DigitView->SetLittleEndian( true );
1626 DisplayChanged();
1627 }
1628
Onm_BlockSizeClick(wxCommandEvent &)1629 void HexEditPanel::Onm_BlockSizeClick(wxCommandEvent& /*event*/)
1630 {
1631 PopupMenu( &m_BlockSizeMenu );
1632 }
1633
OnSetBlockSize1(wxCommandEvent &)1634 void HexEditPanel::OnSetBlockSize1(wxCommandEvent& /*event*/)
1635 {
1636 m_DigitView->SetBlockBytes( 1 );
1637 DisplayChanged();
1638 }
1639
OnSetBlockSize2(wxCommandEvent &)1640 void HexEditPanel::OnSetBlockSize2(wxCommandEvent& /*event*/)
1641 {
1642 m_DigitView->SetBlockBytes( 2 );
1643 DisplayChanged();
1644 }
1645
OnSetBlockSize4(wxCommandEvent &)1646 void HexEditPanel::OnSetBlockSize4(wxCommandEvent& /*event*/)
1647 {
1648 m_DigitView->SetBlockBytes( 4 );
1649 DisplayChanged();
1650 }
1651
OnSetBlockSize8(wxCommandEvent &)1652 void HexEditPanel::OnSetBlockSize8(wxCommandEvent& /*event*/)
1653 {
1654 m_DigitView->SetBlockBytes( 8 );
1655 DisplayChanged();
1656 }
1657
Onm_ColsModeClick(wxCommandEvent &)1658 void HexEditPanel::Onm_ColsModeClick(wxCommandEvent& /*event*/)
1659 {
1660 PopupMenu( &m_ColsModeMenu );
1661 }
1662
OnSetColsMul1(wxCommandEvent &)1663 void HexEditPanel::OnSetColsMul1(wxCommandEvent& /*event*/)
1664 {
1665 ColsMode( CM_MULT, 1 );
1666 }
1667
OnSetColsMul2(wxCommandEvent &)1668 void HexEditPanel::OnSetColsMul2(wxCommandEvent& /*event*/)
1669 {
1670 ColsMode( CM_MULT, 2 );
1671 }
1672
OnSetColsMul3(wxCommandEvent &)1673 void HexEditPanel::OnSetColsMul3(wxCommandEvent& /*event*/)
1674 {
1675 ColsMode( CM_MULT, 3 );
1676 }
1677
OnSetColsMul4(wxCommandEvent &)1678 void HexEditPanel::OnSetColsMul4(wxCommandEvent& /*event*/)
1679 {
1680 ColsMode( CM_MULT, 4 );
1681 }
1682
OnSetColsMul5(wxCommandEvent &)1683 void HexEditPanel::OnSetColsMul5(wxCommandEvent& /*event*/)
1684 {
1685 ColsMode( CM_MULT, 5 );
1686 }
1687
OnSetColsMul6(wxCommandEvent &)1688 void HexEditPanel::OnSetColsMul6(wxCommandEvent& /*event*/)
1689 {
1690 ColsMode( CM_MULT, 6 );
1691 }
1692
OnSetColsMul7(wxCommandEvent &)1693 void HexEditPanel::OnSetColsMul7(wxCommandEvent& /*event*/)
1694 {
1695 ColsMode( CM_MULT, 7 );
1696 }
1697
OnSetColsMul8(wxCommandEvent &)1698 void HexEditPanel::OnSetColsMul8(wxCommandEvent& /*event*/)
1699 {
1700 ColsMode( CM_MULT, 8 );
1701 }
1702
OnSetColsMulOther(wxCommandEvent &)1703 void HexEditPanel::OnSetColsMulOther(wxCommandEvent& /*event*/)
1704 {
1705 long val = ::wxGetNumberFromUser( _("Enter number"), _("Enter number"), _("Colums setting"), 2, 2, 100, this );
1706 if ( val > 0 ) ColsMode( CM_MULT, val );
1707 }
1708
OnSetColsValue1(wxCommandEvent &)1709 void HexEditPanel::OnSetColsValue1(wxCommandEvent& /*event*/)
1710 {
1711 ColsMode( CM_SPECIFIED, 1 );
1712 }
1713
OnSetColsValue2(wxCommandEvent &)1714 void HexEditPanel::OnSetColsValue2(wxCommandEvent& /*event*/)
1715 {
1716 ColsMode( CM_SPECIFIED, 2 );
1717 }
1718
OnSetColsValue3(wxCommandEvent &)1719 void HexEditPanel::OnSetColsValue3(wxCommandEvent& /*event*/)
1720 {
1721 ColsMode( CM_SPECIFIED, 3 );
1722 }
1723
OnSetColsValue4(wxCommandEvent &)1724 void HexEditPanel::OnSetColsValue4(wxCommandEvent& /*event*/)
1725 {
1726 ColsMode( CM_SPECIFIED, 4 );
1727 }
1728
OnSetColsValue5(wxCommandEvent &)1729 void HexEditPanel::OnSetColsValue5(wxCommandEvent& /*event*/)
1730 {
1731 ColsMode( CM_SPECIFIED, 5 );
1732 }
1733
OnSetColsValue6(wxCommandEvent &)1734 void HexEditPanel::OnSetColsValue6(wxCommandEvent& /*event*/)
1735 {
1736 ColsMode( CM_SPECIFIED, 6 );
1737 }
1738
OnSetColsValue7(wxCommandEvent &)1739 void HexEditPanel::OnSetColsValue7(wxCommandEvent& /*event*/)
1740 {
1741 ColsMode( CM_SPECIFIED, 7 );
1742 }
1743
OnSetColsValue8(wxCommandEvent &)1744 void HexEditPanel::OnSetColsValue8(wxCommandEvent& /*event*/)
1745 {
1746 ColsMode( CM_SPECIFIED, 8 );
1747 }
1748
OnSetColsValueOther(wxCommandEvent &)1749 void HexEditPanel::OnSetColsValueOther(wxCommandEvent& /*event*/)
1750 {
1751 long val = ::wxGetNumberFromUser( _("Enter number"), _("Enter number"), _("Colums setting"), 1, 1, 100, this );
1752 if ( val > 0 ) ColsMode( CM_SPECIFIED, val );
1753 }
1754
OnSetColsPower2(wxCommandEvent &)1755 void HexEditPanel::OnSetColsPower2(wxCommandEvent& /*event*/)
1756 {
1757 ColsMode( CM_POWER, 2 );
1758 }
1759
OnSetColsPower4(wxCommandEvent &)1760 void HexEditPanel::OnSetColsPower4(wxCommandEvent& /*event*/)
1761 {
1762 ColsMode( CM_POWER, 4 );
1763 }
1764
OnSetColsPower8(wxCommandEvent &)1765 void HexEditPanel::OnSetColsPower8(wxCommandEvent& /*event*/)
1766 {
1767 ColsMode( CM_POWER, 8 );
1768 }
1769
OnSetColsPowerOther(wxCommandEvent &)1770 void HexEditPanel::OnSetColsPowerOther(wxCommandEvent& /*event*/)
1771 {
1772 long val = ::wxGetNumberFromUser( _("Enter number"), _("Enter number"), _("Colums setting"), 2, 2, 100, this );
1773 if ( val > 0 ) ColsMode( CM_POWER, val );
1774 }
1775
ColsMode(int mode,int value)1776 void HexEditPanel::ColsMode(int mode, int value)
1777 {
1778 m_ColsMode = mode;
1779 m_ColsValue = value;
1780
1781 if ( m_ColsMode == CM_MULT && m_ColsValue == 1 )
1782 {
1783 m_ColsMode = CM_ANY;
1784 }
1785
1786 DisplayChanged();
1787 }
1788
MatchColumnsCount(int colsCount)1789 bool HexEditPanel::MatchColumnsCount(int colsCount)
1790 {
1791 switch ( m_ColsMode )
1792 {
1793 case CM_MULT:
1794 return ( colsCount % m_ColsValue ) == 0;
1795
1796 case CM_SPECIFIED:
1797 return colsCount == m_ColsValue;
1798
1799 case CM_POWER:
1800 while ( colsCount > 1 )
1801 {
1802 if ( colsCount % m_ColsValue ) return false;
1803 colsCount /= m_ColsValue;
1804 }
1805 return true;
1806
1807 default:
1808 return true;
1809 }
1810 }
1811
OnButton4Click1(wxCommandEvent &)1812 void HexEditPanel::OnButton4Click1(wxCommandEvent& /*event*/)
1813 {
1814 wxArrayString tests;
1815 tests.Add(_("Expression parser"));
1816 tests.Add(_("On-Disk file edition"));
1817
1818 int index = cbGetSingleChoiceIndex( _("Select tests to perform"), _("Self tests"), tests, this);
1819 TestCasesBase* test = 0;
1820
1821 switch ( index )
1822 {
1823 case 0: test = &Expression::GetTests(); break;
1824 case 1: test = &FileContentDisk::GetTests(); break;
1825 default: break;
1826 }
1827
1828 if ( !test ) return;
1829
1830 TestCasesDlg( this, *test ).ShowModal();
1831 }
1832
1833
OnButton6Click(wxCommandEvent &)1834 void HexEditPanel::OnButton6Click(wxCommandEvent& /*event*/)
1835 {
1836 ProcessGoto();
1837 }
1838
OnButton5Click(wxCommandEvent &)1839 void HexEditPanel::OnButton5Click(wxCommandEvent& /*event*/)
1840 {
1841 ProcessSearch();
1842 }
1843