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