- fix Entry::read_tree() and get_next_path_component()

- jump to FileChildWindow's directory when entered in address bar

svn path=/trunk/; revision=9105
This commit is contained in:
Martin Fuchs 2004-04-12 15:58:48 +00:00
parent d24371eaec
commit 6a3ea3a956
19 changed files with 171 additions and 76 deletions

View file

@ -60,7 +60,7 @@ void CollectProgramsThread::collect_programs(const ShellPath& path)
ShellDirectory* dir = new ShellDirectory(GetDesktopFolder(), path, 0);
_dirs.push(dir);
dir->smart_scan(/*SCAN_EXTRACT_ICONS|*/SCAN_FILESYSTEM);
dir->smart_scan(SORT_NONE, /*SCAN_EXTRACT_ICONS|*/SCAN_FILESYSTEM);
for(Entry*entry=dir->_down; entry; entry=entry->_next) {
if (!_alive)

View file

@ -112,24 +112,24 @@ Entry::~Entry()
// read directory tree and expand to the given location
Entry* Entry::read_tree(const void* path, SORT_ORDER sortOrder)
Entry* Entry::read_tree(const void* path, SORT_ORDER sortOrder, int scan_flags)
{
CONTEXT("Entry::read_tree()");
HCURSOR old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
Entry* entry = this;
Entry* next_entry = entry;
for(const void*p=path; p&&next_entry; p=entry->get_next_path_component(p)) {
entry = next_entry;
entry->read_directory(sortOrder);
for(const void*p=path; p && entry; ) {
entry->smart_scan(sortOrder, scan_flags);
if (entry->_down)
entry->_expanded = true;
next_entry = entry->find_entry(p);
Entry* found = entry->find_entry(p);
p = entry->get_next_path_component(p);
entry = found;
}
SetCursor(old_cursor);
@ -138,9 +138,9 @@ Entry* Entry::read_tree(const void* path, SORT_ORDER sortOrder)
}
void Entry::read_directory(SORT_ORDER sortOrder, int scan_flags)
void Entry::read_directory_base(SORT_ORDER sortOrder, int scan_flags)
{
CONTEXT("Entry::read_directory(SORT_ORDER)");
CONTEXT("Entry::read_directory_base()");
// call into subclass
read_directory(scan_flags);
@ -304,13 +304,13 @@ void Entry::sort_directory(SORT_ORDER sortOrder)
}
void Entry::smart_scan(int scan_flags)
void Entry::smart_scan(SORT_ORDER sortOrder, int scan_flags)
{
CONTEXT("Entry::smart_scan()");
if (!_scanned) {
free_subentries();
read_directory(SORT_NAME, scan_flags); // we could use IShellFolder2::GetDefaultColumn to determine sort order
read_directory_base(sortOrder, scan_flags); ///@todo We could use IShellFolder2::GetDefaultColumn to determine sort order.
}
}
@ -475,18 +475,26 @@ void Entry::free_subentries()
}
const void* Directory::get_next_path_component(const void* p)
Entry* Root::read_tree(LPCTSTR path, int scan_flags)
{
LPCTSTR s = (LPCTSTR) p;
Entry* entry;
while(*s && *s!=TEXT('\\') && *s!=TEXT('/'))
++s;
if (path && *path)
entry = _entry->read_tree(path, _sort_order);
else {
entry = _entry->read_tree(NULL, _sort_order);
while(*s==TEXT('\\') || *s==TEXT('/'))
++s;
_entry->smart_scan();
if (!*s)
return NULL;
if (_entry->_down)
_entry->_expanded = true;
}
return s;
return entry;
}
Entry* Root::read_tree(LPCITEMIDLIST pidl, int scan_flags)
{
return _entry->read_tree(pidl, _sort_order);
}

View file

@ -99,14 +99,14 @@ public:
void free_subentries();
void read_directory(SORT_ORDER sortOrder, int scan_flags=SCAN_ALL);
Entry* read_tree(const void* path, SORT_ORDER sortOrder);
void read_directory_base(SORT_ORDER sortOrder=SORT_NAME, int scan_flags=SCAN_ALL);
Entry* read_tree(const void* path, SORT_ORDER sortOrder=SORT_NAME, int scan_flags=SCAN_ALL);
void sort_directory(SORT_ORDER sortOrder);
void smart_scan(int scan_flags=SCAN_ALL);
void smart_scan(SORT_ORDER sortOrder=SORT_NAME, int scan_flags=SCAN_ALL);
void extract_icon();
virtual void read_directory(int scan_flags=SCAN_ALL) {}
virtual const void* get_next_path_component(const void*) {return NULL;}
virtual const void* get_next_path_component(const void*) const {return NULL;}
virtual Entry* find_entry(const void*) {return NULL;}
virtual bool get_path(PTSTR path) const = 0;
virtual ShellPath create_absolute_pidl() const {return (LPCITEMIDLIST)NULL;}
@ -121,9 +121,6 @@ protected:
Directory() : _path(NULL) {}
virtual ~Directory() {}
// default implementation like that of Windows file systems
virtual const void* get_next_path_component(const void*);
void* _path;
};
@ -139,4 +136,8 @@ struct Root {
TCHAR _fs[_MAX_DIR];
DWORD _drive_type;
DWORD _fs_flags;
SORT_ORDER _sort_order;
Entry* read_tree(LPCTSTR path, int scan_flags=SCAN_ALL);
Entry* read_tree(LPCITEMIDLIST pidl, int scan_flags=SCAN_ALL);
};

