add opened files to the "recent documents" list
[reactos.git] / reactos / subsys / system / explorer / shell / shellbrowser.cpp
1 /*
2 * Copyright 2003 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 "../utility/utility.h"
30
31 #include "../explorer.h"
32 #include "../globals.h"
33
34 #include "../explorer_intres.h"
35
36
37 static LPARAM TreeView_GetItemData(HWND hwndTreeView, HTREEITEM hItem)
38 {
39 TVITEM tvItem;
40
41 tvItem.mask = TVIF_PARAM;
42 tvItem.hItem = hItem;
43
44 if (!TreeView_GetItem(hwndTreeView, &tvItem))
45 return 0;
46
47 return tvItem.lParam;
48 }
49
50
51 ShellBrowserChild::ShellBrowserChild(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info)
52 : _hwnd(hwnd),
53 _left_hwnd(left_hwnd),
54 _right_hwnd(right_hwnd),
55 _create_info(create_info)
56 {
57 _pShellView = NULL;
58 _pDropTarget = NULL;
59 _himlSmall = 0;
60 _last_sel = 0;
61
62 // SDI integration
63 _split_pos = DEFAULT_SPLIT_POS;
64 _last_split = DEFAULT_SPLIT_POS;
65
66 _cur_dir = NULL;
67
68 Init(hwnd);
69 }
70
71 ShellBrowserChild::~ShellBrowserChild()
72 {
73 if (_pShellView)
74 _pShellView->Release();
75
76 if (_pDropTarget) {
77 _pDropTarget->Release();
78 _pDropTarget = NULL;
79 }
80
81 if (_right_hwnd) {
82 DestroyWindow(_right_hwnd);
83 _right_hwnd = 0;
84 }
85 }
86
87
88 LRESULT ShellBrowserChild::Init(HWND hWndFrame)
89 {
90 CONTEXT("ShellBrowserChild::Init()");
91
92 _hWndFrame = hWndFrame;
93
94 ClientRect rect(_hwnd);
95
96 SHFILEINFO sfi;
97
98 _himlSmall = (HIMAGELIST)SHGetFileInfo(TEXT("C:\\"), 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
99 // _himlLarge = (HIMAGELIST)SHGetFileInfo(TEXT("C:\\"), 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX|SHGFI_LARGEICON);
100
101 if (_left_hwnd) {
102 InitializeTree();
103 InitDragDrop();
104 }
105
106 const String& root_name = GetDesktopFolder().get_name(_create_info._root_shell_path, SHGDN_FORPARSING);
107
108 _root._drive_type = DRIVE_UNKNOWN;
109 lstrcpy(_root._volname, root_name); // most of the time "Desktop"
110 _root._fs_flags = 0;
111 lstrcpy(_root._fs, TEXT("Desktop"));
112
113 _root._entry = new ShellDirectory(GetDesktopFolder(), _create_info._root_shell_path, _hwnd);
114
115 jump_to(_create_info._shell_path);
116
117 // -> set_curdir()
118 _root._entry->read_directory();
119
120 /* already filled by ShellDirectory constructor
121 lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop")); */
122
123 return 0;
124 }
125
126
127 void ShellBrowserChild::InitializeTree()
128 {
129 CONTEXT("ShellBrowserChild::InitializeTree()");
130
131 TreeView_SetImageList(_left_hwnd, _himlSmall, TVSIL_NORMAL);
132 TreeView_SetScrollTime(_left_hwnd, 100);
133
134 TV_ITEM tvItem;
135
136 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
137 tvItem.lParam = (LPARAM)_root._entry;
138 tvItem.pszText = LPSTR_TEXTCALLBACK;
139 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
140 tvItem.cChildren = 1;
141
142 TV_INSERTSTRUCT tvInsert;
143
144 tvInsert.hParent = 0;
145 tvInsert.hInsertAfter = TVI_LAST;
146 tvInsert.item = tvItem;
147
148 HTREEITEM hItem = TreeView_InsertItem(_left_hwnd, &tvInsert);
149 TreeView_SelectItem(_left_hwnd, hItem);
150 TreeView_Expand(_left_hwnd, hItem, TVE_EXPAND);
151 }
152
153
154 bool ShellBrowserChild::InitDragDrop()
155 {
156 CONTEXT("ShellBrowserChild::InitDragDrop()");
157
158 _pDropTarget = new TreeDropTarget(_left_hwnd);
159
160 if (!_pDropTarget)
161 return false;
162
163 _pDropTarget->AddRef();
164
165 if (FAILED(RegisterDragDrop(_left_hwnd, _pDropTarget))) {//calls addref
166 _pDropTarget->Release(); // free TreeDropTarget
167 _pDropTarget = NULL;
168 return false;
169 }
170 else
171 _pDropTarget->Release();
172
173 FORMATETC ftetc;
174
175 ftetc.dwAspect = DVASPECT_CONTENT;
176 ftetc.lindex = -1;
177 ftetc.tymed = TYMED_HGLOBAL;
178 ftetc.cfFormat = CF_HDROP;
179
180 _pDropTarget->AddSuportedFormat(ftetc);
181
182 return true;
183 }
184
185
186 void ShellBrowserChild::OnTreeItemRClick(int idCtrl, LPNMHDR pnmh)
187 {
188 CONTEXT("ShellBrowserChild::OnTreeItemRClick()");
189
190 TVHITTESTINFO tvhti;
191
192 GetCursorPos(&tvhti.pt);
193 ScreenToClient(_left_hwnd, &tvhti.pt);
194
195 tvhti.flags = LVHT_NOWHERE;
196 TreeView_HitTest(_left_hwnd, &tvhti);
197
198 if (TVHT_ONITEM & tvhti.flags) {
199 ClientToScreen(_left_hwnd, &tvhti.pt);
200 Tree_DoItemMenu(_left_hwnd, tvhti.hItem , &tvhti.pt);
201 }
202 }
203
204 void ShellBrowserChild::Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPOINT pptScreen)
205 {
206 CONTEXT("ShellBrowserChild::Tree_DoItemMenu()");
207
208 LPARAM itemData = TreeView_GetItemData(hwndTreeView, hItem);
209
210 if (itemData) {
211 Entry* entry = (Entry*)itemData;
212
213 if (entry->_etype == ET_SHELL) {
214 ShellDirectory* dir = static_cast<ShellDirectory*>(entry->_up);
215 ShellFolder folder = dir? dir->_folder: GetDesktopFolder();
216 LPCITEMIDLIST pidl = static_cast<ShellEntry*>(entry)->_pidl;
217
218 CHECKERROR(ShellFolderContextMenu(folder, ::GetParent(hwndTreeView), 1, &pidl, pptScreen->x, pptScreen->y));
219 } else {
220 ShellPath shell_path = entry->create_absolute_pidl();
221 LPCITEMIDLIST pidl = shell_path;
222
223 ///@todo use parent folder instead of desktop
224 CHECKERROR(ShellFolderContextMenu(GetDesktopFolder(), _hwnd, 1, &pidl, pptScreen->x, pptScreen->y));
225 }
226 }
227 }
228
229 void ShellBrowserChild::OnTreeGetDispInfo(int idCtrl, LPNMHDR pnmh)
230 {
231 CONTEXT("ShellBrowserChild::OnTreeGetDispInfo()");
232
233 LPNMTVDISPINFO lpdi = (LPNMTVDISPINFO)pnmh;
234 ShellEntry* entry = (ShellEntry*)lpdi->item.lParam;
235
236 if (lpdi->item.mask & TVIF_TEXT)
237 lpdi->item.pszText = entry->_display_name;
238
239 if (lpdi->item.mask & (/*TVIF_TEXT|*/TVIF_IMAGE|TVIF_SELECTEDIMAGE)) {
240 ShellPath pidl_abs = entry->create_absolute_pidl(); // Caching of absolute PIDLs could enhance performance.
241 LPCITEMIDLIST pidl = pidl_abs;
242
243 SHFILEINFO sfi;
244 /*
245 if (lpdi->item.mask & TVIF_TEXT)
246 if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_DISPLAYNAME))
247 lstrcpy(lpdi->item.pszText, sfi.szDisplayName); ///@todo look at cchTextMax if there is enough space available
248 else
249 lpdi->item.pszText = entry->_data.cFileName;
250 */
251 if (lpdi->item.mask & TVIF_IMAGE)
252 if ((HIMAGELIST)SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_LINKOVERLAY) == _himlSmall)
253 lpdi->item.iImage = sfi.iIcon;
254 else
255 lpdi->item.iImage = -1;
256
257 if (lpdi->item.mask & TVIF_SELECTEDIMAGE)
258 if ((HIMAGELIST)SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_OPENICON) == _himlSmall)
259 lpdi->item.iSelectedImage = sfi.iIcon;
260 else
261 lpdi->item.iSelectedImage = -1;
262 }
263 }
264
265 void ShellBrowserChild::OnTreeItemExpanding(int idCtrl, LPNMTREEVIEW pnmtv)
266 {
267 CONTEXT("ShellBrowserChild::OnTreeItemExpanding()");
268
269 if (pnmtv->action == TVE_COLLAPSE)
270 TreeView_Expand(_left_hwnd, pnmtv->itemNew.hItem, TVE_COLLAPSE|TVE_COLLAPSERESET);
271 else if (pnmtv->action == TVE_EXPAND) {
272 ShellDirectory* entry = (ShellDirectory*)TreeView_GetItemData(_left_hwnd, pnmtv->itemNew.hItem);
273
274 if (entry)
275 if (!InsertSubitems(pnmtv->itemNew.hItem, entry, entry->_folder)) {
276 entry->_shell_attribs &= ~SFGAO_HASSUBFOLDER;
277
278 // remove subitem "+"
279 TV_ITEM tvItem;
280
281 tvItem.mask = TVIF_CHILDREN;
282 tvItem.hItem = pnmtv->itemNew.hItem;
283 tvItem.cChildren = 0;
284
285 TreeView_SetItem(_left_hwnd, &tvItem);
286 }
287 }
288 }
289
290 int ShellBrowserChild::InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder)
291 {
292 CONTEXT("ShellBrowserChild::InsertSubitems()");
293
294 WaitCursor wait;
295
296 int cnt = 0;
297
298 SendMessage(_left_hwnd, WM_SETREDRAW, FALSE, 0);
299
300 try {
301 entry->smart_scan();
302 } catch(COMException& e) {
303 HandleException(e, g_Globals._hMainWnd);
304 }
305
306 TV_ITEM tvItem;
307 TV_INSERTSTRUCT tvInsert;
308
309 for(entry=entry->_down; entry; entry=entry->_next) {
310 #ifndef _LEFT_FILES
311 if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
312 #endif
313 {
314 ZeroMemory(&tvItem, sizeof(tvItem));
315
316 tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
317 tvItem.pszText = LPSTR_TEXTCALLBACK;
318 tvItem.iImage = tvItem.iSelectedImage = I_IMAGECALLBACK;
319 tvItem.lParam = (LPARAM)entry;
320 tvItem.cChildren = entry->_shell_attribs & SFGAO_HASSUBFOLDER? 1: 0;
321
322 if (entry->_shell_attribs & SFGAO_SHARE) {
323 tvItem.mask |= TVIF_STATE;
324 tvItem.stateMask |= TVIS_OVERLAYMASK;
325 tvItem.state |= INDEXTOOVERLAYMASK(1);
326 }
327
328 tvInsert.item = tvItem;
329 tvInsert.hInsertAfter = TVI_LAST;
330 tvInsert.hParent = hParentItem;
331
332 TreeView_InsertItem(_left_hwnd, &tvInsert);
333 }
334
335 ++cnt;
336 }
337
338 SendMessage(_left_hwnd, WM_SETREDRAW, TRUE, 0);
339
340 return cnt;
341 }
342
343 void ShellBrowserChild::OnTreeItemSelected(int idCtrl, LPNMTREEVIEW pnmtv)
344 {
345 CONTEXT("ShellBrowserChild::OnTreeItemSelected()");
346
347 _last_sel = pnmtv->itemNew.hItem;
348 Entry* entry = (Entry*)pnmtv->itemNew.lParam;
349
350 jump_to(entry);
351 }
352
353 void ShellBrowserChild::UpdateFolderView(IShellFolder* folder)
354 {
355 CONTEXT("ShellBrowserChild::UpdateFolderView()");
356
357 FOLDERSETTINGS fs;
358 IShellView* pLastShellView = _pShellView;
359
360 _folder = folder;
361
362 if (pLastShellView)
363 pLastShellView->GetCurrentInfo(&fs);
364 else {
365 fs.ViewMode = _create_info._open_mode&OWM_DETAILS? FVM_DETAILS: FVM_ICON;
366 fs.fFlags = FWF_BESTFITWINDOW;
367 }
368
369 HRESULT hr = folder->CreateViewObject(_hwnd, IID_IShellView, (void**)&_pShellView);
370
371 if (FAILED(hr)) {
372 _pShellView = NULL;
373 return;
374 }
375
376 RECT rect = {CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT};
377 hr = _pShellView->CreateViewWindow(pLastShellView, &fs, static_cast<IShellBrowser*>(this), &rect, &_right_hwnd/*&m_hWndListView*/);
378
379 if (pLastShellView) {
380 pLastShellView->GetCurrentInfo(&fs);
381 pLastShellView->UIActivate(SVUIA_DEACTIVATE);
382 pLastShellView->DestroyViewWindow();
383 pLastShellView->Release();
384
385 resize_children();
386 }
387
388 _pShellView->UIActivate(SVUIA_ACTIVATE_NOFOCUS);
389 }
390
391
392 void ShellBrowserChild::resize_children()
393 {
394 RECT rect = _clnt_rect;
395
396 HDWP hdwp = BeginDeferWindowPos(2);
397
398 int cx = rect.left;
399
400 if (_left_hwnd) {
401 cx = _split_pos + SPLIT_WIDTH/2;
402
403 hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, rect.left, rect.top, _split_pos-SPLIT_WIDTH/2-rect.left, rect.bottom-rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
404 } else {
405 _split_pos = 0;
406 cx = 0;
407 }
408
409 if (_right_hwnd)
410 hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rect.left+cx+1, rect.top, rect.right-cx, rect.bottom-rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
411
412 EndDeferWindowPos(hdwp);
413 }
414
415
416 LRESULT ShellBrowserChild::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
417 {
418 switch(nmsg) {
419 case WM_GETISHELLBROWSER: // for Registry Explorer Plugin
420 return (LRESULT)static_cast<IShellBrowser*>(this);
421
422
423 // SDI integration:
424
425 case WM_PAINT: {
426 PaintCanvas canvas(_hwnd);
427 ClientRect rt(_hwnd);
428 rt.left = _split_pos-SPLIT_WIDTH/2;
429 rt.right = _split_pos+SPLIT_WIDTH/2+1;
430
431 if (_right_hwnd) {
432 WindowRect right_rect(_right_hwnd);
433 ScreenToClient(_hwnd, &right_rect);
434 rt.top = right_rect.top;
435 rt.bottom = right_rect.bottom;
436 }
437
438 HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR));
439 Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1);
440 SelectObject(canvas, lastBrush);
441 break;}
442
443 case WM_SETCURSOR:
444 if (LOWORD(lparam) == HTCLIENT) {
445 POINT pt;
446 GetCursorPos(&pt);
447 ScreenToClient(_hwnd, &pt);
448
449 if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) {
450 SetCursor(LoadCursor(0, IDC_SIZEWE));
451 return TRUE;
452 }
453 }
454 goto def;
455
456 case WM_LBUTTONDOWN: {
457 int x = GET_X_LPARAM(lparam);
458
459 ClientRect rt(_hwnd);
460
461 if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) {
462 _last_split = _split_pos;
463 SetCapture(_hwnd);
464 }
465
466 break;}
467
468 case WM_LBUTTONUP:
469 if (GetCapture() == _hwnd)
470 ReleaseCapture();
471 break;
472
473 case WM_KEYDOWN:
474 if (wparam == VK_ESCAPE)
475 if (GetCapture() == _hwnd) {
476 _split_pos = _last_split;
477 resize_children();
478 _last_split = -1;
479 ReleaseCapture();
480 SetCursor(LoadCursor(0, IDC_ARROW));
481 }
482 break;
483
484 case WM_MOUSEMOVE:
485 if (GetCapture() == _hwnd) {
486 int x = LOWORD(lparam);
487
488 ClientRect rt(_hwnd);
489
490 if (x>=0 && x<rt.right) {
491 _split_pos = x;
492 resize_children();
493 rt.left = x-SPLIT_WIDTH/2;
494 rt.right = x+SPLIT_WIDTH/2+1;
495 InvalidateRect(_hwnd, &rt, FALSE);
496 UpdateWindow(_left_hwnd);
497 UpdateWindow(_hwnd);
498 UpdateWindow(_right_hwnd);
499 }
500 }
501 break;
502
503
504 default: def:
505 return DefWindowProc(_hwnd, nmsg, wparam, lparam);
506 }
507
508 return 0;
509 }
510
511 int ShellBrowserChild::Command(int id, int code)
512 {
513 switch(id) {
514 case ID_BROWSE_BACK:
515 break;//@todo
516
517 case ID_BROWSE_FORWARD:
518 break;//@todo
519
520 case ID_BROWSE_UP:
521 if (_left_hwnd) {
522 //@@ not necessary in this simply case: jump_to(_cur_dir->_up);
523
524 //@@ -> move into jump_to()
525 HTREEITEM hitem = TreeView_GetParent(_left_hwnd, _last_sel);
526
527 if (hitem)
528 TreeView_SelectItem(_left_hwnd, hitem); // sends TVN_SELCHANGED notification
529 } else {
530 if (_cur_dir->_up)
531 jump_to(_cur_dir->_up);
532 }
533 break;
534
535 default:
536 return 1;
537 }
538
539 return 0;
540 }
541
542 int ShellBrowserChild::Notify(int id, NMHDR* pnmh)
543 {
544 switch(pnmh->code) {
545 case TVN_GETDISPINFO: OnTreeGetDispInfo(id, pnmh); break;
546 case TVN_ITEMEXPANDING: OnTreeItemExpanding(id, (LPNMTREEVIEW)pnmh); break;
547 case TVN_SELCHANGED: OnTreeItemSelected(id, (LPNMTREEVIEW)pnmh); break;
548 case NM_RCLICK: OnTreeItemRClick(id, pnmh); break;
549 }
550
551 return 0;
552 }
553
554
555 HRESULT ShellBrowserChild::OnDefaultCommand(LPIDA pida)
556 {
557 CONTEXT("ShellBrowserChild::OnDefaultCommand()");
558
559 if (pida->cidl >= 1) {
560 if (_left_hwnd) { // explorer mode
561 //@@if (_last_sel) {
562 ShellDirectory* parent = _cur_dir;//@@(ShellDirectory*)TreeView_GetItemData(_left_hwnd, _last_sel);
563
564 if (parent) {
565 try {
566 parent->smart_scan();
567 } catch(COMException& e) {
568 return e.Error();
569 }
570
571 UINT firstOffset = pida->aoffset[1];
572 LPITEMIDLIST pidl = (LPITEMIDLIST)((LPBYTE)pida+firstOffset);
573
574 Entry* entry = parent->find_entry(pidl);
575
576 if (entry && (entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
577 if (entry->_etype == ET_SHELL)
578 if (expand_folder(static_cast<ShellDirectory*>(entry)))
579 return S_OK;
580 }
581 //@@}
582 } else { // no tree control
583 if (MainFrame::OpenShellFolders(pida, _hWndFrame))
584 return S_OK;
585
586 /* create new Frame Window
587 if (MainFrame::OpenShellFolders(pida, 0))
588 return S_OK;
589 */
590 }
591 }
592
593 return E_NOTIMPL;
594 }
595
596
597 bool ShellBrowserChild::expand_folder(ShellDirectory* entry)
598 {
599 CONTEXT("ShellBrowserChild::expand_folder()");
600
601 //HTREEITEM hitem_sel = TreeView_GetSelection(_left_hwnd);
602 if (!_last_sel)
603 return false;
604
605 if (!TreeView_Expand(_left_hwnd, _last_sel, TVE_EXPAND))
606 return false;
607
608 for(HTREEITEM hitem=TreeView_GetChild(_left_hwnd,_last_sel); hitem; hitem=TreeView_GetNextSibling(_left_hwnd,hitem)) {
609 if ((ShellDirectory*)TreeView_GetItemData(_left_hwnd,hitem) == entry) {
610 if (TreeView_SelectItem(_left_hwnd, hitem) &&
611 TreeView_Expand(_left_hwnd, hitem, TVE_EXPAND))
612 return true;
613
614 break;
615 }
616 }
617
618 return false;
619 }
620
621
622 void ShellBrowserChild::jump_to(LPCTSTR path)
623 {
624 ///@todo implement "file://", ... parsing
625 jump_to(ShellPath(path));
626 }
627
628
629 void ShellBrowserChild::jump_to(LPCITEMIDLIST pidl)
630 {
631 Entry* entry = NULL;
632
633 //@@
634 if (!_cur_dir)
635 _cur_dir = static_cast<ShellDirectory*>(_root._entry);
636
637 /*@todo
638 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
639 _root._entry->read_tree(shell_info._root_shell_path.get_folder(), info._shell_path, SORT_NAME);
640 -> see FileChildWindow::FileChildWindow()
641 */
642
643 if (_cur_dir) {
644 static DynamicFct<LPITEMIDLIST(WINAPI*)(LPCITEMIDLIST, LPCITEMIDLIST)> ILFindChild(TEXT("SHELL32"), 24);
645
646 LPCITEMIDLIST child_pidl;
647
648 if (ILFindChild)
649 child_pidl = (*ILFindChild)(_cur_dir->create_absolute_pidl(), pidl);
650 else
651 child_pidl = pidl; // This is not correct in the common case, but works on the desktop level.
652
653 if (child_pidl) {
654 _cur_dir->smart_scan();
655
656 entry = _cur_dir->find_entry(child_pidl);
657
658 if (entry)
659 jump_to(entry);
660 }
661 }
662
663 //@@ work around as long as we don't iterate correctly through the ShellEntry tree
664 if (!entry) {
665 UpdateFolderView(ShellFolder(pidl));
666 }
667 }
668
669 void ShellBrowserChild::jump_to(Entry* entry)
670 {
671 if (entry->_etype == ET_SHELL) {
672 IShellFolder* folder;
673 ShellDirectory* se = static_cast<ShellDirectory*>(entry);
674
675 if (se->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
676 folder = static_cast<ShellDirectory*>(se)->_folder;
677 else
678 folder = se->get_parent_folder();
679
680 if (!folder) {
681 assert(folder);
682 return;
683 }
684
685 UpdateFolderView(folder);
686
687 _cur_dir = se;
688 }
689 }