1 // wxGUI.cpp
2
3 #include "StdAfx.h"
4
5 // For compilers that support precompilation, includes "wx/wx.h".
6 #include "wx/wxprec.h"
7
8 #ifdef __BORLANDC__
9 #pragma hdrstop
10 #endif
11
12 // for all others, include the necessary headers (this file is usually all you
13 // need because it includes almost all "standard" wxWidgets headers)
14 #ifndef WX_PRECOMP
15 #include "wx/wx.h"
16 #endif
17
18 #define static const
19 #include "../GUI/p7zip_32.xpm"
20 #undef static
21
22 #undef ACTIVATE_DIALOG_TESTS
23
24 int Main1(int argc,TCHAR **argv);
25
26 #include "Windows/Registry.h"
27 using namespace NWindows;
28 using namespace NRegistry;
29
30
31 #include "Common/StringConvert.h"
32 #include "Windows/FileDir.h"
33 #include "Windows/Synchronization.h"
34
35 #include "ExtractRes.h"
36 #include "../Explorer/MyMessages.h"
37
38 #include "ExtractGUI.h"
39 #include "UpdateGUI.h"
40 #include "BenchmarkDialog.h"
41 #include "../FileManager/RegistryUtils.h"
42
43 using namespace NWindows;
44 using namespace NFile;
45
46 #include "../FileManager/ProgramLocation.h"
47
48 static LPCWSTR kHelpFileName = L"help/";
49
ShowHelpWindow(HWND hwnd,LPCWSTR topicFile)50 void ShowHelpWindow(HWND hwnd, LPCWSTR topicFile)
51 {
52 UString path;
53 if (!::GetProgramFolderPath(path))
54 return;
55 path += kHelpFileName;
56 path += topicFile;
57 printf("ShowHelpWindow(%p,%ls)=>%ls\n",hwnd,topicFile,(const wchar_t *)path);
58 // HtmlHelp(hwnd, GetSystemString(path), HH_DISPLAY_TOPIC, NULL);
59 wxString path2(path);
60 wxLaunchDefaultBrowser(path2);
61 }
62
63 ////////////////////////////// TRIES ///////////////////////////////////
64
65 #ifdef ACTIVATE_DIALOG_TESTS
ErrorMessage(const wchar_t * message)66 static void ErrorMessage(const wchar_t *message)
67 {
68 MessageBox(0,message, wxT("7-Zip GUI"),wxICON_ERROR);
69 }
70
71 #include "../FileManager/PasswordDialog.h"
72 #include "../FileManager/MessagesDialog.h"
73 #include "../FileManager/OverwriteDialog.h"
74 #include "Windows/Thread.h"
75
myErrorMsg(const wchar_t * message)76 void myErrorMsg(const wchar_t *message)
77 {
78 MessageBox(0,message, wxT("Message"),wxICON_ERROR);
79 }
80
testCMessagesDialog()81 void testCMessagesDialog()
82 {
83 UStringVector Messages;
84
85 Messages.Add(L"message 1");
86 Messages.Add(L"message 2");
87 Messages.Add(L"message 3");
88 Messages.Add(L"message 4");
89 Messages.Add(L"message 5");
90 Messages.Add(L"message 6");
91 Messages.Add(L"message 7");
92 Messages.Add(L"message 8");
93 Messages.Add(L"message 9");
94
95 CMessagesDialog messagesDialog;
96 messagesDialog.Messages = &Messages;
97 int ret = messagesDialog.Create( 0 ); // ParentWindow
98
99 if (ret == IDOK) myErrorMsg(wxT("CMessagesDialog => IDOK"));
100 else if (ret == IDCANCEL) myErrorMsg(wxT("CMessagesDialog => IDCANCEL"));
101 else myErrorMsg(wxT("CMessagesDialog => ?"));
102
103 }
104
testCOverwriteDialog()105 void testCOverwriteDialog()
106 {
107 SYSTEMTIME systemTime;
108 GetSystemTime( &systemTime );
109
110
111 const wchar_t *existName = L"existName";
112 FILETIME data_existTime;
113 FILETIME *existTime = &data_existTime ;
114 UInt64 data_existSize = 1234;
115 UInt64 *existSize = &data_existSize;
116 const wchar_t *newName = L"newName";
117 FILETIME data_newTime;
118 FILETIME *newTime = &data_newTime;
119 UInt64 data_newSize = 45678;
120 UInt64 *newSize = &data_newSize;
121 Int32 data_answer=0;
122 Int32 *answer = &data_answer;
123
124 SystemTimeToFileTime( &systemTime , &data_existTime);
125 SystemTimeToFileTime( &systemTime , &data_newTime);
126
127 COverwriteDialog dialog;
128
129 dialog.OldFileInfo.Time = *existTime;
130 dialog.OldFileInfo.TimeIsDefined = true; // FIXME : look again at the sample !
131
132 dialog.OldFileInfo.SizeIsDefined = (existSize != NULL);
133 if (dialog.OldFileInfo.SizeIsDefined)
134 dialog.OldFileInfo.Size = *existSize;
135 dialog.OldFileInfo.Name = existName;
136
137 if (newTime == 0)
138 dialog.NewFileInfo.TimeIsDefined = false;
139 else
140 {
141 dialog.NewFileInfo.TimeIsDefined = true;
142 dialog.NewFileInfo.Time = *newTime;
143 }
144
145 dialog.NewFileInfo.SizeIsDefined = (newSize != NULL);
146 if (dialog.NewFileInfo.SizeIsDefined)
147 dialog.NewFileInfo.Size = *newSize;
148 dialog.NewFileInfo.Name = newName;
149
150 /*
151 NOverwriteDialog::NResult::EEnum writeAnswer =
152 NOverwriteDialog::Execute(oldFileInfo, newFileInfo);
153 */
154 INT_PTR writeAnswer = dialog.Create(NULL); // ParentWindow doesn't work with 7z
155
156 switch(writeAnswer)
157 {
158 case IDCANCEL: myErrorMsg(wxT("COverwriteDialog => IDCANCEL")); break;
159 case IDNO: myErrorMsg(wxT("COverwriteDialog => IDNO")); break;
160 case IDC_BUTTON_OVERWRITE_NO_TO_ALL: myErrorMsg(wxT("COverwriteDialog => IDC_BUTTON_OVERWRITE_NO_TO_ALL")); break;
161 case IDC_BUTTON_OVERWRITE_YES_TO_ALL:myErrorMsg(wxT("COverwriteDialog => IDC_BUTTON_OVERWRITE_YES_TO_ALL")); break;
162 case IDC_BUTTON_OVERWRITE_AUTO_RENAME:myErrorMsg(wxT("COverwriteDialog => IDC_BUTTON_OVERWRITE_AUTO_RENAME")); break;
163 case IDYES: myErrorMsg(wxT("COverwriteDialog => IDYES")); break;
164 default: myErrorMsg(wxT("COverwriteDialog => default")); break;
165 }
166 }
167
testCPasswordDialog()168 void testCPasswordDialog()
169 {
170 CPasswordDialog dialog;
171
172 int ret = dialog.Create(0);
173 if (ret == IDOK) {
174 UString Password = dialog.Password;
175 UString msg = wxT("CPasswordDialog => IDOK password=\"");
176 msg += Password;
177 msg += wxT("\"");
178 myErrorMsg(msg);
179 }
180 else if (ret == IDCANCEL) myErrorMsg(wxT("CPasswordDialog => IDCANCEL"));
181 else myErrorMsg(wxT("CPasswordDialog => ?"));
182
183 }
184
185 struct CThreadProgressDialog
186 {
187 CProgressDialog * ProgressDialog;
MyThreadFunctionCThreadProgressDialog188 static THREAD_FUNC_DECL MyThreadFunction(void *param)
189 {
190 ((CThreadProgressDialog *)param)->Result = ((CThreadProgressDialog *)param)->Process();
191 return 0;
192 }
193 HRESULT Result;
ProcessCThreadProgressDialog194 HRESULT Process()
195 {
196 Sleep(1000);
197 int total = 1000;
198
199 ProgressDialog->ProgressSynch.SetTitleFileName(L"SetTitleFileName");
200 ProgressDialog->ProgressSynch.SetNumFilesTotal(100);
201 ProgressDialog->ProgressSynch.SetNumFilesCur(1);
202 ProgressDialog->ProgressSynch.SetProgress(total, 0);
203 // ProgressDialog.ProgressSynch.SetRatioInfo(inSize, outSize);
204 // ProgressDialog.ProgressSynch.SetCurrentFileName(name);
205
206 ProgressDialog->ProgressSynch.SetPos(total/10);
207 ProgressDialog->ProgressSynch.SetCurrentFileName(L"File1");
208 Sleep(1000);
209 ProgressDialog->ProgressSynch.SetPos(total/2);
210 ProgressDialog->ProgressSynch.SetCurrentFileName(L"File2");
211 Sleep(1000);
212 ProgressDialog->ProgressSynch.SetPos(total);
213 ProgressDialog->ProgressSynch.SetCurrentFileName(L"File3");
214 Sleep(1000);
215 ProgressDialog->MyClose();
216 return 0;
217 }
218 };
219
testCProgressDialog()220 void testCProgressDialog()
221 {
222 CProgressDialog ProgressDialog;
223
224 CThreadProgressDialog benchmarker;
225 benchmarker.ProgressDialog = &ProgressDialog;
226 NWindows::CThread thread;
227 thread.Create(CThreadProgressDialog::MyThreadFunction, &benchmarker);
228
229 // void StartProgressDialog(const UString &title)
230 int ret = ProgressDialog.Create(L"testCProgressDialog", 0);
231
232 if (ret == IDOK) myErrorMsg(wxT("CProgressDialog => IDOK"));
233 else if (ret == IDCANCEL) myErrorMsg(wxT("CProgressDialog => IDCANCEL"));
234 else myErrorMsg(wxT("CProgressDialog => ?"));
235
236 }
237
testDialog(int num)238 void testDialog(int num)
239 {
240 NWindows::NControl::CModalDialog dialog;
241
242 printf("Generic Dialog(%d)\n",num);
243 int ret = dialog.Create(num, 0);
244 if (ret == IDOK) myErrorMsg(wxT("Generic Dialog => IDOK"));
245 else if (ret == IDCANCEL) myErrorMsg(wxT("Generic Dialog => IDCANCEL"));
246 else myErrorMsg(wxT("Generic Dialog => ?"));
247 }
248
testMessageBox()249 void testMessageBox()
250 {
251 int ret = MessageBoxW(0, L"test yes/no/cancel",
252 L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION | MB_TASKMODAL);
253 if (ret == IDYES) myErrorMsg(wxT("MessageBoxW => IDYES"));
254 else if (ret == IDNO) myErrorMsg(wxT("MessageBoxW => IDNO"));
255 else if (ret == IDCANCEL) myErrorMsg(wxT("MessageBoxW => IDCANCEL"));
256 else myErrorMsg(wxT("MessageBoxW => ?"));
257 }
258
testRegistry()259 static void testRegistry()
260 {
261 SaveRegLang(L"fr");
262
263 UString langFile;
264 ReadRegLang(langFile);
265
266 printf("testRegistry : -%ls-\n",(const wchar_t *)langFile);
267 }
268
269
270 int Main2(int argc,TCHAR **argv);
271
Main3(int argc,wxChar ** argv)272 int Main3(int argc,wxChar **argv)
273 {
274 testRegistry();
275
276 int num = -1;
277
278 if (argc >=2 )
279 {
280 num = argv[1][0] - L'0';
281 }
282 printf("num=%d\n",num);
283
284
285 switch(num)
286 {
287 case 0:
288 {
289 TCHAR **argv2 = (TCHAR **)calloc(argc,sizeof(*argv));
290
291 argv2[0] = argv[0];
292 for(int i = 2; i < argc; i++) argv2[i-1] = argv[i];
293
294 return Main2(argc-1,argv2);
295 }
296 // TODO Benchmark
297 // TODO CCompressDialog
298 // TODO CExtractDialog ?
299 case 1 : testCMessagesDialog(); break;
300 case 2 : testCOverwriteDialog(); break;
301 case 3 : testCPasswordDialog(); break;
302 case 4 : testCProgressDialog(); break;
303 case 5 : testMessageBox(); break;
304 case 9 :
305 if (argc >= 3)
306 {
307 AString str = GetAnsiString(argv[2]);
308 int num = atoi((const char*)str);
309 testDialog(num);
310 }
311 else
312 {
313 printf("usage : 7zG 9 <windowID>\n");
314 }
315 break;
316 default :
317 printf("usage : 7zG number\n");
318
319 };
320
321 return 0;
322 }
323
324 #endif // ACTIVATE_DIALOG_TESTS
325
326 static const TCHAR *kCUBasePath = TEXT("Software/7-ZIP");
327 static const WCHAR *kLangValueName = L"Lang";
328
SaveRegLang(const UString & langFile)329 void SaveRegLang(const UString &langFile)
330 {
331 CKey key;
332 key.Create(HKEY_CURRENT_USER, kCUBasePath);
333 key.SetValue(kLangValueName, langFile);
334 }
335
ReadRegLang(UString & langFile)336 void ReadRegLang(UString &langFile)
337 {
338 langFile.Empty();
339 CKey key;
340 if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)
341 key.QueryValue(kLangValueName, langFile);
342 }
343
344
345 //////////////////////////////////
346
347 #define NEED_NAME_WINDOWS_TO_UNIX
348 #include "myPrivate.h" // global_use_utf16_conversion
349
mySplitCommandLineW(int numArguments,TCHAR ** arguments,UStringVector & parts)350 void mySplitCommandLineW(int numArguments, TCHAR **arguments,UStringVector &parts) {
351
352 parts.Clear();
353 for(int ind=0;ind < numArguments; ind++) {
354 UString tmp = arguments[ind];
355 // tmp.Trim(); " " is a valid filename ...
356 if (!tmp.IsEmpty()) {
357 parts.Add(tmp);
358 // DEBUG printf("ARG %d : '%ls'\n",ind,(const wchar_t *)tmp);
359 }
360 }
361 }
362
363 // ----------------------------------------------------------------------------
364 // private classes
365 // ----------------------------------------------------------------------------
366
367 // Define a new frame type
368 class MyFrame: public wxFrame
369 {
370 public:
371 // ctor
372 MyFrame(wxFrame *frame, const wxString& title, int x, int y, int w, int h);
373 // virtual ~MyFrame();
374
375 // operations
WriteText(const wxString & text)376 void WriteText(const wxString& text) { m_txtctrl->WriteText(text); }
377
378 protected:
379 // callbacks
380 void OnWorkerEvent(wxCommandEvent& event);
381 private:
382 // just some place to put our messages in
383 wxTextCtrl *m_txtctrl;
384 DECLARE_EVENT_TABLE()
385 };
386
387 enum {
388 WORKER_EVENT=100 // this one gets sent from the worker thread
389 };
390
BEGIN_EVENT_TABLE(MyFrame,wxFrame)391 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
392 EVT_MENU(WORKER_EVENT, MyFrame::OnWorkerEvent)
393 // EVT_IDLE(MyFrame::OnIdle)
394 END_EVENT_TABLE()
395
396 // My frame constructor
397 MyFrame::MyFrame(wxFrame *frame, const wxString& title,
398 int x, int y, int w, int h)
399 : wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
400 {
401 this->SetIcon(wxICON(p7zip_32));
402
403 #if wxUSE_STATUSBAR
404 CreateStatusBar(2);
405 #endif // wxUSE_STATUSBAR
406
407 m_txtctrl = new wxTextCtrl(this, wxID_ANY, _T(""), wxPoint(0, 0), wxSize(0, 0), wxTE_MULTILINE | wxTE_READONLY);
408 }
409
410 void myCreateHandle(int n);
411 wxWindow * g_window=0;
412
OnWorkerEvent(wxCommandEvent & event)413 void MyFrame::OnWorkerEvent(wxCommandEvent& event)
414 {
415 int n = event.GetInt();
416 myCreateHandle(n);
417 }
418
419
420 // Define a new application type, each program should derive a class from wxApp
421 class MyApp : public wxApp
422 {
423 public:
424 // override base class virtuals
425 // ----------------------------
426
427 // this one is called on application startup and is a good place for the app
428 // initialization (doing it here and not in the ctor allows to have an error
429 // return: if OnInit() returns false, the application terminates)
430 virtual bool OnInit();
431 };
432
433 // Create a new application object: this macro will allow wxWidgets to create
434 // the application object during program execution (it's better than using a
435 // static object for many reasons) and also implements the accessor function
436 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
437 // not wxApp)
438 IMPLEMENT_APP(MyApp)
439
440 time_t g_T0 = 0;
441 class MyThread : public wxThread
442 {
443 int _argc;
444 TCHAR **_argv;
445 public:
MyThread(int argc,TCHAR ** argv)446 MyThread(int argc,TCHAR **argv): wxThread(),_argc(argc), _argv(argv) {}
447
448 // thread execution starts here
Entry()449 virtual void *Entry()
450 {
451 #ifdef ACTIVATE_DIALOG_TESTS
452 int ret = Main3(_argc,_argv);
453 #else
454 int ret = Main1(_argc,_argv);
455 #endif
456 exit(ret);
457 }
458 };
459
460 // 'Main program' equivalent: the program execution "starts" here
OnInit()461 bool MyApp::OnInit()
462 {
463 // don't parse the command-line options !
464 // : if ( !wxApp::OnInit() ) return false;
465
466 { // define P7ZIP_HOME_DIR
467 extern void my_windows_split_path(const AString &p_path, AString &dir , AString &base);
468 static char p7zip_home_dir[MAX_PATH];
469
470 UString fullPath;
471 NDirectory::MyGetFullPathName(wxApp::argv[0], fullPath);
472 AString afullPath = GetAnsiString(fullPath);
473
474 AString dir,name;
475
476 my_windows_split_path(afullPath,dir,name);
477
478 const char *dir2 = nameWindowToUnix((const char *)dir);
479 snprintf(p7zip_home_dir,sizeof(p7zip_home_dir),"P7ZIP_HOME_DIR=%s/",dir2);
480 p7zip_home_dir[sizeof(p7zip_home_dir)-1] = 0;
481 putenv(p7zip_home_dir);
482 // DEBUG printf("putenv(%s)\n",p7zip_home_dir);
483 }
484 global_use_utf16_conversion = 1; // UNICODE !
485
486 g_T0 = time(0);
487 // DEBUG printf("MAIN Thread : 0x%lx\n",wxThread::GetCurrentId());
488
489 // Create the main frame window
490 MyFrame *frame = new MyFrame((wxFrame *)NULL, _T("7-zip Main Window"), 50, 50, 450, 340);
491 // Don't Show the frame !
492 // frame->Show(true);
493
494 SetTopWindow(frame);
495
496 g_window = frame;
497
498 MyThread *thread = new MyThread(wxApp::argc,wxApp::argv);
499 thread->Create(); // != wxTHREAD_NO_ERROR
500 thread->Run();
501
502 // success: wxApp::OnRun() will be called which will enter the main message
503 // loop and the application will run. If we returned false here, the
504 // application would exit immediately.
505 return true;
506 }
507
GetTickCount(VOID)508 DWORD WINAPI GetTickCount(VOID) {
509 static wxStopWatch sw;
510 return sw.Time();
511 }
512
513 //////////////////////////////////////////
514
515 #include "resource.h"
516 #include "ExtractRes.h"
517
518 static CStringTable g_stringTable[] =
519 {
520 /* resource.rc */
521 /***************/
522 { IDS_OPEN_TYPE_ALL_FILES, L"All Files" },
523 { IDS_METHOD_STORE, L"Store" },
524 { IDS_METHOD_NORMAL, L"Normal" },
525 { IDS_METHOD_MAXIMUM, L"Maximum" },
526 { IDS_METHOD_FAST, L"Fast" },
527 { IDS_METHOD_FASTEST, L"Fastest" },
528 { IDS_METHOD_ULTRA, L"Ultra" },
529 { IDS_COMPRESS_NON_SOLID, L"Non-solid" },
530 { IDS_COMPRESS_SOLID, L"Solid" },
531
532 { IDS_COMPRESS_UPDATE_MODE_ADD, L"Add and replace files" },
533 { IDS_COMPRESS_UPDATE_MODE_UPDATE, L"Update and add files" },
534 { IDS_COMPRESS_UPDATE_MODE_FRESH, L"Freshen existing files" },
535 { IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE, L"Synchronize files" },
536 { IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE, L"Browse" },
537 { IDS_COMPRESS_INCORRECT_VOLUME_SIZE, L"Incorrect volume size" },
538 { IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE, L"Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?" },
539
540 { IDS_PASSWORD_USE_ASCII, L"Use only English letters, numbers and special characters (!, #, $, ...) for password." },
541 { IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH, L"Passwords do not match" },
542 { IDS_PASSWORD_IS_TOO_LONG, L"Password is too long" },
543
544 { IDS_PROGRESS_COMPRESSING, L"Compressing" },
545 { IDS_PROGRESS_TESTING, L"Testing" },
546 { IDS_MESSAGE_NO_ERRORS, L"There are no errors" },
547 { IDS_FILES_COLON, L"Files:" },
548 { IDS_FOLDERS_COLON, L"Folders:" },
549 { IDS_SIZE_COLON, L"Size:" },
550 { IDS_COMPRESSED_COLON, L"Compressed size:" },
551 { IDS_ARCHIVES_COLON, L"Archives:" },
552
553 /* Extract.rc */
554 /**************/
555 { IDS_CANNOT_CREATE_FOLDER , L"Cannot create folder '{0}'"},
556 { IDS_OPEN_IS_NOT_SUPORTED_ARCHIVE, L"File is not supported archive."},
557
558 { IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC , L"CRC failed in '{0}'. File is broken."},
559 { IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR , L"Data error in '{0}'. File is broken"},
560 { IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_UNSUPPORTED_METHOD , L"Unsupported compression method for '{0}'."},
561 { IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CRC_ENCRYPTED , L"CRC failed in encrypted file '{0}'. Wrong password?"},
562 { IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED , L"Data error in encrypted file '{0}'. Wrong password?"},
563
564 { IDS_EXTRACT_SET_FOLDER , L"Specify a location for extracted files."},
565 { IDS_MESSAGES_DIALOG_EXTRACT_MESSAGE_CANNOT_OPEN_FILE, L"Can not open output file '{0}'."},
566 { IDS_PROGRESS_EXTRACTING, L"Extracting" },
567
568 { IDS_CANT_OPEN_ARCHIVE , L"Can not open file '{0}' as archive"},
569 { IDS_CANT_OPEN_ENCRYPTED_ARCHIVE , L"Can not open encrypted archive '{0}'. Wrong password?"},
570
571 { 0 , 0 }
572 };
573
574 REGISTER_STRINGTABLE(g_stringTable)
575
576