// BrowseDialog.cpp | |
#include "StdAfx.h" | |
#ifndef UNDER_CE | |
#include "../../../Windows/CommonDialog.h" | |
#include "../../../Windows/Shell.h" | |
#endif | |
#include "../../../Windows/FileName.h" | |
#include "../../../Windows/FileFind.h" | |
#ifdef UNDER_CE | |
#include <commdlg.h> | |
#endif | |
#include "BrowseDialog.h" | |
#define USE_MY_BROWSE_DIALOG | |
#ifdef USE_MY_BROWSE_DIALOG | |
#include "../../../Common/Defs.h" | |
#include "../../../Common/IntToString.h" | |
#include "../../../Common/Wildcard.h" | |
#include "../../../Windows/FileDir.h" | |
#include "../../../Windows/PropVariantConv.h" | |
#include "../../../Windows/Control/ComboBox.h" | |
#include "../../../Windows/Control/Dialog.h" | |
#include "../../../Windows/Control/Edit.h" | |
#include "../../../Windows/Control/ListView.h" | |
#include "BrowseDialogRes.h" | |
#include "PropertyNameRes.h" | |
#include "SysIconUtils.h" | |
#ifndef _SFX | |
#include "RegistryUtils.h" | |
#endif | |
#endif | |
#include "ComboDialog.h" | |
#include "LangUtils.h" | |
#include "resource.h" | |
using namespace NWindows; | |
using namespace NFile; | |
using namespace NName; | |
using namespace NFind; | |
#ifdef USE_MY_BROWSE_DIALOG | |
extern bool g_LVN_ITEMACTIVATE_Support; | |
static const int kParentIndex = -1; | |
static const UINT k_Message_RefreshPathEdit = WM_APP + 1; | |
static HRESULT GetNormalizedError() | |
{ | |
DWORD errorCode = GetLastError(); | |
return errorCode == 0 ? E_FAIL : errorCode; | |
} | |
extern UString HResultToMessage(HRESULT errorCode); | |
static void MessageBox_Error_Global(HWND wnd, const wchar_t *message) | |
{ | |
::MessageBoxW(wnd, message, L"7-Zip", MB_ICONERROR); | |
} | |
static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name) | |
{ | |
UString s = HResultToMessage(errorCode); | |
if (name) | |
{ | |
s += L'\n'; | |
s += name; | |
} | |
MessageBox_Error_Global(wnd, s); | |
} | |
class CBrowseDialog: public NControl::CModalDialog | |
{ | |
NControl::CListView _list; | |
NControl::CEdit _pathEdit; | |
NControl::CComboBox _filterCombo; | |
CObjectVector<CFileInfo> _files; | |
CExtToIconMap _extToIconMap; | |
int _sortIndex; | |
bool _ascending; | |
bool _showDots; | |
UString _topDirPrefix; // we don't open parent of that folder | |
UString DirPrefix; | |
virtual bool OnInit(); | |
virtual bool OnSize(WPARAM wParam, int xSize, int ySize); | |
virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam); | |
virtual bool OnNotify(UINT controlID, LPNMHDR header); | |
virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo); | |
virtual bool OnButtonClicked(int buttonID, HWND buttonHWND); | |
virtual void OnOK(); | |
void Post_RefreshPathEdit() { PostMessage(k_Message_RefreshPathEdit); } | |
bool GetParentPath(const UString &path, UString &parentPrefix, UString &name); | |
// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter | |
HRESULT Reload(const UString &pathPrefix, const UString &selectedName); | |
HRESULT Reload(); | |
void OpenParentFolder(); | |
void SetPathEditText(); | |
void OnCreateDir(); | |
void OnItemEnter(); | |
void FinishOnOK(); | |
int GetRealItemIndex(int indexInListView) const | |
{ | |
LPARAM param; | |
if (!_list.GetItemParam(indexInListView, param)) | |
return (int)-1; | |
return (int)param; | |
} | |
public: | |
bool FolderMode; | |
UString Title; | |
UString FilePath; // input/ result path | |
bool ShowAllFiles; | |
UStringVector Filters; | |
UString FilterDescription; | |
CBrowseDialog(): FolderMode(false), _showDots(false), ShowAllFiles(true) {} | |
void SetFilter(const UString &s); | |
INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_BROWSE, parent); } | |
int CompareItems(LPARAM lParam1, LPARAM lParam2); | |
}; | |
void CBrowseDialog::SetFilter(const UString &s) | |
{ | |
Filters.Clear(); | |
UString mask; | |
unsigned i; | |
for (i = 0; i < s.Len(); i++) | |
{ | |
wchar_t c = s[i]; | |
if (c == ';') | |
{ | |
if (!mask.IsEmpty()) | |
Filters.Add(mask); | |
mask.Empty(); | |
} | |
else | |
mask += c; | |
} | |
if (!mask.IsEmpty()) | |
Filters.Add(mask); | |
ShowAllFiles = Filters.IsEmpty(); | |
for (i = 0; i < Filters.Size(); i++) | |
{ | |
const UString &f = Filters[i]; | |
if (f == L"*.*" || f == L"*") | |
{ | |
ShowAllFiles = true; | |
break; | |
} | |
} | |
} | |
bool CBrowseDialog::OnInit() | |
{ | |
#ifdef LANG | |
LangSetDlgItems(*this, NULL, 0); | |
#endif | |
if (!Title.IsEmpty()) | |
SetText(Title); | |
_list.Attach(GetItem(IDL_BROWSE)); | |
_filterCombo.Attach(GetItem(IDC_BROWSE_FILTER)); | |
_pathEdit.Attach(GetItem(IDE_BROWSE_PATH)); | |
if (FolderMode) | |
HideItem(IDC_BROWSE_FILTER); | |
else | |
EnableItem(IDC_BROWSE_FILTER, false); | |
#ifndef UNDER_CE | |
_list.SetUnicodeFormat(); | |
#endif | |
#ifndef _SFX | |
if (ReadSingleClick()) | |
_list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT); | |
_showDots = ReadShowDots(); | |
#endif | |
{ | |
UString s; | |
if (!FilterDescription.IsEmpty()) | |
s = FilterDescription; | |
else if (ShowAllFiles) | |
s = L"*.*"; | |
else | |
{ | |
FOR_VECTOR (i, Filters) | |
{ | |
if (i != 0) | |
s += L' '; | |
s += Filters[i]; | |
} | |
} | |
_filterCombo.AddString(s); | |
_filterCombo.SetCurSel(0); | |
} | |
_list.SetImageList(GetSysImageList(true), LVSIL_SMALL); | |
_list.SetImageList(GetSysImageList(false), LVSIL_NORMAL); | |
_list.InsertColumn(0, LangString(IDS_PROP_NAME), 100); | |
_list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100); | |
{ | |
LV_COLUMNW column; | |
column.iSubItem = 2; | |
column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; | |
column.fmt = LVCFMT_RIGHT; | |
column.cx = 100; | |
const UString s = LangString(IDS_PROP_SIZE); | |
column.pszText = (wchar_t *)(const wchar_t *)s; | |
_list.InsertColumn(2, &column); | |
} | |
_list.InsertItem(0, L"12345678901234567" | |
#ifndef UNDER_CE | |
L"1234567890" | |
#endif | |
); | |
_list.SetSubItem(0, 1, L"2009-09-09" | |
#ifndef UNDER_CE | |
L" 09:09" | |
#endif | |
); | |
_list.SetSubItem(0, 2, L"9999 MB"); | |
for (int i = 0; i < 3; i++) | |
_list.SetColumnWidthAuto(i); | |
_list.DeleteAllItems(); | |
_ascending = true; | |
_sortIndex = 0; | |
NormalizeSize(); | |
_topDirPrefix.Empty(); | |
{ | |
int rootSize = GetRootPrefixSize(FilePath); | |
// We can go up from root folder to drives list | |
if (NName::IsDrivePath(FilePath)) | |
rootSize = 0; | |
else if (IsSuperPath(FilePath)) | |
{ | |
if (NName::IsDrivePath(&FilePath[kSuperPathPrefixSize])) | |
rootSize = kSuperPathPrefixSize; | |
} | |
_topDirPrefix.SetFrom(FilePath, rootSize); | |
} | |
UString name; | |
if (!GetParentPath(FilePath, DirPrefix, name)) | |
DirPrefix = _topDirPrefix; | |
for(;;) | |
{ | |
UString baseFolder = DirPrefix; | |
if (Reload(baseFolder, name) == S_OK) | |
break; | |
name.Empty(); | |
if (DirPrefix.IsEmpty()) | |
break; | |
UString parent, name2; | |
GetParentPath(DirPrefix, parent, name2); | |
DirPrefix = parent; | |
} | |
if (name.IsEmpty()) | |
name = FilePath; | |
if (FolderMode) | |
NormalizeDirPathPrefix(name); | |
_pathEdit.SetText(name); | |
#ifndef UNDER_CE | |
/* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible, | |
even if we use mouse for pressing the button to open this dialog. */ | |
PostMessage(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS)); | |
#endif | |
return CModalDialog::OnInit(); | |
} | |
bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize) | |
{ | |
int mx, my; | |
{ | |
RECT r; | |
GetClientRectOfItem(IDB_BROWSE_PARENT, r); | |
mx = r.left; | |
my = r.top; | |
} | |
InvalidateRect(NULL); | |
int xLim = xSize - mx; | |
{ | |
RECT r; | |
GetClientRectOfItem(IDT_BROWSE_FOLDER, r); | |
MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r)); | |
} | |
int bx1, bx2, by; | |
GetItemSizes(IDCANCEL, bx1, by); | |
GetItemSizes(IDOK, bx2, by); | |
int y = ySize - my - by; | |
int x = xLim - bx1; | |
MoveItem(IDCANCEL, x, y, bx1, by); | |
MoveItem(IDOK, x - mx - bx2, y, bx2, by); | |
// Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead | |
int yPathSize; | |
{ | |
RECT r; | |
GetClientRectOfItem(IDE_BROWSE_PATH, r); | |
yPathSize = RECT_SIZE_Y(r); | |
_pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize); | |
} | |
{ | |
RECT r; | |
GetClientRectOfItem(IDC_BROWSE_FILTER, r); | |
_filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r)); | |
} | |
{ | |
RECT r; | |
GetClientRectOfItem(IDL_BROWSE, r); | |
_list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top); | |
} | |
return false; | |
} | |
bool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) | |
{ | |
if (message == k_Message_RefreshPathEdit) | |
{ | |
SetPathEditText(); | |
return true; | |
} | |
return CModalDialog::OnMessage(message, wParam, lParam); | |
} | |
bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header) | |
{ | |
if (header->hwndFrom != _list) | |
return false; | |
switch (header->code) | |
{ | |
case LVN_ITEMACTIVATE: | |
if (g_LVN_ITEMACTIVATE_Support) | |
OnItemEnter(); | |
break; | |
case NM_DBLCLK: | |
case NM_RETURN: // probabably it's unused | |
if (!g_LVN_ITEMACTIVATE_Support) | |
OnItemEnter(); | |
break; | |
case LVN_COLUMNCLICK: | |
{ | |
int index = LPNMLISTVIEW(header)->iSubItem; | |
if (index == _sortIndex) | |
_ascending = !_ascending; | |
else | |
{ | |
_ascending = (index == 0); | |
_sortIndex = index; | |
} | |
Reload(); | |
return false; | |
} | |
case LVN_KEYDOWN: | |
{ | |
bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header)); | |
Post_RefreshPathEdit(); | |
return boolResult; | |
} | |
case NM_RCLICK: | |
case NM_CLICK: | |
case LVN_BEGINDRAG: | |
Post_RefreshPathEdit(); | |
break; | |
} | |
return false; | |
} | |
bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo) | |
{ | |
bool ctrl = IsKeyDown(VK_CONTROL); | |
switch (keyDownInfo->wVKey) | |
{ | |
case VK_BACK: | |
OpenParentFolder(); | |
return true; | |
case 'R': | |
if (ctrl) | |
{ | |
Reload(); | |
return true; | |
} | |
return false; | |
case VK_F7: | |
OnCreateDir(); | |
return true; | |
} | |
return false; | |
} | |
bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND) | |
{ | |
switch (buttonID) | |
{ | |
case IDB_BROWSE_PARENT: OpenParentFolder(); break; | |
case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break; | |
default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND); | |
} | |
_list.SetFocus(); | |
return true; | |
} | |
void CBrowseDialog::OnOK() | |
{ | |
/* When we press "Enter" in listview, Windows sends message to first Button. | |
We check that message was from ListView; */ | |
if (GetFocus() == _list) | |
{ | |
OnItemEnter(); | |
return; | |
} | |
FinishOnOK(); | |
} | |
bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name) | |
{ | |
parentPrefix.Empty(); | |
name.Empty(); | |
if (path.IsEmpty()) | |
return false; | |
if (_topDirPrefix == path) | |
return false; | |
UString s = path; | |
if (s.Back() == WCHAR_PATH_SEPARATOR) | |
s.DeleteBack(); | |
if (s.IsEmpty()) | |
return false; | |
if (s.Back() == WCHAR_PATH_SEPARATOR) | |
return false; | |
int pos = s.ReverseFind(WCHAR_PATH_SEPARATOR); | |
parentPrefix.SetFrom(s, pos + 1); | |
name = s.Ptr(pos + 1); | |
return true; | |
} | |
int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) | |
{ | |
if (lParam1 == kParentIndex) return -1; | |
if (lParam2 == kParentIndex) return 1; | |
const CFileInfo &f1 = _files[(int)lParam1]; | |
const CFileInfo &f2 = _files[(int)lParam2]; | |
bool isDir1 = f1.IsDir(); | |
bool isDir2 = f2.IsDir(); | |
if (isDir1 && !isDir2) return -1; | |
if (isDir2 && !isDir1) return 1; | |
int res = 0; | |
switch (_sortIndex) | |
{ | |
case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break; | |
case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break; | |
case 2: res = MyCompare(f1.Size, f2.Size); break; | |
} | |
return _ascending ? res: -res; | |
} | |
static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) | |
{ | |
return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2); | |
} | |
static void ConvertSizeToString(UInt64 v, wchar_t *s) | |
{ | |
Byte c = 0; | |
if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; } | |
else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; } | |
else if (v >= ((UInt64)10000 << 0)) { v >>= 10; c = 'K'; } | |
ConvertUInt64ToString(v, s); | |
if (c != 0) | |
{ | |
s += MyStringLen(s); | |
*s++ = ' '; | |
*s++ = c; | |
*s++ = 0; | |
} | |
} | |
// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter | |
HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName) | |
{ | |
CObjectVector<CFileInfo> files; | |
#ifndef UNDER_CE | |
bool isDrive = false; | |
if (pathPrefix.IsEmpty() || pathPrefix == kSuperPathPrefix) | |
{ | |
isDrive = true; | |
FStringVector drives; | |
if (!MyGetLogicalDriveStrings(drives)) | |
return GetNormalizedError(); | |
FOR_VECTOR (i, drives) | |
{ | |
FString d = drives[i]; | |
if (d.Len() < 3 || d.Back() != '\\') | |
return E_FAIL; | |
d.DeleteBack(); | |
CFileInfo &fi = files.AddNew(); | |
fi.SetAsDir(); | |
fi.Name = d; | |
} | |
} | |
else | |
#endif | |
{ | |
CEnumerator enumerator(us2fs(pathPrefix + L'*')); | |
for (;;) | |
{ | |
bool found; | |
CFileInfo fi; | |
if (!enumerator.Next(fi, found)) | |
return GetNormalizedError(); | |
if (!found) | |
break; | |
if (!fi.IsDir()) | |
{ | |
if (FolderMode) | |
continue; | |
if (!ShowAllFiles) | |
{ | |
unsigned i; | |
for (i = 0; i < Filters.Size(); i++) | |
if (DoesWildcardMatchName(Filters[i], fs2us(fi.Name))) | |
break; | |
if (i == Filters.Size()) | |
continue; | |
} | |
} | |
files.Add(fi); | |
} | |
} | |
DirPrefix = pathPrefix; | |
_files = files; | |
SetItemText(IDT_BROWSE_FOLDER, DirPrefix); | |
_list.SetRedraw(false); | |
_list.DeleteAllItems(); | |
LVITEMW item; | |
int index = 0; | |
int cursorIndex = -1; | |
#ifndef _SFX | |
if (_showDots && _topDirPrefix != DirPrefix) | |
{ | |
item.iItem = index; | |
const UString itemName = L".."; | |
if (selectedName.IsEmpty()) | |
cursorIndex = index; | |
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; | |
int subItem = 0; | |
item.iSubItem = subItem++; | |
item.lParam = kParentIndex; | |
item.pszText = (wchar_t *)(const wchar_t *)itemName; | |
item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix); | |
if (item.iImage < 0) | |
item.iImage = 0; | |
_list.InsertItem(&item); | |
_list.SetSubItem(index, subItem++, L""); | |
_list.SetSubItem(index, subItem++, L""); | |
index++; | |
} | |
#endif | |
for (unsigned i = 0; i < _files.Size(); i++, index++) | |
{ | |
item.iItem = index; | |
const CFileInfo &fi = _files[i]; | |
const UString name = fs2us(fi.Name); | |
if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0) | |
cursorIndex = index; | |
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE; | |
int subItem = 0; | |
item.iSubItem = subItem++; | |
item.lParam = i; | |
item.pszText = (wchar_t *)(const wchar_t *)name; | |
const UString fullPath = DirPrefix + name; | |
#ifndef UNDER_CE | |
if (isDrive) | |
{ | |
if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0) | |
item.iImage = 0; | |
} | |
else | |
#endif | |
item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath); | |
if (item.iImage < 0) | |
item.iImage = 0; | |
_list.InsertItem(&item); | |
wchar_t s[32]; | |
{ | |
FILETIME ft; | |
s[0] = 0; | |
if (FileTimeToLocalFileTime(&fi.MTime, &ft)) | |
ConvertFileTimeToString(ft, s, | |
#ifndef UNDER_CE | |
true | |
#else | |
false | |
#endif | |
, false); | |
_list.SetSubItem(index, subItem++, s); | |
} | |
{ | |
s[0] = 0; | |
if (!fi.IsDir()) | |
ConvertSizeToString(fi.Size, s); | |
_list.SetSubItem(index, subItem++, s); | |
} | |
} | |
if (_list.GetItemCount() > 0 && cursorIndex >= 0) | |
_list.SetItemState_FocusedSelected(cursorIndex); | |
_list.SortItems(CompareItems2, (LPARAM)this); | |
if (_list.GetItemCount() > 0 && cursorIndex < 0) | |
_list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED); | |
_list.EnsureVisible(_list.GetFocusedItem(), false); | |
_list.SetRedraw(true); | |
_list.InvalidateRect(NULL, true); | |
return S_OK; | |
} | |
HRESULT CBrowseDialog::Reload() | |
{ | |
UString selected; | |
int index = _list.GetNextSelectedItem(-1); | |
if (index >= 0) | |
{ | |
int fileIndex = GetRealItemIndex(index); | |
if (fileIndex != kParentIndex) | |
selected = fs2us(_files[fileIndex].Name); | |
} | |
UString dirPathTemp = DirPrefix; | |
return Reload(dirPathTemp, selected); | |
} | |
void CBrowseDialog::OpenParentFolder() | |
{ | |
UString parent, selected; | |
if (GetParentPath(DirPrefix, parent, selected)) | |
{ | |
Reload(parent, selected); | |
SetPathEditText(); | |
} | |
} | |
void CBrowseDialog::SetPathEditText() | |
{ | |
int index = _list.GetNextSelectedItem(-1); | |
if (index < 0) | |
{ | |
if (FolderMode) | |
_pathEdit.SetText(DirPrefix); | |
return; | |
} | |
int fileIndex = GetRealItemIndex(index); | |
if (fileIndex == kParentIndex) | |
{ | |
if (FolderMode) | |
_pathEdit.SetText(L".." WSTRING_PATH_SEPARATOR); | |
return; | |
} | |
const CFileInfo &file = _files[fileIndex]; | |
if (file.IsDir()) | |
{ | |
if (!FolderMode) | |
return; | |
_pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR); | |
} | |
else | |
_pathEdit.SetText(fs2us(file.Name)); | |
} | |
void CBrowseDialog::OnCreateDir() | |
{ | |
UString name; | |
{ | |
UString enteredName; | |
Dlg_CreateFolder((HWND)*this, enteredName); | |
if (enteredName.IsEmpty()) | |
return; | |
if (!CorrectFsPath(DirPrefix, enteredName, name)) | |
{ | |
MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name); | |
return; | |
} | |
} | |
if (name.IsEmpty()) | |
return; | |
FString destPath; | |
if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath)) | |
{ | |
if (!NDir::CreateComplexDir(destPath)) | |
{ | |
MessageBox_HResError((HWND)*this, GetNormalizedError(), fs2us(destPath)); | |
} | |
else | |
{ | |
UString tempPath = DirPrefix; | |
Reload(tempPath, name); | |
SetPathEditText(); | |
} | |
_list.SetFocus(); | |
} | |
} | |
void CBrowseDialog::OnItemEnter() | |
{ | |
int index = _list.GetNextSelectedItem(-1); | |
if (index < 0) | |
return; | |
int fileIndex = GetRealItemIndex(index); | |
if (fileIndex == kParentIndex) | |
OpenParentFolder(); | |
else | |
{ | |
const CFileInfo &file = _files[fileIndex]; | |
if (!file.IsDir()) | |
{ | |
if (!FolderMode) | |
FinishOnOK(); | |
/* | |
MessageBox_Error_Global(*this, FolderMode ? | |
L"You must select some folder": | |
L"You must select some file"); | |
*/ | |
return; | |
} | |
UString s = DirPrefix + fs2us(file.Name) + WCHAR_PATH_SEPARATOR; | |
HRESULT res = Reload(s, L""); | |
if (res != S_OK) | |
MessageBox_HResError(*this, res, s); | |
SetPathEditText(); | |
} | |
} | |
void CBrowseDialog::FinishOnOK() | |
{ | |
UString s; | |
_pathEdit.GetText(s); | |
FString destPath; | |
if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath)) | |
{ | |
MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s); | |
return; | |
} | |
FilePath = fs2us(destPath); | |
if (FolderMode) | |
NormalizeDirPathPrefix(FilePath); | |
End(IDOK); | |
} | |
#endif | |
bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath) | |
{ | |
resultPath.Empty(); | |
#ifndef UNDER_CE | |
#ifdef USE_MY_BROWSE_DIALOG | |
if (!IsSuperOrDevicePath(path)) | |
#endif | |
return NShell::BrowseForFolder(owner, title, path, resultPath); | |
#endif | |
#ifdef USE_MY_BROWSE_DIALOG | |
CBrowseDialog dialog; | |
dialog.FolderMode = true; | |
if (title) | |
dialog.Title = title; | |
if (path) | |
dialog.FilePath = path; | |
if (dialog.Create(owner) != IDOK) | |
return false; | |
resultPath = dialog.FilePath; | |
#endif | |
return true; | |
} | |
bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, | |
LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath) | |
{ | |
resultPath.Empty(); | |
#ifndef UNDER_CE | |
#ifdef USE_MY_BROWSE_DIALOG | |
if (!IsSuperOrDevicePath(path)) | |
#endif | |
{ | |
if (MyGetOpenFileName(owner, title, NULL, path, filterDescription, filter, resultPath)) | |
return true; | |
#ifdef UNDER_CE | |
return false; | |
#else | |
// maybe we must use GetLastError in WinCE. | |
DWORD errorCode = CommDlgExtendedError(); | |
const wchar_t *errorMessage = NULL; | |
switch (errorCode) | |
{ | |
case 0: return false; // cancel or close obn dialog | |
case FNERR_INVALIDFILENAME: errorMessage = L"Invalid File Name"; break; | |
default: errorMessage = L"Open Dialog Error"; | |
} | |
if (!errorMessage) | |
return false; | |
{ | |
UString s = errorMessage; | |
s += L"\n"; | |
s += path; | |
MessageBox_Error_Global(owner, s); | |
} | |
#endif | |
} | |
#endif | |
#ifdef USE_MY_BROWSE_DIALOG | |
CBrowseDialog dialog; | |
if (title) | |
dialog.Title = title; | |
if (path) | |
dialog.FilePath = path; | |
dialog.FolderMode = false; | |
if (filter) | |
dialog.SetFilter(filter); | |
if (filterDescription) | |
dialog.FilterDescription = filterDescription; | |
if (dialog.Create(owner) != IDOK) | |
return false; | |
resultPath = dialog.FilePath; | |
#endif | |
return true; | |
} | |
#ifdef _WIN32 | |
static void RemoveDotsAndSpaces(UString &path) | |
{ | |
while (!path.IsEmpty()) | |
{ | |
wchar_t c = path.Back(); | |
if (c != ' ' && c != '.') | |
return; | |
path.DeleteBack(); | |
} | |
} | |
bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result) | |
{ | |
result.Empty(); | |
UString path = path2; | |
path.Replace('/', WCHAR_PATH_SEPARATOR); | |
unsigned start = 0; | |
UString base; | |
if (NName::IsAbsolutePath(path)) | |
{ | |
if (IsSuperOrDevicePath(path)) | |
{ | |
result = path; | |
return true; | |
} | |
int pos = GetRootPrefixSize(path); | |
if (pos > 0) | |
start = pos; | |
} | |
else | |
{ | |
if (IsSuperOrDevicePath(relBase)) | |
{ | |
result = path; | |
return true; | |
} | |
base = relBase; | |
} | |
/* We can't use backward, since we must change only disk paths */ | |
/* | |
for (;;) | |
{ | |
if (path.Len() <= start) | |
break; | |
if (DoesFileOrDirExist(us2fs(path))) | |
break; | |
if (path.Back() == WCHAR_PATH_SEPARATOR) | |
{ | |
path.DeleteBack(); | |
result.Insert(0, WCHAR_PATH_SEPARATOR);; | |
} | |
int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1; | |
UString cur = path.Ptr(pos); | |
RemoveDotsAndSpaces(cur); | |
result.Insert(0, cur); | |
path.DeleteFrom(pos); | |
} | |
result.Insert(0, path); | |
return true; | |
*/ | |
result += path.Left(start); | |
bool checkExist = true; | |
UString cur; | |
for (;;) | |
{ | |
if (start == path.Len()) | |
break; | |
int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start); | |
cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : slashPos) - start); | |
if (checkExist) | |
{ | |
CFileInfo fi; | |
if (fi.Find(us2fs(base + result + cur))) | |
{ | |
if (!fi.IsDir()) | |
{ | |
result = path; | |
break; | |
} | |
} | |
else | |
checkExist = false; | |
} | |
if (!checkExist) | |
RemoveDotsAndSpaces(cur); | |
result += cur; | |
if (slashPos < 0) | |
break; | |
result += WCHAR_PATH_SEPARATOR; | |
start = slashPos + 1; | |
} | |
return true; | |
} | |
#else | |
bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result) | |
{ | |
result = path; | |
return true; | |
} | |
#endif | |
bool Dlg_CreateFolder(HWND wnd, UString &destName) | |
{ | |
destName.Empty(); | |
CComboDialog dlg; | |
LangString(IDS_CREATE_FOLDER, dlg.Title); | |
LangString(IDS_CREATE_FOLDER_NAME, dlg.Static); | |
LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value); | |
if (dlg.Create(wnd) != IDOK) | |
return false; | |
destName = dlg.Value; | |
return true; | |
} |