From da28077952faf9e716ed7987b842d31617a10125 Mon Sep 17 00:00:00 2001 From: Igor Pavlov Date: Thu, 11 Jan 2018 22:16:32 +0100 Subject: 18.00 --- CPP/7zip/UI/FileManager/LinkDialog.cpp | 6 +- CPP/7zip/UI/FileManager/PanelFolderChange.cpp | 3 +- CPP/7zip/UI/FileManager/PanelListNotify.cpp | 2 + CPP/7zip/UI/FileManager/PanelMenu.cpp | 119 +++++++++++++++++--------- CPP/7zip/UI/FileManager/PanelSelect.cpp | 3 + CPP/7zip/UI/FileManager/PanelSplitFile.cpp | 113 +++++++++++++++++++----- 6 files changed, 180 insertions(+), 66 deletions(-) (limited to 'CPP/7zip/UI/FileManager') diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp index 70b0ba65..ddef365c 100644 --- a/CPP/7zip/UI/FileManager/LinkDialog.cpp +++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp @@ -55,7 +55,8 @@ static bool GetSymLink(CFSTR path, CReparseAttr &attr) if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) return false; - if (!attr.Parse(buf, returnedSize)) + DWORD errorCode = 0; + if (!attr.Parse(buf, returnedSize, errorCode)) return false; CByteBuffer data2; @@ -291,7 +292,8 @@ void CLinkDialog::OnButton_Link() } CReparseAttr attr; - if (!attr.Parse(data, data.Size())) + DWORD errorCode = 0; + if (!attr.Parse(data, data.Size(), errorCode)) { ShowError(L"Internal conversion error"); return; diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp index 6e1e434f..1f93f862 100644 --- a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp +++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp @@ -827,7 +827,8 @@ void CPanel::OpenFolder(int index) SetNewFolder(newFolder); LoadFullPath(); RefreshListCtrl(); - _listView.SetItemState_Selected(_listView.GetFocusedItem()); + // 17.02: fixed : now we don't select first item + // _listView.SetItemState_Selected(_listView.GetFocusedItem()); _listView.EnsureVisible(_listView.GetFocusedItem(), false); } diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp index d7785d12..9061e585 100644 --- a/CPP/7zip/UI/FileManager/PanelListNotify.cpp +++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp @@ -702,6 +702,8 @@ void CPanel::Refresh_StatusBar() wchar_t temp[32]; ConvertUInt32ToString(indices.Size(), temp); + wcscat(temp, L" / "); + ConvertUInt32ToString(_selectedStatusVector.Size(), temp + wcslen(temp)); // UString s1 = MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, NumberToString(indices.Size())); // UString s1 = MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size())); diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 945a41f8..3db65be4 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -403,82 +403,117 @@ void CPanel::EditPaste() // InvokeSystemCommand("paste"); } + + +struct CFolderPidls +{ + LPITEMIDLIST parent; + CRecordVector items; + + CFolderPidls(): parent(NULL) {} + ~CFolderPidls() + { + FOR_VECTOR (i, items) + CoTaskMemFree(items[i]); + CoTaskMemFree(parent); + } +}; + + HRESULT CPanel::CreateShellContextMenu( const CRecordVector &operatedIndices, CMyComPtr &systemContextMenu) { systemContextMenu.Release(); - UString folderPath = GetFsPath(); + const UString folderPath = GetFsPath(); CMyComPtr desktopFolder; RINOK(::SHGetDesktopFolder(&desktopFolder)); if (!desktopFolder) { - // ShowMessage("Failed to get Desktop folder."); + // ShowMessage("Failed to get Desktop folder"); return E_FAIL; } - // Separate the file from the folder. - - - // Get a pidl for the folder the file - // is located in. - LPITEMIDLIST parentPidl; + CFolderPidls pidls; DWORD eaten; + + // if (folderPath.IsEmpty()), then ParseDisplayName returns pidls of "My Computer" RINOK(desktopFolder->ParseDisplayName( - GetParent(), 0, (wchar_t *)(const wchar_t *)folderPath, - &eaten, &parentPidl, 0)); + GetParent(), NULL, (wchar_t *)(const wchar_t *)folderPath, + &eaten, &pidls.parent, NULL)); + + /* + STRRET pName; + res = desktopFolder->GetDisplayNameOf(pidls.parent, SHGDN_NORMAL, &pName); + WCHAR dir[MAX_PATH]; + if (!SHGetPathFromIDListW(pidls.parent, dir)) + dir[0] = 0; + */ + + if (!pidls.parent) + return E_FAIL; + + if (operatedIndices.IsEmpty()) + { + // how to get IContextMenu, if there are no selected files? + return E_FAIL; + + /* + xp64 : + 1) we can't use GetUIObjectOf() with (numItems == 0), it throws exception + 2) we can't use desktopFolder->GetUIObjectOf() with absolute pidls of folder + context menu items are different in that case: + "Open / Explorer" for folder + "Delete" for "My Computer" icon + "Preperties" for "System" + */ + /* + parentFolder = desktopFolder; + pidls.items.AddInReserved(pidls.parent); + pidls.parent = NULL; + */ + + // CreateViewObject() doesn't show all context menu items + /* + HRESULT res = parentFolder->CreateViewObject( + GetParent(), IID_IContextMenu, (void**)&systemContextMenu); + */ + } - // Get an IShellFolder for the folder - // the file is located in. CMyComPtr parentFolder; - RINOK(desktopFolder->BindToObject(parentPidl, - 0, IID_IShellFolder, (void**)&parentFolder)); + RINOK(desktopFolder->BindToObject(pidls.parent, + NULL, IID_IShellFolder, (void**)&parentFolder)); if (!parentFolder) { - // ShowMessage("Invalid file name."); + // ShowMessage("Invalid file name"); return E_FAIL; } - // Get a pidl for the file itself. - CRecordVector pidls; - pidls.ClearAndReserve(operatedIndices.Size()); + pidls.items.ClearAndReserve(operatedIndices.Size()); FOR_VECTOR (i, operatedIndices) { LPITEMIDLIST pidl; - UString fileName = GetItemRelPath2(operatedIndices[i]); + const UString fileName = GetItemRelPath2(operatedIndices[i]); RINOK(parentFolder->ParseDisplayName(GetParent(), 0, - (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0)); - pidls.AddInReserved(pidl); - } - - ITEMIDLIST temp; - if (pidls.Size() == 0) - { - temp.mkid.cb = 0; - /* - LPITEMIDLIST pidl; - HRESULT result = parentFolder->ParseDisplayName(GetParent(), 0, - L"." WSTRING_PATH_SEPARATOR, &eaten, &pidl, 0); - if (result != NOERROR) - return; - */ - pidls.Add(&temp); + (wchar_t *)(const wchar_t *)fileName, &eaten, &pidl, 0)); + pidls.items.AddInReserved(pidl); } + + // Get IContextMenu for items - // Get the IContextMenu for the file. - CMyComPtr cm; - RINOK( parentFolder->GetUIObjectOf(GetParent(), pidls.Size(), - (LPCITEMIDLIST *)&pidls.Front(), IID_IContextMenu, 0, (void**)&cm)); - if (!cm) + RINOK(parentFolder->GetUIObjectOf(GetParent(), pidls.items.Size(), + (LPCITEMIDLIST *)&pidls.items.Front(), IID_IContextMenu, 0, (void**)&systemContextMenu)); + + if (!systemContextMenu) { - // ShowMessage("Unable to get context menu interface."); + // ShowMessage("Unable to get context menu interface"); return E_FAIL; } - systemContextMenu = cm; return S_OK; } + void CPanel::CreateSystemMenu(HMENU menuSpec, const CRecordVector &operatedIndices, CMyComPtr &systemContextMenu) diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp index 268b64af..8cfb23f4 100644 --- a/CPP/7zip/UI/FileManager/PanelSelect.cpp +++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp @@ -218,6 +218,8 @@ void CPanel::InvertSelection() FOR_VECTOR (i, _selectedStatusVector) if (_selectedStatusVector[i]) numSelected++; + // 17.02: fixed : now we invert item even, if single item is selected + /* if (numSelected == 1) { int focused = _listView.GetFocusedItem(); @@ -229,6 +231,7 @@ void CPanel::InvertSelection() _selectedStatusVector[realIndex] = false; } } + */ } FOR_VECTOR (i, _selectedStatusVector) _selectedStatusVector[i] = !_selectedStatusVector[i]; diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp index 3f7111a1..7cab2cf9 100644 --- a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp +++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp @@ -77,8 +77,6 @@ UString CVolSeqName::GetNextName() return UnchangedPart + ChangedPart; } -static const UInt32 kBufSize = (1 << 20); - class CThreadSplit: public CProgressThreadVirt { HRESULT ProcessVirt(); @@ -89,30 +87,84 @@ public: CRecordVector VolumeSizes; }; + +class CPreAllocOutFile +{ + UInt64 _preAllocSize; +public: + NIO::COutFile File; + UInt64 Written; + + CPreAllocOutFile(): _preAllocSize(0), Written(0) {} + + ~CPreAllocOutFile() + { + SetCorrectFileLength(); + } + + void PreAlloc(UInt64 preAllocSize) + { + _preAllocSize = 0; + if (File.SetLength(preAllocSize)) + _preAllocSize = preAllocSize; + File.SeekToBegin(); + } + + bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw() + { + bool res = File.Write(data, size, processedSize); + Written += processedSize; + return res; + } + + void Close() + { + SetCorrectFileLength(); + Written = 0; + _preAllocSize = 0; + File.Close(); + } + + void SetCorrectFileLength() + { + if (Written < _preAllocSize) + { + File.SetLength(Written); + _preAllocSize = 0; + } + } +}; + + +static const UInt32 kBufSize = (1 << 20); + HRESULT CThreadSplit::ProcessVirt() { NIO::CInFile inFile; if (!inFile.Open(FilePath)) return GetLastError(); - NIO::COutFile outFile; - CMyBuffer bufferObject; - if (!bufferObject.Allocate(kBufSize)) + + CPreAllocOutFile outFile; + + CMyBuffer buffer; + if (!buffer.Allocate(kBufSize)) return E_OUTOFMEMORY; - Byte *buffer = (Byte *)(void *)bufferObject; - UInt64 curVolSize = 0; + CVolSeqName seqName; seqName.SetNumDigits(NumVolumes); + UInt64 length; if (!inFile.GetLength(length)) return GetLastError(); CProgressSync &sync = ProgressDialog.Sync; sync.Set_NumBytesTotal(length); - UInt64 pos = 0; + UInt64 pos = 0; + UInt64 prev = 0; UInt64 numFiles = 0; unsigned volIndex = 0; - + for (;;) { UInt64 volSize; @@ -121,46 +173,65 @@ HRESULT CThreadSplit::ProcessVirt() else volSize = VolumeSizes.Back(); - UInt32 needSize = (UInt32)(MyMin((UInt64)kBufSize, volSize - curVolSize)); + UInt32 needSize = kBufSize; + { + const UInt64 rem = volSize - outFile.Written; + if (needSize > rem) + needSize = (UInt32)rem; + } UInt32 processedSize; if (!inFile.Read(buffer, needSize, processedSize)) return GetLastError(); if (processedSize == 0) - break; + return S_OK; needSize = processedSize; - if (curVolSize == 0) + + if (outFile.Written == 0) { FString name = VolBasePath; name += '.'; name += us2fs(seqName.GetNextName()); sync.Set_FilePath(fs2us(name)); - sync.Set_NumFilesCur(numFiles++); - if (!outFile.Create(name, false)) + if (!outFile.File.Create(name, false)) { HRESULT res = GetLastError(); AddErrorPath(name); return res; } + UInt64 expectSize = volSize; + if (pos < length) + { + const UInt64 rem = length - pos; + if (expectSize > rem) + expectSize = rem; + } + outFile.PreAlloc(expectSize); } + if (!outFile.Write(buffer, needSize, processedSize)) return GetLastError(); if (needSize != processedSize) throw g_Message_FileWriteError; - curVolSize += processedSize; - if (curVolSize == volSize) + + pos += processedSize; + + if (outFile.Written == volSize) { outFile.Close(); + sync.Set_NumFilesCur(++numFiles); if (volIndex < VolumeSizes.Size()) volIndex++; - curVolSize = 0; } - pos += processedSize; - RINOK(sync.Set_NumBytesCur(pos)); + + if (pos - prev >= ((UInt32)1 << 22) || outFile.Written == 0) + { + RINOK(sync.Set_NumBytesCur(pos)); + prev = pos; + } } - sync.Set_NumFilesCur(numFiles); - return S_OK; } + void CApp::Split() { int srcPanelIndex = GetFocusedPanelIndex(); -- cgit v1.2.3