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