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