View file

@ -203,6 +203,23 @@ void FATDirectory::read_directory(int scan_flags)
}
const void* FATDirectory::get_next_path_component(const void* p) const
{
LPCTSTR s = (LPCTSTR) p;
while(*s && *s!=TEXT('\\') && *s!=TEXT('/'))
++s;
while(*s==TEXT('\\') || *s==TEXT('/'))
++s;
if (!*s)
return NULL;
return s;
}
Entry* FATDirectory::find_entry(const void* p)
{
LPCTSTR name = (LPCTSTR)p;

View file

@ -51,6 +51,7 @@ struct FATDirectory : public FATEntry, public Directory
~FATDirectory();
virtual void read_directory(int scan_flags=SCAN_ALL);
virtual const void* get_next_path_component(const void*) const;
virtual Entry* find_entry(const void*);
protected:

View file

@ -138,6 +138,8 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
switch(info._etype) {
case ET_SHELL: { //@@ separate into FileChildWindow in ShellChildWindow, WinChildWindow, UnixChildWindow ?
_root._drive_type = DRIVE_UNKNOWN;
_root._sort_order = SORT_NAME;
lstrcpy(drv, TEXT("\\"));
lstrcpy(_root._volname, TEXT("Desktop"));
_root._fs_flags = 0;
@ -145,12 +147,13 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
_root._entry = new ShellDirectory(GetDesktopFolder(), DesktopFolderPath(), hwnd);
const ShellChildWndInfo& shell_info = static_cast<const ShellChildWndInfo&>(info);
entry = _root._entry->read_tree((LPCTSTR)&*shell_info._shell_path, SORT_NAME);
entry = _root.read_tree(&*shell_info._shell_path);
break;}
#ifdef __WINE__
case ET_UNIX:
_root._drive_type = GetDriveType(info._path);
_root._sort_order = SORT_NAME;
_tsplitpath(info._path, drv, NULL, NULL, NULL);
lstrcat(drv, TEXT("/"));
@ -159,12 +162,13 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
lstrcpy(_root._fs, TEXT("unixfs"));
lstrcpy(_root._path, TEXT("/"));
_root._entry = new UnixDirectory(_root._path);
entry = _root._entry->read_tree(info._path, SORT_NAME);
entry = _root.read_tree(info._path+_tcslen(_root._path));
break;
#endif
case ET_NTOBJS:
_root._drive_type = DRIVE_UNKNOWN;
_root._sort_order = SORT_NAME;
_tsplitpath(info._path, drv, NULL, NULL, NULL);
lstrcat(drv, TEXT("\\"));
@ -172,11 +176,12 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
lstrcpy(_root._fs, TEXT("NTOBJ"));
lstrcpy(_root._path, drv);
_root._entry = new NtObjDirectory(_root._path);
entry = _root._entry->read_tree(info._path, SORT_NAME);
entry = _root.read_tree(info._path+_tcslen(_root._path));
break;
case ET_REGISTRY:
_root._drive_type = DRIVE_UNKNOWN;
_root._sort_order = SORT_NONE;
_tsplitpath(info._path, drv, NULL, NULL, NULL);
lstrcat(drv, TEXT("\\"));
@ -184,11 +189,12 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
lstrcpy(_root._fs, TEXT("Registry"));
lstrcpy(_root._path, drv);
_root._entry = new RegistryRoot();
entry = _root._entry->read_tree(info._path, SORT_NONE);
entry = _root.read_tree(info._path+_tcslen(_root._path));
break;
case ET_FAT: {
_root._drive_type = DRIVE_UNKNOWN;
_root._sort_order = SORT_NONE;
_tsplitpath(info._path, drv, NULL, NULL, NULL);
lstrcat(drv, TEXT("\\"));
@ -199,19 +205,20 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
if (drive->_hDrive != INVALID_HANDLE_VALUE) {
_root._entry = drive;
entry = _root._entry->read_tree(info._path, SORT_NONE);
entry = _root.read_tree(info._path+_tcslen(_root._path));
}
break;}
default: // ET_WINDOWS
_root._drive_type = GetDriveType(info._path);
_root._sort_order = SORT_NAME;
_tsplitpath(info._path, drv, NULL, NULL, NULL);
lstrcat(drv, TEXT("\\"));
GetVolumeInformation(drv, _root._volname, _MAX_FNAME, 0, 0, &_root._fs_flags, _root._fs, _MAX_DIR);
lstrcpy(_root._path, drv);
_root._entry = new WinDirectory(_root._path);
entry = _root._entry->read_tree(info._path, SORT_NAME);
entry = _root.read_tree(info._path+_tcslen(_root._path));
}
if (_root._entry) {
@ -230,17 +237,17 @@ FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
COL_TYPE|COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_INDEX|COL_LINKS|COL_CONTENT));
}
_sortOrder = SORT_NAME;
_header_wdths_ok = false;
if (entry)
set_curdir(entry);
else
set_curdir(_root._entry);
if (_left_hwnd) {
int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), _left->_cur);
ListBox_SetCurSel(_left_hwnd, idx);
///@todo scroll to visibility
//SetFocus(_left_hwnd);
}
// store path into history
@ -263,8 +270,10 @@ void FileChildWindow::set_curdir(Entry* entry)
if (!entry->_scanned)
scan_entry(entry);
else {
HiddenWindow hide(_right_hwnd);
ListBox_ResetContent(_right_hwnd);
_right->insert_entries(entry->_down, -1);
_right->insert_entries(entry->_down);
_right->calc_widths(false);
_right->set_header();
}
@ -277,7 +286,7 @@ void FileChildWindow::set_curdir(Entry* entry)
if (_path[0])
if (SetCurrentDirectory(_path))
set_url(_path); //@@ use "file://" format?
set_url(_path); //set_url(FmtString(TEXT("file://%s"), _path));
else
_path[0] = TEXT('\0');
}
@ -313,6 +322,8 @@ bool FileChildWindow::expand_entry(Entry* dir)
dir->_expanded = true;
// insert entries in left pane
HiddenWindow hide(_left_hwnd);
_left->insert_entries(p, idx);
if (!_header_wdths_ok) {
@ -621,15 +632,16 @@ void FileChildWindow::scan_entry(Entry* entry)
entry->_expanded = false;
// read contents from disk
entry->read_directory(_sortOrder);
entry->read_directory_base(_root._sort_order); ///@todo use modifyable sort order instead of fixed file system default
// insert found entries in right pane
_right->insert_entries(entry->_down, -1);
HiddenWindow hide(_right_hwnd);
_right->insert_entries(entry->_down);
_right->calc_widths(false);
_right->set_header();
_header_wdths_ok = FALSE;
_header_wdths_ok = false;
SetCursor(old_cursor);
}
@ -652,42 +664,61 @@ String FileChildWindow::jump_to_int(LPCTSTR url)
switch(_root._entry->_etype) {
case ET_SHELL: { //@@ separate into FileChildWindow in ShellChildWindow, WinChildWindow, UnixChildWindow ?
ShellPath shell_path(dir);
entry = _root._entry->read_tree((LPCTSTR)&*shell_path, SORT_NAME);
entry = _root.read_tree(&*shell_path);
break;}
#ifdef __WINE__
case ET_UNIX:
entry = _root._entry->read_tree(info._path, SORT_NAME);
{
LPCTSTR path = dir;
if (!_tcsicmp(path, _root._path, _tcslen(_root._path)))
path += _tcslen(_root._path);
entry = _root.read_tree(path);
}
break;
#endif
case ET_NTOBJS:
entry = _root._entry->read_tree(dir, SORT_NAME);
break;
default: // ET_UNIX, ET_NTOBJS, ET_REGISTRY, ET_FAT, ET_WINDOWS
{
LPCTSTR path = dir;
case ET_REGISTRY:
entry = _root._entry->read_tree(dir, SORT_NONE);
break;
if (!_tcsnicmp(path, _root._path, _tcslen(_root._path)))
path += _tcslen(_root._path);
case ET_FAT: {
entry = _root._entry->read_tree(dir, SORT_NONE);
break;}
default: // ET_WINDOWS
entry = _root._entry->read_tree(dir, SORT_NAME); //@@ smart_scan() ?!
entry = _root.read_tree(path);
}
}
if (entry) {
// refresh left pane entries
HiddenWindow hide(_left_hwnd);
ListBox_ResetContent(_left_hwnd);
_left->insert_entries(_root._entry);
if (!_header_wdths_ok) {
if (_left->calc_widths(false)) {
_left->set_header();
_header_wdths_ok = true;
}
}
set_curdir(entry);
if (_left_hwnd) {
int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), entry);
ListBox_SetCurSel(_left_hwnd, idx);
int idx = ListBox_FindItemData(_left_hwnd, -1, entry);
///@todo scroll to visibility
if (idx != -1) { // The item should always be found.
ListBox_SetCurSel(_left_hwnd, idx);
SetFocus(_left_hwnd);
}
}
return FmtString(TEXT("file://%s"), (LPCTSTR)dir);
return dir; //FmtString(TEXT("file://%s"), (LPCTSTR)dir);
}
}

