Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / base / shell / explorer / shell / filechild.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // filechild.cpp
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28
29 #include <precomp.h>
30
31 #include "ntobjfs.h"
32 #include "regfs.h"
33 #include "fatfs.h"
34
35 #include "../resource.h"
36
37
38 FileChildWndInfo::FileChildWndInfo(HWND hmdiclient, LPCTSTR path, ENTRY_TYPE etype)
39 : super(hmdiclient),
40 _etype(etype)
41 {
42 #ifndef _NO_WIN_FS
43 if (etype == ET_UNKNOWN)
44 #ifdef __WINE__
45 if (*path == '/')
46 _etype = ET_UNIX;
47 else
48 #endif
49 _etype = ET_WINDOWS;
50 #endif
51
52 _path = path;
53
54 _pos.length = sizeof(WINDOWPLACEMENT);
55 _pos.flags = 0;
56 _pos.showCmd = SW_SHOWNORMAL;
57 _pos.rcNormalPosition.left = CW_USEDEFAULT;
58 _pos.rcNormalPosition.top = CW_USEDEFAULT;
59 _pos.rcNormalPosition.right = CW_USEDEFAULT;
60 _pos.rcNormalPosition.bottom = CW_USEDEFAULT;
61
62 _open_mode = OWM_EXPLORE|OWM_DETAILS;
63 }
64
65
66 ShellChildWndInfo::ShellChildWndInfo(HWND hmdiclient, LPCTSTR path, const ShellPath& root_shell_path)
67 : FileChildWndInfo(hmdiclient, path, ET_SHELL),
68 _shell_path(path&&*path? path: root_shell_path),
69 _root_shell_path(root_shell_path)
70 {
71 }
72
73
74 NtObjChildWndInfo::NtObjChildWndInfo(HWND hmdiclient, LPCTSTR path)
75 : FileChildWndInfo(hmdiclient, path, ET_NTOBJS)
76 {
77 }
78
79
80 RegistryChildWndInfo::RegistryChildWndInfo(HWND hmdiclient, LPCTSTR path)
81 : FileChildWndInfo(hmdiclient, path, ET_REGISTRY)
82 {
83 }
84
85
86 FATChildWndInfo::FATChildWndInfo(HWND hmdiclient, LPCTSTR path)
87 : FileChildWndInfo(hmdiclient, path, ET_FAT)
88 {
89 }
90
91
92 WebChildWndInfo::WebChildWndInfo(HWND hmdiclient, LPCTSTR url)
93 : FileChildWndInfo(hmdiclient, url, ET_WEB)
94 {
95 }
96
97
98 INT_PTR CALLBACK ExecuteDialog::WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
99 {
100 static struct ExecuteDialog* dlg;
101
102 switch(nmsg) {
103 case WM_INITDIALOG:
104 dlg = (struct ExecuteDialog*) lparam;
105 return 1;
106
107 case WM_COMMAND: {
108 int id = (int)wparam;
109
110 if (id == IDOK) {
111 GetWindowText(GetDlgItem(hwnd, 201), dlg->cmd, COUNTOF(dlg->cmd));
112 dlg->cmdshow = Button_GetState(GetDlgItem(hwnd,214))&BST_CHECKED?
113 SW_SHOWMINIMIZED: SW_SHOWNORMAL;
114 EndDialog(hwnd, id);
115 } else if (id == IDCANCEL)
116 EndDialog(hwnd, id);
117
118 return 1;}
119 }
120
121 return 0;
122 }
123
124
125 // FileChildWindow
126
127 FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
128 : super(hwnd, info)
129 {
130 CONTEXT("FileChildWindow::FileChildWindow()");
131
132 TCHAR drv[_MAX_DRIVE+1];
133 Entry* entry = NULL;
134
135 _left = NULL;
136 _right = NULL;
137
138 switch(info._etype) {
139 #ifdef __WINE__
140 case ET_UNIX:
141 _root._drive_type = GetDriveType(info._path);
142 _root._sort_order = SORT_NAME;
143
144 _tsplitpath(info._path, drv, NULL, NULL, NULL);
145 lstrcat(drv, TEXT("/"));
146 lstrcpy(_root._volname, TEXT("root fs"));
147 _root._fs_flags = 0;
148 lstrcpy(_root._fs, TEXT("unixfs"));
149 lstrcpy(_root._path, TEXT("/"));
150 _root._entry = new UnixDirectory(_root._path);
151 entry = _root.read_tree(info._path+_tcslen(_root._path));
152 break;
153 #endif
154
155 case ET_NTOBJS:
156 _root._drive_type = DRIVE_UNKNOWN;
157 _root._sort_order = SORT_NAME;
158
159 _tsplitpath_s(info._path, drv, COUNTOF(drv), NULL, 0, NULL, 0, NULL, 0);
160 lstrcat(drv, TEXT("\\"));
161 lstrcpy(_root._volname, TEXT("NT Object Namespace"));
162 lstrcpy(_root._fs, TEXT("NTOBJ"));
163 lstrcpy(_root._path, drv);
164 _root._entry = new NtObjDirectory(_root._path);
165 entry = _root.read_tree(info._path+_tcslen(_root._path));
166 break;
167
168 case ET_REGISTRY:
169 _root._drive_type = DRIVE_UNKNOWN;
170 _root._sort_order = SORT_NONE;
171
172 _tsplitpath_s(info._path, drv, COUNTOF(drv), NULL, 0, NULL, 0, NULL, 0);
173 lstrcat(drv, TEXT("\\"));
174 lstrcpy(_root._volname, TEXT("Registry"));
175 lstrcpy(_root._fs, TEXT("Registry"));
176 lstrcpy(_root._path, drv);
177 _root._entry = new RegistryRoot();
178 entry = _root.read_tree(info._path+_tcslen(_root._path));
179 break;
180 #ifdef _DEBUG
181 case ET_FAT: {
182 _root._drive_type = DRIVE_UNKNOWN;
183 _root._sort_order = SORT_NONE;
184
185 _tsplitpath_s(info._path, drv, COUNTOF(drv), NULL, 0, NULL, 0, NULL, 0);
186 lstrcat(drv, TEXT("\\"));
187 lstrcpy(_root._volname, TEXT("FAT XXX")); //@@
188 lstrcpy(_root._fs, TEXT("FAT"));
189 lstrcpy(_root._path, drv);
190 FATDrive* drive = new FATDrive(TEXT("c:/reactos-emu/c.img")); //TEXT("\\\\.\\F:")); //@@
191
192 if (drive->_hDrive != INVALID_HANDLE_VALUE) {
193 _root._entry = drive;
194 entry = _root.read_tree(info._path+_tcslen(_root._path));
195 }
196 break;}
197 #endif
198 #ifndef _NO_WIN_FS
199 default: // ET_WINDOWS
200 _root._drive_type = GetDriveType(info._path);
201 _root._sort_order = SORT_NAME;
202
203 _tsplitpath_s(info._path, drv, COUNTOF(drv), NULL, 0, NULL, 0, NULL, 0);
204 lstrcat(drv, TEXT("\\"));
205 GetVolumeInformation(drv, _root._volname, _MAX_FNAME, 0, 0, &_root._fs_flags, _root._fs, COUNTOF(_root._fs));
206 lstrcpy(_root._path, drv);
207 _root._entry = new WinDirectory(_root._path);
208 entry = _root.read_tree(info._path+_tcslen(_root._path));
209 break;
210 #else
211 default:
212 #endif
213
214 case ET_SHELL: { //@@ separate FileChildWindow into ShellChildWindow, WinChildWindow, UnixChildWindow ?
215 _root._drive_type = DRIVE_UNKNOWN;
216 _root._sort_order = SORT_NAME;
217
218 lstrcpy(drv, TEXT("\\"));
219 lstrcpy(_root._volname, TEXT("Desktop"));
220 _root._fs_flags = 0;
221 lstrcpy(_root._fs, TEXT("Shell"));
222
223 _root._entry = new ShellDirectory(GetDesktopFolder(), DesktopFolderPath(), hwnd);
224 const ShellChildWndInfo& shell_info = static_cast<const ShellChildWndInfo&>(info);
225 entry = _root.read_tree(&*shell_info._shell_path);
226 break;}
227 }
228
229 if (_root._entry) {
230 if (info._etype != ET_SHELL)
231 wsprintf(_root._entry->_data.cFileName, TEXT("%s - %s"), drv, _root._fs);
232 /*@@else
233 lstrcpy(_root._entry->_data.cFileName, TEXT("GetDesktopFolder"));*/
234
235 _root._entry->_data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
236
237
238 ///@todo use OWM_ROOTED flag
239
240 if (info._open_mode & OWM_EXPLORE) ///@todo Is not-explore-mode for FileChildWindow completely implemented?
241 _left_hwnd = *(_left=new Pane(_hwnd, IDW_TREE_LEFT, IDW_HEADER_LEFT, _root._entry, true, COL_CONTENT));
242
243 _right_hwnd = *(_right=new Pane(_hwnd, IDW_TREE_RIGHT, IDW_HEADER_RIGHT, NULL, false,
244 COL_TYPE|COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_INDEX|COL_LINKS|COL_CONTENT));
245 }
246
247 _header_wdths_ok = false;
248
249 if (!_left_hwnd && !_right_hwnd)
250 return;
251
252 if (entry)
253 set_curdir(entry);
254 else if (_root._entry)
255 set_curdir(_root._entry);
256
257 if (_left_hwnd) {
258 int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), _left->_cur);
259 ListBox_SetCurSel(_left_hwnd, idx);
260 //SetFocus(_left_hwnd);
261 }
262
263 // store path into history
264 if (info._path && *info._path)
265 _url_history.push(info._path);
266 }
267
268
269 void FileChildWindow::set_curdir(Entry* entry)
270 {
271 CONTEXT("FileChildWindow::set_curdir()");
272
273 _path[0] = TEXT('\0');
274
275 _left->_cur = entry;
276 _right->_root = entry&&entry->_down? entry->_down: entry;
277 _right->_cur = entry;
278
279 if (entry) {
280 WaitCursor wait;
281
282 if (!entry->_scanned)
283 scan_entry(entry);
284 else {
285 HiddenWindow hide(_right_hwnd);
286
287 ListBox_ResetContent(_right_hwnd);
288 _right->insert_entries(entry->_down);
289
290 _right->calc_widths(false); ///@todo make configurable (This call takes really _very_ long compared to all other processing!)
291
292 _right->set_header();
293 }
294
295 entry->get_path(_path, COUNTOF(_path));
296 }
297
298 if (_hwnd) // only change window title if the window already exists
299 SetWindowText(_hwnd, _path);
300
301 if (_path[0])
302 {
303 if (SetCurrentDirectory(_path))
304 set_url(_path); //set_url(FmtString(TEXT("file://%s"), _path));
305 else
306 _path[0] = TEXT('\0');
307 }
308 }
309
310
311 // expand a directory entry
312
313 bool FileChildWindow::expand_entry(Entry* dir)
314 {
315 int idx;
316 Entry* p;
317
318 if (!dir || dir->_expanded || !dir->_down)
319 return false;
320
321 p = dir->_down;
322
323 if (p->_data.cFileName[0]=='.' && p->_data.cFileName[1]=='\0' && p->_next) {
324 p = p->_next;
325
326 if (p->_data.cFileName[0]=='.' && p->_data.cFileName[1]=='.' &&
327 p->_data.cFileName[2]=='\0' && p->_next)
328 p = p->_next;
329 }
330
331 // no subdirectories ?
332 if (!(p->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && // not a directory?
333 !p->_down) // not a file with NTFS sub-streams?
334 return FALSE;
335
336 idx = ListBox_FindItemData(_left_hwnd, 0, dir);
337
338 dir->_expanded = true;
339
340 // insert entries in left pane
341 HiddenWindow hide(_left_hwnd);
342
343 _left->insert_entries(p, idx);
344
345 if (!_header_wdths_ok) {
346 if (_left->calc_widths(false)) {
347 _left->set_header();
348
349 _header_wdths_ok = true;
350 }
351 }
352
353 return true;
354 }
355
356
357 void FileChildWindow::collapse_entry(Pane* pane, Entry* dir)
358 {
359 int idx = ListBox_FindItemData(*pane, 0, dir);
360
361 SendMessage(*pane, WM_SETREDRAW, FALSE, 0); //ShowWindow(*pane, SW_HIDE);
362
363 // hide sub entries
364 for(;;) {
365 LRESULT res = ListBox_GetItemData(*pane, idx+1);
366 Entry* sub = (Entry*) res;
367
368 if (res==LB_ERR || !sub || sub->_level<=dir->_level)
369 break;
370
371 ListBox_DeleteString(*pane, idx+1);
372 }
373
374 dir->_expanded = false;
375
376 SendMessage(*pane, WM_SETREDRAW, TRUE, 0); //ShowWindow(*pane, SW_SHOW);
377 }
378
379
380 FileChildWindow* FileChildWindow::create(const FileChildWndInfo& info)
381 {
382 CONTEXT("FileChildWindow::create()");
383
384 MDICREATESTRUCT mcs;
385
386 mcs.szClass = CLASSNAME_WINEFILETREE;
387 mcs.szTitle = (LPTSTR)info._path;
388 mcs.hOwner = g_Globals._hInstance;
389 mcs.x = info._pos.rcNormalPosition.left;
390 mcs.y = info._pos.rcNormalPosition.top;
391 mcs.cx = info._pos.rcNormalPosition.right - info._pos.rcNormalPosition.left;
392 mcs.cy = info._pos.rcNormalPosition.bottom - info._pos.rcNormalPosition.top;
393 mcs.style = 0;
394 mcs.lParam = 0;
395
396 FileChildWindow* child = static_cast<FileChildWindow*>(
397 create_mdi_child(info, mcs, WINDOW_CREATOR_INFO(FileChildWindow,FileChildWndInfo)));
398
399 if (!child->_left_hwnd && !child->_right_hwnd) {
400 SendMessage(info._hmdiclient, WM_MDIDESTROY, (WPARAM)child->_hwnd, 0);
401 MessageBox(info._hmdiclient, TEXT("Error opening child window"), TEXT("ROS Explorer"), MB_OK);
402 }
403
404 return child;
405 }
406
407
408 void FileChildWindow::resize_children(int cx, int cy)
409 {
410 HDWP hdwp = BeginDeferWindowPos(4);
411 RECT rt;
412
413 rt.left = 0;
414 rt.top = 0;
415 rt.right = cx;
416 rt.bottom = cy;
417
418 cx = _split_pos + SPLIT_WIDTH/2;
419
420 if (_left && _right) {
421 WINDOWPOS wp;
422 HD_LAYOUT hdl;
423
424 hdl.prc = &rt;
425 hdl.pwpos = &wp;
426
427 Header_Layout(_left->_hwndHeader, &hdl);
428
429 hdwp = DeferWindowPos(hdwp, _left->_hwndHeader, wp.hwndInsertAfter,
430 wp.x-1, wp.y, _split_pos-SPLIT_WIDTH/2+1, wp.cy, wp.flags);
431
432 hdwp = DeferWindowPos(hdwp, _right->_hwndHeader, wp.hwndInsertAfter,
433 rt.left+cx+1, wp.y, wp.cx-cx+2, wp.cy, wp.flags);
434 }
435
436 if (_left_hwnd)
437 hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, rt.left, rt.top, _split_pos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
438
439 if (_right_hwnd)
440 hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
441
442 EndDeferWindowPos(hdwp);
443 }
444
445
446 LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
447 {
448 switch(nmsg) {
449 case WM_DRAWITEM: {
450 LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lparam;
451 Entry* entry = (Entry*) dis->itemData;
452
453 if (dis->CtlID == IDW_TREE_LEFT) {
454 _left->draw_item(dis, entry);
455 return TRUE;
456 } else if (dis->CtlID == IDW_TREE_RIGHT) {
457 _right->draw_item(dis, entry);
458 return TRUE;
459 }
460
461 goto def;}
462
463 case WM_SIZE:
464 if (wparam != SIZE_MINIMIZED)
465 resize_children(LOWORD(lparam), HIWORD(lparam));
466 return DefMDIChildProc(_hwnd, nmsg, wparam, lparam);
467
468 case PM_GET_FILEWND_PTR:
469 return (LRESULT)this;
470
471 case WM_SETFOCUS: {
472 TCHAR path[MAX_PATH];
473
474 if (_left && _left->_cur) {
475 _left->_cur->get_path(path, COUNTOF(path));
476 SetCurrentDirectory(path);
477 }
478
479 SetFocus(_focus_pane? _right_hwnd: _left_hwnd);
480 goto def;}
481
482 case PM_DISPATCH_COMMAND: {
483 Pane* pane = GetFocus()==_left_hwnd? _left: _right;
484
485 switch(LOWORD(wparam)) {
486 case ID_WINDOW_NEW: {CONTEXT("FileChildWindow PM_DISPATCH_COMMAND ID_WINDOW_NEW");
487 if (_root._entry->_etype == ET_SHELL)
488 FileChildWindow::create(ShellChildWndInfo(GetParent(_hwnd)/*_hmdiclient*/, _path, DesktopFolderPath()));
489 else
490 FileChildWindow::create(FileChildWndInfo(GetParent(_hwnd)/*_hmdiclient*/, _path));
491 break;}
492
493 case ID_REFRESH: {CONTEXT("ID_REFRESH");
494 refresh();
495 break;}
496
497 case ID_ACTIVATE: {CONTEXT("ID_ACTIVATE");
498 activate_entry(pane);
499 break;}
500
501 default:
502 if (pane->command(LOWORD(wparam)))
503 return TRUE;
504 else
505 return super::WndProc(nmsg, wparam, lparam);
506 }
507
508 return TRUE;}
509
510 case WM_CONTEXTMENU: {
511 // first select the current item in the listbox
512 HWND hpanel = (HWND) wparam;
513 POINT pt;
514 pt.x = LOWORD(lparam);
515 pt.y = HIWORD(lparam);
516 POINT pt_screen = pt;
517 ScreenToClient(hpanel, &pt);
518 SendMessage(hpanel, WM_LBUTTONDOWN, 0, MAKELONG(pt.x, pt.y));
519 SendMessage(hpanel, WM_LBUTTONUP, 0, MAKELONG(pt.x, pt.y));
520
521 // now create the popup menu using shell namespace and IContextMenu
522 Pane* pane = GetFocus()==_left_hwnd? _left: _right;
523 int idx = ListBox_GetCurSel(*pane);
524 if (idx != -1) {
525 Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx);
526
527 HRESULT hr = entry->do_context_menu(_hwnd, pt_screen, _cm_ifs);
528
529 if (SUCCEEDED(hr))
530 refresh();
531 else
532 CHECKERROR(hr);
533 }
534 break;}
535
536 default: def:
537 return super::WndProc(nmsg, wparam, lparam);
538 }
539
540 return 0;
541 }
542
543
544 void FileChildWindow::refresh()
545 {
546 WaitCursor wait;
547 bool expanded = _left->_cur->_expanded;
548
549 scan_entry(_left->_cur);
550
551 if (expanded)
552 expand_entry(_left->_cur);
553 }
554
555
556 int FileChildWindow::Command(int id, int code)
557 {
558 Pane* pane = GetFocus()==_left_hwnd? _left: _right;
559
560 switch(code) {
561 case LBN_SELCHANGE: {
562 int idx = ListBox_GetCurSel(*pane);
563 Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx);
564
565 if (pane == _left)
566 set_curdir(entry);
567 else
568 pane->_cur = entry;
569 break;}
570
571 case LBN_DBLCLK:
572 activate_entry(pane);
573 break;
574 }
575
576 return 0;
577 }
578
579
580 void FileChildWindow::activate_entry(Pane* pane) ///@todo enable using RETURN key accelerator
581 {
582 Entry* entry = pane->_cur;
583
584 if (!entry)
585 return;
586
587 WaitCursor wait;
588
589 if ((entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || // a directory?
590 entry->_down) // a file with NTFS sub-streams?
591 {
592 int scanned_old = entry->_scanned;
593
594 if (!scanned_old)
595 scan_entry(entry);
596
597 if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('\0'))
598 return;
599
600 if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('.') && entry->_data.cFileName[2]==TEXT('\0')) {
601 entry = _left->_cur->_up;
602 collapse_entry(_left, entry);
603 goto focus_entry;
604 } else if (entry->_expanded)
605 collapse_entry(pane, _left->_cur);
606 else {
607 expand_entry(_left->_cur);
608
609 if (!pane->_treePane) focus_entry: {
610 int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), entry);
611 ListBox_SetCurSel(_left_hwnd, idx);
612
613 set_curdir(entry);
614 }
615 }
616
617 if (!scanned_old) {
618 pane->calc_widths(false);
619
620 pane->set_header();
621 }
622 } else {
623 entry->launch_entry(_hwnd);
624 }
625 }
626
627
628 void FileChildWindow::scan_entry(Entry* entry)
629 {
630 CONTEXT("FileChildWindow::scan_entry()");
631
632 int idx = ListBox_GetCurSel(_left_hwnd);
633
634 // delete sub entries in left pane
635 for(;;) {
636 LRESULT res = ListBox_GetItemData(_left_hwnd, idx+1);
637 Entry* sub = (Entry*) res;
638
639 if (res==LB_ERR || !sub || sub->_level<=entry->_level)
640 break;
641
642 ListBox_DeleteString(_left_hwnd, idx+1);
643 }
644
645 // empty right pane
646 ListBox_ResetContent(_right_hwnd);
647
648 // release memory
649 entry->free_subentries();
650 entry->_expanded = false;
651
652 // read contents from disk
653 entry->read_directory_base(_root._sort_order); ///@todo use modifyable sort order instead of fixed file system default
654
655 // insert found entries in right pane
656 HiddenWindow hide(_right_hwnd);
657 _right->insert_entries(entry->_down);
658
659 _right->calc_widths(false);
660 _right->set_header();
661
662 _header_wdths_ok = false;
663 }
664
665
666 int FileChildWindow::Notify(int id, NMHDR* pnmh)
667 {
668 return (pnmh->idFrom==IDW_HEADER_LEFT? _left: _right)->Notify(id, pnmh);
669 }
670
671
672 String FileChildWindow::jump_to_int(LPCTSTR url)
673 {
674 String dir, fname;
675
676 if (SplitFileSysURL(url, dir, fname)) {
677 Entry* entry = NULL;
678
679 // call read_tree() to iterate through the hierarchy and open all folders to reach dir
680 if (_root._entry)
681 switch(_root._entry->_etype) {
682 case ET_SHELL: { //@@ separate into FileChildWindow in ShellChildWindow, WinChildWindow, UnixChildWindow ?
683 ShellPath shell_path(dir);
684 entry = _root.read_tree(&*shell_path);
685 break;}
686
687 #ifdef __WINE__
688 case ET_UNIX: {
689 LPCTSTR path = dir;
690
691 if (!_tcsicmp(path, _root._path, _tcslen(_root._path)))
692 path += _tcslen(_root._path);
693
694 entry = _root.read_tree(path);
695 break;}
696 #endif
697
698 default: { // ET_NTOBJS, ET_REGISTRY, ET_FAT, ET_WINDOWS
699 LPCTSTR path = dir;
700
701 if (!_tcsnicmp(path, _root._path, _tcslen(_root._path)))
702 path += _tcslen(_root._path);
703
704 entry = _root.read_tree(path);
705 break;}
706 }
707
708 if (entry) {
709 // refresh left pane entries
710 HiddenWindow hide(_left_hwnd);
711
712 ListBox_ResetContent(_left_hwnd);
713
714 _left->insert_entries(_root._entry);
715
716 if (!_header_wdths_ok) {
717 if (_left->calc_widths(false)) {
718 _left->set_header();
719
720 _header_wdths_ok = true;
721 }
722 }
723
724 set_curdir(entry);
725
726 if (_left_hwnd) {
727 int idx = ListBox_FindItemData(_left_hwnd, -1, entry);
728
729 if (idx != -1) { // The item should always be found.
730 ListBox_SetCurSel(_left_hwnd, idx);
731 SetFocus(_left_hwnd);
732 }
733 }
734
735 ///@todo use fname
736
737 return dir; //FmtString(TEXT("file://%s"), (LPCTSTR)dir);
738 }
739 }
740
741 return String();
742 }