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