1 // Dialog.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 #include "Windows/Control/DialogImpl.h"
19 #include "Windows/Synchronization.h"
20 
21 // #include "../GUI/p7zip_32.xpm"
22 extern const char * p7zip_32_xpm[];
23 
nameWindowToUnix(const TCHAR * lpFileName)24 const TCHAR * nameWindowToUnix(const TCHAR * lpFileName) {
25   if ((lpFileName[0] == wxT('c')) && (lpFileName[1] == wxT(':'))) return lpFileName+2;
26   return lpFileName;
27 }
28 
29 
30 extern time_t g_T0; // FIXME
31 
32 extern wxWindow * g_window;
33 
34 enum { // FIXME - duplicate
35     WORKER_EVENT=100    // this one gets sent from the worker thread
36 };
37 
38 #define DIALOG_ID_MESSAGEBOX  8100
39 #define DIALOG_ID_DIR_DIALOG  8101
40 #define DIALOG_ID_FILE_DIALOG 8102
41 #define DIALOG_ID_POST_DIALOG 8190
42 #define DIALOG_ID_END_DIALOG  8199
43 
44 static struct
45 {
46 	bool busy;
47 
48 	int id;
49 	wxWindow *parentWindow;
50 
51 	// CreateDialog
52 	NWindows::NControl::CModalDialog * dialog;
53 
54 	// EndModal
55 	int value;
56 	NWindows::NControl::CModalDialogImpl * window;
57 
58 	// MessageBox
59 	const TCHAR * msg;
60 	const TCHAR * title;
61 	int flag;
62 
63 	//
64 	LPCWSTR initialFolderOrFile;
65 
66 	wxSemaphore * sem;
67 	int ret;
68 
69 	UString resultPath;
70 
71 #define MAX_CREATE 16
72 } g_tabCreate[MAX_CREATE];
73 
74 static int myCreateHandle2(int n);
75 
findFreeInd()76 static int findFreeInd()
77 {
78 static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
79 
80 	g_CriticalSection.Enter();
81 	int ind = 0;
82 	while (ind < MAX_CREATE)
83 	{
84 		if (g_tabCreate[ind].busy == false)
85 		{
86 			g_tabCreate[ind].busy = true;
87 			break;
88 		}
89 		ind++;
90 	}
91 	g_CriticalSection.Leave();
92 
93 	return ind;
94 }
95 
WaitInd(int ind,int id,wxWindow * parent,UString & resultPath)96 static int WaitInd(int ind,int id,wxWindow * parent,UString &resultPath)
97 {
98 	int ret = 0;
99 
100 	g_tabCreate[ind].id           = id;
101 	g_tabCreate[ind].parentWindow = parent;
102 	g_tabCreate[ind].ret          = 0;
103 	g_tabCreate[ind].resultPath   = wxEmptyString;
104 
105 	if (wxThread::IsMain())
106 	{
107 		ret = myCreateHandle2(ind);
108 		resultPath = g_tabCreate[ind].resultPath;
109 	}
110 	else
111 	{
112 		g_tabCreate[ind].sem = new wxSemaphore(0);
113 
114 		// create any type of command event here
115 		wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT );
116 		event.SetInt( ind );
117 
118 		// send in a thread-safe way
119 		// DEBUG printf("T=0x%lx - %d : WaitInd(%d,%p): BEGIN\n", wxThread::GetCurrentId(),time(0)-g_T0,g_tabCreate[ind].id,g_tabCreate[ind].parentWindow);
120 		wxPostEvent( g_window, event );
121 
122 		g_tabCreate[ind].sem->Wait();
123 
124 		ret = g_tabCreate[ind].ret;
125 		resultPath = g_tabCreate[ind].resultPath;
126 		// DEBUG printf("T=0x%lx - %d : WaitInd(%d,%p): ret=%d\n", wxThread::GetCurrentId(),time(0)-g_T0,g_tabCreate[ind].id,g_tabCreate[ind].parentWindow,ret);
127 		delete g_tabCreate[ind].sem;
128 		g_tabCreate[ind].sem = 0;
129 	}
130 
131 	g_tabCreate[ind].busy = false;
132 
133 	return ret;
134 }
135 
WaitInd(int ind,int id,wxWindow * parent)136 static int WaitInd(int ind,int id,wxWindow * parent)
137 {
138 	UString resultPath;
139 	return WaitInd(ind,id,parent,resultPath);
140 }
141 
142 class LockGUI
143 {
144 	bool _IsMain;
145 	public:
LockGUI()146 		LockGUI() {
147 			_IsMain = wxThread::IsMain();
148 			if (!_IsMain) {
149 				// DEBUG printf("GuiEnter(0x%lx)\n",wxThread::GetCurrentId());
150 				wxMutexGuiEnter();
151 			}
152 	       	}
~LockGUI()153 		~LockGUI() {
154 			if (!_IsMain) {
155 				wxMutexGuiLeave();
156 				// DEBUG printf("GuiLeave(0x%lx)\n",wxThread::GetCurrentId());
157 			}
158 	       	}
159 };
160 
161 static const unsigned int kNumDialogsMax = 32;
162 static unsigned int g_NumDialogs = 0;
163 static const CDialogInfo *g_Dialogs[kNumDialogsMax];
164 
RegisterDialog(const CDialogInfo * dialogInfo)165 void RegisterDialog(const CDialogInfo *dialogInfo)
166 {
167   // DEBUG printf("RegisterDialog : %d\n",dialogInfo->id);
168   if (g_NumDialogs < kNumDialogsMax)
169     g_Dialogs[g_NumDialogs++] = dialogInfo;
170 }
171 
172 namespace NWindows {
173 
MyLoadString(unsigned int resourceID)174 	CSysString MyLoadString(unsigned int resourceID)
175 	{
176 		for(int i=0; i < g_NumDialogs; i++) {
177 			if (g_Dialogs[i]->stringTable) {
178 				int j = 0;
179 				while(g_Dialogs[i]->stringTable[j].str) {
180 					if (resourceID == g_Dialogs[i]->stringTable[j].id) {
181 						return g_Dialogs[i]->stringTable[j].str;
182 					}
183 
184 					j++;
185 				}
186 			}
187 		}
188 		return L"FIXME-MyLoadStringW-";
189 	}
190 
191 	namespace NControl {
192 
193 /////////////////////////////////////////// CModalDialog //////////////////////////////////
194 
CheckButton(int buttonID,UINT checkState)195 			bool CModalDialog::CheckButton(int buttonID, UINT checkState)
196 			{
197 				LockGUI lock;
198 				wxCheckBox* w = (wxCheckBox*)_window->FindWindow(buttonID);
199 				if (w)
200 				{
201 					w->SetValue(checkState == BST_CHECKED);
202 					return true;
203 				}
204 				return false;
205 			}
206 
IsButtonChecked(int buttonID) const207 			UINT CModalDialog::IsButtonChecked(int buttonID) const
208 			{
209 				LockGUI lock;
210 				wxCheckBox* w = (wxCheckBox*)_window->FindWindow(buttonID);
211 				if (w)
212 				{
213 					bool bret = w->GetValue();
214 					if (bret) return BST_CHECKED;
215 				}
216 				return BST_UNCHECKED;
217 			}
218 
EnableItem(int id,bool state)219 			void CModalDialog::EnableItem(int id, bool state)
220 			{
221 				LockGUI lock;
222 				wxWindow* w = _window->FindWindow(id);
223 				if (w) w->Enable(state);
224 			}
225 
SetItemText(int id,const TCHAR * txt)226 			void CModalDialog::SetItemText(int id, const TCHAR *txt)
227 			{
228 				LockGUI lock;
229 				wxWindow* w = _window->FindWindow(id);
230 				if (w)
231 				{
232 					wxString label(txt);
233 					w->SetLabel(label);
234 				}
235 			}
236 
GetItem(long id) const237 			wxWindow * CModalDialog::GetItem(long id) const
238 			{
239 				LockGUI lock;
240 				return _window->FindWindow(id);
241 			}
242 
ShowItem(int itemID,int cmdShow) const243 			void CModalDialog::ShowItem(int itemID, int cmdShow) const
244 			{
245 				LockGUI lock;
246 				// cmdShow = SW_HIDE or SW_SHOW (sometimes false or true !)
247 				wxWindow* w = _window->FindWindow(itemID);
248 				if (w)
249 				{
250 // FIXME					w->Show(cmdShow != SW_HIDE);
251 					w->Enable(cmdShow != SW_HIDE);
252 				}
253 			}
254 
SetTimer(UINT_PTR idEvent,unsigned milliseconds)255 			UINT_PTR CModalDialog::SetTimer(UINT_PTR idEvent , unsigned milliseconds)
256 			{
257 				LockGUI lock;
258 				return _window->SetTimer(idEvent , milliseconds);
259 			}
260 
KillTimer(UINT_PTR idEvent)261 			void CModalDialog::KillTimer(UINT_PTR idEvent)
262 			{
263 				LockGUI lock;
264 				_window->KillTimer(idEvent);
265 			}
266 
SetText(const TCHAR * _title)267 			void CModalDialog::SetText(const TCHAR *_title) {
268 				LockGUI lock;
269 			      	_window->SetTitle(_title);
270 		       	}
271 
272 
GetText(CSysString & s)273 			bool CModalDialog::GetText(CSysString &s) {
274 				wxString str;
275 				{
276 					LockGUI lock;
277 	  				str = _window->GetTitle();
278 				}
279 	  			s = str;
280 	  			return true;
281 		       	}
282 
Create(int id,HWND parentWindow)283 			INT_PTR CModalDialog::Create(int id , HWND parentWindow)
284 			{
285 				int ind = findFreeInd();
286 
287 				g_tabCreate[ind].dialog = this;
288 
289 				return WaitInd(ind,id,parentWindow);
290 			}
291 
End(int result)292 			void CModalDialog::End(int result)
293 			{
294 				int ind = findFreeInd();
295 
296 				g_tabCreate[ind].window  = _window;
297 				g_tabCreate[ind].value   = result;
298 
299 				WaitInd(ind,DIALOG_ID_END_DIALOG,0);
300 			}
301 
PostMessage(UINT message)302 			void CModalDialog::PostMessage(UINT message)
303 			{
304 				int ind = findFreeInd();
305 
306 				g_tabCreate[ind].dialog  = this;
307 				g_tabCreate[ind].value   = message;
308 
309 				WaitInd(ind,DIALOG_ID_POST_DIALOG,0);
310 			}
311 
312 /////////////////////////////////////////// CModalDialogImpl ///////////////////////////////////////
313 
CModalDialogImpl(CDialog * dialog,wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,long style)314 			CModalDialogImpl::CModalDialogImpl(CDialog *dialog, wxWindow* parent, wxWindowID id,
315 					 const wxString& title, const wxPoint& pos,
316 					 const wxSize& size, long style) :
317 			   		wxDialog(parent, id, title , pos , size, style /* | wxDIALOG_NO_PARENT */ ) ,
318 				       	_timer(this, TIMER_ID_IMPL), _dialog(dialog)
319 			{
320 				// set the frame icon
321 				this->SetIcon(wxICON(p7zip_32));
322 			}
323 
OnAnyButton(wxCommandEvent & event)324 			void CModalDialogImpl::OnAnyButton(wxCommandEvent& event)
325 			{
326 				int id = event.GetId();
327 				if (id == wxID_OK)
328 				{
329 					if (_dialog) _dialog->OnOK();
330 					// event.Skip(true);
331 				}
332 				else if (id == wxID_CANCEL)
333 				{
334 					if (_dialog) _dialog->OnCancel();
335 					// event.Skip(true);
336 				}
337 				else if (id == wxID_HELP)
338 				{
339 					if (_dialog) _dialog->OnHelp();
340 				}
341 				else
342 				{
343 					if (_dialog)
344 					{
345 						bool bret = _dialog->OnButtonClicked(id, FindWindow(id) );
346 					}
347 				}
348 			}
349 
OnAnyChoice(wxCommandEvent & event)350 			void CModalDialogImpl::OnAnyChoice(wxCommandEvent &event)
351 			{
352 				int itemID =  event.GetId();
353 				if (_dialog) _dialog->OnCommand(CBN_SELCHANGE, itemID, 0);
354 			}
355 
OnAnyTimer(wxTimerEvent & event)356 			void CModalDialogImpl::OnAnyTimer(wxTimerEvent &event)
357 			{
358 				int timerID =  event.GetId();
359 				if (_dialog) _dialog->OnTimer(timerID , 0);
360 			}
361 	}
362 }
363 
364 ///////////////////////// myCreateHandle
365 
366 
myCreateHandle2(int n)367 static int myCreateHandle2(int n)
368 {
369 	int                                    id           = g_tabCreate[n].id;
370 	wxWindow *                             parentWindow = g_tabCreate[n].parentWindow;
371 	NWindows::NControl::CModalDialogImpl * window       = 0;
372 
373 	// DEBUG printf("T=0x%lx - %d : myCreateHandle(%d): BEGIN\n", wxThread::GetCurrentId(),time(0)-g_T0,n);
374 
375 	if (id == DIALOG_ID_END_DIALOG)
376 	{
377 		/* FIXME : the dialog must be shown before ending it ?
378 		while (!_window->IsShownOnScreen()) Sleep(200);
379 		Sleep(200);
380 		*/
381 		g_tabCreate[n].window->EndModal(g_tabCreate[n].value);
382 		return 0;
383 	}
384 
385 	if (id == DIALOG_ID_POST_DIALOG)
386 	{
387 		g_tabCreate[n].dialog->OnMessage(g_tabCreate[n].value, 0, 0);
388 		return 0;
389 	}
390 
391 	if (id == DIALOG_ID_MESSAGEBOX)
392 	{
393 		long style = g_tabCreate[n].flag;
394 		long decorated_style = style;
395 		if ( ( style & ( wxICON_EXCLAMATION | wxICON_HAND | wxICON_INFORMATION |
396 				wxICON_QUESTION ) ) == 0 )
397 		{
398 			decorated_style |= ( style & wxYES ) ? wxICON_QUESTION : wxICON_INFORMATION ;
399 		}
400 		wxMessageDialog dialog(parentWindow, g_tabCreate[n].msg, g_tabCreate[n].title, decorated_style);
401 		dialog.SetIcon(wxICON(p7zip_32));
402 		int ret = dialog.ShowModal();
403 
404 		return ret;
405 	}
406 
407 	if (id == DIALOG_ID_DIR_DIALOG)
408 	{
409 		wxString defaultDir = g_tabCreate[n].initialFolderOrFile;
410 		wxDirDialog dirDialog(g_tabCreate[n].parentWindow,
411 			       	g_tabCreate[n].title, defaultDir);
412 		dirDialog.SetIcon(wxICON(p7zip_32));
413 		int ret = dirDialog.ShowModal();
414 		if (ret == wxID_OK) g_tabCreate[n].resultPath = dirDialog.GetPath();
415 		return ret;
416 	}
417 
418 	if (id == DIALOG_ID_FILE_DIALOG)
419 	{
420 		wxString defaultFilename = g_tabCreate[n].initialFolderOrFile;
421 		wxFileDialog fileDialog(g_tabCreate[n].parentWindow, g_tabCreate[n].title,
422 				wxEmptyString, defaultFilename,
423 		       		wxT("All Files (*.*)|*.*"), wxSAVE|wxOVERWRITE_PROMPT);
424 		fileDialog.SetIcon(wxICON(p7zip_32));
425 		int ret = fileDialog.ShowModal();
426 		if (ret == wxID_OK) g_tabCreate[n].resultPath = fileDialog.GetPath();
427 		return ret;
428 	}
429 
430 	for(int i=0; i < g_NumDialogs; i++) {
431 		if (id == g_Dialogs[i]->id) {
432 			// DEBUG printf("%d : Create(%d,%p): CreateDialog-1\n",time(0)-g_T0,id,parentWindow);
433 			window = (g_Dialogs[i]->createDialog)(g_tabCreate[n].dialog,g_tabCreate[n].parentWindow);
434 			// DEBUG printf("%d : Create(%d,%p): CreateDialog-2\n",time(0)-g_T0,id,parentWindow);
435 			break;
436 		}
437 	}
438 
439 	if (window) {
440 
441 		// DEBUG printf("%d : Create(%d,%p): %p->ShowModal()\n",time(0)-g_T0,id,parentWindow,window);
442 
443 		INT_PTR ret = window->ShowModal();
444 
445 		// DEBUG printf("%d : Create(%d,%p): %p->ShowModal() - ret=%d\n",time(0)-g_T0,id,parentWindow,window,ret);
446 		window->Detach();
447 		window->Destroy();
448 
449 		// DEBUG printf("%d : Create(%d,%p): END\n",time(0)-g_T0,id,parentWindow,window);
450 
451 		return ret;
452 	}
453 
454 	// FIXME
455 	printf("INTERNAL ERROR : cannot find dialog %d\n",id);
456 
457 	return 0;
458 }
459 
myCreateHandle(int n)460 void myCreateHandle(int n)
461 {
462 	int ret = myCreateHandle2(n);
463 	g_tabCreate[n].ret = ret;
464 	g_tabCreate[n].sem->Post();
465 }
466 
MessageBoxW(wxWindow * parent,const TCHAR * msg,const TCHAR * title,int flag)467 int MessageBoxW(wxWindow * parent, const TCHAR * msg, const TCHAR * title,int flag)
468 {
469 	int ind = findFreeInd();
470 
471 	g_tabCreate[ind].msg          = msg;
472 	g_tabCreate[ind].title        = title;
473 	g_tabCreate[ind].flag         = flag;
474 
475 	return WaitInd(ind,DIALOG_ID_MESSAGEBOX,parent);
476 }
477 
478 
479 
480 // FIXME : should be in Windows/Shell.cpp
481 
482 namespace NWindows{
483 namespace NShell{
484 
BrowseForFolder(HWND owner,LPCWSTR title,LPCWSTR initialFolder,UString & resultPath)485 bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
486 {
487 	int ind = findFreeInd();
488 
489 	g_tabCreate[ind].title               = title;
490 	g_tabCreate[ind].initialFolderOrFile = nameWindowToUnix(initialFolder);
491 
492 	UString resTmp;
493 	int ret = WaitInd(ind,DIALOG_ID_DIR_DIALOG,owner,resTmp);
494 	if(ret == wxID_OK)
495 	{
496 		resultPath = resTmp;
497 		return true;
498 	}
499 	return false;
500 }
501 
502 }}
503 
504 /////////////////////////// CPP/Windows/CommonDialog.cpp
505 namespace NWindows
506 {
507 
MyGetOpenFileName(HWND hwnd,LPCWSTR title,LPCWSTR fullFileName,LPCWSTR s,UString & resPath)508 	bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR fullFileName, LPCWSTR s, UString &resPath)
509 	{
510 		int ind = findFreeInd();
511 
512 		g_tabCreate[ind].title               = title;
513 		g_tabCreate[ind].initialFolderOrFile = nameWindowToUnix(fullFileName);
514 
515 		UString resTmp;
516 		int ret = WaitInd(ind,DIALOG_ID_FILE_DIALOG,hwnd,resTmp);
517 		if(ret == wxID_OK)
518 		{
519 			resPath = resTmp;
520 			return true;
521 		}
522 		return false;
523 	}
524 }
525 
526