View file

@ -113,7 +113,6 @@ protected:
Root _root;
Pane* _left;
Pane* _right;
SORT_ORDER _sortOrder;
TCHAR _path[MAX_PATH];
bool _header_wdths_ok;

View file

@ -663,8 +663,6 @@ void Pane::insert_entries(Entry* dir, int idx)
if (!entry)
return;
SendMessage(_hwnd, WM_SETREDRAW, FALSE, 0); //ShowWindow(_hwnd, SW_HIDE);
for(; entry; entry=entry->_next) {
#ifndef _LEFT_FILES
if (_treePane &&
@ -688,8 +686,6 @@ void Pane::insert_entries(Entry* dir, int idx)
if (_treePane && entry->_expanded)
insert_entries(entry->_down, idx);
}
SendMessage(_hwnd, WM_SETREDRAW, TRUE, 0); //ShowWindow(_hwnd, SW_SHOW);
}

View file

@ -92,7 +92,7 @@ struct Pane : public SubclassedWindow
void calc_single_width(int col);
void draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol=-1);
void insert_entries(Entry* dir, int idx);
void insert_entries(Entry* dir, int idx=-1);
BOOL command(UINT cmd);
int Notify(int id, NMHDR* pnmh);

View file

@ -181,6 +181,23 @@ void RegDirectory::read_directory(int scan_flags)
}
const void* RegDirectory::get_next_path_component(const void* p) const
{
LPCTSTR s = (LPCTSTR) p;
while(*s && *s!=TEXT('\\'))
++s;
while(*s==TEXT('\\'))
++s;
if (!*s)
return NULL;
return s;
}
Entry* RegDirectory::find_entry(const void* p)
{
LPCTSTR name = (LPCTSTR)p;

View file

@ -51,6 +51,7 @@ struct RegDirectory : public RegEntry, public Directory
}
virtual void read_directory(int scan_flags=SCAN_ALL);
virtual const void* get_next_path_component(const void*) const;
virtual Entry* find_entry(const void*);
protected:

