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("&nbsp;") );
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