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 #define NANINT 0xFFFFFFFFFFFFFFFFLL
25 #include "HexDialogs.h"
26 #include <wx/progdlg.h>
27 typedef bool _Bool;
28 #include <mhash.h>
29
30 #ifdef __SSE2__
31 #include <emmintrin.h>
32 #endif
33
34 #ifdef _OPENMP_
35 #include <omp.h>
36 #endif
37
38 #ifdef __WXMSW__
39 #define wxNewline wxT("\r\n")
40 #else
41 #define wxNewline wxT("\n")
42 #endif
43
44 #ifndef __WXMSW__
45 #include <sys/resource.h>
46
SetStackLimit(void)47 void SetStackLimit(void){
48 const rlim_t kStackSize = 32L * 1024L * 1024L;
49 struct rlimit rl;
50 int result;
51
52 result = getrlimit(RLIMIT_STACK, &rl);
53 fprintf(stderr, "current stack limit = %ul\n", static_cast<unsigned int>(rl.rlim_cur) );
54 if (result == 0){
55 if (rl.rlim_cur < kStackSize)
56 {
57 rl.rlim_cur = kStackSize;
58 result = setrlimit(RLIMIT_STACK, &rl);
59 if (result != 0)
60 {
61 fprintf(stderr, "setrlimit returned result = %d\n", result);
62 }
63 }
64 }
65 }
66 #endif
67
HexVerifyAndPrepare(wxString & hexval,wxString Value_Name,wxWindow * parent)68 bool HexVerifyAndPrepare(wxString& hexval, wxString Value_Name, wxWindow* parent) {
69 if( hexval.Len() < 2 )
70 return false;
71 //Remove all space chars and update the Search value
72 while( hexval.find(' ') != -1 )
73 hexval.Remove( hexval.find(' '),1);
74
75 for( unsigned i = 0 ; i < hexval.Len() ; i++ )
76 if( !isxdigit( hexval[i] ) || hexval == ' ' ) { //Not hexadecimal!
77 OSXwxMessageBox( _("Value is not hexadecimal!"), _("Format Error!"), wxOK, parent );
78 wxBell();
79 return false;
80 }
81 //there is odd hex value, must be even digit for search!
82 if( hexval.Len() % 2 ) {
83 OSXwxMessageBox( _("Value must be even digit!"), _("Format Error!"), wxOK, parent );
84 wxBell();
85 return false;
86 }
87 return true;
88 }
89
90 //Prepares and updates combo boxes with 10 elements, sycnhronizing with wxConfig..
ComboBoxFill(wxString KeyName,wxComboBox * CurrentBox,bool AddString)91 void ComboBoxFill( wxString KeyName, wxComboBox* CurrentBox, bool AddString){
92 wxString TempString;
93 wxArrayString SearchStrings;
94 //Prepare Array;
95 ///Note that, lower indices will shown at bottom, not at top!
96 for( int i = 0 ; i < 10 ; i ++)
97 if (myConfigBase::Get()->Read(KeyName+wxEmptyString<<i , &TempString)){
98 SearchStrings.Add( TempString );
99 #ifdef _DEBUG_
100 std::cout << "ComboBoxFill Read (" << i << ") : " << TempString.ToAscii() << std::endl;
101 #endif
102 }
103
104 wxString AddNewString = CurrentBox->GetValue();
105 //Adds New String
106 if( AddString && (AddNewString != wxEmptyString) ){
107 if( SearchStrings.Index( AddNewString ) != wxNOT_FOUND )
108 SearchStrings.Remove( AddNewString );
109 else if( SearchStrings.Count() >= 10 )
110 SearchStrings.RemoveAt(0);
111 SearchStrings.Add( AddNewString );
112
113 for( unsigned i = 0 ; i < 10 && i < SearchStrings.Count(); i ++){
114 #ifdef _DEBUG_
115 std::cout << "ComboBoxFill Write (" << i << ") : " << SearchStrings.Item(i).ToAscii() << std::endl;
116 #endif
117 myConfigBase::Get()->Write(KeyName+wxEmptyString<<i, SearchStrings.Item(i));
118 }
119 }
120 //Set ComboBox
121 unsigned i;
122 for( i = 0 ; i < SearchStrings.Count() ; i ++ )
123 CurrentBox->SetString( i, SearchStrings.Item(SearchStrings.Count()-i-1) );
124 for( ; i < 10 ; i ++ )
125 CurrentBox->SetString( i, wxEmptyString);
126 CurrentBox->SetSelection(0);
127 }
128
GotoDialog(wxWindow * _parent,uint64_t & _offset,uint64_t _cursor_offset,uint64_t _filesize,unsigned _BlockSize)129 GotoDialog::GotoDialog( wxWindow* _parent, uint64_t& _offset, uint64_t _cursor_offset, uint64_t _filesize, unsigned _BlockSize ):GotoDialogGui(_parent, wxID_ANY){
130 offset = &_offset;
131 cursor_offset = _cursor_offset;
132 is_olddec = true;
133 filesize = _filesize;
134 BlockSize = _BlockSize;
135 parent= static_cast< HexEditor* >(_parent);
136 SetAutoLayout(true);
137
138 int options=0;
139 myConfigBase::Get()->Read( _T("GoToOptions"), &options );
140
141 options & OPT_DEC_INPUT ? m_dec->SetValue(true) : m_hex->SetValue(true);
142 /* wxArrayString hex_letters;//=wxT("abcdefABCDEFxX");
143 wxArrayString dec_letters;//=wxT("1234567890");
144 wxString decStr=wxT("1234567890");
145 for(int i=0;i<decStr.Len();i++)
146 dec_letters.Add( decStr[i]);
147
148 hex_letters=dec_letters;
149 wxString hexStr=wxT("abcdefABCDEFxX");
150 for(int i=0;i<hexStr.Len();i++)
151 hex_letters.Add( hexStr[i] );
152 wxString *x=new wxString();
153 *x=wxT("0");
154
155 m_comboBoxOffset->SetValidator( wxTextValidator( wxFILTER_INCLUDE_CHAR_LIST, x) );
156 static_cast<wxTextValidator*>(m_comboBoxOffset->GetValidator())->SetIncludes ( options & OPT_DEC_INPUT ? dec_letters : hex_letters );
157 */
158
159 m_branch->SetSelection( options & OPT_BRANCH_NORMAL ? 0 :
160 options & OPT_BRANCH_END ? 2 : 1);
161
162 m_choiceMode->Clear();
163 m_choiceMode->SetColumns(2);
164 m_choiceMode->Append(_("Offset") );
165 wxYield();
166 m_choiceMode->SetSelection(0);
167 if( BlockSize <= 1 )
168 BlockSize=1;
169 else{
170 m_choiceMode->Append(_("Sector") );
171 if(!(options & OPT_OFFSET_MODE)){
172 m_button_next->Show();
173 m_button_prev->Show();
174 Fit();
175 wxYield();
176 m_choiceMode->SetSelection( 1 );
177 }
178 }
179 ComboBoxFill( _T("GotoOffset"), m_comboBoxOffset, false);
180 m_comboBoxOffset->Select(0);
181 m_comboBoxOffset->SetFocus();
182 }
183
EventHandler(wxCommandEvent & event)184 void GotoDialog::EventHandler( wxCommandEvent& event ){
185 // if( event.GetId() == m_dec->GetId()
186 // || event.GetId() == m_hex->GetId()
187 // )
188 // OnConvert( event );
189
190 if( event.GetId()==m_choiceMode->GetId()){
191 m_button_next->Show(event.GetSelection());
192 m_button_prev->Show(event.GetSelection());
193 // m_staticline->Show(event.GetSelection());
194 // m_staticTextSector->Show(event.GetSelection());
195 Fit();
196 wxYield();
197 SetSize(DoGetBestSize());
198 //Layout();
199 }
200
201 int options=0;
202 options |= m_choiceMode->GetSelection() == 0 ? OPT_OFFSET_MODE : 0;
203 options |= m_dec->GetValue() ? OPT_DEC_INPUT : 0;
204 options |= m_branch->GetSelection() == 0 ? OPT_BRANCH_NORMAL :
205 m_branch->GetSelection() == 2 ? OPT_BRANCH_END : 0;
206
207 myConfigBase::Get()->Write( _T("GoToOptions"), options );
208
209 m_comboBoxOffset->SetFocusFromKbd();
210 }
211
Filter(wxString text)212 wxString GotoDialog::Filter( wxString text ){
213 for( unsigned i = 0 ; i < text.Length() ; i++ ){
214 if( !(m_dec->GetValue() ? isdigit( text.GetChar( i ) ) : isxdigit( text.GetChar( i ) )))
215 text.Remove( i--, 1);
216 }
217 return text;
218 }
219
OnInput(wxCommandEvent & event)220 void GotoDialog::OnInput( wxCommandEvent& event ){
221 wxString OldValue = m_comboBoxOffset->GetValue();
222 wxString NewValue = Filter( OldValue );
223 if( OldValue != NewValue ){
224 m_comboBoxOffset->SetValue( NewValue );
225 m_comboBoxOffset->SetInsertionPointEnd();
226 wxBell();
227 }
228 event.Skip(true);
229 }
230
OnChar(wxKeyEvent & event)231 void GotoDialog::OnChar( wxKeyEvent& event ){
232 if( ( event.GetKeyCode() == WXK_BACK )
233 || ( event.GetKeyCode() == WXK_RETURN )
234 || ( event.GetKeyCode() == WXK_LEFT )
235 || ( event.GetKeyCode() == WXK_RIGHT )
236 || ( event.GetKeyCode() == WXK_DELETE )
237 || ( event.GetKeyCode() == WXK_TAB )
238 || ( event.GetKeyCode() == WXK_END )
239 || ( event.GetKeyCode() == WXK_HOME )
240 || ( event.GetKeyCode() == WXK_CAPITAL )
241 || ( event.GetKeyCode() == WXK_RETURN )
242 || ( event.ControlDown() && (
243 event.GetKeyCode()==1 // CTRL+A
244 || event.GetKeyCode()==24 // CTRL+X
245 || event.GetKeyCode()==3 // CTRL+C
246 || event.GetKeyCode()==22 // CTRL+V
247 ))
248 || ( m_dec->GetValue() ? isdigit(event.GetKeyCode()) : isxdigit( event.GetKeyCode()) )
249 )
250 event.Skip(true);
251 else{
252 wxBell();
253 event.Skip(false);
254 }
255 #ifdef _DEBUG_
256 std::cout << "CTRL:" << event.ControlDown() << " KeyCode:" << event.GetKeyCode() << " Raw:" << event.GetRawKeyCode() << std::endl ;
257 #endif
258 if( event.GetKeyCode() == WXK_ESCAPE ){
259 if(m_comboBoxOffset->GetValue().IsEmpty())
260 Close();
261 else
262 m_comboBoxOffset->SetValue(wxEmptyString);
263 }
264 }
265
OnPreviousSector(wxCommandEvent & event)266 void GotoDialog::OnPreviousSector( wxCommandEvent& event ){
267 //parent->Goto( parent->CursorOffset() - BlockSize);
268 parent->LoadFromOffset( parent->CursorOffset() - BlockSize );
269 }
OnNextSector(wxCommandEvent & event)270 void GotoDialog::OnNextSector( wxCommandEvent& event ){
271 //parent->Goto( parent->CursorOffset() + BlockSize );
272 parent->LoadFromOffset( parent->CursorOffset() + BlockSize );
273 }
274
OnGo(wxCommandEvent & event)275 void GotoDialog::OnGo( wxCommandEvent& event ){
276 if( m_comboBoxOffset->GetValue()==wxEmptyString ){
277 wxBell();
278 return;
279 }
280 wxULongLong_t wxul = 0;
281 if( !m_comboBoxOffset->GetValue().ToULongLong( &wxul, m_dec->GetValue() ? 10 : 16 ))//Mingw32/64 workaround
282 wxul = strtoull( m_comboBoxOffset->GetValue().ToAscii(), 0, m_dec->GetValue() ? 10 : 16 );
283 *offset = wxul;
284
285 //Store value to Registry or Updates it!
286 ComboBoxFill( _T("GotoOffset"), m_comboBoxOffset, true);
287
288 unsigned SectorSize=1;
289 if( m_choiceMode->GetSelection() == 1)
290 SectorSize=BlockSize;
291
292 if( m_branch->GetSelection() == 1)
293 *offset += cursor_offset*SectorSize;
294 else if( m_branch->GetSelection() == 2){
295 if(filesize < *offset * SectorSize)
296 *offset = 0;
297 else
298 *offset = filesize - *offset * SectorSize;
299 }
300 else
301 *offset *= SectorSize;
302 /*
303 //No -locations due uint64_t
304 if( *offset < 0 )
305 *offset = 0;
306 */
307
308 EndModal( wxID_OK );
309 }
310
311 // TODO (death#1#):Paint 4 Find All
312 // TODO (death#1#):Remember options last state
FindDialog(wxWindow * _parent,FAL * _findfile,wxString title)313 FindDialog::FindDialog( wxWindow* _parent, FAL *_findfile, wxString title ):FindDialogGui( _parent, wxID_ANY, title){
314 parent = static_cast< HexEditor* >(_parent);
315 findfile = _findfile;
316
317 int options=0;
318 myConfigBase::Get()->Read( _T("FindOptions"), &options );
319 m_searchtype->SetSelection( options & SEARCH_TEXT ? 0 : 1);
320 chkWrapAround->SetValue( options & SEARCH_WRAPAROUND );
321 chkSearchBackwards->SetValue( options & SEARCH_BACKWARDS );
322 chkUTF8->SetValue( options & SEARCH_UTF8 );
323 chkMatchCase->SetValue( options & SEARCH_MATCHCASE );
324 chkMatchCase->Enable( options & SEARCH_TEXT );
325
326 //Load previous search results.
327 PrepareComboBox( false );
328 m_comboBoxSearch->Select(0);
329 m_comboBoxSearch->SetFocus();
330
331 #ifdef _DEBUG_FIND_UNIT_TEST_
332 SearchAtBufferUnitTest();
333 #endif
334 }
335
SearchAtBufferUnitTest(void)336 bool FindDialog::SearchAtBufferUnitTest(void){
337 enum { STEP = 100000 };
338 char buff[STEP];
339 for(unsigned i=0;i<STEP;i++) buff[i]=0;
340 wxString src = "keYWord";
341
342 wxMemoryBuffer target;
343 target.AppendData( src.Lower().ToAscii(), src.Len() );
344
345 char ers[10];
346 memset( ers, 0, 10 );
347 for(unsigned i=0; i < STEP-src.Len() ; i++){
348 //bzero(buff, MB);
349 unsigned sz = i + target.GetDataLen() > STEP ? STEP-i : target.GetDataLen();
350 memcpy( buff+i, target, sz );
351 UTF8SpeedHackChrs[0]=toupper(target[0]);
352 UTF8SpeedHackChrs[1]=toupper(target[1]);
353
354 std::cout << "\rSearching key at: " << i ;
355 ///Manully change OPTIONS for testing!
356 //int f = SearchAtBuffer( buff, STEP, src, strlen(src), SEARCH_TEXT|SEARCH_MATCHCASE );
357 //int f = SearchAtBuffer( buff, STEP, tolower(src), strlen(src), SEARCH_TEXT );
358 //int f = SearchAtBuffer( buff, STEP, src, strlen(src), SEARCH_HEX|SEARCH_BACKWARDS|SEARCH_MATCHCASE );
359 int f = SearchAtBuffer( buff, STEP, (char*)target.GetData(), target.GetDataLen(), SEARCH_TEXT|SEARCH_BACKWARDS );
360
361 memcpy( buff+i, ers, sz );
362 if( f == static_cast<int>(i) )
363 std::cout << " OK";
364 else{
365 std::cout << "ERROR \nFor key at : "<< i << "\t result = " << f << "\t sz: " << sz;
366 return false;
367 }
368 std::cout.flush();
369 }
370 std::cout << std::endl;
371 return true;
372 }
373
PrepareComboBox(bool AddString)374 void FindDialog::PrepareComboBox( bool AddString ){
375 int searchType = m_searchtype->GetSelection() == 0 ? SEARCH_TEXT : SEARCH_HEX;
376 if( searchType == SEARCH_TEXT )
377 ComboBoxFill( _T("SearchTextString"), m_comboBoxSearch, AddString);
378 else
379 ComboBoxFill( _T("SearchHexString"), m_comboBoxSearch, AddString);
380 }
381
OnChar(wxKeyEvent & event)382 void FindDialog::OnChar( wxKeyEvent& event ){
383 if( m_searchtype->GetSelection()==1 ){ //Just for Hex Mode
384 if( ( event.GetKeyCode() == WXK_BACK )
385 || ( event.GetKeyCode() == WXK_RETURN )
386 || ( event.GetKeyCode() == WXK_LEFT )
387 || ( event.GetKeyCode() == WXK_RIGHT )
388 || ( event.GetKeyCode() == WXK_DELETE )
389 || ( event.GetKeyCode() == WXK_TAB )
390 || ( event.GetKeyCode() == WXK_END )
391 || ( event.GetKeyCode() == WXK_HOME )
392 || ( event.GetKeyCode() == WXK_CAPITAL )
393 || ( event.GetKeyCode() == WXK_RETURN )
394 || ( event.ControlDown() && (
395 event.GetKeyCode()==1 // CTRL+A
396 || event.GetKeyCode()==24 // CTRL+X
397 || event.GetKeyCode()==3 // CTRL+C
398 || event.GetKeyCode()==22 // CTRL+V
399 ))
400 || ( isxdigit( event.GetKeyCode()) )
401 )
402 event.Skip(true);
403 else{
404 wxBell();
405 event.Skip(false);
406 }
407 }
408 else{
409 event.Skip( true );
410 }
411
412 #ifdef _DEBUG_
413 std::cout << "CTRL:" << event.ControlDown() << " KeyCode:" << event.GetKeyCode() << " Raw:" << event.GetRawKeyCode() << std::endl ;
414 #endif
415 if( event.GetKeyCode() == WXK_ESCAPE ){
416 if( static_cast<wxComboBox*>(event.GetEventObject())->GetValue().IsEmpty() )
417 Close();
418 else
419 static_cast<wxComboBox*>(event.GetEventObject())->SetValue(wxEmptyString);
420 }
421 }
422
EventHandler(wxCommandEvent & event)423 void FindDialog::EventHandler( wxCommandEvent& event ){
424 WX_CLEAR_ARRAY(parent->HighlightArray )
425 parent->HighlightArray.Shrink();
426
427 if( event.GetId() == btnFind->GetId())
428 OnFind();
429 else if(event.GetId() == m_comboBoxSearch->GetId()){
430 if( event.GetEventType() == 10041)//Handles ENTER key
431 OnFind();
432 else
433 chkUTF8->SetValue( !m_comboBoxSearch->GetValue().IsAscii() );
434 }
435 else if( event.GetId() == m_searchtype->GetId()){
436 chkMatchCase->Enable(m_searchtype->GetSelection() == 0);
437
438 PrepareComboBox( false );
439 m_comboBoxSearch->SetValue( wxEmptyString );//For clearing current value to make selection operation proper
440 m_comboBoxSearch->SetSelection(0);
441 m_comboBoxSearch->SetFocus();
442 }
443 else if( event.GetId() == btnFindAll->GetId() )
444 OnFindAll();
445 else if(event.GetId() == btnFindSomeBytes->GetId())
446 FindSomeBytes();
447
448 //Disables chkUTF8 setting by user.
449 else if( event.GetId() == chkUTF8->GetId() ){
450 chkUTF8->SetValue( !chkUTF8->GetValue( ));
451 wxBell();
452 }
453
454 int options=0;
455 options |= m_searchtype->GetSelection() == 0 ? SEARCH_TEXT : SEARCH_HEX;
456 options |= chkWrapAround->GetValue() ? SEARCH_WRAPAROUND : 0;
457 options |= chkSearchBackwards->GetValue() ? SEARCH_BACKWARDS : 0;
458 options |= chkUTF8->GetValue() ? SEARCH_UTF8 : 0;
459 options |= chkMatchCase->GetValue() ? SEARCH_MATCHCASE : 0;
460 myConfigBase::Get()->Write( _T("FindOptions"), options );
461 }
462
FindSomeBytes(void)463 void FindDialog::FindSomeBytes( void ){
464 if( findfile->Length() == 0)
465 return;
466 wxString msg= _("Finding Some Bytes...");
467 wxString emsg=wxT("\n");
468 wxProgressDialog progress_gauge(_("wxHexEditor Searching") , msg+emsg, 1000, this, wxPD_SMOOTH|wxPD_REMAINING_TIME|wxPD_CAN_ABORT|wxPD_AUTO_HIDE );
469 progress_gauge.SetWindowStyleFlag( progress_gauge.GetWindowStyleFlag()|wxSTAY_ON_TOP|wxMINIMIZE_BOX );
470 // TODO (death#1#): Search icon
471 //wxIcon search_ICON (?_xpm);
472 //progress_gauge.SetIcon(search_ICON);
473
474 uint64_t current_offset = parent->CursorOffset();
475 unsigned BlockSz= 10*1024*1024;
476 int search_step = findfile->Length() < BlockSz ? findfile->Length() : BlockSz ;
477 findfile->Seek( current_offset, wxFromStart );
478 char* buffer = new char [search_step];
479 if(buffer == NULL) return;
480 // TODO (death#6#): insert error check message here
481 int readed = 0;
482 char diff_search;
483 findfile->Read( &diff_search, 1);
484 time_t ts,te;
485 time (&ts);
486 te=ts;
487 uint64_t read_speed=0;
488 //Search step 1: From cursor to file end.
489 do{
490 findfile->Seek( current_offset, wxFromStart );
491 readed = findfile->Read( buffer , search_step );
492 read_speed += readed;
493 for( int i=0; i < readed ; i++)
494 if( buffer[i] != diff_search ){
495 parent->Goto( current_offset+i );
496 //Destroy();
497 return;
498 }
499
500 time(&te);
501 if(ts != te ){
502 ts=te;
503 emsg = msg + wxT("\n") + _("Search Speed : ") + wxString::Format( wxT("%.2f "), 1.0*read_speed/MB) + _("MB/s");
504 read_speed=0;
505 }
506 if( ! progress_gauge.Update(current_offset*1000/findfile->Length(), emsg)) // update progress and break on abort
507 break;
508
509 current_offset += readed;
510 }while(readed >= search_step); //indicate also file end.
511 wxBell();
512 }
513
OnFind(bool internal)514 bool FindDialog::OnFind( bool internal ){
515 #ifdef _DEBUG_
516 std::cout << "FindDialog::OnFind() " << std::endl;
517 #endif
518 #ifdef _DEBUG_FIND_UNIT_TEST_
519 return FindBinaryUnitTest();
520 #endif // _DEBUG_FIND_UNIT_TEST_
521
522 uint64_t found = NANINT;
523 uint64_t search_size = 0;
524 //prepare Operator
525 unsigned options = 0;
526 options |= m_searchtype->GetSelection() == 0 ? SEARCH_TEXT : SEARCH_HEX;
527 options |= chkWrapAround->GetValue() ? SEARCH_WRAPAROUND : 0;
528 options |= chkSearchBackwards->GetValue() ? SEARCH_BACKWARDS : 0;
529 if(options & SEARCH_TEXT) {
530 PrepareComboBox( true );
531 options |= chkUTF8->GetValue() ? SEARCH_UTF8 : 0;
532 options |= chkMatchCase->GetValue() ? SEARCH_MATCHCASE : 0;
533 if( m_comboBoxSearch->GetValue().IsAscii() )
534 search_size = m_comboBoxSearch->GetValue().Len();
535 else{
536 search_size=0;
537 while( m_comboBoxSearch->GetValue().ToUTF8()[search_size++]);
538 search_size--;
539 }
540 found = FindText( m_comboBoxSearch->GetValue(), parent->CursorOffset()+(options&SEARCH_BACKWARDS ? 0:1), options ); //+1 for forward operations!
541 }
542 else { //SEARCH_HEX
543 //Hex Validation and Format
544 wxString hexval = m_comboBoxSearch->GetValue();
545 if(!HexVerifyAndPrepare( hexval, _("Search"), this ) )
546 return false;
547 m_comboBoxSearch->SetValue(hexval.Upper());
548
549 PrepareComboBox( true );
550 wxMemoryBuffer search_binary = wxHexCtrl::HexToBin( m_comboBoxSearch->GetValue());
551 search_size = search_binary.GetDataLen();
552 found = FindBinary( search_binary, parent->CursorOffset()+(options&SEARCH_BACKWARDS ? 0:1), options ); //+1 for forward operations!
553 }
554
555 if( found != NANINT ) {
556 parent->Goto( found );
557 parent->Select( found, found+search_size-1 );
558 return true;
559 }
560
561 else if( !internal )
562 OSXwxMessageBox(_("Search value not found"), _("Nothing found!"), wxOK, this );
563 return false;
564 }
565
FindText(wxString target,uint64_t start_from,unsigned options)566 uint64_t FindDialog::FindText( wxString target, uint64_t start_from, unsigned options ){
567 #ifdef _DEBUG_
568 std::cout << "FindText() from: " << start_from << "\t Search Length " << target.Len() << std::endl;
569 #endif
570
571 if(!(options & SEARCH_MATCHCASE)){
572 //!Compare with lowered characters
573 target = target.Lower();
574 }
575
576 wxMemoryBuffer textsrc;
577 if( target.IsAscii() ){
578 textsrc.AppendData( target.ToAscii() , target.Length() );
579 return FindBinary( textsrc, start_from, options );
580 }
581
582 else{//Search as UTF string.
583 wxCharBuffer a = target.ToUTF8().data(); //Convert to UTF8 Binary
584 int i=0;
585 char *b=a.data(); //Silences errors
586 while(b[i++] != 0); //Find stream size
587 textsrc.AppendData( a , i-1 );//-1 for discard null termination char
588
589 ///Since we cannot convert whole buffer to UTF8 for issuing upper() function on it,
590 ///we just need "search string" upper & lower versions.
591 // First 2 byte will be searched and if matches, full comparison will made.
592 if(!(options & SEARCH_MATCHCASE)){//If non-matchcase operation
593 wxCharBuffer a = target.Upper().ToUTF8().data(); //Calculate Uppercase variant of first character
594 UTF8SpeedHackChrs[0]=a.data()[0]; //This will be huge speed up but needed to handled differently on
595 UTF8SpeedHackChrs[1]=a.data()[1]; //SearchAtBuffer stack!
596 }
597 return FindBinary( textsrc, start_from, options|SEARCH_UTF8 );
598 }
599 }
600
SkipRAM(uint64_t & current_offset,unsigned search_size,unsigned & search_step,bool backward)601 bool FindDialog::SkipRAM( uint64_t& current_offset, unsigned search_size, unsigned& search_step, bool backward ){
602 uint64_t map_start;
603 uint64_t map_end;
604 #ifdef _DEBUG_
605 printf( "SkipRAM() Processing from 0x%lX, %s\n", current_offset, (backward ? "Backward": ""));
606 #endif
607 if( !parent->ProcessRAM_FindMap( current_offset, map_start, map_end, backward ) ){
608 current_offset = parent->ProcessRAM_FindNextMap(current_offset, backward);
609 #ifdef _DEBUG_
610 printf( "Skipping to 0x%lX\n", current_offset);
611 #endif
612 }
613
614 if(backward){
615 if( current_offset - map_start < search_step )
616 search_step = current_offset - map_start;
617 }
618 else{
619 if( map_end - current_offset > search_step )
620 search_step = map_end - current_offset;
621 }
622
623 if( search_step < search_size){
624 current_offset = parent->ProcessRAM_FindNextMap(current_offset, backward);
625 #ifdef _DEBUG_
626 printf( "Skipping to 0x%lX due step size.\n", current_offset);
627 #endif
628 }
629 #ifdef _DEBUG_
630 std::cout << "Step size:" << search_step << std::endl;
631 #endif
632
633 if( map_start <= current_offset && map_end >= current_offset ){
634 std::cout << "ProcessRAM_FindMap pass\n" << std::endl;
635 }
636 if( current_offset == 0 ) //means memory map ends
637 return true;
638 return false;
639 }
640
641 #define _MULTI_SEARCH_
642 // TODO (death#1#):
643 #ifdef _DEBUG_FIND_UNIT_TEST_
FindBinaryUnitTest(void)644 bool FindDialog::FindBinaryUnitTest( void ){
645 #ifdef _DEBUG_
646 std::cout << "FindDialog::FindBinaryUnitTest() " << std::endl;
647 #endif
648 wxFileName a(wxT("tempfile-deleteable"));
649 wxFile b(a.GetFullPath(),wxFile::write );
650
651 int fs=1024*1024*1;
652 char *buff= new char[fs];
653 memset( buff, 0, fs );
654 b.Write( buff, fs );
655 b.Close();
656 b.Flush();
657
658 FAL tmpfile(a, FAL::ReadWrite ) ;
659 findfile=&tmpfile;
660
661 //somehow, FAL->Length return 0 for some time
662 while(findfile->Length() <= 0);
663
664 wxString teststr="testSTr";
665 wxMemoryBuffer target;
666 //For No_MATCH_CASE!
667 //teststr=teststr.Lower()
668 target.AppendData( teststr.ToAscii(), teststr.Len() );
669
670 for(int i=fs-strlen(teststr); i > 0 ; i-- ) //for Forward Search, put search string to last possible location first
671 //for(int i=0; i < fs - 7; i++ ) //for Backward Search, put search string to begining of the file first
672 {
673 // tmpfile.Seek( i );
674 // tmpfile.Write( teststr, 7 );
675 tmpfile.Add( i, teststr, strlen(teststr) );
676 //not need to commit to real file
677 //tmpfile.Apply();
678
679 std::cout << "\rSearching key at: " << i ;
680 ///Test Cases
681 int f = FindBinary( target, 0, SEARCH_TEXT | SEARCH_MATCHCASE );
682 //int f = FindBinary( target, 0, SEARCH_TEXT );
683 //int f = FindBinary( target, findfile->Length()/2, SEARCH_TEXT | SEARCH_MATCHCASE | SEARCH_WRAPAROUND );
684
685 //int f = FindBinary( target, tmpfile.Length()-1, SEARCH_TEXT | SEARCH_MATCHCASE | SEARCH_BACKWARDS);
686 //int f = FindBinary( target, findfile->Length()/2, SEARCH_TEXT | SEARCH_MATCHCASE | SEARCH_BACKWARDS | SEARCH_WRAPAROUND ); //SSE2 OK
687
688 tmpfile.Undo();//remove last mod
689
690 if( f == i )
691 std::cout << " OK";
692 else{
693 std::cout << "ERROR \nFor key at : "<< i << "\t result = " << f;
694 return false;
695 }
696 std::cout.flush();
697 }
698 std::cout << std::endl;
699 return false;
700 }
701 #endif // _DEBUG_FIND_UNIT_TEST_
702
FindBinary(wxMemoryBuffer target,uint64_t from,unsigned options)703 uint64_t FindDialog::FindBinary( wxMemoryBuffer target, uint64_t from, unsigned options ){
704 #ifdef _DEBUG_
705 std::cout << "FindDialog::FindBinary() From:" << from << std::endl;
706 #endif
707 if( target.GetDataLen() == 0 ){
708 OSXwxMessageBox( wxT("FindBinary() function called with Empty Target!\n"), _("Error"), wxOK, this);
709 return NANINT;
710 }
711
712 //Disabling search on empty files and if fileLength smaller than file size.
713 if( findfile->Length() == 0 || findfile->Length() < static_cast<int>( target.GetDataLen() ))
714 return NANINT;
715 #ifndef _DEBUG_FIND_UNIT_TEST_
716 wxString msg= _("Finding matches...");
717 wxString emsg=wxT("\n");
718 wxProgressDialog progress_gauge(_("wxHexEditor Searching") , msg+emsg, 1000, this, wxPD_SMOOTH|wxPD_REMAINING_TIME|wxPD_CAN_ABORT|wxPD_AUTO_HIDE );
719 progress_gauge.SetWindowStyleFlag( progress_gauge.GetWindowStyleFlag()|wxSTAY_ON_TOP|wxMINIMIZE_BOX );
720 #endif //_DEBUG_FIND_UNIT_TEST_
721 // TODO (death#1#): Search icon
722 //wxIcon search_ICON (?_xpm);
723 //progress_gauge.SetIcon(search_ICON);
724
725 // TODO (death#6#): insert error check message here
726
727 int found = -1;
728 uint64_t totalread=0;
729 uint64_t current_offset = from;
730
731 //SEARCH_FINDALL forces Forward searching
732 if(( options & SEARCH_FINDALL ) || !(options & SEARCH_BACKWARDS) ){
733 if( options & SEARCH_FINDALL )
734 current_offset=0;
735 #ifdef _DEBUG_FIND_UNIT_TEST_
736 wxString msg;
737 found = FindBinaryForward(target, current_offset, findfile->Length(), options, NULL, msg, totalread);
738 #else
739 found = FindBinaryForward(target, current_offset, findfile->Length(), options, &progress_gauge, msg, totalread );
740 #endif //_DEBUG_FIND_UNIT_TEST_
741 if(found >= 0)
742 return found;
743
744 //Second round from file end to current offset
745 if(( options & SEARCH_WRAPAROUND ) && !( options & SEARCH_FINDALL ))
746 #ifdef _DEBUG_FIND_UNIT_TEST_
747 return FindBinaryForward(target, 0, current_offset , options, NULL, msg, totalread );
748 #else
749 return FindBinaryForward(target, 0, current_offset , options, &progress_gauge, msg, totalread );
750 #endif
751 }
752
753 // TODO (death#1#): MemorySearch Backward.
754 //BACKWARD SEARCH!
755 else{
756 //First search from current offset to 0
757 #ifdef _DEBUG_FIND_UNIT_TEST_
758 wxString msg;
759 found = FindBinaryBackward(target, current_offset, 0, options, NULL, msg, totalread);
760 #else
761 found = FindBinaryBackward(target, current_offset, 0, options, &progress_gauge, msg, totalread );
762 #endif //_DEBUG_FIND_UNIT_TEST_
763 if(found >= 0)
764 return found;
765 //Second round from file end to current offset
766 if( options & SEARCH_WRAPAROUND )
767 #ifdef _DEBUG_FIND_UNIT_TEST_
768 return FindBinaryBackward(target, findfile->Length(), current_offset , options, NULL, msg, totalread );
769 #else
770 return FindBinaryBackward(target, findfile->Length(), current_offset , options, &progress_gauge, msg, totalread );
771 #endif
772 }
773 return NANINT;
774 }
775
FindBinaryForward(wxMemoryBuffer target,uint64_t from,uint64_t to_offset,unsigned options,wxProgressDialog * progress_gauge,wxString & gauge_msg,uint64_t & totalread)776 uint64_t FindDialog::FindBinaryForward(wxMemoryBuffer target, uint64_t from , uint64_t to_offset, unsigned options,
777 wxProgressDialog* progress_gauge, wxString& gauge_msg, uint64_t& totalread){
778 if(from>to_offset){
779 std::cout << "FindDialog::FindBinaryForward() called with from > to_offset" << std::endl;
780 return -1;
781 }
782
783 bool first_run=true;
784 wxString emsg = gauge_msg + wxT("\n") ;
785 uint64_t current_offset = from;
786
787 if( options & SEARCH_FINDALL )
788 current_offset = 0;
789
790 unsigned BlockSz= 1024*1024*1;
791 unsigned search_step = findfile->Length() < BlockSz ? findfile->Length() : BlockSz ;
792
793 char* buffer = new char [search_step];
794 if(buffer == NULL)
795 return NANINT;
796
797 char* buffer_prefetch = new char [search_step];
798 if(buffer_prefetch==NULL){
799 delete [] buffer;
800 buffer == NULL;
801 return NANINT;
802 }
803 time_t ts,te;
804 time (&ts);
805 te=ts;
806 int found = -1, readed = -1,readed_prefetch = -1;
807 unsigned read_speed=0,percentage=0;
808 uint64_t read_speed_offset=0,processfootprint=0;
809
810 if( findfile->IsProcess() )
811 processfootprint = parent->ProcessRAM_GetFootPrint();
812
813 findfile->Seek( current_offset, wxFromStart );
814
815 std::vector< int > partial_results;
816 std::vector< uint64_t > results;
817
818 do{
819 //Skipping unmapped regions if ProcessRAM operation
820 if( findfile->IsProcess() ){
821 search_step=BlockSz;
822 //if( SkipRAM( current_offset, target.GetDataLen(), search_step ) ) //SkipRAM adjust current_offset and search_step
823 // break;
824 uint64_t map_start,map_end;
825 if( !parent->ProcessRAM_FindMap( current_offset, map_start, map_end ) ){
826 #ifdef _DEBUG_
827 printf( "Skipping from: 0x%lX to", current_offset) ;
828 #endif
829 current_offset = parent->ProcessRAM_FindNextMap(current_offset);
830 #ifdef _DEBUG_
831 printf( "0x%lX\n", current_offset) ;
832 #endif
833 if( current_offset == 0 ) break;
834 }
835 /*
836 if( map_end - current_offset < search_step )
837 search_step = map_end - current_offset;
838
839 if( search_step < search_size){
840 #ifdef _DEBUG_
841 std::cout << "Skipping due StepSize: " << current_offset << " to " ;
842 #endif
843 current_offset = parent->ProcessRAM_FindNextMap(current_offset);
844 #ifdef _DEBUG_
845 std::cout << current_offset << std::ios::dec << std::endl;
846 #endif
847 }
848 */
849 }
850
851 if(readed_prefetch>0){//PreLoad file, +%50 speed on SSD buffers.
852 readed=readed_prefetch;
853 std::swap(buffer, buffer_prefetch);
854 }
855 else{
856 findfile->Seek( current_offset, wxFromStart );
857 readed = findfile->Read( buffer , search_step );
858 }
859 //read_speed += readed;
860 #ifdef _DEBUG_
861 std::cout << "Readed: " << readed << std::endl;
862 printf( "FindBinaryForward() 0x%lX - 0x%lX\n" , current_offset , current_offset+search_step);
863 #endif
864
865 // NON-MULTI SEARCH
866 // found = SearchAtBuffer( buffer, readed, static_cast<char*>(target.GetData()),target.GetDataLen(), options );//Makes raw search here
867 // if(found >= 0){//We found something
868 // if( options & SEARCH_FINDALL ){
869 // TagElement *mytag=new TagElement(current_offset+found, current_offset+found+target.GetDataLen()-1,wxEmptyString,*wxBLACK, wxColour(255,255,0,0) );
870 // parent->HighlightArray.Add(mytag);
871 // current_offset += found+target.GetDataLen(); //Unprocessed bytes remaining at buffer!!!
872 // readed=search_step; //to stay in loop
873 // }
874 // else{
875 // delete [] buffer;
876 // delete [] buffer_prefetch;
877 // return current_offset+found;
878 // }
879 // }
880 // else{
881 // int z = readed - target.GetDataLen() -1;
882 // current_offset += (z <= 0 ? 1 : z); //for unprocessed bytes
883 // }
884
885 partial_results.clear();
886 #define _READ_PREFETCH_
887 #ifdef _READ_PREFETCH_
888 #pragma omp parallel sections
889 {
890 //this preloads next data to swap buffer.
891 #pragma omp section
892 {
893 //precalculate next read location
894 findfile->Seek( current_offset+readed-target.GetDataLen()+1, wxFromStart );
895 readed_prefetch=findfile->Read( buffer_prefetch , search_step );
896 }
897
898 #pragma omp section
899 {
900 //found = MultiThreadMultiSearchAtBuffer( buffer, readed, static_cast<char*>(target.GetData()),target.GetDataLen(), options, &partial_results );//Makes raw search here
901 found = SearchAtBuffer( buffer, readed, static_cast<char*>(target.GetData()),target.GetDataLen(), options, &partial_results );//Makes raw search here
902 }
903 }
904 #else //code without prefetching
905 found = /*MultiThread*/SearchAtBuffer( buffer, readed, static_cast<char*>(target.GetData()),target.GetDataLen(), options, &partial_results );//Makes raw search here
906 #endif //_READ_PREFETCH_
907 if( partial_results.size() > 0 ){// Houston, We found something!
908 if( options & SEARCH_FINDALL ){
909 for(unsigned i=0 ; i < partial_results.size() ; i++ )
910 results.push_back( partial_results[i] + current_offset );
911 //current_offset += partial_results.back()+target.GetDataLen();
912 current_offset += readed-target.GetDataLen()+1;
913 }
914 //If only searching one result, throw first one.
915 else{
916 delete [] buffer;
917 delete [] buffer_prefetch;
918 return current_offset+partial_results.front();
919 }
920 }
921 else{
922 int offset_increase = readed - target.GetDataLen() +1;
923 current_offset += (offset_increase <= 0 ? 1 : offset_increase); //for unprocessed bytes
924 #ifdef _DEBUG_
925 std::cout << "Offset Increased: " << offset_increase << std::endl;
926 #endif
927 }
928
929 #ifndef _DEBUG_FIND_UNIT_TEST_
930 ///Progress dialog and while loop from now...
931 time(&te);
932 if(ts != te ){
933 ts=te;
934 emsg = gauge_msg + wxT("\n") + _("Search Speed : ") + wxString::Format( wxT("%.2f "), 1.0*(current_offset-read_speed_offset)/MB) + _("MB/s");
935 read_speed_offset = current_offset;
936 }
937
938 totalread += readed; // We need this on step 2
939 if( findfile->IsProcess() ){
940 #ifdef _DEBUG_
941 printf( "ProcessRAM Virtual Offset: 0x%lX, \t Offset:0x%lX, \tFootPrint: 0x%lX\n", parent->ProcessRAM_GetVirtualOffset( current_offset ), current_offset, processfootprint);
942 #endif
943 percentage = parent->ProcessRAM_GetVirtualOffset( current_offset )*1000/processfootprint;
944 }
945
946 else
947 percentage = ( options & SEARCH_WRAPAROUND && !( options & SEARCH_FINDALL ))
948 ? (current_offset-from)*1000/(findfile->Length())
949 : (current_offset-from)*1000/(findfile->Length()-from+1);//+1 to avoid error
950
951 if( ! progress_gauge->Update( percentage, emsg)) // update progress and break on abort
952 break;
953 #endif
954 }while( (to_offset > current_offset + target.GetDataLen()) && (readed == static_cast<int>(search_step))); //indicate also file end.
955
956 //WX_CLEAR_ARRAY( parent->HighlightArray )
957 //parent->HighlightArray.Shrink();
958
959 delete [] buffer;
960 delete [] buffer_prefetch;
961 if (! options & SEARCH_FINDALL)
962
963 return found;
964
965 //Create tags from results and put them into HighlightArray
966 for(unsigned i=0 ; i < results.size() && i < 100000 ; i++ ){
967 TagElement *mytag=new TagElement(results[i] , results[i]+target.GetDataLen()-1,wxEmptyString,*wxBLACK, wxColour(255,255,0,0) );
968 parent->HighlightArray.Add(mytag);
969 }
970
971 if(results.size() > 0)
972 found = results[0];
973
974 partial_results.clear();
975 results.clear();
976
977 return found;
978 }
979
FindBinaryBackward(wxMemoryBuffer target,uint64_t from,uint64_t to_offset,unsigned options,wxProgressDialog * progress_gauge,wxString & gauge_msg,uint64_t & totalread)980 uint64_t FindDialog::FindBinaryBackward(wxMemoryBuffer target, uint64_t from , uint64_t to_offset, unsigned options,
981 wxProgressDialog* progress_gauge, wxString& gauge_msg, uint64_t& totalread){
982 //BACKWARD SEARCH!
983 bool first_run=true;
984 wxString emsg = gauge_msg + wxT("\n") ;
985 uint64_t current_offset = from ; //higher offset
986 uint64_t end_offset = to_offset; //lower offset due backward search
987 if( current_offset < end_offset )
988 wxSwap( current_offset, end_offset);
989 uint64_t backward_offset = current_offset;
990
991 bool first_search=true;
992 unsigned BlockSz= 1024*1024*1;
993 unsigned search_step = findfile->Length() < BlockSz ? findfile->Length() : BlockSz ;
994
995 char* buffer = new char [search_step];
996 if(buffer == NULL) return NANINT;
997 // TODO (death#6#): insert error check message here
998 int found = -1, readed = -1;
999
1000 char* buffer_prefetch = new char [search_step];
1001 if(buffer_prefetch == NULL){
1002 delete [] buffer;
1003 return NANINT;
1004 }
1005 int readed_prefetch = -1;
1006
1007 time_t ts,te;
1008 time (&ts);
1009 te=ts;
1010 unsigned read_speed=0,percentage=0;
1011 uint64_t read_speed_offset=0,processfootprint=0;
1012 if( findfile->IsProcess() )
1013 processfootprint = parent->ProcessRAM_GetFootPrint();
1014 do{
1015 if( findfile->IsProcess() ){
1016 search_step=BlockSz;
1017 if( SkipRAM( current_offset, target.GetDataLen(), search_step, true ) ) //SkipRAM adjust current_offset and search_step
1018 break;
1019 }
1020 backward_offset = current_offset < search_step ? 0 : current_offset-search_step;
1021 search_step = backward_offset + search_step > current_offset ? current_offset-backward_offset : search_step;
1022
1023 #ifdef _DEBUG_
1024 std::cout << std::dec << "FindBinary() BACKWARD " << backward_offset << "-" << current_offset << " \t " << "SearchStep:" << search_step<< std::endl;
1025 #endif
1026 if(readed_prefetch>0){//PreLoad file, +%50 speed on SSD buffers.
1027 readed=readed_prefetch;
1028 std::swap(buffer, buffer_prefetch);
1029 }
1030 else{
1031 findfile->Seek( backward_offset, wxFromStart );
1032 readed=findfile->Read( buffer , search_step );
1033 }
1034
1035 read_speed += readed;
1036
1037 #ifdef _READ_PREFETCH_xxx
1038 #pragma omp parallel sections
1039 {
1040 //this preloads next data to swap buffer.
1041 #pragma omp section
1042 {
1043 //precalculate next read location from original functions:
1044 //current_offset = backward_offset + target.GetDataLen();
1045 //backward_offset = current_offset < search_step ? 0 : current_offset-search_step;
1046 //search_step = backward_offset + search_step > current_offset ? current_offset-backward_offset : search_step;
1047
1048 uint64_t current_offset_prefech = backward_offset + target.GetDataLen();
1049 uint64_t backward_offset_prefetch = current_offset_prefech < search_step ? 0 : current_offset_prefech-search_step;
1050 unsigned search_step_prefetch = backward_offset_prefetch + search_step > current_offset_prefech ? current_offset_prefech-backward_offset_prefetch : search_step;
1051 if (backward_offset_prefetch > end_offset){
1052 findfile->Seek( backward_offset_prefetch, wxFromStart );
1053 readed_prefetch=findfile->Read( buffer_prefetch , search_step_prefetch );
1054 }
1055 else
1056 readed_prefetch=0;
1057 }
1058
1059 #pragma omp section
1060 {
1061 //we do not need MultiSearch here. Because it's not a SEARCH_FINDALL
1062 found = SearchAtBuffer( buffer, readed, static_cast<char*>(target.GetData()),target.GetDataLen(), options );
1063 }
1064 }
1065 #else //code without prefetching
1066
1067 //Since it's not possible SEARCH_FINDALL and SEARCH_BACKWARD flags same time, we don't need MultiSearchAtBufer function.
1068 found = SearchAtBuffer( buffer, readed, static_cast<char*>(target.GetData()),target.GetDataLen(), options );
1069 #endif //_READ_PREFETCH_
1070
1071 if(found >= 0){
1072 delete [] buffer;
1073 delete [] buffer_prefetch;
1074 return backward_offset+found;
1075 }
1076 else
1077 current_offset = backward_offset + target.GetDataLen(); //Unprocessed bytes
1078
1079 #ifndef _DEBUG_FIND_UNIT_TEST_ // Unit test will disable gauge.
1080 //Gauge update
1081 time(&te);
1082 if(ts != te || first_run ){
1083 first_run=false;
1084 ts=te;
1085 emsg = gauge_msg + wxT("\n") + _("Search Speed : ") + wxString::Format( wxT("%.2f "), (1.0*read_speed/MB )) + _("MB/s");
1086 read_speed=0;
1087 }
1088 totalread += readed;
1089
1090 if( findfile->IsProcess() ){
1091 percentage = options & SEARCH_WRAPAROUND
1092 ? (processfootprint-totalread)*1000 / processfootprint
1093 : parent->ProcessRAM_GetVirtualOffset(current_offset)*1000/(parent->ProcessRAM_GetVirtualOffset(from)+1); //+1 to avoid error
1094 }
1095 else
1096 percentage = (findfile->Length()-totalread)*1000/findfile->Length();
1097 if( progress_gauge != NULL)
1098 if(first_run){
1099 if( ! progress_gauge->Update( percentage) ); // update progress and break on abort
1100 break;
1101 }
1102 else if( ! progress_gauge->Update( percentage, emsg)) // update progress and break on abort
1103 break;
1104 #endif //_DEBUG_FIND_UNIT_TEST_
1105 }while(backward_offset > end_offset);
1106
1107 delete [] buffer;
1108 delete [] buffer_prefetch;
1109 return NANINT;
1110 }
1111
OnFindAll(bool internal)1112 void FindDialog::OnFindAll( bool internal ){
1113 for( unsigned i=0; i < parent->HighlightArray.Count(); i++ )
1114 delete parent->HighlightArray.Item(i);
1115 parent->HighlightArray.Clear();
1116
1117 unsigned options = SEARCH_FINDALL; //fill continue search until file and with this option.
1118 options |= m_searchtype->GetSelection() == 0 ? SEARCH_TEXT : SEARCH_HEX;
1119 options |= chkWrapAround->GetValue() ? SEARCH_WRAPAROUND : 0;
1120 options |= chkSearchBackwards->GetValue() ? SEARCH_BACKWARDS : 0;
1121
1122 //Text Search
1123 if(options & SEARCH_TEXT) {
1124 PrepareComboBox( true );
1125 options |= chkUTF8->GetValue() ? SEARCH_UTF8 : 0;
1126 options |= chkMatchCase->GetValue() ? SEARCH_MATCHCASE : 0;
1127
1128 ///FindAll discards SEARCH_BACKWARDS and SEARCH_WRAPAROUND options.
1129 FindText( m_comboBoxSearch->GetValue(), 0, options );
1130
1131 /*
1132 if( options & SEARCH_WRAPAROUND )
1133 FindText( m_comboBoxSearch->GetValue(), 0, options );
1134 else if( options & SEARCH_BACKWARDS )
1135 FindText( m_comboBoxSearch->GetValue(), parent->CursorOffset() , options );
1136 else
1137 FindText( m_comboBoxSearch->GetValue(), parent->CursorOffset()+1 , options );
1138 */
1139 }
1140
1141 //Hexadecimal / Binary Search
1142 else {
1143 wxString hexval = m_comboBoxSearch->GetValue();
1144 //parent->Goto(0);
1145 if(!HexVerifyAndPrepare( hexval, _("Search"), this ) )
1146 return;
1147 m_comboBoxSearch->SetValue(hexval.Upper());
1148 PrepareComboBox( true );
1149 FindBinary( wxHexCtrl::HexToBin( m_comboBoxSearch->GetValue()), 0 ,options );
1150 }
1151
1152 if(parent->HighlightArray.GetCount()==0){
1153 OSXwxMessageBox(_("Search value not found"), _("Nothing found!"), wxOK, this );
1154 }
1155 else {
1156 parent->Goto( parent->HighlightArray.Item(0)->start );
1157
1158 if( !internal ){
1159 this->Hide();
1160 OSXwxMessageBox(wxString::Format(_("Found %d matches."), static_cast<int>( parent->HighlightArray.GetCount()) ), _("Find All Done!"), wxOK, parent );
1161 EndModal(0);
1162 }
1163 }
1164
1165 wxUpdateUIEvent eventx( SEARCH_CHANGE_EVENT );
1166 wxPostEvent(parent, eventx );
1167 }
1168
1169 //inline int FindDialog::MultiThreadMultiSearchAtBuffer( char *bfr, int bfr_size, char* search, int search_size, unsigned options, std::vector<int> *ret_ptr ){
1170 //#define _DUAL_THREAD_SEARCH_
1171 //
1172 //#ifdef _DUAL_THREAD_SEARCH_
1173 // ///DualThread
1174 // std::vector<int> v1,v2;
1175 // #pragma omp parallel sections // starts a new team
1176 // {
1177 // #pragma omp section
1178 // {MultiSearchAtBuffer( bfr, bfr_size/2, search, search_size, options, &v1 );}
1179 // #pragma omp section
1180 // {MultiSearchAtBuffer( bfr+ bfr_size-bfr_size/2-search_size+1,bfr_size/2+search_size-1, search, search_size, options , &v2);}
1181 // }
1182 // int cnt;
1183 // cnt=v1.size();
1184 // for( int i=0; i<cnt; i++)
1185 // ret_ptr->push_back(v1[i]);
1186 // cnt=v2.size();
1187 // for( int i=0; i<cnt; i++)
1188 // ret_ptr->push_back(v2[i]+bfr_size-bfr_size/2-search_size+1);
1189 //
1190 // return ret_ptr->size();
1191 //
1192 //#else
1193 /////QuadThread
1194 // int ztep=bfr_size/4;
1195 // std::vector<int> v1,v2,v3,v4;;
1196 ///*
1197 // #ifndef OMP_H
1198 // return SearchAtBufferSingleThread( bfr, bfr_size, search, search_size, options );
1199 // #else
1200 //*/
1201 // if( ztep < search_size*128 ) //For safety & avoid overhead
1202 // return MultiSearchAtBuffer( bfr, bfr_size, search, search_size, options, ret_ptr );
1203 // #pragma omp parallel sections // starts a new team
1204 // {
1205 // { MultiSearchAtBuffer( bfr, bfr_size/2, search, search_size, options, &v1); }
1206 // #pragma omp section
1207 // { MultiSearchAtBuffer( bfr+ztep-search_size+1, ztep+search_size-1, search, search_size, options, &v2); }
1208 // #pragma omp section
1209 // { MultiSearchAtBuffer( bfr+(ztep*2)-search_size+1, ztep+search_size-1, search, search_size, options, &v3); }
1210 // #pragma omp section
1211 // { MultiSearchAtBuffer( bfr+(ztep*3)-search_size+1, bfr_size-ztep*3+search_size-1, search, search_size, options, &v4); }
1212 // }
1213 //
1214 // int cnt;
1215 // cnt=v1.size();
1216 // for( int i=0; i<cnt; i++)
1217 // ret_ptr->push_back(v1[i]);
1218 // cnt=v2.size();
1219 // for( int i=0; i<cnt; i++)
1220 // ret_ptr->push_back(v2[i]+ztep-search_size+1);
1221 // cnt=v3.size();
1222 // for( int i=0; i<cnt; i++)
1223 // ret_ptr->push_back(v3[i]+(ztep*2)-search_size+1);
1224 // cnt=v4.size();
1225 // for( int i=0; i<cnt; i++)
1226 // ret_ptr->push_back(v4[i]+(ztep*3)-search_size+1);
1227 //
1228 // return ret_ptr->size();
1229 //#endif
1230 // }
1231
1232 ///This function will slow down searching process due overhead of OpenMP
1233 //inline int FindDialog::SearchAtBufferMultiThread( char *bfr, int bfr_size, char* search, int search_size, unsigned options){
1234 // return SearchAtBuffer( bfr, bfr_size, search, search_size, options );
1235 //
1236 /////DualThread
1237 // int f1,f2;
1238 // #pragma omp parallel sections // starts a new team
1239 // {
1240 // #pragma omp section
1241 // {f1=SearchAtBuffer( bfr, bfr_size/2, search, search_size, options );}
1242 // #pragma omp section
1243 // {f2=SearchAtBuffer( bfr+ bfr_size-bfr_size/2-search_size+1, bfr_size/2+search_size-1, search, search_size, options );}
1244 // }
1245 // return f1 >= 0 ? f1 : bfr_size/2+f2;
1246 //
1247 /////QuadThread
1248 // int ztep=bfr_size/4;
1249 // int f1,f2,f3,f4;
1250 //
1251 // #ifndef OMP_H
1252 // return SearchAtBuffer( bfr, bfr_size, search, search_size, options );
1253 // #else
1254 // if( ztep < search_size*128 ) //For safety & avoid overhead
1255 // return SearchAtBufferSingleThread( bfr, bfr_size, search, search_size, options );
1256 // #pragma omp parallel sections // starts a new team
1257 // {
1258 // { f1=SearchAtBufferSingleThread( bfr, ztep, search, search_size, options ); }
1259 // #pragma omp section
1260 // { f2=SearchAtBufferSingleThread( bfr+ztep-search_size+1, ztep+search_size-1, search, search_size, options ); }
1261 // #pragma omp section
1262 // { f3=SearchAtBufferSingleThread( bfr+(ztep*2)-search_size+1, ztep+search_size-1, search, search_size, options ); }
1263 // #pragma omp section
1264 // { f4=SearchAtBufferSingleThread( bfr+(ztep*3)-search_size+1, bfr_size-ztep*3+search_size-1, search, search_size, options ); }
1265 // }
1266 // //std::cout << "SearchAtBuffer f1:" << f1 << "\tf2:" << f2 << "\tf3:" << f3 << "\tf4:" << f4 << std::endl;
1267 // return f1>=0 ? f1 :
1268 // f2>=0 ? f2 + ztep-search_size:
1269 // f3>=0 ? f3 + 2*ztep:
1270 // f4>=0 ? f4 + 3*ztep : -1;
1271 // #endif
1272 // }
1273
1274 // TODO (death#9#): Implement better search algorithm instead of 1:1 comparison + (using OpenCL, OpenMP, SIMD) :)
1275 // DONE : SIMD SSE2 engine.
1276
1277
1278
1279 //Returns indice of byte if used with (! options & SEARCH_FINDALL)
1280 //Returns indice of first found if used with ( options & SEARCH_FINDALL) ret_ptr return vector pointer filled with locations at buffer
1281 //WARNING! THIS FUNCTION WILL CHANGE BFR and/or SEARCH strings if SEARCH_MATCHCASE not selected as an option!
SearchAtBuffer(char * bfr,int bfr_size,char * search,int search_size,unsigned options,std::vector<int> * ret_ptr)1282 inline int FindDialog::SearchAtBuffer( char *bfr, int bfr_size, char* search, int search_size, unsigned options, std::vector<int> *ret_ptr ){
1283 if( bfr_size < search_size )
1284 return -1;
1285
1286 ///SEARCH_FINDALL operation supersedes SEARCH_BACKWARDS and SEARCH_WRAPAROUND
1287 if(options & SEARCH_FINDALL)
1288 options &= ~SEARCH_BACKWARDS;
1289
1290 //UTF with NO matched case handled here !!!SLOW!!! both for FORWARD and BACKWARD
1291 if(options & SEARCH_UTF8 && options & SEARCH_TEXT && !(options & SEARCH_MATCHCASE) ){
1292 //!!!UTF8 Search Speed Hack handling here!!!
1293
1294 // TODO (death#1#): Have doubts if thish lead Segmentation fault or works OK every time? Need unit test for this fx
1295 //For UTF8, search_size must be > 2. Than, we are in the safe! :)
1296 if(1){
1297 wxString ucode;
1298 wxCharBuffer ubuf;
1299
1300 if( (options & SEARCH_FINDALL) || !(options & SEARCH_BACKWARDS) )
1301 for(int i=0 ; i <= bfr_size - search_size ; i++ ){
1302 //Compare buffer's first and second bytes with search(lower version) and UTF8SpeedHackChrs (upper version)
1303 if( ( bfr[i]==search[0] && bfr[i+1]==search[1] ) ||
1304 ( bfr[i]==UTF8SpeedHackChrs[0] && bfr[i+1]==UTF8SpeedHackChrs[1] ) // Safe due UTF8??
1305 ){
1306 //Partial match found!
1307 //Now generate UTF8 Lower binary from buffer for full comparison.
1308 ucode = wxString::FromUTF8(bfr+i, search_size);
1309 ubuf = ucode.Lower().ToUTF8();
1310 if(! memcmp( ubuf, search, search_size)){ //if match found
1311 if(options & SEARCH_FINDALL)
1312 ret_ptr->push_back(i);
1313 else
1314 return i;
1315 }
1316 }
1317 }
1318 else //Backward Search!
1319 for(int i=bfr_size - search_size ; i >= 0 ; i-- ){
1320 if( ( bfr[i]==search[0] && bfr[i+1]==search[1] ) ||
1321 ( bfr[i]==UTF8SpeedHackChrs[0] && bfr[i+1]==UTF8SpeedHackChrs[1] ) // Safe due UTF8??
1322 ){
1323 //Partial match found!
1324 //Now generate UTF8 Lower binary from buffer for full comparison.
1325 ucode = wxString::FromUTF8(bfr+i, search_size);
1326 ubuf = ucode.Lower().ToUTF8();
1327 if(! memcmp( ubuf, search, search_size)){ //if match found
1328 if(options & SEARCH_FINDALL)
1329 ret_ptr->push_back(i);
1330 else
1331 return i;
1332 }
1333 }
1334 }
1335 }
1336 else{//Old and deadly slow code
1337 wxString ucode;
1338 wxCharBuffer ubuf;
1339 if((options & SEARCH_FINDALL) || !( options & SEARCH_BACKWARDS)){ //Backward Search!
1340 for(int i=0 ; i <= bfr_size - search_size ; i++ ){
1341 ucode = wxString::FromUTF8(bfr+i, search_size);
1342 ubuf = ucode.Lower().ToUTF8();
1343 if(! memcmp( ubuf, search, search_size )){ //if match found
1344 if(options & SEARCH_FINDALL)
1345 ret_ptr->push_back(i);
1346 else
1347 return i;
1348 }
1349 }
1350 }
1351 else{ //Backward Search!
1352 for(int i=bfr_size - search_size ; i >= 0 ; i-- ){
1353 ucode = wxString::FromUTF8(bfr+i, search_size);
1354 ubuf = ucode.Lower().ToUTF8();
1355 if(! memcmp( ubuf, search, search_size )){ //if match found
1356 if(options & SEARCH_FINDALL)
1357 ret_ptr->push_back(i);
1358 else
1359 return i;
1360 }
1361 }
1362 }
1363 }
1364 }
1365
1366 //TEXT search handled here with NO_MATCH CASE, both for FORWARD and BACKWARD
1367 else if(options & SEARCH_TEXT && !(options & SEARCH_MATCHCASE)){
1368 //Search at no match case ASCII handled here
1369 ///Search text already need to be lowered at FindText()
1370 #ifdef __SSE2__
1371 __m128i b = _mm_set1_epi8 ( search[0] );
1372 __m128i c = _mm_set1_epi8 ( UTF8SpeedHackChrs[0] );
1373 if((options & SEARCH_FINDALL) || !( options & SEARCH_BACKWARDS)){ //Normal Operation
1374 for(int i=0; i <= bfr_size-search_size ; i+=16 ){
1375 __m128i a = _mm_loadu_si128 ( reinterpret_cast<__m128i*>(bfr+i));
1376 __m128i r1 = _mm_cmpeq_epi8 ( a, b );
1377 __m128i r2 = _mm_cmpeq_epi8 ( a, c );
1378 short reg1=_mm_movemask_epi8( r1 );
1379 short reg2=_mm_movemask_epi8( r2 );
1380 if(reg1 || reg2){ //If SIMD return a possible match in this block
1381 #ifdef _DEBUG_FIND_
1382 char s[16];
1383 __m128i* k = (__m128i*)(s);
1384 std::cout << "\nSSE2 Debug for i=" << i << std::hex << "\t Reg1 : 0x" << reg1 << "\t Reg2 : 0x" << reg2 << std::dec;
1385 _mm_storeu_si128(k, a);
1386 std::cout << "\nREG MMX A=";
1387 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':s[z]);
1388 _mm_storeu_si128(k, b);
1389 std::cout << "\nREG MMX B=";
1390 for(int z=0; z< 16 ; z++ ) std::cout << s[z];
1391 _mm_storeu_si128(k, r1);
1392 std::cout << "\nREG MMX R=";
1393 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':'X');
1394 _mm_storeu_si128(k, c);
1395 std::cout << "\nREG MMX C=";
1396 for(int z=0; z< 16 ; z++ ) std::cout << s[z];
1397 _mm_storeu_si128(k, r2);
1398 std::cout << "\nREG MMX R=";
1399 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':'X');
1400 std::cout << std::endl;
1401 #endif // _DEBUG_FIND_
1402 for(short j=0 ; j < 16 ; j++ ){
1403 //since search[0] allready lowered & UTF8SpeedHackChrs[0] is uppered
1404 if( bfr[i+j] == search[0] || bfr[i+j] == UTF8SpeedHackChrs[0] ) {
1405 //we got first byte match here, let lower bfr[i:search_size] to full match
1406 //partialy lowering buffer
1407 for( int k = i+j ; (k < bfr_size) && (k-(i+j)<search_size); k++)
1408 bfr[k]=tolower(bfr[k]);
1409 if(! memcmp( bfr+i+j, search, search_size )){ //if match found
1410 if(options & SEARCH_FINDALL)
1411 ret_ptr->push_back(i+j);
1412 else
1413 return i+j;
1414 }
1415 }
1416 }
1417 }
1418 }
1419 }
1420 else{ //Backward Search!
1421 for(int i=bfr_size - search_size ; i >= 0 ; i-=16 ){
1422 __m128i a = _mm_loadu_si128 ( reinterpret_cast<__m128i*>(bfr+i));
1423 __m128i r1 = _mm_cmpeq_epi8 ( a, b );
1424 __m128i r2 = _mm_cmpeq_epi8 ( a, c );
1425 short reg1=_mm_movemask_epi8( r1 );
1426 short reg2=_mm_movemask_epi8( r2 );
1427 if(reg1 || reg2){ //If SIMD return a possible match in this block
1428
1429 #ifdef _DEBUG_FIND_
1430 char s[16];
1431 __m128i* k = (__m128i*)(s);
1432 std::cout << "\nSSE2 Debug for i=" << i << std::hex << "\t Reg1 : 0x" << reg1 << "\t Reg2 : 0x" << reg2 << std::dec;
1433 _mm_storeu_si128(k, a);
1434 std::cout << "\nREG MMX A=";
1435 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':s[z]);
1436 _mm_storeu_si128(k, b);
1437 std::cout << "\nREG MMX B=";
1438 for(int z=0; z< 16 ; z++ ) std::cout << s[z];
1439 _mm_storeu_si128(k, r1);
1440 std::cout << "\nREG MMX R=";
1441 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':'X');
1442 _mm_storeu_si128(k, c);
1443 std::cout << "\nREG MMX C=";
1444 for(int z=0; z< 16 ; z++ ) std::cout << s[z];
1445 _mm_storeu_si128(k, r2);
1446 std::cout << "\nREG MMX R=";
1447 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':'X');
1448 std::cout << std::endl;
1449 #endif // _DEBUG_FIND_
1450 for( short j=15 ; j>=0 ; j--)
1451 //since search[0] allready lowered & UTF8SpeedHackChrs[0] is uppered
1452 if(( bfr[i+j] == search[0] || bfr[i+j] == UTF8SpeedHackChrs[0] )){
1453 //we got first byte match here, let lower bfr[i:search_size] to full match
1454 //partialy lowering buffer
1455 for( int k = i+j ; (k < bfr_size) && (k-(i+j)<search_size); k++)
1456 bfr[k]=tolower(bfr[k]);
1457 if(! memcmp( bfr+i+j, search, search_size )){ //if match found
1458 if(options & SEARCH_FINDALL)
1459 ret_ptr->push_back(i+j);
1460 else
1461 return i+j;
1462 }
1463 }
1464 }
1465 }
1466 //Process last chunk that smaller than 16 byte (SSE2 register's max load is 16 bytes)
1467 for(int i=16 ; i >= 0 ; i-- )
1468 if( bfr[i] == search[0] )
1469 if(! memcmp( bfr+i, search, search_size )){ //if match found
1470 if(options & SEARCH_FINDALL)
1471 ret_ptr->push_back(i);
1472 else
1473 return i;
1474 }
1475 }
1476 #else
1477 //Forward Operation
1478 if((options & SEARCH_FINDALL) || !( options & SEARCH_BACKWARDS)){
1479 for(int i=0 ; i <= bfr_size - search_size ; i++ )
1480 //since search[0] allready lowered, UTF8SpeedHackChrs[0] is uppered
1481 if( bfr[i] == search[0] || bfr[i] == UTF8SpeedHackChrs[0] ){
1482 //we got first byte match here, let lower bfr[i:search_size] to full match
1483 //partialy lowering
1484 for( int j = i ; (j < bfr_size) && (j-i<search_size); j++)
1485 bfr[j]=tolower(bfr[j]);
1486
1487 if(! memcmp( bfr+i, search, search_size )){ //if match found
1488 if(options & SEARCH_FINDALL)
1489 ret_ptr->push_back(i);
1490 else
1491 return i;
1492 }
1493 }
1494 }
1495 //Backward Operation
1496 else{
1497 for( int i=bfr_size - search_size ; i >= 0 ; i-- )
1498 if( bfr[i] == search[0] || bfr[i] == UTF8SpeedHackChrs[0] ){
1499 //partial lowering code
1500 for( int j = i ; (j < bfr_size) && (j-i<search_size); j++)
1501 bfr[j]=tolower(bfr[j]);
1502
1503 if(! memcmp( bfr+i, search, search_size )){ //if match found
1504 if(options & SEARCH_FINDALL)
1505 ret_ptr->push_back(i);
1506 else
1507 return i;
1508 }
1509 }
1510 }
1511 #endif
1512 }
1513
1514 //Search as HEX, TEXT with MATCHCASE FORWARD Search.
1515 else if((options & SEARCH_FINDALL) || !(options & SEARCH_BACKWARDS)){
1516 //#pragma omp parallel for schedule(static)
1517 #ifdef __SSE2__
1518 //681 clk with SSE2 vs 1200clk with C++
1519 __m128i b = _mm_set1_epi8 ( search[0] );
1520
1521 for(int i=0; i <= bfr_size-search_size ; i+=16 ){
1522 __m128i a = _mm_loadu_si128 ( reinterpret_cast<__m128i*>(bfr+i));
1523 __m128i r = _mm_cmpeq_epi8 ( a, b );
1524 short reg=_mm_movemask_epi8( r );
1525 #ifdef _DEBUG_FIND_
1526 char s[16];
1527 __m128i* k = (__m128i*)(s);
1528 std::cout << " SSE2 Debug for i=" << i << std::hex << "\t Reg : 0x" << reg << std::dec;
1529 _mm_storeu_si128(k, a);
1530 std::cout << "\nREG MMX A=";
1531 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':s[z]);
1532 _mm_storeu_si128(k, b);
1533 std::cout << "\nREG MMX B=";
1534 for(int z=0; z< 16 ; z++ ) std::cout << s[z];
1535 _mm_storeu_si128(k, r);
1536 std::cout << "\nREG MMX R=";
1537 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':'X');
1538 std::cout << std::endl;
1539 #endif // _DEBUG_FIND_
1540 if( reg )
1541 for( short j=0 ; j<=15 ; j++)
1542 //if( (1<<j) & reg)
1543 if( bfr[i+j] == search[0] ) //xxxclk
1544 if(! memcmp( bfr+i+j, search, search_size )){ //if match found
1545 if(options & SEARCH_FINDALL)
1546 ret_ptr->push_back(i+j);
1547 else
1548 return i+j;
1549 }
1550 }
1551 //Process last chunk that smaller than 16 byte (SSE2 register's max load is 16 bytes)
1552 // for(int i=0 ; i < 16 ; i++ )
1553 // if( bfr[i] == search[0] )
1554 // if(! memcmp( bfr+i, search, search_size )) //if match found
1555 // ret_ptr->push_back(i);
1556
1557 #else
1558 for(int i=0 ; i <= bfr_size - search_size ; i++ )
1559 if( bfr[i] == search[0] )
1560 if(! memcmp( bfr+i, search, search_size )) //if match found
1561 if(options & SEARCH_FINDALL)
1562 ret_ptr->push_back(i);
1563 else
1564 return i;
1565 #endif //__SSE2__
1566 }
1567
1568 //Search as HEX, TEXT with MATCHCASE BACKWARD Search.
1569 else{
1570 #ifdef __SSE2__
1571 //676clk with SSE2, 1251 clk with C++
1572 __m128i b = _mm_set1_epi8 ( search[0] );
1573 for(int i=bfr_size - search_size ; i >= 0 ; i-=16 ){
1574 __m128i a = _mm_loadu_si128 ( reinterpret_cast<__m128i*>(bfr+i));
1575 __m128i r = _mm_cmpeq_epi8 ( a, b );
1576 short reg=_mm_movemask_epi8( r );
1577 #ifdef _DEBUG_FIND_
1578
1579 char s[16];
1580 __m128i* k = (__m128i*)(s);
1581 std::cout << " SSE2 Debug for i=" << i << std::hex << "\t Reg : 0x" << reg << std::dec;
1582 _mm_storeu_si128(k, a);
1583 std::cout << "\nREG MMX A=";
1584 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':s[z]);
1585 _mm_storeu_si128(k, b);
1586 std::cout << "\nREG MMX B=";
1587 for(int z=0; z< 16 ; z++ ) std::cout << s[z];
1588 _mm_storeu_si128(k, r);
1589 std::cout << "\nREG MMX R=";
1590 for(int z=0; z< 16 ; z++ ) std::cout << (s[z]==0?' ':'X');
1591 std::cout << std::endl;
1592 #endif // _DEBUG_FIND_
1593 if( reg ){
1594 for( short j=15 ; j>=0 ; j--)
1595 //if( (1<<j) & reg)
1596 if( bfr[i+j] == search[0] )
1597 if(! memcmp( bfr+i+j, search, search_size )){ //if match found
1598 if(options & SEARCH_FINDALL)
1599 ret_ptr->push_back(i+j);
1600 else
1601 return i+j;
1602 }
1603 }
1604 }
1605 //Process last chunk that smaller than 16 byte (SSE2 register's max load is 16 bytes)
1606 for(int i=16 ; i >= 0 ; i-- )
1607 if( bfr[i] == search[0] )
1608 if(! memcmp( bfr+i, search, search_size )){ //if match found
1609 if(options & SEARCH_FINDALL)
1610 ret_ptr->push_back(i);
1611 else
1612 return i;
1613 }
1614 #else
1615 for(int i=bfr_size - search_size ; i >= 0 ; i-- )
1616 if( bfr[i] == search[0] )
1617 if(! memcmp( bfr+i, search, search_size )){ //if match found
1618 if(options & SEARCH_FINDALL)
1619 ret_ptr->push_back(i);
1620 else
1621 return i;
1622 }
1623 #endif // __SSE2__
1624 }
1625
1626
1627 if((options & SEARCH_FINDALL) && (ret_ptr->size() > 0) )
1628 return ret_ptr->at(0);
1629 return NANINT;
1630 }
1631
ReplaceDialog(wxWindow * parent,FAL * find_file,wxString title)1632 ReplaceDialog::ReplaceDialog( wxWindow* parent, FAL *find_file, wxString title ):FindDialog( parent, find_file, title ){
1633 //Enabling hidden replace dialog elements.
1634 m_comboBoxReplace->Show();
1635 m_static_replace->Show();
1636 m_staticline->Show();
1637 btnReplace->Show();
1638 btnReplaceAll->Show();
1639 Fit();
1640 //Load previous search results to replace box.
1641 PrepareComboBox( false );
1642 m_comboBoxReplace->Select(0);
1643 }
1644
OnReplace(bool internal)1645 int ReplaceDialog::OnReplace( bool internal ){
1646 if( !parent->select->GetState() ) {
1647 if( OnFind( internal ) == false )
1648 return 0;
1649 else
1650 return -1;
1651 }
1652
1653 else{
1654 if( m_searchtype->GetSelection() == 0 ){//text search
1655 PrepareComboBox( true );
1656 if( parent->select->GetSize() == m_comboBoxReplace->GetValue().Len() ){
1657 parent->FileAddDiff( parent->CursorOffset(), m_comboBoxReplace->GetValue().ToAscii(), m_comboBoxReplace->GetValue().Len());
1658 parent->select->SetState( false );
1659 parent->Reload();
1660 wxUpdateUIEvent eventx( UNREDO_EVENT );
1661 wxPostEvent(parent, eventx );
1662 return 1;
1663 }
1664 else{
1665 OSXwxMessageBox(_("Search and Replace sizes are not equal!\nReplacing with different size are not supported yet."), _("Error!"), wxOK, this);
1666 return 0;
1667 }
1668 }
1669 else{ //hex search
1670 //Hex Validation and Format
1671 wxString hexval = m_comboBoxReplace->GetValue();
1672
1673 if( !HexVerifyAndPrepare( hexval, _("Replace"), this ) )
1674 return 0;
1675
1676 m_comboBoxReplace->SetValue(hexval.Upper());
1677
1678 PrepareComboBox( true );
1679
1680 wxMemoryBuffer search_binary = wxHexCtrl::HexToBin( m_comboBoxReplace->GetValue());
1681 if( parent->select->GetSize() == search_binary.GetDataLen() ){
1682 parent->FileAddDiff( parent->CursorOffset(), static_cast<char*>(search_binary.GetData()) ,search_binary.GetDataLen() );
1683 parent->select->SetState( false );
1684 parent->Reload();
1685 wxUpdateUIEvent eventx( UNREDO_EVENT );
1686 wxPostEvent( parent, eventx);
1687 return 1;
1688 }
1689 else{
1690 OSXwxMessageBox(_("Search and Replace sizes are not equal!\nReplacing with different size are not supported yet."), _("Error!"), wxOK, this);
1691 return 0;
1692 }
1693 }
1694 }
1695 }
1696
OnReplaceAll(void)1697 void ReplaceDialog::OnReplaceAll( void ){
1698 //First search all file with find all to detect locations.
1699 OnFindAll( true );
1700 //Now Highlight array has matches. We could replace them with replace string.
1701 for( uint32_t i=0 ; i < parent->HighlightArray.Count() ; i++ ){
1702 if( m_searchtype->GetSelection() == 0 ){ //text search
1703 PrepareComboBox( true );
1704 parent->FileAddDiff( parent->HighlightArray.Item(i)->start,
1705 m_comboBoxReplace->GetValue().ToAscii(),
1706 m_comboBoxReplace->GetValue().Len());
1707 }
1708 else{ //hex search
1709 //Hex Validation and Format
1710 wxString hexval = m_comboBoxReplace->GetValue();
1711 if(!HexVerifyAndPrepare( hexval, _("Replace"), this ) )
1712 return;
1713 m_comboBoxReplace->SetValue(hexval.Upper());
1714 PrepareComboBox( true );
1715
1716 wxMemoryBuffer search_binary = wxHexCtrl::HexToBin( m_comboBoxReplace->GetValue());
1717 parent->FileAddDiff( parent->HighlightArray.Item(i)->start,
1718 static_cast<char*>(search_binary.GetData()),
1719 search_binary.GetDataLen() );
1720 }
1721
1722 if( parent->HighlightArray.Count() < 20 ) // if there is too much matches,
1723 parent->Goto( parent->HighlightArray.Item(i)->start ); // this make program unresponsive and slow.
1724 }
1725
1726 if( parent->HighlightArray.Count() > 0){
1727 parent->Goto( parent->HighlightArray.Item(0)->start );
1728 parent->Refresh();
1729 this->Hide();
1730 wxUpdateUIEvent eventx( UNREDO_EVENT );
1731 wxPostEvent( parent, eventx);
1732 OSXwxMessageBox(wxString::Format(_("%d records changed."), parent->HighlightArray.Count() ), _("Info"), wxOK, parent);
1733 EndModal(0);
1734 }
1735 }
1736
EventHandler(wxCommandEvent & event)1737 void ReplaceDialog::EventHandler( wxCommandEvent& event ){
1738 int id = event.GetId();
1739 if( id == btnFind->GetId() )
1740 OnFind();
1741 else if( id == btnFindAll->GetId() )
1742 OnFindAll();
1743 else if( id == btnReplace->GetId() )
1744 OnReplace();
1745 else if( id == btnReplaceAll->GetId() )
1746 OnReplaceAll();
1747 }
1748
PrepareComboBox(bool AddString)1749 void ReplaceDialog::PrepareComboBox( bool AddString ){
1750 int searchType = m_searchtype->GetSelection() == 0 ? SEARCH_TEXT : SEARCH_HEX;
1751 if( searchType == SEARCH_TEXT )
1752 ComboBoxFill( _T("ReplaceTextString"), m_comboBoxReplace, AddString);
1753 else
1754 ComboBoxFill( _T("ReplaceHexString"), m_comboBoxReplace, AddString);
1755 }
1756
CopyAsDialog(wxWindow * _parent,FAL * file,Select * select_,ArrayOfTAG * MainTagArray_)1757 CopyAsDialog::CopyAsDialog( wxWindow* _parent, FAL *file, Select *select_ , ArrayOfTAG* MainTagArray_):CopyAsDialogGui( _parent , wxID_ANY){
1758 parent = static_cast< HexEditor* >( _parent );
1759 spnBytePerLine->SetValue( parent->BytePerLine() );
1760 select = select_;
1761 copy_file = file;
1762 MainTagArray=MainTagArray_;
1763 bool IsBigEndian;
1764 //parent->interpreter->chkBigEndian->GetValue(); Does this approach better than remembering old value?
1765 myConfigBase::Get()->Read( _T("CopyAsBigEndian"), &IsBigEndian );
1766 chkBigEndian->SetValue( IsBigEndian );
1767
1768 int CopyAsFunction;
1769 if (myConfigBase::Get()->Read(_T("CopyAsSelectedFunction"), &CopyAsFunction))
1770 chcCopyAs->SetSelection( CopyAsFunction );
1771 PrepareOptions( CopyAsFunction );
1772 }
1773
PrepareOptions(int SelectedFunction)1774 void CopyAsDialog::PrepareOptions( int SelectedFunction ){
1775 //wxT("Full Text"), wxT("Special Hex"), wxT("HTML"), wxT("C/C++"), wxT("Assembler")
1776 chcOption->Enable(SelectedFunction > 0);
1777 chcOption->Clear();
1778
1779 if( SelectedFunction == 0){
1780 chcOption->Insert(_("Not Available"),0);
1781 chkOffset->Enable(true);
1782 chkHex->Enable(true);
1783 chkText->Enable(true);
1784 }
1785 else if( SelectedFunction == 1){ // Hex
1786 chcOption->Insert(_("Raw Hex"),0);
1787 chcOption->Insert(_("With Space"),1);
1788 chcOption->Insert(_("Quad Hex"),2);
1789 chcOption->Insert(_("with 0x"),3);
1790 chcOption->Insert(_("with 0x and Comma"),4);
1791 chkOffset->Enable(false);
1792 chkHex->Enable(false);
1793 chkText->Enable(false);
1794
1795 }
1796 else if( SelectedFunction == 2){ // HTML
1797 chcOption->Insert(_("HTML format"),0);
1798 chcOption->Insert(_("HTML with TAGs"),1);
1799 chcOption->Insert(_("phpBB forum style"),2);
1800 chcOption->Insert(_("WiKi format"),3);
1801 chcOption->Insert(_("WiKi with TAGs"),4);
1802 chkOffset->Enable(true);
1803 chkHex->Enable(true);
1804 chkText->Enable(true);
1805 }
1806 else if( SelectedFunction >= 3){ // C/C++/ASM Sources
1807 chcOption->Insert(_("8bit - Byte "),0);
1808 chcOption->Insert(_("16bit - Words"),1);
1809 chcOption->Insert(_("32bit - Dwords"),2);
1810 chcOption->Insert(_("64bit - Qwords"),3);
1811 chkOffset->Enable(false);
1812 chkHex->Enable(false);
1813 chkText->Enable(false);
1814 }
1815 int option=0;
1816 myConfigBase::Get()->Read(_T("CopyAsSelectedOptionOfFunction") + wxString::Format(wxT("%d"),SelectedFunction), &option);
1817 chcOption->SetSelection( option );
1818
1819 //Enable big endian checkbox if multi byte representation selected for C/C++/ASM sources.
1820 chkBigEndian->Enable( chcCopyAs->GetSelection() >=3 && chcOption->GetSelection() > 0 );
1821
1822 wxYield();
1823 this->GetSizer()->Fit(this);
1824 this->GetSizer()->Layout();
1825 }
1826
EventHandler(wxCommandEvent & event)1827 void CopyAsDialog::EventHandler( wxCommandEvent& event ){
1828 int id = event.GetId();
1829 if( id == wxID_CANCEL )
1830 EndModal(id);
1831 else if( id == wxID_OK ){
1832 Copy();
1833 EndModal(id);
1834 }
1835 else if( id == chcCopyAs->GetId() ){
1836 int SelectedFunction = chcCopyAs->GetSelection();
1837 PrepareOptions(SelectedFunction);
1838
1839 int option;
1840 //Adjustinf selection part
1841 if (myConfigBase::Get()->Read(_T("CopyAsSelectedOptionOfFunction") + wxString::Format(wxT("%d"),SelectedFunction), &option))
1842 chcOption->SetSelection( option );
1843 else
1844 chcOption->SetSelection(0);
1845
1846 myConfigBase::Get()->Write( _T("CopyAsSelectedFunction"), SelectedFunction );
1847 }
1848 else if( id == chcOption->GetId() ){
1849 myConfigBase::Get()->Write( _T("CopyAsSelectedOptionOfFunction") + wxString::Format(wxT("%d"), chcCopyAs->GetSelection()), chcOption->GetSelection() );
1850
1851 //Enable big endian checkbox if multi byte representation selected for C/C++/ASM sources.
1852 chkBigEndian->Enable( chcCopyAs->GetSelection() >=3 && chcOption->GetSelection() > 0 );
1853 }
1854 else if( id == chkBigEndian->GetId() ){
1855 myConfigBase::Get()->Write( _T("CopyAsBigEndian"), chkBigEndian->GetValue() );
1856 }
1857
1858 }
1859
PrepareFullText(wxString & cb,wxMemoryBuffer & buff)1860 void CopyAsDialog::PrepareFullText( wxString& cb, wxMemoryBuffer& buff ){
1861 unsigned BytePerLine = spnBytePerLine->GetValue();
1862 for(unsigned current_offset = 0; current_offset < select->GetSize() ; current_offset += BytePerLine){
1863 if(chkOffset->GetValue()){
1864 cb += parent->GetFormatedOffsetString( select->GetStart() + current_offset );
1865 cb += wxT(" ");
1866 }
1867
1868 //Add 16 hex val
1869 if(chkHex->GetValue()){
1870 for(unsigned i = 0 ; i < BytePerLine ; i++){
1871 if( i + current_offset < select->GetSize())
1872 cb+= wxString::Format( wxT("%02X "), (unsigned char)buff[ current_offset + i] );
1873 else
1874 cb+= wxT(" "); //fill with zero to make text area at proper location
1875 }
1876 cb += wxT(" "); //Why only 2 ? Because we got extra 1 space from Hex
1877 }
1878
1879 if(chkText->GetValue()){
1880 //Add 16 Ascii rep
1881 // unsigned char chr;
1882 // for(unsigned i = 0 ; i < BytePerLine ; i++){
1883 // if( i + current_offset < select->GetSize()){
1884 // chr = buff[ current_offset + i];
1885 // //Char filter for ascii
1886 // if( (chr !=173) && ( (chr>31 && chr<127) || chr>159) )
1887 // cb+= wxString::FromAscii( buff[ current_offset + i]%0x7F);
1888 // else
1889 // cb+= '.';
1890 // }
1891 // }
1892 cb += wxString::From8BitData( &buff[current_offset],
1893 (current_offset+BytePerLine > select->GetSize()) ?
1894 select->GetSize()-current_offset : BytePerLine);
1895 }
1896 cb += wxNewline;
1897 }
1898 }
1899
PrepareFullTextWithTAGs(wxString & cb,wxMemoryBuffer & buff,wxString startup,wxString ending,wxString blank)1900 void CopyAsDialog::PrepareFullTextWithTAGs( wxString& cb, wxMemoryBuffer& buff, wxString startup, wxString ending, wxString blank ){
1901 bool TAGenable=true;
1902
1903 wxString x3Blank=blank+blank+blank;
1904
1905 unsigned BytePerLine = spnBytePerLine->GetValue();
1906 wxString last_color_hex,last_color_text;
1907 if(TAGenable){
1908 cb += startup+wxT("TAG List:")+ending;
1909 for( unsigned i =0 ; i < MainTagArray->Count() ; i++ ){
1910 TagElement *tag = MainTagArray->Item(i);
1911 if(( tag->start < select->GetStart() && tag->end >= select->GetStart() ) ||
1912 ( tag->start >= select->GetStart() && tag->start <= select->GetEnd() ) ||
1913 ( tag->end >= select->GetStart() && tag->end <= select->GetEnd() ) ){
1914
1915 cb += startup+wxT("<span style=\"background-color:") + tag->SoftColour( tag->NoteClrData.GetColour() ).GetAsString(wxC2S_HTML_SYNTAX) +
1916 wxT(";color:") + tag->FontClrData.GetColour().GetAsString(wxC2S_HTML_SYNTAX) + wxT(";\">") + tag->tag +wxT("</span>")+ending;
1917 }
1918 }
1919 cb += startup+ending;
1920 }
1921
1922 for(unsigned current_offset = 0; current_offset < select->GetSize() ; current_offset += BytePerLine){
1923 if(chkOffset->GetValue()){
1924 cb += startup + parent->GetFormatedOffsetString( select->GetStart() + current_offset );
1925 cb += x3Blank;
1926 }
1927
1928 if(chkHex->GetValue()){
1929 //Add 16 hex val
1930 //Check for middle TAG selection starts
1931 if( current_offset == 0 )
1932 for( unsigned j = 0 ; j< MainTagArray->Count() ; j++ ){
1933 TagElement *tg = MainTagArray->Item(j);
1934 if( tg->isCover( select->GetStart() ) )
1935 last_color_hex = last_color_hex = tg->SoftColour(tg->NoteClrData.GetColour()).GetAsString(wxC2S_HTML_SYNTAX);
1936 }
1937
1938 if( last_color_hex.Len() )
1939 cb += wxT("<span style=\"background-color:") + last_color_hex + wxT(";\">");
1940
1941 for(unsigned i = 0 ; i < BytePerLine ; i++){
1942
1943 //TAG Paint Loop
1944 if(TAGenable)
1945 for( unsigned j = 0 ; j< MainTagArray->Count() ; j++ ){
1946 TagElement *tg = MainTagArray->Item(j);
1947 if( MainTagArray->Item(j)->start == i + current_offset + select->GetStart()){
1948 last_color_hex = tg->SoftColour(tg->NoteClrData.GetColour()).GetAsString(wxC2S_HTML_SYNTAX);
1949 cb += wxT("<span style=\"background-color:") + last_color_hex + wxT(";\">");
1950 }
1951 if( MainTagArray->Item(j)->end +1== i + current_offset + select->GetStart() ){
1952 cb += wxT("</span>");
1953 last_color_hex = wxEmptyString;
1954 }
1955 }
1956
1957 if( i + current_offset < select->GetSize())
1958 cb+= wxString::Format( wxT("%02X "), (unsigned char)buff[ current_offset + i] );
1959 else{
1960 if(last_color_hex.Len() )
1961 cb += wxT("</span>");
1962 last_color_hex = wxEmptyString;
1963 cb+= x3Blank; //fill with zero to make text area at proper location
1964 }
1965 //This avoid to paint text section.
1966 if(last_color_hex.Len() && i==BytePerLine-1)
1967 cb += wxT("</span>");
1968 }
1969 //cb += wxT(" "); //Why only 2 ? Because we got extra 1 space from Hex
1970 cb += blank+blank; //Why only 2 ? Because we got extra 1 space from Hex
1971 }
1972
1973 if(chkText->GetValue()){
1974 //Add 16 Ascii rep
1975
1976 if( current_offset == 0 )
1977 for( unsigned j = 0 ; j< MainTagArray->Count() ; j++ ){
1978 TagElement *tg = MainTagArray->Item(j);
1979 if( tg->isCover( select->GetStart() ) )
1980 last_color_text = tg->SoftColour(tg->NoteClrData.GetColour()).GetAsString(wxC2S_HTML_SYNTAX);
1981 }
1982
1983 if( last_color_text.Len() )
1984 cb += wxT("<span style=\"background-color:") + last_color_text + wxT(";\">");
1985 for(unsigned i = 0 ; i < BytePerLine ; i++){
1986 if( i + current_offset < select->GetSize()){
1987 //TAG Paint Loop
1988 if(TAGenable)
1989 for( unsigned j = 0 ; j< MainTagArray->Count() ; j++ ){
1990 TagElement *tg = MainTagArray->Item(j);
1991 if( MainTagArray->Item(j)->start == i + current_offset + select->GetStart()){
1992 last_color_text = tg->SoftColour( tg->NoteClrData.GetColour()).GetAsString(wxC2S_HTML_SYNTAX);
1993 cb += wxT("<span style=\"background-color:") + last_color_text + wxT(";\">");
1994 }
1995 if( MainTagArray->Item(j)->end +1== i + current_offset + select->GetStart()){
1996 cb += wxT("</span>");
1997 last_color_text = wxEmptyString;
1998 }
1999 }
2000
2001 //Char filter for ascii
2002 cb += wxString::From8BitData( &buff[ current_offset + i], 1 );
2003 }
2004 if(last_color_text.Len() && i==BytePerLine-1)
2005 cb += wxT("</span>");
2006 }
2007 }
2008 cb += ending;
2009 }
2010 cb += startup + ending;
2011 }
2012
Copy(void)2013 void CopyAsDialog::Copy( void ){
2014 if( select->GetState() ) {
2015 int BytePerLine = spnBytePerLine->GetValue();
2016 wxString cb;
2017 uint64_t RAM_limit = 10*MB;
2018 wxMemoryBuffer buff;
2019 if(select->GetSize() > RAM_limit) {
2020 OSXwxMessageBox( _("Selected block bigger than limit." ),_("Error!"), wxOK|wxICON_ERROR , this);
2021 return;
2022 }
2023
2024 copy_file->Seek( select->GetStart(), wxFromStart );
2025 buff.UngetWriteBuf( copy_file->Read( static_cast<unsigned char*>(buff.GetWriteBuf(select->GetSize())), select->GetSize() ) );
2026
2027 if( chcCopyAs->GetSelection() == 0 ){ //Full text copy
2028 PrepareFullText( cb, buff );
2029 }
2030 else if( chcCopyAs->GetSelection() == 1){
2031 wxString HexFormat;
2032 bool quad=false;
2033 switch( chcOption->GetSelection()){
2034 case 0: HexFormat=wxT("%02X");break; //Raw Hex
2035 case 1: HexFormat=wxT("%02X ");break; //Standard
2036 case 2: HexFormat=wxT("%02X"); quad=true; break; //Quad
2037 case 3: HexFormat=wxT("0x%02X ");break; //Ox
2038 case 4: HexFormat=wxT("0x%02X, ");break; //Ox with period
2039 }
2040
2041 for(unsigned current_offset = 0; current_offset < select->GetSize() ; current_offset ++){
2042 cb+= wxString::Format( HexFormat, (unsigned char)buff[ current_offset ] );
2043 if(current_offset+1==select->GetSize())
2044 if (HexFormat.EndsWith(", ")) //Ox with period
2045 cb=cb.RemoveLast(2);
2046 if( quad && ((current_offset+1)%2)==0)
2047 cb += wxT(" ");
2048 if(( (current_offset+1) % BytePerLine)==0 )
2049 cb += wxNewline;
2050 }
2051
2052 }
2053
2054 else if( chcCopyAs->GetSelection() == 2){//Internet
2055 if( chcOption->GetSelection() == 0 ){ //html
2056 // <html><head><title></title></head><body>
2057 // <pre>
2058 // <code style="color:#000000;background-color:#FFFFFF">0000E973 1375 6E5A 8696 553A 01C9 51A2 F244 90BD .unZ..U:.ÉQ¢òD.½</code>
2059 // <code style="color:#000000;background-color:zebra?;">0000E983 1375 6E5A 8696 553A 01C9 51A2 F244 90BD .unZ..U:.ÉQ¢òD.½</code>
2060 // </pre>
2061 // <font size="-3">Generated by <a href="http://wxhexeditor.sourceforge.net/">wxHexEditor</a></font>
2062 // </body></html>
2063 cb += wxT("<pre><code style=\"color:#000000;\">");
2064 PrepareFullText( cb, buff );
2065 cb += wxT("</code></pre><font size=\"-3\">Generated by <a href=\"http://www.wxHexEditor.org/\">wxHexEditor</a></font>");
2066 }
2067
2068 else if( chcOption->GetSelection() == 1 ){ //HTML with Tags
2069 cb += wxT("<pre><code style=\"color:#000000;\">");
2070 PrepareFullTextWithTAGs( cb, buff, wxT(""), wxT("<br/>"), wxT(" ") );
2071 cb += wxT("</code></pre><font size=\"-3\">Generated by <a href=\"http://www.wxHexEditor.org\">wxHexEditor</a></font>");
2072 }
2073
2074 else if( chcOption->GetSelection() == 2 ){ //phpBB Forum
2075 cb+= wxT("[code]");
2076 PrepareFullText( cb, buff );
2077 cb += wxT("[/code]Generated by [url=http://www.wxHexEditor.org]wxHexEditor[/url]" wxNewline);
2078 }
2079
2080 else if( chcOption->GetSelection() == 3 ){ //WiKi format
2081 cb+= wxT("<pre>");
2082 PrepareFullText( cb, buff );
2083 cb += wxT("</pre> Generated by [http://www.wxHexEditor.org/ wxHexEditor]" wxNewline);
2084 }
2085 else if( chcOption->GetSelection() == 4 ){ //WiKi with TAGs
2086 PrepareFullTextWithTAGs( cb, buff, wxT(" "),wxT("\n"),wxT(" ") );
2087 cb += wxT(" Generated by [http://www.wxHexEditor.org/ wxHexEditor]" wxNewline);
2088 }
2089 }
2090 else if( chcCopyAs->GetSelection() == 3){//C/C++
2091 unsigned HexSize = pow( 2, chcOption->GetSelection());
2092 unsigned count = select->GetSize()/HexSize;
2093 cb+=wxT("// Generated by wxHexEditor //" wxNewline);
2094 switch( HexSize ){
2095 case 1: cb += wxT("int8_t"); break;
2096 case 2: cb += wxT("int16_t"); break;
2097 case 4: cb += wxT("int32_t"); break;
2098 case 8: cb += wxT("int64_t"); break;
2099 }
2100
2101 cb+=wxString::Format( wxT(" hexData[0x%x] = {" wxNewline " "), count );
2102 bool bigEndianSwapReq = chkBigEndian->GetValue() && chcOption->GetSelection();//No big endian for 8 bit
2103 int b;
2104 int limit=(bigEndianSwapReq ? -1 : HexSize);
2105 int incr = (bigEndianSwapReq ? -1 : +1);
2106 for(unsigned current_offset = 0; current_offset < count ; current_offset ++){
2107 b = (bigEndianSwapReq ? HexSize-1 : 0);
2108 cb+= wxT("0x");
2109 for(; b != limit ; b+=incr)
2110 cb+= wxString::Format( wxT("%02X"), reinterpret_cast<unsigned char*>( buff.GetData() )[current_offset*HexSize+b]);
2111 cb+= wxT(", ");
2112 // switch( HexSize ){
2113 // case 1: cb+= wxString::Format( wxT("0x%02X, "), *reinterpret_cast<unsigned char*>( buff.GetData()+current_offset*HexSize )); break;
2114 // case 2: cb+= wxString::Format( wxT("0x%04X, "), *reinterpret_cast<unsigned short*>( buff.GetData()+current_offset*HexSize )); break;
2115 // case 4: cb+= wxString::Format( wxT("0x%08X, "), *reinterpret_cast<unsigned int*>( buff.GetData()+current_offset*HexSize )); break;
2116 // case 8: cb+= wxString::Format( wxT("0x%016" wxLongLongFmtSpec "X, "), *reinterpret_cast<uint64_t*>( buff.GetData()+current_offset*HexSize )); break;
2117 // }
2118 if(( (current_offset+1) % (BytePerLine/HexSize)==0 ) && current_offset != count)
2119 cb += wxT("" wxNewline " ");
2120 }
2121 cb=cb.BeforeLast(',')+wxT(" }" wxNewline);
2122 }
2123 else if( chcCopyAs->GetSelection() == 4){//ASM
2124 unsigned HexSize = pow( 2, chcOption->GetSelection());
2125 unsigned count = select->GetSize()/HexSize;
2126 cb+=wxT(";Generated by wxHexEditor");
2127
2128 wxString HexFormat;
2129 switch( HexSize ){
2130 case 1: HexFormat += wxT("" wxNewline "db "); break;
2131 case 2: HexFormat += wxT("" wxNewline "dw "); break;
2132 case 4: HexFormat += wxT("" wxNewline "dd "); break;
2133 case 8: HexFormat += wxT("" wxNewline "dq "); break;
2134 }
2135
2136 bool bigEndianSwapReq = chkBigEndian->GetValue() && chcOption->GetSelection();//No big endian for 8 bit
2137 int b;
2138 int limit=(bigEndianSwapReq ? -1 : HexSize);
2139 int incr = (bigEndianSwapReq ? -1 : +1);
2140 for(unsigned current_offset = 0; current_offset < count ; current_offset ++){
2141 if( current_offset % (BytePerLine/HexSize)==0 )
2142 cb += HexFormat;
2143 b = (bigEndianSwapReq ? HexSize-1 : 0);
2144 cb+= wxT("0");
2145 for(; b != limit ; b+=incr)
2146 cb+= wxString::Format( wxT("%02X"), reinterpret_cast<unsigned char*>( buff.GetData() )[current_offset*HexSize+b]);
2147 cb+= wxT("h ");
2148 // switch( HexSize ){
2149 // case 1: cb+= wxString::Format( wxT("0%02Xh "), *reinterpret_cast<unsigned char*>( buff.GetData()+current_offset*HexSize )); break;
2150 // case 2: cb+= wxString::Format( wxT("0%04Xh "), *reinterpret_cast<unsigned short*>( buff.GetData()+current_offset*HexSize )); break;
2151 // case 4: cb+= wxString::Format( wxT("0%08Xh "), *reinterpret_cast<unsigned int*>( buff.GetData()+current_offset*HexSize )); break;
2152 // case 8: cb+= wxString::Format( wxT("0%016" wxLongLongFmtSpec "Xh "), *reinterpret_cast<uint64_t*>( buff.GetData()+current_offset*HexSize )); break;
2153 // }
2154 }
2155 cb+=wxT('\n');
2156 }
2157
2158 if(wxTheClipboard->Open()) {
2159 // if (wxTheClipboard->IsSupported( wxDF_TEXT )){
2160 wxTheClipboard->Clear();
2161 wxTheClipboard->SetData( new wxTextDataObject( cb ));
2162 wxTheClipboard->Flush();
2163 wxTheClipboard->Close();
2164 }
2165 }
2166 }
2167
CompareDialog(wxWindow * parent_,wxString File1,wxString File2)2168 CompareDialog::CompareDialog( wxWindow* parent_, wxString File1, wxString File2 ):CompareDialogGui(parent_, wxID_ANY){
2169 parent = static_cast< HexEditorFrame* >(parent_);
2170 filePick1->Connect(wxEVT_DROP_FILES, wxDropFilesEventHandler(CompareDialog::EventHandler2),NULL, this);
2171 filePick2->Connect(wxEVT_DROP_FILES, wxDropFilesEventHandler(CompareDialog::EventHandler2),NULL, this);
2172
2173 if( File1 != wxEmptyString ){
2174 filePick1->SetPath( File1 );
2175 filePick2->SetPath( File2 );
2176 filePick1->Hide();
2177 filePick2->Hide();
2178 m_TextFile1->Hide();
2179 m_TextFile2->Hide();
2180 btnCompare->Enable(true);
2181 Fit();
2182 }
2183
2184 //Not working on linux somehow???
2185 // else{
2186 // wxString tmp;
2187 // myConfigBase::Get()->Read( _T("CompareFile1"), &tmp );
2188 // filePick1->SetLabel( tmp );
2189 // filePick1->SetPath( tmp );
2190 //
2191 // myConfigBase::Get()->Read( _T("CompareFile2"), &tmp );
2192 // filePick2->SetLabel( tmp );
2193 // filePick2->SetPath( tmp );
2194 // filePick2->UpdateTextCtrlFromPicker();
2195 // }
2196
2197 int options=0;
2198 myConfigBase::Get()->Read( _T("CompareOptions"), &options );
2199 checkConnectFiles->SetValue( options & OPT_CMP_CONNECT );
2200 checkMergeSection->SetValue( options & OPT_CMP_MERGE_SECTION );
2201 spinMergeSection->Enable( options & OPT_CMP_MERGE_SECTION );
2202 checkStopCompare->SetValue( options & OPT_CMP_STOP_AFTER );
2203 spinStopCompare->Enable( options & OPT_CMP_STOP_AFTER );
2204 checkSaveResults->SetValue( options & OPT_CMP_SAVE );
2205 filePickSave->Enable( options & OPT_CMP_SAVE );
2206 m_radioDifferent->SetValue( options & OPT_CMP_SEARCH_DIFF );
2207 m_radioSame->SetValue( !(options & OPT_CMP_SEARCH_DIFF) );
2208
2209 int tmp;
2210 myConfigBase::Get()->Read( _T("CompareOptionStopAfter"), &tmp );
2211 spinStopCompare->SetValue(tmp);
2212
2213 myConfigBase::Get()->Read( _T("CompareOptionMergeSection"), &tmp );
2214 spinMergeSection->SetValue(tmp);
2215 }
2216
~CompareDialog(void)2217 CompareDialog::~CompareDialog(void){
2218 filePick1->Disconnect( wxEVT_DROP_FILES, wxDropFilesEventHandler(CompareDialog::EventHandler2),NULL, this);
2219 filePick2->Disconnect( wxEVT_DROP_FILES, wxDropFilesEventHandler(CompareDialog::EventHandler2),NULL, this);
2220 }
2221
Compare(wxFileName fl1,wxFileName fl2,bool SearchForDiff,int StopAfterNMatch,wxFileName flsave)2222 bool CompareDialog::Compare( wxFileName fl1, wxFileName fl2, bool SearchForDiff, int StopAfterNMatch, wxFileName flsave ){
2223 if(!fl1.IsFileReadable()){
2224 wxMessageBox( _("File #1 is not readable."), _("Error") );
2225 return false;
2226 }
2227 if(!fl2.IsFileReadable() ){
2228 wxMessageBox( _("File #2 is not readable."), _("Error") );
2229 return false;
2230 }
2231
2232 myConfigBase::Get()->Write( _T("CompareFile1"), fl1.GetFullPath() );
2233 myConfigBase::Get()->Write( _T("CompareFile2"), fl2.GetFullPath() );
2234 myConfigBase::Get()->Flush();
2235 // if( flsave != wxEmptyString ){
2236 // if(!flsave.IsFileWritable() )
2237 // wxMessageBox( _("Error, Save File is not writeable.") );
2238 // return false;
2239 // }
2240
2241 wxFFile f1,f2,fs;
2242 // TODO (death#1#): Why we dont use FAL at ALL?
2243 if( !f1.Open( fl1.GetFullPath(), wxT("rb") ) ){
2244 wxMessageBox( _("Error, File #1 cannot open." ) );
2245 return false;
2246 }
2247 if( !f2.Open( fl2.GetFullPath(), wxT("rb") ) ){
2248 wxMessageBox( _("Error, File #2 cannot open." ) );
2249 return false;
2250 }
2251
2252 if( flsave != wxEmptyString )
2253 if( !fs.Open( flsave.GetFullPath(), wxT("wb") ) ){
2254 wxMessageBox( _("Error, Save File cannot open." ) );
2255 return false;
2256 }
2257 wxString msg= _("Comparing files...");
2258 wxString emsg=wxT("\n");
2259 wxProgressDialog pdlg( _("wxHexEditor Comparing"), msg+emsg, 1000, this, wxPD_AUTO_HIDE | wxPD_SMOOTH | wxPD_APP_MODAL|wxPD_CAN_ABORT/*|wxPD_CAN_SKIP*/|wxPD_REMAINING_TIME); //SKIP not ready and Buggy
2260 pdlg.SetWindowStyleFlag( pdlg.GetWindowStyleFlag()|wxSTAY_ON_TOP|wxMINIMIZE_BOX );
2261 pdlg.Show();
2262
2263 time_t ts,te;
2264 time (&ts);
2265 te=ts;
2266 unsigned read_speed=0;
2267
2268
2269 int64_t diffBuff[1*MB]; //up to 500K differences.
2270 //Structure is : even indices for difference start offset, odd indices for end offsets
2271 int diffHit = 0;
2272 bool diff=false;
2273 uint64_t drange = wxMin( f1.Length() , f2.Length() );
2274 if(drange == 0)
2275 drange++; //to avoid Gauge zero div error
2276
2277 //Section Merge Code
2278 int compare_range=0;
2279 if( checkMergeSection->GetValue() )
2280 compare_range=spinMergeSection->GetValue();
2281
2282 bool BreakDoubleFor=false;
2283 int rdBlockSz=1*MB;
2284
2285 int rd1,rd2;
2286 char *buffer1=new char[rdBlockSz];
2287 char *buffer2=new char[rdBlockSz];
2288 char *buffer1_prefetch=new char[rdBlockSz];
2289 char *buffer2_prefetch=new char[rdBlockSz];
2290 int* bfr_int1;
2291 int* bfr_int2;
2292 int rd1_prefetch=0,rd2_prefetch=0;
2293 //#ifdef _DEBUG_
2294 std::cout << "StopAfterNMatch:" << StopAfterNMatch << std::endl;
2295 //#endif
2296
2297 // for( uint64_t mb = 0 ; !(f1.Eof() || f2.Eof() || BreakDoubleFor) ; mb+=rdBlockSz){
2298 for( int64_t mb = 0 ; mb < wxMin(f1.Length(),f2.Length()) && !BreakDoubleFor ; mb+=rdBlockSz){
2299 if(rd1_prefetch==0){
2300 // buffer1.UngetWriteBuf( f1.Read(buffer1.GetWriteBuf( rdBlockSz ),rdBlockSz) );
2301 // buffer2.UngetWriteBuf( f2.Read(buffer2.GetWriteBuf( rdBlockSz ),rdBlockSz) );
2302 rd1=f1.Read(buffer1,rdBlockSz);
2303 rd2=f2.Read(buffer2,rdBlockSz);
2304 }
2305 else{
2306 std::swap(buffer1, buffer1_prefetch);
2307 std::swap(buffer2, buffer2_prefetch);
2308 rd1=rd1_prefetch;
2309 rd2=rd2_prefetch;
2310 }
2311 #ifdef _DEBUG_
2312 std::cout << "Diff Compare Start Offset: " << mb << std::endl;
2313 #endif
2314 bool show_limit_message=false;
2315 //Not enabled due f1.Eof() loop. If read last byte, for loop get out immeditialy!
2316 #ifdef _READ_PREFETCH_
2317 #pragma omp parallel sections
2318 // #pragma omp parallel
2319 // #pragma omp single nowait
2320 {
2321 //this preloads next data to swap buffer.
2322 #pragma omp section
2323 //#pragma omp task shared(f1,f2,rd1_prefetch,rd2_prefetch)
2324 {
2325 //precalculate next read location
2326 // buffer1_prefetch.UngetWriteBuf( f1.Read(buffer1_prefetch.GetWriteBuf( rdBlockSz ),rdBlockSz) );
2327 // buffer2_prefetch.UngetWriteBuf( f2.Read(buffer2_prefetch.GetWriteBuf( rdBlockSz ),rdBlockSz) );
2328 rd1_prefetch=f1.Read(buffer1_prefetch,rdBlockSz);
2329 rd2_prefetch=f2.Read(buffer2_prefetch,rdBlockSz);
2330 }
2331 #pragma omp section
2332 //#pragma omp task
2333 {
2334 // bfr_int1 = static_cast<int*>(buffer1.GetData());
2335 // bfr_int2 = static_cast<int*>(buffer2.GetData());
2336 bfr_int1 = reinterpret_cast<int*>(buffer1);
2337 bfr_int2 = reinterpret_cast<int*>(buffer2);
2338
2339 // for( unsigned i = 0 ; (i < wxMin( buffer1.GetDataLen(), buffer2.GetDataLen())) && !BreakDoubleFor; i ++ ){
2340 for( int i = 0 ; (i < wxMin( rd1, rd2)) && !BreakDoubleFor; ){
2341 if(diffHit >= 500000){
2342 show_limit_message=true;
2343 BreakDoubleFor = true;
2344 //break; //not possible to use under OpenMP, instead use continue
2345 continue;
2346 }
2347
2348 //Here we made the comparison on INTEGER for speedup
2349 if( bfr_int1[i/sizeof(int)]==bfr_int2[i/sizeof(int)] ){
2350 //bytes are eq, goto check next integer
2351 if( !diff ){
2352 i+=sizeof(int);
2353 continue;
2354 }
2355 }
2356
2357 //If integer comparison is failed, here we made the comparison in byte
2358 if((buffer1[i] != buffer2[i]) == SearchForDiff){
2359 //Different bytes found.
2360 if(!diff){//Set difference start
2361 #ifdef _DEBUG_
2362 std::cout << "Diff Start " << mb+i << " to " ;
2363 #endif
2364 diff=true;
2365 if( ( (mb+i)-diffBuff[diffHit-1] ) <= compare_range &&
2366 compare_range > 0 && diffHit>1){
2367 diffHit--; //re-push old diff ending to stack
2368 //StopAfterNMatch++;//and count 2 difference as 1
2369 #ifdef _DEBUG_
2370 std::cout << "StopAfterNMatch:" << StopAfterNMatch << std::endl;
2371 #endif
2372 }
2373 else
2374 diffBuff[diffHit++]=mb+i;
2375 }
2376
2377 //this adds latest diff stream to array if one file ends
2378 if( i+1 == wxMin( rd1, rd2) ){
2379 //#pragma omp taskwait
2380 if(f1.Eof() || f2.Eof() ){
2381 //avoid false file ends at using prefetches!
2382 if( wxMin(rd1_prefetch,rd2_prefetch) <= 0 )
2383 diffBuff[diffHit++]=mb+i;
2384 }
2385 }
2386 }
2387
2388 else{ //bytes are eq.
2389 if(diff){//Set difference end
2390 #ifdef _DEBUG_
2391 std::cout << mb+i-1 << std::endl;
2392 #endif
2393 diff=false;
2394 diffBuff[diffHit++]=mb+i-1;
2395
2396
2397 if( --StopAfterNMatch == 0 ){
2398 #ifdef _DEBUG_
2399 std::cout << "Break comparison due StopAfterNMatch." << std::endl ;
2400 #endif
2401 BreakDoubleFor=true;
2402 break;
2403 //continue;//not possible to use under OpenMP, instead use continue
2404 }
2405 }
2406 }
2407 i++;
2408 }// Buffer comparison block for loop end
2409 }
2410 }//omp parallel end
2411
2412 if(show_limit_message)
2413 wxMessageBox( wxString(_("Sorry, this program supports up to 500K differences."))+wxT("\n")+_("Remaining differences not shown."), _("Error on Comparison"));
2414
2415 #endif // _READ_PREFETCH_
2416
2417 bool skip=false;
2418 read_speed+=rdBlockSz;
2419 //Progress window processing..
2420 time(&te);
2421 if(ts != te ){
2422 ts=te;
2423 emsg = msg + wxT("\n") + _("Comparison Speed : ") + wxString::Format( wxT("%.2f "), 1.0*read_speed/MB) + _("MB/s");
2424 read_speed=0;
2425 }
2426
2427 if( !pdlg.Update( mb/drange, emsg, &skip ) ){
2428 f1.Close();
2429 f2.Close();
2430 return false;
2431 }
2432
2433 if(skip)
2434 break;
2435 }//End of for loops / comparison
2436
2437 delete [] buffer1;
2438 delete [] buffer2;
2439 delete [] buffer1_prefetch;
2440 delete [] buffer2_prefetch;
2441
2442 pdlg.Show( false );
2443
2444 if( flsave != wxEmptyString ){
2445 wxString ln = _("File #1 : ") + fl1.GetFullPath() + wxT("\n")+_("File #2 : ") + fl2.GetFullPath() + wxT("\n\n");
2446 fs.Write( ln );
2447 wxString line;
2448 for(int i = 0 ; i < diffHit-1 ; i+=2){
2449 line = wxString::Format( "%s found %" wxLongLongFmtSpec "u - %" wxLongLongFmtSpec "u \t Total : %" wxLongLongFmtSpec "u bytes.\n", ( SearchForDiff ? wxT("Diff"):wxT("Match")), diffBuff[i] , diffBuff[i+1], diffBuff[i+1]-diffBuff[i]+1 );
2450 fs.Write( line );
2451 }
2452
2453 if( f1.Length() != f2.Length() ){
2454 if( f1.Length() > f2.Length() )
2455 line = wxString::Format( "\nFile #2 ends at offset %" wxLongLongFmtSpec "u. File #1 has extra %" wxLongLongFmtSpec "u bytes.\n",f2.Length(), f1.Length() - f2.Length() );
2456
2457 else
2458 line = wxString::Format( "\nFile #1 ends at offset %" wxLongLongFmtSpec "u. File #2 has extra %" wxLongLongFmtSpec "u bytes.\n",f1.Length(), f2.Length() - f1.Length() );
2459
2460 fs.Write( line );
2461 }
2462 }
2463 int file1size= f1.Length();
2464 int file2size= f2.Length();
2465 f1.Close();
2466 f2.Close();
2467 fs.Close();
2468
2469 HexEditor* hexeditor1 = parent->OpenFile( fl1 );
2470 HexEditor* hexeditor2 = parent->OpenFile( fl2 , true);
2471 hexeditor1->SetFileAccessMode( FAL::ReadOnly );
2472 hexeditor2->SetFileAccessMode( FAL::ReadOnly );
2473 // parent->MyNotebook.Split(-1, wxRIGHT); //Not available due protected wxNotepad. Changed OpenFile function instead.
2474
2475 if(checkConnectFiles->GetValue()){
2476 hexeditor1->ConnectScroll( hexeditor2 );
2477 }
2478
2479 if(hexeditor1 != NULL && hexeditor2 != NULL){
2480 for(int i = 0 ; i < diffHit-1 ; i+=2){
2481 TagElement *mytag=new TagElement(diffBuff[i], diffBuff[i+1],wxEmptyString,*wxBLACK, *wxRED );
2482 hexeditor1->CompareArray.Add(mytag);
2483 mytag=new TagElement(diffBuff[i], diffBuff[i+1],wxEmptyString,*wxBLACK, *wxRED );
2484 hexeditor2->CompareArray.Add(mytag);
2485 }
2486 if( file1size != file2size ){
2487 if( file1size > file2size ){
2488 TagElement *mytag=new TagElement(file2size, file1size,_("This part doesn't exist at compared file"),*wxBLACK, *wxCYAN );
2489 hexeditor1->CompareArray.Add(mytag);
2490 }
2491 else{
2492 TagElement *mytag=new TagElement(file1size, file2size,_("This part doesn't exist at compared file"),*wxBLACK, *wxCYAN );
2493 hexeditor2->CompareArray.Add(mytag);
2494 }
2495 }
2496 //Show first tag
2497 if( hexeditor1->CompareArray.Count() > 0 )
2498 hexeditor1->Goto( hexeditor1->CompareArray.Item(0)->start, true );
2499 if( hexeditor2->CompareArray.Count() > 0 ) //This check is needed if files are identical but one file has bigger than other.
2500 hexeditor2->Goto( hexeditor2->CompareArray.Item(0)->start, false );
2501
2502 //Generate event to show compare panel
2503 wxUpdateUIEvent eventx( COMPARE_CHANGE_EVENT );
2504 wxPostEvent( parent, eventx );
2505 }
2506
2507 return true;
2508 }
2509
OnFileChange(wxFileDirPickerEvent & event)2510 void CompareDialog::OnFileChange( wxFileDirPickerEvent& event ){
2511 if( filePick1->GetPath() != wxEmptyString && filePick2->GetPath() != wxEmptyString)
2512 btnCompare->Enable(true);
2513 else
2514 btnCompare->Enable(false);
2515 }
2516
EventHandler2(wxDropFilesEvent & event)2517 void CompareDialog::EventHandler2( wxDropFilesEvent& event ){
2518 wxBell();
2519 if( filePick1->GetPath() != wxEmptyString && filePick2->GetPath() != wxEmptyString)
2520 btnCompare->Enable(true);
2521 else
2522 btnCompare->Enable(false);
2523 }
2524
2525 // TODO (death#1#): Drag Drop file change event!
EventHandler(wxCommandEvent & event)2526 void CompareDialog::EventHandler( wxCommandEvent& event ){
2527 #ifdef _DEBUG_
2528 std::cout << "CompareDialog::EventHandler()" << std::endl;
2529 #endif
2530 if(event.GetId() == wxID_CANCEL)
2531 EndModal(event.GetId());
2532 else if(event.GetId() == btnCompare->GetId()){
2533 if( !filePick1->GetPath().IsEmpty() && !filePick2->GetPath().IsEmpty()){
2534 if( checkSaveResults->GetValue() && filePickSave->GetPath().IsEmpty() ){
2535 wxMessageBox( _("Error, Save File is not selected.") );
2536 return;
2537 }
2538 ///Note:Triggers stack Overflow on windows. Use bigger stack...
2539 #ifndef __WXMSW__
2540 SetStackLimit();
2541 #endif
2542
2543 if( Compare( filePick1->GetPath(), //First file.
2544 filePick2->GetPath(), //Second file to compare.
2545 m_radioDifferent->GetValue(), //Compare diffs or same bytes option.
2546 (checkStopCompare->GetValue() ? spinStopCompare->GetValue() : 0), //Stop after N Matches. 0 means unlimited.
2547 (checkSaveResults->GetValue() ? filePickSave->GetPath() : wxT("") )) //comparison result save path.
2548 )
2549 EndModal(event.GetId());
2550 }
2551 else
2552 wxBell();
2553 }
2554 else if( event.GetId() == checkStopCompare->GetId() )
2555 spinStopCompare->Enable(event.IsChecked());
2556
2557 else if( event.GetId() == checkMergeSection->GetId() )
2558 spinMergeSection->Enable(event.IsChecked());
2559
2560 else if( event.GetId() == checkSaveResults->GetId() )
2561 filePickSave->Enable(event.IsChecked());
2562
2563 int options=0;
2564 options|=checkConnectFiles->GetValue() ? OPT_CMP_CONNECT : 0;
2565 options|=checkMergeSection->GetValue() ? OPT_CMP_MERGE_SECTION : 0;
2566 options|=checkStopCompare->GetValue() ? OPT_CMP_STOP_AFTER : 0;
2567 options|=checkSaveResults->GetValue() ? OPT_CMP_SAVE : 0;
2568 options|=m_radioDifferent->GetValue() ? OPT_CMP_SEARCH_DIFF : 0;
2569 myConfigBase::Get()->Write( _T("CompareOptions"), options );
2570
2571 int optionStopAfter = spinStopCompare->GetValue();
2572 int optionMergeSection = spinMergeSection->GetValue();
2573 myConfigBase::Get()->Write( _T("CompareOptionStopAfter"), optionStopAfter );
2574 myConfigBase::Get()->Write( _T("CompareOptionMergeSection"), optionMergeSection );
2575 }
2576
ChecksumDialog(wxWindow * parent_)2577 ChecksumDialog::ChecksumDialog( wxWindow* parent_ ):ChecksumDialogGui(parent_, wxID_ANY){
2578 parent = static_cast< HexEditorFrame* >(parent_);
2579 bool active_hex = parent->GetActiveHexEditor() != NULL;
2580 chkFile->Enable(active_hex);
2581 chkFile->SetValue(active_hex);
2582 filePick->Enable(!active_hex);
2583 btnCalculate->Enable( active_hex );
2584
2585 int options;
2586 myConfigBase::Get()->Read( _T("SelectedChecksumFunctions"), &options );
2587
2588 chkMD2->SetValue( options & (1 << MHASH_MD2) );
2589 chkMD4->SetValue( options & (1 << MHASH_MD4) );
2590 chkMD5->SetValue( options & (1 << MHASH_MD5) );
2591 chkSHA1->SetValue( options & (1 << MHASH_SHA1) );
2592 chkSHA224->SetValue( options & (1 << MHASH_SHA224) );
2593 chkSHA256->SetValue( options & (1 << MHASH_SHA256) );
2594 chkSHA384->SetValue( options & (1 << MHASH_SHA384) );
2595 chkSHA512->SetValue( options & (1 << MHASH_SHA512) );
2596 chkRIPEMD128->SetValue( options & (1 << MHASH_RIPEMD128) );
2597 chkRIPEMD160->SetValue( options & (1 << MHASH_RIPEMD160) );
2598 chkRIPEMD256->SetValue( options & (1 << MHASH_RIPEMD256) );
2599 chkRIPEMD320->SetValue( options & (1 << MHASH_RIPEMD320) );
2600
2601 chkHAVAL128->SetValue( options & (1 << MHASH_HAVAL128) );
2602 chkHAVAL160->SetValue( options & (1 << MHASH_HAVAL160) );
2603 chkHAVAL192->SetValue( options & (1 << MHASH_HAVAL192) );
2604 chkHAVAL224->SetValue( options & (1 << MHASH_HAVAL224) );
2605 chkHAVAL256->SetValue( options & (1 << MHASH_HAVAL256) );
2606
2607 chkTIGER128->SetValue( options & (1 << MHASH_TIGER128) );
2608 chkTIGER160->SetValue( options & (1 << MHASH_TIGER160) );
2609 chkTIGER ->SetValue( options & (1 << MHASH_TIGER192) );
2610
2611 chkADLER32 ->SetValue( options & (1 << MHASH_ADLER32) );
2612 chkCRC32 ->SetValue( options & (1 << MHASH_CRC32) );
2613 chkCRC32B ->SetValue( options & (1 << MHASH_CRC32B) );
2614 chkWHIRLPOOL->SetValue( options & (1 << MHASH_WHIRLPOOL) );
2615 chkGOST ->SetValue( options & (1 << MHASH_GOST) );
2616 chkSNEFRU128->SetValue( options & (1 << MHASH_SNEFRU128) );
2617 chkSNEFRU256->SetValue( options & (1 << MHASH_SNEFRU256) );
2618
2619 }
2620
EventHandler(wxCommandEvent & event)2621 void ChecksumDialog::EventHandler( wxCommandEvent& event ){
2622 #ifdef _DEBUG_
2623 std::cout << "ChecksumDialog::EventHandler()" << std::endl;
2624 #endif
2625 int options=0;
2626 options |= (chkMD2->GetValue() ? 1 << MHASH_MD2 : 0);
2627 options |= (chkMD4->GetValue() ? 1 << MHASH_MD4 : 0);
2628 options |= (chkMD5->GetValue() ? 1 << MHASH_MD5 : 0);
2629
2630 options |= (chkSHA1->GetValue() ? 1 << MHASH_SHA1 : 0);
2631 //options |= (chkSHA192->GetValue() ? 1 << MHASH_SHA192 : 0);
2632 options |= (chkSHA224->GetValue() ? 1 << MHASH_SHA224 : 0);
2633 options |= (chkSHA256->GetValue() ? 1 << MHASH_SHA256 : 0);
2634 options |= (chkSHA384->GetValue() ? 1 << MHASH_SHA384 : 0);
2635 options |= (chkSHA512->GetValue() ? 1 << MHASH_SHA512 : 0);
2636
2637 options |= (chkRIPEMD128->GetValue() ? 1 << MHASH_RIPEMD128 : 0);
2638 options |= (chkRIPEMD160->GetValue() ? 1 << MHASH_RIPEMD160 : 0);
2639 options |= (chkRIPEMD256->GetValue() ? 1 << MHASH_RIPEMD256 : 0);
2640 options |= (chkRIPEMD320->GetValue() ? 1 << MHASH_RIPEMD320 : 0);
2641
2642 options |= (chkHAVAL128->GetValue() ? 1 << MHASH_HAVAL128 : 0);
2643 options |= (chkHAVAL160->GetValue() ? 1 << MHASH_HAVAL160 : 0);
2644 options |= (chkHAVAL192->GetValue() ? 1 << MHASH_HAVAL192 : 0);
2645 options |= (chkHAVAL224->GetValue() ? 1 << MHASH_HAVAL224 : 0);
2646 options |= (chkHAVAL256->GetValue() ? 1 << MHASH_HAVAL256 : 0);
2647
2648 options |= (chkTIGER128->GetValue() ? 1 << MHASH_TIGER128 : 0);
2649 options |= (chkTIGER160->GetValue() ? 1 << MHASH_TIGER160 : 0);
2650 options |= (chkTIGER->GetValue() ? 1 << MHASH_TIGER192 : 0);
2651
2652 options |= (chkADLER32->GetValue() ? 1 << MHASH_ADLER32 : 0);
2653 options |= (chkCRC32->GetValue() ? 1 << MHASH_CRC32 : 0);
2654 options |= (chkCRC32B->GetValue() ? 1 << MHASH_CRC32B : 0);
2655 options |= (chkWHIRLPOOL->GetValue() ? 1 << MHASH_WHIRLPOOL : 0);
2656 options |= (chkGOST->GetValue() ? 1 << MHASH_GOST : 0);
2657 options |= (chkSNEFRU128->GetValue() ? 1 << MHASH_SNEFRU128 : 0);
2658 options |= (chkSNEFRU256->GetValue() ? 1 << MHASH_SNEFRU256 : 0);
2659
2660 myConfigBase::Get()->Write( _T("SelectedChecksumFunctions"), options );
2661
2662 if(event.GetId() == wxID_CANCEL)
2663 EndModal(event.GetId());
2664
2665 else if(event.GetId() == btnCalculate->GetId()){
2666 wxString msg;
2667 FAL *F=NULL;
2668 if( chkFile->GetValue() )
2669 F=parent->GetActiveHexEditor()->myfile;
2670
2671 else if( filePick->GetPath() != wxEmptyString ){
2672 wxFileName fl( filePick->GetPath() );
2673 F= new FAL( fl );
2674 }
2675 std::cout << F->Length() << std::endl;
2676 if( F->Length() == 0 ){
2677 wxMessageBox(_("Cannot calculate checksum of an empty file."), _("Error"));
2678 return;
2679 }
2680
2681 msg = CalculateChecksum( *F, options );
2682 if(msg != wxEmptyString)
2683 msg = _("File: ") + F->GetFileName().GetFullPath() + wxNewline
2684 +(chkFile->GetValue() && F->IsChanged() ? _("Notice: Checksum includes non-saved changes.") + wxString(wxNewline) + wxNewline : wxNewline )
2685 + msg;
2686
2687 if(!chkFile->GetValue() && (F != NULL)){
2688 F->Close();
2689 delete F;
2690 }
2691
2692 if(wxTheClipboard->Open()) {
2693 // if (wxTheClipboard->IsSupported( wxDF_TEXT )){
2694 wxTheClipboard->Clear();
2695 wxTheClipboard->SetData( new wxTextDataObject( msg ));
2696 wxTheClipboard->Flush();
2697 wxTheClipboard->Close();
2698 // }
2699 }
2700
2701 //Not looks so good due variable size of the text.
2702 wxMessageBox( msg + wxNewline + _("Results copied to the clipboard."), _("Checksum Results"),wxOK|wxCENTRE );
2703
2704 }
2705
2706 else if(event.GetId() == chkFile->GetId() ){
2707 filePick->Enable( !event.IsChecked() );
2708 }
2709
2710 if( options == 0 || !((filePick->GetPath() != wxEmptyString) || chkFile->GetValue()) )
2711 btnCalculate->Enable(false);
2712 else
2713 btnCalculate->Enable(true);
2714 }
2715
OnFileChange(wxFileDirPickerEvent & event)2716 void ChecksumDialog::OnFileChange( wxFileDirPickerEvent& event ){
2717 wxCommandEvent e;
2718 EventHandler( e );
2719 }
2720
CalculateChecksum(FAL & f,int options)2721 wxString ChecksumDialog::CalculateChecksum(FAL& f, int options){
2722 f.Seek(0);
2723 wxString msg = _("Please wait while calculating checksum.");
2724 wxString emsg = wxT("\n");
2725 wxProgressDialog mypd(_("Calculating Checksum"), msg+emsg , 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_CAN_ABORT|wxPD_REMAINING_TIME);
2726 mypd.Show();
2727 //checksum_options_strings = { "MD5","SHA1","SHA256","SHA384","SHA512" };
2728
2729 unsigned NumBits=0;
2730 for( unsigned i = 0; i < 32 ; i ++ ){
2731 NumBits += (options>>i)&0x1;
2732 }
2733 MHASH *myhash=new MHASH[NumBits];
2734 unsigned i=0;
2735
2736 hashid algs[]={MHASH_MD2,MHASH_MD4,MHASH_MD5,
2737 MHASH_SHA1,MHASH_SHA224,MHASH_SHA256,MHASH_SHA384,MHASH_SHA512,
2738 MHASH_RIPEMD128,MHASH_RIPEMD160,MHASH_RIPEMD256,MHASH_RIPEMD320,
2739 MHASH_HAVAL128,MHASH_HAVAL160,MHASH_HAVAL192,MHASH_HAVAL224,MHASH_HAVAL256,
2740 MHASH_TIGER128,MHASH_TIGER160,MHASH_TIGER192,
2741 MHASH_ADLER32,MHASH_CRC32,MHASH_CRC32B,MHASH_WHIRLPOOL,MHASH_GOST,MHASH_SNEFRU128,MHASH_SNEFRU256};
2742 for( unsigned j = 0 ; j < sizeof algs/sizeof algs[0]; j++)
2743 if( options & (1 << algs[j] ))
2744 myhash[i++]= mhash_init(algs[j]);
2745
2746 int rdBlockSz=1024*1024;
2747 unsigned char *buffer = new unsigned char[rdBlockSz];
2748 unsigned char *buffer_prefetch = new unsigned char[rdBlockSz];
2749 int readed=rdBlockSz;
2750 int readed_prefetch=0;
2751
2752 uint64_t readfrom=0,read_speed=0, range=f.Length();
2753 time_t ts,te;
2754 time (&ts);
2755
2756 do{
2757 if(readed_prefetch>0){//PreLoad file, +%50 speed on SSD buffers.
2758 readed=readed_prefetch;
2759 std::swap(buffer, buffer_prefetch);
2760 }
2761 else{
2762 readed=f.Read( buffer, rdBlockSz );
2763 }
2764
2765 readfrom+=readed;
2766 read_speed+=readed;
2767
2768 //Paralelize with OpenMP
2769 #pragma omp parallel shared(myhash) private(i)
2770 {
2771 //Use OpenMP for hash many cores at once.
2772 #pragma omp for schedule(dynamic) nowait
2773 for( unsigned i = 0 ; i < NumBits ; i++){
2774 mhash( myhash[i], buffer, readed);
2775 }
2776
2777 //this preloads next data to swap buffer
2778 #pragma omp single
2779 {readed_prefetch=f.Read( buffer_prefetch, rdBlockSz );}
2780
2781 }
2782
2783 time(&te);
2784 if(ts != te ){
2785 ts=te;
2786 emsg = msg + wxT("\n") + _("Hash Speed : ") + wxString::Format( wxT("%.2f "), 1.0*read_speed/MB) + _("MB/s");
2787 read_speed=0;
2788 }
2789 if(!mypd.Update((readfrom*1000)/range, emsg )){
2790 delete [] buffer;
2791 delete [] buffer_prefetch;
2792 return wxEmptyString;
2793 }
2794 }while(readed == rdBlockSz);
2795
2796 delete [] buffer;
2797 delete [] buffer_prefetch;
2798 wxString results;
2799 i=0;
2800
2801 unsigned char *hash;
2802 wxString AlgName;
2803 unsigned MaxAlgoName=0;
2804 for(unsigned i = 0 ; i < NumBits ; i++)
2805 MaxAlgoName = wxMax( MaxAlgoName, wxString::FromAscii( reinterpret_cast<const char*>(mhash_get_hash_name_static( mhash_get_mhash_algo(myhash[i]) ))).Len() );
2806
2807 for(unsigned i = 0 ; i < NumBits ; i++){
2808 AlgName = wxString::FromAscii( reinterpret_cast<const char*>(mhash_get_hash_name_static( mhash_get_mhash_algo(myhash[i]) )));
2809 results << AlgName;
2810 results << wxT(":");
2811
2812 //Instead of tab char, we got better formatter loop here
2813 for( unsigned j = 0 ; j < MaxAlgoName +1 - AlgName.Len(); j++ )
2814 results << wxT(" ");
2815
2816 hash = static_cast<unsigned char *>( mhash_end(myhash[i]) );
2817 unsigned hashblocksize=mhash_get_block_size( mhash_get_mhash_algo(myhash[i]));
2818 for (unsigned k = 0; k < hashblocksize ; k++)
2819 results << wxString::Format( wxT("%.2x"), hash[k]);
2820
2821 results << wxNewline;
2822 }
2823 delete [] myhash;
2824 return results;// checksum_options_strings = { "MD5","SHA1","SHA256","SHA384","SHA512" };
2825 }
2826
2827
XORViewDialog(wxWindow * parent,wxMemoryBuffer * XORKey_)2828 XORViewDialog::XORViewDialog( wxWindow* parent, wxMemoryBuffer *XORKey_ ):XORViewDialogGui(parent, wxID_ANY){
2829 XORKey=XORKey_;
2830 XORtext->SetFocus();
2831 }
2832
EventHandler(wxCommandEvent & event)2833 void XORViewDialog::EventHandler( wxCommandEvent& event ){
2834 if( event.GetId() == wxID_CANCEL ){
2835 EndModal( wxID_CANCEL );
2836 }
2837 else if( event.GetId() == wxID_OK){
2838 if( XORtext->GetValue()==wxEmptyString ){
2839 wxBell();
2840 return;
2841 }
2842 if( radioHex->GetValue() ){
2843 wxString hexval = XORtext->GetValue();
2844 if(!HexVerifyAndPrepare( hexval, wxT("XOR"), this ) )
2845 return;
2846 wxMemoryBuffer z = wxHexCtrl::HexToBin( hexval );
2847 XORKey->AppendData( z.GetData(), z.GetDataLen() );
2848 EndModal( wxID_OK );
2849 }
2850 else{
2851 XORKey->AppendData( XORtext->GetValue().ToAscii(), XORtext->GetValue().Len() );
2852 EndModal( wxID_OK );
2853 }
2854 }
2855 else if( event.GetId() == XORtext->GetId())
2856 XORtext->SetFocus();
2857 event.Skip();
2858 }
2859
PreferencesDialog(wxWindow * parent)2860 PreferencesDialog::PreferencesDialog( wxWindow* parent ):PreferencesDialogGui(parent, wxID_ANY){
2861 GetInstalledLanguages( LangNames, LangIds );
2862
2863 chkPortable->Hide(); //Not yet ready.
2864
2865 chcLang->Clear();
2866 LangNames.Sort();
2867 chcLang->Append( LangNames );
2868 wxConfigBase *pConfig = myConfigBase::Get();
2869
2870 if ( ! pConfig->Read(_T("Language")).IsEmpty() ){
2871 wxString lang = pConfig->Read(_T("Language"), wxEmptyString) ;
2872 if ( !lang.IsEmpty() )
2873 for( unsigned i = 0 ; i < LangNames.Count() ; i++)
2874 if( lang == LangNames.Item(i)){
2875 chcLang->SetSelection(i);
2876 break;
2877 }
2878 }
2879 else
2880 chcLang->SetSelection(0);
2881
2882 wxString TempString;
2883 bool TempBool;
2884 if( myConfigBase::Get()->Read( _T("ColourHexForeground"), &TempString) ) clrPickerForeground->SetColour( TempString );
2885 if( myConfigBase::Get()->Read( _T("ColourHexBackground"), &TempString) ) clrPickerBackground->SetColour( TempString );
2886 if( myConfigBase::Get()->Read( _T("ColourHexBackgroundZebra"), &TempString) ) clrPickerBackgroundZebra->SetColour( TempString );
2887 if( myConfigBase::Get()->Read( _T("ColourHexSelectionForeground"), &TempString) ) clrPickerSelectionForeground->SetColour(TempString);
2888 if( myConfigBase::Get()->Read( _T("ColourHexSelectionBackground"), &TempString) ) clrPickerSelectionBackground->SetColour(TempString);
2889 if( myConfigBase::Get()->Read( _T("AutoShowTagPanel"), &TempBool ) ) chkAutoShowTagPanel->SetValue( TempBool );
2890 if( myConfigBase::Get()->Read( _T("UseCustomHexFormat"), &TempBool ) ) chkCustom->SetValue( TempBool );
2891 if( myConfigBase::Get()->Read( _T("CustomHexFormat"), &TempString ) ) comboCustomHexFormat->SetValue( TempString );
2892 comboCustomHexFormat->Enable( chkCustom->IsChecked() );
2893 if( myConfigBase::Get()->Read( _T("useBytesPerLineLimit"), &TempBool ) ) chkBytePerLineLimit->SetValue( TempBool );
2894 spinBytePerLine->Enable( chkBytePerLineLimit->IsChecked() );
2895
2896 int TempInt;
2897 myConfigBase::Get()->Read( _T("BytesPerLineLimit"), &TempInt, 16);
2898 spinBytePerLine->SetValue( TempInt );
2899
2900 myConfigBase::Get()->Read( _T("FontSize"), &TempInt, 10 );
2901 spinFontSize->SetValue( TempInt );
2902
2903 if( AvailableEncodings.IsEmpty() )
2904 AvailableEncodings=GetSupportedEncodings();
2905
2906 chcCharacterEncodingFamily->Clear();
2907 chcCharacterEncoding->Clear();
2908
2909 wxArrayString ChrEncFamArray;
2910 ChrEncFamArray.Add(wxT("Code for Information Interchange"));
2911 ChrEncFamArray.Add(wxT("DOS"));
2912 ChrEncFamArray.Add(wxT("ISO/IEC"));
2913 ChrEncFamArray.Add(wxT("KOI"));
2914 ChrEncFamArray.Add(wxT("Macintosh"));
2915 ChrEncFamArray.Add(wxT("Industrial Standard"));
2916 ChrEncFamArray.Add(wxT("Extended Binary Coded Decimal Interchange Code"));
2917 ChrEncFamArray.Add(wxT("Windows"));
2918 ChrEncFamArray.Add(wxT("UTF"));
2919 ChrEncFamArray.Sort();
2920 ChrEncFamArray.Add(wxT("Experimental"));
2921 ChrEncFamArray.Add(wxT("Other"));
2922 chcCharacterEncodingFamily->Append(ChrEncFamArray);
2923
2924 myConfigBase::Get()->Read( _T("CharacterEncodingFamily"), &TempString, wxT("DOS") );
2925 chcCharacterEncodingFamily->SetStringSelection( TempString );
2926
2927 ExperimentalEncodingsList.Clear();
2928 for(unsigned i=0; i< AvailableEncodings.Count(); i++){
2929 if(( AvailableEncodings.Item(i).Find( wxT("Industrial Standard") ) != wxNOT_FOUND ) ||
2930 ( AvailableEncodings.Item(i).Find( wxT("Arabic") ) != wxNOT_FOUND ) ||
2931 ( AvailableEncodings.Item(i).Find( wxT("Hebrew") ) != wxNOT_FOUND ) ||
2932 ( AvailableEncodings.Item(i).Find( wxT("ISCII") ) != wxNOT_FOUND ) ||
2933 ( AvailableEncodings.Item(i).Find( wxT("TSCII") ) != wxNOT_FOUND ) ||
2934 ( AvailableEncodings.Item(i).Find( wxT("ANSEL") ) != wxNOT_FOUND ) ||
2935 ( AvailableEncodings.Item(i).Find( wxT("AtariST") ) != wxNOT_FOUND ) ||
2936 ( AvailableEncodings.Item(i).Find( wxT("EUC") ) != wxNOT_FOUND ) ||
2937 ( AvailableEncodings.Item(i).Find( wxT("Big5") ) != wxNOT_FOUND ) ||
2938 ( AvailableEncodings.Item(i).Find( wxT("JIS") ) != wxNOT_FOUND ) ||
2939 ( AvailableEncodings.Item(i).Find( wxT("GBK") ) != wxNOT_FOUND ) ||
2940 ( AvailableEncodings.Item(i).Find( wxT("Thai") ) != wxNOT_FOUND ) ||
2941 ( AvailableEncodings.Item(i).Find( wxT("Iran") ) != wxNOT_FOUND )
2942 )
2943 ExperimentalEncodingsList.Add( AvailableEncodings.Item(i) );
2944 }
2945
2946 wxCommandEvent e;
2947 e.SetString( TempString );
2948 e.SetId( chcCharacterEncodingFamily->GetId() );
2949 EventHandler( e );
2950
2951 myConfigBase::Get()->Read( _T("CharacterEncoding"), &TempString, wxT("OEM - IBM PC/DOS CP437 - MS-DOS Latin US" ));
2952 if(TempString==wxT("Extended Binary Coded Decimal Interchange Code"))
2953 TempString=wxT("EBCDIC");
2954 if( !chcCharacterEncoding->SetStringSelection( TempString ) )
2955 chcCharacterEncoding->SetSelection( 0 );
2956 }
2957
GetInstalledLanguages(wxArrayString & names,wxArrayLong & identifiers)2958 void PreferencesDialog::GetInstalledLanguages(wxArrayString & names, wxArrayLong & identifiers) {
2959 names.Clear();
2960 identifiers.Clear();
2961 const wxLanguageInfo * langinfo;
2962 wxString name = wxLocale::GetLanguageName(wxLANGUAGE_DEFAULT);
2963 if(!name.IsEmpty()) {
2964 names.Add(_T("Default"));
2965 identifiers.Add(wxLANGUAGE_DEFAULT);
2966 }
2967
2968 names.Add(_T("English"));
2969 identifiers.Add(wxLANGUAGE_ENGLISH);
2970
2971 wxString dirname;
2972 wxFileName flnm( wxGetApp().argv[0] );
2973 //This part scans default installation on linux directory for available catalogs - both on main and on local share
2974 for( int i = 0 ; i < 2 ; i++ ) {
2975 if( i == 0 )
2976 dirname = (_T("/usr/local/share/locale"));
2977 else dirname = (_T("/usr/share/locale"));
2978 if(wxDir::Exists( dirname )) {
2979 wxDir dir(dirname);
2980 for(bool cont = dir.GetFirst(&dirname,_T(""),wxDIR_DEFAULT);
2981 cont;
2982 cont = dir.GetNext(&dirname)) {
2983 langinfo = wxLocale::FindLanguageInfo(dirname);
2984 if(langinfo != NULL) {
2985 if(wxFileExists(
2986 dir.GetName() + wxFileName::GetPathSeparator() +
2987 dirname + wxFileName::GetPathSeparator() +
2988 _T("LC_MESSAGES") + wxFileName::GetPathSeparator() +
2989 _T("wxHexEditor") + _T(".mo"))) {
2990
2991 bool duplicate = false;
2992 for( unsigned i = 0 ; i < identifiers.Count() ; i++ ) //Avoid duplicated locales
2993 if( identifiers.Item(i) == langinfo->Language ) {
2994 duplicate = true;
2995 break;
2996 }
2997 if ( duplicate ) break;
2998
2999 names.Add(langinfo->Description);
3000 identifiers.Add(langinfo->Language);
3001 }
3002 }
3003 }
3004 }
3005 }
3006
3007 //This part scans for for available catalogs on local directory, for Windows and Linux.
3008 dirname = (flnm.GetPath() + wxFileName::GetPathSeparator() + _T("locale"));
3009 if(wxDir::Exists( dirname )) {
3010 wxDir dir(dirname);
3011 for(bool cont = dir.GetFirst(&dirname,_T(""),wxDIR_DEFAULT);
3012 cont;
3013 cont = dir.GetNext(&dirname)) {
3014 langinfo = wxLocale::FindLanguageInfo(dirname);
3015 if(langinfo != NULL) {
3016 if(wxFileExists(
3017 dir.GetName() + wxFileName::GetPathSeparator() +
3018 dirname + wxFileName::GetPathSeparator() +
3019 _T("wxHexEditor") + _T(".mo"))) {
3020
3021 bool duplicate = false;
3022 for( unsigned i = 0 ; i < identifiers.Count() ; i++ ) //Avoid duplicated locales
3023 if( identifiers.Item(i) == langinfo->Language ) {
3024 duplicate = true;
3025 break;
3026 }
3027 if ( duplicate ) break;
3028
3029 names.Add(langinfo->Description);
3030 identifiers.Add(langinfo->Language);
3031 }
3032 }
3033 }
3034 }
3035
3036 #ifdef __WXMAC__
3037 //This part scans for for available catalogs on Bundle directory,for Mac.
3038 dirname = (flnm.GetPath() + wxFileName::GetPathSeparator() +
3039 _T("..") + wxFileName::GetPathSeparator() +
3040 _T("Resources") + wxFileName::GetPathSeparator() +
3041 _T("locale"));
3042
3043 if(wxDir::Exists( dirname )) {
3044 wxDir dir(dirname);
3045 for(bool cont = dir.GetFirst(&dirname,_T(""),wxDIR_DEFAULT);
3046 cont;
3047 cont = dir.GetNext(&dirname)) {
3048 langinfo = wxLocale::FindLanguageInfo(dirname);
3049 if(langinfo != NULL) {
3050 if(wxFileExists(
3051 dir.GetName() + wxFileName::GetPathSeparator() +
3052 dirname + wxFileName::GetPathSeparator() +
3053 _T("wxHexEditor") + _T(".mo"))) {
3054
3055 bool duplicate = false;
3056 for( unsigned i = 0 ; i < identifiers.Count() ; i++ ) //Avoid duplicated locales
3057 if( identifiers.Item(i) == langinfo->Language ) {
3058 duplicate = true;
3059 break;
3060 }
3061 if ( duplicate ) break;
3062
3063 names.Add(langinfo->Description);
3064 identifiers.Add(langinfo->Language);
3065 }
3066 }
3067 }
3068 }
3069 #endif //__WXMAC__
3070 }
3071
3072 //Could use EventHandler directly but that breaks GCC4.4 :p
SpinEventHandler(wxSpinEvent & event)3073 void PreferencesDialog::SpinEventHandler( wxSpinEvent& event ) {
3074 myConfigBase::Get()->Write( _T("FontSize"), spinFontSize->GetValue() );
3075 myConfigBase::Get()->Flush();
3076 wxUpdateUIEvent eventx( RESET_STYLE_EVENT );
3077 wxPostEvent( GetParent(), eventx );
3078 }
3079
EventHandler(wxCommandEvent & event)3080 void PreferencesDialog::EventHandler( wxCommandEvent& event ) {
3081 wxString PrevSelection;
3082 myConfigBase::Get()->Read( _T("CharacterEncoding"), &PrevSelection );
3083
3084 if(event.GetId()==chcCharacterEncodingFamily->GetId()){
3085 wxArrayString Encodings;
3086 if( event.GetString()==wxT("Experimental") )
3087 Encodings=ExperimentalEncodingsList;
3088
3089 else if( event.GetString()==wxT("Other") ){
3090 Encodings=AvailableEncodings;
3091 for(unsigned i=0; i< ExperimentalEncodingsList.Count(); i++)
3092 Encodings.Remove(ExperimentalEncodingsList.Item(i));
3093
3094 wxArrayString families=chcCharacterEncodingFamily->GetStrings();
3095 for(unsigned f=0; f< families.Count(); f++)
3096 for(unsigned i=0; i< AvailableEncodings.Count(); i++){
3097 wxString family=families.Item(f);
3098 if(family==wxT("Extended Binary Coded Decimal Interchange Code"))
3099 family=wxT("EBCDIC");
3100 if( AvailableEncodings.Item(i).Find( family ) != wxNOT_FOUND )
3101 Encodings.Remove( AvailableEncodings.Item(i) );
3102 }
3103 }
3104 else
3105 for(unsigned i=0; i< AvailableEncodings.Count(); i++){
3106 wxString family=event.GetString();
3107 if(family==wxT("Extended Binary Coded Decimal Interchange Code"))
3108 family=wxT("EBCDIC");
3109 if(( AvailableEncodings.Item(i).Find( family ) != wxNOT_FOUND ) &&
3110 ( ExperimentalEncodingsList.Index( AvailableEncodings.Item(i) )==wxNOT_FOUND) )
3111 Encodings.Add( AvailableEncodings.Item(i) );
3112 }
3113
3114 Encodings.Sort();
3115 chcCharacterEncoding->Clear();
3116 chcCharacterEncoding->Append( Encodings );
3117 wxString Selection;
3118 myConfigBase::Get()->Read( _T("CharacterEncoding"), &Selection );
3119 if( !chcCharacterEncoding->SetStringSelection( Selection ) )
3120 chcCharacterEncoding->SetSelection( 0 );
3121 }
3122 /*
3123 if(event.GetId()==chcCharacterEncoding->GetId()){
3124 myConfigBase::Get()->Write( _T("CharacterEncoding"), chcCharacterEncoding->GetStringSelection() );
3125 myConfigBase::Get()->Flush();
3126 wxUpdateUIEvent eventx( REDRAW_EVENT );
3127 wxPostEvent( GetParent(), eventx );
3128 }
3129 */
3130 if(event.GetId() == chkCustom->GetId() )
3131 comboCustomHexFormat->Enable( event.IsChecked() );
3132 if(event.GetId() == chkBytePerLineLimit->GetId() )
3133 spinBytePerLine->Enable( event.IsChecked() );
3134
3135 //Redrawing because we need to re-interpret the readed bytes.
3136 //SaveRegistry();
3137 }
3138
SaveRegistry(void)3139 void PreferencesDialog::SaveRegistry( void ) {
3140 myConfigBase::Get()->Write( _T("Language"), wxLocale::FindLanguageInfo( chcLang->GetString( chcLang->GetSelection() ) )->Description ); //Saves string into configuration file.
3141
3142 myConfigBase::Get()->Write( _T("ColourHexForeground"), clrPickerForeground->GetColour().GetAsString(wxC2S_HTML_SYNTAX) );
3143 myConfigBase::Get()->Write( _T("ColourHexBackground"), clrPickerBackground->GetColour().GetAsString(wxC2S_HTML_SYNTAX) );
3144 myConfigBase::Get()->Write( _T("ColourHexBackgroundZebra"), clrPickerBackgroundZebra->GetColour().GetAsString(wxC2S_HTML_SYNTAX) );
3145 myConfigBase::Get()->Write( _T("ColourHexSelectionForeground"), clrPickerSelectionForeground->GetColour().GetAsString(wxC2S_HTML_SYNTAX) );
3146 myConfigBase::Get()->Write( _T("ColourHexSelectionBackground"), clrPickerSelectionBackground->GetColour().GetAsString(wxC2S_HTML_SYNTAX) );
3147
3148 myConfigBase::Get()->Write( _T("UseCustomHexFormat"), chkCustom->GetValue() );
3149 myConfigBase::Get()->Write( _T("CustomHexFormat"), comboCustomHexFormat->GetValue() );
3150
3151 myConfigBase::Get()->Write( _T("UseBytesPerLineLimit"), chkBytePerLineLimit->GetValue() );
3152 myConfigBase::Get()->Write( _T("BytesPerLineLimit"), spinBytePerLine->GetValue());
3153 myConfigBase::Get()->Write( _T("CharacterEncodingFamily"), chcCharacterEncodingFamily->GetStringSelection() );
3154 myConfigBase::Get()->Write( _T("CharacterEncoding"), chcCharacterEncoding->GetStringSelection() );
3155 myConfigBase::Get()->Write( _T("FontSize"), spinFontSize->GetValue() );
3156
3157 myConfigBase::Get()->Write( _T("AutoShowTagPanel"), chkAutoShowTagPanel->GetValue() );
3158
3159 myConfigBase::Get()->Flush();
3160
3161 wxUpdateUIEvent eventx( REDRAW_EVENT );
3162 wxPostEvent( GetParent(), eventx );
3163 }
OnSave(wxCommandEvent & event)3164 void PreferencesDialog::OnSave( wxCommandEvent& event ) {
3165 //myConfigBase::Get()->Write( _T("Language"), LangIds.Item(chcLang->GetSelection()) );
3166 //myConfigBase::Get()->Write( _T("Language"), wxLocale::FindLanguageInfo( chcLang->GetString( chcLang->GetSelection() ) )->Language );
3167 SaveRegistry();
3168 Close();
3169 }
3170
OnResetColours(wxCommandEvent & event)3171 void PreferencesDialog::OnResetColours( wxCommandEvent& event ) {
3172 if( wxOK == wxMessageBox( _("Are you sure about resetting colours?"), _("Resetting Hex Colours"), wxOK|wxCANCEL) ){
3173 myConfigBase::Get()->DeleteEntry(_T("ColourHexForeground"));
3174 myConfigBase::Get()->DeleteEntry(_T("ColourHexBackground"));
3175 myConfigBase::Get()->DeleteEntry(_T("ColourHexBackgroundZebra"));
3176 myConfigBase::Get()->DeleteEntry(_T("ColourHexSelectionForeground"));
3177 myConfigBase::Get()->DeleteEntry(_T("ColourHexSelectionBackground"));
3178 myConfigBase::Get()->Flush();
3179
3180 wxUpdateUIEvent eventx( RESET_STYLE_EVENT );
3181 wxPostEvent( GetParent(), eventx );
3182 Close();
3183 }
3184 }
3185
3186 extern wxArrayString GetDeviceList( bool=true );
3187
DeviceBackupDialog(wxWindow * parent)3188 DeviceBackupDialog::DeviceBackupDialog( wxWindow* parent ):DeviceBackupDialogGui(parent, wxID_ANY){
3189 wxArrayString disks = GetDeviceList();
3190 for( unsigned i =0 ; i < disks.Count() ; i++)
3191 disks[i]=disks.Item(i).AfterLast('/');
3192
3193 #ifdef __WXMSW__
3194 for( unsigned i=0 ; i < disks.Count() ; i++ )
3195 if(disks.Item(i).StartsWith(wxT("\\Device")))
3196 disks.RemoveAt(i);
3197 #endif
3198 chcPartition->Append( disks );
3199 }
3200
OnBackup(wxCommandEvent & event)3201 void DeviceBackupDialog::OnBackup( wxCommandEvent &event ){
3202 wxArrayString disks = GetDeviceList();
3203 //disks.Sort();
3204 wxFileName src(disks.Item( chcPartition->GetSelection() ) );
3205 wxFileName dst(filePickBackup->GetPath());
3206
3207 FAL src_fl(src);
3208
3209 wxFFile dst_fl(dst.GetFullPath(), wxT("wb"));
3210
3211 wxString msg = _("Please wait while backing up disk/partition image.");
3212 wxString emsg = wxT("\n");
3213 wxProgressDialog mypd(_("Disk/Partition Backup"), msg+emsg, 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_CAN_ABORT|wxPD_REMAINING_TIME);
3214 mypd.Show();
3215
3216 MHASH myhash = mhash_init( MHASH_MD5 );
3217
3218 enum { rdBlockSz=1024*1024 };
3219 unsigned char buff[rdBlockSz];
3220 int rd=rdBlockSz;
3221
3222 uint64_t readfrom=0,read_speed=0, range=src_fl.Length();
3223 time_t ts,te;
3224 time (&ts);
3225
3226 while(rd == rdBlockSz){
3227 rd=src_fl.Read(buff, rdBlockSz);
3228 read_speed+=rd;
3229 readfrom+=rd;
3230 if( static_cast<unsigned int>(rd) != dst_fl.Write( buff, rd ) ){
3231 wxMessageBox( _("Error on writing to backup image."), _("ERROR!") );
3232 return;
3233 }
3234 mhash( myhash, buff, rd);
3235
3236 time(&te);
3237 if(ts != te ){
3238 ts=te;
3239 emsg = msg + wxT("\n") + _("Backup Speed : ") + wxString::Format( wxT("%.2f "), 1.0*read_speed/MB) + _("MB/s");
3240 read_speed=0;
3241 }
3242
3243 if(!mypd.Update((readfrom*1000)/range, emsg )){
3244 src_fl.Close();
3245 dst_fl.Close();
3246 wxRemoveFile(dst.GetFullPath());
3247 return;
3248 }
3249 }
3250 src_fl.Close();
3251 dst_fl.Close();
3252
3253 wxString AlgName = wxString::FromAscii( reinterpret_cast<const char*>(mhash_get_hash_name_static( mhash_get_mhash_algo(myhash) )));
3254 wxFFile dst_hash(dst.GetFullPath()+wxT(".")+AlgName.Lower(), wxT("wb"));
3255
3256 unsigned char *hash;
3257 hash = static_cast<unsigned char *>( mhash_end(myhash) );
3258
3259 wxString result;
3260 for (unsigned k = 0; k < mhash_get_block_size( mhash_get_mhash_algo(myhash) ); k++)
3261 result << wxString::Format( wxT("%.2x"), hash[k]);
3262
3263 dst_hash.Write( result );
3264 dst_hash.Write( wxT(" ") );
3265 dst_hash.Write( dst.GetFullName() );
3266 dst_hash.Close();
3267
3268 wxMessageBox( _("Backup operation completed."), _("Operation Complete") );
3269 }
3270
DeviceRestoreDialog(wxWindow * parent)3271 DeviceRestoreDialog::DeviceRestoreDialog( wxWindow* parent ):DeviceRestoreDialogGui(parent, wxID_ANY){
3272 wxArrayString disks = GetDeviceList();
3273 for( unsigned i =0 ; i < disks.Count() ; i++)
3274 disks[i]=disks.Item(i).AfterLast('/');
3275 #ifdef __WXMSW__
3276 for( unsigned i=0 ; i < disks.Count() ; i++ )
3277 if(disks.Item(i).StartsWith(wxT("\\Device")))
3278 disks.RemoveAt(i);
3279 #endif
3280 chcPartition->Append( disks );
3281 }
3282
OnRestore(wxCommandEvent & event)3283 void DeviceRestoreDialog::OnRestore( wxCommandEvent &event ){
3284 wxArrayString disks = GetDeviceList();
3285 wxFileName dst(disks.Item( chcPartition->GetSelection() ) );
3286 wxFileName src(filePickBackup->GetPath());
3287
3288 wxFFile src_fl(src.GetFullPath(), wxT("rb"));
3289
3290 FAL dst_fl( dst, FAL::ReadWrite );
3291
3292 if( wxCANCEL == wxMessageBox( _("WARNING! THIS OPERATION WILL DESTROY EVERY INFORMATION AT :\n")+dst.GetFullPath()+wxT("\n")+_("ARE YOU SURE?"), _("WARNING!"), wxOK|wxCANCEL|wxCENTRE, this ))
3293 return;
3294
3295 if( src_fl.Length() > dst_fl.Length() ){
3296 wxMessageBox( _("ERROR!: Disk space is smaller than the image file."), _("ERROR!"), wxCANCEL|wxCENTRE, this );
3297 return;
3298 }
3299
3300 if( src_fl.Length() < dst_fl.Length() ){
3301 if( wxCANCEL==wxMessageBox( _("WARNING!: Disk space is bigger than the image file. \nRemaining space will remain untouched."), _("WARNING!"), wxOK|wxCANCEL|wxCENTRE, this ) )
3302 return;
3303 }
3304
3305 wxString msg = _("Please wait while restoring disk/partition.");
3306 wxString emsg = wxT("\n");
3307 wxProgressDialog mypd(_("Disk/Partition Restore"), msg+emsg , 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_CAN_ABORT|wxPD_REMAINING_TIME);
3308 mypd.Show();
3309
3310 enum { rdBlockSz=1024*1024 };
3311 unsigned char buff[rdBlockSz];
3312 int rd=rdBlockSz;
3313
3314 uint64_t readfrom=0,read_speed=0, range=src_fl.Length();
3315 time_t ts,te;
3316 time (&ts);
3317
3318
3319 while(rd == rdBlockSz){
3320 rd=src_fl.Read(buff, rdBlockSz);
3321 read_speed+=rd;
3322 readfrom+=rd;
3323
3324 dst_fl.BlockWrite( buff, rd );
3325
3326 time(&te);
3327 if(ts != te ){
3328 ts=te;
3329 emsg = msg + wxT("\n") + _("Restore Speed : ") + wxString::Format( wxT("%.2f "), 1.0*read_speed/MB) + _("MB/s");
3330 read_speed=0;
3331 }
3332 if(!mypd.Update((readfrom*1000)/range, emsg ))
3333 return;
3334 }
3335 src_fl.Close();
3336 dst_fl.Close();
3337 wxMessageBox( _("Restore operation completed."), _("Operation Complete") );
3338 }
3339
DeviceEraseDialog(wxWindow * parent)3340 DeviceEraseDialog::DeviceEraseDialog( wxWindow* parent ):DeviceEraseDialogGui(parent, wxID_ANY){
3341 wxArrayString disks = GetDeviceList();
3342 for( unsigned i =0 ; i < disks.Count() ; i++)
3343 disks[i]=disks.Item(i).AfterLast('/');
3344 chcPartition->Append( disks );
3345 }
3346
OnErase(wxCommandEvent & event)3347 void DeviceEraseDialog::OnErase( wxCommandEvent &event ){
3348 wxArrayString disks = GetDeviceList();
3349 wxFileName dst(disks.Item( chcPartition->GetSelection() ) );
3350 FAL dst_fl( dst, FAL::ReadWrite );
3351
3352 if( wxCANCEL == wxMessageBox( _("WARNING! THIS OPERATION WILL DESTROY EVERY INFORMATION AT :\n")+dst.GetFullPath()+wxT("\n")+_("ARE YOU SURE?"), _("WARNING!"), wxOK|wxCANCEL|wxCENTRE, this ))
3353 return;
3354
3355 wxString msg = _("Please wait while erasing disk/partition image.");
3356 wxString emsg = wxT("\n");
3357 wxProgressDialog mypd(_("Disk/Partition Erase"), msg+emsg , 1000, this, wxPD_APP_MODAL|wxPD_AUTO_HIDE|wxPD_CAN_ABORT|wxPD_REMAINING_TIME);
3358 mypd.Show();
3359
3360 enum { rdBlockSz=1024*1024 };
3361 unsigned char buff[rdBlockSz];
3362 int rd=rdBlockSz;
3363
3364 uint64_t readfrom=0,read_speed=0, range=dst_fl.Length();
3365 time_t ts,te;
3366 time (&ts);
3367
3368 int sel = radioErase->GetSelection();
3369 memset( buff, (sel == 0 ? 0x00 : 0xFF ), rdBlockSz);
3370
3371 srand((unsigned)time(0));
3372
3373 while(readfrom < range){
3374
3375 // TODO (death#1#): Speed up for random
3376 if( sel == 2 )
3377 for( unsigned i = 0 ; i < rdBlockSz ; i++ )
3378 buff[i]=rand()%0xFF;
3379
3380 if( readfrom+rd > range )
3381 rd = range-readfrom;
3382
3383 dst_fl.BlockWrite( buff, rd );
3384 read_speed+=rd;
3385 readfrom+=rd;
3386
3387 time(&te);
3388 if(ts != te ){
3389 ts=te;
3390 emsg = msg + wxT("\n") + _("Erase Speed : ") + wxString::Format( wxT("%.2f "), 1.0*read_speed/MB) + _("MB/s");
3391 read_speed=0;
3392 }
3393 if(!mypd.Update((readfrom*1000)/range, emsg ))
3394 return;
3395 }
3396
3397 wxMessageBox( _("Erase operation completed."), _("Operation Complete") );
3398
3399 }
3400
OSXMessageDialog(wxWindow * parent,wxString message,wxString Caption)3401 OSXMessageDialog::OSXMessageDialog( wxWindow* parent, wxString message, wxString Caption):OSXMessageDialogGui(parent, wxID_ANY){
3402 txtMessage->SetLabel( message );
3403 txtCaption->SetLabel( Caption );
3404 wxIcon wxHexEditor_ICON ( wxhex_xpm );
3405 icon_bitmap->SetIcon(wxHexEditor_ICON);
3406 this->Fit();
3407 this->Layout();
3408 }
3409
OSXwxMessageBox(wxString message,wxString Caption,int x,wxWindow * parent)3410 void OSXwxMessageBox( wxString message, wxString Caption, int x, wxWindow* parent ){
3411 #ifndef __WXMAC__
3412 wxMessageBox( message,Caption,x, parent );
3413 #else
3414 OSXMessageDialog osxmsg(parent, message, Caption );
3415 osxmsg.ShowModal();
3416 #endif
3417 }
3418