View file

@ -80,18 +80,20 @@ LRESULT ShellBrowserChild::Init(LPCREATESTRUCT pcs)
const String& root_name = GetDesktopFolder().get_name(_create_info._root_shell_path, SHGDN_FORPARSING);
_root._drive_type = DRIVE_UNKNOWN;
_root._sort_order = SORT_NAME;
lstrcpy(_root._volname, root_name); // most of the time "Desktop"
_root._fs_flags = 0;
lstrcpy(_root._fs, TEXT("Desktop"));
//@@ _root._entry->read_tree(shell_info._root_shell_path.get_folder(), info._shell_path, SORT_NAME/*_sortOrder*/);
//@@ _root._entry->read_tree(shell_info._root_shell_path.get_folder(), info._shell_path, _root._sort_order/*_sortOrder*/);
/*@todo
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
-> see FileChildWindow::FileChildWindow()
*/
_root._entry = new ShellDirectory(GetDesktopFolder(), _create_info._root_shell_path, _hwnd);
_root._entry->read_directory();
_root._entry->read_directory_base(_root._sort_order);
/* already filled by ShellDirectory constructor
lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop")); */

View file

@ -433,7 +433,7 @@ void ShellDirectory::read_directory(int scan_flags)
_scanned = true;
}
const void* ShellDirectory::get_next_path_component(const void* p)
const void* ShellDirectory::get_next_path_component(const void* p) const
{
LPITEMIDLIST pidl = (LPITEMIDLIST)p;
@ -450,6 +450,10 @@ Entry* ShellDirectory::find_entry(const void* p)
{
LPITEMIDLIST pidl = (LPITEMIDLIST) p;
// handle special case of empty trailing id list entry
if (!pidl->mkid.cb)
return this;
for(Entry*entry=_down; entry; entry=entry->_next)
if (entry->_etype == ET_SHELL) {
ShellEntry* se = static_cast<ShellEntry*>(entry);

View file

@ -99,7 +99,7 @@ struct ShellDirectory : public ShellEntry, public Directory
}
virtual void read_directory(int scan_flags=SCAN_ALL);
virtual const void* get_next_path_component(const void*);
virtual const void* get_next_path_component(const void*) const;
virtual Entry* find_entry(const void* p);
virtual bool get_path(PTSTR path) const;

View file

@ -188,6 +188,23 @@ void WinDirectory::read_directory(int scan_flags)
}
const void* WinDirectory::get_next_path_component(const void* p) const
{
LPCTSTR s = (LPCTSTR) p;
while(*s && *s!=TEXT('\\') && *s!=TEXT('/'))
++s;
while(*s==TEXT('\\') || *s==TEXT('/'))
++s;
if (!*s)
return NULL;
return s;
}
Entry* WinDirectory::find_entry(const void* p)
{
LPCTSTR name = (LPCTSTR)p;

View file

@ -61,6 +61,7 @@ struct WinDirectory : public WinEntry, public Directory
}
virtual void read_directory(int scan_flags=SCAN_ALL);
virtual const void* get_next_path_component(const void*) const;
virtual Entry* find_entry(const void*);
};

