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/PropertyName.h"
20 #include "../FileManager/SplitUtils.h"
21 #include "../FileManager/resourceGui.h"
22
23 #include "../Explorer/MyMessages.h"
24
25 #include "../Common/ZipRegistry.h"
26
27 #include "CompressDialog.h"
28
29 #ifndef _UNICODE
30 extern bool g_IsNT;
31 #endif
32
33 #include "../FileManager/LangUtils.h"
34
35 #include "CompressDialogRes.h"
36 #include "ExtractRes.h"
37 #include "resource2.h"
38
39 // #define PRINT_PARAMS
40
41 #ifdef Z7_LANG
42
43 // #define IDS_OPTIONS 2100
44
45 static const UInt32 kLangIDs[] =
46 {
47 IDT_COMPRESS_ARCHIVE,
48 IDT_COMPRESS_UPDATE_MODE,
49 IDT_COMPRESS_FORMAT,
50 IDT_COMPRESS_LEVEL,
51 IDT_COMPRESS_METHOD,
52 IDT_COMPRESS_DICTIONARY,
53 IDT_COMPRESS_ORDER,
54 IDT_COMPRESS_SOLID,
55 IDT_COMPRESS_THREADS,
56 IDT_COMPRESS_PARAMETERS,
57
58 IDB_COMPRESS_OPTIONS, // IDS_OPTIONS
59
60 IDG_COMPRESS_OPTIONS,
61 IDX_COMPRESS_SFX,
62 IDX_COMPRESS_SHARED,
63 IDX_COMPRESS_DEL,
64
65 IDT_COMPRESS_MEMORY,
66 IDT_COMPRESS_MEMORY_DE,
67
68 IDG_COMPRESS_ENCRYPTION,
69 IDT_COMPRESS_ENCRYPTION_METHOD,
70 IDX_COMPRESS_ENCRYPT_FILE_NAMES,
71
72 IDT_PASSWORD_ENTER,
73 IDT_PASSWORD_REENTER,
74 IDX_PASSWORD_SHOW,
75
76 IDT_SPLIT_TO_VOLUMES,
77 IDT_COMPRESS_PATH_MODE,
78 };
79 #endif
80
81 using namespace NWindows;
82 using namespace NFile;
83 using namespace NName;
84 using namespace NDir;
85
86 static const unsigned kHistorySize = 20;
87
88 static const UInt32 kSolidLog_NoSolid = 0;
89 static const UInt32 kSolidLog_FullSolid = 64;
90
91 static const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28;
92
93 static const UINT k_Message_ArcChanged = WM_APP + 1;
94
95 /*
96 static const UInt32 kZstd_MAX_DictSize = (UInt32)1 << MY_ZSTD_WINDOWLOG_MAX;
97 */
98
99 /* The top value for windowLog_Chain:
100 (MY_ZSTD_CHAINLOG_MAX - 1): in BT mode
101 (MY_ZSTD_CHAINLOG_MAX) : in non-BT mode. But such big value is useless in most cases.
102 So we always reduce top value to (MY_ZSTD_CHAINLOG_MAX - 1) */
103 /*
104 static const unsigned kMaxDictChain = MY_ZSTD_CHAINLOG_MAX - 1;
105 static const UInt32 kZstd_MAX_DictSize_Chain = (UInt32)1 << kMaxDictChain;
106 */
107
108 static LPCSTR const kExeExt = ".exe";
109
110 static const UInt32 g_Levels[] =
111 {
112 IDS_METHOD_STORE,
113 IDS_METHOD_FASTEST,
114 0,
115 IDS_METHOD_FAST,
116 0,
117 IDS_METHOD_NORMAL,
118 0,
119 IDS_METHOD_MAXIMUM,
120 0,
121 IDS_METHOD_ULTRA
122 };
123
124 enum EMethodID
125 {
126 kCopy,
127 kLZMA,
128 kLZMA2,
129 kPPMd,
130 kBZip2,
131 kDeflate,
132 kDeflate64,
133 kPPMdZip,
134 // kZSTD,
135 kSha256,
136 kSha1,
137 kCrc32,
138 kCrc64,
139 kGnu,
140 kPosix
141 };
142
143 static LPCSTR const kMethodsNames[] =
144 {
145 "Copy"
146 , "LZMA"
147 , "LZMA2"
148 , "PPMd"
149 , "BZip2"
150 , "Deflate"
151 , "Deflate64"
152 , "PPMd"
153 // , "ZSTD"
154 , "SHA256"
155 , "SHA1"
156 , "CRC32"
157 , "CRC64"
158 , "GNU"
159 , "POSIX"
160 };
161
162 static const EMethodID g_7zMethods[] =
163 {
164 kLZMA2,
165 kLZMA,
166 kPPMd,
167 kBZip2
168 , kDeflate
169 , kDeflate64
170 // , kZSTD
171 , kCopy
172 };
173
174 static const EMethodID g_7zSfxMethods[] =
175 {
176 kCopy,
177 kLZMA,
178 kLZMA2,
179 kPPMd
180 };
181
182 static const EMethodID g_ZipMethods[] =
183 {
184 kDeflate,
185 kDeflate64,
186 kBZip2,
187 kLZMA,
188 kPPMdZip
189 // , kZSTD
190 };
191
192 static const EMethodID g_GZipMethods[] =
193 {
194 kDeflate
195 };
196
197 static const EMethodID g_BZip2Methods[] =
198 {
199 kBZip2
200 };
201
202 static const EMethodID g_XzMethods[] =
203 {
204 kLZMA2
205 };
206
207 /*
208 static const EMethodID g_ZstdMethods[] =
209 {
210 kZSTD
211 };
212 */
213
214 static const EMethodID g_SwfcMethods[] =
215 {
216 kDeflate
217 // kLZMA
218 };
219
220 static const EMethodID g_TarMethods[] =
221 {
222 kGnu,
223 kPosix
224 };
225
226 static const EMethodID g_HashMethods[] =
227 {
228 kSha256
229 , kSha1
230 // , kCrc32
231 // , kCrc64
232 };
233
234 static const UInt32 kFF_Filter = 1 << 0;
235 static const UInt32 kFF_Solid = 1 << 1;
236 static const UInt32 kFF_MultiThread = 1 << 2;
237 static const UInt32 kFF_Encrypt = 1 << 3;
238 static const UInt32 kFF_EncryptFileNames = 1 << 4;
239 static const UInt32 kFF_MemUse = 1 << 5;
240 static const UInt32 kFF_SFX = 1 << 6;
241
242 /*
243 static const UInt32 kFF_Time_Win = 1 << 10;
244 static const UInt32 kFF_Time_Unix = 1 << 11;
245 static const UInt32 kFF_Time_DOS = 1 << 12;
246 static const UInt32 kFF_Time_1ns = 1 << 13;
247 */
248
249 struct CFormatInfo
250 {
251 LPCSTR Name;
252 UInt32 LevelsMask;
253 unsigned NumMethods;
254 const EMethodID *MethodIDs;
255
256 UInt32 Flags;
257
Filter_CFormatInfo258 bool Filter_() const { return (Flags & kFF_Filter) != 0; }
Solid_CFormatInfo259 bool Solid_() const { return (Flags & kFF_Solid) != 0; }
MultiThread_CFormatInfo260 bool MultiThread_() const { return (Flags & kFF_MultiThread) != 0; }
Encrypt_CFormatInfo261 bool Encrypt_() const { return (Flags & kFF_Encrypt) != 0; }
EncryptFileNames_CFormatInfo262 bool EncryptFileNames_() const { return (Flags & kFF_EncryptFileNames) != 0; }
MemUse_CFormatInfo263 bool MemUse_() const { return (Flags & kFF_MemUse) != 0; }
SFX_CFormatInfo264 bool SFX_() const { return (Flags & kFF_SFX) != 0; }
265 };
266
267 #define METHODS_PAIR(x) Z7_ARRAY_SIZE(x), x
268
269 static const CFormatInfo g_Formats[] =
270 {
271 {
272 "",
273 // (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
274 ((UInt32)1 << 10) - 1,
275 // (UInt32)(Int32)-1,
276 0, NULL,
277 kFF_MultiThread | kFF_MemUse
278 },
279 {
280 "7z",
281 (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
282 METHODS_PAIR(g_7zMethods),
283 kFF_Filter | kFF_Solid | kFF_MultiThread | kFF_Encrypt |
284 kFF_EncryptFileNames | kFF_MemUse | kFF_SFX
285 // | kFF_Time_Win
286 },
287 {
288 "Zip",
289 (1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
290 METHODS_PAIR(g_ZipMethods),
291 kFF_MultiThread | kFF_Encrypt | kFF_MemUse
292 // | kFF_Time_Win | kFF_Time_Unix | kFF_Time_DOS
293 },
294 {
295 "GZip",
296 (1 << 1) | (1 << 5) | (1 << 7) | (1 << 9),
297 METHODS_PAIR(g_GZipMethods),
298 kFF_MemUse
299 // | kFF_Time_Unix
300 },
301 {
302 "BZip2",
303 (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
304 METHODS_PAIR(g_BZip2Methods),
305 kFF_MultiThread | kFF_MemUse
306 },
307 {
308 "xz",
309 (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
310 METHODS_PAIR(g_XzMethods),
311 kFF_Solid | kFF_MultiThread | kFF_MemUse
312 },
313 /*
314 {
315 "zstd",
316 // (1 << (MY_ZSTD_LEVEL_MAX + 1)) - 1,
317 (1 << (9 + 1)) - 1,
318 METHODS_PAIR(g_ZstdMethods),
319 // kFF_Solid |
320 kFF_MultiThread
321 | kFF_MemUse
322 },
323 */
324 {
325 "Swfc",
326 (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9),
327 METHODS_PAIR(g_SwfcMethods),
328 0
329 },
330 {
331 "Tar",
332 (1 << 0),
333 METHODS_PAIR(g_TarMethods),
334 0
335 // kFF_Time_Unix | kFF_Time_Win // | kFF_Time_1ns
336 },
337 {
338 "wim",
339 (1 << 0),
340 0, NULL,
341 0
342 // | kFF_Time_Win
343 },
344 {
345 "Hash",
346 (0 << 0),
347 METHODS_PAIR(g_HashMethods),
348 0
349 }
350 };
351
IsMethodSupportedBySfx(int methodID)352 static bool IsMethodSupportedBySfx(int methodID)
353 {
354 for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_7zSfxMethods); i++)
355 if (methodID == g_7zSfxMethods[i])
356 return true;
357 return false;
358 }
359
360
361 static const
362 // NCompressDialog::NUpdateMode::EEnum
363 int
364 k_UpdateMode_Vals[] =
365 {
366 NCompressDialog::NUpdateMode::kAdd,
367 NCompressDialog::NUpdateMode::kUpdate,
368 NCompressDialog::NUpdateMode::kFresh,
369 NCompressDialog::NUpdateMode::kSync
370 };
371
372 static const UInt32 k_UpdateMode_IDs[] =
373 {
374 IDS_COMPRESS_UPDATE_MODE_ADD,
375 IDS_COMPRESS_UPDATE_MODE_UPDATE,
376 IDS_COMPRESS_UPDATE_MODE_FRESH,
377 IDS_COMPRESS_UPDATE_MODE_SYNC
378 };
379
380 static const
381 // NWildcard::ECensorPathMode
382 int
383 k_PathMode_Vals[] =
384 {
385 NWildcard::k_RelatPath,
386 NWildcard::k_FullPath,
387 NWildcard::k_AbsPath,
388 };
389
390 static const UInt32 k_PathMode_IDs[] =
391 {
392 IDS_PATH_MODE_RELAT,
393 IDS_EXTRACT_PATHS_FULL,
394 IDS_EXTRACT_PATHS_ABS
395 };
396
397 void AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal);
398
SetMethods(const CObjectVector<CCodecInfoUser> & userCodecs)399 void CCompressDialog::SetMethods(const CObjectVector<CCodecInfoUser> &userCodecs)
400 {
401 ExternalMethods.Clear();
402 {
403 FOR_VECTOR (i, userCodecs)
404 {
405 const CCodecInfoUser &c = userCodecs[i];
406 if (!c.EncoderIsAssigned
407 || !c.IsFilter_Assigned
408 || c.IsFilter
409 || c.NumStreams != 1)
410 continue;
411 unsigned k;
412 for (k = 0; k < Z7_ARRAY_SIZE(g_7zMethods); k++)
413 if (c.Name.IsEqualTo_Ascii_NoCase(kMethodsNames[g_7zMethods[k]]))
414 break;
415 if (k != Z7_ARRAY_SIZE(g_7zMethods))
416 continue;
417 ExternalMethods.Add(c.Name);
418 }
419 }
420 }
421
422
OnInit()423 bool CCompressDialog::OnInit()
424 {
425 #ifdef Z7_LANG
426 LangSetWindowText(*this, IDD_COMPRESS);
427 LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
428 // LangSetDlgItemText(*this, IDB_COMPRESS_OPTIONS, IDS_OPTIONS); // IDG_COMPRESS_OPTIONS
429 #endif
430
431 {
432 UInt64 size = (UInt64)(sizeof(size_t)) << 29;
433 _ramSize_Defined = NSystem::GetRamSize(size);
434 // size = (UInt64)3 << 62; // for debug only;
435 _ramSize = size;
436 const UInt64 kMinUseSize = (1 << 26);
437 if (size < kMinUseSize)
438 size = kMinUseSize;
439
440 unsigned bits = sizeof(size_t) * 8;
441 if (bits == 32)
442 {
443 const UInt32 limit2 = (UInt32)7 << 28;
444 if (size > limit2)
445 size = limit2;
446 }
447
448 _ramSize_Reduced = size;
449
450 // 80% - is auto usage limit in handlers
451 _ramUsage_Auto = Calc_From_Val_Percents(size, 80);
452 }
453
454 _password1Control.Attach(GetItem(IDE_COMPRESS_PASSWORD1));
455 _password2Control.Attach(GetItem(IDE_COMPRESS_PASSWORD2));
456 _password1Control.SetText(Info.Password);
457 _password2Control.SetText(Info.Password);
458 _encryptionMethod.Attach(GetItem(IDC_COMPRESS_ENCRYPTION_METHOD));
459 _default_encryptionMethod_Index = -1;
460
461 m_ArchivePath.Attach(GetItem(IDC_COMPRESS_ARCHIVE));
462 m_Format.Attach(GetItem(IDC_COMPRESS_FORMAT)); // that combo has CBS_SORT style in resources
463 m_Level.Attach(GetItem(IDC_COMPRESS_LEVEL));
464 m_Method.Attach(GetItem(IDC_COMPRESS_METHOD));
465 m_Dictionary.Attach(GetItem(IDC_COMPRESS_DICTIONARY));
466
467 /*
468 {
469 RECT r;
470 GetClientRectOfItem(IDC_COMPRESS_DICTIONARY, r);
471 _dictionaryCombo_left = r.left;
472 }
473 */
474 _dictionaryCombo_left = 0; // 230;
475
476 // m_Dictionary_Chain.Attach(GetItem(IDC_COMPRESS_DICTIONARY2));
477 m_Order.Attach(GetItem(IDC_COMPRESS_ORDER));
478 m_Solid.Attach(GetItem(IDC_COMPRESS_SOLID));
479 m_NumThreads.Attach(GetItem(IDC_COMPRESS_THREADS));
480 m_MemUse.Attach(GetItem(IDC_COMPRESS_MEM_USE));
481
482 m_UpdateMode.Attach(GetItem(IDC_COMPRESS_UPDATE_MODE));
483 m_PathMode.Attach(GetItem(IDC_COMPRESS_PATH_MODE));
484
485 m_Volume.Attach(GetItem(IDC_COMPRESS_VOLUME));
486 m_Params.Attach(GetItem(IDE_COMPRESS_PARAMETERS));
487
488 AddVolumeItems(m_Volume);
489
490 m_RegistryInfo.Load();
491 CheckButton(IDX_PASSWORD_SHOW, m_RegistryInfo.ShowPassword);
492 CheckButton(IDX_COMPRESS_ENCRYPT_FILE_NAMES, m_RegistryInfo.EncryptHeaders);
493
494 UpdatePasswordControl();
495
496 {
497 const bool needSetMain = (Info.FormatIndex < 0);
498 FOR_VECTOR(i, ArcIndices)
499 {
500 const unsigned arcIndex = ArcIndices[i];
501 const CArcInfoEx &ai = (*ArcFormats)[arcIndex];
502 const int index = (int)m_Format.AddString(ai.Name);
503 m_Format.SetItemData(index, (LPARAM)arcIndex);
504 if (!needSetMain)
505 {
506 if (Info.FormatIndex == (int)arcIndex)
507 m_Format.SetCurSel(index);
508 continue;
509 }
510 if (i == 0 || ai.Name.IsEqualTo_NoCase(m_RegistryInfo.ArcType))
511 {
512 m_Format.SetCurSel(index);
513 Info.FormatIndex = (int)arcIndex;
514 }
515 }
516 }
517
518 CheckButton(IDX_COMPRESS_SFX, Info.SFXMode);
519
520 {
521 UString fileName;
522 SetArcPathFields(Info.ArcPath, fileName, true);
523 StartDirPrefix = DirPrefix;
524 SetArchiveName(fileName);
525 }
526
527 for (unsigned i = 0; i < m_RegistryInfo.ArcPaths.Size() && i < kHistorySize; i++)
528 m_ArchivePath.AddString(m_RegistryInfo.ArcPaths[i]);
529
530 AddComboItems(m_UpdateMode, k_UpdateMode_IDs, Z7_ARRAY_SIZE(k_UpdateMode_IDs),
531 k_UpdateMode_Vals, Info.UpdateMode);
532
533 AddComboItems(m_PathMode, k_PathMode_IDs, Z7_ARRAY_SIZE(k_PathMode_IDs),
534 k_PathMode_Vals, Info.PathMode);
535
536
537 TCHAR s[32] = { TEXT('/'), TEXT(' '), 0 };
538 ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
539 SetItemText(IDT_COMPRESS_HARDWARE_THREADS, s);
540
541 CheckButton(IDX_COMPRESS_SHARED, Info.OpenShareForWrite);
542 CheckButton(IDX_COMPRESS_DEL, Info.DeleteAfterCompressing);
543
544 FormatChanged(false); // isChanged
545
546 // OnButtonSFX();
547
548 NormalizePosition();
549
550 return CModalDialog::OnInit();
551 }
552
553 /*
554 namespace NCompressDialog
555 {
556 bool CInfo::GetFullPathName(UString &result) const
557 {
558 #ifndef UNDER_CE
559 // NDirectory::MySetCurrentDirectory(CurrentDirPrefix);
560 #endif
561 FString resultF;
562 bool res = MyGetFullPathName(us2fs(ArchiveName), resultF);
563 result = fs2us(resultF);
564 return res;
565 }
566 }
567 */
568
UpdatePasswordControl()569 void CCompressDialog::UpdatePasswordControl()
570 {
571 const bool showPassword = IsShowPasswordChecked();
572 const TCHAR c = showPassword ? (TCHAR)0: TEXT('*');
573 _password1Control.SetPasswordChar((WPARAM)c);
574 _password2Control.SetPasswordChar((WPARAM)c);
575 UString password;
576 _password1Control.GetText(password);
577 _password1Control.SetText(password);
578 _password2Control.GetText(password);
579 _password2Control.SetText(password);
580
581 ShowItem_Bool(IDT_PASSWORD_REENTER, !showPassword);
582 _password2Control.Show_Bool(!showPassword);
583 }
584
OnButtonClicked(unsigned buttonID,HWND buttonHWND)585 bool CCompressDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
586 {
587 switch (buttonID)
588 {
589 case IDB_COMPRESS_SET_ARCHIVE:
590 {
591 OnButtonSetArchive();
592 return true;
593 }
594 case IDX_COMPRESS_SFX:
595 {
596 SetMethod(GetMethodID());
597 OnButtonSFX();
598 SetMemoryUsage();
599 return true;
600 }
601 case IDX_PASSWORD_SHOW:
602 {
603 UpdatePasswordControl();
604 return true;
605 }
606 case IDB_COMPRESS_OPTIONS:
607 {
608 COptionsDialog dialog(this);
609 if (dialog.Create(*this) == IDOK)
610 ShowOptionsString();
611 return true;
612 }
613 }
614 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
615 }
616
CheckSFXControlsEnable()617 void CCompressDialog::CheckSFXControlsEnable()
618 {
619 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
620 bool enable = fi.SFX_();
621 if (enable)
622 {
623 const int methodID = GetMethodID();
624 enable = (methodID == -1 || IsMethodSupportedBySfx(methodID));
625 }
626 if (!enable)
627 CheckButton(IDX_COMPRESS_SFX, false);
628 EnableItem(IDX_COMPRESS_SFX, enable);
629 }
630
631 /*
632 void CCompressDialog::CheckVolumeEnable()
633 {
634 bool isSFX = IsSFX();
635 m_Volume.Enable(!isSFX);
636 if (isSFX)
637 m_Volume.SetText(TEXT(""));
638 }
639 */
640
EnableMultiCombo(unsigned id)641 void CCompressDialog::EnableMultiCombo(unsigned id)
642 {
643 NWindows::NControl::CComboBox combo;
644 combo.Attach(GetItem(id));
645 const bool enable = (combo.GetCount() > 1);
646 EnableItem(id, enable);
647 }
648
649 static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s);
650
Combine_Two_BoolPairs(const CBoolPair & b1,const CBoolPair & b2,CBool1 & res)651 static void Combine_Two_BoolPairs(const CBoolPair &b1, const CBoolPair &b2, CBool1 &res)
652 {
653 if (!b1.Def && b2.Def)
654 res.Val = b2.Val;
655 else
656 res.Val = b1.Val;
657 }
658
659 #define SET_GUI_BOOL(name) \
660 Combine_Two_BoolPairs(Info. name, m_RegistryInfo. name, name)
661
662
Set_Final_BoolPairs(const CBool1 & gui,CBoolPair & cmd,CBoolPair & reg)663 static void Set_Final_BoolPairs(
664 const CBool1 &gui,
665 CBoolPair &cmd,
666 CBoolPair ®)
667 {
668 if (!cmd.Def)
669 {
670 reg.Val = gui.Val;
671 reg.Def = gui.Val;
672 }
673 if (gui.Supported)
674 {
675 cmd.Val = gui.Val;
676 cmd.Def = gui.Val;
677 }
678 else
679 cmd.Init();
680 }
681
682 #define SET_FINAL_BOOL_PAIRS(name) \
683 Set_Final_BoolPairs(name, Info. name, m_RegistryInfo. name)
684
FormatChanged(bool isChanged)685 void CCompressDialog::FormatChanged(bool isChanged)
686 {
687 SetLevel();
688 SetSolidBlockSize();
689 SetParams();
690 SetMemUseCombo();
691 SetNumThreads();
692
693 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
694 Info.SolidIsSpecified = fi.Solid_();
695 Info.EncryptHeadersIsAllowed = fi.EncryptFileNames_();
696
697 /*
698 const bool multiThreadEnable = fi.MultiThread;
699 Info.MultiThreadIsAllowed = multiThreadEnable;
700 EnableItem(IDC_COMPRESS_SOLID, fi.Solid);
701 EnableItem(IDC_COMPRESS_THREADS, multiThreadEnable);
702 const bool methodEnable = (fi.MethodIDs != NULL);
703 EnableItem(IDC_COMPRESS_METHOD, methodEnable);
704 EnableMultiCombo(IDC_COMPRESS_DICTIONARY, methodEnable);
705 EnableItem(IDC_COMPRESS_ORDER, methodEnable);
706 */
707
708 CheckSFXControlsEnable();
709
710 {
711 if (!isChanged)
712 {
713 SET_GUI_BOOL (SymLinks);
714 SET_GUI_BOOL (HardLinks);
715 SET_GUI_BOOL (AltStreams);
716 SET_GUI_BOOL (NtSecurity);
717 SET_GUI_BOOL (PreserveATime);
718 }
719
720 PreserveATime.Supported = true;
721
722 {
723 const CArcInfoEx &ai = Get_ArcInfoEx();
724 SymLinks.Supported = ai.Flags_SymLinks();
725 HardLinks.Supported = ai.Flags_HardLinks();
726 AltStreams.Supported = ai.Flags_AltStreams();
727 NtSecurity.Supported = ai.Flags_NtSecurity();
728 }
729
730 ShowOptionsString();
731 }
732 // CheckVolumeEnable();
733
734 const bool encrypt = fi.Encrypt_();
735 EnableItem(IDG_COMPRESS_ENCRYPTION, encrypt);
736
737 EnableItem(IDT_PASSWORD_ENTER, encrypt);
738 EnableItem(IDT_PASSWORD_REENTER, encrypt);
739 EnableItem(IDE_COMPRESS_PASSWORD1, encrypt);
740 EnableItem(IDE_COMPRESS_PASSWORD2, encrypt);
741 EnableItem(IDX_PASSWORD_SHOW, encrypt);
742
743 EnableItem(IDT_COMPRESS_ENCRYPTION_METHOD, encrypt);
744 EnableItem(IDC_COMPRESS_ENCRYPTION_METHOD, encrypt);
745 EnableItem(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_());
746
747 ShowItem_Bool(IDX_COMPRESS_ENCRYPT_FILE_NAMES, fi.EncryptFileNames_());
748
749 SetEncryptionMethod();
750 SetMemoryUsage();
751 }
752
753
IsSFX()754 bool CCompressDialog::IsSFX()
755 {
756 return IsWindowEnabled(GetItem(IDX_COMPRESS_SFX))
757 && IsButtonCheckedBool(IDX_COMPRESS_SFX);
758 }
759
GetExtDotPos(const UString & s)760 static int GetExtDotPos(const UString &s)
761 {
762 const int dotPos = s.ReverseFind_Dot();
763 if (dotPos > s.ReverseFind_PathSepar() + 1)
764 return dotPos;
765 return -1;
766 }
767
OnButtonSFX()768 void CCompressDialog::OnButtonSFX()
769 {
770 UString fileName;
771 m_ArchivePath.GetText(fileName);
772 const int dotPos = GetExtDotPos(fileName);
773 if (IsSFX())
774 {
775 if (dotPos >= 0)
776 fileName.DeleteFrom(dotPos);
777 fileName += kExeExt;
778 m_ArchivePath.SetText(fileName);
779 }
780 else
781 {
782 if (dotPos >= 0)
783 {
784 const UString ext = fileName.Ptr(dotPos);
785 if (ext.IsEqualTo_Ascii_NoCase(kExeExt))
786 {
787 fileName.DeleteFrom(dotPos);
788 m_ArchivePath.SetText(fileName);
789 }
790 }
791 SetArchiveName2(false); // it's for OnInit
792 }
793
794 // CheckVolumeEnable();
795 }
796
797
GetFinalPath_Smart(UString & resPath) const798 bool CCompressDialog::GetFinalPath_Smart(UString &resPath) const
799 {
800 resPath.Empty();
801 UString name;
802 m_ArchivePath.GetText(name);
803 name.Trim();
804 FString fullPath;
805 UString dirPrefx = DirPrefix;
806 if (dirPrefx.IsEmpty())
807 dirPrefx = StartDirPrefix;
808 const bool res = !dirPrefx.IsEmpty() ?
809 NName::GetFullPath(us2fs(dirPrefx), us2fs(name), fullPath):
810 NName::GetFullPath( us2fs(name), fullPath);
811 if (res)
812 resPath = fs2us(fullPath);
813 return res;
814 }
815
816
SetArcPathFields(const UString & path)817 bool CCompressDialog::SetArcPathFields(const UString &path)
818 {
819 UString name;
820 return SetArcPathFields(path, name, true); // always
821 }
822
823
SetArcPathFields(const UString & path,UString & name,bool always)824 bool CCompressDialog::SetArcPathFields(const UString &path, UString &name, bool always)
825 {
826 FString resDirPrefix;
827 FString resFileName;
828 const bool res = GetFullPathAndSplit(us2fs(path), resDirPrefix, resFileName);
829 if (res)
830 {
831 DirPrefix = fs2us(resDirPrefix);
832 name = fs2us(resFileName);
833 }
834 else
835 {
836 if (!always)
837 return false;
838 DirPrefix.Empty();
839 name = path;
840 }
841 SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix);
842 m_ArchivePath.SetText(name);
843 return res;
844 }
845
846
847 static const wchar_t * const k_IncorrectPathMessage = L"Incorrect archive path";
848
AddFilter(CObjectVector<CBrowseFilterInfo> & filters,const UString & description,const UString & ext)849 static void AddFilter(CObjectVector<CBrowseFilterInfo> &filters,
850 const UString &description, const UString &ext)
851 {
852 CBrowseFilterInfo &f = filters.AddNew();
853 UString mask ("*.");
854 mask += ext;
855 f.Masks.Add(mask);
856 f.Description = description;
857 f.Description += " (";
858 f.Description += mask;
859 f.Description += ")";
860 }
861
862
863 static const char * const k_DontSave_Exts =
864 "xpi odt ods docx xlsx ";
865
OnButtonSetArchive()866 void CCompressDialog::OnButtonSetArchive()
867 {
868 UString path;
869 if (!GetFinalPath_Smart(path))
870 {
871 ShowErrorMessage(*this, k_IncorrectPathMessage);
872 return;
873 }
874
875 int filterIndex;
876 CObjectVector<CBrowseFilterInfo> filters;
877 unsigned numFormats = 0;
878
879 const bool isSFX = IsSFX();
880 if (isSFX)
881 {
882 filterIndex = 0;
883 const UString ext ("exe");
884 AddFilter(filters, ext, ext);
885 }
886 else
887 {
888 filterIndex = m_Format.GetCurSel();
889 numFormats = (unsigned)m_Format.GetCount();
890
891 // filters [0, ... numFormats - 1] corresponds to items in m_Format combo
892 UString desc;
893 UStringVector masks;
894 CStringFinder finder;
895
896 for (unsigned i = 0; i < numFormats; i++)
897 {
898 const CArcInfoEx &ai = (*ArcFormats)[(unsigned)m_Format.GetItemData(i)];
899 CBrowseFilterInfo &f = filters.AddNew();
900 f.Description = ai.Name;
901 f.Description += " (";
902 bool needSpace_desc = false;
903
904 FOR_VECTOR (k, ai.Exts)
905 {
906 const UString &ext = ai.Exts[k].Ext;
907 UString mask ("*.");
908 mask += ext;
909
910 if (finder.FindWord_In_LowCaseAsciiList_NoCase(k_DontSave_Exts, ext))
911 continue;
912
913 f.Masks.Add(mask);
914 masks.Add(mask);
915 if (needSpace_desc)
916 f.Description.Add_Space();
917 needSpace_desc = true;
918 f.Description += ext;
919 }
920 f.Description += ")";
921 // we use only main ext in desc to reduce the size of list
922 if (i != 0)
923 desc.Add_Space();
924 desc += ai.GetMainExt();
925 }
926
927 CBrowseFilterInfo &f = filters.AddNew();
928 f.Description = LangString(IDT_COMPRESS_ARCHIVE); // IDS_ARCHIVES_COLON;
929 if (f.Description.IsEmpty())
930 GetItemText(IDT_COMPRESS_ARCHIVE, f.Description);
931 f.Description.RemoveChar(L'&');
932 // f.Description = "archive";
933 f.Description += " (";
934 f.Description += desc;
935 f.Description += ")";
936 f.Masks = masks;
937 }
938
939 AddFilter(filters, LangString(IDS_OPEN_TYPE_ALL_FILES), UString("*"));
940 if (filterIndex < 0)
941 filterIndex = (int)filters.Size() - 1;
942
943 const UString title = LangString(IDS_COMPRESS_SET_ARCHIVE_BROWSE);
944 CBrowseInfo bi;
945 bi.lpstrTitle = title;
946 bi.SaveMode = true;
947 bi.FilterIndex = filterIndex;
948 bi.hwndOwner = *this;
949 bi.FilePath = path;
950
951 if (!bi.BrowseForFile(filters))
952 return;
953
954 path = bi.FilePath;
955
956 if (isSFX)
957 {
958 const int dotPos = GetExtDotPos(path);
959 if (dotPos >= 0)
960 path.DeleteFrom(dotPos);
961 path += kExeExt;
962 }
963 else
964 // if (bi.FilterIndex >= 0)
965 // if (bi.FilterIndex != filterIndex)
966 if ((unsigned)bi.FilterIndex < numFormats)
967 {
968 // archive format was confirmed. So we try to set format extension
969 bool needAddExt = true;
970 const CArcInfoEx &ai = (*ArcFormats)[(unsigned)m_Format.GetItemData((unsigned)bi.FilterIndex)];
971 const int dotPos = GetExtDotPos(path);
972 if (dotPos >= 0)
973 {
974 const UString ext = path.Ptr(dotPos + 1);
975 if (ai.FindExtension(ext) >= 0)
976 needAddExt = false;
977 }
978 if (needAddExt)
979 {
980 if (path.IsEmpty() || path.Back() != '.')
981 path.Add_Dot();
982 path += ai.GetMainExt();
983 }
984 }
985
986 SetArcPathFields(path);
987
988 if (!isSFX)
989 if ((unsigned)bi.FilterIndex < numFormats)
990 if (bi.FilterIndex != m_Format.GetCurSel())
991 {
992 m_Format.SetCurSel(bi.FilterIndex);
993 SaveOptionsInMem();
994 FormatChanged(true); // isChanged
995 return;
996 }
997
998 ArcPath_WasChanged(path);
999 }
1000
1001
1002 // in ExtractDialog.cpp
1003 extern void AddUniqueString(UStringVector &strings, const UString &srcString);
1004
IsAsciiString(const UString & s)1005 static bool IsAsciiString(const UString &s)
1006 {
1007 for (unsigned i = 0; i < s.Len(); i++)
1008 {
1009 const wchar_t c = s[i];
1010 if (c < 0x20 || c > 0x7F)
1011 return false;
1012 }
1013 return true;
1014 }
1015
1016
AddSize_MB(UString & s,UInt64 size)1017 static void AddSize_MB(UString &s, UInt64 size)
1018 {
1019 s.Add_LF();
1020 const UInt64 v2 = size + ((UInt32)1 << 20) - 1;
1021 if (size < v2)
1022 size = v2;
1023 s.Add_UInt64(size >> 20);
1024 s += " MB : ";
1025 }
1026
AddSize_MB_id(UString & s,UInt64 size,UInt32 id)1027 static void AddSize_MB_id(UString &s, UInt64 size, UInt32 id)
1028 {
1029 AddSize_MB(s, size);
1030 AddLangString(s, id);
1031 }
1032
1033 void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString);
SetErrorMessage_MemUsage(UString & s,UInt64 reqSize,UInt64 ramSize,UInt64 ramLimit,const UString & usageString)1034 void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString)
1035 {
1036 AddLangString(s, IDS_MEM_OPERATION_BLOCKED);
1037 s.Add_LF();
1038 AddLangString(s, IDS_MEM_REQUIRES_BIG_MEM);
1039 s.Add_LF();
1040 AddSize_MB(s, reqSize);
1041 s += usageString;
1042 AddSize_MB_id(s, ramSize, IDS_MEM_RAM_SIZE);
1043 // if (ramLimit != 0)
1044 {
1045 AddSize_MB_id(s, ramLimit, IDS_MEM_USAGE_LIMIT_SET_BY_7ZIP);
1046 }
1047 s.Add_LF();
1048 s.Add_LF();
1049 AddLangString(s, IDS_MEM_ERROR);
1050 }
1051
1052
OnOK()1053 void CCompressDialog::OnOK()
1054 {
1055 _password1Control.GetText(Info.Password);
1056 if (IsZipFormat())
1057 {
1058 if (!IsAsciiString(Info.Password))
1059 {
1060 ShowErrorMessageHwndRes(*this, IDS_PASSWORD_USE_ASCII);
1061 return;
1062 }
1063 UString method = GetEncryptionMethodSpec();
1064 if (method.IsPrefixedBy_Ascii_NoCase("aes"))
1065 {
1066 if (Info.Password.Len() > 99)
1067 {
1068 ShowErrorMessageHwndRes(*this, IDS_PASSWORD_TOO_LONG);
1069 return;
1070 }
1071 }
1072 }
1073 if (!IsShowPasswordChecked())
1074 {
1075 UString password2;
1076 _password2Control.GetText(password2);
1077 if (password2 != Info.Password)
1078 {
1079 ShowErrorMessageHwndRes(*this, IDS_PASSWORD_NOT_MATCH);
1080 return;
1081 }
1082 }
1083
1084 {
1085 UInt64 decompressMem;
1086 const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem);
1087 if (memUsage != (UInt64)(Int64)-1)
1088 {
1089 const UInt64 limit = Get_MemUse_Bytes();
1090 if (memUsage > limit)
1091 {
1092 UString s2;
1093 LangString_OnlyFromLangFile(IDS_MEM_REQUIRED_MEM_SIZE, s2);
1094 if (s2.IsEmpty())
1095 {
1096 s2 = LangString(IDT_COMPRESS_MEMORY);
1097 if (s2.IsEmpty())
1098 GetItemText(IDT_COMPRESS_MEMORY, s2);
1099 s2.RemoveChar(L':');
1100 }
1101 UString s;
1102 SetErrorMessage_MemUsage(s, memUsage, _ramSize, limit, s2);
1103 MessageBoxError(s);
1104 return;
1105 }
1106 }
1107 }
1108
1109 SaveOptionsInMem();
1110
1111 UStringVector arcPaths;
1112 {
1113 UString s;
1114 if (!GetFinalPath_Smart(s))
1115 {
1116 ShowErrorMessage(*this, k_IncorrectPathMessage);
1117 return;
1118 }
1119 Info.ArcPath = s;
1120 AddUniqueString(arcPaths, s);
1121 }
1122
1123 Info.UpdateMode = (NCompressDialog::NUpdateMode::EEnum)k_UpdateMode_Vals[m_UpdateMode.GetCurSel()];
1124 Info.PathMode = (NWildcard::ECensorPathMode)k_PathMode_Vals[m_PathMode.GetCurSel()];
1125
1126 Info.Level = GetLevelSpec();
1127 Info.Dict64 = GetDictSpec();
1128 // Info.Dict64_Chain = GetDictChainSpec();
1129 Info.Order = GetOrderSpec();
1130 Info.OrderMode = GetOrderMode();
1131 Info.NumThreads = GetNumThreadsSpec();
1132
1133 Info.MemUsage.Clear();
1134 {
1135 const UString mus = Get_MemUse_Spec();
1136 if (!mus.IsEmpty())
1137 {
1138 NCompression::CMemUse mu;
1139 mu.Parse(mus);
1140 if (mu.IsDefined)
1141 Info.MemUsage = mu;
1142 }
1143 }
1144
1145 {
1146 // Info.SolidIsSpecified = g_Formats[GetStaticFormatIndex()].Solid;
1147 const UInt32 solidLogSize = GetBlockSizeSpec();
1148 Info.SolidBlockSize = 0;
1149 if (solidLogSize == (UInt32)(Int32)-1)
1150 Info.SolidIsSpecified = false;
1151 else if (solidLogSize > 0)
1152 Info.SolidBlockSize = (solidLogSize >= 64) ?
1153 (UInt64)(Int64)-1 :
1154 ((UInt64)1 << solidLogSize);
1155 }
1156
1157 Info.Method = GetMethodSpec();
1158 Info.EncryptionMethod = GetEncryptionMethodSpec();
1159 Info.FormatIndex = (int)GetFormatIndex();
1160 Info.SFXMode = IsSFX();
1161 Info.OpenShareForWrite = IsButtonCheckedBool(IDX_COMPRESS_SHARED);
1162 Info.DeleteAfterCompressing = IsButtonCheckedBool(IDX_COMPRESS_DEL);
1163
1164 m_RegistryInfo.EncryptHeaders =
1165 Info.EncryptHeaders = IsButtonCheckedBool(IDX_COMPRESS_ENCRYPT_FILE_NAMES);
1166
1167
1168 /* (Info) is for saving to registry:
1169 (CBoolPair::Val) will be set as (false), if it was (false)
1170 in registry at dialog creation, and user didn't click checkbox.
1171 in another case (CBoolPair::Val) will be set as (true) */
1172
1173 {
1174 /* Info properties could be for another archive types.
1175 so we disable unsupported properties in Info */
1176 // const CArcInfoEx &ai = Get_ArcInfoEx();
1177
1178 SET_FINAL_BOOL_PAIRS (SymLinks);
1179 SET_FINAL_BOOL_PAIRS (HardLinks);
1180 SET_FINAL_BOOL_PAIRS (AltStreams);
1181 SET_FINAL_BOOL_PAIRS (NtSecurity);
1182
1183 SET_FINAL_BOOL_PAIRS (PreserveATime);
1184 }
1185
1186 {
1187 const NCompression::CFormatOptions &fo = Get_FormatOptions();
1188
1189 Info.TimePrec = fo.TimePrec;
1190 Info.MTime = fo.MTime;
1191 Info.CTime = fo.CTime;
1192 Info.ATime = fo.ATime;
1193 Info.SetArcMTime = fo.SetArcMTime;
1194 }
1195
1196 m_Params.GetText(Info.Options);
1197
1198 UString volumeString;
1199 m_Volume.GetText(volumeString);
1200 volumeString.Trim();
1201 Info.VolumeSizes.Clear();
1202
1203 if (!volumeString.IsEmpty())
1204 {
1205 if (!ParseVolumeSizes(volumeString, Info.VolumeSizes))
1206 {
1207 ShowErrorMessageHwndRes(*this, IDS_INCORRECT_VOLUME_SIZE);
1208 return;
1209 }
1210 if (!Info.VolumeSizes.IsEmpty())
1211 {
1212 const UInt64 volumeSize = Info.VolumeSizes.Back();
1213 if (volumeSize < (100 << 10))
1214 {
1215 wchar_t s[32];
1216 ConvertUInt64ToString(volumeSize, s);
1217 if (::MessageBoxW(*this, MyFormatNew(IDS_SPLIT_CONFIRM, s),
1218 L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
1219 return;
1220 }
1221 }
1222 }
1223
1224 if (Info.FormatIndex >= 0)
1225 m_RegistryInfo.ArcType = (*ArcFormats)[Info.FormatIndex].Name;
1226 m_RegistryInfo.ShowPassword = IsShowPasswordChecked();
1227
1228 FOR_VECTOR (i, m_RegistryInfo.ArcPaths)
1229 {
1230 if (arcPaths.Size() >= kHistorySize)
1231 break;
1232 AddUniqueString(arcPaths, m_RegistryInfo.ArcPaths[i]);
1233 }
1234 m_RegistryInfo.ArcPaths = arcPaths;
1235
1236 m_RegistryInfo.Save();
1237
1238 CModalDialog::OnOK();
1239 }
1240
1241 #define kHelpTopic "fm/plugins/7-zip/add.htm"
1242 #define kHelpTopic_Options "fm/plugins/7-zip/add.htm#options"
1243
OnHelp()1244 void CCompressDialog::OnHelp()
1245 {
1246 ShowHelpWindow(kHelpTopic);
1247 }
1248
1249
ArcPath_WasChanged(const UString & path)1250 void CCompressDialog::ArcPath_WasChanged(const UString &path)
1251 {
1252 const int dotPos = GetExtDotPos(path);
1253 if (dotPos < 0)
1254 return;
1255 const UString ext = path.Ptr(dotPos + 1);
1256 {
1257 const CArcInfoEx &ai = Get_ArcInfoEx();
1258 if (ai.FindExtension(ext) >= 0)
1259 return;
1260 }
1261
1262 const unsigned count = (unsigned)m_Format.GetCount();
1263 for (unsigned i = 0; i < count; i++)
1264 {
1265 const CArcInfoEx &ai = (*ArcFormats)[(unsigned)m_Format.GetItemData(i)];
1266 if (ai.FindExtension(ext) >= 0)
1267 {
1268 m_Format.SetCurSel(i);
1269 SaveOptionsInMem();
1270 FormatChanged(true); // isChanged
1271 return;
1272 }
1273 }
1274 }
1275
1276
OnMessage(UINT message,WPARAM wParam,LPARAM lParam)1277 bool CCompressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
1278 {
1279 switch (message)
1280 {
1281 case k_Message_ArcChanged:
1282 {
1283 // UString path;
1284 // m_ArchivePath.GetText(path);
1285 const int select = m_ArchivePath.GetCurSel();
1286 if ((unsigned)select < m_RegistryInfo.ArcPaths.Size())
1287 // if (path == m_RegistryInfo.ArcPaths[select])
1288 {
1289 const UString &path = m_RegistryInfo.ArcPaths[select];
1290 SetArcPathFields(path);
1291 // ArcPath_WasChanged(path);
1292 }
1293 return 0;
1294 }
1295 }
1296 return CModalDialog::OnMessage(message, wParam, lParam);
1297 }
1298
1299
OnCommand(unsigned code,unsigned itemID,LPARAM lParam)1300 bool CCompressDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam)
1301 {
1302 if (code == CBN_SELCHANGE)
1303 {
1304 switch (itemID)
1305 {
1306 case IDC_COMPRESS_ARCHIVE:
1307 {
1308 /* CBN_SELCHANGE is called before actual value of combo text will be changed.
1309 So GetText() here returns old value (before change) of combo text.
1310 So here we can change all controls except of m_ArchivePath.
1311 */
1312 const int select = m_ArchivePath.GetCurSel();
1313 if ((unsigned)select < m_RegistryInfo.ArcPaths.Size())
1314 {
1315 // DirPrefix.Empty();
1316 // SetItemText(IDT_COMPRESS_ARCHIVE_FOLDER, DirPrefix);
1317 const UString &path = m_RegistryInfo.ArcPaths[select];
1318 // SetArcPathFields(path);
1319 ArcPath_WasChanged(path);
1320 // we use PostMessage(k_Message_ArcChanged) here that later will change m_ArchivePath control
1321 PostMsg(k_Message_ArcChanged);
1322 }
1323 return true;
1324 }
1325
1326 case IDC_COMPRESS_FORMAT:
1327 {
1328 const bool isSFX = IsSFX();
1329 SaveOptionsInMem();
1330 FormatChanged(true); // isChanged
1331 SetArchiveName2(isSFX);
1332 return true;
1333 }
1334
1335 case IDC_COMPRESS_LEVEL:
1336 {
1337 Get_FormatOptions().ResetForLevelChange();
1338
1339 SetMethod(); // call it if level changes method
1340
1341 // call the following if level change keeps old method
1342 /*
1343 {
1344 // try to keep old method
1345 SetMethod(GetMethodID());
1346 MethodChanged();
1347 }
1348 */
1349
1350 SetSolidBlockSize();
1351 SetNumThreads();
1352 CheckSFXNameChange();
1353 SetMemoryUsage();
1354 return true;
1355 }
1356
1357 case IDC_COMPRESS_METHOD:
1358 {
1359 MethodChanged();
1360 SetSolidBlockSize();
1361 SetNumThreads();
1362 CheckSFXNameChange();
1363 SetMemoryUsage();
1364 if (Get_ArcInfoEx().Flags_HashHandler())
1365 SetArchiveName2(false);
1366
1367 return true;
1368 }
1369
1370 case IDC_COMPRESS_DICTIONARY:
1371 // case IDC_COMPRESS_DICTIONARY2:
1372 {
1373 /* we want to change the reported threads for Auto line
1374 and keep selected NumThreads option
1375 So we save selected NumThreads option in memory */
1376 SaveOptionsInMem();
1377 const UInt32 blockSizeLog = GetBlockSizeSpec();
1378 if (// blockSizeLog != (UInt32)(Int32)-1 &&
1379 blockSizeLog != kSolidLog_NoSolid
1380 && blockSizeLog != kSolidLog_FullSolid)
1381 {
1382 Get_FormatOptions().Reset_BlockLogSize();
1383 // SetSolidBlockSize(true);
1384 }
1385
1386 SetDictionary2();
1387 SetSolidBlockSize();
1388 SetNumThreads(); // we want to change the reported threads for Auto line only
1389 SetMemoryUsage();
1390 return true;
1391 }
1392
1393 case IDC_COMPRESS_ORDER:
1394 {
1395 #ifdef PRINT_PARAMS
1396 Print_Params();
1397 #endif
1398 return true;
1399 }
1400
1401 case IDC_COMPRESS_SOLID:
1402 {
1403 SetMemoryUsage();
1404 return true;
1405 }
1406
1407 case IDC_COMPRESS_THREADS:
1408 {
1409 SetMemoryUsage();
1410 return true;
1411 }
1412
1413 case IDC_COMPRESS_MEM_USE:
1414 {
1415 /* we want to change the reported threads for Auto line
1416 and keep selected NumThreads option
1417 So we save selected NumThreads option in memory */
1418 SaveOptionsInMem();
1419
1420 SetNumThreads(); // we want to change the reported threads for Auto line only
1421 SetMemoryUsage();
1422 return true;
1423 }
1424 }
1425 }
1426 return CModalDialog::OnCommand(code, itemID, lParam);
1427 }
1428
CheckSFXNameChange()1429 void CCompressDialog::CheckSFXNameChange()
1430 {
1431 const bool isSFX = IsSFX();
1432 CheckSFXControlsEnable();
1433 if (isSFX != IsSFX())
1434 SetArchiveName2(isSFX);
1435 }
1436
SetArchiveName2(bool prevWasSFX)1437 void CCompressDialog::SetArchiveName2(bool prevWasSFX)
1438 {
1439 UString fileName;
1440 m_ArchivePath.GetText(fileName);
1441 const CArcInfoEx &prevArchiverInfo = (*ArcFormats)[m_PrevFormat];
1442 if (prevArchiverInfo.Flags_KeepName() || Info.KeepName)
1443 {
1444 UString prevExtension;
1445 if (prevWasSFX)
1446 prevExtension = kExeExt;
1447 else
1448 {
1449 prevExtension.Add_Dot();
1450 prevExtension += prevArchiverInfo.GetMainExt();
1451 }
1452 const unsigned prevExtensionLen = prevExtension.Len();
1453 if (fileName.Len() >= prevExtensionLen)
1454 if (StringsAreEqualNoCase(fileName.RightPtr(prevExtensionLen), prevExtension))
1455 fileName.DeleteFrom(fileName.Len() - prevExtensionLen);
1456 }
1457 SetArchiveName(fileName);
1458 }
1459
1460 // if type.KeepName then use OriginalFileName
1461 // else if !KeepName remove extension
1462 // add new extension
1463
SetArchiveName(const UString & name)1464 void CCompressDialog::SetArchiveName(const UString &name)
1465 {
1466 UString fileName = name;
1467 Info.FormatIndex = (int)GetFormatIndex();
1468 const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];
1469 m_PrevFormat = Info.FormatIndex;
1470 if (ai.Flags_KeepName())
1471 {
1472 fileName = OriginalFileName;
1473 }
1474 else
1475 {
1476 if (!Info.KeepName)
1477 {
1478 int dotPos = GetExtDotPos(fileName);
1479 if (dotPos >= 0)
1480 fileName.DeleteFrom(dotPos);
1481 }
1482 }
1483
1484 if (IsSFX())
1485 fileName += kExeExt;
1486 else
1487 {
1488 fileName.Add_Dot();
1489 UString ext = ai.GetMainExt();
1490 if (ai.Flags_HashHandler())
1491 {
1492 UString estimatedName;
1493 GetMethodSpec(estimatedName);
1494 if (!estimatedName.IsEmpty())
1495 {
1496 ext = estimatedName;
1497 ext.MakeLower_Ascii();
1498 }
1499 }
1500 fileName += ext;
1501 }
1502 m_ArchivePath.SetText(fileName);
1503 }
1504
1505
FindRegistryFormat(const UString & name)1506 int CCompressDialog::FindRegistryFormat(const UString &name)
1507 {
1508 FOR_VECTOR (i, m_RegistryInfo.Formats)
1509 {
1510 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[i];
1511 if (name.IsEqualTo_NoCase(GetUnicodeString(fo.FormatID)))
1512 return (int)i;
1513 }
1514 return -1;
1515 }
1516
1517
FindRegistryFormat_Always(const UString & name)1518 unsigned CCompressDialog::FindRegistryFormat_Always(const UString &name)
1519 {
1520 const int index = FindRegistryFormat(name);
1521 if (index >= 0)
1522 return (unsigned)index;
1523 {
1524 NCompression::CFormatOptions fo;
1525 fo.FormatID = GetSystemString(name);
1526 return m_RegistryInfo.Formats.Add(fo);
1527 }
1528 }
1529
1530
Get_FormatOptions()1531 NCompression::CFormatOptions &CCompressDialog::Get_FormatOptions()
1532 {
1533 const CArcInfoEx &ai = Get_ArcInfoEx();
1534 return m_RegistryInfo.Formats[FindRegistryFormat_Always(ai.Name)];
1535 }
1536
1537
GetStaticFormatIndex()1538 unsigned CCompressDialog::GetStaticFormatIndex()
1539 {
1540 const CArcInfoEx &ai = Get_ArcInfoEx();
1541 for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Formats); i++)
1542 if (ai.Name.IsEqualTo_Ascii_NoCase(g_Formats[i].Name))
1543 return i;
1544 return 0; // -1;
1545 }
1546
SetNearestSelectComboBox(NControl::CComboBox & comboBox,UInt32 value)1547 void CCompressDialog::SetNearestSelectComboBox(NControl::CComboBox &comboBox, UInt32 value)
1548 {
1549 for (int i = comboBox.GetCount() - 1; i >= 0; i--)
1550 if ((UInt32)comboBox.GetItemData(i) <= value)
1551 {
1552 comboBox.SetCurSel(i);
1553 return;
1554 }
1555 if (comboBox.GetCount() > 0)
1556 comboBox.SetCurSel(0);
1557 }
1558
SetLevel2()1559 void CCompressDialog::SetLevel2()
1560 {
1561 m_Level.ResetContent();
1562 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1563 const CArcInfoEx &ai = Get_ArcInfoEx();
1564 UInt32 level = 5;
1565 {
1566 int index = FindRegistryFormat(ai.Name);
1567 if (index >= 0)
1568 {
1569 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1570 if (fo.Level <= 9)
1571 level = fo.Level;
1572 else if (fo.Level == (UInt32)(Int32)-1)
1573 level = 5;
1574 else
1575 level = 9;
1576 }
1577 }
1578
1579 const bool isZstd = ai.Is_Zstd();
1580
1581 for (unsigned i = 0; i < sizeof(UInt32) * 8; i++)
1582 {
1583 const UInt32 mask = (UInt32)1 << i;
1584 if ((fi.LevelsMask & mask) != 0)
1585 {
1586 const UInt32 langID = g_Levels[i];
1587 UString s;
1588 s.Add_UInt32(i);
1589 // if (fi.LevelsMask < (1 << (MY_ZSTD_LEVEL_MAX + 1)) - 1)
1590 if (langID)
1591 if (i != 0 || !isZstd)
1592 {
1593 s += " - ";
1594 s += LangString(langID);
1595 }
1596 const int index = (int)m_Level.AddString(s);
1597 m_Level.SetItemData(index, (LPARAM)i);
1598 }
1599 if (fi.LevelsMask <= mask)
1600 break;
1601 }
1602 SetNearestSelectComboBox(m_Level, level);
1603 }
1604
1605
ComboBox_AddStringAscii(NControl::CComboBox & cb,const char * s)1606 static LRESULT ComboBox_AddStringAscii(NControl::CComboBox &cb, const char *s)
1607 {
1608 return cb.AddString((CSysString)s);
1609 }
1610
1611 static const char *k_Auto_Prefix = "* ";
1612
Modify_Auto(AString & s)1613 static void Modify_Auto(AString &s)
1614 {
1615 s.Insert(0, k_Auto_Prefix);
1616 }
1617
SetMethod2(int keepMethodId)1618 void CCompressDialog::SetMethod2(int keepMethodId)
1619 {
1620 m_Method.ResetContent();
1621 _auto_MethodId = -1;
1622 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
1623 const CArcInfoEx &ai = Get_ArcInfoEx();
1624 if (GetLevel() == 0 && !ai.Flags_HashHandler())
1625 {
1626 if (!ai.Is_Tar() &&
1627 !ai.Is_Zstd())
1628 {
1629 MethodChanged();
1630 return;
1631 }
1632 }
1633 UString defaultMethod;
1634 {
1635 const int index = FindRegistryFormat(ai.Name);
1636 if (index >= 0)
1637 {
1638 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1639 defaultMethod = fo.Method;
1640 }
1641 }
1642 const bool isSfx = IsSFX();
1643 bool weUseSameMethod = false;
1644
1645 const bool is7z = ai.Is_7z();
1646
1647 for (unsigned m = 0;; m++)
1648 {
1649 int methodID;
1650 const char *method;
1651 if (m < fi.NumMethods)
1652 {
1653 methodID = fi.MethodIDs[m];
1654 method = kMethodsNames[methodID];
1655 if (is7z)
1656 if (methodID == kCopy
1657 || methodID == kDeflate
1658 || methodID == kDeflate64
1659 )
1660 continue;
1661 }
1662 else
1663 {
1664 if (!is7z)
1665 break;
1666 const unsigned extIndex = m - fi.NumMethods;
1667 if (extIndex >= ExternalMethods.Size())
1668 break;
1669 methodID = (int)(Z7_ARRAY_SIZE(kMethodsNames) + extIndex);
1670 method = ExternalMethods[extIndex].Ptr();
1671 }
1672 if (isSfx)
1673 if (!IsMethodSupportedBySfx(methodID))
1674 continue;
1675
1676 AString s (method);
1677 int writtenMethodId = methodID;
1678 if (m == 0)
1679 {
1680 _auto_MethodId = methodID;
1681 writtenMethodId = -1;
1682 Modify_Auto(s);
1683 }
1684 const int itemIndex = (int)ComboBox_AddStringAscii(m_Method, s);
1685 m_Method.SetItemData(itemIndex, writtenMethodId);
1686 if (keepMethodId == methodID)
1687 {
1688 m_Method.SetCurSel(itemIndex);
1689 weUseSameMethod = true;
1690 continue;
1691 }
1692 if ((defaultMethod.IsEqualTo_Ascii_NoCase(method) || m == 0) && !weUseSameMethod)
1693 m_Method.SetCurSel(itemIndex);
1694 }
1695
1696 if (!weUseSameMethod)
1697 MethodChanged();
1698 }
1699
1700
1701
IsZipFormat()1702 bool CCompressDialog::IsZipFormat()
1703 {
1704 return Get_ArcInfoEx().Is_Zip();
1705 }
1706
IsXzFormat()1707 bool CCompressDialog::IsXzFormat()
1708 {
1709 return Get_ArcInfoEx().Is_Xz();
1710 }
1711
SetEncryptionMethod()1712 void CCompressDialog::SetEncryptionMethod()
1713 {
1714 _encryptionMethod.ResetContent();
1715 _default_encryptionMethod_Index = -1;
1716 const CArcInfoEx &ai = Get_ArcInfoEx();
1717 if (ai.Is_7z())
1718 {
1719 ComboBox_AddStringAscii(_encryptionMethod, "AES-256");
1720 _encryptionMethod.SetCurSel(0);
1721 _default_encryptionMethod_Index = 0;
1722 }
1723 else if (ai.Is_Zip())
1724 {
1725 int index = FindRegistryFormat(ai.Name);
1726 UString encryptionMethod;
1727 if (index >= 0)
1728 {
1729 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1730 encryptionMethod = fo.EncryptionMethod;
1731 }
1732 int sel = 0;
1733 // if (ZipCryptoIsAllowed)
1734 {
1735 ComboBox_AddStringAscii(_encryptionMethod, "ZipCrypto");
1736 sel = (encryptionMethod.IsPrefixedBy_Ascii_NoCase("aes") ? 1 : 0);
1737 _default_encryptionMethod_Index = 0;
1738 }
1739 ComboBox_AddStringAscii(_encryptionMethod, "AES-256");
1740 _encryptionMethod.SetCurSel(sel);
1741 }
1742 }
1743
1744
GetMethodID_RAW()1745 int CCompressDialog::GetMethodID_RAW()
1746 {
1747 if (m_Method.GetCount() <= 0)
1748 return -1;
1749 return (int)(Int32)(UInt32)m_Method.GetItemData_of_CurSel();
1750 }
1751
GetMethodID()1752 int CCompressDialog::GetMethodID()
1753 {
1754 int raw = GetMethodID_RAW();
1755 if (raw < 0)
1756 return _auto_MethodId;
1757 return raw;
1758 }
1759
1760
GetMethodSpec(UString & estimatedName)1761 UString CCompressDialog::GetMethodSpec(UString &estimatedName)
1762 {
1763 estimatedName.Empty();
1764 if (m_Method.GetCount() < 1)
1765 return estimatedName;
1766 const int methodIdRaw = GetMethodID_RAW();
1767 int methodId = methodIdRaw;
1768 if (methodIdRaw < 0)
1769 methodId = _auto_MethodId;
1770 UString s;
1771 if (methodId >= 0)
1772 {
1773 if ((unsigned)methodId < Z7_ARRAY_SIZE(kMethodsNames))
1774 estimatedName = kMethodsNames[methodId];
1775 else
1776 estimatedName = ExternalMethods[(unsigned)methodId - (unsigned)Z7_ARRAY_SIZE(kMethodsNames)];
1777 if (methodIdRaw >= 0)
1778 s = estimatedName;
1779 }
1780 return s;
1781 }
1782
1783
GetMethodSpec()1784 UString CCompressDialog::GetMethodSpec()
1785 {
1786 UString estimatedName;
1787 UString s = GetMethodSpec(estimatedName);
1788 return s;
1789 }
1790
IsMethodEqualTo(const UString & s)1791 bool CCompressDialog::IsMethodEqualTo(const UString &s)
1792 {
1793 UString estimatedName;
1794 const UString shortName = GetMethodSpec(estimatedName);
1795 if (s.IsEmpty())
1796 return shortName.IsEmpty();
1797 return s.IsEqualTo_NoCase(estimatedName);
1798 }
1799
1800
GetEncryptionMethodSpec()1801 UString CCompressDialog::GetEncryptionMethodSpec()
1802 {
1803 UString s;
1804 if (_encryptionMethod.GetCount() > 0
1805 && _encryptionMethod.GetCurSel() != _default_encryptionMethod_Index)
1806 {
1807 _encryptionMethod.GetText(s);
1808 s.RemoveChar(L'-');
1809 }
1810 return s;
1811 }
1812
1813
1814 static const size_t k_Auto_Dict = (size_t)0 - 1;
1815
Combo_AddDict2(NWindows::NControl::CComboBox & cb,size_t sizeReal,size_t sizeShow)1816 static int Combo_AddDict2(NWindows::NControl::CComboBox &cb, size_t sizeReal, size_t sizeShow)
1817 {
1818 char c = 0;
1819 unsigned moveBits = 0;
1820 if ((sizeShow & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
1821 else if ((sizeShow & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
1822 AString s;
1823 s.Add_UInt64(sizeShow >> moveBits);
1824 s.Add_Space();
1825 if (c != 0)
1826 s.Add_Char(c);
1827 s.Add_Char('B');
1828 if (sizeReal == k_Auto_Dict)
1829 Modify_Auto(s);
1830 const int index = (int)ComboBox_AddStringAscii(cb, s);
1831 cb.SetItemData(index, (LPARAM)sizeReal);
1832 return index;
1833 }
1834
AddDict2(size_t sizeReal,size_t sizeShow)1835 int CCompressDialog::AddDict2(size_t sizeReal, size_t sizeShow)
1836 {
1837 return Combo_AddDict2(m_Dictionary, sizeReal, sizeShow);
1838 }
1839
AddDict(size_t size)1840 int CCompressDialog::AddDict(size_t size)
1841 {
1842 return AddDict2(size, size);
1843 }
1844
1845 /*
1846 int CCompressDialog::AddDict_Chain(size_t size)
1847 {
1848 return Combo_AddDict2(m_Dictionary_Chain, size, size);
1849 }
1850 */
1851
SetDictionary2()1852 void CCompressDialog::SetDictionary2()
1853 {
1854 m_Dictionary.ResetContent();
1855 // m_Dictionary_Chain.ResetContent();
1856
1857 // _auto_Dict = (UInt32)1 << 24; // we can use this dictSize to calculate _auto_Solid for unknown method for 7z
1858 _auto_Dict = (UInt32)(Int32)-1; // for debug
1859 // _auto_Dict_Chain = (UInt32)(Int32)-1; // for debug
1860
1861 const CArcInfoEx &ai = Get_ArcInfoEx();
1862 UInt32 defaultDict = (UInt32)(Int32)-1;
1863 // UInt32 defaultDict_Chain = (UInt32)(Int32)-1;
1864 {
1865 const int index = FindRegistryFormat(ai.Name);
1866 if (index >= 0)
1867 {
1868 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
1869 if (IsMethodEqualTo(fo.Method))
1870 {
1871 defaultDict = fo.Dictionary;
1872 // defaultDict_Chain = fo.DictionaryChain;
1873 }
1874 }
1875 }
1876
1877 const int methodID = GetMethodID();
1878 const UInt32 level = GetLevel2();
1879
1880 {
1881 RECT r, rLabel;
1882 GetClientRectOfItem(IDT_COMPRESS_DICTIONARY, rLabel);
1883 GetClientRectOfItem(IDC_COMPRESS_DICTIONARY, r);
1884 if (_dictionaryCombo_left == 0)
1885 _dictionaryCombo_left = r.left;
1886
1887 // bool showDict2;
1888 int newLableRight;
1889 int newDictLeft;
1890
1891 /*
1892 if (methodID == kZSTD)
1893 {
1894 showDict2 = true;
1895 newDictLeft = _dictionaryCombo_left;
1896 RECT r2;
1897 GetClientRectOfItem(IDC_COMPRESS_DICTIONARY2, r2);
1898 newLableRight = r2.left;
1899 }
1900 else
1901 */
1902 {
1903 // showDict2 = false;
1904 RECT rBig;
1905 GetClientRectOfItem(IDC_COMPRESS_METHOD, rBig);
1906 newDictLeft= rBig.left;
1907 newLableRight = newDictLeft;
1908 }
1909
1910 if (newLableRight != rLabel.right)
1911 {
1912 rLabel.right = newLableRight;
1913 MoveItem_RECT(IDT_COMPRESS_DICTIONARY, rLabel);
1914 InvalidateRect(&rLabel);
1915 }
1916 if (newDictLeft != r.left)
1917 {
1918 r.left = newDictLeft;
1919 MoveItem_RECT(IDC_COMPRESS_DICTIONARY, r);
1920 // InvalidateRect(&r);
1921 }
1922 // ShowItem_Bool(IDC_COMPRESS_DICTIONARY2, showDict2);
1923 }
1924
1925 if (methodID < 0)
1926 return;
1927
1928 switch (methodID)
1929 {
1930 case kLZMA:
1931 case kLZMA2:
1932 {
1933 {
1934 _auto_Dict =
1935 ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
1936 ( level <= 6 ? ((UInt32)1 << (level + 19)) :
1937 ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
1938 )));
1939 }
1940
1941 // we use threshold 3.75 GiB to switch to kLzmaMaxDictSize.
1942 if (defaultDict != (UInt32)(Int32)-1
1943 && defaultDict >= ((UInt32)15 << 28))
1944 defaultDict = kLzmaMaxDictSize;
1945
1946 const size_t kLzmaMaxDictSize_Up = (size_t)1 << (20 + sizeof(size_t) / 4 * 6);
1947
1948 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
1949
1950 for (unsigned i = (16 - 1) * 2; i <= (32 - 1) * 2; i++)
1951 {
1952 if (i < (20 - 1) * 2
1953 && i != (16 - 1) * 2
1954 && i != (18 - 1) * 2)
1955 continue;
1956 if (i == (20 - 1) * 2 + 1)
1957 continue;
1958 const size_t dict_up = (size_t)(2 + (i & 1)) << (i / 2);
1959 size_t dict = dict_up;
1960 if (dict_up >= kLzmaMaxDictSize)
1961 dict = kLzmaMaxDictSize; // we reduce dictionary
1962
1963 const int index = AddDict(dict);
1964 // AddDict2(dict, dict_up); // for debug : we show 4 GB
1965
1966 // const UInt32 numThreads = 2;
1967 // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(numThreads, dict);
1968 if (defaultDict != (UInt32)(Int32)-1)
1969 if (dict <= defaultDict || curSel <= 0)
1970 // if (!maxRamSize_Defined || memUsage <= maxRamSize)
1971 curSel = index;
1972 if (dict_up >= kLzmaMaxDictSize_Up)
1973 break;
1974 }
1975
1976 m_Dictionary.SetCurSel(curSel);
1977 break;
1978 }
1979
1980 /*
1981 case kZSTD:
1982 {
1983 if (defaultDict != (UInt32)(Int32)-1 &&
1984 defaultDict > kZstd_MAX_DictSize)
1985 defaultDict = kZstd_MAX_DictSize;
1986
1987 if (defaultDict_Chain != (UInt32)(Int32)-1 &&
1988 defaultDict_Chain > kZstd_MAX_DictSize_Chain)
1989 defaultDict_Chain = kZstd_MAX_DictSize_Chain;
1990
1991 {
1992 CZstdEncProps props;
1993 ZstdEncProps_Init(&props);
1994 // props.level_zstd = level;
1995 props.level_7z = level;
1996 ZstdEncProps_Set_WindowSize(&props, defaultDict != (UInt32)(Int32)-1 ? defaultDict: 0);
1997 ZstdEncProps_NormalizeFull(&props);
1998 _auto_Dict_Chain = (UInt32)1 << props.windowLog_Chain;
1999 }
2000 {
2001 CZstdEncProps props;
2002 ZstdEncProps_Init(&props);
2003 // props.level_zstd = level;
2004 props.level_7z = level;
2005 ZstdEncProps_Set_WindowChainSize(&props, defaultDict_Chain != (UInt32)(Int32)-1 ? defaultDict_Chain: 0);
2006 ZstdEncProps_NormalizeFull(&props);
2007 _auto_Dict = (UInt32)1 << props.windowLog;
2008 }
2009
2010 // if there is collision of two window sizes, we reduce dict_Chain
2011 if (defaultDict != (UInt32)(Int32)-1 &&
2012 defaultDict_Chain != (UInt32)(Int32)-1 &&
2013 defaultDict < defaultDict_Chain)
2014 defaultDict_Chain = defaultDict;
2015
2016 {
2017 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
2018
2019 // defaultDict = 12 << 10; // for debug
2020 const UInt32 kWinStart = 18;
2021 if (defaultDict != 0 && defaultDict < ((UInt32)1 << kWinStart))
2022 curSel = AddDict(defaultDict);
2023
2024 for (unsigned i = kWinStart; i <= MY_ZSTD_WINDOWLOG_MAX; i++)
2025 {
2026 const size_t dict = (size_t)1 << i;
2027 const int index = AddDict(dict);
2028 if (defaultDict != (UInt32)(Int32)-1)
2029 if (dict <= defaultDict || curSel <= 0)
2030 curSel = index;
2031 }
2032 m_Dictionary.SetCurSel(curSel);
2033 }
2034
2035 {
2036 int curSel = Combo_AddDict2(m_Dictionary_Chain, k_Auto_Dict, _auto_Dict_Chain);
2037
2038 // defaultDict_Chain = 10 << 10; // for debug
2039 const UInt32 kWinChainStart = 15;
2040 if (defaultDict_Chain != 0 && defaultDict_Chain < ((UInt32)1 << kWinChainStart))
2041 curSel = AddDict_Chain(defaultDict_Chain);
2042
2043 for (unsigned i = kWinChainStart; i <= kMaxDictChain; i++)
2044 {
2045 const size_t dict = (size_t)1 << i;
2046 if (defaultDict != (UInt32)(Int32)-1 && dict > defaultDict)
2047 break;
2048 const int index = AddDict_Chain(dict);
2049 if (defaultDict_Chain != (UInt32)(Int32)-1)
2050 if (dict <= defaultDict_Chain || curSel <= 0)
2051 curSel = index;
2052 }
2053 m_Dictionary_Chain.SetCurSel(curSel);
2054 }
2055
2056 break;
2057 }
2058 */
2059
2060 case kPPMd:
2061 {
2062 _auto_Dict = (UInt32)1 << (level + 19);
2063
2064 const UInt32 kPpmd_Default_4g = (UInt32)0 - ((UInt32)1 << 10);
2065 const size_t kPpmd_MaxDictSize_Up = (size_t)1 << (29 + sizeof(size_t) / 8);
2066
2067 if (defaultDict != (UInt32)(Int32)-1
2068 && defaultDict >= ((UInt32)15 << 28)) // threshold
2069 defaultDict = kPpmd_Default_4g;
2070
2071 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
2072
2073 for (unsigned i = (20 - 1) * 2; i <= (32 - 1) * 2; i++)
2074 {
2075 if (i == (20 - 1) * 2 + 1)
2076 continue;
2077
2078 const size_t dict_up = (size_t)(2 + (i & 1)) << (i / 2);
2079 size_t dict = dict_up;
2080 if (dict_up >= kPpmd_Default_4g)
2081 dict = kPpmd_Default_4g;
2082
2083 const int index = AddDict2(dict, dict_up);
2084 // AddDict2((UInt32)((UInt32)0 - 2), dict_up); // for debug
2085 // AddDict(dict_up); // for debug
2086 // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
2087 if (defaultDict != (UInt32)(Int32)-1)
2088 if (dict <= defaultDict || curSel <= 0)
2089 // if (!maxRamSize_Defined || memUsage <= maxRamSize)
2090 curSel = index;
2091 if (dict_up >= kPpmd_MaxDictSize_Up)
2092 break;
2093 }
2094 m_Dictionary.SetCurSel(curSel);
2095 break;
2096 }
2097
2098 case kPPMdZip:
2099 {
2100 _auto_Dict = (UInt32)1 << (level + 19);
2101
2102 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
2103
2104 for (unsigned i = 20; i <= 28; i++)
2105 {
2106 const UInt32 dict = (UInt32)1 << i;
2107 const int index = AddDict(dict);
2108 // const UInt64 memUsage = GetMemoryUsageComp_Threads_Dict(1, dict);
2109 if (defaultDict != (UInt32)(Int32)-1)
2110 if (dict <= defaultDict || curSel <= 0)
2111 // if (!maxRamSize_Defined || memUsage <= maxRamSize)
2112 curSel = index;
2113 }
2114 m_Dictionary.SetCurSel(curSel);
2115 break;
2116 }
2117
2118 case kDeflate:
2119 case kDeflate64:
2120 {
2121 const UInt32 dict = (methodID == kDeflate ? (UInt32)(1 << 15) : (UInt32)(1 << 16));
2122 _auto_Dict = dict;
2123 AddDict2(k_Auto_Dict, _auto_Dict);
2124 m_Dictionary.SetCurSel(0);
2125 // EnableItem(IDC_COMPRESS_DICTIONARY, false);
2126 break;
2127 }
2128
2129 case kBZip2:
2130 {
2131 {
2132 if (level >= 5) _auto_Dict = (900 << 10);
2133 else if (level >= 3) _auto_Dict = (500 << 10);
2134 else _auto_Dict = (100 << 10);
2135 }
2136
2137 int curSel = AddDict2(k_Auto_Dict, _auto_Dict);
2138
2139 for (unsigned i = 1; i <= 9; i++)
2140 {
2141 const UInt32 dict = ((UInt32)i * 100) << 10;
2142 AddDict(dict);
2143 // AddDict2(i * 100000, dict);
2144 if (defaultDict != (UInt32)(Int32)-1)
2145 if (i <= defaultDict / 100000 || curSel <= 0)
2146 curSel = m_Dictionary.GetCount() - 1;
2147 }
2148 m_Dictionary.SetCurSel(curSel);
2149 break;
2150 }
2151
2152 case kCopy:
2153 {
2154 _auto_Dict = 0;
2155 AddDict(0);
2156 m_Dictionary.SetCurSel(0);
2157 break;
2158 }
2159 }
2160 }
2161
2162
GetComboValue(NWindows::NControl::CComboBox & c,int defMax)2163 UInt32 CCompressDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax)
2164 {
2165 if (c.GetCount() <= defMax)
2166 return (UInt32)(Int32)-1;
2167 return (UInt32)c.GetItemData_of_CurSel();
2168 }
2169
2170
GetComboValue_64(NWindows::NControl::CComboBox & c,int defMax)2171 UInt64 CCompressDialog::GetComboValue_64(NWindows::NControl::CComboBox &c, int defMax)
2172 {
2173 if (c.GetCount() <= defMax)
2174 return (UInt64)(Int64)-1;
2175 // LRESULT is signed. so we cast it to unsigned size_t at first:
2176 LRESULT val = c.GetItemData_of_CurSel();
2177 if (val == (LPARAM)(INT_PTR)(-1))
2178 return (UInt64)(Int64)-1;
2179 return (UInt64)(size_t)c.GetItemData_of_CurSel();
2180 }
2181
GetLevel2()2182 UInt32 CCompressDialog::GetLevel2()
2183 {
2184 UInt32 level = GetLevel();
2185 if (level == (UInt32)(Int32)-1)
2186 level = 5;
2187 return level;
2188 }
2189
2190
AddOrder(UInt32 size)2191 int CCompressDialog::AddOrder(UInt32 size)
2192 {
2193 char s[32];
2194 ConvertUInt32ToString(size, s);
2195 const int index = (int)ComboBox_AddStringAscii(m_Order, s);
2196 m_Order.SetItemData(index, (LPARAM)size);
2197 return index;
2198 }
2199
AddOrder_Auto()2200 int CCompressDialog::AddOrder_Auto()
2201 {
2202 AString s;
2203 s.Add_UInt32(_auto_Order);
2204 Modify_Auto(s);
2205 int index = (int)ComboBox_AddStringAscii(m_Order, s);
2206 m_Order.SetItemData(index, (LPARAM)(INT_PTR)(-1));
2207 return index;
2208 }
2209
SetOrder2()2210 void CCompressDialog::SetOrder2()
2211 {
2212 m_Order.ResetContent();
2213
2214 _auto_Order = 1;
2215
2216 const CArcInfoEx &ai = Get_ArcInfoEx();
2217 UInt32 defaultOrder = (UInt32)(Int32)-1;
2218
2219 {
2220 const int index = FindRegistryFormat(ai.Name);
2221 if (index >= 0)
2222 {
2223 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
2224 if (IsMethodEqualTo(fo.Method))
2225 defaultOrder = fo.Order;
2226 }
2227 }
2228
2229 const int methodID = GetMethodID();
2230 const UInt32 level = GetLevel2();
2231 if (methodID < 0)
2232 return;
2233
2234 switch (methodID)
2235 {
2236 case kLZMA:
2237 case kLZMA2:
2238 {
2239 _auto_Order = (level < 7 ? 32 : 64);
2240 int curSel = AddOrder_Auto();
2241 for (unsigned i = 2 * 2; i < 8 * 2; i++)
2242 {
2243 UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
2244 if (order > 256)
2245 order = 273;
2246 const int index = AddOrder(order);
2247 if (defaultOrder != (UInt32)(Int32)-1)
2248 if (order <= defaultOrder || curSel <= 0)
2249 curSel = index;
2250 }
2251 m_Order.SetCurSel(curSel);
2252 break;
2253 }
2254
2255 /*
2256 case kZSTD:
2257 {
2258 {
2259 CZstdEncProps props;
2260 ZstdEncProps_Init(&props);
2261 // props.level_zstd = level;
2262 props.level_7z = level;
2263 ZstdEncProps_NormalizeFull(&props);
2264 _auto_Order = props.targetLength;
2265 if (props.strategy < ZSTD_strategy_btopt)
2266 {
2267 // ZSTD_strategy_fast uses targetLength to change fast level.
2268 // targetLength probably is used only in ZSTD_strategy_btopt and higher
2269 break;
2270 }
2271 }
2272 int curSel = AddOrder_Auto();
2273
2274 for (unsigned i = 6; i <= 9 * 2; i++)
2275 {
2276 UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
2277 // if (order > 999) order = 999;
2278 const int index = AddOrder(order);
2279 if (defaultOrder != (UInt32)(Int32)-1)
2280 if (order <= defaultOrder || curSel <= 0)
2281 curSel = index;
2282 }
2283 m_Order.SetCurSel(curSel);
2284 break;
2285 }
2286 */
2287
2288 case kDeflate:
2289 case kDeflate64:
2290 {
2291 {
2292 if (level >= 9) _auto_Order = 128;
2293 else if (level >= 7) _auto_Order = 64;
2294 else _auto_Order = 32;
2295 }
2296 int curSel = AddOrder_Auto();
2297 for (unsigned i = 2 * 2; i < 8 * 2; i++)
2298 {
2299 UInt32 order = ((UInt32)(2 + (i & 1)) << (i / 2));
2300 if (order > 256)
2301 order = (methodID == kDeflate64 ? 257 : 258);
2302 const int index = AddOrder(order);
2303 if (defaultOrder != (UInt32)(Int32)-1)
2304 if (order <= defaultOrder || curSel <= 0)
2305 curSel = index;
2306 }
2307
2308 m_Order.SetCurSel(curSel);
2309 break;
2310 }
2311
2312 case kPPMd:
2313 {
2314 {
2315 if (level >= 9) _auto_Order = 32;
2316 else if (level >= 7) _auto_Order = 16;
2317 else if (level >= 5) _auto_Order = 6;
2318 else _auto_Order = 4;
2319 }
2320
2321 int curSel = AddOrder_Auto();
2322
2323 for (unsigned i = 0;; i++)
2324 {
2325 UInt32 order = i + 2;
2326 if (i >= 2)
2327 order = (4 + ((i - 2) & 3)) << ((i - 2) / 4);
2328 const int index = AddOrder(order);
2329 if (defaultOrder != (UInt32)(Int32)-1)
2330 if (order <= defaultOrder || curSel <= 0)
2331 curSel = index;
2332 if (order >= 32)
2333 break;
2334 }
2335 m_Order.SetCurSel(curSel);
2336 break;
2337 }
2338
2339 case kPPMdZip:
2340 {
2341 _auto_Order = level + 3;
2342 int curSel = AddOrder_Auto();
2343 for (unsigned i = 2; i <= 16; i++)
2344 {
2345 const int index = AddOrder(i);
2346 if (defaultOrder != (UInt32)(Int32)-1)
2347 if (i <= defaultOrder || curSel <= 0)
2348 curSel = index;
2349 }
2350 m_Order.SetCurSel(curSel);
2351 break;
2352 }
2353
2354 // case kBZip2:
2355 default:
2356 break;
2357 }
2358 }
2359
GetOrderMode()2360 bool CCompressDialog::GetOrderMode()
2361 {
2362 switch (GetMethodID())
2363 {
2364 case kPPMd:
2365 case kPPMdZip:
2366 return true;
2367 }
2368 return false;
2369 }
2370
2371
Get_Lzma2_ChunkSize(UInt64 dict)2372 static UInt64 Get_Lzma2_ChunkSize(UInt64 dict)
2373 {
2374 // we use same default chunk sizes as defined in 7z encoder and lzma2 encoder
2375 UInt64 cs = (UInt64)dict << 2;
2376 const UInt32 kMinSize = (UInt32)1 << 20;
2377 const UInt32 kMaxSize = (UInt32)1 << 28;
2378 if (cs < kMinSize) cs = kMinSize;
2379 if (cs > kMaxSize) cs = kMaxSize;
2380 if (cs < dict) cs = dict;
2381 cs += (kMinSize - 1);
2382 cs &= ~(UInt64)(kMinSize - 1);
2383 return cs;
2384 }
2385
2386
Add_Size(AString & s,UInt64 val)2387 static void Add_Size(AString &s, UInt64 val)
2388 {
2389 unsigned moveBits = 0;
2390 char c = 0;
2391 if ((val & 0x3FFFFFFF) == 0) { moveBits = 30; c = 'G'; }
2392 else if ((val & 0xFFFFF) == 0) { moveBits = 20; c = 'M'; }
2393 else if ((val & 0x3FF) == 0) { moveBits = 10; c = 'K'; }
2394 s.Add_UInt64(val >> moveBits);
2395 s.Add_Space();
2396 if (moveBits != 0)
2397 s.Add_Char(c);
2398 s.Add_Char('B');
2399 }
2400
2401
SetSolidBlockSize2()2402 void CCompressDialog::SetSolidBlockSize2()
2403 {
2404 m_Solid.ResetContent();
2405 _auto_Solid = 1 << 20;
2406
2407 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
2408 if (!fi.Solid_())
2409 return;
2410
2411 const UInt32 level = GetLevel2();
2412 if (level == 0)
2413 return;
2414
2415 UInt64 dict = GetDict2();
2416 if (dict == (UInt64)(Int64)-1)
2417 {
2418 dict = 1 << 25; // default dict for unknown methods
2419 // return;
2420 }
2421
2422
2423 UInt32 defaultBlockSize = (UInt32)(Int32)-1;
2424
2425 const CArcInfoEx &ai = Get_ArcInfoEx();
2426
2427 /*
2428 if (usePrevDictionary)
2429 defaultBlockSize = GetBlockSizeSpec();
2430 else
2431 */
2432 {
2433 const int index = FindRegistryFormat(ai.Name);
2434 if (index >= 0)
2435 {
2436 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
2437 if (IsMethodEqualTo(fo.Method))
2438 defaultBlockSize = fo.BlockLogSize;
2439 }
2440 }
2441
2442 const bool is7z = ai.Is_7z();
2443
2444 const UInt64 cs = Get_Lzma2_ChunkSize(dict);
2445
2446 // Solid Block Size
2447 UInt64 blockSize = cs; // for xz
2448
2449 if (is7z)
2450 {
2451 // we use same default block sizes as defined in 7z encoder
2452 UInt64 kMaxSize = (UInt64)1 << 32;
2453 const int methodId = GetMethodID();
2454 if (methodId == kLZMA2)
2455 {
2456 blockSize = cs << 6;
2457 kMaxSize = (UInt64)1 << 34;
2458 }
2459 else
2460 {
2461 UInt64 dict2 = dict;
2462 if (methodId == kBZip2)
2463 {
2464 dict2 /= 100000;
2465 if (dict2 < 1)
2466 dict2 = 1;
2467 dict2 *= 100000;
2468 }
2469 blockSize = dict2 << 7;
2470 }
2471
2472 const UInt32 kMinSize = (UInt32)1 << 24;
2473 if (blockSize < kMinSize) blockSize = kMinSize;
2474 if (blockSize > kMaxSize) blockSize = kMaxSize;
2475 }
2476
2477 _auto_Solid = blockSize;
2478
2479 int curSel;
2480 {
2481 AString s;
2482 Add_Size(s, _auto_Solid);
2483 Modify_Auto(s);
2484 const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
2485 m_Solid.SetItemData(index, (LPARAM)(UInt32)(Int32)-1);
2486 curSel = index;
2487 }
2488
2489 if (is7z)
2490 {
2491 UString s ('-');
2492 // kSolidLog_NoSolid = 0 for xz means default blockSize
2493 if (is7z)
2494 LangString(IDS_COMPRESS_NON_SOLID, s);
2495 const int index = (int)m_Solid.AddString(s);
2496 m_Solid.SetItemData(index, (LPARAM)(UInt32)kSolidLog_NoSolid);
2497 if (defaultBlockSize == kSolidLog_NoSolid)
2498 curSel = index;
2499 }
2500
2501 for (unsigned i = 20; i <= 36; i++)
2502 {
2503 AString s;
2504 Add_Size(s, (UInt64)1 << i);
2505 const int index = (int)ComboBox_AddStringAscii(m_Solid, s);
2506 m_Solid.SetItemData(index, (LPARAM)(UInt32)i);
2507 if (defaultBlockSize != (UInt32)(Int32)-1)
2508 if (i <= defaultBlockSize || index <= 1)
2509 curSel = index;
2510 }
2511
2512 {
2513 const int index = (int)m_Solid.AddString(LangString(IDS_COMPRESS_SOLID));
2514 m_Solid.SetItemData(index, (LPARAM)kSolidLog_FullSolid);
2515 if (defaultBlockSize == kSolidLog_FullSolid)
2516 curSel = index;
2517 }
2518
2519 m_Solid.SetCurSel(curSel);
2520 }
2521
2522
2523 /*
2524 static void ZstdEncProps_SetDictProps_From_CompressDialog(CZstdEncProps *props, CCompressDialog &cd)
2525 {
2526 {
2527 const UInt64 d64 = cd.GetDictSpec();
2528 UInt32 d32 = 0; // 0 is default for ZstdEncProps::windowLog
2529 if (d64 != (UInt64)(Int64)-1)
2530 {
2531 d32 = (UInt32)d64;
2532 if (d32 != d64)
2533 d32 = (UInt32)(Int32)-2;
2534 }
2535 ZstdEncProps_Set_WindowSize(props, d32);
2536 }
2537 {
2538 const UInt64 d64 = cd.GetDictChainSpec();
2539 UInt32 d32 = 0; // 0 is default for ZstdEncProps::windowLog_Chain
2540 if (d64 != (UInt64)(Int64)-1)
2541 {
2542 d32 = (UInt32)d64;
2543 if (d32 != d64)
2544 d32 = (UInt32)(Int32)-2;
2545 }
2546 ZstdEncProps_Set_WindowChainSize(props, d32);
2547 }
2548 }
2549
2550 static bool Is_Zstd_Mt_Supported()
2551 {
2552 if (!GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "InitializeConditionVariable"))
2553 return false;
2554 return true;
2555 }
2556 */
2557
2558 static const char *k_ST_Threads = " (ST)";
2559
SetNumThreads2()2560 void CCompressDialog::SetNumThreads2()
2561 {
2562 _auto_NumThreads = 1;
2563
2564 m_NumThreads.ResetContent();
2565 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
2566 if (!fi.MultiThread_())
2567 return;
2568
2569 const UInt32 numHardwareThreads = NSystem::GetNumberOfProcessors();
2570 // 64; // for debug:
2571
2572 UInt32 defaultValue = numHardwareThreads;
2573 bool useAutoThreads = true;
2574
2575 {
2576 const CArcInfoEx &ai = Get_ArcInfoEx();
2577 int index = FindRegistryFormat(ai.Name);
2578 if (index >= 0)
2579 {
2580 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
2581 if (IsMethodEqualTo(fo.Method) && fo.NumThreads != (UInt32)(Int32)-1)
2582 {
2583 defaultValue = fo.NumThreads;
2584 useAutoThreads = false;
2585 }
2586 }
2587 }
2588
2589 // const UInt32 num_ZSTD_threads_MAX = Is_Zstd_Mt_Supported() ? MY_ZSTDMT_NBWORKERS_MAX : 0;
2590
2591 UInt32 numAlgoThreadsMax = numHardwareThreads * 2;
2592 const int methodID = GetMethodID();
2593
2594 switch (methodID)
2595 {
2596 case kLZMA: numAlgoThreadsMax = 2; break;
2597 case kLZMA2: numAlgoThreadsMax = 256; break;
2598 case kBZip2: numAlgoThreadsMax = 32; break;
2599 // case kZSTD: numAlgoThreadsMax = num_ZSTD_threads_MAX; break;
2600 case kCopy:
2601 case kPPMd:
2602 case kDeflate:
2603 case kDeflate64:
2604 case kPPMdZip:
2605 numAlgoThreadsMax = 1;
2606 }
2607 const bool isZip = IsZipFormat();
2608 if (isZip)
2609 {
2610 numAlgoThreadsMax =
2611 #ifdef _WIN32
2612 64; // _WIN32 supports only 64 threads in one group. So no need for more threads here
2613 #else
2614 128;
2615 #endif
2616 }
2617
2618 UInt32 autoThreads = numHardwareThreads;
2619 if (autoThreads > numAlgoThreadsMax)
2620 autoThreads = numAlgoThreadsMax;
2621
2622 const UInt64 memUse_Limit = Get_MemUse_Bytes();
2623
2624 if (_ramSize_Defined)
2625 if (autoThreads > 1
2626 // || (autoThreads == 0 && methodID == kZSTD)
2627 )
2628 {
2629 if (isZip)
2630 {
2631 for (; autoThreads > 1; autoThreads--)
2632 {
2633 const UInt64 dict64 = GetDict2();
2634 UInt64 decompressMemory;
2635 const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
2636 if (usage <= memUse_Limit)
2637 break;
2638 }
2639 }
2640 else if (methodID == kLZMA2)
2641 {
2642 const UInt64 dict64 = GetDict2();
2643 const UInt32 numThreads1 = (GetLevel2() >= 5 ? 2 : 1);
2644 UInt32 numBlockThreads = autoThreads / numThreads1;
2645 for (; numBlockThreads > 1; numBlockThreads--)
2646 {
2647 autoThreads = numBlockThreads * numThreads1;
2648 UInt64 decompressMemory;
2649 const UInt64 usage = GetMemoryUsage_Threads_Dict_DecompMem(autoThreads, dict64, decompressMemory);
2650 if (usage <= memUse_Limit)
2651 break;
2652 }
2653 autoThreads = numBlockThreads * numThreads1;
2654 }
2655 /*
2656 else if (methodID == kZSTD)
2657 {
2658 if (num_ZSTD_threads_MAX != 0)
2659 {
2660 CZstdEncProps props;
2661 ZstdEncProps_Init(&props);
2662 // props.level_zstd = level;
2663 props.level_7z = GetLevel2();
2664 ZstdEncProps_SetDictProps_From_CompressDialog(&props, *this);
2665 autoThreads = ZstdEncProps_GetNumThreads_for_MemUsageLimit(&props, memUse_Limit, autoThreads);
2666 }
2667 }
2668 */
2669 }
2670
2671 _auto_NumThreads = autoThreads;
2672
2673 int curSel = -1;
2674 {
2675 AString s;
2676 s.Add_UInt32(autoThreads);
2677 if (autoThreads == 0) s += k_ST_Threads;
2678 Modify_Auto(s);
2679 const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
2680 m_NumThreads.SetItemData(index, (LPARAM)(INT_PTR)(-1));
2681 // m_NumThreads.SetItemData(index, autoThreads);
2682 if (useAutoThreads)
2683 curSel = index;
2684 }
2685
2686 if (numAlgoThreadsMax != autoThreads || autoThreads != 1)
2687 for (UInt32 i =
2688 // (methodID == kZSTD) ? 0 :
2689 1;
2690 i <= numHardwareThreads * 2 && i <= numAlgoThreadsMax; i++)
2691 {
2692 AString s;
2693 s.Add_UInt32(i);
2694 if (i == 0) s += k_ST_Threads;
2695 const int index = (int)ComboBox_AddStringAscii(m_NumThreads, s);
2696 m_NumThreads.SetItemData(index, (LPARAM)(UInt32)i);
2697 if (!useAutoThreads && i == defaultValue)
2698 curSel = index;
2699 }
2700
2701 m_NumThreads.SetCurSel(curSel);
2702 }
2703
2704
AddMemSize(UString & res,UInt64 size)2705 static void AddMemSize(UString &res, UInt64 size)
2706 {
2707 char c;
2708 unsigned moveBits = 0;
2709 if (size >= ((UInt64)1 << 31) && (size & 0x3FFFFFFF) == 0)
2710 { moveBits = 30; c = 'G'; }
2711 else // if (size >= ((UInt32)1 << 21) && (size & 0xFFFFF) == 0)
2712 { moveBits = 20; c = 'M'; }
2713 // else { moveBits = 10; c = 'K'; }
2714 res.Add_UInt64(size >> moveBits);
2715 res.Add_Space();
2716 if (moveBits != 0)
2717 res.Add_Char(c);
2718 res.Add_Char('B');
2719 }
2720
2721
AddMemComboItem(UInt64 val,bool isPercent,bool isDefault)2722 int CCompressDialog::AddMemComboItem(UInt64 val, bool isPercent, bool isDefault)
2723 {
2724 UString sUser;
2725 UString sRegistry;
2726 if (isPercent)
2727 {
2728 UString s;
2729 s.Add_UInt64(val);
2730 s.Add_Char('%');
2731 if (isDefault)
2732 sUser = k_Auto_Prefix;
2733 else
2734 sRegistry = s;
2735 sUser += s;
2736 }
2737 else
2738 {
2739 AddMemSize(sUser, val);
2740 sRegistry = sUser;
2741 for (;;)
2742 {
2743 const int pos = sRegistry.Find(L' ');
2744 if (pos < 0)
2745 break;
2746 sRegistry.Delete(pos);
2747 }
2748 if (!sRegistry.IsEmpty())
2749 if (sRegistry.Back() == 'B')
2750 sRegistry.DeleteBack();
2751 }
2752 const unsigned dataIndex = _memUse_Strings.Add(sRegistry);
2753 const int index = (int)m_MemUse.AddString(sUser);
2754 m_MemUse.SetItemData(index, (LPARAM)dataIndex);
2755 return index;
2756 }
2757
2758
2759
SetMemUseCombo()2760 void CCompressDialog::SetMemUseCombo()
2761 {
2762 _memUse_Strings.Clear();
2763 m_MemUse.ResetContent();
2764 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
2765
2766 {
2767 const bool enable = fi.MemUse_();
2768 ShowItem_Bool(IDT_COMPRESS_MEMORY, enable);
2769 ShowItem_Bool(IDT_COMPRESS_MEMORY_VALUE, enable);
2770 ShowItem_Bool(IDT_COMPRESS_MEMORY_DE, enable);
2771 ShowItem_Bool(IDT_COMPRESS_MEMORY_DE_VALUE, enable);
2772 ShowItem_Bool(IDC_COMPRESS_MEM_USE, enable);
2773 EnableItem(IDC_COMPRESS_MEM_USE, enable);
2774 if (!enable)
2775 return;
2776 }
2777
2778 UInt64 curMem_Bytes = 0;
2779 UInt64 curMem_Percents = 0;
2780 bool needSetCur_Bytes = false;
2781 bool needSetCur_Percents = false;
2782 {
2783 const NCompression::CFormatOptions &fo = Get_FormatOptions();
2784 if (!fo.MemUse.IsEmpty())
2785 {
2786 NCompression::CMemUse mu;
2787 mu.Parse(fo.MemUse);
2788 if (mu.IsDefined)
2789 {
2790 if (mu.IsPercent)
2791 {
2792 curMem_Percents = mu.Val;
2793 needSetCur_Percents = true;
2794 }
2795 else
2796 {
2797 curMem_Bytes = mu.GetBytes(_ramSize_Reduced);
2798 needSetCur_Bytes = true;
2799 }
2800 }
2801 }
2802 }
2803
2804
2805 // 80% - is auto usage limit in handlers
2806 AddMemComboItem(80, true, true);
2807 m_MemUse.SetCurSel(0);
2808
2809 {
2810 for (unsigned i = 10;; i += 10)
2811 {
2812 UInt64 size = i;
2813 if (i > 100)
2814 size = (UInt64)(Int64)-1;
2815 if (needSetCur_Percents && size >= curMem_Percents)
2816 {
2817 const int index = AddMemComboItem(curMem_Percents, true);
2818 m_MemUse.SetCurSel(index);
2819 needSetCur_Percents = false;
2820 if (size == curMem_Percents)
2821 continue;
2822 }
2823 if (size == (UInt64)(Int64)-1)
2824 break;
2825 AddMemComboItem(size, true);
2826 }
2827 }
2828 {
2829 for (unsigned i = (27) * 2;; i++)
2830 {
2831 UInt64 size = (UInt64)(2 + (i & 1)) << (i / 2);
2832 if (i > (20 + sizeof(size_t) * 3 - 1) * 2)
2833 size = (UInt64)(Int64)-1;
2834 if (needSetCur_Bytes && size >= curMem_Bytes)
2835 {
2836 const int index = AddMemComboItem(curMem_Bytes);
2837 m_MemUse.SetCurSel(index);
2838 needSetCur_Bytes = false;
2839 if (size == curMem_Bytes)
2840 continue;
2841 }
2842 if (size == (UInt64)(Int64)-1)
2843 break;
2844 AddMemComboItem(size);
2845 }
2846 }
2847 }
2848
2849
Get_MemUse_Spec()2850 UString CCompressDialog::Get_MemUse_Spec()
2851 {
2852 if (m_MemUse.GetCount() < 1)
2853 return UString();
2854 return _memUse_Strings[(unsigned)m_MemUse.GetItemData_of_CurSel()];
2855 }
2856
2857
Get_MemUse_Bytes()2858 UInt64 CCompressDialog::Get_MemUse_Bytes()
2859 {
2860 const UString mus = Get_MemUse_Spec();
2861 NCompression::CMemUse mu;
2862 if (!mus.IsEmpty())
2863 {
2864 mu.Parse(mus);
2865 if (mu.IsDefined)
2866 return mu.GetBytes(_ramSize_Reduced);
2867 }
2868 return _ramUsage_Auto; // _ramSize_Reduced; // _ramSize;;
2869 }
2870
2871
2872
GetMemoryUsage_DecompMem(UInt64 & decompressMemory)2873 UInt64 CCompressDialog::GetMemoryUsage_DecompMem(UInt64 &decompressMemory)
2874 {
2875 return GetMemoryUsage_Dict_DecompMem(GetDict2(), decompressMemory);
2876 }
2877
2878
2879 /*
2880 we could use that function to reduce the dictionary if small RAM
2881 UInt64 CCompressDialog::GetMemoryUsageComp_Threads_Dict(UInt32 numThreads, UInt64 dict64)
2882 {
2883 UInt64 decompressMemory;
2884 return GetMemoryUsage_Threads_Dict_DecompMem(numThreads, dict64, decompressMemory);
2885 }
2886 */
2887
2888
GetMemoryUsage_Dict_DecompMem(UInt64 dict64,UInt64 & decompressMemory)2889 UInt64 CCompressDialog::GetMemoryUsage_Dict_DecompMem(UInt64 dict64, UInt64 &decompressMemory)
2890 {
2891 return GetMemoryUsage_Threads_Dict_DecompMem(GetNumThreads2(), dict64, decompressMemory);
2892 }
2893
GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads,UInt64 dict64,UInt64 & decompressMemory)2894 UInt64 CCompressDialog::GetMemoryUsage_Threads_Dict_DecompMem(UInt32 numThreads, UInt64 dict64, UInt64 &decompressMemory)
2895 {
2896 decompressMemory = (UInt64)(Int64)-1;
2897
2898 const UInt32 level = GetLevel2();
2899 if (level == 0 && !Get_ArcInfoEx().Is_Zstd())
2900 {
2901 decompressMemory = (1 << 20);
2902 return decompressMemory;
2903 }
2904 UInt64 size = 0;
2905
2906 const CFormatInfo &fi = g_Formats[GetStaticFormatIndex()];
2907 if (fi.Filter_() && level >= 9)
2908 size += (12 << 20) * 2 + (5 << 20);
2909 // UInt32 numThreads = GetNumThreads2();
2910
2911 UInt32 numMainZipThreads = 1;
2912
2913 if (IsZipFormat())
2914 {
2915 UInt32 numSubThreads = 1;
2916 if (GetMethodID() == kLZMA && numThreads > 1 && level >= 5)
2917 numSubThreads = 2;
2918 numMainZipThreads = numThreads / numSubThreads;
2919 if (numMainZipThreads > 1)
2920 size += (UInt64)numMainZipThreads * ((size_t)sizeof(size_t) << 23);
2921 else
2922 numMainZipThreads = 1;
2923 }
2924
2925 const int methodId = GetMethodID();
2926
2927 if (dict64 == (UInt64)(Int64)-1
2928 // && methodId != kZSTD
2929 )
2930 return (UInt64)(Int64)-1;
2931
2932
2933 switch (methodId)
2934 {
2935 case kLZMA:
2936 case kLZMA2:
2937 {
2938 const UInt32 dict = (dict64 >= kLzmaMaxDictSize ? kLzmaMaxDictSize : (UInt32)dict64);
2939 UInt32 hs = dict - 1;
2940 hs |= (hs >> 1);
2941 hs |= (hs >> 2);
2942 hs |= (hs >> 4);
2943 hs |= (hs >> 8);
2944 hs >>= 1;
2945 if (hs >= (1 << 24))
2946 hs >>= 1;
2947 hs |= (1 << 16) - 1;
2948 // if (numHashBytes >= 5)
2949 if (level < 5)
2950 hs |= (256 << 10) - 1;
2951 hs++;
2952 UInt64 size1 = (UInt64)hs * 4;
2953 size1 += (UInt64)dict * 4;
2954 if (level >= 5)
2955 size1 += (UInt64)dict * 4;
2956 size1 += (2 << 20);
2957
2958 UInt32 numThreads1 = 1;
2959 if (numThreads > 1 && level >= 5)
2960 {
2961 size1 += (2 << 20) + (4 << 20);
2962 numThreads1 = 2;
2963 }
2964
2965 UInt32 numBlockThreads = numThreads / numThreads1;
2966
2967 UInt64 chunkSize = 0; // it's solid chunk
2968
2969 if (methodId != kLZMA && numBlockThreads != 1)
2970 {
2971 chunkSize = Get_Lzma2_ChunkSize(dict);
2972
2973 if (IsXzFormat())
2974 {
2975 UInt32 blockSizeLog = GetBlockSizeSpec();
2976 if (blockSizeLog != (UInt32)(Int32)-1)
2977 {
2978 if (blockSizeLog == kSolidLog_FullSolid)
2979 {
2980 numBlockThreads = 1;
2981 chunkSize = 0;
2982 }
2983 else if (blockSizeLog != kSolidLog_NoSolid)
2984 chunkSize = (UInt64)1 << blockSizeLog;
2985 }
2986 }
2987 }
2988
2989 if (chunkSize == 0)
2990 {
2991 const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16);
2992 UInt64 blockSize = (UInt64)dict + (1 << 16)
2993 + (numThreads1 > 1 ? (1 << 20) : 0);
2994 blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2));
2995 if (blockSize >= kBlockSizeMax)
2996 blockSize = kBlockSizeMax;
2997 size += numBlockThreads * (size1 + blockSize);
2998 }
2999 else
3000 {
3001 size += numBlockThreads * (size1 + chunkSize);
3002 UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;
3003 if (chunkSize < ((UInt32)1 << 26)) numBlockThreads++;
3004 if (chunkSize < ((UInt32)1 << 24)) numBlockThreads++;
3005 if (chunkSize < ((UInt32)1 << 22)) numBlockThreads++;
3006 size += numPackChunks * chunkSize;
3007 }
3008
3009 decompressMemory = dict + (2 << 20);
3010 return size;
3011 }
3012
3013 /*
3014 case kZSTD:
3015 {
3016 CZstdEncProps props;
3017 ZstdEncProps_Init(&props);
3018 // props.level_zstd = level;
3019 props.level_7z = level;
3020 props.nbWorkers = numThreads;
3021 ZstdEncProps_SetDictProps_From_CompressDialog(&props, *this);
3022 ZstdEncProps_NormalizeFull(&props);
3023 size = ZstdEncProps_GetMemUsage(&props);
3024 decompressMemory = (UInt64)1 << props.windowLog;
3025 return size;
3026 }
3027 */
3028
3029 case kPPMd:
3030 {
3031 decompressMemory = dict64 + (2 << 20);
3032 return size + decompressMemory;
3033 }
3034
3035 case kDeflate:
3036 case kDeflate64:
3037 {
3038 UInt64 size1 = 3 << 20;
3039 // if (level >= 7)
3040 size1 += (1 << 20);
3041 size += size1 * numMainZipThreads;
3042 decompressMemory = (2 << 20);
3043 return size;
3044 }
3045
3046 case kBZip2:
3047 {
3048 decompressMemory = (7 << 20);
3049 UInt64 memForOneThread = (10 << 20);
3050 return size + memForOneThread * numThreads;
3051 }
3052
3053 case kPPMdZip:
3054 {
3055 decompressMemory = dict64 + (2 << 20);
3056 return size + (UInt64)decompressMemory * numThreads;
3057 }
3058 }
3059
3060 return (UInt64)(Int64)-1;
3061 }
3062
3063
3064
AddMemUsage(UString & s,UInt64 v)3065 static void AddMemUsage(UString &s, UInt64 v)
3066 {
3067 const char *post;
3068 if (v <= ((UInt64)16 << 30))
3069 {
3070 v = (v + (1 << 20) - 1) >> 20;
3071 post = "MB";
3072 }
3073 else if (v <= ((UInt64)64 << 40))
3074 {
3075 v = (v + (1 << 30) - 1) >> 30;
3076 post = "GB";
3077 }
3078 else
3079 {
3080 const UInt64 v2 = v + ((UInt64)1 << 40) - 1;
3081 if (v <= v2)
3082 v = v2;
3083 v >>= 40;
3084 post = "TB";
3085 }
3086 s.Add_UInt64(v);
3087 s.Add_Space();
3088 s += post;
3089 }
3090
3091
PrintMemUsage(UINT res,UInt64 value)3092 void CCompressDialog::PrintMemUsage(UINT res, UInt64 value)
3093 {
3094 if (value == (UInt64)(Int64)-1)
3095 {
3096 SetItemText(res, TEXT("?"));
3097 return;
3098 }
3099 UString s;
3100 AddMemUsage(s, value);
3101 if (res == IDT_COMPRESS_MEMORY_VALUE)
3102 {
3103 const UString mus = Get_MemUse_Spec();
3104 NCompression::CMemUse mu;
3105 if (!mus.IsEmpty())
3106 mu.Parse(mus);
3107 if (mu.IsDefined)
3108 {
3109 s += " / ";
3110 AddMemUsage(s, mu.GetBytes(_ramSize_Reduced));
3111 }
3112 else if (_ramSize_Defined)
3113 {
3114 s += " / ";
3115 AddMemUsage(s, _ramUsage_Auto);
3116 }
3117
3118 if (_ramSize_Defined)
3119 {
3120 s += " / ";
3121 AddMemUsage(s, _ramSize);
3122 }
3123 }
3124 SetItemText(res, s);
3125 }
3126
3127
SetMemoryUsage()3128 void CCompressDialog::SetMemoryUsage()
3129 {
3130 UInt64 decompressMem;
3131 const UInt64 memUsage = GetMemoryUsage_DecompMem(decompressMem);
3132 PrintMemUsage(IDT_COMPRESS_MEMORY_VALUE, memUsage);
3133 PrintMemUsage(IDT_COMPRESS_MEMORY_DE_VALUE, decompressMem);
3134 #ifdef PRINT_PARAMS
3135 Print_Params();
3136 #endif
3137 }
3138
3139
3140
3141 #ifdef PRINT_PARAMS
3142
3143 static const char kPropDelimeter = ' '; // ':'
3144
AddPropName(AString & s,const char * name)3145 static void AddPropName(AString &s, const char *name)
3146 {
3147 if (!s.IsEmpty())
3148 s += kPropDelimeter;
3149 s += name;
3150 }
3151
AddProp(AString & s,const char * name,unsigned v)3152 static void AddProp(AString &s, const char *name, unsigned v)
3153 {
3154 AddPropName(s, name);
3155 s.Add_UInt32(v);
3156 }
3157
AddProp_switch(AString & s,const char * name,E_ZSTD_paramSwitch_e e)3158 static void AddProp_switch(AString &s, const char *name, E_ZSTD_paramSwitch_e e)
3159 {
3160 AddPropName(s, name);
3161 s += e == k_ZSTD_ps_enable ? "" : "-";
3162 }
3163
PrintPropAsLog(AString & s,const char * name,size_t v)3164 static void PrintPropAsLog(AString &s, const char *name, size_t v)
3165 {
3166 AddPropName(s, name);
3167 for (unsigned i = 0; i < sizeof(size_t) * 8; i++)
3168 {
3169 if (((size_t)1 << i) == v)
3170 {
3171 s.Add_UInt32(i);
3172 return;
3173 }
3174 }
3175 char c = 'b';
3176 if ((v & 0x3FFFFFFF) == 0) { v >>= 30; c = 'G'; }
3177 else if ((v & 0xFFFFF) == 0) { v >>= 20; c = 'M'; }
3178 else if ((v & 0x3FF) == 0) { v >>= 10; c = 'K'; }
3179 s.Add_UInt64(v);
3180 s += c;
3181 }
3182
ZstdEncProps_Print(CZstdEncProps * props,AString & s)3183 static void ZstdEncProps_Print(CZstdEncProps *props, AString &s)
3184 {
3185 if (props->level_zstd >= 0)
3186 AddProp(s, "zx", props->level_zstd);
3187 else
3188 AddProp(s, "zf", -(props->level_zstd));
3189 AddProp(s, "a", props->strategy);
3190 AddProp(s, "d", props->windowLog);
3191 AddProp(s, "zclog", props->chainLog);
3192 AddProp(s, "zhb", props->hashLog);
3193 AddProp(s, "mml", props->minMatch);
3194 AddProp(s, "mcb", props->searchLog);
3195 AddProp(s, "fb", props->targetLength);
3196 AddProp(s, "mt", props->nbWorkers);
3197 PrintPropAsLog(s, "c", props->jobSize);
3198 AddProp(s, "zov", props->overlapLog);
3199 PrintPropAsLog(s, "ztps", props->targetPrefixSize);
3200 AddProp_switch(s, "zmfr", props->useRowMatchFinder);
3201 if (props->ldmParams.enableLdm == k_ZSTD_ps_enable)
3202 {
3203 AddProp_switch(s, "zle", props->ldmParams.enableLdm);
3204 AddProp(s, "zlhb", props->ldmParams.hashLog);
3205 AddProp(s, "zlbb", props->ldmParams.bucketSizeLog);
3206 AddProp(s, "zlmml", props->ldmParams.minMatchLength);
3207 AddProp(s, "zlhrb", props->ldmParams.hashRateLog);
3208 }
3209 }
3210
Print_Params()3211 void CCompressDialog::Print_Params()
3212 {
3213 {
3214 CZstdEncProps props;
3215 ZstdEncProps_Init(&props);
3216 // props.level_zstd = level;
3217 props.level_7z = GetLevel2();
3218 ZstdEncProps_SetDictProps_From_CompressDialog(&props, *this);
3219 {
3220 UInt32 order = GetOrderSpec();
3221 if (order != (UInt32)(Int32)-1)
3222 props.targetLength = GetOrderSpec();
3223 }
3224 props.nbWorkers = GetNumThreads2();
3225 // props.windowLog = 18; // for debug
3226 ZstdEncProps_NormalizeFull(&props);
3227 AString s;
3228 ZstdEncProps_Print(&props, s);
3229 SetItemTextA(IDT_COMPRESS_PARAMS_INFO, s);
3230 }
3231 }
3232
3233 #endif // PRINT_PARAMS
3234
3235
3236
SetParams()3237 void CCompressDialog::SetParams()
3238 {
3239 const CArcInfoEx &ai = Get_ArcInfoEx();
3240 m_Params.SetText(TEXT(""));
3241 const int index = FindRegistryFormat(ai.Name);
3242 if (index >= 0)
3243 {
3244 const NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
3245 m_Params.SetText(fo.Options);
3246 }
3247 }
3248
SaveOptionsInMem()3249 void CCompressDialog::SaveOptionsInMem()
3250 {
3251 /* these options are for (Info.FormatIndex).
3252 If it's called just after format changing,
3253 then it's format that was selected before format changing
3254 So we store previous format properties */
3255
3256 m_Params.GetText(Info.Options);
3257 Info.Options.Trim();
3258
3259 const CArcInfoEx &ai = (*ArcFormats)[Info.FormatIndex];
3260 const unsigned index = FindRegistryFormat_Always(ai.Name);
3261 NCompression::CFormatOptions &fo = m_RegistryInfo.Formats[index];
3262 fo.Options = Info.Options;
3263 fo.Level = GetLevelSpec();
3264 {
3265 const UInt64 dict64 = GetDictSpec();
3266 UInt32 dict32;
3267 if (dict64 == (UInt64)(Int64)-1)
3268 dict32 = (UInt32)(Int32)-1;
3269 else
3270 {
3271 dict32 = (UInt32)dict64;
3272 if (dict64 != dict32)
3273 {
3274 /* here we must write 32-bit value for registry that indicates big_value
3275 (UInt32)(Int32)-1 : is used as marker for default size
3276 (UInt32)(Int32)-2 : it can be used to indicate big value (4 GiB)
3277 the value must be larger than threshold
3278 */
3279 dict32 = (UInt32)(Int32)-2;
3280 // dict32 = kLzmaMaxDictSize; // it must be larger than threshold
3281 }
3282 }
3283 fo.Dictionary = dict32;
3284 }
3285 /*
3286 {
3287 const UInt64 dict64 = GetDictChainSpec();
3288 UInt32 dict32;
3289 if (dict64 == (UInt64)(Int64)-1)
3290 dict32 = (UInt32)(Int32)-1;
3291 else
3292 {
3293 dict32 = (UInt32)dict64;
3294 if (dict64 != dict32)
3295 {
3296 dict32 = (UInt32)(Int32)-2;
3297 // dict32 = k_Zstd_MAX_DictSize; // it must be larger than threshold
3298 }
3299 }
3300 fo.DictionaryChain = dict32;
3301 }
3302 */
3303
3304 fo.Order = GetOrderSpec();
3305 fo.Method = GetMethodSpec();
3306 fo.EncryptionMethod = GetEncryptionMethodSpec();
3307 fo.NumThreads = GetNumThreadsSpec();
3308 fo.BlockLogSize = GetBlockSizeSpec();
3309 fo.MemUse = Get_MemUse_Spec();
3310 }
3311
3312
GetFormatIndex()3313 unsigned CCompressDialog::GetFormatIndex()
3314 {
3315 return (unsigned)m_Format.GetItemData_of_CurSel();
3316 }
3317
3318
3319
AddText_from_BoolPair(AString & s,const char * name,const CBoolPair & bp)3320 static void AddText_from_BoolPair(AString &s, const char *name, const CBoolPair &bp)
3321 {
3322 if (bp.Def)
3323 {
3324 s.Add_OptSpaced(name);
3325 if (!bp.Val)
3326 s += "-";
3327 }
3328 /*
3329 else if (bp.Val)
3330 {
3331 s.Add_OptSpaced("[");
3332 s += name;
3333 s += "]";
3334 }
3335 */
3336 }
3337
3338
AddText_from_Bool1(AString & s,const char * name,const CBool1 & b)3339 static void AddText_from_Bool1(AString &s, const char *name, const CBool1 &b)
3340 {
3341 if (b.Supported && b.Val)
3342 s.Add_OptSpaced(name);
3343 }
3344
3345
ShowOptionsString()3346 void CCompressDialog::ShowOptionsString()
3347 {
3348 NCompression::CFormatOptions &fo = Get_FormatOptions();
3349
3350 AString s;
3351 if (fo.IsSet_TimePrec())
3352 {
3353 s.Add_OptSpaced("tp");
3354 s.Add_UInt32(fo.TimePrec);
3355 }
3356 AddText_from_BoolPair(s, "tm", fo.MTime);
3357 AddText_from_BoolPair(s, "tc", fo.CTime);
3358 AddText_from_BoolPair(s, "ta", fo.ATime);
3359 AddText_from_BoolPair(s, "-stl", fo.SetArcMTime);
3360
3361 // const CArcInfoEx &ai = Get_ArcInfoEx();
3362 AddText_from_Bool1(s, "SL", SymLinks);
3363 AddText_from_Bool1(s, "HL", HardLinks);
3364 AddText_from_Bool1(s, "AS", AltStreams);
3365 AddText_from_Bool1(s, "Sec", NtSecurity);
3366
3367 // AddText_from_Bool1(s, "Preserve", PreserveATime);
3368
3369 SetItemText(IDT_COMPRESS_OPTIONS, GetUnicodeString(s));
3370 }
3371
3372
3373
3374
3375
3376 // ---------- OPTIONS ----------
3377
3378
CheckButton_Bool1(UINT id,const CBool1 & b1)3379 void COptionsDialog::CheckButton_Bool1(UINT id, const CBool1 &b1)
3380 {
3381 CheckButton(id, b1.Val);
3382 }
3383
GetButton_Bool1(UINT id,CBool1 & b1)3384 void COptionsDialog::GetButton_Bool1(UINT id, CBool1 &b1)
3385 {
3386 b1.Val = IsButtonCheckedBool(id);
3387 }
3388
3389
CheckButton_BoolBox(bool supported,const CBoolPair & b2,CBoolBox & bb)3390 void COptionsDialog::CheckButton_BoolBox(
3391 bool supported, const CBoolPair &b2, CBoolBox &bb)
3392 {
3393 const bool isSet = b2.Def;
3394 const bool val = isSet ? b2.Val : bb.DefaultVal;
3395
3396 bb.IsSupported = supported;
3397
3398 CheckButton (bb.Set_Id, isSet);
3399 ShowItem_Bool (bb.Set_Id, supported);
3400 CheckButton (bb.Id, val);
3401 EnableItem (bb.Id, isSet);
3402 ShowItem_Bool (bb.Id, supported);
3403 }
3404
GetButton_BoolBox(CBoolBox & bb)3405 void COptionsDialog::GetButton_BoolBox(CBoolBox &bb)
3406 {
3407 // we save value for invisible buttons too
3408 bb.BoolPair.Val = IsButtonCheckedBool (bb.Id);
3409 bb.BoolPair.Def = IsButtonCheckedBool (bb.Set_Id);
3410 }
3411
3412
Store_TimeBoxes()3413 void COptionsDialog::Store_TimeBoxes()
3414 {
3415 TimePrec = GetPrecSpec();
3416 GetButton_BoolBox (MTime);
3417 GetButton_BoolBox (CTime);
3418 GetButton_BoolBox (ATime);
3419 GetButton_BoolBox (ZTime);
3420 }
3421
3422
GetComboValue(NWindows::NControl::CComboBox & c,int defMax)3423 UInt32 COptionsDialog::GetComboValue(NWindows::NControl::CComboBox &c, int defMax)
3424 {
3425 if (c.GetCount() <= defMax)
3426 return (UInt32)(Int32)-1;
3427 return (UInt32)c.GetItemData_of_CurSel();
3428 }
3429
3430 static const unsigned kTimePrec_Win = 0;
3431 static const unsigned kTimePrec_Unix = 1;
3432 static const unsigned kTimePrec_DOS = 2;
3433 static const unsigned kTimePrec_1ns = 3;
3434
AddTimeOption(UString & s,UInt32 val,const UString & unit,const char * sys=NULL)3435 static void AddTimeOption(UString &s, UInt32 val, const UString &unit, const char *sys = NULL)
3436 {
3437 // s += " : ";
3438 {
3439 AString s2;
3440 s2.Add_UInt32(val);
3441 s += s2;
3442 }
3443 s.Add_Space();
3444 s += unit;
3445 if (sys)
3446 {
3447 s += " : ";
3448 s += sys;
3449 }
3450 }
3451
AddPrec(unsigned prec,bool isDefault)3452 int COptionsDialog::AddPrec(unsigned prec, bool isDefault)
3453 {
3454 UString s;
3455 UInt32 writePrec = prec;
3456 if (isDefault)
3457 {
3458 // s += "* ";
3459 // writePrec = (UInt32)(Int32)-1;
3460 }
3461 if (prec == kTimePrec_Win) AddTimeOption(s, 100, NsString, "Windows");
3462 else if (prec == kTimePrec_Unix) AddTimeOption(s, 1, SecString, "Unix");
3463 else if (prec == kTimePrec_DOS) AddTimeOption(s, 2, SecString, "DOS");
3464 else if (prec == kTimePrec_1ns) AddTimeOption(s, 1, NsString, "Linux");
3465 else if (prec == k_PropVar_TimePrec_Base) AddTimeOption(s, 1, SecString);
3466 else if (prec >= k_PropVar_TimePrec_Base)
3467 {
3468 UInt32 d = 1;
3469 for (unsigned i = prec; i < k_PropVar_TimePrec_Base + 9; i++)
3470 d *= 10;
3471 AddTimeOption(s, d, NsString);
3472 }
3473 else
3474 s.Add_UInt32(prec);
3475 const int index = (int)m_Prec.AddString(s);
3476 m_Prec.SetItemData(index, (LPARAM)writePrec);
3477 return index;
3478 }
3479
3480
SetPrec()3481 void COptionsDialog::SetPrec()
3482 {
3483 // const CFormatInfo &fi = g_Formats[cd->GetStaticFormatIndex()];
3484 const CArcInfoEx &ai = cd->Get_ArcInfoEx();
3485
3486 // UInt32 flags = fi.Flags;
3487
3488 UInt32 flags = ai.Get_TimePrecFlags();
3489 UInt32 defaultPrec = ai.Get_DefaultTimePrec();
3490 if (defaultPrec != 0)
3491 flags |= ((UInt32)1 << defaultPrec);
3492
3493 // const NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
3494
3495 // unsigned defaultPrec = kTimePrec_Win;
3496
3497 if (ai.Is_GZip())
3498 defaultPrec = kTimePrec_Unix;
3499
3500 {
3501 UString s;
3502 s += GetNameOfProperty(kpidType, L"type");
3503 s += ": ";
3504 s += ai.Name;
3505 if (ai.Is_Tar())
3506 {
3507 const int methodID = cd->GetMethodID();
3508
3509 // for debug
3510 // defaultPrec = kTimePrec_Unix;
3511 // flags = (UInt32)1 << kTimePrec_Unix;
3512
3513 s.Add_Colon();
3514 if (methodID >= 0 && (unsigned)methodID < Z7_ARRAY_SIZE(kMethodsNames))
3515 s += kMethodsNames[methodID];
3516 if (methodID == kPosix)
3517 {
3518 // for debug
3519 // flags |= (UInt32)1 << kTimePrec_Win;
3520 // flags |= (UInt32)1 << kTimePrec_1ns;
3521 }
3522 }
3523 else
3524 {
3525 // if (is_for_MethodChanging) return;
3526 }
3527
3528 SetItemText(IDT_COMPRESS_TIME_INFO, s);
3529 }
3530
3531 m_Prec.ResetContent();
3532 _auto_Prec = defaultPrec;
3533
3534 unsigned selectedPrec = defaultPrec;
3535 {
3536 // if (TimePrec >= kTimePrec_Win && TimePrec <= kTimePrec_DOS)
3537 if ((Int32)TimePrec >= 0)
3538 selectedPrec = TimePrec;
3539 }
3540
3541 int curSel = -1;
3542 int defaultPrecIndex = -1;
3543 for (unsigned prec = 0;
3544 // prec <= k_PropVar_TimePrec_HighPrec;
3545 prec <= k_PropVar_TimePrec_1ns;
3546 prec++)
3547 {
3548 if (((flags >> prec) & 1) == 0)
3549 continue;
3550 const bool isDefault = (defaultPrec == prec);
3551 const int index = AddPrec(prec, isDefault);
3552 if (isDefault)
3553 defaultPrecIndex = index;
3554 if (selectedPrec == prec)
3555 curSel = index;
3556 }
3557
3558 if (curSel < 0 && selectedPrec > kTimePrec_DOS)
3559 curSel = AddPrec(selectedPrec, false); // isDefault
3560 if (curSel < 0)
3561 curSel = defaultPrecIndex;
3562 if (curSel >= 0)
3563 m_Prec.SetCurSel(curSel);
3564
3565 {
3566 const bool isSet = IsSet_TimePrec();
3567 const int count = m_Prec.GetCount();
3568 const bool showPrec = (count != 0);
3569 ShowItem_Bool(IDC_COMPRESS_TIME_PREC, showPrec);
3570 ShowItem_Bool(IDT_COMPRESS_TIME_PREC, showPrec);
3571 EnableItem(IDC_COMPRESS_TIME_PREC, isSet && (count > 1));
3572
3573 CheckButton(IDX_COMPRESS_PREC_SET, isSet);
3574 const bool setIsSupported = isSet || (count > 1);
3575 EnableItem(IDX_COMPRESS_PREC_SET, setIsSupported);
3576 ShowItem_Bool(IDX_COMPRESS_PREC_SET, setIsSupported);
3577 }
3578
3579 SetTimeMAC();
3580 }
3581
3582
SetTimeMAC()3583 void COptionsDialog::SetTimeMAC()
3584 {
3585 const CArcInfoEx &ai = cd->Get_ArcInfoEx();
3586
3587 const
3588 bool m_allow = ai.Flags_MTime();
3589 bool c_allow = ai.Flags_CTime();
3590 bool a_allow = ai.Flags_ATime();
3591
3592 if (ai.Is_Tar())
3593 {
3594 const int methodID = cd->GetMethodID();
3595 c_allow = false;
3596 a_allow = false;
3597 if (methodID == kPosix)
3598 {
3599 // c_allow = true; // do we need it as change time ?
3600 a_allow = true;
3601 }
3602 }
3603
3604 if (ai.Is_Zip())
3605 {
3606 // const int methodID = GetMethodID();
3607 UInt32 prec = GetPrec();
3608 if (prec == (UInt32)(Int32)-1)
3609 prec = _auto_Prec;
3610 if (prec != kTimePrec_Win)
3611 {
3612 c_allow = false;
3613 a_allow = false;
3614 }
3615 }
3616
3617
3618 /*
3619 MTime.DefaultVal = true;
3620 CTime.DefaultVal = false;
3621 ATime.DefaultVal = false;
3622 */
3623
3624 MTime.DefaultVal = ai.Flags_MTime_Default();
3625 CTime.DefaultVal = ai.Flags_CTime_Default();
3626 ATime.DefaultVal = ai.Flags_ATime_Default();
3627
3628 ZTime.DefaultVal = false;
3629
3630 const NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
3631
3632 CheckButton_BoolBox (m_allow, fo.MTime, MTime );
3633 CheckButton_BoolBox (c_allow, fo.CTime, CTime );
3634 CheckButton_BoolBox (a_allow, fo.ATime, ATime );
3635 CheckButton_BoolBox (true, fo.SetArcMTime, ZTime);
3636
3637 if (m_allow && !fo.MTime.Def)
3638 {
3639 const bool isSingleFile = ai.Flags_KeepName();
3640 if (!isSingleFile)
3641 {
3642 // we can hide changing checkboxes for MTime here:
3643 ShowItem_Bool (MTime.Set_Id, false);
3644 EnableItem (MTime.Id, false);
3645 }
3646 }
3647 // On_CheckBoxSet_Prec_Clicked();
3648 // const bool isSingleFile = ai.Flags_KeepName();
3649 // mtime for Gz can be
3650 }
3651
3652
3653
On_CheckBoxSet_Prec_Clicked()3654 void COptionsDialog::On_CheckBoxSet_Prec_Clicked()
3655 {
3656 const bool isSet = IsButtonCheckedBool(IDX_COMPRESS_PREC_SET);
3657 if (!isSet)
3658 {
3659 // We save current MAC boxes to memory before SetPrec()
3660 Store_TimeBoxes();
3661 Reset_TimePrec();
3662 SetPrec();
3663 }
3664 EnableItem(IDC_COMPRESS_TIME_PREC, isSet);
3665 }
3666
On_CheckBoxSet_Clicked(const CBoolBox & bb)3667 void COptionsDialog::On_CheckBoxSet_Clicked(const CBoolBox &bb)
3668 {
3669 const bool isSet = IsButtonCheckedBool(bb.Set_Id);
3670 if (!isSet)
3671 CheckButton(bb.Id, bb.DefaultVal);
3672 EnableItem(bb.Id, isSet);
3673 }
3674
3675
3676
3677
3678 #ifdef Z7_LANG
3679 static const UInt32 kLangIDs_Options[] =
3680 {
3681 IDX_COMPRESS_NT_SYM_LINKS,
3682 IDX_COMPRESS_NT_HARD_LINKS,
3683 IDX_COMPRESS_NT_ALT_STREAMS,
3684 IDX_COMPRESS_NT_SECUR,
3685
3686 IDG_COMPRESS_TIME,
3687 IDT_COMPRESS_TIME_PREC,
3688 IDX_COMPRESS_MTIME,
3689 IDX_COMPRESS_CTIME,
3690 IDX_COMPRESS_ATIME,
3691 IDX_COMPRESS_ZTIME,
3692 IDX_COMPRESS_PRESERVE_ATIME
3693 };
3694 #endif
3695
3696
OnInit()3697 bool COptionsDialog::OnInit()
3698 {
3699 #ifdef Z7_LANG
3700 LangSetWindowText(*this, IDB_COMPRESS_OPTIONS); // IDS_OPTIONS
3701 LangSetDlgItems(*this, kLangIDs_Options, Z7_ARRAY_SIZE(kLangIDs_Options));
3702 // LangSetDlgItemText(*this, IDB_COMPRESS_TIME_DEFAULT, IDB_COMPRESS_TIME_DEFAULT);
3703 // LangSetDlgItemText(*this, IDX_COMPRESS_TIME_DEFAULT, IDX_COMPRESS_TIME_DEFAULT);
3704 #endif
3705
3706 LangString(IDS_COMPRESS_SEC, SecString);
3707 if (SecString.IsEmpty())
3708 SecString = "sec";
3709 LangString(IDS_COMPRESS_NS, NsString);
3710 if (NsString.IsEmpty())
3711 NsString = "ns";
3712
3713 {
3714 // const CArcInfoEx &ai = cd->Get_ArcInfoEx();
3715
3716 ShowItem_Bool ( IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks.Supported);
3717 ShowItem_Bool ( IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks.Supported);
3718 ShowItem_Bool ( IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams.Supported);
3719 ShowItem_Bool ( IDX_COMPRESS_NT_SECUR, cd->NtSecurity.Supported);
3720
3721 ShowItem_Bool ( IDG_COMPRESS_NTFS,
3722 cd->SymLinks.Supported
3723 || cd->HardLinks.Supported
3724 || cd->AltStreams.Supported
3725 || cd->NtSecurity.Supported);
3726 }
3727
3728 /* we read property from two sources:
3729 1) command line : (Info)
3730 2) registry : (m_RegistryInfo)
3731 (Info) has priority, if both are no defined */
3732
3733 CheckButton_Bool1 ( IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks);
3734 CheckButton_Bool1 ( IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks);
3735 CheckButton_Bool1 ( IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams);
3736 CheckButton_Bool1 ( IDX_COMPRESS_NT_SECUR, cd->NtSecurity);
3737
3738 CheckButton_Bool1 (IDX_COMPRESS_PRESERVE_ATIME, cd->PreserveATime);
3739
3740 m_Prec.Attach (GetItem(IDC_COMPRESS_TIME_PREC));
3741
3742 MTime.SetIDs ( IDX_COMPRESS_MTIME, IDX_COMPRESS_MTIME_SET);
3743 CTime.SetIDs ( IDX_COMPRESS_CTIME, IDX_COMPRESS_CTIME_SET);
3744 ATime.SetIDs ( IDX_COMPRESS_ATIME, IDX_COMPRESS_ATIME_SET);
3745 ZTime.SetIDs ( IDX_COMPRESS_ZTIME, IDX_COMPRESS_ZTIME_SET);
3746
3747 {
3748 const NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
3749 TimePrec = fo.TimePrec;
3750 MTime.BoolPair = fo.MTime;
3751 CTime.BoolPair = fo.CTime;
3752 ATime.BoolPair = fo.ATime;
3753 ZTime.BoolPair = fo.SetArcMTime;
3754 }
3755
3756 SetPrec();
3757
3758 NormalizePosition();
3759
3760 return CModalDialog::OnInit();
3761 }
3762
3763
OnCommand(unsigned code,unsigned itemID,LPARAM lParam)3764 bool COptionsDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam)
3765 {
3766 if (code == CBN_SELCHANGE)
3767 {
3768 switch (itemID)
3769 {
3770 case IDC_COMPRESS_TIME_PREC:
3771 {
3772 Store_TimeBoxes();
3773 SetTimeMAC(); // for zip/tar
3774 return true;
3775 }
3776 }
3777 }
3778 return CModalDialog::OnCommand(code, itemID, lParam);
3779 }
3780
3781
OnButtonClicked(unsigned buttonID,HWND buttonHWND)3782 bool COptionsDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
3783 {
3784 switch (buttonID)
3785 {
3786 case IDX_COMPRESS_PREC_SET: { On_CheckBoxSet_Prec_Clicked(); return true; }
3787 case IDX_COMPRESS_MTIME_SET: { On_CheckBoxSet_Clicked (MTime); return true; }
3788 case IDX_COMPRESS_CTIME_SET: { On_CheckBoxSet_Clicked (CTime); return true; }
3789 case IDX_COMPRESS_ATIME_SET: { On_CheckBoxSet_Clicked (ATime); return true; }
3790 case IDX_COMPRESS_ZTIME_SET: { On_CheckBoxSet_Clicked (ZTime); return true; }
3791 }
3792 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
3793 }
3794
3795
OnOK()3796 void COptionsDialog::OnOK()
3797 {
3798 GetButton_Bool1 (IDX_COMPRESS_NT_SYM_LINKS, cd->SymLinks);
3799 GetButton_Bool1 (IDX_COMPRESS_NT_HARD_LINKS, cd->HardLinks);
3800 GetButton_Bool1 (IDX_COMPRESS_NT_ALT_STREAMS, cd->AltStreams);
3801 GetButton_Bool1 (IDX_COMPRESS_NT_SECUR, cd->NtSecurity);
3802 GetButton_Bool1 (IDX_COMPRESS_PRESERVE_ATIME, cd->PreserveATime);
3803
3804 Store_TimeBoxes();
3805 {
3806 NCompression::CFormatOptions &fo = cd->Get_FormatOptions();
3807 fo.TimePrec = TimePrec;
3808 fo.MTime = MTime.BoolPair;
3809 fo.CTime = CTime.BoolPair;
3810 fo.ATime = ATime.BoolPair;
3811 fo.SetArcMTime = ZTime.BoolPair;
3812 }
3813
3814 CModalDialog::OnOK();
3815 }
3816
OnHelp()3817 void COptionsDialog::OnHelp()
3818 {
3819 ShowHelpWindow(kHelpTopic_Options);
3820 }
3821