1 /***********************************(GPL)********************************
2 *   wxHexEditor is a hex edit tool for editing massive files in Linux   *
3 *   Copyright (C) 2010  Erdem U. Altinyurt                              *
4 *                                                                       *
5 *   This program is free software; you can redistribute it and/or       *
6 *   modify it under the terms of the GNU General Public License         *
7 *   as published by the Free Software Foundation; either version 2      *
8 *   of the License.                                                     *
9 *                                                                       *
10 *   This program 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 this program;                                            *
17 *   if not, write to the Free Software Foundation, Inc.,                *
18 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA        *
19 *                                                                       *
20 *               home  : www.wxhexeditor.org                             *
21 *               email : spamjunkeater@gmail.com                         *
22 *************************************************************************/
23 
24 
25 #include "HexEditor.h"
26 
HexEditor(wxWindow * parent,int id,wxStatusBar * statbar_,DataInterpreter * interpreter_,InfoPanel * infopanel_,TagPanel * tagpanel_,DisassemblerPanel * dasmpanel_,wxFileName * myfilename_,const wxPoint & pos,const wxSize & size,long style)27 HexEditor::HexEditor(	wxWindow* parent,
28                         int id,
29                         wxStatusBar *statbar_,
30                         DataInterpreter *interpreter_,
31                         InfoPanel *infopanel_,
32                         TagPanel *tagpanel_,
33                         DisassemblerPanel *dasmpanel_,
34                         wxFileName* myfilename_,
35                         const wxPoint& pos,
36                         const wxSize& size,
37                         long style ):
38 	HexEditorCtrl(parent, id, pos, size, wxTAB_TRAVERSAL),
39 	statusbar(statbar_),
40 	interpreter(interpreter_),
41 	infopanel(infopanel_),
42 	tagpanel(tagpanel_),
43 	dasmpanel(dasmpanel_) {
44 	ComparatorHexEditor=NULL;
45 	// Here, code praying to the GOD for protecting our open file from wxHexEditor's bugs and other things.
46 	// This is really crucial step! Be adviced to not remove it, even if you don't believer.
47 	printf("Rahman ve Rahim olan Allah'ın adıyla.\n");
48 	myfile = NULL;
49 #ifndef DO_NOT_USE_THREAD_FOR_SCROLL
50 	myscrollthread = NULL;
51 #endif
52 	if( myfilename_ != NULL ) {
53 		if( !FileOpen( *myfilename_ ) ) {
54 			}
55 		}
56 	offset_scroll->Enable( true );
57 	Dynamic_Connector();
58 	copy_mark = new copy_maker( );
59 	BlockSelectOffset = -1;
60 	MouseCapture = false;
61 	}
62 
ConnectScroll(HexEditor * connection)63 void HexEditor::ConnectScroll(HexEditor* connection){
64 	ComparatorHexEditor=connection;
65 	connection->ComparatorHexEditor=this;
66 	}
67 
DisconnectScroll(void)68 void HexEditor::DisconnectScroll( void ){
69 	if(ComparatorHexEditor!=NULL){
70 		ComparatorHexEditor->ComparatorHexEditor=NULL;
71 		ComparatorHexEditor=NULL;
72 		}
73 	}
74 
~HexEditor()75 HexEditor::~HexEditor() {
76 	DisconnectScroll();
77 	//FileClose();
78 	Dynamic_Disconnector();
79 	// Free resources
80 #ifndef DO_NOT_USE_THREAD_FOR_SCROLL
81    if(myscrollthread != NULL ){
82 		myscrollthread->Exit();
83 		delete myscrollthread;
84 		}
85 #endif
86 	delete copy_mark;
87 	}
88 
Dynamic_Connector()89 void HexEditor::Dynamic_Connector() {
90 	Connect( wxEVT_COMMAND_TEXT_UPDATED, 	wxCommandEventHandler( HexEditor::ThreadPaint ), NULL, this );
91 
92 	hex_ctrl ->Connect( wxEVT_KEY_DOWN,		wxKeyEventHandler(HexEditor::OnKeyboardInput),NULL, this);
93 	text_ctrl->Connect( wxEVT_KEY_DOWN,		wxKeyEventHandler(HexEditor::OnKeyboardInput),NULL, this);
94 	//this is not up arrow key, just means release of key press.
95 //	hex_ctrl ->Connect( wxEVT_KEY_UP,		wxKeyEventHandler(HexEditor::OnKeyboardSelectionEnd),NULL, this);
96 //	text_ctrl->Connect( wxEVT_KEY_UP,		wxKeyEventHandler(HexEditor::OnKeyboardSelectionEnd),NULL, this);
97 	hex_ctrl ->Connect( wxEVT_CHAR,			wxKeyEventHandler(HexEditor::OnKeyboardChar),NULL, this);
98 	text_ctrl->Connect( wxEVT_CHAR,			wxKeyEventHandler(HexEditor::OnKeyboardChar),NULL, this);
99 	hex_ctrl ->Connect( wxEVT_LEFT_DOWN,	wxMouseEventHandler(HexEditor::OnMouseLeft),NULL, this);
100 	text_ctrl->Connect( wxEVT_LEFT_DOWN,	wxMouseEventHandler(HexEditor::OnMouseLeft),NULL, this);
101 	hex_ctrl ->Connect( wxEVT_LEFT_UP,		wxMouseEventHandler(HexEditor::OnMouseSelectionEnd),NULL, this);
102 	text_ctrl->Connect( wxEVT_LEFT_UP,		wxMouseEventHandler(HexEditor::OnMouseSelectionEnd),NULL, this);
103 	offset_ctrl->Connect( wxEVT_RIGHT_DOWN,	wxMouseEventHandler(HexEditor::OnMouseRight),NULL, this);
104 	hex_ctrl ->Connect( wxEVT_RIGHT_DOWN,	wxMouseEventHandler(HexEditor::OnMouseRight),NULL, this);
105 	text_ctrl->Connect( wxEVT_RIGHT_DOWN,	wxMouseEventHandler(HexEditor::OnMouseRight),NULL, this);
106 	hex_ctrl ->Connect( wxEVT_MIDDLE_DOWN,	wxMouseEventHandler(HexEditor::OnMouseTest),NULL, this);
107 	text_ctrl->Connect( wxEVT_MIDDLE_DOWN,	wxMouseEventHandler(HexEditor::OnMouseTest),NULL, this);
108 	hex_ctrl ->Connect( wxEVT_MOTION,		wxMouseEventHandler(HexEditor::OnMouseMove),NULL, this);
109 	text_ctrl->Connect( wxEVT_MOTION,		wxMouseEventHandler(HexEditor::OnMouseMove),NULL, this);
110 	hex_ctrl ->Connect( wxEVT_MOUSEWHEEL,	wxMouseEventHandler(HexEditor::OnMouseWhell),NULL, this);
111 	text_ctrl->Connect( wxEVT_MOUSEWHEEL,	wxMouseEventHandler(HexEditor::OnMouseWhell),NULL, this);
112 
113 	m_static_offset->Connect( wxEVT_LEFT_DCLICK,wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
114 	m_static_offset->Connect( wxEVT_LEFT_DOWN,	wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
115 	m_static_offset->Connect( wxEVT_RIGHT_DCLICK,wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
116 	m_static_offset->Connect( wxEVT_RIGHT_DOWN,	wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
117 	m_static_offset->Connect( wxEVT_MOTION,		wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
118 	}
119 
Dynamic_Disconnector()120 void HexEditor::Dynamic_Disconnector() {
121 	Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( HexEditor::ThreadPaint ), NULL, this );
122 
123 	hex_ctrl ->Disconnect( wxEVT_KEY_DOWN,	wxKeyEventHandler(HexEditor::OnKeyboardInput),NULL, this);
124 	text_ctrl->Disconnect( wxEVT_KEY_DOWN,	wxKeyEventHandler(HexEditor::OnKeyboardInput),NULL, this);
125 	//this is not up arrow key, just means release of key press.
126 //	hex_ctrl ->Disconnect( wxEVT_KEY_UP,	wxKeyEventHandler(HexEditor::OnKeyboardSelectionEnd),NULL, this);
127 //	text_ctrl->Disconnect( wxEVT_KEY_UP,	wxKeyEventHandler(HexEditor::OnKeyboardSelectionEnd),NULL, this);
128 	hex_ctrl ->Disconnect( wxEVT_CHAR,		wxKeyEventHandler(HexEditor::OnKeyboardChar),NULL, this);
129 	text_ctrl->Disconnect( wxEVT_CHAR,		wxKeyEventHandler(HexEditor::OnKeyboardChar),NULL, this);
130 	hex_ctrl ->Disconnect( wxEVT_LEFT_DOWN,	wxMouseEventHandler(HexEditor::OnMouseLeft),NULL, this);
131 	text_ctrl->Disconnect( wxEVT_LEFT_DOWN,	wxMouseEventHandler(HexEditor::OnMouseLeft),NULL, this);
132 	hex_ctrl ->Disconnect( wxEVT_LEFT_UP,	wxMouseEventHandler(HexEditor::OnMouseSelectionEnd),NULL, this);
133 	text_ctrl->Disconnect( wxEVT_LEFT_UP,	wxMouseEventHandler(HexEditor::OnMouseSelectionEnd),NULL, this);
134 	offset_ctrl->Disconnect( wxEVT_RIGHT_DOWN,wxMouseEventHandler(HexEditor::OnMouseRight),NULL, this);
135 	hex_ctrl ->Disconnect( wxEVT_RIGHT_DOWN,wxMouseEventHandler(HexEditor::OnMouseRight),NULL, this);
136 	text_ctrl->Disconnect( wxEVT_RIGHT_DOWN,wxMouseEventHandler(HexEditor::OnMouseRight),NULL, this);
137 	hex_ctrl ->Disconnect( wxEVT_MIDDLE_DOWN,wxMouseEventHandler(HexEditor::OnMouseTest),NULL, this);
138 	text_ctrl->Disconnect( wxEVT_MIDDLE_DOWN,wxMouseEventHandler(HexEditor::OnMouseTest),NULL, this);
139 	hex_ctrl ->Disconnect( wxEVT_MOTION,	wxMouseEventHandler(HexEditor::OnMouseMove),NULL, this);
140 	text_ctrl->Disconnect( wxEVT_MOTION,	wxMouseEventHandler(HexEditor::OnMouseMove),NULL, this);
141 
142 	m_static_offset->Disconnect( wxEVT_LEFT_DCLICK,	wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
143 	m_static_offset->Disconnect( wxEVT_LEFT_DOWN,	wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
144 	m_static_offset->Disconnect( wxEVT_RIGHT_DCLICK,wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
145 	m_static_offset->Disconnect( wxEVT_RIGHT_DOWN,	wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
146 	m_static_offset->Disconnect( wxEVT_MOTION,		wxMouseEventHandler(HexEditor::OnOffsetMouse),NULL, this);
147 	}
148 
HashVerify(wxString hash_file,FAL * File)149 int HexEditor::HashVerify(wxString hash_file, FAL* File){
150 	if( File==NULL )
151 		File=myfile;
152 
153 	wxFFile f( hash_file, wxT("rt") );
154 	wxMemoryBuffer mbf;
155 	hashid hash_alg;
156 	if( hash_file.EndsWith( wxT(".md5") ))
157 		hash_alg=MHASH_MD5;
158 	else if( hash_file.EndsWith( wxT(".sha1") ))
159 		hash_alg=MHASH_SHA1;
160 	else//if( hash_file.EndsWith(wxT(".sha256" )) )
161 		hash_alg=MHASH_SHA256;
162 	unsigned hash_block_size=mhash_get_block_size( hash_alg );
163 	if( hash_block_size*2 != f.Read( mbf.GetWriteBuf( hash_block_size*2 ), hash_block_size*2 ) ){
164 		wxMessageBox(_("Cannot read hash file!"),_("Error!"));
165 		return -1;
166 		}
167 	mbf.UngetWriteBuf(hash_block_size*2);
168 	wxString MyHashStr = wxString::From8BitData( reinterpret_cast<char*>(mbf.GetData()), hash_block_size*2 );
169 	wxMemoryBuffer compare = hex_ctrl->HexToBin(MyHashStr);
170 
171 	File->Seek(0);
172 
173 	wxString msg = _("Please wait while calculating checksum.");
174 	wxString emsg = wxT("\n");
175 	wxProgressDialog mypd(_("Calculating Checksum"), msg+emsg , 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_CAN_ABORT|wxPD_REMAINING_TIME);
176 	mypd.Show();
177 
178 	MHASH myhash=mhash_init(hash_alg);
179 
180 	enum { rdBlockSz=2*128*1024 };
181 	unsigned char buff[rdBlockSz];
182 	int rd=rdBlockSz;
183 
184 	uint64_t readfrom=0,readspeed=0, range=File->Length();
185 	time_t ts,te;
186 	time (&ts);
187 
188 	while(rd == rdBlockSz){
189 		rd = File->Read( buff, rdBlockSz );
190 		readfrom+=rd;
191 		mhash( myhash, buff, rd);
192 		time(&te);
193 		if(ts != te ){
194 			ts=te;
195 			emsg = msg + wxT("\n") + _("Hash Speed : ") + wxString::Format( wxT("%.2f "), 1.0*(readfrom-readspeed)/MB) + _("MB/s");
196 			readspeed=readfrom;
197 			}
198 		if(!mypd.Update((readfrom*1000)/range, emsg ))
199 			return -1;
200 		}
201 
202 	wxString results;
203 	unsigned char *hash;
204 
205 	hash = static_cast<unsigned char *>( mhash_end(myhash) );
206 	if( memcmp( compare.GetData(), hash, hash_block_size ) ){
207 		wxBell();
208 		wxString msg = wxString(_("File Corrupt!"))+wxT("\n")+_("File Hash:")+wxT("\t");
209 		for (unsigned k = 0; k < hash_block_size; k++)
210 			msg += wxString::Format( wxT("%.2x"), hash[k]);
211 		msg +=wxString( wxT("\n") ) +_("Hash File:")+wxT("\t") + MyHashStr;
212 		wxMessageBox(msg, _("Hash Result") );
213 		return 0;
214 		}
215 	else{
216 		wxMessageBox(_("File Verified."), _("Hash Result") );
217 		return 1;
218 		}
219 	}
220 
FileOpen(wxFileName & myfilename)221 bool HexEditor::FileOpen(wxFileName& myfilename ) {
222 	if(myfile!=NULL) {
223 		wxLogError(_("Critical Error. File pointer is not empty!"));
224 		return false;
225 		}
226 
227 		//Windows Device Loader
228 #ifdef __WXMSW__
229 	//if File is Windows device file! Let pass it and process under FAM
230 	if( myfilename.GetFullPath().StartsWith( wxT(".:"))
231 		|| myfilename.GetFullPath().StartsWith( wxT("\\Device\\Harddisk") )){
232 		myfile = new FAL( myfilename ); //OpenDevice
233 		if(myfile->IsOpened()) {
234 #ifndef DO_NOT_USE_THREAD_FOR_SCROLL
235 			myscrollthread = new scrollthread(0,this);
236 #endif
237 //			copy_mark = new copy_maker();
238 			offset_ctrl->SetOffsetLimit( FileLength() );
239 			sector_size = FDtoBlockSize( GetFD() );//myfile->GetBlockSize();
240 			LoadFromOffset(0, true);
241 			SetLocalHexInsertionPoint(0);
242 			return true;
243 			}
244 		else {
245 			wxMessageBox(_("File cannot open."),_("Error"), wxOK|wxICON_ERROR, this);
246 			return false;
247 			}
248 		}
249 	else
250 #endif
251 
252 	if ( myfilename.GetSize( ) < 50*MB && myfilename.IsFileWritable() )
253 		myfile = new FAL( myfilename, FAL::ReadWrite, 0 );
254 	else
255 		myfile = new FAL( myfilename, FAL::ReadOnly, 0 );
256 
257 	if(myfile->IsOpened()) {
258 #ifndef DO_NOT_USE_THREAD_FOR_SCROLL
259 		myscrollthread = new scrollthread(0,this);
260 #endif
261 //			copy_mark = new copy_maker();
262 
263 		if( myfile->IsProcess() ){
264 			#ifdef __WXGTK__
265 			//offset_scroll->Enable(false);
266 			std::cout << "PID MAPS loading..." << std::endl;
267 			wxString command( wxT("cat /proc/") );
268 			command << myfile->GetPID() << wxT("/maps");
269 			std::cout << command.ToAscii() << std::endl;
270 			wxArrayString output;
271 
272 			wxExecute( command, output);
273 			//output has Count() lines process it
274 
275 			for( unsigned i=0; i < output.Count() ; i++){
276 				TagElement *tmp = new TagElement();
277 				long long unsigned int x;
278 				output[i].BeforeFirst('-').ToULongLong(&x, 16);
279 				tmp->start = x;
280 				tmp->end = x;
281 				ProcessRAMMap.Add(x);
282 				output[i].AfterFirst('-').BeforeFirst(' ').ToULongLong(&x,16);
283 				ProcessRAMMap.Add(x);
284 				tmp->tag = output[i].AfterLast( wxT(' '));
285 				tmp->FontClrData.SetColour( *wxBLACK );
286 				tmp->NoteClrData.SetColour( *wxCYAN );
287 				MainTagArray.Add(tmp);
288 				}
289 			#endif
290 			}
291 
292 		LoadTAGS( myfilename.GetFullPath().Append(wxT(".tags")) ); //Load tags to wxHexEditorCtrl
293 
294 		tagpanel->Set(MainTagArray); //Sets Tags to Tag panel
295 		if(MainTagArray.Count() > 0){
296 			//TODO This tagpanel->Show() code doesn't working good
297 			//tagpanel->Show();
298 			}
299 		offset_ctrl->SetOffsetLimit(  FileLength() );
300 		sector_size = myfile->GetBlockSize(); //FDtoBlockSize( GetFD() );
301 		LoadFromOffset(0, true);
302 		SetLocalHexInsertionPoint(0);
303 		return true;
304 		}
305 	else {
306 		///Handled on FAM Layer...
307 		///wxMessageBox(_("File cannot open."),_("Error"), wxOK|wxICON_ERROR, this);
308 		return false;
309 		}
310 	}
311 
IsFileUsingXORKey(void)312 bool HexEditor::IsFileUsingXORKey( void ){
313 	return myfile->GetXORKey().GetDataLen() != 0;
314 	}
315 
FileGetXORKey(void)316 wxString HexEditor::FileGetXORKey( void ){
317 	if( myfile->GetXORKey().GetDataLen() == 0 )
318 		return wxEmptyString;
319 	else
320 		return wxString::From8BitData( reinterpret_cast<char*>(myfile->GetXORKey().GetData()),myfile->GetXORKey().GetDataLen() );
321 	}
322 
FileSetXORKey(bool enable)323 void HexEditor::FileSetXORKey( bool enable ){
324 	wxMemoryBuffer x;
325 	if( enable ){
326 		XORViewDialog a( this, &x );
327 		if( a.ShowModal() == wxID_CANCEL )
328 			return;
329 
330 		if(x.GetDataLen() != 0){
331  			FileReOpen();
332 			}
333 		}
334 	else{
335 		if( wxMessageBox( _("Switching to XORView Thru mode will reset Undo&Redo buffer. Unsaved changes will be discarded.\n Note also that you can't use methods that change file size (like delete and inject) while XORView Thru mode is active."), _("XORView Thru Warning"), wxOK | wxCANCEL | wxICON_EXCLAMATION ) == wxCANCEL)
336 			return;
337 		FileReOpen();
338 		}
339 	myfile->SetXORKey( x );
340 
341 	infopanel->Set( GetFileName(), FileLength(), GetFileAccessModeString(), GetFD(), FileGetXORKey() );
342 
343 	Reload();
344 
345 	//This Triggers (XORView) Extension on Notebook bar...
346 	wxUpdateUIEvent new_event;
347 	new_event.SetId( XORVIEW_EVENT );
348 	new_event.SetString( ( x.GetDataLen() ? wxT("Checked") : wxT("UnChecked")) );
349 	GetEventHandler()->ProcessEvent( new_event );
350 	}
351 
FileSave(bool question)352 bool HexEditor::FileSave( bool question ) {
353 	if( myfile->IsChanged() ) {
354 		if ( myfile->GetAccessMode() == FAL::ReadOnly) {
355 			wxMessageBox( _( "File in Read Only mode. Cannot save file."), _("File Save"), wxOK|wxICON_EXCLAMATION, this );
356 			return false;
357 			}
358 		if ( myfile->IsInjected() ) {
359 			wxMessageBox( _( "File has some insertion/deletions. You cannot save this file-self (yet). Please use SaveAs."), _("File Save Error."), wxOK|wxICON_EXCLAMATION, this );
360 			return false;
361 			}
362 		int select = wxYES;
363 		if ( question )
364 			select=wxMessageBox( _( "Do you want to save this file?"), _("File Save"), wxYES_NO|wxCANCEL|wxICON_QUESTION, this );
365 
366 		switch( select ) {
367 			case(wxYES):
368 				if( !myfile->Apply() ) {
369 					wxMessageBox( _( "File cannot saved. Operation Cancelled"), _("File Save Error"), wxOK|wxICON_ERROR, this );
370 					return false;
371 					}
372 			case(wxNO):
373 				return true;
374 			case(wxCANCEL):
375 			default:
376 				return false;
377 			}
378 		}
379 	else {
380 		wxMessageBox( _( "File is not changed. Nothing to save.\n"), _("File Save"), wxOK|wxICON_EXCLAMATION, this );
381 		}
382 	return false;
383 	}
384 
FileSave(wxString savefilename)385 bool HexEditor::FileSave( wxString savefilename ) {
386 // TODO (death#1#): Protection to save opened file/samefile
387 	wxFFile savefile( savefilename, wxT("wb") );
388 
389 	wxDiskspaceSize_t available, total;
390 	do{
391 		wxGetDiskSpace( savefilename, &total, &available );
392 		if( FileLength() > available ){
393 			int state = wxMessageBox( wxString::Format( _( "There are not enough free disk space.\nRequired: %s\nAvailable: %s"),
394 															wxFileName::GetHumanReadableSize( wxULongLong(FileLength()) ),
395 															wxFileName::GetHumanReadableSize( wxULongLong(available.GetValue()) ) ), _("Not Enought Space"), wxCANCEL|wxOK|wxICON_QUESTION, this );
396 			if(state==wxCANCEL)
397 				return false;
398 			}
399 		}while(FileLength() > available);
400 
401 	if(savefile.IsOpened()) {
402 		myfile->Seek( 0, wxFromStart);
403 		int64_t range = FileLength();
404 		wxString msg = _("File save in progress");
405 		wxString emsg = wxT("\n");
406 		wxProgressDialog mpd( _("Saving file"),msg+emsg, 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_CAN_ABORT|wxPD_REMAINING_TIME|wxPD_SMOOTH );
407 		mpd.Show();
408 		int BlockSz = 128*1024;
409 		char *buffer = new char[BlockSz];
410 		uint64_t readfrom=0,readspeed=0;
411 		unsigned rd;
412 
413 		time_t ts,te;
414 		time (&ts);
415 		while( savefile.Tell() < FileLength() ) {
416 			rd=myfile->Read( buffer, BlockSz );
417 			readfrom+=rd;
418 			if( savefile.Write( buffer, rd ) != rd ){
419 				savefile.Close();
420 				wxRemoveFile( savefilename );
421 				return false;
422 				};
423 			memset(buffer,0,BlockSz);
424 			time(&te);
425 			if(ts != te ){
426 				ts=te;
427 				emsg = msg + wxT("\n") + _("Write Speed : ") + wxString::Format( wxT("%.2f "), 1.0*(readfrom-readspeed)/MB) + _("MB/s");
428 				readspeed=readfrom;
429 				}
430 			if( !mpd.Update( (readfrom*1000)/range, emsg) ){
431 				savefile.Close();
432 				wxRemoveFile( savefilename );
433 				wxMessageBox( wxString(_("File cannot save as ")).Append( savefilename ),_("Error"), wxOK|wxICON_ERROR, this );
434 				return false;
435 				}
436 			}
437 		return true;
438 		}
439 	else
440 		return false;
441 	}
442 
FileClose(bool WithoutChange)443 bool HexEditor::FileClose( bool WithoutChange ) {
444 	if( myfile != NULL ) {
445 		if( myfile->IsChanged() && !WithoutChange) {
446 			int state = wxMessageBox( _( "Do you want to save file?\n"), _("File Has Changed!"), wxYES_NO|wxCANCEL|wxICON_QUESTION, this );
447 			switch(state) {
448 				case(wxYES):
449 					if( !FileSave( false ) )
450 						return false;
451 					break;
452 				case(wxNO):
453 					break;
454 				case(wxCANCEL):
455 					return false;
456 				default:
457 					wxBell();
458 				}
459 			}
460 		if( !SaveTAGS( myfile->GetFileName() ) && MainTagArray.Count() != 0 )
461 			while( wxYES == wxMessageBox( _( "TAG file cannot be saved to default location.\nDo you want to Export TAGs file?"), _("TAGs Cannot Be Saved!!"), wxYES_NO|wxYES_DEFAULT|wxICON_EXCLAMATION, this ) )
462 				{
463 				wxFileDialog filediag(this,_("Choose a file for export TAGs"),
464 													wxEmptyString,
465 													wxEmptyString,
466 													wxT("*.tags"),
467 													wxFD_SAVE|wxFD_OVERWRITE_PROMPT|wxFD_CHANGE_DIR,
468 													wxDefaultPosition);
469 				if(wxID_OK == filediag.ShowModal())
470 						if( SaveTAGS( wxFileNameFromPath(filediag.GetPath()) ) )
471 							break;
472 						else
473 							wxMessageBox( wxString(_( "TAGs cannot be exported to file : ")).Append( filediag.GetPath() ),_("Error"), wxOK|wxICON_ERROR, this );
474 				else
475 					break;
476 				}
477 
478 		MainTagArray.Empty();
479 		CompareArray.Empty();
480 		HighlightArray.Empty();
481 		//myscrollthread->GetMyThread()->Delete();
482 		//myscrollthread->GetMyThread()->Wait();
483 //		delete myscrollthread;
484 //		delete copy_mark;
485 		Clear( true );
486 		DisconnectScroll(); //disconnects file from scroll link if available
487 		myfile->Close();
488 		delete myfile;
489 		myfile = NULL;
490 		tagpanel->Set(MainTagArray);
491 
492 		}
493 	return true;
494 	}
495 
FileReOpen(void)496 bool HexEditor::FileReOpen( void ){
497 	wxFileName f = myfile->GetFileName();
498 	uint64_t last_offset = page_offset;
499 	unsigned last_cursor = GetLocalHexInsertionPoint();
500 	FileClose( true );
501 	bool success = FileOpen(f);
502 	LoadFromOffset( last_offset );
503 	SetLocalHexInsertionPoint(last_cursor);
504 	return success;
505 	};
506 
DoUndo(void)507 void HexEditor::DoUndo( void ) {
508 	//TODO: Tag Movement
509 	const DiffNode* x = myfile->GetFirstUndoNodeOrLast();
510 	if( x != NULL )
511 		if( x->flag_inject )
512 			MoveTAGS( x->start_offset, -x->size );
513 
514 	Goto( myfile->Undo() );
515 
516 #ifdef _DEBUG_FILE_
517 	std::cout << "Send UnReDo Event" << std::endl;
518 #endif
519 	wxUpdateUIEvent eventx( UNREDO_EVENT );
520 	GetEventHandler()->ProcessEvent( eventx );
521 	}
522 
DoRedo(void)523 void HexEditor::DoRedo( void ) {
524 #ifdef _DEBUG_FILE_
525 	std::cout << "Send UnReDo Event" << std::endl;
526 #endif
527 	const DiffNode* x = myfile->GetFirstUndoNodeOrLast();
528 	if( x != NULL )
529 		if( x->flag_inject )
530 			MoveTAGS( x->start_offset, x->size );
531 
532 	Goto( myfile->Redo() );
533 
534 	wxUpdateUIEvent eventx( UNREDO_EVENT );
535 	GetEventHandler()->ProcessEvent( eventx );
536 	}
537 
Goto(int64_t cursor_offset,bool set_focus)538 void HexEditor::Goto( int64_t cursor_offset, bool set_focus ){
539 #ifdef _DEBUG_
540 	std::cout << "Goto: " << cursor_offset << std::endl;
541 #endif // _DEBUG_FILE_
542 	if(page_offset <= cursor_offset &&
543 	      page_offset+ByteCapacity() >= cursor_offset) {	//cursor_offset is in visible area
544 		Reload();					//Reload data needed for undo - redo
545 		SetLocalHexInsertionPoint( (cursor_offset - page_offset)*2 );
546 		}
547 	else { // out of view
548 		page_offset = cursor_offset;
549 		page_offset -= static_cast<int64_t>( ByteCapacity() * 0.20 ); // load some bytes behind of request for make lines at top side
550 		page_offset -= page_offset % BytePerLine();	//to allign offset
551 		wxMax(0,page_offset);
552 		if(page_offset < 0)
553 			page_offset = 0;
554 		else if(page_offset > FileLength() )
555 			page_offset = wxMax(0, FileLength() - ByteCapacity() + 2*BytePerLine());
556 		Reload();
557 		SetLocalHexInsertionPoint( (cursor_offset - page_offset)*2 );
558 		}
559 //	UpdateCursorLocation();
560 //	UpdateScrollOffset(); Moved to HexEditorCtrl::ReadFromBuffer code
561 	if( set_focus )
562 		hex_ctrl->SetFocus();
563 	}
564 
BlockSelect(void)565 void HexEditor::BlockSelect( void ){
566 	if(BlockSelectOffset == -1 )
567 		BlockSelectOffset=CursorOffset();
568 	else{
569 		Select(BlockSelectOffset, CursorOffset() );
570 		UpdateCursorLocation(); //Update statusbar
571 		BlockSelectOffset = -1;
572 		}
573 	}
574 
FillSelection(void)575 bool HexEditor::FillSelection( void ){
576 	wxString hexval = wxGetTextFromUser(_( "Enter hex value(s) for fill"), _("Fill Dialog"), wxT("00"), this );
577 	if(!HexVerifyAndPrepare( hexval, _("Fill"), this ) )
578 		return false;
579 	wxMemoryBuffer pattern = hex_ctrl->HexToBin( hexval );
580 	wxMemoryBuffer buffer;
581 	for( unsigned i=0; i<select->GetSize() ; i++ )
582 		buffer.AppendByte( pattern[ i % pattern.GetDataLen() ] );
583 
584 	myfile->Add( select->GetStart(), reinterpret_cast<const char*>( buffer.GetData()), buffer.GetDataLen(), false );
585 
586 	wxUpdateUIEvent eventx( UNREDO_EVENT );
587 	GetEventHandler()->ProcessEvent( eventx );
588 
589 	Reload();
590 	return true;
591 	}
592 
SaveAsDump(void)593 bool HexEditor::SaveAsDump( void ){
594    wxFileDialog filediag(this,
595    _("Choose a file for saving dump"), wxEmptyString, wxEmptyString, wxT("*"),
596    wxFD_SAVE|wxFD_OVERWRITE_PROMPT|wxFD_CHANGE_DIR, wxDefaultPosition);
597 
598    if(wxID_OK == filediag.ShowModal()) {
599 // TODO (death#1#): Avoid overwrite of original file!
600 	wxFFile savefile( filediag.GetPath(), wxT("wb") );
601       if(savefile.IsOpened()) {
602          int rd;
603          wxMemoryBuffer m_buffer;
604          void* buff=NULL;
605 			buff = m_buffer.GetWriteBuf( select->GetSize() );
606 
607 			myfile->Seek( select->GetStart(), wxFromStart);
608 			rd = myfile->Read( static_cast< char*>( buff ), select->GetSize() );
609 
610 			m_buffer.UngetWriteBuf( rd );
611 			savefile.Write( m_buffer.GetData(), rd );
612 			savefile.Close();
613 			return true;
614 			}
615 	  else {
616 			wxMessageBox( wxString(_("Dump cannot saved as ")).Append( filediag.GetPath() ),_("Error"), wxOK|wxICON_ERROR, this );
617 			return false;
618 			}
619       }
620 	return false;
621    }
622 
OnOffsetScroll(wxScrollEvent & event)623 void HexEditor::OnOffsetScroll( wxScrollEvent& event ) {
624 	LoadFromOffset( static_cast<int64_t>(offset_scroll->GetThumbPosition()) * BytePerLine() );
625 	UpdateCursorLocation();
626 #if wxUSE_STATUSBAR
627 	if( statusbar != NULL )
628 		statusbar->SetStatusText(wxString::Format(_("Showing Page: %" wxLongLongFmtSpec "u"), page_offset/ByteCapacity() ), 0);
629 #endif
630 		wxYieldIfNeeded();
631 	}
632 
LoadFromOffset(int64_t position,bool cursor_reset,bool paint,bool from_comparator)633 void HexEditor::LoadFromOffset(int64_t position, bool cursor_reset, bool paint, bool from_comparator) {
634 #ifdef _DEBUG_FILE_
635 	std::cout << "\nLoadFromOffset() : " << position << std::endl;
636 #endif
637 
638 	//For file compare mode
639 	if(ComparatorHexEditor!=NULL && !from_comparator)
640 		ComparatorHexEditor->LoadFromOffset(position, cursor_reset, true, true);
641 
642 	myfile->Seek(position, wxFromStart);
643 	char *buffer = new char[ ByteCapacity() ];
644 	int readedbytes = myfile->Read(buffer, ByteCapacity());
645 
646 	if( readedbytes == -1 ){
647 		wxMessageBox( _("File cannot read!"),_("Error"), wxOK|wxICON_ERROR );
648 		delete [] buffer;
649 		return;
650 		}
651 	ReadFromBuffer( position, readedbytes, buffer, cursor_reset, paint );
652 	delete [] buffer;
653 	}
654 
ThreadPaint(wxCommandEvent & event)655 void HexEditor::ThreadPaint(wxCommandEvent& event){
656 #ifdef _DEBUG_THREAD_SCROLL_
657 	std::cout << "ThreadPaint() Enter" << std::endl;
658 #endif // _DEBUG_THREAD_SCROLL_
659 	if( event.GetId()==THREAD_UPDATE_EVENT){
660 		LoadFromOffset( page_offset, false, false );
661 		SetLocalHexInsertionPoint(GetLocalHexInsertionPoint());
662 		Selector();
663 		PaintSelection();
664 		UpdateCursorLocation( true );
665 
666 ///	Offset scroll automated at HexEditorCTRL::ReadFromBuffer
667 //		if( parent->offset_scroll->GetThumbPosition() != parent->page_offset / parent->BytePerLine() )
668 //			parent->offset_scroll->SetThumbPosition( parent->page_offset / parent->BytePerLine() );
669 
670 		event.Skip(false);
671 #ifndef DO_NOT_USE_THREAD_FOR_SCROLL
672 		myscrollthread->ThreadScrool.Unlock();
673 #endif
674 		}
675 	}
676 
677 #if _FSWATCHER_
OnFileModify(wxFileSystemWatcherEvent & event)678 void HexEditor::OnFileModify(wxFileSystemWatcherEvent &event){
679 	#ifdef _DEBUG_
680 	bool x=(event.GetChangeType()&(wxFSW_EVENT_MODIFY|wxFSW_EVENT_RENAME|wxFSW_EVENT_ATTRIB))!=0;
681 	std::cout << "HexEditor::OnFileModify()... : 0x" << std::hex<< event.GetChangeType() << std::dec << " mask:" << x << std::endl;
682 	#endif // _DEBUG_
683 	//wxFSW_EVENT_MODIFY 0x08
684 	//wxFSW_EVENT_RENAME 0x04
685 	//wxFSW_EVENT_ATTRIB 0x20 -- Some programs like gedit return this. But AFAIK our opened file is different than actual.
686 	if( (event.GetChangeType()&(wxFSW_EVENT_MODIFY))!=0
687 		&& event.GetPath() == myfile->GetFileName().GetFullPath()){
688 		Reload();
689 		}
690 	event.Skip(true);
691 	}
692 #endif
693 
Reload(void)694 void HexEditor::Reload( void ) {
695 	LoadFromOffset( page_offset, false, true, false );
696 //	myfile->Seek(page_offset, wxFromStart);
697 //	char *buffer = new char[ ByteCapacity() ];
698 //	int readedbytes = myfile->Read(buffer, ByteCapacity());
699 //	ReadFromBuffer( page_offset, readedbytes, buffer, false, true );
700 //	delete [] buffer;
701 	}
702 
ReDraw()703 void HexEditor::ReDraw(){
704 #ifdef _DEBUG_
705 	std::cout << "HexEditor::ReDraw()" << std::endl ;
706 #endif // _DEBUG_
707 	wxSizeEvent ev(GetSize());
708 	OnResize(ev);
709 	}
710 
OnResize(wxSizeEvent & event)711 void HexEditor::OnResize( wxSizeEvent &event ) {
712 #ifdef _DEBUG_SIZE_
713 	std::cout << "HexEditor::OnResize() Event Type:" << event.GetEventType() << std::endl ;
714 	std::cout << "ByteCapacity() Before:" << ByteCapacity() << std::endl;
715 #endif
716 	HexEditorCtrl::OnResize( event );
717 	//event.Skip( true );
718 	if(myfile != NULL && 0 < BytePerLine()){
719 		offset_scroll->SetScrollbar(page_offset / BytePerLine(),
720 		                            LineCount(),
721 		                            1 + FileLength() / BytePerLine(),
722 		                            LineCount(),true
723 		                           );
724 		Reload();
725 		}
726 	}
727 
FileAddDiff(int64_t start_byte,const char * data,int64_t size,bool injection)728 bool HexEditor::FileAddDiff( int64_t start_byte, const char* data, int64_t size, bool injection ) {
729 	return myfile->Add( start_byte, data, size, injection );
730 	}
731 
OnKeyboardSelector(wxKeyEvent & event)732 void HexEditor::OnKeyboardSelector(wxKeyEvent& event) {
733 	#ifdef _DEBUG_SELECT_
734 	std::cout << "HexEditor::OnKeyboardSelector's event.ShiftDown()=" << event.ShiftDown() << std::endl;
735 	#endif
736 	//On GTK, only ShiftDown doesn't return event.ShiftDwn()
737 	#ifdef __WXMSW__
738 	if(	event.GetKeyCode()==WXK_UP || event.GetKeyCode()==WXK_NUMPAD_UP ||
739 			event.GetKeyCode()==WXK_DOWN || event.GetKeyCode()==WXK_NUMPAD_DOWN ||
740 			event.GetKeyCode()==WXK_LEFT || event.GetKeyCode()==WXK_NUMPAD_LEFT ||
741 			event.GetKeyCode()==WXK_RIGHT || event.GetKeyCode()==WXK_NUMPAD_RIGHT ||
742 			event.GetKeyCode()==WXK_HOME || event.GetKeyCode()==WXK_NUMPAD_HOME ||
743 			event.GetKeyCode()==WXK_END || event.GetKeyCode()==WXK_NUMPAD_END ||
744 			event.GetKeyCode()==WXK_PAGEUP || event.GetKeyCode()==WXK_NUMPAD_PAGEUP ||
745 			event.GetKeyCode()==WXK_PAGEDOWN || event.GetKeyCode()==WXK_NUMPAD_PAGEDOWN
746 		)
747 	#endif
748 	if( event.ShiftDown() ){
749 		Selector();
750 		}
751 	else if( event.ControlDown() || event.AltDown() ){
752 		//do nothing!
753 		}
754 	else if( select->GetState() ) //Only SetState if there is a selection to decrease OnUpdateUI event overhead!
755 		select->SetState( false );
756 	}
757 
758 // TODO (death#1#): BUG: Remove Text Selection when UNDO (CTRL+SHIFT)
759 // TODO (death#5#): File Name star'in * when file changed & saved
760 
OnKeyboardInput(wxKeyEvent & event)761 void HexEditor::OnKeyboardInput( wxKeyEvent& event ) {
762 #ifdef _DEBUG_
763 		std::cout << "Received KeyCode : " << std::hex << event.GetKeyCode() << std::endl;
764 #endif
765 	if(myfile != NULL) {
766 		wxHexCtrl *myctrl = static_cast<wxHexCtrl*>(event.GetEventObject());
767 		//Keyboard Selection Code
768 		if( event.ShiftDown() &&
769 			(event.GetKeyCode()==WXK_UP || event.GetKeyCode()==WXK_NUMPAD_UP ||
770 			event.GetKeyCode()==WXK_DOWN || event.GetKeyCode()==WXK_NUMPAD_DOWN ||
771 			event.GetKeyCode()==WXK_LEFT || event.GetKeyCode()==WXK_NUMPAD_LEFT ||
772 			event.GetKeyCode()==WXK_RIGHT || event.GetKeyCode()==WXK_NUMPAD_RIGHT ||
773 			event.GetKeyCode()==WXK_HOME || event.GetKeyCode()==WXK_NUMPAD_HOME ||
774 			event.GetKeyCode()==WXK_END || event.GetKeyCode()==WXK_NUMPAD_END ||
775 			event.GetKeyCode()==WXK_PAGEUP || event.GetKeyCode()==WXK_NUMPAD_PAGEUP ||
776 			event.GetKeyCode()==WXK_PAGEDOWN || event.GetKeyCode()==WXK_NUMPAD_PAGEDOWN )
777 			)
778                 OnKeyboardSelector(event);	//Selection Starter call
779 
780 		switch (event.GetKeyCode()) {
781 			case (WXK_UP):
782 			case (WXK_NUMPAD_UP):
783 				if (ActiveLine() == 1) {	//If cursor at first line
784 					if( page_offset == 0 )
785 						wxBell();					// there is no line over up!
786 					else {							// Illusion code
787 						LoadFromOffset( page_offset - BytePerLine() );	//offset decreasing one line & update text with new location, makes screen slide illusion
788 						UpdateCursorLocation();
789 						}
790 					}
791 				else
792 					SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() - HexPerLine() );
793 				break;
794 
795 			case (WXK_DOWN):
796 			case (WXK_NUMPAD_DOWN):
797 				if ( ActiveLine() == LineCount() ) {			//If cursor at bottom of screen
798 					if(page_offset + ByteCapacity() < FileLength() ) { //detects if another line is present or not
799 						int temp = GetLocalHexInsertionPoint();	//preserving cursor location
800 						LoadFromOffset( page_offset + BytePerLine() );	//offset increasing one line and update text with new location, makes screen slide illusion
801 						SetLocalHexInsertionPoint(temp);			//restoring cursor location
802 						}
803 					else {
804 						wxBell();											//there is no line to slide bell
805 						}
806 					}
807 				else if( ActiveLine() * HexPerLine() > GetLastPosition() )
808 					wxBell();	//If cursor at last line but not at bottom of screen
809 				else
810 					SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() + HexPerLine() );
811 				break;
812 // TODO (death#1#): bug in left & text ctrl
813 			case (WXK_LEFT):
814 			case (WXK_NUMPAD_LEFT):
815 				if( GetLocalHexInsertionPoint() == 0) {
816 					if(page_offset == 0)
817 						wxBell();
818 					else {
819 						LoadFromOffset( page_offset - BytePerLine() );
820 						SetLocalHexInsertionPoint( HexPerLine() - ((myctrl == hex_ctrl) ? 1 : 2) );
821 						}
822 					}
823 				else
824 					SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() - ((myctrl == hex_ctrl) ? 1 : 2) );
825 				break;
826 			case (WXK_RIGHT):
827 			case (WXK_NUMPAD_RIGHT):{
828 				wxHexTextCtrl *mytxtctrl = dynamic_cast<wxHexTextCtrl*>(event.GetEventObject());
829 				int a=0, b=0;
830 				if( mytxtctrl ){
831 				   a = mytxtctrl->GetInsertionPoint();
832 				   b = mytxtctrl->GetLastPosition();
833 					}
834 				else{
835 					a = myctrl->GetInsertionPoint();
836 				   b = myctrl->GetLastPosition();
837 				   }
838 
839 				if( a >= b ) {
840 					if(page_offset + ByteCapacity() < FileLength() ) {	//Checks if its EOF or not
841 						LoadFromOffset( page_offset + BytePerLine() );
842 						SetLocalHexInsertionPoint( (LineCount() - 1) * HexPerLine() );
843 						}
844 					else
845 						wxBell();
846 					}
847 				else
848 					SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() +  ((myctrl == hex_ctrl)? 1 : 2) );
849 				break;
850 				}
851 			case (WXK_HOME):
852 			case(WXK_NUMPAD_HOME): {
853 					SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() - GetLocalHexInsertionPoint() % HexPerLine() );
854 					break;
855 					}
856 			case (WXK_END):
857 			case(WXK_NUMPAD_END): {
858 					SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() + HexPerLine() - (GetLocalHexInsertionPoint() % HexPerLine()) - 1  );
859 					break;
860 					}
861 			case (WXK_PAGEUP):
862 			case (WXK_NUMPAD_PAGEUP):
863 				if(page_offset - ByteCapacity() > 0) {
864 //							int temp = GetHexInsertionPoint();
865 					LoadFromOffset(page_offset -  ByteCapacity());
866 					UpdateCursorLocation();
867 //							SetLocalHexInsertionPoint(temp);
868 					}
869 				else {
870 					int temp = GetLocalHexInsertionPoint() % HexPerLine();
871 					LoadFromOffset( 0 );
872 					SetLocalHexInsertionPoint(temp);
873 					wxBell();
874 					}
875 				break;
876 // TODO (death#5#): Add last byte problem. Also text ctrl has +1 issue
877 			case (WXK_PAGEDOWN):
878 			case (WXK_NUMPAD_PAGEDOWN):
879 				if(page_offset + ByteCapacity()*2 < FileLength()) { //*2 for cosmetic
880 					int temp = GetLocalHexInsertionPoint();
881 					LoadFromOffset( page_offset +  ByteCapacity() );
882 					SetLocalHexInsertionPoint( temp );
883 					}
884 				else {
885 					int temp = ( GetLocalHexInsertionPoint() %  HexPerLine() ) + ( LineCount()-1 ) * HexPerLine();
886 					page_offset = FileLength() - ByteCapacity();
887 					page_offset += BytePerLine() - page_offset % BytePerLine(); //cosmetic
888 					Reload();
889 					SetLocalHexInsertionPoint(temp);
890 					wxBell();
891 					}
892 				break;
893 
894 			case (WXK_DELETE):
895 			case (WXK_NUMPAD_DELETE):
896 				/*if( myctrl->GetInsertionPoint() != myctrl->GetLastPosition() ){
897 					int hex_loc = myctrl->GetInsertionPoint();
898 					HexCharReplace(hex_loc,'0');
899 					myctrl->SetInsertionPoint(hex_loc);
900 					}
901 				else
902 				*/
903 				wxBell();
904 				break;
905 
906 			case (WXK_BACK):
907 				/*
908 				if( myctrl->GetInsertionPoint()!=0 ){
909 					HexCharReplace(myctrl->GetInsertionPoint()-1,'0');
910 					myctrl->SetInsertionPoint(myctrl->GetInsertionPoint()-1);
911 					}
912 				else
913 					if(page_offset == 0)
914 						wxBell();
915 					else{	//Has to be a line over up
916 				// TODO (death#3#): if BytePerLine() changes, current offset gona be mad, like taking minus argument because it thinks a compleete line over up... spend caution about it.
917 							page_offset -= myctrl->BytePerLine();
918 							LoadFromOffset( page_offset );
919 							HexCharReplace(myctrl->HexPerLine()-1,'0');
920 							myctrl->SetInsertionPoint(myctrl->HexPerLine()-1);
921 							}
922 					*/
923 				break;
924 
925             //Not working?
926             //case (WXK_CONTROL_T):
927             case (0x54):
928                 if( event.ControlDown() )
929                    HexEditorCtrl::TagCreator( !event.ShiftDown() );
930                 break;
931 
932 			default: {
933 ////This part handled by wxMenuItem shortcuts.
934 ////					if( event.ControlDown() )
935 ////						switch( event.GetKeyCode() ) {
936 ////							case( 0x5a ):		// CTRL+Z = UNDO
937 ////								if(event.ShiftDown())
938 ////									DoRedo();	// UNDO with shift = REDO
939 ////								else
940 ////									DoUndo();
941 ////								break;
942 ////							case( 0x59 ):		// CTRL+Y = REDO
943 ////								DoRedo();
944 ////								break;
945 ////							case( 0x53 ): {	// CTRL+S = SAVE
946 ////									FileSave();
947 ////									// TODO (death#1#): File Name star'in * when file changed & saved
948 ////									}
949 ////								break;
950 ////							case( 0x41 ):		// CTRL+A = ALL
951 ////								Select(0, FileLength());
952 ////								break;
953 ////							case( 0x58 ):		// CTRL+X = CUT
954 ////								wxBell();
955 ////								break;
956 ////							case( 0x43 ):		// CTRL+C = COPY
957 ////								CopySelection();
958 ////								break;
959 ////							case( 0x56 ):		// CTRL+V = PASTE
960 ////								PasteFromClipboard();
961 ////								break;
962 ////							case( 0x46 ):		// CTRL+F = FIND
963 ////							   FindDialog();
964 ////								break;
965 ////							case( 0x4f ):		// CTRL+O = OPEN
966 ////								wxBell();
967 ////								break;
968 ////							default:
969 ////								event.Skip();// ->OnKeyboardChar( event );
970 ////								break;
971 ////							}
972 ////					else if ( not event.AltDown() )
973 						event.Skip();// ->OnKeyboardChar( event );
974 					}
975 
976 
977 			}//switch end
978 		//UpdateScrollOffset(); Moved to HexEditorCtrl::ReadFromBuffer code
979 		OnKeyboardSelector(event);//Keeps Keyboard Selection proper
980 		PaintSelection( );
981 		}
982 	}
983 
OnKeyboardChar(wxKeyEvent & event)984 void HexEditor::OnKeyboardChar( wxKeyEvent& event ) {
985 	if(myfile != NULL ) {
986 		wxChar chr = event.GetKeyCode();
987 
988 		if( event.GetEventObject() == hex_ctrl ) {
989 			if( isxdigit(chr) ) {
990 				(chr>='a'&&chr<='f')?(chr-=('a'-'A')):(chr=chr);		// Upper() for Char
991 				HexCharReplace( GetLocalHexInsertionPoint(), chr);		// write to screen
992 
993 				char rdchr = hex_ctrl->ReadByte( GetLocalHexInsertionPoint()/2 );	// read from screen
994 				FileAddDiff( CursorOffset(), &rdchr ,1);				// add node to file
995 
996 				if( hex_ctrl->GetInsertionPoint() >= hex_ctrl->GetLastPosition() ) {
997 					if( CursorOffset() + ByteCapacity() <= FileLength() ) {	//Checks if its EOF or not
998 						LoadFromOffset( page_offset + BytePerLine() );
999 						hex_ctrl->LastLine();
1000 						hex_ctrl->Home();
1001 						}
1002 					else
1003 						wxBell();
1004 					}
1005 				else
1006 					hex_ctrl->NextChar();
1007 				}
1008 			else
1009 				wxBell();
1010 			}
1011 		else if( event.GetEventObject() == text_ctrl ) {
1012 			if( wxString((wxChar)event.GetKeyCode()).IsAscii() &&
1013 			      event.GetKeyCode()!=WXK_BACK &&
1014 			      event.GetKeyCode()!=WXK_DELETE &&
1015 			      !event.ControlDown()
1016 			  ) {
1017 
1018 				/*				if( text_ctrl->GetInsertionPoint() >= text_ctrl->GetLastPosition()){
1019 									if(current_offset+hex_ctrl->ByteCapacity() <= myTempFile->Length() ){	//Checks if its EOF or not
1020 										current_offset += hex_ctrl->BytePerLine();
1021 										LoadFromOffset(current_offset);
1022 										text_ctrl->LastLine();	// HexPerLine = BytePerLine()*2
1023 										}
1024 									}
1025 				*/
1026 				int GLIP = GetLocalInsertionPoint();	//this required because TextCharReplace() calls HexCtrl->Replace that alters entering point
1027 				TextCharReplace(GLIP, event.GetKeyCode());
1028 				char rdchr = hex_ctrl->ReadByte( GLIP );	// read from screen
1029 				FileAddDiff( GLIP + page_offset, &rdchr ,1);						// add node to file
1030 
1031 				if( text_ctrl->GetInsertionPoint() >= text_ctrl->GetLastPosition() ) {
1032 					if( page_offset + ByteCapacity() <= FileLength() ) {	//Checks if its EOF or not
1033 						LoadFromOffset(page_offset + BytePerLine());
1034 						text_ctrl->LastLine();
1035 						text_ctrl->Home();
1036 						}
1037 					else
1038 						wxBell();
1039 					}
1040 				else
1041 					text_ctrl->NextChar();
1042 				}
1043 			else
1044 				wxBell();
1045 			}
1046 		}
1047 #ifdef _DEBUG_FILE_
1048 	std::cout << "Send UnReDo Event" << std::endl;
1049 #endif
1050 	wxUpdateUIEvent eventx( UNREDO_EVENT );
1051 	GetEventHandler()->ProcessEvent( eventx );
1052 
1053 	if( event.AltDown() || event.ControlDown() ) //Control if CTRL or ALT true otherwise evet.skip will also run wxHex::OnChar which makes artefacts.
1054 	   event.Skip(); //This required for ALT+F or CTRL+X...
1055 	}
1056 
SetLocalHexInsertionPoint(int hex_location,bool from_comparator)1057 void HexEditor::SetLocalHexInsertionPoint( int hex_location, bool from_comparator ) {
1058 	if(ComparatorHexEditor!=NULL && !from_comparator)
1059 		ComparatorHexEditor->SetLocalHexInsertionPoint( hex_location, true);
1060 
1061 	HexEditorCtrl::SetLocalHexInsertionPoint( hex_location );
1062 	UpdateCursorLocation();
1063 	}
1064 
OnMouseLeft(wxMouseEvent & event)1065 void HexEditor::OnMouseLeft(wxMouseEvent& event) {
1066 	HexEditorCtrl::OnMouseLeft( event );
1067 #if wxUSE_STATUSBAR
1068 	if ( statusbar ) {
1069 		statusbar->SetStatusText(_("Selected Block: N/A"), 3);
1070 		statusbar->SetStatusText(_("Block Size: N/A") ,4);
1071 		}
1072 #endif // wxUSE_STATUSBAR
1073 	UpdateCursorLocation();
1074 #ifdef _DEBUG_MOUSE_
1075 	std::cout << "CaptureMouse()\n" ;
1076 #endif
1077 	if( MouseCapture == false ) {
1078 		if(FindFocus() == hex_ctrl ) {
1079 			hex_ctrl->CaptureMouse();
1080 			MouseCapture = true;
1081 			}
1082 		else if( FindFocus() == text_ctrl ) {
1083 			text_ctrl->CaptureMouse();
1084 			MouseCapture = true;
1085 			}
1086 		}
1087 	}
1088 
OnMouseRight(wxMouseEvent & event)1089 void HexEditor::OnMouseRight( wxMouseEvent& event ) {
1090 	if(event.GetEventObject() == hex_ctrl)
1091 		LastRightClickAt = page_offset + hex_ctrl->PixelCoordToInternalPosition( event.GetPosition() )/2;
1092 	else if(event.GetEventObject() == text_ctrl)
1093 		LastRightClickAt = page_offset + text_ctrl->PixelCoordToInternalPosition( event.GetPosition() );
1094 	else if( event.GetEventObject() == offset_ctrl){
1095 
1096 		offset_ctrl->OnMouseRight( event );
1097 		int x,y;
1098 		DoGetSize(&x,&y);
1099 		wxSizeEvent mevent(wxSize(x,y));
1100 		OnResize(mevent);
1101 		UpdateCursorLocation();
1102 		return;//to avoid ShowContextMenu
1103 		}
1104 
1105 	//Adjust required operations enable/disable
1106 	ShowContextMenu( event );
1107 
1108 	event.Skip(false); //Disables HexEditorCtrl::OnMouseRight
1109 	}
1110 
ShowContextMenu(const wxMouseEvent & event)1111 void HexEditor::ShowContextMenu( const wxMouseEvent& event ) {
1112 	wxMenu menu;
1113 	uint64_t TagPosition=0;
1114 	if( event.GetEventObject() == hex_ctrl )
1115 		TagPosition = page_offset + (hex_ctrl->PixelCoordToInternalPosition( event.GetPosition() ) / 2);
1116 	else if( event.GetEventObject() == text_ctrl )
1117 		TagPosition = page_offset + text_ctrl->PixelCoordToInternalPosition( event.GetPosition() );
1118 
1119 	menu.Append(wxID_COPY, _("Copy"));
1120 	menu.Append(idCopyAs, wxString( _("CopyAs") ) + wxChar('\t') + wxT("CTRL+SHIFT+C"));
1121 	menu.Append(wxID_PASTE, _("Paste"));
1122 	if(!IsFileUsingXORKey()){
1123 		menu.AppendSeparator();
1124 		menu.Append(wxID_CUT, _("Cut"));
1125 		menu.Append(wxID_DELETE, _("Delete"));
1126 		menu.Append(idInjection, _("Insert"));
1127 		}
1128 //	if(XORKey == wxEmptyString){//Disable injection on XORkey
1129 //		menu.Enable( idInjection, select->IsState( select->SELECT_FALSE) );
1130 //		menu.Enable( wxID_CUT, select->IsState( select->SELECT_END) );
1131 //		menu.Enable( wxID_DELETE, select->IsState( select->SELECT_END) );
1132 //		}
1133 
1134 	menu.AppendSeparator();
1135 	menu.Append(idSaveAsDump, wxString( _("Save As Dump") )+wxChar('\t')+wxT("CTRL+ALT+S"));
1136 	menu.Append(idFillSelection, _("Fill Selection"));
1137 	if( BlockSelectOffset == -1 )
1138 		menu.Append(idBlockSelect, _("Set Selection Block Start"));
1139 	else
1140 		menu.Append(idBlockSelect, _("Set Selection Block End"));
1141 	menu.AppendSeparator();
1142 	menu.Append(idTagQuick,        wxString( _("Quick Tag") ) + wxChar('\t') + wxT("CTRL+T"), _("Creates empty tag with Random Color."));
1143 	menu.Append(idTagAddSelection, wxString( _("New Tag") )+ wxChar('\t') + wxT("CTRL+SHIFT+T") );
1144 	menu.Append(idTagEdit,          _("Tag Edit"));
1145 //	menu.AppendSeparator();
1146 //	menu.Append(idClose, 			 _("Close File")); Results Seg-error
1147 
1148 	menu.Enable( idTagEdit, false );
1149 	for( unsigned i = 0 ; i < MainTagArray.Count() ; i++ ) {
1150 		TagElement *TAG = MainTagArray.Item(i);
1151 		if( TAG->isCover(TagPosition) ) {
1152 			menu.Enable( idTagEdit, true );
1153 			break;
1154 			}
1155 		}
1156 
1157 	menu.Enable( idTagQuick, select->GetState() );
1158 	menu.Enable( idTagAddSelection, select->GetState() );
1159 	menu.Enable( wxID_COPY, select->GetState() );
1160 	menu.Enable( idCopyAs, select->GetState() );
1161 	menu.Enable( idSaveAsDump, select->GetState() );
1162 	menu.Enable( idFillSelection, select->GetState() );
1163 	menu.Enable( wxID_PASTE, !select->GetState() );
1164 
1165 	if( !IsBlockDevice() ){
1166 		menu.Enable( wxID_DELETE, select->GetState());
1167 		menu.Enable( idInjection, !select->GetState());
1168 		menu.Enable( wxID_CUT, select->GetState());
1169 		}
1170 	else{
1171 		menu.Enable( wxID_DELETE, false);
1172 		menu.Enable( idInjection, false);
1173 		menu.Enable( wxID_CUT, false);
1174 		}
1175 
1176 	if( FileLength() == 0 ){
1177 		unsigned ids[]={wxID_DELETE, idTagQuick, idTagAddSelection, idTagEdit, wxID_COPY, idCopyAs, idSaveAsDump, idFillSelection, wxID_PASTE, wxID_DELETE, wxID_CUT};
1178 		for( unsigned i=0; i< sizeof(ids)/4 ; i++ ){
1179 			menu.Enable( ids[i], false );
1180 			printf("i: %d\n",i);
1181 			}
1182 		menu.Enable( idInjection, false );
1183 		}
1184 
1185 	wxPoint pos = event.GetPosition();
1186 	wxWindow *scr = static_cast<wxWindow*>( event.GetEventObject() );
1187 	pos += scr->GetPosition();
1188 	PopupMenu(&menu, pos);
1189 	// test for destroying items in popup menus
1190 #if 0 // doesn't work in wxGTK!
1191 // TODO (death#1#): inspect here	menu.Destroy(Menu_Popup_Submenu);
1192 	PopupMenu( &menu, event.GetX(), event.GetY() );
1193 #endif // 0
1194 	}
1195 
OnMouseWhell(wxMouseEvent & event)1196 void HexEditor::OnMouseWhell( wxMouseEvent& event ) {
1197 #ifdef _DEBUG_MOUSE_
1198 	std::cout << "MouseWhell Rotation = " << event.GetWheelRotation() << "\t Delta = " << event.GetWheelDelta()
1199 	          << "\tLinesPerAction: " << event.GetLinesPerAction() << std::endl;
1200 
1201 #endif
1202 	if(event.GetWheelRotation() > 0) {		// Going to UP
1203 		page_offset -= BytePerLine()*event.GetLinesPerAction(); 	//offset decreasing
1204 		if( page_offset <= 0 ) {
1205 			page_offset = 0;
1206 			wxBell();					// there is no line over up!
1207 			}
1208 		Reload();	//update text with new location, makes screen slide illusion
1209 		if( page_offset != 0 ) {
1210 			if( ActiveLine() + event.GetLinesPerAction() <= LineCount() )	//cursor at bottom
1211 				SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() + HexPerLine() * event.GetLinesPerAction() );	//restoring cursor location
1212 			else
1213 				SetLocalHexInsertionPoint( GetLocalHexInsertionPoint()%HexPerLine() + HexPerLine()*(LineCount()-1) );
1214 			}
1215 		}
1216 	else if(event.GetWheelRotation() < 0 ) {	// Going to BOTTOM
1217 		if(page_offset + ByteCapacity() < FileLength() ) { //detects if another line is present or not
1218 			LoadFromOffset( page_offset + BytePerLine() * event.GetLinesPerAction());	//offset increasing line as mouse whell rolls
1219 			if( ActiveLine() > event.GetLinesPerAction() )	//cursor at top GetLinesPerAction
1220 				SetLocalHexInsertionPoint( GetLocalHexInsertionPoint() - HexPerLine() * event.GetLinesPerAction() );	//restoring cursor location
1221 			else
1222 				SetLocalHexInsertionPoint( GetLocalHexInsertionPoint()%HexPerLine() );
1223 			}
1224 		else {
1225 			wxBell();							//there is no line to slide bell
1226 			}
1227 		}
1228 	//UpdateScrollOffset(); Moved to HexEditorCtrl::ReadFromBuffer code
1229 	}
1230 
OnMouseMove(wxMouseEvent & event)1231 void HexEditor::OnMouseMove( wxMouseEvent& event ) {
1232 #ifdef _DEBUG_MOUSE_
1233 	std::cout << "HexEditor::OnMouseMove Coordinate X:Y = " << event.GetX()	<< " " << event.GetY()
1234 	          << "\tLeft mouse button:" << event.LeftIsDown() << std::endl;
1235 #endif
1236 	if( event.LeftIsDown() ) {
1237 		int spd=0;
1238 		if( event.GetY() < 0 && page_offset != 0) {
1239 			spd = static_cast<int>(0 - pow(2, abs(event.GetY()) / 25));
1240 			(spd < -1024) ? (spd = -1024):(spd=spd);
1241 			}
1242 		else if(event.GetY()> hex_ctrl->GetSize().GetHeight() && page_offset + ByteCapacity() < FileLength()) {
1243 			int pointer_diff = event.GetY() - hex_ctrl->GetSize().GetHeight();
1244 			spd = static_cast<int>(pow(2, pointer_diff / 25));
1245 			(spd > 1024) ? (spd = 1024):(spd=spd);
1246 			}
1247 #ifdef DO_NOT_USE_THREAD_FOR_SCROLL //WXMSW Stuck sometimes if thread on
1248 		ScrollNoThread( spd );
1249 	#ifdef _DEBUG_MOUSE_
1250 		std::cout << "Scroll (Non-Thread) Speed = " << spd << std::endl;
1251 	#endif
1252 #else
1253 	//This is workaround.
1254 	//Reading from RAM doesn't like read from "thread" and return "0xFF" somehow.
1255 	if( myfile->IsProcess() )
1256 		ScrollNoThread( spd );
1257 	else
1258 		myscrollthread->UpdateSpeed(spd);
1259 	#ifdef _DEBUG_MOUSE_
1260 		std::cout << "Scroll (Thread) Speed = " << spd << std::endl;
1261 	#endif
1262 #endif
1263 		HexEditorCtrl::OnMouseMove( event );//Also makes selection in it
1264 		UpdateCursorLocation();//Dont remember why did I put this here? -- Remembered, for make selection block status text proper.
1265 		}
1266 	else
1267 		event.Skip(); //need for tag views
1268 	}
1269 
ScrollNoThread(int speed)1270 void HexEditor::ScrollNoThread( int speed ) {
1271 	if( ((speed > 0) && (page_offset + ByteCapacity() < FileLength()))
1272 		|| ( (speed < 0) && (page_offset > 0) )
1273 	  ) {
1274 #ifdef _DEBUG_MOUSE_
1275 		std::cout << "Loop Scroll speed  :" << speed << std::endl;
1276 		std::cout << "Loop Pending Event :" << wxTheApp->Pending() << std::endl;
1277 #endif
1278 		page_offset += BytePerLine() * speed;
1279 		if( page_offset < 0 )
1280 			page_offset = 0;
1281 		else if( page_offset + ByteCapacity() >= FileLength() ) {
1282 			page_offset = FileLength() - ByteCapacity();
1283 			page_offset += BytePerLine() - (page_offset % BytePerLine()) ; //cosmetic
1284 			}
1285 		LoadFromOffset( page_offset, false, false );
1286 	//	SetLocalHexInsertionPoint(cursor); //to update cursor location on WXMSW!
1287 		Selector();
1288 		PaintSelection();
1289 		UpdateCursorLocation( true );
1290 		if( offset_scroll->GetThumbPosition() != page_offset / BytePerLine() )
1291 			offset_scroll->SetThumbPosition( page_offset / BytePerLine() );
1292 		}
1293 	return;
1294 	///REMAINING CODE IS DISABLED
1295 	//Old and which has errors in newer versions of wx
1296 	while( (
1297 			!wxTheApp->Pending() &&
1298 			speed != 0
1299 			)
1300 	     && ( ((speed > 0) && (page_offset + ByteCapacity() < FileLength()))
1301 			|| ( (speed < 0) && (page_offset > 0) ))
1302 	     ) {
1303 #ifdef _DEBUG_MOUSE_
1304 		std::cout << "Loop Scroll speed  :" << speed << std::endl;
1305 		std::cout << "Loop Pending Event :" << wxTheApp->Pending() << std::endl;
1306 #endif
1307 		page_offset += BytePerLine() * speed;
1308 		if( page_offset < 0 )
1309 			page_offset = 0;
1310 		else if( page_offset + ByteCapacity() >= FileLength() ) {
1311 			page_offset = FileLength() - ByteCapacity();
1312 			page_offset += BytePerLine() - (page_offset % BytePerLine()) ; //cosmetic
1313 			}
1314 		LoadFromOffset( page_offset, false, false );
1315 	//	SetLocalHexInsertionPoint(cursor); //to update cursor location on WXMSW!
1316 		Selector();
1317 		PaintSelection();
1318 		UpdateCursorLocation( true );
1319 //		if( offset_scroll->GetThumbPosition() != page_offset / ByteCapacity() )
1320 //			offset_scroll->SetThumbPosition( page_offset / ByteCapacity() );
1321 		if( offset_scroll->GetThumbPosition() != page_offset / BytePerLine() )
1322 			offset_scroll->SetThumbPosition( page_offset / BytePerLine() );
1323 
1324 		if( page_offset == 0 || page_offset + ByteCapacity() >= FileLength() )
1325 			break;
1326 
1327 		//break;
1328 		}
1329 	}
1330 
OnMouseSelectionEnd(wxMouseEvent & event)1331 void HexEditor::OnMouseSelectionEnd( wxMouseEvent& event ) {
1332 	HexEditorCtrl::OnMouseSelectionEnd( event );
1333 #ifndef DO_NOT_USE_THREAD_FOR_SCROLL
1334 	myscrollthread->UpdateSpeed( 0 );
1335 #endif
1336 	if( MouseCapture ) {
1337 #if defined( _DEBUG_ )
1338 		std::cout << "GetCapture()->ReleaseMouse()\n" ;
1339 #endif
1340       //ReleaseMouse(); //this one popup dragging issues, program crash under windows.
1341 		//GetCapture()->ReleaseMouse();//this is proper one but breaks -O3 optimizations.
1342 
1343 		//This avoid assetions and do not break the optimizations.
1344 		if(event.GetEventObject()==hex_ctrl)
1345 			hex_ctrl->ReleaseMouse();
1346 		else if (event.GetEventObject()==text_ctrl)
1347 			text_ctrl->ReleaseMouse();
1348 		MouseCapture = false;
1349 		}
1350 	}
1351 
UpdateCursorLocation(bool force)1352 void HexEditor::UpdateCursorLocation( bool force ) {
1353 	static wxMutex update;
1354 // TODO (death#1#): Search if speedup available
1355 //	static int64_t lastPoint=-1;				//? Speed up Van goh
1356 //	if( !force )
1357 //		if( lastPoint == CursorOffset() )
1358 //			return;
1359 //	lastPoint = CursorOffset();
1360 #ifdef _DEBUG_MUTEX_
1361 	std::cout << "mutex Update Locking..." << std::endl;
1362 #endif
1363 	if( update.TryLock()!=wxMUTEX_NO_ERROR ){
1364 		std::cout << "mutex update cannot lock..." << std::endl;
1365 		return;
1366 		}
1367 
1368 /// This leads recursion!
1369 //		if( GetLocalHexInsertionPoint()/2+page_offset > FileLength() ) {
1370 //			SetLocalHexInsertionPoint( (FileLength() - page_offset)*2 - 1 );
1371 //			}
1372 	wxMemoryBuffer bfr;
1373 	myfile->Seek( CursorOffset(), wxFromStart );
1374 #ifdef _DEBUG_FILE_
1375 	std::cout << "UpdateCursorLocation() read file for panels" << std::endl;
1376 #endif
1377 
1378 	int size = myfile->Read( reinterpret_cast<char*>(bfr.GetWriteBuf( 8 )), 8);
1379 	if(size>0)
1380 		bfr.UngetWriteBuf( size );
1381 
1382 	if(size>0){
1383 		if( interpreter != NULL ) {
1384 			interpreter->Set( bfr );
1385 			}
1386 		if( dasmpanel != NULL ) {
1387 			if( ! select->GetState() ){ //If there is a NO selection, take 8 bytes from cursor location
1388 				dasmpanel->Set( bfr );
1389 				}
1390 			else{  //If there is a selection, use selection up to 100 bytes.
1391 				myfile->Seek( select->GetStart(), wxFromStart );
1392 				//Take just first 128 bytes!
1393 				int sz = select->GetSize() > 128 ? 128 : select->GetSize();
1394 			#ifdef _DEBUG_FILE_
1395 				std::cout << "UpdateCursorLocation() read file for dasm" << std::endl;
1396 			#endif
1397 				int size = myfile->Read( reinterpret_cast<char*>(bfr.GetWriteBuf( sz )), sz);
1398 				bfr.UngetWriteBuf( size );
1399 				dasmpanel->Set( bfr );
1400 				}
1401 			}
1402 	}
1403 #if wxUSE_STATUSBAR
1404 	if( statusbar != NULL ) {
1405 		statusbar->SetStatusText(wxString::Format(_("Showing Page: %" wxLongLongFmtSpec "u"), page_offset/ByteCapacity() ), 0);
1406 		statusbar->SetStatusText(wxString::Format(_("Cursor Offset: ") +  offset_ctrl->GetFormatedOffsetString( CursorOffset(), true )), 1);
1407 		statusbar->SetStatusText(wxString::Format(_("Cursor Value: %u"), reinterpret_cast<uint8_t*>(bfr.GetData())[0]), 2);
1408 		if( !select->GetState() ) {
1409 			statusbar->SetStatusText(_("Selected Block: N/A"), 3);
1410 			statusbar->SetStatusText(_("Block Size: N/A") ,4);
1411 			}
1412 		else {
1413 			statusbar->SetStatusText(wxString::Format(_("Selected Block: %" wxLongLongFmtSpec "u -> %" wxLongLongFmtSpec "u"),select->GetStart(),select->GetEnd()), 3);
1414 			statusbar->SetStatusText(wxString::Format(_("Block Size: %" wxLongLongFmtSpec "u"), select->GetSize()), 4);
1415 			}
1416 		}
1417 #endif // wxUSE_STATUSBAR
1418 #ifdef _DEBUG_MUTEX_
1419 	std::cout << "mutex Update UnLocking..." << std::endl;
1420 #endif
1421 	update.Unlock();
1422 	}
1423 
OnMouseTest(wxMouseEvent & event)1424 void HexEditor::OnMouseTest( wxMouseEvent& event ) {
1425 	myfile->ShowDebugState();
1426 	}
1427 
FindDialog(void)1428 void HexEditor::FindDialog( void ) {
1429 	::FindDialog *myfind = new ::FindDialog( this, myfile );
1430 	myfind->ShowModal();
1431 	#ifndef __WXOSX__ // TODO: This might leak memory but OSX magically give error if I Destroy this.. Really Weird. Please help to fix this.
1432 	myfind->Destroy();
1433 	#endif
1434 	}
1435 
ReplaceDialog(void)1436 void HexEditor::ReplaceDialog( void ) {
1437 	::ReplaceDialog *myfind = new ::ReplaceDialog( this, myfile );
1438 	myfind->ShowModal();
1439 	#ifndef __WXOSX__ // TODO: This might leak memory but OSX magically give error if I Destroy this.. Really Weird. Please help to fix this.
1440 	myfind->Destroy();
1441 	#endif
1442 	}
1443 
CopyAsDialog(void)1444 void HexEditor::CopyAsDialog( void ) {
1445 	::CopyAsDialog *mycopyas = new ::CopyAsDialog( this, myfile, HexEditorCtrl::select, &MainTagArray );
1446 	mycopyas->ShowModal();
1447 	#ifndef __WXOSX__ // TODO: This might leak memory but OSX magically give error if I Destroy this manually... Really Weird...
1448 	mycopyas->Destroy();
1449 	#endif
1450 	}
1451 
GotoDialog(void)1452 void HexEditor::GotoDialog( void ) {
1453 	uint64_t newoffset;
1454 	::GotoDialog *mygoto = new ::GotoDialog( this, newoffset, CursorOffset(), FileLength(), FDtoBlockSize( GetFD() ) );
1455 	if( mygoto->ShowModal() == wxID_OK ) {
1456 		Goto( newoffset );
1457 		}
1458 	mygoto->Destroy();
1459 	}
1460 
InsertBytes(void)1461 bool HexEditor::InsertBytes( void ) {
1462 #ifdef _DEBUG_
1463 	std::cout << "Insert Bytes!" << std::endl;
1464 #endif
1465 	long injection_size = wxGetNumberFromUser( wxString::Format(_("Notice!: This command will increase the file size and will generate too much overhead on file save.\n" \
1466 	                      "How many bytes do you want to inject to location to offset location %lld?"), CursorOffset()), _("Bytes"), _("Injection!"), 0, 0, 0x7fffffff ); //Max long up to 2 GB insertion.
1467 	std::cout << "insert " << injection_size << " bytes " << std::endl;
1468 	if( injection_size == -1 )
1469 		return false;
1470 
1471 	char* zerostream = new char[injection_size];
1472 	if( zerostream == NULL)
1473 		return false;
1474 	for(int i=0; i < injection_size ; i++) zerostream[i]=0; //Fill stream with 0
1475 	bool success=myfile->Add( CursorOffset(), zerostream, injection_size, true );
1476 
1477 	if(success)
1478 		MoveTAGS( CursorOffset(), injection_size );
1479 	select->SetState( false );
1480 
1481 	delete [] zerostream;
1482 
1483 	infopanel->Set( GetFileName(), FileLength(), GetFileAccessModeString(), GetFD(), FileGetXORKey() );
1484 
1485 	Reload();
1486 	wxUpdateUIEvent eventx( UNREDO_EVENT );
1487 	GetEventHandler()->ProcessEvent( eventx );
1488 	return success;
1489 	}
1490 
CutSelection(void)1491 bool HexEditor::CutSelection( void ) {
1492 #ifdef _DEBUG_
1493 	std::cout << "CutSelection!" << std::endl;
1494 #endif
1495 	bool success=false;
1496 	if( CopySelection() ) {
1497 		success=DeleteSelection();
1498 		infopanel->Set( GetFileName(), FileLength(), GetFileAccessModeString(), GetFD(), FileGetXORKey() );
1499 		}
1500 	return success;
1501 	}
1502 
DeleteSelection(void)1503 bool HexEditor::DeleteSelection( void ) {
1504 #ifdef _DEBUG_
1505 	std::cout << "DeleteSelection!" << std::endl;
1506 #endif
1507 	bool success=false;
1508 	if( select->GetState() ) {
1509 		success = myfile->Add( std::min(select->StartOffset , select->EndOffset), NULL, -select->GetSize(), true );
1510 		if(success)
1511 			MoveTAGS( std::min(select->StartOffset , select->EndOffset), -select->GetSize() );
1512 
1513 		select->SetState( false );
1514 		}
1515 	else {
1516 		wxBell();
1517 		return false;
1518 		}
1519 	Reload();
1520 	infopanel->Set( GetFileName(), FileLength(), GetFileAccessModeString(), GetFD(), FileGetXORKey() );
1521 	wxUpdateUIEvent eventx( UNREDO_EVENT );
1522 	GetEventHandler()->ProcessEvent( eventx );
1523 	return success;
1524 	}
1525 
1526 
CopySelection(void)1527 bool HexEditor::CopySelection( void ) {
1528 	if( select->GetState()) {
1529 		uint64_t RAM_limit = 10*MB;
1530 		if(select->GetSize() < RAM_limit) {								//copy to clipboard if < 10 MB
1531 			myfile->Seek( select->GetStart(), wxFromStart );
1532 			void* buff=NULL;
1533 			buff = copy_mark->m_buffer.GetWriteBuf( select->GetSize() );
1534 			if( buff != NULL ) {
1535 				myfile->Read( static_cast< char*>( buff ), select->GetSize() );
1536 				copy_mark->m_buffer.UngetWriteBuf( select->GetSize() );
1537 				wxString CopyString;
1538 				if( focus == HEX_CTRL ) {
1539 					for( unsigned i=0 ; i<select->GetSize() ; i++ )
1540 						CopyString << wxString::Format(wxT("%02X "),static_cast<unsigned char>(copy_mark->m_buffer[i]));
1541 					CopyString.Trim();	//remove last ' '
1542 					}
1543 				else if( focus == TEXT_CTRL )
1544 					{
1545 					copy_mark->m_buffer.AppendByte('\0');
1546 
1547 					//CopyString << wxString::FromAscii( static_cast<const char*>(copy_mark->m_buffer.GetData()) );
1548 					CopyString << wxString::From8BitData( static_cast<const char*>(copy_mark->m_buffer.GetData()) );
1549 
1550 					if( select->GetSize() > CopyString.size() ) {
1551 						wxMessageBox(_( "WARNING:\n"\
1552 						                "The text you are copying includes a null character\n"\
1553 						                "(00 in the hex pane) and will be truncated!\n\n"\
1554 						                "If copying to another file in wxHexEditor you\n"\
1555 						                "should copy from the Hex pane, not the text pane"),
1556 						             _("Warning"), wxOK|wxICON_INFORMATION, this);
1557 						}
1558 					}
1559 				return copy_mark->SetClipboardData( CopyString );
1560 				}
1561 			else {
1562 				wxMessageBox( wxString(_( "You have no RAM to copy this data.")) + wxT("\n") + _("Operation cancelled!"), _("Copy To Clipboard Error"), wxOK|wxICON_ERROR, this);
1563 				return false;
1564 				}
1565 			}
1566 		else {
1567 			wxMessageBox(_( "You have tried to copy more than 10 MB of data.\n"\
1568 			                "Copying above 10 MB to clipboard is not allowed.\n"\
1569 			                "Only internal copy buffer used!"),
1570 			             _("Info"), wxOK|wxICON_INFORMATION, this);
1571 
1572 			void* buff=NULL;
1573 			buff = copy_mark->m_buffer.GetWriteBuf( select->GetSize() );
1574 			if( buff != NULL ) {
1575 				myfile->Seek( select->GetStart() , wxFromStart );
1576 				myfile->Read( static_cast<char*>(buff), select->GetSize());
1577 				copy_mark->m_buffer.UngetWriteBuf( select->GetSize() );
1578 				wxString CopyString = wxT("wxHexEditor Internal Buffer Object : ");
1579 				CopyString += wxString::Format(wxT("%p"), (copy_mark->m_buffer.GetData()) );
1580 				copy_mark->SetClipboardData( CopyString );
1581 				return true;
1582 				}
1583 			else {
1584 // TODO (death#1#): If there is no ram, use HDD temp file
1585 				return false;
1586 				}
1587 			}
1588 		}
1589 	else {
1590 		wxBell();
1591 		return false;
1592 		}
1593 	}
1594 
PasteFromClipboard(void)1595 bool HexEditor::PasteFromClipboard( void ) {
1596 	bool ret = false;
1597 	wxString str = copy_mark->GetClipboardData();
1598 		if( str.IsEmpty() )
1599 			wxMessageBox(_("No data available at clipboad!"));
1600 		else if( str.StartsWith(wxT("wxHexEditor Internal Buffer Object : "))){
1601 			wxMessageBox(_("Note: Used internal binary copy buffer at paste operation."));
1602 			myfile->Add( CursorOffset(), static_cast<const char*>(copy_mark->m_buffer.GetData()), copy_mark->m_buffer.GetDataLen(), 0 );
1603 			Select(CursorOffset(), CursorOffset()+copy_mark->m_buffer.GetDataLen()-1);
1604 			Goto( CursorOffset() + copy_mark->m_buffer.GetDataLen());
1605 			ret = true;
1606 			}
1607 		else if( focus==HEX_CTRL ) {
1608 			wxMemoryBuffer mymem = wxHexCtrl::HexToBin( str );
1609 			FileAddDiff( CursorOffset(), static_cast<char*>(mymem.GetData()), mymem.GetDataLen() );
1610 			//select->SetState( false );
1611 			Select(CursorOffset(), CursorOffset()+mymem.GetDataLen() -1);
1612 			Goto( CursorOffset() + mymem.GetDataLen());
1613 			ret = true;
1614 			}
1615 		else if ( focus==TEXT_CTRL ) {
1616 			char *ch = new char [str.Len()];
1617 			for( unsigned i=0; i<str.Len(); i++ )
1618 				ch[i] = str[i];
1619 			FileAddDiff( CursorOffset(), ch, str.Len() );
1620 			//select->SetState( false );
1621 			Select(CursorOffset(), CursorOffset()+str.Len() -1);
1622 			Goto( CursorOffset() + str.Len() );
1623 			ret = true;
1624 			}
1625 		else
1626 			wxMessageBox(wxT( "There is no focus!"), wxT("Paste Error"), wxOK|wxICON_ERROR, this);
1627 
1628 #ifdef _DEBUG_FILE_
1629 	std::cout << "Send UnReDo Event" << std::endl;
1630 #endif
1631 	wxUpdateUIEvent eventx( UNREDO_EVENT );
1632 	GetEventHandler()->ProcessEvent( eventx );
1633 	return ret;
1634 	}
1635 
OnOffsetMouse(wxMouseEvent & event)1636 void HexEditor::OnOffsetMouse(wxMouseEvent& event){
1637 	if( event.LeftIsDown() ){
1638 #ifdef _DEBUG_
1639 	std::cout << "OnOffsetMouse +1" << std::endl;
1640 #endif // _DEBUG_
1641 		LoadFromOffset( wxMin(page_offset +1, FileLength() ));
1642 		}
1643 	if( event.RightIsDown() ){
1644 #ifdef _DEBUG_
1645 	std::cout << "OnOffsetMouse -1" << std::endl;
1646 #endif // _DEBUG_
1647 		LoadFromOffset( wxMax(page_offset -1,0) );
1648 		}
1649 	}
1650