1 /*
2  * Copyright 2003, 2004, 2005 Martin Fuchs
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 
19 
20  //
21  // Explorer clone
22  //
23  // mainframe.cpp
24  //
25  // Martin Fuchs, 23.07.2003
26  //
27 
28 
29 #include <precomp.h>
30 
31 /* We can't include webchild.h here - otherwise MinGW produces errors like: "multiple definition of `QACONTAINERFLAGS'"
32 #include "webchild.h"
33 */
34 extern HWND create_webchildwindow(const WebChildWndInfo& info);
35 
36 #include "../dialogs/settings.h"	// for MdiSdiDlg
37 
38 //#define _NO_REBAR
39 
40 HWND MainFrameBase::Create(const ExplorerCmd& cmd)
41 {
42 	HWND hFrame;
43 
44 #ifndef _NO_MDI
45 	if (cmd._mdi)
46 		hFrame = MDIMainFrame::Create();
47 	else
48 #endif
49 		hFrame = SDIMainFrame::Create();
50 
51 	if (hFrame) {
52 		HWND hwndOld = g_Globals._hMainWnd;
53 
54 		g_Globals._hMainWnd = hFrame;
55 
56 		if (hwndOld)
57 			DestroyWindow(hwndOld);
58 
59 		ShowWindow(hFrame, cmd._cmdShow);
60 		UpdateWindow(hFrame);
61 
62 		 // Open the first child window after initializing the application
63 		if (cmd.IsValidPath()) {
64 			 // We use the static s_path variable to store the path string in order
65 			 // to avoid accessing prematurely freed memory in the PostMessage handlers.
66 			static String s_path = cmd._path;
67 
68 			PostMessage(hFrame, PM_OPEN_WINDOW, cmd._flags, (LPARAM)(LPCTSTR)s_path);
69 		} else
70 			PostMessage(hFrame, PM_OPEN_WINDOW, OWM_EXPLORE|OWM_DETAILS, 0);
71 	}
72 
73 	return hFrame;
74 }
75 
76 
77 int MainFrameBase::OpenShellFolders(LPIDA pida, HWND hFrameWnd)
78 {
79 	int cnt = 0;
80 
81 	LPCITEMIDLIST parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
82 	ShellFolder folder(parent_pidl);
83 	LOG(FmtString(TEXT("MainFrameBase::OpenShellFolders(): parent_pidl=%s"), (LPCTSTR)FileSysShellPath(parent_pidl)));
84 
85 	for(int i=pida->cidl; i>0; --i) {
86 		LPCITEMIDLIST pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i]);
87 
88 		SFGAOF attribs = SFGAO_FOLDER;
89 		HRESULT hr = folder->GetAttributesOf(1, &pidl, &attribs);
90 
91 		if (SUCCEEDED(hr))
92 			if (attribs & SFGAO_FOLDER) {
93 				try {
94 					XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
95 
96 					bool mdi = XMLBool(explorer_options, "mdi", true);
97 					bool separateFolders = XMLBool(explorer_options, "separate-folders", false);
98 
99 					ShellPath pidl_abs = ShellPath(pidl).create_absolute_pidl(parent_pidl);
100 					LOG(FmtString(TEXT("MainFrameBase::OpenShellFolders(): pidl_abs=%s"), (LPCTSTR)FileSysShellPath(pidl_abs)));
101 
102 					if (hFrameWnd && (mdi || !separateFolders)) {
103 						int flags = OWM_PIDL;
104 
105 						if (separateFolders)
106 							flags |= OWM_SEPARATE;
107 
108 						if (SendMessage(hFrameWnd, PM_OPEN_WINDOW, flags, (LPARAM)(LPCITEMIDLIST)pidl_abs))
109 							++cnt;
110 					} else {
111 						HWND hwnd;
112 #ifndef _NO_MDI
113 						if (mdi)
114 							hwnd = MDIMainFrame::Create(pidl_abs, 0);
115 						else
116 #endif
117 							hwnd = SDIMainFrame::Create(pidl_abs, 0);
118 
119 						if (hwnd)
120 							++cnt;
121 					}
122 				} catch(COMException& e) {
123 					HandleException(e, g_Globals._hMainWnd);
124 				}
125 			}/*TEST
126 			else { // !(attribs & SFGAO_FOLDER))
127 				SHELLEXECUTEINFOA shexinfo;
128 
129 				shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
130 				shexinfo.fMask = SEE_MASK_INVOKEIDLIST;
131 				shexinfo.hwnd = NULL;
132 				shexinfo.lpVerb = NULL;
133 				shexinfo.lpFile = NULL;
134 				shexinfo.lpParameters = NULL;
135 				shexinfo.lpDirectory = NULL;
136 				shexinfo.nShow = SW_NORMAL;
137 				shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
138 
139 				if (ShellExecuteExA(&shexinfo))
140 					++cnt;
141 
142 				ILFree((LPITEMIDLIST)shexinfo.lpIDList);
143 			}*/
144 	}
145 
146 	return cnt;
147 }
148 
149 
150 MainFrameBase::MainFrameBase(HWND hwnd)
151  :	super(hwnd)
152 {
153     HDC hDC = GetDC(NULL);
154 #ifndef _NO_REBAR
155 	//static TCHAR Title1[] = TEXT("Toolbar");
156 	static TCHAR Title2[] = TEXT("Address :");
157 #endif
158 
159     if (hDC)
160     {
161         DWORD ilMask;
162         INT bpp = GetDeviceCaps(hDC, BITSPIXEL);
163         ReleaseDC(NULL, hDC);
164 
165         if (bpp <= 4)
166             ilMask = ILC_COLOR4;
167         else if (bpp <= 8)
168             ilMask = ILC_COLOR8;
169         else if (bpp <= 16)
170             ilMask = ILC_COLOR16;
171         else if (bpp <= 24)
172             ilMask = ILC_COLOR24;
173         else if (bpp <= 32)
174             ilMask = ILC_COLOR32;
175         else
176             ilMask = ILC_COLOR;
177 
178         ilMask |= ILC_MASK;
179 
180         _himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ilMask, 2, 0);
181     }
182 
183 	_hMenuFrame = GetMenu(hwnd);
184 	_hMenuWindow = GetSubMenu(_hMenuFrame, GetMenuItemCount(_hMenuFrame)-3);
185 
186 	_menu_info._hMenuView = GetSubMenu(_hMenuFrame, 1);
187 
188 	_hAccel = LoadAccelerators(g_Globals._hInstance, MAKEINTRESOURCE(IDA_EXPLORER));
189 
190 
191 	TBBUTTON toolbarBtns[] = {
192 #ifdef _NO_REBAR
193 		{0, 0, 0, BTNS_SEP, {0, 0}, 0, 0},
194 #endif
195 		{7, ID_GO_BACK, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
196 		{8, ID_GO_FORWARD, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
197 		{9, ID_GO_UP, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
198 		{10, ID_GO_HOME, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
199 		{11, ID_GO_SEARCH, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
200 		{12, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
201 		{13, ID_STOP, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}
202 	};
203 
204 	_htoolbar = CreateToolbarEx(hwnd,
205 #ifndef _NO_REBAR
206 		CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
207 #endif
208 		WS_CHILD|TBSTYLE_FLAT|WS_VISIBLE, IDW_TOOLBAR, 2, g_Globals._hInstance, IDB_TOOLBAR,
209 		toolbarBtns, sizeof(toolbarBtns)/sizeof(TBBUTTON),
210 		16, 16, 16, 16, sizeof(TBBUTTON));
211 
212 	CheckMenuItem(_menu_info._hMenuView, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED);
213 
214 
215 	 // address bar
216 	_haddrcombo = CreateWindowEx(0,
217 								WC_COMBOBOX,
218 								TEXT("Address"),
219 								WS_CHILD|WS_TABSTOP|WS_BORDER|WS_VISIBLE|CBS_DROPDOWN|
220 								CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|CCS_NOMOVEY,
221 								0, 0, 0, 0,
222 								hwnd,
223 								(HMENU)IDW_ADDRESSBAR,
224 								g_Globals._hInstance,
225 								0);
226 
227 	HFONT hFont = (HFONT)GetStockObject(ANSI_VAR_FONT);
228 	SendMessageW(_haddrcombo, WM_SETFONT, (WPARAM)hFont, 0);
229 
230 
231 	_hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, hwnd, IDW_STATUSBAR);
232 	CheckMenuItem(_menu_info._hMenuView, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED);
233 
234 	_hsidebar = CreateWindowEx(WS_EX_STATICEDGE, WC_TREEVIEW, TEXT("Sidebar"),
235 					WS_CHILD|WS_TABSTOP|WS_BORDER|/*WS_VISIBLE|*/TVS_HASLINES|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_INFOTIP,
236 					-1, -1, 200, 0, _hwnd, (HMENU)IDW_SIDEBAR, g_Globals._hInstance, 0);
237 
238 	_himl_old = TreeView_SetImageList(_hsidebar, _himl, TVSIL_NORMAL);
239 
240 	CheckMenuItem(_menu_info._hMenuView, ID_VIEW_SIDE_BAR, MF_BYCOMMAND|MF_UNCHECKED/*MF_CHECKED*/);
241 
242 
243 	 // create rebar window to manage toolbar and drivebar
244 #ifndef _NO_REBAR
245 	_hwndrebar = CreateWindowEx(WS_EX_TOOLWINDOW,
246 								REBARCLASSNAME,
247 								NULL,
248 								WS_CHILD|WS_VISIBLE|WS_BORDER|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|
249 								 RBS_VARHEIGHT|RBS_DBLCLKTOGGLE| RBS_AUTOSIZE|RBS_BANDBORDERS,
250 								0, 0, 0, 0,
251 								_hwnd,
252 								NULL,
253 								g_Globals._hInstance,
254 								0);
255 
256 	int btn_hgt = HIWORD(SendMessage(_htoolbar, TB_GETBUTTONSIZE, 0, 0));
257 
258 	REBARBANDINFO rbBand;
259 
260 	rbBand.cbSize = sizeof(REBARBANDINFO);
261 	rbBand.fMask  = RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE;
262 	rbBand.fStyle = RBBS_CHILDEDGE|RBBS_GRIPPERALWAYS|RBBS_HIDETITLE;
263 
264 	rbBand.cxMinChild = 0;
265 	rbBand.cyMinChild = 0;
266 	rbBand.cyChild = 0;
267 	rbBand.cyMaxChild = 0;
268 	rbBand.cyIntegral = btn_hgt;
269 
270 	rbBand.lpText = NULL;//Title1
271 	rbBand.hwndChild = _htoolbar;
272 	rbBand.cxMinChild = 0;
273 	rbBand.cyMinChild = btn_hgt;
274 	rbBand.cx = 284;
275 	SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)0, (LPARAM)&rbBand);
276 
277 	rbBand.fStyle &= ~RBBS_HIDETITLE;
278 	rbBand.fStyle |= RBBS_BREAK;
279     rbBand.lpText = Title2;
280 	rbBand.hwndChild = _haddrcombo;
281 	rbBand.cxMinChild = 0;
282 	rbBand.cyMinChild = btn_hgt;
283 	rbBand.cx = 400;
284 	SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)3, (LPARAM)&rbBand);
285 #endif
286 }
287 
288 
289 MainFrameBase::~MainFrameBase()
290 {
291 	(void)TreeView_SetImageList(_hsidebar, _himl_old, TVSIL_NORMAL);
292 	ImageList_Destroy(_himl);
293 
294 	 // don't exit desktop when closing file manager window
295 	if (!g_Globals._desktop_mode)
296 		if (g_Globals._hMainWnd == _hwnd)	// don't quit when switching between MDI and SDI mode
297 			PostQuitMessage(0);
298 }
299 
300 
301 LRESULT MainFrameBase::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
302 {
303 	LRESULT res;
304 
305 	if (ProcessMessage(nmsg, wparam, lparam, &res))
306 		return res;
307 	else
308 		return super::WndProc(nmsg, wparam, lparam);
309 }
310 
311 bool MainFrameBase::ProcessMessage(UINT nmsg, WPARAM wparam, LPARAM lparam, LRESULT* pres)
312 {
313 	switch(nmsg) {
314 	  case PM_TRANSLATE_MSG:
315 		*pres = TranslateMsg((MSG*)lparam);
316 		return true;
317 
318 	  case WM_SHOWWINDOW:
319 		if (wparam) {	// trigger child resizing after window creation - now we can succesfully call IsWindowVisible()
320             int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
321     		MoveWindow(_hwndrebar, 0, 0, LOWORD(lparam), height, TRUE);
322 			resize_frame_client();
323         }
324 		return false; // goto def;
325 
326 	  case WM_CLOSE:
327 		DestroyWindow(_hwnd);
328 		g_Globals._hMainWnd = 0;
329 		break;
330 
331 	  case WM_DESTROY:
332 		break;
333 
334 	  case WM_SIZE: {
335 		resize_frame(LOWORD(lparam), HIWORD(lparam));
336 		SendMessage(_hwndrebar, WM_SIZE, 0, 0);
337 		break;}	// do not pass message to DefFrameProc
338 
339 	  case WM_GETMINMAXINFO: {
340 		LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
341 
342 		lpmmi->ptMaxTrackSize.x <<= 1;/*2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN */
343 		lpmmi->ptMaxTrackSize.y <<= 1;/*2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN */
344 		break;}
345 
346 	  case PM_FRM_CALC_CLIENT:
347 		frame_get_clientspace((PRECT)lparam);
348 		*pres = TRUE;
349 		return true;
350 
351 	  case PM_FRM_GET_MENUINFO:
352 		*pres = (LPARAM)&_menu_info;
353 		return true;
354 
355 	  case PM_GET_CONTROLWINDOW:
356 		if (wparam == FCW_STATUS) {
357 			*pres = (LRESULT)(HWND)_hstatusbar;
358 			return true;
359 		}
360 		break;
361 
362 	  case PM_SETSTATUSTEXT:
363 		SendMessage(_hstatusbar, SB_SETTEXT, 0, lparam);
364 		break;
365 
366 	  case WM_SYSCOLORCHANGE:
367 		SendMessage(_hwndrebar, WM_SYSCOLORCHANGE, 0, 0);
368 		SendMessage(_htoolbar, WM_SYSCOLORCHANGE, 0, 0);
369 		break;
370 
371 	  default:
372 		return false;
373 	}
374 
375 	*pres = 0;
376 	return true;
377 }
378 
379 BOOL MainFrameBase::TranslateMsg(MSG* pmsg)
380 {
381 	if (TranslateAccelerator(_hwnd, _hAccel, pmsg))
382 		return TRUE;
383 
384 	return FALSE;
385 }
386 
387 
388 int MainFrameBase::Command(int id, int code)
389 {
390 	CONTEXT("MainFrameBase::Command()");
391 
392 	switch(id) {
393 	  case ID_FILE_EXIT:
394 		SendMessage(_hwnd, WM_CLOSE, 0, 0);
395 		break;
396 
397 	  case ID_VIEW_TOOL_BAR:
398 		toggle_child(_hwnd, id, _htoolbar, 0);
399 		break;
400 
401 	  case ID_VIEW_STATUSBAR:
402 		toggle_child(_hwnd, id, _hstatusbar);
403 		break;
404 
405 	  case ID_VIEW_SIDE_BAR:
406 		 // lazy initialization
407 		if (!TreeView_GetCount(_hsidebar))
408 			FillBookmarks();
409 
410 		toggle_child(_hwnd, id, _hsidebar);
411 		break;
412 
413 	  case ID_EXECUTE: {
414 		ExecuteDialog dlg = {{0}, 0};
415 
416 		if (DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(IDD_EXECUTE), _hwnd, ExecuteDialog::WndProc, (LPARAM)&dlg) == IDOK) {
417 			CONTEXT("ID_EXECUTE - ShellExecute()");
418 
419 			HINSTANCE hinst = ShellExecute(_hwnd, NULL/*operation*/, dlg.cmd/*file*/, NULL/*parameters*/, NULL/*dir*/, dlg.cmdshow);
420 
421 			if ((int)hinst <= 32)
422 				display_error(_hwnd, GetLastError());
423 		}
424 		break;}
425 
426 	  case ID_HELP:
427 		WinHelp(_hwnd, TEXT("explorer")/*file explorer.hlp*/, HELP_INDEX, 0);
428 		break;
429 
430 	  case ID_VIEW_FULLSCREEN:
431 		CheckMenuItem(_menu_info._hMenuView, id, toggle_fullscreen()?MF_CHECKED:0);
432 		break;
433 
434 	  case ID_TOOLS_OPTIONS:
435 		Dialog::DoModal(IDD_MDI_SDI, WINDOW_CREATOR(MdiSdiDlg), _hwnd);
436 		break;
437 
438 	  case ID_ABOUT_WINDOWS:
439 		ShellAbout(_hwnd, ResString(IDS_TITLE), NULL, 0);
440 		break;
441 
442 	  case ID_ABOUT_EXPLORER:
443 		explorer_about(_hwnd);
444 		break;
445 
446 	  case ID_EXPLORER_FAQ:
447 		launch_file(_hwnd, TEXT("http://www.sky.franken.de/explorer/"), SW_SHOW);
448 		break;
449 
450 	  default:
451 		return 1;	// no command handlers in Window::Command()
452 	}
453 
454 	return 0;
455 }
456 
457 int MainFrameBase::Notify(int id, NMHDR* pnmh)
458 {
459 	switch(pnmh->code) {
460 		 // resize children windows when the rebar size changes
461 
462       case RBN_AUTOSIZE:
463 		resize_frame_client();
464 		break;
465 
466 	  case TVN_GETINFOTIP: {
467 		NMTVGETINFOTIP* pnmgit = (NMTVGETINFOTIP*)pnmh;
468 
469 		if (pnmgit->lParam) {
470 			const BookmarkNode& node = *(BookmarkNode*)pnmgit->lParam;
471 
472 			if (node._type == BookmarkNode::BMNT_FOLDER) {
473 				 // display tooltips for bookmark folders
474 				if (!node._pfolder->_description.empty())
475 					lstrcpyn(pnmgit->pszText, node._pfolder->_description.c_str(), pnmgit->cchTextMax);
476 			} else if (node._type == BookmarkNode::BMNT_BOOKMARK) {
477 				 // display tooltips for bookmark folders
478 				String txt = node._pbookmark->_description;
479 
480 				if (!node._pbookmark->_url.empty()) {
481 					if (!txt.empty())
482 						txt += TEXT("  -  ");
483 
484 					txt += node._pbookmark->_url;
485 				}
486 
487 				lstrcpyn(pnmgit->pszText, txt.c_str(), pnmgit->cchTextMax);
488 			}
489 		}
490 		break;}
491 
492 	  case NM_DBLCLK: {
493 		HTREEITEM hitem = TreeView_GetSelection(_hsidebar);
494 		LPARAM lparam = TreeView_GetItemData(_hsidebar, hitem);
495 
496 		if (lparam) {
497 			const BookmarkNode& node = *(BookmarkNode*)lparam;
498 
499 			if (node._type == BookmarkNode::BMNT_BOOKMARK) {
500 				bool new_window = GetAsyncKeyState(VK_SHIFT)<0;
501 
502 				go_to(node._pbookmark->_url, new_window);
503 			}
504 		}
505 		break;}
506 	}
507 
508 	return 0;
509 }
510 
511 
512 void MainFrameBase::resize_frame(int cx, int cy)
513 {
514 	if (cy <= 0)
515 		return;	// avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
516 
517 	RECT rect = {0, 0, cx, cy};
518 
519 	if (_hwndrebar) {
520         int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
521 		rect.top += height;
522         rect.top += 5;
523 
524 		SetWindowPos(_haddrcombo, NULL, 0, 0, cx, height, SWP_NOMOVE);
525 	} else {
526 		if (IsWindowVisible(_htoolbar)) {
527 			SendMessage(_htoolbar, WM_SIZE, 0, 0);
528 			WindowRect rt(_htoolbar);
529 			rect.top = rt.bottom;
530 		//	rect.bottom -= rt.bottom;
531 		}
532 	}
533 
534 	if (IsWindowVisible(_hstatusbar)) {
535 		int parts[] = {300, 500};
536 
537 		SendMessage(_hstatusbar, WM_SIZE, 0, 0);
538 		SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
539 		ClientRect rt(_hstatusbar);
540 		rect.bottom -= rt.bottom;
541 	}
542 
543 	if (IsWindowVisible(_hsidebar)) {
544 		WindowRect rt(_hsidebar);
545 		rect.left += rt.right-rt.left;
546 
547 		SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
548 	}
549 }
550 
551 void MainFrameBase::resize_frame_client()
552 {
553 	ClientRect rect(_hwnd);
554 
555 	resize_frame(rect.right, rect.bottom);
556 }
557 
558 void MainFrameBase::frame_get_clientspace(PRECT prect)
559 {
560 	if (!IsIconic(_hwnd))
561 		GetClientRect(_hwnd, prect);
562 	else {
563 		WINDOWPLACEMENT wp;
564 
565 		GetWindowPlacement(_hwnd, &wp);
566 
567 		prect->left = prect->top = 0;
568 		prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left-
569 						2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE));
570 		prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top-
571 						2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))-
572 						GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE);
573 	}
574 
575 	if (IsWindowVisible(_htoolbar)) {
576 		ClientRect rt(_htoolbar);
577 		prect->top += rt.bottom+2;
578 	}
579 
580 	if (IsWindowVisible(_hstatusbar)) {
581 		ClientRect rt(_hstatusbar);
582 		prect->bottom -= rt.bottom;
583 	}
584 }
585 
586 BOOL MainFrameBase::toggle_fullscreen()
587 {
588 	RECT rt;
589 
590 	if ((_fullscreen._mode=!_fullscreen._mode)) {
591 		GetWindowRect(_hwnd, &_fullscreen._orgPos);
592 		_fullscreen._wasZoomed = IsZoomed(_hwnd);
593 
594 		Frame_CalcFrameClient(_hwnd, &rt);
595 		ClientToScreen(_hwnd, (LPPOINT)&rt.left);
596 		ClientToScreen(_hwnd, (LPPOINT)&rt.right);
597 
598 		rt.left = _fullscreen._orgPos.left-rt.left;
599 		rt.top = _fullscreen._orgPos.top-rt.top;
600 		rt.right = GetSystemMetrics(SM_CXSCREEN)+_fullscreen._orgPos.right-rt.right;
601 		rt.bottom = GetSystemMetrics(SM_CYSCREEN)+_fullscreen._orgPos.bottom-rt.bottom;
602 
603 		MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
604 	} else {
605 		MoveWindow(_hwnd, _fullscreen._orgPos.left, _fullscreen._orgPos.top,
606 							_fullscreen._orgPos.right-_fullscreen._orgPos.left,
607 							_fullscreen._orgPos.bottom-_fullscreen._orgPos.top, TRUE);
608 
609 		if (_fullscreen._wasZoomed)
610 			ShowWindow(_hwnd, WS_MAXIMIZE);
611 	}
612 
613 	return _fullscreen._mode;
614 }
615 
616 void MainFrameBase::fullscreen_move()
617 {
618 	RECT rt, pos;
619 	GetWindowRect(_hwnd, &pos);
620 
621 	Frame_CalcFrameClient(_hwnd, &rt);
622 	ClientToScreen(_hwnd, (LPPOINT)&rt.left);
623 	ClientToScreen(_hwnd, (LPPOINT)&rt.right);
624 
625 	rt.left = pos.left-rt.left;
626 	rt.top = pos.top-rt.top;
627 	rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
628 	rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
629 
630 	MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
631 }
632 
633 
634 void MainFrameBase::toggle_child(HWND hwnd, UINT cmd, HWND hchild, int band_idx)
635 {
636 	BOOL vis = IsWindowVisible(hchild);
637 
638 	CheckMenuItem(_menu_info._hMenuView, cmd, vis?MF_BYCOMMAND:MF_BYCOMMAND|MF_CHECKED);
639 
640 	if (band_idx != -1)
641 		SendMessage(_hwndrebar, RB_SHOWBAND, band_idx, !vis);
642 	else
643 		ShowWindow(hchild, vis? SW_HIDE: SW_SHOW);
644 
645 	if (_fullscreen._mode)
646 		fullscreen_move();
647 
648 	resize_frame_client();
649 }
650 
651 void MainFrameBase::FillBookmarks()
652 {
653 	HiddenWindow hide(_hsidebar);
654 	WindowCanvas canvas(_hwnd);
655 
656 	TreeView_DeleteAllItems(_hsidebar);
657 
658 	g_Globals._icon_cache.get_icon(ICID_FAVORITES).add_to_imagelist(_himl, canvas);
659 	g_Globals._icon_cache.get_icon(ICID_BOOKMARK).add_to_imagelist(_himl, canvas);
660 	ImageList_AddAlphaIcon(_himl, SmallIcon(IDI_DOT), GetStockBrush(WHITE_BRUSH), canvas);
661 	g_Globals._icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas);
662 	g_Globals._icon_cache.get_icon(ICID_FOLDER).add_to_imagelist(_himl, canvas);
663 
664 	TV_INSERTSTRUCT tvi;
665 
666 	tvi.hParent = TVI_ROOT;
667 	tvi.hInsertAfter = TVI_LAST;
668 	tvi.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
669 	ResString sFavorites(IDS_FAVORITES);
670 	tvi.item.pszText = sFavorites.str();
671 	tvi.item.iSelectedImage = tvi.item.iImage = 0;
672 
673 	HTREEITEM hitem_bookmarks = TreeView_InsertItem(_hsidebar, &tvi);
674 
675 	g_Globals._favorites.fill_tree(_hsidebar, hitem_bookmarks, _himl, canvas);
676 
677 	TreeView_Expand(_hsidebar, hitem_bookmarks, TVE_EXPAND);
678 }
679 
680 
681 bool MainFrameBase::go_to(LPCTSTR url, bool new_window)
682 {
683 	///@todo SDI implementation
684 
685 	return false;
686 }
687 
688 
689 #ifndef _NO_MDI
690 
691 MDIMainFrame::MDIMainFrame(HWND hwnd)
692  :	super(hwnd)
693 {
694 	TBBUTTON mdiBtns[] = {
695 		{0, 0, 0, BTNS_SEP, {0, 0}, 0, 0},
696 		{0, ID_WINDOW_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
697 		{1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
698 		{2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
699 		{3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0}
700 	};
701 
702 	SendMessage(_htoolbar, TB_ADDBUTTONS, sizeof(mdiBtns)/sizeof(TBBUTTON), (LPARAM)&mdiBtns);
703 
704 	CLIENTCREATESTRUCT ccs;
705 
706 	ccs.hWindowMenu = _hMenuWindow;
707 	ccs.idFirstChild = IDW_FIRST_CHILD;
708 
709 	_hmdiclient = CreateWindowEx(WS_EX_CLIENTEDGE|WS_EX_NOPARENTNOTIFY, TEXT("MDICLIENT"), NULL,
710 					WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
711 					0, 0, 0, 0,
712 					hwnd, 0, g_Globals._hInstance, &ccs);
713 
714 	TBBUTTON extraBtns = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
715 
716 #ifndef _NO_REBAR
717 	_hextrabar = CreateToolbarEx(hwnd,
718 				CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
719 				WS_CHILD|TBSTYLE_FLAT|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
720 				IDW_EXTRABAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, NULL, 0,
721 				16, 16, 16, 16, sizeof(TBBUTTON));
722 #else
723 	_hextrabar = CreateToolbarEx(hwnd,
724 				WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,CCS_NODIVIDER|
725 				IDW_EXTRABAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &extraBtns, 1,
726 				16, 13, 16, 13, sizeof(TBBUTTON));
727 #endif
728 
729 	CheckMenuItem(_menu_info._hMenuView, ID_VIEW_EXTRA_BAR, MF_BYCOMMAND|MF_CHECKED);
730 
731 
732 	extraBtns.fsStyle = BTNS_BUTTON;
733 
734 #ifdef __WINE__
735 	 // insert unix file system button
736 	extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("/\0"));
737 	extraBtns.idCommand = ID_DRIVE_UNIX_FS;
738 	SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
739 #endif
740 
741 	 // insert explorer window button
742 	extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Explore\0"));
743 	extraBtns.idCommand = ID_DRIVE_DESKTOP;
744 	SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
745 
746 	 // insert shell namespace button
747 	extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Shell\0"));
748 	extraBtns.idCommand = ID_DRIVE_SHELL_NS;
749 	extraBtns.iBitmap = 6;
750 	SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
751 
752 	 // insert web control button
753 	extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Web\0"));
754 	extraBtns.idCommand = ID_WEB_WINDOW;
755 	extraBtns.iBitmap = 7;
756 	SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
757 
758 	if ((HIWORD(GetVersion())>>14) == W_VER_NT) {
759 		 // insert NT object namespace button
760 		extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("NT Obj\0"));
761 		extraBtns.idCommand = ID_DRIVE_NTOBJ_NS;
762 		extraBtns.iBitmap = 8;
763 		SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
764 	}
765 
766 	 // insert Registry button
767 	extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("Reg.\0"));
768 	extraBtns.idCommand = ID_DRIVE_REGISTRY;
769 	extraBtns.iBitmap = 9;
770 	SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
771 
772 #ifdef _DEBUG
773 	 // insert FAT direct file system access button
774 	extraBtns.iString = SendMessage(_hextrabar, TB_ADDSTRING, 0, (LPARAM)TEXT("FAT\0"));
775 	extraBtns.idCommand = ID_DRIVE_FAT;
776 	extraBtns.iBitmap = 10;
777 	SendMessage(_hextrabar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&extraBtns);
778 #endif
779 
780 
781 	TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
782 #ifndef _NO_WIN_FS
783 	PTSTR p;
784 
785 #ifndef _NO_REBAR
786 	_hdrivebar = CreateToolbarEx(hwnd,
787 				CCS_NOPARENTALIGN|CCS_NORESIZE|CCS_NODIVIDER|
788 				WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT|CCS_NOMOVEY|TBSTYLE_LIST,
789 				IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, NULL, 0,
790 				16, 16, 16, 16, sizeof(TBBUTTON));
791 #else
792 	_hdrivebar = CreateToolbarEx(hwnd,
793 				WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST|CCS_NODIVIDER,
794 				IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &drivebarBtn, 1,
795 				16, 13, 16, 13, sizeof(TBBUTTON));
796 #endif
797 #endif
798 
799 	CheckMenuItem(_menu_info._hMenuView, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_UNCHECKED);
800 
801 
802 #ifndef _NO_WIN_FS
803 	GetLogicalDriveStrings(BUFFER_LEN, _drives);
804 
805 	 // register windows drive root strings
806 	SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)_drives);
807 
808 	drivebarBtn.fsStyle = BTNS_BUTTON;
809 	drivebarBtn.idCommand = ID_DRIVE_FIRST;
810 
811 	for(p=_drives; *p; ) {
812 		switch(GetDriveType(p)) {
813 			case DRIVE_REMOVABLE:	drivebarBtn.iBitmap = 1;	break;
814 			case DRIVE_CDROM:		drivebarBtn.iBitmap = 3;	break;
815 			case DRIVE_REMOTE:		drivebarBtn.iBitmap = 4;	break;
816 			case DRIVE_RAMDISK: 	drivebarBtn.iBitmap = 5;	break;
817 			default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2;
818 		}
819 
820 		SendMessage(_hdrivebar, TB_INSERTBUTTON, INT_MAX, (LPARAM)&drivebarBtn);
821 		++drivebarBtn.idCommand;
822 		++drivebarBtn.iString;
823 
824 		while(*p++);
825 	}
826 #endif
827 
828 
829 #ifndef _NO_REBAR
830 	int btn_hgt = HIWORD(SendMessage(_htoolbar, TB_GETBUTTONSIZE, 0, 0));
831 
832 	REBARBANDINFO rbBand;
833 
834 	rbBand.cbSize = sizeof(REBARBANDINFO);
835 	rbBand.fMask  = RBBIM_TEXT|RBBIM_STYLE|RBBIM_CHILD|RBBIM_CHILDSIZE|RBBIM_SIZE;
836 #ifndef RBBS_HIDETITLE // missing in MinGW headers as of 25.02.2004
837 #define RBBS_HIDETITLE	0x400
838 #endif
839 	rbBand.fStyle = RBBS_CHILDEDGE|RBBS_GRIPPERALWAYS|RBBS_HIDETITLE;
840 
841 	TCHAR ExtrasBand[] = _T("Extras");
842 	rbBand.lpText = ExtrasBand;
843 	rbBand.hwndChild = _hextrabar;
844 	rbBand.cxMinChild = 0;
845 	rbBand.cyMinChild = btn_hgt;
846 	rbBand.cx = 284;
847 	SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)1, (LPARAM)&rbBand);
848 
849 #ifndef _NO_WIN_FS
850 	rbBand.fStyle |= RBBS_BREAK;
851 	TCHAR DrivesBand[] = _T("Drives");
852 	rbBand.lpText = DrivesBand;
853 	rbBand.hwndChild = _hdrivebar;
854 	rbBand.cxMinChild = 0;
855 	rbBand.cyMinChild = btn_hgt;
856 	rbBand.cx = 400;
857 	SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)2, (LPARAM)&rbBand);
858 
859 	// hide the drivebar by default
860 	SendMessage(_hwndrebar, RB_SHOWBAND, 2, FALSE);
861 #endif
862 #endif
863 }
864 
865 
866 HWND MDIMainFrame::Create()
867 {
868 	HMENU hMenuFrame = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(IDM_MDIFRAME));
869 
870 	return Window::Create(WINDOW_CREATOR(MDIMainFrame), 0,
871 				(LPCTSTR)(int)g_Globals._hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
872 				CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
873 				0/*hwndDesktop*/, hMenuFrame);
874 }
875 
876 HWND MDIMainFrame::Create(LPCTSTR path, int mode)
877 {
878 	HWND hFrame = Create();
879 	if (!hFrame)
880 		return 0;
881 
882 	ShowWindow(hFrame, SW_SHOW);
883 
884 	MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
885 
886 	if (pMainFrame)
887 		pMainFrame->CreateChild(path, mode);
888 
889 	return hFrame;
890 }
891 
892 HWND MDIMainFrame::Create(LPCITEMIDLIST pidl, int mode)
893 {
894 	HWND hFrame = Create();
895 	if (!hFrame)
896 		return 0;
897 
898 	ShowWindow(hFrame, SW_SHOW);
899 
900 	MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
901 
902 	if (pMainFrame)
903 		pMainFrame->CreateChild(pidl, mode);
904 
905 	return hFrame;
906 }
907 
908 
909 ChildWindow* MDIMainFrame::CreateChild(LPCTSTR path, int mode)
910 {
911 	return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode, (LPARAM)path));
912 }
913 
914 ChildWindow* MDIMainFrame::CreateChild(LPCITEMIDLIST pidl, int mode)
915 {
916 	return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode|OWM_PIDL, (LPARAM)pidl));
917 }
918 
919 
920 BOOL MDIMainFrame::TranslateMsg(MSG* pmsg)
921 {
922 	if (_hmdiclient && TranslateMDISysAccel(_hmdiclient, pmsg))
923 		return TRUE;
924 
925 	return super::TranslateMsg(pmsg);
926 }
927 
928 LRESULT MDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
929 {
930 	switch(nmsg) {
931 	  case PM_OPEN_WINDOW: {
932 		CONTEXT("MDIMainFrame PM_OPEN_WINDOW");
933 
934 		TCHAR buffer[MAX_PATH];
935 		LPCTSTR path;
936 		ShellPath shell_path = DesktopFolderPath();
937 
938 		if (lparam) {
939 			if (wparam & OWM_PIDL) {
940 				 // take over PIDL from lparam
941 				shell_path.assign((LPCITEMIDLIST)lparam);	// create as "rooted" window
942 				FileSysShellPath fsp(shell_path);
943 				path = fsp;
944 
945 				if (path) {
946 					LOG(FmtString(TEXT("MDIMainFrame PM_OPEN_WINDOW: path=%s"), path));
947 					lstrcpy(buffer, path);
948 					path = buffer;
949 				}
950 			} else {
951 				 // take over path from lparam
952 				path = (LPCTSTR)lparam;
953 				shell_path = path;	// create as "rooted" window
954 			}
955 		} else {
956 			///@todo read paths and window placements from registry
957 			if (!GetCurrentDirectory(MAX_PATH, buffer))
958 				*buffer = '\0';
959 
960 			path = buffer;
961 		}
962 
963 		if (path && _tcsstr(path, TEXT("://"))) {	// "http://...", "ftp://", ...
964 			OBJ_CONTEXT("create WebChild window", path);
965 
966 			return (LRESULT)GET_WINDOW(ChildWindow, create_webchildwindow(WebChildWndInfo(_hmdiclient, path)));
967 		} else {
968 			OBJ_CONTEXT("create ShellChildWndInfo", path);
969 
970 			 // Shell Namespace as default view
971 			ShellChildWndInfo create_info(_hmdiclient, path, shell_path);
972 
973 			if (wparam & OWM_ROOTED)
974 				create_info._root_shell_path = shell_path;
975 			else
976 				create_info._root_shell_path = DesktopFolderPath();	//SpecialFolderPath(CSIDL_DRIVES, _hwnd);
977 
978 			create_info._pos.showCmd = wparam&OWM_SEPARATE? SW_SHOWNORMAL: SW_SHOWMAXIMIZED;
979 			create_info._pos.rcNormalPosition.left = CW_USEDEFAULT;
980 			create_info._pos.rcNormalPosition.top = CW_USEDEFAULT;
981 			create_info._pos.rcNormalPosition.right = CW_USEDEFAULT;
982 			create_info._pos.rcNormalPosition.bottom = CW_USEDEFAULT;
983 
984 			create_info._open_mode = wparam;
985 
986 		//	FileChildWindow::create(_hmdiclient, create_info);
987 			return (LRESULT)MDIShellBrowserChild::create(create_info);
988 		}
989 		return TRUE;}	// success
990 
991 	  case WM_SYSCOLORCHANGE: {
992 		LRESULT res;
993 		HWND hChild;
994 
995 		/* Forward WM_SYSCOLORCHANGE to common controls */
996 		SendMessage(_hextrabar, WM_SYSCOLORCHANGE, 0, 0);
997 		SendMessage(_hdrivebar, WM_SYSCOLORCHANGE, 0, 0);
998 
999 		for(hChild = GetNextWindow(_hmdiclient,GW_CHILD); hChild; hChild = GetNextWindow(hChild, GW_HWNDNEXT))
1000 			SendMessage(hChild, WM_SYSCOLORCHANGE, 0, 0);
1001 
1002 		super::ProcessMessage(nmsg, wparam, lparam, &res);
1003 		break; }
1004 
1005 	  default: {
1006 		LRESULT res;
1007 
1008 		if (super::ProcessMessage(nmsg, wparam, lparam, &res))
1009 			return res;
1010 		else
1011 			return DefFrameProc(_hwnd, _hmdiclient, nmsg, wparam, lparam);
1012 	  }
1013 	}
1014 
1015 	return 0;
1016 }
1017 
1018 int MDIMainFrame::Command(int id, int code)
1019 {
1020 	CONTEXT("MDIMainFrame::Command()");
1021 
1022 	HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
1023 
1024 	if (hwndClient)
1025 		if (SendMessage(hwndClient, PM_DISPATCH_COMMAND, MAKELONG(id,code), 0))
1026 			return 0;
1027 
1028 #ifndef _NO_WIN_FS
1029 	if (id>=ID_DRIVE_FIRST && id<=ID_DRIVE_FIRST+0xFF) {
1030 		TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
1031 		LPCTSTR root = _drives;
1032 
1033 		for(int i=id-ID_DRIVE_FIRST; i--; root++)
1034 			while(*root)
1035 				++root;
1036 
1037 		if (activate_drive_window(root))
1038 			return 0;
1039 
1040 		_tsplitpath_s(root, drv, COUNTOF(drv), NULL, 0, NULL, 0, NULL, 0);
1041 
1042 		if (!SetCurrentDirectory(drv)) {
1043 			display_error(_hwnd, GetLastError());
1044 			return 0;
1045 		}
1046 
1047 		GetCurrentDirectory(MAX_PATH, path); ///@todo store last directory per drive
1048 
1049 		FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
1050 
1051 		return 1;
1052 	}
1053 #endif
1054 
1055 	switch(id) {
1056 	  case ID_WINDOW_NEW: {
1057 		TCHAR path[MAX_PATH];
1058 
1059 		GetCurrentDirectory(MAX_PATH, path);
1060 
1061 		FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
1062 		break;}
1063 
1064 	  case ID_WINDOW_CASCADE:
1065 		SendMessage(_hmdiclient, WM_MDICASCADE, 0, 0);
1066 		break;
1067 
1068 	  case ID_WINDOW_TILE_HORZ:
1069 		SendMessage(_hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
1070 		break;
1071 
1072 	  case ID_WINDOW_TILE_VERT:
1073 		SendMessage(_hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0);
1074 		break;
1075 
1076 	  case ID_WINDOW_ARRANGE:
1077 		SendMessage(_hmdiclient, WM_MDIICONARRANGE, 0, 0);
1078 		break;
1079 
1080 	  case ID_VIEW_EXTRA_BAR:
1081 		toggle_child(_hwnd, id, _hextrabar, 1);
1082 		break;
1083 
1084 #ifndef _NO_WIN_FS
1085 	  case ID_VIEW_DRIVE_BAR:
1086 		toggle_child(_hwnd, id, _hdrivebar, 2);
1087 		break;
1088 #endif
1089 
1090 #ifdef __WINE__
1091 	  case ID_DRIVE_UNIX_FS: {
1092 		TCHAR path[MAX_PATH];
1093 		FileChildWindow* child;
1094 
1095 		getcwd(path, COUNTOF(path));
1096 
1097 		if (activate_child_window(TEXT("unixfs")))
1098 			break;
1099 
1100 		FileChildWindow::create(_hmdiclient, FileChildWndInfo(path));
1101 		break;}
1102 #endif
1103 
1104 	  case ID_DRIVE_DESKTOP: {
1105 		TCHAR path[MAX_PATH];
1106 
1107 		if (activate_child_window(TEXT("Desktop")))
1108 			break;
1109 
1110 		GetCurrentDirectory(MAX_PATH, path);
1111 
1112 		MDIShellBrowserChild::create(ShellChildWndInfo(_hmdiclient, path, DesktopFolderPath()));
1113 		break;}
1114 
1115 	  case ID_DRIVE_SHELL_NS: {
1116 		TCHAR path[MAX_PATH];
1117 		GetCurrentDirectory(MAX_PATH, path);
1118 
1119 		if (activate_child_window(TEXT("Shell")))
1120 			break;
1121 
1122 		FileChildWindow::create(ShellChildWndInfo(_hmdiclient, path, DesktopFolderPath()));
1123 		break;}
1124 
1125 	  case ID_DRIVE_NTOBJ_NS: {
1126 		if (activate_child_window(TEXT("NTOBJ")))
1127 			break;
1128 
1129 		FileChildWindow::create(NtObjChildWndInfo(_hmdiclient, TEXT("\\")));
1130 	  break;}
1131 
1132 	  case ID_DRIVE_REGISTRY: {
1133 		if (activate_child_window(TEXT("Registry")))
1134 			break;
1135 
1136 		FileChildWindow::create(RegistryChildWndInfo(_hmdiclient, TEXT("\\")));
1137 	  break;}
1138 
1139 	  case ID_DRIVE_FAT: {
1140 
1141 	  	///@todo prompt for image file
1142 
1143 		if (activate_child_window(TEXT("FAT")))
1144 			break;
1145 
1146 		FileChildWindow::create(FATChildWndInfo(_hmdiclient, TEXT("FAT Image")));	//@@
1147 	  break;}
1148 
1149 	  case ID_WEB_WINDOW:
1150 #ifdef _DEBUG
1151 		create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://localhost")));
1152 #else
1153 		create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://www.reactos.org")));
1154 #endif
1155 		break;
1156 
1157 	  case ID_EXPLORER_FAQ:
1158 		create_webchildwindow(WebChildWndInfo(_hmdiclient, TEXT("http://www.sky.franken.de/explorer/")));
1159 		break;
1160 
1161 	  case ID_VIEW_SDI:
1162 		MainFrameBase::Create(ExplorerCmd());
1163 		break;
1164 
1165 	///@todo There are even more menu items!
1166 
1167 	  default:
1168 		if (super::Command(id, code) == 0)
1169 			return 0;
1170 		else
1171 			return DefFrameProc(_hwnd, _hmdiclient, WM_COMMAND, MAKELONG(id,code), 0);
1172 	}
1173 
1174 	return 0;
1175 }
1176 
1177 
1178 void MDIMainFrame::frame_get_clientspace(PRECT prect)
1179 {
1180 	super::frame_get_clientspace(prect);
1181 
1182 #ifndef _NO_WIN_FS
1183 	if (IsWindowVisible(_hdrivebar)) {
1184 		ClientRect rt(_hdrivebar);
1185 		prect->top += rt.bottom+2;
1186 	}
1187 #endif
1188 }
1189 
1190 void MDIMainFrame::resize_frame(int cx, int cy)
1191 {
1192 	if (cy <= 0)
1193 		return;	// avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
1194 
1195 	RECT rect = {0, 0, cx, cy};
1196 
1197 	if (_hwndrebar) {
1198         int height = SendMessage(_hwndrebar, RB_GETBARHEIGHT, 0, 0);
1199 		rect.top += height;
1200         rect.top += 5;
1201 	} else {
1202 		if (IsWindowVisible(_htoolbar)) {
1203 			SendMessage(_htoolbar, WM_SIZE, 0, 0);
1204 			WindowRect rt(_htoolbar);
1205 			rect.top = rt.bottom;
1206 		//	rect.bottom -= rt.bottom;
1207 		}
1208 
1209 		if (IsWindowVisible(_hextrabar)) {
1210 			SendMessage(_hextrabar, WM_SIZE, 0, 0);
1211 			WindowRect rt(_hextrabar);
1212 			int new_top = --rect.top + rt.bottom;
1213 			MoveWindow(_hextrabar, 0, rect.top, rt.right, new_top, TRUE);
1214 			rect.top = new_top;
1215 		//	rect.bottom -= rt.bottom;
1216 		}
1217 
1218 #ifndef _NO_WIN_FS
1219 		if (IsWindowVisible(_hdrivebar)) {
1220 			SendMessage(_hdrivebar, WM_SIZE, 0, 0);
1221 			WindowRect rt(_hdrivebar);
1222 			int new_top = --rect.top + rt.bottom;
1223 			MoveWindow(_hdrivebar, 0, rect.top, rt.right, new_top, TRUE);
1224 			rect.top = new_top;
1225 		//	rect.bottom -= rt.bottom;
1226 		}
1227 #endif
1228 	}
1229 
1230 	if (IsWindowVisible(_hstatusbar)) {
1231 		int parts[] = {300, 500};
1232 
1233 		SendMessage(_hstatusbar, WM_SIZE, 0, 0);
1234 		SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
1235 		ClientRect rt(_hstatusbar);
1236 		rect.bottom -= rt.bottom;
1237 	}
1238 
1239 	if (IsWindowVisible(_hsidebar)) {
1240 		WindowRect rt(_hsidebar);
1241 		rect.left += rt.right-rt.left;
1242 
1243 		SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
1244 	}
1245 
1246 	MoveWindow(_hmdiclient, rect.left-1, rect.top-1, rect.right-rect.left+1, rect.bottom-rect.top+1, TRUE);
1247 }
1248 
1249 bool MDIMainFrame::activate_drive_window(LPCTSTR path)
1250 {
1251 	TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE];
1252 	HWND child_wnd;
1253 
1254 	_tsplitpath_s(path, drv1, COUNTOF(drv1), NULL, 0, NULL, 0, NULL, 0);
1255 
1256 	 // search for a already open window for the same drive
1257 	for(child_wnd=GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1258 		FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
1259 
1260 		if (child) {
1261 			_tsplitpath_s(child->get_root()._path, drv2, COUNTOF(drv2), NULL, 0, NULL, 0, NULL, 0);
1262 
1263 			if (!lstrcmpi(drv2, drv1)) {
1264 				SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1265 
1266 				if (IsMinimized(child_wnd))
1267 					ShowWindow(child_wnd, SW_SHOWNORMAL);
1268 
1269 				return true;
1270 			}
1271 		}
1272 	}
1273 
1274 	return false;
1275 }
1276 
1277 bool MDIMainFrame::activate_child_window(LPCTSTR filesys)
1278 {
1279 	HWND child_wnd;
1280 
1281 	 // search for a already open window of the given file system name
1282 	for(child_wnd=GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=GetNextWindow(child_wnd, GW_HWNDNEXT)) {
1283 		FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
1284 
1285 		if (child) {
1286 			if (!lstrcmpi(child->get_root()._fs, filesys)) {
1287 				SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1288 
1289 				if (IsMinimized(child_wnd))
1290 					ShowWindow(child_wnd, SW_SHOWNORMAL);
1291 
1292 				return true;
1293 			}
1294 		} else {
1295 			ShellBrowser* shell_child = (ShellBrowser*) SendMessage(child_wnd, PM_GET_SHELLBROWSER_PTR, 0, 0);
1296 
1297 			if (shell_child) {
1298 				if (!lstrcmpi(shell_child->get_root()._fs, filesys)) {
1299 					SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
1300 
1301 					if (IsMinimized(child_wnd))
1302 						ShowWindow(child_wnd, SW_SHOWNORMAL);
1303 
1304 					return true;
1305 				}
1306 			}
1307 		}
1308 	}
1309 
1310 	return false;
1311 }
1312 
1313 bool MDIMainFrame::go_to(LPCTSTR url, bool new_window)
1314 {
1315 	if (!new_window) {
1316 		HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
1317 
1318 		if (hwndClient)
1319 			if (SendMessage(hwndClient, PM_JUMP_TO_URL, 0, (LPARAM)url))
1320 				return true;
1321 	}
1322 
1323 	if (CreateChild(url))
1324 		return true;
1325 
1326 	return super::go_to(url, new_window);
1327 }
1328 
1329 #endif // _NO_MDI
1330 
1331 
1332 SDIMainFrame::SDIMainFrame(HWND hwnd)
1333  :	super(hwnd)
1334 {
1335 	_split_pos = DEFAULT_SPLIT_POS;
1336 	_last_split = DEFAULT_SPLIT_POS;
1337 
1338 	/* wait for PM_OPEN_WINDOW message before creating a shell view
1339 	update_shell_browser();*/
1340 }
1341 
1342 HWND SDIMainFrame::Create()
1343 {
1344 	HMENU hMenuFrame = LoadMenu(g_Globals._hInstance, MAKEINTRESOURCE(IDM_SDIFRAME));
1345 
1346 	return Window::Create(WINDOW_CREATOR(SDIMainFrame), 0,
1347 				(LPCTSTR)(int)g_Globals._hframeClass, ResString(IDS_TITLE), WS_OVERLAPPEDWINDOW,
1348 				CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1349 				0/*hwndDesktop*/, hMenuFrame);
1350 }
1351 
1352 HWND SDIMainFrame::Create(LPCITEMIDLIST pidl, int mode)
1353 {
1354 	HWND hFrame = Create();
1355 	if (!hFrame)
1356 		return 0;
1357 
1358 	ShowWindow(hFrame, SW_SHOW);
1359 
1360 	SDIMainFrame* pFrame = GET_WINDOW(SDIMainFrame, hFrame);
1361 
1362 	if (pFrame)
1363 		pFrame->jump_to(pidl, mode);
1364 
1365 	return hFrame;
1366 }
1367 
1368 HWND SDIMainFrame::Create(LPCTSTR path, int mode)
1369 {
1370 	HWND hFrame = Create();
1371 	if (!hFrame)
1372 		return 0;
1373 
1374 	ShowWindow(hFrame, SW_SHOW);
1375 
1376 	MDIMainFrame* pMainFrame = GET_WINDOW(MDIMainFrame, hFrame);
1377 
1378 	if (pMainFrame)
1379 		pMainFrame->CreateChild(path, mode);
1380 
1381 	return hFrame;
1382 }
1383 
1384 LRESULT SDIMainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
1385 {
1386 	switch(nmsg) {
1387 	  case WM_SIZE:
1388 		resize_frame(LOWORD(lparam), HIWORD(lparam));
1389 		break;
1390 
1391 	  case WM_PAINT: {
1392 		PaintCanvas canvas(_hwnd);
1393 
1394 		if (_left_hwnd) {
1395 			ClientRect rt(_hwnd);
1396 			rt.left = _split_pos-SPLIT_WIDTH/2;
1397 			rt.right = _split_pos+SPLIT_WIDTH/2+1;
1398 
1399 			if (_right_hwnd) {
1400 				WindowRect right_rect(_right_hwnd);
1401 				ScreenToClient(_hwnd, &right_rect);
1402 				rt.top = right_rect.top;
1403 				rt.bottom = right_rect.bottom;
1404 			}
1405 
1406 			HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR));
1407 			Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1);
1408 			SelectObject(canvas, lastBrush);
1409 		}
1410 		break;}
1411 
1412 	  case WM_SETCURSOR:
1413   		if (_left_hwnd)
1414 			if (LOWORD(lparam) == HTCLIENT) {
1415 				POINT pt;
1416 				GetCursorPos(&pt);
1417 				ScreenToClient(_hwnd, &pt);
1418 
1419 				if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) {
1420 					SetCursor(LoadCursor(0, IDC_SIZEWE));
1421 					return TRUE;
1422 				}
1423 			}
1424 		goto def;
1425 
1426 	  case WM_LBUTTONDOWN:
1427 		if (_left_hwnd) {
1428 			int x = GET_X_LPARAM(lparam);
1429 
1430 			ClientRect rt(_hwnd);
1431 
1432 			if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) {
1433 				_last_split = _split_pos;
1434 				SetCapture(_hwnd);
1435 			}
1436 		}
1437 		break;
1438 
1439 	  case WM_LBUTTONUP:
1440 		if (GetCapture() == _hwnd)
1441 			ReleaseCapture();
1442 		break;
1443 
1444 	  case WM_KEYDOWN:
1445 		if (wparam == VK_ESCAPE)
1446 			if (GetCapture() == _hwnd) {
1447 				_split_pos = _last_split;
1448 				resize_children();
1449 				_last_split = -1;
1450 				ReleaseCapture();
1451 				SetCursor(LoadCursor(0, IDC_ARROW));
1452 			}
1453 		break;
1454 
1455 	  case WM_MOUSEMOVE:
1456 		if (GetCapture() == _hwnd) {
1457 			int x = GET_X_LPARAM(lparam);
1458 
1459 			ClientRect rt(_hwnd);
1460 
1461 			if (x>=0 && x<rt.right) {
1462 				_split_pos = x;
1463 				resize_children();
1464 				rt.left = x-SPLIT_WIDTH/2;
1465 				rt.right = x+SPLIT_WIDTH/2+1;
1466 				InvalidateRect(_hwnd, &rt, FALSE);
1467 				UpdateWindow(_left_hwnd);
1468 				UpdateWindow(_hwnd);
1469 				UpdateWindow(_right_hwnd);
1470 			}
1471 		}
1472 		break;
1473 
1474 	  case PM_OPEN_WINDOW: {
1475 		CONTEXT("SDIMainFrame PM_OPEN_WINDOW");
1476 
1477 		TCHAR buffer[MAX_PATH];
1478 		LPCTSTR path;
1479 		ShellPath shell_path = DesktopFolderPath();
1480 
1481 		if (lparam) {
1482 			if (wparam & OWM_PIDL) {
1483 				 // take over PIDL from lparam
1484 				shell_path.assign((LPCITEMIDLIST)lparam);	// create as "rooted" window
1485 				FileSysShellPath fsp(shell_path);
1486 				path = fsp;
1487 
1488 				if (path) {
1489 					LOG(FmtString(TEXT("SDIMainFrame PM_OPEN_WINDOW: path=%s"), path));
1490 					lstrcpy(buffer, path);
1491 					path = buffer;
1492 				}
1493 			} else {
1494 				 // take over path from lparam
1495 				path = (LPCTSTR)lparam;
1496 				shell_path = path;	// create as "rooted" window
1497 			}
1498 		} else {
1499 			///@todo read paths and window placements from registry
1500 			if (!GetCurrentDirectory(MAX_PATH, buffer))
1501 				*buffer = '\0';
1502 
1503 			path = buffer;
1504 			shell_path = path;
1505 		}
1506 
1507 		if (wparam & OWM_ROOTED)
1508 			_shellpath_info._root_shell_path = shell_path;
1509 		else
1510 			_shellpath_info._root_shell_path = DesktopFolderPath();	//SpecialFolderPath(CSIDL_DRIVES, _hwnd);
1511 
1512 		jump_to(shell_path, wparam);	///@todo content of 'path' not used any more
1513 		return TRUE;}	// success
1514 
1515 	  default: def:
1516 		return super::WndProc(nmsg, wparam, lparam);
1517 	}
1518 
1519 	return 0;
1520 }
1521 
1522 int SDIMainFrame::Command(int id, int code)
1523 {
1524 	switch(id) {
1525 	  case ID_VIEW_MDI:
1526 		MainFrameBase::Create(ExplorerCmd(_url, true));
1527 		break;
1528 
1529 	  default:
1530 		return super::Command(id, code);
1531 	}
1532 
1533 	return 0;
1534 }
1535 
1536 void SDIMainFrame::resize_frame(int cx, int cy)
1537 {
1538 	if (cy <= 0)
1539 		return;	// avoid resizing children when receiving RBN_AUTOSIZE while getting minimized
1540 
1541 	RECT rect = {0, 0, cx, cy};
1542 
1543 	if (_hwndrebar) {
1544 		int height = ClientRect(_hwndrebar).bottom;
1545 		rect.top += height;
1546         rect.top += 5;
1547 	} else {
1548 		if (IsWindowVisible(_htoolbar)) {
1549 			SendMessage(_htoolbar, WM_SIZE, 0, 0);
1550 			WindowRect rt(_htoolbar);
1551 			rect.top = rt.bottom;
1552 		//	rect.bottom -= rt.bottom;
1553 		}
1554 	}
1555 
1556 	if (IsWindowVisible(_hstatusbar)) {
1557 		int parts[] = {300, 500};
1558 
1559 		SendMessage(_hstatusbar, WM_SIZE, 0, 0);
1560 		SendMessage(_hstatusbar, SB_SETPARTS, 2, (LPARAM)&parts);
1561 		ClientRect rt(_hstatusbar);
1562 		rect.bottom -= rt.bottom;
1563 	}
1564 
1565 	if (IsWindowVisible(_hsidebar)) {
1566 		WindowRect rt(_hsidebar);
1567 		rect.left += rt.right-rt.left;
1568 
1569 		SetWindowPos(_hsidebar, 0, -1, rect.top-1, rt.right-rt.left, rect.bottom-rect.top+1, SWP_NOACTIVATE|SWP_NOZORDER);
1570 	}
1571 
1572 	_clnt_rect = rect;
1573 
1574 	resize_children();
1575 }
1576 
1577 void SDIMainFrame::resize_children()
1578 {
1579 	HDWP hdwp = BeginDeferWindowPos(2);
1580 
1581 	int cx = _clnt_rect.left;
1582 
1583 	if (_left_hwnd) {
1584 		cx = _split_pos + SPLIT_WIDTH/2;
1585 
1586 		hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, _clnt_rect.left, _clnt_rect.top, _split_pos-SPLIT_WIDTH/2-_clnt_rect.left, _clnt_rect.bottom-_clnt_rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
1587 	} else {
1588 		//_split_pos = -1;
1589 		cx = 0;
1590 	}
1591 
1592 	if (_right_hwnd)
1593 		hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, _clnt_rect.left+cx+1, _clnt_rect.top, _clnt_rect.right-cx, _clnt_rect.bottom-_clnt_rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
1594 
1595 	EndDeferWindowPos(hdwp);
1596 }
1597 
1598 void SDIMainFrame::update_clnt_rect()
1599 {
1600 	ClientRect rect(_hwnd);
1601 
1602 	resize_frame(rect.right, rect.bottom);
1603 }
1604 
1605 void SDIMainFrame::update_shell_browser()
1606 {
1607 	int split_pos = DEFAULT_SPLIT_POS;
1608 
1609 	if (_shellBrowser.get()) {
1610 		split_pos = _split_pos;
1611 		delete _shellBrowser.release();
1612 	}
1613 
1614 	 // create explorer treeview
1615 	if (_shellpath_info._open_mode & OWM_EXPLORE) {
1616 		if (!_left_hwnd) {
1617 			ClientRect rect(_hwnd);
1618 
1619 			_left_hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
1620 							WS_CHILD|WS_TABSTOP|WS_VISIBLE|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_NOTOOLTIPS|TVS_SHOWSELALWAYS,
1621 							0, rect.top, split_pos-SPLIT_WIDTH/2, rect.bottom-rect.top,
1622 							_hwnd, (HMENU)IDC_FILETREE, g_Globals._hInstance, 0);
1623 
1624 			 // display tree window as long as the shell view is not yet visible
1625 			resize_frame(rect.right, rect.bottom);
1626 			MoveWindow(_left_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
1627 		}
1628 	} else {
1629 		if (_left_hwnd) {
1630 			DestroyWindow(_left_hwnd);
1631 			_left_hwnd = 0;
1632 		}
1633 	}
1634 
1635 	_shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _hwnd, _left_hwnd, _right_hwnd,
1636 												_shellpath_info, this, _cm_ifs));
1637 
1638 	if (_left_hwnd)
1639 		_shellBrowser->Init();
1640 
1641 	 // update _clnt_rect and set size of new created shell view windows
1642 	update_clnt_rect();
1643 }
1644 
1645 void SDIMainFrame::entry_selected(Entry* entry)
1646 {
1647 	if (_left_hwnd)
1648 		_shellBrowser->select_folder(entry, false);
1649 
1650 	_shellBrowser->UpdateFolderView(entry->get_shell_folder());
1651 
1652 	 // set size of new created shell view windows
1653 	resize_children();
1654 }
1655 
1656 void SDIMainFrame::set_url(LPCTSTR url)
1657 {
1658 	if (_url != url) {
1659 		_url = url;
1660 		SetWindowText(_haddrcombo, url);
1661 	}
1662 }
1663 
1664 
1665 void SDIMainFrame::jump_to(LPCTSTR path, int mode)
1666 {/*@@todo
1667 	if (_shellBrowser.get() && (_shellpath_info._open_mode&~OWM_PIDL)==(mode&~OWM_PIDL)) {
1668 		_shellBrowser->jump_to(path);
1669 
1670 		_shellpath_info._shell_path = path;
1671 	} else */{
1672 		_shellpath_info._open_mode = mode;
1673 		_shellpath_info._shell_path = path;
1674 
1675 		update_shell_browser();
1676 	}
1677 }
1678 
1679 void SDIMainFrame::jump_to(LPCITEMIDLIST path, int mode)
1680 {
1681 	if (_shellBrowser.get() && (_shellpath_info._open_mode&~OWM_PIDL)==(mode&~OWM_PIDL)) {
1682 		ShellPath shell_path = path;
1683 
1684 		_shellBrowser->jump_to(shell_path);
1685 
1686 		_shellpath_info._shell_path = shell_path;
1687 	} else {
1688 		_shellpath_info._open_mode = mode;
1689 		_shellpath_info._shell_path = path;
1690 
1691 		update_shell_browser();
1692 	}
1693 }
1694