/* * Copyright 2003 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // // Explorer clone // // filechild.cpp // // Martin Fuchs, 23.07.2003 // #include "../utility/utility.h" #include "../explorer.h" #include "../globals.h" #include "../explorer_intres.h" FileChildWndInfo::FileChildWndInfo(LPCTSTR path) { #ifdef __linux__ if (*path == '/') _etype = ET_UNIX; else #endif _etype = ET_WINDOWS; _path = path; _pos.length = sizeof(WINDOWPLACEMENT); _pos.flags = 0; _pos.showCmd = SW_SHOWNORMAL; _pos.rcNormalPosition.left = CW_USEDEFAULT; _pos.rcNormalPosition.top = CW_USEDEFAULT; _pos.rcNormalPosition.right = CW_USEDEFAULT; _pos.rcNormalPosition.bottom = CW_USEDEFAULT; _mode_explore = true; } ShellChildWndInfo::ShellChildWndInfo(LPCTSTR path, const ShellPath& root_shell_path) : FileChildWndInfo(path), _shell_path(path), _root_shell_path(root_shell_path) { _etype = ET_SHELL; _path = path; } FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info) : ChildWindow(hwnd) { TCHAR drv[_MAX_DRIVE+1]; Entry* entry; if (info._etype == ET_SHELL) //@@ evtl. Aufteilung von FileChildWindow in ShellChildWindow, WinChildWindow, UnixChildWindow { _root._drive_type = DRIVE_UNKNOWN; lstrcpy(drv, TEXT("\\")); lstrcpy(_root._volname, TEXT("Desktop")); _root._fs_flags = 0; lstrcpy(_root._fs, TEXT("Shell")); const ShellChildWndInfo& shell_info = static_cast(info); _root._entry = new ShellDirectory(Desktop(), DesktopFolder(), hwnd); entry = _root._entry->read_tree((LPCTSTR)&*shell_info._shell_path, SORT_NAME/*_sortOrder*/); } else #ifdef __linux__ if (info._etype == ET_UNIX) { _root._drive_type = GetDriveType(info._path); _tsplitpath(info._path, drv, NULL, NULL, NULL); lstrcat(drv, TEXT("/")); lstrcpy(_root._volname, TEXT("root fs")); _root._fs_flags = 0; lstrcpy(_root._fs, TEXT("unixfs")); lstrcpy(_root._path, TEXT("/")); _root._entry = new UnixDirectory(_root._path); entry = _root._entry->read_tree(info._path, SORT_NAME/*_sortOrder*/); } else #endif {// if (info._etype == ET_WINDOWS) _root._drive_type = GetDriveType(info._path); _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/*_sortOrder*/); } if (info._etype != ET_SHELL) wsprintf(_root._entry->_data.cFileName, TEXT("%s - %s"), drv, _root._fs); /*@@else lstrcpy(_root._entry->_data.cFileName, TEXT("Desktop"));*/ _root._entry->_data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; if (info._mode_explore) //TODO: Is not-explore-mode for FileChildWindow completely implemented? _left_hwnd = *(_left=new Pane(_hwnd, IDW_TREE_LEFT, IDW_HEADER_LEFT, _root._entry, true, 0)); _right_hwnd = *(_right=new Pane(_hwnd, IDW_TREE_RIGHT, IDW_HEADER_RIGHT, NULL, false, COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_INDEX|COL_LINKS)); _sortOrder = SORT_NAME; _header_wdths_ok = false; set_curdir(entry, hwnd); if (_left_hwnd) { int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), _left->_cur); ListBox_SetCurSel(_left_hwnd, idx); } //TODO: scroll to visibility } FileChildWindow::~FileChildWindow() { } void FileChildWindow::set_curdir(Entry* entry, HWND hwnd) { _path[0] = TEXT('\0'); _left->_cur = entry; _right->_root = entry&&entry->_down? entry->_down: entry; _right->_cur = entry; if (entry) { if (!entry->_scanned) scan_entry(entry, hwnd); else { ListBox_ResetContent(_right_hwnd); _right->insert_entries(entry->_down, -1); _right->calc_widths(false); _right->set_header(); } entry->get_path(_path); } if (hwnd) // only change window title, if the window already exists SetWindowText(hwnd, _path); if (_path[0]) if (!SetCurrentDirectory(_path)) _path[0] = TEXT('\0'); } // expand a directory entry bool FileChildWindow::expand_entry(Entry* dir) { int idx; Entry* p; if (!dir || dir->_expanded || !dir->_down) return false; p = dir->_down; if (p->_data.cFileName[0]=='.' && p->_data.cFileName[1]=='\0' && p->_next) { p = p->_next; if (p->_data.cFileName[0]=='.' && p->_data.cFileName[1]=='.' && p->_data.cFileName[2]=='\0' && p->_next) p = p->_next; } // no subdirectories ? if (!(p->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return FALSE; idx = ListBox_FindItemData(_left_hwnd, 0, dir); dir->_expanded = true; // insert entries in left pane _left->insert_entries(p, idx); if (!_header_wdths_ok) { if (_left->calc_widths(false)) { _left->set_header(); _header_wdths_ok = true; } } return true; } void FileChildWindow::collapse_entry(Pane* pane, Entry* dir) { int idx = ListBox_FindItemData(*pane, 0, dir); SendMessage(*pane, WM_SETREDRAW, FALSE, 0); //ShowWindow(*pane, SW_HIDE); // hide sub entries for(;;) { LRESULT res = ListBox_GetItemData(*pane, idx+1); Entry* sub = (Entry*) res; if (res==LB_ERR || !sub || sub->_level<=dir->_level) break; ListBox_DeleteString(*pane, idx+1); } dir->_expanded = false; SendMessage(*pane, WM_SETREDRAW, TRUE, 0); //ShowWindow(*pane, SW_SHOW); } FileChildWindow* FileChildWindow::create(HWND hmdiclient, const FileChildWndInfo& info) { MDICREATESTRUCT mcs; mcs.szClass = CLASSNAME_WINEFILETREE; mcs.szTitle = (LPTSTR)info._path; mcs.hOwner = g_Globals._hInstance; mcs.x = info._pos.rcNormalPosition.left; mcs.y = info._pos.rcNormalPosition.top; mcs.cx = info._pos.rcNormalPosition.right - info._pos.rcNormalPosition.left; mcs.cy = info._pos.rcNormalPosition.bottom - info._pos.rcNormalPosition.top; mcs.style = 0; mcs.lParam = 0; FileChildWindow* child = static_cast( create_mdi_child(hmdiclient, mcs, WINDOW_CREATOR_INFO(FileChildWindow,FileChildWndInfo), &info)); return child; } void FileChildWindow::resize_children(int cx, int cy) { HDWP hdwp = BeginDeferWindowPos(4); RECT rt; rt.left = 0; rt.top = 0; rt.right = cx; rt.bottom = cy; cx = _split_pos + SPLIT_WIDTH/2; { WINDOWPOS wp; HD_LAYOUT hdl; hdl.prc = &rt; hdl.pwpos = ℘ Header_Layout(_left->_hwndHeader, &hdl); hdwp = DeferWindowPos(hdwp, _left->_hwndHeader, wp.hwndInsertAfter, wp.x-1, wp.y, _split_pos-SPLIT_WIDTH/2+1, wp.cy, wp.flags); hdwp = DeferWindowPos(hdwp, _right->_hwndHeader, wp.hwndInsertAfter, rt.left+cx+1, wp.y, wp.cx-cx+2, wp.cy, wp.flags); } if (_left_hwnd) 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); hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE); EndDeferWindowPos(hdwp); } LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { case WM_DRAWITEM: { LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lparam; Entry* entry = (Entry*) dis->itemData; if (dis->CtlID == IDW_TREE_LEFT) _left->draw_item(dis, entry); else _right->draw_item(dis, entry); return TRUE;} case WM_SIZE: if (wparam != SIZE_MINIMIZED) resize_children(LOWORD(lparam), HIWORD(lparam)); return DefMDIChildProc(_hwnd, nmsg, wparam, lparam); case PM_GET_FILEWND_PTR: return (LRESULT)this; case WM_SETFOCUS: { TCHAR path[MAX_PATH]; if (_left->_cur) { _left->_cur->get_path(path); SetCurrentDirectory(path); } SetFocus(_focus_pane? _right_hwnd: _left_hwnd); goto def;} case PM_DISPATCH_COMMAND: { Pane* pane = GetFocus()==_left_hwnd? _left: _right; switch(LOWORD(wparam)) { case ID_WINDOW_NEW: if (_root._entry->_etype == ET_SHELL) FileChildWindow::create(GetParent(_hwnd)/*_hmdiclient*/, ShellChildWndInfo(_path,DesktopFolder())); else FileChildWindow::create(GetParent(_hwnd)/*_hmdiclient*/, FileChildWndInfo(_path)); break; case ID_REFRESH: { bool expanded = _left->_cur->_expanded; scan_entry(_left->_cur, _hwnd); if (expanded) expand_entry(_left->_cur); break;} case ID_ACTIVATE: activate_entry(pane, _hwnd); break; default: return pane->command(LOWORD(wparam)); } return TRUE;} default: def: return super::WndProc(nmsg, wparam, lparam); } return 0; } int FileChildWindow::Command(int id, int code) { Pane* pane = GetFocus()==_left_hwnd? _left: _right; switch(code) { case LBN_SELCHANGE: { int idx = ListBox_GetCurSel(*pane); Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx); if (pane == _left) set_curdir(entry, _hwnd); else pane->_cur = entry; break;} case LBN_DBLCLK: activate_entry(pane, _hwnd); break; } return 0; } void FileChildWindow::activate_entry(Pane* pane, HWND hwnd) { Entry* entry = pane->_cur; if (!entry) return; if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { int scanned_old = entry->_scanned; if (!scanned_old) scan_entry(entry, hwnd); if (entry->_data.cFileName[0]=='.' && entry->_data.cFileName[1]=='\0') return; if (entry->_data.cFileName[0]=='.' && entry->_data.cFileName[1]=='.' && entry->_data.cFileName[2]=='\0') { entry = _left->_cur->_up; collapse_entry(_left, entry); goto focus_entry; } else if (entry->_expanded) collapse_entry(pane, _left->_cur); else { expand_entry(_left->_cur); if (!pane->_treePane) focus_entry: { int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), entry); ListBox_SetCurSel(_left_hwnd, idx); set_curdir(entry, _hwnd); } } if (!scanned_old) { pane->calc_widths(FALSE); pane->set_header(); } } else { entry->launch_entry(_hwnd); } } void FileChildWindow::scan_entry(Entry* entry, HWND hwnd) { int idx = ListBox_GetCurSel(_left_hwnd); HCURSOR old_cursor = SetCursor(LoadCursor(0, IDC_WAIT)); // delete sub entries in left pane for(;;) { LRESULT res = ListBox_GetItemData(_left_hwnd, idx+1); Entry* sub = (Entry*) res; if (res==LB_ERR || !sub || sub->_level<=entry->_level) break; ListBox_DeleteString(_left_hwnd, idx+1); } // empty right pane ListBox_ResetContent(_right_hwnd); // release memory entry->free_subentries(); entry->_expanded = false; // read contents from disk entry->read_directory(_sortOrder); // insert found entries in right pane _right->insert_entries(entry->_down, -1); _right->calc_widths(false); _right->set_header(); _header_wdths_ok = FALSE; SetCursor(old_cursor); } int FileChildWindow::Notify(int id, NMHDR* pnmh) { return (pnmh->idFrom==IDW_HEADER_LEFT? _left: _right)->Notify(id, pnmh); } BOOL CALLBACK ExecuteDialog::WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam) { static struct ExecuteDialog* dlg; switch(nmsg) { case WM_INITDIALOG: dlg = (struct ExecuteDialog*) lparam; return 1; case WM_COMMAND: { int id = (int)wparam; if (id == IDOK) { GetWindowText(GetDlgItem(hwnd, 201), dlg->cmd, MAX_PATH); dlg->cmdshow = Button_GetState(GetDlgItem(hwnd,214))&BST_CHECKED? SW_SHOWMINIMIZED: SW_SHOWNORMAL; EndDialog(hwnd, id); } else if (id == IDCANCEL) EndDialog(hwnd, id); return 1;} } return 0; }