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