aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/UI/GUI/CompressDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--CPP/7zip/UI/GUI/CompressDialog.cpp2593
1 files changed, 2593 insertions, 0 deletions
diff --git a/CPP/7zip/UI/GUI/CompressDialog.cpp b/CPP/7zip/UI/GUI/CompressDialog.cpp
new file mode 100644
index 0000000..16a3585
--- /dev/null
+++ b/CPP/7zip/UI/GUI/CompressDialog.cpp
@@ -0,0 +1,2593 @@
1// CompressDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../../C/CpuArch.h"
6
7#include "../../../Common/IntToString.h"
8#include "../../../Common/StringConvert.h"
9
10#include "../../../Windows/FileDir.h"
11#include "../../../Windows/FileName.h"
12#include "../../../Windows/System.h"
13
14#include "../../Common/MethodProps.h"
15
16#include "../FileManager/BrowseDialog.h"
17#include "../FileManager/FormatUtils.h"
18#include "../FileManager/HelpUtils.h"
19#include "../FileManager/SplitUtils.h"
20
21#include "../Explorer/MyMessages.h"
22
23#include "../Common/ZipRegistry.h"
24
25#include "CompressDialog.h"
26
27#ifndef _UNICODE
28extern bool g_IsNT;
29#endif
30
31#ifdef LANG
32#include "../FileManager/LangUtils.h"
33#endif
34
35#include "CompressDialogRes.h"
36#include "ExtractRes.h"
37
38#ifdef LANG
39static const UInt32 kLangIDs[] =
40{
41 IDT_COMPRESS_ARCHIVE,
42 IDT_COMPRESS_UPDATE_MODE,
43 IDT_COMPRESS_FORMAT,
44 IDT_COMPRESS_LEVEL,
45 IDT_COMPRESS_METHOD,
46 IDT_COMPRESS_DICTIONARY,
47 IDT_COMPRESS_ORDER,
48 IDT_COMPRESS_SOLID,
49 IDT_COMPRESS_THREADS,
50 IDT_COMPRESS_PARAMETERS,
51
52 IDG_COMPRESS_OPTIONS,
53 IDX_COMPRESS_SFX,
54 IDX_COMPRESS_SHARED,
55 IDX_COMPRESS_DEL,
56
57 IDT_COMPRESS_MEMORY,
58 IDT_COMPRESS_MEMORY_DE,
59
60 IDX_COMPRESS_NT_SYM_LINKS,
61 IDX_COMPRESS_NT_HARD_LINKS,
62 IDX_COMPRESS_NT_ALT_STREAMS,
63 IDX_COMPRESS_NT_SECUR,
64
65 IDG_COMPRESS_ENCRYPTION,
66 IDT_COMPRESS_ENCRYPTION_METHOD,
67 IDX_COMPRESS_ENCRYPT_FILE_NAMES,
68
69 IDT_PASSWORD_ENTER,
70 IDT_PASSWORD_REENTER,
71 IDX_PASSWORD_SHOW,
72
73 IDT_SPLIT_TO_VOLUMES,
74 IDT_COMPRESS_PATH_MODE
75};
76#endif
77
78using namespace NWindows;
79using namespace NFile;
80using namespace NName;
81using namespace NDir;
82
83static const unsigned kHistorySize = 20;
84
85static const UInt32 kSolidLog_NoSolid = 0;
86static const UInt32 kSolidLog_FullSolid = 64;
87
88static const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28;
89
90static LPCSTR const kExeExt = ".exe";
91
92#define k7zFormat "7z"
93
94static const UInt32 g_Levels[] =
95{
96 IDS_METHOD_STORE,
97 IDS_METHOD_FASTEST,
98 0,
99 IDS_METHOD_FAST,
100 0,
101 IDS_METHOD_NORMAL,
102 0,
103 IDS_METHOD_MAXIMUM,
104 0,
105 IDS_METHOD_ULTRA
106};
107
108enum EMethodID
109{
110 kCopy,
111 kLZMA,
112 kLZMA2,
113 kPPMd,
114 kBZip2,
115 kDeflate,
116 kDeflate64,
117 kPPMdZip,
118 kSha256,
119 kSha1,
120 kCrc32,
121 kCrc64,
122};
123
124static LPCSTR const kMethodsNames[] =
125{
126 "Copy"
127 , "LZMA"
128 , "LZMA2"
129 , "PPMd"
130 , "BZip2"
131 , "Deflate"
132 , "Deflate64"
133 , "PPMd"
134 , "SHA256"
135 , "SHA1"
136 , "CRC32"
137 , "CRC64"
138};
139
140static const EMethodID g_7zMethods[] =
141{
142 kLZMA2,
143 kLZMA,
144 kPPMd,
145 kBZip2
146 , kDeflate
147 , kDeflate64
148 , kCopy
149};
150
151static const EMethodID g_7zSfxMethods[] =
152{
153 kCopy,
154 kLZMA,
155 kLZMA2,
156 kPPMd
157};
158
159static const EMethodID g_ZipMethods[] =
160{
161 kDeflate,
162 kDeflate64,
163 kBZip2,
164 kLZMA,
165 kPPMdZip
166};
167
168static const EMethodID g_GZipMethods[] =
169{
170 kDeflate
171};
172
173static const EMethodID g_BZip2Methods[] =
174{
175 kBZip2
176};
177
178static const EMethodID g_XzMethods[] =
179{
180 kLZMA2
181};
182
183static const EMethodID g_SwfcMethods[] =
184{
185 kDeflate
186 // kLZMA
187};
188
189static const EMethodID g_HashMethods[] =
190{
191 kSha256
192 , kSha1
193 // , kCrc32
194 // , kCrc64
195};
196
197static const UInt32 kFF_Filter = 1 << 0;
198static const UInt32 kFF_Solid = 1 << 1;
199static const UInt32 kFF_MultiThread = 1 << 2;
200static const UInt32 kFF_Encrypt = 1 << 3;
201static const UInt32 kFF_EncryptFileNames = 1 << 4;
202static const UInt32 kFF_MemUse = 1 << 5;
203static const UInt32 kFF_SFX = 1 << 6;
204
205struct CFormatInfo
206{
207 LPCSTR Name;
208 UInt32 LevelsMask;
209 unsigned NumMethods;
210 const EMethodID *MethodIDs;
211
212 UInt32 Flags;
213
214 bool Filter_() const { return (Flags & kFF_Filter) != 0; }
215 bool Solid_() const { return (Flags & kFF_Solid) != 0; }
216 bool MultiThread_() const { return (Flags & kFF_MultiThread) != 0; }
217 bool Encrypt_() const { return (Flags & kFF_Encrypt) != 0; }
218 bool EncryptFileNames_() const { return (Flags & kFF_EncryptFileNames) != 0; }
219 bool MemUse_() const { return (Flags & kFF_MemUse) != 0; }
220 bool SFX_() const { return (Flags & kFF_SFX) != 0; }
221};
222
223#define METHODS_PAIR(x) ARRAY_SIZE(x), x
224
225static const CFormatInfo g_Formats[] =
226{
227 {
228 "",
229 // (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
230 ((UInt32)1 << 10) - 1,
231 // (UInt32)(Int32)-1,
232 0, NULL,
233 kFF_MultiThread | kFF_MemUse
234 },
235 {
236 k7zFormat,
237 (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
238 METHODS_PAIR(g_7zMethods),
239 kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt |
240 kFF_EncryptFileNames | kFF_MemUse | kFF_SFX
241 },
242 {
243 "Zip",
244 (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
245 METHODS_PAIR(g_ZipMethods),
246 kFF_MultiThread | kFF_Encrypt | kFF_MemUse
247 },
248 {
249 "GZip",
250 (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9),
251 METHODS_PAIR(g_GZipMethods),
252 kFF_MemUse
253 },
254 {
255 "BZip2",
256 (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
257 METHODS_PAIR(g_BZip2Methods),
258 kFF_MultiThread | kFF_MemUse
259 },
260 {
261 "xz",
262 (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
263 METHODS_PAIR(g_XzMethods),
264 kFF_Solid | kFF_MultiThread | kFF_MemUse
265 },
266 {
267 "Swfc",
268 (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
269 METHODS_PAIR(g_SwfcMethods),
270 0
271 },
272 {
273 "Tar",
274 (1 << 0),
275 0, NULL,
276 0
277 },
278 {
279 "wim",
280 (1 << 0),
281 0, NULL,
282 0
283 },
284 {
285 "Hash",
286 (0 << 0),
287 METHODS_PAIR(g_HashMethods),
288 0
289 }
290};
291
292static bool IsMethodSupportedBySfx(int methodID)
293{
294 for (unsigned i = 0; i < ARRAY_SIZE(g_7zSfxMethods); i++)
295 if (methodID == g_7zSfxMethods[i])
296 return true;
297 return false;
298}
299
300
301static const
302 // NCompressDialog::NUpdateMode::EEnum
303 int
304 k_UpdateMode_Vals[] =
305{
306 NCompressDialog::NUpdateMode::kAdd,
307 NCompressDialog::NUpdateMode::kUpdate,
308 NCompressDialog::NUpdateMode::kFresh,
309 NCompressDialog::NUpdateMode::kSync
310};
311
312static const UInt32 k_UpdateMode_IDs[] =
313{
314 IDS_COMPRESS_UPDATE_MODE_ADD,
315 IDS_COMPRESS_UPDATE_MODE_UPDATE,
316 IDS_COMPRESS_UPDATE_MODE_FRESH,
317 IDS_COMPRESS_UPDATE_MODE_SYNC
318};
319
320static const
321 // NWildcard::ECensorPathMode
322 int
323 k_PathMode_Vals[] =
324{
325 NWildcard::k_RelatPath,
326 NWildcard::k_FullPath,
327 NWildcard::k_AbsPath,
328};
329
330static const UInt32 k_PathMode_IDs[] =
331{
332 IDS_PATH_MODE_RELAT,
333 IDS_EXTRACT_PATHS_FULL,
334 IDS_EXTRACT_PATHS_ABS
335};
336
337void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal);
338bool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2);
339
340void CCompressDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2)
341{
342 CheckButton(id, GetBoolsVal(b1, b2));
343}
344
345void CCompressDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2)
346{
347 bool val = IsButtonCheckedBool(id);
348 bool oldVal = GetBoolsVal(b1, b2);
349 if (val != oldVal)
350 b1.Def = b2.Def = true;
351 b1.Val = b2.Val = val;
352}
353
354
355void CCompressDialog::SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs)
356{
357 ExternalMethods.Clear();
358 {
359 FOR_VECTOR (i, userCodecs)
360 {
361 const CCodecInfoUser &c = userCodecs[i];
362 if (!c.EncoderIsAssigned
363 || !c.IsFilter_Assigned
364 || c.IsFilter
365 || c.NumStreams != 1)
366 continue;
367 unsigned k;
368 for (k = 0; k < ARRAY_SIZE(g_7zMethods); k++)
369 if (c.Name.IsEqualTo_Ascii_NoCase(kMethodsNames[g_7zMethods[k]]))
370 break;
371 if (k != ARRAY_SIZE(g_7zMethods))
372 continue;
373 ExternalMethods.Add(c.Name);
374 }
375 }
376}
377
378
379bool CCompressDialog::OnInit()
380{
381 #ifdef LANG
382 LangSetWindowText(*this, IDD_COMPRESS);
383 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
384 #endif
385
386 {
387 UInt64 size = (UInt64)(sizeof(size_t)) << 29;
388 _ramSize_Defined = NSystem::GetRamSize(size);
389 // size = (UInt64)3 << 62; // for debug only;
390 _ramSize = size;
391 const UInt64 kMinUseSize = (1 << 26);
392 if (size < kMinUseSize)
393 size = kMinUseSize;
394
395 unsigned bits = sizeof(size_t) * 8;
396 if (bits == 32)
397 {
398 const UInt32 limit2 = (UInt32)7 << 28;
399 if (size > limit2)
400 size = limit2;
401 }
402
403 _ramSize_Reduced = size;
404
405 // 80% - is auto usage limit in handlers
406 _ramUsage_Auto = Calc_From_Val_Percents(size, 80);
407 }
408
409 _password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1));
410 _password2Control.Attach(GetItem(IDE_COMPRESS_PASSWORD2));
411 _password1Control.SetText(Info.Password);
412 _password2Control.SetText(Info.Password);
413 _encryptionMethod.Attach(GetItem(IDC_COMPRESS_ENCRYPTION_METHOD));
414 _default_encryptionMethod_Index = -1;
415
416 m_ArchivePath.Attach(GetItem(IDC_COMPRESS_ARCHIVE));
417 m_Format.Attach(GetItem(IDC_COMPRESS_FORMAT));
418 m_Level.Attach(GetItem(IDC_COMPRESS_LEVEL));
419 m_Method.Attach(GetItem(IDC_COMPRESS_METHOD));
420 m_Dictionary.Attach(GetItem(IDC_COMPRESS_DICTIONARY));
421 m_Order.Attach(GetItem(IDC_COMPRESS_ORDER));
422 m_Solid.Attach(GetItem(IDC_COMPRESS_SOLID));
423 m_NumThreads.Attach(GetItem(IDC_COMPRESS_THREADS));
424 m_MemUse.Attach(GetItem(IDC_COMPRESS_MEM_USE));
425
426 m_UpdateMode.Attach(GetItem(IDC_COMPRESS_UPDATE_MODE));
427 m_PathMode.Attach(GetItem(IDC_COMPRESS_PATH_MODE));
428
429 m_Volume.Attach(GetItem(IDC_COMPRESS_VOLUME));
430 m_Params.Attach(GetItem(IDE_COMPRESS_PARAMETERS));
431
432 AddVolumeItems(m_Volume);
433
434 m_RegistryInfo.Load();
435 CheckButton(IDX_PASSWORD_SHOW, m_RegistryInfo.ShowPassword);
436 CheckButton(IDX_COMPRESS_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders);
437
438 CheckButton_TwoBools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks);
439 CheckButton_TwoBools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks);
440 CheckButton_TwoBools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams);
441 CheckButton_TwoBools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity);
442
443 UpdatePasswordControl();
444
445 {
446 bool needSetMain = (Info.FormatIndex < 0);
447 FOR_VECTOR(i, ArcIndices)
448 {
449 unsigned arcIndex = ArcIndices[i];
450 const CArcInfoEx &ai = (*ArcFormats)[arcIndex];
451 int index = (int)m_Format.AddString(ai.Name);
452 m_Format.SetItemData(index, arcIndex);
453 if (!needSetMain)
454 {
455 if (Info.FormatIndex == (int)arcIndex)
456 m_Format.SetCurSel(index);
457 continue;
458 }
459 if (i == 0 || ai.Name.IsEqualTo_NoCase(m_RegistryInfo.ArcType))
460 {
461 m_Format.SetCurSel(index);
462 Info.FormatIndex = arcIndex;
463 }
464 }
465 }
466
467 CheckButton(IDX_COMPRESS_SFX, Info.SFXMode);
468
469 {
470 UString fileName;
471 SetArcPathFields(Info.ArcPath, fileName, true);
472 StartDirPrefix = DirPrefix;
473 SetArchiveName(fileName);
474 }
475
476 for (unsigned i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++)
477 m_ArchivePath.AddString(m_RegistryInfo.ArcPaths[i]);
478
479 AddComboItems(m_UpdateMode, k_UpdateMode_IDs, ARRAY_SIZE(k_UpdateMode_IDs),
480 k_UpdateMode_Vals, Info.UpdateMode);
481
482 AddComboItems(m_PathMode, k_PathMode_IDs, ARRAY_SIZE(k_PathMode_IDs),
483 k_PathMode_Vals, Info.PathMode);
484
485
486 TCHAR s[32] = { TEXT('/'), TEXT(' '), 0 };
487 ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
488 SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s);
489
490 CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite);
491 CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing);
492
493 FormatChanged();
494
495 // OnButtonSFX();
496
497 NormalizePosition();
498
499 return CModalDialog::OnInit();
500}
501
502/*
503namespace NCompressDialog
504{
505 bool CInfo::GetFullPathName(UString &result) const
506 {
507 #ifndef UNDER_CE
508 // NDirectory::MySetCurrentDirectory(CurrentDirPrefix);
509 #endif
510 FString resultF;
511 bool res = MyGetFullPathName(us2fs(ArchiveName), resultF);
512 result = fs2us(resultF);
513 return res;
514 }
515}
516*/
517
518void CCompressDialog::UpdatePasswordControl()
519{
520 bool showPassword = IsShowPasswordChecked();
521 TCHAR c = showPassword ? (TCHAR)0: TEXT('*');
522 _password1Control.SetPasswordChar(c);
523 _password2Control.SetPasswordChar(c);
524 UString password;
525 _password1Control.GetText(password);
526 _password1Control.SetText(password);
527 _password2Control.GetText(password);
528 _password2Control.SetText(password);
529
530 ShowItem_Bool(IDT_PASSWORD_REENTER, !showPassword);
531 _password2Control.Show_Bool(!showPassword);
532}
533
534bool CCompressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
535{
536 switch (buttonID)
537 {
538 case IDB_COMPRESS_SET_ARCHIVE:
539 {
540 OnButtonSetArchive();
541 return true;
542 }
543 case IDX_COMPRESS_SFX:
544 {
545 SetMethod(GetMethodID());
546 OnButtonSFX();
547 SetMemoryUsage();
548 return true;
549 }
550 case IDX_PASSWORD_SHOW:
551 {
552 UpdatePasswordControl();
553 return true;
554 }
555 }
556 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
557}
558
559void CCompressDialog::CheckSFXControlsEnable()
560{
561 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
562 bool enable = fi.SFX_();
563 if (enable)
564 {
565 const int methodID = GetMethodID();
566 enable = (methodID == -1 || IsMethodSupportedBySfx(methodID));
567 }
568 if (!enable)
569 CheckButton(IDX_COMPRESS_SFX, false);
570 EnableItem(IDX_COMPRESS_SFX, enable);
571}
572
573/*
574void CCompressDialog::CheckVolumeEnable()
575{
576 bool isSFX = IsSFX();
577 m_Volume.Enable(!isSFX);
578 if (isSFX)
579 m_Volume.SetText(TEXT(""));
580}
581*/
582
583void CCompressDialog::EnableMultiCombo(unsigned id)
584{
585 NWindows::NControl::CComboBox combo;
586 combo.Attach(GetItem(id));
587 const bool enable = (combo.GetCount() > 1);
588 EnableItem(id, enable);
589}
590
591
592void CCompressDialog::FormatChanged()
593{
594 SetLevel();
595 SetSolidBlockSize();
596 SetParams();
597 SetMemUseCombo();
598 SetNumThreads();
599
600 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
601 Info.SolidIsSpecified = fi.Solid_();
602 Info.EncryptHeadersIsAllowed = fi.EncryptFileNames_();
603
604 /*
605 const bool multiThreadEnable = fi.MultiThread;
606 Info.MultiThreadIsAllowed = multiThreadEnable;
607 EnableItem(IDC_COMPRESS_SOLID, fi.Solid);
608 EnableItem(IDC_COMPRESS_THREADS, multiThreadEnable);
609 const bool methodEnable = (fi.MethodIDs != NULL);
610 EnableItem(IDC_COMPRESS_METHOD, methodEnable);
611 EnableMultiCombo(IDC_COMPRESS_DICTIONARY, methodEnable);
612 EnableItem(IDC_COMPRESS_ORDER, methodEnable);
613 */
614
615 CheckSFXControlsEnable();
616
617 {
618 const CArcInfoEx &ai = Get_ArcInfoEx();
619
620 ShowItem_Bool(IDX_COMPRESS_NT_SYM_LINKS, ai.Flags_SymLinks());
621 ShowItem_Bool(IDX_COMPRESS_NT_HARD_LINKS, ai.Flags_HardLinks());
622 ShowItem_Bool(IDX_COMPRESS_NT_ALT_STREAMS, ai.Flags_AltStreams());
623 ShowItem_Bool(IDX_COMPRESS_NT_SECUR, ai.Flags_NtSecure());
624
625 ShowItem_Bool(IDG_COMPRESS_NTFS,
626 ai.Flags_SymLinks()
627 || ai.Flags_HardLinks()
628 || ai.Flags_AltStreams()
629 || ai.Flags_NtSecure());
630 }
631 // CheckVolumeEnable();
632
633 const bool encrypt = fi.Encrypt_();
634 EnableItem(IDG_COMPRESS_ENCRYPTION, encrypt);
635
636 EnableItem(IDT_PASSWORD_ENTER, encrypt);
637 EnableItem(IDT_PASSWORD_REENTER, encrypt);
638 EnableItem(IDE_COMPRESS_PASSWORD1, encrypt);
639 EnableItem(IDE_COMPRESS_PASSWORD2, encrypt);
640 EnableItem(IDX_PASSWORD_SHOW, encrypt);
641
642 EnableItem(IDT_COMPRESS_ENCRYPTION_METHOD, encrypt);
643 EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, encrypt);
644 EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_());
645
646 ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_());
647
648 SetEncryptionMethod();
649 SetMemoryUsage();
650}
651
652
653bool CCompressDialog::IsSFX()
654{
655 CWindow sfxButton = GetItem(IDX_COMPRESS_SFX);
656 return sfxButton.IsEnabled() && IsButtonCheckedBool(IDX_COMPRESS_SFX);
657}
658
659static int GetExtDotPos(const UString &s)
660{
661 int dotPos = s.ReverseFind_Dot();
662 if (dotPos > s.ReverseFind_PathSepar() + 1)
663 return dotPos;
664 return -1;
665}
666
667void CCompressDialog::OnButtonSFX()
668{
669 UString fileName;
670 m_ArchivePath.GetText(fileName);
671 int dotPos = GetExtDotPos(fileName);
672 if (IsSFX())
673 {
674 if (dotPos >= 0)
675 fileName.DeleteFrom(dotPos);
676 fileName += kExeExt;
677 m_ArchivePath.SetText(fileName);
678 }
679 else
680 {
681 if (dotPos >= 0)
682 {
683 UString ext = fileName.Ptr(dotPos);
684 if (ext.IsEqualTo_Ascii_NoCase(kExeExt))
685 {
686 fileName.DeleteFrom(dotPos);
687 m_ArchivePath.SetText(fileName);
688 }
689 }
690 SetArchiveName2(false); // it's for OnInit
691 }
692
693 // CheckVolumeEnable();
694}
695
696bool CCompressDialog::GetFinalPath_Smart(UString &resPath)
697{
698 UString name;
699 m_ArchivePath.GetText(name);
700 name.Trim();
701 UString tempPath = name;
702 if (!IsAbsolutePath(name))
703 {
704 UString newDirPrefix = DirPrefix;
705 if (newDirPrefix.IsEmpty())
706 newDirPrefix = StartDirPrefix;
707 FString resultF;
708 if (!MyGetFullPathName(us2fs(newDirPrefix + name), resultF))
709 return false;
710 tempPath = fs2us(resultF);
711 }
712 if (!SetArcPathFields(tempPath, name, false))
713 return false;
714 FString resultF;
715 if (!MyGetFullPathName(us2fs(DirPrefix + name), resultF))
716 return false;
717 resPath = fs2us(resultF);
718 return true;
719}
720
721bool CCompressDialog::SetArcPathFields(const UString &path, UString &name, bool always)
722{
723 FString resDirPrefix;
724 FString resFileName;
725 bool res = GetFullPathAndSplit(us2fs(path), resDirPrefix, resFileName);
726 if (res)
727 {
728 DirPrefix = fs2us(resDirPrefix);
729 name = fs2us(resFileName);
730 }
731 else
732 {
733 if (!always)
734 return false;
735 DirPrefix.Empty();
736 name = path;
737 }
738 SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix);
739 m_ArchivePath.SetText(name);
740 return res;
741}
742
743static const wchar_t * const k_IncorrectPathMessage = L"Incorrect archive path";
744
745void CCompressDialog::OnButtonSetArchive()
746{
747 UString path;
748 if (!GetFinalPath_Smart(path))
749 {
750 ShowErrorMessage(*this, k_IncorrectPathMessage);
751 return;
752 }
753
754 UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_BROWSE);
755 UString filterDescription = LangString(IDS_OPEN_TYPE_ALL_FILES);
756 filterDescription += " (*.*)";
757 UString resPath;
758 CurrentDirWasChanged = true;
759 if (!MyBrowseForFile(*this, title,
760 // DirPrefix.IsEmpty() ? NULL : (const wchar_t *)DirPrefix,
761 // NULL,
762 path,
763 filterDescription,
764 NULL, // L"*.*",
765 resPath))
766 return;
767 UString dummyName;
768 SetArcPathFields(resPath, dummyName, true);
769}
770
771// in ExtractDialog.cpp
772extern void AddUniqueString(UStringVector &strings, const UString &srcString);
773
774static bool IsAsciiString(const UString &s)
775{
776 for (unsigned i = 0; i < s.Len(); i++)
777 {
778 wchar_t c = s[i];
779 if (c < 0x20 || c > 0x7F)
780 return false;
781 }
782 return true;
783}
784
785
786static void AddSize_MB(UString &s, UInt64 size)
787{
788 const UInt64 v2 = size + ((UInt32)1 << 20) - 1;
789 if (size <= v2)
790 size = v2;
791 s.Add_UInt64(size >> 20);
792 s += " MB";
793}
794
795
796void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString)
797{
798 s += "The operation was blocked by 7-Zip";
799 s.Add_LF();
800 s += "The operation can require big amount of RAM (memory):";
801 s.Add_LF();
802 s.Add_LF();
803 AddSize_MB(s, reqSize);
804
805 if (!usageString.IsEmpty())
806 {
807 s += " : ";
808 s += usageString;
809 }
810
811 s.Add_LF();
812 AddSize_MB(s, ramSize);
813 s += " : RAM";
814
815 // if (ramLimit != 0)
816 {
817 s.Add_LF();
818 AddSize_MB(s, ramLimit);
819 s += " : 7-Zip limit";
820 }
821
822 s.Add_LF();
823 s.Add_LF();
824 s += LangString(IDS_MEM_ERROR);
825}
826
827
828void CCompressDialog::OnOK()
829{
830 _password1Control.GetText(Info.Password);
831 if (IsZipFormat())
832 {
833 if (!IsAsciiString(Info.Password))
834 {
835 ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII);
836 return;
837 }
838 UString method = GetEncryptionMethodSpec();
839 if (method.IsPrefixedBy_Ascii_NoCase("aes"))
840 {
841 if (Info.Password.Len() > 99)
842 {
843 ShowErrorMessageHwndRes(*this, IDS_PASSWORD_TOO_LONG);
844 return;
845 }
846 }
847 }
848 if (!IsShowPasswordChecked())
849 {
850 UString password2;
851 _password2Control.GetText(password2);
852 if (password2 != Info.Password)
853 {
854 ShowErrorMessageHwndRes(*this, IDS_PASSWORD_NOT_MATCH);
855 return;
856 }
857 }
858
859 {
860 UInt64 decompressMem;
861 const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem);
862 if (memUsage != (UInt64)(Int64)-1)
863 {
864 const UInt64 limit = Get_MemUse_Bytes();
865 if (memUsage > limit)
866 {
867 UString s;
868 UString s2 = LangString(IDT_COMPRESS_MEMORY);
869 if (s2.IsEmpty())
870 GetItemText(IDT_COMPRESS_MEMORY, s2);
871 SetErrorMessage_MemUsage(s, memUsage, _ramSize, limit, s2);
872 MessageBoxError(s);
873 return;
874 }
875 }
876 }
877
878 SaveOptionsInMem();
879 {
880 UString s;
881 if (!GetFinalPath_Smart(s))
882 {
883 ShowErrorMessage(*this, k_IncorrectPathMessage);
884 return;
885 }
886
887 m_RegistryInfo.ArcPaths.Clear();
888 AddUniqueString(m_RegistryInfo.ArcPaths, s);
889 Info.ArcPath = s;
890 }
891
892 Info.UpdateMode = (NCompressDialog::NUpdateMode::EEnum)k_UpdateMode_Vals[m_UpdateMode.GetCurSel()];;
893 Info.PathMode = (NWildcard::ECensorPathMode)k_PathMode_Vals[m_PathMode.GetCurSel()];
894
895 Info.Level = GetLevelSpec();
896 Info.Dict64 = GetDictSpec();
897 Info.Order = GetOrderSpec();
898 Info.OrderMode = GetOrderMode();
899 Info.NumThreads = GetNumThreadsSpec();
900
901 Info.MemUsage.Clear();
902 {
903 const UString mus = Get_MemUse_Spec();
904 if (!mus.IsEmpty())
905 {
906 NCompression::CMemUse mu;
907 mu.Parse(mus);
908 if (mu.IsDefined)
909 Info.MemUsage = mu;
910 }
911 }
912
913 {
914 // Info.SolidIsSpecified = g_Formats[GetStaticFormatIndex()].Solid;
915 const UInt32 solidLogSize = GetBlockSizeSpec();
916 Info.SolidBlockSize = 0;
917 if (solidLogSize == (UInt32)(Int32)-1)
918 Info.SolidIsSpecified = false;
919 else if (solidLogSize > 0)
920 Info.SolidBlockSize = (solidLogSize >= 64) ?
921 (UInt64)(Int64)-1 :
922 ((UInt64)1 << solidLogSize);
923 }
924
925 Info.Method = GetMethodSpec();
926 Info.EncryptionMethod = GetEncryptionMethodSpec();
927 Info.FormatIndex = GetFormatIndex();
928 Info.SFXMode = IsSFX();
929 Info.OpenShareForWrite = IsButtonCheckedBool(IDX_COMPRESS_SHARED);
930 Info.DeleteAfterCompressing = IsButtonCheckedBool(IDX_COMPRESS_DEL);
931
932 m_RegistryInfo.EncryptHeaders =
933 Info.EncryptHeaders = IsButtonCheckedBool(IDX_COMPRESS_ENCRYPT_FILE_NAMES);
934
935
936 GetButton_Bools(IDX_COMPRESS_NT_SYM_LINKS, Info.SymLinks, m_RegistryInfo.SymLinks);
937 GetButton_Bools(IDX_COMPRESS_NT_HARD_LINKS, Info.HardLinks, m_RegistryInfo.HardLinks);
938 GetButton_Bools(IDX_COMPRESS_NT_ALT_STREAMS, Info.AltStreams, m_RegistryInfo.AltStreams);
939 GetButton_Bools(IDX_COMPRESS_NT_SECUR, Info.NtSecurity, m_RegistryInfo.NtSecurity);
940
941 {
942 const CArcInfoEx &ai = Get_ArcInfoEx();
943 if (!ai.Flags_SymLinks()) Info.SymLinks.Val = false;
944 if (!ai.Flags_HardLinks()) Info.HardLinks.Val = false;
945 if (!ai.Flags_AltStreams()) Info.AltStreams.Val = false;
946 if (!ai.Flags_NtSecure()) Info.NtSecurity.Val = false;
947 }
948
949 m_Params.GetText(Info.Options);
950
951 UString volumeString;
952 m_Volume.GetText(volumeString);
953 volumeString.Trim();
954 Info.VolumeSizes.Clear();
955
956 if (!volumeString.IsEmpty())
957 {
958 if (!ParseVolumeSizes(volumeString, Info.VolumeSizes))
959 {
960 ShowErrorMessageHwndRes(*this, IDS_INCORRECT_VOLUME_SIZE);
961 return;
962 }
963 if (!Info.VolumeSizes.IsEmpty())
964 {
965 const UInt64 volumeSize = Info.VolumeSizes.Back();
966 if (volumeSize < (100 << 10))
967 {
968 wchar_t s[32];
969 ConvertUInt64ToString(volumeSize, s);
970 if (::MessageBoxW(*this, MyFormatNew(IDS_SPLIT_CONFIRM, s),
971 L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
972 return;
973 }
974 }
975 }
976
977 for (int i = 0; i < m_ArchivePath.GetCount(); i++)
978 {
979 UString sTemp;
980 m_ArchivePath.GetLBText(i, sTemp);
981 sTemp.Trim();
982 AddUniqueString(m_RegistryInfo.ArcPaths, sTemp);
983 }
984
985 if (m_RegistryInfo.ArcPaths.Size() > kHistorySize)
986 m_RegistryInfo.ArcPaths.DeleteBack();
987
988 if (Info.FormatIndex >= 0)
989 m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name;
990 m_RegistryInfo.ShowPassword = IsShowPasswordChecked();
991
992 m_RegistryInfo.Save();
993
994 CModalDialog::OnOK();
995}
996
997#define kHelpTopic "fm/plugins/7-zip/add.htm"
998
999void CCompressDialog::OnHelp()
1000{
1001 ShowHelpWindow(kHelpTopic);
1002}
1003
1004bool CCompressDialog::OnCommand(int code, int itemID, LPARAM lParam)
1005{
1006 if (code == CBN_SELCHANGE)
1007 {
1008 switch (itemID)
1009 {
1010 case IDC_COMPRESS_ARCHIVE:
1011 {
1012 // we can 't change m_ArchivePath in that handler !
1013 DirPrefix.Empty();
1014 SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix);
1015
1016 /*
1017 UString path;
1018 m_ArchivePath.GetText(path);
1019 m_ArchivePath.SetText(L"");
1020 if (IsAbsolutePath(path))
1021 {
1022 UString fileName;
1023 SetArcPathFields(path, fileName);
1024 SetArchiveName(fileName);
1025 }
1026 */
1027 return true;
1028 }
1029
1030 case IDC_COMPRESS_FORMAT:
1031 {
1032 const bool isSFX = IsSFX();
1033 SaveOptionsInMem();
1034 FormatChanged();
1035 SetArchiveName2(isSFX);
1036 return true;
1037 }
1038
1039 case IDC_COMPRESS_LEVEL:
1040 {
1041 Get_FormatOptions().ResetForLevelChange();
1042
1043 SetMethod();
1044 SetSolidBlockSize();
1045 SetNumThreads();
1046 CheckSFXNameChange();
1047 SetMemoryUsage();
1048 return true;
1049 }
1050
1051 case IDC_COMPRESS_METHOD:
1052 {
1053 MethodChanged();
1054 SetSolidBlockSize();
1055 SetNumThreads();
1056 CheckSFXNameChange();
1057 SetMemoryUsage();
1058 if (Get_ArcInfoEx().Flags_HashHandler())
1059 SetArchiveName2(false);
1060 return true;
1061 }
1062
1063 case IDC_COMPRESS_DICTIONARY:
1064 {
1065 /* we want to change the reported threads for Auto line
1066 and keep selected NumThreads option
1067 So we save selected NumThreads option in memory */
1068 SaveOptionsInMem();
1069 const UInt32 blockSizeLog = GetBlockSizeSpec();
1070 if (// blockSizeLog != (UInt32)(Int32)-1 &&
1071 blockSizeLog != kSolidLog_NoSolid
1072 && blockSizeLog != kSolidLog_FullSolid)
1073 {
1074 Get_FormatOptions().Reset_BlockLogSize();
1075 // SetSolidBlockSize(true);
1076 }
1077
1078 SetSolidBlockSize();
1079 SetNumThreads(); // we want to change the reported threads for Auto line only
1080 SetMemoryUsage();
1081 return true;
1082 }
1083
1084 case IDC_COMPRESS_ORDER:
1085 return true;
1086
1087 case IDC_COMPRESS_SOLID:
1088 {
1089 SetMemoryUsage();
1090 return true;
1091 }
1092
1093 case IDC_COMPRESS_THREADS:
1094 {
1095 SetMemoryUsage();
1096 return true;
1097 }
1098
1099 case IDC_COMPRESS_MEM_USE:
1100 {
1101 /* we want to change the reported threads for Auto line
1102 and keep selected NumThreads option
1103 So we save selected NumThreads option in memory */
1104 SaveOptionsInMem();
1105
1106 SetNumThreads(); // we want to change the reported threads for Auto line only
1107 SetMemoryUsage();
1108 return true;
1109 }
1110 }
1111 }
1112 return CModalDialog::OnCommand(code, itemID, lParam);
1113}
1114
1115void CCompressDialog::CheckSFXNameChange()
1116{
1117 const bool isSFX = IsSFX();
1118 CheckSFXControlsEnable();
1119 if (isSFX != IsSFX())
1120 SetArchiveName2(isSFX);
1121}
1122
1123void CCompressDialog::SetArchiveName2(bool prevWasSFX)
1124{
1125 UString fileName;
1126 m_ArchivePath.GetText(fileName);
1127 const CArcInfoEx &prevArchiverInfo = (*ArcFormats)[m_PrevFormat];
1128 if (prevArchiverInfo.Flags_KeepName() || Info.KeepName)
1129 {
1130 UString prevExtension;
1131 if (prevWasSFX)
1132 prevExtension = kExeExt;
1133 else
1134 {
1135 prevExtension += '.';
1136 prevExtension += prevArchiverInfo.GetMainExt();
1137 }
1138 const unsigned prevExtensionLen = prevExtension.Len();
1139 if (fileName.Len() >= prevExtensionLen)
1140 if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension))
1141 fileName.DeleteFrom(fileName.Len() - prevExtensionLen);
1142 }
1143 SetArchiveName(fileName);
1144}
1145
1146// if type.KeepName then use OriginalFileName
1147// else if !KeepName remove extension
1148// add new extension
1149
1150void CCompressDialog::SetArchiveName(const UString &name)
1151{
1152 UString fileName = name;
1153 Info.FormatIndex = GetFormatIndex();
1154 const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];
1155 m_PrevFormat = Info.FormatIndex;
1156 if (ai.Flags_KeepName())
1157 {
1158 fileName = OriginalFileName;
1159 }
1160 else
1161 {
1162 if (!Info.KeepName)
1163 {
1164 int dotPos = GetExtDotPos(fileName);
1165 if (dotPos >= 0)
1166 fileName.DeleteFrom(dotPos);
1167 }
1168 }
1169
1170 if (IsSFX())
1171 fileName += kExeExt;
1172 else
1173 {
1174 fileName += '.';
1175 UString ext = ai.GetMainExt();
1176 if (ai.Flags_HashHandler())
1177 {
1178 UString estimatedName;
1179 GetMethodSpec(estimatedName);
1180 if (!estimatedName.IsEmpty())
1181 {
1182 ext = estimatedName;
1183 ext.MakeLower_Ascii();
1184 }
1185 }
1186 fileName += ext;
1187 }
1188 m_ArchivePath.SetText(fileName);
1189}
1190
1191int CCompressDialog::FindRegistryFormat(const UString &name)
1192{
1193 FOR_VECTOR (i, m_RegistryInfo.Formats)
1194 {
1195 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i];
1196 if (name.IsEqualTo_NoCase(GetUnicodeString(fo.FormatID)))
1197 return i;
1198 }
1199 return -1;
1200}
1201
1202int CCompressDialog::FindRegistryFormatAlways(const UString &name)
1203{
1204 int index = FindRegistryFormat(name);
1205 if (index < 0)
1206 {
1207 NCompression::CFormatOptions fo;
1208 fo.FormatID = GetSystemString(name);
1209 index = m_RegistryInfo.Formats.Add(fo);
1210 }
1211 return index;
1212}
1213
1214int CCompressDialog::GetStaticFormatIndex()
1215{
1216 const CArcInfoEx &ai = Get_ArcInfoEx();
1217 for (unsigned i = 0; i < ARRAY_SIZE(g_Formats); i++)
1218 if (ai.Name.IsEqualTo_Ascii_NoCase(g_Formats[i].Name))
1219 return i;
1220 return 0; // -1;
1221}
1222
1223void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value)
1224{
1225 for (int i = comboBox.GetCount() - 1; i >= 0; i--)
1226 if ((UInt32)comboBox.GetItemData(i) <= value)
1227 {
1228 comboBox.SetCurSel(i);
1229 return;
1230 }
1231 if (comboBox.GetCount() > 0)
1232 comboBox.SetCurSel(0);
1233}
1234
1235void CCompressDialog::SetLevel2()
1236{
1237 m_Level.ResetContent();
1238 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1239 const CArcInfoEx &ai = Get_ArcInfoEx();
1240 UInt32 level = 5;
1241 {
1242 int index = FindRegistryFormat(ai.Name);
1243 if (index >= 0)
1244 {
1245 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1246 if (fo.Level <= 9)
1247 level = fo.Level;
1248 else if (fo.Level == (UInt32)(Int32)-1)
1249 level = 5;
1250 else
1251 level = 9;
1252 }
1253 }
1254
1255 for (unsigned i = 0; i < sizeof(UInt32) * 8; i++)
1256 {
1257 const UInt32 mask = (UInt32)1 << i;
1258 if ((fi.LevelsMask & mask) != 0)
1259 {
1260 UInt32 langID = g_Levels[i];
1261 UString s;
1262 s.Add_UInt32(i);
1263 s += " - ";
1264 s += LangString(langID);
1265 int index = (int)m_Level.AddString(s);
1266 m_Level.SetItemData(index, i);
1267 }
1268 if (fi.LevelsMask <= mask)
1269 break;
1270 }
1271 SetNearestSelectComboBox(m_Level, level);
1272}
1273
1274
1275static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s)
1276{
1277 return cb.AddString((CSysString)s);
1278}
1279
1280// static const char *k_Auto = "- "; // "auto : ";
1281
1282static void Modify_Auto(AString &s)
1283{
1284 s.Insert(0, "* ");
1285 // s += " -";
1286}
1287
1288void CCompressDialog::SetMethod2(int keepMethodId)
1289{
1290 m_Method.ResetContent();
1291 _auto_MethodId = -1;
1292 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1293 const CArcInfoEx &ai = Get_ArcInfoEx();
1294 if (GetLevel() == 0 && !ai.Flags_HashHandler())
1295 {
1296 MethodChanged();
1297 return;
1298 }
1299 UString defaultMethod;
1300 {
1301 const int index = FindRegistryFormat(ai.Name);
1302 if (index >= 0)
1303 {
1304 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1305 defaultMethod = fo.Method;
1306 }
1307 }
1308 const bool isSfx = IsSFX();
1309 bool weUseSameMethod = false;
1310
1311 const bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z");
1312
1313 for (unsigned m = 0;; m++)
1314 {
1315 int methodID;
1316 const char *method;
1317 if (m < fi.NumMethods)
1318 {
1319 methodID = fi.MethodIDs[m];
1320 method = kMethodsNames[methodID];
1321 if (is7z)
1322 if (methodID == kCopy
1323 || methodID == kDeflate
1324 || methodID == kDeflate64
1325 )
1326 continue;
1327 }
1328 else
1329 {
1330 if (!is7z)
1331 break;
1332 unsigned extIndex = m - fi.NumMethods;
1333 if (extIndex >= ExternalMethods.Size())
1334 break;
1335 methodID = ARRAY_SIZE(kMethodsNames) + extIndex;
1336 method = ExternalMethods[extIndex].Ptr();
1337 }
1338 if (isSfx)
1339 if (!IsMethodSupportedBySfx(methodID))
1340 continue;
1341
1342 AString s (method);
1343 int writtenMethodId = methodID;
1344 if (m == 0)
1345 {
1346 _auto_MethodId = methodID;
1347 writtenMethodId = -1;
1348 Modify_Auto(s);
1349 }
1350 const int itemIndex = (int)ComboBox_AddStringAscii(m_Method, s);
1351 m_Method.SetItemData(itemIndex, writtenMethodId);
1352 if (keepMethodId == methodID)
1353 {
1354 m_Method.SetCurSel(itemIndex);
1355 weUseSameMethod = true;
1356 continue;
1357 }
1358 if ((defaultMethod.IsEqualTo_Ascii_NoCase(method) || m == 0) && !weUseSameMethod)
1359 m_Method.SetCurSel(itemIndex);
1360 }
1361
1362 if (!weUseSameMethod)
1363 MethodChanged();
1364}
1365
1366
1367
1368bool CCompressDialog::IsZipFormat()
1369{
1370 return Get_ArcInfoEx().Name.IsEqualTo_Ascii_NoCase("zip");
1371}
1372
1373bool CCompressDialog::IsXzFormat()
1374{
1375 return Get_ArcInfoEx().Name.IsEqualTo_Ascii_NoCase("xz");
1376}
1377
1378void CCompressDialog::SetEncryptionMethod()
1379{
1380 _encryptionMethod.ResetContent();
1381 _default_encryptionMethod_Index = -1;
1382 const CArcInfoEx &ai = Get_ArcInfoEx();
1383 if (ai.Name.IsEqualTo_Ascii_NoCase("7z"))
1384 {
1385 ComboBox_AddStringAscii(_encryptionMethod, "AES-256");
1386 _encryptionMethod.SetCurSel(0);
1387 _default_encryptionMethod_Index = 0;
1388 }
1389 else if (ai.Name.IsEqualTo_Ascii_NoCase("zip"))
1390 {
1391 int index = FindRegistryFormat(ai.Name);
1392 UString encryptionMethod;
1393 if (index >= 0)
1394 {
1395 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1396 encryptionMethod = fo.EncryptionMethod;
1397 }
1398 int sel = 0;
1399 // if (ZipCryptoIsAllowed)
1400 {
1401 ComboBox_AddStringAscii(_encryptionMethod, "ZipCrypto");
1402 sel = (encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0);
1403 _default_encryptionMethod_Index = 0;
1404 }
1405 ComboBox_AddStringAscii(_encryptionMethod, "AES-256");
1406 _encryptionMethod.SetCurSel(sel);
1407 }
1408}
1409
1410
1411int CCompressDialog::GetMethodID_RAW()
1412{
1413 if (m_Method.GetCount() <= 0)
1414 return -1;
1415 return (int)(Int32)(UInt32)m_Method.GetItemData_of_CurSel();
1416}
1417
1418int CCompressDialog::GetMethodID()
1419{
1420 int raw = GetMethodID_RAW();
1421 if (raw < 0)
1422 return _auto_MethodId;
1423 return raw;
1424}
1425
1426
1427UString CCompressDialog::GetMethodSpec(UString &estimatedName)
1428{
1429 estimatedName.Empty();
1430 if (m_Method.GetCount() < 1)
1431 return estimatedName;
1432 const int methodIdRaw = GetMethodID_RAW();
1433 int methodId = methodIdRaw;
1434 if (methodIdRaw < 0)
1435 methodId = _auto_MethodId;
1436 UString s;
1437 if (methodId >= 0)
1438 {
1439 if ((unsigned)methodId < ARRAY_SIZE(kMethodsNames))
1440 estimatedName = kMethodsNames[methodId];
1441 else
1442 estimatedName = ExternalMethods[methodId - ARRAY_SIZE(kMethodsNames)];
1443 if (methodIdRaw >= 0)
1444 s = estimatedName;
1445 }
1446 return s;
1447}
1448
1449
1450UString CCompressDialog::GetMethodSpec()
1451{
1452 UString estimatedName;
1453 UString s = GetMethodSpec(estimatedName);
1454 return s;
1455}
1456
1457bool CCompressDialog::IsMethodEqualTo(const UString &s)
1458{
1459 UString estimatedName;
1460 const UString shortName = GetMethodSpec(estimatedName);
1461 if (s.IsEmpty())
1462 return shortName.IsEmpty();
1463 return s.IsEqualTo_NoCase(estimatedName);
1464}
1465
1466
1467UString CCompressDialog::GetEncryptionMethodSpec()
1468{
1469 UString s;
1470 if (_encryptionMethod.GetCount() > 0
1471 && _encryptionMethod.GetCurSel() != _default_encryptionMethod_Index)
1472 {
1473 _encryptionMethod.GetText(s);
1474 s.RemoveChar(L'-');
1475 }
1476 return s;
1477}
1478
1479static const size_t k_Auto_Dict = (size_t)0 - 1;
1480
1481
1482int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow)
1483{
1484 char c = 0;
1485 unsigned moveBits = 0;
1486 if ((sizeShow & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
1487 else if ((sizeShow & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
1488 AString s;
1489 s.Add_UInt64(sizeShow >> moveBits);
1490 s.Add_Space();
1491 if (moveBits != 0)
1492 s += c;
1493 s += 'B';
1494 if (sizeReal == k_Auto_Dict)
1495 Modify_Auto(s);
1496 const int index = (int)ComboBox_AddStringAscii(m_Dictionary, s);
1497 m_Dictionary.SetItemData(index, sizeReal);
1498 return index;
1499}
1500
1501
1502int CCompressDialog::AddDict(size_t size)
1503{
1504 return AddDict2(size, size);
1505}
1506
1507
1508void CCompressDialog::SetDictionary2()
1509{
1510 m_Dictionary.ResetContent();
1511 // _auto_Dict = (UInt32)1 << 24; // we can use this dictSize to calculate _auto_Solid for unknown method for 7z
1512 _auto_Dict = (UInt32)(Int32)-1; // for debug:
1513
1514 const CArcInfoEx &ai = Get_ArcInfoEx();
1515 UInt32 defaultDict = (UInt32)(Int32)-1;
1516 {
1517 const int index = FindRegistryFormat(ai.Name);
1518 if (index >= 0)
1519 {
1520 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1521 if (IsMethodEqualTo(fo.Method))
1522 defaultDict = fo.Dictionary;
1523 }
1524 }
1525
1526 const int methodID = GetMethodID();
1527 const UInt32 level = GetLevel2();
1528 if (methodID < 0)
1529 return;
1530
1531 switch (methodID)
1532 {
1533 case kLZMA:
1534 case kLZMA2:
1535 {
1536 {
1537 _auto_Dict =
1538 ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
1539 ( level <= 6 ? ((UInt32)1 << (level + 19)) :
1540 ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
1541 )));
1542 }
1543
1544 // we use threshold 3.75 GiB to switch to kLzmaMaxDictSize.
1545 if (defaultDict != (UInt32)(Int32)-1
1546 && defaultDict >= ((UInt32)15 << 28))
1547 defaultDict = kLzmaMaxDictSize;
1548
1549 const size_t kLzmaMaxDictSize_Up = (size_t)1 << (20 + sizeof(size_t) / 4 * 6);
1550
1551 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
1552
1553 for (unsigned i = (16 - 1) * 2; i <= (32 - 1) * 2; i++)
1554 {
1555 if (i < (20 - 1) * 2
1556 && i != (16 - 1) * 2
1557 && i != (18 - 1) * 2)
1558 continue;
1559 if (i == (20 - 1) * 2 + 1)
1560 continue;
1561 const size_t dict_up = (size_t)(2 + (i & 1)) << (i / 2);
1562 size_t dict = dict_up;
1563 if (dict_up >= kLzmaMaxDictSize)
1564 dict = kLzmaMaxDictSize; // we reduce dictionary
1565
1566 const int index = AddDict(dict);
1567 // AddDict2(dict, dict_up); // for debug : we show 4 GB
1568
1569 // const UInt32 numThreads = 2;
1570 // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(numThreads, dict);
1571 if (defaultDict != (UInt32)(Int32)-1)
1572 if (dict <= defaultDict || curSel <= 0)
1573 // if (!maxRamSize_Defined || memUsage <= maxRamSize)
1574 curSel = index;
1575 if (dict_up >= kLzmaMaxDictSize_Up)
1576 break;
1577 }
1578
1579 m_Dictionary.SetCurSel(curSel);
1580 break;
1581 }
1582
1583 case kPPMd:
1584 {
1585 _auto_Dict = (UInt32)1 << (level + 19);
1586
1587 const UInt32 kPpmd_Default_4g = (UInt32)0 - ((UInt32)1 << 10);
1588 const size_t kPpmd_MaxDictSize_Up = (size_t)1 << (29 + sizeof(size_t) / 8);
1589
1590 if (defaultDict != (UInt32)(Int32)-1
1591 && defaultDict >= ((UInt32)15 << 28)) // threshold
1592 defaultDict = kPpmd_Default_4g;
1593
1594 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
1595
1596 for (unsigned i = (20 - 1) * 2; i <= (32 - 1) * 2; i++)
1597 {
1598 if (i == (20 - 1) * 2 + 1)
1599 continue;
1600
1601 const size_t dict_up = (size_t)(2 + (i & 1)) << (i / 2);
1602 size_t dict = dict_up;
1603 if (dict_up >= kPpmd_Default_4g)
1604 dict = kPpmd_Default_4g;
1605
1606 const int index = AddDict2(dict, dict_up);
1607 // AddDict2((UInt32)((UInt32)0 - 2), dict_up); // for debug
1608 // AddDict(dict_up); // for debug
1609 // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
1610 if (defaultDict != (UInt32)(Int32)-1)
1611 if (dict <= defaultDict || curSel <= 0)
1612 // if (!maxRamSize_Defined || memUsage <= maxRamSize)
1613 curSel = index;
1614 if (dict_up >= kPpmd_MaxDictSize_Up)
1615 break;
1616 }
1617 m_Dictionary.SetCurSel(curSel);
1618 break;
1619 }
1620
1621 case kPPMdZip:
1622 {
1623 _auto_Dict = (UInt32)1 << (level + 19);
1624
1625 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
1626
1627 for (unsigned i = 20; i <= 28; i++)
1628 {
1629 const UInt32 dict = (UInt32)1 << i;
1630 const int index = AddDict(dict);
1631 // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
1632 if (defaultDict != (UInt32)(Int32)-1)
1633 if (dict <= defaultDict || curSel <= 0)
1634 // if (!maxRamSize_Defined || memUsage <= maxRamSize)
1635 curSel = index;
1636 }
1637 m_Dictionary.SetCurSel(curSel);
1638 break;
1639 }
1640
1641 case kDeflate:
1642 case kDeflate64:
1643 {
1644 const UInt32 dict = (methodID == kDeflate ? (UInt32)(1 << 15) : (UInt32)(1 << 16));
1645 _auto_Dict = dict;
1646 AddDict2(k_Auto_Dict, _auto_Dict);
1647 m_Dictionary.SetCurSel(0);
1648 // EnableItem(IDC_COMPRESS_DICTIONARY, false);
1649 break;
1650 }
1651
1652 case kBZip2:
1653 {
1654 {
1655 if (level >= 5) _auto_Dict = (900 << 10);
1656 else if (level >= 3) _auto_Dict = (500 << 10);
1657 else _auto_Dict = (100 << 10);
1658 }
1659
1660 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
1661
1662 for (unsigned i = 1; i <= 9; i++)
1663 {
1664 const UInt32 dict = ((UInt32)i * 100) << 10;
1665 AddDict(dict);
1666 // AddDict2(i * 100000, dict);
1667 if (defaultDict != (UInt32)(Int32)-1)
1668 if (i <= defaultDict / 100000 || curSel <= 0)
1669 curSel = m_Dictionary.GetCount() - 1;
1670 }
1671 m_Dictionary.SetCurSel(curSel);
1672 break;
1673 }
1674
1675 case kCopy:
1676 {
1677 _auto_Dict = 0;
1678 AddDict(0);
1679 m_Dictionary.SetCurSel(0);
1680 break;
1681 }
1682 }
1683}
1684
1685
1686UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax)
1687{
1688 if (c.GetCount() <= defMax)
1689 return (UInt32)(Int32)-1;
1690 return (UInt32)c.GetItemData_of_CurSel();
1691}
1692
1693
1694UInt64 CCompressDialog::GetComboValue_64(NWindows::NControl::CComboBox &c, int defMax)
1695{
1696 if (c.GetCount() <= defMax)
1697 return (UInt64)(Int64)-1;
1698 // LRESULT is signed. so we cast it to unsigned size_t at first:
1699 LRESULT val = c.GetItemData_of_CurSel();
1700 if (val == (LPARAM)(INT_PTR)(-1))
1701 return (UInt64)(Int64)-1;
1702 return (UInt64)(size_t)c.GetItemData_of_CurSel();
1703}
1704
1705UInt32 CCompressDialog::GetLevel2()
1706{
1707 UInt32 level = GetLevel();
1708 if (level == (UInt32)(Int32)-1)
1709 level = 5;
1710 return level;
1711}
1712
1713
1714int CCompressDialog::AddOrder(UInt32 size)
1715{
1716 char s[32];
1717 ConvertUInt32ToString(size, s);
1718 int index = (int)ComboBox_AddStringAscii(m_Order, s);
1719 m_Order.SetItemData(index, size);
1720 return index;
1721}
1722
1723int CCompressDialog::AddOrder_Auto()
1724{
1725 AString s;
1726 s.Add_UInt32(_auto_Order);
1727 Modify_Auto(s);
1728 int index = (int)ComboBox_AddStringAscii(m_Order, s);
1729 m_Order.SetItemData(index, (LPARAM)(INT_PTR)(-1));
1730 return index;
1731}
1732
1733void CCompressDialog::SetOrder2()
1734{
1735 m_Order.ResetContent();
1736
1737 _auto_Order = 1;
1738
1739 const CArcInfoEx &ai = Get_ArcInfoEx();
1740 UInt32 defaultOrder = (UInt32)(Int32)-1;
1741
1742 {
1743 const int index = FindRegistryFormat(ai.Name);
1744 if (index >= 0)
1745 {
1746 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1747 if (IsMethodEqualTo(fo.Method))
1748 defaultOrder = fo.Order;
1749 }
1750 }
1751
1752 const int methodID = GetMethodID();
1753 const UInt32 level = GetLevel2();
1754 if (methodID < 0)
1755 return;
1756
1757 switch (methodID)
1758 {
1759 case kLZMA:
1760 case kLZMA2:
1761 {
1762 _auto_Order = (level < 7 ? 32 : 64);
1763 int curSel = AddOrder_Auto();
1764 for (unsigned i = 2 * 2; i < 8 * 2; i++)
1765 {
1766 UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
1767 if (order > 256)
1768 order = 273;
1769 const int index = AddOrder(order);
1770 if (defaultOrder != (UInt32)(Int32)-1)
1771 if (order <= defaultOrder || curSel <= 0)
1772 curSel = index;
1773 }
1774 m_Order.SetCurSel(curSel);
1775 break;
1776 }
1777
1778 case kDeflate:
1779 case kDeflate64:
1780 {
1781 {
1782 if (level >= 9) _auto_Order = 128;
1783 else if (level >= 7) _auto_Order = 64;
1784 else _auto_Order = 32;
1785 }
1786 int curSel = AddOrder_Auto();
1787 for (unsigned i = 2 * 2; i < 8 * 2; i++)
1788 {
1789 UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
1790 if (order > 256)
1791 order = (methodID == kDeflate64 ? 257 : 258);
1792 const int index = AddOrder(order);
1793 if (defaultOrder != (UInt32)(Int32)-1)
1794 if (order <= defaultOrder || curSel <= 0)
1795 curSel = index;
1796 }
1797
1798 m_Order.SetCurSel(curSel);
1799 break;
1800 }
1801
1802 case kPPMd:
1803 {
1804 {
1805 if (level >= 9) _auto_Order = 32;
1806 else if (level >= 7) _auto_Order = 16;
1807 else if (level >= 5) _auto_Order = 6;
1808 else _auto_Order = 4;
1809 }
1810
1811 int curSel = AddOrder_Auto();
1812
1813 for (unsigned i = 0;; i++)
1814 {
1815 UInt32 order = i + 2;
1816 if (i >= 2)
1817 order = (4 + ((i - 2) & 3)) << ((i - 2) / 4);
1818 const int index = AddOrder(order);
1819 if (defaultOrder != (UInt32)(Int32)-1)
1820 if (order <= defaultOrder || curSel <= 0)
1821 curSel = index;
1822 if (order >= 32)
1823 break;
1824 }
1825 m_Order.SetCurSel(curSel);
1826 break;
1827 }
1828
1829 case kPPMdZip:
1830 {
1831 _auto_Order = level + 3;
1832 int curSel = AddOrder_Auto();
1833 for (unsigned i = 2; i <= 16; i++)
1834 {
1835 const int index = AddOrder(i);
1836 if (defaultOrder != (UInt32)(Int32)-1)
1837 if (i <= defaultOrder || curSel <= 0)
1838 curSel = index;
1839 }
1840 m_Order.SetCurSel(curSel);
1841 break;
1842 }
1843
1844 // case kBZip2:
1845 default:
1846 break;
1847 }
1848}
1849
1850bool CCompressDialog::GetOrderMode()
1851{
1852 switch (GetMethodID())
1853 {
1854 case kPPMd:
1855 case kPPMdZip:
1856 return true;
1857 }
1858 return false;
1859}
1860
1861
1862static UInt64 Get_Lzma2_ChunkSize(UInt64 dict)
1863{
1864 // we use same default chunk sizes as defined in 7z encoder and lzma2 encoder
1865 UInt64 cs = (UInt64)dict << 2;
1866 const UInt32 kMinSize = (UInt32)1 << 20;
1867 const UInt32 kMaxSize = (UInt32)1 << 28;
1868 if (cs < kMinSize) cs = kMinSize;
1869 if (cs > kMaxSize) cs = kMaxSize;
1870 if (cs < dict) cs = dict;
1871 cs += (kMinSize - 1);
1872 cs &= ~(UInt64)(kMinSize - 1);
1873 return cs;
1874}
1875
1876
1877static void Add_Size(AString &s, UInt64 val)
1878{
1879 unsigned moveBits = 0;
1880 char c = 0;
1881 if ((val & 0x3FFFFFFF) == 0) { moveBits = 30; c = 'G'; }
1882 else if ((val & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
1883 else if ((val & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
1884 s.Add_UInt64(val >> moveBits);
1885 s.Add_Space();
1886 if (moveBits != 0)
1887 s += c;
1888 s += 'B';
1889}
1890
1891
1892void CCompressDialog::SetSolidBlockSize2()
1893{
1894 m_Solid.ResetContent();
1895 _auto_Solid = 1 << 20;
1896
1897 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1898 if (!fi.Solid_())
1899 return;
1900
1901 const UInt32 level = GetLevel2();
1902 if (level == 0)
1903 return;
1904
1905 UInt64 dict = GetDict2();
1906 if (dict == (UInt64)(Int64)-1)
1907 {
1908 dict = 1 << 25; // default dict for unknown methods
1909 // return;
1910 }
1911
1912
1913 UInt32 defaultBlockSize = (UInt32)(Int32)-1;
1914
1915 const CArcInfoEx &ai = Get_ArcInfoEx();
1916
1917 /*
1918 if (usePrevDictionary)
1919 defaultBlockSize = GetBlockSizeSpec();
1920 else
1921 */
1922 {
1923 const int index = FindRegistryFormat(ai.Name);
1924 if (index >= 0)
1925 {
1926 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1927 if (IsMethodEqualTo(fo.Method))
1928 defaultBlockSize = fo.BlockLogSize;
1929 }
1930 }
1931
1932 const bool is7z = ai.Name.IsEqualTo_Ascii_NoCase("7z");
1933
1934 const UInt64 cs = Get_Lzma2_ChunkSize(dict);
1935
1936 // Solid Block Size
1937 UInt64 blockSize = cs; // for xz
1938
1939 if (is7z)
1940 {
1941 // we use same default block sizes as defined in 7z encoder
1942 UInt64 kMaxSize = (UInt64)1 << 32;
1943 const int methodId = GetMethodID();
1944 if (methodId == kLZMA2)
1945 {
1946 blockSize = cs << 6;
1947 kMaxSize = (UInt64)1 << 34;
1948 }
1949 else
1950 {
1951 UInt64 dict2 = dict;
1952 if (methodId == kBZip2)
1953 {
1954 dict2 /= 100000;
1955 if (dict2 < 1)
1956 dict2 = 1;
1957 dict2 *= 100000;
1958 }
1959 blockSize = dict2 << 7;
1960 }
1961
1962 const UInt32 kMinSize = (UInt32)1 << 24;
1963 if (blockSize < kMinSize) blockSize = kMinSize;
1964 if (blockSize > kMaxSize) blockSize = kMaxSize;
1965 }
1966
1967 _auto_Solid = blockSize;
1968
1969 int curSel;
1970 {
1971 AString s;
1972 Add_Size(s, _auto_Solid);
1973 Modify_Auto(s);
1974 int index = (int)ComboBox_AddStringAscii(m_Solid, s);
1975 m_Solid.SetItemData(index, (UInt32)(Int32)-1);
1976 curSel = index;
1977 }
1978
1979 if (is7z)
1980 {
1981 UString s ('-');
1982 // kSolidLog_NoSolid = 0 for xz means default blockSize
1983 if (is7z)
1984 LangString(IDS_COMPRESS_NON_SOLID, s);
1985 const int index = (int)m_Solid.AddString(s);
1986 m_Solid.SetItemData(index, (UInt32)kSolidLog_NoSolid);
1987 if (defaultBlockSize == kSolidLog_NoSolid)
1988 curSel = index;
1989 }
1990
1991 for (unsigned i = 20; i <= 36; i++)
1992 {
1993 AString s;
1994 Add_Size(s, (UInt64)1 << i);
1995 const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
1996 m_Solid.SetItemData(index, (UInt32)i);
1997 if (defaultBlockSize != (UInt32)(Int32)-1)
1998 if (i <= defaultBlockSize || index <= 1)
1999 curSel = index;
2000 }
2001
2002 {
2003 const int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID));
2004 m_Solid.SetItemData(index, kSolidLog_FullSolid);
2005 if (defaultBlockSize == kSolidLog_FullSolid)
2006 curSel = index;
2007 }
2008
2009 m_Solid.SetCurSel(curSel);
2010}
2011
2012
2013void CCompressDialog::SetNumThreads2()
2014{
2015 _auto_NumThreads = 1;
2016
2017 m_NumThreads.ResetContent();
2018 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
2019 if (!fi.MultiThread_())
2020 return;
2021
2022 const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();
2023 // 64; // for debug:
2024
2025 UInt32 defaultValue = numHardwareThreads;
2026 bool useAutoThreads = true;
2027
2028 {
2029 const CArcInfoEx &ai = Get_ArcInfoEx();
2030 int index = FindRegistryFormat(ai.Name);
2031 if (index >= 0)
2032 {
2033 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
2034 if (IsMethodEqualTo(fo.Method) && fo.NumThreads != (UInt32)(Int32)-1)
2035 {
2036 defaultValue = fo.NumThreads;
2037 useAutoThreads = false;
2038 }
2039 }
2040 }
2041
2042 UInt32 numAlgoThreadsMax = numHardwareThreads * 2;
2043 const int methodID = GetMethodID();
2044 switch (methodID)
2045 {
2046 case kLZMA: numAlgoThreadsMax = 2; break;
2047 case kLZMA2: numAlgoThreadsMax = 256; break;
2048 case kBZip2: numAlgoThreadsMax = 32; break;
2049 case kCopy:
2050 case kPPMd:
2051 case kDeflate:
2052 case kDeflate64:
2053 case kPPMdZip:
2054 numAlgoThreadsMax = 1;
2055 }
2056 const bool isZip = IsZipFormat();
2057 if (isZip)
2058 {
2059 numAlgoThreadsMax =
2060 #ifdef _WIN32
2061 64; // _WIN32 supports only 64 threads in one group. So no need for more threads here
2062 #else
2063 128;
2064 #endif
2065 }
2066
2067 UInt32 autoThreads = numHardwareThreads;
2068 if (autoThreads > numAlgoThreadsMax)
2069 autoThreads = numAlgoThreadsMax;
2070
2071 const UInt64 memUse_Limit = Get_MemUse_Bytes();
2072
2073 if (autoThreads > 1 && _ramSize_Defined)
2074 {
2075 if (isZip)
2076 {
2077 for (; autoThreads > 1; autoThreads--)
2078 {
2079 const UInt64 dict64 = GetDict2();
2080 UInt64 decompressMemory;
2081 const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
2082 if (usage <= memUse_Limit)
2083 break;
2084 }
2085 }
2086 else if (methodID == kLZMA2)
2087 {
2088 const UInt64 dict64 = GetDict2();
2089 const UInt32 numThreads1 = (GetLevel2() >= 5 ? 2 : 1);
2090 UInt32 numBlockThreads = autoThreads / numThreads1;
2091 for (; numBlockThreads > 1; numBlockThreads--)
2092 {
2093 autoThreads = numBlockThreads * numThreads1;
2094 UInt64 decompressMemory;
2095 const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
2096 if (usage <= memUse_Limit)
2097 break;
2098 }
2099 autoThreads = numBlockThreads * numThreads1;
2100 }
2101 }
2102
2103 _auto_NumThreads = autoThreads;
2104
2105 int curSel = -1;
2106 {
2107 AString s;
2108 s.Add_UInt32(autoThreads);
2109 Modify_Auto(s);
2110 int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
2111 m_NumThreads.SetItemData(index, (LPARAM)(INT_PTR)(-1));
2112 // m_NumThreads.SetItemData(index, autoThreads);
2113 if (useAutoThreads)
2114 curSel = index;
2115 }
2116
2117 if (numAlgoThreadsMax != autoThreads || autoThreads != 1)
2118 for (UInt32 i = 1; i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++)
2119 {
2120 char s[32];
2121 ConvertUInt32ToString(i, s);
2122 int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
2123 m_NumThreads.SetItemData(index, (UInt32)i);
2124 if (!useAutoThreads && i == defaultValue)
2125 curSel = index;
2126 }
2127
2128 m_NumThreads.SetCurSel(curSel);
2129}
2130
2131
2132static void AddMemSize(UString &res, UInt64 size)
2133{
2134 char c;
2135 unsigned moveBits = 0;
2136 if (size >= ((UInt64)1 << 31) && (size & 0x3FFFFFFF) == 0)
2137 { moveBits = 30; c = 'G'; }
2138 else // if (size >= ((UInt32)1 << 21) && (size & 0xFFFFF) == 0)
2139 { moveBits = 20; c = 'M'; }
2140 // else { moveBits = 10; c = 'K'; }
2141 res.Add_UInt64(size >> moveBits);
2142 res.Add_Space();
2143 if (moveBits != 0)
2144 res += c;
2145 res += 'B';
2146}
2147
2148
2149int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault)
2150{
2151 UString sUser;
2152 UString sRegistry;
2153 if (isPercent)
2154 {
2155 UString s;
2156 s.Add_UInt64(val);
2157 s += '%';
2158 if (isDefault)
2159 sUser = "* ";
2160 else
2161 sRegistry = s;
2162 sUser += s;
2163 }
2164 else
2165 {
2166 AddMemSize(sUser, val);
2167 sRegistry = sUser;
2168 for (;;)
2169 {
2170 int pos = sRegistry.Find(L' ');
2171 if (pos < 0)
2172 break;
2173 sRegistry.Delete(pos);
2174 }
2175 if (!sRegistry.IsEmpty())
2176 if (sRegistry.Back() == 'B')
2177 sRegistry.DeleteBack();
2178 }
2179 const unsigned dataIndex = _memUse_Strings.Add(sRegistry);
2180 const int index = (int)m_MemUse.AddString(sUser);
2181 m_MemUse.SetItemData(index, dataIndex);
2182 return index;
2183}
2184
2185
2186
2187void CCompressDialog::SetMemUseCombo()
2188{
2189 _memUse_Strings.Clear();
2190 m_MemUse.ResetContent();
2191 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
2192
2193 {
2194 const bool enable = fi.MemUse_();
2195 ShowItem_Bool(IDT_COMPRESS_MEMORY, enable);
2196 ShowItem_Bool(IDT_COMPRESS_MEMORY_VALUE, enable);
2197 ShowItem_Bool(IDT_COMPRESS_MEMORY_DE, enable);
2198 ShowItem_Bool(IDT_COMPRESS_MEMORY_DE_VALUE, enable);
2199 ShowItem_Bool(IDC_COMPRESS_MEM_USE, enable);
2200 EnableItem(IDC_COMPRESS_MEM_USE, enable);
2201 if (!enable)
2202 return;
2203 }
2204
2205 UInt64 curMem_Bytes = 0;
2206 UInt64 curMem_Percents = 0;
2207 bool needSetCur_Bytes = false;
2208 bool needSetCur_Percents = false;
2209 {
2210 const NCompression::CFormatOptions &fo = Get_FormatOptions();
2211 if (!fo.MemUse.IsEmpty())
2212 {
2213 NCompression::CMemUse mu;
2214 mu.Parse(fo.MemUse);
2215 if (mu.IsDefined)
2216 {
2217 if (mu.IsPercent)
2218 {
2219 curMem_Percents = mu.Val;
2220 needSetCur_Percents = true;
2221 }
2222 else
2223 {
2224 curMem_Bytes = mu.GetBytes(_ramSize_Reduced);
2225 needSetCur_Bytes = true;
2226 }
2227 }
2228 }
2229 }
2230
2231
2232 // 80% - is auto usage limit in handlers
2233 AddMemComboItem(80, true, true);
2234 m_MemUse.SetCurSel(0);
2235
2236 {
2237 for (unsigned i = 10;; i += 10)
2238 {
2239 UInt64 size = i;
2240 if (i > 100)
2241 size = (UInt64)(Int64)-1;
2242 if (needSetCur_Percents && size >= curMem_Percents)
2243 {
2244 const int index = AddMemComboItem(curMem_Percents, true);
2245 m_MemUse.SetCurSel(index);
2246 needSetCur_Percents = false;
2247 if (size == curMem_Percents)
2248 continue;
2249 }
2250 if (size == (UInt64)(Int64)-1)
2251 break;
2252 AddMemComboItem(size, true);
2253 }
2254 }
2255 {
2256 for (unsigned i = (27) * 2;; i++)
2257 {
2258 UInt64 size = (UInt64)(2 + (i & 1)) << (i / 2);
2259 if (i > (20 + sizeof(size_t) * 3 - 1) * 2)
2260 size = (UInt64)(Int64)-1;
2261 if (needSetCur_Bytes && size >= curMem_Bytes)
2262 {
2263 const int index = AddMemComboItem(curMem_Bytes);
2264 m_MemUse.SetCurSel(index);
2265 needSetCur_Bytes = false;
2266 if (size == curMem_Bytes)
2267 continue;
2268 }
2269 if (size == (UInt64)(Int64)-1)
2270 break;
2271 AddMemComboItem(size);
2272 }
2273 }
2274}
2275
2276
2277UString CCompressDialog::Get_MemUse_Spec()
2278{
2279 if (m_MemUse.GetCount() < 1)
2280 return UString();
2281 return _memUse_Strings[(unsigned)m_MemUse.GetItemData_of_CurSel()];
2282}
2283
2284
2285UInt64 CCompressDialog::Get_MemUse_Bytes()
2286{
2287 const UString mus = Get_MemUse_Spec();
2288 NCompression::CMemUse mu;
2289 if (!mus.IsEmpty())
2290 {
2291 mu.Parse(mus);
2292 if (mu.IsDefined)
2293 return mu.GetBytes(_ramSize_Reduced);
2294 }
2295 return _ramUsage_Auto; // _ramSize_Reduced; // _ramSize;;
2296}
2297
2298
2299
2300UInt64 CCompressDialog::GetMemoryUsage_DecompMem(UInt64 &decompressMemory)
2301{
2302 return GetMemoryUsage_Dict_DecompMem(GetDict2(), decompressMemory);
2303}
2304
2305UInt64 CCompressDialog::GetMemoryUsageComp_Threads_Dict(UInt32 numThreads, UInt64 dict64)
2306{
2307 UInt64 decompressMemory;
2308 return GetMemoryUsage_Threads_Dict_DecompMem(numThreads, dict64, decompressMemory);
2309}
2310
2311UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &decompressMemory)
2312{
2313 return GetMemoryUsage_Threads_Dict_DecompMem(GetNumThreads2(), dict64, decompressMemory);
2314}
2315
2316UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 dict64, UInt64 &decompressMemory)
2317{
2318 decompressMemory = (UInt64)(Int64)-1;
2319 if (dict64 == (UInt64)(Int64)-1)
2320 return (UInt64)(Int64)-1;
2321
2322 UInt32 level = GetLevel2();
2323 if (level == 0)
2324 {
2325 decompressMemory = (1 << 20);
2326 return decompressMemory;
2327 }
2328 UInt64 size = 0;
2329
2330 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
2331 if (fi.Filter_() && level >= 9)
2332 size += (12 << 20) * 2 + (5 << 20);
2333 // UInt32 numThreads = GetNumThreads2();
2334
2335 UInt32 numMainZipThreads = 1;
2336
2337 if (IsZipFormat())
2338 {
2339 UInt32 numSubThreads = 1;
2340 if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5)
2341 numSubThreads = 2;
2342 numMainZipThreads = numThreads / numSubThreads;
2343 if (numMainZipThreads > 1)
2344 size += (UInt64)numMainZipThreads * ((size_t)sizeof(size_t) << 23);
2345 else
2346 numMainZipThreads = 1;
2347 }
2348
2349 const int methodId = GetMethodID();
2350
2351 switch (methodId)
2352 {
2353 case kLZMA:
2354 case kLZMA2:
2355 {
2356 const UInt32 dict = (dict64 >= kLzmaMaxDictSize ? kLzmaMaxDictSize : (UInt32)dict64);
2357 UInt32 hs = dict - 1;
2358 hs |= (hs >> 1);
2359 hs |= (hs >> 2);
2360 hs |= (hs >> 4);
2361 hs |= (hs >> 8);
2362 hs >>= 1;
2363 if (hs >= (1 << 24))
2364 hs >>= 1;
2365 hs |= (1 << 16) - 1;
2366 // if (numHashBytes >= 5)
2367 if (level < 5)
2368 hs |= (256 << 10) - 1;
2369 hs++;
2370 UInt64 size1 = (UInt64)hs * 4;
2371 size1 += (UInt64)dict * 4;
2372 if (level >= 5)
2373 size1 += (UInt64)dict * 4;
2374 size1 += (2 << 20);
2375
2376 UInt32 numThreads1 = 1;
2377 if (numThreads > 1 && level >= 5)
2378 {
2379 size1 += (2 << 20) + (4 << 20);
2380 numThreads1 = 2;
2381 }
2382
2383 UInt32 numBlockThreads = numThreads / numThreads1;
2384
2385 UInt64 chunkSize = 0; // it's solid chunk
2386
2387 if (methodId != kLZMA && numBlockThreads != 1)
2388 {
2389 chunkSize = Get_Lzma2_ChunkSize(dict);
2390
2391 if (IsXzFormat())
2392 {
2393 UInt32 blockSizeLog = GetBlockSizeSpec();
2394 if (blockSizeLog != (UInt32)(Int32)-1)
2395 {
2396 if (blockSizeLog == kSolidLog_FullSolid)
2397 {
2398 numBlockThreads = 1;
2399 chunkSize = 0;
2400 }
2401 else if (blockSizeLog != kSolidLog_NoSolid)
2402 chunkSize = (UInt64)1 << blockSizeLog;
2403 }
2404 }
2405 }
2406
2407 if (chunkSize == 0)
2408 {
2409 const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16);
2410 UInt64 blockSize = (UInt64)dict + (1 << 16)
2411 + (numThreads1 > 1 ? (1 << 20) : 0);
2412 blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2));
2413 if (blockSize >= kBlockSizeMax)
2414 blockSize = kBlockSizeMax;
2415 size += numBlockThreads * (size1 + blockSize);
2416 }
2417 else
2418 {
2419 size += numBlockThreads * (size1 + chunkSize);
2420 UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
2421 if (chunkSize < ((UInt32)1 << 26)) numBlockThreads++;
2422 if (chunkSize < ((UInt32)1 << 24)) numBlockThreads++;
2423 if (chunkSize < ((UInt32)1 << 22)) numBlockThreads++;
2424 size += numPackChunks * chunkSize;
2425 }
2426
2427 decompressMemory = dict + (2 << 20);
2428 return size;
2429 }
2430
2431 case kPPMd:
2432 {
2433 decompressMemory = dict64 + (2 << 20);
2434 return size + decompressMemory;
2435 }
2436
2437 case kDeflate:
2438 case kDeflate64:
2439 {
2440 UInt64 size1 = 3 << 20;
2441 // if (level >= 7)
2442 size1 += (1 << 20);
2443 size += size1 * numMainZipThreads;
2444 decompressMemory = (2 << 20);
2445 return size;
2446 }
2447
2448 case kBZip2:
2449 {
2450 decompressMemory = (7 << 20);
2451 UInt64 memForOneThread = (10 << 20);
2452 return size + memForOneThread * numThreads;
2453 }
2454
2455 case kPPMdZip:
2456 {
2457 decompressMemory = dict64 + (2 << 20);
2458 return size + (UInt64)decompressMemory * numThreads;
2459 }
2460 }
2461
2462 return (UInt64)(Int64)-1;
2463}
2464
2465
2466
2467static void AddMemUsage(UString &s, UInt64 v)
2468{
2469 const char *post;
2470 if (v <= ((UInt64)16 << 30))
2471 {
2472 v = (v + (1 << 20) - 1) >> 20;
2473 post = "MB";
2474 }
2475 else if (v <= ((UInt64)64 << 40))
2476 {
2477 v = (v + (1 << 30) - 1) >> 30;
2478 post = "GB";
2479 }
2480 else
2481 {
2482 const UInt64 v2 = v + ((UInt64)1 << 40) - 1;
2483 if (v <= v2)
2484 v = v2;
2485 v >>= 40;
2486 post = "TB";
2487 }
2488 s.Add_UInt64(v);
2489 s.Add_Space();
2490 s += post;
2491}
2492
2493
2494void CCompressDialog::PrintMemUsage(UINT res, UInt64 value)
2495{
2496 if (value == (UInt64)(Int64)-1)
2497 {
2498 SetItemText(res, TEXT("?"));
2499 return;
2500 }
2501 UString s;
2502 AddMemUsage(s, value);
2503 if (res == IDT_COMPRESS_MEMORY_VALUE)
2504 {
2505 const UString mus = Get_MemUse_Spec();
2506 NCompression::CMemUse mu;
2507 if (!mus.IsEmpty())
2508 mu.Parse(mus);
2509 if (mu.IsDefined)
2510 {
2511 s += " / ";
2512 AddMemUsage(s, mu.GetBytes(_ramSize_Reduced));
2513 }
2514 else if (_ramSize_Defined)
2515 {
2516 s += " / ";
2517 AddMemUsage(s, _ramUsage_Auto);
2518 }
2519
2520 if (_ramSize_Defined)
2521 {
2522 s += " / ";
2523 AddMemUsage(s, _ramSize);
2524 }
2525 }
2526 SetItemText(res, s);
2527}
2528
2529
2530void CCompressDialog::SetMemoryUsage()
2531{
2532 UInt64 decompressMem;
2533 const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem);
2534 PrintMemUsage(IDT_COMPRESS_MEMORY_VALUE, memUsage);
2535 PrintMemUsage(IDT_COMPRESS_MEMORY_DE_VALUE, decompressMem);
2536}
2537
2538void CCompressDialog::SetParams()
2539{
2540 const CArcInfoEx &ai = Get_ArcInfoEx();
2541 m_Params.SetText(TEXT(""));
2542 const int index = FindRegistryFormat(ai.Name);
2543 if (index >= 0)
2544 {
2545 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
2546 m_Params.SetText(fo.Options);
2547 }
2548}
2549
2550void CCompressDialog::SaveOptionsInMem()
2551{
2552 m_Params.GetText(Info.Options);
2553 Info.Options.Trim();
2554
2555 const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];
2556 const int index = FindRegistryFormatAlways(ai.Name);
2557 NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
2558 fo.Options = Info.Options;
2559 fo.Level = GetLevelSpec();
2560 {
2561 const UInt64 dict64 = GetDictSpec();
2562 UInt32 dict32;
2563 if (dict64 == (UInt64)(Int64)-1)
2564 dict32 = (UInt32)(Int32)-1;
2565 else
2566 {
2567 dict32 = (UInt32)dict64;
2568 if (dict64 != dict32)
2569 {
2570 /* here we must write 32-bit value for registry that indicates big_value
2571 (UInt32)(Int32)-1 : is used as marker for default size
2572 (UInt32)(Int32)-2 : it can be used to indicate big value (4 GiB)
2573 the value must be larger than threshold
2574 */
2575 dict32 = (UInt32)(Int32)-2;
2576 // dict32 = kLzmaMaxDictSize; // it must be larger than threshold
2577 }
2578 }
2579 fo.Dictionary = dict32;
2580 }
2581
2582 fo.Order = GetOrderSpec();
2583 fo.Method = GetMethodSpec();
2584 fo.EncryptionMethod = GetEncryptionMethodSpec();
2585 fo.NumThreads = GetNumThreadsSpec();
2586 fo.BlockLogSize = GetBlockSizeSpec();
2587 fo.MemUse = Get_MemUse_Spec();
2588}
2589
2590unsigned CCompressDialog::GetFormatIndex()
2591{
2592 return (unsigned)m_Format.GetItemData_of_CurSel();
2593}