diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2021-11-29 06:08:41 +0300 |
---|---|---|
committer | fn ⌃ ⌥ <70830482+FnControlOption@users.noreply.github.com> | 2021-11-29 06:08:41 +0300 |
commit | ccbf6ad3c1dffaffd43890e62235b3a860bc9081 (patch) | |
tree | bdb7b203c923af669be1a7efe88ffaead9ec487a /CPP/7zip/UI | |
parent | 1194dc935382931bbfdd4e49004bd755e6165df1 (diff) |
21.0621.06
Diffstat (limited to 'CPP/7zip/UI')
21 files changed, 1027 insertions, 175 deletions
diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp index b85a0ae6..9fea6dc2 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp @@ -348,6 +348,8 @@ STDMETHODIMP CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const U void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts, FString &fullPath) { + // we use (_item.IsDir) in this function + bool isAbsPath = false; if (!dirPathParts.IsEmpty()) @@ -375,12 +377,41 @@ void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPat fullPath.Add_PathSepar(); const UString &s = dirPathParts[i]; fullPath += us2fs(s); + + const bool isFinalDir = (i == dirPathParts.Size() - 1 && _item.IsDir); + + if (fullPath.IsEmpty()) + { + if (isFinalDir) + _itemFailure = true; + continue; + } + #if defined(_WIN32) && !defined(UNDER_CE) if (_pathMode == NExtract::NPathMode::kAbsPaths) if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s)) + { + if (isFinalDir) + { + // we don't want to call SetAttrib() for root drive path + _itemFailure = true; + } continue; + } #endif + + // bool res = CreateDir(fullPath); + // if (!res) + if (isFinalDir) + { + if (!NFile::NFind::DoesDirExist(fullPath)) + { + _itemFailure = true; + SendMessageError("Cannot create folder", fullPath); + // SendMessageError_with_LastError() + } + } } } @@ -655,6 +686,7 @@ HRESULT CArchiveExtractCallback::ReadLink() { IInArchive *archive = _arc->Archive; const UInt32 index = _index; + _link.Clear(); { NCOM::CPropVariant prop; @@ -717,7 +749,8 @@ HRESULT CArchiveExtractCallback::ReadLink() if (propType != NPropDataType::kRaw) return E_FAIL; - #ifdef _WIN32 + // 21.06: we need kpidNtReparse in linux for wim archives created in Windows + // #ifdef _WIN32 NtReparse_Data = data; NtReparse_Size = dataSize; @@ -739,11 +772,14 @@ HRESULT CArchiveExtractCallback::ReadLink() else _link.isRelative = reparse.IsRelative_Win(); + // const AString s = GetAnsiString(_link.linkPath); + // printf("\n_link.linkPath: %s\n", s.Ptr()); + #ifndef _WIN32 _link.linkPath.Replace(L'\\', WCHAR_PATH_SEPARATOR); #endif } - #endif + // #endif } } @@ -908,7 +944,10 @@ void CArchiveExtractCallback::CreateFolders() if (!_item.IsDir) return; - CDirPathTime &pt = _extractedFolders.AddNew(); + if (_itemFailure) + return; + + CDirPathTime pt; pt.CTime = _fi.CTime; pt.CTimeDefined = (WriteCTime && _fi.CTimeDefined); @@ -931,9 +970,13 @@ void CArchiveExtractCallback::CreateFolders() pt.MTimeDefined = true; } } - - pt.Path = fullPathNew; - pt.SetDirTime(); + + if (pt.MTimeDefined || pt.ATimeDefined || pt.CTimeDefined) + { + pt.Path = fullPathNew; + pt.SetDirTime(); + _extractedFolders.Add(pt); + } } @@ -1125,7 +1168,11 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream #ifdef SUPPORT_LINKS if (_link.linkPath.IsEmpty()) #endif + { + if (!isAnti) + SetAttrib(); return S_OK; + } } else if (!_isSplit) { @@ -1154,6 +1201,12 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream { bool linkWasSet = false; RINOK(SetFromLinkPath(fullProcessedPath, _link, linkWasSet)); + if (linkWasSet) + { + _isSymLinkCreated = _link.IsSymLink(); + SetAttrib(); + // printf("\nlinkWasSet %s\n", GetAnsiString(_diskFilePath)); + } } #endif // UNDER_CE @@ -1186,6 +1239,9 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream return S_OK; } + // printf("\nHard linkWasSet Archive_Get_HardLinkNode %s\n", GetAnsiString(_diskFilePath)); + // _needSetAttrib = true; // do we need to set attribute ? + SetAttrib(); needExit = false; return S_OK; } @@ -1210,22 +1266,25 @@ HRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream } } - _fileWasExtracted = true; + _needSetAttrib = true; + + bool is_SymLink_in_Data = false; if (_curSizeDefined && _curSize > 0 && _curSize < (1 << 12)) { if (_fi.IsLinuxSymLink()) { - _is_SymLink_in_Data = true; + is_SymLink_in_Data = true; _is_SymLink_in_Data_Linux = true; } else if (_fi.IsReparse()) { - _is_SymLink_in_Data = true; + is_SymLink_in_Data = true; _is_SymLink_in_Data_Linux = false; } } - if (_is_SymLink_in_Data) + + if (is_SymLink_in_Data) { _outMemBuf.Alloc((size_t)_curSize); _bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream; @@ -1347,17 +1406,36 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStre _diskFilePath.Empty(); _isRenamed = false; + // _fi.Clear(); - _is_SymLink_in_Data = false; - _is_SymLink_in_Data_Linux = false; - _fileWasExtracted = false; + // _is_SymLink_in_Data = false; + _is_SymLink_in_Data_Linux = false; + + _needSetAttrib = false; + _isSymLinkCreated = false; + _itemFailure = false; #ifdef SUPPORT_LINKS // _CopyFile_Path.Empty(); _link.Clear(); #endif + _extractMode = false; + + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: + if (_testMode) + { + // askExtractMode = NArchive::NExtract::NAskMode::kTest; + } + else + _extractMode = true; + break; + }; + + IInArchive *archive = _arc->Archive; RINOK(GetItem(index)); @@ -1832,6 +1910,7 @@ HRESULT CArchiveExtractCallback::SetFromLinkPath( bool CLinkInfo::Parse(const Byte *data, size_t dataSize, bool isLinuxData) { + Clear(); // this->isLinux = isLinuxData; if (isLinuxData) @@ -1955,10 +2034,20 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() RINOK(SendMessageError_with_LastError("can't delete file", _diskFilePath)); } { + /* + // for DEBUG ONLY: we can extract sym links as WSL links + // to elimanate (non-admin) errors for sym links. + #ifdef _WIN32 + if (!linkInfo.isHardLink && !linkInfo.isJunction) + linkInfo.isWSL = true; + #endif + */ bool linkWasSet = false; RINOK(SetFromLinkPath(_diskFilePath, linkInfo, linkWasSet)); - if (!linkWasSet) - _fileWasExtracted = false; + if (linkWasSet) + _isSymLinkCreated = linkInfo.IsSymLink(); + else + _needSetAttrib = false; } /* if (!NFile::NIO::SetReparseData(_diskFilePath, _item.IsDir, )) @@ -1974,11 +2063,40 @@ HRESULT CArchiveExtractCallback::CloseReparseAndFile() } +void CArchiveExtractCallback::SetAttrib() +{ + #ifndef _WIN32 + // Linux now doesn't support permissions for symlinks + if (_isSymLinkCreated) + return; + #endif + + if (_itemFailure + || _diskFilePath.IsEmpty() + || _stdOutMode + || !_extractMode + || !_fi.AttribDefined) + return; + + { + // const AString s = GetAnsiString(_diskFilePath); + // printf("\nSetFileAttrib_PosixHighDetect: %s: hex:%x\n", s.Ptr(), _fi.Attrib); + bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); + if (!res) + { + // do we need error message here in Windows and in posix? + SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); + } + } +} + STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) { COM_TRY_BEGIN + // printf("\nCArchiveExtractCallback::SetOperationResult: %d %s\n", opRes, GetAnsiString(_diskFilePath)); + #ifndef _SFX if (ExtractToStreamCallback) { @@ -2052,16 +2170,8 @@ STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 opRes) else NumFiles++; - if (_fileWasExtracted) - if (!_stdOutMode && _extractMode && _fi.AttribDefined) - { - bool res = SetFileAttrib_PosixHighDetect(_diskFilePath, _fi.Attrib); - if (!res) - { - // do we need error message here in Windows and in posix? - SendMessageError_with_LastError("Cannot set file attribute", _diskFilePath); - } - } + if (_needSetAttrib) + SetAttrib(); RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted))); diff --git a/CPP/7zip/UI/Common/ArchiveExtractCallback.h b/CPP/7zip/UI/Common/ArchiveExtractCallback.h index e44801de..fe9cb32e 100644 --- a/CPP/7zip/UI/Common/ArchiveExtractCallback.h +++ b/CPP/7zip/UI/Common/ArchiveExtractCallback.h @@ -189,7 +189,17 @@ struct CLinkInfo bool isRelative; bool isWSL; UString linkPath; - + + bool IsSymLink() const { return !isHardLink; } + + CLinkInfo(): + // IsCopyLink(false), + isHardLink(false), + isJunction(false), + isRelative(false), + isWSL(false) + {} + void Clear() { // IsCopyLink = false; @@ -291,10 +301,12 @@ class CArchiveExtractCallback: } } _fi; - bool _is_SymLink_in_Data; + // bool _is_SymLink_in_Data; bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX - bool _fileWasExtracted; + bool _needSetAttrib; + bool _isSymLinkCreated; + bool _itemFailure; UInt32 _index; UInt64 _curSize; @@ -352,6 +364,8 @@ class CArchiveExtractCallback: FString Hash_GetFullFilePath(); + void SetAttrib(); + public: HRESULT SendMessageError(const char *message, const FString &path); HRESULT SendMessageError_with_LastError(const char *message, const FString &path); diff --git a/CPP/7zip/UI/Common/DirItem.h b/CPP/7zip/UI/Common/DirItem.h index 55b2872c..e5f578dd 100644 --- a/CPP/7zip/UI/Common/DirItem.h +++ b/CPP/7zip/UI/Common/DirItem.h @@ -118,7 +118,9 @@ struct CDirItem UInt32 GetPosixAttrib() const { UInt32 v = IsDir() ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG; - v |= (IsReadOnly() ? 0555 : 0777); + /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY). + So extracting at Linux will be allowed to write files inside (0777) directories. */ + v |= ((IsReadOnly() && !IsDir()) ? 0555 : 0777); return v; } #endif diff --git a/CPP/7zip/UI/Common/ZipRegistry.cpp b/CPP/7zip/UI/Common/ZipRegistry.cpp index 558a159c..ab4871fb 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.cpp +++ b/CPP/7zip/UI/Common/ZipRegistry.cpp @@ -2,7 +2,10 @@ #include "StdAfx.h" +#include "../../../../C/CpuArch.h" + #include "../../../Common/IntToString.h" +#include "../../../Common/StringToInt.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/Registry.h" @@ -195,6 +198,13 @@ static void GetRegUInt32(CKey &key, LPCTSTR name, UInt32 &value) value = (UInt32)(Int32)-1; } +static LPCWSTR const kMemUse = L"MemUse" + #if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4) + L"32"; + #else + L"64"; + #endif + void CInfo::Save() const { CS_LOCK @@ -234,6 +244,7 @@ void CInfo::Save() const SetRegString(fk, kMethod, fo.Method); SetRegString(fk, kOptions, fo.Options); SetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); + SetRegString(fk, kMemUse, fo.MemUse); } } } @@ -274,9 +285,10 @@ void CInfo::Load() fo.FormatID = formatIDs[i]; if (fk.Open(optionsKey, fo.FormatID, KEY_READ) == ERROR_SUCCESS) { - GetRegString(fk, kOptions, fo.Options); GetRegString(fk, kMethod, fo.Method); + GetRegString(fk, kOptions, fo.Options); GetRegString(fk, kEncryptionMethod, fo.EncryptionMethod); + GetRegString(fk, kMemUse, fo.MemUse); GetRegUInt32(fk, kLevel, fo.Level); GetRegUInt32(fk, kDictionary, fo.Dictionary); @@ -298,6 +310,116 @@ void CInfo::Load() key.GetValue_IfOk(kEncryptHeaders, EncryptHeaders); } + +static bool ParseMemUse(const wchar_t *s, CMemUse &mu) +{ + mu.Clear(); + + bool percentMode = false; + { + const wchar_t c = *s; + if (MyCharLower_Ascii(c) == 'p') + { + percentMode = true; + s++; + } + } + const wchar_t *end; + UInt64 number = ConvertStringToUInt64(s, &end); + if (end == s) + return false; + + wchar_t c = *end; + + if (percentMode) + { + if (c != 0) + return false; + mu.IsPercent = true; + mu.Val = number; + return true; + } + + if (c == 0) + { + mu.Val = number; + return true; + } + + c = MyCharLower_Ascii(c); + + const wchar_t c1 = end[1]; + + if (c == '%') + { + if (c1 != 0) + return false; + mu.IsPercent = true; + mu.Val = number; + return true; + } + + if (c == 'b') + { + if (c1 != 0) + return false; + mu.Val = number; + return true; + } + + if (c1 != 0) + if (MyCharLower_Ascii(c1) != 'b' || end[2] != 0) + return false; + + unsigned numBits; + switch (c) + { + case 'k': numBits = 10; break; + case 'm': numBits = 20; break; + case 'g': numBits = 30; break; + case 't': numBits = 40; break; + default: return false; + } + if (number >= ((UInt64)1 << (64 - numBits))) + return false; + mu.Val = number << numBits; + return true; +} + + +void CMemUse::Parse(const UString &s) +{ + IsDefined = ParseMemUse(s, *this); +} + +/* +void MemLimit_Save(const UString &s) +{ + CS_LOCK + CKey key; + CreateMainKey(key, kKeyName); + SetRegString(key, kMemUse, s); +} + +bool MemLimit_Load(NCompression::CMemUse &mu) +{ + mu.Clear(); + UString a; + { + CS_LOCK + CKey key; + if (OpenMainKey(key, kKeyName) != ERROR_SUCCESS) + return false; + if (key.QueryValue(kMemUse, a) != ERROR_SUCCESS) + return false; + } + if (a.IsEmpty()) + return false; + mu.Parse(a); + return mu.IsDefined; +} +*/ + } static LPCTSTR const kOptionsInfoKeyName = TEXT("Options"); diff --git a/CPP/7zip/UI/Common/ZipRegistry.h b/CPP/7zip/UI/Common/ZipRegistry.h index 76a98447..3d2e4b98 100644 --- a/CPP/7zip/UI/Common/ZipRegistry.h +++ b/CPP/7zip/UI/Common/ZipRegistry.h @@ -6,6 +6,8 @@ #include "../../../Common/MyTypes.h" #include "../../../Common/MyString.h" +#include "../../Common/MethodProps.h" + #include "ExtractMode.h" namespace NExtract @@ -35,6 +37,36 @@ namespace NExtract namespace NCompression { + struct CMemUse + { + // UString Str; + bool IsDefined; + bool IsPercent; + UInt64 Val; + + CMemUse(): + IsDefined(false), + IsPercent(false), + Val(0) + {} + + void Clear() + { + // Str.Empty(); + IsDefined = false; + IsPercent = false; + Val = 0; + } + + UInt64 GetBytes(UInt64 ramSize) const + { + if (!IsPercent) + return Val; + return Calc_From_Val_Percents(ramSize, Val); + } + void Parse(const UString &s); + }; + struct CFormatOptions { UInt32 Level; @@ -47,6 +79,7 @@ namespace NCompression UString Method; UString Options; UString EncryptionMethod; + UString MemUse; void Reset_BlockLogSize() { diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h index 21b160dc..3c3c5ef2 100644 --- a/CPP/7zip/UI/FileManager/App.h +++ b/CPP/7zip/UI/FileManager/App.h @@ -18,8 +18,9 @@ const unsigned kNumPanelsMax = 2; extern bool g_IsSmallScreen; -const int kMenuCmdID_Plugin_Start = 1000; // must be large them context menu IDs -const int kMenuCmdID_Toolbar_Start = 1500; +// must be larger than context menu IDs +const int kMenuCmdID_Toolbar_Start = 1070; +const int kMenuCmdID_Plugin_Start = 1100; enum { diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp index 99a76cfa..1a09a8f6 100644 --- a/CPP/7zip/UI/FileManager/PanelMenu.cpp +++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp @@ -30,7 +30,7 @@ LONG g_DllRefCount; LONG g_DllRefCount = 0; static const UINT kSevenZipStartMenuID = kMenuCmdID_Plugin_Start; -static const UINT kSystemStartMenuID = kMenuCmdID_Plugin_Start + 100; +static const UINT kSystemStartMenuID = kMenuCmdID_Plugin_Start + 400; void CPanel::InvokeSystemCommand(const char *command) { @@ -993,11 +993,19 @@ bool CPanel::InvokePluginCommand(unsigned id, IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu) { UInt32 offset; - bool isSystemMenu = (id >= kSystemStartMenuID); + const bool isSystemMenu = (id >= kSystemStartMenuID); if (isSystemMenu) + { + if (!systemContextMenu) + return false; offset = id - kSystemStartMenuID; + } else + { + if (!sevenZipContextMenu) + return false; offset = id - kSevenZipStartMenuID; + } #ifdef use_CMINVOKECOMMANDINFOEX CMINVOKECOMMANDINFOEX diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp index bdd62f71..28687217 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.cpp +++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp @@ -2,17 +2,20 @@ #include "StdAfx.h" -#include "../../../Common/StringConvert.h" +// #include "../../../Common/IntToString.h" +// #include "../../../Common/StringConvert.h" #ifndef UNDER_CE #include "../../../Windows/MemoryLock.h" +// #include "../../../Windows/System.h" #endif +// #include "../Common/ZipRegistry.h" + #include "HelpUtils.h" #include "LangUtils.h" #include "RegistryUtils.h" #include "SettingsPage.h" - #include "SettingsPageRes.h" using namespace NWindows; @@ -27,16 +30,87 @@ static const UInt32 kLangIDs[] = IDX_SETTINGS_SINGLE_CLICK, IDX_SETTINGS_ALTERNATIVE_SELECTION, IDX_SETTINGS_LARGE_PAGES + // , IDT_COMPRESS_MEMORY }; #define kSettingsTopic "FM/options.htm#settings" extern bool IsLargePageSupported(); +/* +static void AddMemSize(UString &res, UInt64 size, bool needRound = false) +{ + char c; + unsigned moveBits = 0; + if (needRound) + { + UInt64 rn = 0; + if (size >= (1 << 31)) + rn = (1 << 28) - 1; + UInt32 kRound = (1 << 20) - 1; + if (rn < kRound) + rn = kRound; + size += rn; + size &= ~rn; + } + if (size >= ((UInt64)1 << 31) && (size & 0x3FFFFFFF) == 0) + { moveBits = 30; c = 'G'; } + else + { moveBits = 20; c = 'M'; } + res.Add_UInt64(size >> moveBits); + res.Add_Space(); + if (moveBits != 0) + res += c; + res += 'B'; +} + + +int CSettingsPage::AddMemComboItem(UInt64 size, UInt64 percents, bool isDefault) +{ + UString sUser; + UString sRegistry; + if (size == 0) + { + UString s; + s.Add_UInt64(percents); + s += '%'; + if (isDefault) + sUser = "* "; + else + sRegistry = s; + sUser += s; + } + else + { + AddMemSize(sUser, size); + sRegistry = sUser; + for (;;) + { + int pos = sRegistry.Find(L' '); + if (pos < 0) + break; + sRegistry.Delete(pos); + } + if (!sRegistry.IsEmpty()) + if (sRegistry.Back() == 'B') + sRegistry.DeleteBack(); + } + const int index = (int)_memCombo.AddString(sUser); + _memCombo.SetItemData(index, _memLimitStrings.Size()); + _memLimitStrings.Add(sRegistry); + return index; +} +*/ + bool CSettingsPage::OnInit() { _wasChanged = false; _largePages_wasChanged = false; + /* + _wasChanged_MemLimit = false; + _memLimitStrings.Clear(); + _memCombo.Attach(GetItem(IDC_SETTINGS_MEM)); + */ LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); @@ -57,6 +131,55 @@ bool CSettingsPage::OnInit() CheckButton(IDX_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable()); else EnableItem(IDX_SETTINGS_LARGE_PAGES, false); + + + /* + NCompression::CMemUse mu; + bool needSetCur = NCompression::MemLimit_Load(mu); + UInt64 curMemLimit; + { + AddMemComboItem(0, 90, true); + _memCombo.SetCurSel(0); + } + if (mu.IsPercent) + { + const int index = AddMemComboItem(0, mu.Val); + _memCombo.SetCurSel(index); + needSetCur = false; + } + { + _ramSize = (UInt64)(sizeof(size_t)) << 29; + _ramSize_Defined = NSystem::GetRamSize(_ramSize); + UString s; + if (_ramSize_Defined) + { + s += "/ "; + AddMemSize(s, _ramSize, true); + } + SetItemText(IDT_SETTINGS_MEM_RAM, s); + + curMemLimit = mu.GetBytes(_ramSize); + + // size = 100 << 20; // for debug only; + for (unsigned i = (27) * 2;; i++) + { + UInt64 size = (UInt64)(2 + (i & 1)) << (i / 2); + if (i > (20 + sizeof(size_t) * 3 * 1 - 1) * 2) + size = (UInt64)(Int64)-1; + if (needSetCur && (size >= curMemLimit)) + { + const int index = AddMemComboItem(curMemLimit); + _memCombo.SetCurSel(index); + needSetCur = false; + if (size == curMemLimit) + continue; + } + if (size == (UInt64)(Int64)-1) + break; + AddMemComboItem(size); + } + } + */ // EnableSubItems(); @@ -70,6 +193,14 @@ void CSettingsPage::EnableSubItems() } */ +/* +static void AddSize_MB(UString &s, UInt64 size) +{ + s.Add_UInt64((size + (1 << 20) - 1) >> 20); + s += " MB"; +} +*/ + LONG CSettingsPage::OnApply() { if (_wasChanged) @@ -86,10 +217,9 @@ LONG CSettingsPage::OnApply() st.ShowSystemMenu = IsButtonCheckedBool(IDX_SETTINGS_SHOW_SYSTEM_MENU); st.Save(); - _wasChanged = false; } - + #ifndef UNDER_CE if (_largePages_wasChanged) { @@ -102,7 +232,66 @@ LONG CSettingsPage::OnApply() _largePages_wasChanged = false; } #endif - + + /* + if (_wasChanged_MemLimit) + { + const unsigned index = (int)_memCombo.GetItemData_of_CurSel(); + const UString str = _memLimitStrings[index]; + + bool needSave = true; + + NCompression::CMemUse mu; + + if (_ramSize_Defined) + mu.Parse(str); + if (mu.IsDefined) + { + const UInt64 usage64 = mu.GetBytes(_ramSize); + if (_ramSize <= usage64) + { + UString s2 = LangString(IDT_COMPRESS_MEMORY); + if (s2.IsEmpty()) + GetItemText(IDT_COMPRESS_MEMORY, s2); + UString s; + + s += "The selected value is not safe for system performance."; + s.Add_LF(); + s += "The memory consumption for compression operation will exceed RAM size."; + s.Add_LF(); + s.Add_LF(); + AddSize_MB(s, usage64); + + if (!s2.IsEmpty()) + { + s += " : "; + s += s2; + } + + s.Add_LF(); + AddSize_MB(s, _ramSize); + s += " : RAM"; + + s.Add_LF(); + s.Add_LF(); + s += "Are you sure you want set that unsafe value for memory usage?"; + + int res = MessageBoxW(*this, s, L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION); + if (res != IDYES) + needSave = false; + } + } + + if (needSave) + { + NCompression::MemLimit_Save(str); + _wasChanged_MemLimit = false; + } + else + return PSNRET_INVALID_NOCHANGEPAGE; + } + */ + return PSNRET_NOERROR; } @@ -111,6 +300,25 @@ void CSettingsPage::OnNotifyHelp() ShowHelpWindow(kSettingsTopic); } +/* +bool CSettingsPage::OnCommand(int code, int itemID, LPARAM param) +{ + if (code == CBN_SELCHANGE) + { + switch (itemID) + { + case IDC_SETTINGS_MEM: + { + _wasChanged_MemLimit = true; + Changed(); + break; + } + } + } + return CPropertyPage::OnCommand(code, itemID, param); +} +*/ + bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND) { switch (buttonID) diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h index 77cc67b9..f3f57a4b 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.h +++ b/CPP/7zip/UI/FileManager/SettingsPage.h @@ -4,20 +4,30 @@ #define __SETTINGS_PAGE_H #include "../../../Windows/Control/PropertyPage.h" +#include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Edit.h" class CSettingsPage: public NWindows::NControl::CPropertyPage { bool _wasChanged; - bool _largePages_wasChanged; + /* + bool _wasChanged_MemLimit; + NWindows::NControl::CComboBox _memCombo; + UStringVector _memLimitStrings; + UInt64 _ramSize; + UInt64 _ramSize_Defined; + + int AddMemComboItem(UInt64 size, UInt64 percents = 0, bool isDefault = false); + */ // void EnableSubItems(); + // bool OnCommand(int code, int itemID, LPARAM param); bool OnButtonClicked(int buttonID, HWND buttonHWND); -public: virtual bool OnInit(); virtual void OnNotifyHelp(); virtual LONG OnApply(); +public: }; #endif diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc index c724fcb7..baab484a 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage.rc @@ -2,7 +2,7 @@ #include "../../GuiCommon.rc" #define xc 240 -#define yc 120 +#define yc 250 IDD_SETTINGS MY_PAGE #include "SettingsPage2.rc" diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc index 277f45d5..cf907420 100644 --- a/CPP/7zip/UI/FileManager/SettingsPage2.rc +++ b/CPP/7zip/UI/FileManager/SettingsPage2.rc @@ -1,3 +1,5 @@ +// #define g1xs 60 + CAPTION "Settings" BEGIN CONTROL "Show "".."" item", IDX_SETTINGS_SHOW_DOTS, MY_CHECKBOX, m, 8, xc, 10 @@ -10,4 +12,8 @@ BEGIN CONTROL "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, m, 100, xc, 10 CONTROL "Use &large memory pages", IDX_SETTINGS_LARGE_PAGES, MY_CHECKBOX, m, 122, xc, 10 + + // LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 140, xc, 8 + // COMBOBOX IDC_SETTINGS_MEM, m , 152, g1xs, yc - 152, MY_COMBO + // LTEXT "/ RAM", IDT_SETTINGS_MEM_RAM, m + g1xs + m, 154, xc - g1xs - m, MY_TEXT_NOPREFIX END diff --git a/CPP/7zip/UI/FileManager/SettingsPageRes.h b/CPP/7zip/UI/FileManager/SettingsPageRes.h index 71204597..e990babc 100644 --- a/CPP/7zip/UI/FileManager/SettingsPageRes.h +++ b/CPP/7zip/UI/FileManager/SettingsPageRes.h @@ -9,3 +9,9 @@ #define IDX_SETTINGS_SINGLE_CLICK 2506 #define IDX_SETTINGS_ALTERNATIVE_SELECTION 2507 #define IDX_SETTINGS_LARGE_PAGES 2508 + + +// #define IDT_SETTINGS_MEM 100 +// #define IDC_SETTINGS_MEM 101 +// #define IDT_SETTINGS_MEM_RAM 102 +// #define IDT_COMPRESS_MEMORY 4017 diff --git a/CPP/7zip/UI/FileManager/VerCtrl.cpp b/CPP/7zip/UI/FileManager/VerCtrl.cpp index 7e53d81f..3eea3942 100644 --- a/CPP/7zip/UI/FileManager/VerCtrl.cpp +++ b/CPP/7zip/UI/FileManager/VerCtrl.cpp @@ -126,6 +126,18 @@ static void WriteFile(const FString &path, bool createAlways, const CFileDataInf } +static UInt64 FILETIME_to_UInt64(const FILETIME &ft) +{ + return ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32); +} + +static void UInt64_TO_FILETIME(UInt64 v, FILETIME &ft) +{ + ft.dwLowDateTime = (DWORD)v; + ft.dwHighDateTime = (DWORD)(v >> 32); +} + + void CApp::VerCtrl(unsigned id) { const CPanel &panel = GetFocusedPanel(); @@ -297,6 +309,55 @@ void CApp::VerCtrl(unsigned id) return; } } + + const UInt64 timeStampOriginal = FILETIME_to_UInt64(fdi.Info.ftLastWriteTime); + UInt64 timeStamp2 = 0; + if (fdi2.IsOpen) + timeStamp2 = FILETIME_to_UInt64(fdi2.Info.ftLastWriteTime); + + if (timeStampOriginal > timeStamp2) + { + const UInt64 k_Ntfs_prec = 10000000; + UInt64 timeStamp = timeStampOriginal; + const UInt32 k_precs[] = { 60 * 60, 60, 2, 1 }; + for (unsigned i = 0; i < ARRAY_SIZE(k_precs); i++) + { + timeStamp = timeStampOriginal; + const UInt64 prec = k_Ntfs_prec * k_precs[i]; + // timeStamp += prec - 1; // for rounding up + timeStamp /= prec; + timeStamp *= prec; + if (timeStamp > timeStamp2) + break; + } + + if (timeStamp != timeStampOriginal + && timeStamp > timeStamp2) + { + FILETIME mTime; + UInt64_TO_FILETIME(timeStamp, mTime); + // NDir::SetFileAttrib(path, 0); + { + NIO::COutFile outFile; + if (!outFile.Open(path, OPEN_EXISTING)) + { + panel.MessageBox_LastError(); + return; + // if (::GetLastError() != ERROR_SUCCESS) + // throw "open error"; + } + else + { + const UInt64 cTime = FILETIME_to_UInt64(fdi.Info.ftCreationTime); + if (cTime > timeStamp) + outFile.SetTime(&mTime, NULL, &mTime); + else + outFile.SetMTime(&mTime); + } + } + } + } + if (!SetFileAttrib(path, fdi.Info.dwFileAttributes | FILE_ATTRIBUTE_READONLY)) { panel.MessageBox_LastError(); diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp index 41e0927d..44d25035 100644 --- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp +++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp @@ -733,9 +733,7 @@ void CBenchmarkDialog::SetItemText_Number(int itemID, UInt64 val, LPCTSTR post) static void AddSize_MB(UString &s, UInt64 size) { - char temp[32]; - ConvertUInt64ToString((size + (1 << 20) - 1) >> 20, temp); - s += temp; + s.Add_UInt64((size + (1 << 20) - 1) >> 20); s += kMB; } @@ -1555,16 +1553,13 @@ HRESULT CFreqCallback::AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage s.Add_LF(); } s += " "; - char temp[64]; if (numThreads != 1) { - ConvertUInt64ToString(GetUsagePercents(usage), temp); - s += temp; + s.Add_UInt64(GetUsagePercents(usage)); s += '%'; s.Add_Space(); } - ConvertUInt64ToString(GetMips(freq), temp); - s += temp; + s.Add_UInt64(GetMips(freq)); // BenchmarkDialog->Sync.sd.NeedPrint_Freq = true; res = sync.Exit ? E_ABORT : S_OK; } diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index 510d1ec3..0ede8292 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -11,6 +11,8 @@ #include "../../../Windows/FileName.h" #include "../../../Windows/System.h" +#include "../../Common/MethodProps.h" + #include "../FileManager/BrowseDialog.h" #include "../FileManager/FormatUtils.h" #include "../FileManager/HelpUtils.h" @@ -192,19 +194,30 @@ static const EMethodID g_HashMethods[] = // , kCrc64 }; +static const UInt32 kFF_Filter = 1 << 0; +static const UInt32 kFF_Solid = 1 << 1; +static const UInt32 kFF_MultiThread = 1 << 2; +static const UInt32 kFF_Encrypt = 1 << 3; +static const UInt32 kFF_EncryptFileNames = 1 << 4; +static const UInt32 kFF_MemUse = 1 << 5; +static const UInt32 kFF_SFX = 1 << 6; + struct CFormatInfo { LPCSTR Name; UInt32 LevelsMask; unsigned NumMethods; const EMethodID *MethodIDs; - bool Filter; - bool Solid; - bool MultiThread; - bool SFX; - - bool Encrypt; - bool EncryptFileNames; + + UInt32 Flags; + + bool Filter_() const { return (Flags & kFF_Filter) != 0; } + bool Solid_() const { return (Flags & kFF_Solid) != 0; } + bool MultiThread_() const { return (Flags & kFF_MultiThread) != 0; } + bool Encrypt_() const { return (Flags & kFF_Encrypt) != 0; } + bool EncryptFileNames_() const { return (Flags & kFF_EncryptFileNames) != 0; } + bool MemUse_() const { return (Flags & kFF_MemUse) != 0; } + bool SFX_() const { return (Flags & kFF_SFX) != 0; } }; #define METHODS_PAIR(x) ARRAY_SIZE(x), x @@ -216,62 +229,63 @@ static const CFormatInfo g_Formats[] = // (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), ((UInt32)1 << 10) - 1, // (UInt32)(Int32)-1, - 0, 0, - false, false, true, false, false, false + 0, NULL, + kFF_MultiThread | kFF_MemUse }, { k7zFormat, (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_7zMethods), - true, true, true, true, true, true + kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt | + kFF_EncryptFileNames | kFF_MemUse | kFF_SFX }, { "Zip", (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_ZipMethods), - false, false, true, false, true, false + kFF_MultiThread | kFF_Encrypt | kFF_MemUse }, { "GZip", (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_GZipMethods), - false, false, false, false, false, false + kFF_MemUse }, { "BZip2", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_BZip2Methods), - false, false, true, false, false, false + kFF_MultiThread | kFF_MemUse }, { "xz", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_XzMethods), - false, true, true, false, false, false + kFF_Solid | kFF_MultiThread | kFF_MemUse }, { "Swfc", (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), METHODS_PAIR(g_SwfcMethods), - false, false, true, false, false, false + 0 }, { "Tar", (1 << 0), - 0, 0, - false, false, false, false, false, false + 0, NULL, + 0 }, { "wim", (1 << 0), - 0, 0, - false, false, false, false, false, false + 0, NULL, + 0 }, { "Hash", (0 << 0), METHODS_PAIR(g_HashMethods), - false, false, false, false, false, false + 0 } }; @@ -372,14 +386,12 @@ bool CCompressDialog::OnInit() { UInt64 size = (UInt64)(sizeof(size_t)) << 29; _ramSize_Defined = NSystem::GetRamSize(size); - // size = 100 << 20; // for debug only; + // size = (UInt64)3 << 62; // for debug only; _ramSize = size; const UInt64 kMinUseSize = (1 << 26); if (size < kMinUseSize) size = kMinUseSize; - _ramUsage_Limit = size / 32 * 30; // it's relaxed limit for user defined settings - unsigned bits = sizeof(size_t) * 8; if (bits == 32) { @@ -388,7 +400,10 @@ bool CCompressDialog::OnInit() size = limit2; } - _ramUsage_Auto = size / 32 * 28; // it's same as in auto usage limit in handlers + _ramSize_Reduced = size; + + // 80% - is auto usage limit in handlers + _ramUsage_Auto = Calc_From_Val_Percents(size, 80); } _password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1)); @@ -406,6 +421,7 @@ bool CCompressDialog::OnInit() m_Order.Attach(GetItem(IDC_COMPRESS_ORDER)); m_Solid.Attach(GetItem(IDC_COMPRESS_SOLID)); m_NumThreads.Attach(GetItem(IDC_COMPRESS_THREADS)); + m_MemUse.Attach(GetItem(IDC_COMPRESS_MEM_USE)); m_UpdateMode.Attach(GetItem(IDC_COMPRESS_UPDATE_MODE)); m_PathMode.Attach(GetItem(IDC_COMPRESS_PATH_MODE)); @@ -543,7 +559,7 @@ bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) void CCompressDialog::CheckSFXControlsEnable() { const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - bool enable = fi.SFX; + bool enable = fi.SFX_(); if (enable) { const int methodID = GetMethodID(); @@ -578,11 +594,12 @@ void CCompressDialog::FormatChanged() SetLevel(); SetSolidBlockSize(); SetParams(); + SetMemUseCombo(); SetNumThreads(); const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - Info.SolidIsSpecified = fi.Solid; - Info.EncryptHeadersIsAllowed = fi.EncryptFileNames; + Info.SolidIsSpecified = fi.Solid_(); + Info.EncryptHeadersIsAllowed = fi.EncryptFileNames_(); /* const bool multiThreadEnable = fi.MultiThread; @@ -613,19 +630,20 @@ void CCompressDialog::FormatChanged() } // CheckVolumeEnable(); - EnableItem(IDG_COMPRESS_ENCRYPTION, fi.Encrypt); + const bool encrypt = fi.Encrypt_(); + EnableItem(IDG_COMPRESS_ENCRYPTION, encrypt); - EnableItem(IDT_PASSWORD_ENTER, fi.Encrypt); - EnableItem(IDT_PASSWORD_REENTER, fi.Encrypt); - EnableItem(IDE_COMPRESS_PASSWORD1, fi.Encrypt); - EnableItem(IDE_COMPRESS_PASSWORD2, fi.Encrypt); - EnableItem(IDX_PASSWORD_SHOW, fi.Encrypt); + EnableItem(IDT_PASSWORD_ENTER, encrypt); + EnableItem(IDT_PASSWORD_REENTER, encrypt); + EnableItem(IDE_COMPRESS_PASSWORD1, encrypt); + EnableItem(IDE_COMPRESS_PASSWORD2, encrypt); + EnableItem(IDX_PASSWORD_SHOW, encrypt); - EnableItem(IDT_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); - EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); - EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); + EnableItem(IDT_COMPRESS_ENCRYPTION_METHOD, encrypt); + EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, encrypt); + EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_()); - ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); + ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_()); SetEncryptionMethod(); SetMemoryUsage(); @@ -767,9 +785,10 @@ static bool IsAsciiString(const UString &s) static void AddSize_MB(UString &s, UInt64 size) { - char temp[32]; - ConvertUInt64ToString((size + (1 << 20) - 1) >> 20, temp); - s += temp; + const UInt64 v2 = size + ((UInt32)1 << 20) - 1; + if (size <= v2) + size = v2; + s.Add_UInt64(size >> 20); s += " MB"; } @@ -793,7 +812,7 @@ void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 AddSize_MB(s, ramSize); s += " : RAM"; - if (ramLimit != 0) + // if (ramLimit != 0) { s.Add_LF(); AddSize_MB(s, ramLimit); @@ -841,15 +860,18 @@ void CCompressDialog::OnOK() UInt64 decompressMem; const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem); if (memUsage != (UInt64)(Int64)-1) - if (_ramSize_Defined && memUsage > _ramUsage_Limit) { - UString s; - UString s2 = LangString(IDT_COMPRESS_MEMORY); - if (s2.IsEmpty()) - GetItemText(IDT_COMPRESS_MEMORY, s2); - SetErrorMessage_MemUsage(s, memUsage, _ramSize, _ramUsage_Limit, s2); - MessageBoxError(s); - return; + const UInt64 limit = Get_MemUse_Bytes(); + if (memUsage > limit) + { + UString s; + UString s2 = LangString(IDT_COMPRESS_MEMORY); + if (s2.IsEmpty()) + GetItemText(IDT_COMPRESS_MEMORY, s2); + SetErrorMessage_MemUsage(s, memUsage, _ramSize, limit, s2); + MessageBoxError(s); + return; + } } } @@ -876,6 +898,18 @@ void CCompressDialog::OnOK() Info.OrderMode = GetOrderMode(); Info.NumThreads = GetNumThreadsSpec(); + Info.MemUsage.Clear(); + { + const UString mus = Get_MemUse_Spec(); + if (!mus.IsEmpty()) + { + NCompression::CMemUse mu; + mu.Parse(mus); + if (mu.IsDefined) + Info.MemUsage = mu; + } + } + { // Info.SolidIsSpecified = g_Formats[GetStaticFormatIndex()].Solid; const UInt32 solidLogSize = GetBlockSizeSpec(); @@ -1061,6 +1095,18 @@ bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) SetMemoryUsage(); return true; } + + case IDC_COMPRESS_MEM_USE: + { + /* we want to change the reported threads for Auto line + and keep selected NumThreads option + So we save selected NumThreads option in memory */ + SaveOptionsInMem(); + + SetNumThreads(); // we want to change the reported threads for Auto line only + SetMemoryUsage(); + return true; + } } } return CModalDialog::OnCommand(code, itemID, lParam); @@ -1435,22 +1481,19 @@ static const size_t k_Auto_Dict = (size_t)0 - 1; int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow) { - Byte c = 0; + char c = 0; unsigned moveBits = 0; if ((sizeShow & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; } else if ((sizeShow & 0x3FF) == 0) { moveBits = 10; c = 'K'; } - char s[32]; - ConvertUInt64ToString(sizeShow >> moveBits, s); - unsigned pos = MyStringLen(s); - s[pos++] = ' '; + AString s; + s.Add_UInt64(sizeShow >> moveBits); + s.Add_Space(); if (moveBits != 0) - s[pos++] = c; - s[pos++] = 'B'; - s[pos++] = 0; - AString s2 (s); + s += c; + s += 'B'; if (sizeReal == k_Auto_Dict) - Modify_Auto(s2); - const int index = (int)ComboBox_AddStringAscii(m_Dictionary, s2); + Modify_Auto(s); + const int index = (int)ComboBox_AddStringAscii(m_Dictionary, s); m_Dictionary.SetItemData(index, sizeReal); return index; } @@ -1831,22 +1874,18 @@ static UInt64 Get_Lzma2_ChunkSize(UInt64 dict) } -static void Add_Size(AString &s2, UInt64 val) +static void Add_Size(AString &s, UInt64 val) { unsigned moveBits = 0; - Byte c = 0; + char c = 0; if ((val & 0x3FFFFFFF) == 0) { moveBits = 30; c = 'G'; } else if ((val & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; } else if ((val & 0x3FF) == 0) { moveBits = 10; c = 'K'; } - char s[32]; - ConvertUInt64ToString(val >> moveBits, s); - unsigned pos = MyStringLen(s); - s[pos++] = ' '; + s.Add_UInt64(val >> moveBits); + s.Add_Space(); if (moveBits != 0) - s[pos++] = c; - s[pos++] = 'B'; - s[pos++] = 0; - s2 += s; + s += c; + s += 'B'; } @@ -1856,7 +1895,7 @@ void CCompressDialog::SetSolidBlockSize2() _auto_Solid = 1 << 20; const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (!fi.Solid) + if (!fi.Solid_()) return; const UInt32 level = GetLevel2(); @@ -1977,7 +2016,7 @@ void CCompressDialog::SetNumThreads2() m_NumThreads.ResetContent(); const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (!fi.MultiThread) + if (!fi.MultiThread_()) return; const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); @@ -2029,6 +2068,8 @@ void CCompressDialog::SetNumThreads2() if (autoThreads > numAlgoThreadsMax) autoThreads = numAlgoThreadsMax; + const UInt64 memUse_Limit = Get_MemUse_Bytes(); + if (autoThreads > 1 && _ramSize_Defined) { if (isZip) @@ -2038,7 +2079,7 @@ void CCompressDialog::SetNumThreads2() const UInt64 dict64 = GetDict2(); UInt64 decompressMemory; const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory); - if (usage <= _ramUsage_Auto) + if (usage <= memUse_Limit) break; } } @@ -2052,7 +2093,7 @@ void CCompressDialog::SetNumThreads2() autoThreads = numBlockThreads * numThreads1; UInt64 decompressMemory; const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory); - if (usage <= _ramUsage_Auto) + if (usage <= memUse_Limit) break; } autoThreads = numBlockThreads * numThreads1; @@ -2088,6 +2129,174 @@ void CCompressDialog::SetNumThreads2() } +static void AddMemSize(UString &res, UInt64 size) +{ + char c; + unsigned moveBits = 0; + if (size >= ((UInt64)1 << 31) && (size & 0x3FFFFFFF) == 0) + { moveBits = 30; c = 'G'; } + else // if (size >= ((UInt32)1 << 21) && (size & 0xFFFFF) == 0) + { moveBits = 20; c = 'M'; } + // else { moveBits = 10; c = 'K'; } + res.Add_UInt64(size >> moveBits); + res.Add_Space(); + if (moveBits != 0) + res += c; + res += 'B'; +} + + +int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault) +{ + UString sUser; + UString sRegistry; + if (isPercent) + { + UString s; + s.Add_UInt64(val); + s += '%'; + if (isDefault) + sUser = "* "; + else + sRegistry = s; + sUser += s; + } + else + { + AddMemSize(sUser, val); + sRegistry = sUser; + for (;;) + { + int pos = sRegistry.Find(L' '); + if (pos < 0) + break; + sRegistry.Delete(pos); + } + if (!sRegistry.IsEmpty()) + if (sRegistry.Back() == 'B') + sRegistry.DeleteBack(); + } + const unsigned dataIndex = _memUse_Strings.Add(sRegistry); + const int index = (int)m_MemUse.AddString(sUser); + m_MemUse.SetItemData(index, dataIndex); + return index; +} + + + +void CCompressDialog::SetMemUseCombo() +{ + _memUse_Strings.Clear(); + m_MemUse.ResetContent(); + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + + { + const bool enable = fi.MemUse_(); + ShowItem_Bool(IDT_COMPRESS_MEMORY, enable); + ShowItem_Bool(IDT_COMPRESS_MEMORY_VALUE, enable); + ShowItem_Bool(IDT_COMPRESS_MEMORY_DE, enable); + ShowItem_Bool(IDT_COMPRESS_MEMORY_DE_VALUE, enable); + ShowItem_Bool(IDC_COMPRESS_MEM_USE, enable); + EnableItem(IDC_COMPRESS_MEM_USE, enable); + if (!enable) + return; + } + + UInt64 curMem_Bytes = 0; + UInt64 curMem_Percents = 0; + bool needSetCur_Bytes = false; + bool needSetCur_Percents = false; + { + const NCompression::CFormatOptions &fo = Get_FormatOptions(); + if (!fo.MemUse.IsEmpty()) + { + NCompression::CMemUse mu; + mu.Parse(fo.MemUse); + if (mu.IsDefined) + { + if (mu.IsPercent) + { + curMem_Percents = mu.Val; + needSetCur_Percents = true; + } + else + { + curMem_Bytes = mu.GetBytes(_ramSize_Reduced); + needSetCur_Bytes = true; + } + } + } + } + + + // 80% - is auto usage limit in handlers + AddMemComboItem(80, true, true); + m_MemUse.SetCurSel(0); + + { + for (unsigned i = 10;; i += 10) + { + UInt64 size = i; + if (i > 100) + size = (UInt64)(Int64)-1; + if (needSetCur_Percents && size >= curMem_Percents) + { + const int index = AddMemComboItem(curMem_Percents, true); + m_MemUse.SetCurSel(index); + needSetCur_Percents = false; + if (size == curMem_Percents) + continue; + } + if (size == (UInt64)(Int64)-1) + break; + AddMemComboItem(size, true); + } + } + { + for (unsigned i = (27) * 2;; i++) + { + UInt64 size = (UInt64)(2 + (i & 1)) << (i / 2); + if (i > (20 + sizeof(size_t) * 3 - 1) * 2) + size = (UInt64)(Int64)-1; + if (needSetCur_Bytes && size >= curMem_Bytes) + { + const int index = AddMemComboItem(curMem_Bytes); + m_MemUse.SetCurSel(index); + needSetCur_Bytes = false; + if (size == curMem_Bytes) + continue; + } + if (size == (UInt64)(Int64)-1) + break; + AddMemComboItem(size); + } + } +} + + +UString CCompressDialog::Get_MemUse_Spec() +{ + if (m_MemUse.GetCount() < 1) + return UString(); + return _memUse_Strings[(unsigned)m_MemUse.GetItemData_of_CurSel()]; +} + + +UInt64 CCompressDialog::Get_MemUse_Bytes() +{ + const UString mus = Get_MemUse_Spec(); + NCompression::CMemUse mu; + if (!mus.IsEmpty()) + { + mu.Parse(mus); + if (mu.IsDefined) + return mu.GetBytes(_ramSize_Reduced); + } + return _ramUsage_Auto; // _ramSize_Reduced; // _ramSize;; +} + + + UInt64 CCompressDialog::GetMemoryUsage_DecompMem(UInt64 &decompressMemory) { return GetMemoryUsage_Dict_DecompMem(GetDict2(), decompressMemory); @@ -2119,7 +2328,7 @@ UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 size = 0; const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (fi.Filter && level >= 9) + if (fi.Filter_() && level >= 9) size += (12 << 20) * 2 + (5 << 20); // UInt32 numThreads = GetNumThreads2(); @@ -2254,28 +2463,69 @@ UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, } -void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) + +static void AddMemUsage(UString &s, UInt64 v) { - if (value == (UInt64)(Int64)-1) + const char *post; + if (v <= ((UInt64)16 << 30)) { - SetItemText(res, TEXT("?")); - return; + v = (v + (1 << 20) - 1) >> 20; + post = "MB"; } - TCHAR s[32]; - if (value <= ((UInt64)16 << 30)) + else if (v <= ((UInt64)64 << 40)) { - value = (value + (1 << 20) - 1) >> 20; - ConvertUInt64ToString(value, s); - lstrcat(s, TEXT(" MB")); + v = (v + (1 << 30) - 1) >> 30; + post = "GB"; } else { - value = (value + (1 << 30) - 1) >> 30; - ConvertUInt64ToString(value, s); - lstrcat(s, TEXT(" GB")); + const UInt64 v2 = v + ((UInt64)1 << 40) - 1; + if (v <= v2) + v = v2; + v >>= 40; + post = "TB"; + } + s.Add_UInt64(v); + s.Add_Space(); + s += post; +} + + +void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) +{ + if (value == (UInt64)(Int64)-1) + { + SetItemText(res, TEXT("?")); + return; + } + UString s; + AddMemUsage(s, value); + if (res == IDT_COMPRESS_MEMORY_VALUE) + { + const UString mus = Get_MemUse_Spec(); + NCompression::CMemUse mu; + if (!mus.IsEmpty()) + mu.Parse(mus); + if (mu.IsDefined) + { + s += " / "; + AddMemUsage(s, mu.GetBytes(_ramSize_Reduced)); + } + else if (_ramSize_Defined) + { + s += " / "; + AddMemUsage(s, _ramUsage_Auto); + } + + if (_ramSize_Defined) + { + s += " / "; + AddMemUsage(s, _ramSize); + } } SetItemText(res, s); } + void CCompressDialog::SetMemoryUsage() { @@ -2334,6 +2584,7 @@ void CCompressDialog::SaveOptionsInMem() fo.EncryptionMethod = GetEncryptionMethodSpec(); fo.NumThreads = GetNumThreadsSpec(); fo.BlockLogSize = GetBlockSizeSpec(); + fo.MemUse = Get_MemUse_Spec(); } unsigned CCompressDialog::GetFormatIndex() diff --git a/CPP/7zip/UI/GUI/CompressDialog.h b/CPP/7zip/UI/GUI/CompressDialog.h index d8091b04..171d1189 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.h +++ b/CPP/7zip/UI/GUI/CompressDialog.h @@ -38,6 +38,8 @@ namespace NCompressDialog UInt64 SolidBlockSize; UInt32 NumThreads; + NCompression::CMemUse MemUsage; + CRecordVector<UInt64> VolumeSizes; UInt32 Level; @@ -102,8 +104,11 @@ class CCompressDialog: public NWindows::NControl::CModalDialog NWindows::NControl::CComboBox m_Order; NWindows::NControl::CComboBox m_Solid; NWindows::NControl::CComboBox m_NumThreads; + NWindows::NControl::CComboBox m_MemUse; NWindows::NControl::CComboBox m_Volume; + UStringVector _memUse_Strings; + NWindows::NControl::CDialogChildControl m_Params; NWindows::NControl::CComboBox m_UpdateMode; @@ -128,10 +133,9 @@ class CCompressDialog: public NWindows::NControl::CModalDialog UString StartDirPrefix; bool _ramSize_Defined; - UInt64 _ramSize; + UInt64 _ramSize; // full RAM size avail + UInt64 _ramSize_Reduced; // full for 64-bit and reduced for 32-bit UInt64 _ramUsage_Auto; - UInt64 _ramUsage_Limit; - void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2); void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2); @@ -254,6 +258,10 @@ class CCompressDialog: public NWindows::NControl::CModalDialog EnableMultiCombo(IDC_COMPRESS_THREADS); } + int AddMemComboItem(UInt64 val, bool isPercent = false, bool isDefault = false); + void SetMemUseCombo(); + UString Get_MemUse_Spec(); + UInt64 Get_MemUse_Bytes(); UInt64 GetMemoryUsage_Dict_DecompMem(UInt64 dict, UInt64 &decompressMemory); UInt64 GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 dict, UInt64 &decompressMemory); diff --git a/CPP/7zip/UI/GUI/CompressDialog.rc b/CPP/7zip/UI/GUI/CompressDialog.rc index d6ce5ac0..52c9546a 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.rc +++ b/CPP/7zip/UI/GUI/CompressDialog.rc @@ -29,7 +29,7 @@ #define g0xs (gSize - g1xs) #define g1x (m + g0xs) -#define g3xs 40 +#define g3xs 52 #define g2xs (gSize - g3xs) #define g3x (m + g2xs) @@ -82,14 +82,15 @@ BEGIN LTEXT "Number of CPU &threads:", IDT_COMPRESS_THREADS, m, 167, g0xs, 8 COMBOBOX IDC_COMPRESS_THREADS, g1x, 165, g1xs - 35, 140, MY_COMBO - RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, 8 + RTEXT "", IDT_COMPRESS_HARDWARE_THREADS, g1x + g1xs - 35 + 10, 167, 25, MY_TEXT_NOPREFIX - LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 190, g2xs, 8 - RTEXT "", IDT_COMPRESS_MEMORY_VALUE, g3x, 190, g3xs, 8 + LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 184, g2xs, 8 + COMBOBOX IDC_COMPRESS_MEM_USE, g3x, 188, g3xs, 140, MY_COMBO + LTEXT "", IDT_COMPRESS_MEMORY_VALUE, m, 194, g2xs, MY_TEXT_NOPREFIX - LTEXT "Memory usage for Decompressing:", IDT_COMPRESS_MEMORY_DE, m, 206, g2xs, 8 - RTEXT "", IDT_COMPRESS_MEMORY_DE_VALUE, g3x, 206, g3xs, 8 + LTEXT "Memory usage for Decompressing:", IDT_COMPRESS_MEMORY_DE, m, 208, g2xs, 8 + RTEXT "", IDT_COMPRESS_MEMORY_DE_VALUE, g3x, 208, g3xs, MY_TEXT_NOPREFIX LTEXT "Split to &volumes, bytes:", IDT_SPLIT_TO_VOLUMES, m, 225, gSize, 8 diff --git a/CPP/7zip/UI/GUI/CompressDialogRes.h b/CPP/7zip/UI/GUI/CompressDialogRes.h index ff99fa94..341b7533 100644 --- a/CPP/7zip/UI/GUI/CompressDialogRes.h +++ b/CPP/7zip/UI/GUI/CompressDialogRes.h @@ -20,6 +20,7 @@ #define IDG_COMPRESS_NTFS 115 #define IDC_COMPRESS_PATH_MODE 116 +#define IDC_COMPRESS_MEM_USE 117 #define IDE_COMPRESS_PASSWORD1 120 #define IDE_COMPRESS_PASSWORD2 121 diff --git a/CPP/7zip/UI/GUI/ExtractGUI.cpp b/CPP/7zip/UI/GUI/ExtractGUI.cpp index 59403ee9..a9191a8b 100644 --- a/CPP/7zip/UI/GUI/ExtractGUI.cpp +++ b/CPP/7zip/UI/GUI/ExtractGUI.cpp @@ -44,9 +44,7 @@ static void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColo if (addColon) s += ':'; s.Add_Space(); - char sz[32]; - ConvertUInt64ToString(value, sz); - s += sz; + s.Add_UInt64(value); s.Add_LF(); } diff --git a/CPP/7zip/UI/GUI/HashGUI.cpp b/CPP/7zip/UI/GUI/HashGUI.cpp index 219135fb..5782f790 100644 --- a/CPP/7zip/UI/GUI/HashGUI.cpp +++ b/CPP/7zip/UI/GUI/HashGUI.cpp @@ -75,11 +75,10 @@ void AddSizeValue(UString &s, UInt64 value) if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; } else if (value >= (10 << 20)) { value >>= 20; c = 'M'; } else { value >>= 10; c = 'K'; } - char sz[32]; - ConvertUInt64ToString(value, sz); + s += " ("; - s += sz; - s += " "; + s.Add_UInt64(value); + s.Add_Space(); s += (wchar_t)c; s += "iB)"; } diff --git a/CPP/7zip/UI/GUI/UpdateGUI.cpp b/CPP/7zip/UI/GUI/UpdateGUI.cpp index 1bdc9ffe..6fd1b60b 100644 --- a/CPP/7zip/UI/GUI/UpdateGUI.cpp +++ b/CPP/7zip/UI/GUI/UpdateGUI.cpp @@ -61,7 +61,7 @@ HRESULT CThreadUpdating::ProcessVirt() return HRESULT_FROM_WIN32(ei.SystemError); } -static void AddProp(CObjectVector<CProperty> &properties, const char *name, const UString &value) +static void AddProp_UString(CObjectVector<CProperty> &properties, const char *name, const UString &value) { CProperty prop; prop.Name = name; @@ -69,16 +69,16 @@ static void AddProp(CObjectVector<CProperty> &properties, const char *name, cons properties.Add(prop); } -static void AddProp(CObjectVector<CProperty> &properties, const char *name, UInt32 value) +static void AddProp_UInt32(CObjectVector<CProperty> &properties, const char *name, UInt32 value) { - char tmp[32]; - ConvertUInt64ToString(value, tmp); - AddProp(properties, name, UString(tmp)); + UString s; + s.Add_UInt32(value); + AddProp_UString(properties, name, s); } -static void AddProp(CObjectVector<CProperty> &properties, const char *name, bool value) +static void AddProp_bool(CObjectVector<CProperty> &properties, const char *name, bool value) { - AddProp(properties, name, UString(value ? "on": "off")); + AddProp_UString(properties, name, UString(value ? "on": "off")); } static bool IsThereMethodOverride(bool is7z, const UString &propertiesString) @@ -126,16 +126,16 @@ static void ParseAndAddPropertires(CObjectVector<CProperty> &properties, } } -static UString GetNumInBytesString(UInt64 v) + +static void AddProp_Size(CObjectVector<CProperty> &properties, const char *name, const UInt64 size) { - char s[32]; - ConvertUInt64ToString(v, s); - size_t len = MyStringLen(s); - s[len++] = 'B'; - s[len] = '\0'; - return UString(s); + UString s; + s.Add_UInt64(size); + s += 'b'; + AddProp_UString(properties, name, s); } + static void SetOutProperties( CObjectVector<CProperty> &properties, bool is7z, @@ -150,21 +150,22 @@ static void SetOutProperties( UInt32 numThreads, const UString &encryptionMethod, bool encryptHeadersIsAllowed, bool encryptHeaders, + const NCompression::CMemUse &memUse, bool /* sfxMode */) { if (level != (UInt32)(Int32)-1) - AddProp(properties, "x", (UInt32)level); + AddProp_UInt32(properties, "x", (UInt32)level); if (setMethod) { if (!method.IsEmpty()) - AddProp(properties, is7z ? "0": "m", method); + AddProp_UString(properties, is7z ? "0": "m", method); if (dict64 != (UInt64)(Int64)-1) { AString name; if (is7z) name = "0"; name += (orderMode ? "mem" : "d"); - AddProp(properties, name, GetNumInBytesString(dict64)); + AddProp_Size(properties, name, dict64); } if (order != (UInt32)(Int32)-1) { @@ -172,21 +173,37 @@ static void SetOutProperties( if (is7z) name = "0"; name += (orderMode ? "o" : "fb"); - AddProp(properties, name, (UInt32)order); + AddProp_UInt32(properties, name, (UInt32)order); } } if (!encryptionMethod.IsEmpty()) - AddProp(properties, "em", encryptionMethod); + AddProp_UString(properties, "em", encryptionMethod); if (encryptHeadersIsAllowed) - AddProp(properties, "he", encryptHeaders); + AddProp_bool(properties, "he", encryptHeaders); if (solidIsSpecified) - AddProp(properties, "s", GetNumInBytesString(solidBlockSize)); + AddProp_Size(properties, "s", solidBlockSize); + if ( // multiThreadIsAllowed && numThreads != (UInt32)(Int32)-1) - AddProp(properties, "mt", numThreads); + AddProp_UInt32(properties, "mt", numThreads); + + if (memUse.IsDefined) + { + const char *kMemUse = "memuse"; + if (memUse.IsPercent) + { + UString s; + // s += 'p'; // for debug: alternate percent method + s.Add_UInt64(memUse.Val); + s += '%'; + AddProp_UString(properties, kMemUse, s); + } + else + AddProp_Size(properties, kMemUse, memUse.Val); + } } struct C_UpdateMode_ToAction_Pair @@ -408,6 +425,7 @@ static HRESULT ShowDialog( di.NumThreads, di.EncryptionMethod, di.EncryptHeadersIsAllowed, di.EncryptHeaders, + di.MemUsage, di.SFXMode); options.OpenShareForWrite = di.OpenShareForWrite; |