View file

@ -376,7 +376,7 @@ void BookmarkList::import_IE_favorites(ShellDirectory& dir, HWND hwnd)
{
TCHAR path[MAX_PATH], ext[_MAX_EXT];
dir.smart_scan(SCAN_FILESYSTEM);
dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM);
for(Entry*entry=dir._down; entry; entry=entry->_next) {
if (entry->_shell_attribs & SFGAO_HIDDEN) // ignore files like "desktop.ini"

View file

@ -108,7 +108,7 @@ void QuickLaunchBar::AddShortcuts()
RecursiveCreateDirectory(path);
_dir = new ShellDirectory(GetDesktopFolder(), path, _hwnd);
_dir->smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
_dir->smart_scan(SORT_NAME, SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
} catch(COMException&) {
return;
}

View file

@ -193,9 +193,9 @@ void StartMenu::AddEntries()
WaitCursor wait;
#ifdef _LAZY_ICONEXTRACT
dir.smart_scan(SCAN_FILESYSTEM); // lazy icon extraction, try to read directly from filesystem
dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM); // lazy icon extraction, try to read directly from filesystem
#else
dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
dir.smart_scan(SORT_NAME, SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
#endif
}
@ -1870,9 +1870,9 @@ void RecentStartMenu::AddEntries()
WaitCursor wait;
#ifdef _LAZY_ICONEXTRACT
dir.smart_scan(SCAN_FILESYSTEM);
dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM);
#else
dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
dir.smart_scan(SORT_NAME, SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
#endif
}