mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 17:15:00 -06:00
3821 lines
92 KiB
C++
Executable File
3821 lines
92 KiB
C++
Executable File
// 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 "../../Common/MethodProps.h"
|
|
|
|
#include "../FileManager/BrowseDialog.h"
|
|
#include "../FileManager/FormatUtils.h"
|
|
#include "../FileManager/HelpUtils.h"
|
|
#include "../FileManager/PropertyName.h"
|
|
#include "../FileManager/SplitUtils.h"
|
|
|
|
#include "../Explorer/MyMessages.h"
|
|
|
|
#include "../Common/ZipRegistry.h"
|
|
|
|
#include "CompressDialog.h"
|
|
|
|
#ifndef _UNICODE
|
|
extern bool g_IsNT;
|
|
#endif
|
|
|
|
#include "../FileManager/LangUtils.h"
|
|
|
|
#include "CompressDialogRes.h"
|
|
#include "ExtractRes.h"
|
|
#include "resource2.h"
|
|
|
|
// #define PRINT_PARAMS
|
|
|
|
#ifdef Z7_LANG
|
|
|
|
// #define IDS_OPTIONS 2100
|
|
|
|
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,
|
|
|
|
IDB_COMPRESS_OPTIONS, // IDS_OPTIONS
|
|
|
|
IDG_COMPRESS_OPTIONS,
|
|
IDX_COMPRESS_SFX,
|
|
IDX_COMPRESS_SHARED,
|
|
IDX_COMPRESS_DEL,
|
|
|
|
IDT_COMPRESS_MEMORY,
|
|
IDT_COMPRESS_MEMORY_DE,
|
|
|
|
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 const UInt32 kSolidLog_NoSolid = 0;
|
|
static const UInt32 kSolidLog_FullSolid = 64;
|
|
|
|
static const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28;
|
|
|
|
static const UINT k_Message_ArcChanged = WM_APP + 1;
|
|
|
|
/*
|
|
static const UInt32 kZstd_MAX_DictSize = (UInt32)1 << MY_ZSTD_WINDOWLOG_MAX;
|
|
*/
|
|
|
|
/* The top value for windowLog_Chain:
|
|
(MY_ZSTD_CHAINLOG_MAX - 1): in BT mode
|
|
(MY_ZSTD_CHAINLOG_MAX) : in non-BT mode. But such big value is useless in most cases.
|
|
So we always reduce top value to (MY_ZSTD_CHAINLOG_MAX - 1) */
|
|
/*
|
|
static const unsigned kMaxDictChain = MY_ZSTD_CHAINLOG_MAX - 1;
|
|
static const UInt32 kZstd_MAX_DictSize_Chain = (UInt32)1 << kMaxDictChain;
|
|
*/
|
|
|
|
static LPCSTR const kExeExt = ".exe";
|
|
|
|
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,
|
|
kLZMA,
|
|
kLZMA2,
|
|
kPPMd,
|
|
kBZip2,
|
|
kDeflate,
|
|
kDeflate64,
|
|
kPPMdZip,
|
|
// kZSTD,
|
|
kSha256,
|
|
kSha1,
|
|
kCrc32,
|
|
kCrc64,
|
|
kGnu,
|
|
kPosix
|
|
};
|
|
|
|
static LPCSTR const kMethodsNames[] =
|
|
{
|
|
"Copy"
|
|
, "LZMA"
|
|
, "LZMA2"
|
|
, "PPMd"
|
|
, "BZip2"
|
|
, "Deflate"
|
|
, "Deflate64"
|
|
, "PPMd"
|
|
// , "ZSTD"
|
|
, "SHA256"
|
|
, "SHA1"
|
|
, "CRC32"
|
|
, "CRC64"
|
|
, "GNU"
|
|
, "POSIX"
|
|
};
|
|
|
|
static const EMethodID g_7zMethods[] =
|
|
{
|
|
kLZMA2,
|
|
kLZMA,
|
|
kPPMd,
|
|
kBZip2
|
|
, kDeflate
|
|
, kDeflate64
|
|
// , kZSTD
|
|
, kCopy
|
|
};
|
|
|
|
static const EMethodID g_7zSfxMethods[] =
|
|
{
|
|
kCopy,
|
|
kLZMA,
|
|
kLZMA2,
|
|
kPPMd
|
|
};
|
|
|
|
static const EMethodID g_ZipMethods[] =
|
|
{
|
|
kDeflate,
|
|
kDeflate64,
|
|
kBZip2,
|
|
kLZMA,
|
|
kPPMdZip
|
|
// , kZSTD
|
|
};
|
|
|
|
static const EMethodID g_GZipMethods[] =
|
|
{
|
|
kDeflate
|
|
};
|
|
|
|
static const EMethodID g_BZip2Methods[] =
|
|
{
|
|
kBZip2
|
|
};
|
|
|
|
static const EMethodID g_XzMethods[] =
|
|
{
|
|
kLZMA2
|
|
};
|
|
|
|
/*
|
|
static const EMethodID g_ZstdMethods[] =
|
|
{
|
|
kZSTD
|
|
};
|
|
*/
|
|
|
|
static const EMethodID g_SwfcMethods[] =
|
|
{
|
|
kDeflate
|
|
// kLZMA
|
|
};
|
|
|
|
static const EMethodID g_TarMethods[] =
|
|
{
|
|
kGnu,
|
|
kPosix
|
|
};
|
|
|
|
static const EMethodID g_HashMethods[] =
|
|
{
|
|
kSha256
|
|
, kSha1
|
|
// , kCrc32
|
|
// , 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;
|
|
|
|
/*
|
|
static const UInt32 kFF_Time_Win = 1 << 10;
|
|
static const UInt32 kFF_Time_Unix = 1 << 11;
|
|
static const UInt32 kFF_Time_DOS = 1 << 12;
|
|
static const UInt32 kFF_Time_1ns = 1 << 13;
|
|
*/
|
|
|
|
struct CFormatInfo
|
|
{
|
|
LPCSTR Name;
|
|
UInt32 LevelsMask;
|
|
unsigned NumMethods;
|
|
const EMethodID *MethodIDs;
|
|
|
|
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) Z7_ARRAY_SIZE(x), x
|
|
|
|
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, NULL,
|
|
kFF_MultiThread | kFF_MemUse
|
|
},
|
|
{
|
|
"7z",
|
|
(1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
|
|
METHODS_PAIR(g_7zMethods),
|
|
kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt |
|
|
kFF_EncryptFileNames | kFF_MemUse | kFF_SFX
|
|
// | kFF_Time_Win
|
|
},
|
|
{
|
|
"Zip",
|
|
(1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
|
|
METHODS_PAIR(g_ZipMethods),
|
|
kFF_MultiThread | kFF_Encrypt | kFF_MemUse
|
|
// | kFF_Time_Win | kFF_Time_Unix | kFF_Time_DOS
|
|
},
|
|
{
|
|
"GZip",
|
|
(1 << 1) | (1 << 5) | (1 << 7) | (1 << 9),
|
|
METHODS_PAIR(g_GZipMethods),
|
|
kFF_MemUse
|
|
// | kFF_Time_Unix
|
|
},
|
|
{
|
|
"BZip2",
|
|
(1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
|
|
METHODS_PAIR(g_BZip2Methods),
|
|
kFF_MultiThread | kFF_MemUse
|
|
},
|
|
{
|
|
"xz",
|
|
(1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
|
|
METHODS_PAIR(g_XzMethods),
|
|
kFF_Solid | kFF_MultiThread | kFF_MemUse
|
|
},
|
|
/*
|
|
{
|
|
"zstd",
|
|
// (1 << (MY_ZSTD_LEVEL_MAX + 1)) - 1,
|
|
(1 << (9 + 1)) - 1,
|
|
METHODS_PAIR(g_ZstdMethods),
|
|
// kFF_Solid |
|
|
kFF_MultiThread
|
|
| kFF_MemUse
|
|
},
|
|
*/
|
|
{
|
|
"Swfc",
|
|
(1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
|
|
METHODS_PAIR(g_SwfcMethods),
|
|
0
|
|
},
|
|
{
|
|
"Tar",
|
|
(1 << 0),
|
|
METHODS_PAIR(g_TarMethods),
|
|
0
|
|
// kFF_Time_Unix | kFF_Time_Win // | kFF_Time_1ns
|
|
},
|
|
{
|
|
"wim",
|
|
(1 << 0),
|
|
0, NULL,
|
|
0
|
|
// | kFF_Time_Win
|
|
},
|
|
{
|
|
"Hash",
|
|
(0 << 0),
|
|
METHODS_PAIR(g_HashMethods),
|
|
0
|
|
}
|
|
};
|
|
|
|
static bool IsMethodSupportedBySfx(int methodID)
|
|
{
|
|
for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_7zSfxMethods); i++)
|
|
if (methodID == g_7zSfxMethods[i])
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
void CCompressDialog::SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs)
|
|
{
|
|
ExternalMethods.Clear();
|
|
{
|
|
FOR_VECTOR (i, userCodecs)
|
|
{
|
|
const CCodecInfoUser &c = userCodecs[i];
|
|
if (!c.EncoderIsAssigned
|
|
|| !c.IsFilter_Assigned
|
|
|| c.IsFilter
|
|
|| c.NumStreams != 1)
|
|
continue;
|
|
unsigned k;
|
|
for (k = 0; k < Z7_ARRAY_SIZE(g_7zMethods); k++)
|
|
if (c.Name.IsEqualTo_Ascii_NoCase(kMethodsNames[g_7zMethods[k]]))
|
|
break;
|
|
if (k != Z7_ARRAY_SIZE(g_7zMethods))
|
|
continue;
|
|
ExternalMethods.Add(c.Name);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool CCompressDialog::OnInit()
|
|
{
|
|
#ifdef Z7_LANG
|
|
LangSetWindowText(*this, IDD_COMPRESS);
|
|
LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
|
|
// LangSetDlgItemText(*this, IDB_COMPRESS_OPTIONS, IDS_OPTIONS); // IDG_COMPRESS_OPTIONS
|
|
#endif
|
|
|
|
{
|
|
UInt64 size = (UInt64)(sizeof(size_t)) << 29;
|
|
_ramSize_Defined = NSystem::GetRamSize(size);
|
|
// size = (UInt64)3 << 62; // for debug only;
|
|
_ramSize = size;
|
|
const UInt64 kMinUseSize = (1 << 26);
|
|
if (size < kMinUseSize)
|
|
size = kMinUseSize;
|
|
|
|
unsigned bits = sizeof(size_t) * 8;
|
|
if (bits == 32)
|
|
{
|
|
const UInt32 limit2 = (UInt32)7 << 28;
|
|
if (size > limit2)
|
|
size = limit2;
|
|
}
|
|
|
|
_ramSize_Reduced = size;
|
|
|
|
// 80% - is auto usage limit in handlers
|
|
_ramUsage_Auto = Calc_From_Val_Percents(size, 80);
|
|
}
|
|
|
|
_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));
|
|
_default_encryptionMethod_Index = -1;
|
|
|
|
m_ArchivePath.Attach(GetItem(IDC_COMPRESS_ARCHIVE));
|
|
m_Format.Attach(GetItem(IDC_COMPRESS_FORMAT)); // that combo has CBS_SORT style in resources
|
|
m_Level.Attach(GetItem(IDC_COMPRESS_LEVEL));
|
|
m_Method.Attach(GetItem(IDC_COMPRESS_METHOD));
|
|
m_Dictionary.Attach(GetItem(IDC_COMPRESS_DICTIONARY));
|
|
|
|
/*
|
|
{
|
|
RECT r;
|
|
GetClientRectOfItem(IDC_COMPRESS_DICTIONARY, r);
|
|
_dictionaryCombo_left = r.left;
|
|
}
|
|
*/
|
|
_dictionaryCombo_left = 0; // 230;
|
|
|
|
// m_Dictionary_Chain.Attach(GetItem(IDC_COMPRESS_DICTIONARY2));
|
|
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));
|
|
|
|
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);
|
|
|
|
UpdatePasswordControl();
|
|
|
|
{
|
|
const bool needSetMain = (Info.FormatIndex < 0);
|
|
FOR_VECTOR(i, ArcIndices)
|
|
{
|
|
const unsigned arcIndex = ArcIndices[i];
|
|
const CArcInfoEx &ai = (*ArcFormats)[arcIndex];
|
|
const int index = (int)m_Format.AddString(ai.Name);
|
|
m_Format.SetItemData(index, (LPARAM)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 = (int)arcIndex;
|
|
}
|
|
}
|
|
}
|
|
|
|
CheckButton(IDX_COMPRESS_SFX, Info.SFXMode);
|
|
|
|
{
|
|
UString fileName;
|
|
SetArcPathFields(Info.ArcPath, fileName, true);
|
|
StartDirPrefix = DirPrefix;
|
|
SetArchiveName(fileName);
|
|
}
|
|
|
|
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, Z7_ARRAY_SIZE(k_UpdateMode_IDs),
|
|
k_UpdateMode_Vals, Info.UpdateMode);
|
|
|
|
AddComboItems(m_PathMode, k_PathMode_IDs, Z7_ARRAY_SIZE(k_PathMode_IDs),
|
|
k_PathMode_Vals, Info.PathMode);
|
|
|
|
|
|
TCHAR s[32] = { TEXT('/'), TEXT(' '), 0 };
|
|
ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
|
|
SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s);
|
|
|
|
CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite);
|
|
CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing);
|
|
|
|
FormatChanged(false); // isChanged
|
|
|
|
// OnButtonSFX();
|
|
|
|
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()
|
|
{
|
|
const bool showPassword = IsShowPasswordChecked();
|
|
const TCHAR c = showPassword ? (TCHAR)0: TEXT('*');
|
|
_password1Control.SetPasswordChar((WPARAM)c);
|
|
_password2Control.SetPasswordChar((WPARAM)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(unsigned 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;
|
|
}
|
|
case IDB_COMPRESS_OPTIONS:
|
|
{
|
|
COptionsDialog dialog(this);
|
|
if (dialog.Create(*this) == IDOK)
|
|
ShowOptionsString();
|
|
return true;
|
|
}
|
|
}
|
|
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
|
|
}
|
|
|
|
void CCompressDialog::CheckSFXControlsEnable()
|
|
{
|
|
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
|
|
bool enable = fi.SFX_();
|
|
if (enable)
|
|
{
|
|
const 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::EnableMultiCombo(unsigned id)
|
|
{
|
|
NWindows::NControl::CComboBox combo;
|
|
combo.Attach(GetItem(id));
|
|
const bool enable = (combo.GetCount() > 1);
|
|
EnableItem(id, enable);
|
|
}
|
|
|
|
static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s);
|
|
|
|
static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res)
|
|
{
|
|
if (!b1.Def && b2.Def)
|
|
res.Val = b2.Val;
|
|
else
|
|
res.Val = b1.Val;
|
|
}
|
|
|
|
#define SET_GUI_BOOL(name) \
|
|
Combine_Two_BoolPairs(Info. name, m_RegistryInfo. name, name)
|
|
|
|
|
|
static void Set_Final_BoolPairs(
|
|
const CBool1 &gui,
|
|
CBoolPair &cmd,
|
|
CBoolPair ®)
|
|
{
|
|
if (!cmd.Def)
|
|
{
|
|
reg.Val = gui.Val;
|
|
reg.Def = gui.Val;
|
|
}
|
|
if (gui.Supported)
|
|
{
|
|
cmd.Val = gui.Val;
|
|
cmd.Def = gui.Val;
|
|
}
|
|
else
|
|
cmd.Init();
|
|
}
|
|
|
|
#define SET_FINAL_BOOL_PAIRS(name) \
|
|
Set_Final_BoolPairs(name, Info. name, m_RegistryInfo. name)
|
|
|
|
void CCompressDialog::FormatChanged(bool isChanged)
|
|
{
|
|
SetLevel();
|
|
SetSolidBlockSize();
|
|
SetParams();
|
|
SetMemUseCombo();
|
|
SetNumThreads();
|
|
|
|
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
|
|
Info.SolidIsSpecified = fi.Solid_();
|
|
Info.EncryptHeadersIsAllowed = fi.EncryptFileNames_();
|
|
|
|
/*
|
|
const bool multiThreadEnable = fi.MultiThread;
|
|
Info.MultiThreadIsAllowed = multiThreadEnable;
|
|
EnableItem(IDC_COMPRESS_SOLID, fi.Solid);
|
|
EnableItem(IDC_COMPRESS_THREADS, multiThreadEnable);
|
|
const bool methodEnable = (fi.MethodIDs != NULL);
|
|
EnableItem(IDC_COMPRESS_METHOD, methodEnable);
|
|
EnableMultiCombo(IDC_COMPRESS_DICTIONARY, methodEnable);
|
|
EnableItem(IDC_COMPRESS_ORDER, methodEnable);
|
|
*/
|
|
|
|
CheckSFXControlsEnable();
|
|
|
|
{
|
|
if (!isChanged)
|
|
{
|
|
SET_GUI_BOOL (SymLinks);
|
|
SET_GUI_BOOL (HardLinks);
|
|
SET_GUI_BOOL (AltStreams);
|
|
SET_GUI_BOOL (NtSecurity);
|
|
SET_GUI_BOOL (PreserveATime);
|
|
}
|
|
|
|
PreserveATime.Supported = true;
|
|
|
|
{
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
SymLinks.Supported = ai.Flags_SymLinks();
|
|
HardLinks.Supported = ai.Flags_HardLinks();
|
|
AltStreams.Supported = ai.Flags_AltStreams();
|
|
NtSecurity.Supported = ai.Flags_NtSecurity();
|
|
}
|
|
|
|
ShowOptionsString();
|
|
}
|
|
// CheckVolumeEnable();
|
|
|
|
const bool encrypt = fi.Encrypt_();
|
|
EnableItem(IDG_COMPRESS_ENCRYPTION, 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, encrypt);
|
|
EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, encrypt);
|
|
EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_());
|
|
|
|
ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_());
|
|
|
|
SetEncryptionMethod();
|
|
SetMemoryUsage();
|
|
}
|
|
|
|
|
|
bool CCompressDialog::IsSFX()
|
|
{
|
|
return IsWindowEnabled(GetItem(IDX_COMPRESS_SFX))
|
|
&& IsButtonCheckedBool(IDX_COMPRESS_SFX);
|
|
}
|
|
|
|
static int GetExtDotPos(const UString &s)
|
|
{
|
|
const int dotPos = s.ReverseFind_Dot();
|
|
if (dotPos > s.ReverseFind_PathSepar() + 1)
|
|
return dotPos;
|
|
return -1;
|
|
}
|
|
|
|
void CCompressDialog::OnButtonSFX()
|
|
{
|
|
UString fileName;
|
|
m_ArchivePath.GetText(fileName);
|
|
const int dotPos = GetExtDotPos(fileName);
|
|
if (IsSFX())
|
|
{
|
|
if (dotPos >= 0)
|
|
fileName.DeleteFrom(dotPos);
|
|
fileName += kExeExt;
|
|
m_ArchivePath.SetText(fileName);
|
|
}
|
|
else
|
|
{
|
|
if (dotPos >= 0)
|
|
{
|
|
const UString ext = fileName.Ptr(dotPos);
|
|
if (ext.IsEqualTo_Ascii_NoCase(kExeExt))
|
|
{
|
|
fileName.DeleteFrom(dotPos);
|
|
m_ArchivePath.SetText(fileName);
|
|
}
|
|
}
|
|
SetArchiveName2(false); // it's for OnInit
|
|
}
|
|
|
|
// CheckVolumeEnable();
|
|
}
|
|
|
|
|
|
bool CCompressDialog::GetFinalPath_Smart(UString &resPath) const
|
|
{
|
|
resPath.Empty();
|
|
UString name;
|
|
m_ArchivePath.GetText(name);
|
|
name.Trim();
|
|
FString fullPath;
|
|
UString dirPrefx = DirPrefix;
|
|
if (dirPrefx.IsEmpty())
|
|
dirPrefx = StartDirPrefix;
|
|
const bool res = !dirPrefx.IsEmpty() ?
|
|
NName::GetFullPath(us2fs(dirPrefx), us2fs(name), fullPath):
|
|
NName::GetFullPath( us2fs(name), fullPath);
|
|
if (res)
|
|
resPath = fs2us(fullPath);
|
|
return res;
|
|
}
|
|
|
|
|
|
bool CCompressDialog::SetArcPathFields(const UString &path)
|
|
{
|
|
UString name;
|
|
return SetArcPathFields(path, name, true); // always
|
|
}
|
|
|
|
|
|
bool CCompressDialog::SetArcPathFields(const UString &path, UString &name, bool always)
|
|
{
|
|
FString resDirPrefix;
|
|
FString resFileName;
|
|
const 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 * const k_IncorrectPathMessage = L"Incorrect archive path";
|
|
|
|
static void AddFilter(CObjectVector<CBrowseFilterInfo> &filters,
|
|
const UString &description, const UString &ext)
|
|
{
|
|
CBrowseFilterInfo &f = filters.AddNew();
|
|
UString mask ("*.");
|
|
mask += ext;
|
|
f.Masks.Add(mask);
|
|
f.Description = description;
|
|
f.Description += " (";
|
|
f.Description += mask;
|
|
f.Description += ")";
|
|
}
|
|
|
|
|
|
static const char * const k_DontSave_Exts =
|
|
"xpi odt ods docx xlsx ";
|
|
|
|
void CCompressDialog::OnButtonSetArchive()
|
|
{
|
|
UString path;
|
|
if (!GetFinalPath_Smart(path))
|
|
{
|
|
ShowErrorMessage(*this, k_IncorrectPathMessage);
|
|
return;
|
|
}
|
|
|
|
int filterIndex;
|
|
CObjectVector<CBrowseFilterInfo> filters;
|
|
unsigned numFormats = 0;
|
|
|
|
const bool isSFX = IsSFX();
|
|
if (isSFX)
|
|
{
|
|
filterIndex = 0;
|
|
const UString ext ("exe");
|
|
AddFilter(filters, ext, ext);
|
|
}
|
|
else
|
|
{
|
|
filterIndex = m_Format.GetCurSel();
|
|
numFormats = (unsigned)m_Format.GetCount();
|
|
|
|
// filters [0, ... numFormats - 1] corresponds to items in m_Format combo
|
|
UString desc;
|
|
UStringVector masks;
|
|
CStringFinder finder;
|
|
|
|
for (unsigned i = 0; i < numFormats; i++)
|
|
{
|
|
const CArcInfoEx &ai = (*ArcFormats)[(unsigned)m_Format.GetItemData(i)];
|
|
CBrowseFilterInfo &f = filters.AddNew();
|
|
f.Description = ai.Name;
|
|
f.Description += " (";
|
|
bool needSpace_desc = false;
|
|
|
|
FOR_VECTOR (k, ai.Exts)
|
|
{
|
|
const UString &ext = ai.Exts[k].Ext;
|
|
UString mask ("*.");
|
|
mask += ext;
|
|
|
|
if (finder.FindWord_In_LowCaseAsciiList_NoCase(k_DontSave_Exts, ext))
|
|
continue;
|
|
|
|
f.Masks.Add(mask);
|
|
masks.Add(mask);
|
|
if (needSpace_desc)
|
|
f.Description.Add_Space();
|
|
needSpace_desc = true;
|
|
f.Description += ext;
|
|
}
|
|
f.Description += ")";
|
|
// we use only main ext in desc to reduce the size of list
|
|
if (i != 0)
|
|
desc.Add_Space();
|
|
desc += ai.GetMainExt();
|
|
}
|
|
|
|
CBrowseFilterInfo &f = filters.AddNew();
|
|
f.Description = LangString(IDT_COMPRESS_ARCHIVE); // IDS_ARCHIVES_COLON;
|
|
if (f.Description.IsEmpty())
|
|
GetItemText(IDT_COMPRESS_ARCHIVE, f.Description);
|
|
f.Description.RemoveChar(L'&');
|
|
// f.Description = "archive";
|
|
f.Description += " (";
|
|
f.Description += desc;
|
|
f.Description += ")";
|
|
f.Masks = masks;
|
|
}
|
|
|
|
AddFilter(filters, LangString(IDS_OPEN_TYPE_ALL_FILES), UString("*"));
|
|
if (filterIndex < 0)
|
|
filterIndex = (int)filters.Size() - 1;
|
|
|
|
const UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_BROWSE);
|
|
CBrowseInfo bi;
|
|
bi.lpstrTitle = title;
|
|
bi.SaveMode = true;
|
|
bi.FilterIndex = filterIndex;
|
|
bi.hwndOwner = *this;
|
|
bi.FilePath = path;
|
|
|
|
if (!bi.BrowseForFile(filters))
|
|
return;
|
|
|
|
path = bi.FilePath;
|
|
|
|
if (isSFX)
|
|
{
|
|
const int dotPos = GetExtDotPos(path);
|
|
if (dotPos >= 0)
|
|
path.DeleteFrom(dotPos);
|
|
path += kExeExt;
|
|
}
|
|
else
|
|
// if (bi.FilterIndex >= 0)
|
|
// if (bi.FilterIndex != filterIndex)
|
|
if ((unsigned)bi.FilterIndex < numFormats)
|
|
{
|
|
// archive format was confirmed. So we try to set format extension
|
|
bool needAddExt = true;
|
|
const CArcInfoEx &ai = (*ArcFormats)[(unsigned)m_Format.GetItemData((unsigned)bi.FilterIndex)];
|
|
const int dotPos = GetExtDotPos(path);
|
|
if (dotPos >= 0)
|
|
{
|
|
const UString ext = path.Ptr(dotPos + 1);
|
|
if (ai.FindExtension(ext) >= 0)
|
|
needAddExt = false;
|
|
}
|
|
if (needAddExt)
|
|
{
|
|
if (path.IsEmpty() || path.Back() != '.')
|
|
path.Add_Dot();
|
|
path += ai.GetMainExt();
|
|
}
|
|
}
|
|
|
|
SetArcPathFields(path);
|
|
|
|
if (!isSFX)
|
|
if ((unsigned)bi.FilterIndex < numFormats)
|
|
if (bi.FilterIndex != m_Format.GetCurSel())
|
|
{
|
|
m_Format.SetCurSel(bi.FilterIndex);
|
|
SaveOptionsInMem();
|
|
FormatChanged(true); // isChanged
|
|
return;
|
|
}
|
|
|
|
ArcPath_WasChanged(path);
|
|
}
|
|
|
|
|
|
// 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++)
|
|
{
|
|
const wchar_t c = s[i];
|
|
if (c < 0x20 || c > 0x7F)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
static void AddSize_MB(UString &s, UInt64 size)
|
|
{
|
|
const UInt64 v2 = size + ((UInt32)1 << 20) - 1;
|
|
if (size <= v2)
|
|
size = v2;
|
|
s.Add_UInt64(size >> 20);
|
|
s += " MB";
|
|
}
|
|
|
|
|
|
void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString);
|
|
void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString)
|
|
{
|
|
s += "The operation was blocked by 7-Zip";
|
|
s.Add_LF();
|
|
s += "The operation can require big amount of RAM (memory):";
|
|
s.Add_LF();
|
|
s.Add_LF();
|
|
AddSize_MB(s, reqSize);
|
|
|
|
if (!usageString.IsEmpty())
|
|
{
|
|
s += " : ";
|
|
s += usageString;
|
|
}
|
|
|
|
s.Add_LF();
|
|
AddSize_MB(s, ramSize);
|
|
s += " : RAM";
|
|
|
|
// if (ramLimit != 0)
|
|
{
|
|
s.Add_LF();
|
|
AddSize_MB(s, ramLimit);
|
|
s += " : 7-Zip limit";
|
|
}
|
|
|
|
s.Add_LF();
|
|
s.Add_LF();
|
|
AddLangString(s, IDS_MEM_ERROR);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
{
|
|
UInt64 decompressMem;
|
|
const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem);
|
|
if (memUsage != (UInt64)(Int64)-1)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
SaveOptionsInMem();
|
|
|
|
UStringVector arcPaths;
|
|
{
|
|
UString s;
|
|
if (!GetFinalPath_Smart(s))
|
|
{
|
|
ShowErrorMessage(*this, k_IncorrectPathMessage);
|
|
return;
|
|
}
|
|
Info.ArcPath = s;
|
|
AddUniqueString(arcPaths, 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.Dict64 = GetDictSpec();
|
|
// Info.Dict64_Chain = GetDictChainSpec();
|
|
Info.Order = GetOrderSpec();
|
|
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();
|
|
Info.SolidBlockSize = 0;
|
|
if (solidLogSize == (UInt32)(Int32)-1)
|
|
Info.SolidIsSpecified = false;
|
|
else if (solidLogSize > 0)
|
|
Info.SolidBlockSize = (solidLogSize >= 64) ?
|
|
(UInt64)(Int64)-1 :
|
|
((UInt64)1 << solidLogSize);
|
|
}
|
|
|
|
Info.Method = GetMethodSpec();
|
|
Info.EncryptionMethod = GetEncryptionMethodSpec();
|
|
Info.FormatIndex = (int)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);
|
|
|
|
|
|
/* (Info) is for saving to registry:
|
|
(CBoolPair::Val) will be set as (false), if it was (false)
|
|
in registry at dialog creation, and user didn't click checkbox.
|
|
in another case (CBoolPair::Val) will be set as (true) */
|
|
|
|
{
|
|
/* Info properties could be for another archive types.
|
|
so we disable unsupported properties in Info */
|
|
// const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
|
|
SET_FINAL_BOOL_PAIRS (SymLinks);
|
|
SET_FINAL_BOOL_PAIRS (HardLinks);
|
|
SET_FINAL_BOOL_PAIRS (AltStreams);
|
|
SET_FINAL_BOOL_PAIRS (NtSecurity);
|
|
|
|
SET_FINAL_BOOL_PAIRS (PreserveATime);
|
|
}
|
|
|
|
{
|
|
const NCompression::CFormatOptions &fo = Get_FormatOptions();
|
|
|
|
Info.TimePrec = fo.TimePrec;
|
|
Info.MTime = fo.MTime;
|
|
Info.CTime = fo.CTime;
|
|
Info.ATime = fo.ATime;
|
|
Info.SetArcMTime = fo.SetArcMTime;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Info.FormatIndex >= 0)
|
|
m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name;
|
|
m_RegistryInfo.ShowPassword = IsShowPasswordChecked();
|
|
|
|
FOR_VECTOR (i, m_RegistryInfo.ArcPaths)
|
|
{
|
|
if (arcPaths.Size() >= kHistorySize)
|
|
break;
|
|
AddUniqueString(arcPaths, m_RegistryInfo.ArcPaths[i]);
|
|
}
|
|
m_RegistryInfo.ArcPaths = arcPaths;
|
|
|
|
m_RegistryInfo.Save();
|
|
|
|
CModalDialog::OnOK();
|
|
}
|
|
|
|
#define kHelpTopic "fm/plugins/7-zip/add.htm"
|
|
#define kHelpTopic_Options "fm/plugins/7-zip/add.htm#options"
|
|
|
|
void CCompressDialog::OnHelp()
|
|
{
|
|
ShowHelpWindow(kHelpTopic);
|
|
}
|
|
|
|
|
|
void CCompressDialog::ArcPath_WasChanged(const UString &path)
|
|
{
|
|
const int dotPos = GetExtDotPos(path);
|
|
if (dotPos < 0)
|
|
return;
|
|
const UString ext = path.Ptr(dotPos + 1);
|
|
{
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
if (ai.FindExtension(ext) >= 0)
|
|
return;
|
|
}
|
|
|
|
const unsigned count = (unsigned)m_Format.GetCount();
|
|
for (unsigned i = 0; i < count; i++)
|
|
{
|
|
const CArcInfoEx &ai = (*ArcFormats)[(unsigned)m_Format.GetItemData(i)];
|
|
if (ai.FindExtension(ext) >= 0)
|
|
{
|
|
m_Format.SetCurSel(i);
|
|
SaveOptionsInMem();
|
|
FormatChanged(true); // isChanged
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool CCompressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case k_Message_ArcChanged:
|
|
{
|
|
// UString path;
|
|
// m_ArchivePath.GetText(path);
|
|
const int select = m_ArchivePath.GetCurSel();
|
|
if ((unsigned)select < m_RegistryInfo.ArcPaths.Size())
|
|
// if (path == m_RegistryInfo.ArcPaths[select])
|
|
{
|
|
const UString &path = m_RegistryInfo.ArcPaths[select];
|
|
SetArcPathFields(path);
|
|
// ArcPath_WasChanged(path);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return CModalDialog::OnMessage(message, wParam, lParam);
|
|
}
|
|
|
|
|
|
bool CCompressDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam)
|
|
{
|
|
if (code == CBN_SELCHANGE)
|
|
{
|
|
switch (itemID)
|
|
{
|
|
case IDC_COMPRESS_ARCHIVE:
|
|
{
|
|
/* CBN_SELCHANGE is called before actual value of combo text will be changed.
|
|
So GetText() here returns old value (before change) of combo text.
|
|
So here we can change all controls except of m_ArchivePath.
|
|
*/
|
|
const int select = m_ArchivePath.GetCurSel();
|
|
if ((unsigned)select < m_RegistryInfo.ArcPaths.Size())
|
|
{
|
|
// DirPrefix.Empty();
|
|
// SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix);
|
|
const UString &path = m_RegistryInfo.ArcPaths[select];
|
|
// SetArcPathFields(path);
|
|
ArcPath_WasChanged(path);
|
|
// we use PostMessage(k_Message_ArcChanged) here that later will change m_ArchivePath control
|
|
PostMsg(k_Message_ArcChanged);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
case IDC_COMPRESS_FORMAT:
|
|
{
|
|
const bool isSFX = IsSFX();
|
|
SaveOptionsInMem();
|
|
FormatChanged(true); // isChanged
|
|
SetArchiveName2(isSFX);
|
|
return true;
|
|
}
|
|
|
|
case IDC_COMPRESS_LEVEL:
|
|
{
|
|
Get_FormatOptions().ResetForLevelChange();
|
|
|
|
SetMethod(); // call it if level changes method
|
|
|
|
// call the following if level change keeps old method
|
|
/*
|
|
{
|
|
// try to keep old method
|
|
SetMethod(GetMethodID());
|
|
MethodChanged();
|
|
}
|
|
*/
|
|
|
|
SetSolidBlockSize();
|
|
SetNumThreads();
|
|
CheckSFXNameChange();
|
|
SetMemoryUsage();
|
|
return true;
|
|
}
|
|
|
|
case IDC_COMPRESS_METHOD:
|
|
{
|
|
MethodChanged();
|
|
SetSolidBlockSize();
|
|
SetNumThreads();
|
|
CheckSFXNameChange();
|
|
SetMemoryUsage();
|
|
if (Get_ArcInfoEx().Flags_HashHandler())
|
|
SetArchiveName2(false);
|
|
|
|
return true;
|
|
}
|
|
|
|
case IDC_COMPRESS_DICTIONARY:
|
|
// case IDC_COMPRESS_DICTIONARY2:
|
|
{
|
|
/* we want to change the reported threads for Auto line
|
|
and keep selected NumThreads option
|
|
So we save selected NumThreads option in memory */
|
|
SaveOptionsInMem();
|
|
const UInt32 blockSizeLog = GetBlockSizeSpec();
|
|
if (// blockSizeLog != (UInt32)(Int32)-1 &&
|
|
blockSizeLog != kSolidLog_NoSolid
|
|
&& blockSizeLog != kSolidLog_FullSolid)
|
|
{
|
|
Get_FormatOptions().Reset_BlockLogSize();
|
|
// SetSolidBlockSize(true);
|
|
}
|
|
|
|
SetDictionary2();
|
|
SetSolidBlockSize();
|
|
SetNumThreads(); // we want to change the reported threads for Auto line only
|
|
SetMemoryUsage();
|
|
return true;
|
|
}
|
|
|
|
case IDC_COMPRESS_ORDER:
|
|
{
|
|
#ifdef PRINT_PARAMS
|
|
Print_Params();
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
case IDC_COMPRESS_SOLID:
|
|
{
|
|
SetMemoryUsage();
|
|
return true;
|
|
}
|
|
|
|
case IDC_COMPRESS_THREADS:
|
|
{
|
|
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);
|
|
}
|
|
|
|
void CCompressDialog::CheckSFXNameChange()
|
|
{
|
|
const 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.Add_Dot();
|
|
prevExtension += 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 = (int)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.Add_Dot();
|
|
UString ext = ai.GetMainExt();
|
|
if (ai.Flags_HashHandler())
|
|
{
|
|
UString estimatedName;
|
|
GetMethodSpec(estimatedName);
|
|
if (!estimatedName.IsEmpty())
|
|
{
|
|
ext = estimatedName;
|
|
ext.MakeLower_Ascii();
|
|
}
|
|
}
|
|
fileName += ext;
|
|
}
|
|
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 (int)i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
unsigned CCompressDialog::FindRegistryFormat_Always(const UString &name)
|
|
{
|
|
const int index = FindRegistryFormat(name);
|
|
if (index >= 0)
|
|
return (unsigned)index;
|
|
{
|
|
NCompression::CFormatOptions fo;
|
|
fo.FormatID = GetSystemString(name);
|
|
return m_RegistryInfo.Formats.Add(fo);
|
|
}
|
|
}
|
|
|
|
|
|
NCompression::CFormatOptions &CCompressDialog::Get_FormatOptions()
|
|
{
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
return m_RegistryInfo.Formats[FindRegistryFormat_Always(ai.Name)];
|
|
}
|
|
|
|
|
|
unsigned CCompressDialog::GetStaticFormatIndex()
|
|
{
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Formats); i++)
|
|
if (ai.Name.IsEqualTo_Ascii_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::SetLevel2()
|
|
{
|
|
m_Level.ResetContent();
|
|
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
UInt32 level = 5;
|
|
{
|
|
int index = FindRegistryFormat(ai.Name);
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
if (fo.Level <= 9)
|
|
level = fo.Level;
|
|
else if (fo.Level == (UInt32)(Int32)-1)
|
|
level = 5;
|
|
else
|
|
level = 9;
|
|
}
|
|
}
|
|
|
|
const bool isZstd = ai.Is_Zstd();
|
|
|
|
for (unsigned i = 0; i < sizeof(UInt32) * 8; i++)
|
|
{
|
|
const UInt32 mask = (UInt32)1 << i;
|
|
if ((fi.LevelsMask & mask) != 0)
|
|
{
|
|
const UInt32 langID = g_Levels[i];
|
|
UString s;
|
|
s.Add_UInt32(i);
|
|
// if (fi.LevelsMask < (1 << (MY_ZSTD_LEVEL_MAX + 1)) - 1)
|
|
if (langID)
|
|
if (i != 0 || !isZstd)
|
|
{
|
|
s += " - ";
|
|
s += LangString(langID);
|
|
}
|
|
const int index = (int)m_Level.AddString(s);
|
|
m_Level.SetItemData(index, (LPARAM)i);
|
|
}
|
|
if (fi.LevelsMask <= mask)
|
|
break;
|
|
}
|
|
SetNearestSelectComboBox(m_Level, level);
|
|
}
|
|
|
|
|
|
static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s)
|
|
{
|
|
return cb.AddString((CSysString)s);
|
|
}
|
|
|
|
static const char *k_Auto_Prefix = "* ";
|
|
|
|
static void Modify_Auto(AString &s)
|
|
{
|
|
s.Insert(0, k_Auto_Prefix);
|
|
}
|
|
|
|
void CCompressDialog::SetMethod2(int keepMethodId)
|
|
{
|
|
m_Method.ResetContent();
|
|
_auto_MethodId = -1;
|
|
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
if (GetLevel() == 0 && !ai.Flags_HashHandler())
|
|
{
|
|
if (!ai.Is_Tar() &&
|
|
!ai.Is_Zstd())
|
|
{
|
|
MethodChanged();
|
|
return;
|
|
}
|
|
}
|
|
UString defaultMethod;
|
|
{
|
|
const int index = FindRegistryFormat(ai.Name);
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
defaultMethod = fo.Method;
|
|
}
|
|
}
|
|
const bool isSfx = IsSFX();
|
|
bool weUseSameMethod = false;
|
|
|
|
const bool is7z = ai.Is_7z();
|
|
|
|
for (unsigned m = 0;; m++)
|
|
{
|
|
int methodID;
|
|
const char *method;
|
|
if (m < fi.NumMethods)
|
|
{
|
|
methodID = fi.MethodIDs[m];
|
|
method = kMethodsNames[methodID];
|
|
if (is7z)
|
|
if (methodID == kCopy
|
|
|| methodID == kDeflate
|
|
|| methodID == kDeflate64
|
|
)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (!is7z)
|
|
break;
|
|
const unsigned extIndex = m - fi.NumMethods;
|
|
if (extIndex >= ExternalMethods.Size())
|
|
break;
|
|
methodID = (int)(Z7_ARRAY_SIZE(kMethodsNames) + extIndex);
|
|
method = ExternalMethods[extIndex].Ptr();
|
|
}
|
|
if (isSfx)
|
|
if (!IsMethodSupportedBySfx(methodID))
|
|
continue;
|
|
|
|
AString s (method);
|
|
int writtenMethodId = methodID;
|
|
if (m == 0)
|
|
{
|
|
_auto_MethodId = methodID;
|
|
writtenMethodId = -1;
|
|
Modify_Auto(s);
|
|
}
|
|
const int itemIndex = (int)ComboBox_AddStringAscii(m_Method, s);
|
|
m_Method.SetItemData(itemIndex, writtenMethodId);
|
|
if (keepMethodId == methodID)
|
|
{
|
|
m_Method.SetCurSel(itemIndex);
|
|
weUseSameMethod = true;
|
|
continue;
|
|
}
|
|
if ((defaultMethod.IsEqualTo_Ascii_NoCase(method) || m == 0) && !weUseSameMethod)
|
|
m_Method.SetCurSel(itemIndex);
|
|
}
|
|
|
|
if (!weUseSameMethod)
|
|
MethodChanged();
|
|
}
|
|
|
|
|
|
|
|
bool CCompressDialog::IsZipFormat()
|
|
{
|
|
return Get_ArcInfoEx().Is_Zip();
|
|
}
|
|
|
|
bool CCompressDialog::IsXzFormat()
|
|
{
|
|
return Get_ArcInfoEx().Is_Xz();
|
|
}
|
|
|
|
void CCompressDialog::SetEncryptionMethod()
|
|
{
|
|
_encryptionMethod.ResetContent();
|
|
_default_encryptionMethod_Index = -1;
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
if (ai.Is_7z())
|
|
{
|
|
ComboBox_AddStringAscii(_encryptionMethod, "AES-256");
|
|
_encryptionMethod.SetCurSel(0);
|
|
_default_encryptionMethod_Index = 0;
|
|
}
|
|
else if (ai.Is_Zip())
|
|
{
|
|
int index = FindRegistryFormat(ai.Name);
|
|
UString encryptionMethod;
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
encryptionMethod = fo.EncryptionMethod;
|
|
}
|
|
int sel = 0;
|
|
// if (ZipCryptoIsAllowed)
|
|
{
|
|
ComboBox_AddStringAscii(_encryptionMethod, "ZipCrypto");
|
|
sel = (encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0);
|
|
_default_encryptionMethod_Index = 0;
|
|
}
|
|
ComboBox_AddStringAscii(_encryptionMethod, "AES-256");
|
|
_encryptionMethod.SetCurSel(sel);
|
|
}
|
|
}
|
|
|
|
|
|
int CCompressDialog::GetMethodID_RAW()
|
|
{
|
|
if (m_Method.GetCount() <= 0)
|
|
return -1;
|
|
return (int)(Int32)(UInt32)m_Method.GetItemData_of_CurSel();
|
|
}
|
|
|
|
int CCompressDialog::GetMethodID()
|
|
{
|
|
int raw = GetMethodID_RAW();
|
|
if (raw < 0)
|
|
return _auto_MethodId;
|
|
return raw;
|
|
}
|
|
|
|
|
|
UString CCompressDialog::GetMethodSpec(UString &estimatedName)
|
|
{
|
|
estimatedName.Empty();
|
|
if (m_Method.GetCount() < 1)
|
|
return estimatedName;
|
|
const int methodIdRaw = GetMethodID_RAW();
|
|
int methodId = methodIdRaw;
|
|
if (methodIdRaw < 0)
|
|
methodId = _auto_MethodId;
|
|
UString s;
|
|
if (methodId >= 0)
|
|
{
|
|
if ((unsigned)methodId < Z7_ARRAY_SIZE(kMethodsNames))
|
|
estimatedName = kMethodsNames[methodId];
|
|
else
|
|
estimatedName = ExternalMethods[(unsigned)methodId - (unsigned)Z7_ARRAY_SIZE(kMethodsNames)];
|
|
if (methodIdRaw >= 0)
|
|
s = estimatedName;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
UString CCompressDialog::GetMethodSpec()
|
|
{
|
|
UString estimatedName;
|
|
UString s = GetMethodSpec(estimatedName);
|
|
return s;
|
|
}
|
|
|
|
bool CCompressDialog::IsMethodEqualTo(const UString &s)
|
|
{
|
|
UString estimatedName;
|
|
const UString shortName = GetMethodSpec(estimatedName);
|
|
if (s.IsEmpty())
|
|
return shortName.IsEmpty();
|
|
return s.IsEqualTo_NoCase(estimatedName);
|
|
}
|
|
|
|
|
|
UString CCompressDialog::GetEncryptionMethodSpec()
|
|
{
|
|
UString s;
|
|
if (_encryptionMethod.GetCount() > 0
|
|
&& _encryptionMethod.GetCurSel() != _default_encryptionMethod_Index)
|
|
{
|
|
_encryptionMethod.GetText(s);
|
|
s.RemoveChar(L'-');
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
static const size_t k_Auto_Dict = (size_t)0 - 1;
|
|
|
|
static int Combo_AddDict2(NWindows::NControl::CComboBox &cb, size_t sizeReal, size_t sizeShow)
|
|
{
|
|
char c = 0;
|
|
unsigned moveBits = 0;
|
|
if ((sizeShow & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
|
|
else if ((sizeShow & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
|
|
AString s;
|
|
s.Add_UInt64(sizeShow >> moveBits);
|
|
s.Add_Space();
|
|
if (c != 0)
|
|
s += c;
|
|
s += 'B';
|
|
if (sizeReal == k_Auto_Dict)
|
|
Modify_Auto(s);
|
|
const int index = (int)ComboBox_AddStringAscii(cb, s);
|
|
cb.SetItemData(index, (LPARAM)sizeReal);
|
|
return index;
|
|
}
|
|
|
|
int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow)
|
|
{
|
|
return Combo_AddDict2(m_Dictionary, sizeReal, sizeShow);
|
|
}
|
|
|
|
int CCompressDialog::AddDict(size_t size)
|
|
{
|
|
return AddDict2(size, size);
|
|
}
|
|
|
|
/*
|
|
int CCompressDialog::AddDict_Chain(size_t size)
|
|
{
|
|
return Combo_AddDict2(m_Dictionary_Chain, size, size);
|
|
}
|
|
*/
|
|
|
|
void CCompressDialog::SetDictionary2()
|
|
{
|
|
m_Dictionary.ResetContent();
|
|
// m_Dictionary_Chain.ResetContent();
|
|
|
|
// _auto_Dict = (UInt32)1 << 24; // we can use this dictSize to calculate _auto_Solid for unknown method for 7z
|
|
_auto_Dict = (UInt32)(Int32)-1; // for debug
|
|
// _auto_Dict_Chain = (UInt32)(Int32)-1; // for debug
|
|
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
UInt32 defaultDict = (UInt32)(Int32)-1;
|
|
// UInt32 defaultDict_Chain = (UInt32)(Int32)-1;
|
|
{
|
|
const int index = FindRegistryFormat(ai.Name);
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
if (IsMethodEqualTo(fo.Method))
|
|
{
|
|
defaultDict = fo.Dictionary;
|
|
// defaultDict_Chain = fo.DictionaryChain;
|
|
}
|
|
}
|
|
}
|
|
|
|
const int methodID = GetMethodID();
|
|
const UInt32 level = GetLevel2();
|
|
|
|
{
|
|
RECT r, rLabel;
|
|
GetClientRectOfItem(IDT_COMPRESS_DICTIONARY, rLabel);
|
|
GetClientRectOfItem(IDC_COMPRESS_DICTIONARY, r);
|
|
if (_dictionaryCombo_left == 0)
|
|
_dictionaryCombo_left = r.left;
|
|
|
|
// bool showDict2;
|
|
int newLableRight;
|
|
int newDictLeft;
|
|
|
|
/*
|
|
if (methodID == kZSTD)
|
|
{
|
|
showDict2 = true;
|
|
newDictLeft = _dictionaryCombo_left;
|
|
RECT r2;
|
|
GetClientRectOfItem(IDC_COMPRESS_DICTIONARY2, r2);
|
|
newLableRight = r2.left;
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
// showDict2 = false;
|
|
RECT rBig;
|
|
GetClientRectOfItem(IDC_COMPRESS_METHOD, rBig);
|
|
newDictLeft= rBig.left;
|
|
newLableRight = newDictLeft;
|
|
}
|
|
|
|
if (newLableRight != rLabel.right)
|
|
{
|
|
rLabel.right = newLableRight;
|
|
MoveItem_RECT(IDT_COMPRESS_DICTIONARY, rLabel);
|
|
InvalidateRect(&rLabel);
|
|
}
|
|
if (newDictLeft != r.left)
|
|
{
|
|
r.left = newDictLeft;
|
|
MoveItem_RECT(IDC_COMPRESS_DICTIONARY, r);
|
|
// InvalidateRect(&r);
|
|
}
|
|
// ShowItem_Bool(IDC_COMPRESS_DICTIONARY2, showDict2);
|
|
}
|
|
|
|
if (methodID < 0)
|
|
return;
|
|
|
|
switch (methodID)
|
|
{
|
|
case kLZMA:
|
|
case kLZMA2:
|
|
{
|
|
{
|
|
_auto_Dict =
|
|
( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
|
|
( level <= 6 ? ((UInt32)1 << (level + 19)) :
|
|
( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
|
|
)));
|
|
}
|
|
|
|
// we use threshold 3.75 GiB to switch to kLzmaMaxDictSize.
|
|
if (defaultDict != (UInt32)(Int32)-1
|
|
&& defaultDict >= ((UInt32)15 << 28))
|
|
defaultDict = kLzmaMaxDictSize;
|
|
|
|
const size_t kLzmaMaxDictSize_Up = (size_t)1 << (20 + sizeof(size_t) / 4 * 6);
|
|
|
|
int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
|
|
|
|
for (unsigned i = (16 - 1) * 2; i <= (32 - 1) * 2; i++)
|
|
{
|
|
if (i < (20 - 1) * 2
|
|
&& i != (16 - 1) * 2
|
|
&& i != (18 - 1) * 2)
|
|
continue;
|
|
if (i == (20 - 1) * 2 + 1)
|
|
continue;
|
|
const size_t dict_up = (size_t)(2 + (i & 1)) << (i / 2);
|
|
size_t dict = dict_up;
|
|
if (dict_up >= kLzmaMaxDictSize)
|
|
dict = kLzmaMaxDictSize; // we reduce dictionary
|
|
|
|
const int index = AddDict(dict);
|
|
// AddDict2(dict, dict_up); // for debug : we show 4 GB
|
|
|
|
// const UInt32 numThreads = 2;
|
|
// const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(numThreads, dict);
|
|
if (defaultDict != (UInt32)(Int32)-1)
|
|
if (dict <= defaultDict || curSel <= 0)
|
|
// if (!maxRamSize_Defined || memUsage <= maxRamSize)
|
|
curSel = index;
|
|
if (dict_up >= kLzmaMaxDictSize_Up)
|
|
break;
|
|
}
|
|
|
|
m_Dictionary.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
case kZSTD:
|
|
{
|
|
if (defaultDict != (UInt32)(Int32)-1 &&
|
|
defaultDict > kZstd_MAX_DictSize)
|
|
defaultDict = kZstd_MAX_DictSize;
|
|
|
|
if (defaultDict_Chain != (UInt32)(Int32)-1 &&
|
|
defaultDict_Chain > kZstd_MAX_DictSize_Chain)
|
|
defaultDict_Chain = kZstd_MAX_DictSize_Chain;
|
|
|
|
{
|
|
CZstdEncProps props;
|
|
ZstdEncProps_Init(&props);
|
|
// props.level_zstd = level;
|
|
props.level_7z = level;
|
|
ZstdEncProps_Set_WindowSize(&props, defaultDict != (UInt32)(Int32)-1 ? defaultDict: 0);
|
|
ZstdEncProps_NormalizeFull(&props);
|
|
_auto_Dict_Chain = (UInt32)1 << props.windowLog_Chain;
|
|
}
|
|
{
|
|
CZstdEncProps props;
|
|
ZstdEncProps_Init(&props);
|
|
// props.level_zstd = level;
|
|
props.level_7z = level;
|
|
ZstdEncProps_Set_WindowChainSize(&props, defaultDict_Chain != (UInt32)(Int32)-1 ? defaultDict_Chain: 0);
|
|
ZstdEncProps_NormalizeFull(&props);
|
|
_auto_Dict = (UInt32)1 << props.windowLog;
|
|
}
|
|
|
|
// if there is collision of two window sizes, we reduce dict_Chain
|
|
if (defaultDict != (UInt32)(Int32)-1 &&
|
|
defaultDict_Chain != (UInt32)(Int32)-1 &&
|
|
defaultDict < defaultDict_Chain)
|
|
defaultDict_Chain = defaultDict;
|
|
|
|
{
|
|
int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
|
|
|
|
// defaultDict = 12 << 10; // for debug
|
|
const UInt32 kWinStart = 18;
|
|
if (defaultDict != 0 && defaultDict < ((UInt32)1 << kWinStart))
|
|
curSel = AddDict(defaultDict);
|
|
|
|
for (unsigned i = kWinStart; i <= MY_ZSTD_WINDOWLOG_MAX; i++)
|
|
{
|
|
const size_t dict = (size_t)1 << i;
|
|
const int index = AddDict(dict);
|
|
if (defaultDict != (UInt32)(Int32)-1)
|
|
if (dict <= defaultDict || curSel <= 0)
|
|
curSel = index;
|
|
}
|
|
m_Dictionary.SetCurSel(curSel);
|
|
}
|
|
|
|
{
|
|
int curSel = Combo_AddDict2(m_Dictionary_Chain, k_Auto_Dict, _auto_Dict_Chain);
|
|
|
|
// defaultDict_Chain = 10 << 10; // for debug
|
|
const UInt32 kWinChainStart = 15;
|
|
if (defaultDict_Chain != 0 && defaultDict_Chain < ((UInt32)1 << kWinChainStart))
|
|
curSel = AddDict_Chain(defaultDict_Chain);
|
|
|
|
for (unsigned i = kWinChainStart; i <= kMaxDictChain; i++)
|
|
{
|
|
const size_t dict = (size_t)1 << i;
|
|
if (defaultDict != (UInt32)(Int32)-1 && dict > defaultDict)
|
|
break;
|
|
const int index = AddDict_Chain(dict);
|
|
if (defaultDict_Chain != (UInt32)(Int32)-1)
|
|
if (dict <= defaultDict_Chain || curSel <= 0)
|
|
curSel = index;
|
|
}
|
|
m_Dictionary_Chain.SetCurSel(curSel);
|
|
}
|
|
|
|
break;
|
|
}
|
|
*/
|
|
|
|
case kPPMd:
|
|
{
|
|
_auto_Dict = (UInt32)1 << (level + 19);
|
|
|
|
const UInt32 kPpmd_Default_4g = (UInt32)0 - ((UInt32)1 << 10);
|
|
const size_t kPpmd_MaxDictSize_Up = (size_t)1 << (29 + sizeof(size_t) / 8);
|
|
|
|
if (defaultDict != (UInt32)(Int32)-1
|
|
&& defaultDict >= ((UInt32)15 << 28)) // threshold
|
|
defaultDict = kPpmd_Default_4g;
|
|
|
|
int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
|
|
|
|
for (unsigned i = (20 - 1) * 2; i <= (32 - 1) * 2; i++)
|
|
{
|
|
if (i == (20 - 1) * 2 + 1)
|
|
continue;
|
|
|
|
const size_t dict_up = (size_t)(2 + (i & 1)) << (i / 2);
|
|
size_t dict = dict_up;
|
|
if (dict_up >= kPpmd_Default_4g)
|
|
dict = kPpmd_Default_4g;
|
|
|
|
const int index = AddDict2(dict, dict_up);
|
|
// AddDict2((UInt32)((UInt32)0 - 2), dict_up); // for debug
|
|
// AddDict(dict_up); // for debug
|
|
// const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
|
|
if (defaultDict != (UInt32)(Int32)-1)
|
|
if (dict <= defaultDict || curSel <= 0)
|
|
// if (!maxRamSize_Defined || memUsage <= maxRamSize)
|
|
curSel = index;
|
|
if (dict_up >= kPpmd_MaxDictSize_Up)
|
|
break;
|
|
}
|
|
m_Dictionary.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
case kPPMdZip:
|
|
{
|
|
_auto_Dict = (UInt32)1 << (level + 19);
|
|
|
|
int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
|
|
|
|
for (unsigned i = 20; i <= 28; i++)
|
|
{
|
|
const UInt32 dict = (UInt32)1 << i;
|
|
const int index = AddDict(dict);
|
|
// const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
|
|
if (defaultDict != (UInt32)(Int32)-1)
|
|
if (dict <= defaultDict || curSel <= 0)
|
|
// if (!maxRamSize_Defined || memUsage <= maxRamSize)
|
|
curSel = index;
|
|
}
|
|
m_Dictionary.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
case kDeflate:
|
|
case kDeflate64:
|
|
{
|
|
const UInt32 dict = (methodID == kDeflate ? (UInt32)(1 << 15) : (UInt32)(1 << 16));
|
|
_auto_Dict = dict;
|
|
AddDict2(k_Auto_Dict, _auto_Dict);
|
|
m_Dictionary.SetCurSel(0);
|
|
// EnableItem(IDC_COMPRESS_DICTIONARY, false);
|
|
break;
|
|
}
|
|
|
|
case kBZip2:
|
|
{
|
|
{
|
|
if (level >= 5) _auto_Dict = (900 << 10);
|
|
else if (level >= 3) _auto_Dict = (500 << 10);
|
|
else _auto_Dict = (100 << 10);
|
|
}
|
|
|
|
int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
|
|
|
|
for (unsigned i = 1; i <= 9; i++)
|
|
{
|
|
const UInt32 dict = ((UInt32)i * 100) << 10;
|
|
AddDict(dict);
|
|
// AddDict2(i * 100000, dict);
|
|
if (defaultDict != (UInt32)(Int32)-1)
|
|
if (i <= defaultDict / 100000 || curSel <= 0)
|
|
curSel = m_Dictionary.GetCount() - 1;
|
|
}
|
|
m_Dictionary.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
case kCopy:
|
|
{
|
|
_auto_Dict = 0;
|
|
AddDict(0);
|
|
m_Dictionary.SetCurSel(0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax)
|
|
{
|
|
if (c.GetCount() <= defMax)
|
|
return (UInt32)(Int32)-1;
|
|
return (UInt32)c.GetItemData_of_CurSel();
|
|
}
|
|
|
|
|
|
UInt64 CCompressDialog::GetComboValue_64(NWindows::NControl::CComboBox &c, int defMax)
|
|
{
|
|
if (c.GetCount() <= defMax)
|
|
return (UInt64)(Int64)-1;
|
|
// LRESULT is signed. so we cast it to unsigned size_t at first:
|
|
LRESULT val = c.GetItemData_of_CurSel();
|
|
if (val == (LPARAM)(INT_PTR)(-1))
|
|
return (UInt64)(Int64)-1;
|
|
return (UInt64)(size_t)c.GetItemData_of_CurSel();
|
|
}
|
|
|
|
UInt32 CCompressDialog::GetLevel2()
|
|
{
|
|
UInt32 level = GetLevel();
|
|
if (level == (UInt32)(Int32)-1)
|
|
level = 5;
|
|
return level;
|
|
}
|
|
|
|
|
|
int CCompressDialog::AddOrder(UInt32 size)
|
|
{
|
|
char s[32];
|
|
ConvertUInt32ToString(size, s);
|
|
const int index = (int)ComboBox_AddStringAscii(m_Order, s);
|
|
m_Order.SetItemData(index, (LPARAM)size);
|
|
return index;
|
|
}
|
|
|
|
int CCompressDialog::AddOrder_Auto()
|
|
{
|
|
AString s;
|
|
s.Add_UInt32(_auto_Order);
|
|
Modify_Auto(s);
|
|
int index = (int)ComboBox_AddStringAscii(m_Order, s);
|
|
m_Order.SetItemData(index, (LPARAM)(INT_PTR)(-1));
|
|
return index;
|
|
}
|
|
|
|
void CCompressDialog::SetOrder2()
|
|
{
|
|
m_Order.ResetContent();
|
|
|
|
_auto_Order = 1;
|
|
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
UInt32 defaultOrder = (UInt32)(Int32)-1;
|
|
|
|
{
|
|
const int index = FindRegistryFormat(ai.Name);
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
if (IsMethodEqualTo(fo.Method))
|
|
defaultOrder = fo.Order;
|
|
}
|
|
}
|
|
|
|
const int methodID = GetMethodID();
|
|
const UInt32 level = GetLevel2();
|
|
if (methodID < 0)
|
|
return;
|
|
|
|
switch (methodID)
|
|
{
|
|
case kLZMA:
|
|
case kLZMA2:
|
|
{
|
|
_auto_Order = (level < 7 ? 32 : 64);
|
|
int curSel = AddOrder_Auto();
|
|
for (unsigned i = 2 * 2; i < 8 * 2; i++)
|
|
{
|
|
UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
|
|
if (order > 256)
|
|
order = 273;
|
|
const int index = AddOrder(order);
|
|
if (defaultOrder != (UInt32)(Int32)-1)
|
|
if (order <= defaultOrder || curSel <= 0)
|
|
curSel = index;
|
|
}
|
|
m_Order.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
case kZSTD:
|
|
{
|
|
{
|
|
CZstdEncProps props;
|
|
ZstdEncProps_Init(&props);
|
|
// props.level_zstd = level;
|
|
props.level_7z = level;
|
|
ZstdEncProps_NormalizeFull(&props);
|
|
_auto_Order = props.targetLength;
|
|
if (props.strategy < ZSTD_strategy_btopt)
|
|
{
|
|
// ZSTD_strategy_fast uses targetLength to change fast level.
|
|
// targetLength probably is used only in ZSTD_strategy_btopt and higher
|
|
break;
|
|
}
|
|
}
|
|
int curSel = AddOrder_Auto();
|
|
|
|
for (unsigned i = 6; i <= 9 * 2; i++)
|
|
{
|
|
UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
|
|
// if (order > 999) order = 999;
|
|
const int index = AddOrder(order);
|
|
if (defaultOrder != (UInt32)(Int32)-1)
|
|
if (order <= defaultOrder || curSel <= 0)
|
|
curSel = index;
|
|
}
|
|
m_Order.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
*/
|
|
|
|
case kDeflate:
|
|
case kDeflate64:
|
|
{
|
|
{
|
|
if (level >= 9) _auto_Order = 128;
|
|
else if (level >= 7) _auto_Order = 64;
|
|
else _auto_Order = 32;
|
|
}
|
|
int curSel = AddOrder_Auto();
|
|
for (unsigned i = 2 * 2; i < 8 * 2; i++)
|
|
{
|
|
UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
|
|
if (order > 256)
|
|
order = (methodID == kDeflate64 ? 257 : 258);
|
|
const int index = AddOrder(order);
|
|
if (defaultOrder != (UInt32)(Int32)-1)
|
|
if (order <= defaultOrder || curSel <= 0)
|
|
curSel = index;
|
|
}
|
|
|
|
m_Order.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
case kPPMd:
|
|
{
|
|
{
|
|
if (level >= 9) _auto_Order = 32;
|
|
else if (level >= 7) _auto_Order = 16;
|
|
else if (level >= 5) _auto_Order = 6;
|
|
else _auto_Order = 4;
|
|
}
|
|
|
|
int curSel = AddOrder_Auto();
|
|
|
|
for (unsigned i = 0;; i++)
|
|
{
|
|
UInt32 order = i + 2;
|
|
if (i >= 2)
|
|
order = (4 + ((i - 2) & 3)) << ((i - 2) / 4);
|
|
const int index = AddOrder(order);
|
|
if (defaultOrder != (UInt32)(Int32)-1)
|
|
if (order <= defaultOrder || curSel <= 0)
|
|
curSel = index;
|
|
if (order >= 32)
|
|
break;
|
|
}
|
|
m_Order.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
case kPPMdZip:
|
|
{
|
|
_auto_Order = level + 3;
|
|
int curSel = AddOrder_Auto();
|
|
for (unsigned i = 2; i <= 16; i++)
|
|
{
|
|
const int index = AddOrder(i);
|
|
if (defaultOrder != (UInt32)(Int32)-1)
|
|
if (i <= defaultOrder || curSel <= 0)
|
|
curSel = index;
|
|
}
|
|
m_Order.SetCurSel(curSel);
|
|
break;
|
|
}
|
|
|
|
// case kBZip2:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool CCompressDialog::GetOrderMode()
|
|
{
|
|
switch (GetMethodID())
|
|
{
|
|
case kPPMd:
|
|
case kPPMdZip:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
static UInt64 Get_Lzma2_ChunkSize(UInt64 dict)
|
|
{
|
|
// we use same default chunk sizes as defined in 7z encoder and lzma2 encoder
|
|
UInt64 cs = (UInt64)dict << 2;
|
|
const UInt32 kMinSize = (UInt32)1 << 20;
|
|
const UInt32 kMaxSize = (UInt32)1 << 28;
|
|
if (cs < kMinSize) cs = kMinSize;
|
|
if (cs > kMaxSize) cs = kMaxSize;
|
|
if (cs < dict) cs = dict;
|
|
cs += (kMinSize - 1);
|
|
cs &= ~(UInt64)(kMinSize - 1);
|
|
return cs;
|
|
}
|
|
|
|
|
|
static void Add_Size(AString &s, UInt64 val)
|
|
{
|
|
unsigned moveBits = 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'; }
|
|
s.Add_UInt64(val >> moveBits);
|
|
s.Add_Space();
|
|
if (moveBits != 0)
|
|
s += c;
|
|
s += 'B';
|
|
}
|
|
|
|
|
|
void CCompressDialog::SetSolidBlockSize2()
|
|
{
|
|
m_Solid.ResetContent();
|
|
_auto_Solid = 1 << 20;
|
|
|
|
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
|
|
if (!fi.Solid_())
|
|
return;
|
|
|
|
const UInt32 level = GetLevel2();
|
|
if (level == 0)
|
|
return;
|
|
|
|
UInt64 dict = GetDict2();
|
|
if (dict == (UInt64)(Int64)-1)
|
|
{
|
|
dict = 1 << 25; // default dict for unknown methods
|
|
// return;
|
|
}
|
|
|
|
|
|
UInt32 defaultBlockSize = (UInt32)(Int32)-1;
|
|
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
|
|
/*
|
|
if (usePrevDictionary)
|
|
defaultBlockSize = GetBlockSizeSpec();
|
|
else
|
|
*/
|
|
{
|
|
const int index = FindRegistryFormat(ai.Name);
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
if (IsMethodEqualTo(fo.Method))
|
|
defaultBlockSize = fo.BlockLogSize;
|
|
}
|
|
}
|
|
|
|
const bool is7z = ai.Is_7z();
|
|
|
|
const UInt64 cs = Get_Lzma2_ChunkSize(dict);
|
|
|
|
// Solid Block Size
|
|
UInt64 blockSize = cs; // for xz
|
|
|
|
if (is7z)
|
|
{
|
|
// we use same default block sizes as defined in 7z encoder
|
|
UInt64 kMaxSize = (UInt64)1 << 32;
|
|
const int methodId = GetMethodID();
|
|
if (methodId == kLZMA2)
|
|
{
|
|
blockSize = cs << 6;
|
|
kMaxSize = (UInt64)1 << 34;
|
|
}
|
|
else
|
|
{
|
|
UInt64 dict2 = dict;
|
|
if (methodId == kBZip2)
|
|
{
|
|
dict2 /= 100000;
|
|
if (dict2 < 1)
|
|
dict2 = 1;
|
|
dict2 *= 100000;
|
|
}
|
|
blockSize = dict2 << 7;
|
|
}
|
|
|
|
const UInt32 kMinSize = (UInt32)1 << 24;
|
|
if (blockSize < kMinSize) blockSize = kMinSize;
|
|
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
|
}
|
|
|
|
_auto_Solid = blockSize;
|
|
|
|
int curSel;
|
|
{
|
|
AString s;
|
|
Add_Size(s, _auto_Solid);
|
|
Modify_Auto(s);
|
|
const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
|
|
m_Solid.SetItemData(index, (LPARAM)(UInt32)(Int32)-1);
|
|
curSel = index;
|
|
}
|
|
|
|
if (is7z)
|
|
{
|
|
UString s ('-');
|
|
// kSolidLog_NoSolid = 0 for xz means default blockSize
|
|
if (is7z)
|
|
LangString(IDS_COMPRESS_NON_SOLID, s);
|
|
const int index = (int)m_Solid.AddString(s);
|
|
m_Solid.SetItemData(index, (LPARAM)(UInt32)kSolidLog_NoSolid);
|
|
if (defaultBlockSize == kSolidLog_NoSolid)
|
|
curSel = index;
|
|
}
|
|
|
|
for (unsigned i = 20; i <= 36; i++)
|
|
{
|
|
AString s;
|
|
Add_Size(s, (UInt64)1 << i);
|
|
const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
|
|
m_Solid.SetItemData(index, (LPARAM)(UInt32)i);
|
|
if (defaultBlockSize != (UInt32)(Int32)-1)
|
|
if (i <= defaultBlockSize || index <= 1)
|
|
curSel = index;
|
|
}
|
|
|
|
{
|
|
const int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID));
|
|
m_Solid.SetItemData(index, (LPARAM)kSolidLog_FullSolid);
|
|
if (defaultBlockSize == kSolidLog_FullSolid)
|
|
curSel = index;
|
|
}
|
|
|
|
m_Solid.SetCurSel(curSel);
|
|
}
|
|
|
|
|
|
/*
|
|
static void ZstdEncProps_SetDictProps_From_CompressDialog(CZstdEncProps *props, CCompressDialog &cd)
|
|
{
|
|
{
|
|
const UInt64 d64 = cd.GetDictSpec();
|
|
UInt32 d32 = 0; // 0 is default for ZstdEncProps::windowLog
|
|
if (d64 != (UInt64)(Int64)-1)
|
|
{
|
|
d32 = (UInt32)d64;
|
|
if (d32 != d64)
|
|
d32 = (UInt32)(Int32)-2;
|
|
}
|
|
ZstdEncProps_Set_WindowSize(props, d32);
|
|
}
|
|
{
|
|
const UInt64 d64 = cd.GetDictChainSpec();
|
|
UInt32 d32 = 0; // 0 is default for ZstdEncProps::windowLog_Chain
|
|
if (d64 != (UInt64)(Int64)-1)
|
|
{
|
|
d32 = (UInt32)d64;
|
|
if (d32 != d64)
|
|
d32 = (UInt32)(Int32)-2;
|
|
}
|
|
ZstdEncProps_Set_WindowChainSize(props, d32);
|
|
}
|
|
}
|
|
|
|
static bool Is_Zstd_Mt_Supported()
|
|
{
|
|
if (!GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "InitializeConditionVariable"))
|
|
return false;
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
static const char *k_ST_Threads = " (ST)";
|
|
|
|
void CCompressDialog::SetNumThreads2()
|
|
{
|
|
_auto_NumThreads = 1;
|
|
|
|
m_NumThreads.ResetContent();
|
|
const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
|
|
if (!fi.MultiThread_())
|
|
return;
|
|
|
|
const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();
|
|
// 64; // for debug:
|
|
|
|
UInt32 defaultValue = numHardwareThreads;
|
|
bool useAutoThreads = true;
|
|
|
|
{
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
int index = FindRegistryFormat(ai.Name);
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
if (IsMethodEqualTo(fo.Method) && fo.NumThreads != (UInt32)(Int32)-1)
|
|
{
|
|
defaultValue = fo.NumThreads;
|
|
useAutoThreads = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// const UInt32 num_ZSTD_threads_MAX = Is_Zstd_Mt_Supported() ? MY_ZSTDMT_NBWORKERS_MAX : 0;
|
|
|
|
UInt32 numAlgoThreadsMax = numHardwareThreads * 2;
|
|
const int methodID = GetMethodID();
|
|
|
|
switch (methodID)
|
|
{
|
|
case kLZMA: numAlgoThreadsMax = 2; break;
|
|
case kLZMA2: numAlgoThreadsMax = 256; break;
|
|
case kBZip2: numAlgoThreadsMax = 32; break;
|
|
// case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break;
|
|
case kCopy:
|
|
case kPPMd:
|
|
case kDeflate:
|
|
case kDeflate64:
|
|
case kPPMdZip:
|
|
numAlgoThreadsMax = 1;
|
|
}
|
|
const bool isZip = IsZipFormat();
|
|
if (isZip)
|
|
{
|
|
numAlgoThreadsMax =
|
|
#ifdef _WIN32
|
|
64; // _WIN32 supports only 64 threads in one group. So no need for more threads here
|
|
#else
|
|
128;
|
|
#endif
|
|
}
|
|
|
|
UInt32 autoThreads = numHardwareThreads;
|
|
if (autoThreads > numAlgoThreadsMax)
|
|
autoThreads = numAlgoThreadsMax;
|
|
|
|
const UInt64 memUse_Limit = Get_MemUse_Bytes();
|
|
|
|
if (_ramSize_Defined)
|
|
if (autoThreads > 1
|
|
// || (autoThreads == 0 && methodID == kZSTD)
|
|
)
|
|
{
|
|
if (isZip)
|
|
{
|
|
for (; autoThreads > 1; autoThreads--)
|
|
{
|
|
const UInt64 dict64 = GetDict2();
|
|
UInt64 decompressMemory;
|
|
const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
|
|
if (usage <= memUse_Limit)
|
|
break;
|
|
}
|
|
}
|
|
else if (methodID == kLZMA2)
|
|
{
|
|
const UInt64 dict64 = GetDict2();
|
|
const UInt32 numThreads1 = (GetLevel2() >= 5 ? 2 : 1);
|
|
UInt32 numBlockThreads = autoThreads / numThreads1;
|
|
for (; numBlockThreads > 1; numBlockThreads--)
|
|
{
|
|
autoThreads = numBlockThreads * numThreads1;
|
|
UInt64 decompressMemory;
|
|
const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
|
|
if (usage <= memUse_Limit)
|
|
break;
|
|
}
|
|
autoThreads = numBlockThreads * numThreads1;
|
|
}
|
|
/*
|
|
else if (methodID == kZSTD)
|
|
{
|
|
if (num_ZSTD_threads_MAX != 0)
|
|
{
|
|
CZstdEncProps props;
|
|
ZstdEncProps_Init(&props);
|
|
// props.level_zstd = level;
|
|
props.level_7z = GetLevel2();
|
|
ZstdEncProps_SetDictProps_From_CompressDialog(&props, *this);
|
|
autoThreads = ZstdEncProps_GetNumThreads_for_MemUsageLimit(&props, memUse_Limit, autoThreads);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
_auto_NumThreads = autoThreads;
|
|
|
|
int curSel = -1;
|
|
{
|
|
AString s;
|
|
s.Add_UInt32(autoThreads);
|
|
if (autoThreads == 0) s += k_ST_Threads;
|
|
Modify_Auto(s);
|
|
const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
|
|
m_NumThreads.SetItemData(index, (LPARAM)(INT_PTR)(-1));
|
|
// m_NumThreads.SetItemData(index, autoThreads);
|
|
if (useAutoThreads)
|
|
curSel = index;
|
|
}
|
|
|
|
if (numAlgoThreadsMax != autoThreads || autoThreads != 1)
|
|
for (UInt32 i =
|
|
// (methodID == kZSTD) ? 0 :
|
|
1;
|
|
i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++)
|
|
{
|
|
AString s;
|
|
s.Add_UInt32(i);
|
|
if (i == 0) s += k_ST_Threads;
|
|
const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
|
|
m_NumThreads.SetItemData(index, (LPARAM)(UInt32)i);
|
|
if (!useAutoThreads && i == defaultValue)
|
|
curSel = index;
|
|
}
|
|
|
|
m_NumThreads.SetCurSel(curSel);
|
|
}
|
|
|
|
|
|
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 = k_Auto_Prefix;
|
|
else
|
|
sRegistry = s;
|
|
sUser += s;
|
|
}
|
|
else
|
|
{
|
|
AddMemSize(sUser, val);
|
|
sRegistry = sUser;
|
|
for (;;)
|
|
{
|
|
const 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, (LPARAM)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);
|
|
}
|
|
|
|
|
|
/*
|
|
we could use that function to reduce the dictionary if small RAM
|
|
UInt64 CCompressDialog::GetMemoryUsageComp_Threads_Dict(UInt32 numThreads, UInt64 dict64)
|
|
{
|
|
UInt64 decompressMemory;
|
|
return GetMemoryUsage_Threads_Dict_DecompMem(numThreads, dict64, decompressMemory);
|
|
}
|
|
*/
|
|
|
|
|
|
UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &decompressMemory)
|
|
{
|
|
return GetMemoryUsage_Threads_Dict_DecompMem(GetNumThreads2(), dict64, decompressMemory);
|
|
}
|
|
|
|
UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 dict64, UInt64 &decompressMemory)
|
|
{
|
|
decompressMemory = (UInt64)(Int64)-1;
|
|
|
|
const UInt32 level = GetLevel2();
|
|
if (level == 0 && !Get_ArcInfoEx().Is_Zstd())
|
|
{
|
|
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();
|
|
|
|
UInt32 numMainZipThreads = 1;
|
|
|
|
if (IsZipFormat())
|
|
{
|
|
UInt32 numSubThreads = 1;
|
|
if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5)
|
|
numSubThreads = 2;
|
|
numMainZipThreads = numThreads / numSubThreads;
|
|
if (numMainZipThreads > 1)
|
|
size += (UInt64)numMainZipThreads * ((size_t)sizeof(size_t) << 23);
|
|
else
|
|
numMainZipThreads = 1;
|
|
}
|
|
|
|
const int methodId = GetMethodID();
|
|
|
|
if (dict64 == (UInt64)(Int64)-1
|
|
// && methodId != kZSTD
|
|
)
|
|
return (UInt64)(Int64)-1;
|
|
|
|
|
|
switch (methodId)
|
|
{
|
|
case kLZMA:
|
|
case kLZMA2:
|
|
{
|
|
const UInt32 dict = (dict64 >= kLzmaMaxDictSize ? kLzmaMaxDictSize : (UInt32)dict64);
|
|
UInt32 hs = dict - 1;
|
|
hs |= (hs >> 1);
|
|
hs |= (hs >> 2);
|
|
hs |= (hs >> 4);
|
|
hs |= (hs >> 8);
|
|
hs >>= 1;
|
|
if (hs >= (1 << 24))
|
|
hs >>= 1;
|
|
hs |= (1 << 16) - 1;
|
|
// if (numHashBytes >= 5)
|
|
if (level < 5)
|
|
hs |= (256 << 10) - 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;
|
|
|
|
UInt64 chunkSize = 0; // it's solid chunk
|
|
|
|
if (methodId != kLZMA && numBlockThreads != 1)
|
|
{
|
|
chunkSize = Get_Lzma2_ChunkSize(dict);
|
|
|
|
if (IsXzFormat())
|
|
{
|
|
UInt32 blockSizeLog = GetBlockSizeSpec();
|
|
if (blockSizeLog != (UInt32)(Int32)-1)
|
|
{
|
|
if (blockSizeLog == kSolidLog_FullSolid)
|
|
{
|
|
numBlockThreads = 1;
|
|
chunkSize = 0;
|
|
}
|
|
else if (blockSizeLog != kSolidLog_NoSolid)
|
|
chunkSize = (UInt64)1 << blockSizeLog;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (chunkSize == 0)
|
|
{
|
|
const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16);
|
|
UInt64 blockSize = (UInt64)dict + (1 << 16)
|
|
+ (numThreads1 > 1 ? (1 << 20) : 0);
|
|
blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2));
|
|
if (blockSize >= kBlockSizeMax)
|
|
blockSize = kBlockSizeMax;
|
|
size += numBlockThreads * (size1 + blockSize);
|
|
}
|
|
else
|
|
{
|
|
size += numBlockThreads * (size1 + chunkSize);
|
|
UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
|
|
if (chunkSize < ((UInt32)1 << 26)) numBlockThreads++;
|
|
if (chunkSize < ((UInt32)1 << 24)) numBlockThreads++;
|
|
if (chunkSize < ((UInt32)1 << 22)) numBlockThreads++;
|
|
size += numPackChunks * chunkSize;
|
|
}
|
|
|
|
decompressMemory = dict + (2 << 20);
|
|
return size;
|
|
}
|
|
|
|
/*
|
|
case kZSTD:
|
|
{
|
|
CZstdEncProps props;
|
|
ZstdEncProps_Init(&props);
|
|
// props.level_zstd = level;
|
|
props.level_7z = level;
|
|
props.nbWorkers = numThreads;
|
|
ZstdEncProps_SetDictProps_From_CompressDialog(&props, *this);
|
|
ZstdEncProps_NormalizeFull(&props);
|
|
size = ZstdEncProps_GetMemUsage(&props);
|
|
decompressMemory = (UInt64)1 << props.windowLog;
|
|
return size;
|
|
}
|
|
*/
|
|
|
|
case kPPMd:
|
|
{
|
|
decompressMemory = dict64 + (2 << 20);
|
|
return size + decompressMemory;
|
|
}
|
|
|
|
case kDeflate:
|
|
case kDeflate64:
|
|
{
|
|
UInt64 size1 = 3 << 20;
|
|
// if (level >= 7)
|
|
size1 += (1 << 20);
|
|
size += size1 * numMainZipThreads;
|
|
decompressMemory = (2 << 20);
|
|
return size;
|
|
}
|
|
|
|
case kBZip2:
|
|
{
|
|
decompressMemory = (7 << 20);
|
|
UInt64 memForOneThread = (10 << 20);
|
|
return size + memForOneThread * numThreads;
|
|
}
|
|
|
|
case kPPMdZip:
|
|
{
|
|
decompressMemory = dict64 + (2 << 20);
|
|
return size + (UInt64)decompressMemory * numThreads;
|
|
}
|
|
}
|
|
|
|
return (UInt64)(Int64)-1;
|
|
}
|
|
|
|
|
|
|
|
static void AddMemUsage(UString &s, UInt64 v)
|
|
{
|
|
const char *post;
|
|
if (v <= ((UInt64)16 << 30))
|
|
{
|
|
v = (v + (1 << 20) - 1) >> 20;
|
|
post = "MB";
|
|
}
|
|
else if (v <= ((UInt64)64 << 40))
|
|
{
|
|
v = (v + (1 << 30) - 1) >> 30;
|
|
post = "GB";
|
|
}
|
|
else
|
|
{
|
|
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()
|
|
{
|
|
UInt64 decompressMem;
|
|
const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem);
|
|
PrintMemUsage(IDT_COMPRESS_MEMORY_VALUE, memUsage);
|
|
PrintMemUsage(IDT_COMPRESS_MEMORY_DE_VALUE, decompressMem);
|
|
#ifdef PRINT_PARAMS
|
|
Print_Params();
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
#ifdef PRINT_PARAMS
|
|
|
|
static const char kPropDelimeter = ' '; // ':'
|
|
|
|
static void AddPropName(AString &s, const char *name)
|
|
{
|
|
if (!s.IsEmpty())
|
|
s += kPropDelimeter;
|
|
s += name;
|
|
}
|
|
|
|
static void AddProp(AString &s, const char *name, unsigned v)
|
|
{
|
|
AddPropName(s, name);
|
|
s.Add_UInt32(v);
|
|
}
|
|
|
|
static void AddProp_switch(AString &s, const char *name, E_ZSTD_paramSwitch_e e)
|
|
{
|
|
AddPropName(s, name);
|
|
s += e == k_ZSTD_ps_enable ? "" : "-";
|
|
}
|
|
|
|
static void PrintPropAsLog(AString &s, const char *name, size_t v)
|
|
{
|
|
AddPropName(s, name);
|
|
for (unsigned i = 0; i < sizeof(size_t) * 8; i++)
|
|
{
|
|
if (((size_t)1 << i) == v)
|
|
{
|
|
s.Add_UInt32(i);
|
|
return;
|
|
}
|
|
}
|
|
char c = 'b';
|
|
if ((v & 0x3FFFFFFF) == 0) { v >>= 30; c = 'G'; }
|
|
else if ((v & 0xFFFFF) == 0) { v >>= 20; c = 'M'; }
|
|
else if ((v & 0x3FF) == 0) { v >>= 10; c = 'K'; }
|
|
s.Add_UInt64(v);
|
|
s += c;
|
|
}
|
|
|
|
static void ZstdEncProps_Print(CZstdEncProps *props, AString &s)
|
|
{
|
|
if (props->level_zstd >= 0)
|
|
AddProp(s, "zx", props->level_zstd);
|
|
else
|
|
AddProp(s, "zf", -(props->level_zstd));
|
|
AddProp(s, "a", props->strategy);
|
|
AddProp(s, "d", props->windowLog);
|
|
AddProp(s, "zclog", props->chainLog);
|
|
AddProp(s, "zhb", props->hashLog);
|
|
AddProp(s, "mml", props->minMatch);
|
|
AddProp(s, "mcb", props->searchLog);
|
|
AddProp(s, "fb", props->targetLength);
|
|
AddProp(s, "mt", props->nbWorkers);
|
|
PrintPropAsLog(s, "c", props->jobSize);
|
|
AddProp(s, "zov", props->overlapLog);
|
|
PrintPropAsLog(s, "ztps", props->targetPrefixSize);
|
|
AddProp_switch(s, "zmfr", props->useRowMatchFinder);
|
|
if (props->ldmParams.enableLdm == k_ZSTD_ps_enable)
|
|
{
|
|
AddProp_switch(s, "zle", props->ldmParams.enableLdm);
|
|
AddProp(s, "zlhb", props->ldmParams.hashLog);
|
|
AddProp(s, "zlbb", props->ldmParams.bucketSizeLog);
|
|
AddProp(s, "zlmml", props->ldmParams.minMatchLength);
|
|
AddProp(s, "zlhrb", props->ldmParams.hashRateLog);
|
|
}
|
|
}
|
|
|
|
void CCompressDialog::Print_Params()
|
|
{
|
|
{
|
|
CZstdEncProps props;
|
|
ZstdEncProps_Init(&props);
|
|
// props.level_zstd = level;
|
|
props.level_7z = GetLevel2();
|
|
ZstdEncProps_SetDictProps_From_CompressDialog(&props, *this);
|
|
{
|
|
UInt32 order = GetOrderSpec();
|
|
if (order != (UInt32)(Int32)-1)
|
|
props.targetLength = GetOrderSpec();
|
|
}
|
|
props.nbWorkers = GetNumThreads2();
|
|
// props.windowLog = 18; // for debug
|
|
ZstdEncProps_NormalizeFull(&props);
|
|
AString s;
|
|
ZstdEncProps_Print(&props, s);
|
|
SetItemTextA(IDT_COMPRESS_PARAMS_INFO, s);
|
|
}
|
|
}
|
|
|
|
#endif // PRINT_PARAMS
|
|
|
|
|
|
|
|
void CCompressDialog::SetParams()
|
|
{
|
|
const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
m_Params.SetText(TEXT(""));
|
|
const int index = FindRegistryFormat(ai.Name);
|
|
if (index >= 0)
|
|
{
|
|
const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
m_Params.SetText(fo.Options);
|
|
}
|
|
}
|
|
|
|
void CCompressDialog::SaveOptionsInMem()
|
|
{
|
|
/* these options are for (Info.FormatIndex).
|
|
If it's called just after format changing,
|
|
then it's format that was selected before format changing
|
|
So we store previous format properties */
|
|
|
|
m_Params.GetText(Info.Options);
|
|
Info.Options.Trim();
|
|
|
|
const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];
|
|
const unsigned index = FindRegistryFormat_Always(ai.Name);
|
|
NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
|
|
fo.Options = Info.Options;
|
|
fo.Level = GetLevelSpec();
|
|
{
|
|
const UInt64 dict64 = GetDictSpec();
|
|
UInt32 dict32;
|
|
if (dict64 == (UInt64)(Int64)-1)
|
|
dict32 = (UInt32)(Int32)-1;
|
|
else
|
|
{
|
|
dict32 = (UInt32)dict64;
|
|
if (dict64 != dict32)
|
|
{
|
|
/* here we must write 32-bit value for registry that indicates big_value
|
|
(UInt32)(Int32)-1 : is used as marker for default size
|
|
(UInt32)(Int32)-2 : it can be used to indicate big value (4 GiB)
|
|
the value must be larger than threshold
|
|
*/
|
|
dict32 = (UInt32)(Int32)-2;
|
|
// dict32 = kLzmaMaxDictSize; // it must be larger than threshold
|
|
}
|
|
}
|
|
fo.Dictionary = dict32;
|
|
}
|
|
/*
|
|
{
|
|
const UInt64 dict64 = GetDictChainSpec();
|
|
UInt32 dict32;
|
|
if (dict64 == (UInt64)(Int64)-1)
|
|
dict32 = (UInt32)(Int32)-1;
|
|
else
|
|
{
|
|
dict32 = (UInt32)dict64;
|
|
if (dict64 != dict32)
|
|
{
|
|
dict32 = (UInt32)(Int32)-2;
|
|
// dict32 = k_Zstd_MAX_DictSize; // it must be larger than threshold
|
|
}
|
|
}
|
|
fo.DictionaryChain = dict32;
|
|
}
|
|
*/
|
|
|
|
fo.Order = GetOrderSpec();
|
|
fo.Method = GetMethodSpec();
|
|
fo.EncryptionMethod = GetEncryptionMethodSpec();
|
|
fo.NumThreads = GetNumThreadsSpec();
|
|
fo.BlockLogSize = GetBlockSizeSpec();
|
|
fo.MemUse = Get_MemUse_Spec();
|
|
}
|
|
|
|
|
|
unsigned CCompressDialog::GetFormatIndex()
|
|
{
|
|
return (unsigned)m_Format.GetItemData_of_CurSel();
|
|
}
|
|
|
|
|
|
|
|
static void AddText_from_BoolPair(AString &s, const char *name, const CBoolPair &bp)
|
|
{
|
|
if (bp.Def)
|
|
{
|
|
s.Add_OptSpaced(name);
|
|
if (!bp.Val)
|
|
s += "-";
|
|
}
|
|
/*
|
|
else if (bp.Val)
|
|
{
|
|
s.Add_OptSpaced("[");
|
|
s += name;
|
|
s += "]";
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
static void AddText_from_Bool1(AString &s, const char *name, const CBool1 &b)
|
|
{
|
|
if (b.Supported && b.Val)
|
|
s.Add_OptSpaced(name);
|
|
}
|
|
|
|
|
|
void CCompressDialog::ShowOptionsString()
|
|
{
|
|
NCompression::CFormatOptions &fo = Get_FormatOptions();
|
|
|
|
AString s;
|
|
if (fo.IsSet_TimePrec())
|
|
{
|
|
s.Add_OptSpaced("tp");
|
|
s.Add_UInt32(fo.TimePrec);
|
|
}
|
|
AddText_from_BoolPair(s, "tm", fo.MTime);
|
|
AddText_from_BoolPair(s, "tc", fo.CTime);
|
|
AddText_from_BoolPair(s, "ta", fo.ATime);
|
|
AddText_from_BoolPair(s, "-stl", fo.SetArcMTime);
|
|
|
|
// const CArcInfoEx &ai = Get_ArcInfoEx();
|
|
AddText_from_Bool1(s, "SL", SymLinks);
|
|
AddText_from_Bool1(s, "HL", HardLinks);
|
|
AddText_from_Bool1(s, "AS", AltStreams);
|
|
AddText_from_Bool1(s, "Sec", NtSecurity);
|
|
|
|
// AddText_from_Bool1(s, "Preserve", PreserveATime);
|
|
|
|
SetItemText(IDT_COMPRESS_OPTIONS, GetUnicodeString(s));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------- OPTIONS ----------
|
|
|
|
|
|
void COptionsDialog::CheckButton_Bool1(UINT id, const CBool1 &b1)
|
|
{
|
|
CheckButton(id, b1.Val);
|
|
}
|
|
|
|
void COptionsDialog::GetButton_Bool1(UINT id, CBool1 &b1)
|
|
{
|
|
b1.Val = IsButtonCheckedBool(id);
|
|
}
|
|
|
|
|
|
void COptionsDialog::CheckButton_BoolBox(
|
|
bool supported, const CBoolPair &b2, CBoolBox &bb)
|
|
{
|
|
const bool isSet = b2.Def;
|
|
const bool val = isSet ? b2.Val : bb.DefaultVal;
|
|
|
|
bb.IsSupported = supported;
|
|
|
|
CheckButton (bb.Set_Id, isSet);
|
|
ShowItem_Bool (bb.Set_Id, supported);
|
|
CheckButton (bb.Id, val);
|
|
EnableItem (bb.Id, isSet);
|
|
ShowItem_Bool (bb.Id, supported);
|
|
}
|
|
|
|
void COptionsDialog::GetButton_BoolBox(CBoolBox &bb)
|
|
{
|
|
// we save value for invisible buttons too
|
|
bb.BoolPair.Val = IsButtonCheckedBool (bb.Id);
|
|
bb.BoolPair.Def = IsButtonCheckedBool (bb.Set_Id);
|
|
}
|
|
|
|
|
|
void COptionsDialog::Store_TimeBoxes()
|
|
{
|
|
TimePrec = GetPrecSpec();
|
|
GetButton_BoolBox (MTime);
|
|
GetButton_BoolBox (CTime);
|
|
GetButton_BoolBox (ATime);
|
|
GetButton_BoolBox (ZTime);
|
|
}
|
|
|
|
|
|
UInt32 COptionsDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax)
|
|
{
|
|
if (c.GetCount() <= defMax)
|
|
return (UInt32)(Int32)-1;
|
|
return (UInt32)c.GetItemData_of_CurSel();
|
|
}
|
|
|
|
static const unsigned kTimePrec_Win = 0;
|
|
static const unsigned kTimePrec_Unix = 1;
|
|
static const unsigned kTimePrec_DOS = 2;
|
|
static const unsigned kTimePrec_1ns = 3;
|
|
|
|
static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL)
|
|
{
|
|
// s += " : ";
|
|
{
|
|
AString s2;
|
|
s2.Add_UInt32(val);
|
|
s += s2;
|
|
}
|
|
s.Add_Space();
|
|
s += unit;
|
|
if (sys)
|
|
{
|
|
s += " : ";
|
|
s += sys;
|
|
}
|
|
}
|
|
|
|
int COptionsDialog::AddPrec(unsigned prec, bool isDefault)
|
|
{
|
|
UString s;
|
|
UInt32 writePrec = prec;
|
|
if (isDefault)
|
|
{
|
|
// s += "* ";
|
|
// writePrec = (UInt32)(Int32)-1;
|
|
}
|
|
if (prec == kTimePrec_Win) AddTimeOption(s, 100, NsString, "Windows");
|
|
else if (prec == kTimePrec_Unix) AddTimeOption(s, 1, SecString, "Unix");
|
|
else if (prec == kTimePrec_DOS) AddTimeOption(s, 2, SecString, "DOS");
|
|
else if (prec == kTimePrec_1ns) AddTimeOption(s, 1, NsString, "Linux");
|
|
else if (prec == k_PropVar_TimePrec_Base) AddTimeOption(s, 1, SecString);
|
|
else if (prec >= k_PropVar_TimePrec_Base)
|
|
{
|
|
UInt32 d = 1;
|
|
for (unsigned i = prec; i < k_PropVar_TimePrec_Base + 9; i++)
|
|
d *= 10;
|
|
AddTimeOption(s, d, NsString);
|
|
}
|
|
else
|
|
s.Add_UInt32(prec);
|
|
const int index = (int)m_Prec.AddString(s);
|
|
m_Prec.SetItemData(index, (LPARAM)writePrec);
|
|
return index;
|
|
}
|
|
|
|
|
|
void COptionsDialog::SetPrec()
|
|
{
|
|
// const CFormatInfo &fi = g_Formats[cd->GetStaticFormatIndex()];
|
|
const CArcInfoEx &ai = cd->Get_ArcInfoEx();
|
|
|
|
// UInt32 flags = fi.Flags;
|
|
|
|
UInt32 flags = ai.Get_TimePrecFlags();
|
|
UInt32 defaultPrec = ai.Get_DefaultTimePrec();
|
|
if (defaultPrec != 0)
|
|
flags |= ((UInt32)1 << defaultPrec);
|
|
|
|
// const NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
|
|
|
|
// unsigned defaultPrec = kTimePrec_Win;
|
|
|
|
if (ai.Is_GZip())
|
|
defaultPrec = kTimePrec_Unix;
|
|
|
|
{
|
|
UString s;
|
|
s += GetNameOfProperty(kpidType, L"type");
|
|
s += ": ";
|
|
s += ai.Name;
|
|
if (ai.Is_Tar())
|
|
{
|
|
const int methodID = cd->GetMethodID();
|
|
|
|
// for debug
|
|
// defaultPrec = kTimePrec_Unix;
|
|
// flags = (UInt32)1 << kTimePrec_Unix;
|
|
|
|
s += ":";
|
|
if (methodID >= 0 && (unsigned)methodID < Z7_ARRAY_SIZE(kMethodsNames))
|
|
s += kMethodsNames[methodID];
|
|
if (methodID == kPosix)
|
|
{
|
|
// for debug
|
|
// flags |= (UInt32)1 << kTimePrec_Win;
|
|
// flags |= (UInt32)1 << kTimePrec_1ns;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if (is_for_MethodChanging) return;
|
|
}
|
|
|
|
SetItemText(IDT_COMPRESS_TIME_INFO, s);
|
|
}
|
|
|
|
m_Prec.ResetContent();
|
|
_auto_Prec = defaultPrec;
|
|
|
|
unsigned selectedPrec = defaultPrec;
|
|
{
|
|
// if (TimePrec >= kTimePrec_Win && TimePrec <= kTimePrec_DOS)
|
|
if ((Int32)TimePrec >= 0)
|
|
selectedPrec = TimePrec;
|
|
}
|
|
|
|
int curSel = -1;
|
|
int defaultPrecIndex = -1;
|
|
for (unsigned prec = 0;
|
|
// prec <= k_PropVar_TimePrec_HighPrec;
|
|
prec <= k_PropVar_TimePrec_1ns;
|
|
prec++)
|
|
{
|
|
if (((flags >> prec) & 1) == 0)
|
|
continue;
|
|
const bool isDefault = (defaultPrec == prec);
|
|
const int index = AddPrec(prec, isDefault);
|
|
if (isDefault)
|
|
defaultPrecIndex = index;
|
|
if (selectedPrec == prec)
|
|
curSel = index;
|
|
}
|
|
|
|
if (curSel < 0 && selectedPrec > kTimePrec_DOS)
|
|
curSel = AddPrec(selectedPrec, false); // isDefault
|
|
if (curSel < 0)
|
|
curSel = defaultPrecIndex;
|
|
if (curSel >= 0)
|
|
m_Prec.SetCurSel(curSel);
|
|
|
|
{
|
|
const bool isSet = IsSet_TimePrec();
|
|
const int count = m_Prec.GetCount();
|
|
const bool showPrec = (count != 0);
|
|
ShowItem_Bool(IDC_COMPRESS_TIME_PREC, showPrec);
|
|
ShowItem_Bool(IDT_COMPRESS_TIME_PREC, showPrec);
|
|
EnableItem(IDC_COMPRESS_TIME_PREC, isSet && (count > 1));
|
|
|
|
CheckButton(IDX_COMPRESS_PREC_SET, isSet);
|
|
const bool setIsSupported = isSet || (count > 1);
|
|
EnableItem(IDX_COMPRESS_PREC_SET, setIsSupported);
|
|
ShowItem_Bool(IDX_COMPRESS_PREC_SET, setIsSupported);
|
|
}
|
|
|
|
SetTimeMAC();
|
|
}
|
|
|
|
|
|
void COptionsDialog::SetTimeMAC()
|
|
{
|
|
const CArcInfoEx &ai = cd->Get_ArcInfoEx();
|
|
|
|
const
|
|
bool m_allow = ai.Flags_MTime();
|
|
bool c_allow = ai.Flags_CTime();
|
|
bool a_allow = ai.Flags_ATime();
|
|
|
|
if (ai.Is_Tar())
|
|
{
|
|
const int methodID = cd->GetMethodID();
|
|
c_allow = false;
|
|
a_allow = false;
|
|
if (methodID == kPosix)
|
|
{
|
|
// c_allow = true; // do we need it as change time ?
|
|
a_allow = true;
|
|
}
|
|
}
|
|
|
|
if (ai.Is_Zip())
|
|
{
|
|
// const int methodID = GetMethodID();
|
|
UInt32 prec = GetPrec();
|
|
if (prec == (UInt32)(Int32)-1)
|
|
prec = _auto_Prec;
|
|
if (prec != kTimePrec_Win)
|
|
{
|
|
c_allow = false;
|
|
a_allow = false;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
MTime.DefaultVal = true;
|
|
CTime.DefaultVal = false;
|
|
ATime.DefaultVal = false;
|
|
*/
|
|
|
|
MTime.DefaultVal = ai.Flags_MTime_Default();
|
|
CTime.DefaultVal = ai.Flags_CTime_Default();
|
|
ATime.DefaultVal = ai.Flags_ATime_Default();
|
|
|
|
ZTime.DefaultVal = false;
|
|
|
|
const NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
|
|
|
|
CheckButton_BoolBox (m_allow, fo.MTime, MTime );
|
|
CheckButton_BoolBox (c_allow, fo.CTime, CTime );
|
|
CheckButton_BoolBox (a_allow, fo.ATime, ATime );
|
|
CheckButton_BoolBox (true, fo.SetArcMTime, ZTime);
|
|
|
|
if (m_allow && !fo.MTime.Def)
|
|
{
|
|
const bool isSingleFile = ai.Flags_KeepName();
|
|
if (!isSingleFile)
|
|
{
|
|
// we can hide changing checkboxes for MTime here:
|
|
ShowItem_Bool (MTime.Set_Id, false);
|
|
EnableItem (MTime.Id, false);
|
|
}
|
|
}
|
|
// On_CheckBoxSet_Prec_Clicked();
|
|
// const bool isSingleFile = ai.Flags_KeepName();
|
|
// mtime for Gz can be
|
|
}
|
|
|
|
|
|
|
|
void COptionsDialog::On_CheckBoxSet_Prec_Clicked()
|
|
{
|
|
const bool isSet = IsButtonCheckedBool(IDX_COMPRESS_PREC_SET);
|
|
if (!isSet)
|
|
{
|
|
// We save current MAC boxes to memory before SetPrec()
|
|
Store_TimeBoxes();
|
|
Reset_TimePrec();
|
|
SetPrec();
|
|
}
|
|
EnableItem(IDC_COMPRESS_TIME_PREC, isSet);
|
|
}
|
|
|
|
void COptionsDialog::On_CheckBoxSet_Clicked(const CBoolBox &bb)
|
|
{
|
|
const bool isSet = IsButtonCheckedBool(bb.Set_Id);
|
|
if (!isSet)
|
|
CheckButton(bb.Id, bb.DefaultVal);
|
|
EnableItem(bb.Id, isSet);
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef Z7_LANG
|
|
static const UInt32 kLangIDs_Options[] =
|
|
{
|
|
IDX_COMPRESS_NT_SYM_LINKS,
|
|
IDX_COMPRESS_NT_HARD_LINKS,
|
|
IDX_COMPRESS_NT_ALT_STREAMS,
|
|
IDX_COMPRESS_NT_SECUR,
|
|
|
|
IDG_COMPRESS_TIME,
|
|
IDT_COMPRESS_TIME_PREC,
|
|
IDX_COMPRESS_MTIME,
|
|
IDX_COMPRESS_CTIME,
|
|
IDX_COMPRESS_ATIME,
|
|
IDX_COMPRESS_ZTIME,
|
|
IDX_COMPRESS_PRESERVE_ATIME
|
|
};
|
|
#endif
|
|
|
|
|
|
bool COptionsDialog::OnInit()
|
|
{
|
|
#ifdef Z7_LANG
|
|
LangSetWindowText(*this, IDB_COMPRESS_OPTIONS); // IDS_OPTIONS
|
|
LangSetDlgItems(*this, kLangIDs_Options, Z7_ARRAY_SIZE(kLangIDs_Options));
|
|
// LangSetDlgItemText(*this, IDB_COMPRESS_TIME_DEFAULT, IDB_COMPRESS_TIME_DEFAULT);
|
|
// LangSetDlgItemText(*this, IDX_COMPRESS_TIME_DEFAULT, IDX_COMPRESS_TIME_DEFAULT);
|
|
#endif
|
|
|
|
LangString(IDS_COMPRESS_SEC, SecString);
|
|
if (SecString.IsEmpty())
|
|
SecString = "sec";
|
|
LangString(IDS_COMPRESS_NS, NsString);
|
|
if (NsString.IsEmpty())
|
|
NsString = "ns";
|
|
|
|
{
|
|
// const CArcInfoEx &ai = cd->Get_ArcInfoEx();
|
|
|
|
ShowItem_Bool ( IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks.Supported);
|
|
ShowItem_Bool ( IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks.Supported);
|
|
ShowItem_Bool ( IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams.Supported);
|
|
ShowItem_Bool ( IDX_COMPRESS_NT_SECUR, cd->NtSecurity.Supported);
|
|
|
|
ShowItem_Bool ( IDG_COMPRESS_NTFS,
|
|
cd->SymLinks.Supported
|
|
|| cd->HardLinks.Supported
|
|
|| cd->AltStreams.Supported
|
|
|| cd->NtSecurity.Supported);
|
|
}
|
|
|
|
/* we read property from two sources:
|
|
1) command line : (Info)
|
|
2) registry : (m_RegistryInfo)
|
|
(Info) has priority, if both are no defined */
|
|
|
|
CheckButton_Bool1 ( IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks);
|
|
CheckButton_Bool1 ( IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks);
|
|
CheckButton_Bool1 ( IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams);
|
|
CheckButton_Bool1 ( IDX_COMPRESS_NT_SECUR, cd->NtSecurity);
|
|
|
|
CheckButton_Bool1 (IDX_COMPRESS_PRESERVE_ATIME, cd->PreserveATime);
|
|
|
|
m_Prec.Attach (GetItem(IDC_COMPRESS_TIME_PREC));
|
|
|
|
MTime.SetIDs ( IDX_COMPRESS_MTIME, IDX_COMPRESS_MTIME_SET);
|
|
CTime.SetIDs ( IDX_COMPRESS_CTIME, IDX_COMPRESS_CTIME_SET);
|
|
ATime.SetIDs ( IDX_COMPRESS_ATIME, IDX_COMPRESS_ATIME_SET);
|
|
ZTime.SetIDs ( IDX_COMPRESS_ZTIME, IDX_COMPRESS_ZTIME_SET);
|
|
|
|
{
|
|
const NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
|
|
TimePrec = fo.TimePrec;
|
|
MTime.BoolPair = fo.MTime;
|
|
CTime.BoolPair = fo.CTime;
|
|
ATime.BoolPair = fo.ATime;
|
|
ZTime.BoolPair = fo.SetArcMTime;
|
|
}
|
|
|
|
SetPrec();
|
|
|
|
NormalizePosition();
|
|
|
|
return CModalDialog::OnInit();
|
|
}
|
|
|
|
|
|
bool COptionsDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam)
|
|
{
|
|
if (code == CBN_SELCHANGE)
|
|
{
|
|
switch (itemID)
|
|
{
|
|
case IDC_COMPRESS_TIME_PREC:
|
|
{
|
|
Store_TimeBoxes();
|
|
SetTimeMAC(); // for zip/tar
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return CModalDialog::OnCommand(code, itemID, lParam);
|
|
}
|
|
|
|
|
|
bool COptionsDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
|
|
{
|
|
switch (buttonID)
|
|
{
|
|
case IDX_COMPRESS_PREC_SET: { On_CheckBoxSet_Prec_Clicked(); return true; }
|
|
case IDX_COMPRESS_MTIME_SET: { On_CheckBoxSet_Clicked (MTime); return true; }
|
|
case IDX_COMPRESS_CTIME_SET: { On_CheckBoxSet_Clicked (CTime); return true; }
|
|
case IDX_COMPRESS_ATIME_SET: { On_CheckBoxSet_Clicked (ATime); return true; }
|
|
case IDX_COMPRESS_ZTIME_SET: { On_CheckBoxSet_Clicked (ZTime); return true; }
|
|
}
|
|
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
|
|
}
|
|
|
|
|
|
void COptionsDialog::OnOK()
|
|
{
|
|
GetButton_Bool1 (IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks);
|
|
GetButton_Bool1 (IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks);
|
|
GetButton_Bool1 (IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams);
|
|
GetButton_Bool1 (IDX_COMPRESS_NT_SECUR, cd->NtSecurity);
|
|
GetButton_Bool1 (IDX_COMPRESS_PRESERVE_ATIME, cd->PreserveATime);
|
|
|
|
Store_TimeBoxes();
|
|
{
|
|
NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
|
|
fo.TimePrec = TimePrec;
|
|
fo.MTime = MTime.BoolPair;
|
|
fo.CTime = CTime.BoolPair;
|
|
fo.ATime = ATime.BoolPair;
|
|
fo.SetArcMTime = ZTime.BoolPair;
|
|
}
|
|
|
|
CModalDialog::OnOK();
|
|
}
|
|
|
|
void COptionsDialog::OnHelp()
|
|
{
|
|
ShowHelpWindow(kHelpTopic_Options);
|
|
}
|