work around GCC's wide string constant bug to fix tree list image loading
[reactos.git] / reactos / subsys / system / explorer / shell / shellbrowser.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 // shellbrowser.cpp
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28
29 #include <precomp.h>
30
31 #include "../resource.h"
32
33
34 // work around GCC's wide string constant bug
35 #ifdef __GNUC__
36 const LPCTSTR C_DRIVE = C_DRIVE_STR;
37 #endif
38
39
40 ShellBrowser::ShellBrowser(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info,
41 HIMAGELIST himl, BrowserCallback* cb, CtxMenuInterfaces& cm_ifs)
42 #ifndef __MINGW32__ // IShellFolderViewCB missing in MinGW (as of 25.09.2005)
43 : super(IID_IShellFolderViewCB),
44 #else
45 :
46 #endif
47 _hwnd(hwnd),
48 _left_hwnd(left_hwnd),
49 _right_hwnd(right_hwnd),
50 _create_info(create_info),
51 _himl(himl),
52 _callback(cb),
53 _cm_ifs(cm_ifs)
54 {
55 _pShellView = NULL;
56 _pDropTarget = NULL;
57 _last_sel = 0;
58
59 _cur_dir = NULL;
60 }
61
62 ShellBrowser::~ShellBrowser()
63 {
64 (void)TreeView_SetImageList(_left_hwnd, _himl_old, TVSIL_NORMAL);
65
66 if (_pShellView)
67 _pShellView->Release();
68
69 if (_pDropTarget) {
70 _pDropTarget->Release();
71 _pDropTarget = NULL;
72 }
73
74 if (_right_hwnd) {
75 DestroyWindow(_right_hwnd);
76 _right_hwnd = 0;
77 }
78 }
79
80
81 LRESULT ShellBrowser::Init(HWND hWndFrame)
82 {
83 CONTEXT("ShellBrowser::Init()");
84
85 _hWndFrame = hWndFrame;
86
87 const String& root_name = GetDesktopFolder().get_name(_create_info._root_shell_path, SHGDN_FORADDRESSBAR);
88
89 _root._drive_type = DRIVE_UNKNOWN;
90 lstrcpy(_root._volname, root_name);
91 _root._fs_flags = 0;
92 lstrcpy(_root._fs, TEXT("Desktop"));
93
94 _root._entry = new ShellDirectory(GetDesktopFolder(), _create_info._root_shell_path, _hwnd);
95
96 jump_to(_create_info._shell_path);
97
98 // -> set_curdir()
99 _root._entry->read_directory();
100
101 /* already filled by ShellDirectory constructor
102 lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop")); */
103
104 return 0;
105 }
106
107 void ShellBrowser::jump_to(LPCITEMIDLIST pidl)
108 {
109 Entry* entry = NULL;
110
111 //@@
112 if (!_cur_dir)
113 _cur_dir = static_cast<ShellDirectory*>(_root._entry);
114
115 /*@todo
116 we should call read_tree() here to iterate through the hierarchy and open all folders from shell_info._root_shell_path to shell_info._shell_path
117 _root._entry->read_tree(shell_info._root_shell_path.get_folder(), info._shell_path, SORT_NAME);
118 -> see FileChildWindow::FileChildWindow()
119 */
120
121 LOG(FmtString(TEXT("ShellBrowser::jump_to(): pidl=%s"), (LPCTSTR)FileSysShellPath(pidl)));
122
123 if (_cur_dir) {
124 static DynamicFct<LPITEMIDLIST(WINAPI*)(LPCITEMIDLIST, LPCITEMIDLIST)> ILFindChild(TEXT("SHELL32"), 24);
125
126 LPCITEMIDLIST child_pidl;
127
128 if (ILFindChild)
129 child_pidl = (*ILFindChild)(_cur_dir->create_absolute_pidl(), pidl);
130 else
131 child_pidl = pidl; // This is not correct in the common case, but works on the desktop level.
132
133 if (child_pidl) {
134 _cur_dir->smart_scan();
135
136 entry = _cur_dir->find_entry(child_pidl);
137
138 if (entry) {
139 _cur_dir = static_cast<ShellDirectory*>(entry);
140 _callback->entry_selected(entry);
141 }
142 }
143 }
144
145 //@@ work around as long as we don't iterate correctly through the ShellEntry tree
146 if (!entry)
147 UpdateFolderView(ShellFolder(pidl));
148 }
149
150
151 void ShellBrowser::InitializeTree(HIMAGELIST himl)
152 {
153 CONTEXT("ShellBrowserChild::InitializeTree()");
154
155 _himl_old = TreeView_SetImageList(_left_hwnd, himl, TVSIL_NORMAL);
156 TreeView_SetScrollTime(_left_hwnd, 100);
157
158 TV_INSERTSTRUCT tvInsert;
159
160 tvInsert.hParent = 0;
161 tvInsert.hInsertAfter = TVI_LAST;
162
163 TV_ITEM& tvItem = tvInsert.item;
164 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
165 tvItem.lParam = (LPARAM)_root._entry;
166 tvItem.pszText = LPSTR_TEXTCALLBACK;
167 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
168 tvItem.cChildren = 1;
169
170 HTREEITEM hItem = TreeView_InsertItem(_left_hwnd, &tvInsert);
171 TreeView_SelectItem(_left_hwnd, hItem);
172 TreeView_Expand(_left_hwnd, hItem, TVE_EXPAND);
173 }
174
175 bool ShellBrowser::InitDragDrop()
176 {
177 CONTEXT("ShellBrowser::InitDragDrop()");
178
179 _pDropTarget = new TreeDropTarget(_left_hwnd);
180
181 if (!_pDropTarget)
182 return false;
183
184 _pDropTarget->AddRef();
185
186 if (FAILED(RegisterDragDrop(_left_hwnd, _pDropTarget))) {//calls addref
187 _pDropTarget->Release(); // free TreeDropTarget
188 _pDropTarget = NULL;
189 return false;
190 }
191 else
192 _pDropTarget->Release();
193
194 FORMATETC ftetc;
195
196 ftetc.dwAspect = DVASPECT_CONTENT;
197 ftetc.lindex = -1;
198 ftetc.tymed = TYMED_HGLOBAL;
199 ftetc.cfFormat = CF_HDROP;
200
201 _pDropTarget->AddSuportedFormat(ftetc);
202
203 return true;
204 }
205
206
207 void ShellBrowser::OnTreeItemRClick(int idCtrl, LPNMHDR pnmh)
208 {
209 CONTEXT("ShellBrowser::OnTreeItemRClick()");
210
211 TVHITTESTINFO tvhti;
212
213 GetCursorPos(&tvhti.pt);
214 ScreenToClient(_left_hwnd, &tvhti.pt);
215
216 tvhti.flags = LVHT_NOWHERE;
217 (void)TreeView_HitTest(_left_hwnd, &tvhti);
218
219 if (TVHT_ONITEM & tvhti.flags) {
220 LPARAM itemData = TreeView_GetItemData(_left_hwnd, tvhti.hItem);
221
222 if (itemData) {
223 Entry* entry = (Entry*)itemData;
224 ClientToScreen(_left_hwnd, &tvhti.pt);
225
226 CHECKERROR(entry->do_context_menu(_hwnd, tvhti.pt, _cm_ifs));
227 }
228 }
229 }
230
231 void ShellBrowser::OnTreeGetDispInfo(int idCtrl, LPNMHDR pnmh)
232 {
233 CONTEXT("ShellBrowser::OnTreeGetDispInfo()");
234
235 LPNMTVDISPINFO lpdi = (LPNMTVDISPINFO)pnmh;
236 ShellEntry* entry = (ShellEntry*)lpdi->item.lParam;
237
238 if (entry) {
239 if (lpdi->item.mask & TVIF_TEXT)
240 lpdi->item.pszText = entry->_display_name;
241
242 if (lpdi->item.mask & (/*TVIF_TEXT|*/TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
243 ShellPath pidl_abs = entry->create_absolute_pidl(); // Caching of absolute PIDLs could enhance performance.
244 LPCITEMIDLIST pidl = pidl_abs;
245
246 SHFILEINFO sfi;
247 /*
248 if (lpdi->item.mask & TVIF_TEXT)
249 if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_DISPLAYNAME))
250 lstrcpy(lpdi->item.pszText, sfi.szDisplayName); ///@todo look at cchTextMax if there is enough space available
251 else
252 lpdi->item.pszText = entry->_data.cFileName;
253 */
254 if (lpdi->item.mask & TVIF_IMAGE)
255 if ((HIMAGELIST)SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_LINKOVERLAY) == _himl)
256 lpdi->item.iImage = sfi.iIcon;
257 else
258 lpdi->item.iImage = -1;
259
260 if (lpdi->item.mask & TVIF_SELECTEDIMAGE)
261 if ((HIMAGELIST)SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_OPENICON) == _himl)
262 lpdi->item.iSelectedImage = sfi.iIcon;
263 else
264 lpdi->item.iSelectedImage = -1;
265 }
266 }
267 }
268
269 void ShellBrowser::OnTreeItemExpanding(int idCtrl, LPNMTREEVIEW pnmtv)
270 {
271 CONTEXT("ShellBrowser::OnTreeItemExpanding()");
272
273 if (pnmtv->action == TVE_COLLAPSE)
274 TreeView_Expand(_left_hwnd, pnmtv->itemNew.hItem, TVE_COLLAPSE|TVE_COLLAPSERESET);
275 else if (pnmtv->action == TVE_EXPAND) {
276 ShellDirectory* entry = (ShellDirectory*)TreeView_GetItemData(_left_hwnd, pnmtv->itemNew.hItem);
277
278 if (entry)
279 if (!InsertSubitems(pnmtv->itemNew.hItem, entry, entry->_folder)) {
280 entry->_shell_attribs &= ~SFGAO_HASSUBFOLDER;
281
282 // remove subitem "+"
283 TV_ITEM tvItem;
284
285 tvItem.mask = TVIF_CHILDREN;
286 tvItem.hItem = pnmtv->itemNew.hItem;
287 tvItem.cChildren = 0;
288
289 TreeView_SetItem(_left_hwnd, &tvItem);
290 }
291 }
292 }
293
294 int ShellBrowser::InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder)
295 {
296 CONTEXT("ShellBrowser::InsertSubitems()");
297
298 WaitCursor wait;
299
300 int cnt = 0;
301
302 SendMessage(_left_hwnd, WM_SETREDRAW, FALSE, 0);
303
304 try {
305 entry->smart_scan();
306 } catch(COMException& e) {
307 HandleException(e, g_Globals._hMainWnd);
308 }
309
310 TV_ITEM tvItem;
311 TV_INSERTSTRUCT tvInsert;
312
313 for(entry=entry->_down; entry; entry=entry->_next) {
314 #ifndef _LEFT_FILES
315 if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
316 #endif
317 {
318 ZeroMemory(&tvItem, sizeof(tvItem));
319
320 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
321 tvItem.pszText = LPSTR_TEXTCALLBACK;
322 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
323 tvItem.lParam = (LPARAM)entry;
324 tvItem.cChildren = entry->_shell_attribs & SFGAO_HASSUBFOLDER? 1: 0;
325
326 if (entry->_shell_attribs & SFGAO_SHARE) {
327 tvItem.mask |= TVIF_STATE;
328 tvItem.stateMask |= TVIS_OVERLAYMASK;
329 tvItem.state |= INDEXTOOVERLAYMASK(1);
330 }
331
332 tvInsert.item = tvItem;
333 tvInsert.hInsertAfter = TVI_LAST;
334 tvInsert.hParent = hParentItem;
335
336 (void)TreeView_InsertItem(_left_hwnd, &tvInsert);
337 }
338
339 ++cnt;
340 }
341
342 SendMessage(_left_hwnd, WM_SETREDRAW, TRUE, 0);
343
344 return cnt;
345 }
346
347 void ShellBrowser::OnTreeItemSelected(int idCtrl, LPNMTREEVIEW pnmtv)
348 {
349 CONTEXT("ShellBrowser::OnTreeItemSelected()");
350
351 ShellEntry* entry = (ShellEntry*)pnmtv->itemNew.lParam;
352
353 _last_sel = pnmtv->itemNew.hItem;
354
355 if (entry)
356 _callback->entry_selected(entry);
357 }
358
359 void ShellBrowser::UpdateFolderView(IShellFolder* folder)
360 {
361 CONTEXT("ShellBrowser::UpdateFolderView()");
362
363 FOLDERSETTINGS fs;
364 IShellView* pLastShellView = _pShellView;
365
366 _folder = folder;
367
368 if (pLastShellView)
369 pLastShellView->GetCurrentInfo(&fs);
370 else {
371 fs.ViewMode = _create_info._open_mode&OWM_DETAILS? FVM_DETAILS: FVM_ICON;
372 fs.fFlags = FWF_NOCLIENTEDGE|FWF_BESTFITWINDOW;
373 }
374
375 #ifndef __MINGW32__ // IShellFolderViewCB missing in MinGW (as of 25.09.2005)
376 SFV_CREATE sfv_create;
377
378 sfv_create.cbSize = sizeof(SFV_CREATE);
379 sfv_create.pshf = folder;
380 sfv_create.psvOuter = NULL;
381 sfv_create.psfvcb = this;
382
383 HRESULT hr = SHCreateShellFolderView(&sfv_create, &_pShellView);
384 #else
385 HRESULT hr = folder->CreateViewObject(_hwnd, IID_IShellView, (void**)&_pShellView);
386 #endif
387
388 if (FAILED(hr)) {
389 _pShellView = NULL;
390 return;
391 }
392
393 RECT rect = {CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT};
394 hr = _pShellView->CreateViewWindow(pLastShellView, &fs, static_cast<IShellBrowser*>(this), &rect, &_right_hwnd/*&m_hWndListView*/);
395
396 if (pLastShellView) {
397 pLastShellView->GetCurrentInfo(&fs);
398 pLastShellView->UIActivate(SVUIA_DEACTIVATE);
399 pLastShellView->DestroyViewWindow();
400 pLastShellView->Release();
401 }
402
403 _pShellView->UIActivate(SVUIA_ACTIVATE_NOFOCUS);
404 }
405
406
407 #ifndef __MINGW32__ // IShellFolderViewCB missing in MinGW (as of 25.09.2005)
408
409 /// shell view callback
410 HRESULT STDMETHODCALLTYPE ShellBrowser::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
411 {
412 if (uMsg == SFVM_INITMENUPOPUP) {
413 //@todo never reached
414 InsertMenu((HMENU)lParam, 0, MF_BYPOSITION, 12345, TEXT("TEST ENTRY"));
415 return S_OK;
416 }
417
418 return E_NOTIMPL;
419 }
420
421 #endif
422
423
424 HRESULT ShellBrowser::OnDefaultCommand(LPIDA pida)
425 {
426 CONTEXT("ShellBrowser::OnDefaultCommand()");
427
428 if (pida->cidl >= 1) {
429 if (_left_hwnd) { // explorer mode
430 if (_last_sel) {
431 ShellDirectory* parent = (ShellDirectory*)TreeView_GetItemData(_left_hwnd, _last_sel);
432
433 if (parent) {
434 try {
435 parent->smart_scan();
436 } catch(COMException& e) {
437 return e.Error();
438 }
439
440 UINT firstOffset = pida->aoffset[1];
441 LPITEMIDLIST pidl = (LPITEMIDLIST)((LPBYTE)pida+firstOffset);
442
443 Entry* entry = parent->find_entry(pidl);
444
445 if (entry && (entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
446 if (entry->_etype == ET_SHELL)
447 if (_last_sel && select_entry(_last_sel, entry))
448 return S_OK;
449 }
450 }
451 } else { // no tree control
452 if (MainFrameBase::OpenShellFolders(pida, _hWndFrame))
453 return S_OK;
454
455 /* create new Frame Window
456 if (MainFrame::OpenShellFolders(pida, 0))
457 return S_OK;
458 */
459 }
460 }
461
462 return E_NOTIMPL;
463 }
464
465
466 HTREEITEM ShellBrowser::select_entry(HTREEITEM hitem, Entry* entry, bool expand)
467 {
468 CONTEXT("ShellBrowser::select_entry()");
469
470 if (expand && !TreeView_Expand(_left_hwnd, hitem, TVE_EXPAND))
471 return 0;
472
473 for(hitem=TreeView_GetChild(_left_hwnd,hitem); hitem; hitem=TreeView_GetNextSibling(_left_hwnd,hitem)) {
474 if ((Entry*)TreeView_GetItemData(_left_hwnd,hitem) == entry) {
475 if (TreeView_SelectItem(_left_hwnd, hitem)) {
476 if (expand)
477 TreeView_Expand(_left_hwnd, hitem, TVE_EXPAND);
478
479 return hitem;
480 }
481
482 break;
483 }
484 }
485
486 return 0;
487 }
488
489
490 bool ShellBrowser::jump_to_pidl(LPCITEMIDLIST pidl)
491 {
492 if (!_root._entry)
493 return false;
494
495 // iterate through the hierarchy and open all folders to reach pidl
496 WaitCursor wait;
497
498 HTREEITEM hitem = TreeView_GetRoot(_left_hwnd);
499 Entry* entry = _root._entry;
500
501 for(const void*p=pidl;;) {
502 if (!p)
503 return true;
504
505 if (!entry || !hitem)
506 break;
507
508 entry->smart_scan(SORT_NAME);
509
510 Entry* found = entry->find_entry(p);
511 p = entry->get_next_path_component(p);
512
513 if (found)
514 hitem = select_entry(hitem, found);
515
516 entry = found;
517 }
518
519 return false;
520 }
521
522
523 #ifndef _NO_MDI
524
525 MDIShellBrowserChild::MDIShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info)
526 : super(hwnd, info),
527 _create_info(info),
528 _shellpath_info(info) //@@ copies info -> no referenz to _create_info !
529 {
530 /**todo Conversion of shell path into path string -> store into URL history
531 const String& path = GetDesktopFolder().get_name(info._shell_path, SHGDN_FORADDRESSBAR);
532 const String& parsingpath = GetDesktopFolder().get_name(info._shell_path, SHGDN_FORPARSING);
533
534 // store path into history
535 if (info._path && *info._path)
536 _url_history.push(info._path);
537 */
538 }
539
540
541 MDIShellBrowserChild* MDIShellBrowserChild::create(const ShellChildWndInfo& info)
542 {
543 ChildWindow* child = ChildWindow::create(info, info._pos.rcNormalPosition,
544 WINDOW_CREATOR_INFO(MDIShellBrowserChild,ShellChildWndInfo), CLASSNAME_CHILDWND, NULL, info._pos.showCmd==SW_SHOWMAXIMIZED? WS_MAXIMIZE: 0);
545
546 return static_cast<MDIShellBrowserChild*>(child);
547 }
548
549
550 LRESULT MDIShellBrowserChild::Init(LPCREATESTRUCT pcs)
551 {
552 CONTEXT("MDIShellBrowserChild::Init()");
553
554 if (super::Init(pcs))
555 return 1;
556
557 init_himl();
558
559 update_shell_browser();
560
561 if (&*_shellBrowser)
562 if (_left_hwnd)
563 _shellBrowser->Init(_himlSmall);
564 else
565 _shellBrowser->UpdateFolderView(_create_info._shell_path.get_folder());
566
567 return 0;
568 }
569
570
571 LRESULT MDIShellBrowserChild::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
572 {
573 switch(nmsg) {
574 case PM_DISPATCH_COMMAND: {
575 switch(LOWORD(wparam)) {
576 case ID_WINDOW_NEW: {CONTEXT("MDIShellBrowserChild PM_DISPATCH_COMMAND ID_WINDOW_NEW");
577 MDIShellBrowserChild::create(_create_info);
578 break;}
579
580 case ID_REFRESH:
581 //@todo refresh shell child
582 break;
583
584 case ID_VIEW_SDI:
585 MainFrameBase::Create(_url, false);
586 break;
587
588 default:
589 return super::WndProc(nmsg, wparam, lparam);
590 }
591 return TRUE;}
592
593 default:
594 return super::WndProc(nmsg, wparam, lparam);
595 }
596
597 return 0;
598 }
599
600 void MDIShellBrowserChild::update_shell_browser()
601 {
602 int split_pos = DEFAULT_SPLIT_POS;
603
604 if (_shellBrowser.get()) {
605 split_pos = _split_pos;
606 delete _shellBrowser.release();
607 }
608
609 // create explorer treeview
610 if (_create_info._open_mode & OWM_EXPLORE) {
611 if (!_left_hwnd) {
612 ClientRect rect(_hwnd);
613
614 _left_hwnd = CreateWindowEx(0, WC_TREEVIEW, NULL,
615 WS_CHILD|WS_TABSTOP|WS_VISIBLE|WS_CHILD|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS,//|TVS_NOTOOLTIPS
616 0, rect.top, split_pos-SPLIT_WIDTH/2, rect.bottom-rect.top,
617 _hwnd, (HMENU)IDC_FILETREE, g_Globals._hInstance, 0);
618 }
619 } else {
620 if (_left_hwnd) {
621 DestroyWindow(_left_hwnd);
622 _left_hwnd = 0;
623 }
624 }
625
626 _shellBrowser = auto_ptr<ShellBrowser>(new ShellBrowser(_hwnd, _left_hwnd, _right_hwnd,
627 _shellpath_info, _himlSmall, this, _cm_ifs));
628
629 _shellBrowser->Init(_hwndFrame);
630 }
631
632
633 String MDIShellBrowserChild::jump_to_int(LPCTSTR url)
634 {
635 String dir, fname;
636
637 if (!_tcsnicmp(url, TEXT("shell://"), 8)) {
638 if (_shellBrowser->jump_to_pidl(ShellPath(url+8)))
639 return url;
640 }
641
642 if (SplitFileSysURL(url, dir, fname)) {
643
644 ///@todo use fname
645
646 if (_shellBrowser->jump_to_pidl(ShellPath(dir)))
647 return FmtString(TEXT("file://%s"), (LPCTSTR)dir);
648 }
649
650 return String();
651 }
652
653
654 void MDIShellBrowserChild::entry_selected(Entry* entry)
655 {
656 if (entry->_etype == ET_SHELL) {
657 ShellEntry* shell_entry = static_cast<ShellEntry*>(entry);
658 IShellFolder* folder;
659
660 if (shell_entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
661 folder = static_cast<ShellDirectory*>(shell_entry)->_folder;
662 else
663 folder = shell_entry->get_parent_folder();
664
665 if (!folder) {
666 assert(folder);
667 return;
668 }
669
670 TCHAR path[MAX_PATH];
671
672 if (shell_entry->get_path(path, COUNTOF(path))) {
673 String url;
674
675 if (path[0] == ':')
676 url.printf(TEXT("shell://%s"), path);
677 else
678 url.printf(TEXT("file://%s"), path);
679
680 set_url(url);
681 }
682
683 _shellBrowser->UpdateFolderView(folder);
684
685 // set size of new created shell view windows
686 ClientRect rt(_hwnd);
687 resize_children(rt.right, rt.bottom);
688 }
689 }
690
691 #endif