diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp index d04336de..964d335a 100644 --- a/CPP/7zip/UI/GUI/CompressDialog.cpp +++ b/CPP/7zip/UI/GUI/CompressDialog.cpp @@ -1,1865 +1,1865 @@ -// CompressDialog.cpp - -#include "StdAfx.h" - -#include "../../../../C/CpuArch.h" - -#include "../../../Common/IntToString.h" -#include "../../../Common/StringConvert.h" - -#include "../../../Windows/FileDir.h" -#include "../../../Windows/FileName.h" -#include "../../../Windows/System.h" - -#include "../FileManager/BrowseDialog.h" -#include "../FileManager/FormatUtils.h" -#include "../FileManager/HelpUtils.h" -#include "../FileManager/SplitUtils.h" - -#include "../Explorer/MyMessages.h" - -#include "../Common/ZipRegistry.h" - -#include "CompressDialog.h" - -#ifndef _UNICODE -extern bool g_IsNT; -#endif - -#ifdef LANG -#include "../FileManager/LangUtils.h" -#endif - -#include "CompressDialogRes.h" -#include "ExtractRes.h" - -#ifdef LANG -static const UInt32 kLangIDs[] = -{ - IDT_COMPRESS_ARCHIVE, - IDT_COMPRESS_UPDATE_MODE, - IDT_COMPRESS_FORMAT, - IDT_COMPRESS_LEVEL, - IDT_COMPRESS_METHOD, - IDT_COMPRESS_DICTIONARY, - IDT_COMPRESS_ORDER, - IDT_COMPRESS_SOLID, - IDT_COMPRESS_THREADS, - IDT_COMPRESS_PARAMETERS, - - IDG_COMPRESS_OPTIONS, - IDX_COMPRESS_SFX, - IDX_COMPRESS_SHARED, - IDX_COMPRESS_DEL, - - IDT_COMPRESS_MEMORY, - IDT_COMPRESS_MEMORY_DE, - - IDX_COMPRESS_NT_SYM_LINKS, - IDX_COMPRESS_NT_HARD_LINKS, - IDX_COMPRESS_NT_ALT_STREAMS, - IDX_COMPRESS_NT_SECUR, - - IDG_COMPRESS_ENCRYPTION, - IDT_COMPRESS_ENCRYPTION_METHOD, - IDX_COMPRESS_ENCRYPT_FILE_NAMES, - - IDT_PASSWORD_ENTER, - IDT_PASSWORD_REENTER, - IDX_PASSWORD_SHOW, - - IDT_SPLIT_TO_VOLUMES, - IDT_COMPRESS_PATH_MODE -}; -#endif - -using namespace NWindows; -using namespace NFile; -using namespace NName; -using namespace NDir; - -static const unsigned kHistorySize = 20; - -static LPCWSTR kExeExt = L".exe"; -static LPCWSTR k7zFormat = L"7z"; - -static const UInt32 g_Levels[] = -{ - IDS_METHOD_STORE, - IDS_METHOD_FASTEST, - 0, - IDS_METHOD_FAST, - 0, - IDS_METHOD_NORMAL, - 0, - IDS_METHOD_MAXIMUM, - 0, - IDS_METHOD_ULTRA -}; - -enum EMethodID -{ - kCopy, - kZSTD, - kLZMA, - kLZMA2, - kPPMd, - kBZip2, - kDeflate, - kDeflate64, - kPPMdZip -}; - -static const LPCWSTR kMethodsNames[] = -{ - L"Copy", - L"ZSTD", - L"LZMA", - L"LZMA2", - L"PPMd", - L"BZip2", - L"Deflate", - L"Deflate64", - L"PPMd" -}; - -static const EMethodID g_7zMethods[] = -{ - kZSTD, - kLZMA2, - kLZMA, - kPPMd, - kDeflate, - kDeflate64, - kBZip2 -}; - -static const EMethodID g_7zSfxMethods[] = -{ - kCopy, - kZSTD, - kLZMA, - kLZMA2, - kPPMd -}; - -static const EMethodID g_ZipMethods[] = -{ - kDeflate, - kDeflate64, - kBZip2, - kLZMA, - kPPMdZip -}; - -static const EMethodID g_GZipMethods[] = -{ - kDeflate -}; - -static const EMethodID g_BZip2Methods[] = -{ - kBZip2 -}; - -static const EMethodID g_XzMethods[] = -{ - kLZMA2 -}; - -static const EMethodID g_SwfcMethods[] = -{ - kDeflate -}; - -struct CFormatInfo -{ - LPCWSTR Name; - UInt32 LevelsMask; - const EMethodID *MethodIDs; - unsigned NumMethods; - - bool Filter; - bool Solid; - bool MultiThread; - bool SFX; - bool Encrypt; - bool EncryptFileNames; -}; - -#define METHODS_PAIR(x) x, ARRAY_SIZE(x) - -static const CFormatInfo g_Formats[] = -{ - { - L"", - (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), - 0, 0, - false, false, false, false, false, false - }, - { - k7zFormat, - (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), - METHODS_PAIR(g_7zMethods), - true, true, true, true, true, true - }, - { - L"Zip", - (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), - METHODS_PAIR(g_ZipMethods), - false, false, true, false, true, false - }, - { - L"GZip", - (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), - METHODS_PAIR(g_GZipMethods), - false, false, false, false, false, false - }, - { - L"BZip2", - (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), - METHODS_PAIR(g_BZip2Methods), - false, false, true, false, false, false - }, - { - L"xz", - (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), - METHODS_PAIR(g_XzMethods), - false, false, true, false, false, false - }, - { - L"Swfc", - (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), - METHODS_PAIR(g_SwfcMethods), - false, false, true, false, false, false - }, - { - L"Tar", - (1 << 0), - 0, 0, - false, false, false, false, false, false - }, - { - L"wim", - (1 << 0), - 0, 0, - false, false, false, false, false, false - } -}; - -static bool IsMethodSupportedBySfx(int methodID) -{ - for (int i = 0; i < ARRAY_SIZE(g_7zSfxMethods); i++) - if (methodID == g_7zSfxMethods[i]) - return true; - return false; -} - -static bool GetMaxRamSizeForProgram(UInt64 &physSize) -{ - physSize = (UInt64)(sizeof(size_t)) << 29; - bool ramSize_Defined = NSystem::GetRamSize(physSize); - const UInt64 kMinSysSize = (1 << 24); - if (physSize <= kMinSysSize) - physSize = 0; - else - physSize -= kMinSysSize; - const UInt64 kMinUseSize = (1 << 24); - if (physSize < kMinUseSize) - physSize = kMinUseSize; - return ramSize_Defined; -} - - -static const - // NCompressDialog::NUpdateMode::EEnum - int - k_UpdateMode_Vals[] = -{ - NCompressDialog::NUpdateMode::kAdd, - NCompressDialog::NUpdateMode::kUpdate, - NCompressDialog::NUpdateMode::kFresh, - NCompressDialog::NUpdateMode::kSync -}; - -static const UInt32 k_UpdateMode_IDs[] = -{ - IDS_COMPRESS_UPDATE_MODE_ADD, - IDS_COMPRESS_UPDATE_MODE_UPDATE, - IDS_COMPRESS_UPDATE_MODE_FRESH, - IDS_COMPRESS_UPDATE_MODE_SYNC -}; - -static const - // NWildcard::ECensorPathMode - int - k_PathMode_Vals[] = -{ - NWildcard::k_RelatPath, - NWildcard::k_FullPath, - NWildcard::k_AbsPath, -}; - -static const UInt32 k_PathMode_IDs[] = -{ - IDS_PATH_MODE_RELAT, - IDS_EXTRACT_PATHS_FULL, - IDS_EXTRACT_PATHS_ABS -}; - -void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); -bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2); - -void CCompressDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2) -{ - CheckButton(id, GetBoolsVal(b1, b2)); -} - -void CCompressDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) -{ - bool val = IsButtonCheckedBool(id); - bool oldVal = GetBoolsVal(b1, b2); - if (val != oldVal) - b1.Def = b2.Def = true; - b1.Val = b2.Val = val; -} - - -bool CCompressDialog::OnInit() -{ - #ifdef LANG - LangSetWindowText(*this, IDD_COMPRESS); - LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); - #endif - - _password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1)); - _password2Control.Attach(GetItem(IDE_COMPRESS_PASSWORD2)); - _password1Control.SetText(Info.Password); - _password2Control.SetText(Info.Password); - _encryptionMethod.Attach(GetItem(IDC_COMPRESS_ENCRYPTION_METHOD)); - - m_ArchivePath.Attach(GetItem(IDC_COMPRESS_ARCHIVE)); - m_Format.Attach(GetItem(IDC_COMPRESS_FORMAT)); - m_Level.Attach(GetItem(IDC_COMPRESS_LEVEL)); - m_Method.Attach(GetItem(IDC_COMPRESS_METHOD)); - m_Dictionary.Attach(GetItem(IDC_COMPRESS_DICTIONARY)); - m_Order.Attach(GetItem(IDC_COMPRESS_ORDER)); - m_Solid.Attach(GetItem(IDC_COMPRESS_SOLID)); - m_NumThreads.Attach(GetItem(IDC_COMPRESS_THREADS)); - - m_UpdateMode.Attach(GetItem(IDC_COMPRESS_UPDATE_MODE)); - m_PathMode.Attach(GetItem(IDC_COMPRESS_PATH_MODE)); - - m_Volume.Attach(GetItem(IDC_COMPRESS_VOLUME)); - m_Params.Attach(GetItem(IDE_COMPRESS_PARAMETERS)); - - AddVolumeItems(m_Volume); - - m_RegistryInfo.Load(); - CheckButton(IDX_PASSWORD_SHOW, m_RegistryInfo.ShowPassword); - CheckButton(IDX_COMPRESS_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders); - - CheckButton_TwoBools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); - CheckButton_TwoBools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); - CheckButton_TwoBools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); - CheckButton_TwoBools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); - - UpdatePasswordControl(); - - { - bool needSetMain = (Info.FormatIndex < 0); - FOR_VECTOR(i, ArcIndices) - { - unsigned arcIndex = ArcIndices[i]; - const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; - int index = (int)m_Format.AddString(ai.Name); - m_Format.SetItemData(index, arcIndex); - if (!needSetMain) - { - if (Info.FormatIndex == (int)arcIndex) - m_Format.SetCurSel(index); - continue; - } - if (i == 0 || ai.Name.IsEqualTo_NoCase(m_RegistryInfo.ArcType)) - { - m_Format.SetCurSel(index); - Info.FormatIndex = arcIndex; - } - } - } - - { - UString fileName; - SetArcPathFields(Info.ArcPath, fileName, true); - StartDirPrefix = DirPrefix; - SetArchiveName(fileName); - } - SetLevel(); - SetParams(); - - for (unsigned i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++) - m_ArchivePath.AddString(m_RegistryInfo.ArcPaths[i]); - - AddComboItems(m_UpdateMode, k_UpdateMode_IDs, ARRAY_SIZE(k_UpdateMode_IDs), - k_UpdateMode_Vals, Info.UpdateMode); - - AddComboItems(m_PathMode, k_PathMode_IDs, ARRAY_SIZE(k_PathMode_IDs), - k_PathMode_Vals, Info.PathMode); - - SetSolidBlockSize(); - SetNumThreads(); - - TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; - ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); - SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s); - - CheckButton(IDX_COMPRESS_SFX, Info.SFXMode); - CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); - CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); - - CheckControlsEnable(); - - // OnButtonSFX(); - - SetEncryptionMethod(); - SetMemoryUsage(); - - NormalizePosition(); - - return CModalDialog::OnInit(); -} - -/* -namespace NCompressDialog -{ - bool CInfo::GetFullPathName(UString &result) const - { - #ifndef UNDER_CE - // NDirectory::MySetCurrentDirectory(CurrentDirPrefix); - #endif - FString resultF; - bool res = MyGetFullPathName(us2fs(ArchiveName), resultF); - result = fs2us(resultF); - return res; - } -} -*/ - -void CCompressDialog::UpdatePasswordControl() -{ - bool showPassword = IsShowPasswordChecked(); - TCHAR c = showPassword ? (TCHAR)0: TEXT('*'); - _password1Control.SetPasswordChar(c); - _password2Control.SetPasswordChar(c); - UString password; - _password1Control.GetText(password); - _password1Control.SetText(password); - _password2Control.GetText(password); - _password2Control.SetText(password); - - ShowItem_Bool(IDT_PASSWORD_REENTER, !showPassword); - _password2Control.Show_Bool(!showPassword); -} - -bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) -{ - switch (buttonID) - { - case IDB_COMPRESS_SET_ARCHIVE: - { - OnButtonSetArchive(); - return true; - } - case IDX_COMPRESS_SFX: - { - SetMethod(GetMethodID()); - OnButtonSFX(); - SetMemoryUsage(); - return true; - } - case IDX_PASSWORD_SHOW: - { - UpdatePasswordControl(); - return true; - } - } - return CModalDialog::OnButtonClicked(buttonID, buttonHWND); -} - -void CCompressDialog::CheckSFXControlsEnable() -{ - const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - bool enable = fi.SFX; - if (enable) - { - int methodID = GetMethodID(); - enable = (methodID == -1 || IsMethodSupportedBySfx(methodID)); - } - if (!enable) - CheckButton(IDX_COMPRESS_SFX, false); - EnableItem(IDX_COMPRESS_SFX, enable); -} - -/* -void CCompressDialog::CheckVolumeEnable() -{ - bool isSFX = IsSFX(); - m_Volume.Enable(!isSFX); - if (isSFX) - m_Volume.SetText(TEXT("")); -} -*/ - -void CCompressDialog::CheckControlsEnable() -{ - const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - Info.SolidIsSpecified = fi.Solid; - bool multiThreadEnable = fi.MultiThread; - Info.MultiThreadIsAllowed = multiThreadEnable; - Info.EncryptHeadersIsAllowed = fi.EncryptFileNames; - - EnableItem(IDC_COMPRESS_SOLID, fi.Solid); - EnableItem(IDC_COMPRESS_THREADS, multiThreadEnable); - - CheckSFXControlsEnable(); - - { - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - - ShowItem_Bool(IDX_COMPRESS_NT_SYM_LINKS, ai.Flags_SymLinks()); - ShowItem_Bool(IDX_COMPRESS_NT_HARD_LINKS, ai.Flags_HardLinks()); - ShowItem_Bool(IDX_COMPRESS_NT_ALT_STREAMS, ai.Flags_AltStreams()); - ShowItem_Bool(IDX_COMPRESS_NT_SECUR, ai.Flags_NtSecure()); - - ShowItem_Bool(IDG_COMPRESS_NTFS, - ai.Flags_SymLinks() - || ai.Flags_HardLinks() - || ai.Flags_AltStreams() - || ai.Flags_NtSecure()); - } - // CheckVolumeEnable(); - - EnableItem(IDG_COMPRESS_ENCRYPTION, fi.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_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); - EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); - EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); - - ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); -} - -bool CCompressDialog::IsSFX() -{ - CWindow sfxButton = GetItem(IDX_COMPRESS_SFX); - return sfxButton.IsEnabled() && IsButtonCheckedBool(IDX_COMPRESS_SFX); -} - -static int GetExtDotPos(const UString &s) -{ - int dotPos = s.ReverseFind_Dot(); - if (dotPos > s.ReverseFind_PathSepar() + 1) - return dotPos; - return -1; -} - -void CCompressDialog::OnButtonSFX() -{ - UString fileName; - m_ArchivePath.GetText(fileName); - int dotPos = GetExtDotPos(fileName); - if (IsSFX()) - { - if (dotPos >= 0) - fileName.DeleteFrom(dotPos); - fileName += kExeExt; - m_ArchivePath.SetText(fileName); - } - else - { - if (dotPos >= 0) - { - UString ext = fileName.Ptr(dotPos); - if (ext.IsEqualTo_NoCase(kExeExt)) - { - fileName.DeleteFrom(dotPos); - m_ArchivePath.SetText(fileName); - } - } - SetArchiveName2(false); // it's for OnInit - } - - // CheckVolumeEnable(); -} - -bool CCompressDialog::GetFinalPath_Smart(UString &resPath) -{ - UString name; - m_ArchivePath.GetText(name); - name.Trim(); - UString tempPath = name; - if (!IsAbsolutePath(name)) - { - UString newDirPrefix = DirPrefix; - if (newDirPrefix.IsEmpty()) - newDirPrefix = StartDirPrefix; - FString resultF; - if (!MyGetFullPathName(us2fs(newDirPrefix + name), resultF)) - return false; - tempPath = fs2us(resultF); - } - if (!SetArcPathFields(tempPath, name, false)) - return false; - FString resultF; - if (!MyGetFullPathName(us2fs(DirPrefix + name), resultF)) - return false; - resPath = fs2us(resultF); - return true; -} - -bool CCompressDialog::SetArcPathFields(const UString &path, UString &name, bool always) -{ - FString resDirPrefix; - FString resFileName; - bool res = GetFullPathAndSplit(us2fs(path), resDirPrefix, resFileName); - if (res) - { - DirPrefix = fs2us(resDirPrefix); - name = fs2us(resFileName); - } - else - { - if (!always) - return false; - DirPrefix.Empty(); - name = path; - } - SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix); - m_ArchivePath.SetText(name); - return res; -} - -static const wchar_t *k_IncorrectPathMessage = L"Incorrect archive path"; - -void CCompressDialog::OnButtonSetArchive() -{ - UString path; - if (!GetFinalPath_Smart(path)) - { - ShowErrorMessage(*this, k_IncorrectPathMessage); - return; - } - - UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_BROWSE); - UString filterDescription = LangString(IDS_OPEN_TYPE_ALL_FILES); - filterDescription += L" (*.*)"; - UString resPath; - CurrentDirWasChanged = true; - if (!MyBrowseForFile(*this, title, - // DirPrefix.IsEmpty() ? NULL : (const wchar_t *)DirPrefix, - // NULL, - path, - filterDescription, - NULL, // L"*.*", - resPath)) - return; - UString dummyName; - SetArcPathFields(resPath, dummyName, true); -} - -// in ExtractDialog.cpp -extern void AddUniqueString(UStringVector &strings, const UString &srcString); - -static bool IsAsciiString(const UString &s) -{ - for (unsigned i = 0; i < s.Len(); i++) - { - wchar_t c = s[i]; - if (c < 0x20 || c > 0x7F) - return false; - } - return true; -} - -void CCompressDialog::OnOK() -{ - _password1Control.GetText(Info.Password); - if (IsZipFormat()) - { - if (!IsAsciiString(Info.Password)) - { - ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII); - return; - } - UString method = GetEncryptionMethodSpec(); - if (method.IsPrefixedBy_Ascii_NoCase("aes")) - { - if (Info.Password.Len() > 99) - { - ShowErrorMessageHwndRes(*this, IDS_PASSWORD_TOO_LONG); - return; - } - } - } - if (!IsShowPasswordChecked()) - { - UString password2; - _password2Control.GetText(password2); - if (password2 != Info.Password) - { - ShowErrorMessageHwndRes(*this, IDS_PASSWORD_NOT_MATCH); - return; - } - } - - SaveOptionsInMem(); - { - UString s; - if (!GetFinalPath_Smart(s)) - { - ShowErrorMessage(*this, k_IncorrectPathMessage); - return; - } - - m_RegistryInfo.ArcPaths.Clear(); - AddUniqueString(m_RegistryInfo.ArcPaths, s); - Info.ArcPath = s; - } - - Info.UpdateMode = (NCompressDialog::NUpdateMode::EEnum)k_UpdateMode_Vals[m_UpdateMode.GetCurSel()];; - Info.PathMode = (NWildcard::ECensorPathMode)k_PathMode_Vals[m_PathMode.GetCurSel()]; - - Info.Level = GetLevelSpec(); - Info.Dictionary = GetDictionarySpec(); - Info.Order = GetOrderSpec(); - Info.OrderMode = GetOrderMode(); - Info.NumThreads = GetNumThreadsSpec(); - - UInt32 solidLogSize = GetBlockSizeSpec(); - Info.SolidBlockSize = 0; - if (solidLogSize > 0 && solidLogSize != (UInt32)(Int32)-1) - Info.SolidBlockSize = (solidLogSize >= 64) ? (UInt64)(Int64)-1 : ((UInt64)1 << solidLogSize); - - Info.Method = GetMethodSpec(); - Info.EncryptionMethod = GetEncryptionMethodSpec(); - Info.FormatIndex = GetFormatIndex(); - Info.SFXMode = IsSFX(); - Info.OpenShareForWrite = IsButtonCheckedBool(IDX_COMPRESS_SHARED); - Info.DeleteAfterCompressing = IsButtonCheckedBool(IDX_COMPRESS_DEL); - - m_RegistryInfo.EncryptHeaders = - Info.EncryptHeaders = IsButtonCheckedBool(IDX_COMPRESS_ENCRYPT_FILE_NAMES); - - - GetButton_Bools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); - GetButton_Bools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); - GetButton_Bools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); - GetButton_Bools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); - - { - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - if (!ai.Flags_SymLinks()) Info.SymLinks.Val = false; - if (!ai.Flags_HardLinks()) Info.HardLinks.Val = false; - if (!ai.Flags_AltStreams()) Info.AltStreams.Val = false; - if (!ai.Flags_NtSecure()) Info.NtSecurity.Val = false; - } - - m_Params.GetText(Info.Options); - - UString volumeString; - m_Volume.GetText(volumeString); - volumeString.Trim(); - Info.VolumeSizes.Clear(); - - if (!volumeString.IsEmpty()) - { - if (!ParseVolumeSizes(volumeString, Info.VolumeSizes)) - { - ShowErrorMessageHwndRes(*this, IDS_INCORRECT_VOLUME_SIZE); - return; - } - if (!Info.VolumeSizes.IsEmpty()) - { - const UInt64 volumeSize = Info.VolumeSizes.Back(); - if (volumeSize < (100 << 10)) - { - wchar_t s[32]; - ConvertUInt64ToString(volumeSize, s); - if (::MessageBoxW(*this, MyFormatNew(IDS_SPLIT_CONFIRM, s), - L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES) - return; - } - } - } - - for (int i = 0; i < m_ArchivePath.GetCount(); i++) - { - UString sTemp; - m_ArchivePath.GetLBText(i, sTemp); - sTemp.Trim(); - AddUniqueString(m_RegistryInfo.ArcPaths, sTemp); - } - - if (m_RegistryInfo.ArcPaths.Size() > kHistorySize) - m_RegistryInfo.ArcPaths.DeleteBack(); - - if (Info.FormatIndex >= 0) - m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name; - m_RegistryInfo.ShowPassword = IsShowPasswordChecked(); - - m_RegistryInfo.Save(); - - CModalDialog::OnOK(); -} - -static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm"; - -void CCompressDialog::OnHelp() -{ - ShowHelpWindow(NULL, kHelpTopic); -} - -bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) -{ - if (code == CBN_SELCHANGE) - { - switch (itemID) - { - case IDC_COMPRESS_ARCHIVE: - { - // we can 't change m_ArchivePath in that handler ! - DirPrefix.Empty(); - SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix); - - /* - - - UString path; - m_ArchivePath.GetText(path); - m_ArchivePath.SetText(L""); - if (IsAbsolutePath(path)) - { - UString fileName; - SetArcPathFields(path, fileName); - SetArchiveName(fileName); - } - */ - return true; - } - case IDC_COMPRESS_FORMAT: - { - bool isSFX = IsSFX(); - SaveOptionsInMem(); - SetLevel(); - SetSolidBlockSize(); - SetNumThreads(); - SetParams(); - CheckControlsEnable(); - SetArchiveName2(isSFX); - SetEncryptionMethod(); - SetMemoryUsage(); - return true; - } - case IDC_COMPRESS_LEVEL: - { - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - int index = FindRegistryFormatAlways(ai.Name); - NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - fo.ResetForLevelChange(); - SetMethod(GetMethodID()); - SetSolidBlockSize(); - SetNumThreads(); - CheckSFXNameChange(); - SetMemoryUsage(); - return true; - } - case IDC_COMPRESS_METHOD: - { - // MessageBoxW(*this, L"IDC_COMPRESS_METHOD!", L"7-Zip", MB_ICONERROR); - if (GetMethodID() == kZSTD) - { - SetLevel_zstd(); - } else { - SetLevel_default(); - } - SetDictionary(); - SetOrder(); - SetSolidBlockSize(); - SetNumThreads(); - CheckSFXNameChange(); - SetMemoryUsage(); - return true; - } - case IDC_COMPRESS_DICTIONARY: - case IDC_COMPRESS_ORDER: - { - SetSolidBlockSize(); - SetMemoryUsage(); - return true; - } - case IDC_COMPRESS_THREADS: - { - SetMemoryUsage(); - return true; - } - } - } - return CModalDialog::OnCommand(code, itemID, lParam); -} - -void CCompressDialog::CheckSFXNameChange() -{ - bool isSFX = IsSFX(); - CheckSFXControlsEnable(); - if (isSFX != IsSFX()) - SetArchiveName2(isSFX); -} - -void CCompressDialog::SetArchiveName2(bool prevWasSFX) -{ - UString fileName; - m_ArchivePath.GetText(fileName); - const CArcInfoEx &prevArchiverInfo = (*ArcFormats)[m_PrevFormat]; - if (prevArchiverInfo.Flags_KeepName() || Info.KeepName) - { - UString prevExtension; - if (prevWasSFX) - prevExtension = kExeExt; - else - prevExtension = UString(L'.') + prevArchiverInfo.GetMainExt(); - const unsigned prevExtensionLen = prevExtension.Len(); - if (fileName.Len() >= prevExtensionLen) - if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension)) - fileName.DeleteFrom(fileName.Len() - prevExtensionLen); - } - SetArchiveName(fileName); -} - -// if type.KeepName then use OriginalFileName -// else if !KeepName remove extension -// add new extension - -void CCompressDialog::SetArchiveName(const UString &name) -{ - UString fileName = name; - Info.FormatIndex = GetFormatIndex(); - const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; - m_PrevFormat = Info.FormatIndex; - if (ai.Flags_KeepName()) - { - fileName = OriginalFileName; - } - else - { - if (!Info.KeepName) - { - int dotPos = GetExtDotPos(fileName); - if (dotPos >= 0) - fileName.DeleteFrom(dotPos); - } - } - - if (IsSFX()) - fileName += kExeExt; - else - { - fileName += L'.'; - fileName += ai.GetMainExt(); - } - m_ArchivePath.SetText(fileName); -} - -int CCompressDialog::FindRegistryFormat(const UString &name) -{ - FOR_VECTOR (i, m_RegistryInfo.Formats) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i]; - if (name.IsEqualTo_NoCase(GetUnicodeString(fo.FormatID))) - return i; - } - return -1; -} - -int CCompressDialog::FindRegistryFormatAlways(const UString &name) -{ - int index = FindRegistryFormat(name); - if (index < 0) - { - NCompression::CFormatOptions fo; - fo.FormatID = GetSystemString(name); - index = m_RegistryInfo.Formats.Add(fo); - } - return index; -} - -int CCompressDialog::GetStaticFormatIndex() -{ - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++) - if (ai.Name.IsEqualTo_NoCase(g_Formats[i].Name)) - return i; - return 0; // -1; -} - -void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value) -{ - for (int i = comboBox.GetCount() - 1; i >= 0; i--) - if ((UInt32)comboBox.GetItemData(i) <= value) - { - comboBox.SetCurSel(i); - return; - } - if (comboBox.GetCount() > 0) - comboBox.SetCurSel(0); -} - -void CCompressDialog::SetLevel_zstd() -{ - UInt32 level = GetLevel2(); - - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - { - int index = FindRegistryFormat(ai.Name); - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Level <= 22) - level = fo.Level; - } - } - - /* ZStandard has 22 levels */ - m_Level.ResetContent(); - for (unsigned i = 0; i <= 22; i++) - { - TCHAR s[40]; - TCHAR t[50] = { TEXT('L'), TEXT('e'), TEXT('v'), TEXT('e'), TEXT('l'), TEXT(' '), 0 }; - ConvertUInt32ToString(i, s); - lstrcat(t, s); - switch (i) { - case 0: - lstrcat(t, TEXT(" (")); - lstrcat(t, LangString(IDS_METHOD_STORE)); - lstrcat(t, TEXT(")")); - break; - case 1: - lstrcat(t, TEXT(" (")); - lstrcat(t, LangString(IDS_METHOD_FASTEST)); - lstrcat(t, TEXT(")")); - break; - case 5: - lstrcat(t, TEXT(" (")); - lstrcat(t, LangString(IDS_METHOD_FAST)); - lstrcat(t, TEXT(")")); - break; - case 11: - lstrcat(t, TEXT(" (")); - lstrcat(t, LangString(IDS_METHOD_NORMAL)); - lstrcat(t, TEXT(")")); - break; - case 17: - lstrcat(t, TEXT(" (")); - lstrcat(t, LangString(IDS_METHOD_MAXIMUM)); - lstrcat(t, TEXT(")")); - break; - case 22: - lstrcat(t, TEXT(" (")); - lstrcat(t, LangString(IDS_METHOD_ULTRA)); - lstrcat(t, TEXT(")")); - break; - } - int index = (int)m_Level.AddString(t); - m_Level.SetItemData(index, i); - } - - SetNearestSelectComboBox(m_Level, level); - return; -} - -void CCompressDialog::SetLevel_default() -{ - UInt32 level = GetLevel2(); - - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - { - int index = FindRegistryFormat(ai.Name); - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Level <= 9) - level = fo.Level; - else - level = 9; - } - } - - /* 9 default levels */ - m_Level.ResetContent(); - const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - - for (unsigned i = 0; i <= 9; i++) - { - if ((fi.LevelsMask & (1 << i)) != 0) - { - TCHAR s[40]; - TCHAR t[50] = { TEXT('L'), TEXT('e'), TEXT('v'), TEXT('e'), TEXT('l'), TEXT(' '), 0 }; - UInt32 langID = g_Levels[i]; - ConvertUInt32ToString(i, s); - lstrcat(t, s); - lstrcat(t, TEXT(" (")); - lstrcat(t, LangString(langID)); - lstrcat(t, TEXT(")")); - int index = (int)m_Level.AddString(t); - m_Level.SetItemData(index, i); - } - } - - SetNearestSelectComboBox(m_Level, level); - return; -} - -void CCompressDialog::SetLevel() -{ - SetMethod(); - - if (GetMethodID() == kZSTD) - { - SetLevel_zstd(); - } else { - SetLevel_default(); - } -} - -void CCompressDialog::SetMethod(int keepMethodId) -{ - m_Method.ResetContent(); - UInt32 level = GetLevel2(); - if (level == 0) - { - SetDictionary(); - SetOrder(); - return; - } - const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - int index = FindRegistryFormat(ai.Name); - UString defaultMethod; - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - defaultMethod = fo.Method; - } - bool isSfx = IsSFX(); - bool weUseSameMethod = false; - - for (unsigned m = 0; m < fi.NumMethods; m++) - { - EMethodID methodID = fi.MethodIDs[m]; - if (isSfx) - if (!IsMethodSupportedBySfx(methodID)) - continue; - const LPCWSTR method = kMethodsNames[methodID]; - int itemIndex = (int)m_Method.AddString(GetSystemString(method)); - m_Method.SetItemData(itemIndex, methodID); - - - if (keepMethodId == methodID) - { - m_Method.SetCurSel(itemIndex); - weUseSameMethod = true; - continue; - } - - if ((defaultMethod.IsEqualTo_NoCase(method) || m == 0) && !weUseSameMethod) - m_Method.SetCurSel(itemIndex); - } - - if (!weUseSameMethod) - { - SetDictionary(); - SetOrder(); - } -} - -bool CCompressDialog::IsZipFormat() -{ - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - return ai.Name.IsEqualTo_Ascii_NoCase("zip"); -} - -void CCompressDialog::SetEncryptionMethod() -{ - _encryptionMethod.ResetContent(); - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - if (ai.Name.IsEqualTo_Ascii_NoCase("7z")) - { - _encryptionMethod.AddString(TEXT("AES-256")); - _encryptionMethod.SetCurSel(0); - } - else if (ai.Name.IsEqualTo_Ascii_NoCase("zip")) - { - int index = FindRegistryFormat(ai.Name); - UString encryptionMethod; - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - encryptionMethod = fo.EncryptionMethod; - } - _encryptionMethod.AddString(TEXT("ZipCrypto")); - _encryptionMethod.AddString(TEXT("AES-256")); - _encryptionMethod.SetCurSel(encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0); - } -} - -int CCompressDialog::GetMethodID() -{ - if (m_Method.GetCount() <= 0) - return -1; - return (int)(UInt32)m_Method.GetItemData_of_CurSel(); -} - -UString CCompressDialog::GetMethodSpec() -{ - if (m_Method.GetCount() <= 1) - return UString(); - return kMethodsNames[GetMethodID()]; -} - -UString CCompressDialog::GetEncryptionMethodSpec() -{ - if (_encryptionMethod.GetCount() <= 1) - return UString(); - if (_encryptionMethod.GetCurSel() <= 0) - return UString(); - UString result; - _encryptionMethod.GetText(result); - result.RemoveChar(L'-'); - return result; -} - -void CCompressDialog::AddDictionarySize(UInt32 size) -{ - Byte c = 0; - unsigned moveBits = 0; - if ((size & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; } - else if ((size & 0x3FF) == 0) { moveBits = 10; c = 'K'; } - TCHAR s[40]; - ConvertUInt32ToString(size >> moveBits, s); - unsigned pos = MyStringLen(s); - s[pos++] = ' '; - if (moveBits != 0) - s[pos++] = c; - s[pos++] = 'B'; - s[pos++] = 0; - int index = (int)m_Dictionary.AddString(s); - m_Dictionary.SetItemData(index, size); -} - -void CCompressDialog::SetDictionary() -{ - m_Dictionary.ResetContent(); - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - int index = FindRegistryFormat(ai.Name); - UInt32 defaultDict = (UInt32)(Int32)-1; - - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) - defaultDict = fo.Dictionary; - } - - int methodID = GetMethodID(); - UInt32 level = GetLevel2(); - if (methodID < 0) - return; - UInt64 maxRamSize; - bool maxRamSize_Defined = GetMaxRamSizeForProgram(maxRamSize); - - switch (methodID) - { - case kLZMA: - case kLZMA2: - { - static const UInt32 kMinDicSize = (1 << 16); - if (defaultDict == (UInt32)(Int32)-1) - { - if (level >= 9) defaultDict = (1 << 26); - else if (level >= 7) defaultDict = (1 << 25); - else if (level >= 5) defaultDict = (1 << 24); - else if (level >= 3) defaultDict = (1 << 20); - else defaultDict = (kMinDicSize); - } - - AddDictionarySize(kMinDicSize); - m_Dictionary.SetCurSel(0); - - for (unsigned i = 20; i <= 31; i++) - for (unsigned j = 0; j < 2; j++) - { - if (i == 20 && j > 0) - continue; - UInt32 dict = ((UInt32)(2 + j) << (i - 1)); - - if (dict > - #ifdef MY_CPU_64BIT - (3 << 29) - #else - (1 << 26) - #endif - ) - continue; - - AddDictionarySize(dict); - UInt64 decomprSize; - UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); - if (dict <= defaultDict && (!maxRamSize_Defined || requiredComprSize <= maxRamSize)) - m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); - } - - // SetNearestSelectComboBox(m_Dictionary, defaultDict); - break; - } - - case kPPMd: - { - if (defaultDict == (UInt32)(Int32)-1) - { - if (level >= 9) defaultDict = (192 << 20); - else if (level >= 7) defaultDict = ( 64 << 20); - else if (level >= 5) defaultDict = ( 16 << 20); - else defaultDict = ( 4 << 20); - } - - for (unsigned i = 20; i < 31; i++) - for (unsigned j = 0; j < 2; j++) - { - if (i == 20 && j > 0) - continue; - UInt32 dict = ((UInt32)(2 + j) << (i - 1)); - if (dict > - #ifdef MY_CPU_64BIT - (1 << 30) - #else - (1 << 29) - #endif - ) - continue; - AddDictionarySize(dict); - UInt64 decomprSize; - UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); - if ((dict <= defaultDict && (!maxRamSize_Defined || requiredComprSize <= maxRamSize)) - || m_Dictionary.GetCount() == 1) - m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); - } - - // SetNearestSelectComboBox(m_Dictionary, defaultDict); - break; - } - - case kDeflate: - { - AddDictionarySize(32 << 10); - m_Dictionary.SetCurSel(0); - break; - } - - case kDeflate64: - { - AddDictionarySize(64 << 10); - m_Dictionary.SetCurSel(0); - break; - } - - case kBZip2: - { - if (defaultDict == (UInt32)(Int32)-1) - { - if (level >= 5) defaultDict = (900 << 10); - else if (level >= 3) defaultDict = (500 << 10); - else defaultDict = (100 << 10); - } - - for (unsigned i = 1; i <= 9; i++) - { - UInt32 dict = ((UInt32)i * 100) << 10; - AddDictionarySize(dict); - if (dict <= defaultDict || m_Dictionary.GetCount() == 0) - m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); - } - - break; - } - - case kPPMdZip: - { - if (defaultDict == (UInt32)(Int32)-1) - defaultDict = (1 << (19 + (level > 8 ? 8 : level))); - - for (unsigned i = 20; i <= 28; i++) - { - UInt32 dict = (1 << i); - AddDictionarySize(dict); - UInt64 decomprSize; - UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); - if ((dict <= defaultDict && (!maxRamSize_Defined || requiredComprSize <= maxRamSize)) - || m_Dictionary.GetCount() == 1) - m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); - } - - // SetNearestSelectComboBox(m_Dictionary, defaultDict); - break; - } - - } -} - -UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax) -{ - if (c.GetCount() <= defMax) - return (UInt32)(Int32)-1; - return (UInt32)c.GetItemData_of_CurSel(); -} - -UInt32 CCompressDialog::GetLevel2() -{ - UInt32 level = GetLevel(); - if (level == (UInt32)(Int32)-1) - level = 5; - return level; -} - -int CCompressDialog::AddOrder(UInt32 size) -{ - TCHAR s[40]; - ConvertUInt32ToString(size, s); - int index = (int)m_Order.AddString(s); - m_Order.SetItemData(index, size); - return index; -} - -void CCompressDialog::SetOrder() -{ - m_Order.ResetContent(); - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - int index = FindRegistryFormat(ai.Name); - UInt32 defaultOrder = (UInt32)(Int32)-1; - - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) - defaultOrder = fo.Order; - } - - int methodID = GetMethodID(); - UInt32 level = GetLevel2(); - if (methodID < 0) - return; - - switch (methodID) - { - case kLZMA: - case kLZMA2: - { - if (defaultOrder == (UInt32)(Int32)-1) - defaultOrder = (level >= 7) ? 64 : 32; - for (unsigned i = 3; i <= 8; i++) - for (unsigned j = 0; j < 2; j++) - { - UInt32 order = ((UInt32)(2 + j) << (i - 1)); - if (order <= 256) - AddOrder(order); - } - AddOrder(273); - SetNearestSelectComboBox(m_Order, defaultOrder); - break; - } - - case kPPMd: - { - if (defaultOrder == (UInt32)(Int32)-1) - { - if (level >= 9) defaultOrder = 32; - else if (level >= 7) defaultOrder = 16; - else if (level >= 5) defaultOrder = 6; - else defaultOrder = 4; - } - - AddOrder(2); - AddOrder(3); - - for (unsigned i = 2; i < 8; i++) - for (unsigned j = 0; j < 4; j++) - { - UInt32 order = (4 + j) << (i - 2); - if (order < 32) - AddOrder(order); - } - - AddOrder(32); - SetNearestSelectComboBox(m_Order, defaultOrder); - break; - } - - case kDeflate: - case kDeflate64: - { - if (defaultOrder == (UInt32)(Int32)-1) - { - if (level >= 9) defaultOrder = 128; - else if (level >= 7) defaultOrder = 64; - else defaultOrder = 32; - } - - for (unsigned i = 3; i <= 8; i++) - for (unsigned j = 0; j < 2; j++) - { - UInt32 order = ((UInt32)(2 + j) << (i - 1));; - if (order <= 256) - AddOrder(order); - } - - AddOrder(methodID == kDeflate64 ? 257 : 258); - SetNearestSelectComboBox(m_Order, defaultOrder); - break; - } - - case kBZip2: - break; - - case kPPMdZip: - { - if (defaultOrder == (UInt32)(Int32)-1) - defaultOrder = level + 3; - for (unsigned i = 2; i <= 16; i++) - AddOrder(i); - SetNearestSelectComboBox(m_Order, defaultOrder); - break; - } - } -} - -bool CCompressDialog::GetOrderMode() -{ - switch (GetMethodID()) - { - case kPPMd: - case kPPMdZip: - return true; - } - return false; -} - -static const UInt32 kNoSolidBlockSize = 0; -static const UInt32 kSolidBlockSize = 64; - -void CCompressDialog::SetSolidBlockSize() -{ - m_Solid.ResetContent(); - const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (!fi.Solid) - return; - - UInt32 level = GetLevel2(); - if (level == 0) - return; - - UInt32 dict = GetDictionarySpec(); - if (dict == (UInt32)(Int32)-1) - dict = 1; - - UInt32 defaultBlockSize = (UInt32)(Int32)-1; - - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - { - int index = FindRegistryFormat(ai.Name); - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) - defaultBlockSize = fo.BlockLogSize; - } - } - - { - int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID)); - m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize); - m_Solid.SetCurSel(0); - } - - bool needSet = (defaultBlockSize == (UInt32)(Int32)-1); - - for (unsigned i = 20; i <= 36; i++) - { - if (needSet && dict >= (((UInt64)1 << (i - 7))) && i <= 32) - defaultBlockSize = i; - TCHAR s[40]; - ConvertUInt32ToString(1 << (i % 10), s); - if (i < 30) lstrcat(s, TEXT(" M")); - else lstrcat(s, TEXT(" G")); - lstrcat(s, TEXT("B")); - int index = (int)m_Solid.AddString(s); - m_Solid.SetItemData(index, (UInt32)i); - } - - { - int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID)); - m_Solid.SetItemData(index, kSolidBlockSize); - } - - if (defaultBlockSize == (UInt32)(Int32)-1) - defaultBlockSize = kSolidBlockSize; - if (defaultBlockSize != kNoSolidBlockSize) - SetNearestSelectComboBox(m_Solid, defaultBlockSize); -} - -void CCompressDialog::SetNumThreads() -{ - m_NumThreads.ResetContent(); - - const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (!fi.MultiThread) - return; - - UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); - UInt32 defaultValue = numHardwareThreads; - - { - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - int index = FindRegistryFormat(ai.Name); - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1) - defaultValue = fo.NumThreads; - } - } - - UInt32 numAlgoThreadsMax = 1; - int methodID = GetMethodID(); - switch (methodID) - { - case kLZMA: numAlgoThreadsMax = 2; break; - case kLZMA2: numAlgoThreadsMax = 32; break; - case kBZip2: numAlgoThreadsMax = 32; break; - } - if (IsZipFormat()) - numAlgoThreadsMax = 128; - for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) - { - TCHAR s[40]; - ConvertUInt32ToString(i, s); - int index = (int)m_NumThreads.AddString(s); - m_NumThreads.SetItemData(index, (UInt32)i); - } - SetNearestSelectComboBox(m_NumThreads, defaultValue); -} - -UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory) -{ - decompressMemory = UInt64(Int64(-1)); - UInt32 level = GetLevel2(); - if (level == 0) - { - decompressMemory = (1 << 20); - return decompressMemory; - } - UInt64 size = 0; - - const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; - if (fi.Filter && level >= 9) - size += (12 << 20) * 2 + (5 << 20); - UInt32 numThreads = GetNumThreads2(); - - if (IsZipFormat()) - { - UInt32 numSubThreads = 1; - if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5) - numSubThreads = 2; - UInt32 numMainThreads = numThreads / numSubThreads; - if (numMainThreads > 1) - size += (UInt64)numMainThreads << 25; - } - - int methidId = GetMethodID(); - - switch (methidId) - { - case kLZMA: - case kLZMA2: - { - UInt32 hs = dict - 1; - hs |= (hs >> 1); - hs |= (hs >> 2); - hs |= (hs >> 4); - hs |= (hs >> 8); - hs >>= 1; - hs |= 0xFFFF; - if (hs > (1 << 24)) - hs >>= 1; - hs++; - UInt64 size1 = (UInt64)hs * 4; - size1 += (UInt64)dict * 4; - if (level >= 5) - size1 += (UInt64)dict * 4; - size1 += (2 << 20); - - UInt32 numThreads1 = 1; - if (numThreads > 1 && level >= 5) - { - size1 += (2 << 20) + (4 << 20); - numThreads1 = 2; - } - - UInt32 numBlockThreads = numThreads / numThreads1; - - if (methidId == kLZMA || numBlockThreads == 1) - size1 += (UInt64)dict * 3 / 2; - else - { - UInt64 chunkSize = (UInt64)dict << 2; - chunkSize = MyMax(chunkSize, (UInt64)(1 << 20)); - chunkSize = MyMin(chunkSize, (UInt64)(1 << 28)); - chunkSize = MyMax(chunkSize, (UInt64)dict); - size1 += chunkSize * 2; - } - size += size1 * numBlockThreads; - - decompressMemory = dict + (2 << 20); - return size; - } - - case kPPMd: - { - decompressMemory = dict + (2 << 20); - return size + decompressMemory; - } - - case kZSTD: - { - /* Code Snippet for CPP/7zip/UI/GUI/CompressDialog.cpp with blocklen=4194304 */ - size = 0; - switch (level) { - case 1: size = 562124; break; - case 2: size = 758732; break; - case 3: size = 1807308; break; - case 4: size = 1053644; break; - case 5: size = 1676236; break; - case 6: size = 2855884; break; - case 7: size = 5215180; break; - case 8: size = 5739468; break; - case 9: size = 8885196; break; - case 10: size = 10982348; break; - case 11: size = 21468108; break; - case 12: size = 21468108; break; - case 13: size = 25662412; break; - case 14: size = 25662412; break; - case 15: size = 17273804; break; - case 16: size = 34051020; break; - case 17: size = 50828236; break; - case 18: size = 50977224; break; - case 19: size = 51621650; break; - case 20: size = 51621650; break; - case 21: size = 51621650; break; - case 22: size = 51621650; break; - } - decompressMemory = 152872; - return size; - } - - case kDeflate: - case kDeflate64: - { - UInt32 order = GetOrder(); - if (order == (UInt32)(Int32)-1) - order = 32; - if (level >= 7) - size += (1 << 20); - size += 3 << 20; - decompressMemory = (2 << 20); - return size; - } - - case kBZip2: - { - decompressMemory = (7 << 20); - UInt64 memForOneThread = (10 << 20); - return size + memForOneThread * numThreads; - } - - case kPPMdZip: - { - decompressMemory = dict + (2 << 20); - return size + (UInt64)decompressMemory * numThreads; - } - } - - return (UInt64)(Int64)-1; -} - -UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory) -{ - return GetMemoryUsage(GetDictionary(), decompressMemory); -} - -void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) -{ - if (value == (UInt64)(Int64)-1) - { - SetItemText(res, TEXT("?")); - return; - } - value = (value + (1 << 20) - 1) >> 20; - TCHAR s[40]; - ConvertUInt64ToString(value, s); - lstrcat(s, TEXT(" MB")); - SetItemText(res, s); -} - -void CCompressDialog::SetMemoryUsage() -{ - UInt64 decompressMem; - UInt64 memUsage = GetMemoryUsage(decompressMem); - PrintMemUsage(IDT_COMPRESS_MEMORY_VALUE, memUsage); - PrintMemUsage(IDT_COMPRESS_MEMORY_DE_VALUE, decompressMem); -} - -void CCompressDialog::SetParams() -{ - const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; - m_Params.SetText(TEXT("")); - int index = FindRegistryFormat(ai.Name); - if (index >= 0) - { - const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - m_Params.SetText(fo.Options); - } -} - -void CCompressDialog::SaveOptionsInMem() -{ - const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; - int index = FindRegistryFormatAlways(ai.Name); - m_Params.GetText(Info.Options); - Info.Options.Trim(); - NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; - fo.Options = Info.Options; - fo.Level = GetLevelSpec(); - fo.Dictionary = GetDictionarySpec(); - fo.Order = GetOrderSpec(); - fo.Method = GetMethodSpec(); - fo.EncryptionMethod = GetEncryptionMethodSpec(); - fo.NumThreads = GetNumThreadsSpec(); - fo.BlockLogSize = GetBlockSizeSpec(); -} - -unsigned CCompressDialog::GetFormatIndex() -{ - return (unsigned)m_Format.GetItemData_of_CurSel(); -} +// CompressDialog.cpp + +#include "StdAfx.h" + +#include "../../../../C/CpuArch.h" + +#include "../../../Common/IntToString.h" +#include "../../../Common/StringConvert.h" + +#include "../../../Windows/FileDir.h" +#include "../../../Windows/FileName.h" +#include "../../../Windows/System.h" + +#include "../FileManager/BrowseDialog.h" +#include "../FileManager/FormatUtils.h" +#include "../FileManager/HelpUtils.h" +#include "../FileManager/SplitUtils.h" + +#include "../Explorer/MyMessages.h" + +#include "../Common/ZipRegistry.h" + +#include "CompressDialog.h" + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +#ifdef LANG +#include "../FileManager/LangUtils.h" +#endif + +#include "CompressDialogRes.h" +#include "ExtractRes.h" + +#ifdef LANG +static const UInt32 kLangIDs[] = +{ + IDT_COMPRESS_ARCHIVE, + IDT_COMPRESS_UPDATE_MODE, + IDT_COMPRESS_FORMAT, + IDT_COMPRESS_LEVEL, + IDT_COMPRESS_METHOD, + IDT_COMPRESS_DICTIONARY, + IDT_COMPRESS_ORDER, + IDT_COMPRESS_SOLID, + IDT_COMPRESS_THREADS, + IDT_COMPRESS_PARAMETERS, + + IDG_COMPRESS_OPTIONS, + IDX_COMPRESS_SFX, + IDX_COMPRESS_SHARED, + IDX_COMPRESS_DEL, + + IDT_COMPRESS_MEMORY, + IDT_COMPRESS_MEMORY_DE, + + IDX_COMPRESS_NT_SYM_LINKS, + IDX_COMPRESS_NT_HARD_LINKS, + IDX_COMPRESS_NT_ALT_STREAMS, + IDX_COMPRESS_NT_SECUR, + + IDG_COMPRESS_ENCRYPTION, + IDT_COMPRESS_ENCRYPTION_METHOD, + IDX_COMPRESS_ENCRYPT_FILE_NAMES, + + IDT_PASSWORD_ENTER, + IDT_PASSWORD_REENTER, + IDX_PASSWORD_SHOW, + + IDT_SPLIT_TO_VOLUMES, + IDT_COMPRESS_PATH_MODE +}; +#endif + +using namespace NWindows; +using namespace NFile; +using namespace NName; +using namespace NDir; + +static const unsigned kHistorySize = 20; + +static LPCWSTR kExeExt = L".exe"; +static LPCWSTR k7zFormat = L"7z"; + +static const UInt32 g_Levels[] = +{ + IDS_METHOD_STORE, + IDS_METHOD_FASTEST, + 0, + IDS_METHOD_FAST, + 0, + IDS_METHOD_NORMAL, + 0, + IDS_METHOD_MAXIMUM, + 0, + IDS_METHOD_ULTRA +}; + +enum EMethodID +{ + kCopy, + kZSTD, + kLZMA, + kLZMA2, + kPPMd, + kBZip2, + kDeflate, + kDeflate64, + kPPMdZip +}; + +static const LPCWSTR kMethodsNames[] = +{ + L"Copy", + L"ZSTD", + L"LZMA", + L"LZMA2", + L"PPMd", + L"BZip2", + L"Deflate", + L"Deflate64", + L"PPMd" +}; + +static const EMethodID g_7zMethods[] = +{ + kZSTD, + kLZMA2, + kLZMA, + kPPMd, + kDeflate, + kDeflate64, + kBZip2 +}; + +static const EMethodID g_7zSfxMethods[] = +{ + kCopy, + kZSTD, + kLZMA, + kLZMA2, + kPPMd +}; + +static const EMethodID g_ZipMethods[] = +{ + kDeflate, + kDeflate64, + kBZip2, + kLZMA, + kPPMdZip +}; + +static const EMethodID g_GZipMethods[] = +{ + kDeflate +}; + +static const EMethodID g_BZip2Methods[] = +{ + kBZip2 +}; + +static const EMethodID g_XzMethods[] = +{ + kLZMA2 +}; + +static const EMethodID g_SwfcMethods[] = +{ + kDeflate +}; + +struct CFormatInfo +{ + LPCWSTR Name; + UInt32 LevelsMask; + const EMethodID *MethodIDs; + unsigned NumMethods; + + bool Filter; + bool Solid; + bool MultiThread; + bool SFX; + bool Encrypt; + bool EncryptFileNames; +}; + +#define METHODS_PAIR(x) x, ARRAY_SIZE(x) + +static const CFormatInfo g_Formats[] = +{ + { + L"", + (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + 0, 0, + false, false, false, false, false, false + }, + { + k7zFormat, + (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_7zMethods), + true, true, true, true, true, true + }, + { + L"Zip", + (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_ZipMethods), + false, false, true, false, true, false + }, + { + L"GZip", + (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_GZipMethods), + false, false, false, false, false, false + }, + { + L"BZip2", + (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_BZip2Methods), + false, false, true, false, false, false + }, + { + L"xz", + (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_XzMethods), + false, false, true, false, false, false + }, + { + L"Swfc", + (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9), + METHODS_PAIR(g_SwfcMethods), + false, false, true, false, false, false + }, + { + L"Tar", + (1 << 0), + 0, 0, + false, false, false, false, false, false + }, + { + L"wim", + (1 << 0), + 0, 0, + false, false, false, false, false, false + } +}; + +static bool IsMethodSupportedBySfx(int methodID) +{ + for (int i = 0; i < ARRAY_SIZE(g_7zSfxMethods); i++) + if (methodID == g_7zSfxMethods[i]) + return true; + return false; +} + +static bool GetMaxRamSizeForProgram(UInt64 &physSize) +{ + physSize = (UInt64)(sizeof(size_t)) << 29; + bool ramSize_Defined = NSystem::GetRamSize(physSize); + const UInt64 kMinSysSize = (1 << 24); + if (physSize <= kMinSysSize) + physSize = 0; + else + physSize -= kMinSysSize; + const UInt64 kMinUseSize = (1 << 24); + if (physSize < kMinUseSize) + physSize = kMinUseSize; + return ramSize_Defined; +} + + +static const + // NCompressDialog::NUpdateMode::EEnum + int + k_UpdateMode_Vals[] = +{ + NCompressDialog::NUpdateMode::kAdd, + NCompressDialog::NUpdateMode::kUpdate, + NCompressDialog::NUpdateMode::kFresh, + NCompressDialog::NUpdateMode::kSync +}; + +static const UInt32 k_UpdateMode_IDs[] = +{ + IDS_COMPRESS_UPDATE_MODE_ADD, + IDS_COMPRESS_UPDATE_MODE_UPDATE, + IDS_COMPRESS_UPDATE_MODE_FRESH, + IDS_COMPRESS_UPDATE_MODE_SYNC +}; + +static const + // NWildcard::ECensorPathMode + int + k_PathMode_Vals[] = +{ + NWildcard::k_RelatPath, + NWildcard::k_FullPath, + NWildcard::k_AbsPath, +}; + +static const UInt32 k_PathMode_IDs[] = +{ + IDS_PATH_MODE_RELAT, + IDS_EXTRACT_PATHS_FULL, + IDS_EXTRACT_PATHS_ABS +}; + +void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal); +bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2); + +void CCompressDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2) +{ + CheckButton(id, GetBoolsVal(b1, b2)); +} + +void CCompressDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2) +{ + bool val = IsButtonCheckedBool(id); + bool oldVal = GetBoolsVal(b1, b2); + if (val != oldVal) + b1.Def = b2.Def = true; + b1.Val = b2.Val = val; +} + + +bool CCompressDialog::OnInit() +{ + #ifdef LANG + LangSetWindowText(*this, IDD_COMPRESS); + LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); + #endif + + _password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1)); + _password2Control.Attach(GetItem(IDE_COMPRESS_PASSWORD2)); + _password1Control.SetText(Info.Password); + _password2Control.SetText(Info.Password); + _encryptionMethod.Attach(GetItem(IDC_COMPRESS_ENCRYPTION_METHOD)); + + m_ArchivePath.Attach(GetItem(IDC_COMPRESS_ARCHIVE)); + m_Format.Attach(GetItem(IDC_COMPRESS_FORMAT)); + m_Level.Attach(GetItem(IDC_COMPRESS_LEVEL)); + m_Method.Attach(GetItem(IDC_COMPRESS_METHOD)); + m_Dictionary.Attach(GetItem(IDC_COMPRESS_DICTIONARY)); + m_Order.Attach(GetItem(IDC_COMPRESS_ORDER)); + m_Solid.Attach(GetItem(IDC_COMPRESS_SOLID)); + m_NumThreads.Attach(GetItem(IDC_COMPRESS_THREADS)); + + m_UpdateMode.Attach(GetItem(IDC_COMPRESS_UPDATE_MODE)); + m_PathMode.Attach(GetItem(IDC_COMPRESS_PATH_MODE)); + + m_Volume.Attach(GetItem(IDC_COMPRESS_VOLUME)); + m_Params.Attach(GetItem(IDE_COMPRESS_PARAMETERS)); + + AddVolumeItems(m_Volume); + + m_RegistryInfo.Load(); + CheckButton(IDX_PASSWORD_SHOW, m_RegistryInfo.ShowPassword); + CheckButton(IDX_COMPRESS_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders); + + CheckButton_TwoBools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); + CheckButton_TwoBools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); + CheckButton_TwoBools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); + CheckButton_TwoBools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); + + UpdatePasswordControl(); + + { + bool needSetMain = (Info.FormatIndex < 0); + FOR_VECTOR(i, ArcIndices) + { + unsigned arcIndex = ArcIndices[i]; + const CArcInfoEx &ai = (*ArcFormats)[arcIndex]; + int index = (int)m_Format.AddString(ai.Name); + m_Format.SetItemData(index, arcIndex); + if (!needSetMain) + { + if (Info.FormatIndex == (int)arcIndex) + m_Format.SetCurSel(index); + continue; + } + if (i == 0 || ai.Name.IsEqualTo_NoCase(m_RegistryInfo.ArcType)) + { + m_Format.SetCurSel(index); + Info.FormatIndex = arcIndex; + } + } + } + + { + UString fileName; + SetArcPathFields(Info.ArcPath, fileName, true); + StartDirPrefix = DirPrefix; + SetArchiveName(fileName); + } + SetLevel(); + SetParams(); + + for (unsigned i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++) + m_ArchivePath.AddString(m_RegistryInfo.ArcPaths[i]); + + AddComboItems(m_UpdateMode, k_UpdateMode_IDs, ARRAY_SIZE(k_UpdateMode_IDs), + k_UpdateMode_Vals, Info.UpdateMode); + + AddComboItems(m_PathMode, k_PathMode_IDs, ARRAY_SIZE(k_PathMode_IDs), + k_PathMode_Vals, Info.PathMode); + + SetSolidBlockSize(); + SetNumThreads(); + + TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 }; + ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2); + SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s); + + CheckButton(IDX_COMPRESS_SFX, Info.SFXMode); + CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite); + CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing); + + CheckControlsEnable(); + + // OnButtonSFX(); + + SetEncryptionMethod(); + SetMemoryUsage(); + + NormalizePosition(); + + return CModalDialog::OnInit(); +} + +/* +namespace NCompressDialog +{ + bool CInfo::GetFullPathName(UString &result) const + { + #ifndef UNDER_CE + // NDirectory::MySetCurrentDirectory(CurrentDirPrefix); + #endif + FString resultF; + bool res = MyGetFullPathName(us2fs(ArchiveName), resultF); + result = fs2us(resultF); + return res; + } +} +*/ + +void CCompressDialog::UpdatePasswordControl() +{ + bool showPassword = IsShowPasswordChecked(); + TCHAR c = showPassword ? (TCHAR)0: TEXT('*'); + _password1Control.SetPasswordChar(c); + _password2Control.SetPasswordChar(c); + UString password; + _password1Control.GetText(password); + _password1Control.SetText(password); + _password2Control.GetText(password); + _password2Control.SetText(password); + + ShowItem_Bool(IDT_PASSWORD_REENTER, !showPassword); + _password2Control.Show_Bool(!showPassword); +} + +bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND) +{ + switch (buttonID) + { + case IDB_COMPRESS_SET_ARCHIVE: + { + OnButtonSetArchive(); + return true; + } + case IDX_COMPRESS_SFX: + { + SetMethod(GetMethodID()); + OnButtonSFX(); + SetMemoryUsage(); + return true; + } + case IDX_PASSWORD_SHOW: + { + UpdatePasswordControl(); + return true; + } + } + return CModalDialog::OnButtonClicked(buttonID, buttonHWND); +} + +void CCompressDialog::CheckSFXControlsEnable() +{ + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + bool enable = fi.SFX; + if (enable) + { + int methodID = GetMethodID(); + enable = (methodID == -1 || IsMethodSupportedBySfx(methodID)); + } + if (!enable) + CheckButton(IDX_COMPRESS_SFX, false); + EnableItem(IDX_COMPRESS_SFX, enable); +} + +/* +void CCompressDialog::CheckVolumeEnable() +{ + bool isSFX = IsSFX(); + m_Volume.Enable(!isSFX); + if (isSFX) + m_Volume.SetText(TEXT("")); +} +*/ + +void CCompressDialog::CheckControlsEnable() +{ + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + Info.SolidIsSpecified = fi.Solid; + bool multiThreadEnable = fi.MultiThread; + Info.MultiThreadIsAllowed = multiThreadEnable; + Info.EncryptHeadersIsAllowed = fi.EncryptFileNames; + + EnableItem(IDC_COMPRESS_SOLID, fi.Solid); + EnableItem(IDC_COMPRESS_THREADS, multiThreadEnable); + + CheckSFXControlsEnable(); + + { + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + + ShowItem_Bool(IDX_COMPRESS_NT_SYM_LINKS, ai.Flags_SymLinks()); + ShowItem_Bool(IDX_COMPRESS_NT_HARD_LINKS, ai.Flags_HardLinks()); + ShowItem_Bool(IDX_COMPRESS_NT_ALT_STREAMS, ai.Flags_AltStreams()); + ShowItem_Bool(IDX_COMPRESS_NT_SECUR, ai.Flags_NtSecure()); + + ShowItem_Bool(IDG_COMPRESS_NTFS, + ai.Flags_SymLinks() + || ai.Flags_HardLinks() + || ai.Flags_AltStreams() + || ai.Flags_NtSecure()); + } + // CheckVolumeEnable(); + + EnableItem(IDG_COMPRESS_ENCRYPTION, fi.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_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); + EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt); + EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); + + ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames); +} + +bool CCompressDialog::IsSFX() +{ + CWindow sfxButton = GetItem(IDX_COMPRESS_SFX); + return sfxButton.IsEnabled() && IsButtonCheckedBool(IDX_COMPRESS_SFX); +} + +static int GetExtDotPos(const UString &s) +{ + int dotPos = s.ReverseFind_Dot(); + if (dotPos > s.ReverseFind_PathSepar() + 1) + return dotPos; + return -1; +} + +void CCompressDialog::OnButtonSFX() +{ + UString fileName; + m_ArchivePath.GetText(fileName); + int dotPos = GetExtDotPos(fileName); + if (IsSFX()) + { + if (dotPos >= 0) + fileName.DeleteFrom(dotPos); + fileName += kExeExt; + m_ArchivePath.SetText(fileName); + } + else + { + if (dotPos >= 0) + { + UString ext = fileName.Ptr(dotPos); + if (ext.IsEqualTo_NoCase(kExeExt)) + { + fileName.DeleteFrom(dotPos); + m_ArchivePath.SetText(fileName); + } + } + SetArchiveName2(false); // it's for OnInit + } + + // CheckVolumeEnable(); +} + +bool CCompressDialog::GetFinalPath_Smart(UString &resPath) +{ + UString name; + m_ArchivePath.GetText(name); + name.Trim(); + UString tempPath = name; + if (!IsAbsolutePath(name)) + { + UString newDirPrefix = DirPrefix; + if (newDirPrefix.IsEmpty()) + newDirPrefix = StartDirPrefix; + FString resultF; + if (!MyGetFullPathName(us2fs(newDirPrefix + name), resultF)) + return false; + tempPath = fs2us(resultF); + } + if (!SetArcPathFields(tempPath, name, false)) + return false; + FString resultF; + if (!MyGetFullPathName(us2fs(DirPrefix + name), resultF)) + return false; + resPath = fs2us(resultF); + return true; +} + +bool CCompressDialog::SetArcPathFields(const UString &path, UString &name, bool always) +{ + FString resDirPrefix; + FString resFileName; + bool res = GetFullPathAndSplit(us2fs(path), resDirPrefix, resFileName); + if (res) + { + DirPrefix = fs2us(resDirPrefix); + name = fs2us(resFileName); + } + else + { + if (!always) + return false; + DirPrefix.Empty(); + name = path; + } + SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix); + m_ArchivePath.SetText(name); + return res; +} + +static const wchar_t *k_IncorrectPathMessage = L"Incorrect archive path"; + +void CCompressDialog::OnButtonSetArchive() +{ + UString path; + if (!GetFinalPath_Smart(path)) + { + ShowErrorMessage(*this, k_IncorrectPathMessage); + return; + } + + UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_BROWSE); + UString filterDescription = LangString(IDS_OPEN_TYPE_ALL_FILES); + filterDescription += L" (*.*)"; + UString resPath; + CurrentDirWasChanged = true; + if (!MyBrowseForFile(*this, title, + // DirPrefix.IsEmpty() ? NULL : (const wchar_t *)DirPrefix, + // NULL, + path, + filterDescription, + NULL, // L"*.*", + resPath)) + return; + UString dummyName; + SetArcPathFields(resPath, dummyName, true); +} + +// in ExtractDialog.cpp +extern void AddUniqueString(UStringVector &strings, const UString &srcString); + +static bool IsAsciiString(const UString &s) +{ + for (unsigned i = 0; i < s.Len(); i++) + { + wchar_t c = s[i]; + if (c < 0x20 || c > 0x7F) + return false; + } + return true; +} + +void CCompressDialog::OnOK() +{ + _password1Control.GetText(Info.Password); + if (IsZipFormat()) + { + if (!IsAsciiString(Info.Password)) + { + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII); + return; + } + UString method = GetEncryptionMethodSpec(); + if (method.IsPrefixedBy_Ascii_NoCase("aes")) + { + if (Info.Password.Len() > 99) + { + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_TOO_LONG); + return; + } + } + } + if (!IsShowPasswordChecked()) + { + UString password2; + _password2Control.GetText(password2); + if (password2 != Info.Password) + { + ShowErrorMessageHwndRes(*this, IDS_PASSWORD_NOT_MATCH); + return; + } + } + + SaveOptionsInMem(); + { + UString s; + if (!GetFinalPath_Smart(s)) + { + ShowErrorMessage(*this, k_IncorrectPathMessage); + return; + } + + m_RegistryInfo.ArcPaths.Clear(); + AddUniqueString(m_RegistryInfo.ArcPaths, s); + Info.ArcPath = s; + } + + Info.UpdateMode = (NCompressDialog::NUpdateMode::EEnum)k_UpdateMode_Vals[m_UpdateMode.GetCurSel()];; + Info.PathMode = (NWildcard::ECensorPathMode)k_PathMode_Vals[m_PathMode.GetCurSel()]; + + Info.Level = GetLevelSpec(); + Info.Dictionary = GetDictionarySpec(); + Info.Order = GetOrderSpec(); + Info.OrderMode = GetOrderMode(); + Info.NumThreads = GetNumThreadsSpec(); + + UInt32 solidLogSize = GetBlockSizeSpec(); + Info.SolidBlockSize = 0; + if (solidLogSize > 0 && solidLogSize != (UInt32)(Int32)-1) + Info.SolidBlockSize = (solidLogSize >= 64) ? (UInt64)(Int64)-1 : ((UInt64)1 << solidLogSize); + + Info.Method = GetMethodSpec(); + Info.EncryptionMethod = GetEncryptionMethodSpec(); + Info.FormatIndex = GetFormatIndex(); + Info.SFXMode = IsSFX(); + Info.OpenShareForWrite = IsButtonCheckedBool(IDX_COMPRESS_SHARED); + Info.DeleteAfterCompressing = IsButtonCheckedBool(IDX_COMPRESS_DEL); + + m_RegistryInfo.EncryptHeaders = + Info.EncryptHeaders = IsButtonCheckedBool(IDX_COMPRESS_ENCRYPT_FILE_NAMES); + + + GetButton_Bools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks); + GetButton_Bools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks); + GetButton_Bools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams); + GetButton_Bools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity); + + { + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + if (!ai.Flags_SymLinks()) Info.SymLinks.Val = false; + if (!ai.Flags_HardLinks()) Info.HardLinks.Val = false; + if (!ai.Flags_AltStreams()) Info.AltStreams.Val = false; + if (!ai.Flags_NtSecure()) Info.NtSecurity.Val = false; + } + + m_Params.GetText(Info.Options); + + UString volumeString; + m_Volume.GetText(volumeString); + volumeString.Trim(); + Info.VolumeSizes.Clear(); + + if (!volumeString.IsEmpty()) + { + if (!ParseVolumeSizes(volumeString, Info.VolumeSizes)) + { + ShowErrorMessageHwndRes(*this, IDS_INCORRECT_VOLUME_SIZE); + return; + } + if (!Info.VolumeSizes.IsEmpty()) + { + const UInt64 volumeSize = Info.VolumeSizes.Back(); + if (volumeSize < (100 << 10)) + { + wchar_t s[32]; + ConvertUInt64ToString(volumeSize, s); + if (::MessageBoxW(*this, MyFormatNew(IDS_SPLIT_CONFIRM, s), + L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES) + return; + } + } + } + + for (int i = 0; i < m_ArchivePath.GetCount(); i++) + { + UString sTemp; + m_ArchivePath.GetLBText(i, sTemp); + sTemp.Trim(); + AddUniqueString(m_RegistryInfo.ArcPaths, sTemp); + } + + if (m_RegistryInfo.ArcPaths.Size() > kHistorySize) + m_RegistryInfo.ArcPaths.DeleteBack(); + + if (Info.FormatIndex >= 0) + m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name; + m_RegistryInfo.ShowPassword = IsShowPasswordChecked(); + + m_RegistryInfo.Save(); + + CModalDialog::OnOK(); +} + +static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm"; + +void CCompressDialog::OnHelp() +{ + ShowHelpWindow(NULL, kHelpTopic); +} + +bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam) +{ + if (code == CBN_SELCHANGE) + { + switch (itemID) + { + case IDC_COMPRESS_ARCHIVE: + { + // we can 't change m_ArchivePath in that handler ! + DirPrefix.Empty(); + SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix); + + /* + + + UString path; + m_ArchivePath.GetText(path); + m_ArchivePath.SetText(L""); + if (IsAbsolutePath(path)) + { + UString fileName; + SetArcPathFields(path, fileName); + SetArchiveName(fileName); + } + */ + return true; + } + case IDC_COMPRESS_FORMAT: + { + bool isSFX = IsSFX(); + SaveOptionsInMem(); + SetLevel(); + SetSolidBlockSize(); + SetNumThreads(); + SetParams(); + CheckControlsEnable(); + SetArchiveName2(isSFX); + SetEncryptionMethod(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_LEVEL: + { + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormatAlways(ai.Name); + NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + fo.ResetForLevelChange(); + SetMethod(GetMethodID()); + SetSolidBlockSize(); + SetNumThreads(); + CheckSFXNameChange(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_METHOD: + { + // MessageBoxW(*this, L"IDC_COMPRESS_METHOD!", L"7-Zip", MB_ICONERROR); + if (GetMethodID() == kZSTD) + { + SetLevel_zstd(); + } else { + SetLevel_default(); + } + SetDictionary(); + SetOrder(); + SetSolidBlockSize(); + SetNumThreads(); + CheckSFXNameChange(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_DICTIONARY: + case IDC_COMPRESS_ORDER: + { + SetSolidBlockSize(); + SetMemoryUsage(); + return true; + } + case IDC_COMPRESS_THREADS: + { + SetMemoryUsage(); + return true; + } + } + } + return CModalDialog::OnCommand(code, itemID, lParam); +} + +void CCompressDialog::CheckSFXNameChange() +{ + bool isSFX = IsSFX(); + CheckSFXControlsEnable(); + if (isSFX != IsSFX()) + SetArchiveName2(isSFX); +} + +void CCompressDialog::SetArchiveName2(bool prevWasSFX) +{ + UString fileName; + m_ArchivePath.GetText(fileName); + const CArcInfoEx &prevArchiverInfo = (*ArcFormats)[m_PrevFormat]; + if (prevArchiverInfo.Flags_KeepName() || Info.KeepName) + { + UString prevExtension; + if (prevWasSFX) + prevExtension = kExeExt; + else + prevExtension = UString(L'.') + prevArchiverInfo.GetMainExt(); + const unsigned prevExtensionLen = prevExtension.Len(); + if (fileName.Len() >= prevExtensionLen) + if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension)) + fileName.DeleteFrom(fileName.Len() - prevExtensionLen); + } + SetArchiveName(fileName); +} + +// if type.KeepName then use OriginalFileName +// else if !KeepName remove extension +// add new extension + +void CCompressDialog::SetArchiveName(const UString &name) +{ + UString fileName = name; + Info.FormatIndex = GetFormatIndex(); + const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; + m_PrevFormat = Info.FormatIndex; + if (ai.Flags_KeepName()) + { + fileName = OriginalFileName; + } + else + { + if (!Info.KeepName) + { + int dotPos = GetExtDotPos(fileName); + if (dotPos >= 0) + fileName.DeleteFrom(dotPos); + } + } + + if (IsSFX()) + fileName += kExeExt; + else + { + fileName += L'.'; + fileName += ai.GetMainExt(); + } + m_ArchivePath.SetText(fileName); +} + +int CCompressDialog::FindRegistryFormat(const UString &name) +{ + FOR_VECTOR (i, m_RegistryInfo.Formats) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i]; + if (name.IsEqualTo_NoCase(GetUnicodeString(fo.FormatID))) + return i; + } + return -1; +} + +int CCompressDialog::FindRegistryFormatAlways(const UString &name) +{ + int index = FindRegistryFormat(name); + if (index < 0) + { + NCompression::CFormatOptions fo; + fo.FormatID = GetSystemString(name); + index = m_RegistryInfo.Formats.Add(fo); + } + return index; +} + +int CCompressDialog::GetStaticFormatIndex() +{ + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++) + if (ai.Name.IsEqualTo_NoCase(g_Formats[i].Name)) + return i; + return 0; // -1; +} + +void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value) +{ + for (int i = comboBox.GetCount() - 1; i >= 0; i--) + if ((UInt32)comboBox.GetItemData(i) <= value) + { + comboBox.SetCurSel(i); + return; + } + if (comboBox.GetCount() > 0) + comboBox.SetCurSel(0); +} + +void CCompressDialog::SetLevel_zstd() +{ + UInt32 level = GetLevel2(); + + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + { + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Level <= 22) + level = fo.Level; + } + } + + /* ZStandard has 22 levels */ + m_Level.ResetContent(); + for (unsigned i = 0; i <= 22; i++) + { + TCHAR s[40]; + TCHAR t[50] = { TEXT('L'), TEXT('e'), TEXT('v'), TEXT('e'), TEXT('l'), TEXT(' '), 0 }; + ConvertUInt32ToString(i, s); + lstrcat(t, s); + switch (i) { + case 0: + lstrcat(t, TEXT(" (")); + lstrcat(t, LangString(IDS_METHOD_STORE)); + lstrcat(t, TEXT(")")); + break; + case 1: + lstrcat(t, TEXT(" (")); + lstrcat(t, LangString(IDS_METHOD_FASTEST)); + lstrcat(t, TEXT(")")); + break; + case 5: + lstrcat(t, TEXT(" (")); + lstrcat(t, LangString(IDS_METHOD_FAST)); + lstrcat(t, TEXT(")")); + break; + case 11: + lstrcat(t, TEXT(" (")); + lstrcat(t, LangString(IDS_METHOD_NORMAL)); + lstrcat(t, TEXT(")")); + break; + case 17: + lstrcat(t, TEXT(" (")); + lstrcat(t, LangString(IDS_METHOD_MAXIMUM)); + lstrcat(t, TEXT(")")); + break; + case 22: + lstrcat(t, TEXT(" (")); + lstrcat(t, LangString(IDS_METHOD_ULTRA)); + lstrcat(t, TEXT(")")); + break; + } + int index = (int)m_Level.AddString(t); + m_Level.SetItemData(index, i); + } + + SetNearestSelectComboBox(m_Level, level); + return; +} + +void CCompressDialog::SetLevel_default() +{ + UInt32 level = GetLevel2(); + + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + { + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Level <= 9) + level = fo.Level; + else + level = 9; + } + } + + /* 9 default levels */ + m_Level.ResetContent(); + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + + for (unsigned i = 0; i <= 9; i++) + { + if ((fi.LevelsMask & (1 << i)) != 0) + { + TCHAR s[40]; + TCHAR t[50] = { TEXT('L'), TEXT('e'), TEXT('v'), TEXT('e'), TEXT('l'), TEXT(' '), 0 }; + UInt32 langID = g_Levels[i]; + ConvertUInt32ToString(i, s); + lstrcat(t, s); + lstrcat(t, TEXT(" (")); + lstrcat(t, LangString(langID)); + lstrcat(t, TEXT(")")); + int index = (int)m_Level.AddString(t); + m_Level.SetItemData(index, i); + } + } + + SetNearestSelectComboBox(m_Level, level); + return; +} + +void CCompressDialog::SetLevel() +{ + SetMethod(); + + if (GetMethodID() == kZSTD) + { + SetLevel_zstd(); + } else { + SetLevel_default(); + } +} + +void CCompressDialog::SetMethod(int keepMethodId) +{ + m_Method.ResetContent(); + UInt32 level = GetLevel2(); + if (level == 0) + { + SetDictionary(); + SetOrder(); + return; + } + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + UString defaultMethod; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + defaultMethod = fo.Method; + } + bool isSfx = IsSFX(); + bool weUseSameMethod = false; + + for (unsigned m = 0; m < fi.NumMethods; m++) + { + EMethodID methodID = fi.MethodIDs[m]; + if (isSfx) + if (!IsMethodSupportedBySfx(methodID)) + continue; + const LPCWSTR method = kMethodsNames[methodID]; + int itemIndex = (int)m_Method.AddString(GetSystemString(method)); + m_Method.SetItemData(itemIndex, methodID); + + + if (keepMethodId == methodID) + { + m_Method.SetCurSel(itemIndex); + weUseSameMethod = true; + continue; + } + + if ((defaultMethod.IsEqualTo_NoCase(method) || m == 0) && !weUseSameMethod) + m_Method.SetCurSel(itemIndex); + } + + if (!weUseSameMethod) + { + SetDictionary(); + SetOrder(); + } +} + +bool CCompressDialog::IsZipFormat() +{ + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + return ai.Name.IsEqualTo_Ascii_NoCase("zip"); +} + +void CCompressDialog::SetEncryptionMethod() +{ + _encryptionMethod.ResetContent(); + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + if (ai.Name.IsEqualTo_Ascii_NoCase("7z")) + { + _encryptionMethod.AddString(TEXT("AES-256")); + _encryptionMethod.SetCurSel(0); + } + else if (ai.Name.IsEqualTo_Ascii_NoCase("zip")) + { + int index = FindRegistryFormat(ai.Name); + UString encryptionMethod; + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + encryptionMethod = fo.EncryptionMethod; + } + _encryptionMethod.AddString(TEXT("ZipCrypto")); + _encryptionMethod.AddString(TEXT("AES-256")); + _encryptionMethod.SetCurSel(encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0); + } +} + +int CCompressDialog::GetMethodID() +{ + if (m_Method.GetCount() <= 0) + return -1; + return (int)(UInt32)m_Method.GetItemData_of_CurSel(); +} + +UString CCompressDialog::GetMethodSpec() +{ + if (m_Method.GetCount() <= 1) + return UString(); + return kMethodsNames[GetMethodID()]; +} + +UString CCompressDialog::GetEncryptionMethodSpec() +{ + if (_encryptionMethod.GetCount() <= 1) + return UString(); + if (_encryptionMethod.GetCurSel() <= 0) + return UString(); + UString result; + _encryptionMethod.GetText(result); + result.RemoveChar(L'-'); + return result; +} + +void CCompressDialog::AddDictionarySize(UInt32 size) +{ + Byte c = 0; + unsigned moveBits = 0; + if ((size & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; } + else if ((size & 0x3FF) == 0) { moveBits = 10; c = 'K'; } + TCHAR s[40]; + ConvertUInt32ToString(size >> moveBits, s); + unsigned pos = MyStringLen(s); + s[pos++] = ' '; + if (moveBits != 0) + s[pos++] = c; + s[pos++] = 'B'; + s[pos++] = 0; + int index = (int)m_Dictionary.AddString(s); + m_Dictionary.SetItemData(index, size); +} + +void CCompressDialog::SetDictionary() +{ + m_Dictionary.ResetContent(); + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + UInt32 defaultDict = (UInt32)(Int32)-1; + + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) + defaultDict = fo.Dictionary; + } + + int methodID = GetMethodID(); + UInt32 level = GetLevel2(); + if (methodID < 0) + return; + UInt64 maxRamSize; + bool maxRamSize_Defined = GetMaxRamSizeForProgram(maxRamSize); + + switch (methodID) + { + case kLZMA: + case kLZMA2: + { + static const UInt32 kMinDicSize = (1 << 16); + if (defaultDict == (UInt32)(Int32)-1) + { + if (level >= 9) defaultDict = (1 << 26); + else if (level >= 7) defaultDict = (1 << 25); + else if (level >= 5) defaultDict = (1 << 24); + else if (level >= 3) defaultDict = (1 << 20); + else defaultDict = (kMinDicSize); + } + + AddDictionarySize(kMinDicSize); + m_Dictionary.SetCurSel(0); + + for (unsigned i = 20; i <= 31; i++) + for (unsigned j = 0; j < 2; j++) + { + if (i == 20 && j > 0) + continue; + UInt32 dict = ((UInt32)(2 + j) << (i - 1)); + + if (dict > + #ifdef MY_CPU_64BIT + (3 << 29) + #else + (1 << 26) + #endif + ) + continue; + + AddDictionarySize(dict); + UInt64 decomprSize; + UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); + if (dict <= defaultDict && (!maxRamSize_Defined || requiredComprSize <= maxRamSize)) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + + // SetNearestSelectComboBox(m_Dictionary, defaultDict); + break; + } + + case kPPMd: + { + if (defaultDict == (UInt32)(Int32)-1) + { + if (level >= 9) defaultDict = (192 << 20); + else if (level >= 7) defaultDict = ( 64 << 20); + else if (level >= 5) defaultDict = ( 16 << 20); + else defaultDict = ( 4 << 20); + } + + for (unsigned i = 20; i < 31; i++) + for (unsigned j = 0; j < 2; j++) + { + if (i == 20 && j > 0) + continue; + UInt32 dict = ((UInt32)(2 + j) << (i - 1)); + if (dict > + #ifdef MY_CPU_64BIT + (1 << 30) + #else + (1 << 29) + #endif + ) + continue; + AddDictionarySize(dict); + UInt64 decomprSize; + UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); + if ((dict <= defaultDict && (!maxRamSize_Defined || requiredComprSize <= maxRamSize)) + || m_Dictionary.GetCount() == 1) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + + // SetNearestSelectComboBox(m_Dictionary, defaultDict); + break; + } + + case kDeflate: + { + AddDictionarySize(32 << 10); + m_Dictionary.SetCurSel(0); + break; + } + + case kDeflate64: + { + AddDictionarySize(64 << 10); + m_Dictionary.SetCurSel(0); + break; + } + + case kBZip2: + { + if (defaultDict == (UInt32)(Int32)-1) + { + if (level >= 5) defaultDict = (900 << 10); + else if (level >= 3) defaultDict = (500 << 10); + else defaultDict = (100 << 10); + } + + for (unsigned i = 1; i <= 9; i++) + { + UInt32 dict = ((UInt32)i * 100) << 10; + AddDictionarySize(dict); + if (dict <= defaultDict || m_Dictionary.GetCount() == 0) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + + break; + } + + case kPPMdZip: + { + if (defaultDict == (UInt32)(Int32)-1) + defaultDict = (1 << (19 + (level > 8 ? 8 : level))); + + for (unsigned i = 20; i <= 28; i++) + { + UInt32 dict = (1 << i); + AddDictionarySize(dict); + UInt64 decomprSize; + UInt64 requiredComprSize = GetMemoryUsage(dict, decomprSize); + if ((dict <= defaultDict && (!maxRamSize_Defined || requiredComprSize <= maxRamSize)) + || m_Dictionary.GetCount() == 1) + m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1); + } + + // SetNearestSelectComboBox(m_Dictionary, defaultDict); + break; + } + + } +} + +UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax) +{ + if (c.GetCount() <= defMax) + return (UInt32)(Int32)-1; + return (UInt32)c.GetItemData_of_CurSel(); +} + +UInt32 CCompressDialog::GetLevel2() +{ + UInt32 level = GetLevel(); + if (level == (UInt32)(Int32)-1) + level = 5; + return level; +} + +int CCompressDialog::AddOrder(UInt32 size) +{ + TCHAR s[40]; + ConvertUInt32ToString(size, s); + int index = (int)m_Order.AddString(s); + m_Order.SetItemData(index, size); + return index; +} + +void CCompressDialog::SetOrder() +{ + m_Order.ResetContent(); + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + UInt32 defaultOrder = (UInt32)(Int32)-1; + + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) + defaultOrder = fo.Order; + } + + int methodID = GetMethodID(); + UInt32 level = GetLevel2(); + if (methodID < 0) + return; + + switch (methodID) + { + case kLZMA: + case kLZMA2: + { + if (defaultOrder == (UInt32)(Int32)-1) + defaultOrder = (level >= 7) ? 64 : 32; + for (unsigned i = 3; i <= 8; i++) + for (unsigned j = 0; j < 2; j++) + { + UInt32 order = ((UInt32)(2 + j) << (i - 1)); + if (order <= 256) + AddOrder(order); + } + AddOrder(273); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + + case kPPMd: + { + if (defaultOrder == (UInt32)(Int32)-1) + { + if (level >= 9) defaultOrder = 32; + else if (level >= 7) defaultOrder = 16; + else if (level >= 5) defaultOrder = 6; + else defaultOrder = 4; + } + + AddOrder(2); + AddOrder(3); + + for (unsigned i = 2; i < 8; i++) + for (unsigned j = 0; j < 4; j++) + { + UInt32 order = (4 + j) << (i - 2); + if (order < 32) + AddOrder(order); + } + + AddOrder(32); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + + case kDeflate: + case kDeflate64: + { + if (defaultOrder == (UInt32)(Int32)-1) + { + if (level >= 9) defaultOrder = 128; + else if (level >= 7) defaultOrder = 64; + else defaultOrder = 32; + } + + for (unsigned i = 3; i <= 8; i++) + for (unsigned j = 0; j < 2; j++) + { + UInt32 order = ((UInt32)(2 + j) << (i - 1));; + if (order <= 256) + AddOrder(order); + } + + AddOrder(methodID == kDeflate64 ? 257 : 258); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + + case kBZip2: + break; + + case kPPMdZip: + { + if (defaultOrder == (UInt32)(Int32)-1) + defaultOrder = level + 3; + for (unsigned i = 2; i <= 16; i++) + AddOrder(i); + SetNearestSelectComboBox(m_Order, defaultOrder); + break; + } + } +} + +bool CCompressDialog::GetOrderMode() +{ + switch (GetMethodID()) + { + case kPPMd: + case kPPMdZip: + return true; + } + return false; +} + +static const UInt32 kNoSolidBlockSize = 0; +static const UInt32 kSolidBlockSize = 64; + +void CCompressDialog::SetSolidBlockSize() +{ + m_Solid.ResetContent(); + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + if (!fi.Solid) + return; + + UInt32 level = GetLevel2(); + if (level == 0) + return; + + UInt32 dict = GetDictionarySpec(); + if (dict == (UInt32)(Int32)-1) + dict = 1; + + UInt32 defaultBlockSize = (UInt32)(Int32)-1; + + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + { + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec())) + defaultBlockSize = fo.BlockLogSize; + } + } + + { + int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID)); + m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize); + m_Solid.SetCurSel(0); + } + + bool needSet = (defaultBlockSize == (UInt32)(Int32)-1); + + for (unsigned i = 20; i <= 36; i++) + { + if (needSet && dict >= (((UInt64)1 << (i - 7))) && i <= 32) + defaultBlockSize = i; + TCHAR s[40]; + ConvertUInt32ToString(1 << (i % 10), s); + if (i < 30) lstrcat(s, TEXT(" M")); + else lstrcat(s, TEXT(" G")); + lstrcat(s, TEXT("B")); + int index = (int)m_Solid.AddString(s); + m_Solid.SetItemData(index, (UInt32)i); + } + + { + int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID)); + m_Solid.SetItemData(index, kSolidBlockSize); + } + + if (defaultBlockSize == (UInt32)(Int32)-1) + defaultBlockSize = kSolidBlockSize; + if (defaultBlockSize != kNoSolidBlockSize) + SetNearestSelectComboBox(m_Solid, defaultBlockSize); +} + +void CCompressDialog::SetNumThreads() +{ + m_NumThreads.ResetContent(); + + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + if (!fi.MultiThread) + return; + + UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors(); + UInt32 defaultValue = numHardwareThreads; + + { + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + if (fo.Method.IsEqualTo_NoCase(GetMethodSpec()) && fo.NumThreads != (UInt32)(Int32)-1) + defaultValue = fo.NumThreads; + } + } + + UInt32 numAlgoThreadsMax = 1; + int methodID = GetMethodID(); + switch (methodID) + { + case kLZMA: numAlgoThreadsMax = 2; break; + case kLZMA2: numAlgoThreadsMax = 32; break; + case kBZip2: numAlgoThreadsMax = 32; break; + } + if (IsZipFormat()) + numAlgoThreadsMax = 128; + for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++) + { + TCHAR s[40]; + ConvertUInt32ToString(i, s); + int index = (int)m_NumThreads.AddString(s); + m_NumThreads.SetItemData(index, (UInt32)i); + } + SetNearestSelectComboBox(m_NumThreads, defaultValue); +} + +UInt64 CCompressDialog::GetMemoryUsage(UInt32 dict, UInt64 &decompressMemory) +{ + decompressMemory = UInt64(Int64(-1)); + UInt32 level = GetLevel2(); + if (level == 0) + { + decompressMemory = (1 << 20); + return decompressMemory; + } + UInt64 size = 0; + + const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()]; + if (fi.Filter && level >= 9) + size += (12 << 20) * 2 + (5 << 20); + UInt32 numThreads = GetNumThreads2(); + + if (IsZipFormat()) + { + UInt32 numSubThreads = 1; + if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5) + numSubThreads = 2; + UInt32 numMainThreads = numThreads / numSubThreads; + if (numMainThreads > 1) + size += (UInt64)numMainThreads << 25; + } + + int methidId = GetMethodID(); + + switch (methidId) + { + case kLZMA: + case kLZMA2: + { + UInt32 hs = dict - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + hs++; + UInt64 size1 = (UInt64)hs * 4; + size1 += (UInt64)dict * 4; + if (level >= 5) + size1 += (UInt64)dict * 4; + size1 += (2 << 20); + + UInt32 numThreads1 = 1; + if (numThreads > 1 && level >= 5) + { + size1 += (2 << 20) + (4 << 20); + numThreads1 = 2; + } + + UInt32 numBlockThreads = numThreads / numThreads1; + + if (methidId == kLZMA || numBlockThreads == 1) + size1 += (UInt64)dict * 3 / 2; + else + { + UInt64 chunkSize = (UInt64)dict << 2; + chunkSize = MyMax(chunkSize, (UInt64)(1 << 20)); + chunkSize = MyMin(chunkSize, (UInt64)(1 << 28)); + chunkSize = MyMax(chunkSize, (UInt64)dict); + size1 += chunkSize * 2; + } + size += size1 * numBlockThreads; + + decompressMemory = dict + (2 << 20); + return size; + } + + case kPPMd: + { + decompressMemory = dict + (2 << 20); + return size + decompressMemory; + } + + case kZSTD: + { + /* Code Snippet for CPP/7zip/UI/GUI/CompressDialog.cpp with blocklen=4194304 */ + size = 0; + switch (level) { + case 1: size = 1086412; decompressMemory = 677160; return size; + case 2: size = 1283020; decompressMemory = 677160; return size; + case 3: size = 2855884; decompressMemory = 1201448; return size; + case 4: size = 2102220; decompressMemory = 1201448; return size; + case 5: size = 2724812; decompressMemory = 1201448; return size; + case 6: size = 4953036; decompressMemory = 2250024; return size; + case 7: size = 7312332; decompressMemory = 2250024; return size; + case 8: size = 7836620; decompressMemory = 2250024; return size; + case 9: size = 10982348; decompressMemory = 2250024; return size; + case 10: size = 13079500; decompressMemory = 2250024; return size; + case 11: size = 25662412; decompressMemory = 4347176; return size; + case 12: size = 25662412; decompressMemory = 4347176; return size; + case 13: size = 29856716; decompressMemory = 4347176; return size; + case 14: size = 29856716; decompressMemory = 4347176; return size; + case 15: size = 21468108; decompressMemory = 4347176; return size; + case 16: size = 38245324; decompressMemory = 4347176; return size; + case 17: size = 55022540; decompressMemory = 4347176; return size; + case 18: size = 55171528; decompressMemory = 4347176; return size; + case 19: size = 55815954; decompressMemory = 4347176; return size; + case 20: size = 55815954; decompressMemory = 4347176; return size; + case 21: size = 55815954; decompressMemory = 4347176; return size; + case 22: size = 55815954; decompressMemory = 4347176; return size; + } + decompressMemory = 0; + return size; + } + + case kDeflate: + case kDeflate64: + { + UInt32 order = GetOrder(); + if (order == (UInt32)(Int32)-1) + order = 32; + if (level >= 7) + size += (1 << 20); + size += 3 << 20; + decompressMemory = (2 << 20); + return size; + } + + case kBZip2: + { + decompressMemory = (7 << 20); + UInt64 memForOneThread = (10 << 20); + return size + memForOneThread * numThreads; + } + + case kPPMdZip: + { + decompressMemory = dict + (2 << 20); + return size + (UInt64)decompressMemory * numThreads; + } + } + + return (UInt64)(Int64)-1; +} + +UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory) +{ + return GetMemoryUsage(GetDictionary(), decompressMemory); +} + +void CCompressDialog::PrintMemUsage(UINT res, UInt64 value) +{ + if (value == (UInt64)(Int64)-1) + { + SetItemText(res, TEXT("?")); + return; + } + value = (value + (1 << 20) - 1) >> 20; + TCHAR s[40]; + ConvertUInt64ToString(value, s); + lstrcat(s, TEXT(" MB")); + SetItemText(res, s); +} + +void CCompressDialog::SetMemoryUsage() +{ + UInt64 decompressMem; + UInt64 memUsage = GetMemoryUsage(decompressMem); + PrintMemUsage(IDT_COMPRESS_MEMORY_VALUE, memUsage); + PrintMemUsage(IDT_COMPRESS_MEMORY_DE_VALUE, decompressMem); +} + +void CCompressDialog::SetParams() +{ + const CArcInfoEx &ai = (*ArcFormats)[GetFormatIndex()]; + m_Params.SetText(TEXT("")); + int index = FindRegistryFormat(ai.Name); + if (index >= 0) + { + const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + m_Params.SetText(fo.Options); + } +} + +void CCompressDialog::SaveOptionsInMem() +{ + const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex]; + int index = FindRegistryFormatAlways(ai.Name); + m_Params.GetText(Info.Options); + Info.Options.Trim(); + NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index]; + fo.Options = Info.Options; + fo.Level = GetLevelSpec(); + fo.Dictionary = GetDictionarySpec(); + fo.Order = GetOrderSpec(); + fo.Method = GetMethodSpec(); + fo.EncryptionMethod = GetEncryptionMethodSpec(); + fo.NumThreads = GetNumThreadsSpec(); + fo.BlockLogSize = GetBlockSizeSpec(); +} + +unsigned CCompressDialog::GetFormatIndex() +{ + return (unsigned)m_Format.GetItemData_of_CurSel(); +}