1 // CompressDialog.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "Common/Defs.h"
6 #include "Common/IntToString.h"
7 #include "Common/StringConvert.h"
8 
9 #include "Windows/CommonDialog.h"
10 #include "Windows/FileDir.h"
11 #include "Windows/FileName.h"
12 #include "Windows/ResourceString.h"
13 #include "Windows/System.h"
14 
15 #include "../FileManager/FormatUtils.h"
16 #include "../FileManager/HelpUtils.h"
17 #include "../FileManager/SplitUtils.h"
18 
19 #include "../Explorer/MyMessages.h"
20 
21 #include "../Common/ZipRegistry.h"
22 
23 #include "CompressDialog.h"
24 
25 #include "resource.h"
26 
27 #ifndef _UNICODE
28 extern bool g_IsNT;
29 #endif
30 
31 #ifdef LANG
32 #include "../FileManager/LangUtils.h"
33 #endif
34 
35 #include "CompressDialogRes.h"
36 
37 #define MY_SIZE_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
38 
39 #ifdef LANG
40 static CIDLangPair kIDLangPairs[] =
41 {
42   { IDC_STATIC_COMPRESS_ARCHIVE, 0x02000D01 },
43   { IDC_STATIC_COMPRESS_FORMAT, 0x02000D03 },
44   { IDC_STATIC_COMPRESS_LEVEL, 0x02000D0B },
45   { IDC_STATIC_COMPRESS_METHOD, 0x02000D04 },
46   { IDC_STATIC_COMPRESS_DICTIONARY, 0x02000D0C },
47   { IDC_STATIC_COMPRESS_ORDER, 0x02000D0D },
48   { IDC_STATIC_COMPRESS_MEMORY, 0x02000D0E },
49   { IDC_STATIC_COMPRESS_MEMORY_DE, 0x02000D0F },
50   { IDC_STATIC_COMPRESS_THREADS, 0x02000D12 },
51   { IDC_STATIC_COMPRESS_SOLID, 0x02000D13 },
52   { IDC_STATIC_COMPRESS_VOLUME, 0x02000D40 },
53   { IDC_STATIC_COMPRESS_PARAMETERS, 0x02000D06 },
54 
55   { IDC_STATIC_COMPRESS_UPDATE_MODE, 0x02000D02 },
56   { IDC_STATIC_COMPRESS_OPTIONS, 0x02000D07 },
57   { IDC_COMPRESS_SFX, 0x02000D08 },
58   { IDC_COMPRESS_SHARED, 0x02000D16 },
59 
60   { IDC_COMPRESS_ENCRYPTION, 0x02000D10 },
61   { IDC_STATIC_COMPRESS_PASSWORD1, 0x02000B01 },
62   { IDC_STATIC_COMPRESS_PASSWORD2, 0x02000B03 },
63   { IDC_COMPRESS_CHECK_SHOW_PASSWORD, 0x02000B02 },
64   { IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, 0x02000D11 },
65   { IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, 0x02000D0A },
66 
67   { IDOK, 0x02000702 },
68   { IDCANCEL, 0x02000710 },
69   { IDHELP, 0x02000720 }
70 };
71 #endif
72 
73 using namespace NWindows;
74 using namespace NFile;
75 using namespace NName;
76 using namespace NDirectory;
77 
78 static const int kHistorySize = 20;
79 
80 static LPCWSTR kExeExt = L".exe";
81 static LPCWSTR k7zFormat = L"7z";
82 
83 struct CLevelInfo
84 {
85   UInt32 ResourceID;
86   UInt32 LangID;
87 };
88 
89 enum ELevel
90 {
91   kStore = 0,
92   kFastest = 1,
93   kFast = 3,
94   kNormal = 5,
95   kMaximum = 7,
96   kUltra = 9
97 };
98 
99 static const CLevelInfo g_Levels[] =
100 {
101   { IDS_METHOD_STORE, 0x02000D81 },
102   { IDS_METHOD_FASTEST, 0x02000D85 },
103   { 0, 0 },
104   { IDS_METHOD_FAST, 0x02000D84 },
105   { 0, 0 },
106   { IDS_METHOD_NORMAL, 0x02000D82 },
107   { 0, 0 },
108   { IDS_METHOD_MAXIMUM, 0x02000D83 },
109   { 0, 0 },
110   { IDS_METHOD_ULTRA, 0x02000D86 }
111 };
112 
113 enum EMethodID
114 {
115   kCopy,
116   kLZMA,
117   kLZMA2,
118   kPPMd,
119   kBZip2,
120   kDeflate,
121   kDeflate64
122 };
123 
124 static const LPCWSTR kMethodsNames[] =
125 {
126   L"Copy",
127   L"LZMA",
128   L"LZMA2",
129   L"PPMd",
130   L"BZip2",
131   L"Deflate",
132   L"Deflate64"
133 };
134 
135 static const EMethodID g_7zMethods[] =
136 {
137   kLZMA,
138   kLZMA2,
139   kPPMd,
140   kBZip2
141 };
142 
143 static const EMethodID g_7zSfxMethods[] =
144 {
145   kCopy,
146   kLZMA,
147   kLZMA2,
148   kPPMd
149 };
150 
151 static EMethodID g_ZipMethods[] =
152 {
153   kDeflate,
154   kDeflate64,
155   kBZip2,
156   kLZMA
157 };
158 
159 static EMethodID g_GZipMethods[] =
160 {
161   kDeflate
162 };
163 
164 static EMethodID g_BZip2Methods[] =
165 {
166   kBZip2
167 };
168 
169 static EMethodID g_XzMethods[] =
170 {
171   kLZMA2
172 };
173 
174 struct CFormatInfo
175 {
176   LPCWSTR Name;
177   UInt32 LevelsMask;
178   const EMethodID *MathodIDs;
179   int NumMethods;
180   bool Filter;
181   bool Solid;
182   bool MultiThread;
183   bool SFX;
184   bool Encrypt;
185   bool EncryptFileNames;
186 };
187 
188 #define METHODS_PAIR(x) x, MY_SIZE_OF_ARRAY(x)
189 
190 static const CFormatInfo g_Formats[] =
191 {
192   {
193     L"",
194     (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
195     0, 0,
196     false, false, false, false, false, false
197   },
198   {
199     k7zFormat,
200     (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
201     METHODS_PAIR(g_7zMethods),
202     true, true, true, true, true, true
203   },
204   {
205     L"Zip",
206     (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
207     METHODS_PAIR(g_ZipMethods),
208     false, false, true, false, true, false
209   },
210   {
211     L"GZip",
212     (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9),
213     METHODS_PAIR(g_GZipMethods),
214     false, false, false, false, false, false
215   },
216   {
217     L"BZip2",
218     (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
219     METHODS_PAIR(g_BZip2Methods),
220     false, false, true, false, false, false
221   },
222   {
223     L"xz",
224     (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
225     METHODS_PAIR(g_XzMethods),
226     false, false, true, false, false, false
227   },
228   {
229     L"Tar",
230     (1 << 0),
231     0, 0,
232     false, false, false, false, false, false
233   }
234 };
235 
IsMethodSupportedBySfx(int methodID)236 static bool IsMethodSupportedBySfx(int methodID)
237 {
238   for (int i = 0; i < MY_SIZE_OF_ARRAY(g_7zSfxMethods); i++)
239     if (methodID == g_7zSfxMethods[i])
240       return true;
241   return false;
242 };
243 
GetMaxRamSizeForProgram()244 static UInt64 GetMaxRamSizeForProgram()
245 {
246   UInt64 physSize = NSystem::GetRamSize();
247   const UInt64 kMinSysSize = (1 << 24);
248   if (physSize <= kMinSysSize)
249     physSize = 0;
250   else
251     physSize -= kMinSysSize;
252   const UInt64 kMinUseSize = (1 << 25);
253   if (physSize < kMinUseSize)
254     physSize = kMinUseSize;
255   return physSize;
256 }
257 
OnInit()258 bool CCompressDialog::OnInit()
259 {
260   #ifdef LANG
261   LangSetWindowText(HWND(*this), 0x02000D00);
262   LangSetDlgItemsText(HWND(*this), kIDLangPairs, MY_SIZE_OF_ARRAY(kIDLangPairs) );
263   #endif
264   _password1Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD1));
265   _password2Control.Attach(GetItem(IDC_COMPRESS_EDIT_PASSWORD2));
266   _password1Control.SetText(Info.Password);
267   _password2Control.SetText(Info.Password);
268   _encryptionMethod.Attach(GetItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD));
269 
270   m_ArchivePath.Attach(GetItem(IDC_COMPRESS_COMBO_ARCHIVE));
271   m_Format.Attach(GetItem(IDC_COMPRESS_COMBO_FORMAT));
272   m_Level.Attach(GetItem(IDC_COMPRESS_COMBO_LEVEL));
273   m_Method.Attach(GetItem(IDC_COMPRESS_COMBO_METHOD));
274   m_Dictionary.Attach(GetItem(IDC_COMPRESS_COMBO_DICTIONARY));
275   m_Order.Attach(GetItem(IDC_COMPRESS_COMBO_ORDER));
276   m_Solid.Attach(GetItem(IDC_COMPRESS_COMBO_SOLID));
277   m_NumThreads.Attach(GetItem(IDC_COMPRESS_COMBO_THREADS));
278 
279   m_UpdateMode.Attach(GetItem(IDC_COMPRESS_COMBO_UPDATE_MODE));
280   m_Volume.Attach(GetItem(IDC_COMPRESS_COMBO_VOLUME));
281   m_Params.Attach(GetItem(IDC_COMPRESS_EDIT_PARAMETERS));
282 
283   AddVolumeItems(m_Volume);
284 
285   ReadCompressionInfo(m_RegistryInfo);
286   CheckButton(IDC_COMPRESS_CHECK_SHOW_PASSWORD, m_RegistryInfo.ShowPassword);
287   CheckButton(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders);
288 
289   UpdatePasswordControl();
290 
291   Info.ArchiverInfoIndex = 0;
292   int i;
293   for (i = 0; i < m_ArchiverInfoList.Size(); i++)
294   {
295     const CArcInfoEx &ai = m_ArchiverInfoList[i];
296     int index = (int)m_Format.AddString(ai.Name);
297     m_Format.SetItemData(index, i);
298     if (ai.Name.CompareNoCase(m_RegistryInfo.ArchiveType) == 0 || i == 0)
299     {
300       m_Format.SetCurSel(index);
301       Info.ArchiverInfoIndex = i;
302     }
303   }
304 
305   SetArchiveName(Info.ArchiveName);
306   SetLevel();
307   SetParams();
308 
309   for (i = 0; i < m_RegistryInfo.HistoryArchives.Size() && i < kHistorySize; i++)
310     m_ArchivePath.AddString(m_RegistryInfo.HistoryArchives[i]);
311 
312   m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_ADD, 0x02000DA1));
313   m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_UPDATE, 0x02000DA2));
314   m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_FRESH, 0x02000DA3));
315   m_UpdateMode.AddString(LangString(IDS_COMPRESS_UPDATE_MODE_SYNCHRONIZE, 0x02000DA4));
316 
317   m_UpdateMode.SetCurSel(0);
318 
319   SetSolidBlockSize();
320   SetNumThreads();
321 
322   TCHAR s[40] = { TEXT('/'), TEXT(' '), 0 };
323   ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
324   SetItemText(IDC_COMPRESS_HARDWARE_THREADS, s);
325 
326   CheckButton(IDC_COMPRESS_SFX, Info.SFXMode);
327   CheckButton(IDC_COMPRESS_SHARED, Info.OpenShareForWrite);
328 
329   CheckControlsEnable();
330 
331   OnButtonSFX();
332 
333   SetEncryptionMethod();
334   SetMemoryUsage();
335   return CModalDialog::OnInit();
336 }
337 
338 namespace NCompressDialog
339 {
GetFullPathName(UString & result) const340   bool CInfo::GetFullPathName(UString &result) const
341   {
342     NDirectory::MySetCurrentDirectory(CurrentDirPrefix);
343     return MyGetFullPathName(ArchiveName, result);
344   }
345 }
346 
UpdatePasswordControl()347 void CCompressDialog::UpdatePasswordControl()
348 {
349   bool showPassword = IsShowPasswordChecked();
350   TCHAR c = showPassword ? 0: TEXT('*');
351   _password1Control.SetPasswordChar(c);
352   _password2Control.SetPasswordChar(c);
353   UString password;
354   _password1Control.GetText(password);
355   _password1Control.SetText(password);
356   _password2Control.GetText(password);
357   _password2Control.SetText(password);
358 
359   int cmdShow = showPassword ? SW_HIDE : SW_SHOW;
360   ShowItem(IDC_STATIC_COMPRESS_PASSWORD2, cmdShow);
361   _password2Control.Show(cmdShow);
362 }
363 
OnButtonClicked(int buttonID,HWND buttonHWND)364 bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
365 {
366   switch(buttonID)
367   {
368     case IDC_COMPRESS_BUTTON_SET_ARCHIVE:
369     {
370       OnButtonSetArchive();
371       return true;
372     }
373     case IDC_COMPRESS_SFX:
374     {
375       OnButtonSFX();
376       SetMemoryUsage();
377       return true;
378     }
379     case IDC_COMPRESS_CHECK_SHOW_PASSWORD:
380     {
381       UpdatePasswordControl();
382       return true;
383     }
384   }
385   return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
386 }
387 
CheckSFXControlsEnable()388 void CCompressDialog::CheckSFXControlsEnable()
389 {
390   const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
391   bool enable = fi.SFX;
392   if (enable)
393   {
394     int methodID = GetMethodID();
395     enable = (methodID == -1 || IsMethodSupportedBySfx(methodID));
396   }
397   if (!enable)
398     CheckButton(IDC_COMPRESS_SFX, false);
399   EnableItem(IDC_COMPRESS_SFX, enable);
400 }
401 
CheckVolumeEnable()402 void CCompressDialog::CheckVolumeEnable()
403 {
404   bool isSFX = IsSFX();
405   m_Volume.Enable(!isSFX);
406   if (isSFX)
407     m_Volume.SetText(TEXT(""));
408 }
409 
CheckControlsEnable()410 void CCompressDialog::CheckControlsEnable()
411 {
412   const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
413   Info.SolidIsSpecified = fi.Solid;
414   bool multiThreadEnable = fi.MultiThread;
415   Info.MultiThreadIsAllowed = multiThreadEnable;
416   Info.EncryptHeadersIsAllowed = fi.EncryptFileNames;
417 
418   EnableItem(IDC_COMPRESS_COMBO_SOLID, fi.Solid);
419   EnableItem(IDC_COMPRESS_COMBO_THREADS, multiThreadEnable);
420   CheckSFXControlsEnable();
421   CheckVolumeEnable();
422 
423   EnableItem(IDC_COMPRESS_ENCRYPTION, fi.Encrypt);
424 
425   EnableItem(IDC_STATIC_COMPRESS_PASSWORD1, fi.Encrypt);
426   EnableItem(IDC_STATIC_COMPRESS_PASSWORD2, fi.Encrypt);
427   EnableItem(IDC_COMPRESS_EDIT_PASSWORD1, fi.Encrypt);
428   EnableItem(IDC_COMPRESS_EDIT_PASSWORD2, fi.Encrypt);
429   EnableItem(IDC_COMPRESS_CHECK_SHOW_PASSWORD, fi.Encrypt);
430 
431   EnableItem(IDC_STATIC_COMPRESS_ENCRYPTION_METHOD, fi.Encrypt);
432   EnableItem(IDC_COMPRESS_COMBO_ENCRYPTION_METHOD, fi.Encrypt);
433   EnableItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames);
434 
435   ShowItem(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES, fi.EncryptFileNames ? SW_SHOW : SW_HIDE);
436 }
437 
IsSFX()438 bool CCompressDialog::IsSFX()
439 {
440   CWindow sfxButton = GetItem(IDC_COMPRESS_SFX);
441   return sfxButton.IsEnabled() && IsButtonCheckedBool(IDC_COMPRESS_SFX);
442 }
443 
OnButtonSFX()444 void CCompressDialog::OnButtonSFX()
445 {
446   SetMethod(GetMethodID());
447 
448   UString fileName;
449   m_ArchivePath.GetText(fileName);
450   int dotPos = fileName.ReverseFind(L'.');
451   int slashPos = fileName.ReverseFind(WCHAR_PATH_SEPARATOR);
452   if (dotPos < 0 || dotPos <= slashPos)
453     dotPos = -1;
454   if (IsSFX())
455   {
456     if (dotPos >= 0)
457       fileName = fileName.Left(dotPos);
458     fileName += kExeExt;
459     m_ArchivePath.SetText(fileName);
460   }
461   else
462   {
463     if (dotPos >= 0)
464     {
465       UString ext = fileName.Mid(dotPos);
466       if (ext.CompareNoCase(kExeExt) == 0)
467       {
468         fileName = fileName.Left(dotPos);
469         m_ArchivePath.SetText(fileName);
470       }
471     }
472     SetArchiveName2(false); // it's for OnInit
473   }
474 
475   CheckVolumeEnable();
476 }
477 
OnButtonSetArchive()478 void CCompressDialog::OnButtonSetArchive()
479 {
480   UString fileName;
481   m_ArchivePath.GetText(fileName);
482   fileName.Trim();
483   Info.ArchiveName = fileName;
484   UString fullFileName;
485   if (!Info.GetFullPathName(fullFileName))
486   {
487     fullFileName = Info.ArchiveName;
488     return;
489   }
490   UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_DIALOG_TITLE, 0x02000D90);
491   UString s = LangString(IDS_OPEN_TYPE_ALL_FILES, 0x02000DB1);
492   s += L" (*.*)";
493   UString resPath;
494   if (!MyGetOpenFileName(HWND(*this), title, fullFileName, s, resPath))
495     return;
496   m_ArchivePath.SetText(resPath);
497 }
498 
499 // in ExtractDialog.cpp
500 extern void AddUniqueString(UStringVector &strings, const UString &srcString);
501 
IsAsciiString(const UString & s)502 static bool IsAsciiString(const UString &s)
503 {
504   for (int i = 0; i < s.Length(); i++)
505   {
506     wchar_t c = s[i];
507     if (c < 0x20 || c > 0x7F)
508       return false;
509   }
510   return true;
511 }
512 
OnOK()513 void CCompressDialog::OnOK()
514 {
515   _password1Control.GetText(Info.Password);
516   if (IsZipFormat())
517   {
518     if (!IsAsciiString(Info.Password))
519     {
520       ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII, 0x02000B11);
521       return;
522     }
523     UString method = GetEncryptionMethodSpec();
524     method.MakeUpper();
525     if (method.Find(L"AES") == 0)
526     {
527       if (Info.Password.Length() > 99)
528       {
529         ShowErrorMessageHwndRes(*this, IDS_PASSWORD_IS_TOO_LONG, 0x02000B12);
530         return;
531       }
532     }
533   }
534   if (!IsShowPasswordChecked())
535   {
536     UString password2;
537     _password2Control.GetText(password2);
538     if (password2 != Info.Password)
539     {
540       ShowErrorMessageHwndRes(*this, IDS_PASSWORD_PASSWORDS_DO_NOT_MATCH, 0x02000B10);
541       return;
542     }
543   }
544 
545   SaveOptionsInMem();
546   UString s;
547   m_ArchivePath.GetText(s);
548   s.Trim();
549   m_RegistryInfo.HistoryArchives.Clear();
550   AddUniqueString(m_RegistryInfo.HistoryArchives, s);
551   Info.ArchiveName = s;
552   Info.UpdateMode = NCompressDialog::NUpdateMode::EEnum(m_UpdateMode.GetCurSel());
553 
554   Info.Level = GetLevelSpec();
555   Info.Dictionary = GetDictionarySpec();
556   Info.Order = GetOrderSpec();
557   Info.OrderMode = GetOrderMode();
558   Info.NumThreads = GetNumThreadsSpec();
559 
560   UInt32 solidLogSize = GetBlockSizeSpec();
561   Info.SolidBlockSize = 0;
562   if (solidLogSize > 0 && solidLogSize != (UInt32)-1)
563     Info.SolidBlockSize = (solidLogSize >= 64) ? (UInt64)(Int64)-1 : ((UInt64)1 << solidLogSize);
564 
565   Info.Method = GetMethodSpec();
566   Info.EncryptionMethod = GetEncryptionMethodSpec();
567   Info.ArchiverInfoIndex = GetFormatIndex();
568   Info.SFXMode = IsSFX();
569   Info.OpenShareForWrite = IsButtonCheckedBool(IDC_COMPRESS_SHARED);
570 
571   m_RegistryInfo.EncryptHeaders = Info.EncryptHeaders = IsButtonCheckedBool(IDC_COMPRESS_CHECK_ENCRYPT_FILE_NAMES);
572 
573   m_Params.GetText(Info.Options);
574   UString volumeString;
575   m_Volume.GetText(volumeString);
576   volumeString.Trim();
577   Info.VolumeSizes.Clear();
578   if (!volumeString.IsEmpty())
579   {
580     if (!ParseVolumeSizes(volumeString, Info.VolumeSizes))
581     {
582       ShowErrorMessageHwndRes(*this, IDS_COMPRESS_INCORRECT_VOLUME_SIZE, 0x02000D41);
583       return;
584     }
585     if (!Info.VolumeSizes.IsEmpty())
586     {
587       const UInt64 volumeSize = Info.VolumeSizes.Back();
588       if (volumeSize < (100 << 10))
589       {
590         wchar_t s[32];
591         ConvertUInt64ToString(volumeSize, s);
592         if (::MessageBoxW(*this, MyFormatNew(IDS_COMPRESS_SPLIT_CONFIRM_MESSAGE, 0x02000D42, s),
593             L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION | MB_TASKMODAL) != IDYES)
594           return;
595       }
596     }
597   }
598 
599   for (int i = 0; i < m_ArchivePath.GetCount(); i++)
600   {
601     UString sTemp;
602     m_ArchivePath.GetLBText(i, sTemp);
603     sTemp.Trim();
604     AddUniqueString(m_RegistryInfo.HistoryArchives, sTemp);
605   }
606   if (m_RegistryInfo.HistoryArchives.Size() > kHistorySize)
607     m_RegistryInfo.HistoryArchives.DeleteBack();
608 
609   m_RegistryInfo.ArchiveType = m_ArchiverInfoList[Info.ArchiverInfoIndex].Name;
610   m_RegistryInfo.ShowPassword = IsShowPasswordChecked();
611 
612   SaveCompressionInfo(m_RegistryInfo);
613 
614   CModalDialog::OnOK();
615 }
616 
617 static LPCWSTR kHelpTopic = L"fm/plugins/7-zip/add.htm";
618 
OnHelp()619 void CCompressDialog::OnHelp()
620 {
621   ShowHelpWindow(NULL, kHelpTopic);
622 }
623 
OnCommand(int code,int itemID,LPARAM lParam)624 bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
625 {
626   if (code == CBN_SELCHANGE)
627   {
628     switch(itemID)
629     {
630       case IDC_COMPRESS_COMBO_FORMAT:
631       {
632         bool isSFX = IsSFX();
633         SaveOptionsInMem();
634         SetLevel();
635         SetSolidBlockSize();
636         SetNumThreads();
637         SetParams();
638         CheckControlsEnable();
639         SetArchiveName2(isSFX);
640         SetEncryptionMethod();
641         SetMemoryUsage();
642         return true;
643       }
644       case IDC_COMPRESS_COMBO_LEVEL:
645       {
646         const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
647         int index = FindRegistryFormatAlways(ai.Name);
648         NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
649         fo.ResetForLevelChange();
650         SetMethod();
651         SetSolidBlockSize();
652         SetNumThreads();
653         CheckSFXNameChange();
654         SetMemoryUsage();
655         return true;
656       }
657       case IDC_COMPRESS_COMBO_METHOD:
658       {
659         SetDictionary();
660         SetOrder();
661         SetSolidBlockSize();
662         SetNumThreads();
663         CheckSFXNameChange();
664         SetMemoryUsage();
665         return true;
666       }
667       case IDC_COMPRESS_COMBO_DICTIONARY:
668       case IDC_COMPRESS_COMBO_ORDER:
669       {
670         SetSolidBlockSize();
671         SetMemoryUsage();
672         return true;
673       }
674       case IDC_COMPRESS_COMBO_THREADS:
675       {
676         SetMemoryUsage();
677         return true;
678       }
679     }
680   }
681   return CModalDialog::OnCommand(code, itemID, lParam);
682 }
683 
CheckSFXNameChange()684 void CCompressDialog::CheckSFXNameChange()
685 {
686   bool isSFX = IsSFX();
687   CheckSFXControlsEnable();
688   if (isSFX != IsSFX())
689     SetArchiveName2(isSFX);
690 }
691 
SetArchiveName2(bool prevWasSFX)692 void CCompressDialog::SetArchiveName2(bool prevWasSFX)
693 {
694   UString fileName;
695   m_ArchivePath.GetText(fileName);
696   const CArcInfoEx &prevArchiverInfo = m_ArchiverInfoList[m_PrevFormat];
697   if (prevArchiverInfo.KeepName || Info.KeepName)
698   {
699     UString prevExtension = prevArchiverInfo.GetMainExt();
700     if (prevWasSFX)
701       prevExtension = kExeExt;
702     else
703       prevExtension = UString('.') + prevExtension;
704     const int prevExtensionLen = prevExtension.Length();
705     if (fileName.Length() >= prevExtensionLen)
706       if (fileName.Right(prevExtensionLen).CompareNoCase(prevExtension) == 0)
707         fileName = fileName.Left(fileName.Length() - prevExtensionLen);
708   }
709   SetArchiveName(fileName);
710 }
711 
712 // if type.KeepName then use OriginalFileName
713 // else if !KeepName remove extension
714 // add new extension
715 
SetArchiveName(const UString & name)716 void CCompressDialog::SetArchiveName(const UString &name)
717 {
718   UString fileName = name;
719   Info.ArchiverInfoIndex = GetFormatIndex();
720   const CArcInfoEx &ai = m_ArchiverInfoList[Info.ArchiverInfoIndex];
721   m_PrevFormat = Info.ArchiverInfoIndex;
722   if (ai.KeepName)
723   {
724     fileName = OriginalFileName;
725   }
726   else
727   {
728     if (!Info.KeepName)
729     {
730       int dotPos = fileName.ReverseFind('.');
731       int slashPos = MyMax(fileName.ReverseFind(WCHAR_PATH_SEPARATOR), fileName.ReverseFind('/'));
732       if (dotPos >= 0 && dotPos > slashPos + 1)
733         fileName = fileName.Left(dotPos);
734     }
735   }
736 
737   if (IsSFX())
738     fileName += kExeExt;
739   else
740   {
741     fileName += L'.';
742     fileName += ai.GetMainExt();
743   }
744   m_ArchivePath.SetText(fileName);
745 }
746 
FindRegistryFormat(const UString & name)747 int CCompressDialog::FindRegistryFormat(const UString &name)
748 {
749   for (int i = 0; i < m_RegistryInfo.FormatOptionsVector.Size(); i++)
750   {
751     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[i];
752     if (GetUnicodeString(fo.FormatID) == name)
753       return i;
754   }
755   return -1;
756 }
757 
FindRegistryFormatAlways(const UString & name)758 int CCompressDialog::FindRegistryFormatAlways(const UString &name)
759 {
760   int index = FindRegistryFormat(name);
761   if (index < 0)
762   {
763     NCompression::CFormatOptions fo;
764     fo.FormatID = GetSystemString(name);
765     index = m_RegistryInfo.FormatOptionsVector.Add(fo);
766   }
767   return index;
768 }
769 
GetStaticFormatIndex()770 int CCompressDialog::GetStaticFormatIndex()
771 {
772   int formatIndex = GetFormatIndex();
773   const CArcInfoEx &ai = m_ArchiverInfoList[formatIndex];
774   for (int i = 0; i < MY_SIZE_OF_ARRAY(g_Formats); i++)
775     if (ai.Name.CompareNoCase(g_Formats[i].Name) == 0)
776       return i;
777   return 0; // -1;
778 }
779 
SetNearestSelectComboBox(NControl::CComboBox & comboBox,UInt32 value)780 void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value)
781 {
782   for (int i = comboBox.GetCount() - 1; i >= 0; i--)
783     if ((UInt32)comboBox.GetItemData(i) <= value)
784     {
785       comboBox.SetCurSel(i);
786       return;
787     }
788   if (comboBox.GetCount() > 0)
789     comboBox.SetCurSel(0);
790 }
791 
SetLevel()792 void CCompressDialog::SetLevel()
793 {
794   m_Level.ResetContent();
795   const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
796   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
797   int index = FindRegistryFormat(ai.Name);
798   UInt32 level = kNormal;
799   if (index >= 0)
800   {
801     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
802     if (fo.Level <= kUltra)
803       level = fo.Level;
804     else
805       level = kUltra;
806   }
807   int i;
808   for (i = 0; i <= kUltra; i++)
809   {
810     if ((fi.LevelsMask & (1 << i)) != 0)
811     {
812       const CLevelInfo &levelInfo = g_Levels[i];
813       int index = (int)m_Level.AddString(LangString(levelInfo.ResourceID, levelInfo.LangID));
814       m_Level.SetItemData(index, i);
815     }
816   }
817   SetNearestSelectComboBox(m_Level, level);
818   SetMethod();
819 }
820 
SetMethod(int keepMethodId)821 void CCompressDialog::SetMethod(int keepMethodId)
822 {
823   m_Method.ResetContent();
824   UInt32 level = GetLevel();
825   if (level == 0)
826   {
827     SetDictionary();
828     SetOrder();
829     return;
830   }
831   const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
832   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
833   int index = FindRegistryFormat(ai.Name);
834   UString defaultMethod;
835   if (index >= 0)
836   {
837     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
838     defaultMethod = fo.Method;
839   }
840   bool isSfx = IsSFX();
841   bool weUseSameMethod = false;
842   for (int m = 0; m < fi.NumMethods; m++)
843   {
844     EMethodID methodID = fi.MathodIDs[m];
845     if (isSfx)
846       if (!IsMethodSupportedBySfx(methodID))
847         continue;
848     const LPCWSTR method = kMethodsNames[methodID];
849     int itemIndex = (int)m_Method.AddString(GetSystemString(method));
850     if (keepMethodId == methodID)
851     {
852       m_Method.SetCurSel(itemIndex);
853       weUseSameMethod = true;
854       continue;
855     }
856     if ((defaultMethod.CompareNoCase(method) == 0 || m == 0) && !weUseSameMethod)
857       m_Method.SetCurSel(itemIndex);
858   }
859   if (!weUseSameMethod)
860   {
861     SetDictionary();
862     SetOrder();
863   }
864 }
865 
IsZipFormat()866 bool CCompressDialog::IsZipFormat()
867 {
868   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
869   return (ai.Name.CompareNoCase(L"zip") == 0);
870 }
871 
SetEncryptionMethod()872 void CCompressDialog::SetEncryptionMethod()
873 {
874   _encryptionMethod.ResetContent();
875   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
876   if (ai.Name.CompareNoCase(L"7z") == 0)
877   {
878     _encryptionMethod.AddString(TEXT("AES-256"));
879     _encryptionMethod.SetCurSel(0);
880   }
881   else if (ai.Name.CompareNoCase(L"zip") == 0)
882   {
883     int index = FindRegistryFormat(ai.Name);
884     UString encryptionMethod;
885     if (index >= 0)
886     {
887       const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
888       encryptionMethod = fo.EncryptionMethod;
889     }
890     _encryptionMethod.AddString(TEXT("ZipCrypto"));
891     _encryptionMethod.AddString(TEXT("AES-256"));
892     _encryptionMethod.SetCurSel(encryptionMethod.Find(L"AES") == 0 ? 1 : 0);
893   }
894 }
895 
GetMethodID()896 int CCompressDialog::GetMethodID()
897 {
898   UString methodName;
899   m_Method.GetText(methodName);
900   for (int i = 0; i < MY_SIZE_OF_ARRAY(kMethodsNames); i++)
901     if (methodName.CompareNoCase(kMethodsNames[i]) == 0)
902       return i;
903   return -1;
904 }
905 
GetMethodSpec()906 UString CCompressDialog::GetMethodSpec()
907 {
908   if (m_Method.GetCount() <= 1)
909     return UString();
910   UString result;
911   m_Method.GetText(result);
912   return result;
913 }
914 
GetEncryptionMethodSpec()915 UString CCompressDialog::GetEncryptionMethodSpec()
916 {
917   if (_encryptionMethod.GetCount() <= 1)
918     return UString();
919   if (_encryptionMethod.GetCurSel() <= 0)
920     return UString();
921   UString result;
922   _encryptionMethod.GetText(result);
923   result.Replace(L"-", L"");
924   return result;
925 }
926 
AddDictionarySize(UInt32 size,bool kilo,bool maga)927 int CCompressDialog::AddDictionarySize(UInt32 size, bool kilo, bool maga)
928 {
929   UInt32 sizePrint = size;
930   if (kilo)
931     sizePrint >>= 10;
932   else if (maga)
933     sizePrint >>= 20;
934   TCHAR s[40];
935   ConvertUInt32ToString(sizePrint, s);
936   if (kilo)
937     lstrcat(s, TEXT(" K"));
938   else if (maga)
939     lstrcat(s, TEXT(" M"));
940   else
941     lstrcat(s, TEXT(" "));
942   lstrcat(s, TEXT("B"));
943   int index = (int)m_Dictionary.AddString(s);
944   m_Dictionary.SetItemData(index, size);
945   return index;
946 }
947 
AddDictionarySize(UInt32 size)948 int CCompressDialog::AddDictionarySize(UInt32 size)
949 {
950   if (size > 0)
951   {
952     if ((size & 0xFFFFF) == 0)
953       return AddDictionarySize(size, false, true);
954     if ((size & 0x3FF) == 0)
955       return AddDictionarySize(size, true, false);
956   }
957   return AddDictionarySize(size, false, false);
958 }
959 
SetDictionary()960 void CCompressDialog::SetDictionary()
961 {
962   m_Dictionary.ResetContent();
963   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
964   int index = FindRegistryFormat(ai.Name);
965   UInt32 defaultDictionary = UInt32(-1);
966   if (index >= 0)
967   {
968     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
969     if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
970       defaultDictionary = fo.Dictionary;
971   }
972   int methodID = GetMethodID();
973   UInt32 level = GetLevel2();
974   if (methodID < 0)
975     return;
976   const UInt64 maxRamSize = GetMaxRamSizeForProgram();
977   switch (methodID)
978   {
979     case kLZMA:
980     case kLZMA2:
981     {
982       static const UInt32 kMinDicSize = (1 << 16);
983       if (defaultDictionary == UInt32(-1))
984       {
985         if (level >= 9)      defaultDictionary = (1 << 26);
986         else if (level >= 7) defaultDictionary = (1 << 25);
987         else if (level >= 5) defaultDictionary = (1 << 24);
988         else if (level >= 3) defaultDictionary = (1 << 20);
989         else                 defaultDictionary = (kMinDicSize);
990       }
991       int i;
992       AddDictionarySize(kMinDicSize);
993       m_Dictionary.SetCurSel(0);
994       for (i = 20; i <= 30; i++)
995         for (int j = 0; j < 2; j++)
996         {
997           if (i == 20 && j > 0)
998             continue;
999           UInt32 dictionary = (1 << i) + (j << (i - 1));
1000           if (dictionary >
1001           #ifdef _WIN64
1002             (1 << 30)
1003           #else
1004             (1 << 26)
1005           #endif
1006             )
1007             continue;
1008           AddDictionarySize(dictionary);
1009           UInt64 decomprSize;
1010           UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);
1011           if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize)
1012              m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
1013         }
1014 
1015       // SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
1016       break;
1017     }
1018     case kPPMd:
1019     {
1020       if (defaultDictionary == UInt32(-1))
1021       {
1022         if (level >= 9)      defaultDictionary = (192 << 20);
1023         else if (level >= 7) defaultDictionary = ( 64 << 20);
1024         else if (level >= 5) defaultDictionary = ( 16 << 20);
1025         else                 defaultDictionary = (  4 << 20);
1026       }
1027       int i;
1028       for (i = 20; i < 31; i++)
1029         for (int j = 0; j < 2; j++)
1030         {
1031           if (i == 20 && j > 0)
1032             continue;
1033           UInt32 dictionary = (1 << i) + (j << (i - 1));
1034           if (dictionary >= (1 << 31))
1035             continue;
1036           AddDictionarySize(dictionary);
1037           UInt64 decomprSize;
1038           UInt64 requiredComprSize = GetMemoryUsage(dictionary, decomprSize);
1039           if (dictionary <= defaultDictionary && requiredComprSize <= maxRamSize || m_Dictionary.GetCount() == 0)
1040              m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
1041         }
1042       SetNearestSelectComboBox(m_Dictionary, defaultDictionary);
1043       break;
1044     }
1045     case kDeflate:
1046     {
1047       AddDictionarySize(32 << 10);
1048       m_Dictionary.SetCurSel(0);
1049       break;
1050     }
1051     case kDeflate64:
1052     {
1053       AddDictionarySize(64 << 10);
1054       m_Dictionary.SetCurSel(0);
1055       break;
1056     }
1057     case kBZip2:
1058     {
1059       // UInt32 defaultDictionary;
1060       if (defaultDictionary == UInt32(-1))
1061       {
1062         if (level >= 5)
1063           defaultDictionary = (900 << 10);
1064         else if (level >= 3)
1065           defaultDictionary = (500 << 10);
1066         else
1067           defaultDictionary = (100 << 10);
1068       }
1069       for (int i = 1; i <= 9; i++)
1070       {
1071         UInt32 dictionary = (i * 100) << 10;
1072         AddDictionarySize(dictionary);
1073         if (dictionary <= defaultDictionary || m_Dictionary.GetCount() == 0)
1074            m_Dictionary.SetCurSel(m_Dictionary.GetCount() - 1);
1075       }
1076       break;
1077     }
1078   }
1079 }
1080 
GetComboValue(NWindows::NControl::CComboBox & c,int defMax)1081 UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax)
1082 {
1083   if (c.GetCount() <= defMax)
1084     return (UInt32)-1;
1085   return (UInt32)c.GetItemData(c.GetCurSel());
1086 }
1087 
GetLevel2()1088 UInt32 CCompressDialog::GetLevel2()
1089 {
1090   UInt32 level = GetLevel();
1091   if (level == (UInt32)-1)
1092     level = 5;
1093   return level;
1094 }
1095 
AddOrder(UInt32 size)1096 int CCompressDialog::AddOrder(UInt32 size)
1097 {
1098   TCHAR s[40];
1099   ConvertUInt32ToString(size, s);
1100   int index = (int)m_Order.AddString(s);
1101   m_Order.SetItemData(index, size);
1102   return index;
1103 }
1104 
SetOrder()1105 void CCompressDialog::SetOrder()
1106 {
1107   m_Order.ResetContent();
1108   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
1109   int index = FindRegistryFormat(ai.Name);
1110   UInt32 defaultOrder = UInt32(-1);
1111   if (index >= 0)
1112   {
1113     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
1114     if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
1115       defaultOrder = fo.Order;
1116   }
1117   int methodID = GetMethodID();
1118   UInt32 level = GetLevel2();
1119   if (methodID < 0)
1120     return;
1121   switch (methodID)
1122   {
1123     case kLZMA:
1124     case kLZMA2:
1125     {
1126       if (defaultOrder == UInt32(-1))
1127         defaultOrder = (level >= 7) ? 64 : 32;
1128       for (int i = 3; i <= 8; i++)
1129         for (int j = 0; j < 2; j++)
1130         {
1131           UInt32 order = (1 << i) + (j << (i - 1));
1132           if (order <= 256)
1133             AddOrder(order);
1134         }
1135       AddOrder(273);
1136       SetNearestSelectComboBox(m_Order, defaultOrder);
1137       break;
1138     }
1139     case kPPMd:
1140     {
1141       if (defaultOrder == UInt32(-1))
1142       {
1143         if (level >= 9)
1144           defaultOrder = 32;
1145         else if (level >= 7)
1146           defaultOrder = 16;
1147         else if (level >= 5)
1148           defaultOrder = 6;
1149         else
1150           defaultOrder = 4;
1151       }
1152       int i;
1153       AddOrder(2);
1154       AddOrder(3);
1155       for (i = 2; i < 8; i++)
1156         for (int j = 0; j < 4; j++)
1157         {
1158           UInt32 order = (1 << i) + (j << (i - 2));
1159           if (order < 32)
1160             AddOrder(order);
1161         }
1162       AddOrder(32);
1163       SetNearestSelectComboBox(m_Order, defaultOrder);
1164       break;
1165     }
1166     case kDeflate:
1167     case kDeflate64:
1168     {
1169       if (defaultOrder == UInt32(-1))
1170       {
1171         if (level >= 9)
1172           defaultOrder = 128;
1173         else if (level >= 7)
1174           defaultOrder = 64;
1175         else
1176           defaultOrder = 32;
1177       }
1178       int i;
1179       for (i = 3; i <= 8; i++)
1180         for (int j = 0; j < 2; j++)
1181         {
1182           UInt32 order = (1 << i) + (j << (i - 1));
1183           if (order <= 256)
1184             AddOrder(order);
1185         }
1186       AddOrder(methodID == kDeflate64 ? 257 : 258);
1187       SetNearestSelectComboBox(m_Order, defaultOrder);
1188       break;
1189     }
1190     case kBZip2:
1191     {
1192       break;
1193     }
1194   }
1195 }
1196 
GetOrderMode()1197 bool CCompressDialog::GetOrderMode()
1198 {
1199   switch (GetMethodID())
1200   {
1201     case kPPMd:
1202       return true;
1203   }
1204   return false;
1205 }
1206 
1207 static const UInt32 kNoSolidBlockSize = 0;
1208 static const UInt32 kSolidBlockSize = 64;
1209 
SetSolidBlockSize()1210 void CCompressDialog::SetSolidBlockSize()
1211 {
1212   m_Solid.ResetContent();
1213   const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1214   if (!fi.Solid)
1215     return;
1216 
1217   UInt32 level = GetLevel2();
1218   if (level == 0)
1219     return;
1220 
1221   UInt32 dictionary = GetDictionarySpec();
1222   if (dictionary == UInt32(-1))
1223     dictionary = 1;
1224 
1225   UInt32 defaultBlockSize = (UInt32)-1;
1226 
1227   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
1228   int index = FindRegistryFormat(ai.Name);
1229   if (index >= 0)
1230   {
1231     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
1232     if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
1233       defaultBlockSize = fo.BlockLogSize;
1234   }
1235 
1236   index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_NON_SOLID, 0x02000D14));
1237   m_Solid.SetItemData(index, (UInt32)kNoSolidBlockSize);
1238   m_Solid.SetCurSel(0);
1239   bool needSet = defaultBlockSize == (UInt32)-1;
1240   for (int i = 20; i <= 36; i++)
1241   {
1242     if (needSet && dictionary >= (((UInt64)1 << (i - 7))) && i <= 32)
1243       defaultBlockSize = i;
1244     TCHAR s[40];
1245     ConvertUInt32ToString(1 << (i % 10), s);
1246     if (i < 30) lstrcat(s, TEXT(" M"));
1247     else        lstrcat(s, TEXT(" G"));
1248     lstrcat(s, TEXT("B"));
1249     int index = (int)m_Solid.AddString(s);
1250     m_Solid.SetItemData(index, (UInt32)i);
1251   }
1252   index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID, 0x02000D15));
1253   m_Solid.SetItemData(index, kSolidBlockSize);
1254   if (defaultBlockSize == (UInt32)-1)
1255     defaultBlockSize = kSolidBlockSize;
1256   if (defaultBlockSize != kNoSolidBlockSize)
1257     SetNearestSelectComboBox(m_Solid, defaultBlockSize);
1258 }
1259 
SetNumThreads()1260 void CCompressDialog::SetNumThreads()
1261 {
1262   m_NumThreads.ResetContent();
1263 
1264   const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1265   if (!fi.MultiThread)
1266     return;
1267 
1268   UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();
1269   UInt32 defaultValue = numHardwareThreads;
1270 
1271   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
1272   int index = FindRegistryFormat(ai.Name);
1273   if (index >= 0)
1274   {
1275     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
1276     if (fo.Method.CompareNoCase(GetMethodSpec()) == 0)
1277       defaultValue = fo.NumThreads;
1278   }
1279 
1280   UInt32 numAlgoThreadsMax = 1;
1281   int methodID = GetMethodID();
1282   switch (methodID)
1283   {
1284     case kLZMA: numAlgoThreadsMax = 2; break;
1285     case kLZMA2: numAlgoThreadsMax = 32; break;
1286     case kBZip2: numAlgoThreadsMax = 32; break;
1287   }
1288   if (IsZipFormat())
1289     numAlgoThreadsMax = 128;
1290   for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++)
1291   {
1292     TCHAR s[40];
1293     ConvertUInt32ToString(i, s);
1294     int index = (int)m_NumThreads.AddString(s);
1295     m_NumThreads.SetItemData(index, (UInt32)i);
1296   }
1297   SetNearestSelectComboBox(m_NumThreads, defaultValue);
1298 }
1299 
1300 
GetMemoryUsage(UInt32 dictionary,UInt64 & decompressMemory)1301 UInt64 CCompressDialog::GetMemoryUsage(UInt32 dictionary, UInt64 &decompressMemory)
1302 {
1303   decompressMemory = UInt64(Int64(-1));
1304   UInt32 level = GetLevel2();
1305   if (level == 0)
1306   {
1307     decompressMemory = (1 << 20);
1308     return decompressMemory;
1309   }
1310   UInt64 size = 0;
1311 
1312   const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1313   if (fi.Filter && level >= 9)
1314     size += (12 << 20) * 2 + (5 << 20);
1315   UInt32 numThreads = GetNumThreads2();
1316   if (IsZipFormat())
1317   {
1318     UInt32 numSubThreads = 1;
1319     if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5)
1320       numSubThreads = 2;
1321     UInt32 numMainThreads = numThreads / numSubThreads;
1322     if (numMainThreads > 1)
1323       size += (UInt64)numMainThreads << 25;
1324   }
1325   int methidId = GetMethodID();
1326   switch (methidId)
1327   {
1328     case kLZMA:
1329     case kLZMA2:
1330     {
1331       UInt32 hs = dictionary - 1;
1332       hs |= (hs >> 1);
1333       hs |= (hs >> 2);
1334       hs |= (hs >> 4);
1335       hs |= (hs >> 8);
1336       hs >>= 1;
1337       hs |= 0xFFFF;
1338       if (hs > (1 << 24))
1339         hs >>= 1;
1340       hs++;
1341       UInt64 size1 = (UInt64)hs * 4;
1342       size1 += (UInt64)dictionary * 4;
1343       if (level >= 5)
1344         size1 += (UInt64)dictionary * 4;
1345       size1 += (2 << 20);
1346 
1347       UInt32 numThreads1 = 1;
1348       if (numThreads > 1 && level >= 5)
1349       {
1350         size1 += (2 << 20) + (4 << 20);
1351         numThreads1 = 2;
1352       }
1353       UInt32 numBlockThreads = numThreads / numThreads1;
1354       if (methidId == kLZMA || numBlockThreads == 1)
1355         size1 += (UInt64)dictionary * 3 / 2;
1356       else
1357       {
1358         UInt64 chunkSize = (UInt64)dictionary << 2;
1359         chunkSize = MyMax(chunkSize, (UInt64)(1 << 20));
1360         chunkSize = MyMin(chunkSize, (UInt64)(1 << 28));
1361         chunkSize = MyMax(chunkSize, (UInt64)dictionary);
1362         size1 += chunkSize * 2;
1363       }
1364       size += size1 * numBlockThreads;
1365 
1366       decompressMemory = dictionary + (2 << 20);
1367       return size;
1368     }
1369     case kPPMd:
1370     {
1371       decompressMemory = dictionary + (2 << 20);
1372       return size + decompressMemory;
1373     }
1374     case kDeflate:
1375     case kDeflate64:
1376     {
1377       UInt32 order = GetOrder();
1378       if (order == UInt32(-1))
1379         order = 32;
1380       if (level >= 7)
1381         size += (1 << 20);
1382       size += 3 << 20;
1383       decompressMemory = (2 << 20);
1384       return size;
1385     }
1386     case kBZip2:
1387     {
1388       decompressMemory = (7 << 20);
1389       UInt64 memForOneThread = (10 << 20);
1390       return size + memForOneThread * numThreads;
1391     }
1392   }
1393   return UInt64(Int64(-1));
1394 }
1395 
GetMemoryUsage(UInt64 & decompressMemory)1396 UInt64 CCompressDialog::GetMemoryUsage(UInt64 &decompressMemory)
1397 {
1398   return GetMemoryUsage(GetDictionary(), decompressMemory);
1399 }
1400 
PrintMemUsage(UINT res,UInt64 value)1401 void CCompressDialog::PrintMemUsage(UINT res, UInt64 value)
1402 {
1403   if (value == (UInt64)(Int64)-1)
1404   {
1405     SetItemText(res, TEXT("?"));
1406     return;
1407   }
1408   value = (value + (1 << 20) - 1) >> 20;
1409   TCHAR s[40];
1410   ConvertUInt64ToString(value, s);
1411   lstrcat(s, TEXT(" MB"));
1412   SetItemText(res, s);
1413 }
1414 
SetMemoryUsage()1415 void CCompressDialog::SetMemoryUsage()
1416 {
1417   UInt64 decompressMem;
1418   UInt64 memUsage = GetMemoryUsage(decompressMem);
1419   PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_VALUE, memUsage);
1420   PrintMemUsage(IDC_STATIC_COMPRESS_MEMORY_DE_VALUE, decompressMem);
1421 }
1422 
SetParams()1423 void CCompressDialog::SetParams()
1424 {
1425   const CArcInfoEx &ai = m_ArchiverInfoList[GetFormatIndex()];
1426   m_Params.SetText(TEXT(""));
1427   int index = FindRegistryFormat(ai.Name);
1428   if (index >= 0)
1429   {
1430     const NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
1431     m_Params.SetText(fo.Options);
1432   }
1433 }
1434 
SaveOptionsInMem()1435 void CCompressDialog::SaveOptionsInMem()
1436 {
1437   const CArcInfoEx &ai = m_ArchiverInfoList[Info.ArchiverInfoIndex];
1438   int index = FindRegistryFormatAlways(ai.Name);
1439   m_Params.GetText(Info.Options);
1440   Info.Options.Trim();
1441   NCompression::CFormatOptions &fo = m_RegistryInfo.FormatOptionsVector[index];
1442   fo.Options = Info.Options;
1443   fo.Level = GetLevelSpec();
1444   fo.Dictionary = GetDictionarySpec();
1445   fo.Order = GetOrderSpec();
1446   fo.Method = GetMethodSpec();
1447   fo.EncryptionMethod = GetEncryptionMethodSpec();
1448   fo.NumThreads = GetNumThreadsSpec();
1449   fo.BlockLogSize = GetBlockSizeSpec();
1450 }
1451 
GetFormatIndex()1452 int CCompressDialog::GetFormatIndex()
1453 {
1454   return (int)m_Format.GetItemData(m_Format.GetCurSel());
1455 }
1456