aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/UI/FileManager
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/7zip/UI/FileManager
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-21.07.tar.gz
7zip-21.07.tar.bz2
7zip-21.07.zip
'21.07'21.07
Diffstat (limited to 'CPP/7zip/UI/FileManager')
-rw-r--r--CPP/7zip/UI/FileManager/7zFM.exe.manifest20
-rw-r--r--CPP/7zip/UI/FileManager/7zipLogo.icobin0 -> 9150 bytes
-rw-r--r--CPP/7zip/UI/FileManager/AboutDialog.cpp77
-rw-r--r--CPP/7zip/UI/FileManager/AboutDialog.h19
-rw-r--r--CPP/7zip/UI/FileManager/AboutDialog.rc26
-rw-r--r--CPP/7zip/UI/FileManager/AboutDialogRes.h8
-rw-r--r--CPP/7zip/UI/FileManager/Add.bmpbin0 -> 982 bytes
-rw-r--r--CPP/7zip/UI/FileManager/Add2.bmpbin0 -> 406 bytes
-rw-r--r--CPP/7zip/UI/FileManager/AltStreamsFolder.cpp839
-rw-r--r--CPP/7zip/UI/FileManager/AltStreamsFolder.h100
-rw-r--r--CPP/7zip/UI/FileManager/App.cpp998
-rw-r--r--CPP/7zip/UI/FileManager/App.h378
-rw-r--r--CPP/7zip/UI/FileManager/AppState.h95
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.cpp1025
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.h21
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialog.rc25
-rw-r--r--CPP/7zip/UI/FileManager/BrowseDialogRes.h9
-rw-r--r--CPP/7zip/UI/FileManager/ClassDefs.cpp12
-rw-r--r--CPP/7zip/UI/FileManager/ComboDialog.cpp64
-rw-r--r--CPP/7zip/UI/FileManager/ComboDialog.h28
-rw-r--r--CPP/7zip/UI/FileManager/ComboDialog.rc16
-rw-r--r--CPP/7zip/UI/FileManager/ComboDialogRes.h4
-rw-r--r--CPP/7zip/UI/FileManager/Copy.bmpbin0 -> 982 bytes
-rw-r--r--CPP/7zip/UI/FileManager/Copy2.bmpbin0 -> 406 bytes
-rw-r--r--CPP/7zip/UI/FileManager/CopyDialog.cpp106
-rw-r--r--CPP/7zip/UI/FileManager/CopyDialog.h31
-rw-r--r--CPP/7zip/UI/FileManager/CopyDialog.rc20
-rw-r--r--CPP/7zip/UI/FileManager/CopyDialogRes.h8
-rw-r--r--CPP/7zip/UI/FileManager/Delete.bmpbin0 -> 982 bytes
-rw-r--r--CPP/7zip/UI/FileManager/Delete2.bmpbin0 -> 406 bytes
-rw-r--r--CPP/7zip/UI/FileManager/DialogSize.h16
-rw-r--r--CPP/7zip/UI/FileManager/EditDialog.cpp57
-rw-r--r--CPP/7zip/UI/FileManager/EditDialog.h25
-rw-r--r--CPP/7zip/UI/FileManager/EditDialog.rc15
-rw-r--r--CPP/7zip/UI/FileManager/EditDialogRes.h2
-rw-r--r--CPP/7zip/UI/FileManager/EditPage.cpp147
-rw-r--r--CPP/7zip/UI/FileManager/EditPage.h30
-rw-r--r--CPP/7zip/UI/FileManager/EditPage.rc19
-rw-r--r--CPP/7zip/UI/FileManager/EditPage2.rc14
-rw-r--r--CPP/7zip/UI/FileManager/EditPageRes.h15
-rw-r--r--CPP/7zip/UI/FileManager/EnumFormatEtc.cpp108
-rw-r--r--CPP/7zip/UI/FileManager/EnumFormatEtc.h10
-rw-r--r--CPP/7zip/UI/FileManager/Extract.bmpbin0 -> 982 bytes
-rw-r--r--CPP/7zip/UI/FileManager/Extract2.bmpbin0 -> 406 bytes
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.cpp1049
-rw-r--r--CPP/7zip/UI/FileManager/ExtractCallback.h327
-rw-r--r--CPP/7zip/UI/FileManager/FM.cpp1093
-rw-r--r--CPP/7zip/UI/FileManager/FM.dsp1643
-rw-r--r--CPP/7zip/UI/FileManager/FM.dsw29
-rw-r--r--CPP/7zip/UI/FileManager/FM.icobin0 -> 4846 bytes
-rw-r--r--CPP/7zip/UI/FileManager/FM.mak100
-rw-r--r--CPP/7zip/UI/FileManager/FSDrives.cpp494
-rw-r--r--CPP/7zip/UI/FileManager/FSDrives.h59
-rw-r--r--CPP/7zip/UI/FileManager/FSFolder.cpp1107
-rw-r--r--CPP/7zip/UI/FileManager/FSFolder.h215
-rw-r--r--CPP/7zip/UI/FileManager/FSFolderCopy.cpp673
-rw-r--r--CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp357
-rw-r--r--CPP/7zip/UI/FileManager/FileFolderPluginOpen.h27
-rw-r--r--CPP/7zip/UI/FileManager/FilePlugins.cpp69
-rw-r--r--CPP/7zip/UI/FileManager/FilePlugins.h33
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPage.cpp166
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPage.h32
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPage.rc23
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPage2.rc16
-rw-r--r--CPP/7zip/UI/FileManager/FoldersPageRes.h12
-rw-r--r--CPP/7zip/UI/FileManager/FormatUtils.cpp28
-rw-r--r--CPP/7zip/UI/FileManager/FormatUtils.h14
-rw-r--r--CPP/7zip/UI/FileManager/HelpUtils.cpp32
-rw-r--r--CPP/7zip/UI/FileManager/HelpUtils.h10
-rw-r--r--CPP/7zip/UI/FileManager/IFolder.h218
-rw-r--r--CPP/7zip/UI/FileManager/Info.bmpbin0 -> 982 bytes
-rw-r--r--CPP/7zip/UI/FileManager/Info2.bmpbin0 -> 406 bytes
-rw-r--r--CPP/7zip/UI/FileManager/LangPage.cpp120
-rw-r--r--CPP/7zip/UI/FileManager/LangPage.h25
-rw-r--r--CPP/7zip/UI/FileManager/LangPage.rc37
-rw-r--r--CPP/7zip/UI/FileManager/LangPageRes.h8
-rw-r--r--CPP/7zip/UI/FileManager/LangUtils.cpp293
-rw-r--r--CPP/7zip/UI/FileManager/LangUtils.h40
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.cpp399
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.h34
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialog.rc38
-rw-r--r--CPP/7zip/UI/FileManager/LinkDialogRes.h22
-rw-r--r--CPP/7zip/UI/FileManager/ListViewDialog.cpp321
-rw-r--r--CPP/7zip/UI/FileManager/ListViewDialog.h46
-rw-r--r--CPP/7zip/UI/FileManager/ListViewDialog.rc14
-rw-r--r--CPP/7zip/UI/FileManager/ListViewDialogRes.h2
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.cpp362
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.h52
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage.rc24
-rw-r--r--CPP/7zip/UI/FileManager/MenuPage2.rc17
-rw-r--r--CPP/7zip/UI/FileManager/MenuPageRes.h11
-rw-r--r--CPP/7zip/UI/FileManager/MessagesDialog.cpp76
-rw-r--r--CPP/7zip/UI/FileManager/MessagesDialog.h25
-rw-r--r--CPP/7zip/UI/FileManager/MessagesDialog.rc14
-rw-r--r--CPP/7zip/UI/FileManager/MessagesDialogRes.h3
-rw-r--r--CPP/7zip/UI/FileManager/Move.bmpbin0 -> 982 bytes
-rw-r--r--CPP/7zip/UI/FileManager/Move2.bmpbin0 -> 406 bytes
-rw-r--r--CPP/7zip/UI/FileManager/MyCom2.h47
-rw-r--r--CPP/7zip/UI/FileManager/MyLoadMenu.cpp833
-rw-r--r--CPP/7zip/UI/FileManager/MyLoadMenu.h40
-rw-r--r--CPP/7zip/UI/FileManager/MyWindowsNew.h76
-rw-r--r--CPP/7zip/UI/FileManager/NetFolder.cpp281
-rw-r--r--CPP/7zip/UI/FileManager/NetFolder.h40
-rw-r--r--CPP/7zip/UI/FileManager/OpenCallback.cpp129
-rw-r--r--CPP/7zip/UI/FileManager/OpenCallback.h96
-rw-r--r--CPP/7zip/UI/FileManager/OptionsDialog.cpp87
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.cpp138
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.h79
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialog.rc91
-rw-r--r--CPP/7zip/UI/FileManager/OverwriteDialogRes.h17
-rw-r--r--CPP/7zip/UI/FileManager/Panel.cpp1113
-rw-r--r--CPP/7zip/UI/FileManager/Panel.h926
-rw-r--r--CPP/7zip/UI/FileManager/PanelCopy.cpp410
-rw-r--r--CPP/7zip/UI/FileManager/PanelCrc.cpp421
-rw-r--r--CPP/7zip/UI/FileManager/PanelDrag.cpp956
-rw-r--r--CPP/7zip/UI/FileManager/PanelFolderChange.cpp879
-rw-r--r--CPP/7zip/UI/FileManager/PanelItemOpen.cpp1874
-rw-r--r--CPP/7zip/UI/FileManager/PanelItems.cpp1306
-rw-r--r--CPP/7zip/UI/FileManager/PanelKey.cpp347
-rw-r--r--CPP/7zip/UI/FileManager/PanelListNotify.cpp860
-rw-r--r--CPP/7zip/UI/FileManager/PanelMenu.cpp1153
-rw-r--r--CPP/7zip/UI/FileManager/PanelOperations.cpp526
-rw-r--r--CPP/7zip/UI/FileManager/PanelSelect.cpp315
-rw-r--r--CPP/7zip/UI/FileManager/PanelSort.cpp269
-rw-r--r--CPP/7zip/UI/FileManager/PanelSplitFile.cpp562
-rw-r--r--CPP/7zip/UI/FileManager/PasswordDialog.cpp58
-rw-r--r--CPP/7zip/UI/FileManager/PasswordDialog.h28
-rw-r--r--CPP/7zip/UI/FileManager/PasswordDialog.rc14
-rw-r--r--CPP/7zip/UI/FileManager/PasswordDialogRes.h5
-rw-r--r--CPP/7zip/UI/FileManager/PluginInterface.h31
-rw-r--r--CPP/7zip/UI/FileManager/PluginLoader.h28
-rw-r--r--CPP/7zip/UI/FileManager/ProgramLocation.cpp3
-rw-r--r--CPP/7zip/UI/FileManager/ProgramLocation.h6
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.cpp199
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.h170
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog.rc12
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.cpp1460
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.h357
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2.rc40
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2Res.h49
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialog2a.rc85
-rw-r--r--CPP/7zip/UI/FileManager/ProgressDialogRes.h3
-rw-r--r--CPP/7zip/UI/FileManager/PropertyName.cpp23
-rw-r--r--CPP/7zip/UI/FileManager/PropertyName.h10
-rw-r--r--CPP/7zip/UI/FileManager/PropertyName.rc100
-rw-r--r--CPP/7zip/UI/FileManager/PropertyNameRes.h95
-rw-r--r--CPP/7zip/UI/FileManager/RegistryAssociations.cpp167
-rw-r--r--CPP/7zip/UI/FileManager/RegistryAssociations.h31
-rw-r--r--CPP/7zip/UI/FileManager/RegistryPlugins.cpp139
-rw-r--r--CPP/7zip/UI/FileManager/RegistryPlugins.h32
-rw-r--r--CPP/7zip/UI/FileManager/RegistryUtils.cpp191
-rw-r--r--CPP/7zip/UI/FileManager/RegistryUtils.h50
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.cpp318
-rw-r--r--CPP/7zip/UI/FileManager/RootFolder.h27
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage.cpp350
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage.h33
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage.rc22
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPage2.rc19
-rw-r--r--CPP/7zip/UI/FileManager/SettingsPageRes.h17
-rw-r--r--CPP/7zip/UI/FileManager/SplitDialog.cpp116
-rw-r--r--CPP/7zip/UI/FileManager/SplitDialog.h28
-rw-r--r--CPP/7zip/UI/FileManager/SplitDialog.rc16
-rw-r--r--CPP/7zip/UI/FileManager/SplitDialogRes.h8
-rw-r--r--CPP/7zip/UI/FileManager/SplitUtils.cpp96
-rw-r--r--CPP/7zip/UI/FileManager/SplitUtils.h15
-rw-r--r--CPP/7zip/UI/FileManager/StdAfx.cpp3
-rw-r--r--CPP/7zip/UI/FileManager/StdAfx.h21
-rw-r--r--CPP/7zip/UI/FileManager/StringUtils.cpp65
-rw-r--r--CPP/7zip/UI/FileManager/StringUtils.h13
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.cpp255
-rw-r--r--CPP/7zip/UI/FileManager/SysIconUtils.h62
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.cpp464
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.h126
-rw-r--r--CPP/7zip/UI/FileManager/SystemPage.rc43
-rw-r--r--CPP/7zip/UI/FileManager/SystemPageRes.h9
-rw-r--r--CPP/7zip/UI/FileManager/Test.bmpbin0 -> 982 bytes
-rw-r--r--CPP/7zip/UI/FileManager/Test2.bmpbin0 -> 406 bytes
-rw-r--r--CPP/7zip/UI/FileManager/TextPairs.cpp190
-rw-r--r--CPP/7zip/UI/FileManager/TextPairs.h32
-rw-r--r--CPP/7zip/UI/FileManager/UpdateCallback100.cpp124
-rw-r--r--CPP/7zip/UI/FileManager/UpdateCallback100.h52
-rw-r--r--CPP/7zip/UI/FileManager/VerCtrl.cpp428
-rw-r--r--CPP/7zip/UI/FileManager/ViewSettings.cpp313
-rw-r--r--CPP/7zip/UI/FileManager/ViewSettings.h115
-rw-r--r--CPP/7zip/UI/FileManager/makefile107
-rw-r--r--CPP/7zip/UI/FileManager/resource.h182
-rw-r--r--CPP/7zip/UI/FileManager/resource.rc268
-rw-r--r--CPP/7zip/UI/FileManager/resourceGui.h15
-rw-r--r--CPP/7zip/UI/FileManager/resourceGui.rc19
189 files changed, 35424 insertions, 0 deletions
diff --git a/CPP/7zip/UI/FileManager/7zFM.exe.manifest b/CPP/7zip/UI/FileManager/7zFM.exe.manifest
new file mode 100644
index 0000000..6a13c92
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/7zFM.exe.manifest
@@ -0,0 +1,20 @@
1<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
3 <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="7-Zip.7-Zip.7zFM" type="win32"/>
4 <description>7-Zip File Manager.</description>
5 <dependency>
6 <dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/></dependentAssembly>
7 </dependency>
8<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application>
9<!-- Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
10<!-- Win 7 --> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
11<!-- Win 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
12<!-- Win 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
13<!-- Win 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
14</application></compatibility>
15 <asmv3:application>
16 <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
17 <dpiAware>true</dpiAware>
18 </asmv3:windowsSettings>
19 </asmv3:application>
20</assembly>
diff --git a/CPP/7zip/UI/FileManager/7zipLogo.ico b/CPP/7zip/UI/FileManager/7zipLogo.ico
new file mode 100644
index 0000000..973241c
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/7zipLogo.ico
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.cpp b/CPP/7zip/UI/FileManager/AboutDialog.cpp
new file mode 100644
index 0000000..082902e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AboutDialog.cpp
@@ -0,0 +1,77 @@
1// AboutDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../../C/CpuArch.h"
6
7#include "../../MyVersion.h"
8
9#include "../Common/LoadCodecs.h"
10
11#include "AboutDialog.h"
12#include "PropertyNameRes.h"
13
14#include "HelpUtils.h"
15#include "LangUtils.h"
16
17static const UInt32 kLangIDs[] =
18{
19 IDT_ABOUT_INFO
20};
21
22#define kHomePageURL TEXT("https://www.7-zip.org/")
23#define kHelpTopic "start.htm"
24
25#define LLL_(quote) L##quote
26#define LLL(quote) LLL_(quote)
27
28extern CCodecs *g_CodecsObj;
29
30bool CAboutDialog::OnInit()
31{
32 #ifdef EXTERNAL_CODECS
33 if (g_CodecsObj)
34 {
35 UString s;
36 g_CodecsObj->GetCodecsErrorMessage(s);
37 if (!s.IsEmpty())
38 MessageBoxW(GetParent(), s, L"7-Zip", MB_ICONERROR);
39 }
40 #endif
41
42 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
43 SetItemText(IDT_ABOUT_VERSION, UString("7-Zip " MY_VERSION_CPU));
44 SetItemText(IDT_ABOUT_DATE, LLL(MY_DATE));
45
46 LangSetWindowText(*this, IDD_ABOUT);
47 NormalizePosition();
48 return CModalDialog::OnInit();
49}
50
51void CAboutDialog::OnHelp()
52{
53 ShowHelpWindow(kHelpTopic);
54}
55
56bool CAboutDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
57{
58 LPCTSTR url;
59 switch (buttonID)
60 {
61 case IDB_ABOUT_HOMEPAGE: url = kHomePageURL; break;
62 default:
63 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
64 }
65
66 #ifdef UNDER_CE
67 SHELLEXECUTEINFO s;
68 memset(&s, 0, sizeof(s));
69 s.cbSize = sizeof(s);
70 s.lpFile = url;
71 ::ShellExecuteEx(&s);
72 #else
73 ::ShellExecute(NULL, NULL, url, NULL, NULL, SW_SHOWNORMAL);
74 #endif
75
76 return true;
77}
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.h b/CPP/7zip/UI/FileManager/AboutDialog.h
new file mode 100644
index 0000000..39fd3ba
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AboutDialog.h
@@ -0,0 +1,19 @@
1// AboutDialog.h
2
3#ifndef __ABOUT_DIALOG_H
4#define __ABOUT_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7
8#include "AboutDialogRes.h"
9
10class CAboutDialog: public NWindows::NControl::CModalDialog
11{
12public:
13 virtual bool OnInit();
14 virtual void OnHelp();
15 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
16 INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_ABOUT, wndParent); }
17};
18
19#endif
diff --git a/CPP/7zip/UI/FileManager/AboutDialog.rc b/CPP/7zip/UI/FileManager/AboutDialog.rc
new file mode 100644
index 0000000..b235df0
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AboutDialog.rc
@@ -0,0 +1,26 @@
1#include "AboutDialogRes.h"
2#include "../../GuiCommon.rc"
3#include "../../MyVersion.h"
4
5#define xc 144
6#define yc 144
7
8#define y 93
9
10IDI_LOGO ICON "../../UI/FileManager/7zipLogo.ico"
11
12#ifndef SS_REALSIZEIMAGE
13#define SS_REALSIZEIMAGE 0x800
14#endif
15
16IDD_ABOUT DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
17CAPTION "About 7-Zip"
18{
19 DEFPUSHBUTTON "OK", IDOK, bx1, by, bxs, bys
20 PUSHBUTTON "www.7-zip.org", IDB_ABOUT_HOMEPAGE, bx2, by, bxs, bys
21 ICON IDI_LOGO, -1, m, m, 32, 32, SS_REALSIZEIMAGE
22 LTEXT "", IDT_ABOUT_VERSION, m, 54, xc, 8
23 LTEXT "", IDT_ABOUT_DATE, m, 67, xc, 8
24 LTEXT MY_COPYRIGHT, -1, m, 80, xc, 8
25 LTEXT "7-Zip is free software", IDT_ABOUT_INFO, m, y, xc, (by - y - 1)
26}
diff --git a/CPP/7zip/UI/FileManager/AboutDialogRes.h b/CPP/7zip/UI/FileManager/AboutDialogRes.h
new file mode 100644
index 0000000..b416558
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AboutDialogRes.h
@@ -0,0 +1,8 @@
1#define IDD_ABOUT 2900
2
3#define IDT_ABOUT_INFO 2901
4
5#define IDI_LOGO 100
6#define IDT_ABOUT_VERSION 101
7#define IDT_ABOUT_DATE 102
8#define IDB_ABOUT_HOMEPAGE 110
diff --git a/CPP/7zip/UI/FileManager/Add.bmp b/CPP/7zip/UI/FileManager/Add.bmp
new file mode 100644
index 0000000..a8577fc
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Add.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Add2.bmp b/CPP/7zip/UI/FileManager/Add2.bmp
new file mode 100644
index 0000000..252fc25
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Add2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
new file mode 100644
index 0000000..e1c99d3
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.cpp
@@ -0,0 +1,839 @@
1// AltStreamsFolder.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/ComTry.h"
6#include "../../../Common/StringConvert.h"
7#include "../../../Common/Wildcard.h"
8
9#include "../../../Windows/ErrorMsg.h"
10#include "../../../Windows/FileDir.h"
11#include "../../../Windows/FileIO.h"
12#include "../../../Windows/FileName.h"
13#include "../../../Windows/PropVariant.h"
14
15#include "../Common/ExtractingFilePath.h"
16
17#include "../Agent/IFolderArchive.h"
18
19#include "AltStreamsFolder.h"
20#include "FSDrives.h"
21#include "FSFolder.h"
22
23#include "SysIconUtils.h"
24
25using namespace NWindows;
26using namespace NFile;
27using namespace NFind;
28using namespace NDir;
29using namespace NName;
30
31#ifndef USE_UNICODE_FSTRING
32int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2);
33#endif
34
35#ifndef UNDER_CE
36
37namespace NFsFolder
38{
39bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size);
40}
41
42#endif
43
44namespace NAltStreamsFolder {
45
46static const Byte kProps[] =
47{
48 kpidName,
49 kpidSize,
50 kpidPackSize
51};
52
53static unsigned GetFsParentPrefixSize(const FString &path)
54{
55 if (IsNetworkShareRootPath(path))
56 return 0;
57 unsigned prefixSize = GetRootPrefixSize(path);
58 if (prefixSize == 0 || prefixSize >= path.Len())
59 return 0;
60 FString parentPath = path;
61 int pos = parentPath.ReverseFind_PathSepar();
62 if (pos < 0)
63 return 0;
64 if (pos == (int)parentPath.Len() - 1)
65 {
66 parentPath.DeleteBack();
67 pos = parentPath.ReverseFind_PathSepar();
68 if (pos < 0)
69 return 0;
70 }
71 if ((unsigned)pos + 1 < prefixSize)
72 return 0;
73 return pos + 1;
74}
75
76HRESULT CAltStreamsFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
77{
78 // _parentFolder = parentFolder;
79 if (path.Back() != ':')
80 return E_FAIL;
81
82 _pathPrefix = path;
83 _pathBaseFile = path;
84 _pathBaseFile.DeleteBack();
85
86 {
87 CFileInfo fi;
88 if (!fi.Find(_pathBaseFile))
89 return GetLastError_noZero_HRESULT();
90 }
91
92 unsigned prefixSize = GetFsParentPrefixSize(_pathBaseFile);
93 if (prefixSize == 0)
94 return S_OK;
95 FString parentPath = _pathBaseFile;
96 parentPath.DeleteFrom(prefixSize);
97
98 _findChangeNotification.FindFirst(parentPath, false,
99 FILE_NOTIFY_CHANGE_FILE_NAME
100 | FILE_NOTIFY_CHANGE_DIR_NAME
101 | FILE_NOTIFY_CHANGE_ATTRIBUTES
102 | FILE_NOTIFY_CHANGE_SIZE
103 | FILE_NOTIFY_CHANGE_LAST_WRITE
104 /*
105 | FILE_NOTIFY_CHANGE_LAST_ACCESS
106 | FILE_NOTIFY_CHANGE_CREATION
107 | FILE_NOTIFY_CHANGE_SECURITY
108 */
109 );
110 /*
111 if (_findChangeNotification.IsHandleAllocated())
112 return S_OK;
113 return GetLastError();
114 */
115 return S_OK;
116}
117
118STDMETHODIMP CAltStreamsFolder::LoadItems()
119{
120 Int32 dummy;
121 WasChanged(&dummy);
122 Clear();
123
124 CStreamEnumerator enumerator(_pathBaseFile);
125
126 CStreamInfo si;
127 for (;;)
128 {
129 bool found;
130 if (!enumerator.Next(si, found))
131 {
132 // if (GetLastError() == ERROR_ACCESS_DENIED)
133 // break;
134 // return E_FAIL;
135 break;
136 }
137 if (!found)
138 break;
139 if (si.IsMainStream())
140 continue;
141 CAltStream ss;
142 ss.Name = si.GetReducedName();
143 if (!ss.Name.IsEmpty() && ss.Name[0] == ':')
144 ss.Name.Delete(0);
145
146 ss.Size = si.Size;
147 ss.PackSize_Defined = false;
148 ss.PackSize = si.Size;
149 Streams.Add(ss);
150 }
151
152 return S_OK;
153}
154
155STDMETHODIMP CAltStreamsFolder::GetNumberOfItems(UInt32 *numItems)
156{
157 *numItems = Streams.Size();
158 return S_OK;
159}
160
161#ifdef USE_UNICODE_FSTRING
162
163STDMETHODIMP CAltStreamsFolder::GetItemPrefix(UInt32 /* index */, const wchar_t **name, unsigned *len)
164{
165 *name = 0;
166 *len = 0;
167 return S_OK;
168}
169
170STDMETHODIMP CAltStreamsFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len)
171{
172 *name = 0;
173 *len = 0;
174 {
175 const CAltStream &ss = Streams[index];
176 *name = ss.Name;
177 *len = ss.Name.Len();
178 }
179 return S_OK;
180}
181
182STDMETHODIMP_(UInt64) CAltStreamsFolder::GetItemSize(UInt32 index)
183{
184 return Streams[index].Size;
185}
186
187#endif
188
189
190STDMETHODIMP CAltStreamsFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
191{
192 NCOM::CPropVariant prop;
193 {
194 CAltStream &ss = Streams[index];
195 switch (propID)
196 {
197 case kpidIsDir: prop = false; break;
198 case kpidIsAltStream: prop = true; break;
199 case kpidName: prop = ss.Name; break;
200 case kpidSize: prop = ss.Size; break;
201 case kpidPackSize:
202 #ifdef UNDER_CE
203 prop = ss.Size;
204 #else
205 if (!ss.PackSize_Defined)
206 {
207 ss.PackSize_Defined = true;
208 if (!NFsFolder::MyGetCompressedFileSizeW(_pathPrefix + us2fs(ss.Name), ss.PackSize))
209 ss.PackSize = ss.Size;
210 }
211 prop = ss.PackSize;
212 #endif
213 break;
214 }
215 }
216
217 prop.Detach(value);
218 return S_OK;
219}
220
221
222// returns Position of extension including '.'
223
224static inline const wchar_t *GetExtensionPtr(const UString &name)
225{
226 int dotPos = name.ReverseFind_Dot();
227 return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
228}
229
230STDMETHODIMP_(Int32) CAltStreamsFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 /* propIsRaw */)
231{
232 const CAltStream &ss1 = Streams[index1];
233 const CAltStream &ss2 = Streams[index2];
234
235 switch (propID)
236 {
237 case kpidName:
238 {
239 return CompareFileNames_ForFolderList(ss1.Name, ss2.Name);
240 // return MyStringCompareNoCase(ss1.Name, ss2.Name);
241 }
242 case kpidSize:
243 return MyCompare(ss1.Size, ss2.Size);
244 case kpidPackSize:
245 {
246 #ifdef UNDER_CE
247 return MyCompare(ss1.Size, ss2.Size);
248 #else
249 // PackSize can be undefined here
250 return MyCompare(
251 ss1.PackSize,
252 ss2.PackSize);
253 #endif
254 }
255
256 case kpidExtension:
257 return CompareFileNames_ForFolderList(
258 GetExtensionPtr(ss1.Name),
259 GetExtensionPtr(ss2.Name));
260 }
261
262 return 0;
263}
264
265STDMETHODIMP CAltStreamsFolder::BindToFolder(UInt32 /* index */, IFolderFolder **resultFolder)
266{
267 *resultFolder = 0;
268 return E_INVALIDARG;
269}
270
271STDMETHODIMP CAltStreamsFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder **resultFolder)
272{
273 *resultFolder = 0;
274 return E_INVALIDARG;
275}
276
277// static CFSTR const kSuperPrefix = FTEXT("\\\\?\\");
278
279STDMETHODIMP CAltStreamsFolder::BindToParentFolder(IFolderFolder **resultFolder)
280{
281 *resultFolder = 0;
282 /*
283 if (_parentFolder)
284 {
285 CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
286 *resultFolder = parentFolder.Detach();
287 return S_OK;
288 }
289 */
290
291 if (IsDriveRootPath_SuperAllowed(_pathBaseFile))
292 {
293 CFSDrives *drivesFolderSpec = new CFSDrives;
294 CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
295 drivesFolderSpec->Init();
296 *resultFolder = drivesFolder.Detach();
297 return S_OK;
298 }
299
300 /*
301 parentPath.DeleteFrom(pos + 1);
302
303 if (parentPath == kSuperPrefix)
304 {
305 #ifdef UNDER_CE
306 *resultFolder = 0;
307 #else
308 CFSDrives *drivesFolderSpec = new CFSDrives;
309 CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
310 drivesFolderSpec->Init(false, true);
311 *resultFolder = drivesFolder.Detach();
312 #endif
313 return S_OK;
314 }
315
316 FString parentPathReduced = parentPath.Left(pos);
317
318 #ifndef UNDER_CE
319 pos = parentPathReduced.ReverseFind_PathSepar();
320 if (pos == 1)
321 {
322 if (!IS_PATH_SEPAR_CHAR(parentPath[0]))
323 return E_FAIL;
324 CNetFolder *netFolderSpec = new CNetFolder;
325 CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
326 netFolderSpec->Init(fs2us(parentPath));
327 *resultFolder = netFolder.Detach();
328 return S_OK;
329 }
330 #endif
331
332 CFSFolder *parentFolderSpec = new CFSFolder;
333 CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
334 RINOK(parentFolderSpec->Init(parentPath, 0));
335 *resultFolder = parentFolder.Detach();
336 */
337
338 return S_OK;
339}
340
341STDMETHODIMP CAltStreamsFolder::GetNumberOfProperties(UInt32 *numProperties)
342{
343 *numProperties = ARRAY_SIZE(kProps);
344 return S_OK;
345}
346
347STDMETHODIMP CAltStreamsFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
348
349STDMETHODIMP CAltStreamsFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
350{
351 COM_TRY_BEGIN
352 NWindows::NCOM::CPropVariant prop;
353 switch (propID)
354 {
355 case kpidType: prop = "AltStreamsFolder"; break;
356 case kpidPath: prop = fs2us(_pathPrefix); break;
357 }
358 prop.Detach(value);
359 return S_OK;
360 COM_TRY_END
361}
362
363STDMETHODIMP CAltStreamsFolder::WasChanged(Int32 *wasChanged)
364{
365 bool wasChangedMain = false;
366 for (;;)
367 {
368 if (!_findChangeNotification.IsHandleAllocated())
369 {
370 *wasChanged = BoolToInt(false);
371 return S_OK;
372 }
373
374 DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
375 bool wasChangedLoc = (waitResult == WAIT_OBJECT_0);
376 if (wasChangedLoc)
377 {
378 _findChangeNotification.FindNext();
379 wasChangedMain = true;
380 }
381 else
382 break;
383 }
384 *wasChanged = BoolToInt(wasChangedMain);
385 return S_OK;
386}
387
388STDMETHODIMP CAltStreamsFolder::Clone(IFolderFolder **resultFolder)
389{
390 CAltStreamsFolder *folderSpec = new CAltStreamsFolder;
391 CMyComPtr<IFolderFolder> folderNew = folderSpec;
392 folderSpec->Init(_pathPrefix);
393 *resultFolder = folderNew.Detach();
394 return S_OK;
395}
396
397void CAltStreamsFolder::GetAbsPath(const wchar_t *name, FString &absPath)
398{
399 absPath.Empty();
400 if (!IsAbsolutePath(name))
401 absPath += _pathPrefix;
402 absPath += us2fs(name);
403}
404
405
406
407static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
408 const wchar_t *message, const FString &fileName)
409{
410 UString s = message;
411 s += " : ";
412 s += fs2us(fileName);
413 return callback->ShowMessage(s);
414}
415
416static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
417 const wchar_t *message, const FString &fileName)
418{
419 UString s = message;
420 s += " : ";
421 s += fs2us(fileName);
422 return callback->UpdateErrorMessage(s);
423}
424
425static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
426 const char *message, const FString &fileName)
427{
428 return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
429}
430
431/*
432static HRESULT SendMessageError(IFolderArchiveUpdateCallback *callback,
433 const char *message, const FString &fileName)
434{
435 return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
436}
437*/
438
439STDMETHODIMP CAltStreamsFolder::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
440{
441 return E_NOTIMPL;
442}
443
444STDMETHODIMP CAltStreamsFolder::CreateFile(const wchar_t *name, IProgress * /* progress */)
445{
446 FString absPath;
447 GetAbsPath(name, absPath);
448 NIO::COutFile outFile;
449 if (!outFile.Create(absPath, false))
450 return ::GetLastError();
451 return S_OK;
452}
453
454static DWORD Return_LastError_or_FAIL()
455{
456 DWORD errorCode = GetLastError();
457 if (errorCode == 0)
458 errorCode = (DWORD)E_FAIL;
459 return errorCode;
460}
461
462static UString GetLastErrorMessage()
463{
464 return NError::MyFormatMessage(Return_LastError_or_FAIL());
465}
466
467static HRESULT UpdateFile(NFsFolder::CCopyStateIO &state, CFSTR inPath, CFSTR outPath, IFolderArchiveUpdateCallback *callback)
468{
469 if (NFind::DoesFileOrDirExist(outPath))
470 {
471 RINOK(SendMessageError(callback, NError::MyFormatMessage(ERROR_ALREADY_EXISTS), FString(outPath)));
472 CFileInfo fi;
473 if (fi.Find(inPath))
474 {
475 if (state.TotalSize >= fi.Size)
476 state.TotalSize -= fi.Size;
477 }
478 return S_OK;
479 }
480
481 {
482 if (callback)
483 RINOK(callback->CompressOperation(fs2us(inPath)));
484 RINOK(state.MyCopyFile(inPath, outPath));
485 if (state.ErrorFileIndex >= 0)
486 {
487 if (state.ErrorMessage.IsEmpty())
488 state.ErrorMessage = GetLastErrorMessage();
489 FString errorName;
490 if (state.ErrorFileIndex == 0)
491 errorName = inPath;
492 else
493 errorName = outPath;
494 if (callback)
495 RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
496 }
497 if (callback)
498 RINOK(callback->OperationResult(0));
499 }
500
501 return S_OK;
502}
503
504STDMETHODIMP CAltStreamsFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress)
505{
506 CMyComPtr<IFolderArchiveUpdateCallback> callback;
507 if (progress)
508 {
509 RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
510 }
511
512 FString destPath = _pathPrefix + us2fs(newName);
513
514 const CAltStream &ss = Streams[index];
515
516 if (callback)
517 {
518 RINOK(callback->SetNumFiles(1));
519 RINOK(callback->SetTotal(ss.Size));
520 }
521
522 NFsFolder::CCopyStateIO state;
523 state.Progress = progress;
524 state.TotalSize = 0;
525 state.DeleteSrcFile = true;
526
527 return UpdateFile(state, _pathPrefix + us2fs(ss.Name), destPath, callback);
528}
529
530STDMETHODIMP CAltStreamsFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress)
531{
532 RINOK(progress->SetTotal(numItems));
533 for (UInt32 i = 0; i < numItems; i++)
534 {
535 const CAltStream &ss = Streams[indices[i]];
536 const FString fullPath = _pathPrefix + us2fs(ss.Name);
537 bool result = DeleteFileAlways(fullPath);
538 if (!result)
539 return Return_LastError_or_FAIL();
540 UInt64 completed = i;
541 RINOK(progress->SetCompleted(&completed));
542 }
543 return S_OK;
544}
545
546STDMETHODIMP CAltStreamsFolder::SetProperty(UInt32 /* index */, PROPID /* propID */,
547 const PROPVARIANT * /* value */, IProgress * /* progress */)
548{
549 return E_NOTIMPL;
550}
551
552STDMETHODIMP CAltStreamsFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
553{
554 const CAltStream &ss = Streams[index];
555 *iconIndex = 0;
556 int iconIndexTemp;
557 if (GetRealIconIndex(_pathPrefix + us2fs(ss.Name),
558 0 // fi.Attrib
559 , iconIndexTemp) != 0)
560 {
561 *iconIndex = iconIndexTemp;
562 return S_OK;
563 }
564 return Return_LastError_or_FAIL();
565}
566
567/*
568class CGetProp:
569 public IGetProp,
570 public CMyUnknownImp
571{
572public:
573 // const CArc *Arc;
574 // UInt32 IndexInArc;
575 UString Name; // relative path
576 UInt64 Size;
577
578 MY_UNKNOWN_IMP1(IGetProp)
579 INTERFACE_IGetProp(;)
580};
581
582STDMETHODIMP CGetProp::GetProp(PROPID propID, PROPVARIANT *value)
583{
584 if (propID == kpidName)
585 {
586 COM_TRY_BEGIN
587 NCOM::CPropVariant prop = Name;
588 prop.Detach(value);
589 return S_OK;
590 COM_TRY_END
591 }
592 if (propID == kpidSize)
593 {
594 NCOM::CPropVariant prop = Size;
595 prop.Detach(value);
596 return S_OK;
597 }
598 NCOM::CPropVariant prop;
599 prop.Detach(value);
600 return S_OK;
601}
602*/
603
604static HRESULT CopyStream(
605 NFsFolder::CCopyStateIO &state,
606 const FString &srcPath,
607 const CFileInfo &srcFileInfo,
608 const CAltStream &srcAltStream,
609 const FString &destPathSpec,
610 IFolderOperationsExtractCallback *callback)
611{
612 FString destPath = destPathSpec;
613 if (CompareFileNames(destPath, srcPath) == 0)
614 {
615 RINOK(SendMessageError(callback, "Cannot copy file onto itself", destPath));
616 return E_ABORT;
617 }
618
619 Int32 writeAskResult;
620 CMyComBSTR destPathResult;
621 RINOK(callback->AskWrite(
622 fs2us(srcPath),
623 BoolToInt(false),
624 &srcFileInfo.MTime, &srcAltStream.Size,
625 fs2us(destPath),
626 &destPathResult,
627 &writeAskResult));
628
629 if (IntToBool(writeAskResult))
630 {
631 RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
632 FString destPathNew (us2fs((LPCOLESTR)destPathResult));
633 RINOK(state.MyCopyFile(srcPath, destPathNew));
634 if (state.ErrorFileIndex >= 0)
635 {
636 if (state.ErrorMessage.IsEmpty())
637 state.ErrorMessage = GetLastErrorMessage();
638 FString errorName;
639 if (state.ErrorFileIndex == 0)
640 errorName = srcPath;
641 else
642 errorName = destPathNew;
643 RINOK(SendMessageError(callback, state.ErrorMessage, errorName));
644 return E_ABORT;
645 }
646 state.StartPos += state.CurrentSize;
647 }
648 else
649 {
650 if (state.TotalSize >= srcAltStream.Size)
651 {
652 state.TotalSize -= srcAltStream.Size;
653 RINOK(state.Progress->SetTotal(state.TotalSize));
654 }
655 }
656 return S_OK;
657}
658
659STDMETHODIMP CAltStreamsFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
660 Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
661 const wchar_t *path, IFolderOperationsExtractCallback *callback)
662{
663 if (numItems == 0)
664 return S_OK;
665
666 /*
667 CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;
668 RINOK(callback->QueryInterface(IID_IFolderExtractToStreamCallback, (void **)&ExtractToStreamCallback));
669 if (ExtractToStreamCallback)
670 {
671 Int32 useStreams = 0;
672 if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)
673 useStreams = 0;
674 if (useStreams == 0)
675 ExtractToStreamCallback.Release();
676 }
677 */
678
679 UInt64 totalSize = 0;
680 {
681 UInt32 i;
682 for (i = 0; i < numItems; i++)
683 {
684 totalSize += Streams[indices[i]].Size;
685 }
686 RINOK(callback->SetTotal(totalSize));
687 RINOK(callback->SetNumFiles(numItems));
688 }
689
690 /*
691 if (ExtractToStreamCallback)
692 {
693 CGetProp *GetProp_Spec = new CGetProp;
694 CMyComPtr<IGetProp> GetProp= GetProp_Spec;
695
696 for (UInt32 i = 0; i < numItems; i++)
697 {
698 UInt32 index = indices[i];
699 const CAltStream &ss = Streams[index];
700 GetProp_Spec->Name = ss.Name;
701 GetProp_Spec->Size = ss.Size;
702 CMyComPtr<ISequentialOutStream> outStream;
703 RINOK(ExtractToStreamCallback->GetStream7(GetProp_Spec->Name, BoolToInt(false), &outStream,
704 NArchive::NExtract::NAskMode::kExtract, GetProp)); // isDir
705 FString srcPath;
706 GetFullPath(ss, srcPath);
707 RINOK(ExtractToStreamCallback->PrepareOperation7(NArchive::NExtract::NAskMode::kExtract));
708 RINOK(ExtractToStreamCallback->SetOperationResult7(NArchive::NExtract::NOperationResult::kOK, BoolToInt(false))); // _encrypted
709 // RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback, completedSize));
710 }
711 return S_OK;
712 }
713 */
714
715 FString destPath (us2fs(path));
716 if (destPath.IsEmpty() /* && !ExtractToStreamCallback */)
717 return E_INVALIDARG;
718
719 bool isAltDest = NName::IsAltPathPrefix(destPath);
720 bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
721
722 if (isDirectPath)
723 {
724 if (numItems > 1)
725 return E_INVALIDARG;
726 }
727
728 CFileInfo fi;
729 if (!fi.Find(_pathBaseFile))
730 return GetLastError();
731
732 NFsFolder::CCopyStateIO state;
733 state.Progress = callback;
734 state.DeleteSrcFile = IntToBool(moveMode);
735 state.TotalSize = totalSize;
736
737 for (UInt32 i = 0; i < numItems; i++)
738 {
739 UInt32 index = indices[i];
740 const CAltStream &ss = Streams[index];
741 FString destPath2 = destPath;
742 if (!isDirectPath)
743 destPath2 += us2fs(Get_Correct_FsFile_Name(ss.Name));
744 FString srcPath;
745 GetFullPath(ss, srcPath);
746 RINOK(CopyStream(state, srcPath, fi, ss, destPath2, callback));
747 }
748
749 return S_OK;
750}
751
752STDMETHODIMP CAltStreamsFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
753 const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
754{
755 /*
756 if (numItems == 0)
757 return S_OK;
758
759 CMyComPtr<IFolderArchiveUpdateCallback> callback;
760 if (progress)
761 {
762 RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&callback));
763 }
764
765 if (CompareFileNames(fromFolderPath, fs2us(_pathPrefix)) == 0)
766 {
767 RINOK(SendMessageError(callback, "Cannot copy file onto itself", _pathPrefix));
768 return E_ABORT;
769 }
770
771 if (callback)
772 RINOK(callback->SetNumFiles(numItems));
773
774 UInt64 totalSize = 0;
775
776 UInt32 i;
777
778 FString path;
779 for (i = 0; i < numItems; i++)
780 {
781 path = us2fs(fromFolderPath);
782 path += us2fs(itemsPaths[i]);
783
784 CFileInfo fi;
785 if (!fi.Find(path))
786 return ::GetLastError();
787 if (fi.IsDir())
788 return E_NOTIMPL;
789 totalSize += fi.Size;
790 }
791
792 RINOK(progress->SetTotal(totalSize));
793
794 // UInt64 completedSize = 0;
795
796 NFsFolder::CCopyStateIO state;
797 state.Progress = progress;
798 state.DeleteSrcFile = IntToBool(moveMode);
799 state.TotalSize = totalSize;
800
801 // we need to clear READ-ONLY of parent before creating alt stream
802 {
803 DWORD attrib = GetFileAttrib(_pathBaseFile);
804 if (attrib != INVALID_FILE_ATTRIBUTES
805 && (attrib & FILE_ATTRIBUTE_READONLY) != 0)
806 {
807 if (!SetFileAttrib(_pathBaseFile, attrib & ~FILE_ATTRIBUTE_READONLY))
808 {
809 if (callback)
810 {
811 RINOK(SendMessageError(callback, GetLastErrorMessage(), _pathBaseFile));
812 return S_OK;
813 }
814 return Return_LastError_or_FAIL();
815 }
816 }
817 }
818
819 for (i = 0; i < numItems; i++)
820 {
821 path = us2fs(fromFolderPath);
822 path += us2fs(itemsPaths[i]);
823
824 FString destPath = _pathPrefix + us2fs(itemsPaths[i]);
825
826 RINOK(UpdateFile(state, path, destPath, callback));
827 }
828
829 return S_OK;
830 */
831 return E_NOTIMPL;
832}
833
834STDMETHODIMP CAltStreamsFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
835{
836 return E_NOTIMPL;
837}
838
839}
diff --git a/CPP/7zip/UI/FileManager/AltStreamsFolder.h b/CPP/7zip/UI/FileManager/AltStreamsFolder.h
new file mode 100644
index 0000000..ccd0a58
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AltStreamsFolder.h
@@ -0,0 +1,100 @@
1// AltStreamsFolder.h
2
3#ifndef __ALT_STREAMS_FOLDER_H
4#define __ALT_STREAMS_FOLDER_H
5
6#include "../../../Common/MyCom.h"
7
8#include "../../../Windows/FileFind.h"
9
10#include "../../Archive/IArchive.h"
11
12#include "IFolder.h"
13
14namespace NAltStreamsFolder {
15
16class CAltStreamsFolder;
17
18struct CAltStream
19{
20 UInt64 Size;
21 UInt64 PackSize;
22 bool PackSize_Defined;
23 UString Name;
24};
25
26
27class CAltStreamsFolder:
28 public IFolderFolder,
29 public IFolderCompare,
30 #ifdef USE_UNICODE_FSTRING
31 public IFolderGetItemName,
32 #endif
33 public IFolderWasChanged,
34 public IFolderOperations,
35 // public IFolderOperationsDeleteToRecycleBin,
36 public IFolderClone,
37 public IFolderGetSystemIconIndex,
38 public CMyUnknownImp
39{
40public:
41 MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
42 MY_QUERYINTERFACE_ENTRY(IFolderCompare)
43 #ifdef USE_UNICODE_FSTRING
44 MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
45 #endif
46 MY_QUERYINTERFACE_ENTRY(IFolderWasChanged)
47 // MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin)
48 MY_QUERYINTERFACE_ENTRY(IFolderOperations)
49 MY_QUERYINTERFACE_ENTRY(IFolderClone)
50 MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex)
51 MY_QUERYINTERFACE_END
52 MY_ADDREF_RELEASE
53
54
55 INTERFACE_FolderFolder(;)
56 INTERFACE_FolderOperations(;)
57
58 STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
59
60 #ifdef USE_UNICODE_FSTRING
61 INTERFACE_IFolderGetItemName(;)
62 #endif
63 STDMETHOD(WasChanged)(Int32 *wasChanged);
64 STDMETHOD(Clone)(IFolderFolder **resultFolder);
65
66 STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
67
68private:
69 FString _pathBaseFile; // folder
70 FString _pathPrefix; // folder:
71
72 CObjectVector<CAltStream> Streams;
73 // CMyComPtr<IFolderFolder> _parentFolder;
74
75 NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
76
77 HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress);
78 void GetAbsPath(const wchar_t *name, FString &absPath);
79
80public:
81 // path must be with ':' at tail
82 HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
83
84 CAltStreamsFolder() {}
85
86 void GetFullPath(const CAltStream &item, FString &path) const
87 {
88 path = _pathPrefix;
89 path += us2fs(item.Name);
90 }
91
92 void Clear()
93 {
94 Streams.Clear();
95 }
96};
97
98}
99
100#endif
diff --git a/CPP/7zip/UI/FileManager/App.cpp b/CPP/7zip/UI/FileManager/App.cpp
new file mode 100644
index 0000000..512acc5
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/App.cpp
@@ -0,0 +1,998 @@
1// App.cpp
2
3#include "StdAfx.h"
4
5#include "resource.h"
6#include "OverwriteDialogRes.h"
7
8#include "../../../Windows/FileName.h"
9#include "../../../Windows/PropVariantConv.h"
10
11/*
12#include "Windows/COM.h"
13#include "Windows/Error.h"
14#include "Windows/FileDir.h"
15
16#include "Windows/PropVariant.h"
17#include "Windows/Thread.h"
18*/
19
20#include "App.h"
21#include "CopyDialog.h"
22#include "ExtractCallback.h"
23#include "FormatUtils.h"
24#include "IFolder.h"
25#include "LangUtils.h"
26#include "MyLoadMenu.h"
27#include "RegistryUtils.h"
28#include "ViewSettings.h"
29
30#include "PropertyNameRes.h"
31
32using namespace NWindows;
33using namespace NFile;
34using namespace NDir;
35using namespace NFind;
36using namespace NName;
37
38extern DWORD g_ComCtl32Version;
39extern HINSTANCE g_hInstance;
40
41#define kTempDirPrefix FTEXT("7zE")
42
43void CPanelCallbackImp::OnTab()
44{
45 if (g_App.NumPanels != 1)
46 _app->Panels[1 - _index].SetFocusToList();
47 _app->RefreshTitle();
48}
49
50void CPanelCallbackImp::SetFocusToPath(unsigned index)
51{
52 int newPanelIndex = index;
53 if (g_App.NumPanels == 1)
54 newPanelIndex = g_App.LastFocusedPanel;
55 _app->RefreshTitle();
56 _app->Panels[newPanelIndex]._headerComboBox.SetFocus();
57 _app->Panels[newPanelIndex]._headerComboBox.ShowDropDown();
58}
59
60
61void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); }
62void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); }
63void CPanelCallbackImp::OnSetSubFolder() { _app->OnSetSubFolder(_index); }
64void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitlePanel(_index); }
65void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); }
66void CPanelCallbackImp::DragEnd() { _app->DragEnd(); }
67void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitlePanel(_index, always); }
68
69void CApp::ReloadLang()
70{
71 LangString(IDS_N_SELECTED_ITEMS, LangString_N_SELECTED_ITEMS);
72}
73
74void CApp::SetListSettings()
75{
76 CFmSettings st;
77 st.Load();
78
79 ShowSystemMenu = st.ShowSystemMenu;
80
81 DWORD extendedStyle = LVS_EX_HEADERDRAGDROP;
82 if (st.FullRow)
83 extendedStyle |= LVS_EX_FULLROWSELECT;
84 if (st.ShowGrid)
85 extendedStyle |= LVS_EX_GRIDLINES;
86
87 if (st.SingleClick)
88 {
89 extendedStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT;
90 /*
91 if (ReadUnderline())
92 extendedStyle |= LVS_EX_UNDERLINEHOT;
93 */
94 }
95
96 for (unsigned i = 0; i < kNumPanelsMax; i++)
97 {
98 CPanel &panel = Panels[i];
99 panel._mySelectMode = st.AlternativeSelection;
100 panel._showDots = st.ShowDots;
101 panel._showRealFileIcons = st.ShowRealFileIcons;
102 panel._exStyle = extendedStyle;
103
104 DWORD style = (DWORD)panel._listView.GetStyle();
105 if (st.AlternativeSelection)
106 style |= LVS_SINGLESEL;
107 else
108 style &= ~LVS_SINGLESEL;
109 panel._listView.SetStyle(style);
110 panel.SetExtendedStyle();
111 }
112}
113
114#ifndef ILC_COLOR32
115#define ILC_COLOR32 0x0020
116#endif
117
118HRESULT CApp::CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat,
119 bool needOpenArc,
120 COpenResult &openRes)
121{
122 if (Panels[panelIndex].PanelCreated)
123 return S_OK;
124
125 m_PanelCallbackImp[panelIndex].Init(this, panelIndex);
126
127 UString path;
128 if (mainPath.IsEmpty())
129 {
130 if (!::ReadPanelPath(panelIndex, path))
131 path.Empty();
132 }
133 else
134 path = mainPath;
135
136 int id = 1000 + 100 * panelIndex;
137
138 return Panels[panelIndex].Create(_window, _window,
139 id, path, arcFormat, &m_PanelCallbackImp[panelIndex], &AppState,
140 needOpenArc,
141 openRes);
142}
143
144
145static void CreateToolbar(HWND parent,
146 NControl::CImageList &imageList,
147 NControl::CToolBar &toolBar,
148 bool largeButtons)
149{
150 toolBar.Attach(::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 0
151 | WS_CHILD
152 | WS_VISIBLE
153 | TBSTYLE_FLAT
154 | TBSTYLE_TOOLTIPS
155 | TBSTYLE_WRAPABLE
156 // | TBSTYLE_AUTOSIZE
157 // | CCS_NORESIZE
158 #ifdef UNDER_CE
159 | CCS_NODIVIDER
160 | CCS_NOPARENTALIGN
161 #endif
162 ,0,0,0,0, parent, NULL, g_hInstance, NULL));
163
164 // TB_BUTTONSTRUCTSIZE message, which is required for
165 // backward compatibility.
166 toolBar.ButtonStructSize();
167
168 imageList.Create(
169 largeButtons ? 48: 24,
170 largeButtons ? 36: 24,
171 ILC_MASK | ILC_COLOR32, 0, 0);
172 toolBar.SetImageList(0, imageList);
173}
174
175
176struct CButtonInfo
177{
178 int CommandID;
179 UINT BitmapResID;
180 UINT Bitmap2ResID;
181 UINT StringResID;
182
183 UString GetText() const { return LangString(StringResID); }
184};
185
186static const CButtonInfo g_StandardButtons[] =
187{
188 { IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY },
189 { IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE },
190 { IDM_DELETE, IDB_DELETE, IDB_DELETE2, IDS_BUTTON_DELETE } ,
191 { IDM_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO }
192};
193
194static const CButtonInfo g_ArchiveButtons[] =
195{
196 { kMenuCmdID_Toolbar_Add, IDB_ADD, IDB_ADD2, IDS_ADD },
197 { kMenuCmdID_Toolbar_Extract, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT },
198 { kMenuCmdID_Toolbar_Test, IDB_TEST, IDB_TEST2, IDS_TEST }
199};
200
201static bool SetButtonText(int commandID, const CButtonInfo *buttons, unsigned numButtons, UString &s)
202{
203 for (unsigned i = 0; i < numButtons; i++)
204 {
205 const CButtonInfo &b = buttons[i];
206 if (b.CommandID == commandID)
207 {
208 s = b.GetText();
209 return true;
210 }
211 }
212 return false;
213}
214
215static void SetButtonText(int commandID, UString &s)
216{
217 if (SetButtonText(commandID, g_StandardButtons, ARRAY_SIZE(g_StandardButtons), s))
218 return;
219 SetButtonText(commandID, g_ArchiveButtons, ARRAY_SIZE(g_ArchiveButtons), s);
220}
221
222static void AddButton(
223 NControl::CImageList &imageList,
224 NControl::CToolBar &toolBar,
225 const CButtonInfo &butInfo, bool showText, bool large)
226{
227 TBBUTTON but;
228 but.iBitmap = 0;
229 but.idCommand = butInfo.CommandID;
230 but.fsState = TBSTATE_ENABLED;
231 but.fsStyle = TBSTYLE_BUTTON;
232 but.dwData = 0;
233
234 UString s = butInfo.GetText();
235 but.iString = 0;
236 if (showText)
237 but.iString = (INT_PTR)(LPCWSTR)s;
238
239 but.iBitmap = imageList.GetImageCount();
240 HBITMAP b = ::LoadBitmap(g_hInstance,
241 large ?
242 MAKEINTRESOURCE(butInfo.BitmapResID):
243 MAKEINTRESOURCE(butInfo.Bitmap2ResID));
244 if (b != 0)
245 {
246 imageList.AddMasked(b, RGB(255, 0, 255));
247 ::DeleteObject(b);
248 }
249 #ifdef _UNICODE
250 toolBar.AddButton(1, &but);
251 #else
252 toolBar.AddButtonW(1, &but);
253 #endif
254}
255
256void CApp::ReloadToolbars()
257{
258 _buttonsImageList.Destroy();
259 _toolBar.Destroy();
260
261
262 if (ShowArchiveToolbar || ShowStandardToolbar)
263 {
264 CreateToolbar(_window, _buttonsImageList, _toolBar, LargeButtons);
265 unsigned i;
266 if (ShowArchiveToolbar)
267 for (i = 0; i < ARRAY_SIZE(g_ArchiveButtons); i++)
268 AddButton(_buttonsImageList, _toolBar, g_ArchiveButtons[i], ShowButtonsLables, LargeButtons);
269 if (ShowStandardToolbar)
270 for (i = 0; i < ARRAY_SIZE(g_StandardButtons); i++)
271 AddButton(_buttonsImageList, _toolBar, g_StandardButtons[i], ShowButtonsLables, LargeButtons);
272
273 _toolBar.AutoSize();
274 }
275}
276
277void CApp::SaveToolbarChanges()
278{
279 SaveToolbar();
280 ReloadToolbars();
281 MoveSubWindows();
282}
283
284
285HRESULT CApp::Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, COpenResult &openRes)
286{
287 _window.Attach(hwnd);
288
289 #ifdef UNDER_CE
290 _commandBar.Create(g_hInstance, hwnd, 1);
291 #endif
292
293 MyLoadMenu();
294
295 #ifdef UNDER_CE
296 _commandBar.AutoSize();
297 #endif
298
299 ReadToolbar();
300 ReloadToolbars();
301
302 unsigned i;
303 for (i = 0; i < kNumPanelsMax; i++)
304 Panels[i].PanelCreated = false;
305
306 AppState.Read();
307
308 SetListSettings();
309
310 if (LastFocusedPanel >= kNumPanelsMax)
311 LastFocusedPanel = 0;
312 // ShowDeletedFiles = Read_ShowDeleted();
313
314 CListMode listMode;
315 listMode.Read();
316
317 for (i = 0; i < kNumPanelsMax; i++)
318 {
319 CPanel &panel = Panels[i];
320 panel._ListViewMode = listMode.Panels[i];
321 panel._xSize = xSizes[i];
322 panel._flatModeForArc = ReadFlatView(i);
323 }
324
325 for (i = 0; i < kNumPanelsMax; i++)
326 {
327 unsigned panelIndex = i;
328 if (needOpenArc && LastFocusedPanel == 1)
329 panelIndex = 1 - i;
330
331 bool isMainPanel = (panelIndex == LastFocusedPanel);
332
333 if (NumPanels > 1 || isMainPanel)
334 {
335 if (NumPanels == 1)
336 Panels[panelIndex]._xSize = xSizes[0] + xSizes[1];
337
338 COpenResult openRes2;
339 UString path;
340 if (isMainPanel)
341 path = mainPath;
342
343 RINOK(CreateOnePanel(panelIndex, path, arcFormat,
344 isMainPanel && needOpenArc,
345 *(isMainPanel ? &openRes : &openRes2)));
346
347 if (isMainPanel)
348 {
349 if (needOpenArc && !openRes.ArchiveIsOpened)
350 return S_OK;
351 }
352 }
353 }
354
355 SetFocusedPanel(LastFocusedPanel);
356 Panels[LastFocusedPanel].SetFocusToList();
357 return S_OK;
358}
359
360
361HRESULT CApp::SwitchOnOffOnePanel()
362{
363 if (NumPanels == 1)
364 {
365 NumPanels++;
366 COpenResult openRes;
367 RINOK(CreateOnePanel(1 - LastFocusedPanel, UString(), UString(),
368 false, // needOpenArc
369 openRes));
370 Panels[1 - LastFocusedPanel].Enable(true);
371 Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL);
372 }
373 else
374 {
375 NumPanels--;
376 Panels[1 - LastFocusedPanel].Enable(false);
377 Panels[1 - LastFocusedPanel].Show(SW_HIDE);
378 }
379 MoveSubWindows();
380 return S_OK;
381}
382
383void CApp::Save()
384{
385 AppState.Save();
386 CListMode listMode;
387
388 for (unsigned i = 0; i < kNumPanelsMax; i++)
389 {
390 const CPanel &panel = Panels[i];
391 UString path;
392 if (panel._parentFolders.IsEmpty())
393 path = panel._currentFolderPrefix;
394 else
395 path = panel._parentFolders[0].ParentFolderPath;
396 // GetFolderPath(panel._parentFolders[0].ParentFolder);
397 SavePanelPath(i, path);
398 listMode.Panels[i] = panel.GetListViewMode();
399 SaveFlatView(i, panel._flatModeForArc);
400 }
401
402 listMode.Save();
403 // Save_ShowDeleted(ShowDeletedFiles);
404}
405
406void CApp::Release()
407{
408 // It's for unloading COM dll's: don't change it.
409 for (unsigned i = 0; i < kNumPanelsMax; i++)
410 Panels[i].Release();
411}
412
413// reduces path to part that exists on disk (or root prefix of path)
414// output path is normalized (with WCHAR_PATH_SEPARATOR)
415static void Reduce_Path_To_RealFileSystemPath(UString &path)
416{
417 unsigned prefixSize = GetRootPrefixSize(path);
418
419 while (!path.IsEmpty())
420 {
421 if (NFind::DoesDirExist_FollowLink(us2fs(path)))
422 {
423 NName::NormalizeDirPathPrefix(path);
424 break;
425 }
426 int pos = path.ReverseFind_PathSepar();
427 if (pos < 0)
428 {
429 path.Empty();
430 break;
431 }
432 path.DeleteFrom((unsigned)(pos + 1));
433 if ((unsigned)pos + 1 == prefixSize)
434 break;
435 path.DeleteFrom((unsigned)pos);
436 }
437}
438
439// returns: true, if such dir exists or is root
440/*
441static bool CheckFolderPath(const UString &path)
442{
443 UString pathReduced = path;
444 Reduce_Path_To_RealFileSystemPath(pathReduced);
445 return (pathReduced == path);
446}
447*/
448
449extern UString ConvertSizeToString(UInt64 value);
450
451static void AddSizeValue(UString &s, UInt64 size)
452{
453 s += MyFormatNew(IDS_FILE_SIZE, ConvertSizeToString(size));
454}
455
456static void AddValuePair1(UString &s, UINT resourceID, UInt64 size)
457{
458 AddLangString(s, resourceID);
459 s += ": ";
460 AddSizeValue(s, size);
461 s.Add_LF();
462}
463
464void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size);
465void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size)
466{
467 if (num == 0)
468 return;
469 AddLangString(s, resourceID);
470 s += ": ";
471 s += ConvertSizeToString(num);
472
473 if (size != (UInt64)(Int64)-1)
474 {
475 s += " ( ";
476 AddSizeValue(s, size);
477 s += " )";
478 }
479 s.Add_LF();
480}
481
482static void AddPropValueToSum(IFolderFolder *folder, int index, PROPID propID, UInt64 &sum)
483{
484 if (sum == (UInt64)(Int64)-1)
485 return;
486 NCOM::CPropVariant prop;
487 folder->GetProperty(index, propID, &prop);
488 UInt64 val = 0;
489 if (ConvertPropVariantToUInt64(prop, val))
490 sum += val;
491 else
492 sum = (UInt64)(Int64)-1;
493}
494
495UString CPanel::GetItemsInfoString(const CRecordVector<UInt32> &indices)
496{
497 UString info;
498 UInt64 numDirs, numFiles, filesSize, foldersSize;
499 numDirs = numFiles = filesSize = foldersSize = 0;
500
501 unsigned i;
502 for (i = 0; i < indices.Size(); i++)
503 {
504 int index = indices[i];
505 if (IsItem_Folder(index))
506 {
507 AddPropValueToSum(_folder, index, kpidSize, foldersSize);
508 numDirs++;
509 }
510 else
511 {
512 AddPropValueToSum(_folder, index, kpidSize, filesSize);
513 numFiles++;
514 }
515 }
516
517 AddValuePair2(info, IDS_PROP_FOLDERS, numDirs, foldersSize);
518 AddValuePair2(info, IDS_PROP_FILES, numFiles, filesSize);
519 int numDefined = ((foldersSize != (UInt64)(Int64)-1) && foldersSize != 0) ? 1: 0;
520 numDefined += ((filesSize != (UInt64)(Int64)-1) && filesSize != 0) ? 1: 0;
521 if (numDefined == 2)
522 AddValuePair1(info, IDS_PROP_SIZE, filesSize + foldersSize);
523
524 info.Add_LF();
525 info += _currentFolderPrefix;
526
527 for (i = 0; i < indices.Size() && (int)i < (int)kCopyDialog_NumInfoLines - 6; i++)
528 {
529 info.Add_LF();
530 info += " ";
531 int index = indices[i];
532 info += GetItemRelPath(index);
533 if (IsItem_Folder(index))
534 info.Add_PathSepar();
535 }
536 if (i != indices.Size())
537 {
538 info.Add_LF();
539 info += " ...";
540 }
541 return info;
542}
543
544bool IsCorrectFsName(const UString &name);
545
546
547
548/* Returns true, if path is path that can be used as path for File System functions
549*/
550
551/*
552static bool IsFsPath(const FString &path)
553{
554 if (!IsAbsolutePath(path))
555 return false;
556 unsigned prefixSize = GetRootPrefixSize(path);
557}
558*/
559
560void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
561{
562 unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
563 CPanel &srcPanel = Panels[srcPanelIndex];
564 CPanel &destPanel = Panels[destPanelIndex];
565
566 CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel);
567 CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel);
568
569 if (move)
570 {
571 if (!srcPanel.CheckBeforeUpdate(IDS_MOVE))
572 return;
573 }
574 else if (!srcPanel.DoesItSupportOperations())
575 {
576 srcPanel.MessageBox_Error_UnsupportOperation();
577 return;
578 }
579
580 CRecordVector<UInt32> indices;
581 UString destPath;
582 bool useDestPanel = false;
583
584 {
585 if (copyToSame)
586 {
587 int focusedItem = srcPanel._listView.GetFocusedItem();
588 if (focusedItem < 0)
589 return;
590 int realIndex = srcPanel.GetRealItemIndex(focusedItem);
591 if (realIndex == kParentIndex)
592 return;
593 indices.Add(realIndex);
594 destPath = srcPanel.GetItemName(realIndex);
595 }
596 else
597 {
598 srcPanel.GetOperatedIndicesSmart(indices);
599 if (indices.Size() == 0)
600 return;
601 destPath = destPanel.GetFsPath();
602 if (NumPanels == 1)
603 Reduce_Path_To_RealFileSystemPath(destPath);
604 }
605 }
606
607 UStringVector copyFolders;
608 ReadCopyHistory(copyFolders);
609
610 bool useFullItemPaths = srcPanel.Is_IO_FS_Folder(); // maybe we need flat also here ??
611
612 {
613 CCopyDialog copyDialog;
614
615 copyDialog.Strings = copyFolders;
616 copyDialog.Value = destPath;
617 LangString(move ? IDS_MOVE : IDS_COPY, copyDialog.Title);
618 LangString(move ? IDS_MOVE_TO : IDS_COPY_TO, copyDialog.Static);
619 copyDialog.Info = srcPanel.GetItemsInfoString(indices);
620
621 if (copyDialog.Create(srcPanel.GetParent()) != IDOK)
622 return;
623
624 destPath = copyDialog.Value;
625 }
626
627 {
628 if (destPath.IsEmpty())
629 {
630 srcPanel.MessageBox_Error_UnsupportOperation();
631 return;
632 }
633
634 UString correctName;
635 if (!srcPanel.CorrectFsPath(destPath, correctName))
636 {
637 srcPanel.MessageBox_Error_HRESULT(E_INVALIDARG);
638 return;
639 }
640
641 if (IsAbsolutePath(destPath))
642 destPath.Empty();
643 else
644 destPath = srcPanel.GetFsPath();
645 destPath += correctName;
646
647 #if defined(_WIN32) && !defined(UNDER_CE)
648 if (destPath.Len() > 0 && destPath[0] == '\\')
649 if (destPath.Len() == 1 || destPath[1] != '\\')
650 {
651 srcPanel.MessageBox_Error_UnsupportOperation();
652 return;
653 }
654 #endif
655
656 bool possibleToUseDestPanel = false;
657
658 if (CompareFileNames(destPath, destPanel.GetFsPath()) == 0)
659 {
660 if (NumPanels == 1 || CompareFileNames(destPath, srcPanel.GetFsPath()) == 0)
661 {
662 srcPanel.MessageBox_Error(L"Cannot copy files onto itself");
663 return;
664 }
665
666 if (destPanel.DoesItSupportOperations())
667 possibleToUseDestPanel = true;
668 }
669
670 bool destIsFsPath = false;
671
672 if (possibleToUseDestPanel)
673 {
674 if (destPanel.IsFSFolder() || destPanel.IsAltStreamsFolder())
675 destIsFsPath = true;
676 else if (destPanel.IsFSDrivesFolder() || destPanel.IsRootFolder())
677 {
678 srcPanel.MessageBox_Error_UnsupportOperation();
679 return;
680 }
681 }
682 else
683 {
684 if (IsAltPathPrefix(us2fs(destPath)))
685 {
686 // we allow alt streams dest only to alt stream folder in second panel
687 srcPanel.MessageBox_Error_UnsupportOperation();
688 return;
689 /*
690 FString basePath = us2fs(destPath);
691 basePath.DeleteBack();
692 if (!DoesFileOrDirExist(basePath))
693 {
694 srcPanel.MessageBoxError2Lines(basePath, ERROR_FILE_NOT_FOUND); // GetLastError()
695 return;
696 }
697 destIsFsPath = true;
698 */
699 }
700 else
701 {
702 if (indices.Size() == 1 &&
703 !destPath.IsEmpty() && !IS_PATH_SEPAR(destPath.Back()))
704 {
705 int pos = destPath.ReverseFind_PathSepar();
706 if (pos < 0)
707 {
708 srcPanel.MessageBox_Error_UnsupportOperation();
709 return;
710 }
711 {
712 /*
713 #ifdef _WIN32
714 UString name = destPath.Ptr(pos + 1);
715 if (name.Find(L':') >= 0)
716 {
717 srcPanel.MessageBox_Error_UnsupportOperation();
718 return;
719 }
720 #endif
721 */
722 UString prefix = destPath.Left(pos + 1);
723 if (!CreateComplexDir(us2fs(prefix)))
724 {
725 DWORD lastError = ::GetLastError();
726 srcPanel.MessageBox_Error_2Lines_Message_HRESULT(prefix, lastError);
727 return;
728 }
729 }
730 // bool isFolder = srcPanael.IsItem_Folder(indices[0]);
731 }
732 else
733 {
734 NName::NormalizeDirPathPrefix(destPath);
735 if (!CreateComplexDir(us2fs(destPath)))
736 {
737 DWORD lastError = ::GetLastError();
738 srcPanel.MessageBox_Error_2Lines_Message_HRESULT(destPath, lastError);
739 return;
740 }
741 }
742 destIsFsPath = true;
743 }
744 }
745
746 if (!destIsFsPath)
747 useDestPanel = true;
748
749 AddUniqueStringToHeadOfList(copyFolders, destPath);
750 while (copyFolders.Size() > 20)
751 copyFolders.DeleteBack();
752 SaveCopyHistory(copyFolders);
753 }
754
755 bool useSrcPanel = !useDestPanel || !srcPanel.Is_IO_FS_Folder();
756
757 bool useTemp = useSrcPanel && useDestPanel;
758 if (useTemp && NumPanels == 1)
759 {
760 srcPanel.MessageBox_Error_UnsupportOperation();
761 return;
762 }
763
764 CTempDir tempDirectory;
765 FString tempDirPrefix;
766 if (useTemp)
767 {
768 tempDirectory.Create(kTempDirPrefix);
769 tempDirPrefix = tempDirectory.GetPath();
770 NFile::NName::NormalizeDirPathPrefix(tempDirPrefix);
771 }
772
773 CSelectedState srcSelState;
774 CSelectedState destSelState;
775 srcPanel.SaveSelectedState(srcSelState);
776 destPanel.SaveSelectedState(destSelState);
777
778 CPanel::CDisableNotify disableNotify1(destPanel);
779 CPanel::CDisableNotify disableNotify2(srcPanel);
780
781 HRESULT result = S_OK;
782
783 if (useSrcPanel)
784 {
785 CCopyToOptions options;
786 options.folder = useTemp ? fs2us(tempDirPrefix) : destPath;
787 options.moveMode = move;
788 options.includeAltStreams = true;
789 options.replaceAltStreamChars = false;
790 options.showErrorMessages = true;
791
792 result = srcPanel.CopyTo(options, indices, NULL);
793 }
794
795 if (result == S_OK && useDestPanel)
796 {
797 UStringVector filePaths;
798 UString folderPrefix;
799
800 if (useTemp)
801 folderPrefix = fs2us(tempDirPrefix);
802 else
803 folderPrefix = srcPanel.GetFsPath();
804
805 filePaths.ClearAndReserve(indices.Size());
806
807 FOR_VECTOR (i, indices)
808 {
809 UInt32 index = indices[i];
810 UString s;
811 if (useFullItemPaths)
812 s = srcPanel.GetItemRelPath2(index);
813 else
814 s = srcPanel.GetItemName_for_Copy(index);
815 filePaths.AddInReserved(s);
816 }
817
818 result = destPanel.CopyFrom(move, folderPrefix, filePaths, true, 0);
819 }
820
821 if (result != S_OK)
822 {
823 // disableNotify1.Restore();
824 // disableNotify2.Restore();
825 // For Password:
826 // srcPanel.SetFocusToList();
827 // srcPanel.InvalidateList(NULL, true);
828
829 if (result != E_ABORT)
830 srcPanel.MessageBox_Error_HRESULT(result);
831 // return;
832 }
833
834 RefreshTitleAlways();
835
836 if (copyToSame || move)
837 {
838 srcPanel.RefreshListCtrl(srcSelState);
839 }
840
841 if (!copyToSame)
842 {
843 destPanel.RefreshListCtrl(destSelState);
844 srcPanel.KillSelection();
845 }
846
847 disableNotify1.Restore();
848 disableNotify2.Restore();
849 srcPanel.SetFocusToList();
850}
851
852void CApp::OnSetSameFolder(int srcPanelIndex)
853{
854 if (NumPanels <= 1)
855 return;
856 const CPanel &srcPanel = Panels[srcPanelIndex];
857 CPanel &destPanel = Panels[1 - srcPanelIndex];
858 destPanel.BindToPathAndRefresh(srcPanel._currentFolderPrefix);
859}
860
861void CApp::OnSetSubFolder(int srcPanelIndex)
862{
863 if (NumPanels <= 1)
864 return;
865 const CPanel &srcPanel = Panels[srcPanelIndex];
866 CPanel &destPanel = Panels[1 - srcPanelIndex];
867
868 int focusedItem = srcPanel._listView.GetFocusedItem();
869 if (focusedItem < 0)
870 return;
871 int realIndex = srcPanel.GetRealItemIndex(focusedItem);
872 if (!srcPanel.IsItem_Folder(realIndex))
873 return;
874
875 // destPanel.BindToFolder(srcPanel._currentFolderPrefix + srcPanel.GetItemName(realIndex) + WCHAR_PATH_SEPARATOR);
876
877 CMyComPtr<IFolderFolder> newFolder;
878 if (realIndex == kParentIndex)
879 {
880 if (srcPanel._folder->BindToParentFolder(&newFolder) != S_OK)
881 return;
882 if (!newFolder)
883 {
884 {
885 const UString parentPrefix = srcPanel.GetParentDirPrefix();
886 COpenResult openRes;
887 destPanel.BindToPath(parentPrefix, UString(), openRes);
888 }
889 destPanel.RefreshListCtrl();
890 return;
891 }
892 }
893 else
894 {
895 if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK)
896 return;
897 }
898
899 if (!newFolder)
900 return;
901
902 destPanel.CloseOpenFolders();
903 destPanel.SetNewFolder(newFolder);
904 destPanel.RefreshListCtrl();
905}
906
907/*
908int CApp::GetFocusedPanelIndex() const
909{
910 return LastFocusedPanel;
911 HWND hwnd = ::GetFocus();
912 for (;;)
913 {
914 if (hwnd == 0)
915 return 0;
916 for (unsigned i = 0; i < kNumPanelsMax; i++)
917 {
918 if (PanelsCreated[i] &&
919 ((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd))
920 return i;
921 }
922 hwnd = GetParent(hwnd);
923 }
924}
925*/
926
927static UString g_ToolTipBuffer;
928static CSysString g_ToolTipBufferSys;
929
930void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh)
931{
932 {
933 if (pnmh->code == TTN_GETDISPINFO)
934 {
935 LPNMTTDISPINFO info = (LPNMTTDISPINFO)pnmh;
936 info->hinst = 0;
937 g_ToolTipBuffer.Empty();
938 SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer);
939 g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer);
940 info->lpszText = g_ToolTipBufferSys.Ptr_non_const();
941 return;
942 }
943 #ifndef _UNICODE
944 if (pnmh->code == TTN_GETDISPINFOW)
945 {
946 LPNMTTDISPINFOW info = (LPNMTTDISPINFOW)pnmh;
947 info->hinst = 0;
948 g_ToolTipBuffer.Empty();
949 SetButtonText((int)info->hdr.idFrom, g_ToolTipBuffer);
950 info->lpszText = g_ToolTipBuffer.Ptr_non_const();
951 return;
952 }
953 #endif
954 }
955}
956
957void CApp::RefreshTitle(bool always)
958{
959 UString path = GetFocusedPanel()._currentFolderPrefix;
960 if (path.IsEmpty())
961 path = "7-Zip"; // LangString(IDS_APP_TITLE);
962 if (!always && path == PrevTitle)
963 return;
964 PrevTitle = path;
965 NWindows::MySetWindowText(_window, path);
966}
967
968void CApp::RefreshTitlePanel(unsigned panelIndex, bool always)
969{
970 if (panelIndex != GetFocusedPanelIndex())
971 return;
972 RefreshTitle(always);
973}
974
975static void AddUniqueStringToHead(UStringVector &list, const UString &s)
976{
977 for (unsigned i = 0; i < list.Size();)
978 if (s.IsEqualTo_NoCase(list[i]))
979 list.Delete(i);
980 else
981 i++;
982 list.Insert(0, s);
983}
984
985
986void CFolderHistory::Normalize()
987{
988 const unsigned kMaxSize = 100;
989 if (Strings.Size() > kMaxSize)
990 Strings.DeleteFrom(kMaxSize);
991}
992
993void CFolderHistory::AddString(const UString &s)
994{
995 NSynchronization::CCriticalSectionLock lock(_criticalSection);
996 AddUniqueStringToHead(Strings, s);
997 Normalize();
998}
diff --git a/CPP/7zip/UI/FileManager/App.h b/CPP/7zip/UI/FileManager/App.h
new file mode 100644
index 0000000..3c3c5ef
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/App.h
@@ -0,0 +1,378 @@
1// App.h
2
3#ifndef __APP_H
4#define __APP_H
5
6#include "../../../Windows/Control/CommandBar.h"
7#include "../../../Windows/Control/ImageList.h"
8
9#include "AppState.h"
10#include "Panel.h"
11
12class CApp;
13
14extern CApp g_App;
15extern HWND g_HWND;
16
17const unsigned kNumPanelsMax = 2;
18
19extern bool g_IsSmallScreen;
20
21// must be larger than context menu IDs
22const int kMenuCmdID_Toolbar_Start = 1070;
23const int kMenuCmdID_Plugin_Start = 1100;
24
25enum
26{
27 kMenuCmdID_Toolbar_Add = kMenuCmdID_Toolbar_Start,
28 kMenuCmdID_Toolbar_Extract,
29 kMenuCmdID_Toolbar_Test,
30 kMenuCmdID_Toolbar_End
31};
32
33class CPanelCallbackImp: public CPanelCallback
34{
35 CApp *_app;
36 unsigned _index;
37public:
38 void Init(CApp *app, unsigned index)
39 {
40 _app = app;
41 _index = index;
42 }
43 virtual void OnTab();
44 virtual void SetFocusToPath(unsigned index);
45 virtual void OnCopy(bool move, bool copyToSame);
46 virtual void OnSetSameFolder();
47 virtual void OnSetSubFolder();
48 virtual void PanelWasFocused();
49 virtual void DragBegin();
50 virtual void DragEnd();
51 virtual void RefreshTitle(bool always);
52};
53
54class CApp;
55
56class CDropTarget:
57 public IDropTarget,
58 public CMyUnknownImp
59{
60 CMyComPtr<IDataObject> m_DataObject;
61 UStringVector m_SourcePaths;
62 int m_SelectionIndex;
63 bool m_DropIsAllowed; // = true, if data contain fillist
64 bool m_PanelDropIsAllowed; // = false, if current target_panel is source_panel.
65 // check it only if m_DropIsAllowed == true
66 int m_SubFolderIndex;
67 UString m_SubFolderName;
68
69 CPanel *m_Panel;
70 bool m_IsAppTarget; // true, if we want to drop to app window (not to panel).
71
72 bool m_SetPathIsOK;
73
74 bool IsItSameDrive() const;
75
76 void QueryGetData(IDataObject *dataObject);
77 bool IsFsFolderPath() const;
78 DWORD GetEffect(DWORD keyState, POINTL pt, DWORD allowedEffect);
79 void RemoveSelection();
80 void PositionCursor(POINTL ptl);
81 UString GetTargetPath() const;
82 bool SetPath(bool enablePath) const;
83 bool SetPath();
84
85public:
86 MY_UNKNOWN_IMP1_MT(IDropTarget)
87 STDMETHOD(DragEnter)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect);
88 STDMETHOD(DragOver)(DWORD keyState, POINTL pt, DWORD * effect);
89 STDMETHOD(DragLeave)();
90 STDMETHOD(Drop)(IDataObject * dataObject, DWORD keyState, POINTL pt, DWORD *effect);
91
92 CDropTarget():
93 m_SelectionIndex(-1),
94 m_DropIsAllowed(false),
95 m_PanelDropIsAllowed(false),
96 m_SubFolderIndex(-1),
97 m_Panel(NULL),
98 m_IsAppTarget(false),
99 m_SetPathIsOK(false),
100 App(NULL),
101 SrcPanelIndex(-1),
102 TargetPanelIndex(-1)
103 {}
104
105 CApp *App;
106 int SrcPanelIndex; // index of D&D source_panel
107 int TargetPanelIndex; // what panel to use as target_panel of Application
108};
109
110
111class CApp
112{
113public:
114 NWindows::CWindow _window;
115 bool ShowSystemMenu;
116 // bool ShowDeletedFiles;
117 unsigned NumPanels;
118 unsigned LastFocusedPanel;
119
120 bool ShowStandardToolbar;
121 bool ShowArchiveToolbar;
122 bool ShowButtonsLables;
123 bool LargeButtons;
124
125 CAppState AppState;
126 CPanelCallbackImp m_PanelCallbackImp[kNumPanelsMax];
127 CPanel Panels[kNumPanelsMax];
128
129 NWindows::NControl::CImageList _buttonsImageList;
130
131 #ifdef UNDER_CE
132 NWindows::NControl::CCommandBar _commandBar;
133 #endif
134 NWindows::NControl::CToolBar _toolBar;
135
136 CDropTarget *_dropTargetSpec;
137 CMyComPtr<IDropTarget> _dropTarget;
138
139 UString LangString_N_SELECTED_ITEMS;
140
141 void ReloadLang();
142
143 CApp(): _window(0), NumPanels(2), LastFocusedPanel(0),
144 AutoRefresh_Mode(true)
145 {
146 SetPanels_AutoRefresh_Mode();
147 }
148
149 void CreateDragTarget()
150 {
151 _dropTargetSpec = new CDropTarget();
152 _dropTarget = _dropTargetSpec;
153 _dropTargetSpec->App = (this);
154 }
155
156 void SetFocusedPanel(unsigned index)
157 {
158 LastFocusedPanel = index;
159 _dropTargetSpec->TargetPanelIndex = LastFocusedPanel;
160 }
161
162 void DragBegin(unsigned panelIndex)
163 {
164 _dropTargetSpec->TargetPanelIndex = (NumPanels > 1) ? 1 - panelIndex : panelIndex;
165 _dropTargetSpec->SrcPanelIndex = panelIndex;
166 }
167
168 void DragEnd()
169 {
170 _dropTargetSpec->TargetPanelIndex = LastFocusedPanel;
171 _dropTargetSpec->SrcPanelIndex = -1;
172 }
173
174
175 void OnCopy(bool move, bool copyToSame, int srcPanelIndex);
176 void OnSetSameFolder(int srcPanelIndex);
177 void OnSetSubFolder(int srcPanelIndex);
178
179 HRESULT CreateOnePanel(int panelIndex, const UString &mainPath, const UString &arcFormat, bool needOpenArc, COpenResult &openRes);
180 HRESULT Create(HWND hwnd, const UString &mainPath, const UString &arcFormat, int xSizes[2], bool needOpenArc, COpenResult &openRes);
181 void Read();
182 void Save();
183 void Release();
184
185 // void SetFocus(int panelIndex) { Panels[panelIndex].SetFocusToList(); }
186 void SetFocusToLastItem() { Panels[LastFocusedPanel].SetFocusToLastRememberedItem(); }
187 unsigned GetFocusedPanelIndex() const { return LastFocusedPanel; }
188 bool IsPanelVisible(unsigned index) const { return (NumPanels > 1 || index == LastFocusedPanel); }
189 CPanel &GetFocusedPanel() { return Panels[GetFocusedPanelIndex()]; }
190
191 // File Menu
192 void OpenItem() { GetFocusedPanel().OpenSelectedItems(true); }
193 void OpenItemInside(const wchar_t *type) { GetFocusedPanel().OpenFocusedItemAsInternal(type); }
194 void OpenItemOutside() { GetFocusedPanel().OpenSelectedItems(false); }
195 void EditItem(bool useEditor) { GetFocusedPanel().EditItem(useEditor); }
196 void Rename() { GetFocusedPanel().RenameFile(); }
197 void CopyTo() { OnCopy(false, false, GetFocusedPanelIndex()); }
198 void MoveTo() { OnCopy(true, false, GetFocusedPanelIndex()); }
199 void Delete(bool toRecycleBin) { GetFocusedPanel().DeleteItems(toRecycleBin); }
200 HRESULT CalculateCrc2(const UString &methodName);
201 void CalculateCrc(const char *methodName);
202
203 void DiffFiles(const UString &path1, const UString &path2);
204 void DiffFiles();
205
206 void VerCtrl(unsigned id);
207
208 void Split();
209 void Combine();
210 void Properties() { GetFocusedPanel().Properties(); }
211 void Comment() { GetFocusedPanel().ChangeComment(); }
212
213 #ifndef UNDER_CE
214 void Link();
215 void OpenAltStreams() { GetFocusedPanel().OpenAltStreams(); }
216 #endif
217
218 void CreateFolder() { GetFocusedPanel().CreateFolder(); }
219 void CreateFile() { GetFocusedPanel().CreateFile(); }
220
221 // Edit
222 void EditCut() { GetFocusedPanel().EditCut(); }
223 void EditCopy() { GetFocusedPanel().EditCopy(); }
224 void EditPaste() { GetFocusedPanel().EditPaste(); }
225
226 void SelectAll(bool selectMode) { GetFocusedPanel().SelectAll(selectMode); }
227 void InvertSelection() { GetFocusedPanel().InvertSelection(); }
228 void SelectSpec(bool selectMode) { GetFocusedPanel().SelectSpec(selectMode); }
229 void SelectByType(bool selectMode) { GetFocusedPanel().SelectByType(selectMode); }
230
231 void Refresh_StatusBar() { GetFocusedPanel().Refresh_StatusBar(); }
232
233 void SetListViewMode(UInt32 index) { GetFocusedPanel().SetListViewMode(index); }
234 UInt32 GetListViewMode() { return GetFocusedPanel().GetListViewMode(); }
235 PROPID GetSortID() { return GetFocusedPanel().GetSortID(); }
236
237 void SortItemsWithPropID(PROPID propID) { GetFocusedPanel().SortItemsWithPropID(propID); }
238
239 void OpenRootFolder() { GetFocusedPanel().OpenDrivesFolder(); }
240 void OpenParentFolder() { GetFocusedPanel().OpenParentFolder(); }
241 void FoldersHistory() { GetFocusedPanel().FoldersHistory(); }
242 void RefreshView() { GetFocusedPanel().OnReload(); }
243 void RefreshAllPanels()
244 {
245 for (unsigned i = 0; i < NumPanels; i++)
246 {
247 unsigned index = i;
248 if (NumPanels == 1)
249 index = LastFocusedPanel;
250 Panels[index].OnReload();
251 }
252 }
253
254 /*
255 void SysIconsWereChanged()
256 {
257 for (unsigned i = 0; i < NumPanels; i++)
258 {
259 unsigned index = i;
260 if (NumPanels == 1)
261 index = LastFocusedPanel;
262 Panels[index].SysIconsWereChanged();
263 }
264 }
265 */
266
267 void SetListSettings();
268 HRESULT SwitchOnOffOnePanel();
269
270 CIntVector _timestampLevels;
271
272 bool GetFlatMode() { return Panels[LastFocusedPanel].GetFlatMode(); }
273
274 int GetTimestampLevel() const { return Panels[LastFocusedPanel]._timestampLevel; }
275 void SetTimestampLevel(int level)
276 {
277 unsigned i;
278 for (i = 0; i < kNumPanelsMax; i++)
279 {
280 CPanel &panel = Panels[i];
281 panel._timestampLevel = level;
282 if (panel.PanelCreated)
283 panel.RedrawListItems();
284 }
285 }
286
287 // bool Get_ShowNtfsStrems_Mode() { return Panels[LastFocusedPanel].Get_ShowNtfsStrems_Mode(); }
288
289 void ChangeFlatMode() { Panels[LastFocusedPanel].ChangeFlatMode(); }
290 // void Change_ShowNtfsStrems_Mode() { Panels[LastFocusedPanel].Change_ShowNtfsStrems_Mode(); }
291 // void Change_ShowDeleted() { ShowDeletedFiles = !ShowDeletedFiles; }
292
293 bool AutoRefresh_Mode;
294 bool Get_AutoRefresh_Mode()
295 {
296 // return Panels[LastFocusedPanel].Get_ShowNtfsStrems_Mode();
297 return AutoRefresh_Mode;
298 }
299 void Change_AutoRefresh_Mode()
300 {
301 AutoRefresh_Mode = !AutoRefresh_Mode;
302 SetPanels_AutoRefresh_Mode();
303 }
304 void SetPanels_AutoRefresh_Mode()
305 {
306 for (unsigned i = 0; i < kNumPanelsMax; i++)
307 Panels[i].Set_AutoRefresh_Mode(AutoRefresh_Mode);
308 }
309
310 void OpenBookmark(int index) { GetFocusedPanel().OpenBookmark(index); }
311 void SetBookmark(int index) { GetFocusedPanel().SetBookmark(index); }
312
313 void ReloadToolbars();
314 void ReadToolbar()
315 {
316 UInt32 mask = ReadToolbarsMask();
317 if (mask & ((UInt32)1 << 31))
318 {
319 ShowButtonsLables = !g_IsSmallScreen;
320 LargeButtons = false;
321 ShowStandardToolbar = ShowArchiveToolbar = true;
322 }
323 else
324 {
325 ShowButtonsLables = ((mask & 1) != 0);
326 LargeButtons = ((mask & 2) != 0);
327 ShowStandardToolbar = ((mask & 4) != 0);
328 ShowArchiveToolbar = ((mask & 8) != 0);
329 }
330 }
331 void SaveToolbar()
332 {
333 UInt32 mask = 0;
334 if (ShowButtonsLables) mask |= 1;
335 if (LargeButtons) mask |= 2;
336 if (ShowStandardToolbar) mask |= 4;
337 if (ShowArchiveToolbar) mask |= 8;
338 SaveToolbarsMask(mask);
339 }
340
341 void SaveToolbarChanges();
342
343 void SwitchStandardToolbar()
344 {
345 ShowStandardToolbar = !ShowStandardToolbar;
346 SaveToolbarChanges();
347 }
348 void SwitchArchiveToolbar()
349 {
350 ShowArchiveToolbar = !ShowArchiveToolbar;
351 SaveToolbarChanges();
352 }
353 void SwitchButtonsLables()
354 {
355 ShowButtonsLables = !ShowButtonsLables;
356 SaveToolbarChanges();
357 }
358 void SwitchLargeButtons()
359 {
360 LargeButtons = !LargeButtons;
361 SaveToolbarChanges();
362 }
363
364 void AddToArchive() { GetFocusedPanel().AddToArchive(); }
365 void ExtractArchives() { GetFocusedPanel().ExtractArchives(); }
366 void TestArchives() { GetFocusedPanel().TestArchives(); }
367
368 void OnNotify(int ctrlID, LPNMHDR pnmh);
369
370 UString PrevTitle;
371 void RefreshTitle(bool always = false);
372 void RefreshTitleAlways() { RefreshTitle(true); }
373 void RefreshTitlePanel(unsigned panelIndex, bool always = false);
374
375 void MoveSubWindows();
376};
377
378#endif
diff --git a/CPP/7zip/UI/FileManager/AppState.h b/CPP/7zip/UI/FileManager/AppState.h
new file mode 100644
index 0000000..cc88715
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/AppState.h
@@ -0,0 +1,95 @@
1// AppState.h
2
3#ifndef __APP_STATE_H
4#define __APP_STATE_H
5
6#include "../../../Windows/Synchronization.h"
7
8#include "ViewSettings.h"
9
10class CFastFolders
11{
12 NWindows::NSynchronization::CCriticalSection _criticalSection;
13public:
14 UStringVector Strings;
15 void SetString(unsigned index, const UString &s)
16 {
17 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
18 while (Strings.Size() <= index)
19 Strings.AddNew();
20 Strings[index] = s;
21 }
22 UString GetString(unsigned index)
23 {
24 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
25 if (index >= Strings.Size())
26 return UString();
27 return Strings[index];
28 }
29 void Save()
30 {
31 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
32 SaveFastFolders(Strings);
33 }
34 void Read()
35 {
36 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
37 ReadFastFolders(Strings);
38 }
39};
40
41class CFolderHistory
42{
43 NWindows::NSynchronization::CCriticalSection _criticalSection;
44 UStringVector Strings;
45
46 void Normalize();
47
48public:
49
50 void GetList(UStringVector &foldersHistory)
51 {
52 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
53 foldersHistory = Strings;
54 }
55
56 void AddString(const UString &s);
57
58 void RemoveAll()
59 {
60 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
61 Strings.Clear();
62 }
63
64 void Save()
65 {
66 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
67 SaveFolderHistory(Strings);
68 }
69
70 void Read()
71 {
72 NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
73 ReadFolderHistory(Strings);
74 Normalize();
75 }
76};
77
78struct CAppState
79{
80 CFastFolders FastFolders;
81 CFolderHistory FolderHistory;
82
83 void Save()
84 {
85 FastFolders.Save();
86 FolderHistory.Save();
87 }
88 void Read()
89 {
90 FastFolders.Read();
91 FolderHistory.Read();
92 }
93};
94
95#endif
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.cpp b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
new file mode 100644
index 0000000..6d2b6b5
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.cpp
@@ -0,0 +1,1025 @@
1// BrowseDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyWindows.h"
6
7#include <CommCtrl.h>
8
9#ifndef UNDER_CE
10#include "../../../Windows/CommonDialog.h"
11#include "../../../Windows/Shell.h"
12#endif
13
14#include "../../../Windows/FileName.h"
15#include "../../../Windows/FileFind.h"
16
17#ifdef UNDER_CE
18#include <commdlg.h>
19#endif
20
21#include "BrowseDialog.h"
22
23#define USE_MY_BROWSE_DIALOG
24
25#ifdef USE_MY_BROWSE_DIALOG
26
27#include "../../../Common/Defs.h"
28#include "../../../Common/IntToString.h"
29#include "../../../Common/Wildcard.h"
30
31#include "../../../Windows/FileDir.h"
32#include "../../../Windows/PropVariantConv.h"
33
34#include "../../../Windows/Control/ComboBox.h"
35#include "../../../Windows/Control/Dialog.h"
36#include "../../../Windows/Control/Edit.h"
37#include "../../../Windows/Control/ListView.h"
38
39#include "BrowseDialogRes.h"
40#include "PropertyNameRes.h"
41#include "SysIconUtils.h"
42
43#ifndef _SFX
44#include "RegistryUtils.h"
45#endif
46
47#endif
48
49#include "ComboDialog.h"
50#include "LangUtils.h"
51
52#include "resource.h"
53
54using namespace NWindows;
55using namespace NFile;
56using namespace NName;
57using namespace NFind;
58
59#ifdef USE_MY_BROWSE_DIALOG
60
61extern bool g_LVN_ITEMACTIVATE_Support;
62
63static const int kParentIndex = -1;
64static const UINT k_Message_RefreshPathEdit = WM_APP + 1;
65
66static HRESULT GetNormalizedError()
67{
68 DWORD errorCode = GetLastError();
69 return errorCode == 0 ? E_FAIL : errorCode;
70}
71
72extern UString HResultToMessage(HRESULT errorCode);
73
74static void MessageBox_Error_Global(HWND wnd, const wchar_t *message)
75{
76 ::MessageBoxW(wnd, message, L"7-Zip", MB_ICONERROR);
77}
78
79static void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name)
80{
81 UString s = HResultToMessage(errorCode);
82 if (name)
83 {
84 s.Add_LF();
85 s += name;
86 }
87 MessageBox_Error_Global(wnd, s);
88}
89
90class CBrowseDialog: public NControl::CModalDialog
91{
92 NControl::CListView _list;
93 NControl::CEdit _pathEdit;
94 NControl::CComboBox _filterCombo;
95
96 CObjectVector<CFileInfo> _files;
97
98 CExtToIconMap _extToIconMap;
99 int _sortIndex;
100 bool _ascending;
101 bool _showDots;
102 UString _topDirPrefix; // we don't open parent of that folder
103 UString DirPrefix;
104
105 virtual bool OnInit();
106 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
107 virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
108 virtual bool OnNotify(UINT controlID, LPNMHDR header);
109 virtual bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo);
110 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
111 virtual void OnOK();
112
113 void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); }
114
115 bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);
116 // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
117 HRESULT Reload(const UString &pathPrefix, const UString &selectedName);
118 HRESULT Reload();
119
120 void OpenParentFolder();
121 void SetPathEditText();
122 void OnCreateDir();
123 void OnItemEnter();
124 void FinishOnOK();
125
126 int GetRealItemIndex(int indexInListView) const
127 {
128 LPARAM param;
129 if (!_list.GetItemParam(indexInListView, param))
130 return (int)-1;
131 return (int)param;
132 }
133
134public:
135 bool FolderMode;
136 UString Title;
137 UString FilePath; // input/ result path
138 bool ShowAllFiles;
139 UStringVector Filters;
140 UString FilterDescription;
141
142 CBrowseDialog(): _showDots(false), FolderMode(false), ShowAllFiles(true) {}
143 void SetFilter(const UString &s);
144 INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_BROWSE, parent); }
145 int CompareItems(LPARAM lParam1, LPARAM lParam2);
146};
147
148void CBrowseDialog::SetFilter(const UString &s)
149{
150 Filters.Clear();
151 UString mask;
152 unsigned i;
153 for (i = 0; i < s.Len(); i++)
154 {
155 wchar_t c = s[i];
156 if (c == ';')
157 {
158 if (!mask.IsEmpty())
159 Filters.Add(mask);
160 mask.Empty();
161 }
162 else
163 mask += c;
164 }
165 if (!mask.IsEmpty())
166 Filters.Add(mask);
167 ShowAllFiles = Filters.IsEmpty();
168 for (i = 0; i < Filters.Size(); i++)
169 {
170 const UString &f = Filters[i];
171 if (f == L"*.*" || f == L"*")
172 {
173 ShowAllFiles = true;
174 break;
175 }
176 }
177}
178
179bool CBrowseDialog::OnInit()
180{
181 #ifdef LANG
182 LangSetDlgItems(*this, NULL, 0);
183 #endif
184 if (!Title.IsEmpty())
185 SetText(Title);
186 _list.Attach(GetItem(IDL_BROWSE));
187 _filterCombo.Attach(GetItem(IDC_BROWSE_FILTER));
188 _pathEdit.Attach(GetItem(IDE_BROWSE_PATH));
189
190 if (FolderMode)
191 HideItem(IDC_BROWSE_FILTER);
192 else
193 EnableItem(IDC_BROWSE_FILTER, false);
194
195 #ifndef UNDER_CE
196 _list.SetUnicodeFormat();
197 #endif
198
199 #ifndef _SFX
200 CFmSettings st;
201 st.Load();
202 if (st.SingleClick)
203 _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);
204 _showDots = st.ShowDots;
205 #endif
206
207 {
208 UString s;
209 if (!FilterDescription.IsEmpty())
210 s = FilterDescription;
211 else if (ShowAllFiles)
212 s = "*.*";
213 else
214 {
215 FOR_VECTOR (i, Filters)
216 {
217 if (i != 0)
218 s.Add_Space();
219 s += Filters[i];
220 }
221 }
222 _filterCombo.AddString(s);
223 _filterCombo.SetCurSel(0);
224 }
225
226 _list.SetImageList(GetSysImageList(true), LVSIL_SMALL);
227 _list.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
228
229 _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);
230 _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);
231 {
232 LV_COLUMNW column;
233 column.iSubItem = 2;
234 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
235 column.fmt = LVCFMT_RIGHT;
236 column.cx = 100;
237 const UString s = LangString(IDS_PROP_SIZE);
238 column.pszText = s.Ptr_non_const();
239 _list.InsertColumn(2, &column);
240 }
241
242 _list.InsertItem(0, L"12345678901234567"
243 #ifndef UNDER_CE
244 L"1234567890"
245 #endif
246 );
247 _list.SetSubItem(0, 1, L"2009-09-09"
248 #ifndef UNDER_CE
249 L" 09:09"
250 #endif
251 );
252 _list.SetSubItem(0, 2, L"9999 MB");
253 for (int i = 0; i < 3; i++)
254 _list.SetColumnWidthAuto(i);
255 _list.DeleteAllItems();
256
257 _ascending = true;
258 _sortIndex = 0;
259
260 NormalizeSize();
261
262 _topDirPrefix.Empty();
263 {
264 int rootSize = GetRootPrefixSize(FilePath);
265 #if defined(_WIN32) && !defined(UNDER_CE)
266 // We can go up from root folder to drives list
267 if (IsDrivePath(FilePath))
268 rootSize = 0;
269 else if (IsSuperPath(FilePath))
270 {
271 if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize)))
272 rootSize = kSuperPathPrefixSize;
273 }
274 #endif
275 _topDirPrefix.SetFrom(FilePath, rootSize);
276 }
277
278 UString name;
279 if (!GetParentPath(FilePath, DirPrefix, name))
280 DirPrefix = _topDirPrefix;
281
282 for (;;)
283 {
284 UString baseFolder = DirPrefix;
285 if (Reload(baseFolder, name) == S_OK)
286 break;
287 name.Empty();
288 if (DirPrefix.IsEmpty())
289 break;
290 UString parent, name2;
291 GetParentPath(DirPrefix, parent, name2);
292 DirPrefix = parent;
293 }
294
295 if (name.IsEmpty())
296 name = FilePath;
297 if (FolderMode)
298 NormalizeDirPathPrefix(name);
299 _pathEdit.SetText(name);
300
301 #ifndef UNDER_CE
302 /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,
303 even if we use mouse for pressing the button to open this dialog. */
304 PostMsg(MY__WM_UPDATEUISTATE, MAKEWPARAM(MY__UIS_CLEAR, MY__UISF_HIDEFOCUS));
305 #endif
306
307 return CModalDialog::OnInit();
308}
309
310bool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
311{
312 int mx, my;
313 {
314 RECT r;
315 GetClientRectOfItem(IDB_BROWSE_PARENT, r);
316 mx = r.left;
317 my = r.top;
318 }
319 InvalidateRect(NULL);
320
321 int xLim = xSize - mx;
322 {
323 RECT r;
324 GetClientRectOfItem(IDT_BROWSE_FOLDER, r);
325 MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r));
326 }
327
328 int bx1, bx2, by;
329 GetItemSizes(IDCANCEL, bx1, by);
330 GetItemSizes(IDOK, bx2, by);
331 int y = ySize - my - by;
332 int x = xLim - bx1;
333 MoveItem(IDCANCEL, x, y, bx1, by);
334 MoveItem(IDOK, x - mx - bx2, y, bx2, by);
335
336 // Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead
337
338 int yPathSize;
339 {
340 RECT r;
341 GetClientRectOfItem(IDE_BROWSE_PATH, r);
342 yPathSize = RECT_SIZE_Y(r);
343 _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize);
344 }
345
346 {
347 RECT r;
348 GetClientRectOfItem(IDC_BROWSE_FILTER, r);
349 _filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r));
350 }
351
352 {
353 RECT r;
354 GetClientRectOfItem(IDL_BROWSE, r);
355 _list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top);
356 }
357
358 return false;
359}
360
361bool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
362{
363 if (message == k_Message_RefreshPathEdit)
364 {
365 SetPathEditText();
366 return true;
367 }
368 return CModalDialog::OnMessage(message, wParam, lParam);
369}
370
371bool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
372{
373 if (header->hwndFrom != _list)
374 return false;
375 switch (header->code)
376 {
377 case LVN_ITEMACTIVATE:
378 if (g_LVN_ITEMACTIVATE_Support)
379 OnItemEnter();
380 break;
381 case NM_DBLCLK:
382 case NM_RETURN: // probabably it's unused
383 if (!g_LVN_ITEMACTIVATE_Support)
384 OnItemEnter();
385 break;
386 case LVN_COLUMNCLICK:
387 {
388 int index = LPNMLISTVIEW(header)->iSubItem;
389 if (index == _sortIndex)
390 _ascending = !_ascending;
391 else
392 {
393 _ascending = (index == 0);
394 _sortIndex = index;
395 }
396 Reload();
397 return false;
398 }
399 case LVN_KEYDOWN:
400 {
401 bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header));
402 Post_RefreshPathEdit();
403 return boolResult;
404 }
405 case NM_RCLICK:
406 case NM_CLICK:
407 case LVN_BEGINDRAG:
408 Post_RefreshPathEdit();
409 break;
410 }
411 return false;
412}
413
414bool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo)
415{
416 bool ctrl = IsKeyDown(VK_CONTROL);
417
418 switch (keyDownInfo->wVKey)
419 {
420 case VK_BACK:
421 OpenParentFolder();
422 return true;
423 case 'R':
424 if (ctrl)
425 {
426 Reload();
427 return true;
428 }
429 return false;
430 case VK_F7:
431 OnCreateDir();
432 return true;
433 }
434 return false;
435}
436
437bool CBrowseDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
438{
439 switch (buttonID)
440 {
441 case IDB_BROWSE_PARENT: OpenParentFolder(); break;
442 case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break;
443 default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
444 }
445 _list.SetFocus();
446 return true;
447}
448
449void CBrowseDialog::OnOK()
450{
451 /* When we press "Enter" in listview, Windows sends message to first Button.
452 We check that message was from ListView; */
453 if (GetFocus() == _list)
454 {
455 OnItemEnter();
456 return;
457 }
458 FinishOnOK();
459}
460
461
462bool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name)
463{
464 parentPrefix.Empty();
465 name.Empty();
466 if (path.IsEmpty())
467 return false;
468 if (_topDirPrefix == path)
469 return false;
470 UString s = path;
471 if (IS_PATH_SEPAR(s.Back()))
472 s.DeleteBack();
473 if (s.IsEmpty())
474 return false;
475 if (IS_PATH_SEPAR(s.Back()))
476 return false;
477 int pos = s.ReverseFind_PathSepar();
478 parentPrefix.SetFrom(s, pos + 1);
479 name = s.Ptr((unsigned)(pos + 1));
480 return true;
481}
482
483int CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2)
484{
485 if (lParam1 == kParentIndex) return -1;
486 if (lParam2 == kParentIndex) return 1;
487 const CFileInfo &f1 = _files[(int)lParam1];
488 const CFileInfo &f2 = _files[(int)lParam2];
489
490 bool isDir1 = f1.IsDir();
491 bool isDir2 = f2.IsDir();
492 if (isDir1 && !isDir2) return -1;
493 if (isDir2 && !isDir1) return 1;
494
495 int res = 0;
496 switch (_sortIndex)
497 {
498 case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break;
499 case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break;
500 case 2: res = MyCompare(f1.Size, f2.Size); break;
501 }
502 return _ascending ? res: -res;
503}
504
505static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
506{
507 return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2);
508}
509
510static void ConvertSizeToString(UInt64 v, wchar_t *s)
511{
512 Byte c = 0;
513 if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; }
514 else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; }
515 else if (v >= ((UInt64)10000 << 0)) { v >>= 10; c = 'K'; }
516 ConvertUInt64ToString(v, s);
517 if (c != 0)
518 {
519 s += MyStringLen(s);
520 *s++ = ' ';
521 *s++ = c;
522 *s++ = 0;
523 }
524}
525
526// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter
527
528HRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName)
529{
530 CObjectVector<CFileInfo> files;
531
532 #ifndef UNDER_CE
533 bool isDrive = false;
534 if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix))
535 {
536 isDrive = true;
537 FStringVector drives;
538 if (!MyGetLogicalDriveStrings(drives))
539 return GetNormalizedError();
540 FOR_VECTOR (i, drives)
541 {
542 FString d = drives[i];
543 if (d.Len() < 3 || d.Back() != '\\')
544 return E_FAIL;
545 d.DeleteBack();
546 CFileInfo &fi = files.AddNew();
547 fi.SetAsDir();
548 fi.Name = d;
549 }
550 }
551 else
552 #endif
553 {
554 CEnumerator enumerator;
555 enumerator.SetDirPrefix(us2fs(pathPrefix));
556 for (;;)
557 {
558 bool found;
559 CFileInfo fi;
560 if (!enumerator.Next(fi, found))
561 return GetNormalizedError();
562 if (!found)
563 break;
564 if (!fi.IsDir())
565 {
566 if (FolderMode)
567 continue;
568 if (!ShowAllFiles)
569 {
570 unsigned i;
571 for (i = 0; i < Filters.Size(); i++)
572 if (DoesWildcardMatchName(Filters[i], fs2us(fi.Name)))
573 break;
574 if (i == Filters.Size())
575 continue;
576 }
577 }
578 files.Add(fi);
579 }
580 }
581
582 DirPrefix = pathPrefix;
583
584 _files = files;
585
586 SetItemText(IDT_BROWSE_FOLDER, DirPrefix);
587
588 _list.SetRedraw(false);
589 _list.DeleteAllItems();
590
591 LVITEMW item;
592
593 int index = 0;
594 int cursorIndex = -1;
595
596 #ifndef _SFX
597 if (_showDots && _topDirPrefix != DirPrefix)
598 {
599 item.iItem = index;
600 const UString itemName ("..");
601 if (selectedName.IsEmpty())
602 cursorIndex = index;
603 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
604 int subItem = 0;
605 item.iSubItem = subItem++;
606 item.lParam = kParentIndex;
607 item.pszText = itemName.Ptr_non_const();
608 item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix);
609 if (item.iImage < 0)
610 item.iImage = 0;
611 _list.InsertItem(&item);
612 _list.SetSubItem(index, subItem++, L"");
613 _list.SetSubItem(index, subItem++, L"");
614 index++;
615 }
616 #endif
617
618 for (unsigned i = 0; i < _files.Size(); i++, index++)
619 {
620 item.iItem = index;
621 const CFileInfo &fi = _files[i];
622 const UString name = fs2us(fi.Name);
623 if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0)
624 cursorIndex = index;
625 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
626 int subItem = 0;
627 item.iSubItem = subItem++;
628 item.lParam = i;
629 item.pszText = name.Ptr_non_const();
630
631 const UString fullPath = DirPrefix + name;
632 #ifndef UNDER_CE
633 if (isDrive)
634 {
635 if (GetRealIconIndex(fi.Name + FCHAR_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, item.iImage) == 0)
636 item.iImage = 0;
637 }
638 else
639 #endif
640 item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);
641 if (item.iImage < 0)
642 item.iImage = 0;
643 _list.InsertItem(&item);
644 wchar_t s[32];
645 {
646 s[0] = 0;
647 ConvertUtcFileTimeToString(fi.MTime, s,
648 #ifndef UNDER_CE
649 kTimestampPrintLevel_MIN
650 #else
651 kTimestampPrintLevel_DAY
652 #endif
653 );
654 _list.SetSubItem(index, subItem++, s);
655 }
656 {
657 s[0] = 0;
658 if (!fi.IsDir())
659 ConvertSizeToString(fi.Size, s);
660 _list.SetSubItem(index, subItem++, s);
661 }
662 }
663
664 if (_list.GetItemCount() > 0 && cursorIndex >= 0)
665 _list.SetItemState_FocusedSelected(cursorIndex);
666 _list.SortItems(CompareItems2, (LPARAM)this);
667 if (_list.GetItemCount() > 0 && cursorIndex < 0)
668 _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
669 _list.EnsureVisible(_list.GetFocusedItem(), false);
670 _list.SetRedraw(true);
671 _list.InvalidateRect(NULL, true);
672 return S_OK;
673}
674
675HRESULT CBrowseDialog::Reload()
676{
677 UString selected;
678 int index = _list.GetNextSelectedItem(-1);
679 if (index >= 0)
680 {
681 int fileIndex = GetRealItemIndex(index);
682 if (fileIndex != kParentIndex)
683 selected = fs2us(_files[fileIndex].Name);
684 }
685 UString dirPathTemp = DirPrefix;
686 return Reload(dirPathTemp, selected);
687}
688
689void CBrowseDialog::OpenParentFolder()
690{
691 UString parent, selected;
692 if (GetParentPath(DirPrefix, parent, selected))
693 {
694 Reload(parent, selected);
695 SetPathEditText();
696 }
697}
698
699void CBrowseDialog::SetPathEditText()
700{
701 int index = _list.GetNextSelectedItem(-1);
702 if (index < 0)
703 {
704 if (FolderMode)
705 _pathEdit.SetText(DirPrefix);
706 return;
707 }
708 int fileIndex = GetRealItemIndex(index);
709 if (fileIndex == kParentIndex)
710 {
711 if (FolderMode)
712 _pathEdit.SetText(L".." WSTRING_PATH_SEPARATOR);
713 return;
714 }
715 const CFileInfo &file = _files[fileIndex];
716 if (file.IsDir())
717 {
718 if (!FolderMode)
719 return;
720 _pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR);
721 }
722 else
723 _pathEdit.SetText(fs2us(file.Name));
724}
725
726void CBrowseDialog::OnCreateDir()
727{
728 UString name;
729 {
730 UString enteredName;
731 Dlg_CreateFolder((HWND)*this, enteredName);
732 if (enteredName.IsEmpty())
733 return;
734 if (!CorrectFsPath(DirPrefix, enteredName, name))
735 {
736 MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name);
737 return;
738 }
739 }
740 if (name.IsEmpty())
741 return;
742
743 FString destPath;
744 if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath))
745 {
746 if (!NDir::CreateComplexDir(destPath))
747 {
748 MessageBox_HResError((HWND)*this, GetNormalizedError(), fs2us(destPath));
749 }
750 else
751 {
752 UString tempPath = DirPrefix;
753 Reload(tempPath, name);
754 SetPathEditText();
755 }
756 _list.SetFocus();
757 }
758}
759
760void CBrowseDialog::OnItemEnter()
761{
762 int index = _list.GetNextSelectedItem(-1);
763 if (index < 0)
764 return;
765 int fileIndex = GetRealItemIndex(index);
766 if (fileIndex == kParentIndex)
767 OpenParentFolder();
768 else
769 {
770 const CFileInfo &file = _files[fileIndex];
771 if (!file.IsDir())
772 {
773 if (!FolderMode)
774 FinishOnOK();
775 /*
776 MessageBox_Error_Global(*this, FolderMode ?
777 L"You must select some folder":
778 L"You must select some file");
779 */
780 return;
781 }
782 UString s = DirPrefix;
783 s += fs2us(file.Name);
784 s.Add_PathSepar();
785 HRESULT res = Reload(s, UString());
786 if (res != S_OK)
787 MessageBox_HResError(*this, res, s);
788 SetPathEditText();
789 }
790}
791
792void CBrowseDialog::FinishOnOK()
793{
794 UString s;
795 _pathEdit.GetText(s);
796 FString destPath;
797 if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath))
798 {
799 MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s);
800 return;
801 }
802 FilePath = fs2us(destPath);
803 if (FolderMode)
804 NormalizeDirPathPrefix(FilePath);
805 End(IDOK);
806}
807
808#endif
809
810bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath)
811{
812 resultPath.Empty();
813
814 #ifndef UNDER_CE
815
816 #ifdef USE_MY_BROWSE_DIALOG
817 if (!IsSuperOrDevicePath(path))
818 #endif
819 return NShell::BrowseForFolder(owner, title, path, resultPath);
820
821 #endif
822
823 #ifdef USE_MY_BROWSE_DIALOG
824
825 CBrowseDialog dialog;
826 dialog.FolderMode = true;
827 if (title)
828 dialog.Title = title;
829 if (path)
830 dialog.FilePath = path;
831 if (dialog.Create(owner) != IDOK)
832 return false;
833 resultPath = dialog.FilePath;
834 #endif
835
836 return true;
837}
838
839bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path,
840 LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath)
841{
842 resultPath.Empty();
843
844 #ifndef UNDER_CE
845
846 #ifdef USE_MY_BROWSE_DIALOG
847 if (!IsSuperOrDevicePath(path))
848 #endif
849 {
850 if (MyGetOpenFileName(owner, title, NULL, path, filterDescription, filter, resultPath))
851 return true;
852 #ifdef UNDER_CE
853 return false;
854 #else
855 // maybe we must use GetLastError in WinCE.
856 DWORD errorCode = CommDlgExtendedError();
857 const char *errorMessage = NULL;
858 switch (errorCode)
859 {
860 case 0: return false; // cancel or close obn dialog
861 case FNERR_INVALIDFILENAME: errorMessage = "Invalid File Name"; break;
862 default: errorMessage = "Open Dialog Error";
863 }
864 if (!errorMessage)
865 return false;
866 {
867 UString s (errorMessage);
868 s.Add_LF();
869 s += path;
870 MessageBox_Error_Global(owner, s);
871 }
872 #endif
873 }
874
875 #endif
876
877 #ifdef USE_MY_BROWSE_DIALOG
878 CBrowseDialog dialog;
879 if (title)
880 dialog.Title = title;
881 if (path)
882 dialog.FilePath = path;
883 dialog.FolderMode = false;
884 if (filter)
885 dialog.SetFilter(filter);
886 if (filterDescription)
887 dialog.FilterDescription = filterDescription;
888 if (dialog.Create(owner) != IDOK)
889 return false;
890 resultPath = dialog.FilePath;
891 #endif
892
893 return true;
894}
895
896
897#ifdef _WIN32
898
899static void RemoveDotsAndSpaces(UString &path)
900{
901 while (!path.IsEmpty())
902 {
903 wchar_t c = path.Back();
904 if (c != ' ' && c != '.')
905 return;
906 path.DeleteBack();
907 }
908}
909
910
911bool CorrectFsPath(const UString &relBase, const UString &path2, UString &result)
912{
913 result.Empty();
914
915 UString path = path2;
916 path.Replace(L'/', WCHAR_PATH_SEPARATOR);
917 unsigned start = 0;
918 UString base;
919
920 if (IsAbsolutePath(path))
921 {
922 #if defined(_WIN32) && !defined(UNDER_CE)
923 if (IsSuperOrDevicePath(path))
924 {
925 result = path;
926 return true;
927 }
928 #endif
929 int pos = GetRootPrefixSize(path);
930 if (pos > 0)
931 start = pos;
932 }
933 else
934 {
935 #if defined(_WIN32) && !defined(UNDER_CE)
936 if (IsSuperOrDevicePath(relBase))
937 {
938 result = path;
939 return true;
940 }
941 #endif
942 base = relBase;
943 }
944
945 /* We can't use backward, since we must change only disk paths */
946 /*
947 for (;;)
948 {
949 if (path.Len() <= start)
950 break;
951 if (DoesFileOrDirExist(us2fs(path)))
952 break;
953 if (path.Back() == WCHAR_PATH_SEPARATOR)
954 {
955 path.DeleteBack();
956 result.Insert(0, WCHAR_PATH_SEPARATOR);
957 }
958 int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1;
959 UString cur = path.Ptr(pos);
960 RemoveDotsAndSpaces(cur);
961 result.Insert(0, cur);
962 path.DeleteFrom(pos);
963 }
964 result.Insert(0, path);
965 return true;
966 */
967
968 result += path.Left(start);
969 bool checkExist = true;
970 UString cur;
971
972 for (;;)
973 {
974 if (start == path.Len())
975 break;
976 int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start);
977 cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : slashPos) - start);
978 if (checkExist)
979 {
980 CFileInfo fi;
981 if (fi.Find(us2fs(base + result + cur)))
982 {
983 if (!fi.IsDir())
984 {
985 result = path;
986 break;
987 }
988 }
989 else
990 checkExist = false;
991 }
992 if (!checkExist)
993 RemoveDotsAndSpaces(cur);
994 result += cur;
995 if (slashPos < 0)
996 break;
997 result.Add_PathSepar();
998 start = slashPos + 1;
999 }
1000
1001 return true;
1002}
1003
1004#else
1005
1006bool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result)
1007{
1008 result = path;
1009 return true;
1010}
1011
1012#endif
1013
1014bool Dlg_CreateFolder(HWND wnd, UString &destName)
1015{
1016 destName.Empty();
1017 CComboDialog dlg;
1018 LangString(IDS_CREATE_FOLDER, dlg.Title);
1019 LangString(IDS_CREATE_FOLDER_NAME, dlg.Static);
1020 LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value);
1021 if (dlg.Create(wnd) != IDOK)
1022 return false;
1023 destName = dlg.Value;
1024 return true;
1025}
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.h b/CPP/7zip/UI/FileManager/BrowseDialog.h
new file mode 100644
index 0000000..957af2e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.h
@@ -0,0 +1,21 @@
1// BrowseDialog.h
2
3#ifndef __BROWSE_DIALOG_H
4#define __BROWSE_DIALOG_H
5
6#include "../../../Common/MyString.h"
7
8bool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath);
9bool MyBrowseForFile(HWND owner, LPCWSTR title, LPCWSTR path, LPCWSTR filterDescription, LPCWSTR filter, UString &resultPath);
10
11/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file)
12 But it doesn't change "bad" name in any of the following cases:
13 - path is Super Path (with \\?\ prefix)
14 - path is relative and relBase is Super Path
15 - there is file or dir in filesystem with specified "bad" name */
16
17bool CorrectFsPath(const UString &relBase, const UString &path, UString &result);
18
19bool Dlg_CreateFolder(HWND wnd, UString &destName);
20
21#endif
diff --git a/CPP/7zip/UI/FileManager/BrowseDialog.rc b/CPP/7zip/UI/FileManager/BrowseDialog.rc
new file mode 100644
index 0000000..04a6ad6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialog.rc
@@ -0,0 +1,25 @@
1#include "BrowseDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 256
5#define yc 320
6
7#define k_BROWSE_y_CtrlSize 14
8
9#define k_BROWSE_y_List 24
10
11IDD_BROWSE DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
12CAPTION "7-Zip: Browse"
13{
14 EDITTEXT IDE_BROWSE_PATH, m, by - m - k_BROWSE_y_CtrlSize - k_BROWSE_y_CtrlSize - m, xc, k_BROWSE_y_CtrlSize, ES_AUTOHSCROLL
15 COMBOBOX IDC_BROWSE_FILTER, m, by - m - k_BROWSE_y_CtrlSize, xc, 30, MY_COMBO
16
17 PUSHBUTTON "OK", IDOK, bx2, by, bxs, bys
18 PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
19 PUSHBUTTON "<--", IDB_BROWSE_PARENT, m, m, 24, bys
20 PUSHBUTTON "+", IDB_BROWSE_CREATE_DIR, m + 32, m, 24, bys
21 LTEXT "", IDT_BROWSE_FOLDER, m + 64, m + 3, xc - 20, 8
22 CONTROL "List1", IDL_BROWSE, "SysListView32",
23 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,
24 m, m + k_BROWSE_y_List, xc, yc - bys - m - k_BROWSE_y_List - k_BROWSE_y_CtrlSize - m - k_BROWSE_y_CtrlSize - m
25}
diff --git a/CPP/7zip/UI/FileManager/BrowseDialogRes.h b/CPP/7zip/UI/FileManager/BrowseDialogRes.h
new file mode 100644
index 0000000..aff84ec
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/BrowseDialogRes.h
@@ -0,0 +1,9 @@
1#define IDD_BROWSE 95
2
3#define IDL_BROWSE 100
4#define IDT_BROWSE_FOLDER 101
5#define IDE_BROWSE_PATH 102
6#define IDC_BROWSE_FILTER 103
7
8#define IDB_BROWSE_PARENT 110
9#define IDB_BROWSE_CREATE_DIR 112
diff --git a/CPP/7zip/UI/FileManager/ClassDefs.cpp b/CPP/7zip/UI/FileManager/ClassDefs.cpp
new file mode 100644
index 0000000..5c26904
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ClassDefs.cpp
@@ -0,0 +1,12 @@
1// ClassDefs.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyWindows.h"
6
7#include "../../../Common/MyInitGuid.h"
8
9#include "../Agent/Agent.h"
10
11#include "MyWindowsNew.h"
12#include "../Explorer/MyExplorerCommand.h"
diff --git a/CPP/7zip/UI/FileManager/ComboDialog.cpp b/CPP/7zip/UI/FileManager/ComboDialog.cpp
new file mode 100644
index 0000000..729743e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ComboDialog.cpp
@@ -0,0 +1,64 @@
1// ComboDialog.cpp
2
3#include "StdAfx.h"
4#include "ComboDialog.h"
5
6#include "../../../Windows/Control/Static.h"
7
8#ifdef LANG
9#include "LangUtils.h"
10#endif
11
12using namespace NWindows;
13
14bool CComboDialog::OnInit()
15{
16 #ifdef LANG
17 LangSetDlgItems(*this, NULL, 0);
18 #endif
19 _comboBox.Attach(GetItem(IDC_COMBO));
20
21 /*
22 // why it doesn't work ?
23 DWORD style = _comboBox.GetStyle();
24 if (Sorted)
25 style |= CBS_SORT;
26 else
27 style &= ~CBS_SORT;
28 _comboBox.SetStyle(style);
29 */
30 SetText(Title);
31
32 NControl::CStatic staticContol;
33 staticContol.Attach(GetItem(IDT_COMBO));
34 staticContol.SetText(Static);
35 _comboBox.SetText(Value);
36 FOR_VECTOR (i, Strings)
37 _comboBox.AddString(Strings[i]);
38 NormalizeSize();
39 return CModalDialog::OnInit();
40}
41
42bool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
43{
44 int mx, my;
45 GetMargins(8, mx, my);
46 int bx1, bx2, by;
47 GetItemSizes(IDCANCEL, bx1, by);
48 GetItemSizes(IDOK, bx2, by);
49 int y = ySize - my - by;
50 int x = xSize - mx - bx1;
51
52 InvalidateRect(NULL);
53
54 MoveItem(IDCANCEL, x, y, bx1, by);
55 MoveItem(IDOK, x - mx - bx2, y, bx2, by);
56 ChangeSubWindowSizeX(_comboBox, xSize - mx * 2);
57 return false;
58}
59
60void CComboDialog::OnOK()
61{
62 _comboBox.GetText(Value);
63 CModalDialog::OnOK();
64}
diff --git a/CPP/7zip/UI/FileManager/ComboDialog.h b/CPP/7zip/UI/FileManager/ComboDialog.h
new file mode 100644
index 0000000..29b28b5
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ComboDialog.h
@@ -0,0 +1,28 @@
1// ComboDialog.h
2
3#ifndef __COMBO_DIALOG_H
4#define __COMBO_DIALOG_H
5
6#include "../../../Windows/Control/ComboBox.h"
7#include "../../../Windows/Control/Dialog.h"
8
9#include "ComboDialogRes.h"
10
11class CComboDialog: public NWindows::NControl::CModalDialog
12{
13 NWindows::NControl::CComboBox _comboBox;
14 virtual void OnOK();
15 virtual bool OnInit();
16 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
17public:
18 // bool Sorted;
19 UString Title;
20 UString Static;
21 UString Value;
22 UStringVector Strings;
23
24 // CComboDialog(): Sorted(false) {};
25 INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COMBO, parentWindow); }
26};
27
28#endif
diff --git a/CPP/7zip/UI/FileManager/ComboDialog.rc b/CPP/7zip/UI/FileManager/ComboDialog.rc
new file mode 100644
index 0000000..fddb748
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ComboDialog.rc
@@ -0,0 +1,16 @@
1#include "ComboDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 240
5#define yc 64
6
7IDD_COMBO DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
8CAPTION "Combo"
9{
10 LTEXT "", IDT_COMBO, m, m, xc, 8
11 COMBOBOX IDC_COMBO, m, 20, xc, 65, MY_COMBO_WITH_EDIT
12 OK_CANCEL
13}
14
15#undef xc
16#undef yc
diff --git a/CPP/7zip/UI/FileManager/ComboDialogRes.h b/CPP/7zip/UI/FileManager/ComboDialogRes.h
new file mode 100644
index 0000000..a044797
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ComboDialogRes.h
@@ -0,0 +1,4 @@
1#define IDD_COMBO 98
2
3#define IDT_COMBO 100
4#define IDC_COMBO 101
diff --git a/CPP/7zip/UI/FileManager/Copy.bmp b/CPP/7zip/UI/FileManager/Copy.bmp
new file mode 100644
index 0000000..0f28a32
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Copy.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Copy2.bmp b/CPP/7zip/UI/FileManager/Copy2.bmp
new file mode 100644
index 0000000..ba88ded
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Copy2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/CopyDialog.cpp b/CPP/7zip/UI/FileManager/CopyDialog.cpp
new file mode 100644
index 0000000..4b17110
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/CopyDialog.cpp
@@ -0,0 +1,106 @@
1// CopyDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/FileName.h"
6
7#include "../../../Windows/Control/Static.h"
8
9#include "BrowseDialog.h"
10#include "CopyDialog.h"
11
12#ifdef LANG
13#include "LangUtils.h"
14#endif
15
16using namespace NWindows;
17
18bool CCopyDialog::OnInit()
19{
20 #ifdef LANG
21 LangSetDlgItems(*this, NULL, 0);
22 #endif
23 _path.Attach(GetItem(IDC_COPY));
24 SetText(Title);
25
26 NControl::CStatic staticContol;
27 staticContol.Attach(GetItem(IDT_COPY));
28 staticContol.SetText(Static);
29 #ifdef UNDER_CE
30 // we do it, since WinCE selects Value\something instead of Value !!!!
31 _path.AddString(Value);
32 #endif
33 FOR_VECTOR (i, Strings)
34 _path.AddString(Strings[i]);
35 _path.SetText(Value);
36 SetItemText(IDT_COPY_INFO, Info);
37 NormalizeSize(true);
38 return CModalDialog::OnInit();
39}
40
41bool CCopyDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
42{
43 int mx, my;
44 GetMargins(8, mx, my);
45 int bx1, bx2, by;
46 GetItemSizes(IDCANCEL, bx1, by);
47 GetItemSizes(IDOK, bx2, by);
48 int y = ySize - my - by;
49 int x = xSize - mx - bx1;
50
51 InvalidateRect(NULL);
52
53 {
54 RECT r;
55 GetClientRectOfItem(IDB_COPY_SET_PATH, r);
56 int bx = RECT_SIZE_X(r);
57 MoveItem(IDB_COPY_SET_PATH, xSize - mx - bx, r.top, bx, RECT_SIZE_Y(r));
58 ChangeSubWindowSizeX(_path, xSize - mx - mx - bx - mx);
59 }
60
61 {
62 RECT r;
63 GetClientRectOfItem(IDT_COPY_INFO, r);
64 NControl::CStatic staticContol;
65 staticContol.Attach(GetItem(IDT_COPY_INFO));
66 int yPos = r.top;
67 staticContol.Move(mx, yPos, xSize - mx * 2, y - 2 - yPos);
68 }
69
70 MoveItem(IDCANCEL, x, y, bx1, by);
71 MoveItem(IDOK, x - mx - bx2, y, bx2, by);
72
73 return false;
74}
75
76bool CCopyDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
77{
78 switch (buttonID)
79 {
80 case IDB_COPY_SET_PATH:
81 OnButtonSetPath();
82 return true;
83 }
84 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
85}
86
87void CCopyDialog::OnButtonSetPath()
88{
89 UString currentPath;
90 _path.GetText(currentPath);
91
92 const UString title = LangString(IDS_SET_FOLDER);
93
94 UString resultPath;
95 if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
96 return;
97 NFile::NName::NormalizeDirPathPrefix(resultPath);
98 _path.SetCurSel(-1);
99 _path.SetText(resultPath);
100}
101
102void CCopyDialog::OnOK()
103{
104 _path.GetText(Value);
105 CModalDialog::OnOK();
106}
diff --git a/CPP/7zip/UI/FileManager/CopyDialog.h b/CPP/7zip/UI/FileManager/CopyDialog.h
new file mode 100644
index 0000000..30fde71
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/CopyDialog.h
@@ -0,0 +1,31 @@
1// CopyDialog.h
2
3#ifndef __COPY_DIALOG_H
4#define __COPY_DIALOG_H
5
6#include "../../../Windows/Control/ComboBox.h"
7#include "../../../Windows/Control/Dialog.h"
8
9#include "CopyDialogRes.h"
10
11const int kCopyDialog_NumInfoLines = 11;
12
13class CCopyDialog: public NWindows::NControl::CModalDialog
14{
15 NWindows::NControl::CComboBox _path;
16 virtual void OnOK();
17 virtual bool OnInit();
18 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
19 void OnButtonSetPath();
20 bool OnButtonClicked(int buttonID, HWND buttonHWND);
21public:
22 UString Title;
23 UString Static;
24 UString Value;
25 UString Info;
26 UStringVector Strings;
27
28 INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_COPY, parentWindow); }
29};
30
31#endif
diff --git a/CPP/7zip/UI/FileManager/CopyDialog.rc b/CPP/7zip/UI/FileManager/CopyDialog.rc
new file mode 100644
index 0000000..73d3ea8
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/CopyDialog.rc
@@ -0,0 +1,20 @@
1#include "CopyDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 320
5#define yc 144
6
7#define y 40
8
9IDD_COPY DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
10CAPTION "Copy"
11{
12 LTEXT "", IDT_COPY, m, m, xc, 8
13 COMBOBOX IDC_COPY, m, 20, xc - bxsDots - m, 65, MY_COMBO_WITH_EDIT
14 PUSHBUTTON "...", IDB_COPY_SET_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP
15 LTEXT "", IDT_COPY_INFO, m, y, xc, by - y - 1, SS_NOPREFIX | SS_LEFTNOWORDWRAP
16 OK_CANCEL
17}
18
19#undef xc
20#undef yc
diff --git a/CPP/7zip/UI/FileManager/CopyDialogRes.h b/CPP/7zip/UI/FileManager/CopyDialogRes.h
new file mode 100644
index 0000000..85f5a39
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/CopyDialogRes.h
@@ -0,0 +1,8 @@
1#define IDD_COPY 96
2
3#define IDT_COPY 100
4#define IDC_COPY 101
5#define IDB_COPY_SET_PATH 102
6#define IDT_COPY_INFO 103
7
8#define IDS_SET_FOLDER 6007
diff --git a/CPP/7zip/UI/FileManager/Delete.bmp b/CPP/7zip/UI/FileManager/Delete.bmp
new file mode 100644
index 0000000..d1004d8
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Delete.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Delete2.bmp b/CPP/7zip/UI/FileManager/Delete2.bmp
new file mode 100644
index 0000000..60e08c6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Delete2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/DialogSize.h b/CPP/7zip/UI/FileManager/DialogSize.h
new file mode 100644
index 0000000..504541b
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/DialogSize.h
@@ -0,0 +1,16 @@
1// DialogSize.h
2
3#ifndef __DIALOG_SIZE_H
4#define __DIALOG_SIZE_H
5
6#include "../../../Windows/Control/Dialog.h"
7
8#ifdef UNDER_CE
9#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y);
10#define SIZED_DIALOG(big) (isBig ? big : big ## _2)
11#else
12#define BIG_DIALOG_SIZE(x, y)
13#define SIZED_DIALOG(big) big
14#endif
15
16#endif
diff --git a/CPP/7zip/UI/FileManager/EditDialog.cpp b/CPP/7zip/UI/FileManager/EditDialog.cpp
new file mode 100644
index 0000000..7f59672
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditDialog.cpp
@@ -0,0 +1,57 @@
1// EditDialog.cpp
2
3#include "StdAfx.h"
4
5#include "EditDialog.h"
6
7#ifdef LANG
8#include "LangUtils.h"
9#endif
10
11bool CEditDialog::OnInit()
12{
13 #ifdef LANG
14 LangSetDlgItems(*this, NULL, 0);
15 #endif
16 _edit.Attach(GetItem(IDE_EDIT));
17
18 SetText(Title);
19 _edit.SetText(Text);
20
21 NormalizeSize();
22 return CModalDialog::OnInit();
23}
24
25// #define MY_CLOSE_BUTTON__ID IDCANCEL
26#define MY_CLOSE_BUTTON__ID IDCLOSE
27
28bool CEditDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
29{
30 int mx, my;
31 GetMargins(8, mx, my);
32 int bx1, by;
33 GetItemSizes(MY_CLOSE_BUTTON__ID, bx1, by);
34
35 // int bx2;
36 // GetItemSizes(IDOK, bx2, by);
37
38 int y = ySize - my - by;
39 int x = xSize - mx - bx1;
40
41 /*
42 RECT rect;
43 GetClientRect(&rect);
44 rect.top = y - my;
45 InvalidateRect(&rect);
46 */
47 InvalidateRect(NULL);
48
49 MoveItem(MY_CLOSE_BUTTON__ID, x, y, bx1, by);
50 // MoveItem(IDOK, x - mx - bx2, y, bx2, by);
51 /*
52 if (wParam == SIZE_MAXSHOW || wParam == SIZE_MAXIMIZED || wParam == SIZE_MAXHIDE)
53 mx = 0;
54 */
55 _edit.Move(mx, my, xSize - mx * 2, y - my * 2);
56 return false;
57}
diff --git a/CPP/7zip/UI/FileManager/EditDialog.h b/CPP/7zip/UI/FileManager/EditDialog.h
new file mode 100644
index 0000000..d820516
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditDialog.h
@@ -0,0 +1,25 @@
1// EditDialog.h
2
3#ifndef __EDIT_DIALOG_H
4#define __EDIT_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7#include "../../../Windows/Control/Edit.h"
8
9#include "EditDialogRes.h"
10
11class CEditDialog: public NWindows::NControl::CModalDialog
12{
13 NWindows::NControl::CEdit _edit;
14 virtual bool OnInit();
15 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
16public:
17 UString Title;
18 UString Text;
19
20 INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_EDIT_DLG, wndParent); }
21
22 CEditDialog() {}
23};
24
25#endif
diff --git a/CPP/7zip/UI/FileManager/EditDialog.rc b/CPP/7zip/UI/FileManager/EditDialog.rc
new file mode 100644
index 0000000..cdb0b44
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditDialog.rc
@@ -0,0 +1,15 @@
1#include "EditDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 320
5#define yc 240
6
7IDD_EDIT_DLG DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
8CAPTION "Edit"
9{
10 // OK_CANCEL
11 MY_BUTTON__CLOSE
12
13 EDITTEXT IDE_EDIT, m, m, xc, yc - bys - m,
14 ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_HSCROLL | ES_WANTRETURN
15}
diff --git a/CPP/7zip/UI/FileManager/EditDialogRes.h b/CPP/7zip/UI/FileManager/EditDialogRes.h
new file mode 100644
index 0000000..58c5ca9
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditDialogRes.h
@@ -0,0 +1,2 @@
1#define IDD_EDIT_DLG 94
2#define IDE_EDIT 100
diff --git a/CPP/7zip/UI/FileManager/EditPage.cpp b/CPP/7zip/UI/FileManager/EditPage.cpp
new file mode 100644
index 0000000..0108904
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditPage.cpp
@@ -0,0 +1,147 @@
1// EditPage.cpp
2
3#include "StdAfx.h"
4
5#include "EditPage.h"
6#include "EditPageRes.h"
7
8#include "BrowseDialog.h"
9#include "HelpUtils.h"
10#include "LangUtils.h"
11#include "RegistryUtils.h"
12
13using namespace NWindows;
14
15static const UInt32 kLangIDs[] =
16{
17 IDT_EDIT_EDITOR,
18 IDT_EDIT_DIFF
19};
20
21static const UInt32 kLangIDs_Colon[] =
22{
23 IDT_EDIT_VIEWER
24};
25
26#define kEditTopic "FM/options.htm#editor"
27
28bool CEditPage::OnInit()
29{
30 _initMode = true;
31
32 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
33 LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));
34
35 _ctrls[0].Ctrl = IDE_EDIT_VIEWER; _ctrls[0].Button = IDB_EDIT_VIEWER;
36 _ctrls[1].Ctrl = IDE_EDIT_EDITOR; _ctrls[1].Button = IDB_EDIT_EDITOR;
37 _ctrls[2].Ctrl = IDE_EDIT_DIFF; _ctrls[2].Button = IDB_EDIT_DIFF;
38
39 for (unsigned i = 0; i < 3; i++)
40 {
41 CEditPageCtrl &c = _ctrls[i];
42 c.WasChanged = false;
43 c.Edit.Attach(GetItem(c.Ctrl));
44 UString path;
45 if (i < 2)
46 ReadRegEditor(i > 0, path);
47 else
48 ReadRegDiff(path);
49 c.Edit.SetText(path);
50 }
51
52 _initMode = false;
53
54 return CPropertyPage::OnInit();
55}
56
57LONG CEditPage::OnApply()
58{
59 for (unsigned i = 0; i < 3; i++)
60 {
61 CEditPageCtrl &c = _ctrls[i];
62 if (c.WasChanged)
63 {
64 UString path;
65 c.Edit.GetText(path);
66 if (i < 2)
67 SaveRegEditor(i > 0, path);
68 else
69 SaveRegDiff(path);
70 c.WasChanged = false;
71 }
72 }
73
74 return PSNRET_NOERROR;
75}
76
77void CEditPage::OnNotifyHelp()
78{
79 ShowHelpWindow(kEditTopic);
80}
81
82void SplitCmdLineSmart(const UString &cmd, UString &prg, UString &params);
83
84static void Edit_BrowseForFile(NWindows::NControl::CEdit &edit, HWND hwnd)
85{
86 UString cmd;
87 edit.GetText(cmd);
88
89 UString param;
90 UString prg;
91
92 SplitCmdLineSmart(cmd, prg, param);
93
94 UString resPath;
95
96 if (MyBrowseForFile(hwnd, 0, prg, NULL, L"*.exe", resPath))
97 {
98 resPath.Trim();
99 cmd = resPath;
100 /*
101 if (!param.IsEmpty() && !resPath.IsEmpty())
102 {
103 cmd.InsertAtFront(L'\"');
104 cmd += L'\"';
105 cmd.Add_Space();
106 cmd += param;
107 }
108 */
109
110 edit.SetText(cmd);
111 // Changed();
112 }
113}
114
115bool CEditPage::OnButtonClicked(int buttonID, HWND buttonHWND)
116{
117 for (unsigned i = 0; i < 3; i++)
118 {
119 CEditPageCtrl &c = _ctrls[i];
120 if (buttonID == c.Button)
121 {
122 Edit_BrowseForFile(c.Edit, *this);
123 return true;
124 }
125 }
126
127 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
128}
129
130bool CEditPage::OnCommand(int code, int itemID, LPARAM param)
131{
132 if (!_initMode && code == EN_CHANGE)
133 {
134 for (unsigned i = 0; i < 3; i++)
135 {
136 CEditPageCtrl &c = _ctrls[i];
137 if (itemID == c.Ctrl)
138 {
139 c.WasChanged = true;
140 Changed();
141 return true;
142 }
143 }
144 }
145
146 return CPropertyPage::OnCommand(code, itemID, param);
147}
diff --git a/CPP/7zip/UI/FileManager/EditPage.h b/CPP/7zip/UI/FileManager/EditPage.h
new file mode 100644
index 0000000..208edd8
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditPage.h
@@ -0,0 +1,30 @@
1// EditPage.h
2
3#ifndef __EDIT_PAGE_H
4#define __EDIT_PAGE_H
5
6#include "../../../Windows/Control/PropertyPage.h"
7#include "../../../Windows/Control/Edit.h"
8
9struct CEditPageCtrl
10{
11 NWindows::NControl::CEdit Edit;
12 bool WasChanged;
13 int Ctrl;
14 int Button;
15};
16
17class CEditPage: public NWindows::NControl::CPropertyPage
18{
19 CEditPageCtrl _ctrls[3];
20
21 bool _initMode;
22public:
23 virtual bool OnInit();
24 virtual void OnNotifyHelp();
25 virtual bool OnCommand(int code, int itemID, LPARAM param);
26 virtual LONG OnApply();
27 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
28};
29
30#endif
diff --git a/CPP/7zip/UI/FileManager/EditPage.rc b/CPP/7zip/UI/FileManager/EditPage.rc
new file mode 100644
index 0000000..38f74ea
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditPage.rc
@@ -0,0 +1,19 @@
1#include "EditPageRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 240
5#define yc 80
6
7IDD_EDIT MY_PAGE
8#include "EditPage2.rc"
9
10#ifdef UNDER_CE
11
12#undef xc
13
14#define xc SMALL_PAGE_SIZE_X
15
16IDD_EDIT_2 MY_PAGE
17#include "EditPage2.rc"
18
19#endif
diff --git a/CPP/7zip/UI/FileManager/EditPage2.rc b/CPP/7zip/UI/FileManager/EditPage2.rc
new file mode 100644
index 0000000..2d6554f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditPage2.rc
@@ -0,0 +1,14 @@
1CAPTION "Editor"
2{
3 LTEXT "&View:", IDT_EDIT_VIEWER, m, m, xc, 8
4 EDITTEXT IDE_EDIT_VIEWER, m, m + 12, xc - m - bxsDots, 14, ES_AUTOHSCROLL
5 PUSHBUTTON "...", IDB_EDIT_VIEWER, xs - m - bxsDots, m + 11, bxsDots, bys
6
7 LTEXT "&Editor:", IDT_EDIT_EDITOR, m, m + 32, xc, 8
8 EDITTEXT IDE_EDIT_EDITOR, m, m + 44, xc - m - bxsDots, 14, ES_AUTOHSCROLL
9 PUSHBUTTON "...", IDB_EDIT_EDITOR, xs - m - bxsDots, m + 43, bxsDots, bys
10
11 LTEXT "&Diff:", IDT_EDIT_DIFF, m, m + 64, xc, 8
12 EDITTEXT IDE_EDIT_DIFF, m, m + 76, xc - m - bxsDots, 14, ES_AUTOHSCROLL
13 PUSHBUTTON "...", IDB_EDIT_DIFF, xs - m - bxsDots, m + 75, bxsDots, bys
14}
diff --git a/CPP/7zip/UI/FileManager/EditPageRes.h b/CPP/7zip/UI/FileManager/EditPageRes.h
new file mode 100644
index 0000000..017d702
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EditPageRes.h
@@ -0,0 +1,15 @@
1#define IDD_EDIT 2103
2#define IDD_EDIT_2 12103
3
4#define IDT_EDIT_VIEWER 543
5#define IDT_EDIT_EDITOR 2104
6#define IDT_EDIT_DIFF 2105
7
8#define IDE_EDIT_VIEWER 100
9#define IDB_EDIT_VIEWER 101
10
11#define IDE_EDIT_EDITOR 102
12#define IDB_EDIT_EDITOR 103
13
14#define IDE_EDIT_DIFF 104
15#define IDB_EDIT_DIFF 105
diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp
new file mode 100644
index 0000000..389aa3e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.cpp
@@ -0,0 +1,108 @@
1// EnumFormatEtc.cpp
2
3#include "StdAfx.h"
4
5#include "EnumFormatEtc.h"
6#include "MyCom2.h"
7
8class CEnumFormatEtc :
9public IEnumFORMATETC,
10public CMyUnknownImp
11{
12public:
13 MY_UNKNOWN_IMP1_MT(IEnumFORMATETC)
14
15 STDMETHOD(Next)(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
16 STDMETHOD(Skip)(ULONG celt);
17 STDMETHOD(Reset)(void);
18 STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);
19
20 CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats);
21 ~CEnumFormatEtc();
22
23private:
24 LONG m_RefCount;
25 ULONG m_NumFormats;
26 FORMATETC *m_Formats;
27 ULONG m_Index;
28};
29
30static void DeepCopyFormatEtc(FORMATETC *dest, const FORMATETC *src)
31{
32 *dest = *src;
33 if (src->ptd)
34 {
35 dest->ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(sizeof(DVTARGETDEVICE));
36 *(dest->ptd) = *(src->ptd);
37 }
38}
39
40CEnumFormatEtc::CEnumFormatEtc(const FORMATETC *pFormatEtc, ULONG numFormats)
41{
42 m_RefCount = 1;
43 m_Index = 0;
44 m_NumFormats = 0;
45 m_Formats = new FORMATETC[numFormats];
46 // if (m_Formats)
47 {
48 m_NumFormats = numFormats;
49 for (ULONG i = 0; i < numFormats; i++)
50 DeepCopyFormatEtc(&m_Formats[i], &pFormatEtc[i]);
51 }
52}
53
54CEnumFormatEtc::~CEnumFormatEtc()
55{
56 if (m_Formats)
57 {
58 for (ULONG i = 0; i < m_NumFormats; i++)
59 if (m_Formats[i].ptd)
60 CoTaskMemFree(m_Formats[i].ptd);
61 delete []m_Formats;
62 }
63}
64
65STDMETHODIMP CEnumFormatEtc::Next(ULONG celt, FORMATETC *pFormatEtc, ULONG *pceltFetched)
66{
67 ULONG copied = 0;
68 if (celt == 0 || pFormatEtc == 0)
69 return E_INVALIDARG;
70 while (m_Index < m_NumFormats && copied < celt)
71 {
72 DeepCopyFormatEtc(&pFormatEtc[copied], &m_Formats[m_Index]);
73 copied++;
74 m_Index++;
75 }
76 if (pceltFetched != 0)
77 *pceltFetched = copied;
78 return (copied == celt) ? S_OK : S_FALSE;
79}
80
81STDMETHODIMP CEnumFormatEtc::Skip(ULONG celt)
82{
83 m_Index += celt;
84 return (m_Index <= m_NumFormats) ? S_OK : S_FALSE;
85}
86
87STDMETHODIMP CEnumFormatEtc::Reset(void)
88{
89 m_Index = 0;
90 return S_OK;
91}
92
93STDMETHODIMP CEnumFormatEtc::Clone(IEnumFORMATETC ** ppEnumFormatEtc)
94{
95 HRESULT hResult = CreateEnumFormatEtc(m_NumFormats, m_Formats, ppEnumFormatEtc);
96 if (hResult == S_OK)
97 ((CEnumFormatEtc *)*ppEnumFormatEtc)->m_Index = m_Index;
98 return hResult;
99}
100
101// replacement for SHCreateStdEnumFmtEtc
102HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat)
103{
104 if (numFormats == 0 || formats == 0 || enumFormat == 0)
105 return E_INVALIDARG;
106 *enumFormat = new CEnumFormatEtc(formats, numFormats);
107 return (*enumFormat) ? S_OK : E_OUTOFMEMORY;
108}
diff --git a/CPP/7zip/UI/FileManager/EnumFormatEtc.h b/CPP/7zip/UI/FileManager/EnumFormatEtc.h
new file mode 100644
index 0000000..93a53cb
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/EnumFormatEtc.h
@@ -0,0 +1,10 @@
1// EnumFormatEtc.h
2
3#ifndef __ENUMFORMATETC_H
4#define __ENUMFORMATETC_H
5
6#include "../../../Common/MyWindows.h"
7
8HRESULT CreateEnumFormatEtc(UINT numFormats, const FORMATETC *formats, IEnumFORMATETC **enumFormat);
9
10#endif
diff --git a/CPP/7zip/UI/FileManager/Extract.bmp b/CPP/7zip/UI/FileManager/Extract.bmp
new file mode 100644
index 0000000..0aeba92
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Extract.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Extract2.bmp b/CPP/7zip/UI/FileManager/Extract2.bmp
new file mode 100644
index 0000000..a7e5775
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Extract2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.cpp b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
new file mode 100644
index 0000000..232717f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.cpp
@@ -0,0 +1,1049 @@
1// ExtractCallback.cpp
2
3#include "StdAfx.h"
4
5
6#include "../../../Common/ComTry.h"
7#include "../../../Common/IntToString.h"
8#include "../../../Common/Lang.h"
9#include "../../../Common/StringConvert.h"
10
11#include "../../../Windows/ErrorMsg.h"
12#include "../../../Windows/FileDir.h"
13#include "../../../Windows/FileFind.h"
14#include "../../../Windows/PropVariantConv.h"
15
16#include "../../Common/FilePathAutoRename.h"
17#include "../../Common/StreamUtils.h"
18#include "../Common/ExtractingFilePath.h"
19
20#ifndef _SFX
21#include "../Common/ZipRegistry.h"
22#endif
23
24#include "../GUI/ExtractRes.h"
25#include "resourceGui.h"
26
27#include "ExtractCallback.h"
28#include "FormatUtils.h"
29#include "LangUtils.h"
30#include "OverwriteDialog.h"
31#ifndef _NO_CRYPTO
32#include "PasswordDialog.h"
33#endif
34#include "PropertyName.h"
35
36using namespace NWindows;
37using namespace NFile;
38using namespace NFind;
39
40CExtractCallbackImp::~CExtractCallbackImp() {}
41
42void CExtractCallbackImp::Init()
43{
44 _lang_Extracting = LangString(IDS_PROGRESS_EXTRACTING);
45 _lang_Testing = LangString(IDS_PROGRESS_TESTING);
46 _lang_Skipping = LangString(IDS_PROGRESS_SKIPPING);
47 _lang_Reading = "Reading";
48
49 NumArchiveErrors = 0;
50 ThereAreMessageErrors = false;
51 #ifndef _SFX
52 NumFolders = NumFiles = 0;
53 NeedAddFile = false;
54 #endif
55}
56
57void CExtractCallbackImp::AddError_Message(LPCWSTR s)
58{
59 ThereAreMessageErrors = true;
60 ProgressDialog->Sync.AddError_Message(s);
61}
62
63#ifndef _SFX
64
65STDMETHODIMP CExtractCallbackImp::SetNumFiles(UInt64
66 #ifndef _SFX
67 numFiles
68 #endif
69 )
70{
71 #ifndef _SFX
72 ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
73 #endif
74 return S_OK;
75}
76
77#endif
78
79STDMETHODIMP CExtractCallbackImp::SetTotal(UInt64 total)
80{
81 ProgressDialog->Sync.Set_NumBytesTotal(total);
82 return S_OK;
83}
84
85STDMETHODIMP CExtractCallbackImp::SetCompleted(const UInt64 *value)
86{
87 return ProgressDialog->Sync.Set_NumBytesCur(value);
88}
89
90HRESULT CExtractCallbackImp::Open_CheckBreak()
91{
92 return ProgressDialog->Sync.CheckStop();
93}
94
95HRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)
96{
97 HRESULT res = S_OK;
98 if (!MultiArcMode)
99 {
100 if (files)
101 {
102 _totalFilesDefined = true;
103 // res = ProgressDialog->Sync.Set_NumFilesTotal(*files);
104 }
105 else
106 _totalFilesDefined = false;
107
108 if (bytes)
109 {
110 _totalBytesDefined = true;
111 ProgressDialog->Sync.Set_NumBytesTotal(*bytes);
112 }
113 else
114 _totalBytesDefined = false;
115 }
116
117 return res;
118}
119
120HRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)
121{
122 if (!MultiArcMode)
123 {
124 if (files)
125 {
126 ProgressDialog->Sync.Set_NumFilesCur(*files);
127 }
128
129 if (bytes)
130 {
131 }
132 }
133
134 return ProgressDialog->Sync.CheckStop();
135}
136
137HRESULT CExtractCallbackImp::Open_Finished()
138{
139 return ProgressDialog->Sync.CheckStop();
140}
141
142#ifndef _NO_CRYPTO
143
144HRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)
145{
146 return CryptoGetTextPassword(password);
147}
148
149/*
150HRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)
151{
152 passwordIsDefined = PasswordIsDefined;
153 password = Password;
154 return S_OK;
155}
156
157bool CExtractCallbackImp::Open_WasPasswordAsked()
158{
159 return PasswordWasAsked;
160}
161
162void CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag()
163{
164 PasswordWasAsked = false;
165}
166*/
167
168#endif
169
170
171#ifndef _SFX
172STDMETHODIMP CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
173{
174 ProgressDialog->Sync.Set_Ratio(inSize, outSize);
175 return S_OK;
176}
177#endif
178
179/*
180STDMETHODIMP CExtractCallbackImp::SetTotalFiles(UInt64 total)
181{
182 ProgressDialog->Sync.SetNumFilesTotal(total);
183 return S_OK;
184}
185
186STDMETHODIMP CExtractCallbackImp::SetCompletedFiles(const UInt64 *value)
187{
188 if (value != NULL)
189 ProgressDialog->Sync.SetNumFilesCur(*value);
190 return S_OK;
191}
192*/
193
194STDMETHODIMP CExtractCallbackImp::AskOverwrite(
195 const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
196 const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
197 Int32 *answer)
198{
199 COverwriteDialog dialog;
200
201 dialog.OldFileInfo.SetTime(existTime);
202 dialog.OldFileInfo.SetSize(existSize);
203 dialog.OldFileInfo.Name = existName;
204
205 dialog.NewFileInfo.SetTime(newTime);
206 dialog.NewFileInfo.SetSize(newSize);
207 dialog.NewFileInfo.Name = newName;
208
209 ProgressDialog->WaitCreating();
210 INT_PTR writeAnswer = dialog.Create(*ProgressDialog);
211
212 switch (writeAnswer)
213 {
214 case IDCANCEL: *answer = NOverwriteAnswer::kCancel; return E_ABORT;
215 case IDYES: *answer = NOverwriteAnswer::kYes; break;
216 case IDNO: *answer = NOverwriteAnswer::kNo; break;
217 case IDB_YES_TO_ALL: *answer = NOverwriteAnswer::kYesToAll; break;
218 case IDB_NO_TO_ALL: *answer = NOverwriteAnswer::kNoToAll; break;
219 case IDB_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break;
220 default: return E_FAIL;
221 }
222 return S_OK;
223}
224
225
226STDMETHODIMP CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */)
227{
228 _isFolder = IntToBool(isFolder);
229 _currentFilePath = name;
230
231 const UString *msg = &_lang_Empty;
232 switch (askExtractMode)
233 {
234 case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break;
235 case NArchive::NExtract::NAskMode::kTest: msg = &_lang_Testing; break;
236 case NArchive::NExtract::NAskMode::kSkip: msg = &_lang_Skipping; break;
237 case NArchive::NExtract::NAskMode::kReadExternal: msg = &_lang_Reading; break;
238 // default: s = "Unknown operation";
239 }
240
241 return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder));
242}
243
244STDMETHODIMP CExtractCallbackImp::MessageError(const wchar_t *s)
245{
246 AddError_Message(s);
247 return S_OK;
248}
249
250HRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path)
251{
252 ThereAreMessageErrors = true;
253 ProgressDialog->Sync.AddError_Message_Name(GetUnicodeString(message), fs2us(path));
254 return S_OK;
255}
256
257#ifndef _SFX
258
259STDMETHODIMP CExtractCallbackImp::ShowMessage(const wchar_t *s)
260{
261 AddError_Message(s);
262 return S_OK;
263}
264
265#endif
266
267void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
268void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s)
269{
270 s.Empty();
271
272 if (opRes == NArchive::NExtract::NOperationResult::kOK)
273 return;
274
275 UINT messageID = 0;
276 UINT id = 0;
277
278 switch (opRes)
279 {
280 case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
281 messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;
282 id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;
283 break;
284 case NArchive::NExtract::NOperationResult::kDataError:
285 messageID = encrypted ?
286 IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:
287 IDS_EXTRACT_MESSAGE_DATA_ERROR;
288 id = IDS_EXTRACT_MSG_DATA_ERROR;
289 break;
290 case NArchive::NExtract::NOperationResult::kCRCError:
291 messageID = encrypted ?
292 IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:
293 IDS_EXTRACT_MESSAGE_CRC_ERROR;
294 id = IDS_EXTRACT_MSG_CRC_ERROR;
295 break;
296 case NArchive::NExtract::NOperationResult::kUnavailable:
297 id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;
298 break;
299 case NArchive::NExtract::NOperationResult::kUnexpectedEnd:
300 id = IDS_EXTRACT_MSG_UEXPECTED_END;
301 break;
302 case NArchive::NExtract::NOperationResult::kDataAfterEnd:
303 id = IDS_EXTRACT_MSG_DATA_AFTER_END;
304 break;
305 case NArchive::NExtract::NOperationResult::kIsNotArc:
306 id = IDS_EXTRACT_MSG_IS_NOT_ARC;
307 break;
308 case NArchive::NExtract::NOperationResult::kHeadersError:
309 id = IDS_EXTRACT_MSG_HEADERS_ERROR;
310 break;
311 case NArchive::NExtract::NOperationResult::kWrongPassword:
312 id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM;
313 break;
314 /*
315 default:
316 messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;
317 break;
318 */
319 }
320
321 UString msg;
322 UString msgOld;
323
324 #ifndef _SFX
325 if (id != 0)
326 LangString_OnlyFromLangFile(id, msg);
327 if (messageID != 0 && msg.IsEmpty())
328 LangString_OnlyFromLangFile(messageID, msgOld);
329 #endif
330
331 if (msg.IsEmpty() && !msgOld.IsEmpty())
332 s = MyFormatNew(msgOld, fileName);
333 else
334 {
335 if (msg.IsEmpty() && id != 0)
336 LangString(id, msg);
337 if (!msg.IsEmpty())
338 s += msg;
339 else
340 {
341 s += "Error #";
342 s.Add_UInt32(opRes);
343 }
344
345 if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword)
346 {
347 // s += " : ";
348 // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED);
349 s += " : ";
350 AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
351 }
352 s += " : ";
353 s += fileName;
354 }
355}
356
357STDMETHODIMP CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted)
358{
359 switch (opRes)
360 {
361 case NArchive::NExtract::NOperationResult::kOK:
362 break;
363 default:
364 {
365 UString s;
366 SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s);
367 Add_ArchiveName_Error();
368 AddError_Message(s);
369 }
370 }
371
372 #ifndef _SFX
373 if (_isFolder)
374 NumFolders++;
375 else
376 NumFiles++;
377 ProgressDialog->Sync.Set_NumFilesCur(NumFiles);
378 #endif
379
380 return S_OK;
381}
382
383STDMETHODIMP CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)
384{
385 if (opRes != NArchive::NExtract::NOperationResult::kOK)
386 {
387 UString s;
388 SetExtractErrorMessage(opRes, encrypted, name, s);
389 Add_ArchiveName_Error();
390 AddError_Message(s);
391 }
392 return S_OK;
393}
394
395////////////////////////////////////////
396// IExtractCallbackUI
397
398HRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */)
399{
400 #ifndef _SFX
401 RINOK(ProgressDialog->Sync.CheckStop());
402 ProgressDialog->Sync.Set_TitleFileName(name);
403 #endif
404 _currentArchivePath = name;
405 return S_OK;
406}
407
408HRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path)
409{
410 _currentFilePath = path;
411 #ifndef _SFX
412 ProgressDialog->Sync.Set_FilePath(path);
413 #endif
414 return S_OK;
415}
416
417#ifndef _SFX
418
419HRESULT CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path)
420{
421 #ifndef _SFX
422 if (NeedAddFile)
423 NumFiles++;
424 NeedAddFile = true;
425 ProgressDialog->Sync.Set_NumFilesCur(NumFiles);
426 #endif
427 return SetCurrentFilePath2(path);
428}
429
430#endif
431
432UString HResultToMessage(HRESULT errorCode);
433
434static const UInt32 k_ErrorFlagsIds[] =
435{
436 IDS_EXTRACT_MSG_IS_NOT_ARC,
437 IDS_EXTRACT_MSG_HEADERS_ERROR,
438 IDS_EXTRACT_MSG_HEADERS_ERROR,
439 IDS_OPEN_MSG_UNAVAILABLE_START,
440 IDS_OPEN_MSG_UNCONFIRMED_START,
441 IDS_EXTRACT_MSG_UEXPECTED_END,
442 IDS_EXTRACT_MSG_DATA_AFTER_END,
443 IDS_EXTRACT_MSG_UNSUPPORTED_METHOD,
444 IDS_OPEN_MSG_UNSUPPORTED_FEATURE,
445 IDS_EXTRACT_MSG_DATA_ERROR,
446 IDS_EXTRACT_MSG_CRC_ERROR
447};
448
449static void AddNewLineString(UString &s, const UString &m)
450{
451 s += m;
452 s.Add_LF();
453}
454
455UString GetOpenArcErrorMessage(UInt32 errorFlags);
456UString GetOpenArcErrorMessage(UInt32 errorFlags)
457{
458 UString s;
459
460 for (unsigned i = 0; i < ARRAY_SIZE(k_ErrorFlagsIds); i++)
461 {
462 UInt32 f = ((UInt32)1 << i);
463 if ((errorFlags & f) == 0)
464 continue;
465 UInt32 id = k_ErrorFlagsIds[i];
466 UString m = LangString(id);
467 if (m.IsEmpty())
468 continue;
469 if (f == kpv_ErrorFlags_EncryptedHeadersError)
470 {
471 m += " : ";
472 AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);
473 }
474 if (!s.IsEmpty())
475 s.Add_LF();
476 s += m;
477 errorFlags &= ~f;
478 }
479
480 if (errorFlags != 0)
481 {
482 char sz[16];
483 sz[0] = '0';
484 sz[1] = 'x';
485 ConvertUInt32ToHex(errorFlags, sz + 2);
486 if (!s.IsEmpty())
487 s.Add_LF();
488 s += sz;
489 }
490
491 return s;
492}
493
494static void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)
495{
496 UInt32 errorFlags = er.GetErrorFlags();
497 UInt32 warningFlags = er.GetWarningFlags();
498
499 if (errorFlags != 0)
500 AddNewLineString(s, GetOpenArcErrorMessage(errorFlags));
501
502 if (!er.ErrorMessage.IsEmpty())
503 AddNewLineString(s, er.ErrorMessage);
504
505 if (warningFlags != 0)
506 {
507 s += GetNameOfProperty(kpidWarningFlags, L"Warnings");
508 s += ":";
509 s.Add_LF();
510 AddNewLineString(s, GetOpenArcErrorMessage(warningFlags));
511 }
512
513 if (!er.WarningMessage.IsEmpty())
514 {
515 s += GetNameOfProperty(kpidWarning, L"Warning");
516 s += ": ";
517 s += er.WarningMessage;
518 s.Add_LF();
519 }
520}
521
522static UString GetBracedType(const wchar_t *type)
523{
524 UString s ('[');
525 s += type;
526 s += ']';
527 return s;
528}
529
530void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result);
531void OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)
532{
533 FOR_VECTOR (level, arcLink.Arcs)
534 {
535 const CArc &arc = arcLink.Arcs[level];
536 const CArcErrorInfo &er = arc.ErrorInfo;
537
538 if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0)
539 continue;
540
541 if (s.IsEmpty())
542 {
543 s += name;
544 s.Add_LF();
545 }
546
547 if (level != 0)
548 {
549 AddNewLineString(s, arc.Path);
550 }
551
552 ErrorInfo_Print(s, er);
553
554 if (er.ErrorFormatIndex >= 0)
555 {
556 AddNewLineString(s, GetNameOfProperty(kpidWarning, L"Warning"));
557 if (arc.FormatIndex == er.ErrorFormatIndex)
558 {
559 AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET));
560 }
561 else
562 {
563 AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex))));
564 AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex))));
565 }
566 }
567 }
568
569 if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK)
570 {
571 s += name;
572 s.Add_LF();
573 if (!arcLink.Arcs.IsEmpty())
574 AddNewLineString(s, arcLink.NonOpen_ArcPath);
575
576 if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE)
577 {
578 UINT id = IDS_CANT_OPEN_ARCHIVE;
579 UString param;
580 if (arcLink.PasswordWasAsked)
581 id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE;
582 else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
583 {
584 id = IDS_CANT_OPEN_AS_TYPE;
585 param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex));
586 }
587 UString s2 = MyFormatNew(id, param);
588 s2.Replace(L" ''", L"");
589 s2.Replace(L"''", L"");
590 s += s2;
591 }
592 else
593 s += HResultToMessage(result);
594
595 s.Add_LF();
596 ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo);
597 }
598
599 if (!s.IsEmpty() && s.Back() == '\n')
600 s.DeleteBack();
601}
602
603HRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)
604{
605 _currentArchivePath = name;
606 _needWriteArchivePath = true;
607
608 UString s;
609 OpenResult_GUI(s, codecs, arcLink, name, result);
610 if (!s.IsEmpty())
611 {
612 NumArchiveErrors++;
613 AddError_Message(s);
614 _needWriteArchivePath = false;
615 }
616
617 return S_OK;
618}
619
620HRESULT CExtractCallbackImp::ThereAreNoFiles()
621{
622 return S_OK;
623}
624
625void CExtractCallbackImp::Add_ArchiveName_Error()
626{
627 if (_needWriteArchivePath)
628 {
629 if (!_currentArchivePath.IsEmpty())
630 AddError_Message(_currentArchivePath);
631 _needWriteArchivePath = false;
632 }
633}
634
635HRESULT CExtractCallbackImp::ExtractResult(HRESULT result)
636{
637 if (result == S_OK)
638 return result;
639 NumArchiveErrors++;
640 if (result == E_ABORT
641 || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)
642 )
643 return result;
644
645 Add_ArchiveName_Error();
646 if (!_currentFilePath.IsEmpty())
647 MessageError(_currentFilePath);
648 MessageError(NError::MyFormatMessage(result));
649 return S_OK;
650}
651
652#ifndef _NO_CRYPTO
653
654HRESULT CExtractCallbackImp::SetPassword(const UString &password)
655{
656 PasswordIsDefined = true;
657 Password = password;
658 return S_OK;
659}
660
661STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)
662{
663 PasswordWasAsked = true;
664 if (!PasswordIsDefined)
665 {
666 CPasswordDialog dialog;
667 #ifndef _SFX
668 bool showPassword = NExtract::Read_ShowPassword();
669 dialog.ShowPassword = showPassword;
670 #endif
671 ProgressDialog->WaitCreating();
672 if (dialog.Create(*ProgressDialog) != IDOK)
673 return E_ABORT;
674 Password = dialog.Password;
675 PasswordIsDefined = true;
676 #ifndef _SFX
677 if (dialog.ShowPassword != showPassword)
678 NExtract::Save_ShowPassword(dialog.ShowPassword);
679 #endif
680 }
681 return StringToBstr(Password, password);
682}
683
684#endif
685
686#ifndef _SFX
687
688STDMETHODIMP CExtractCallbackImp::AskWrite(
689 const wchar_t *srcPath, Int32 srcIsFolder,
690 const FILETIME *srcTime, const UInt64 *srcSize,
691 const wchar_t *destPath,
692 BSTR *destPathResult,
693 Int32 *writeAnswer)
694{
695 UString destPathResultTemp = destPath;
696
697 // RINOK(StringToBstr(destPath, destPathResult));
698
699 *destPathResult = 0;
700 *writeAnswer = BoolToInt(false);
701
702 FString destPathSys = us2fs(destPath);
703 bool srcIsFolderSpec = IntToBool(srcIsFolder);
704 CFileInfo destFileInfo;
705
706 if (destFileInfo.Find(destPathSys))
707 {
708 if (srcIsFolderSpec)
709 {
710 if (!destFileInfo.IsDir())
711 {
712 RINOK(MessageError("Cannot replace file with folder with same name", destPathSys));
713 return E_ABORT;
714 }
715 *writeAnswer = BoolToInt(false);
716 return S_OK;
717 }
718
719 if (destFileInfo.IsDir())
720 {
721 RINOK(MessageError("Cannot replace folder with file with same name", destPathSys));
722 *writeAnswer = BoolToInt(false);
723 return S_OK;
724 }
725
726 switch (OverwriteMode)
727 {
728 case NExtract::NOverwriteMode::kSkip:
729 return S_OK;
730 case NExtract::NOverwriteMode::kAsk:
731 {
732 Int32 overwriteResult;
733 UString destPathSpec = destPath;
734 int slashPos = destPathSpec.ReverseFind_PathSepar();
735 destPathSpec.DeleteFrom((unsigned)(slashPos + 1));
736 destPathSpec += fs2us(destFileInfo.Name);
737
738 RINOK(AskOverwrite(
739 destPathSpec,
740 &destFileInfo.MTime, &destFileInfo.Size,
741 srcPath,
742 srcTime, srcSize,
743 &overwriteResult));
744
745 switch (overwriteResult)
746 {
747 case NOverwriteAnswer::kCancel: return E_ABORT;
748 case NOverwriteAnswer::kNo: return S_OK;
749 case NOverwriteAnswer::kNoToAll: OverwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;
750 case NOverwriteAnswer::kYes: break;
751 case NOverwriteAnswer::kYesToAll: OverwriteMode = NExtract::NOverwriteMode::kOverwrite; break;
752 case NOverwriteAnswer::kAutoRename: OverwriteMode = NExtract::NOverwriteMode::kRename; break;
753 default:
754 return E_FAIL;
755 }
756 break;
757 }
758 default:
759 break;
760 }
761
762 if (OverwriteMode == NExtract::NOverwriteMode::kRename)
763 {
764 if (!AutoRenamePath(destPathSys))
765 {
766 RINOK(MessageError("Cannot create name for file", destPathSys));
767 return E_ABORT;
768 }
769 destPathResultTemp = fs2us(destPathSys);
770 }
771 else
772 {
773 if (NFind::DoesFileExist_Raw(destPathSys))
774 if (!NDir::DeleteFileAlways(destPathSys))
775 if (GetLastError() != ERROR_FILE_NOT_FOUND)
776 {
777 RINOK(MessageError("Cannot delete output file", destPathSys));
778 return E_ABORT;
779 }
780 }
781 }
782 *writeAnswer = BoolToInt(true);
783 return StringToBstr(destPathResultTemp, destPathResult);
784}
785
786
787STDMETHODIMP CExtractCallbackImp::UseExtractToStream(Int32 *res)
788{
789 *res = BoolToInt(StreamMode);
790 return S_OK;
791}
792
793static HRESULT GetTime(IGetProp *getProp, PROPID propID, FILETIME &ft, bool &ftDefined)
794{
795 ftDefined = false;
796 NCOM::CPropVariant prop;
797 RINOK(getProp->GetProp(propID, &prop));
798 if (prop.vt == VT_FILETIME)
799 {
800 ft = prop.filetime;
801 ftDefined = (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0);
802 }
803 else if (prop.vt != VT_EMPTY)
804 return E_FAIL;
805 return S_OK;
806}
807
808
809static HRESULT GetItemBoolProp(IGetProp *getProp, PROPID propID, bool &result)
810{
811 NCOM::CPropVariant prop;
812 result = false;
813 RINOK(getProp->GetProp(propID, &prop));
814 if (prop.vt == VT_BOOL)
815 result = VARIANT_BOOLToBool(prop.boolVal);
816 else if (prop.vt != VT_EMPTY)
817 return E_FAIL;
818 return S_OK;
819}
820
821
822STDMETHODIMP CExtractCallbackImp::GetStream7(const wchar_t *name,
823 Int32 isDir,
824 ISequentialOutStream **outStream, Int32 askExtractMode,
825 IGetProp *getProp)
826{
827 COM_TRY_BEGIN
828 *outStream = 0;
829 _newVirtFileWasAdded = false;
830 _hashStreamWasUsed = false;
831 _needUpdateStat = false;
832
833 if (_hashStream)
834 _hashStreamSpec->ReleaseStream();
835
836 GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream);
837
838 if (!ProcessAltStreams && _isAltStream)
839 return S_OK;
840
841 _filePath = name;
842 _isFolder = IntToBool(isDir);
843 _curSize = 0;
844 _curSizeDefined = false;
845
846 UInt64 size = 0;
847 bool sizeDefined;
848 {
849 NCOM::CPropVariant prop;
850 RINOK(getProp->GetProp(kpidSize, &prop));
851 sizeDefined = ConvertPropVariantToUInt64(prop, size);
852 }
853
854 if (sizeDefined)
855 {
856 _curSize = size;
857 _curSizeDefined = true;
858 }
859
860 if (askExtractMode != NArchive::NExtract::NAskMode::kExtract &&
861 askExtractMode != NArchive::NExtract::NAskMode::kTest)
862 return S_OK;
863
864 _needUpdateStat = true;
865
866 CMyComPtr<ISequentialOutStream> outStreamLoc;
867
868 if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract)
869 {
870 CVirtFile &file = VirtFileSystemSpec->AddNewFile();
871 _newVirtFileWasAdded = true;
872 file.Name = name;
873 file.IsDir = IntToBool(isDir);
874 file.IsAltStream = _isAltStream;
875 file.Size = 0;
876
877 RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTimeDefined));
878 RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATimeDefined));
879 RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTimeDefined));
880
881 NCOM::CPropVariant prop;
882 RINOK(getProp->GetProp(kpidAttrib, &prop));
883 if (prop.vt == VT_UI4)
884 {
885 file.Attrib = prop.ulVal;
886 file.AttribDefined = true;
887 }
888 // else if (isDir) file.Attrib = FILE_ATTRIBUTE_DIRECTORY;
889
890 file.ExpectedSize = 0;
891 if (sizeDefined)
892 file.ExpectedSize = size;
893 outStreamLoc = VirtFileSystem;
894 }
895
896 if (_hashStream)
897 {
898 {
899 _hashStreamSpec->SetStream(outStreamLoc);
900 outStreamLoc = _hashStream;
901 _hashStreamSpec->Init(true);
902 _hashStreamWasUsed = true;
903 }
904 }
905
906 if (outStreamLoc)
907 *outStream = outStreamLoc.Detach();
908 return S_OK;
909 COM_TRY_END
910}
911
912STDMETHODIMP CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode)
913{
914 COM_TRY_BEGIN
915 _needUpdateStat = (
916 askExtractMode == NArchive::NExtract::NAskMode::kExtract
917 || askExtractMode == NArchive::NExtract::NAskMode::kTest
918 || askExtractMode == NArchive::NExtract::NAskMode::kReadExternal
919 );
920
921 /*
922 _extractMode = false;
923 switch (askExtractMode)
924 {
925 case NArchive::NExtract::NAskMode::kExtract:
926 if (_testMode)
927 askExtractMode = NArchive::NExtract::NAskMode::kTest;
928 else
929 _extractMode = true;
930 break;
931 };
932 */
933 return SetCurrentFilePath2(_filePath);
934 COM_TRY_END
935}
936
937STDMETHODIMP CExtractCallbackImp::SetOperationResult8(Int32 opRes, Int32 encrypted, UInt64 size)
938{
939 COM_TRY_BEGIN
940 if (VirtFileSystem && _newVirtFileWasAdded)
941 {
942 // FIXME: probably we must request file size from VirtFileSystem
943 // _curSize = VirtFileSystem->GetLastFileSize()
944 // _curSizeDefined = true;
945 RINOK(VirtFileSystemSpec->CloseMemFile());
946 }
947 if (_hashStream && _hashStreamWasUsed)
948 {
949 _hashStreamSpec->_hash->Final(_isFolder, _isAltStream, _filePath);
950 _curSize = _hashStreamSpec->GetSize();
951 _curSizeDefined = true;
952 _hashStreamSpec->ReleaseStream();
953 _hashStreamWasUsed = false;
954 }
955 else if (_hashCalc && _needUpdateStat)
956 {
957 _hashCalc->SetSize(size); // (_curSize) before 21.04
958 _hashCalc->Final(_isFolder, _isAltStream, _filePath);
959 }
960 return SetOperationResult(opRes, encrypted);
961 COM_TRY_END
962}
963
964
965
966// static const UInt32 kBlockSize = ((UInt32)1 << 31);
967
968STDMETHODIMP CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize)
969{
970 if (processedSize)
971 *processedSize = 0;
972 if (size == 0)
973 return S_OK;
974 if (!_fileMode)
975 {
976 CVirtFile &file = Files.Back();
977 size_t rem = file.Data.Size() - (size_t)file.Size;
978 bool useMem = true;
979 if (rem < size)
980 {
981 UInt64 b = 0;
982 if (file.Data.Size() == 0)
983 b = file.ExpectedSize;
984 UInt64 a = file.Size + size;
985 if (b < a)
986 b = a;
987 a = (UInt64)file.Data.Size() * 2;
988 if (b < a)
989 b = a;
990 useMem = false;
991 const size_t b_sizet = (size_t)b;
992 if (b == b_sizet && b <= MaxTotalAllocSize)
993 useMem = file.Data.ReAlloc_KeepData(b_sizet, (size_t)file.Size);
994 }
995 if (useMem)
996 {
997 memcpy(file.Data + file.Size, data, size);
998 file.Size += size;
999 if (processedSize)
1000 *processedSize = (UInt32)size;
1001 return S_OK;
1002 }
1003 _fileMode = true;
1004 }
1005 RINOK(FlushToDisk(false));
1006 return _outFileStream->Write(data, size, processedSize);
1007}
1008
1009HRESULT CVirtFileSystem::FlushToDisk(bool closeLast)
1010{
1011 if (!_outFileStream)
1012 {
1013 _outFileStreamSpec = new COutFileStream;
1014 _outFileStream = _outFileStreamSpec;
1015 }
1016 while (_numFlushed < Files.Size())
1017 {
1018 const CVirtFile &file = Files[_numFlushed];
1019 const FString path = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.Name));
1020 if (!_fileIsOpen)
1021 {
1022 if (!_outFileStreamSpec->Create(path, false))
1023 {
1024 _outFileStream.Release();
1025 return E_FAIL;
1026 // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath));
1027 }
1028 _fileIsOpen = true;
1029 RINOK(WriteStream(_outFileStream, file.Data, (size_t)file.Size));
1030 }
1031 if (_numFlushed == Files.Size() - 1 && !closeLast)
1032 break;
1033 if (file.CTimeDefined ||
1034 file.ATimeDefined ||
1035 file.MTimeDefined)
1036 _outFileStreamSpec->SetTime(
1037 file.CTimeDefined ? &file.CTime : NULL,
1038 file.ATimeDefined ? &file.ATime : NULL,
1039 file.MTimeDefined ? &file.MTime : NULL);
1040 _outFileStreamSpec->Close();
1041 _numFlushed++;
1042 _fileIsOpen = false;
1043 if (file.AttribDefined)
1044 NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib);
1045 }
1046 return S_OK;
1047}
1048
1049#endif
diff --git a/CPP/7zip/UI/FileManager/ExtractCallback.h b/CPP/7zip/UI/FileManager/ExtractCallback.h
new file mode 100644
index 0000000..02578bb
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ExtractCallback.h
@@ -0,0 +1,327 @@
1// ExtractCallback.h
2
3#ifndef __EXTRACT_CALLBACK_H
4#define __EXTRACT_CALLBACK_H
5
6#include "../../../../C/Alloc.h"
7
8#include "../../../Common/MyCom.h"
9#include "../../../Common/StringConvert.h"
10
11#ifndef _SFX
12#include "../Agent/IFolderArchive.h"
13#endif
14
15#include "../Common/ArchiveExtractCallback.h"
16#include "../Common/ArchiveOpenCallback.h"
17
18#ifndef _NO_CRYPTO
19#include "../../IPassword.h"
20#endif
21
22#ifndef _SFX
23#include "IFolder.h"
24#endif
25
26#include "ProgressDialog2.h"
27
28#ifdef LANG
29#include "LangUtils.h"
30#endif
31
32#ifndef _SFX
33
34class CGrowBuf
35{
36 Byte *_items;
37 size_t _size;
38
39 CLASS_NO_COPY(CGrowBuf);
40
41public:
42 bool ReAlloc_KeepData(size_t newSize, size_t keepSize)
43 {
44 void *buf = MyAlloc(newSize);
45 if (!buf)
46 return false;
47 if (keepSize != 0)
48 memcpy(buf, _items, keepSize);
49 MyFree(_items);
50 _items = (Byte *)buf;
51 _size = newSize;
52 return true;
53 }
54
55 CGrowBuf(): _items(0), _size(0) {}
56 ~CGrowBuf() { MyFree(_items); }
57
58 operator Byte *() { return _items; }
59 operator const Byte *() const { return _items; }
60 size_t Size() const { return _size; }
61};
62
63struct CVirtFile
64{
65 CGrowBuf Data;
66
67 UInt64 Size; // real size
68 UInt64 ExpectedSize; // the size from props request. 0 if unknown
69
70 UString Name;
71
72 bool CTimeDefined;
73 bool ATimeDefined;
74 bool MTimeDefined;
75 bool AttribDefined;
76
77 bool IsDir;
78 bool IsAltStream;
79
80 DWORD Attrib;
81
82 FILETIME CTime;
83 FILETIME ATime;
84 FILETIME MTime;
85
86 CVirtFile():
87 CTimeDefined(false),
88 ATimeDefined(false),
89 MTimeDefined(false),
90 AttribDefined(false),
91 IsDir(false),
92 IsAltStream(false) {}
93};
94
95class CVirtFileSystem:
96 public ISequentialOutStream,
97 public CMyUnknownImp
98{
99 UInt64 _totalAllocSize;
100
101 size_t _pos;
102 unsigned _numFlushed;
103 bool _fileIsOpen;
104 bool _fileMode;
105 COutFileStream *_outFileStreamSpec;
106 CMyComPtr<ISequentialOutStream> _outFileStream;
107public:
108 CObjectVector<CVirtFile> Files;
109 UInt64 MaxTotalAllocSize;
110 FString DirPrefix;
111
112 CVirtFile &AddNewFile()
113 {
114 if (!Files.IsEmpty())
115 {
116 MaxTotalAllocSize -= Files.Back().Data.Size();
117 }
118 return Files.AddNew();
119 }
120 HRESULT CloseMemFile()
121 {
122 if (_fileMode)
123 {
124 return FlushToDisk(true);
125 }
126 CVirtFile &file = Files.Back();
127 if (file.Data.Size() != file.Size)
128 {
129 file.Data.ReAlloc_KeepData((size_t)file.Size, (size_t)file.Size);
130 }
131 return S_OK;
132 }
133
134 bool IsStreamInMem() const
135 {
136 if (_fileMode)
137 return false;
138 if (Files.Size() < 1 || /* Files[0].IsAltStream || */ Files[0].IsDir)
139 return false;
140 return true;
141 }
142
143 size_t GetMemStreamWrittenSize() const { return _pos; }
144
145 CVirtFileSystem(): _outFileStreamSpec(NULL), MaxTotalAllocSize((UInt64)0 - 1) {}
146
147 void Init()
148 {
149 _totalAllocSize = 0;
150 _fileMode = false;
151 _pos = 0;
152 _numFlushed = 0;
153 _fileIsOpen = false;
154 }
155
156 HRESULT CloseFile(const FString &path);
157 HRESULT FlushToDisk(bool closeLast);
158 size_t GetPos() const { return _pos; }
159
160 MY_UNKNOWN_IMP
161 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
162};
163
164#endif
165
166class CExtractCallbackImp:
167 public IExtractCallbackUI, // it includes IFolderArchiveExtractCallback
168 public IOpenCallbackUI,
169 public IFolderArchiveExtractCallback2,
170 #ifndef _SFX
171 public IFolderOperationsExtractCallback,
172 public IFolderExtractToStreamCallback,
173 public ICompressProgressInfo,
174 #endif
175 #ifndef _NO_CRYPTO
176 public ICryptoGetTextPassword,
177 #endif
178 public CMyUnknownImp
179{
180 HRESULT MessageError(const char *message, const FString &path);
181 void Add_ArchiveName_Error();
182public:
183 MY_QUERYINTERFACE_BEGIN2(IFolderArchiveExtractCallback)
184 MY_QUERYINTERFACE_ENTRY(IFolderArchiveExtractCallback2)
185 #ifndef _SFX
186 MY_QUERYINTERFACE_ENTRY(IFolderOperationsExtractCallback)
187 MY_QUERYINTERFACE_ENTRY(IFolderExtractToStreamCallback)
188 MY_QUERYINTERFACE_ENTRY(ICompressProgressInfo)
189 #endif
190 #ifndef _NO_CRYPTO
191 MY_QUERYINTERFACE_ENTRY(ICryptoGetTextPassword)
192 #endif
193 MY_QUERYINTERFACE_END
194 MY_ADDREF_RELEASE
195
196 INTERFACE_IProgress(;)
197 INTERFACE_IOpenCallbackUI(;)
198 INTERFACE_IFolderArchiveExtractCallback(;)
199 INTERFACE_IFolderArchiveExtractCallback2(;)
200 // STDMETHOD(SetTotalFiles)(UInt64 total);
201 // STDMETHOD(SetCompletedFiles)(const UInt64 *value);
202
203 INTERFACE_IExtractCallbackUI(;)
204
205 #ifndef _SFX
206 // IFolderOperationsExtractCallback
207 STDMETHOD(AskWrite)(
208 const wchar_t *srcPath,
209 Int32 srcIsFolder,
210 const FILETIME *srcTime,
211 const UInt64 *srcSize,
212 const wchar_t *destPathRequest,
213 BSTR *destPathResult,
214 Int32 *writeAnswer);
215 STDMETHOD(ShowMessage)(const wchar_t *message);
216 STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath);
217 STDMETHOD(SetNumFiles)(UInt64 numFiles);
218 INTERFACE_IFolderExtractToStreamCallback(;)
219 STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
220 #endif
221
222 // ICryptoGetTextPassword
223 #ifndef _NO_CRYPTO
224 STDMETHOD(CryptoGetTextPassword)(BSTR *password);
225 #endif
226
227private:
228 UString _currentArchivePath;
229 bool _needWriteArchivePath;
230
231 UString _currentFilePath;
232 bool _isFolder;
233
234 bool _isAltStream;
235 UInt64 _curSize;
236 bool _curSizeDefined;
237 UString _filePath;
238 // bool _extractMode;
239 // bool _testMode;
240 bool _newVirtFileWasAdded;
241 bool _needUpdateStat;
242
243
244 HRESULT SetCurrentFilePath2(const wchar_t *filePath);
245 void AddError_Message(LPCWSTR message);
246
247 #ifndef _SFX
248 bool _hashStreamWasUsed;
249 COutStreamWithHash *_hashStreamSpec;
250 CMyComPtr<ISequentialOutStream> _hashStream;
251 IHashCalc *_hashCalc; // it's for stat in Test operation
252 #endif
253
254public:
255
256 #ifndef _SFX
257 CVirtFileSystem *VirtFileSystemSpec;
258 CMyComPtr<ISequentialOutStream> VirtFileSystem;
259 #endif
260
261 bool ProcessAltStreams;
262
263 bool StreamMode;
264
265 CProgressDialog *ProgressDialog;
266 #ifndef _SFX
267 UInt64 NumFolders;
268 UInt64 NumFiles;
269 bool NeedAddFile;
270 #endif
271 UInt32 NumArchiveErrors;
272 bool ThereAreMessageErrors;
273 NExtract::NOverwriteMode::EEnum OverwriteMode;
274
275 #ifndef _NO_CRYPTO
276 bool PasswordIsDefined;
277 bool PasswordWasAsked;
278 UString Password;
279 #endif
280
281
282 UString _lang_Extracting;
283 UString _lang_Testing;
284 UString _lang_Skipping;
285 UString _lang_Reading;
286 UString _lang_Empty;
287
288 bool _totalFilesDefined;
289 bool _totalBytesDefined;
290 bool MultiArcMode;
291
292 CExtractCallbackImp():
293 #ifndef _SFX
294 _hashCalc(NULL),
295 #endif
296 ProcessAltStreams(true),
297 StreamMode(false),
298 OverwriteMode(NExtract::NOverwriteMode::kAsk),
299 #ifndef _NO_CRYPTO
300 PasswordIsDefined(false),
301 PasswordWasAsked(false),
302 #endif
303 _totalFilesDefined(false),
304 _totalBytesDefined(false),
305 MultiArcMode(false)
306 {}
307
308 ~CExtractCallbackImp();
309 void Init();
310
311 #ifndef _SFX
312 void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }
313
314 void SetHashMethods(IHashCalc *hash)
315 {
316 if (!hash)
317 return;
318 _hashStreamSpec = new COutStreamWithHash;
319 _hashStream = _hashStreamSpec;
320 _hashStreamSpec->_hash = hash;
321 }
322 #endif
323
324 bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }
325};
326
327#endif
diff --git a/CPP/7zip/UI/FileManager/FM.cpp b/CPP/7zip/UI/FileManager/FM.cpp
new file mode 100644
index 0000000..812eff6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FM.cpp
@@ -0,0 +1,1093 @@
1// FM.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyWindows.h"
6
7#include <Shlwapi.h>
8
9#include "../../../../C/Alloc.h"
10#ifdef _WIN32
11#include "../../../../C/DllSecur.h"
12#endif
13
14#include "../../../Common/StringConvert.h"
15#include "../../../Common/StringToInt.h"
16
17#include "../../../Windows/ErrorMsg.h"
18#include "../../../Windows/MemoryLock.h"
19#include "../../../Windows/NtCheck.h"
20#include "../../../Windows/System.h"
21
22#ifndef UNDER_CE
23#include "../../../Windows/SecurityUtils.h"
24#endif
25
26#include "../GUI/ExtractRes.h"
27
28#include "resource.h"
29
30#include "App.h"
31#include "FormatUtils.h"
32#include "LangUtils.h"
33#include "MyLoadMenu.h"
34#include "Panel.h"
35#include "RegistryUtils.h"
36#include "StringUtils.h"
37#include "ViewSettings.h"
38
39using namespace NWindows;
40using namespace NFile;
41using namespace NFind;
42
43// #define MAX_LOADSTRING 100
44
45extern
46bool g_RAM_Size_Defined;
47bool g_RAM_Size_Defined;
48
49static bool g_LargePagesMode = false;
50// static bool g_OpenArchive = false;
51
52static bool g_Maximized = false;
53
54extern
55UInt64 g_RAM_Size;
56UInt64 g_RAM_Size;
57
58#ifdef _WIN32
59extern
60HINSTANCE g_hInstance;
61HINSTANCE g_hInstance;
62#endif
63
64HWND g_HWND;
65
66static UString g_MainPath;
67static UString g_ArcFormat;
68
69// HRESULT LoadGlobalCodecs();
70void FreeGlobalCodecs();
71
72#ifndef UNDER_CE
73
74extern
75DWORD g_ComCtl32Version;
76DWORD g_ComCtl32Version;
77
78static DWORD GetDllVersion(LPCTSTR dllName)
79{
80 DWORD dwVersion = 0;
81 HINSTANCE hinstDll = LoadLibrary(dllName);
82 if (hinstDll)
83 {
84 DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)(void *)GetProcAddress(hinstDll, "DllGetVersion");
85 if (pDllGetVersion)
86 {
87 DLLVERSIONINFO dvi;
88 ZeroMemory(&dvi, sizeof(dvi));
89 dvi.cbSize = sizeof(dvi);
90 HRESULT hr = (*pDllGetVersion)(&dvi);
91 if (SUCCEEDED(hr))
92 dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);
93 }
94 FreeLibrary(hinstDll);
95 }
96 return dwVersion;
97}
98
99#endif
100
101bool g_IsSmallScreen = false;
102
103extern
104bool g_LVN_ITEMACTIVATE_Support;
105bool g_LVN_ITEMACTIVATE_Support = true;
106// LVN_ITEMACTIVATE replaces both NM_DBLCLK & NM_RETURN
107// Windows 2000
108// NT/98 + IE 3 (g_ComCtl32Version >= 4.70)
109
110
111static const int kNumDefaultPanels = 1;
112static const int kSplitterWidth = 4;
113static const int kSplitterRateMax = 1 << 16;
114static const int kPanelSizeMin = 120;
115
116
117class CSplitterPos
118{
119 int _ratio; // 10000 is max
120 int _pos;
121 int _fullWidth;
122 void SetRatioFromPos(HWND hWnd)
123 { _ratio = (_pos + kSplitterWidth / 2) * kSplitterRateMax /
124 MyMax(GetWidth(hWnd), 1); }
125public:
126 int GetPos() const
127 { return _pos; }
128 int GetWidth(HWND hWnd) const
129 {
130 RECT rect;
131 ::GetClientRect(hWnd, &rect);
132 return rect.right;
133 }
134 void SetRatio(HWND hWnd, int aRatio)
135 {
136 _ratio = aRatio;
137 SetPosFromRatio(hWnd);
138 }
139 void SetPosPure(HWND hWnd, int pos)
140 {
141 int posMax = GetWidth(hWnd) - kSplitterWidth;
142 if (posMax < kPanelSizeMin * 2)
143 pos = posMax / 2;
144 else
145 {
146 if (pos > posMax - kPanelSizeMin)
147 pos = posMax - kPanelSizeMin;
148 else if (pos < kPanelSizeMin)
149 pos = kPanelSizeMin;
150 }
151 _pos = pos;
152 }
153 void SetPos(HWND hWnd, int pos)
154 {
155 _fullWidth = GetWidth(hWnd);
156 SetPosPure(hWnd, pos);
157 SetRatioFromPos(hWnd);
158 }
159 void SetPosFromRatio(HWND hWnd)
160 {
161 int fullWidth = GetWidth(hWnd);
162 if (_fullWidth != fullWidth && fullWidth != 0)
163 {
164 _fullWidth = fullWidth;
165 SetPosPure(hWnd, GetWidth(hWnd) * _ratio / kSplitterRateMax - kSplitterWidth / 2);
166 }
167 }
168};
169
170static bool g_CanChangeSplitter = false;
171static UInt32 g_SplitterPos = 0;
172static CSplitterPos g_Splitter;
173static bool g_PanelsInfoDefined = false;
174static bool g_WindowWasCreated = false;
175
176static int g_StartCaptureMousePos;
177static int g_StartCaptureSplitterPos;
178
179CApp g_App;
180
181LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
182
183static const wchar_t * const kWindowClass = L"FM";
184
185#ifdef UNDER_CE
186#define WS_OVERLAPPEDWINDOW ( \
187 WS_OVERLAPPED | \
188 WS_CAPTION | \
189 WS_SYSMENU | \
190 WS_THICKFRAME | \
191 WS_MINIMIZEBOX | \
192 WS_MAXIMIZEBOX)
193#endif
194
195// FUNCTION: InitInstance(HANDLE, int)
196static BOOL InitInstance(int nCmdShow)
197{
198 CWindow wnd;
199
200 // LoadString(hInstance, IDS_CLASS, windowClass, MAX_LOADSTRING);
201
202 UString title ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000);
203
204 /*
205 //If it is already running, then focus on the window
206 hWnd = FindWindow(windowClass, title);
207 if (hWnd)
208 {
209 SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
210 return 0;
211 }
212 */
213
214 WNDCLASSW wc;
215
216 // wc.style = CS_HREDRAW | CS_VREDRAW;
217 wc.style = 0;
218 wc.lpfnWndProc = (WNDPROC) WndProc;
219 wc.cbClsExtra = 0;
220 wc.cbWndExtra = 0;
221 wc.hInstance = g_hInstance;
222 wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
223
224 // wc.hCursor = LoadCursor (NULL, IDC_ARROW);
225 wc.hCursor = ::LoadCursor(0, IDC_SIZEWE);
226 // wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
227 wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
228
229 wc.lpszMenuName =
230 #ifdef UNDER_CE
231 0
232 #else
233 MAKEINTRESOURCEW(IDM_MENU)
234 #endif
235 ;
236
237 wc.lpszClassName = kWindowClass;
238
239 MyRegisterClass(&wc);
240
241 // RECT rect;
242 // GetClientRect(hWnd, &rect);
243
244 DWORD style = WS_OVERLAPPEDWINDOW;
245 // DWORD style = 0;
246
247 CWindowInfo info;
248 info.maximized = false;
249 int x, y, xSize, ySize;
250 x = y = xSize = ySize = CW_USEDEFAULT;
251 bool windowPosIsRead;
252 info.Read(windowPosIsRead, g_PanelsInfoDefined);
253
254 if (windowPosIsRead)
255 {
256 x = info.rect.left;
257 y = info.rect.top;
258
259 xSize = RECT_SIZE_X(info.rect);
260 ySize = RECT_SIZE_Y(info.rect);
261 }
262
263
264 if (g_PanelsInfoDefined)
265 {
266 g_SplitterPos = info.splitterPos;
267 if (info.numPanels < 1 || info.numPanels > 2)
268 info.numPanels = kNumDefaultPanels;
269 if (info.currentPanel >= 2)
270 info.currentPanel = 0;
271 }
272 else
273 {
274 info.numPanels = kNumDefaultPanels;
275 info.currentPanel = 0;
276 }
277
278 g_App.NumPanels = info.numPanels;
279 g_App.LastFocusedPanel = info.currentPanel;
280
281 if (!wnd.Create(kWindowClass, title, style,
282 x, y, xSize, ySize, NULL, NULL, g_hInstance, NULL))
283 return FALSE;
284
285 if (nCmdShow == SW_SHOWNORMAL ||
286 nCmdShow == SW_SHOW
287 #ifndef UNDER_CE
288 || nCmdShow == SW_SHOWDEFAULT
289 #endif
290 )
291 {
292 if (info.maximized)
293 nCmdShow = SW_SHOWMAXIMIZED;
294 else
295 nCmdShow = SW_SHOWNORMAL;
296 }
297
298 if (nCmdShow == SW_SHOWMAXIMIZED)
299 g_Maximized = true;
300
301 #ifndef UNDER_CE
302 WINDOWPLACEMENT placement;
303 placement.length = sizeof(placement);
304 if (wnd.GetPlacement(&placement))
305 {
306 if (windowPosIsRead)
307 placement.rcNormalPosition = info.rect;
308 placement.showCmd = nCmdShow;
309 wnd.SetPlacement(&placement);
310 }
311 else
312 #endif
313 wnd.Show(nCmdShow);
314
315 return TRUE;
316}
317
318/*
319static void GetCommands(const UString &aCommandLine, UString &aCommands)
320{
321 UString aProgramName;
322 aCommands.Empty();
323 bool aQuoteMode = false;
324 for (int i = 0; i < aCommandLine.Length(); i++)
325 {
326 wchar_t aChar = aCommandLine[i];
327 if (aChar == L'\"')
328 aQuoteMode = !aQuoteMode;
329 else if (aChar == L' ' && !aQuoteMode)
330 {
331 if (!aQuoteMode)
332 {
333 i++;
334 break;
335 }
336 }
337 else
338 aProgramName += aChar;
339 }
340 aCommands = aCommandLine.Ptr(i);
341}
342*/
343
344#if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE)
345
346bool g_Is_Wow64;
347
348typedef BOOL (WINAPI *Func_IsWow64Process)(HANDLE, PBOOL);
349
350static void Set_Wow64()
351{
352 g_Is_Wow64 = false;
353 Func_IsWow64Process fnIsWow64Process = (Func_IsWow64Process)(void *)GetProcAddress(
354 GetModuleHandleA("kernel32.dll"), "IsWow64Process");
355 if (fnIsWow64Process)
356 {
357 BOOL isWow;
358 if (fnIsWow64Process(GetCurrentProcess(), &isWow))
359 g_Is_Wow64 = (isWow != FALSE);
360 }
361}
362
363#endif
364
365
366bool IsLargePageSupported();
367bool IsLargePageSupported()
368{
369 #ifdef _WIN64
370 return true;
371 #else
372 OSVERSIONINFO vi;
373 vi.dwOSVersionInfoSize = sizeof(vi);
374 if (!::GetVersionEx(&vi))
375 return false;
376 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
377 return false;
378 if (vi.dwMajorVersion < 5) return false;
379 if (vi.dwMajorVersion > 5) return true;
380 if (vi.dwMinorVersion < 1) return false;
381 if (vi.dwMinorVersion > 1) return true;
382 // return g_Is_Wow64;
383 return false;
384 #endif
385}
386
387#ifndef UNDER_CE
388
389static void SetMemoryLock()
390{
391 if (!IsLargePageSupported())
392 return;
393 // if (ReadLockMemoryAdd())
394 NSecurity::AddLockMemoryPrivilege();
395
396 if (ReadLockMemoryEnable())
397 if (NSecurity::Get_LargePages_RiskLevel() == 0)
398 {
399 // note: child processes can inherit that Privilege
400 g_LargePagesMode = NSecurity::EnablePrivilege_LockMemory();
401 }
402}
403
404extern
405bool g_SymLink_Supported;
406bool g_SymLink_Supported = false;
407
408static void Set_SymLink_Supported()
409{
410 g_SymLink_Supported = false;
411 OSVERSIONINFO vi;
412 vi.dwOSVersionInfoSize = sizeof(vi);
413 if (!::GetVersionEx(&vi))
414 return;
415 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT || vi.dwMajorVersion < 6)
416 return;
417 g_SymLink_Supported = true;
418 // if (g_SymLink_Supported)
419 {
420 NSecurity::EnablePrivilege_SymLink();
421 }
422}
423
424#endif
425
426/*
427static const int kNumSwitches = 1;
428
429namespace NKey {
430enum Enum
431{
432 kOpenArachive = 0
433};
434
435}
436
437static const CSwitchForm kSwitchForms[kNumSwitches] =
438 {
439 { L"SOA", NSwitchType::kSimple, false },
440 };
441*/
442
443// int APIENTRY WinMain2(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int /* nCmdShow */);
444
445static void ErrorMessage(const wchar_t *s)
446{
447 MessageBoxW(0, s, L"7-Zip", MB_ICONERROR);
448}
449
450static void ErrorMessage(const char *s)
451{
452 ErrorMessage(GetUnicodeString(s));
453}
454
455
456#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)
457#define NT_CHECK_FAIL_ACTION ErrorMessage("Unsupported Windows version"); return 1;
458#endif
459
460static int WINAPI WinMain2(int nCmdShow)
461{
462 g_RAM_Size_Defined = NSystem::GetRamSize(g_RAM_Size);
463
464 #ifdef _WIN32
465
466 /*
467 #ifndef _WIN64
468 #ifndef UNDER_CE
469 {
470 HMODULE hMod = GetModuleHandle("Kernel32.dll");
471 if (hMod)
472 {
473 typedef BOOL (WINAPI *PSETDEP)(DWORD);
474 #define MY_PROCESS_DEP_ENABLE 1
475 PSETDEP procSet = (PSETDEP)GetProcAddress(hMod,"SetProcessDEPPolicy");
476 if (procSet)
477 procSet(MY_PROCESS_DEP_ENABLE);
478
479 typedef BOOL (WINAPI *HSI)(HANDLE, HEAP_INFORMATION_CLASS ,PVOID, SIZE_T);
480 HSI hsi = (HSI)GetProcAddress(hMod, "HeapSetInformation");
481 #define MY_HeapEnableTerminationOnCorruption ((HEAP_INFORMATION_CLASS)1)
482 if (hsi)
483 hsi(NULL, MY_HeapEnableTerminationOnCorruption, NULL, 0);
484 }
485 }
486 #endif
487 #endif
488 */
489
490 NT_CHECK
491 SetLargePageSize();
492
493 #endif
494
495 LoadLangOneTime();
496
497 InitCommonControls();
498
499 #ifndef UNDER_CE
500 g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll"));
501 g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));
502 #endif
503
504 #if defined(_WIN32) && !defined(_WIN64) && !defined(UNDER_CE)
505 Set_Wow64();
506 #endif
507
508
509 g_IsSmallScreen = !NWindows::NControl::IsDialogSizeOK(200, 200);
510
511 // OleInitialize is required for drag and drop.
512 #ifndef UNDER_CE
513 OleInitialize(NULL);
514 #endif
515 // Maybe needs CoInitializeEx also ?
516 // NCOM::CComInitializer comInitializer;
517
518 UString commandsString;
519 // MessageBoxW(0, GetCommandLineW(), L"", 0);
520
521 #ifdef UNDER_CE
522 commandsString = GetCommandLineW();
523 #else
524 UString programString;
525 SplitStringToTwoStrings(GetCommandLineW(), programString, commandsString);
526 #endif
527
528 commandsString.Trim();
529 UString paramString, tailString;
530 SplitStringToTwoStrings(commandsString, paramString, tailString);
531 paramString.Trim();
532 tailString.Trim();
533 if (tailString.IsPrefixedBy(L"-t"))
534 g_ArcFormat = tailString.Ptr(2);
535
536 /*
537 UStringVector switches;
538 for (;;)
539 {
540 if (tailString.IsEmpty())
541 break;
542 UString s1, s2;
543 SplitStringToTwoStrings(tailString, s1, s2);
544 if (s2.IsEmpty())
545 {
546 tailString.Trim();
547 switches.Add(tailString);
548 break;
549 }
550 s1.Trim();
551 switches.Add(s1);
552 tailString = s2;
553 }
554
555 FOR_VECTOR(i, switches)
556 {
557 const UString &sw = switches[i];
558 if (sw.IsPrefixedBy(L"-t"))
559 g_ArcFormat = sw.Ptr(2);
560 //
561 else if (sw.IsPrefixedBy(L"-stp"))
562 {
563 const wchar_t *end;
564 UInt32 val = ConvertStringToUInt32(sw.Ptr(4), &end);
565 if (*end != 0)
566 throw 111;
567 g_TypeParseLevel = val;
568 }
569 else
570 //
571 throw 112;
572 }
573 */
574
575 if (!paramString.IsEmpty())
576 {
577 g_MainPath = paramString;
578 // return WinMain2(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
579
580 // MessageBoxW(0, paramString, L"", 0);
581 }
582 /*
583 UStringVector commandStrings;
584 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
585 NCommandLineParser::CParser parser(kNumSwitches);
586 try
587 {
588 parser.ParseStrings(kSwitchForms, commandStrings);
589 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
590 if (nonSwitchStrings.Size() > 1)
591 {
592 g_MainPath = nonSwitchStrings[1];
593 // g_OpenArchive = parser[NKey::kOpenArachive].ThereIs;
594 CFileInfoW fileInfo;
595 if (FindFile(g_MainPath, fileInfo))
596 {
597 if (!fileInfo.IsDir())
598 g_OpenArchive = true;
599 }
600 }
601 }
602 catch(...) { }
603 */
604
605
606 #if defined(_WIN32) && !defined(UNDER_CE)
607 SetMemoryLock();
608 Set_SymLink_Supported();
609 #endif
610
611 g_App.ReloadLang();
612
613 MSG msg;
614 if (!InitInstance (nCmdShow))
615 return FALSE;
616
617 // we will load Global_Codecs at first use instead.
618 /*
619 OutputDebugStringW(L"Before LoadGlobalCodecs");
620 LoadGlobalCodecs();
621 OutputDebugStringW(L"After LoadGlobalCodecs");
622 */
623
624 #ifndef _UNICODE
625 if (g_IsNT)
626 {
627 HACCEL hAccels = LoadAcceleratorsW(g_hInstance, MAKEINTRESOURCEW(IDR_ACCELERATOR1));
628 while (GetMessageW(&msg, NULL, 0, 0))
629 {
630 if (TranslateAcceleratorW(g_HWND, hAccels, &msg) == 0)
631 {
632 TranslateMessage(&msg);
633 DispatchMessageW(&msg);
634 }
635 }
636 }
637 else
638 #endif
639 {
640 HACCEL hAccels = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
641 while (GetMessage(&msg, NULL, 0, 0))
642 {
643 if (TranslateAccelerator(g_HWND, hAccels, &msg) == 0)
644 {
645 // if (g_Hwnd != NULL || !IsDialogMessage(g_Hwnd, &msg))
646 // if (!IsDialogMessage(g_Hwnd, &msg))
647 TranslateMessage(&msg);
648 DispatchMessage(&msg);
649 }
650 }
651 }
652
653 // Destructor of g_CodecsReleaser can release DLLs.
654 // But we suppose that it's better to release DLLs here (before destructor).
655 FreeGlobalCodecs();
656
657 g_HWND = 0;
658 #ifndef UNDER_CE
659 OleUninitialize();
660 #endif
661 return (int)msg.wParam;
662}
663
664int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,
665 #ifdef UNDER_CE
666 LPWSTR
667 #else
668 LPSTR
669 #endif
670 /* lpCmdLine */, int nCmdShow)
671{
672 g_hInstance = hInstance;
673
674 try
675 {
676 try
677 {
678 #ifdef _WIN32
679 My_SetDefaultDllDirectories();
680 #endif
681 return WinMain2(nCmdShow);
682 }
683 catch (...)
684 {
685 g_ExitEventLauncher.Exit(true);
686 throw;
687 }
688 }
689 catch(const CNewException &)
690 {
691 ErrorMessage(LangString(IDS_MEM_ERROR));
692 return 1;
693 }
694 catch(const UString &s)
695 {
696 ErrorMessage(s);
697 return 1;
698 }
699 catch(const AString &s)
700 {
701 ErrorMessage(s.Ptr());
702 return 1;
703 }
704 catch(const wchar_t *s)
705 {
706 ErrorMessage(s);
707 return 1;
708 }
709 catch(const char *s)
710 {
711 ErrorMessage(s);
712 return 1;
713 }
714 catch(int v)
715 {
716 AString e ("Error: ");
717 e.Add_UInt32(v);
718 ErrorMessage(e);
719 return 1;
720 }
721 catch(...)
722 {
723 ErrorMessage("Unknown error");
724 return 1;
725 }
726}
727
728static void SaveWindowInfo(HWND aWnd)
729{
730 CWindowInfo info;
731
732 #ifdef UNDER_CE
733
734 if (!::GetWindowRect(aWnd, &info.rect))
735 return;
736 info.maximized = g_Maximized;
737
738 #else
739
740 WINDOWPLACEMENT placement;
741 placement.length = sizeof(placement);
742 if (!::GetWindowPlacement(aWnd, &placement))
743 return;
744 info.rect = placement.rcNormalPosition;
745 info.maximized = BOOLToBool(::IsZoomed(aWnd));
746
747 #endif
748
749 info.numPanels = g_App.NumPanels;
750 info.currentPanel = g_App.LastFocusedPanel;
751 info.splitterPos = g_Splitter.GetPos();
752
753 info.Save();
754}
755
756static void ExecuteCommand(UINT commandID)
757{
758 CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]);
759 CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]);
760
761 switch (commandID)
762 {
763 case kMenuCmdID_Toolbar_Add: g_App.AddToArchive(); break;
764 case kMenuCmdID_Toolbar_Extract: g_App.ExtractArchives(); break;
765 case kMenuCmdID_Toolbar_Test: g_App.TestArchives(); break;
766 }
767}
768
769LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
770{
771 switch (message)
772 {
773 case WM_COMMAND:
774 {
775 unsigned wmId = LOWORD(wParam);
776 unsigned wmEvent = HIWORD(wParam);
777 if ((HWND) lParam != NULL && wmEvent != 0)
778 break;
779 if (wmId >= kMenuCmdID_Toolbar_Start && wmId < kMenuCmdID_Toolbar_End)
780 {
781 ExecuteCommand(wmId);
782 return 0;
783 }
784 if (OnMenuCommand(hWnd, wmId))
785 return 0;
786 break;
787 }
788 case WM_INITMENUPOPUP:
789 OnMenuActivating(hWnd, HMENU(wParam), LOWORD(lParam));
790 break;
791
792 /*
793 It doesn't help
794 case WM_EXITMENULOOP:
795 {
796 OnMenuUnActivating(hWnd);
797 break;
798 }
799 case WM_UNINITMENUPOPUP:
800 OnMenuUnActivating(hWnd, HMENU(wParam), lParam);
801 break;
802 */
803
804 case WM_CREATE:
805 {
806 g_HWND = hWnd;
807 /*
808 INITCOMMONCONTROLSEX icex;
809 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
810 icex.dwICC = ICC_BAR_CLASSES;
811 InitCommonControlsEx(&icex);
812
813 // Toolbar buttons used to create the first 4 buttons.
814 TBBUTTON tbb [ ] =
815 {
816 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
817 // {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
818 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
819 {VIEW_NEWFOLDER, ID_FILE_CREATEFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
820 };
821
822 int baseID = 100;
823 NWindows::NControl::CToolBar aToolBar;
824 aToolBar.Attach(::CreateToolbarEx (hWnd,
825 WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, // | TBSTYLE_FLAT
826 baseID + 2, 11,
827 (HINSTANCE)HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR,
828 (LPCTBBUTTON)&tbb, ARRAY_SIZE(tbb),
829 0, 0, 100, 30, sizeof (TBBUTTON)));
830 */
831 // HCURSOR cursor = ::LoadCursor(0, IDC_SIZEWE);
832 // ::SetCursor(cursor);
833
834 if (g_PanelsInfoDefined)
835 g_Splitter.SetPos(hWnd, g_SplitterPos);
836 else
837 {
838 g_Splitter.SetRatio(hWnd, kSplitterRateMax / 2);
839 g_SplitterPos = g_Splitter.GetPos();
840 }
841
842 RECT rect;
843 ::GetClientRect(hWnd, &rect);
844 int xSize = rect.right;
845 int xSizes[2];
846 xSizes[0] = g_Splitter.GetPos();
847 xSizes[1] = xSize - kSplitterWidth - xSizes[0];
848 if (xSizes[1] < 0)
849 xSizes[1] = 0;
850
851 g_App.CreateDragTarget();
852
853 COpenResult openRes;
854 bool needOpenArc = false;
855
856 UString fullPath = g_MainPath;
857 if (!fullPath.IsEmpty() /* && g_OpenArchive */)
858 {
859 if (!NFile::NName::IsAbsolutePath(fullPath))
860 {
861 FString fullPathF;
862 if (NFile::NName::GetFullPath(us2fs(fullPath), fullPathF))
863 fullPath = fs2us(fullPathF);
864 }
865 if (NFile::NFind::DoesFileExist_FollowLink(us2fs(fullPath)))
866 needOpenArc = true;
867 }
868
869 HRESULT res = g_App.Create(hWnd, fullPath, g_ArcFormat, xSizes,
870 needOpenArc,
871 openRes);
872
873 if (res == E_ABORT)
874 return -1;
875
876 if ((needOpenArc && !openRes.ArchiveIsOpened) || res != S_OK)
877 {
878 UString m ("Error");
879 if (res == S_FALSE || res == S_OK)
880 {
881 m = MyFormatNew(openRes.Encrypted ?
882 IDS_CANT_OPEN_ENCRYPTED_ARCHIVE :
883 IDS_CANT_OPEN_ARCHIVE,
884 fullPath);
885 }
886 else if (res != S_OK)
887 m = HResultToMessage(res);
888 if (!openRes.ErrorMessage.IsEmpty())
889 {
890 m.Add_LF();
891 m += openRes.ErrorMessage;
892 }
893 ErrorMessage(m);
894 return -1;
895 }
896
897 g_WindowWasCreated = true;
898
899 // g_SplitterPos = 0;
900
901 // ::DragAcceptFiles(hWnd, TRUE);
902 RegisterDragDrop(hWnd, g_App._dropTarget);
903
904 break;
905 }
906
907 case WM_DESTROY:
908 {
909 // ::DragAcceptFiles(hWnd, FALSE);
910 RevokeDragDrop(hWnd);
911 g_App._dropTarget.Release();
912
913 if (g_WindowWasCreated)
914 g_App.Save();
915
916 g_App.Release();
917
918 if (g_WindowWasCreated)
919 SaveWindowInfo(hWnd);
920
921 g_ExitEventLauncher.Exit(true);
922 PostQuitMessage(0);
923 break;
924 }
925
926 // case WM_MOVE: break;
927
928 case WM_LBUTTONDOWN:
929 g_StartCaptureMousePos = LOWORD(lParam);
930 g_StartCaptureSplitterPos = g_Splitter.GetPos();
931 ::SetCapture(hWnd);
932 break;
933
934 case WM_LBUTTONUP:
935 {
936 ::ReleaseCapture();
937 break;
938 }
939
940 case WM_MOUSEMOVE:
941 {
942 if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd)
943 {
944 g_Splitter.SetPos(hWnd, g_StartCaptureSplitterPos +
945 (short)LOWORD(lParam) - g_StartCaptureMousePos);
946 g_App.MoveSubWindows();
947 }
948 break;
949 }
950
951 case WM_SIZE:
952 {
953 if (g_CanChangeSplitter)
954 g_Splitter.SetPosFromRatio(hWnd);
955 else
956 {
957 g_Splitter.SetPos(hWnd, g_SplitterPos );
958 g_CanChangeSplitter = true;
959 }
960
961 g_Maximized = (wParam == SIZE_MAXIMIZED) || (wParam == SIZE_MAXSHOW);
962
963 g_App.MoveSubWindows();
964 /*
965 int xSize = LOWORD(lParam);
966 int ySize = HIWORD(lParam);
967 // int xSplitter = 2;
968 int xWidth = g_SplitPos;
969 // int xSplitPos = xWidth;
970 g_Panel[0]._listView.MoveWindow(0, 0, xWidth, ySize);
971 g_Panel[1]._listView.MoveWindow(xSize - xWidth, 0, xWidth, ySize);
972 */
973 return 0;
974 // break;
975 }
976
977 case WM_SETFOCUS:
978 // g_App.SetFocus(g_App.LastFocusedPanel);
979 g_App.SetFocusToLastItem();
980 break;
981
982 /*
983 case WM_ACTIVATE:
984 {
985 int fActive = LOWORD(wParam);
986 switch (fActive)
987 {
988 case WA_INACTIVE:
989 {
990 // g_FocusIndex = g_App.LastFocusedPanel;
991 // g_App.LastFocusedPanel = g_App.GetFocusedPanelIndex();
992 // return 0;
993 }
994 }
995 break;
996 }
997 */
998
999 /*
1000 case kLangWasChangedMessage:
1001 MyLoadMenu();
1002 return 0;
1003 */
1004
1005 /*
1006 case WM_SETTINGCHANGE:
1007 break;
1008 */
1009
1010 case WM_NOTIFY:
1011 {
1012 g_App.OnNotify((int)wParam, (LPNMHDR)lParam);
1013 break;
1014 }
1015
1016 /*
1017 case WM_DROPFILES:
1018 {
1019 g_App.GetFocusedPanel().CompressDropFiles((HDROP)wParam);
1020 return 0 ;
1021 }
1022 */
1023 }
1024 #ifndef _UNICODE
1025 if (g_IsNT)
1026 return DefWindowProcW(hWnd, message, wParam, lParam);
1027 else
1028 #endif
1029 return DefWindowProc(hWnd, message, wParam, lParam);
1030
1031}
1032
1033static int Window_GetRealHeight(NWindows::CWindow &w)
1034{
1035 RECT rect;
1036 w.GetWindowRect(&rect);
1037 int res = RECT_SIZE_Y(rect);
1038 #ifndef UNDER_CE
1039 WINDOWPLACEMENT placement;
1040 if (w.GetPlacement(&placement))
1041 res += placement.rcNormalPosition.top;
1042 #endif
1043 return res;
1044}
1045
1046void CApp::MoveSubWindows()
1047{
1048 HWND hWnd = _window;
1049 RECT rect;
1050 if (hWnd == 0)
1051 return;
1052 ::GetClientRect(hWnd, &rect);
1053 int xSize = rect.right;
1054 if (xSize == 0)
1055 return;
1056 int headerSize = 0;
1057
1058 #ifdef UNDER_CE
1059 _commandBar.AutoSize();
1060 {
1061 _commandBar.Show(true); // maybe we need it for
1062 headerSize += _commandBar.Height();
1063 }
1064 #endif
1065
1066 if (_toolBar)
1067 {
1068 _toolBar.AutoSize();
1069 #ifdef UNDER_CE
1070 int h2 = Window_GetRealHeight(_toolBar);
1071 _toolBar.Move(0, headerSize, xSize, h2);
1072 #endif
1073 headerSize += Window_GetRealHeight(_toolBar);
1074 }
1075
1076 int ySize = MyMax((int)(rect.bottom - headerSize), 0);
1077
1078 if (NumPanels > 1)
1079 {
1080 Panels[0].Move(0, headerSize, g_Splitter.GetPos(), ySize);
1081 int xWidth1 = g_Splitter.GetPos() + kSplitterWidth;
1082 Panels[1].Move(xWidth1, headerSize, xSize - xWidth1, ySize);
1083 }
1084 else
1085 {
1086 /*
1087 int otherPanel = 1 - LastFocusedPanel;
1088 if (PanelsCreated[otherPanel])
1089 Panels[otherPanel].Move(0, headerSize, 0, ySize);
1090 */
1091 Panels[LastFocusedPanel].Move(0, headerSize, xSize, ySize);
1092 }
1093}
diff --git a/CPP/7zip/UI/FileManager/FM.dsp b/CPP/7zip/UI/FileManager/FM.dsp
new file mode 100644
index 0000000..a12d330
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FM.dsp
@@ -0,0 +1,1643 @@
1# Microsoft Developer Studio Project File - Name="FM" - Package Owner=<4>
2# Microsoft Developer Studio Generated Build File, Format Version 6.00
3# ** DO NOT EDIT **
4
5# TARGTYPE "Win32 (x86) Application" 0x0101
6
7CFG=FM - Win32 DebugU
8!MESSAGE This is not a valid makefile. To build this project using NMAKE,
9!MESSAGE use the Export Makefile command and run
10!MESSAGE
11!MESSAGE NMAKE /f "FM.mak".
12!MESSAGE
13!MESSAGE You can specify a configuration when running NMAKE
14!MESSAGE by defining the macro CFG on the command line. For example:
15!MESSAGE
16!MESSAGE NMAKE /f "FM.mak" CFG="FM - Win32 DebugU"
17!MESSAGE
18!MESSAGE Possible choices for configuration are:
19!MESSAGE
20!MESSAGE "FM - Win32 Release" (based on "Win32 (x86) Application")
21!MESSAGE "FM - Win32 Debug" (based on "Win32 (x86) Application")
22!MESSAGE "FM - Win32 ReleaseU" (based on "Win32 (x86) Application")
23!MESSAGE "FM - Win32 DebugU" (based on "Win32 (x86) Application")
24!MESSAGE
25
26# Begin Project
27# PROP AllowPerConfigDependencies 0
28# PROP Scc_ProjName ""
29# PROP Scc_LocalPath ""
30CPP=cl.exe
31MTL=midl.exe
32RSC=rc.exe
33
34!IF "$(CFG)" == "FM - Win32 Release"
35
36# PROP BASE Use_MFC 0
37# PROP BASE Use_Debug_Libraries 0
38# PROP BASE Output_Dir "Release"
39# PROP BASE Intermediate_Dir "Release"
40# PROP BASE Target_Dir ""
41# PROP Use_MFC 0
42# PROP Use_Debug_Libraries 0
43# PROP Output_Dir "Release"
44# PROP Intermediate_Dir "Release"
45# PROP Ignore_Export_Lib 0
46# PROP Target_Dir ""
47# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
48# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /FAcs /Yu"StdAfx.h" /FD /c
49# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
50# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
51# ADD BASE RSC /l 0x419 /d "NDEBUG"
52# ADD RSC /l 0x409 /d "NDEBUG"
53BSC32=bscmake.exe
54# ADD BASE BSC32 /nologo
55# ADD BSC32 /nologo
56LINK32=link.exe
57# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
58# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zFM.exe" /opt:NOWIN98
59# SUBTRACT LINK32 /pdb:none
60
61!ELSEIF "$(CFG)" == "FM - Win32 Debug"
62
63# PROP BASE Use_MFC 0
64# PROP BASE Use_Debug_Libraries 1
65# PROP BASE Output_Dir "Debug"
66# PROP BASE Intermediate_Dir "Debug"
67# PROP BASE Target_Dir ""
68# PROP Use_MFC 0
69# PROP Use_Debug_Libraries 1
70# PROP Output_Dir "Debug"
71# PROP Intermediate_Dir "Debug"
72# PROP Ignore_Export_Lib 0
73# PROP Target_Dir ""
74# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
75# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
76# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
77# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
78# ADD BASE RSC /l 0x419 /d "_DEBUG"
79# ADD RSC /l 0x409 /d "_DEBUG"
80BSC32=bscmake.exe
81# ADD BASE BSC32 /nologo
82# ADD BSC32 /nologo
83LINK32=link.exe
84# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
85# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zFM.exe" /pdbtype:sept
86
87!ELSEIF "$(CFG)" == "FM - Win32 ReleaseU"
88
89# PROP BASE Use_MFC 0
90# PROP BASE Use_Debug_Libraries 0
91# PROP BASE Output_Dir "ReleaseU"
92# PROP BASE Intermediate_Dir "ReleaseU"
93# PROP BASE Ignore_Export_Lib 0
94# PROP BASE Target_Dir ""
95# PROP Use_MFC 0
96# PROP Use_Debug_Libraries 0
97# PROP Output_Dir "ReleaseU"
98# PROP Intermediate_Dir "ReleaseU"
99# PROP Ignore_Export_Lib 0
100# PROP Target_Dir ""
101# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c
102# ADD CPP /nologo /Gz /MD /W4 /WX /GX /O1 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /c
103# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
104# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
105# ADD BASE RSC /l 0x419 /d "NDEBUG"
106# ADD RSC /l 0x409 /d "NDEBUG"
107BSC32=bscmake.exe
108# ADD BASE BSC32 /nologo
109# ADD BSC32 /nologo
110LINK32=link.exe
111# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /machine:I386
112# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /machine:I386 /out:"C:\Util\7zFM.exe" /opt:NOWIN98
113# SUBTRACT LINK32 /pdb:none
114
115!ELSEIF "$(CFG)" == "FM - Win32 DebugU"
116
117# PROP BASE Use_MFC 0
118# PROP BASE Use_Debug_Libraries 1
119# PROP BASE Output_Dir "DebugU"
120# PROP BASE Intermediate_Dir "DebugU"
121# PROP BASE Ignore_Export_Lib 0
122# PROP BASE Target_Dir ""
123# PROP Use_MFC 0
124# PROP Use_Debug_Libraries 1
125# PROP Output_Dir "DebugU"
126# PROP Intermediate_Dir "DebugU"
127# PROP Ignore_Export_Lib 0
128# PROP Target_Dir ""
129# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
130# ADD CPP /nologo /Gz /MDd /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "LANG" /D "WIN_LONG_PATH" /D "NEW_FOLDER_INTERFACE" /D "EXTERNAL_CODECS" /D "SUPPORT_DEVICE_FILE" /Yu"StdAfx.h" /FD /GZ /c
131# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
132# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
133# ADD BASE RSC /l 0x419 /d "_DEBUG"
134# ADD RSC /l 0x409 /d "_DEBUG"
135BSC32=bscmake.exe
136# ADD BASE BSC32 /nologo
137# ADD BSC32 /nologo
138LINK32=link.exe
139# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
140# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib comctl32.lib Mpr.lib htmlhelp.lib Urlmon.lib /nologo /subsystem:windows /debug /machine:I386 /out:"C:\Util\7zFM.exe" /pdbtype:sept
141
142!ENDIF
143
144# Begin Target
145
146# Name "FM - Win32 Release"
147# Name "FM - Win32 Debug"
148# Name "FM - Win32 ReleaseU"
149# Name "FM - Win32 DebugU"
150# Begin Group "Spec"
151
152# PROP Default_Filter ""
153# Begin Source File
154
155SOURCE=.\7zipLogo.ico
156# End Source File
157# Begin Source File
158
159SOURCE=.\add.bmp
160# End Source File
161# Begin Source File
162
163SOURCE=.\ClassDefs.cpp
164# End Source File
165# Begin Source File
166
167SOURCE=.\Copy.bmp
168# End Source File
169# Begin Source File
170
171SOURCE=.\Delete.bmp
172# End Source File
173# Begin Source File
174
175SOURCE=.\Extract.bmp
176# End Source File
177# Begin Source File
178
179SOURCE=.\FM.ico
180# End Source File
181# Begin Source File
182
183SOURCE=.\Move.bmp
184# End Source File
185# Begin Source File
186
187SOURCE=.\MyWindowsNew.h
188# End Source File
189# Begin Source File
190
191SOURCE=.\Parent.bmp
192# End Source File
193# Begin Source File
194
195SOURCE=.\Properties.bmp
196# End Source File
197# Begin Source File
198
199SOURCE=.\resource.rc
200# ADD BASE RSC /l 0x419
201# ADD RSC /l 0x409
202# End Source File
203# Begin Source File
204
205SOURCE=.\StdAfx.cpp
206# ADD CPP /Yc"StdAfx.h"
207# End Source File
208# Begin Source File
209
210SOURCE=.\StdAfx.h
211# End Source File
212# Begin Source File
213
214SOURCE=.\Test.bmp
215# End Source File
216# End Group
217# Begin Group "Folders"
218
219# PROP Default_Filter ""
220# Begin Source File
221
222SOURCE=.\AltStreamsFolder.cpp
223# End Source File
224# Begin Source File
225
226SOURCE=.\AltStreamsFolder.h
227# End Source File
228# Begin Source File
229
230SOURCE=.\FSDrives.cpp
231# End Source File
232# Begin Source File
233
234SOURCE=.\FSDrives.h
235# End Source File
236# Begin Source File
237
238SOURCE=.\FSFolder.cpp
239# End Source File
240# Begin Source File
241
242SOURCE=.\FSFolder.h
243# End Source File
244# Begin Source File
245
246SOURCE=.\FSFolderCopy.cpp
247# End Source File
248# Begin Source File
249
250SOURCE=.\IFolder.h
251# End Source File
252# Begin Source File
253
254SOURCE=.\NetFolder.cpp
255# End Source File
256# Begin Source File
257
258SOURCE=.\NetFolder.h
259# End Source File
260# Begin Source File
261
262SOURCE=.\RootFolder.cpp
263# End Source File
264# Begin Source File
265
266SOURCE=.\RootFolder.h
267# End Source File
268# End Group
269# Begin Group "Registry"
270
271# PROP Default_Filter ""
272# Begin Source File
273
274SOURCE=.\RegistryAssociations.cpp
275# End Source File
276# Begin Source File
277
278SOURCE=.\RegistryAssociations.h
279# End Source File
280# Begin Source File
281
282SOURCE=.\RegistryPlugins.cpp
283# End Source File
284# Begin Source File
285
286SOURCE=.\RegistryPlugins.h
287# End Source File
288# Begin Source File
289
290SOURCE=.\RegistryUtils.cpp
291# End Source File
292# Begin Source File
293
294SOURCE=.\RegistryUtils.h
295# End Source File
296# Begin Source File
297
298SOURCE=.\ViewSettings.cpp
299# End Source File
300# Begin Source File
301
302SOURCE=.\ViewSettings.h
303# End Source File
304# End Group
305# Begin Group "Panel"
306
307# PROP Default_Filter ""
308# Begin Source File
309
310SOURCE=.\App.cpp
311# End Source File
312# Begin Source File
313
314SOURCE=.\App.h
315# End Source File
316# Begin Source File
317
318SOURCE=.\AppState.h
319# End Source File
320# Begin Source File
321
322SOURCE=.\EnumFormatEtc.cpp
323# End Source File
324# Begin Source File
325
326SOURCE=.\EnumFormatEtc.h
327# End Source File
328# Begin Source File
329
330SOURCE=.\FileFolderPluginOpen.cpp
331# End Source File
332# Begin Source File
333
334SOURCE=.\FileFolderPluginOpen.h
335# End Source File
336# Begin Source File
337
338SOURCE=.\Panel.cpp
339# End Source File
340# Begin Source File
341
342SOURCE=.\Panel.h
343# End Source File
344# Begin Source File
345
346SOURCE=.\PanelCopy.cpp
347# End Source File
348# Begin Source File
349
350SOURCE=.\PanelCrc.cpp
351# End Source File
352# Begin Source File
353
354SOURCE=.\PanelDrag.cpp
355# End Source File
356# Begin Source File
357
358SOURCE=.\PanelFolderChange.cpp
359# End Source File
360# Begin Source File
361
362SOURCE=.\PanelItemOpen.cpp
363# End Source File
364# Begin Source File
365
366SOURCE=.\PanelItems.cpp
367# End Source File
368# Begin Source File
369
370SOURCE=.\PanelKey.cpp
371# End Source File
372# Begin Source File
373
374SOURCE=.\PanelListNotify.cpp
375# End Source File
376# Begin Source File
377
378SOURCE=.\PanelMenu.cpp
379# End Source File
380# Begin Source File
381
382SOURCE=.\PanelOperations.cpp
383# End Source File
384# Begin Source File
385
386SOURCE=.\PanelSelect.cpp
387# End Source File
388# Begin Source File
389
390SOURCE=.\PanelSort.cpp
391# End Source File
392# Begin Source File
393
394SOURCE=.\PanelSplitFile.cpp
395# End Source File
396# Begin Source File
397
398SOURCE=.\VerCtrl.cpp
399# End Source File
400# End Group
401# Begin Group "Dialog"
402
403# PROP Default_Filter ""
404# Begin Group "Options"
405
406# PROP Default_Filter ""
407# Begin Source File
408
409SOURCE=.\EditPage.cpp
410# End Source File
411# Begin Source File
412
413SOURCE=.\EditPage.h
414# End Source File
415# Begin Source File
416
417SOURCE=.\FoldersPage.cpp
418# End Source File
419# Begin Source File
420
421SOURCE=.\FoldersPage.h
422# End Source File
423# Begin Source File
424
425SOURCE=.\LangPage.cpp
426# End Source File
427# Begin Source File
428
429SOURCE=.\LangPage.h
430# End Source File
431# Begin Source File
432
433SOURCE=.\MenuPage.cpp
434# End Source File
435# Begin Source File
436
437SOURCE=.\MenuPage.h
438# End Source File
439# Begin Source File
440
441SOURCE=.\OptionsDialog.cpp
442# End Source File
443# Begin Source File
444
445SOURCE=.\SettingsPage.cpp
446# End Source File
447# Begin Source File
448
449SOURCE=.\SettingsPage.h
450# End Source File
451# Begin Source File
452
453SOURCE=.\SystemPage.cpp
454# End Source File
455# Begin Source File
456
457SOURCE=.\SystemPage.h
458# End Source File
459# End Group
460# Begin Source File
461
462SOURCE=.\AboutDialog.cpp
463# End Source File
464# Begin Source File
465
466SOURCE=.\AboutDialog.h
467# End Source File
468# Begin Source File
469
470SOURCE=.\BrowseDialog.cpp
471# End Source File
472# Begin Source File
473
474SOURCE=.\BrowseDialog.h
475# End Source File
476# Begin Source File
477
478SOURCE=.\ComboDialog.cpp
479# End Source File
480# Begin Source File
481
482SOURCE=.\ComboDialog.h
483# End Source File
484# Begin Source File
485
486SOURCE=CopyDialog.cpp
487# End Source File
488# Begin Source File
489
490SOURCE=CopyDialog.h
491# End Source File
492# Begin Source File
493
494SOURCE=.\DialogSize.h
495# End Source File
496# Begin Source File
497
498SOURCE=.\EditDialog.cpp
499# End Source File
500# Begin Source File
501
502SOURCE=.\EditDialog.h
503# End Source File
504# Begin Source File
505
506SOURCE=.\LinkDialog.cpp
507# End Source File
508# Begin Source File
509
510SOURCE=.\LinkDialog.h
511# End Source File
512# Begin Source File
513
514SOURCE=.\ListViewDialog.cpp
515# End Source File
516# Begin Source File
517
518SOURCE=.\ListViewDialog.h
519# End Source File
520# Begin Source File
521
522SOURCE=MessagesDialog.cpp
523# End Source File
524# Begin Source File
525
526SOURCE=MessagesDialog.h
527# End Source File
528# Begin Source File
529
530SOURCE=OverwriteDialog.cpp
531# End Source File
532# Begin Source File
533
534SOURCE=OverwriteDialog.h
535# End Source File
536# Begin Source File
537
538SOURCE=.\PasswordDialog.cpp
539# End Source File
540# Begin Source File
541
542SOURCE=.\PasswordDialog.h
543# End Source File
544# Begin Source File
545
546SOURCE=.\ProgressDialog2.cpp
547# End Source File
548# Begin Source File
549
550SOURCE=.\ProgressDialog2.h
551# End Source File
552# Begin Source File
553
554SOURCE=.\SplitDialog.cpp
555# End Source File
556# Begin Source File
557
558SOURCE=.\SplitDialog.h
559# End Source File
560# End Group
561# Begin Group "FM Common"
562
563# PROP Default_Filter ""
564# Begin Source File
565
566SOURCE=.\ExtractCallback.cpp
567# End Source File
568# Begin Source File
569
570SOURCE=.\ExtractCallback.h
571# End Source File
572# Begin Source File
573
574SOURCE=.\FormatUtils.cpp
575# End Source File
576# Begin Source File
577
578SOURCE=.\FormatUtils.h
579# End Source File
580# Begin Source File
581
582SOURCE=.\HelpUtils.cpp
583# End Source File
584# Begin Source File
585
586SOURCE=.\HelpUtils.h
587# End Source File
588# Begin Source File
589
590SOURCE=.\LangUtils.cpp
591# End Source File
592# Begin Source File
593
594SOURCE=.\LangUtils.h
595# End Source File
596# Begin Source File
597
598SOURCE=.\ProgramLocation.cpp
599# End Source File
600# Begin Source File
601
602SOURCE=.\ProgramLocation.h
603# End Source File
604# Begin Source File
605
606SOURCE=.\UpdateCallback100.cpp
607# End Source File
608# Begin Source File
609
610SOURCE=.\UpdateCallback100.h
611# End Source File
612# End Group
613# Begin Group "7-Zip Common"
614
615# PROP Default_Filter ""
616# Begin Source File
617
618SOURCE=..\..\Common\CreateCoder.cpp
619# End Source File
620# Begin Source File
621
622SOURCE=..\..\Common\CreateCoder.h
623# End Source File
624# Begin Source File
625
626SOURCE=..\..\Common\FilePathAutoRename.cpp
627# End Source File
628# Begin Source File
629
630SOURCE=..\..\Common\FilePathAutoRename.h
631# End Source File
632# Begin Source File
633
634SOURCE=..\..\Common\FileStreams.cpp
635# End Source File
636# Begin Source File
637
638SOURCE=..\..\Common\FileStreams.h
639# End Source File
640# Begin Source File
641
642SOURCE=..\..\Common\FilterCoder.cpp
643# End Source File
644# Begin Source File
645
646SOURCE=..\..\Common\FilterCoder.h
647# End Source File
648# Begin Source File
649
650SOURCE=..\..\Common\LimitedStreams.cpp
651# End Source File
652# Begin Source File
653
654SOURCE=..\..\Common\LimitedStreams.h
655# End Source File
656# Begin Source File
657
658SOURCE=..\..\Common\MethodProps.cpp
659# End Source File
660# Begin Source File
661
662SOURCE=..\..\Common\MethodProps.h
663# End Source File
664# Begin Source File
665
666SOURCE=..\..\Common\ProgressUtils.cpp
667# End Source File
668# Begin Source File
669
670SOURCE=..\..\Common\ProgressUtils.h
671# End Source File
672# Begin Source File
673
674SOURCE=..\..\Common\PropId.cpp
675# End Source File
676# Begin Source File
677
678SOURCE=..\..\Common\StreamObjects.cpp
679# End Source File
680# Begin Source File
681
682SOURCE=..\..\Common\StreamObjects.h
683# End Source File
684# Begin Source File
685
686SOURCE=..\..\Common\StreamUtils.cpp
687# End Source File
688# Begin Source File
689
690SOURCE=..\..\Common\StreamUtils.h
691# End Source File
692# Begin Source File
693
694SOURCE=..\..\Common\UniqBlocks.cpp
695# End Source File
696# Begin Source File
697
698SOURCE=..\..\Common\UniqBlocks.h
699# End Source File
700# End Group
701# Begin Group "C"
702
703# PROP Default_Filter ""
704# Begin Source File
705
706SOURCE=..\..\..\..\C\7zTypes.h
707# End Source File
708# Begin Source File
709
710SOURCE=..\..\..\..\C\Alloc.c
711# SUBTRACT CPP /YX /Yc /Yu
712# End Source File
713# Begin Source File
714
715SOURCE=..\..\..\..\C\Alloc.h
716# End Source File
717# Begin Source File
718
719SOURCE=..\..\..\..\C\CpuArch.c
720# SUBTRACT CPP /YX /Yc /Yu
721# End Source File
722# Begin Source File
723
724SOURCE=..\..\..\..\C\CpuArch.h
725# End Source File
726# Begin Source File
727
728SOURCE=..\..\..\..\C\DllSecur.c
729# SUBTRACT CPP /YX /Yc /Yu
730# End Source File
731# Begin Source File
732
733SOURCE=..\..\..\..\C\DllSecur.h
734# End Source File
735# Begin Source File
736
737SOURCE=..\..\..\..\C\Sort.c
738# SUBTRACT CPP /YX /Yc /Yu
739# End Source File
740# Begin Source File
741
742SOURCE=..\..\..\..\C\Sort.h
743# End Source File
744# Begin Source File
745
746SOURCE=..\..\..\..\C\Threads.c
747# SUBTRACT CPP /YX /Yc /Yu
748# End Source File
749# Begin Source File
750
751SOURCE=..\..\..\..\C\Threads.h
752# End Source File
753# End Group
754# Begin Group "Windows"
755
756# PROP Default_Filter ""
757# Begin Group "Control"
758
759# PROP Default_Filter ""
760# Begin Source File
761
762SOURCE=..\..\..\Windows\Control\ComboBox.cpp
763# End Source File
764# Begin Source File
765
766SOURCE=..\..\..\Windows\Control\ComboBox.h
767# End Source File
768# Begin Source File
769
770SOURCE=..\..\..\Windows\Control\CommandBar.h
771# End Source File
772# Begin Source File
773
774SOURCE=..\..\..\Windows\Control\Dialog.cpp
775# End Source File
776# Begin Source File
777
778SOURCE=..\..\..\Windows\Control\Dialog.h
779# End Source File
780# Begin Source File
781
782SOURCE=..\..\..\Windows\Control\Edit.h
783# End Source File
784# Begin Source File
785
786SOURCE=..\..\..\Windows\Control\ImageList.h
787# End Source File
788# Begin Source File
789
790SOURCE=..\..\..\Windows\Control\ListView.cpp
791# End Source File
792# Begin Source File
793
794SOURCE=..\..\..\Windows\Control\ListView.h
795# End Source File
796# Begin Source File
797
798SOURCE=..\..\..\Windows\Control\ProgressBar.h
799# End Source File
800# Begin Source File
801
802SOURCE=..\..\..\Windows\Control\PropertyPage.cpp
803# End Source File
804# Begin Source File
805
806SOURCE=..\..\..\Windows\Control\PropertyPage.h
807# End Source File
808# Begin Source File
809
810SOURCE=..\..\..\Windows\Control\ReBar.h
811# End Source File
812# Begin Source File
813
814SOURCE=..\..\..\Windows\Control\Static.h
815# End Source File
816# Begin Source File
817
818SOURCE=..\..\..\Windows\Control\StatusBar.h
819# End Source File
820# Begin Source File
821
822SOURCE=..\..\..\Windows\Control\ToolBar.h
823# End Source File
824# Begin Source File
825
826SOURCE=..\..\..\Windows\Control\Window2.cpp
827# End Source File
828# Begin Source File
829
830SOURCE=..\..\..\Windows\Control\Window2.h
831# End Source File
832# End Group
833# Begin Source File
834
835SOURCE=..\..\..\Windows\Clipboard.cpp
836# End Source File
837# Begin Source File
838
839SOURCE=..\..\..\Windows\Clipboard.h
840# End Source File
841# Begin Source File
842
843SOURCE=..\..\..\Windows\COM.h
844# End Source File
845# Begin Source File
846
847SOURCE=..\..\..\Windows\CommonDialog.cpp
848# End Source File
849# Begin Source File
850
851SOURCE=..\..\..\Windows\CommonDialog.h
852# End Source File
853# Begin Source File
854
855SOURCE=..\..\..\Windows\Defs.h
856# End Source File
857# Begin Source File
858
859SOURCE=..\..\..\Windows\Device.h
860# End Source File
861# Begin Source File
862
863SOURCE=..\..\..\Windows\DLL.cpp
864# End Source File
865# Begin Source File
866
867SOURCE=..\..\..\Windows\DLL.h
868# End Source File
869# Begin Source File
870
871SOURCE=..\..\..\Windows\ErrorMsg.cpp
872# End Source File
873# Begin Source File
874
875SOURCE=..\..\..\Windows\ErrorMsg.h
876# End Source File
877# Begin Source File
878
879SOURCE=..\..\..\Windows\FileDir.cpp
880# End Source File
881# Begin Source File
882
883SOURCE=..\..\..\Windows\FileDir.h
884# End Source File
885# Begin Source File
886
887SOURCE=..\..\..\Windows\FileFind.cpp
888# End Source File
889# Begin Source File
890
891SOURCE=..\..\..\Windows\FileFind.h
892# End Source File
893# Begin Source File
894
895SOURCE=..\..\..\Windows\FileIO.cpp
896# End Source File
897# Begin Source File
898
899SOURCE=..\..\..\Windows\FileIO.h
900# End Source File
901# Begin Source File
902
903SOURCE=..\..\..\Windows\FileLink.cpp
904# End Source File
905# Begin Source File
906
907SOURCE=..\..\..\Windows\FileMapping.h
908# End Source File
909# Begin Source File
910
911SOURCE=..\..\..\Windows\FileName.cpp
912# End Source File
913# Begin Source File
914
915SOURCE=..\..\..\Windows\FileName.h
916# End Source File
917# Begin Source File
918
919SOURCE=..\..\..\Windows\FileSystem.cpp
920# End Source File
921# Begin Source File
922
923SOURCE=..\..\..\Windows\FileSystem.h
924# End Source File
925# Begin Source File
926
927SOURCE=..\..\..\Windows\Handle.h
928# End Source File
929# Begin Source File
930
931SOURCE=..\..\..\Windows\MemoryGlobal.cpp
932# End Source File
933# Begin Source File
934
935SOURCE=..\..\..\Windows\MemoryGlobal.h
936# End Source File
937# Begin Source File
938
939SOURCE=..\..\..\Windows\MemoryLock.cpp
940# End Source File
941# Begin Source File
942
943SOURCE=..\..\..\Windows\MemoryLock.h
944# End Source File
945# Begin Source File
946
947SOURCE=..\..\..\Windows\Menu.cpp
948# End Source File
949# Begin Source File
950
951SOURCE=..\..\..\Windows\Menu.h
952# End Source File
953# Begin Source File
954
955SOURCE=..\..\..\Windows\Net.cpp
956# End Source File
957# Begin Source File
958
959SOURCE=..\..\..\Windows\Net.h
960# End Source File
961# Begin Source File
962
963SOURCE=..\..\..\Windows\NtCheck.h
964# End Source File
965# Begin Source File
966
967SOURCE=..\..\..\Windows\ProcessUtils.cpp
968# End Source File
969# Begin Source File
970
971SOURCE=..\..\..\Windows\ProcessUtils.h
972# End Source File
973# Begin Source File
974
975SOURCE=..\..\..\Windows\PropVariant.cpp
976# End Source File
977# Begin Source File
978
979SOURCE=..\..\..\Windows\PropVariant.h
980# End Source File
981# Begin Source File
982
983SOURCE=..\..\..\Windows\PropVariantConv.cpp
984# End Source File
985# Begin Source File
986
987SOURCE=..\..\..\Windows\PropVariantConv.h
988# End Source File
989# Begin Source File
990
991SOURCE=..\..\..\Windows\Registry.cpp
992# End Source File
993# Begin Source File
994
995SOURCE=..\..\..\Windows\Registry.h
996# End Source File
997# Begin Source File
998
999SOURCE=..\..\..\Windows\ResourceString.cpp
1000# End Source File
1001# Begin Source File
1002
1003SOURCE=..\..\..\Windows\ResourceString.h
1004# End Source File
1005# Begin Source File
1006
1007SOURCE=..\..\..\Windows\SecurityUtils.cpp
1008# End Source File
1009# Begin Source File
1010
1011SOURCE=..\..\..\Windows\SecurityUtils.h
1012# End Source File
1013# Begin Source File
1014
1015SOURCE=..\..\..\Windows\Shell.cpp
1016# End Source File
1017# Begin Source File
1018
1019SOURCE=..\..\..\Windows\Shell.h
1020# End Source File
1021# Begin Source File
1022
1023SOURCE=..\..\..\Windows\Synchronization.cpp
1024# End Source File
1025# Begin Source File
1026
1027SOURCE=..\..\..\Windows\Synchronization.h
1028# End Source File
1029# Begin Source File
1030
1031SOURCE=..\..\..\Windows\System.cpp
1032# End Source File
1033# Begin Source File
1034
1035SOURCE=..\..\..\Windows\System.h
1036# End Source File
1037# Begin Source File
1038
1039SOURCE=..\..\..\Windows\Thread.h
1040# End Source File
1041# Begin Source File
1042
1043SOURCE=..\..\..\Windows\TimeUtils.cpp
1044# End Source File
1045# Begin Source File
1046
1047SOURCE=..\..\..\Windows\TimeUtils.h
1048# End Source File
1049# Begin Source File
1050
1051SOURCE=..\..\..\Windows\Window.cpp
1052# End Source File
1053# Begin Source File
1054
1055SOURCE=..\..\..\Windows\Window.h
1056# End Source File
1057# End Group
1058# Begin Group "Common"
1059
1060# PROP Default_Filter ""
1061# Begin Source File
1062
1063SOURCE=..\..\..\Common\Common.h
1064# End Source File
1065# Begin Source File
1066
1067SOURCE=..\..\..\Common\ComTry.h
1068# End Source File
1069# Begin Source File
1070
1071SOURCE=..\..\..\Common\Defs.h
1072# End Source File
1073# Begin Source File
1074
1075SOURCE=..\..\..\Common\DynamicBuffer.h
1076# End Source File
1077# Begin Source File
1078
1079SOURCE=..\..\..\Common\DynLimBuf.cpp
1080# End Source File
1081# Begin Source File
1082
1083SOURCE=..\..\..\Common\DynLimBuf.h
1084# End Source File
1085# Begin Source File
1086
1087SOURCE=..\..\..\Common\Exception.h
1088# End Source File
1089# Begin Source File
1090
1091SOURCE=..\..\..\Common\IntToString.cpp
1092# End Source File
1093# Begin Source File
1094
1095SOURCE=..\..\..\Common\IntToString.h
1096# End Source File
1097# Begin Source File
1098
1099SOURCE=..\..\..\Common\Lang.cpp
1100# End Source File
1101# Begin Source File
1102
1103SOURCE=..\..\..\Common\Lang.h
1104# End Source File
1105# Begin Source File
1106
1107SOURCE=..\..\..\Common\MyBuffer.h
1108# End Source File
1109# Begin Source File
1110
1111SOURCE=..\..\..\Common\MyCom.h
1112# End Source File
1113# Begin Source File
1114
1115SOURCE=..\..\..\Common\MyString.cpp
1116# End Source File
1117# Begin Source File
1118
1119SOURCE=..\..\..\Common\MyString.h
1120# End Source File
1121# Begin Source File
1122
1123SOURCE=..\..\..\Common\MyTypes.h
1124# End Source File
1125# Begin Source File
1126
1127SOURCE=..\..\..\Common\MyVector.cpp
1128# End Source File
1129# Begin Source File
1130
1131SOURCE=..\..\..\Common\MyVector.h
1132# End Source File
1133# Begin Source File
1134
1135SOURCE=..\..\..\Common\NewHandler.cpp
1136# End Source File
1137# Begin Source File
1138
1139SOURCE=..\..\..\Common\NewHandler.h
1140# End Source File
1141# Begin Source File
1142
1143SOURCE=..\..\..\Common\Random.cpp
1144# End Source File
1145# Begin Source File
1146
1147SOURCE=..\..\..\Common\Random.h
1148# End Source File
1149# Begin Source File
1150
1151SOURCE=..\..\..\Common\StringConvert.cpp
1152# End Source File
1153# Begin Source File
1154
1155SOURCE=..\..\..\Common\StringConvert.h
1156# End Source File
1157# Begin Source File
1158
1159SOURCE=..\..\..\Common\StringToInt.cpp
1160# End Source File
1161# Begin Source File
1162
1163SOURCE=..\..\..\Common\StringToInt.h
1164# End Source File
1165# Begin Source File
1166
1167SOURCE=..\..\..\Common\UTFConvert.cpp
1168# End Source File
1169# Begin Source File
1170
1171SOURCE=..\..\..\Common\UTFConvert.h
1172# End Source File
1173# Begin Source File
1174
1175SOURCE=..\..\..\Common\Wildcard.cpp
1176# End Source File
1177# Begin Source File
1178
1179SOURCE=..\..\..\Common\Wildcard.h
1180# End Source File
1181# End Group
1182# Begin Group "UI"
1183
1184# PROP Default_Filter ""
1185# Begin Group "UI Common"
1186
1187# PROP Default_Filter ""
1188# Begin Source File
1189
1190SOURCE=..\Common\ArchiveExtractCallback.cpp
1191# End Source File
1192# Begin Source File
1193
1194SOURCE=..\Common\ArchiveExtractCallback.h
1195# End Source File
1196# Begin Source File
1197
1198SOURCE=..\Common\ArchiveName.cpp
1199# End Source File
1200# Begin Source File
1201
1202SOURCE=..\Common\ArchiveName.h
1203# End Source File
1204# Begin Source File
1205
1206SOURCE=..\Common\ArchiveOpenCallback.cpp
1207# End Source File
1208# Begin Source File
1209
1210SOURCE=..\Common\ArchiveOpenCallback.h
1211# End Source File
1212# Begin Source File
1213
1214SOURCE=..\Common\CompressCall.cpp
1215# End Source File
1216# Begin Source File
1217
1218SOURCE=..\Common\CompressCall.h
1219# End Source File
1220# Begin Source File
1221
1222SOURCE=..\Common\DefaultName.cpp
1223# End Source File
1224# Begin Source File
1225
1226SOURCE=..\Common\DefaultName.h
1227# End Source File
1228# Begin Source File
1229
1230SOURCE=..\Common\DirItem.h
1231# End Source File
1232# Begin Source File
1233
1234SOURCE=..\Common\EnumDirItems.cpp
1235# End Source File
1236# Begin Source File
1237
1238SOURCE=..\Common\EnumDirItems.h
1239# End Source File
1240# Begin Source File
1241
1242SOURCE=..\Common\ExitCode.h
1243# End Source File
1244# Begin Source File
1245
1246SOURCE=..\Common\ExtractingFilePath.cpp
1247# End Source File
1248# Begin Source File
1249
1250SOURCE=..\Common\ExtractingFilePath.h
1251# End Source File
1252# Begin Source File
1253
1254SOURCE=..\Common\ExtractMode.h
1255# End Source File
1256# Begin Source File
1257
1258SOURCE=..\Common\HashCalc.cpp
1259# End Source File
1260# Begin Source File
1261
1262SOURCE=..\Common\HashCalc.h
1263# End Source File
1264# Begin Source File
1265
1266SOURCE=..\Common\IFileExtractCallback.h
1267# End Source File
1268# Begin Source File
1269
1270SOURCE=..\Common\LoadCodecs.cpp
1271# End Source File
1272# Begin Source File
1273
1274SOURCE=..\Common\LoadCodecs.h
1275# End Source File
1276# Begin Source File
1277
1278SOURCE=..\Common\OpenArchive.cpp
1279# End Source File
1280# Begin Source File
1281
1282SOURCE=..\Common\OpenArchive.h
1283# End Source File
1284# Begin Source File
1285
1286SOURCE=..\Common\Property.h
1287# End Source File
1288# Begin Source File
1289
1290SOURCE=..\Common\PropIDUtils.cpp
1291# End Source File
1292# Begin Source File
1293
1294SOURCE=..\Common\PropIDUtils.h
1295# End Source File
1296# Begin Source File
1297
1298SOURCE=..\Common\SetProperties.cpp
1299# End Source File
1300# Begin Source File
1301
1302SOURCE=..\Common\SetProperties.h
1303# End Source File
1304# Begin Source File
1305
1306SOURCE=..\Common\SortUtils.cpp
1307# End Source File
1308# Begin Source File
1309
1310SOURCE=..\Common\SortUtils.h
1311# End Source File
1312# Begin Source File
1313
1314SOURCE=..\Common\StdAfx.h
1315# End Source File
1316# Begin Source File
1317
1318SOURCE=..\Common\UpdateAction.cpp
1319# End Source File
1320# Begin Source File
1321
1322SOURCE=..\Common\UpdateAction.h
1323# End Source File
1324# Begin Source File
1325
1326SOURCE=..\Common\UpdateCallback.cpp
1327# End Source File
1328# Begin Source File
1329
1330SOURCE=..\Common\UpdateCallback.h
1331# End Source File
1332# Begin Source File
1333
1334SOURCE=..\Common\UpdatePair.cpp
1335# End Source File
1336# Begin Source File
1337
1338SOURCE=..\Common\UpdatePair.h
1339# End Source File
1340# Begin Source File
1341
1342SOURCE=..\Common\UpdateProduce.cpp
1343# End Source File
1344# Begin Source File
1345
1346SOURCE=..\Common\UpdateProduce.h
1347# End Source File
1348# Begin Source File
1349
1350SOURCE=..\Common\WorkDir.cpp
1351# End Source File
1352# Begin Source File
1353
1354SOURCE=..\Common\WorkDir.h
1355# End Source File
1356# Begin Source File
1357
1358SOURCE=..\Common\ZipRegistry.cpp
1359# End Source File
1360# Begin Source File
1361
1362SOURCE=..\Common\ZipRegistry.h
1363# End Source File
1364# End Group
1365# Begin Group "Agent"
1366
1367# PROP Default_Filter ""
1368# Begin Source File
1369
1370SOURCE=..\Agent\Agent.cpp
1371# End Source File
1372# Begin Source File
1373
1374SOURCE=..\Agent\Agent.h
1375# End Source File
1376# Begin Source File
1377
1378SOURCE=..\Agent\AgentOut.cpp
1379# End Source File
1380# Begin Source File
1381
1382SOURCE=..\Agent\AgentProxy.cpp
1383# End Source File
1384# Begin Source File
1385
1386SOURCE=..\Agent\AgentProxy.h
1387# End Source File
1388# Begin Source File
1389
1390SOURCE=..\Agent\ArchiveFolder.cpp
1391# End Source File
1392# Begin Source File
1393
1394SOURCE=..\Agent\ArchiveFolderOpen.cpp
1395# End Source File
1396# Begin Source File
1397
1398SOURCE=..\Agent\ArchiveFolderOut.cpp
1399# End Source File
1400# Begin Source File
1401
1402SOURCE=..\Agent\IFolderArchive.h
1403# End Source File
1404# Begin Source File
1405
1406SOURCE=..\Agent\UpdateCallbackAgent.cpp
1407# End Source File
1408# Begin Source File
1409
1410SOURCE=..\Agent\UpdateCallbackAgent.h
1411# End Source File
1412# End Group
1413# Begin Group "Explorer"
1414
1415# PROP Default_Filter ""
1416# Begin Source File
1417
1418SOURCE=..\Explorer\ContextMenu.cpp
1419# End Source File
1420# Begin Source File
1421
1422SOURCE=..\Explorer\ContextMenu.h
1423# End Source File
1424# Begin Source File
1425
1426SOURCE=..\Explorer\ContextMenuFlags.h
1427# End Source File
1428# Begin Source File
1429
1430SOURCE=..\Explorer\MyExplorerCommand.h
1431# End Source File
1432# Begin Source File
1433
1434SOURCE=..\Explorer\RegistryContextMenu.cpp
1435# End Source File
1436# Begin Source File
1437
1438SOURCE=..\Explorer\RegistryContextMenu.h
1439# End Source File
1440# End Group
1441# Begin Group "GUI"
1442
1443# PROP Default_Filter ""
1444# Begin Source File
1445
1446SOURCE=..\GUI\HashGUI.cpp
1447# End Source File
1448# Begin Source File
1449
1450SOURCE=..\GUI\HashGUI.h
1451# End Source File
1452# Begin Source File
1453
1454SOURCE=..\GUI\UpdateCallbackGUI2.cpp
1455# End Source File
1456# Begin Source File
1457
1458SOURCE=..\GUI\UpdateCallbackGUI2.h
1459# End Source File
1460# End Group
1461# End Group
1462# Begin Group "Compress"
1463
1464# PROP Default_Filter ""
1465# Begin Source File
1466
1467SOURCE=..\..\Compress\CopyCoder.cpp
1468# End Source File
1469# Begin Source File
1470
1471SOURCE=..\..\Compress\CopyCoder.h
1472# End Source File
1473# End Group
1474# Begin Group "Interface"
1475
1476# PROP Default_Filter ""
1477# Begin Source File
1478
1479SOURCE=..\..\Archive\IArchive.h
1480# End Source File
1481# Begin Source File
1482
1483SOURCE=..\..\ICoder.h
1484# End Source File
1485# Begin Source File
1486
1487SOURCE=..\..\IDecl.h
1488# End Source File
1489# Begin Source File
1490
1491SOURCE=..\..\IPassword.h
1492# End Source File
1493# Begin Source File
1494
1495SOURCE=..\..\IProgress.h
1496# End Source File
1497# Begin Source File
1498
1499SOURCE=..\..\IStream.h
1500# End Source File
1501# Begin Source File
1502
1503SOURCE=..\..\PropID.h
1504# End Source File
1505# End Group
1506# Begin Group "ArchiveCommon"
1507
1508# PROP Default_Filter ""
1509# Begin Source File
1510
1511SOURCE=..\..\Archive\Common\ItemNameUtils.cpp
1512# End Source File
1513# Begin Source File
1514
1515SOURCE=..\..\Archive\Common\ItemNameUtils.h
1516# End Source File
1517# End Group
1518# Begin Source File
1519
1520SOURCE=.\7zFM.exe.manifest
1521# End Source File
1522# Begin Source File
1523
1524SOURCE=.\7zipLogo.ico
1525# End Source File
1526# Begin Source File
1527
1528SOURCE=.\Add2.bmp
1529# End Source File
1530# Begin Source File
1531
1532SOURCE=.\Copy2.bmp
1533# End Source File
1534# Begin Source File
1535
1536SOURCE=.\Delete2.bmp
1537# End Source File
1538# Begin Source File
1539
1540SOURCE=.\Extract2.bmp
1541# End Source File
1542# Begin Source File
1543
1544SOURCE=.\FilePlugins.cpp
1545# End Source File
1546# Begin Source File
1547
1548SOURCE=.\FilePlugins.h
1549# End Source File
1550# Begin Source File
1551
1552SOURCE=.\FM.cpp
1553# End Source File
1554# Begin Source File
1555
1556SOURCE=.\Info.bmp
1557# End Source File
1558# Begin Source File
1559
1560SOURCE=.\Info2.bmp
1561# End Source File
1562# Begin Source File
1563
1564SOURCE=.\Move2.bmp
1565# End Source File
1566# Begin Source File
1567
1568SOURCE=.\MyCom2.h
1569# End Source File
1570# Begin Source File
1571
1572SOURCE=.\MyLoadMenu.cpp
1573# End Source File
1574# Begin Source File
1575
1576SOURCE=.\MyLoadMenu.h
1577# End Source File
1578# Begin Source File
1579
1580SOURCE=.\OpenCallback.cpp
1581# End Source File
1582# Begin Source File
1583
1584SOURCE=.\OpenCallback.h
1585# End Source File
1586# Begin Source File
1587
1588SOURCE=.\PluginInterface.h
1589# End Source File
1590# Begin Source File
1591
1592SOURCE=.\PluginLoader.h
1593# End Source File
1594# Begin Source File
1595
1596SOURCE=.\PropertyName.cpp
1597# End Source File
1598# Begin Source File
1599
1600SOURCE=.\PropertyName.h
1601# End Source File
1602# Begin Source File
1603
1604SOURCE=.\resource.h
1605# End Source File
1606# Begin Source File
1607
1608SOURCE=.\SplitUtils.cpp
1609# End Source File
1610# Begin Source File
1611
1612SOURCE=.\SplitUtils.h
1613# End Source File
1614# Begin Source File
1615
1616SOURCE=.\StringUtils.cpp
1617# End Source File
1618# Begin Source File
1619
1620SOURCE=.\StringUtils.h
1621# End Source File
1622# Begin Source File
1623
1624SOURCE=.\SysIconUtils.cpp
1625# End Source File
1626# Begin Source File
1627
1628SOURCE=.\SysIconUtils.h
1629# End Source File
1630# Begin Source File
1631
1632SOURCE=.\Test2.bmp
1633# End Source File
1634# Begin Source File
1635
1636SOURCE=.\TextPairs.cpp
1637# End Source File
1638# Begin Source File
1639
1640SOURCE=.\TextPairs.h
1641# End Source File
1642# End Target
1643# End Project
diff --git a/CPP/7zip/UI/FileManager/FM.dsw b/CPP/7zip/UI/FileManager/FM.dsw
new file mode 100644
index 0000000..1c955d9
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FM.dsw
@@ -0,0 +1,29 @@
1Microsoft Developer Studio Workspace File, Format Version 6.00
2# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
3
4###############################################################################
5
6Project: "FM"=.\FM.dsp - Package Owner=<4>
7
8Package=<5>
9{{{
10}}}
11
12Package=<4>
13{{{
14}}}
15
16###############################################################################
17
18Global:
19
20Package=<5>
21{{{
22}}}
23
24Package=<3>
25{{{
26}}}
27
28###############################################################################
29
diff --git a/CPP/7zip/UI/FileManager/FM.ico b/CPP/7zip/UI/FileManager/FM.ico
new file mode 100644
index 0000000..3a0a34d
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FM.ico
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/FM.mak b/CPP/7zip/UI/FileManager/FM.mak
new file mode 100644
index 0000000..8b3d97a
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FM.mak
@@ -0,0 +1,100 @@
1CFLAGS = $(CFLAGS) \
2 -DLANG \
3 -DNEW_FOLDER_INTERFACE \
4
5!IFDEF UNDER_CE
6LIBS = $(LIBS) ceshell.lib Commctrl.lib
7!ELSE
8LIBS = $(LIBS) comctl32.lib htmlhelp.lib comdlg32.lib Mpr.lib Gdi32.lib
9CFLAGS = $(CFLAGS) -DWIN_LONG_PATH -DSUPPORT_DEVICE_FILE
10LFLAGS = $(LFLAGS) /DELAYLOAD:mpr.dll
11LIBS = $(LIBS) delayimp.lib
12!ENDIF
13
14FM_OBJS = \
15 $O\App.obj \
16 $O\BrowseDialog.obj \
17 $O\ClassDefs.obj \
18 $O\EnumFormatEtc.obj \
19 $O\ExtractCallback.obj \
20 $O\FileFolderPluginOpen.obj \
21 $O\FilePlugins.obj \
22 $O\FM.obj \
23 $O\FoldersPage.obj \
24 $O\FormatUtils.obj \
25 $O\FSFolder.obj \
26 $O\FSFolderCopy.obj \
27 $O\HelpUtils.obj \
28 $O\LangUtils.obj \
29 $O\MenuPage.obj \
30 $O\MyLoadMenu.obj \
31 $O\OpenCallback.obj \
32 $O\OptionsDialog.obj \
33 $O\Panel.obj \
34 $O\PanelCopy.obj \
35 $O\PanelCrc.obj \
36 $O\PanelDrag.obj \
37 $O\PanelFolderChange.obj \
38 $O\PanelItemOpen.obj \
39 $O\PanelItems.obj \
40 $O\PanelKey.obj \
41 $O\PanelListNotify.obj \
42 $O\PanelMenu.obj \
43 $O\PanelOperations.obj \
44 $O\PanelSelect.obj \
45 $O\PanelSort.obj \
46 $O\PanelSplitFile.obj \
47 $O\ProgramLocation.obj \
48 $O\PropertyName.obj \
49 $O\RegistryAssociations.obj \
50 $O\RegistryPlugins.obj \
51 $O\RegistryUtils.obj \
52 $O\RootFolder.obj \
53 $O\SplitUtils.obj \
54 $O\StringUtils.obj \
55 $O\SysIconUtils.obj \
56 $O\TextPairs.obj \
57 $O\UpdateCallback100.obj \
58 $O\ViewSettings.obj \
59 $O\AboutDialog.obj \
60 $O\ComboDialog.obj \
61 $O\CopyDialog.obj \
62 $O\EditDialog.obj \
63 $O\EditPage.obj \
64 $O\LangPage.obj \
65 $O\ListViewDialog.obj \
66 $O\MessagesDialog.obj \
67 $O\OverwriteDialog.obj \
68 $O\PasswordDialog.obj \
69 $O\ProgressDialog2.obj \
70 $O\SettingsPage.obj \
71 $O\SplitDialog.obj \
72 $O\SystemPage.obj \
73 $O\VerCtrl.obj \
74
75!IFNDEF UNDER_CE
76
77FM_OBJS = $(FM_OBJS) \
78 $O\AltStreamsFolder.obj \
79 $O\FSDrives.obj \
80 $O\LinkDialog.obj \
81 $O\NetFolder.obj \
82
83WIN_OBJS = $(WIN_OBJS) \
84 $O\FileSystem.obj \
85 $O\Net.obj \
86 $O\SecurityUtils.obj \
87
88!ENDIF
89
90C_OBJS = $(C_OBJS) \
91 $O\DllSecur.obj \
92
93AGENT_OBJS = \
94 $O\Agent.obj \
95 $O\AgentOut.obj \
96 $O\AgentProxy.obj \
97 $O\ArchiveFolder.obj \
98 $O\ArchiveFolderOpen.obj \
99 $O\ArchiveFolderOut.obj \
100 $O\UpdateCallbackAgent.obj \
diff --git a/CPP/7zip/UI/FileManager/FSDrives.cpp b/CPP/7zip/UI/FileManager/FSDrives.cpp
new file mode 100644
index 0000000..c563907
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FSDrives.cpp
@@ -0,0 +1,494 @@
1// FSDrives.cpp
2
3#include "StdAfx.h"
4
5#include "../../../../C/Alloc.h"
6
7#include "../../../Common/ComTry.h"
8#include "../../../Common/Defs.h"
9#include "../../../Common/IntToString.h"
10#include "../../../Common/StringConvert.h"
11
12#include "../../../Windows/FileDir.h"
13#include "../../../Windows/FileIO.h"
14#include "../../../Windows/FileName.h"
15#include "../../../Windows/FileSystem.h"
16#include "../../../Windows/PropVariant.h"
17
18#include "../../PropID.h"
19
20#include "FSDrives.h"
21#include "FSFolder.h"
22#include "LangUtils.h"
23#include "SysIconUtils.h"
24
25#include "resource.h"
26
27using namespace NWindows;
28using namespace NFile;
29using namespace NFind;
30
31static const char * const kVolPrefix = "\\\\.\\";
32static const char * const kSuperPrefix = "\\\\?\\";
33
34FString CDriveInfo::GetDeviceFileIoName() const
35{
36 FString f (kVolPrefix);
37 f += Name;
38 return f;
39}
40
41struct CPhysTempBuffer
42{
43 void *buffer;
44 CPhysTempBuffer(): buffer(0) {}
45 ~CPhysTempBuffer() { MidFree(buffer); }
46};
47
48static HRESULT CopyFileSpec(CFSTR fromPath, CFSTR toPath, bool writeToDisk, UInt64 fileSize,
49 UInt32 bufferSize, UInt64 progressStart, IProgress *progress)
50{
51 NIO::CInFile inFile;
52 if (!inFile.Open(fromPath))
53 return GetLastError();
54 if (fileSize == (UInt64)(Int64)-1)
55 {
56 if (!inFile.GetLength(fileSize))
57 ::GetLastError();
58 }
59
60 NIO::COutFile outFile;
61 if (writeToDisk)
62 {
63 if (!outFile.Open(toPath, FILE_SHARE_WRITE, OPEN_EXISTING, 0))
64 return GetLastError();
65 }
66 else
67 if (!outFile.Create(toPath, true))
68 return GetLastError();
69
70 CPhysTempBuffer tempBuffer;
71 tempBuffer.buffer = MidAlloc(bufferSize);
72 if (!tempBuffer.buffer)
73 return E_OUTOFMEMORY;
74
75 for (UInt64 pos = 0; pos < fileSize;)
76 {
77 UInt64 progressCur = progressStart + pos;
78 RINOK(progress->SetCompleted(&progressCur));
79 UInt64 rem = fileSize - pos;
80 UInt32 curSize = (UInt32)MyMin(rem, (UInt64)bufferSize);
81 UInt32 processedSize;
82 if (!inFile.Read(tempBuffer.buffer, curSize, processedSize))
83 return GetLastError();
84 if (processedSize == 0)
85 break;
86 curSize = processedSize;
87 if (writeToDisk)
88 {
89 const UInt32 kMask = 0x1FF;
90 curSize = (curSize + kMask) & ~kMask;
91 if (curSize > bufferSize)
92 return E_FAIL;
93 }
94
95 if (!outFile.Write(tempBuffer.buffer, curSize, processedSize))
96 return GetLastError();
97 if (curSize != processedSize)
98 return E_FAIL;
99 pos += curSize;
100 }
101
102 return S_OK;
103}
104
105static const Byte kProps[] =
106{
107 kpidName,
108 // kpidOutName,
109 kpidTotalSize,
110 kpidFreeSpace,
111 kpidType,
112 kpidVolumeName,
113 kpidFileSystem,
114 kpidClusterSize
115};
116
117static const char * const kDriveTypes[] =
118{
119 "Unknown"
120 , "No Root Dir"
121 , "Removable"
122 , "Fixed"
123 , "Remote"
124 , "CD-ROM"
125 , "RAM disk"
126};
127
128STDMETHODIMP CFSDrives::LoadItems()
129{
130 _drives.Clear();
131
132 FStringVector driveStrings;
133 MyGetLogicalDriveStrings(driveStrings);
134
135 FOR_VECTOR (i, driveStrings)
136 {
137 CDriveInfo di;
138
139 const FString &driveName = driveStrings[i];
140
141 di.FullSystemName = driveName;
142 if (!driveName.IsEmpty())
143 di.Name.SetFrom(driveName, driveName.Len() - 1);
144 di.ClusterSize = 0;
145 di.DriveSize = 0;
146 di.FreeSpace = 0;
147 di.DriveType = NSystem::MyGetDriveType(driveName);
148 bool needRead = true;
149
150 if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE)
151 {
152 /*
153 DWORD dwSerialNumber;`
154 if (!::GetVolumeInformation(di.FullSystemName,
155 NULL, 0, &dwSerialNumber, NULL, NULL, NULL, 0))
156 */
157 {
158 needRead = false;
159 }
160 }
161
162 if (needRead)
163 {
164 DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags;
165 NSystem::MyGetVolumeInformation(driveName,
166 di.VolumeName,
167 &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags,
168 di.FileSystemName);
169
170 NSystem::MyGetDiskFreeSpace(driveName,
171 di.ClusterSize, di.DriveSize, di.FreeSpace);
172 di.KnownSizes = true;
173 di.KnownSize = true;
174 }
175
176 _drives.Add(di);
177 }
178
179 if (_volumeMode)
180 {
181 // we must use IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
182 for (unsigned n = 0; n < 16; n++) // why 16 ?
183 {
184 FString name ("PhysicalDrive");
185 name.Add_UInt32(n);
186
187 FString fullPath (kVolPrefix);
188 fullPath += name;
189
190 CFileInfo fi;
191 if (!fi.Find(fullPath))
192 continue;
193
194 CDriveInfo di;
195 di.Name = name;
196 di.FullSystemName = fullPath;
197 di.ClusterSize = 0;
198 di.DriveSize = fi.Size;
199 di.FreeSpace = 0;
200 di.DriveType = 0;
201
202 di.IsPhysicalDrive = true;
203 di.KnownSize = true;
204
205 _drives.Add(di);
206 }
207 }
208
209 return S_OK;
210}
211
212STDMETHODIMP CFSDrives::GetNumberOfItems(UInt32 *numItems)
213{
214 *numItems = _drives.Size();
215 return S_OK;
216}
217
218STDMETHODIMP CFSDrives::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
219{
220 if (itemIndex >= (UInt32)_drives.Size())
221 return E_INVALIDARG;
222 NCOM::CPropVariant prop;
223 const CDriveInfo &di = _drives[itemIndex];
224 switch (propID)
225 {
226 case kpidIsDir: prop = !_volumeMode; break;
227 case kpidName: prop = fs2us(di.Name); break;
228 case kpidOutName:
229 if (!di.Name.IsEmpty() && di.Name.Back() == ':')
230 {
231 FString s = di.Name;
232 s.DeleteBack();
233 AddExt(s, itemIndex);
234 prop = fs2us(s);
235 }
236 break;
237
238 case kpidTotalSize: if (di.KnownSize) prop = di.DriveSize; break;
239 case kpidFreeSpace: if (di.KnownSizes) prop = di.FreeSpace; break;
240 case kpidClusterSize: if (di.KnownSizes) prop = di.ClusterSize; break;
241 case kpidType:
242 if (di.DriveType < ARRAY_SIZE(kDriveTypes))
243 prop = kDriveTypes[di.DriveType];
244 break;
245 case kpidVolumeName: prop = di.VolumeName; break;
246 case kpidFileSystem: prop = di.FileSystemName; break;
247 }
248 prop.Detach(value);
249 return S_OK;
250}
251
252HRESULT CFSDrives::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
253{
254 *resultFolder = 0;
255 if (_volumeMode)
256 return S_OK;
257 NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
258 CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
259 FString path;
260 if (_superMode)
261 path = kSuperPrefix;
262 path += name;
263 RINOK(fsFolderSpec->Init(path));
264 *resultFolder = subFolder.Detach();
265 return S_OK;
266}
267
268STDMETHODIMP CFSDrives::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
269{
270 *resultFolder = 0;
271 if (index >= (UInt32)_drives.Size())
272 return E_INVALIDARG;
273 const CDriveInfo &di = _drives[index];
274 /*
275 if (_volumeMode)
276 {
277 *resultFolder = 0;
278 CPhysDriveFolder *folderSpec = new CPhysDriveFolder;
279 CMyComPtr<IFolderFolder> subFolder = folderSpec;
280 RINOK(folderSpec->Init(di.Name));
281 *resultFolder = subFolder.Detach();
282 return S_OK;
283 }
284 */
285 return BindToFolderSpec(di.FullSystemName, resultFolder);
286}
287
288STDMETHODIMP CFSDrives::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
289{
290 return BindToFolderSpec(us2fs(name), resultFolder);
291}
292
293STDMETHODIMP CFSDrives::BindToParentFolder(IFolderFolder **resultFolder)
294{
295 *resultFolder = 0;
296 return S_OK;
297}
298
299IMP_IFolderFolder_Props(CFSDrives)
300
301STDMETHODIMP CFSDrives::GetFolderProperty(PROPID propID, PROPVARIANT *value)
302{
303 COM_TRY_BEGIN
304 NCOM::CPropVariant prop;
305 switch (propID)
306 {
307 case kpidType: prop = "FSDrives"; break;
308 case kpidPath:
309 if (_volumeMode)
310 prop = kVolPrefix;
311 else if (_superMode)
312 prop = kSuperPrefix;
313 else
314 prop = (UString)LangString(IDS_COMPUTER) + WCHAR_PATH_SEPARATOR;
315 break;
316 }
317 prop.Detach(value);
318 return S_OK;
319 COM_TRY_END
320}
321
322
323STDMETHODIMP CFSDrives::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
324{
325 *iconIndex = 0;
326 const CDriveInfo &di = _drives[index];
327 if (di.IsPhysicalDrive)
328 return S_OK;
329 int iconIndexTemp;
330 if (GetRealIconIndex(di.FullSystemName, 0, iconIndexTemp) != 0)
331 {
332 *iconIndex = iconIndexTemp;
333 return S_OK;
334 }
335 return GetLastError();
336}
337
338void CFSDrives::AddExt(FString &s, unsigned index) const
339{
340 s += '.';
341 const CDriveInfo &di = _drives[index];
342 const char *ext;
343 if (di.DriveType == DRIVE_CDROM)
344 ext = "iso";
345 else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("NTFS"))
346 ext = "ntfs";
347 else if (di.FileSystemName.IsPrefixedBy_Ascii_NoCase("FAT"))
348 ext = "fat";
349 else
350 ext = "img";
351 s += ext;
352}
353
354HRESULT CFSDrives::GetFileSize(unsigned index, UInt64 &fileSize) const
355{
356 NIO::CInFile inFile;
357 if (!inFile.Open(_drives[index].GetDeviceFileIoName()))
358 return GetLastError();
359 if (!inFile.SizeDefined)
360 return E_FAIL;
361 fileSize = inFile.Size;
362 return S_OK;
363}
364
365STDMETHODIMP CFSDrives::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
366 Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
367 const wchar_t *path, IFolderOperationsExtractCallback *callback)
368{
369 if (numItems == 0)
370 return S_OK;
371
372 if (moveMode)
373 return E_NOTIMPL;
374
375 if (!_volumeMode)
376 return E_NOTIMPL;
377
378 UInt64 totalSize = 0;
379 UInt32 i;
380 for (i = 0; i < numItems; i++)
381 {
382 const CDriveInfo &di = _drives[indices[i]];
383 if (di.KnownSize)
384 totalSize += di.DriveSize;
385 }
386 RINOK(callback->SetTotal(totalSize));
387 RINOK(callback->SetNumFiles(numItems));
388
389 FString destPath = us2fs(path);
390 if (destPath.IsEmpty())
391 return E_INVALIDARG;
392
393 bool isAltDest = NName::IsAltPathPrefix(destPath);
394 bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
395
396 if (isDirectPath)
397 {
398 if (numItems > 1)
399 return E_INVALIDARG;
400 }
401
402 UInt64 completedSize = 0;
403 RINOK(callback->SetCompleted(&completedSize));
404
405 for (i = 0; i < numItems; i++)
406 {
407 unsigned index = indices[i];
408 const CDriveInfo &di = _drives[index];
409 FString destPath2 = destPath;
410
411 if (!isDirectPath)
412 {
413 FString destName = di.Name;
414 if (!destName.IsEmpty() && destName.Back() == ':')
415 {
416 destName.DeleteBack();
417 AddExt(destName, index);
418 }
419 destPath2 += destName;
420 }
421
422 FString srcPath = di.GetDeviceFileIoName();
423
424 UInt64 fileSize = 0;
425 if (GetFileSize(index, fileSize) != S_OK)
426 {
427 return E_FAIL;
428 }
429 if (!di.KnownSize)
430 {
431 totalSize += fileSize;
432 RINOK(callback->SetTotal(totalSize));
433 }
434
435 Int32 writeAskResult;
436 CMyComBSTR destPathResult;
437 RINOK(callback->AskWrite(fs2us(srcPath), BoolToInt(false), NULL, &fileSize,
438 fs2us(destPath2), &destPathResult, &writeAskResult));
439
440 if (!IntToBool(writeAskResult))
441 {
442 if (totalSize >= fileSize)
443 totalSize -= fileSize;
444 RINOK(callback->SetTotal(totalSize));
445 continue;
446 }
447
448 RINOK(callback->SetCurrentFilePath(fs2us(srcPath)));
449
450 static const UInt32 kBufferSize = (4 << 20);
451 UInt32 bufferSize = (di.DriveType == DRIVE_REMOVABLE) ? (18 << 10) * 4 : kBufferSize;
452 RINOK(CopyFileSpec(srcPath, us2fs(destPathResult), false, fileSize, bufferSize, completedSize, callback));
453 completedSize += fileSize;
454 }
455
456 return S_OK;
457}
458
459STDMETHODIMP CFSDrives::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
460 const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
461{
462 return E_NOTIMPL;
463}
464
465STDMETHODIMP CFSDrives::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
466{
467 return E_NOTIMPL;
468}
469
470STDMETHODIMP CFSDrives::CreateFolder(const wchar_t * /* name */, IProgress * /* progress */)
471{
472 return E_NOTIMPL;
473}
474
475STDMETHODIMP CFSDrives::CreateFile(const wchar_t * /* name */, IProgress * /* progress */)
476{
477 return E_NOTIMPL;
478}
479
480STDMETHODIMP CFSDrives::Rename(UInt32 /* index */, const wchar_t * /* newName */, IProgress * /* progress */)
481{
482 return E_NOTIMPL;
483}
484
485STDMETHODIMP CFSDrives::Delete(const UInt32 * /* indices */, UInt32 /* numItems */, IProgress * /* progress */)
486{
487 return E_NOTIMPL;
488}
489
490STDMETHODIMP CFSDrives::SetProperty(UInt32 /* index */, PROPID /* propID */,
491 const PROPVARIANT * /* value */, IProgress * /* progress */)
492{
493 return E_NOTIMPL;
494}
diff --git a/CPP/7zip/UI/FileManager/FSDrives.h b/CPP/7zip/UI/FileManager/FSDrives.h
new file mode 100644
index 0000000..f12e4da
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FSDrives.h
@@ -0,0 +1,59 @@
1// FSDrives.h
2
3#ifndef __FS_DRIVES_H
4#define __FS_DRIVES_H
5
6#include "../../../Common/MyCom.h"
7#include "../../../Common/MyString.h"
8
9#include "IFolder.h"
10
11struct CDriveInfo
12{
13 FString Name;
14 FString FullSystemName;
15 UInt64 DriveSize;
16 UInt64 FreeSpace;
17 UInt64 ClusterSize;
18 // UString Type;
19 UString VolumeName;
20 UString FileSystemName;
21 UINT DriveType;
22
23 bool KnownSize;
24 bool KnownSizes;
25 bool IsPhysicalDrive;
26
27 FString GetDeviceFileIoName() const;
28 CDriveInfo(): KnownSize(false), KnownSizes(false), IsPhysicalDrive(false) {}
29};
30
31class CFSDrives:
32 public IFolderFolder,
33 public IFolderOperations,
34 public IFolderGetSystemIconIndex,
35 public CMyUnknownImp
36{
37 CObjectVector<CDriveInfo> _drives;
38 bool _volumeMode;
39 bool _superMode;
40
41 HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder);
42 void AddExt(FString &s, unsigned index) const;
43 HRESULT GetFileSize(unsigned index, UInt64 &fileSize) const;
44public:
45 MY_UNKNOWN_IMP2(IFolderGetSystemIconIndex, IFolderOperations)
46
47 INTERFACE_FolderFolder(;)
48 INTERFACE_FolderOperations(;)
49
50 STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
51
52 void Init(bool volMode = false, bool superMode = false)
53 {
54 _volumeMode = volMode;
55 _superMode = superMode;
56 }
57};
58
59#endif
diff --git a/CPP/7zip/UI/FileManager/FSFolder.cpp b/CPP/7zip/UI/FileManager/FSFolder.cpp
new file mode 100644
index 0000000..f3e04b3
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FSFolder.cpp
@@ -0,0 +1,1107 @@
1// FSFolder.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/ComTry.h"
6#include "../../../Common/Defs.h"
7#include "../../../Common/StringConvert.h"
8#include "../../../Common/UTFConvert.h"
9
10#include "../../../Windows/FileDir.h"
11#include "../../../Windows/FileIO.h"
12#include "../../../Windows/FileName.h"
13#include "../../../Windows/PropVariant.h"
14
15#include "../../PropID.h"
16
17#include "FSDrives.h"
18#include "FSFolder.h"
19
20#ifndef UNDER_CE
21#include "NetFolder.h"
22#endif
23
24#include "SysIconUtils.h"
25
26#if _WIN32_WINNT < 0x0501
27#ifdef _APISETFILE_
28// Windows SDK 8.1 defines in fileapi.h the function GetCompressedFileSizeW only if _WIN32_WINNT >= 0x0501
29// But real support version for that function is NT 3.1 (probably)
30// So we must define GetCompressedFileSizeW
31EXTERN_C_BEGIN
32WINBASEAPI DWORD WINAPI GetCompressedFileSizeW(LPCWSTR lpFileName, LPDWORD lpFileSizeHigh);
33EXTERN_C_END
34#endif
35#endif
36
37using namespace NWindows;
38using namespace NFile;
39using namespace NFind;
40using namespace NDir;
41using namespace NName;
42
43#ifndef USE_UNICODE_FSTRING
44int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2)
45{
46 return CompareFileNames_ForFolderList(fs2us(s1), fs2us(s2));
47}
48#endif
49
50namespace NFsFolder {
51
52static const Byte kProps[] =
53{
54 kpidName,
55 kpidSize,
56 kpidMTime,
57 kpidCTime,
58 kpidATime,
59 kpidAttrib,
60 kpidPackSize,
61 #ifdef FS_SHOW_LINKS_INFO
62 kpidINode,
63 kpidLinks,
64 #endif
65 kpidComment,
66 kpidNumSubDirs,
67 kpidNumSubFiles,
68 kpidPrefix
69};
70
71HRESULT CFSFolder::Init(const FString &path /* , IFolderFolder *parentFolder */)
72{
73 // _parentFolder = parentFolder;
74 _path = path;
75
76 #ifdef _WIN32
77
78 _findChangeNotification.FindFirst(_path, false,
79 FILE_NOTIFY_CHANGE_FILE_NAME
80 | FILE_NOTIFY_CHANGE_DIR_NAME
81 | FILE_NOTIFY_CHANGE_ATTRIBUTES
82 | FILE_NOTIFY_CHANGE_SIZE
83 | FILE_NOTIFY_CHANGE_LAST_WRITE
84 /*
85 | FILE_NOTIFY_CHANGE_LAST_ACCESS
86 | FILE_NOTIFY_CHANGE_CREATION
87 | FILE_NOTIFY_CHANGE_SECURITY
88 */
89 );
90
91 if (!_findChangeNotification.IsHandleAllocated())
92 {
93 DWORD lastError = GetLastError();
94 CFindFile findFile;
95 CFileInfo fi;
96 FString path2 = _path;
97 path2 += '*'; // CHAR_ANY_MASK;
98 if (!findFile.FindFirst(path2, fi))
99 return lastError;
100 }
101
102 #endif
103
104 return S_OK;
105}
106
107
108HRESULT CFsFolderStat::Enumerate()
109{
110 if (Progress)
111 {
112 RINOK(Progress->SetCompleted(NULL));
113 }
114 Path.Add_PathSepar();
115 const unsigned len = Path.Len();
116 CEnumerator enumerator;
117 enumerator.SetDirPrefix(Path);
118 CDirEntry fi;
119 while (enumerator.Next(fi))
120 {
121 if (fi.IsDir())
122 {
123 NumFolders++;
124 Path.DeleteFrom(len);
125 Path += fi.Name;
126 RINOK(Enumerate());
127 }
128 else
129 {
130 NumFiles++;
131 Size += fi.Size;
132 }
133 }
134 return S_OK;
135}
136
137#ifndef UNDER_CE
138
139bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size);
140bool MyGetCompressedFileSizeW(CFSTR path, UInt64 &size)
141{
142 DWORD highPart;
143 DWORD lowPart = INVALID_FILE_SIZE;
144 IF_USE_MAIN_PATH
145 {
146 lowPart = ::GetCompressedFileSizeW(fs2us(path), &highPart);
147 if (lowPart != INVALID_FILE_SIZE || ::GetLastError() == NO_ERROR)
148 {
149 size = ((UInt64)highPart << 32) | lowPart;
150 return true;
151 }
152 }
153 #ifdef WIN_LONG_PATH
154 if (USE_SUPER_PATH)
155 {
156 UString superPath;
157 if (GetSuperPath(path, superPath, USE_MAIN_PATH))
158 {
159 lowPart = ::GetCompressedFileSizeW(superPath, &highPart);
160 if (lowPart != INVALID_FILE_SIZE || ::GetLastError() == NO_ERROR)
161 {
162 size = ((UInt64)highPart << 32) | lowPart;
163 return true;
164 }
165 }
166 }
167 #endif
168 return false;
169}
170
171#endif
172
173HRESULT CFSFolder::LoadSubItems(int dirItem, const FString &relPrefix)
174{
175 const unsigned startIndex = Folders.Size();
176 {
177 CEnumerator enumerator;
178 enumerator.SetDirPrefix(_path + relPrefix);
179 CDirItem fi;
180 fi.FolderStat_Defined = false;
181 fi.NumFolders = 0;
182 fi.NumFiles = 0;
183 fi.Parent = dirItem;
184
185 while (enumerator.Next(fi))
186 {
187 if (fi.IsDir())
188 {
189 fi.Size = 0;
190 if (_flatMode)
191 Folders.Add(relPrefix + fi.Name + FCHAR_PATH_SEPARATOR);
192 }
193 else
194 {
195 /*
196 fi.PackSize_Defined = true;
197 if (!MyGetCompressedFileSizeW(_path + relPrefix + fi.Name, fi.PackSize))
198 fi.PackSize = fi.Size;
199 */
200 }
201
202 #ifndef UNDER_CE
203
204 fi.Reparse.Free();
205 fi.PackSize_Defined = false;
206
207 #ifdef FS_SHOW_LINKS_INFO
208 fi.FileInfo_Defined = false;
209 fi.FileInfo_WasRequested = false;
210 fi.FileIndex = 0;
211 fi.NumLinks = 0;
212 #endif
213
214 fi.PackSize = fi.Size;
215 if (fi.HasReparsePoint())
216 {
217 fi.FileInfo_WasRequested = true;
218 BY_HANDLE_FILE_INFORMATION info;
219 NIO::GetReparseData(_path + relPrefix + fi.Name, fi.Reparse, &info);
220 fi.NumLinks = info.nNumberOfLinks;
221 fi.FileIndex = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
222 fi.FileInfo_Defined = true;
223 }
224
225 #endif
226
227 /* unsigned fileIndex = */ Files.Add(fi);
228
229 #if defined(_WIN32) && !defined(UNDER_CE)
230 /*
231 if (_scanAltStreams)
232 {
233 CStreamEnumerator enumerator(_path + relPrefix + fi.Name);
234 CStreamInfo si;
235 for (;;)
236 {
237 bool found;
238 if (!enumerator.Next(si, found))
239 {
240 // if (GetLastError() == ERROR_ACCESS_DENIED)
241 // break;
242 // return E_FAIL;
243 break;
244 }
245 if (!found)
246 break;
247 if (si.IsMainStream())
248 continue;
249 CAltStream ss;
250 ss.Parent = fileIndex;
251 ss.Name = si.GetReducedName();
252 ss.Size = si.Size;
253 ss.PackSize_Defined = false;
254 ss.PackSize = si.Size;
255 Streams.Add(ss);
256 }
257 }
258 */
259 #endif
260 }
261 }
262 if (!_flatMode)
263 return S_OK;
264
265 const unsigned endIndex = Folders.Size();
266 for (unsigned i = startIndex; i < endIndex; i++)
267 LoadSubItems(i, Folders[i]);
268 return S_OK;
269}
270
271STDMETHODIMP CFSFolder::LoadItems()
272{
273 Int32 dummy;
274 WasChanged(&dummy);
275 Clear();
276 RINOK(LoadSubItems(-1, FString()));
277 _commentsAreLoaded = false;
278 return S_OK;
279}
280
281static CFSTR const kDescriptionFileName = FTEXT("descript.ion");
282
283bool CFSFolder::LoadComments()
284{
285 _comments.Clear();
286 _commentsAreLoaded = true;
287 NIO::CInFile file;
288 if (!file.Open(_path + kDescriptionFileName))
289 return false;
290 UInt64 len;
291 if (!file.GetLength(len))
292 return false;
293 if (len >= (1 << 28))
294 return false;
295 AString s;
296 char *p = s.GetBuf((unsigned)(size_t)len);
297 size_t processedSize;
298 if (!file.ReadFull(p, (unsigned)(size_t)len, processedSize))
299 return false;
300 s.ReleaseBuf_CalcLen((unsigned)(size_t)len);
301 if (processedSize != len)
302 return false;
303 file.Close();
304 UString unicodeString;
305 if (!ConvertUTF8ToUnicode(s, unicodeString))
306 return false;
307 return _comments.ReadFromString(unicodeString);
308}
309
310bool CFSFolder::SaveComments()
311{
312 AString utf;
313 {
314 UString unicode;
315 _comments.SaveToString(unicode);
316 ConvertUnicodeToUTF8(unicode, utf);
317 }
318 if (!utf.IsAscii())
319 utf.Insert(0, "\xEF\xBB\xBF" "\r\n");
320
321 FString path = _path + kDescriptionFileName;
322 // We must set same attrib. COutFile::CreateAlways can fail, if file has another attrib.
323 DWORD attrib = FILE_ATTRIBUTE_NORMAL;
324 {
325 CFileInfo fi;
326 if (fi.Find(path))
327 attrib = fi.Attrib;
328 }
329 NIO::COutFile file;
330 if (!file.CreateAlways(path, attrib))
331 return false;
332 UInt32 processed;
333 file.Write(utf, utf.Len(), processed);
334 _commentsAreLoaded = false;
335 return true;
336}
337
338STDMETHODIMP CFSFolder::GetNumberOfItems(UInt32 *numItems)
339{
340 *numItems = Files.Size() /* + Streams.Size() */;
341 return S_OK;
342}
343
344#ifdef USE_UNICODE_FSTRING
345
346STDMETHODIMP CFSFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len)
347{
348 *name = 0;
349 *len = 0;
350 /*
351 if (index >= Files.Size())
352 index = Streams[index - Files.Size()].Parent;
353 */
354 CDirItem &fi = Files[index];
355 if (fi.Parent >= 0)
356 {
357 const FString &fo = Folders[fi.Parent];
358 USE_UNICODE_FSTRING
359 *name = fo;
360 *len = fo.Len();
361 }
362 return S_OK;
363}
364
365STDMETHODIMP CFSFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len)
366{
367 *name = 0;
368 *len = 0;
369 if (index < Files.Size())
370 {
371 CDirItem &fi = Files[index];
372 *name = fi.Name;
373 *len = fi.Name.Len();
374 return S_OK;
375 }
376 else
377 {
378 // const CAltStream &ss = Streams[index - Files.Size()];
379 // *name = ss.Name;
380 // *len = ss.Name.Len();
381 //
382 // change it;
383 }
384 return S_OK;
385}
386
387STDMETHODIMP_(UInt64) CFSFolder::GetItemSize(UInt32 index)
388{
389 /*
390 if (index >= Files.Size())
391 return Streams[index - Files.Size()].Size;
392 */
393 CDirItem &fi = Files[index];
394 return fi.IsDir() ? 0 : fi.Size;
395}
396
397#endif
398
399#ifdef FS_SHOW_LINKS_INFO
400bool CFSFolder::ReadFileInfo(CDirItem &di)
401{
402 di.FileInfo_WasRequested = true;
403 BY_HANDLE_FILE_INFORMATION info;
404 memset(&info, 0, sizeof(info)); // for vc6-O2
405 if (!NIO::CFileBase::GetFileInformation(_path + GetRelPath(di), &info))
406 return false;
407 di.NumLinks = info.nNumberOfLinks;
408 di.FileIndex = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
409 di.FileInfo_Defined = true;
410 return true;
411}
412#endif
413
414STDMETHODIMP CFSFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
415{
416 NCOM::CPropVariant prop;
417 /*
418 if (index >= (UInt32)Files.Size())
419 {
420 CAltStream &ss = Streams[index - Files.Size()];
421 CDirItem &fi = Files[ss.Parent];
422 switch (propID)
423 {
424 case kpidIsDir: prop = false; break;
425 case kpidIsAltStream: prop = true; break;
426 case kpidName: prop = fs2us(fi.Name) + ss.Name; break;
427 case kpidSize: prop = ss.Size; break;
428 case kpidPackSize:
429 #ifdef UNDER_CE
430 prop = ss.Size;
431 #else
432 if (!ss.PackSize_Defined)
433 {
434 ss.PackSize_Defined = true;
435 if (!MyGetCompressedFileSizeW(_path + GetRelPath(fi) + us2fs(ss.Name), ss.PackSize))
436 ss.PackSize = ss.Size;
437 }
438 prop = ss.PackSize;
439 #endif
440 break;
441 case kpidComment: break;
442 default: index = ss.Parent;
443 }
444 if (index >= (UInt32)Files.Size())
445 {
446 prop.Detach(value);
447 return S_OK;
448 }
449 }
450 */
451 CDirItem &fi = Files[index];
452 switch (propID)
453 {
454 case kpidIsDir: prop = fi.IsDir(); break;
455 case kpidIsAltStream: prop = false; break;
456 case kpidName: prop = fs2us(fi.Name); break;
457 case kpidSize: if (!fi.IsDir() || fi.FolderStat_Defined) prop = fi.Size; break;
458 case kpidPackSize:
459 #ifdef UNDER_CE
460 prop = fi.Size;
461 #else
462 if (!fi.PackSize_Defined)
463 {
464 fi.PackSize_Defined = true;
465 if (fi.IsDir () || !MyGetCompressedFileSizeW(_path + GetRelPath(fi), fi.PackSize))
466 fi.PackSize = fi.Size;
467 }
468 prop = fi.PackSize;
469 #endif
470 break;
471
472 #ifdef FS_SHOW_LINKS_INFO
473
474 case kpidLinks:
475 #ifdef UNDER_CE
476 // prop = fi.NumLinks;
477 #else
478 if (!fi.FileInfo_WasRequested)
479 ReadFileInfo(fi);
480 if (fi.FileInfo_Defined)
481 prop = fi.NumLinks;
482 #endif
483 break;
484
485 case kpidINode:
486 #ifdef UNDER_CE
487 // prop = fi.FileIndex;
488 #else
489 if (!fi.FileInfo_WasRequested)
490 ReadFileInfo(fi);
491 if (fi.FileInfo_Defined)
492 prop = fi.FileIndex;
493 #endif
494 break;
495
496 #endif
497
498 case kpidAttrib: prop = (UInt32)fi.Attrib; break;
499 case kpidCTime: prop = fi.CTime; break;
500 case kpidATime: prop = fi.ATime; break;
501 case kpidMTime: prop = fi.MTime; break;
502 case kpidComment:
503 {
504 if (!_commentsAreLoaded)
505 LoadComments();
506 UString comment;
507 if (_comments.GetValue(fs2us(GetRelPath(fi)), comment))
508 {
509 int pos = comment.Find((wchar_t)4);
510 if (pos >= 0)
511 comment.DeleteFrom((unsigned)pos);
512 prop = comment;
513 }
514 break;
515 }
516 case kpidPrefix:
517 if (fi.Parent >= 0)
518 prop = fs2us(Folders[fi.Parent]);
519 break;
520 case kpidNumSubDirs: if (fi.IsDir() && fi.FolderStat_Defined) prop = fi.NumFolders; break;
521 case kpidNumSubFiles: if (fi.IsDir() && fi.FolderStat_Defined) prop = fi.NumFiles; break;
522 }
523 prop.Detach(value);
524 return S_OK;
525}
526
527
528// ---------- IArchiveGetRawProps ----------
529
530
531STDMETHODIMP CFSFolder::GetNumRawProps(UInt32 *numProps)
532{
533 *numProps = 1;
534 return S_OK;
535}
536
537STDMETHODIMP CFSFolder::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID)
538{
539 *name = NULL;
540 *propID = kpidNtReparse;
541 return S_OK;
542}
543
544STDMETHODIMP CFSFolder::GetParent(UInt32 /* index */, UInt32 * /* parent */, UInt32 * /* parentType */)
545{
546 return E_FAIL;
547}
548
549STDMETHODIMP CFSFolder::GetRawProp(UInt32
550 #ifndef UNDER_CE
551 index
552 #endif
553 , PROPID
554 #ifndef UNDER_CE
555 propID
556 #endif
557 , const void **data, UInt32 *dataSize, UInt32 *propType)
558{
559 *data = NULL;
560 *dataSize = 0;
561 *propType = 0;
562
563 #ifndef UNDER_CE
564 if (propID == kpidNtReparse)
565 {
566 const CDirItem &fi = Files[index];
567 const CByteBuffer &buf = fi.Reparse;
568 if (buf.Size() == 0)
569 return S_OK;
570 *data = buf;
571 *dataSize = (UInt32)buf.Size();
572 *propType = NPropDataType::kRaw;
573 return S_OK;
574 }
575 #endif
576
577 return S_OK;
578}
579
580
581// returns Position of extension including '.'
582
583static inline CFSTR GetExtensionPtr(const FString &name)
584{
585 int dotPos = name.ReverseFind_Dot();
586 return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
587}
588
589STDMETHODIMP_(Int32) CFSFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 /* propIsRaw */)
590{
591 /*
592 const CAltStream *ss1 = NULL;
593 const CAltStream *ss2 = NULL;
594 if (index1 >= (UInt32)Files.Size()) { ss1 = &Streams[index1 - Files.Size()]; index1 = ss1->Parent; }
595 if (index2 >= (UInt32)Files.Size()) { ss2 = &Streams[index2 - Files.Size()]; index2 = ss2->Parent; }
596 */
597 CDirItem &fi1 = Files[index1];
598 CDirItem &fi2 = Files[index2];
599
600 switch (propID)
601 {
602 case kpidName:
603 {
604 int comp = CompareFileNames_ForFolderList(fi1.Name, fi2.Name);
605 /*
606 if (comp != 0)
607 return comp;
608 if (!ss1)
609 return ss2 ? -1 : 0;
610 if (!ss2)
611 return 1;
612 return MyStringCompareNoCase(ss1->Name, ss2->Name);
613 */
614 return comp;
615 }
616 case kpidSize:
617 return MyCompare(
618 /* ss1 ? ss1->Size : */ fi1.Size,
619 /* ss2 ? ss2->Size : */ fi2.Size);
620 case kpidAttrib: return MyCompare(fi1.Attrib, fi2.Attrib);
621 case kpidCTime: return CompareFileTime(&fi1.CTime, &fi2.CTime);
622 case kpidATime: return CompareFileTime(&fi1.ATime, &fi2.ATime);
623 case kpidMTime: return CompareFileTime(&fi1.MTime, &fi2.MTime);
624 case kpidIsDir:
625 {
626 bool isDir1 = /* ss1 ? false : */ fi1.IsDir();
627 bool isDir2 = /* ss2 ? false : */ fi2.IsDir();
628 if (isDir1 == isDir2)
629 return 0;
630 return isDir1 ? -1 : 1;
631 }
632 case kpidPackSize:
633 {
634 #ifdef UNDER_CE
635 return MyCompare(fi1.Size, fi2.Size);
636 #else
637 // PackSize can be undefined here
638 return MyCompare(
639 /* ss1 ? ss1->PackSize : */ fi1.PackSize,
640 /* ss2 ? ss2->PackSize : */ fi2.PackSize);
641 #endif
642 }
643
644 #ifdef FS_SHOW_LINKS_INFO
645 case kpidINode:
646 {
647 #ifndef UNDER_CE
648 if (!fi1.FileInfo_WasRequested) ReadFileInfo(fi1);
649 if (!fi2.FileInfo_WasRequested) ReadFileInfo(fi2);
650 return MyCompare(
651 fi1.FileIndex,
652 fi2.FileIndex);
653 #endif
654 }
655 case kpidLinks:
656 {
657 #ifndef UNDER_CE
658 if (!fi1.FileInfo_WasRequested) ReadFileInfo(fi1);
659 if (!fi2.FileInfo_WasRequested) ReadFileInfo(fi2);
660 return MyCompare(
661 fi1.NumLinks,
662 fi2.NumLinks);
663 #endif
664 }
665 #endif
666
667 case kpidComment:
668 {
669 // change it !
670 UString comment1, comment2;
671 _comments.GetValue(fs2us(GetRelPath(fi1)), comment1);
672 _comments.GetValue(fs2us(GetRelPath(fi2)), comment2);
673 return MyStringCompareNoCase(comment1, comment2);
674 }
675 case kpidPrefix:
676 if (fi1.Parent < 0) return (fi2.Parent < 0) ? 0 : -1;
677 if (fi2.Parent < 0) return 1;
678 return CompareFileNames_ForFolderList(
679 Folders[fi1.Parent],
680 Folders[fi2.Parent]);
681 case kpidExtension:
682 return CompareFileNames_ForFolderList(
683 GetExtensionPtr(fi1.Name),
684 GetExtensionPtr(fi2.Name));
685 }
686
687 return 0;
688}
689
690HRESULT CFSFolder::BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder)
691{
692 *resultFolder = 0;
693 CFSFolder *folderSpec = new CFSFolder;
694 CMyComPtr<IFolderFolder> subFolder = folderSpec;
695 RINOK(folderSpec->Init(_path + name + FCHAR_PATH_SEPARATOR));
696 *resultFolder = subFolder.Detach();
697 return S_OK;
698}
699
700/*
701void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
702{
703 if (item.Parent >= 0)
704 prefix = Folders[item.Parent];
705 else
706 prefix.Empty();
707}
708*/
709
710/*
711void CFSFolder::GetPrefix(const CDirItem &item, FString &prefix) const
712{
713 int parent = item.Parent;
714
715 unsigned len = 0;
716
717 while (parent >= 0)
718 {
719 const CDirItem &cur = Files[parent];
720 len += cur.Name.Len() + 1;
721 parent = cur.Parent;
722 }
723
724 wchar_t *p = prefix.GetBuf_SetEnd(len) + len;
725 parent = item.Parent;
726
727 while (parent >= 0)
728 {
729 const CDirItem &cur = Files[parent];
730 *(--p) = FCHAR_PATH_SEPARATOR;
731 p -= cur.Name.Len();
732 wmemcpy(p, cur.Name, cur.Name.Len());
733 parent = cur.Parent;
734 }
735}
736*/
737
738FString CFSFolder::GetRelPath(const CDirItem &item) const
739{
740 if (item.Parent < 0)
741 return item.Name;
742 return Folders[item.Parent] + item.Name;
743}
744
745STDMETHODIMP CFSFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
746{
747 *resultFolder = 0;
748 const CDirItem &fi = Files[index];
749 if (!fi.IsDir())
750 return E_INVALIDARG;
751 return BindToFolderSpec(GetRelPath(fi), resultFolder);
752}
753
754STDMETHODIMP CFSFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
755{
756 return BindToFolderSpec(us2fs(name), resultFolder);
757}
758
759STDMETHODIMP CFSFolder::BindToParentFolder(IFolderFolder **resultFolder)
760{
761 *resultFolder = 0;
762 /*
763 if (_parentFolder)
764 {
765 CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
766 *resultFolder = parentFolder.Detach();
767 return S_OK;
768 }
769 */
770 if (_path.IsEmpty())
771 return E_INVALIDARG;
772
773 #ifndef UNDER_CE
774
775 if (IsDriveRootPath_SuperAllowed(_path))
776 {
777 CFSDrives *drivesFolderSpec = new CFSDrives;
778 CMyComPtr<IFolderFolder> drivesFolder = drivesFolderSpec;
779 drivesFolderSpec->Init(false, IsSuperPath(_path));
780 *resultFolder = drivesFolder.Detach();
781 return S_OK;
782 }
783
784 int pos = _path.ReverseFind_PathSepar();
785 if (pos < 0 || pos != (int)_path.Len() - 1)
786 return E_FAIL;
787 FString parentPath = _path.Left(pos);
788 pos = parentPath.ReverseFind_PathSepar();
789 parentPath.DeleteFrom((unsigned)(pos + 1));
790
791 if (NName::IsDrivePath_SuperAllowed(parentPath))
792 {
793 CFSFolder *parentFolderSpec = new CFSFolder;
794 CMyComPtr<IFolderFolder> parentFolder = parentFolderSpec;
795 if (parentFolderSpec->Init(parentPath) == S_OK)
796 {
797 *resultFolder = parentFolder.Detach();
798 return S_OK;
799 }
800 }
801
802 /*
803 FString parentPathReduced = parentPath.Left(pos);
804
805 pos = parentPathReduced.ReverseFind_PathSepar();
806 if (pos == 1)
807 {
808 if (!IS_PATH_SEPAR_CHAR(parentPath[0]))
809 return E_FAIL;
810 CNetFolder *netFolderSpec = new CNetFolder;
811 CMyComPtr<IFolderFolder> netFolder = netFolderSpec;
812 netFolderSpec->Init(fs2us(parentPath));
813 *resultFolder = netFolder.Detach();
814 return S_OK;
815 }
816 */
817
818 #endif
819
820 return S_OK;
821}
822
823STDMETHODIMP CFSFolder::GetNumberOfProperties(UInt32 *numProperties)
824{
825 *numProperties = ARRAY_SIZE(kProps);
826 if (!_flatMode)
827 (*numProperties)--;
828 return S_OK;
829}
830
831STDMETHODIMP CFSFolder::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
832
833STDMETHODIMP CFSFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
834{
835 COM_TRY_BEGIN
836 NWindows::NCOM::CPropVariant prop;
837 switch (propID)
838 {
839 case kpidType: prop = "FSFolder"; break;
840 case kpidPath: prop = fs2us(_path); break;
841 }
842 prop.Detach(value);
843 return S_OK;
844 COM_TRY_END
845}
846
847STDMETHODIMP CFSFolder::WasChanged(Int32 *wasChanged)
848{
849 bool wasChangedMain = false;
850
851 #ifdef _WIN32
852
853 for (;;)
854 {
855 if (!_findChangeNotification.IsHandleAllocated())
856 break;
857 DWORD waitResult = ::WaitForSingleObject(_findChangeNotification, 0);
858 if (waitResult != WAIT_OBJECT_0)
859 break;
860 _findChangeNotification.FindNext();
861 wasChangedMain = true;
862 }
863
864 #endif
865
866 *wasChanged = BoolToInt(wasChangedMain);
867 return S_OK;
868}
869
870STDMETHODIMP CFSFolder::Clone(IFolderFolder **resultFolder)
871{
872 CFSFolder *fsFolderSpec = new CFSFolder;
873 CMyComPtr<IFolderFolder> folderNew = fsFolderSpec;
874 fsFolderSpec->Init(_path);
875 *resultFolder = folderNew.Detach();
876 return S_OK;
877}
878
879HRESULT CFSFolder::GetItemsFullSize(const UInt32 *indices, UInt32 numItems, CFsFolderStat &stat)
880{
881 for (UInt32 i = 0; i < numItems; i++)
882 {
883 UInt32 index = indices[i];
884 /*
885 if (index >= Files.Size())
886 {
887 size += Streams[index - Files.Size()].Size;
888 // numFiles++;
889 continue;
890 }
891 */
892 const CDirItem &fi = Files[index];
893 if (fi.IsDir())
894 {
895 stat.Path = _path;
896 stat.Path += GetRelPath(fi);
897 RINOK(stat.Enumerate());
898 stat.NumFolders++;
899 }
900 else
901 {
902 stat.NumFiles++;
903 stat.Size += fi.Size;
904 }
905 }
906 return S_OK;
907}
908
909/*
910HRESULT CFSFolder::GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress)
911{
912 if (index >= Files.Size())
913 {
914 size = Streams[index - Files.Size()].Size;
915 return S_OK;
916 }
917 const CDirItem &fi = Files[index];
918 if (fi.IsDir())
919 {
920 UInt64 numFolders = 0, numFiles = 0;
921 size = 0;
922 return GetFolderSize(_path + GetRelPath(fi), numFolders, numFiles, size, progress);
923 }
924 size = fi.Size;
925 return S_OK;
926}
927
928STDMETHODIMP CFSFolder::GetItemFullSize(UInt32 index, PROPVARIANT *value, IProgress *progress)
929{
930 NCOM::CPropVariant prop;
931 UInt64 size = 0;
932 HRESULT result = GetItemFullSize(index, size, progress);
933 prop = size;
934 prop.Detach(value);
935 return result;
936}
937*/
938
939STDMETHODIMP CFSFolder::CalcItemFullSize(UInt32 index, IProgress *progress)
940{
941 if (index >= (UInt32)Files.Size())
942 return S_OK;
943 CDirItem &fi = Files[index];
944 if (!fi.IsDir())
945 return S_OK;
946 CFsFolderStat stat(_path + GetRelPath(fi), progress);
947 RINOK(stat.Enumerate());
948 fi.Size = stat.Size;
949 fi.NumFolders = stat.NumFolders;
950 fi.NumFiles = stat.NumFiles;
951 fi.FolderStat_Defined = true;
952 return S_OK;
953}
954
955void CFSFolder::GetAbsPath(const wchar_t *name, FString &absPath)
956{
957 absPath.Empty();
958 if (!IsAbsolutePath(name))
959 absPath += _path;
960 absPath += us2fs(name);
961}
962
963STDMETHODIMP CFSFolder::CreateFolder(const wchar_t *name, IProgress * /* progress */)
964{
965 FString absPath;
966 GetAbsPath(name, absPath);
967 if (CreateDir(absPath))
968 return S_OK;
969 if (::GetLastError() == ERROR_ALREADY_EXISTS)
970 return ::GetLastError();
971 if (!CreateComplexDir(absPath))
972 return ::GetLastError();
973 return S_OK;
974}
975
976STDMETHODIMP CFSFolder::CreateFile(const wchar_t *name, IProgress * /* progress */)
977{
978 FString absPath;
979 GetAbsPath(name, absPath);
980 NIO::COutFile outFile;
981 if (!outFile.Create(absPath, false))
982 return ::GetLastError();
983 return S_OK;
984}
985
986STDMETHODIMP CFSFolder::Rename(UInt32 index, const wchar_t *newName, IProgress * /* progress */)
987{
988 if (index >= (UInt32)Files.Size())
989 return E_NOTIMPL;
990 const CDirItem &fi = Files[index];
991 // FString prefix;
992 // GetPrefix(fi, prefix);
993 FString fullPrefix = _path;
994 if (fi.Parent >= 0)
995 fullPrefix += Folders[fi.Parent];
996 if (!MyMoveFile(fullPrefix + fi.Name, fullPrefix + us2fs(newName)))
997 return GetLastError();
998 return S_OK;
999}
1000
1001STDMETHODIMP CFSFolder::Delete(const UInt32 *indices, UInt32 numItems,IProgress *progress)
1002{
1003 RINOK(progress->SetTotal(numItems));
1004 // int prevDeletedFileIndex = -1;
1005 for (UInt32 i = 0; i < numItems; i++)
1006 {
1007 // Sleep(200);
1008 UInt32 index = indices[i];
1009 bool result = true;
1010 /*
1011 if (index >= (UInt32)Files.Size())
1012 {
1013 const CAltStream &ss = Streams[index - (UInt32)Files.Size()];
1014 if (prevDeletedFileIndex != ss.Parent)
1015 {
1016 const CDirItem &fi = Files[ss.Parent];
1017 result = DeleteFileAlways(_path + GetRelPath(fi) + us2fs(ss.Name));
1018 }
1019 }
1020 else
1021 */
1022 {
1023 const CDirItem &fi = Files[index];
1024 const FString fullPath = _path + GetRelPath(fi);
1025 // prevDeletedFileIndex = index;
1026 if (fi.IsDir())
1027 result = RemoveDirWithSubItems(fullPath);
1028 else
1029 result = DeleteFileAlways(fullPath);
1030 }
1031 if (!result)
1032 return GetLastError();
1033 UInt64 completed = i;
1034 RINOK(progress->SetCompleted(&completed));
1035 }
1036 return S_OK;
1037}
1038
1039STDMETHODIMP CFSFolder::SetProperty(UInt32 index, PROPID propID,
1040 const PROPVARIANT *value, IProgress * /* progress */)
1041{
1042 if (index >= (UInt32)Files.Size())
1043 return E_INVALIDARG;
1044 CDirItem &fi = Files[index];
1045 if (fi.Parent >= 0)
1046 return E_NOTIMPL;
1047 switch (propID)
1048 {
1049 case kpidComment:
1050 {
1051 UString filename = fs2us(fi.Name);
1052 filename.Trim();
1053 if (value->vt == VT_EMPTY)
1054 _comments.DeletePair(filename);
1055 else if (value->vt == VT_BSTR)
1056 {
1057 CTextPair pair;
1058 pair.ID = filename;
1059 pair.ID.Trim();
1060 pair.Value.SetFromBstr(value->bstrVal);
1061 pair.Value.Trim();
1062 if (pair.Value.IsEmpty())
1063 _comments.DeletePair(filename);
1064 else
1065 _comments.AddPair(pair);
1066 }
1067 else
1068 return E_INVALIDARG;
1069 SaveComments();
1070 break;
1071 }
1072 default:
1073 return E_NOTIMPL;
1074 }
1075 return S_OK;
1076}
1077
1078STDMETHODIMP CFSFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
1079{
1080 if (index >= (UInt32)Files.Size())
1081 return E_INVALIDARG;
1082 const CDirItem &fi = Files[index];
1083 *iconIndex = 0;
1084 int iconIndexTemp;
1085 if (GetRealIconIndex(_path + GetRelPath(fi), fi.Attrib, iconIndexTemp) != 0)
1086 {
1087 *iconIndex = iconIndexTemp;
1088 return S_OK;
1089 }
1090 return GetLastError();
1091}
1092
1093STDMETHODIMP CFSFolder::SetFlatMode(Int32 flatMode)
1094{
1095 _flatMode = IntToBool(flatMode);
1096 return S_OK;
1097}
1098
1099/*
1100STDMETHODIMP CFSFolder::SetShowNtfsStreamsMode(Int32 showStreamsMode)
1101{
1102 _scanAltStreams = IntToBool(showStreamsMode);
1103 return S_OK;
1104}
1105*/
1106
1107}
diff --git a/CPP/7zip/UI/FileManager/FSFolder.h b/CPP/7zip/UI/FileManager/FSFolder.h
new file mode 100644
index 0000000..fac1ef9
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FSFolder.h
@@ -0,0 +1,215 @@
1// FSFolder.h
2
3#ifndef __FS_FOLDER_H
4#define __FS_FOLDER_H
5
6#include "../../../Common/MyCom.h"
7#include "../../../Common/MyBuffer.h"
8
9#include "../../../Windows/FileFind.h"
10
11#include "../../Archive/IArchive.h"
12
13#include "IFolder.h"
14#include "TextPairs.h"
15
16namespace NFsFolder {
17
18class CFSFolder;
19
20#define FS_SHOW_LINKS_INFO
21
22struct CDirItem: public NWindows::NFile::NFind::CFileInfo
23{
24 #ifndef UNDER_CE
25 UInt64 PackSize;
26 #endif
27
28 #ifdef FS_SHOW_LINKS_INFO
29 UInt64 FileIndex;
30 UInt32 NumLinks;
31 bool FileInfo_Defined;
32 bool FileInfo_WasRequested;
33 #endif
34
35 #ifndef UNDER_CE
36 bool PackSize_Defined;
37 #endif
38
39 bool FolderStat_Defined;
40
41 #ifndef UNDER_CE
42 CByteBuffer Reparse;
43 #endif
44
45 UInt64 NumFolders;
46 UInt64 NumFiles;
47
48 int Parent;
49};
50
51/*
52struct CAltStream
53{
54 UInt64 Size;
55 UInt64 PackSize;
56 bool PackSize_Defined;
57 int Parent;
58 UString Name;
59};
60*/
61
62struct CFsFolderStat
63{
64 UInt64 NumFolders;
65 UInt64 NumFiles;
66 UInt64 Size;
67 IProgress *Progress;
68 FString Path;
69
70 CFsFolderStat(): NumFolders(0), NumFiles(0), Size(0), Progress(NULL) {}
71 CFsFolderStat(const FString &path, IProgress *progress = NULL):
72 NumFolders(0), NumFiles(0), Size(0), Progress(progress), Path(path) {}
73
74 HRESULT Enumerate();
75};
76
77class CFSFolder:
78 public IFolderFolder,
79 public IArchiveGetRawProps,
80 public IFolderCompare,
81 #ifdef USE_UNICODE_FSTRING
82 public IFolderGetItemName,
83 #endif
84 public IFolderWasChanged,
85 public IFolderOperations,
86 // public IFolderOperationsDeleteToRecycleBin,
87 public IFolderCalcItemFullSize,
88 public IFolderClone,
89 public IFolderGetSystemIconIndex,
90 public IFolderSetFlatMode,
91 // public IFolderSetShowNtfsStreamsMode,
92 public CMyUnknownImp
93{
94public:
95 MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
96 MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
97 MY_QUERYINTERFACE_ENTRY(IFolderCompare)
98 #ifdef USE_UNICODE_FSTRING
99 MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
100 #endif
101 MY_QUERYINTERFACE_ENTRY(IFolderWasChanged)
102 // MY_QUERYINTERFACE_ENTRY(IFolderOperationsDeleteToRecycleBin)
103 MY_QUERYINTERFACE_ENTRY(IFolderOperations)
104 MY_QUERYINTERFACE_ENTRY(IFolderCalcItemFullSize)
105 MY_QUERYINTERFACE_ENTRY(IFolderClone)
106 MY_QUERYINTERFACE_ENTRY(IFolderGetSystemIconIndex)
107 MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)
108 // MY_QUERYINTERFACE_ENTRY(IFolderSetShowNtfsStreamsMode)
109 MY_QUERYINTERFACE_END
110 MY_ADDREF_RELEASE
111
112
113 INTERFACE_FolderFolder(;)
114 INTERFACE_IArchiveGetRawProps(;)
115 INTERFACE_FolderOperations(;)
116
117 STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
118
119 #ifdef USE_UNICODE_FSTRING
120 INTERFACE_IFolderGetItemName(;)
121 #endif
122 STDMETHOD(WasChanged)(Int32 *wasChanged);
123 STDMETHOD(Clone)(IFolderFolder **resultFolder);
124 STDMETHOD(CalcItemFullSize)(UInt32 index, IProgress *progress);
125
126 STDMETHOD(SetFlatMode)(Int32 flatMode);
127 // STDMETHOD(SetShowNtfsStreamsMode)(Int32 showStreamsMode);
128
129 STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
130
131private:
132 FString _path;
133
134 CObjectVector<CDirItem> Files;
135 FStringVector Folders;
136 // CObjectVector<CAltStream> Streams;
137 // CMyComPtr<IFolderFolder> _parentFolder;
138
139 bool _commentsAreLoaded;
140 CPairsStorage _comments;
141
142 // bool _scanAltStreams;
143 bool _flatMode;
144
145 #ifdef _WIN32
146 NWindows::NFile::NFind::CFindChangeNotification _findChangeNotification;
147 #endif
148
149 HRESULT GetItemsFullSize(const UInt32 *indices, UInt32 numItems, CFsFolderStat &stat);
150
151 HRESULT GetItemFullSize(unsigned index, UInt64 &size, IProgress *progress);
152 void GetAbsPath(const wchar_t *name, FString &absPath);
153 HRESULT BindToFolderSpec(CFSTR name, IFolderFolder **resultFolder);
154
155 bool LoadComments();
156 bool SaveComments();
157 HRESULT LoadSubItems(int dirItem, const FString &path);
158
159 #ifdef FS_SHOW_LINKS_INFO
160 bool ReadFileInfo(CDirItem &di);
161 #endif
162
163public:
164 HRESULT Init(const FString &path /* , IFolderFolder *parentFolder */);
165 #if !defined(_WIN32) || defined(UNDER_CE)
166 HRESULT InitToRoot() { return Init((FString) FSTRING_PATH_SEPARATOR /* , NULL */); }
167 #endif
168
169 CFSFolder() : _flatMode(false)
170 // , _scanAltStreams(false)
171 {}
172
173 void GetFullPath(const CDirItem &item, FString &path) const
174 {
175 // FString prefix;
176 // GetPrefix(item, prefix);
177 path = _path;
178 if (item.Parent >= 0)
179 path += Folders[item.Parent];
180 path += item.Name;
181 }
182
183 // void GetPrefix(const CDirItem &item, FString &prefix) const;
184
185 FString GetRelPath(const CDirItem &item) const;
186
187 void Clear()
188 {
189 Files.Clear();
190 Folders.Clear();
191 // Streams.Clear();
192 }
193};
194
195struct CCopyStateIO
196{
197 IProgress *Progress;
198 UInt64 TotalSize;
199 UInt64 StartPos;
200 UInt64 CurrentSize;
201 bool DeleteSrcFile;
202
203 int ErrorFileIndex;
204 UString ErrorMessage;
205
206 CCopyStateIO(): TotalSize(0), StartPos(0), DeleteSrcFile(false) {}
207
208 HRESULT MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib = INVALID_FILE_ATTRIBUTES);
209};
210
211HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName);
212
213}
214
215#endif
diff --git a/CPP/7zip/UI/FileManager/FSFolderCopy.cpp b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
new file mode 100644
index 0000000..ff444b3
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FSFolderCopy.cpp
@@ -0,0 +1,673 @@
1// FSFolderCopy.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyWindows.h"
6
7#include <WinBase.h>
8
9#include "../../../Common/Defs.h"
10#include "../../../Common/StringConvert.h"
11#include "../../../Common/Wildcard.h"
12
13#include "../../../Windows/DLL.h"
14#include "../../../Windows/ErrorMsg.h"
15#include "../../../Windows/FileDir.h"
16#include "../../../Windows/FileName.h"
17
18#include "../../Common/FilePathAutoRename.h"
19
20#include "FSFolder.h"
21
22using namespace NWindows;
23using namespace NFile;
24using namespace NDir;
25using namespace NName;
26using namespace NFind;
27
28#ifndef _UNICODE
29extern bool g_IsNT;
30#endif
31
32namespace NFsFolder {
33
34HRESULT CCopyStateIO::MyCopyFile(CFSTR inPath, CFSTR outPath, DWORD attrib)
35{
36 ErrorFileIndex = -1;
37 ErrorMessage.Empty();
38 CurrentSize = 0;
39
40 {
41 const size_t kBufSize = 1 << 16;
42 CByteArr buf(kBufSize);
43
44 NIO::CInFile inFile;
45 NIO::COutFile outFile;
46
47 if (!inFile.Open(inPath))
48 {
49 ErrorFileIndex = 0;
50 return S_OK;
51 }
52
53 if (!outFile.Create(outPath, true))
54 {
55 ErrorFileIndex = 1;
56 return S_OK;
57 }
58
59 for (;;)
60 {
61 UInt32 num;
62 if (!inFile.Read(buf, kBufSize, num))
63 {
64 ErrorFileIndex = 0;
65 return S_OK;
66 }
67 if (num == 0)
68 break;
69
70 UInt32 written = 0;
71 if (!outFile.Write(buf, num, written))
72 {
73 ErrorFileIndex = 1;
74 return S_OK;
75 }
76 if (written != num)
77 {
78 ErrorMessage = "Write error";
79 return S_OK;
80 }
81 CurrentSize += num;
82 if (Progress)
83 {
84 UInt64 completed = StartPos + CurrentSize;
85 RINOK(Progress->SetCompleted(&completed));
86 }
87 }
88 }
89
90 if (attrib != INVALID_FILE_ATTRIBUTES)
91 SetFileAttrib(outPath, attrib);
92
93 if (DeleteSrcFile)
94 {
95 if (!DeleteFileAlways(inPath))
96 {
97 ErrorFileIndex = 0;
98 return S_OK;
99 }
100 }
101
102 return S_OK;
103}
104
105
106/*
107static bool IsItWindows2000orHigher()
108{
109 OSVERSIONINFO versionInfo;
110 versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
111 if (!::GetVersionEx(&versionInfo))
112 return false;
113 return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
114 (versionInfo.dwMajorVersion >= 5);
115}
116*/
117
118struct CProgressInfo
119{
120 UInt64 TotalSize;
121 UInt64 StartPos;
122 UInt64 FileSize;
123 IProgress *Progress;
124 HRESULT ProgressResult;
125
126 void Init() { ProgressResult = S_OK; }
127};
128
129#ifndef PROGRESS_CONTINUE
130
131#define PROGRESS_CONTINUE 0
132#define PROGRESS_CANCEL 1
133
134#define COPY_FILE_FAIL_IF_EXISTS 0x00000001
135
136typedef
137DWORD
138(WINAPI* LPPROGRESS_ROUTINE)(
139 LARGE_INTEGER TotalFileSize,
140 LARGE_INTEGER TotalBytesTransferred,
141 LARGE_INTEGER StreamSize,
142 LARGE_INTEGER StreamBytesTransferred,
143 DWORD dwStreamNumber,
144 DWORD dwCallbackReason,
145 HANDLE hSourceFile,
146 HANDLE hDestinationFile,
147 LPVOID lpData
148 );
149
150#endif
151
152static DWORD CALLBACK CopyProgressRoutine(
153 LARGE_INTEGER TotalFileSize, // file size
154 LARGE_INTEGER TotalBytesTransferred, // bytes transferred
155 LARGE_INTEGER /* StreamSize */, // bytes in stream
156 LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream
157 DWORD /* dwStreamNumber */, // current stream
158 DWORD /* dwCallbackReason */, // callback reason
159 HANDLE /* hSourceFile */, // handle to source file
160 HANDLE /* hDestinationFile */, // handle to destination file
161 LPVOID lpData // from CopyFileEx
162)
163{
164 // StreamSize = StreamSize;
165 // StreamBytesTransferred = StreamBytesTransferred;
166 // dwStreamNumber = dwStreamNumber;
167 // dwCallbackReason = dwCallbackReason;
168
169 CProgressInfo &pi = *(CProgressInfo *)lpData;
170
171 if ((UInt64)TotalFileSize.QuadPart > pi.FileSize)
172 {
173 pi.TotalSize += (UInt64)TotalFileSize.QuadPart - pi.FileSize;
174 pi.FileSize = (UInt64)TotalFileSize.QuadPart;
175 pi.ProgressResult = pi.Progress->SetTotal(pi.TotalSize);
176 }
177 UInt64 completed = pi.StartPos + TotalBytesTransferred.QuadPart;
178 pi.ProgressResult = pi.Progress->SetCompleted(&completed);
179 return (pi.ProgressResult == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL);
180}
181
182typedef BOOL (WINAPI * Func_CopyFileExA)(
183 IN LPCSTR lpExistingFileName,
184 IN LPCSTR lpNewFileName,
185 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
186 IN LPVOID lpData OPTIONAL,
187 IN LPBOOL pbCancel OPTIONAL,
188 IN DWORD dwCopyFlags
189 );
190
191typedef BOOL (WINAPI * Func_CopyFileExW)(
192 IN LPCWSTR lpExistingFileName,
193 IN LPCWSTR lpNewFileName,
194 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
195 IN LPVOID lpData OPTIONAL,
196 IN LPBOOL pbCancel OPTIONAL,
197 IN DWORD dwCopyFlags
198 );
199
200typedef BOOL (WINAPI * Func_MoveFileWithProgressW)(
201 IN LPCWSTR lpExistingFileName,
202 IN LPCWSTR lpNewFileName,
203 IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
204 IN LPVOID lpData OPTIONAL,
205 IN DWORD dwFlags
206 );
207
208struct CCopyState
209{
210 CProgressInfo ProgressInfo;
211 IFolderOperationsExtractCallback *Callback;
212 bool MoveMode;
213 bool UseReadWriteMode;
214
215 Func_CopyFileExW my_CopyFileExW;
216 #ifndef UNDER_CE
217 Func_MoveFileWithProgressW my_MoveFileWithProgressW;
218 #endif
219 #ifndef _UNICODE
220 Func_CopyFileExA my_CopyFileExA;
221 #endif
222
223 void Prepare();
224 bool CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile);
225 bool CopyFile_Sys(CFSTR oldFile, CFSTR newFile);
226 bool MoveFile_Sys(CFSTR oldFile, CFSTR newFile);
227
228 HRESULT CallProgress();
229
230 bool IsCallbackProgressError() { return ProgressInfo.ProgressResult != S_OK; }
231};
232
233HRESULT CCopyState::CallProgress()
234{
235 return ProgressInfo.Progress->SetCompleted(&ProgressInfo.StartPos);
236}
237
238void CCopyState::Prepare()
239{
240 my_CopyFileExW = NULL;
241 #ifndef UNDER_CE
242 my_MoveFileWithProgressW = NULL;
243 #endif
244 #ifndef _UNICODE
245 my_CopyFileExA = NULL;
246 if (!g_IsNT)
247 {
248 my_CopyFileExA = (Func_CopyFileExA)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "CopyFileExA");
249 }
250 else
251 #endif
252 {
253 HMODULE module = ::GetModuleHandleW(
254 #ifdef UNDER_CE
255 L"coredll.dll"
256 #else
257 L"kernel32.dll"
258 #endif
259 );
260 my_CopyFileExW = (Func_CopyFileExW)My_GetProcAddress(module, "CopyFileExW");
261 #ifndef UNDER_CE
262 my_MoveFileWithProgressW = (Func_MoveFileWithProgressW)My_GetProcAddress(module, "MoveFileWithProgressW");
263 #endif
264 }
265}
266
267/* WinXP-64:
268 CopyFileW(fromFile, toFile:altStream)
269 OK - there are NO alt streams in fromFile
270 ERROR_INVALID_PARAMETER - there are alt streams in fromFile
271*/
272
273bool CCopyState::CopyFile_NT(const wchar_t *oldFile, const wchar_t *newFile)
274{
275 BOOL cancelFlag = FALSE;
276 if (my_CopyFileExW)
277 return BOOLToBool(my_CopyFileExW(oldFile, newFile, CopyProgressRoutine,
278 &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS));
279 return BOOLToBool(::CopyFileW(oldFile, newFile, TRUE));
280}
281
282bool CCopyState::CopyFile_Sys(CFSTR oldFile, CFSTR newFile)
283{
284 #ifndef _UNICODE
285 if (!g_IsNT)
286 {
287 if (my_CopyFileExA)
288 {
289 BOOL cancelFlag = FALSE;
290 if (my_CopyFileExA(fs2fas(oldFile), fs2fas(newFile),
291 CopyProgressRoutine, &ProgressInfo, &cancelFlag, COPY_FILE_FAIL_IF_EXISTS))
292 return true;
293 if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
294 return false;
295 }
296 return BOOLToBool(::CopyFile(fs2fas(oldFile), fs2fas(newFile), TRUE));
297 }
298 else
299 #endif
300 {
301 IF_USE_MAIN_PATH_2(oldFile, newFile)
302 {
303 if (CopyFile_NT(fs2us(oldFile), fs2us(newFile)))
304 return true;
305 }
306 #ifdef WIN_LONG_PATH
307 if (USE_SUPER_PATH_2)
308 {
309 if (IsCallbackProgressError())
310 return false;
311 UString superPathOld, superPathNew;
312 if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
313 return false;
314 if (CopyFile_NT(superPathOld, superPathNew))
315 return true;
316 }
317 #endif
318 return false;
319 }
320}
321
322bool CCopyState::MoveFile_Sys(CFSTR oldFile, CFSTR newFile)
323{
324 #ifndef UNDER_CE
325 // if (IsItWindows2000orHigher())
326 // {
327 if (my_MoveFileWithProgressW)
328 {
329 IF_USE_MAIN_PATH_2(oldFile, newFile)
330 {
331 if (my_MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), CopyProgressRoutine,
332 &ProgressInfo, MOVEFILE_COPY_ALLOWED))
333 return true;
334 }
335 #ifdef WIN_LONG_PATH
336 if ((!(USE_MAIN_PATH_2) || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) && USE_SUPER_PATH_2)
337 {
338 if (IsCallbackProgressError())
339 return false;
340 UString superPathOld, superPathNew;
341 if (!GetSuperPaths(oldFile, newFile, superPathOld, superPathNew, USE_MAIN_PATH_2))
342 return false;
343 if (my_MoveFileWithProgressW(superPathOld, superPathNew, CopyProgressRoutine,
344 &ProgressInfo, MOVEFILE_COPY_ALLOWED))
345 return true;
346 }
347 #endif
348 if (::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
349 return false;
350 }
351 // }
352 // else
353 #endif
354 return MyMoveFile(oldFile, newFile);
355}
356
357static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
358 const wchar_t *message, const FString &fileName)
359{
360 UString s = message;
361 s += " : ";
362 s += fs2us(fileName);
363 return callback->ShowMessage(s);
364}
365
366static HRESULT SendMessageError(IFolderOperationsExtractCallback *callback,
367 const char *message, const FString &fileName)
368{
369 return SendMessageError(callback, MultiByteToUnicodeString(message), fileName);
370}
371
372static DWORD Return_LastError_or_FAIL()
373{
374 DWORD errorCode = GetLastError();
375 if (errorCode == 0)
376 errorCode = (DWORD)E_FAIL;
377 return errorCode;
378}
379
380static UString GetLastErrorMessage()
381{
382 return NError::MyFormatMessage(Return_LastError_or_FAIL());
383}
384
385HRESULT SendLastErrorMessage(IFolderOperationsExtractCallback *callback, const FString &fileName)
386{
387 return SendMessageError(callback, GetLastErrorMessage(), fileName);
388}
389
390static HRESULT CopyFile_Ask(
391 CCopyState &state,
392 const FString &srcPath,
393 const CFileInfo &srcFileInfo,
394 const FString &destPath)
395{
396 if (CompareFileNames(destPath, srcPath) == 0)
397 {
398 RINOK(SendMessageError(state.Callback,
399 state.MoveMode ?
400 "Cannot move file onto itself" :
401 "Cannot copy file onto itself"
402 , destPath));
403 return E_ABORT;
404 }
405
406 Int32 writeAskResult;
407 CMyComBSTR destPathResult;
408 RINOK(state.Callback->AskWrite(
409 fs2us(srcPath),
410 BoolToInt(false),
411 &srcFileInfo.MTime, &srcFileInfo.Size,
412 fs2us(destPath),
413 &destPathResult,
414 &writeAskResult));
415
416 if (IntToBool(writeAskResult))
417 {
418 FString destPathNew = us2fs((LPCOLESTR)destPathResult);
419 RINOK(state.Callback->SetCurrentFilePath(fs2us(srcPath)));
420
421 if (state.UseReadWriteMode)
422 {
423 NFsFolder::CCopyStateIO state2;
424 state2.Progress = state.Callback;
425 state2.DeleteSrcFile = state.MoveMode;
426 state2.TotalSize = state.ProgressInfo.TotalSize;
427 state2.StartPos = state.ProgressInfo.StartPos;
428
429 RINOK(state2.MyCopyFile(srcPath, destPathNew, srcFileInfo.Attrib));
430
431 if (state2.ErrorFileIndex >= 0)
432 {
433 if (state2.ErrorMessage.IsEmpty())
434 state2.ErrorMessage = GetLastErrorMessage();
435 FString errorName;
436 if (state2.ErrorFileIndex == 0)
437 errorName = srcPath;
438 else
439 errorName = destPathNew;
440 RINOK(SendMessageError(state.Callback, state2.ErrorMessage, errorName));
441 return E_ABORT;
442 }
443 state.ProgressInfo.StartPos += state2.CurrentSize;
444 }
445 else
446 {
447 state.ProgressInfo.FileSize = srcFileInfo.Size;
448 bool res;
449 if (state.MoveMode)
450 res = state.MoveFile_Sys(srcPath, destPathNew);
451 else
452 res = state.CopyFile_Sys(srcPath, destPathNew);
453 RINOK(state.ProgressInfo.ProgressResult);
454 if (!res)
455 {
456 // GetLastError() is ERROR_REQUEST_ABORTED in case of PROGRESS_CANCEL.
457 RINOK(SendMessageError(state.Callback, GetLastErrorMessage(), destPathNew));
458 return E_ABORT;
459 }
460 state.ProgressInfo.StartPos += state.ProgressInfo.FileSize;
461 }
462 }
463 else
464 {
465 if (state.ProgressInfo.TotalSize >= srcFileInfo.Size)
466 {
467 state.ProgressInfo.TotalSize -= srcFileInfo.Size;
468 RINOK(state.ProgressInfo.Progress->SetTotal(state.ProgressInfo.TotalSize));
469 }
470 }
471 return state.CallProgress();
472}
473
474static FString CombinePath(const FString &folderPath, const FString &fileName)
475{
476 FString s (folderPath);
477 s.Add_PathSepar(); // FCHAR_PATH_SEPARATOR
478 s += fileName;
479 return s;
480}
481
482static bool IsDestChild(const FString &src, const FString &dest)
483{
484 unsigned len = src.Len();
485 if (dest.Len() < len)
486 return false;
487 if (dest.Len() != len && dest[len] != FCHAR_PATH_SEPARATOR)
488 return false;
489 return CompareFileNames(dest.Left(len), src) == 0;
490}
491
492static HRESULT CopyFolder(
493 CCopyState &state,
494 const FString &srcPath, // without TAIL separator
495 const FString &destPath) // without TAIL separator
496{
497 RINOK(state.CallProgress());
498
499 if (IsDestChild(srcPath, destPath))
500 {
501 RINOK(SendMessageError(state.Callback,
502 state.MoveMode ?
503 "Cannot copy folder onto itself" :
504 "Cannot move folder onto itself"
505 , destPath));
506 return E_ABORT;
507 }
508
509 if (state.MoveMode)
510 {
511 if (state.MoveFile_Sys(srcPath, destPath))
512 return S_OK;
513
514 // MSDN: MoveFile() fails for dirs on different volumes.
515 }
516
517 if (!CreateComplexDir(destPath))
518 {
519 RINOK(SendMessageError(state.Callback, "Cannot create folder", destPath));
520 return E_ABORT;
521 }
522
523 CEnumerator enumerator;
524 enumerator.SetDirPrefix(CombinePath(srcPath, FString()));
525
526 for (;;)
527 {
528 NFind::CFileInfo fi;
529 bool found;
530 if (!enumerator.Next(fi, found))
531 {
532 SendLastErrorMessage(state.Callback, srcPath);
533 return S_OK;
534 }
535 if (!found)
536 break;
537 const FString srcPath2 = CombinePath(srcPath, fi.Name);
538 const FString destPath2 = CombinePath(destPath, fi.Name);
539 if (fi.IsDir())
540 {
541 RINOK(CopyFolder(state, srcPath2, destPath2))
542 }
543 else
544 {
545 RINOK(CopyFile_Ask(state, srcPath2, fi, destPath2));
546 }
547 }
548
549 if (state.MoveMode)
550 {
551 if (!RemoveDir(srcPath))
552 {
553 RINOK(SendMessageError(state.Callback, "Cannot remove folder", srcPath));
554 return E_ABORT;
555 }
556 }
557
558 return S_OK;
559}
560
561STDMETHODIMP CFSFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
562 Int32 /* includeAltStreams */, Int32 /* replaceAltStreamColon */,
563 const wchar_t *path, IFolderOperationsExtractCallback *callback)
564{
565 if (numItems == 0)
566 return S_OK;
567
568 FString destPath = us2fs(path);
569 if (destPath.IsEmpty())
570 return E_INVALIDARG;
571
572 bool isAltDest = NName::IsAltPathPrefix(destPath);
573 bool isDirectPath = (!isAltDest && !IsPathSepar(destPath.Back()));
574
575 if (isDirectPath)
576 {
577 if (numItems > 1)
578 return E_INVALIDARG;
579 }
580
581 CFsFolderStat stat;
582 stat.Progress = callback;
583 RINOK(GetItemsFullSize(indices, numItems, stat));
584
585 if (stat.NumFolders != 0 && isAltDest)
586 return E_NOTIMPL;
587
588 RINOK(callback->SetTotal(stat.Size));
589 RINOK(callback->SetNumFiles(stat.NumFiles));
590
591 UInt64 completedSize = 0;
592 RINOK(callback->SetCompleted(&completedSize));
593
594 CCopyState state;
595 state.ProgressInfo.TotalSize = stat.Size;
596 state.ProgressInfo.StartPos = 0;
597 state.ProgressInfo.Progress = callback;
598 state.ProgressInfo.Init();
599 state.Callback = callback;
600 state.MoveMode = IntToBool(moveMode);
601 state.UseReadWriteMode = isAltDest;
602 state.Prepare();
603
604 for (UInt32 i = 0; i < numItems; i++)
605 {
606 UInt32 index = indices[i];
607 if (index >= (UInt32)Files.Size())
608 continue;
609 const CDirItem &fi = Files[index];
610 FString destPath2 = destPath;
611 if (!isDirectPath)
612 destPath2 += fi.Name;
613 FString srcPath;
614 GetFullPath(fi, srcPath);
615
616 if (fi.IsDir())
617 {
618 RINOK(CopyFolder(state, srcPath, destPath2));
619 }
620 else
621 {
622 RINOK(CopyFile_Ask(state, srcPath, fi, destPath2));
623 }
624 }
625 return S_OK;
626}
627
628STDMETHODIMP CFSFolder::CopyFrom(Int32 /* moveMode */, const wchar_t * /* fromFolderPath */,
629 const wchar_t * const * /* itemsPaths */, UInt32 /* numItems */, IProgress * /* progress */)
630{
631 /*
632 UInt64 numFolders, numFiles, totalSize;
633 numFiles = numFolders = totalSize = 0;
634 UInt32 i;
635 for (i = 0; i < numItems; i++)
636 {
637 UString path = (UString)fromFolderPath + itemsPaths[i];
638
639 CFileInfo fi;
640 if (!FindFile(path, fi))
641 return ::GetLastError();
642 if (fi.IsDir())
643 {
644 UInt64 subFolders, subFiles, subSize;
645 RINOK(GetFolderSize(CombinePath(path, fi.Name), subFolders, subFiles, subSize, progress));
646 numFolders += subFolders;
647 numFolders++;
648 numFiles += subFiles;
649 totalSize += subSize;
650 }
651 else
652 {
653 numFiles++;
654 totalSize += fi.Size;
655 }
656 }
657 RINOK(progress->SetTotal(totalSize));
658 RINOK(callback->SetNumFiles(numFiles));
659 for (i = 0; i < numItems; i++)
660 {
661 UString path = (UString)fromFolderPath + itemsPaths[i];
662 }
663 return S_OK;
664 */
665 return E_NOTIMPL;
666}
667
668STDMETHODIMP CFSFolder::CopyFromFile(UInt32 /* index */, const wchar_t * /* fullFilePath */, IProgress * /* progress */)
669{
670 return E_NOTIMPL;
671}
672
673}
diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
new file mode 100644
index 0000000..a7873fe
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.cpp
@@ -0,0 +1,357 @@
1// FileFolderPluginOpen.cpp
2
3#include "StdAfx.h"
4
5#include "resource.h"
6
7#include "../../../Windows/FileName.h"
8#include "../../../Windows/Thread.h"
9
10#include "../Agent/Agent.h"
11#include "../GUI/ExtractRes.h"
12
13#include "FileFolderPluginOpen.h"
14#include "FormatUtils.h"
15#include "LangUtils.h"
16#include "OpenCallback.h"
17#include "PluginLoader.h"
18#include "PropertyName.h"
19#include "RegistryPlugins.h"
20
21using namespace NWindows;
22
23struct CThreadArchiveOpen
24{
25 UString Path;
26 UString ArcFormat;
27 CMyComPtr<IInStream> InStream;
28 CMyComPtr<IFolderManager> FolderManager;
29 CMyComPtr<IProgress> OpenCallback;
30 COpenArchiveCallback *OpenCallbackSpec;
31
32 CMyComPtr<IFolderFolder> Folder;
33 HRESULT Result;
34
35 void Process()
36 {
37 try
38 {
39 CProgressCloser closer(OpenCallbackSpec->ProgressDialog);
40 Result = FolderManager->OpenFolderFile(InStream, Path, ArcFormat, &Folder, OpenCallback);
41 }
42 catch(...) { Result = E_FAIL; }
43 }
44
45 static THREAD_FUNC_DECL MyThreadFunction(void *param)
46 {
47 ((CThreadArchiveOpen *)param)->Process();
48 return 0;
49 }
50};
51
52/*
53static int FindPlugin(const CObjectVector<CPluginInfo> &plugins, const UString &pluginName)
54{
55 for (int i = 0; i < plugins.Size(); i++)
56 if (plugins[i].Name.CompareNoCase(pluginName) == 0)
57 return i;
58 return -1;
59}
60*/
61
62static void SplitNameToPureNameAndExtension(const FString &fullName,
63 FString &pureName, FString &extensionDelimiter, FString &extension)
64{
65 int index = fullName.ReverseFind_Dot();
66 if (index < 0)
67 {
68 pureName = fullName;
69 extensionDelimiter.Empty();
70 extension.Empty();
71 }
72 else
73 {
74 pureName.SetFrom(fullName, index);
75 extensionDelimiter = '.';
76 extension = fullName.Ptr((unsigned)index + 1);
77 }
78}
79
80
81struct CArcLevelInfo
82{
83 UString Error;
84 UString Path;
85 UString Type;
86 UString ErrorType;
87 UString ErrorFlags;
88};
89
90
91struct CArcLevelsInfo
92{
93 CObjectVector<CArcLevelInfo> Levels; // LastLevel Is NON-OPEN
94};
95
96
97UString GetOpenArcErrorMessage(UInt32 errorFlags);
98
99
100static void GetFolderLevels(CMyComPtr<IFolderFolder> &folder, CArcLevelsInfo &levels)
101{
102 levels.Levels.Clear();
103
104 CMyComPtr<IGetFolderArcProps> getFolderArcProps;
105 folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
106
107 if (!getFolderArcProps)
108 return;
109 CMyComPtr<IFolderArcProps> arcProps;
110 getFolderArcProps->GetFolderArcProps(&arcProps);
111 if (!arcProps)
112 return;
113
114 UInt32 numLevels;
115 if (arcProps->GetArcNumLevels(&numLevels) != S_OK)
116 numLevels = 0;
117
118 for (UInt32 level = 0; level <= numLevels; level++)
119 {
120 const PROPID propIDs[] = { kpidError, kpidPath, kpidType, kpidErrorType };
121
122 CArcLevelInfo lev;
123
124 for (Int32 i = 0; i < 4; i++)
125 {
126 CMyComBSTR name;
127 NCOM::CPropVariant prop;
128 if (arcProps->GetArcProp(level, propIDs[i], &prop) != S_OK)
129 continue;
130 if (prop.vt != VT_EMPTY)
131 {
132 UString *s = NULL;
133 switch (propIDs[i])
134 {
135 case kpidError: s = &lev.Error; break;
136 case kpidPath: s = &lev.Path; break;
137 case kpidType: s = &lev.Type; break;
138 case kpidErrorType: s = &lev.ErrorType; break;
139 }
140 *s = (prop.vt == VT_BSTR) ? prop.bstrVal : L"?";
141 }
142 }
143
144 {
145 NCOM::CPropVariant prop;
146 if (arcProps->GetArcProp(level, kpidErrorFlags, &prop) == S_OK)
147 {
148 UInt32 flags = GetOpenArcErrorFlags(prop);
149 if (flags != 0)
150 lev.ErrorFlags = GetOpenArcErrorMessage(flags);
151 }
152 }
153
154 levels.Levels.Add(lev);
155 }
156}
157
158static UString GetBracedType(const wchar_t *type)
159{
160 UString s ('[');
161 s += type;
162 s += ']';
163 return s;
164}
165
166static void GetFolderError(CMyComPtr<IFolderFolder> &folder, UString &open_Errors, UString &nonOpen_Errors)
167{
168 CArcLevelsInfo levs;
169 GetFolderLevels(folder, levs);
170 open_Errors.Empty();
171 nonOpen_Errors.Empty();
172
173 FOR_VECTOR (i, levs.Levels)
174 {
175 bool isNonOpenLevel = (i == 0);
176 const CArcLevelInfo &lev = levs.Levels[levs.Levels.Size() - 1 - i];
177
178 UString m;
179
180 if (!lev.ErrorType.IsEmpty())
181 {
182 m = MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(lev.ErrorType));
183 if (!isNonOpenLevel)
184 {
185 m.Add_LF();
186 m += MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(lev.Type));
187 }
188 }
189
190 if (!lev.Error.IsEmpty())
191 {
192 if (!m.IsEmpty())
193 m.Add_LF();
194 m += GetBracedType(lev.Type);
195 m += " : ";
196 m += GetNameOfProperty(kpidError, L"Error");
197 m += " : ";
198 m += lev.Error;
199 }
200
201 if (!lev.ErrorFlags.IsEmpty())
202 {
203 if (!m.IsEmpty())
204 m.Add_LF();
205 m += GetNameOfProperty(kpidErrorFlags, L"Errors");
206 m += ": ";
207 m += lev.ErrorFlags;
208 }
209
210 if (!m.IsEmpty())
211 {
212 if (isNonOpenLevel)
213 {
214 UString &s = nonOpen_Errors;
215 s += lev.Path;
216 s.Add_LF();
217 s += m;
218 }
219 else
220 {
221 UString &s = open_Errors;
222 if (!s.IsEmpty())
223 s += "--------------------\n";
224 s += lev.Path;
225 s.Add_LF();
226 s += m;
227 }
228 }
229 }
230}
231
232
233HRESULT CFfpOpen::OpenFileFolderPlugin(IInStream *inStream,
234 const FString &path, const UString &arcFormat, HWND parentWindow)
235{
236 CObjectVector<CPluginInfo> plugins;
237 ReadFileFolderPluginInfoList(plugins);
238
239 FString extension, name, pureName, dot;
240
241 int slashPos = path.ReverseFind_PathSepar();
242 FString dirPrefix;
243 FString fileName;
244 if (slashPos >= 0)
245 {
246 dirPrefix.SetFrom(path, (unsigned)(slashPos + 1));
247 fileName = path.Ptr((unsigned)(slashPos + 1));
248 }
249 else
250 fileName = path;
251
252 SplitNameToPureNameAndExtension(fileName, pureName, dot, extension);
253
254 /*
255 if (!extension.IsEmpty())
256 {
257 CExtInfo extInfo;
258 if (ReadInternalAssociation(extension, extInfo))
259 {
260 for (int i = extInfo.Plugins.Size() - 1; i >= 0; i--)
261 {
262 int pluginIndex = FindPlugin(plugins, extInfo.Plugins[i]);
263 if (pluginIndex >= 0)
264 {
265 const CPluginInfo plugin = plugins[pluginIndex];
266 plugins.Delete(pluginIndex);
267 plugins.Insert(0, plugin);
268 }
269 }
270 }
271 }
272 */
273
274 ErrorMessage.Empty();
275
276 FOR_VECTOR (i, plugins)
277 {
278 const CPluginInfo &plugin = plugins[i];
279 if (!plugin.ClassIDDefined)
280 continue;
281 CPluginLibrary library;
282
283 CThreadArchiveOpen t;
284
285 if (plugin.FilePath.IsEmpty())
286 t.FolderManager = new CArchiveFolderManager;
287 else if (library.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &t.FolderManager) != S_OK)
288 continue;
289
290 t.OpenCallbackSpec = new COpenArchiveCallback;
291 t.OpenCallback = t.OpenCallbackSpec;
292 t.OpenCallbackSpec->PasswordIsDefined = Encrypted;
293 t.OpenCallbackSpec->Password = Password;
294 t.OpenCallbackSpec->ParentWindow = parentWindow;
295
296 if (inStream)
297 t.OpenCallbackSpec->SetSubArchiveName(fs2us(fileName));
298 else
299 {
300 RINOK(t.OpenCallbackSpec->LoadFileInfo2(dirPrefix, fileName));
301 }
302
303 t.InStream = inStream;
304 t.Path = fs2us(path);
305 t.ArcFormat = arcFormat;
306
307 const UString progressTitle = LangString(IDS_OPENNING);
308 {
309 CProgressDialog &pd = t.OpenCallbackSpec->ProgressDialog;
310 pd.MainWindow = parentWindow;
311 pd.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
312 pd.MainAddTitle = progressTitle + L' ';
313 pd.WaitMode = true;
314 }
315
316 {
317 NWindows::CThread thread;
318 RINOK(thread.Create(CThreadArchiveOpen::MyThreadFunction, &t));
319 t.OpenCallbackSpec->StartProgressDialog(progressTitle, thread);
320 }
321
322 if (t.Result != S_FALSE && t.Result != S_OK)
323 return t.Result;
324
325 if (t.Folder)
326 {
327 UString open_Errors, nonOpen_Errors;
328 GetFolderError(t.Folder, open_Errors, nonOpen_Errors);
329 if (!nonOpen_Errors.IsEmpty())
330 {
331 ErrorMessage = nonOpen_Errors;
332 // if (t.Result != S_OK) return t.Result;
333 /* if there are good open leves, and non0open level,
334 we could force error as critical error and return error here
335 but it's better to allow to open such rachives */
336 // return S_FALSE;
337 }
338 }
339
340 // if (openCallbackSpec->PasswordWasAsked)
341 {
342 Encrypted = t.OpenCallbackSpec->PasswordIsDefined;
343 Password = t.OpenCallbackSpec->Password;
344 }
345
346 if (t.Result == S_OK)
347 {
348 Library.Attach(library.Detach());
349 // Folder.Attach(t.Folder.Detach());
350 Folder = t.Folder;
351 }
352
353 return t.Result;
354 }
355
356 return S_FALSE;
357}
diff --git a/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h
new file mode 100644
index 0000000..a1f2f10
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FileFolderPluginOpen.h
@@ -0,0 +1,27 @@
1// FileFolderPluginOpen.h
2
3#ifndef __FILE_FOLDER_PLUGIN_OPEN_H
4#define __FILE_FOLDER_PLUGIN_OPEN_H
5
6#include "../../../Windows/DLL.h"
7
8struct CFfpOpen
9{
10 CLASS_NO_COPY(CFfpOpen)
11public:
12 // out:
13 bool Encrypted;
14 UString Password;
15
16 NWindows::NDLL::CLibrary Library;
17 CMyComPtr<IFolderFolder> Folder;
18 UString ErrorMessage;
19
20 CFfpOpen(): Encrypted (false) {}
21
22 HRESULT OpenFileFolderPlugin(IInStream *inStream,
23 const FString &path, const UString &arcFormat, HWND parentWindow);
24};
25
26
27#endif
diff --git a/CPP/7zip/UI/FileManager/FilePlugins.cpp b/CPP/7zip/UI/FileManager/FilePlugins.cpp
new file mode 100644
index 0000000..4600030
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FilePlugins.cpp
@@ -0,0 +1,69 @@
1// FilePlugins.cpp
2
3#include "StdAfx.h"
4
5#include "../Agent/Agent.h"
6
7#include "FilePlugins.h"
8#include "PluginLoader.h"
9#include "StringUtils.h"
10
11int CExtDatabase::FindExt(const UString &ext)
12{
13 FOR_VECTOR (i, Exts)
14 if (Exts[i].Ext.IsEqualTo_NoCase(ext))
15 return i;
16 return -1;
17}
18
19void CExtDatabase::Read()
20{
21 ReadFileFolderPluginInfoList(Plugins);
22 FOR_VECTOR (pluginIndex, Plugins)
23 {
24 const CPluginInfo &plugin = Plugins[pluginIndex];
25
26 CPluginLibrary pluginLib;
27 CMyComPtr<IFolderManager> folderManager;
28
29 if (plugin.FilePath.IsEmpty())
30 folderManager = new CArchiveFolderManager;
31 else if (pluginLib.LoadAndCreateManager(plugin.FilePath, plugin.ClassID, &folderManager) != S_OK)
32 continue;
33 CMyComBSTR extBSTR;
34 if (folderManager->GetExtensions(&extBSTR) != S_OK)
35 return;
36 UStringVector exts;
37 SplitString((const wchar_t *)extBSTR, exts);
38 FOR_VECTOR (i, exts)
39 {
40 const UString &ext = exts[i];
41 #ifdef UNDER_CE
42 if (ext == L"cab")
43 continue;
44 #endif
45
46 Int32 iconIndex;
47 CMyComBSTR iconPath;
48 CPluginToIcon plugPair;
49 plugPair.PluginIndex = pluginIndex;
50 if (folderManager->GetIconPath(ext, &iconPath, &iconIndex) == S_OK)
51 if (iconPath != 0)
52 {
53 plugPair.IconPath = (const wchar_t *)iconPath;
54 plugPair.IconIndex = iconIndex;
55 }
56
57 int index = FindExt(ext);
58 if (index >= 0)
59 Exts[index].Plugins.Add(plugPair);
60 else
61 {
62 CExtPlugins extInfo;
63 extInfo.Plugins.Add(plugPair);
64 extInfo.Ext = ext;
65 Exts.Add(extInfo);
66 }
67 }
68 }
69}
diff --git a/CPP/7zip/UI/FileManager/FilePlugins.h b/CPP/7zip/UI/FileManager/FilePlugins.h
new file mode 100644
index 0000000..43b05f9
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FilePlugins.h
@@ -0,0 +1,33 @@
1// FilePlugins.h
2
3#ifndef __FILE_PLUGINS_H
4#define __FILE_PLUGINS_H
5
6#include "RegistryPlugins.h"
7
8struct CPluginToIcon
9{
10 int PluginIndex;
11 UString IconPath;
12 int IconIndex;
13
14 CPluginToIcon(): IconIndex(-1) {}
15};
16
17struct CExtPlugins
18{
19 UString Ext;
20 CObjectVector<CPluginToIcon> Plugins;
21};
22
23class CExtDatabase
24{
25 int FindExt(const UString &ext);
26public:
27 CObjectVector<CExtPlugins> Exts;
28 CObjectVector<CPluginInfo> Plugins;
29
30 void Read();
31};
32
33#endif
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.cpp b/CPP/7zip/UI/FileManager/FoldersPage.cpp
new file mode 100644
index 0000000..d019bab
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FoldersPage.cpp
@@ -0,0 +1,166 @@
1// FoldersPage.cpp
2
3#include "StdAfx.h"
4
5#include "FoldersPageRes.h"
6#include "FoldersPage.h"
7
8#include "../FileManager/BrowseDialog.h"
9#include "../FileManager/HelpUtils.h"
10#include "../FileManager/LangUtils.h"
11
12using namespace NWindows;
13
14static const UInt32 kLangIDs[] =
15{
16 IDT_FOLDERS_WORKING_FOLDER,
17 IDR_FOLDERS_WORK_SYSTEM,
18 IDR_FOLDERS_WORK_CURRENT,
19 IDR_FOLDERS_WORK_SPECIFIED,
20 IDX_FOLDERS_WORK_FOR_REMOVABLE
21};
22
23static const int kWorkModeButtons[] =
24{
25 IDR_FOLDERS_WORK_SYSTEM,
26 IDR_FOLDERS_WORK_CURRENT,
27 IDR_FOLDERS_WORK_SPECIFIED
28};
29
30#define kFoldersTopic "fm/options.htm#folders"
31
32static const unsigned kNumWorkModeButtons = ARRAY_SIZE(kWorkModeButtons);
33
34bool CFoldersPage::OnInit()
35{
36 _initMode = true;
37 _needSave = false;
38
39 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
40 m_WorkDirInfo.Load();
41
42 CheckButton(IDX_FOLDERS_WORK_FOR_REMOVABLE, m_WorkDirInfo.ForRemovableOnly);
43
44 CheckRadioButton(kWorkModeButtons[0], kWorkModeButtons[kNumWorkModeButtons - 1],
45 kWorkModeButtons[m_WorkDirInfo.Mode]);
46
47 m_WorkPath.Init(*this, IDE_FOLDERS_WORK_PATH);
48
49 m_WorkPath.SetText(fs2us(m_WorkDirInfo.Path));
50
51 MyEnableControls();
52
53 _initMode = false;
54 return CPropertyPage::OnInit();
55}
56
57int CFoldersPage::GetWorkMode() const
58{
59 for (unsigned i = 0; i < kNumWorkModeButtons; i++)
60 if (IsButtonCheckedBool(kWorkModeButtons[i]))
61 return i;
62 throw 0;
63}
64
65void CFoldersPage::MyEnableControls()
66{
67 bool enablePath = (GetWorkMode() == NWorkDir::NMode::kSpecified);
68 m_WorkPath.Enable(enablePath);
69 EnableItem(IDB_FOLDERS_WORK_PATH, enablePath);
70}
71
72void CFoldersPage::GetWorkDir(NWorkDir::CInfo &workDirInfo)
73{
74 UString s;
75 m_WorkPath.GetText(s);
76 workDirInfo.Path = us2fs(s);
77 workDirInfo.ForRemovableOnly = IsButtonCheckedBool(IDX_FOLDERS_WORK_FOR_REMOVABLE);
78 workDirInfo.Mode = NWorkDir::NMode::EEnum(GetWorkMode());
79}
80
81/*
82bool CFoldersPage::WasChanged()
83{
84 NWorkDir::CInfo workDirInfo;
85 GetWorkDir(workDirInfo);
86 return (workDirInfo.Mode != m_WorkDirInfo.Mode ||
87 workDirInfo.ForRemovableOnly != m_WorkDirInfo.ForRemovableOnly ||
88 workDirInfo.Path.Compare(m_WorkDirInfo.Path) != 0);
89}
90*/
91
92void CFoldersPage::ModifiedEvent()
93{
94 if (!_initMode)
95 {
96 _needSave = true;
97 Changed();
98 }
99 /*
100 if (WasChanged())
101 Changed();
102 else
103 UnChanged();
104 */
105}
106
107bool CFoldersPage::OnButtonClicked(int buttonID, HWND buttonHWND)
108{
109 for (unsigned i = 0; i < kNumWorkModeButtons; i++)
110 if (buttonID == kWorkModeButtons[i])
111 {
112 MyEnableControls();
113 ModifiedEvent();
114 return true;
115 }
116
117 switch (buttonID)
118 {
119 case IDB_FOLDERS_WORK_PATH:
120 OnFoldersWorkButtonPath();
121 return true;
122 case IDX_FOLDERS_WORK_FOR_REMOVABLE:
123 break;
124 default:
125 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
126 }
127
128 ModifiedEvent();
129 return true;
130}
131
132bool CFoldersPage::OnCommand(int code, int itemID, LPARAM lParam)
133{
134 if (code == EN_CHANGE && itemID == IDE_FOLDERS_WORK_PATH)
135 {
136 ModifiedEvent();
137 return true;
138 }
139 return CPropertyPage::OnCommand(code, itemID, lParam);
140}
141
142void CFoldersPage::OnFoldersWorkButtonPath()
143{
144 UString currentPath;
145 m_WorkPath.GetText(currentPath);
146 UString title = LangString(IDS_FOLDERS_SET_WORK_PATH_TITLE);
147 UString resultPath;
148 if (MyBrowseForFolder(*this, title, currentPath, resultPath))
149 m_WorkPath.SetText(resultPath);
150}
151
152LONG CFoldersPage::OnApply()
153{
154 if (_needSave)
155 {
156 GetWorkDir(m_WorkDirInfo);
157 m_WorkDirInfo.Save();
158 _needSave = false;
159 }
160 return PSNRET_NOERROR;
161}
162
163void CFoldersPage::OnNotifyHelp()
164{
165 ShowHelpWindow(kFoldersTopic);
166}
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.h b/CPP/7zip/UI/FileManager/FoldersPage.h
new file mode 100644
index 0000000..71c7bfc
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FoldersPage.h
@@ -0,0 +1,32 @@
1// FoldersPage.h
2
3#ifndef __FOLDERS_PAGE_H
4#define __FOLDERS_PAGE_H
5
6#include "../../../Windows/Control/PropertyPage.h"
7
8#include "../Common/ZipRegistry.h"
9
10class CFoldersPage : public NWindows::NControl::CPropertyPage
11{
12 NWorkDir::CInfo m_WorkDirInfo;
13 NWindows::NControl::CDialogChildControl m_WorkPath;
14
15 bool _needSave;
16 bool _initMode;
17
18 void MyEnableControls();
19 void ModifiedEvent();
20
21 void OnFoldersWorkButtonPath();
22 int GetWorkMode() const;
23 void GetWorkDir(NWorkDir::CInfo &workDirInfo);
24 // bool WasChanged();
25 virtual bool OnInit();
26 virtual bool OnCommand(int code, int itemID, LPARAM lParam);
27 virtual void OnNotifyHelp();
28 virtual LONG OnApply();
29 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
30};
31
32#endif
diff --git a/CPP/7zip/UI/FileManager/FoldersPage.rc b/CPP/7zip/UI/FileManager/FoldersPage.rc
new file mode 100644
index 0000000..cb345ea
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FoldersPage.rc
@@ -0,0 +1,23 @@
1#include "FoldersPageRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 240
5#define yc 100
6
7IDD_FOLDERS MY_PAGE
8#include "FoldersPage2.rc"
9
10#ifdef UNDER_CE
11
12#undef xc
13#define xc SMALL_PAGE_SIZE_X
14
15IDD_FOLDERS_2 MY_PAGE
16#include "FoldersPage2.rc"
17
18#endif
19
20STRINGTABLE
21BEGIN
22 IDS_FOLDERS_SET_WORK_PATH_TITLE "Specify a location for temporary archive files."
23END
diff --git a/CPP/7zip/UI/FileManager/FoldersPage2.rc b/CPP/7zip/UI/FileManager/FoldersPage2.rc
new file mode 100644
index 0000000..9b9276e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FoldersPage2.rc
@@ -0,0 +1,16 @@
1CAPTION "Folders"
2BEGIN
3 // GROUPBOX "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 98
4
5 LTEXT "&Working folder", IDT_FOLDERS_WORKING_FOLDER, m, m, xc, 8
6 CONTROL "&System temp folder", IDR_FOLDERS_WORK_SYSTEM, "Button", BS_AUTORADIOBUTTON | WS_GROUP,
7 m, 20, xc, 10
8 CONTROL "&Current", IDR_FOLDERS_WORK_CURRENT, "Button", BS_AUTORADIOBUTTON,
9 m, 34, xc, 10
10 CONTROL "Specified:", IDR_FOLDERS_WORK_SPECIFIED, "Button", BS_AUTORADIOBUTTON,
11 m, 48, xc, 10
12 EDITTEXT IDE_FOLDERS_WORK_PATH, m + m, 62, xc - m - m - bxsDots, 14, ES_AUTOHSCROLL
13 PUSHBUTTON "...", IDB_FOLDERS_WORK_PATH, xs - m - bxsDots, 61, bxsDots, bys
14 CONTROL "Use for removable drives only", IDX_FOLDERS_WORK_FOR_REMOVABLE, MY_CHECKBOX,
15 m, 86, xc, 10
16END
diff --git a/CPP/7zip/UI/FileManager/FoldersPageRes.h b/CPP/7zip/UI/FileManager/FoldersPageRes.h
new file mode 100644
index 0000000..ba9ab73
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FoldersPageRes.h
@@ -0,0 +1,12 @@
1#define IDD_FOLDERS 2400
2#define IDD_FOLDERS_2 12400
3
4#define IDT_FOLDERS_WORKING_FOLDER 2401
5#define IDR_FOLDERS_WORK_SYSTEM 2402
6#define IDR_FOLDERS_WORK_CURRENT 2403
7#define IDR_FOLDERS_WORK_SPECIFIED 2404
8#define IDX_FOLDERS_WORK_FOR_REMOVABLE 2405
9#define IDS_FOLDERS_SET_WORK_PATH_TITLE 2406
10
11#define IDE_FOLDERS_WORK_PATH 100
12#define IDB_FOLDERS_WORK_PATH 101
diff --git a/CPP/7zip/UI/FileManager/FormatUtils.cpp b/CPP/7zip/UI/FileManager/FormatUtils.cpp
new file mode 100644
index 0000000..2143c3f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FormatUtils.cpp
@@ -0,0 +1,28 @@
1// FormatUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6
7#include "FormatUtils.h"
8
9#include "LangUtils.h"
10
11UString NumberToString(UInt64 number)
12{
13 wchar_t numberString[32];
14 ConvertUInt64ToString(number, numberString);
15 return numberString;
16}
17
18UString MyFormatNew(const UString &format, const UString &argument)
19{
20 UString result = format;
21 result.Replace(L"{0}", argument);
22 return result;
23}
24
25UString MyFormatNew(UINT resourceID, const UString &argument)
26{
27 return MyFormatNew(LangString(resourceID), argument);
28}
diff --git a/CPP/7zip/UI/FileManager/FormatUtils.h b/CPP/7zip/UI/FileManager/FormatUtils.h
new file mode 100644
index 0000000..993e803
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/FormatUtils.h
@@ -0,0 +1,14 @@
1// FormatUtils.h
2
3#ifndef __FORMAT_UTILS_H
4#define __FORMAT_UTILS_H
5
6#include "../../../Common/MyTypes.h"
7#include "../../../Common/MyString.h"
8
9UString NumberToString(UInt64 number);
10
11UString MyFormatNew(const UString &format, const UString &argument);
12UString MyFormatNew(UINT resourceID, const UString &argument);
13
14#endif
diff --git a/CPP/7zip/UI/FileManager/HelpUtils.cpp b/CPP/7zip/UI/FileManager/HelpUtils.cpp
new file mode 100644
index 0000000..2db9501
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/HelpUtils.cpp
@@ -0,0 +1,32 @@
1// HelpUtils.cpp
2
3#include "StdAfx.h"
4
5#include "HelpUtils.h"
6
7#if defined(UNDER_CE) || !defined(_WIN32) /* || !defined(_MSC_VER) */
8
9void ShowHelpWindow(LPCSTR)
10{
11}
12
13#else
14
15#include <HtmlHelp.h>
16
17#include "../../../Common/StringConvert.h"
18
19#include "../../../Windows/DLL.h"
20
21#define kHelpFileName "7-zip.chm::/"
22
23void ShowHelpWindow(LPCSTR topicFile)
24{
25 FString path = NWindows::NDLL::GetModuleDirPrefix();
26 path += kHelpFileName;
27 path += topicFile;
28 // HWND hwnd = NULL;
29 HtmlHelp(NULL, GetSystemString(fs2us(path)), HH_DISPLAY_TOPIC, 0);
30}
31
32#endif
diff --git a/CPP/7zip/UI/FileManager/HelpUtils.h b/CPP/7zip/UI/FileManager/HelpUtils.h
new file mode 100644
index 0000000..90c5f7d
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/HelpUtils.h
@@ -0,0 +1,10 @@
1// HelpUtils.h
2
3#ifndef __HELP_UTILS_H
4#define __HELP_UTILS_H
5
6#include "../../../Common/MyString.h"
7
8void ShowHelpWindow(LPCSTR topicFile);
9
10#endif
diff --git a/CPP/7zip/UI/FileManager/IFolder.h b/CPP/7zip/UI/FileManager/IFolder.h
new file mode 100644
index 0000000..c5cff06
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/IFolder.h
@@ -0,0 +1,218 @@
1// IFolder.h
2
3#ifndef __IFOLDER_H
4#define __IFOLDER_H
5
6#include "../../IProgress.h"
7#include "../../IStream.h"
8
9#define FOLDER_INTERFACE_SUB(i, b, x) DECL_INTERFACE_SUB(i, b, 8, x)
10#define FOLDER_INTERFACE(i, x) FOLDER_INTERFACE_SUB(i, IUnknown, x)
11
12namespace NPlugin
13{
14 enum
15 {
16 kName = 0,
17 kType,
18 kClassID,
19 kOptionsClassID
20 };
21}
22
23#define INTERFACE_FolderFolder(x) \
24 STDMETHOD(LoadItems)() x; \
25 STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \
26 STDMETHOD(GetProperty)(UInt32 itemIndex, PROPID propID, PROPVARIANT *value) x; \
27 STDMETHOD(BindToFolder)(UInt32 index, IFolderFolder **resultFolder) x; \
28 STDMETHOD(BindToFolder)(const wchar_t *name, IFolderFolder **resultFolder) x; \
29 STDMETHOD(BindToParentFolder)(IFolderFolder **resultFolder) x; \
30 STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \
31 STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
32 STDMETHOD(GetFolderProperty)(PROPID propID, PROPVARIANT *value) x; \
33
34FOLDER_INTERFACE(IFolderFolder, 0x00)
35{
36 INTERFACE_FolderFolder(PURE)
37};
38
39/*
40 IFolderAltStreams::
41 BindToAltStreams((UInt32)(Int32)-1, ... ) means alt streams of that folder
42*/
43
44#define INTERFACE_FolderAltStreams(x) \
45 STDMETHOD(BindToAltStreams)(UInt32 index, IFolderFolder **resultFolder) x; \
46 STDMETHOD(BindToAltStreams)(const wchar_t *name, IFolderFolder **resultFolder) x; \
47 STDMETHOD(AreAltStreamsSupported)(UInt32 index, Int32 *isSupported) x; \
48
49FOLDER_INTERFACE(IFolderAltStreams, 0x17)
50{
51 INTERFACE_FolderAltStreams(PURE)
52};
53
54FOLDER_INTERFACE(IFolderWasChanged, 0x04)
55{
56 STDMETHOD(WasChanged)(Int32 *wasChanged) PURE;
57};
58
59FOLDER_INTERFACE_SUB(IFolderOperationsExtractCallback, IProgress, 0x0B)
60{
61 // STDMETHOD(SetTotalFiles)(UInt64 total) PURE;
62 // STDMETHOD(SetCompletedFiles)(const UInt64 *completedValue) PURE;
63 STDMETHOD(AskWrite)(
64 const wchar_t *srcPath,
65 Int32 srcIsFolder,
66 const FILETIME *srcTime,
67 const UInt64 *srcSize,
68 const wchar_t *destPathRequest,
69 BSTR *destPathResult,
70 Int32 *writeAnswer) PURE;
71 STDMETHOD(ShowMessage)(const wchar_t *message) PURE;
72 STDMETHOD(SetCurrentFilePath)(const wchar_t *filePath) PURE;
73 STDMETHOD(SetNumFiles)(UInt64 numFiles) PURE;
74};
75
76#define INTERFACE_FolderOperations(x) \
77 STDMETHOD(CreateFolder)(const wchar_t *name, IProgress *progress) x; \
78 STDMETHOD(CreateFile)(const wchar_t *name, IProgress *progress) x; \
79 STDMETHOD(Rename)(UInt32 index, const wchar_t *newName, IProgress *progress) x; \
80 STDMETHOD(Delete)(const UInt32 *indices, UInt32 numItems, IProgress *progress) x; \
81 STDMETHOD(CopyTo)(Int32 moveMode, const UInt32 *indices, UInt32 numItems, \
82 Int32 includeAltStreams, Int32 replaceAltStreamCharsMode, \
83 const wchar_t *path, IFolderOperationsExtractCallback *callback) x; \
84 STDMETHOD(CopyFrom)(Int32 moveMode, const wchar_t *fromFolderPath, \
85 const wchar_t * const *itemsPaths, UInt32 numItems, IProgress *progress) x; \
86 STDMETHOD(SetProperty)(UInt32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress) x; \
87 STDMETHOD(CopyFromFile)(UInt32 index, const wchar_t *fullFilePath, IProgress *progress) x; \
88
89FOLDER_INTERFACE(IFolderOperations, 0x13)
90{
91 INTERFACE_FolderOperations(PURE)
92};
93
94/*
95FOLDER_INTERFACE2(IFolderOperationsDeleteToRecycleBin, 0x06, 0x03)
96{
97 STDMETHOD(DeleteToRecycleBin)(const UInt32 *indices, UInt32 numItems, IProgress *progress) PURE;
98};
99*/
100
101FOLDER_INTERFACE(IFolderGetSystemIconIndex, 0x07)
102{
103 STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex) PURE;
104};
105
106FOLDER_INTERFACE(IFolderGetItemFullSize, 0x08)
107{
108 STDMETHOD(GetItemFullSize)(UInt32 index, PROPVARIANT *value, IProgress *progress) PURE;
109};
110
111FOLDER_INTERFACE(IFolderCalcItemFullSize, 0x14)
112{
113 STDMETHOD(CalcItemFullSize)(UInt32 index, IProgress *progress) PURE;
114};
115
116FOLDER_INTERFACE(IFolderClone, 0x09)
117{
118 STDMETHOD(Clone)(IFolderFolder **resultFolder) PURE;
119};
120
121FOLDER_INTERFACE(IFolderSetFlatMode, 0x0A)
122{
123 STDMETHOD(SetFlatMode)(Int32 flatMode) PURE;
124};
125
126/*
127FOLDER_INTERFACE(IFolderSetShowNtfsStreamsMode, 0xFA)
128{
129 STDMETHOD(SetShowNtfsStreamsMode)(Int32 showStreamsMode) PURE;
130};
131*/
132
133#define INTERFACE_FolderProperties(x) \
134 STDMETHOD(GetNumberOfFolderProperties)(UInt32 *numProperties) x; \
135 STDMETHOD(GetFolderPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
136
137FOLDER_INTERFACE(IFolderProperties, 0x0E)
138{
139 INTERFACE_FolderProperties(PURE)
140};
141
142#define INTERFACE_IFolderArcProps(x) \
143 STDMETHOD(GetArcNumLevels)(UInt32 *numLevels) x; \
144 STDMETHOD(GetArcProp)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \
145 STDMETHOD(GetArcNumProps)(UInt32 level, UInt32 *numProps) x; \
146 STDMETHOD(GetArcPropInfo)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
147 STDMETHOD(GetArcProp2)(UInt32 level, PROPID propID, PROPVARIANT *value) x; \
148 STDMETHOD(GetArcNumProps2)(UInt32 level, UInt32 *numProps) x; \
149 STDMETHOD(GetArcPropInfo2)(UInt32 level, UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \
150
151FOLDER_INTERFACE(IFolderArcProps, 0x10)
152{
153 INTERFACE_IFolderArcProps(PURE)
154};
155
156FOLDER_INTERFACE(IGetFolderArcProps, 0x11)
157{
158 STDMETHOD(GetFolderArcProps)(IFolderArcProps **object) PURE;
159};
160
161FOLDER_INTERFACE(IFolderCompare, 0x15)
162{
163 STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw) PURE;
164};
165
166#define INTERFACE_IFolderGetItemName(x) \
167 STDMETHOD(GetItemName)(UInt32 index, const wchar_t **name, unsigned *len) x; \
168 STDMETHOD(GetItemPrefix)(UInt32 index, const wchar_t **name, unsigned *len) x; \
169 STDMETHOD_(UInt64, GetItemSize)(UInt32 index) x; \
170
171FOLDER_INTERFACE(IFolderGetItemName, 0x16)
172{
173 INTERFACE_IFolderGetItemName(PURE)
174};
175
176#define FOLDER_MANAGER_INTERFACE(i, x) DECL_INTERFACE(i, 9, x)
177
178#define INTERFACE_IFolderManager(x) \
179 STDMETHOD(OpenFolderFile)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, IFolderFolder **resultFolder, IProgress *progress) x; \
180 STDMETHOD(GetExtensions)(BSTR *extensions) x; \
181 STDMETHOD(GetIconPath)(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex) x; \
182
183 // STDMETHOD(GetTypes)(BSTR *types) PURE;
184 // STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress) PURE;
185
186FOLDER_MANAGER_INTERFACE(IFolderManager, 0x05)
187{
188 INTERFACE_IFolderManager(PURE);
189};
190
191/*
192#define IMP_IFolderFolder_GetProp(k) \
193 (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
194 { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
195 const CMy_STATPROPSTG_2 &srcItem = k[index]; \
196 *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \
197
198#define IMP_IFolderFolder_Props(c) \
199 STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \
200 { *numProperties = ARRAY_SIZE(kProps); return S_OK; } \
201 STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
202*/
203
204#define IMP_IFolderFolder_GetProp(k) \
205 (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \
206 { if (index >= ARRAY_SIZE(k)) return E_INVALIDARG; \
207 *propID = k[index]; *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; *name = 0; return S_OK; } \
208
209#define IMP_IFolderFolder_Props(c) \
210 STDMETHODIMP c::GetNumberOfProperties(UInt32 *numProperties) \
211 { *numProperties = ARRAY_SIZE(kProps); return S_OK; } \
212 STDMETHODIMP c::GetPropertyInfo IMP_IFolderFolder_GetProp(kProps)
213
214
215int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2);
216// int CompareFileNames_ForFolderList(const FChar *s1, const FChar *s2);
217
218#endif
diff --git a/CPP/7zip/UI/FileManager/Info.bmp b/CPP/7zip/UI/FileManager/Info.bmp
new file mode 100644
index 0000000..d769a66
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Info.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Info2.bmp b/CPP/7zip/UI/FileManager/Info2.bmp
new file mode 100644
index 0000000..af724d2
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Info2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/LangPage.cpp b/CPP/7zip/UI/FileManager/LangPage.cpp
new file mode 100644
index 0000000..47e7894
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LangPage.cpp
@@ -0,0 +1,120 @@
1// LangPage.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/Lang.h"
6
7#include "../../../Windows/FileFind.h"
8#include "../../../Windows/ResourceString.h"
9
10#include "HelpUtils.h"
11#include "LangPage.h"
12#include "LangPageRes.h"
13#include "LangUtils.h"
14#include "RegistryUtils.h"
15
16using namespace NWindows;
17
18static const UInt32 kLangIDs[] =
19{
20 IDT_LANG_LANG
21};
22
23#define kLangTopic "fm/options.htm#language"
24
25static void NativeLangString(UString &dest, const wchar_t *s)
26{
27 dest += " (";
28 dest += s;
29 dest += ')';
30}
31
32bool LangOpen(CLang &lang, CFSTR fileName);
33
34bool CLangPage::OnInit()
35{
36 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
37
38 _langCombo.Attach(GetItem(IDC_LANG_LANG));
39
40 UString temp = MyLoadString(IDS_LANG_ENGLISH);
41 NativeLangString(temp, MyLoadString(IDS_LANG_NATIVE));
42 int index = (int)_langCombo.AddString(temp);
43 _langCombo.SetItemData(index, _paths.Size());
44 _paths.Add(L"-");
45 _langCombo.SetCurSel(0);
46
47 const FString dirPrefix = GetLangDirPrefix();
48 NFile::NFind::CEnumerator enumerator;
49 enumerator.SetDirPrefix(dirPrefix);
50 NFile::NFind::CFileInfo fi;
51 CLang lang;
52 UString error;
53
54 while (enumerator.Next(fi))
55 {
56 if (fi.IsDir())
57 continue;
58 const unsigned kExtSize = 4;
59 if (fi.Name.Len() < kExtSize)
60 continue;
61 const unsigned pos = fi.Name.Len() - kExtSize;
62 if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".txt"))
63 {
64 // if (!StringsAreEqualNoCase_Ascii(fi.Name.Ptr(pos), ".ttt"))
65 continue;
66 }
67
68 if (!LangOpen(lang, dirPrefix + fi.Name))
69 {
70 error.Add_Space_if_NotEmpty();
71 error += fs2us(fi.Name);
72 continue;
73 }
74
75 const UString shortName = fs2us(fi.Name.Left(pos));
76 UString s = shortName;
77 const wchar_t *eng = lang.Get(IDS_LANG_ENGLISH);
78 if (eng)
79 s = eng;
80 const wchar_t *native = lang.Get(IDS_LANG_NATIVE);
81 if (native)
82 NativeLangString(s, native);
83 index = (int)_langCombo.AddString(s);
84 _langCombo.SetItemData(index, _paths.Size());
85 _paths.Add(shortName);
86 if (g_LangID.IsEqualTo_NoCase(shortName))
87 _langCombo.SetCurSel(index);
88 }
89
90 if (!error.IsEmpty())
91 MessageBoxW(0, error, L"Error in Lang file", MB_ICONERROR);
92 return CPropertyPage::OnInit();
93}
94
95LONG CLangPage::OnApply()
96{
97 int pathIndex = (int)_langCombo.GetItemData_of_CurSel();
98 if (_needSave)
99 SaveRegLang(_paths[pathIndex]);
100 _needSave = false;
101 ReloadLang();
102 LangWasChanged = true;
103 return PSNRET_NOERROR;
104}
105
106void CLangPage::OnNotifyHelp()
107{
108 ShowHelpWindow(kLangTopic);
109}
110
111bool CLangPage::OnCommand(int code, int itemID, LPARAM param)
112{
113 if (code == CBN_SELCHANGE && itemID == IDC_LANG_LANG)
114 {
115 _needSave = true;
116 Changed();
117 return true;
118 }
119 return CPropertyPage::OnCommand(code, itemID, param);
120}
diff --git a/CPP/7zip/UI/FileManager/LangPage.h b/CPP/7zip/UI/FileManager/LangPage.h
new file mode 100644
index 0000000..b806257
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LangPage.h
@@ -0,0 +1,25 @@
1// LangPage.h
2
3#ifndef __LANG_PAGE_H
4#define __LANG_PAGE_H
5
6#include "../../../Windows/Control/PropertyPage.h"
7#include "../../../Windows/Control/ComboBox.h"
8
9class CLangPage: public NWindows::NControl::CPropertyPage
10{
11 NWindows::NControl::CComboBox _langCombo;
12 UStringVector _paths;
13
14 bool _needSave;
15public:
16 bool LangWasChanged;
17
18 CLangPage(): _needSave(false), LangWasChanged(false) {}
19 virtual bool OnInit();
20 virtual void OnNotifyHelp();
21 virtual bool OnCommand(int code, int itemID, LPARAM param);
22 virtual LONG OnApply();
23};
24
25#endif
diff --git a/CPP/7zip/UI/FileManager/LangPage.rc b/CPP/7zip/UI/FileManager/LangPage.rc
new file mode 100644
index 0000000..164e2d3
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LangPage.rc
@@ -0,0 +1,37 @@
1#include "LangPageRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 160
5#define yc 100
6
7IDD_LANG DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
8CAPTION "Language"
9{
10 LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8
11 COMBOBOX IDC_LANG_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED
12}
13
14
15#ifdef UNDER_CE
16
17#undef m
18#undef xc
19
20#define m 4
21#define xc (SMALL_PAGE_SIZE_X + 8)
22
23IDD_LANG_2 MY_PAGE
24CAPTION "Language"
25{
26 LTEXT "Language:", IDT_LANG_LANG, m, m, xc, 8
27 COMBOBOX IDC_LANG_LANG, m, 20, xc, yc - 20, MY_COMBO_SORTED
28}
29
30#endif
31
32
33STRINGTABLE
34BEGIN
35 IDS_LANG_ENGLISH "English"
36 IDS_LANG_NATIVE "English"
37END
diff --git a/CPP/7zip/UI/FileManager/LangPageRes.h b/CPP/7zip/UI/FileManager/LangPageRes.h
new file mode 100644
index 0000000..d7a39d7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LangPageRes.h
@@ -0,0 +1,8 @@
1#define IDD_LANG 2101
2#define IDD_LANG_2 12101
3
4#define IDS_LANG_ENGLISH 1
5#define IDS_LANG_NATIVE 2
6
7#define IDT_LANG_LANG 2102
8#define IDC_LANG_LANG 100
diff --git a/CPP/7zip/UI/FileManager/LangUtils.cpp b/CPP/7zip/UI/FileManager/LangUtils.cpp
new file mode 100644
index 0000000..83d5aa7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LangUtils.cpp
@@ -0,0 +1,293 @@
1// LangUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/Lang.h"
6
7#include "../../../Windows/DLL.h"
8#include "../../../Windows/Synchronization.h"
9#include "../../../Windows/Window.h"
10
11#include "LangUtils.h"
12#include "RegistryUtils.h"
13
14using namespace NWindows;
15
16#ifndef _UNICODE
17extern bool g_IsNT;
18#endif
19
20UString g_LangID;
21
22static CLang g_Lang;
23static bool g_Loaded = false;
24static NSynchronization::CCriticalSection g_CriticalSection;
25
26bool LangOpen(CLang &lang, CFSTR fileName);
27bool LangOpen(CLang &lang, CFSTR fileName)
28{
29 return lang.Open(fileName, "7-Zip");
30}
31
32FString GetLangDirPrefix()
33{
34 return NDLL::GetModuleDirPrefix() + FTEXT("Lang") FSTRING_PATH_SEPARATOR;
35}
36
37void LoadLangOneTime()
38{
39 NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
40 if (g_Loaded)
41 return;
42 g_Loaded = true;
43 ReloadLang();
44}
45
46void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID)
47{
48 const wchar_t *s = g_Lang.Get(langID);
49 if (s)
50 {
51 CWindow window(GetDlgItem(dialog, controlID));
52 window.SetText(s);
53 }
54}
55
56static const CIDLangPair kLangPairs[] =
57{
58 { IDOK, 401 },
59 { IDCANCEL, 402 },
60 { IDYES, 406 },
61 { IDNO, 407 },
62 { IDCLOSE, 408 },
63 { IDHELP, 409 }
64};
65
66
67void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems)
68{
69 unsigned i;
70 for (i = 0; i < ARRAY_SIZE(kLangPairs); i++)
71 {
72 const CIDLangPair &pair = kLangPairs[i];
73 CWindow window(GetDlgItem(dialog, pair.ControlID));
74 if (window)
75 {
76 const wchar_t *s = g_Lang.Get(pair.LangID);
77 if (s)
78 window.SetText(s);
79 }
80 }
81
82 for (i = 0; i < numItems; i++)
83 {
84 UInt32 id = ids[i];
85 LangSetDlgItemText(dialog, id, id);
86 }
87}
88
89void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems)
90{
91 for (unsigned i = 0; i < numItems; i++)
92 {
93 UInt32 id = ids[i];
94 const wchar_t *s = g_Lang.Get(id);
95 if (s)
96 {
97 CWindow window(GetDlgItem(dialog, id));
98 UString s2 = s;
99 s2 += ':';
100 window.SetText(s2);
101 }
102 }
103}
104
105void LangSetWindowText(HWND window, UInt32 langID)
106{
107 const wchar_t *s = g_Lang.Get(langID);
108 if (s)
109 MySetWindowText(window, s);
110}
111
112UString LangString(UInt32 langID)
113{
114 const wchar_t *s = g_Lang.Get(langID);
115 if (s)
116 return s;
117 return MyLoadString(langID);
118}
119
120void AddLangString(UString &s, UInt32 langID)
121{
122 s += LangString(langID);
123}
124
125void LangString(UInt32 langID, UString &dest)
126{
127 const wchar_t *s = g_Lang.Get(langID);
128 if (s)
129 {
130 dest = s;
131 return;
132 }
133 MyLoadString(langID, dest);
134}
135
136void LangString_OnlyFromLangFile(UInt32 langID, UString &dest)
137{
138 dest.Empty();
139 const wchar_t *s = g_Lang.Get(langID);
140 if (s)
141 dest = s;
142}
143
144static const char * const kLangs =
145 "ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is."
146 "it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.sk.sq.sv.th.tr."
147 "ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk."
148 "st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk."
149 "ky.sw.tk.uz.-latn.-cyrl.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa."
150 "mn.=mn.=mng.bo.cy.kh.lo.my.gl.kok..sd.syr.si..iu.am.tzm."
151 "ks.ne.fy.ps.tl.dv..ff.ha..yo.qu.st.ba.lb.kl."
152 "ig.kr.om.ti.gn..la.so.ii..arn..moh..br.."
153 "ug.mi.oc.co."
154 // "gsw.sah.qut.rw.wo....prs...."
155 // ".gd."
156 ;
157
158static void FindShortNames(UInt32 primeLang, AStringVector &names)
159{
160 UInt32 index = 0;
161 for (const char *p = kLangs; *p != 0;)
162 {
163 const char *p2 = p;
164 for (; *p2 != '.'; p2++);
165 bool isSub = (p[0] == '-' || p[0] == '=');
166 if (!isSub)
167 index++;
168 if (index >= primeLang)
169 {
170 if (index > primeLang)
171 break;
172 AString s;
173 if (isSub)
174 {
175 if (p[0] == '-')
176 s = names[0];
177 else
178 p++;
179 }
180 while (p != p2)
181 s += (char)(Byte)*p++;
182 names.Add(s);
183 }
184 p = p2 + 1;
185 }
186}
187
188/*
189#include "../../../Common/IntToString.h"
190
191static struct CC1Lang
192{
193 CC1Lang()
194 {
195 for (int i = 1; i < 150; i++)
196 {
197 UString s;
198 char ttt[32];
199 ConvertUInt32ToHex(i, ttt);
200 s += ttt;
201 UStringVector names;
202 FindShortNames(i, names);
203
204 FOR_VECTOR (k, names)
205 {
206 s.Add_Space();
207 s += names[k];
208 }
209 OutputDebugStringW(s);
210 }
211 }
212} g_cc1;
213*/
214
215// typedef LANGID (WINAPI *GetUserDefaultUILanguageP)();
216
217static void OpenDefaultLang()
218{
219 LANGID sysLang = GetSystemDefaultLangID(); // "Language for non-Unicode programs" in XP64
220 LANGID userLang = GetUserDefaultLangID(); // "Standards and formats" language in XP64
221
222 if (sysLang != userLang)
223 return;
224 LANGID langID = userLang;
225
226 /*
227 LANGID sysUILang; // english in XP64
228 LANGID userUILang; // english in XP64
229
230 GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress(
231 GetModuleHandle("kernel32"), "GetUserDefaultUILanguage");
232 if (fn)
233 userUILang = fn();
234 fn = (GetUserDefaultUILanguageP)GetProcAddress(
235 GetModuleHandle("kernel32"), "GetSystemDefaultUILanguage");
236 if (fn)
237 sysUILang = fn();
238 */
239
240 WORD primLang = (WORD)(PRIMARYLANGID(langID));
241 WORD subLang = (WORD)(SUBLANGID(langID));
242 {
243 AStringVector names;
244 FindShortNames(primLang, names);
245 const FString dirPrefix (GetLangDirPrefix());
246 for (unsigned i = 0; i < 2; i++)
247 {
248 unsigned index = (i == 0 ? subLang : 0);
249 if (index < names.Size())
250 {
251 const AString &name = names[index];
252 if (!name.IsEmpty())
253 {
254 FString path (dirPrefix);
255 path += name;
256 path += ".txt";
257 if (LangOpen(g_Lang, path))
258 {
259 g_LangID = name;
260 return;
261 }
262 }
263 }
264 }
265 }
266}
267
268void ReloadLang()
269{
270 g_Lang.Clear();
271 ReadRegLang(g_LangID);
272 #ifndef _UNICODE
273 if (g_IsNT)
274 #endif
275 {
276 if (g_LangID.IsEmpty())
277 {
278 OpenDefaultLang();
279 return;
280 }
281 }
282 if (g_LangID.Len() > 1 || g_LangID[0] != L'-')
283 {
284 FString s = us2fs(g_LangID);
285 if (s.Find(FCHAR_PATH_SEPARATOR) < 0)
286 {
287 if (s.Find(FTEXT('.')) < 0)
288 s += ".txt";
289 s.Insert(0, GetLangDirPrefix());
290 }
291 LangOpen(g_Lang, s);
292 }
293}
diff --git a/CPP/7zip/UI/FileManager/LangUtils.h b/CPP/7zip/UI/FileManager/LangUtils.h
new file mode 100644
index 0000000..d63a443
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LangUtils.h
@@ -0,0 +1,40 @@
1// LangUtils.h
2
3#ifndef __LANG_UTILS_H
4#define __LANG_UTILS_H
5
6#include "../../../Windows/ResourceString.h"
7
8#ifdef LANG
9
10extern UString g_LangID;
11
12struct CIDLangPair
13{
14 UInt32 ControlID;
15 UInt32 LangID;
16};
17
18void ReloadLang();
19void LoadLangOneTime();
20FString GetLangDirPrefix();
21
22void LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID);
23void LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems);
24void LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems);
25void LangSetWindowText(HWND window, UInt32 langID);
26
27UString LangString(UInt32 langID);
28void AddLangString(UString &s, UInt32 langID);
29void LangString(UInt32 langID, UString &dest);
30void LangString_OnlyFromLangFile(UInt32 langID, UString &dest);
31
32#else
33
34inline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); }
35inline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); }
36inline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); }
37
38#endif
39
40#endif
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.cpp b/CPP/7zip/UI/FileManager/LinkDialog.cpp
new file mode 100644
index 0000000..07f1f06
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LinkDialog.cpp
@@ -0,0 +1,399 @@
1// LinkDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/ErrorMsg.h"
6#include "../../../Windows/FileDir.h"
7#include "../../../Windows/FileFind.h"
8#include "../../../Windows/FileIO.h"
9#include "../../../Windows/FileName.h"
10
11#ifdef LANG
12#include "LangUtils.h"
13#endif
14
15#include "BrowseDialog.h"
16#include "CopyDialogRes.h"
17#include "LinkDialog.h"
18#include "resourceGui.h"
19
20#include "App.h"
21
22#include "resource.h"
23
24extern bool g_SymLink_Supported;
25
26using namespace NWindows;
27using namespace NFile;
28
29#ifdef LANG
30static const UInt32 kLangIDs[] =
31{
32 IDB_LINK_LINK,
33 IDT_LINK_PATH_FROM,
34 IDT_LINK_PATH_TO,
35 IDG_LINK_TYPE,
36 IDR_LINK_TYPE_HARD,
37 IDR_LINK_TYPE_SYM_FILE,
38 IDR_LINK_TYPE_SYM_DIR,
39 IDR_LINK_TYPE_JUNCTION,
40 IDR_LINK_TYPE_WSL
41};
42#endif
43
44
45static bool GetSymLink(CFSTR path, CReparseAttr &attr, UString &errorMessage)
46{
47 CByteBuffer buf;
48 if (!NIO::GetReparseData(path, buf, NULL))
49 return false;
50
51 if (!attr.Parse(buf, buf.Size()))
52 {
53 SetLastError(attr.ErrorCode);
54 return false;
55 }
56
57 CByteBuffer data2;
58 if (!FillLinkData(data2, attr.GetPath(),
59 !attr.IsMountPoint(), attr.IsSymLink_WSL()))
60 {
61 errorMessage = "Cannot reproduce reparse point";
62 return false;
63 }
64
65 if (data2.Size() != buf.Size() ||
66 memcmp(data2, buf, buf.Size()) != 0)
67 {
68 errorMessage = "mismatch for reproduced reparse point";
69 return false;
70 }
71
72 return true;
73}
74
75
76static const int k_LinkType_Buttons[] =
77{
78 IDR_LINK_TYPE_HARD,
79 IDR_LINK_TYPE_SYM_FILE,
80 IDR_LINK_TYPE_SYM_DIR,
81 IDR_LINK_TYPE_JUNCTION,
82 IDR_LINK_TYPE_WSL
83};
84
85void CLinkDialog::Set_LinkType_Radio(int idb)
86{
87 CheckRadioButton(k_LinkType_Buttons[0], k_LinkType_Buttons[ARRAY_SIZE(k_LinkType_Buttons) - 1], idb);
88}
89
90bool CLinkDialog::OnInit()
91{
92 #ifdef LANG
93 LangSetWindowText(*this, IDD_LINK);
94 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
95 #endif
96
97 _pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
98 _pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
99
100 if (!FilePath.IsEmpty())
101 {
102 NFind::CFileInfo fi;
103 int linkType = 0;
104 if (!fi.Find(us2fs(FilePath)))
105 linkType = IDR_LINK_TYPE_SYM_FILE;
106 else
107 {
108 if (fi.HasReparsePoint())
109 {
110 CReparseAttr attr;
111 UString error;
112 bool res = GetSymLink(us2fs(FilePath), attr, error);
113 if (!res && error.IsEmpty())
114 {
115 DWORD lastError = GetLastError();
116 if (lastError != 0)
117 error = NError::MyFormatMessage(lastError);
118 }
119
120 UString s = attr.GetPath();
121 if (!attr.IsSymLink_WSL())
122 if (!attr.IsOkNamePair())
123 {
124 s += " : ";
125 s += attr.PrintName;
126 }
127
128 if (!res)
129 {
130 s.Insert(0, L"ERROR: ");
131 if (!error.IsEmpty())
132 {
133 s += " : ";
134 s += error;
135 }
136 }
137
138
139 SetItemText(IDT_LINK_PATH_TO_CUR, s);
140
141 UString destPath = attr.GetPath();
142 _pathFromCombo.SetText(FilePath);
143 _pathToCombo.SetText(destPath);
144
145 // if (res)
146 {
147 if (attr.IsMountPoint())
148 linkType = IDR_LINK_TYPE_JUNCTION;
149 else if (attr.IsSymLink_WSL())
150 linkType = IDR_LINK_TYPE_WSL;
151 else if (attr.IsSymLink_Win())
152 {
153 linkType =
154 fi.IsDir() ?
155 IDR_LINK_TYPE_SYM_DIR :
156 IDR_LINK_TYPE_SYM_FILE;
157 // if (attr.IsRelative()) linkType = IDR_LINK_TYPE_SYM_RELATIVE;
158 }
159
160 if (linkType != 0)
161 Set_LinkType_Radio(linkType);
162 }
163 }
164 else
165 {
166 // no ReparsePoint
167 _pathFromCombo.SetText(AnotherPath);
168 _pathToCombo.SetText(FilePath);
169 if (fi.IsDir())
170 linkType = g_SymLink_Supported ?
171 IDR_LINK_TYPE_SYM_DIR :
172 IDR_LINK_TYPE_JUNCTION;
173 else
174 linkType = IDR_LINK_TYPE_HARD;
175 }
176 }
177 if (linkType != 0)
178 Set_LinkType_Radio(linkType);
179 }
180
181 NormalizeSize();
182 return CModalDialog::OnInit();
183}
184
185bool CLinkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
186{
187 int mx, my;
188 GetMargins(8, mx, my);
189 int bx1, bx2, by;
190 GetItemSizes(IDCANCEL, bx1, by);
191 GetItemSizes(IDB_LINK_LINK, bx2, by);
192 int yPos = ySize - my - by;
193 int xPos = xSize - mx - bx1;
194
195 InvalidateRect(NULL);
196
197 {
198 RECT r, r2;
199 GetClientRectOfItem(IDB_LINK_PATH_FROM, r);
200 GetClientRectOfItem(IDB_LINK_PATH_TO, r2);
201 int bx = RECT_SIZE_X(r);
202 int newButtonXpos = xSize - mx - bx;
203
204 MoveItem(IDB_LINK_PATH_FROM, newButtonXpos, r.top, bx, RECT_SIZE_Y(r));
205 MoveItem(IDB_LINK_PATH_TO, newButtonXpos, r2.top, bx, RECT_SIZE_Y(r2));
206
207 int newComboXsize = newButtonXpos - mx - mx;
208 ChangeSubWindowSizeX(_pathFromCombo, newComboXsize);
209 ChangeSubWindowSizeX(_pathToCombo, newComboXsize);
210 }
211
212 MoveItem(IDCANCEL, xPos, yPos, bx1, by);
213 MoveItem(IDB_LINK_LINK, xPos - mx - bx2, yPos, bx2, by);
214
215 return false;
216}
217
218bool CLinkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
219{
220 switch (buttonID)
221 {
222 case IDB_LINK_PATH_FROM:
223 OnButton_SetPath(false);
224 return true;
225 case IDB_LINK_PATH_TO:
226 OnButton_SetPath(true);
227 return true;
228 case IDB_LINK_LINK:
229 OnButton_Link();
230 return true;
231 }
232 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
233}
234
235void CLinkDialog::OnButton_SetPath(bool to)
236{
237 UString currentPath;
238 NWindows::NControl::CComboBox &combo = to ?
239 _pathToCombo :
240 _pathFromCombo;
241 combo.GetText(currentPath);
242 // UString title = "Specify a location for output folder";
243 UString title = LangString(IDS_SET_FOLDER);
244
245 UString resultPath;
246 if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
247 return;
248 NName::NormalizeDirPathPrefix(resultPath);
249 combo.SetCurSel(-1);
250 combo.SetText(resultPath);
251}
252
253void CLinkDialog::ShowError(const wchar_t *s)
254{
255 ::MessageBoxW(*this, s, L"7-Zip", MB_ICONERROR);
256}
257
258void CLinkDialog::ShowLastErrorMessage()
259{
260 ShowError(NError::MyFormatMessage(GetLastError()));
261}
262
263void CLinkDialog::OnButton_Link()
264{
265 UString from, to;
266 _pathFromCombo.GetText(from);
267 _pathToCombo.GetText(to);
268
269 if (from.IsEmpty())
270 return;
271 if (!NName::IsAbsolutePath(from))
272 from.Insert(0, CurDirPrefix);
273
274 int idb = -1;
275 for (unsigned i = 0;; i++)
276 {
277 if (i >= ARRAY_SIZE(k_LinkType_Buttons))
278 return;
279 idb = k_LinkType_Buttons[i];
280 if (IsButtonCheckedBool(idb))
281 break;
282 }
283
284 NFind::CFileInfo info1, info2;
285 const bool finded1 = info1.Find(us2fs(from));
286 const bool finded2 = info2.Find(us2fs(to));
287
288 const bool isDirLink = (
289 idb == IDR_LINK_TYPE_SYM_DIR ||
290 idb == IDR_LINK_TYPE_JUNCTION);
291
292 const bool isWSL = (idb == IDR_LINK_TYPE_WSL);
293
294 if (!isWSL)
295 if ((finded1 && info1.IsDir() != isDirLink) ||
296 (finded2 && info2.IsDir() != isDirLink))
297 {
298 ShowError(L"Incorrect link type");
299 return;
300 }
301
302 if (idb == IDR_LINK_TYPE_HARD)
303 {
304 if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to)))
305 {
306 ShowLastErrorMessage();
307 return;
308 }
309 }
310 else
311 {
312 if (finded1 && !info1.IsDir() && !info1.HasReparsePoint() && info1.Size != 0)
313 {
314 UString s ("WARNING: reparse point will hide the data of existing file");
315 s.Add_LF();
316 s += from;
317 ShowError(s);
318 return;
319 }
320
321 const bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION);
322
323 CByteBuffer data;
324 if (!FillLinkData(data, to, isSymLink, isWSL))
325 {
326 ShowError(L"Incorrect link");
327 return;
328 }
329
330 CReparseAttr attr;
331 if (!attr.Parse(data, data.Size()))
332 {
333 ShowError(L"Internal conversion error");
334 return;
335 }
336
337 bool res;
338 if (to.IsEmpty())
339 {
340 // res = NIO::SetReparseData(us2fs(from), isDirLink, NULL, 0);
341 res = NIO::DeleteReparseData(us2fs(from));
342 }
343 else
344 res = NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size());
345
346 if (!res)
347 {
348 ShowLastErrorMessage();
349 return;
350 }
351 }
352
353 End(IDOK);
354}
355
356void CApp::Link()
357{
358 unsigned srcPanelIndex = GetFocusedPanelIndex();
359 CPanel &srcPanel = Panels[srcPanelIndex];
360 if (!srcPanel.IsFSFolder())
361 {
362 srcPanel.MessageBox_Error_UnsupportOperation();
363 return;
364 }
365 CRecordVector<UInt32> indices;
366 srcPanel.GetOperatedItemIndices(indices);
367 if (indices.IsEmpty())
368 return;
369 if (indices.Size() != 1)
370 {
371 srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
372 return;
373 }
374 int index = indices[0];
375 const UString itemName = srcPanel.GetItemName(index);
376
377 const UString fsPrefix = srcPanel.GetFsPath();
378 const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
379 UString path = srcPath;
380 {
381 unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
382 CPanel &destPanel = Panels[destPanelIndex];
383 if (NumPanels > 1)
384 if (destPanel.IsFSFolder())
385 path = destPanel.GetFsPath();
386 }
387
388 CLinkDialog dlg;
389 dlg.CurDirPrefix = fsPrefix;
390 dlg.FilePath = srcPath + itemName;
391 dlg.AnotherPath = path;
392
393 if (dlg.Create(srcPanel.GetParent()) != IDOK)
394 return;
395
396 // fix it: we should refresh panel with changed link
397
398 RefreshTitleAlways();
399}
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.h b/CPP/7zip/UI/FileManager/LinkDialog.h
new file mode 100644
index 0000000..56deec9
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LinkDialog.h
@@ -0,0 +1,34 @@
1// LinkDialog.h
2
3#ifndef __LINK_DIALOG_H
4#define __LINK_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7#include "../../../Windows/Control/ComboBox.h"
8
9#include "LinkDialogRes.h"
10
11class CLinkDialog: public NWindows::NControl::CModalDialog
12{
13 NWindows::NControl::CComboBox _pathFromCombo;
14 NWindows::NControl::CComboBox _pathToCombo;
15
16 virtual bool OnInit();
17 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
18 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
19 void OnButton_SetPath(bool to);
20 void OnButton_Link();
21
22 void ShowLastErrorMessage();
23 void ShowError(const wchar_t *s);
24 void Set_LinkType_Radio(int idb);
25public:
26 UString CurDirPrefix;
27 UString FilePath;
28 UString AnotherPath;
29
30 INT_PTR Create(HWND parentWindow = 0)
31 { return CModalDialog::Create(IDD_LINK, parentWindow); }
32};
33
34#endif
diff --git a/CPP/7zip/UI/FileManager/LinkDialog.rc b/CPP/7zip/UI/FileManager/LinkDialog.rc
new file mode 100644
index 0000000..a9e220b
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LinkDialog.rc
@@ -0,0 +1,38 @@
1#include "LinkDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 288
5#define yc 214
6
7#undef xRadioSize
8#define xRadioSize xc - m - 2
9
10IDD_LINK DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
11CAPTION "Link"
12BEGIN
13 LTEXT "Link from:", IDT_LINK_PATH_FROM, m, m, xc, 8
14 COMBOBOX IDC_LINK_PATH_FROM, m, 20, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT
15 PUSHBUTTON "...", IDB_LINK_PATH_FROM, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP
16
17 LTEXT "Link to:", IDT_LINK_PATH_TO, m, 48, xc, 8
18 COMBOBOX IDC_LINK_PATH_TO, m, 60, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT
19 PUSHBUTTON "...", IDB_LINK_PATH_TO, xs - m - bxsDots, 58, bxsDots, bys, WS_GROUP
20
21 LTEXT "", IDT_LINK_PATH_TO_CUR, m, 78, xc, 8
22
23 GROUPBOX "Link Type", IDG_LINK_TYPE, m, 104, xc, 90
24
25 CONTROL "Hard Link", IDR_LINK_TYPE_HARD, "Button", BS_AUTORADIOBUTTON | WS_GROUP,
26 m + m, 120, xRadioSize, 10
27 CONTROL "File Symbolic Link", IDR_LINK_TYPE_SYM_FILE, "Button", BS_AUTORADIOBUTTON,
28 m + m, 134, xRadioSize, 10
29 CONTROL "Directory Symbolic Link", IDR_LINK_TYPE_SYM_DIR, "Button", BS_AUTORADIOBUTTON,
30 m + m, 148, xRadioSize, 10
31 CONTROL "Directory Junction", IDR_LINK_TYPE_JUNCTION, "Button", BS_AUTORADIOBUTTON,
32 m + m, 162, xRadioSize, 10
33 CONTROL "WSL", IDR_LINK_TYPE_WSL, "Button", BS_AUTORADIOBUTTON,
34 m + m, 176, xRadioSize, 10
35
36 DEFPUSHBUTTON "Link", IDB_LINK_LINK, bx2, by, bxs, bys
37 PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
38END
diff --git a/CPP/7zip/UI/FileManager/LinkDialogRes.h b/CPP/7zip/UI/FileManager/LinkDialogRes.h
new file mode 100644
index 0000000..3f7b3f2
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/LinkDialogRes.h
@@ -0,0 +1,22 @@
1#define IDD_LINK 7700
2
3#define IDB_LINK_LINK 7701
4
5#define IDT_LINK_PATH_FROM 7702
6#define IDT_LINK_PATH_TO 7703
7
8#define IDG_LINK_TYPE 7710
9#define IDR_LINK_TYPE_HARD 7711
10#define IDR_LINK_TYPE_SYM_FILE 7712
11#define IDR_LINK_TYPE_SYM_DIR 7713
12#define IDR_LINK_TYPE_JUNCTION 7714
13#define IDR_LINK_TYPE_WSL 7715
14
15
16#define IDC_LINK_PATH_FROM 100
17#define IDC_LINK_PATH_TO 101
18
19#define IDT_LINK_PATH_TO_CUR 102
20
21#define IDB_LINK_PATH_FROM 103
22#define IDB_LINK_PATH_TO 104
diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.cpp b/CPP/7zip/UI/FileManager/ListViewDialog.cpp
new file mode 100644
index 0000000..a42e790
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ListViewDialog.cpp
@@ -0,0 +1,321 @@
1// ListViewDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/Clipboard.h"
6
7#include "EditDialog.h"
8#include "ListViewDialog.h"
9#include "RegistryUtils.h"
10
11#ifdef LANG
12#include "LangUtils.h"
13#endif
14
15using namespace NWindows;
16
17static const unsigned kOneStringMaxSize = 1024;
18
19
20static void ListView_GetSelected(NControl::CListView &listView, CUIntVector &vector)
21{
22 vector.Clear();
23 int index = -1;
24 for (;;)
25 {
26 index = listView.GetNextSelectedItem(index);
27 if (index < 0)
28 break;
29 vector.Add(index);
30 }
31}
32
33
34bool CListViewDialog::OnInit()
35{
36 #ifdef LANG
37 LangSetDlgItems(*this, NULL, 0);
38 #endif
39 _listView.Attach(GetItem(IDL_LISTVIEW));
40
41 if (NumColumns > 1)
42 {
43 LONG_PTR style = _listView.GetStyle();
44 style &= ~(LONG_PTR)LVS_NOCOLUMNHEADER;
45 _listView.SetStyle(style);
46 }
47
48 CFmSettings st;
49 st.Load();
50
51 DWORD exStyle = 0;
52
53 if (st.SingleClick)
54 exStyle |= LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT;
55
56 exStyle |= LVS_EX_FULLROWSELECT;
57 if (exStyle != 0)
58 _listView.SetExtendedListViewStyle(exStyle);
59
60
61 SetText(Title);
62
63 const int kWidth = 400;
64
65 LVCOLUMN columnInfo;
66 columnInfo.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
67 columnInfo.fmt = LVCFMT_LEFT;
68 columnInfo.iSubItem = 0;
69 columnInfo.cx = kWidth;
70 columnInfo.pszText = NULL; // (TCHAR *)(const TCHAR *)""; // "Property"
71
72 if (NumColumns > 1)
73 {
74 columnInfo.cx = 100;
75 /*
76 // Windows always uses LVCFMT_LEFT for first column.
77 // if we need LVCFMT_RIGHT, we can create dummy column and then remove it
78
79 // columnInfo.mask |= LVCF_TEXT;
80 _listView.InsertColumn(0, &columnInfo);
81
82 columnInfo.iSubItem = 1;
83 columnInfo.fmt = LVCFMT_RIGHT;
84 _listView.InsertColumn(1, &columnInfo);
85 _listView.DeleteColumn(0);
86 */
87 }
88 // else
89 _listView.InsertColumn(0, &columnInfo);
90
91 if (NumColumns > 1)
92 {
93 // columnInfo.fmt = LVCFMT_LEFT;
94 columnInfo.cx = kWidth - columnInfo.cx;
95 columnInfo.iSubItem = 1;
96 // columnInfo.pszText = NULL; // (TCHAR *)(const TCHAR *)""; // "Value"
97 _listView.InsertColumn(1, &columnInfo);
98 }
99
100
101 UString s;
102
103 FOR_VECTOR (i, Strings)
104 {
105 _listView.InsertItem(i, Strings[i]);
106
107 if (NumColumns > 1 && i < Values.Size())
108 {
109 s = Values[i];
110 if (s.Len() > kOneStringMaxSize)
111 {
112 s.DeleteFrom(kOneStringMaxSize);
113 s += " ...";
114 }
115 s.Replace(L"\r\n", L" ");
116 s.Replace(L"\n", L" ");
117 _listView.SetSubItem(i, 1, s);
118 }
119 }
120
121 if (SelectFirst && Strings.Size() > 0)
122 _listView.SetItemState_FocusedSelected(0);
123
124 _listView.SetColumnWidthAuto(0);
125 if (NumColumns > 1)
126 _listView.SetColumnWidthAuto(1);
127 StringsWereChanged = false;
128
129 NormalizeSize();
130 return CModalDialog::OnInit();
131}
132
133bool CListViewDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
134{
135 int mx, my;
136 GetMargins(8, mx, my);
137 int bx1, bx2, by;
138 GetItemSizes(IDCANCEL, bx1, by);
139 GetItemSizes(IDOK, bx2, by);
140 int y = ySize - my - by;
141 int x = xSize - mx - bx1;
142
143 /*
144 RECT rect;
145 GetClientRect(&rect);
146 rect.top = y - my;
147 InvalidateRect(&rect);
148 */
149 InvalidateRect(NULL);
150
151 MoveItem(IDCANCEL, x, y, bx1, by);
152 MoveItem(IDOK, x - mx - bx2, y, bx2, by);
153 /*
154 if (wParam == SIZE_MAXSHOW || wParam == SIZE_MAXIMIZED || wParam == SIZE_MAXHIDE)
155 mx = 0;
156 */
157 _listView.Move(mx, my, xSize - mx * 2, y - my * 2);
158 return false;
159}
160
161
162extern bool g_LVN_ITEMACTIVATE_Support;
163
164void CListViewDialog::CopyToClipboard()
165{
166 CUIntVector indexes;
167 ListView_GetSelected(_listView, indexes);
168 UString s;
169
170 FOR_VECTOR (i, indexes)
171 {
172 unsigned index = indexes[i];
173 s += Strings[index];
174 if (NumColumns > 1 && index < Values.Size())
175 {
176 const UString &v = Values[index];
177 // if (!v.IsEmpty())
178 {
179 s += ": ";
180 s += v;
181 }
182 }
183 // if (indexes.Size() > 1)
184 {
185 s +=
186 #ifdef _WIN32
187 "\r\n"
188 #else
189 "\n"
190 #endif
191 ;
192 }
193 }
194
195 ClipboardSetText(*this, s);
196}
197
198
199void CListViewDialog::ShowItemInfo()
200{
201 CUIntVector indexes;
202 ListView_GetSelected(_listView, indexes);
203 if (indexes.Size() != 1)
204 return;
205 unsigned index = indexes[0];
206
207 CEditDialog dlg;
208 if (NumColumns == 1)
209 dlg.Text = Strings[index];
210 else
211 {
212 dlg.Title = Strings[index];
213 if (index < Values.Size())
214 dlg.Text = Values[index];
215 }
216
217 #ifdef _WIN32
218 if (dlg.Text.Find(L'\r') < 0)
219 dlg.Text.Replace(L"\n", L"\r\n");
220 #endif
221
222 dlg.Create(*this);
223}
224
225
226void CListViewDialog::DeleteItems()
227{
228 for (;;)
229 {
230 int index = _listView.GetNextSelectedItem(-1);
231 if (index < 0)
232 break;
233 StringsWereChanged = true;
234 _listView.DeleteItem(index);
235 if ((unsigned)index < Strings.Size())
236 Strings.Delete(index);
237 if ((unsigned)index < Values.Size())
238 Values.Delete(index);
239 }
240 int focusedIndex = _listView.GetFocusedItem();
241 if (focusedIndex >= 0)
242 _listView.SetItemState_FocusedSelected(focusedIndex);
243 _listView.SetColumnWidthAuto(0);
244}
245
246
247void CListViewDialog::OnEnter()
248{
249 if (IsKeyDown(VK_MENU)
250 || NumColumns > 1)
251 {
252 ShowItemInfo();
253 return;
254 }
255 OnOK();
256}
257
258bool CListViewDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
259{
260 if (header->hwndFrom != _listView)
261 return false;
262 switch (header->code)
263 {
264 case LVN_ITEMACTIVATE:
265 if (g_LVN_ITEMACTIVATE_Support)
266 {
267 OnEnter();
268 return true;
269 }
270 break;
271 case NM_DBLCLK:
272 case NM_RETURN: // probabably it's unused
273 if (!g_LVN_ITEMACTIVATE_Support)
274 {
275 OnEnter();
276 return true;
277 }
278 break;
279
280 case LVN_KEYDOWN:
281 {
282 LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);
283 switch (keyDownInfo->wVKey)
284 {
285 case VK_DELETE:
286 {
287 if (!DeleteIsAllowed)
288 return false;
289 DeleteItems();
290 return true;
291 }
292 case 'A':
293 {
294 if (IsKeyDown(VK_CONTROL))
295 {
296 _listView.SelectAll();
297 return true;
298 }
299 break;
300 }
301 case VK_INSERT:
302 case 'C':
303 {
304 if (IsKeyDown(VK_CONTROL))
305 {
306 CopyToClipboard();
307 return true;
308 }
309 break;
310 }
311 }
312 }
313 }
314 return false;
315}
316
317void CListViewDialog::OnOK()
318{
319 FocusedItemIndex = _listView.GetFocusedItem();
320 CModalDialog::OnOK();
321}
diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.h b/CPP/7zip/UI/FileManager/ListViewDialog.h
new file mode 100644
index 0000000..00206af
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ListViewDialog.h
@@ -0,0 +1,46 @@
1// ListViewDialog.h
2
3#ifndef __LISTVIEW_DIALOG_H
4#define __LISTVIEW_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7#include "../../../Windows/Control/ListView.h"
8
9#include "ListViewDialogRes.h"
10
11class CListViewDialog: public NWindows::NControl::CModalDialog
12{
13 NWindows::NControl::CListView _listView;
14 virtual void OnOK();
15 virtual bool OnInit();
16 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
17 virtual bool OnNotify(UINT controlID, LPNMHDR header);
18 void CopyToClipboard();
19 void DeleteItems();
20 void ShowItemInfo();
21 void OnEnter();
22public:
23 UString Title;
24
25 bool SelectFirst;
26 bool DeleteIsAllowed;
27 bool StringsWereChanged;
28
29 UStringVector Strings;
30 UStringVector Values;
31
32 int FocusedItemIndex;
33 unsigned NumColumns;
34
35 INT_PTR Create(HWND wndParent = 0) { return CModalDialog::Create(IDD_LISTVIEW, wndParent); }
36
37 CListViewDialog():
38 SelectFirst(false),
39 DeleteIsAllowed(false),
40 StringsWereChanged(false),
41 FocusedItemIndex(-1),
42 NumColumns(1)
43 {}
44};
45
46#endif
diff --git a/CPP/7zip/UI/FileManager/ListViewDialog.rc b/CPP/7zip/UI/FileManager/ListViewDialog.rc
new file mode 100644
index 0000000..4343b75
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ListViewDialog.rc
@@ -0,0 +1,14 @@
1#include "ListViewDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 480
5#define yc 320
6
7IDD_LISTVIEW DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
8CAPTION "ListView"
9{
10 CONTROL "List1", IDL_LISTVIEW, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS |
11 LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,
12 m, m, xc, yc - bys - m
13 OK_CANCEL
14}
diff --git a/CPP/7zip/UI/FileManager/ListViewDialogRes.h b/CPP/7zip/UI/FileManager/ListViewDialogRes.h
new file mode 100644
index 0000000..9abdb9d
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ListViewDialogRes.h
@@ -0,0 +1,2 @@
1#define IDD_LISTVIEW 99
2#define IDL_LISTVIEW 100
diff --git a/CPP/7zip/UI/FileManager/MenuPage.cpp b/CPP/7zip/UI/FileManager/MenuPage.cpp
new file mode 100644
index 0000000..05f24d7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MenuPage.cpp
@@ -0,0 +1,362 @@
1// MenuPage.cpp
2
3#include "StdAfx.h"
4
5#include "../Common/ZipRegistry.h"
6
7#include "../../../Windows/DLL.h"
8#include "../../../Windows/ErrorMsg.h"
9#include "../../../Windows/FileFind.h"
10
11#include "../Explorer/ContextMenuFlags.h"
12#include "../Explorer/RegistryContextMenu.h"
13#include "../Explorer/resource.h"
14
15#include "../FileManager/PropertyNameRes.h"
16
17#include "../GUI/ExtractDialogRes.h"
18
19#include "FormatUtils.h"
20#include "HelpUtils.h"
21#include "LangUtils.h"
22#include "MenuPage.h"
23#include "MenuPageRes.h"
24
25
26using namespace NWindows;
27using namespace NContextMenuFlags;
28
29static const UInt32 kLangIDs[] =
30{
31 IDX_SYSTEM_INTEGRATE_TO_MENU,
32 IDX_SYSTEM_CASCADED_MENU,
33 IDX_SYSTEM_ICON_IN_MENU,
34 IDX_EXTRACT_ELIM_DUP,
35 IDT_SYSTEM_CONTEXT_MENU_ITEMS
36};
37
38#define kMenuTopic "fm/options.htm#sevenZip"
39
40struct CContextMenuItem
41{
42 int ControlID;
43 UInt32 Flag;
44};
45
46static const CContextMenuItem kMenuItems[] =
47{
48 { IDS_CONTEXT_OPEN, kOpen },
49 { IDS_CONTEXT_OPEN, kOpenAs },
50 { IDS_CONTEXT_EXTRACT, kExtract },
51 { IDS_CONTEXT_EXTRACT_HERE, kExtractHere },
52 { IDS_CONTEXT_EXTRACT_TO, kExtractTo },
53
54 { IDS_CONTEXT_TEST, kTest },
55
56 { IDS_CONTEXT_COMPRESS, kCompress },
57 { IDS_CONTEXT_COMPRESS_TO, kCompressTo7z },
58 { IDS_CONTEXT_COMPRESS_TO, kCompressToZip },
59
60 #ifndef UNDER_CE
61 { IDS_CONTEXT_COMPRESS_EMAIL, kCompressEmail },
62 { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressTo7zEmail },
63 { IDS_CONTEXT_COMPRESS_TO_EMAIL, kCompressToZipEmail },
64 #endif
65
66 { IDS_PROP_CHECKSUM, kCRC },
67 { IDS_PROP_CHECKSUM, kCRC_Cascaded },
68};
69
70
71#if !defined(_WIN64)
72extern bool g_Is_Wow64;
73#endif
74
75#ifndef KEY_WOW64_64KEY
76 #define KEY_WOW64_64KEY (0x0100)
77#endif
78
79#ifndef KEY_WOW64_32KEY
80 #define KEY_WOW64_32KEY (0x0200)
81#endif
82
83bool CMenuPage::OnInit()
84{
85 _initMode = true;
86
87 Clear_MenuChanged();
88
89 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
90
91 #ifdef UNDER_CE
92
93 HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU);
94 HideItem(IDX_SYSTEM_INTEGRATE_TO_MENU_2);
95
96 #else
97
98 {
99 UString s;
100 {
101 CWindow window(GetItem(IDX_SYSTEM_INTEGRATE_TO_MENU));
102 window.GetText(s);
103 }
104 UString bit64 = LangString(IDS_PROP_BIT64);
105 if (bit64.IsEmpty())
106 bit64 = "64-bit";
107 #ifdef _WIN64
108 bit64.Replace(L"64", L"32");
109 #endif
110 s.Add_Space();
111 s += '(';
112 s += bit64;
113 s += ')';
114 SetItemText(IDX_SYSTEM_INTEGRATE_TO_MENU_2, s);
115 }
116
117 const FString prefix = NDLL::GetModuleDirPrefix();
118
119 _dlls[0].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU;
120 _dlls[1].ctrl = IDX_SYSTEM_INTEGRATE_TO_MENU_2;
121
122 _dlls[0].wow = 0;
123 _dlls[1].wow =
124 #ifdef _WIN64
125 KEY_WOW64_32KEY
126 #else
127 KEY_WOW64_64KEY
128 #endif
129 ;
130
131 for (unsigned d = 0; d < 2; d++)
132 {
133 CShellDll &dll = _dlls[d];
134
135 dll.wasChanged = false;
136
137 #ifndef _WIN64
138 if (d != 0 && !g_Is_Wow64)
139 {
140 HideItem(dll.ctrl);
141 continue;
142 }
143 #endif
144
145 FString &path = dll.Path;
146 path = prefix;
147 path += (d == 0 ? "7-zip.dll" :
148 #ifdef _WIN64
149 "7-zip32.dll"
150 #else
151 "7-zip64.dll"
152 #endif
153 );
154
155
156 if (!NFile::NFind::DoesFileExist_Raw(path))
157 {
158 path.Empty();
159 EnableItem(dll.ctrl, false);
160 }
161 else
162 {
163 dll.prevValue = CheckContextMenuHandler(fs2us(path), dll.wow);
164 CheckButton(dll.ctrl, dll.prevValue);
165 }
166 }
167
168 #endif
169
170
171 CContextMenuInfo ci;
172 ci.Load();
173
174 CheckButton(IDX_SYSTEM_CASCADED_MENU, ci.Cascaded.Val);
175 CheckButton(IDX_SYSTEM_ICON_IN_MENU, ci.MenuIcons.Val);
176 CheckButton(IDX_EXTRACT_ELIM_DUP, ci.ElimDup.Val);
177
178 _listView.Attach(GetItem(IDL_SYSTEM_OPTIONS));
179
180 const UInt32 newFlags = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT;
181 _listView.SetExtendedListViewStyle(newFlags, newFlags);
182
183 _listView.InsertColumn(0, L"", 200);
184
185 for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
186 {
187 const CContextMenuItem &menuItem = kMenuItems[i];
188
189 UString s = LangString(menuItem.ControlID);
190 if (menuItem.Flag == kCRC)
191 s = "CRC SHA";
192 else if (menuItem.Flag == kCRC_Cascaded)
193 s = "7-Zip > CRC SHA";
194 if (menuItem.Flag == kOpenAs
195 || menuItem.Flag == kCRC
196 || menuItem.Flag == kCRC_Cascaded)
197 s += " >";
198
199 switch (menuItem.ControlID)
200 {
201 case IDS_CONTEXT_EXTRACT_TO:
202 {
203 s = MyFormatNew(s, LangString(IDS_CONTEXT_FOLDER));
204 break;
205 }
206 case IDS_CONTEXT_COMPRESS_TO:
207 case IDS_CONTEXT_COMPRESS_TO_EMAIL:
208 {
209 UString s2 = LangString(IDS_CONTEXT_ARCHIVE);
210 switch (menuItem.Flag)
211 {
212 case kCompressTo7z:
213 case kCompressTo7zEmail:
214 s2 += (".7z");
215 break;
216 case kCompressToZip:
217 case kCompressToZipEmail:
218 s2 += (".zip");
219 break;
220 }
221 s = MyFormatNew(s, s2);
222 break;
223 }
224 }
225
226 int itemIndex = _listView.InsertItem(i, s);
227 _listView.SetCheckState(itemIndex, ((ci.Flags & menuItem.Flag) != 0));
228 }
229
230 _listView.SetColumnWidthAuto(0);
231 _initMode = false;
232
233 return CPropertyPage::OnInit();
234}
235
236
237#ifndef UNDER_CE
238
239static void ShowMenuErrorMessage(const wchar_t *m, HWND hwnd)
240{
241 MessageBoxW(hwnd, m, L"7-Zip", MB_ICONERROR);
242}
243
244#endif
245
246
247LONG CMenuPage::OnApply()
248{
249 #ifndef UNDER_CE
250
251 for (unsigned d = 2; d != 0;)
252 {
253 d--;
254 CShellDll &dll = _dlls[d];
255 if (dll.wasChanged && !dll.Path.IsEmpty())
256 {
257 bool newVal = IsButtonCheckedBool(dll.ctrl);
258 LONG res = SetContextMenuHandler(newVal, fs2us(dll.Path), dll.wow);
259 if (res != ERROR_SUCCESS && (dll.prevValue != newVal || newVal))
260 ShowMenuErrorMessage(NError::MyFormatMessage(res), *this);
261 dll.prevValue = CheckContextMenuHandler(fs2us(dll.Path), dll.wow);
262 CheckButton(dll.ctrl, dll.prevValue);
263 dll.wasChanged = false;
264 }
265 }
266
267 #endif
268
269 if (_cascaded_Changed || _menuIcons_Changed || _elimDup_Changed || _flags_Changed)
270 {
271 CContextMenuInfo ci;
272 ci.Cascaded.Val = IsButtonCheckedBool(IDX_SYSTEM_CASCADED_MENU);
273 ci.Cascaded.Def = _cascaded_Changed;
274
275 ci.MenuIcons.Val = IsButtonCheckedBool(IDX_SYSTEM_ICON_IN_MENU);
276 ci.MenuIcons.Def = _menuIcons_Changed;
277
278 ci.ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);
279 ci.ElimDup.Def = _elimDup_Changed;
280
281 ci.Flags = 0;
282
283 for (unsigned i = 0; i < ARRAY_SIZE(kMenuItems); i++)
284 if (_listView.GetCheckState(i))
285 ci.Flags |= kMenuItems[i].Flag;
286
287 ci.Flags_Def = _flags_Changed;
288 ci.Save();
289
290 Clear_MenuChanged();
291 }
292
293 // UnChanged();
294
295 return PSNRET_NOERROR;
296}
297
298void CMenuPage::OnNotifyHelp()
299{
300 ShowHelpWindow(kMenuTopic);
301}
302
303bool CMenuPage::OnButtonClicked(int buttonID, HWND buttonHWND)
304{
305 switch (buttonID)
306 {
307 #ifndef UNDER_CE
308 case IDX_SYSTEM_INTEGRATE_TO_MENU:
309 case IDX_SYSTEM_INTEGRATE_TO_MENU_2:
310 {
311 for (unsigned d = 0; d < 2; d++)
312 {
313 CShellDll &dll = _dlls[d];
314 if (buttonID == dll.ctrl && !dll.Path.IsEmpty())
315 dll.wasChanged = true;
316 }
317 break;
318 }
319 #endif
320
321 case IDX_SYSTEM_CASCADED_MENU: _cascaded_Changed = true; break;
322 case IDX_SYSTEM_ICON_IN_MENU: _menuIcons_Changed = true; break;
323 case IDX_EXTRACT_ELIM_DUP: _elimDup_Changed = true; break;
324
325 default:
326 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
327 }
328
329 Changed();
330 return true;
331}
332
333bool CMenuPage::OnNotify(UINT controlID, LPNMHDR lParam)
334{
335 if (lParam->hwndFrom == HWND(_listView))
336 {
337 switch (lParam->code)
338 {
339 case (LVN_ITEMCHANGED):
340 return OnItemChanged((const NMLISTVIEW *)lParam);
341 }
342 }
343 return CPropertyPage::OnNotify(controlID, lParam);
344}
345
346
347bool CMenuPage::OnItemChanged(const NMLISTVIEW *info)
348{
349 if (_initMode)
350 return true;
351 if ((info->uChanged & LVIF_STATE) != 0)
352 {
353 UINT oldState = info->uOldState & LVIS_STATEIMAGEMASK;
354 UINT newState = info->uNewState & LVIS_STATEIMAGEMASK;
355 if (oldState != newState)
356 {
357 _flags_Changed = true;
358 Changed();
359 }
360 }
361 return true;
362}
diff --git a/CPP/7zip/UI/FileManager/MenuPage.h b/CPP/7zip/UI/FileManager/MenuPage.h
new file mode 100644
index 0000000..3807d9d
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MenuPage.h
@@ -0,0 +1,52 @@
1// MenuPage.h
2
3#ifndef __MENU_PAGE_H
4#define __MENU_PAGE_H
5
6#include "../../../Windows/Control/PropertyPage.h"
7#include "../../../Windows/Control/ListView.h"
8
9struct CShellDll
10{
11 FString Path;
12 bool wasChanged;
13 bool prevValue;
14 int ctrl;
15 UInt32 wow;
16
17 CShellDll(): wasChanged (false), prevValue(false), ctrl(0), wow(0) {}
18};
19
20class CMenuPage: public NWindows::NControl::CPropertyPage
21{
22 bool _initMode;
23
24 bool _cascaded_Changed;
25 bool _menuIcons_Changed;
26 bool _elimDup_Changed;
27 bool _flags_Changed;
28
29 void Clear_MenuChanged()
30 {
31 _cascaded_Changed = false;
32 _menuIcons_Changed = false;
33 _elimDup_Changed = false;
34 _flags_Changed = false;
35 }
36
37 #ifndef UNDER_CE
38 CShellDll _dlls[2];
39 #endif
40
41 NWindows::NControl::CListView _listView;
42
43 virtual bool OnInit();
44 virtual void OnNotifyHelp();
45 virtual bool OnNotify(UINT controlID, LPNMHDR lParam);
46 virtual bool OnItemChanged(const NMLISTVIEW *info);
47 virtual LONG OnApply();
48 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
49public:
50};
51
52#endif
diff --git a/CPP/7zip/UI/FileManager/MenuPage.rc b/CPP/7zip/UI/FileManager/MenuPage.rc
new file mode 100644
index 0000000..fc21107
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MenuPage.rc
@@ -0,0 +1,24 @@
1#include "MenuPageRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 240
5#define yc 252
6
7IDD_MENU MY_PAGE
8#include "MenuPage2.rc"
9
10#ifdef UNDER_CE
11
12#undef m
13#undef xc
14#undef yc
15
16#define m 4
17#define xc (SMALL_PAGE_SIZE_X + 8)
18
19#define yc 112
20
21IDD_MENU_2 MY_PAGE
22#include "MenuPage2.rc"
23
24#endif
diff --git a/CPP/7zip/UI/FileManager/MenuPage2.rc b/CPP/7zip/UI/FileManager/MenuPage2.rc
new file mode 100644
index 0000000..af86226
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MenuPage2.rc
@@ -0,0 +1,17 @@
1#include "../GUI/ExtractDialogRes.h"
2
3#define y 82
4
5CAPTION "7-Zip"
6BEGIN
7 CONTROL "Integrate 7-Zip to shell context menu", IDX_SYSTEM_INTEGRATE_TO_MENU, MY_CHECKBOX, m, m, xc, 10
8 CONTROL "(32-bit)", IDX_SYSTEM_INTEGRATE_TO_MENU_2, MY_CHECKBOX, m, m + 14, xc, 10
9 CONTROL "Cascaded context menu", IDX_SYSTEM_CASCADED_MENU, MY_CHECKBOX, m, m + 28, xc, 10
10 CONTROL "Icons in context menu", IDX_SYSTEM_ICON_IN_MENU, MY_CHECKBOX, m, m + 42, xc, 10
11 CONTROL "Eliminate duplication of root folder", IDX_EXTRACT_ELIM_DUP, MY_CHECKBOX, m, m + 56, xc, 10
12
13 LTEXT "Context menu items:", IDT_SYSTEM_CONTEXT_MENU_ITEMS, m, m + 70, xc, 8
14 CONTROL "List", IDL_SYSTEM_OPTIONS, "SysListView32",
15 LVS_REPORT | LVS_SINGLESEL | LVS_NOCOLUMNHEADER | WS_BORDER | WS_TABSTOP,
16 m, m + y, xc, yc - y
17END
diff --git a/CPP/7zip/UI/FileManager/MenuPageRes.h b/CPP/7zip/UI/FileManager/MenuPageRes.h
new file mode 100644
index 0000000..ae0bf66
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MenuPageRes.h
@@ -0,0 +1,11 @@
1#define IDD_MENU 2300
2#define IDD_MENU_2 12300
3
4#define IDX_SYSTEM_INTEGRATE_TO_MENU 2301
5#define IDX_SYSTEM_CASCADED_MENU 2302
6#define IDT_SYSTEM_CONTEXT_MENU_ITEMS 2303
7#define IDX_SYSTEM_ICON_IN_MENU 2304
8
9#define IDX_SYSTEM_INTEGRATE_TO_MENU_2 2310
10
11#define IDL_SYSTEM_OPTIONS 100
diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.cpp b/CPP/7zip/UI/FileManager/MessagesDialog.cpp
new file mode 100644
index 0000000..4124827
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MessagesDialog.cpp
@@ -0,0 +1,76 @@
1// MessagesDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6
7#include "../../../Windows/ResourceString.h"
8
9#include "MessagesDialog.h"
10
11#include "LangUtils.h"
12
13#include "ProgressDialog2Res.h"
14
15using namespace NWindows;
16
17void CMessagesDialog::AddMessageDirect(LPCWSTR message)
18{
19 int i = _messageList.GetItemCount();
20 wchar_t sz[16];
21 ConvertUInt32ToString((UInt32)i, sz);
22 _messageList.InsertItem(i, sz);
23 _messageList.SetSubItem(i, 1, message);
24}
25
26void CMessagesDialog::AddMessage(LPCWSTR message)
27{
28 UString s = message;
29 while (!s.IsEmpty())
30 {
31 int pos = s.Find(L'\n');
32 if (pos < 0)
33 break;
34 AddMessageDirect(s.Left(pos));
35 s.DeleteFrontal(pos + 1);
36 }
37 AddMessageDirect(s);
38}
39
40bool CMessagesDialog::OnInit()
41{
42 #ifdef LANG
43 LangSetWindowText(*this, IDD_MESSAGES);
44 LangSetDlgItems(*this, NULL, 0);
45 SetItemText(IDOK, LangString(IDS_CLOSE));
46 #endif
47 _messageList.Attach(GetItem(IDL_MESSAGE));
48 _messageList.SetUnicodeFormat();
49
50 _messageList.InsertColumn(0, L"", 30);
51 _messageList.InsertColumn(1, LangString(IDS_MESSAGE), 600);
52
53 FOR_VECTOR (i, *Messages)
54 AddMessage((*Messages)[i]);
55
56 _messageList.SetColumnWidthAuto(0);
57 _messageList.SetColumnWidthAuto(1);
58 NormalizeSize();
59 return CModalDialog::OnInit();
60}
61
62bool CMessagesDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
63{
64 int mx, my;
65 GetMargins(8, mx, my);
66 int bx, by;
67 GetItemSizes(IDOK, bx, by);
68 int y = ySize - my - by;
69 int x = xSize - mx - bx;
70
71 InvalidateRect(NULL);
72
73 MoveItem(IDOK, x, y, bx, by);
74 _messageList.Move(mx, my, xSize - mx * 2, y - my * 2);
75 return false;
76}
diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.h b/CPP/7zip/UI/FileManager/MessagesDialog.h
new file mode 100644
index 0000000..5c017eb
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MessagesDialog.h
@@ -0,0 +1,25 @@
1// MessagesDialog.h
2
3#ifndef __MESSAGES_DIALOG_H
4#define __MESSAGES_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7#include "../../../Windows/Control/ListView.h"
8
9#include "MessagesDialogRes.h"
10
11class CMessagesDialog: public NWindows::NControl::CModalDialog
12{
13 NWindows::NControl::CListView _messageList;
14
15 void AddMessageDirect(LPCWSTR message);
16 void AddMessage(LPCWSTR message);
17 virtual bool OnInit();
18 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
19public:
20 const UStringVector *Messages;
21
22 INT_PTR Create(HWND parent = 0) { return CModalDialog::Create(IDD_MESSAGES, parent); }
23};
24
25#endif
diff --git a/CPP/7zip/UI/FileManager/MessagesDialog.rc b/CPP/7zip/UI/FileManager/MessagesDialog.rc
new file mode 100644
index 0000000..49b73e8
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MessagesDialog.rc
@@ -0,0 +1,14 @@
1#include "MessagesDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 440
5#define yc 160
6
7IDD_MESSAGES DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
8CAPTION "7-Zip: Diagnostic messages"
9{
10 DEFPUSHBUTTON "&Close", IDOK, bx, by, bxs, bys
11 CONTROL "List1", IDL_MESSAGE, "SysListView32",
12 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
13 m, m, xc, yc - bys - m
14}
diff --git a/CPP/7zip/UI/FileManager/MessagesDialogRes.h b/CPP/7zip/UI/FileManager/MessagesDialogRes.h
new file mode 100644
index 0000000..c8fffff
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MessagesDialogRes.h
@@ -0,0 +1,3 @@
1#define IDD_MESSAGES 6602
2#define IDS_MESSAGE 6603
3#define IDL_MESSAGE 100
diff --git a/CPP/7zip/UI/FileManager/Move.bmp b/CPP/7zip/UI/FileManager/Move.bmp
new file mode 100644
index 0000000..eb5f20f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Move.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Move2.bmp b/CPP/7zip/UI/FileManager/Move2.bmp
new file mode 100644
index 0000000..58679ef
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Move2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/MyCom2.h b/CPP/7zip/UI/FileManager/MyCom2.h
new file mode 100644
index 0000000..c45c215
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MyCom2.h
@@ -0,0 +1,47 @@
1// MyCom2.h
2
3#ifndef __MYCOM2_H
4#define __MYCOM2_H
5
6#include "../../../Common/MyCom.h"
7
8#define MY_ADDREF_RELEASE_MT \
9STDMETHOD_(ULONG, AddRef)() { InterlockedIncrement((LONG *)&__m_RefCount); return __m_RefCount; } \
10STDMETHOD_(ULONG, Release)() { InterlockedDecrement((LONG *)&__m_RefCount); if (__m_RefCount != 0) \
11 return __m_RefCount; delete this; return 0; }
12
13#define MY_UNKNOWN_IMP_SPEC_MT2(i1, i) \
14 MY_QUERYINTERFACE_BEGIN \
15 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
16 i \
17 MY_QUERYINTERFACE_END \
18 MY_ADDREF_RELEASE_MT
19
20
21#define MY_UNKNOWN_IMP1_MT(i) MY_UNKNOWN_IMP_SPEC_MT2( \
22 i, \
23 MY_QUERYINTERFACE_ENTRY(i) \
24 )
25
26#define MY_UNKNOWN_IMP2_MT(i1, i2) MY_UNKNOWN_IMP_SPEC_MT2( \
27 i1, \
28 MY_QUERYINTERFACE_ENTRY(i1) \
29 MY_QUERYINTERFACE_ENTRY(i2) \
30 )
31
32#define MY_UNKNOWN_IMP3_MT(i1, i2, i3) MY_UNKNOWN_IMP_SPEC_MT2( \
33 i1, \
34 MY_QUERYINTERFACE_ENTRY(i1) \
35 MY_QUERYINTERFACE_ENTRY(i2) \
36 MY_QUERYINTERFACE_ENTRY(i3) \
37 )
38
39#define MY_UNKNOWN_IMP4_MT(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC_MT2( \
40 i1, \
41 MY_QUERYINTERFACE_ENTRY(i1) \
42 MY_QUERYINTERFACE_ENTRY(i2) \
43 MY_QUERYINTERFACE_ENTRY(i3) \
44 MY_QUERYINTERFACE_ENTRY(i4) \
45 )
46
47#endif
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.cpp b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
new file mode 100644
index 0000000..d87dfe3
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.cpp
@@ -0,0 +1,833 @@
1// MyLoadMenu.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/Menu.h"
6#include "../../../Windows/TimeUtils.h"
7#include "../../../Windows/Control/Dialog.h"
8
9#include "../../PropID.h"
10
11#include "../Common/CompressCall.h"
12
13#include "AboutDialog.h"
14#include "App.h"
15#include "HelpUtils.h"
16#include "LangUtils.h"
17#include "MyLoadMenu.h"
18#include "RegistryUtils.h"
19
20#include "resource.h"
21
22using namespace NWindows;
23
24static const UINT kOpenBookmarkMenuID = 830;
25static const UINT kSetBookmarkMenuID = 810;
26static const UINT kMenuID_Time_Parent = 760;
27static const UINT kMenuID_Time = 761;
28
29extern HINSTANCE g_hInstance;
30
31#define kFMHelpTopic "FM/index.htm"
32
33extern void OptionsDialog(HWND hwndOwner, HINSTANCE hInstance);
34
35enum
36{
37 kMenuIndex_File = 0,
38 kMenuIndex_Edit,
39 kMenuIndex_View,
40 kMenuIndex_Bookmarks
41};
42
43static const UInt32 kTopMenuLangIDs[] = { 500, 501, 502, 503, 504, 505 };
44
45static const UInt32 kAddToFavoritesLangID = 800;
46static const UInt32 kToolbarsLangID = 733;
47
48static const CIDLangPair kIDLangPairs[] =
49{
50 { IDCLOSE, 557 },
51 { IDM_VIEW_ARANGE_BY_NAME, 1004 },
52 { IDM_VIEW_ARANGE_BY_TYPE, 1020 },
53 { IDM_VIEW_ARANGE_BY_DATE, 1012 },
54 { IDM_VIEW_ARANGE_BY_SIZE, 1007 }
55};
56
57static int FindLangItem(unsigned controlID)
58{
59 for (unsigned i = 0; i < ARRAY_SIZE(kIDLangPairs); i++)
60 if (kIDLangPairs[i].ControlID == controlID)
61 return i;
62 return -1;
63}
64
65static int GetSortControlID(PROPID propID)
66{
67 switch (propID)
68 {
69 case kpidName: return IDM_VIEW_ARANGE_BY_NAME;
70 case kpidExtension: return IDM_VIEW_ARANGE_BY_TYPE;
71 case kpidMTime: return IDM_VIEW_ARANGE_BY_DATE;
72 case kpidSize: return IDM_VIEW_ARANGE_BY_SIZE;
73 case kpidNoProperty: return IDM_VIEW_ARANGE_NO_SORT;
74 }
75 return -1;
76}
77
78/*
79static bool g_IsNew_fMask = true;
80
81class CInit_fMask
82{
83public:
84 CInit_fMask()
85 {
86 g_IsNew_fMask = false;
87 OSVERSIONINFO vi;
88 vi.dwOSVersionInfoSize = sizeof(vi);
89 if (::GetVersionEx(&vi))
90 {
91 g_IsNew_fMask = (vi.dwMajorVersion > 4 ||
92 (vi.dwMajorVersion == 4 && vi.dwMinorVersion > 0));
93 }
94 g_IsNew_fMask = false;
95 }
96} g_Init_fMask;
97
98// it's hack for supporting Windows NT
99// constants are from WinUser.h
100
101#if (WINVER < 0x0500)
102#define MIIM_STRING 0x00000040
103#define MIIM_BITMAP 0x00000080
104#define MIIM_FTYPE 0x00000100
105#endif
106
107static UINT Get_fMask_for_String()
108{
109 return g_IsNew_fMask ? MIIM_STRING : MIIM_TYPE;
110}
111
112static UINT Get_fMask_for_FType_and_String()
113{
114 return g_IsNew_fMask ? (MIIM_STRING | MIIM_FTYPE) : MIIM_TYPE;
115}
116*/
117
118static inline UINT Get_fMask_for_String() { return MIIM_TYPE; }
119static inline UINT Get_fMask_for_FType_and_String() { return MIIM_TYPE; }
120
121
122static void MyChangeMenu(HMENU menuLoc, int level, int menuIndex)
123{
124 CMenu menu;
125 menu.Attach(menuLoc);
126
127 for (unsigned i = 0;; i++)
128 {
129 CMenuItem item;
130 item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID;
131 item.fType = MFT_STRING;
132 if (!menu.GetItem(i, true, item))
133 break;
134 {
135 UString newString;
136 if (item.hSubMenu)
137 {
138 UInt32 langID = 0;
139 if (level == 1 && menuIndex == kMenuIndex_Bookmarks)
140 langID = kAddToFavoritesLangID;
141 else
142 {
143 MyChangeMenu(item.hSubMenu, level + 1, i);
144 if (level == 1 && menuIndex == kMenuIndex_View)
145 {
146 if (item.wID == kMenuID_Time_Parent || item.StringValue.IsPrefixedBy_Ascii_NoCase("20"))
147 continue;
148 else
149 langID = kToolbarsLangID;
150 }
151 else if (level == 0 && i < ARRAY_SIZE(kTopMenuLangIDs))
152 langID = kTopMenuLangIDs[i];
153 else
154 continue;
155 }
156
157 LangString_OnlyFromLangFile(langID, newString);
158
159 if (newString.IsEmpty())
160 continue;
161 }
162 else
163 {
164 if (item.IsSeparator())
165 continue;
166 int langPos = FindLangItem(item.wID);
167
168 // we don't need lang change for CRC items!!!
169
170 UInt32 langID = langPos >= 0 ? kIDLangPairs[langPos].LangID : item.wID;
171
172 if (langID == IDM_OPEN_INSIDE_ONE || langID == IDM_OPEN_INSIDE_PARSER)
173 {
174 LangString_OnlyFromLangFile(IDM_OPEN_INSIDE, newString);
175 if (newString.IsEmpty())
176 continue;
177 newString.Replace(L"&", L"");
178 int tabPos = newString.Find(L"\t");
179 if (tabPos >= 0)
180 newString.DeleteFrom(tabPos);
181 newString += (langID == IDM_OPEN_INSIDE_ONE ? " *" : " #");
182 }
183 else if (langID == IDM_BENCHMARK2)
184 {
185 LangString_OnlyFromLangFile(IDM_BENCHMARK, newString);
186 if (newString.IsEmpty())
187 continue;
188 newString.Replace(L"&", L"");
189 int tabPos = newString.Find(L"\t");
190 if (tabPos >= 0)
191 newString.DeleteFrom(tabPos);
192 newString += " 2";
193 }
194 else
195 LangString_OnlyFromLangFile(langID, newString);
196
197 if (newString.IsEmpty())
198 continue;
199
200 int tabPos = item.StringValue.ReverseFind(L'\t');
201 if (tabPos >= 0)
202 newString += item.StringValue.Ptr(tabPos);
203 }
204
205 {
206 item.StringValue = newString;
207 item.fMask = Get_fMask_for_String();
208 item.fType = MFT_STRING;
209 menu.SetItem(i, true, item);
210 }
211 }
212 }
213}
214
215static CMenu g_FileMenu;
216
217static struct CFileMenuDestroyer
218{
219 ~CFileMenuDestroyer() { if ((HMENU)g_FileMenu != 0) g_FileMenu.Destroy(); }
220} g_FileMenuDestroyer;
221
222
223static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec);
224
225static void CopyPopMenu_IfRequired(CMenuItem &item)
226{
227 if (item.hSubMenu)
228 {
229 CMenu popup;
230 popup.CreatePopup();
231 CopyMenu(item.hSubMenu, popup);
232 item.hSubMenu = popup;
233 }
234}
235
236static void CopyMenu(HMENU srcMenuSpec, HMENU destMenuSpec)
237{
238 CMenu srcMenu;
239 srcMenu.Attach(srcMenuSpec);
240 CMenu destMenu;
241 destMenu.Attach(destMenuSpec);
242 int startPos = 0;
243 for (int i = 0;; i++)
244 {
245 CMenuItem item;
246 item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
247 item.fType = MFT_STRING;
248
249 if (!srcMenu.GetItem(i, true, item))
250 break;
251
252 CopyPopMenu_IfRequired(item);
253 if (destMenu.InsertItem(startPos, true, item))
254 startPos++;
255 }
256}
257
258void MyLoadMenu()
259{
260 HMENU baseMenu;
261
262 #ifdef UNDER_CE
263
264 HMENU oldMenu = g_App._commandBar.GetMenu(0);
265 if (oldMenu)
266 ::DestroyMenu(oldMenu);
267 /* BOOL b = */ g_App._commandBar.InsertMenubar(g_hInstance, IDM_MENU, 0);
268 baseMenu = g_App._commandBar.GetMenu(0);
269 // if (startInit)
270 // SetIdsForSubMenes(baseMenu, 0, 0);
271 if (!g_LangID.IsEmpty())
272 MyChangeMenu(baseMenu, 0, 0);
273 g_App._commandBar.DrawMenuBar(0);
274
275 #else
276
277 HWND hWnd = g_HWND;
278 HMENU oldMenu = ::GetMenu(hWnd);
279 ::SetMenu(hWnd, ::LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_MENU)));
280 ::DestroyMenu(oldMenu);
281 baseMenu = ::GetMenu(hWnd);
282 // if (startInit)
283 // SetIdsForSubMenes(baseMenu, 0, 0);
284 if (!g_LangID.IsEmpty())
285 MyChangeMenu(baseMenu, 0, 0);
286 ::DrawMenuBar(hWnd);
287
288 #endif
289
290 if ((HMENU)g_FileMenu != 0)
291 g_FileMenu.Destroy();
292 g_FileMenu.CreatePopup();
293 CopyMenu(::GetSubMenu(baseMenu, 0), g_FileMenu);
294}
295
296void OnMenuActivating(HWND /* hWnd */, HMENU hMenu, int position)
297{
298 HMENU mainMenu =
299 #ifdef UNDER_CE
300 g_App._commandBar.GetMenu(0);
301 #else
302 ::GetMenu(g_HWND)
303 #endif
304 ;
305
306 if (::GetSubMenu(mainMenu, position) != hMenu)
307 return;
308
309 if (position == kMenuIndex_File)
310 {
311 CMenu menu;
312 menu.Attach(hMenu);
313 menu.RemoveAllItems();
314 g_App.GetFocusedPanel().CreateFileMenu(hMenu);
315 }
316 else if (position == kMenuIndex_Edit)
317 {
318 /*
319 CMenu menu;
320 menu.Attach(hMenu);
321 menu.EnableItem(IDM_EDIT_CUT, MF_ENABLED);
322 menu.EnableItem(IDM_EDIT_COPY, MF_ENABLED);
323 menu.EnableItem(IDM_EDIT_PASTE, IsClipboardFormatAvailableHDROP() ? MF_ENABLED : MF_GRAYED);
324 */
325 }
326 else if (position == kMenuIndex_View)
327 {
328 // View;
329 CMenu menu;
330 menu.Attach(hMenu);
331 menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,
332 IDM_VIEW_LARGE_ICONS + g_App.GetListViewMode(), MF_BYCOMMAND);
333
334 menu.CheckRadioItem(IDM_VIEW_ARANGE_BY_NAME, IDM_VIEW_ARANGE_NO_SORT,
335 GetSortControlID(g_App.GetSortID()), MF_BYCOMMAND);
336
337 menu.CheckItemByID(IDM_VIEW_TWO_PANELS, g_App.NumPanels == 2);
338 menu.CheckItemByID(IDM_VIEW_FLAT_VIEW, g_App.GetFlatMode());
339 menu.CheckItemByID(IDM_VIEW_ARCHIVE_TOOLBAR, g_App.ShowArchiveToolbar);
340 menu.CheckItemByID(IDM_VIEW_STANDARD_TOOLBAR, g_App.ShowStandardToolbar);
341 menu.CheckItemByID(IDM_VIEW_TOOLBARS_LARGE_BUTTONS, g_App.LargeButtons);
342 menu.CheckItemByID(IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT, g_App.ShowButtonsLables);
343 menu.CheckItemByID(IDM_VIEW_AUTO_REFRESH, g_App.Get_AutoRefresh_Mode());
344 // menu.CheckItemByID(IDM_VIEW_SHOW_STREAMS, g_App.Get_ShowNtfsStrems_Mode());
345 // menu.CheckItemByID(IDM_VIEW_SHOW_DELETED, g_App.ShowDeletedFiles);
346
347 for (int i = 0;; i++)
348 {
349 CMenuItem item;
350 item.fMask = Get_fMask_for_String() | MIIM_SUBMENU | MIIM_ID;
351 item.fType = MFT_STRING;
352 if (!menu.GetItem(i, true, item))
353 break;
354 if (item.hSubMenu && (item.wID == kMenuID_Time_Parent
355 || item.StringValue.IsPrefixedBy_Ascii_NoCase("20")
356 ))
357 {
358 FILETIME ft;
359 NTime::GetCurUtcFileTime(ft);
360
361 {
362 wchar_t s[64];
363 s[0] = 0;
364 if (ConvertUtcFileTimeToString(ft, s, kTimestampPrintLevel_DAY))
365 item.StringValue = s;
366 }
367
368 item.fMask = Get_fMask_for_String() | MIIM_ID;
369 item.fType = MFT_STRING;
370 item.wID = kMenuID_Time_Parent;
371 menu.SetItem(i, true, item);
372
373 CMenu subMenu;
374 subMenu.Attach(menu.GetSubMenu(i));
375 subMenu.RemoveAllItems();
376
377 const int k_TimeLevels[] =
378 {
379 kTimestampPrintLevel_DAY,
380 kTimestampPrintLevel_MIN,
381 kTimestampPrintLevel_SEC,
382 // 1,2,3,4,5,6,
383 kTimestampPrintLevel_NTFS
384 };
385
386 unsigned last = kMenuID_Time;
387 unsigned selectedCommand = 0;
388 g_App._timestampLevels.Clear();
389 unsigned id = kMenuID_Time;
390
391 for (unsigned k = 0; k < ARRAY_SIZE(k_TimeLevels); k++)
392 {
393 wchar_t s[64];
394 s[0] = 0;
395 int timestampLevel = k_TimeLevels[k];
396 if (ConvertUtcFileTimeToString(ft, s, timestampLevel))
397 {
398 if (subMenu.AppendItem(MF_STRING, id, s))
399 {
400 last = id;
401 g_App._timestampLevels.Add(timestampLevel);
402 if (g_App.GetTimestampLevel() == timestampLevel)
403 selectedCommand = id;
404 id++;
405 }
406 }
407 }
408 if (selectedCommand != 0)
409 menu.CheckRadioItem(kMenuID_Time, last, selectedCommand, MF_BYCOMMAND);
410 }
411 }
412 }
413 else if (position == kMenuIndex_Bookmarks)
414 {
415 CMenu menu;
416 menu.Attach(hMenu);
417
418 CMenu subMenu;
419 subMenu.Attach(menu.GetSubMenu(0));
420 subMenu.RemoveAllItems();
421 int i;
422
423 for (i = 0; i < 10; i++)
424 {
425 UString s = LangString(IDS_BOOKMARK);
426 s.Add_Space();
427 char c = (char)(L'0' + i);
428 s += c;
429 s += "\tAlt+Shift+";
430 s += c;
431 subMenu.AppendItem(MF_STRING, kSetBookmarkMenuID + i, s);
432 }
433
434 menu.RemoveAllItemsFrom(2);
435
436 for (i = 0; i < 10; i++)
437 {
438 UString s = g_App.AppState.FastFolders.GetString(i);
439 const int kMaxSize = 100;
440 const int kFirstPartSize = kMaxSize / 2;
441 if (s.Len() > kMaxSize)
442 {
443 s.Delete(kFirstPartSize, s.Len() - kMaxSize);
444 s.Insert(kFirstPartSize, L" ... ");
445 }
446 if (s.IsEmpty())
447 s = '-';
448 s += "\tAlt+";
449 s += (char)('0' + i);
450 menu.AppendItem(MF_STRING, kOpenBookmarkMenuID + i, s);
451 }
452 }
453}
454
455/*
456It doesn't help
457void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id)
458{
459 if (::GetSubMenu(::GetMenu(g_HWND), 0) != hMenu)
460 return;
461}
462*/
463
464static const unsigned g_Zvc_IDs[] =
465{
466 IDM_VER_EDIT,
467 IDM_VER_COMMIT,
468 IDM_VER_REVERT,
469 IDM_VER_DIFF
470};
471
472static const char * const g_Zvc_Strings[] =
473{
474 "Ver Edit (&1)"
475 , "Ver Commit"
476 , "Ver Revert"
477 , "Ver Diff (&0)"
478};
479
480void CFileMenu::Load(HMENU hMenu, unsigned startPos)
481{
482 CMenu destMenu;
483 destMenu.Attach(hMenu);
484
485 UString diffPath;
486 ReadRegDiff(diffPath);
487
488 unsigned numRealItems = startPos;
489
490 const bool isBigScreen = NControl::IsDialogSizeOK(40, 200, g_HWND);
491
492 for (unsigned i = 0;; i++)
493 {
494 CMenuItem item;
495
496 item.fMask = MIIM_SUBMENU | MIIM_STATE | MIIM_ID | Get_fMask_for_FType_and_String();
497 item.fType = MFT_STRING;
498
499 if (!g_FileMenu.GetItem(i, true, item))
500 break;
501
502 {
503 if (!programMenu && item.wID == IDCLOSE)
504 continue;
505
506 if (item.wID == IDM_DIFF && diffPath.IsEmpty())
507 continue;
508
509 if (item.wID == IDM_OPEN_INSIDE_ONE || item.wID == IDM_OPEN_INSIDE_PARSER)
510 {
511 // We use diff as "super mode" marker for additional commands.
512 /*
513 if (diffPath.IsEmpty())
514 continue;
515 */
516 }
517
518 if (item.wID == IDM_BENCHMARK2)
519 {
520 // We use diff as "super mode" marker for additional commands.
521 if (diffPath.IsEmpty())
522 continue;
523 }
524
525 bool isOneFsFile = (isFsFolder && numItems == 1 && allAreFiles);
526 bool disable = (!isOneFsFile && (item.wID == IDM_SPLIT || item.wID == IDM_COMBINE));
527
528 if (readOnly)
529 {
530 switch (item.wID)
531 {
532 case IDM_RENAME:
533 case IDM_MOVE_TO:
534 case IDM_DELETE:
535 case IDM_COMMENT:
536 case IDM_CREATE_FOLDER:
537 case IDM_CREATE_FILE:
538 disable = true;
539 }
540 }
541
542 if (isHashFolder)
543 {
544 switch (item.wID)
545 {
546 case IDM_OPEN:
547 case IDM_OPEN_INSIDE:
548 case IDM_OPEN_INSIDE_ONE:
549 case IDM_OPEN_INSIDE_PARSER:
550 case IDM_OPEN_OUTSIDE:
551 case IDM_FILE_VIEW:
552 case IDM_FILE_EDIT:
553 // case IDM_RENAME:
554 case IDM_COPY_TO:
555 case IDM_MOVE_TO:
556 // case IDM_DELETE:
557 case IDM_COMMENT:
558 case IDM_CREATE_FOLDER:
559 case IDM_CREATE_FILE:
560 case IDM_LINK:
561 case IDM_DIFF:
562 disable = true;
563 }
564 }
565
566
567 if (item.wID == IDM_LINK && numItems != 1)
568 disable = true;
569
570 if (item.wID == IDM_ALT_STREAMS)
571 disable = !isAltStreamsSupported;
572
573 if (!isBigScreen && (disable || item.IsSeparator()))
574 continue;
575
576 CopyPopMenu_IfRequired(item);
577 if (destMenu.InsertItem(startPos, true, item))
578 {
579 if (disable)
580 destMenu.EnableItem(startPos, MF_BYPOSITION | MF_GRAYED);
581 startPos++;
582 }
583
584 if (!item.IsSeparator())
585 numRealItems = startPos;
586 }
587 }
588
589 UString vercPath;
590 if (!diffPath.IsEmpty() && isFsFolder && allAreFiles && numItems == 1)
591 ReadReg_VerCtrlPath(vercPath);
592
593 if (!vercPath.IsEmpty())
594 {
595 NFile::NFind::CFileInfo fi;
596 if (fi.Find(FilePath) && fi.Size < ((UInt32)1 << 31) && !fi.IsDir())
597 {
598 for (unsigned k = 0; k < ARRAY_SIZE(g_Zvc_IDs); k++)
599 {
600 const unsigned id = g_Zvc_IDs[k];
601 if (fi.IsReadOnly())
602 {
603 if (id == IDM_VER_COMMIT ||
604 id == IDM_VER_REVERT ||
605 id == IDM_VER_DIFF)
606 continue;
607 }
608 else
609 {
610 if (id == IDM_VER_EDIT)
611 continue;
612 }
613
614 CMenuItem item;
615 UString s (g_Zvc_Strings[k]);
616 if (destMenu.AppendItem(MF_STRING, id, s))
617 {
618 startPos++;
619 numRealItems = startPos;
620 }
621 }
622 }
623 }
624
625 destMenu.RemoveAllItemsFrom(numRealItems);
626}
627
628bool ExecuteFileCommand(unsigned id)
629{
630 if (id >= kMenuCmdID_Plugin_Start)
631 {
632 g_App.GetFocusedPanel().InvokePluginCommand(id);
633 g_App.GetFocusedPanel()._sevenZipContextMenu.Release();
634 g_App.GetFocusedPanel()._systemContextMenu.Release();
635 return true;
636 }
637
638 switch (id)
639 {
640 // File
641 case IDM_OPEN: g_App.OpenItem(); break;
642
643 case IDM_OPEN_INSIDE: g_App.OpenItemInside(NULL); break;
644 case IDM_OPEN_INSIDE_ONE: g_App.OpenItemInside(L"*"); break;
645 case IDM_OPEN_INSIDE_PARSER: g_App.OpenItemInside(L"#"); break;
646
647 case IDM_OPEN_OUTSIDE: g_App.OpenItemOutside(); break;
648 case IDM_FILE_VIEW: g_App.EditItem(false); break;
649 case IDM_FILE_EDIT: g_App.EditItem(true); break;
650 case IDM_RENAME: g_App.Rename(); break;
651 case IDM_COPY_TO: g_App.CopyTo(); break;
652 case IDM_MOVE_TO: g_App.MoveTo(); break;
653 case IDM_DELETE: g_App.Delete(!IsKeyDown(VK_SHIFT)); break;
654
655 case IDM_HASH_ALL: g_App.CalculateCrc("*"); break;
656 case IDM_CRC32: g_App.CalculateCrc("CRC32"); break;
657 case IDM_CRC64: g_App.CalculateCrc("CRC64"); break;
658 case IDM_SHA1: g_App.CalculateCrc("SHA1"); break;
659 case IDM_SHA256: g_App.CalculateCrc("SHA256"); break;
660
661 case IDM_DIFF: g_App.DiffFiles(); break;
662
663 case IDM_VER_EDIT:
664 case IDM_VER_COMMIT:
665 case IDM_VER_REVERT:
666 case IDM_VER_DIFF:
667 g_App.VerCtrl(id); break;
668
669 case IDM_SPLIT: g_App.Split(); break;
670 case IDM_COMBINE: g_App.Combine(); break;
671 case IDM_PROPERTIES: g_App.Properties(); break;
672 case IDM_COMMENT: g_App.Comment(); break;
673 case IDM_CREATE_FOLDER: g_App.CreateFolder(); break;
674 case IDM_CREATE_FILE: g_App.CreateFile(); break;
675 #ifndef UNDER_CE
676 case IDM_LINK: g_App.Link(); break;
677 case IDM_ALT_STREAMS: g_App.OpenAltStreams(); break;
678 #endif
679 default: return false;
680 }
681 return true;
682}
683
684static void MyBenchmark(bool totalMode)
685{
686 CPanel::CDisableTimerProcessing disableTimerProcessing1(g_App.Panels[0]);
687 CPanel::CDisableTimerProcessing disableTimerProcessing2(g_App.Panels[1]);
688 Benchmark(totalMode);
689}
690
691bool OnMenuCommand(HWND hWnd, unsigned id)
692{
693 if (ExecuteFileCommand(id))
694 return true;
695
696 switch (id)
697 {
698 // File
699 case IDCLOSE:
700 SendMessage(hWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), (LPARAM)hWnd);
701 g_ExitEventLauncher.Exit(false);
702 SendMessage(hWnd, WM_CLOSE, 0, 0);
703 break;
704
705 // Edit
706 /*
707 case IDM_EDIT_CUT:
708 g_App.EditCut();
709 break;
710 case IDM_EDIT_COPY:
711 g_App.EditCopy();
712 break;
713 case IDM_EDIT_PASTE:
714 g_App.EditPaste();
715 break;
716 */
717 case IDM_SELECT_ALL:
718 g_App.SelectAll(true);
719 g_App.Refresh_StatusBar();
720 break;
721 case IDM_DESELECT_ALL:
722 g_App.SelectAll(false);
723 g_App.Refresh_StatusBar();
724 break;
725 case IDM_INVERT_SELECTION:
726 g_App.InvertSelection();
727 g_App.Refresh_StatusBar();
728 break;
729 case IDM_SELECT:
730 g_App.SelectSpec(true);
731 g_App.Refresh_StatusBar();
732 break;
733 case IDM_DESELECT:
734 g_App.SelectSpec(false);
735 g_App.Refresh_StatusBar();
736 break;
737 case IDM_SELECT_BY_TYPE:
738 g_App.SelectByType(true);
739 g_App.Refresh_StatusBar();
740 break;
741 case IDM_DESELECT_BY_TYPE:
742 g_App.SelectByType(false);
743 g_App.Refresh_StatusBar();
744 break;
745
746 //View
747 case IDM_VIEW_LARGE_ICONS:
748 case IDM_VIEW_SMALL_ICONS:
749 case IDM_VIEW_LIST:
750 case IDM_VIEW_DETAILS:
751 {
752 UINT index = id - IDM_VIEW_LARGE_ICONS;
753 if (index < 4)
754 {
755 g_App.SetListViewMode(index);
756 /*
757 CMenu menu;
758 menu.Attach(::GetSubMenu(::GetMenu(hWnd), kMenuIndex_View));
759 menu.CheckRadioItem(IDM_VIEW_LARGE_ICONS, IDM_VIEW_DETAILS,
760 id, MF_BYCOMMAND);
761 */
762 }
763 break;
764 }
765 case IDM_VIEW_ARANGE_BY_NAME: g_App.SortItemsWithPropID(kpidName); break;
766 case IDM_VIEW_ARANGE_BY_TYPE: g_App.SortItemsWithPropID(kpidExtension); break;
767 case IDM_VIEW_ARANGE_BY_DATE: g_App.SortItemsWithPropID(kpidMTime); break;
768 case IDM_VIEW_ARANGE_BY_SIZE: g_App.SortItemsWithPropID(kpidSize); break;
769 case IDM_VIEW_ARANGE_NO_SORT: g_App.SortItemsWithPropID(kpidNoProperty); break;
770
771 case IDM_OPEN_ROOT_FOLDER: g_App.OpenRootFolder(); break;
772 case IDM_OPEN_PARENT_FOLDER: g_App.OpenParentFolder(); break;
773 case IDM_FOLDERS_HISTORY: g_App.FoldersHistory(); break;
774 case IDM_VIEW_FLAT_VIEW: g_App.ChangeFlatMode(); break;
775 case IDM_VIEW_REFRESH: g_App.RefreshView(); break;
776 case IDM_VIEW_AUTO_REFRESH: g_App.Change_AutoRefresh_Mode(); break;
777
778 // case IDM_VIEW_SHOW_STREAMS: g_App.Change_ShowNtfsStrems_Mode(); break;
779 /*
780 case IDM_VIEW_SHOW_DELETED:
781 {
782 g_App.Change_ShowDeleted();
783 bool isChecked = g_App.ShowDeletedFiles;
784 Save_ShowDeleted(isChecked);
785 }
786 */
787
788 case IDM_VIEW_TWO_PANELS: g_App.SwitchOnOffOnePanel(); break;
789 case IDM_VIEW_STANDARD_TOOLBAR: g_App.SwitchStandardToolbar(); break;
790 case IDM_VIEW_ARCHIVE_TOOLBAR: g_App.SwitchArchiveToolbar(); break;
791
792 case IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT: g_App.SwitchButtonsLables(); break;
793 case IDM_VIEW_TOOLBARS_LARGE_BUTTONS: g_App.SwitchLargeButtons(); break;
794
795 // Tools
796 case IDM_OPTIONS: OptionsDialog(hWnd, g_hInstance); break;
797
798 case IDM_BENCHMARK: MyBenchmark(false); break;
799 case IDM_BENCHMARK2: MyBenchmark(true); break;
800
801 // Help
802 case IDM_HELP_CONTENTS:
803 ShowHelpWindow(kFMHelpTopic);
804 break;
805 case IDM_ABOUT:
806 {
807 CAboutDialog dialog;
808 dialog.Create(hWnd);
809 break;
810 }
811 default:
812 {
813 if (id >= kOpenBookmarkMenuID && id <= kOpenBookmarkMenuID + 9)
814 {
815 g_App.OpenBookmark(id - kOpenBookmarkMenuID);
816 return true;
817 }
818 else if (id >= kSetBookmarkMenuID && id <= kSetBookmarkMenuID + 9)
819 {
820 g_App.SetBookmark(id - kSetBookmarkMenuID);
821 return true;
822 }
823 else if (id >= kMenuID_Time && (unsigned)id <= kMenuID_Time + g_App._timestampLevels.Size())
824 {
825 unsigned index = id - kMenuID_Time;
826 g_App.SetTimestampLevel(g_App._timestampLevels[index]);
827 return true;
828 }
829 return false;
830 }
831 }
832 return true;
833}
diff --git a/CPP/7zip/UI/FileManager/MyLoadMenu.h b/CPP/7zip/UI/FileManager/MyLoadMenu.h
new file mode 100644
index 0000000..764bf7c
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MyLoadMenu.h
@@ -0,0 +1,40 @@
1// MyLoadMenu.h
2
3#ifndef __MY_LOAD_MENU_H
4#define __MY_LOAD_MENU_H
5
6void OnMenuActivating(HWND hWnd, HMENU hMenu, int position);
7// void OnMenuUnActivating(HWND hWnd, HMENU hMenu, int id);
8// void OnMenuUnActivating(HWND hWnd);
9
10bool OnMenuCommand(HWND hWnd, unsigned id);
11void MyLoadMenu();
12
13struct CFileMenu
14{
15 bool programMenu;
16 bool readOnly;
17 bool isHashFolder;
18 bool isFsFolder;
19 bool allAreFiles;
20 bool isAltStreamsSupported;
21 int numItems;
22
23 FString FilePath;
24
25 CFileMenu():
26 programMenu(false),
27 readOnly(false),
28 isHashFolder(false),
29 isFsFolder(false),
30 allAreFiles(false),
31 isAltStreamsSupported(true),
32 numItems(0)
33 {}
34
35 void Load(HMENU hMenu, unsigned startPos);
36};
37
38bool ExecuteFileCommand(unsigned id);
39
40#endif
diff --git a/CPP/7zip/UI/FileManager/MyWindowsNew.h b/CPP/7zip/UI/FileManager/MyWindowsNew.h
new file mode 100644
index 0000000..48a9535
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/MyWindowsNew.h
@@ -0,0 +1,76 @@
1// MyWindowsNew.h
2
3#ifndef __MY_WINDOWS_NEW_H
4#define __MY_WINDOWS_NEW_H
5
6#ifdef _MSC_VER
7
8#include <ShObjIdl.h>
9
10#ifndef __ITaskbarList3_INTERFACE_DEFINED__
11#define __ITaskbarList3_INTERFACE_DEFINED__
12
13typedef enum THUMBBUTTONFLAGS
14{
15 THBF_ENABLED = 0,
16 THBF_DISABLED = 0x1,
17 THBF_DISMISSONCLICK = 0x2,
18 THBF_NOBACKGROUND = 0x4,
19 THBF_HIDDEN = 0x8,
20 THBF_NONINTERACTIVE = 0x10
21} THUMBBUTTONFLAGS;
22
23typedef enum THUMBBUTTONMASK
24{
25 THB_BITMAP = 0x1,
26 THB_ICON = 0x2,
27 THB_TOOLTIP = 0x4,
28 THB_FLAGS = 0x8
29} THUMBBUTTONMASK;
30
31// #include <pshpack8.h>
32
33typedef struct THUMBBUTTON
34{
35 THUMBBUTTONMASK dwMask;
36 UINT iId;
37 UINT iBitmap;
38 HICON hIcon;
39 WCHAR szTip[260];
40 THUMBBUTTONFLAGS dwFlags;
41} THUMBBUTTON;
42
43typedef struct THUMBBUTTON *LPTHUMBBUTTON;
44
45typedef enum TBPFLAG
46{
47 TBPF_NOPROGRESS = 0,
48 TBPF_INDETERMINATE = 0x1,
49 TBPF_NORMAL = 0x2,
50 TBPF_ERROR = 0x4,
51 TBPF_PAUSED = 0x8
52} TBPFLAG;
53
54DEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF);
55
56struct ITaskbarList3: public ITaskbarList2
57{
58 STDMETHOD(SetProgressValue)(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) = 0;
59 STDMETHOD(SetProgressState)(HWND hwnd, TBPFLAG tbpFlags) = 0;
60 STDMETHOD(RegisterTab)(HWND hwndTab, HWND hwndMDI) = 0;
61 STDMETHOD(UnregisterTab)(HWND hwndTab) = 0;
62 STDMETHOD(SetTabOrder)(HWND hwndTab, HWND hwndInsertBefore) = 0;
63 STDMETHOD(SetTabActive)(HWND hwndTab, HWND hwndMDI, DWORD dwReserved) = 0;
64 STDMETHOD(ThumbBarAddButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;
65 STDMETHOD(ThumbBarUpdateButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;
66 STDMETHOD(ThumbBarSetImageList)(HWND hwnd, HIMAGELIST himl) = 0;
67 STDMETHOD(SetOverlayIcon)(HWND hwnd, HICON hIcon, LPCWSTR pszDescription) = 0;
68 STDMETHOD(SetThumbnailTooltip)(HWND hwnd, LPCWSTR pszTip) = 0;
69 STDMETHOD(SetThumbnailClip)(HWND hwnd, RECT *prcClip) = 0;
70};
71
72#endif
73
74#endif
75
76#endif
diff --git a/CPP/7zip/UI/FileManager/NetFolder.cpp b/CPP/7zip/UI/FileManager/NetFolder.cpp
new file mode 100644
index 0000000..a941e73
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/NetFolder.cpp
@@ -0,0 +1,281 @@
1// NetFolder.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/PropVariant.h"
6
7#include "../../PropID.h"
8
9#include "FSFolder.h"
10#include "NetFolder.h"
11#include "SysIconUtils.h"
12
13using namespace NWindows;
14using namespace NNet;
15
16static const Byte kProps[] =
17{
18 kpidName,
19 kpidLocalName,
20 kpidComment,
21 kpidProvider
22};
23
24void CNetFolder::Init(const UString &path)
25{
26 /*
27 if (path.Len() > 2)
28 {
29 if (path[0] == L'\\' && path[1] == L'\\')
30 {
31 CResource netResource;
32 netResource.RemoteName = GetSystemString(path.Left(path.Len() - 1));
33 netResource.Scope = RESOURCE_GLOBALNET;
34 netResource.Type = RESOURCETYPE_DISK;
35 netResource.DisplayType = RESOURCEDISPLAYTYPE_SERVER;
36 netResource.Usage = RESOURCEUSAGE_CONTAINER;
37 Init(&netResource, 0, path);
38 return;
39 }
40 }
41 Init(0, 0 , L"");
42 */
43 CResourceW resource;
44 resource.RemoteNameIsDefined = true;
45 if (!path.IsEmpty())
46 resource.RemoteName.SetFrom(path, path.Len() - 1);
47 resource.ProviderIsDefined = false;
48 resource.LocalNameIsDefined = false;
49 resource.CommentIsDefined = false;
50 resource.Type = RESOURCETYPE_DISK;
51 resource.Scope = RESOURCE_GLOBALNET;
52 resource.Usage = 0;
53 resource.DisplayType = 0;
54 CResourceW destResource;
55 UString systemPathPart;
56 DWORD result = GetResourceInformation(resource, destResource, systemPathPart);
57 if (result == NO_ERROR)
58 Init(&destResource, 0, path);
59 else
60 Init(0, 0 , L"");
61 return;
62}
63
64void CNetFolder::Init(const NWindows::NNet::CResourceW *netResource,
65 IFolderFolder *parentFolder, const UString &path)
66{
67 _path = path;
68 if (netResource == 0)
69 _netResourcePointer = 0;
70 else
71 {
72 _netResource = *netResource;
73 _netResourcePointer = &_netResource;
74
75 // if (_netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)
76 _path = _netResource.RemoteName;
77
78 /* WinXP-64: When we move UP from Network share without _parentFolder chain,
79 we can get empty _netResource.RemoteName. Do we need to use Provider there ? */
80 if (_path.IsEmpty())
81 _path = _netResource.Provider;
82
83 if (!_path.IsEmpty())
84 _path.Add_PathSepar();
85 }
86 _parentFolder = parentFolder;
87}
88
89STDMETHODIMP CNetFolder::LoadItems()
90{
91 _items.Clear();
92 CEnum enumerator;
93
94 for (;;)
95 {
96 DWORD result = enumerator.Open(
97 RESOURCE_GLOBALNET,
98 RESOURCETYPE_DISK,
99 0, // enumerate all resources
100 _netResourcePointer
101 );
102 if (result == NO_ERROR)
103 break;
104 if (result != ERROR_ACCESS_DENIED)
105 return result;
106 if (_netResourcePointer != 0)
107 result = AddConnection2(_netResource,
108 0, 0, CONNECT_INTERACTIVE);
109 if (result != NO_ERROR)
110 return result;
111 }
112
113 for (;;)
114 {
115 CResourceEx resource;
116 DWORD result = enumerator.Next(resource);
117 if (result == NO_ERROR)
118 {
119 if (!resource.RemoteNameIsDefined) // For Win 98, I don't know what's wrong
120 resource.RemoteName = resource.Comment;
121 resource.Name = resource.RemoteName;
122 int pos = resource.Name.ReverseFind_PathSepar();
123 if (pos >= 0)
124 {
125 // _path = resource.Name.Left(pos + 1);
126 resource.Name.DeleteFrontal(pos + 1);
127 }
128 _items.Add(resource);
129 }
130 else if (result == ERROR_NO_MORE_ITEMS)
131 break;
132 else
133 return result;
134 }
135
136 /*
137 It's too slow for some systems.
138 if (_netResourcePointer && _netResource.DisplayType == RESOURCEDISPLAYTYPE_SERVER)
139 {
140 for (char c = 'a'; c <= 'z'; c++)
141 {
142 CResourceEx resource;
143 resource.Name = UString(wchar_t(c)) + L'$';
144 resource.RemoteNameIsDefined = true;
145 resource.RemoteName = _path + resource.Name;
146
147 NFile::NFind::CFindFile findFile;
148 NFile::NFind::CFileInfo fileInfo;
149 if (!findFile.FindFirst(us2fs(resource.RemoteName) + FString(FCHAR_PATH_SEPARATOR) + FCHAR_ANY_MASK, fileInfo))
150 continue;
151 resource.Usage = RESOURCEUSAGE_CONNECTABLE;
152 resource.LocalNameIsDefined = false;
153 resource.CommentIsDefined = false;
154 resource.ProviderIsDefined = false;
155 _items.Add(resource);
156 }
157 }
158 */
159 return S_OK;
160}
161
162
163STDMETHODIMP CNetFolder::GetNumberOfItems(UInt32 *numItems)
164{
165 *numItems = _items.Size();
166 return S_OK;
167}
168
169STDMETHODIMP CNetFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
170{
171 NCOM::CPropVariant prop;
172 const CResourceEx &item = _items[itemIndex];
173 switch (propID)
174 {
175 case kpidIsDir: prop = true; break;
176 case kpidName:
177 // if (item.RemoteNameIsDefined)
178 prop = item.Name;
179 break;
180 case kpidLocalName: if (item.LocalNameIsDefined) prop = item.LocalName; break;
181 case kpidComment: if (item.CommentIsDefined) prop = item.Comment; break;
182 case kpidProvider: if (item.ProviderIsDefined) prop = item.Provider; break;
183 }
184 prop.Detach(value);
185 return S_OK;
186}
187
188STDMETHODIMP CNetFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
189{
190 *resultFolder = 0;
191 const CResourceEx &resource = _items[index];
192 if (resource.Usage == RESOURCEUSAGE_CONNECTABLE ||
193 resource.DisplayType == RESOURCEDISPLAYTYPE_SHARE)
194 {
195 NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
196 CMyComPtr<IFolderFolder> subFolder = fsFolderSpec;
197 RINOK(fsFolderSpec->Init(us2fs(resource.RemoteName + WCHAR_PATH_SEPARATOR))); // , this
198 *resultFolder = subFolder.Detach();
199 }
200 else
201 {
202 CNetFolder *netFolder = new CNetFolder;
203 CMyComPtr<IFolderFolder> subFolder = netFolder;
204 netFolder->Init(&resource, this, resource.Name + WCHAR_PATH_SEPARATOR);
205 *resultFolder = subFolder.Detach();
206 }
207 return S_OK;
208}
209
210STDMETHODIMP CNetFolder::BindToFolder(const wchar_t * /* name */, IFolderFolder ** /* resultFolder */)
211{
212 return E_NOTIMPL;
213}
214
215STDMETHODIMP CNetFolder::BindToParentFolder(IFolderFolder **resultFolder)
216{
217 *resultFolder = 0;
218 if (_parentFolder)
219 {
220 CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
221 *resultFolder = parentFolder.Detach();
222 return S_OK;
223 }
224 if (_netResourcePointer != 0)
225 {
226 CResourceW resourceParent;
227 DWORD result = GetResourceParent(_netResource, resourceParent);
228 if (result != NO_ERROR)
229 return result;
230 if (!_netResource.RemoteNameIsDefined)
231 return S_OK;
232
233 CNetFolder *netFolder = new CNetFolder;
234 CMyComPtr<IFolderFolder> subFolder = netFolder;
235 netFolder->Init(&resourceParent, 0, WSTRING_PATH_SEPARATOR);
236 *resultFolder = subFolder.Detach();
237 }
238 return S_OK;
239}
240
241IMP_IFolderFolder_Props(CNetFolder)
242
243STDMETHODIMP CNetFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
244{
245 NWindows::NCOM::CPropVariant prop;
246 switch (propID)
247 {
248 case kpidType: prop = "NetFolder"; break;
249 case kpidPath: prop = _path; break;
250 }
251 prop.Detach(value);
252 return S_OK;
253}
254
255STDMETHODIMP CNetFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
256{
257 if (index >= (UInt32)_items.Size())
258 return E_INVALIDARG;
259 *iconIndex = 0;
260 const CResourceW &resource = _items[index];
261 int iconIndexTemp;
262 if (resource.DisplayType == RESOURCEDISPLAYTYPE_SERVER ||
263 resource.Usage == RESOURCEUSAGE_CONNECTABLE)
264 {
265 if (GetRealIconIndex(us2fs(resource.RemoteName), 0, iconIndexTemp))
266 {
267 *iconIndex = iconIndexTemp;
268 return S_OK;
269 }
270 }
271 else
272 {
273 if (GetRealIconIndex(FTEXT(""), FILE_ATTRIBUTE_DIRECTORY, iconIndexTemp))
274 {
275 *iconIndex = iconIndexTemp;
276 return S_OK;
277 }
278 // *anIconIndex = GetRealIconIndex(0, L"\\\\HOME");
279 }
280 return GetLastError();
281}
diff --git a/CPP/7zip/UI/FileManager/NetFolder.h b/CPP/7zip/UI/FileManager/NetFolder.h
new file mode 100644
index 0000000..151dd09
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/NetFolder.h
@@ -0,0 +1,40 @@
1// NetFolder.h
2
3#ifndef __NET_FOLDER_H
4#define __NET_FOLDER_H
5
6#include "../../../Common/MyCom.h"
7
8#include "../../../Windows/Net.h"
9
10#include "IFolder.h"
11
12struct CResourceEx: public NWindows::NNet::CResourceW
13{
14 UString Name;
15};
16
17class CNetFolder:
18 public IFolderFolder,
19 public IFolderGetSystemIconIndex,
20 public CMyUnknownImp
21{
22 NWindows::NNet::CResourceW _netResource;
23 NWindows::NNet::CResourceW *_netResourcePointer;
24
25 CObjectVector<CResourceEx> _items;
26
27 CMyComPtr<IFolderFolder> _parentFolder;
28 UString _path;
29public:
30 MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex)
31 INTERFACE_FolderFolder(;)
32 STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
33
34 CNetFolder(): _netResourcePointer(0) {}
35 void Init(const UString &path);
36 void Init(const NWindows::NNet::CResourceW *netResource,
37 IFolderFolder *parentFolder, const UString &path);
38};
39
40#endif
diff --git a/CPP/7zip/UI/FileManager/OpenCallback.cpp b/CPP/7zip/UI/FileManager/OpenCallback.cpp
new file mode 100644
index 0000000..e2e03f5
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OpenCallback.cpp
@@ -0,0 +1,129 @@
1// OpenCallback.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/ComTry.h"
6#include "../../../Common/StringConvert.h"
7
8#include "../../../Windows/FileName.h"
9#include "../../../Windows/PropVariant.h"
10
11#include "../../Common/FileStreams.h"
12
13#include "../Common/ZipRegistry.h"
14
15#include "OpenCallback.h"
16#include "PasswordDialog.h"
17
18using namespace NWindows;
19
20STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 *numFiles, const UInt64 *numBytes)
21{
22 RINOK(ProgressDialog.Sync.CheckStop());
23 {
24 // NSynchronization::CCriticalSectionLock lock(_criticalSection);
25 ProgressDialog.Sync.Set_NumFilesTotal(numFiles ? *numFiles : (UInt64)(Int64)-1);
26 // if (numFiles)
27 {
28 ProgressDialog.Sync.Set_BytesProgressMode(numFiles == NULL);
29 }
30 if (numBytes)
31 ProgressDialog.Sync.Set_NumBytesTotal(*numBytes);
32 }
33 return S_OK;
34}
35
36STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *numFiles, const UInt64 *numBytes)
37{
38 // NSynchronization::CCriticalSectionLock lock(_criticalSection);
39 if (numFiles)
40 ProgressDialog.Sync.Set_NumFilesCur(*numFiles);
41 if (numBytes)
42 ProgressDialog.Sync.Set_NumBytesCur(*numBytes);
43 return ProgressDialog.Sync.CheckStop();
44}
45
46STDMETHODIMP COpenArchiveCallback::SetTotal(const UInt64 total)
47{
48 RINOK(ProgressDialog.Sync.CheckStop());
49 ProgressDialog.Sync.Set_NumBytesTotal(total);
50 return S_OK;
51}
52
53STDMETHODIMP COpenArchiveCallback::SetCompleted(const UInt64 *completed)
54{
55 return ProgressDialog.Sync.Set_NumBytesCur(completed);
56}
57
58STDMETHODIMP COpenArchiveCallback::GetProperty(PROPID propID, PROPVARIANT *value)
59{
60 NCOM::CPropVariant prop;
61 if (_subArchiveMode)
62 {
63 switch (propID)
64 {
65 case kpidName: prop = _subArchiveName; break;
66 }
67 }
68 else
69 {
70 switch (propID)
71 {
72 case kpidName: prop = fs2us(_fileInfo.Name); break;
73 case kpidIsDir: prop = _fileInfo.IsDir(); break;
74 case kpidSize: prop = _fileInfo.Size; break;
75 case kpidAttrib: prop = (UInt32)_fileInfo.Attrib; break;
76 case kpidCTime: prop = _fileInfo.CTime; break;
77 case kpidATime: prop = _fileInfo.ATime; break;
78 case kpidMTime: prop = _fileInfo.MTime; break;
79 }
80 }
81 prop.Detach(value);
82 return S_OK;
83}
84
85STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream)
86{
87 COM_TRY_BEGIN
88 *inStream = NULL;
89 if (_subArchiveMode)
90 return S_FALSE;
91
92 FString fullPath;
93 if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name), fullPath))
94 return S_FALSE;
95 if (!_fileInfo.Find_FollowLink(fullPath))
96 return S_FALSE;
97 if (_fileInfo.IsDir())
98 return S_FALSE;
99 CInFileStream *inFile = new CInFileStream;
100 CMyComPtr<IInStream> inStreamTemp = inFile;
101 if (!inFile->Open(fullPath))
102 return ::GetLastError();
103 *inStream = inStreamTemp.Detach();
104 return S_OK;
105 COM_TRY_END
106}
107
108STDMETHODIMP COpenArchiveCallback::CryptoGetTextPassword(BSTR *password)
109{
110 COM_TRY_BEGIN
111 PasswordWasAsked = true;
112 if (!PasswordIsDefined)
113 {
114 CPasswordDialog dialog;
115 bool showPassword = NExtract::Read_ShowPassword();
116 dialog.ShowPassword = showPassword;
117
118 ProgressDialog.WaitCreating();
119 if (dialog.Create(ProgressDialog) != IDOK)
120 return E_ABORT;
121
122 Password = dialog.Password;
123 PasswordIsDefined = true;
124 if (dialog.ShowPassword != showPassword)
125 NExtract::Save_ShowPassword(dialog.ShowPassword);
126 }
127 return StringToBstr(Password, password);
128 COM_TRY_END
129}
diff --git a/CPP/7zip/UI/FileManager/OpenCallback.h b/CPP/7zip/UI/FileManager/OpenCallback.h
new file mode 100644
index 0000000..9aa5d43
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OpenCallback.h
@@ -0,0 +1,96 @@
1// OpenCallback.h
2
3#ifndef __OPEN_CALLBACK_H
4#define __OPEN_CALLBACK_H
5
6#include "../../../Common/MyCom.h"
7
8#include "../../../Windows/FileFind.h"
9
10#include "../../IPassword.h"
11
12#include "../../Archive/IArchive.h"
13
14#ifdef _SFX
15#include "ProgressDialog.h"
16#else
17#include "ProgressDialog2.h"
18#endif
19
20
21class COpenArchiveCallback:
22 public IArchiveOpenCallback,
23 public IArchiveOpenVolumeCallback,
24 public IArchiveOpenSetSubArchiveName,
25 public IProgress,
26 public ICryptoGetTextPassword,
27 public CMyUnknownImp
28{
29 FString _folderPrefix;
30 NWindows::NFile::NFind::CFileInfo _fileInfo;
31 // NWindows::NSynchronization::CCriticalSection _criticalSection;
32 bool _subArchiveMode;
33 UString _subArchiveName;
34
35public:
36 bool PasswordIsDefined;
37 bool PasswordWasAsked;
38 UString Password;
39 HWND ParentWindow;
40 CProgressDialog ProgressDialog;
41
42 MY_UNKNOWN_IMP5(
43 IArchiveOpenCallback,
44 IArchiveOpenVolumeCallback,
45 IArchiveOpenSetSubArchiveName,
46 IProgress,
47 ICryptoGetTextPassword)
48
49 INTERFACE_IProgress(;)
50 INTERFACE_IArchiveOpenCallback(;)
51 INTERFACE_IArchiveOpenVolumeCallback(;)
52
53 // ICryptoGetTextPassword
54 STDMETHOD(CryptoGetTextPassword)(BSTR *password);
55
56 STDMETHOD(SetSubArchiveName(const wchar_t *name))
57 {
58 _subArchiveMode = true;
59 _subArchiveName = name;
60 return S_OK;
61 }
62
63 COpenArchiveCallback():
64 ParentWindow(0)
65 {
66 _subArchiveMode = false;
67 PasswordIsDefined = false;
68 PasswordWasAsked = false;
69 }
70 /*
71 void Init()
72 {
73 PasswordIsDefined = false;
74 _subArchiveMode = false;
75 }
76 */
77
78 HRESULT LoadFileInfo2(const FString &folderPrefix, const FString &fileName)
79 {
80 _folderPrefix = folderPrefix;
81 if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName))
82 {
83 return GetLastError_noZero_HRESULT();
84 }
85 return S_OK;
86 }
87
88 void ShowMessage(const UInt64 *completed);
89
90 INT_PTR StartProgressDialog(const UString &title, NWindows::CThread &thread)
91 {
92 return ProgressDialog.Create(title, thread, ParentWindow);
93 }
94};
95
96#endif
diff --git a/CPP/7zip/UI/FileManager/OptionsDialog.cpp b/CPP/7zip/UI/FileManager/OptionsDialog.cpp
new file mode 100644
index 0000000..c42e0f8
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OptionsDialog.cpp
@@ -0,0 +1,87 @@
1// OptionsDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/Control/Dialog.h"
6#include "../../../Windows/Control/PropertyPage.h"
7
8#include "DialogSize.h"
9
10#include "EditPage.h"
11#include "EditPageRes.h"
12#include "FoldersPage.h"
13#include "FoldersPageRes.h"
14#include "LangPage.h"
15#include "LangPageRes.h"
16#include "MenuPage.h"
17#include "MenuPageRes.h"
18#include "SettingsPage.h"
19#include "SettingsPageRes.h"
20#include "SystemPage.h"
21#include "SystemPageRes.h"
22
23#include "App.h"
24#include "LangUtils.h"
25#include "MyLoadMenu.h"
26
27#include "resource.h"
28
29using namespace NWindows;
30
31void OptionsDialog(HWND hwndOwner, HINSTANCE hInstance);
32void OptionsDialog(HWND hwndOwner, HINSTANCE /* hInstance */)
33{
34 CSystemPage systemPage;
35 CMenuPage menuPage;
36 CFoldersPage foldersPage;
37 CEditPage editPage;
38 CSettingsPage settingsPage;
39 CLangPage langPage;
40
41 CObjectVector<NControl::CPageInfo> pages;
42 BIG_DIALOG_SIZE(200, 200);
43
44 const UINT pageIDs[] = {
45 SIZED_DIALOG(IDD_SYSTEM),
46 SIZED_DIALOG(IDD_MENU),
47 SIZED_DIALOG(IDD_FOLDERS),
48 SIZED_DIALOG(IDD_EDIT),
49 SIZED_DIALOG(IDD_SETTINGS),
50 SIZED_DIALOG(IDD_LANG) };
51
52 NControl::CPropertyPage *pagePointers[] = { &systemPage, &menuPage, &foldersPage, &editPage, &settingsPage, &langPage };
53
54 for (unsigned i = 0; i < ARRAY_SIZE(pageIDs); i++)
55 {
56 NControl::CPageInfo &page = pages.AddNew();
57 page.ID = pageIDs[i];
58 LangString_OnlyFromLangFile(page.ID, page.Title);
59 page.Page = pagePointers[i];
60 }
61
62 INT_PTR res = NControl::MyPropertySheet(pages, hwndOwner, LangString(IDS_OPTIONS));
63
64 if (res != -1 && res != 0)
65 {
66 if (langPage.LangWasChanged)
67 {
68 // g_App._window.SetText(LangString(IDS_APP_TITLE, 0x03000000));
69 MyLoadMenu();
70 g_App.ReloadToolbars();
71 g_App.MoveSubWindows(); // we need it to change list window aafter _toolBar.AutoSize();
72 g_App.ReloadLang();
73 }
74
75 /*
76 if (systemPage.WasChanged)
77 {
78 // probably it doesn't work, since image list is locked?
79 g_App.SysIconsWereChanged();
80 }
81 */
82
83 g_App.SetListSettings();
84 g_App.RefreshAllPanels();
85 // ::PostMessage(hwndOwner, kLangWasChangedMessage, 0 , 0);
86 }
87}
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.cpp b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
new file mode 100644
index 0000000..b455b14
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.cpp
@@ -0,0 +1,138 @@
1// OverwriteDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/StringConvert.h"
6
7#include "../../../Windows/PropVariantConv.h"
8#include "../../../Windows/ResourceString.h"
9
10#include "../../../Windows/Control/Static.h"
11
12#include "FormatUtils.h"
13#include "LangUtils.h"
14#include "OverwriteDialog.h"
15
16#include "PropertyNameRes.h"
17
18using namespace NWindows;
19
20#ifdef LANG
21static const UInt32 kLangIDs[] =
22{
23 IDT_OVERWRITE_HEADER,
24 IDT_OVERWRITE_QUESTION_BEGIN,
25 IDT_OVERWRITE_QUESTION_END,
26 IDB_YES_TO_ALL,
27 IDB_NO_TO_ALL,
28 IDB_AUTO_RENAME
29};
30#endif
31
32static const unsigned kCurrentFileNameSizeLimit = 82;
33static const unsigned kCurrentFileNameSizeLimit2 = 30;
34
35void COverwriteDialog::ReduceString(UString &s)
36{
37 unsigned size = _isBig ? kCurrentFileNameSizeLimit : kCurrentFileNameSizeLimit2;
38 if (s.Len() > size)
39 {
40 s.Delete(size / 2, s.Len() - size);
41 s.Insert(size / 2, L" ... ");
42 }
43 if (!s.IsEmpty() && s.Back() == ' ')
44 {
45 // s += (wchar_t)(0x2423);
46 s.InsertAtFront(L'\"');
47 s += L'\"';
48 }
49}
50
51void COverwriteDialog::SetFileInfoControl(int textID, int iconID,
52 const NOverwriteDialog::CFileInfo &fileInfo)
53{
54 UString sizeString;
55 if (fileInfo.SizeIsDefined)
56 sizeString = MyFormatNew(IDS_FILE_SIZE, NumberToString(fileInfo.Size));
57
58 const UString &fileName = fileInfo.Name;
59 int slashPos = fileName.ReverseFind_PathSepar();
60 UString s1 = fileName.Left((unsigned)(slashPos + 1));
61 UString s2 = fileName.Ptr((unsigned)(slashPos + 1));
62
63 ReduceString(s1);
64 ReduceString(s2);
65
66 UString s = s1;
67 s.Add_LF();
68 s += s2;
69 s.Add_LF();
70 s += sizeString;
71 s.Add_LF();
72
73 if (fileInfo.TimeIsDefined)
74 {
75 AddLangString(s, IDS_PROP_MTIME);
76 s += ": ";
77 char t[32];
78 ConvertUtcFileTimeToString(fileInfo.Time, t);
79 s += t;
80 }
81
82 NControl::CDialogChildControl control;
83 control.Init(*this, textID);
84 control.SetText(s);
85
86 SHFILEINFO shellFileInfo;
87 if (::SHGetFileInfo(
88 GetSystemString(fileInfo.Name), FILE_ATTRIBUTE_NORMAL, &shellFileInfo,
89 sizeof(shellFileInfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_LARGEICON))
90 {
91 NControl::CStatic staticContol;
92 staticContol.Attach(GetItem(iconID));
93 staticContol.SetIcon(shellFileInfo.hIcon);
94 }
95}
96
97bool COverwriteDialog::OnInit()
98{
99 #ifdef LANG
100 LangSetWindowText(*this, IDD_OVERWRITE);
101 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
102 #endif
103 SetFileInfoControl(IDT_OVERWRITE_OLD_FILE_SIZE_TIME, IDI_OVERWRITE_OLD_FILE, OldFileInfo);
104 SetFileInfoControl(IDT_OVERWRITE_NEW_FILE_SIZE_TIME, IDI_OVERWRITE_NEW_FILE, NewFileInfo);
105 NormalizePosition();
106
107 if (!ShowExtraButtons)
108 {
109 HideItem(IDB_YES_TO_ALL);
110 HideItem(IDB_NO_TO_ALL);
111 HideItem(IDB_AUTO_RENAME);
112 }
113
114 if (DefaultButton_is_NO)
115 {
116 PostMsg(DM_SETDEFID, IDNO);
117 HWND h = GetItem(IDNO);
118 PostMsg(WM_NEXTDLGCTL, (WPARAM)h, TRUE);
119 // ::SetFocus(h);
120 }
121
122 return CModalDialog::OnInit();
123}
124
125bool COverwriteDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
126{
127 switch (buttonID)
128 {
129 case IDYES:
130 case IDNO:
131 case IDB_YES_TO_ALL:
132 case IDB_NO_TO_ALL:
133 case IDB_AUTO_RENAME:
134 End(buttonID);
135 return true;
136 }
137 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
138}
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.h b/CPP/7zip/UI/FileManager/OverwriteDialog.h
new file mode 100644
index 0000000..24e56ca
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.h
@@ -0,0 +1,79 @@
1// OverwriteDialog.h
2
3#ifndef __OVERWRITE_DIALOG_H
4#define __OVERWRITE_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7
8#include "DialogSize.h"
9#include "OverwriteDialogRes.h"
10
11namespace NOverwriteDialog
12{
13 struct CFileInfo
14 {
15 bool SizeIsDefined;
16 bool TimeIsDefined;
17 UInt64 Size;
18 FILETIME Time;
19 UString Name;
20
21 void SetTime(const FILETIME *t)
22 {
23 if (!t)
24 TimeIsDefined = false;
25 else
26 {
27 TimeIsDefined = true;
28 Time = *t;
29 }
30 }
31
32 void SetSize(UInt64 size)
33 {
34 SizeIsDefined = true;
35 Size = size;
36 }
37
38 void SetSize(const UInt64 *size)
39 {
40 if (!size)
41 SizeIsDefined = false;
42 else
43 SetSize(*size);
44 }
45 };
46}
47
48class COverwriteDialog: public NWindows::NControl::CModalDialog
49{
50 bool _isBig;
51
52 void SetFileInfoControl(int textID, int iconID, const NOverwriteDialog::CFileInfo &fileInfo);
53 virtual bool OnInit();
54 bool OnButtonClicked(int buttonID, HWND buttonHWND);
55 void ReduceString(UString &s);
56
57public:
58 bool ShowExtraButtons;
59 bool DefaultButton_is_NO;
60
61
62 COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {}
63
64 INT_PTR Create(HWND parent = 0)
65 {
66 BIG_DIALOG_SIZE(280, 200);
67 #ifdef UNDER_CE
68 _isBig = isBig;
69 #else
70 _isBig = true;
71 #endif
72 return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);
73 }
74
75 NOverwriteDialog::CFileInfo OldFileInfo;
76 NOverwriteDialog::CFileInfo NewFileInfo;
77};
78
79#endif
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialog.rc b/CPP/7zip/UI/FileManager/OverwriteDialog.rc
new file mode 100644
index 0000000..29f9912
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialog.rc
@@ -0,0 +1,91 @@
1#include "OverwriteDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 280
5#define yc 200
6
7#undef iconSize
8#define iconSize 24
9
10#undef x
11#undef fx
12#undef fy
13#define x (m + iconSize + m)
14#define fx (xc - iconSize - m)
15#define fy 50
16
17#define bSizeBig 104
18#undef bx1
19#define bx1 (xs - m - bSizeBig)
20
21IDD_OVERWRITE DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
22CAPTION "Confirm File Replace"
23BEGIN
24 LTEXT "Destination folder already contains processed file.", IDT_OVERWRITE_HEADER, m, 7, xc, 8
25 LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, 28, xc, 8
26
27 ICON "", IDI_OVERWRITE_OLD_FILE, m, 44, iconSize, iconSize
28 LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 44, fx, fy, SS_NOPREFIX
29
30 LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 98, xc, 8
31
32 ICON "", IDI_OVERWRITE_NEW_FILE, m, 114, iconSize, iconSize
33 LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 114, fx, fy, SS_NOPREFIX
34
35 PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys
36 PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys
37 PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bSizeBig, bys
38 PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys
39 PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys
40 PUSHBUTTON "&Cancel", IDCANCEL, xs - m - bxs, by1, bxs, bys
41END
42
43
44#ifdef UNDER_CE
45
46#undef m
47#undef xc
48#undef yc
49
50#define m 4
51#define xc 152
52#define yc 144
53
54#undef fy
55#define fy 40
56
57#undef bxs
58#define bxs 48
59
60#undef bx1
61
62#define bx1 (xs - m - bxs)
63
64IDD_OVERWRITE_2 DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
65CAPTION "Confirm File Replace"
66BEGIN
67 LTEXT "Would you like to replace the existing file", IDT_OVERWRITE_QUESTION_BEGIN, m, m, xc, 8
68
69 ICON "", IDI_OVERWRITE_OLD_FILE, m, 20, iconSize, iconSize
70 LTEXT "", IDT_OVERWRITE_OLD_FILE_SIZE_TIME, x, 20, fx, fy, SS_NOPREFIX
71
72 LTEXT "with this one?", IDT_OVERWRITE_QUESTION_END, m, 60, xc, 8
73
74 ICON "", IDI_OVERWRITE_NEW_FILE, m, 72, iconSize, iconSize
75 LTEXT "", IDT_OVERWRITE_NEW_FILE_SIZE_TIME, x, 72, fx, fy, SS_NOPREFIX
76
77 PUSHBUTTON "&Yes", IDYES, bx3, by2, bxs, bys
78 PUSHBUTTON "Yes to &All", IDB_YES_TO_ALL, bx2, by2, bxs, bys
79 PUSHBUTTON "A&uto Rename", IDB_AUTO_RENAME, bx1, by2, bxs, bys
80 PUSHBUTTON "&No", IDNO, bx3, by1, bxs, bys
81 PUSHBUTTON "No to A&ll", IDB_NO_TO_ALL, bx2, by1, bxs, bys
82 PUSHBUTTON "&Cancel", IDCANCEL, bx1, by1, bxs, bys
83END
84
85#endif
86
87
88STRINGTABLE
89BEGIN
90 IDS_FILE_SIZE "{0} bytes"
91END
diff --git a/CPP/7zip/UI/FileManager/OverwriteDialogRes.h b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
new file mode 100644
index 0000000..b480ba1
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/OverwriteDialogRes.h
@@ -0,0 +1,17 @@
1#define IDD_OVERWRITE 3500
2#define IDD_OVERWRITE_2 13500
3
4#define IDT_OVERWRITE_HEADER 3501
5#define IDT_OVERWRITE_QUESTION_BEGIN 3502
6#define IDT_OVERWRITE_QUESTION_END 3503
7#define IDS_FILE_SIZE 3504
8
9#define IDB_AUTO_RENAME 3505
10#define IDB_YES_TO_ALL 440
11#define IDB_NO_TO_ALL 441
12
13#define IDI_OVERWRITE_OLD_FILE 100
14#define IDI_OVERWRITE_NEW_FILE 101
15
16#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME 102
17#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME 103
diff --git a/CPP/7zip/UI/FileManager/Panel.cpp b/CPP/7zip/UI/FileManager/Panel.cpp
new file mode 100644
index 0000000..e8c0b94
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Panel.cpp
@@ -0,0 +1,1113 @@
1// Panel.cpp
2
3#include "StdAfx.h"
4
5#include <WindowsX.h>
6// #include <stdio.h>
7
8#include "../../../Common/IntToString.h"
9#include "../../../Common/StringConvert.h"
10
11#include "../../../Windows/FileName.h"
12#include "../../../Windows/ErrorMsg.h"
13#include "../../../Windows/PropVariant.h"
14#include "../../../Windows/Thread.h"
15
16#include "../../PropID.h"
17
18#include "resource.h"
19#include "../GUI/ExtractRes.h"
20
21#include "../Common/ArchiveName.h"
22#include "../Common/CompressCall.h"
23
24#include "../Agent/IFolderArchive.h"
25
26#include "App.h"
27#include "ExtractCallback.h"
28#include "FSFolder.h"
29#include "FormatUtils.h"
30#include "Panel.h"
31#include "RootFolder.h"
32
33#include "PropertyNameRes.h"
34
35using namespace NWindows;
36using namespace NControl;
37
38#ifndef _UNICODE
39extern bool g_IsNT;
40#endif
41
42static const UINT_PTR kTimerID = 1;
43static const UINT kTimerElapse = 1000;
44
45static DWORD kStyles[4] = { LVS_ICON, LVS_SMALLICON, LVS_LIST, LVS_REPORT };
46
47// static const int kCreateFolderID = 101;
48
49extern HINSTANCE g_hInstance;
50extern DWORD g_ComCtl32Version;
51
52void CPanel::Release()
53{
54 // It's for unloading COM dll's: don't change it.
55 CloseOpenFolders();
56 _sevenZipContextMenu.Release();
57 _systemContextMenu.Release();
58}
59
60CPanel::~CPanel()
61{
62 CloseOpenFolders();
63}
64
65HWND CPanel::GetParent() const
66{
67 HWND h = CWindow2::GetParent();
68 return (h == 0) ? _mainWindow : h;
69}
70
71#define kClassName L"7-Zip::Panel"
72
73
74HRESULT CPanel::Create(HWND mainWindow, HWND parentWindow, UINT id,
75 const UString &currentFolderPrefix,
76 const UString &arcFormat,
77 CPanelCallback *panelCallback, CAppState *appState,
78 bool needOpenArc,
79 COpenResult &openRes)
80{
81 _mainWindow = mainWindow;
82 _processTimer = true;
83 _processNotify = true;
84 _processStatusBar = true;
85
86 _panelCallback = panelCallback;
87 _appState = appState;
88 // _index = index;
89 _baseID = id;
90 _comboBoxID = _baseID + 3;
91 _statusBarID = _comboBoxID + 1;
92
93 UString cfp = currentFolderPrefix;
94
95 if (!currentFolderPrefix.IsEmpty())
96 if (currentFolderPrefix[0] == L'.')
97 {
98 FString cfpF;
99 if (NFile::NDir::MyGetFullPathName(us2fs(currentFolderPrefix), cfpF))
100 cfp = fs2us(cfpF);
101 }
102
103 RINOK(BindToPath(cfp, arcFormat, openRes));
104
105 if (needOpenArc && !openRes.ArchiveIsOpened)
106 return S_OK;
107
108 if (!CreateEx(0, kClassName, 0, WS_CHILD | WS_VISIBLE,
109 0, 0, _xSize, 260,
110 parentWindow, (HMENU)(UINT_PTR)id, g_hInstance))
111 return E_FAIL;
112 PanelCreated = true;
113
114 return S_OK;
115}
116
117// extern UInt32 g_NumMessages;
118
119LRESULT CPanel::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
120{
121 // g_NumMessages++;
122 switch (message)
123 {
124 case kShiftSelectMessage:
125 OnShiftSelectMessage();
126 return 0;
127 case kReLoadMessage:
128 RefreshListCtrl(_selectedState);
129 return 0;
130 case kSetFocusToListView:
131 _listView.SetFocus();
132 return 0;
133 case kOpenItemChanged:
134 return OnOpenItemChanged(lParam);
135 case kRefresh_StatusBar:
136 if (_processStatusBar)
137 Refresh_StatusBar();
138 return 0;
139 #ifdef UNDER_CE
140 case kRefresh_HeaderComboBox:
141 LoadFullPathAndShow();
142 return 0;
143 #endif
144 case WM_TIMER:
145 OnTimer();
146 return 0;
147 case WM_CONTEXTMENU:
148 if (OnContextMenu(HANDLE(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)))
149 return 0;
150 break;
151 /*
152 case WM_DROPFILES:
153 CompressDropFiles(HDROP(wParam));
154 return 0;
155 */
156 }
157 return CWindow2::OnMessage(message, wParam, lParam);
158}
159
160LRESULT CMyListView::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
161{
162 if (message == WM_CHAR)
163 {
164 UINT scanCode = (UINT)((lParam >> 16) & 0xFF);
165 bool extended = ((lParam & 0x1000000) != 0);
166 UINT virtualKey = MapVirtualKey(scanCode, 1);
167 if (virtualKey == VK_MULTIPLY || virtualKey == VK_ADD ||
168 virtualKey == VK_SUBTRACT)
169 return 0;
170 if ((wParam == '/' && extended)
171 || wParam == '\\' || wParam == '/')
172 {
173 _panel->OpenDrivesFolder();
174 return 0;
175 }
176 }
177 else if (message == WM_SYSCHAR)
178 {
179 // For Alt+Enter Beep disabling
180 UINT scanCode = (UINT)(lParam >> 16) & 0xFF;
181 UINT virtualKey = MapVirtualKey(scanCode, 1);
182 if (virtualKey == VK_RETURN || virtualKey == VK_MULTIPLY ||
183 virtualKey == VK_ADD || virtualKey == VK_SUBTRACT)
184 return 0;
185 }
186 /*
187 else if (message == WM_SYSKEYDOWN)
188 {
189 // return 0;
190 }
191 */
192 else if (message == WM_KEYDOWN)
193 {
194 bool alt = IsKeyDown(VK_MENU);
195 bool ctrl = IsKeyDown(VK_CONTROL);
196 bool shift = IsKeyDown(VK_SHIFT);
197 switch (wParam)
198 {
199 /*
200 case VK_RETURN:
201 {
202 if (shift && !alt && !ctrl)
203 {
204 _panel->OpenSelectedItems(false);
205 return 0;
206 }
207 break;
208 }
209 */
210 case VK_NEXT:
211 {
212 if (ctrl && !alt && !shift)
213 {
214 _panel->OpenFocusedItemAsInternal();
215 return 0;
216 }
217 break;
218 }
219 case VK_PRIOR:
220 if (ctrl && !alt && !shift)
221 {
222 _panel->OpenParentFolder();
223 return 0;
224 }
225 }
226 }
227 #ifdef UNDER_CE
228 else if (message == WM_KEYUP)
229 {
230 if (wParam == VK_F2) // it's VK_TSOFT2
231 {
232 // Activate Menu
233 ::PostMessage(g_HWND, WM_SYSCOMMAND, SC_KEYMENU, 0);
234 return 0;
235 }
236 }
237 #endif
238 else if (message == WM_SETFOCUS)
239 {
240 _panel->_lastFocusedIsList = true;
241 _panel->_panelCallback->PanelWasFocused();
242 }
243 return CListView2::OnMessage(message, wParam, lParam);
244}
245
246/*
247static LRESULT APIENTRY ComboBoxSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
248{
249 CWindow tempDialog(hwnd);
250 CMyComboBox *w = (CMyComboBox *)(tempDialog.GetUserDataLongPtr());
251 if (w == NULL)
252 return 0;
253 return w->OnMessage(message, wParam, lParam);
254}
255
256LRESULT CMyComboBox::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
257{
258 return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);
259}
260*/
261
262#ifndef UNDER_CE
263
264static LRESULT APIENTRY ComboBoxEditSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
265{
266 CWindow tempDialog(hwnd);
267 CMyComboBoxEdit *w = (CMyComboBoxEdit *)(tempDialog.GetUserDataLongPtr());
268 if (w == NULL)
269 return 0;
270 return w->OnMessage(message, wParam, lParam);
271}
272
273#endif
274
275LRESULT CMyComboBoxEdit::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
276{
277 // See MSDN / Subclassing a Combo Box / Creating a Combo-box Toolbar
278 switch (message)
279 {
280 case WM_SYSKEYDOWN:
281 switch (wParam)
282 {
283 case VK_F1:
284 case VK_F2:
285 {
286 // check ALT
287 if ((lParam & (1<<29)) == 0)
288 break;
289 bool alt = IsKeyDown(VK_MENU);
290 bool ctrl = IsKeyDown(VK_CONTROL);
291 bool shift = IsKeyDown(VK_SHIFT);
292 if (alt && !ctrl && !shift)
293 {
294 _panel->_panelCallback->SetFocusToPath(wParam == VK_F1 ? 0 : 1);
295 return 0;
296 }
297 break;
298 }
299 }
300 break;
301 case WM_KEYDOWN:
302 switch (wParam)
303 {
304 case VK_TAB:
305 // SendMessage(hwndMain, WM_ENTER, 0, 0);
306 _panel->SetFocusToList();
307 return 0;
308 case VK_F9:
309 {
310 bool alt = IsKeyDown(VK_MENU);
311 bool ctrl = IsKeyDown(VK_CONTROL);
312 bool shift = IsKeyDown(VK_SHIFT);
313 if (!alt && !ctrl && !shift)
314 {
315 g_App.SwitchOnOffOnePanel();
316 return 0;
317 }
318 break;
319 }
320 }
321 break;
322 case WM_CHAR:
323 switch (wParam)
324 {
325 case VK_TAB:
326 case VK_ESCAPE:
327 return 0;
328 }
329 }
330 #ifndef _UNICODE
331 if (g_IsNT)
332 return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);
333 else
334 #endif
335 return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);
336}
337
338bool CPanel::OnCreate(CREATESTRUCT * /* createStruct */)
339{
340 // _virtualMode = false;
341 // _sortIndex = 0;
342 _sortID = kpidName;
343 _ascending = true;
344 _lastFocusedIsList = true;
345
346 DWORD style = WS_CHILD | WS_VISIBLE; // | WS_BORDER ; // | LVS_SHAREIMAGELISTS; // | LVS_SHOWSELALWAYS;
347
348 style |= LVS_SHAREIMAGELISTS;
349 // style |= LVS_AUTOARRANGE;
350 style |= WS_CLIPCHILDREN;
351 style |= WS_CLIPSIBLINGS;
352
353 const UInt32 kNumListModes = ARRAY_SIZE(kStyles);
354 if (_ListViewMode >= kNumListModes)
355 _ListViewMode = kNumListModes - 1;
356
357 style |= kStyles[_ListViewMode]
358 | WS_TABSTOP
359 | LVS_EDITLABELS;
360 if (_mySelectMode)
361 style |= LVS_SINGLESEL;
362
363 /*
364 if (_virtualMode)
365 style |= LVS_OWNERDATA;
366 */
367
368 DWORD exStyle;
369 exStyle = WS_EX_CLIENTEDGE;
370
371 if (!_listView.CreateEx(exStyle, style, 0, 0, 116, 260,
372 *this, (HMENU)(UINT_PTR)(_baseID + 1), g_hInstance, NULL))
373 return false;
374
375 _listView.SetUnicodeFormat();
376 _listView._panel = this;
377 _listView.SetWindowProc();
378
379 _listView.SetImageList(GetSysImageList(true), LVSIL_SMALL);
380 _listView.SetImageList(GetSysImageList(false), LVSIL_NORMAL);
381
382 // _exStyle |= LVS_EX_HEADERDRAGDROP;
383 // DWORD extendedStyle = _listView.GetExtendedListViewStyle();
384 // extendedStyle |= _exStyle;
385 // _listView.SetExtendedListViewStyle(extendedStyle);
386 SetExtendedStyle();
387
388 _listView.Show(SW_SHOW);
389 _listView.InvalidateRect(NULL, true);
390 _listView.Update();
391
392 // Ensure that the common control DLL is loaded.
393 INITCOMMONCONTROLSEX icex;
394
395 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
396 icex.dwICC = ICC_BAR_CLASSES;
397 InitCommonControlsEx(&icex);
398
399 TBBUTTON tbb [ ] =
400 {
401 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
402 {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, { 0, 0 }, 0, 0 },
403 // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0},
404 // {VIEW_NEWFOLDER, kCreateFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0},
405 };
406
407 #ifndef UNDER_CE
408 if (g_ComCtl32Version >= MAKELONG(71, 4))
409 #endif
410 {
411 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
412 icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
413 InitCommonControlsEx(&icex);
414
415 // if there is no CCS_NOPARENTALIGN, there is space of some pixels after rebar (Incorrect GetWindowRect ?)
416
417 _headerReBar.Attach(::CreateWindowEx(WS_EX_TOOLWINDOW,
418 REBARCLASSNAME,
419 NULL, WS_VISIBLE | WS_BORDER | WS_CHILD |
420 WS_CLIPCHILDREN | WS_CLIPSIBLINGS
421 | CCS_NODIVIDER
422 | CCS_NOPARENTALIGN
423 | CCS_TOP
424 | RBS_VARHEIGHT
425 | RBS_BANDBORDERS
426 ,0,0,0,0, *this, NULL, g_hInstance, NULL));
427 }
428
429 DWORD toolbarStyle = WS_CHILD | WS_VISIBLE ;
430 if (_headerReBar)
431 {
432 toolbarStyle |= 0
433 // | WS_CLIPCHILDREN
434 // | WS_CLIPSIBLINGS
435
436 | TBSTYLE_TOOLTIPS
437 | CCS_NODIVIDER
438 | CCS_NORESIZE
439 | TBSTYLE_FLAT
440 ;
441 }
442
443 _headerToolBar.Attach(::CreateToolbarEx ((*this), toolbarStyle,
444 _baseID + 2, 11,
445 (HINSTANCE)HINST_COMMCTRL,
446 IDB_VIEW_SMALL_COLOR,
447 (LPCTBBUTTON)&tbb, ARRAY_SIZE(tbb),
448 0, 0, 0, 0, sizeof (TBBUTTON)));
449
450 #ifndef UNDER_CE
451 // Load ComboBoxEx class
452 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
453 icex.dwICC = ICC_USEREX_CLASSES;
454 InitCommonControlsEx(&icex);
455 #endif
456
457 _headerComboBox.CreateEx(0,
458 #ifdef UNDER_CE
459 WC_COMBOBOXW
460 #else
461 WC_COMBOBOXEXW
462 #endif
463 , NULL,
464 WS_BORDER | WS_VISIBLE |WS_CHILD | CBS_DROPDOWN | CBS_AUTOHSCROLL,
465 0, 0, 100, 520,
466 ((_headerReBar == 0) ? (HWND)*this : _headerToolBar),
467 (HMENU)(UINT_PTR)(_comboBoxID),
468 g_hInstance, NULL);
469 #ifndef UNDER_CE
470 _headerComboBox.SetUnicodeFormat(true);
471
472 _headerComboBox.SetImageList(GetSysImageList(true));
473
474 _headerComboBox.SetExtendedStyle(CBES_EX_PATHWORDBREAKPROC, CBES_EX_PATHWORDBREAKPROC);
475
476 /*
477 _headerComboBox.SetUserDataLongPtr(LONG_PTR(&_headerComboBox));
478 _headerComboBox._panel = this;
479 _headerComboBox._origWindowProc =
480 (WNDPROC)_headerComboBox.SetLongPtr(GWLP_WNDPROC,
481 LONG_PTR(ComboBoxSubclassProc));
482 */
483 _comboBoxEdit.Attach(_headerComboBox.GetEditControl());
484
485 // _comboBoxEdit.SendMessage(CCM_SETUNICODEFORMAT, (WPARAM)(BOOL)TRUE, 0);
486
487 _comboBoxEdit.SetUserDataLongPtr(LONG_PTR(&_comboBoxEdit));
488 _comboBoxEdit._panel = this;
489 #ifndef _UNICODE
490 if (g_IsNT)
491 _comboBoxEdit._origWindowProc =
492 (WNDPROC)_comboBoxEdit.SetLongPtrW(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
493 else
494 #endif
495 _comboBoxEdit._origWindowProc =
496 (WNDPROC)_comboBoxEdit.SetLongPtr(GWLP_WNDPROC, LONG_PTR(ComboBoxEditSubclassProc));
497
498 #endif
499
500 if (_headerReBar)
501 {
502 REBARINFO rbi;
503 rbi.cbSize = sizeof(REBARINFO); // Required when using this struct.
504 rbi.fMask = 0;
505 rbi.himl = (HIMAGELIST)NULL;
506 _headerReBar.SetBarInfo(&rbi);
507
508 // Send the TB_BUTTONSTRUCTSIZE message, which is required for
509 // backward compatibility.
510 // _headerToolBar.SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
511 SIZE size;
512 _headerToolBar.GetMaxSize(&size);
513
514 REBARBANDINFO rbBand;
515 rbBand.cbSize = sizeof(REBARBANDINFO); // Required
516 rbBand.fMask = RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
517 rbBand.fStyle = RBBS_NOGRIPPER;
518 rbBand.cxMinChild = size.cx;
519 rbBand.cyMinChild = size.cy;
520 rbBand.cyChild = size.cy;
521 rbBand.cx = size.cx;
522 rbBand.hwndChild = _headerToolBar;
523 _headerReBar.InsertBand(-1, &rbBand);
524
525 RECT rc;
526 ::GetWindowRect(_headerComboBox, &rc);
527 rbBand.cxMinChild = 30;
528 rbBand.cyMinChild = rc.bottom - rc.top;
529 rbBand.cx = 1000;
530 rbBand.hwndChild = _headerComboBox;
531 _headerReBar.InsertBand(-1, &rbBand);
532 // _headerReBar.MaximizeBand(1, false);
533 }
534
535 _statusBar.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID);
536 // _statusBar2.Create(WS_CHILD | WS_VISIBLE, L"Status", (*this), _statusBarID + 1);
537
538 const int sizes[] = {220, 320, 420, -1};
539 _statusBar.SetParts(4, sizes);
540 // _statusBar2.SetParts(5, sizes);
541
542 /*
543 RECT rect;
544 GetClientRect(&rect);
545 OnSize(0, RECT_SIZE_X(rect), RECT_SIZE_Y(rect));
546 */
547
548 SetTimer(kTimerID, kTimerElapse);
549
550 // InitListCtrl();
551 RefreshListCtrl();
552
553 return true;
554}
555
556void CPanel::OnDestroy()
557{
558 SaveListViewInfo();
559 CWindow2::OnDestroy();
560}
561
562void CPanel::ChangeWindowSize(int xSize, int ySize)
563{
564 if ((HWND)*this == 0)
565 return;
566 int kHeaderSize;
567 int kStatusBarSize;
568 // int kStatusBar2Size;
569 RECT rect;
570 if (_headerReBar)
571 _headerReBar.GetWindowRect(&rect);
572 else
573 _headerToolBar.GetWindowRect(&rect);
574
575 kHeaderSize = RECT_SIZE_Y(rect);
576
577 _statusBar.GetWindowRect(&rect);
578 kStatusBarSize = RECT_SIZE_Y(rect);
579
580 // _statusBar2.GetWindowRect(&rect);
581 // kStatusBar2Size = RECT_SIZE_Y(rect);
582
583 int yListViewSize = MyMax(ySize - kHeaderSize - kStatusBarSize, 0);
584 const int kStartXPos = 32;
585 if (_headerReBar)
586 {
587 }
588 else
589 {
590 _headerToolBar.Move(0, 0, xSize, 0);
591 _headerComboBox.Move(kStartXPos, 2,
592 MyMax(xSize - kStartXPos - 10, kStartXPos), 0);
593 }
594 _listView.Move(0, kHeaderSize, xSize, yListViewSize);
595 _statusBar.Move(0, kHeaderSize + yListViewSize, xSize, kStatusBarSize);
596 // _statusBar2.MoveWindow(0, kHeaderSize + yListViewSize + kStatusBarSize, xSize, kStatusBar2Size);
597 // _statusBar.MoveWindow(0, 100, xSize, kStatusBarSize);
598 // _statusBar2.MoveWindow(0, 200, xSize, kStatusBar2Size);
599}
600
601bool CPanel::OnSize(WPARAM /* wParam */, int xSize, int ySize)
602{
603 if ((HWND)*this == 0)
604 return true;
605 if (_headerReBar)
606 _headerReBar.Move(0, 0, xSize, 0);
607 ChangeWindowSize(xSize, ySize);
608 return true;
609}
610
611bool CPanel::OnNotifyReBar(LPNMHDR header, LRESULT & /* result */)
612{
613 switch (header->code)
614 {
615 case RBN_HEIGHTCHANGE:
616 {
617 RECT rect;
618 GetWindowRect(&rect);
619 ChangeWindowSize(RECT_SIZE_X(rect), RECT_SIZE_Y(rect));
620 return false;
621 }
622 }
623 return false;
624}
625
626/*
627UInt32 g_OnNotify = 0;
628UInt32 g_LVIF_TEXT = 0;
629UInt32 g_Time = 0;
630
631void Print_OnNotify(const char *name)
632{
633 char s[256];
634 DWORD tim = GetTickCount();
635 sprintf(s,
636 "Time = %7u ms, Notify = %9u, TEXT = %9u, %s",
637 tim - g_Time,
638 g_OnNotify,
639 g_LVIF_TEXT,
640 name);
641 g_Time = tim;
642 OutputDebugStringA(s);
643 g_OnNotify = 0;
644 g_LVIF_TEXT = 0;
645}
646*/
647
648bool CPanel::OnNotify(UINT /* controlID */, LPNMHDR header, LRESULT &result)
649{
650 /*
651 g_OnNotify++;
652
653 if (header->hwndFrom == _listView)
654 {
655 if (header->code == LVN_GETDISPINFOW)
656 {
657 LV_DISPINFOW *dispInfo = (LV_DISPINFOW *)header;
658 if ((dispInfo->item.mask & LVIF_TEXT))
659 g_LVIF_TEXT++;
660 }
661 }
662 */
663
664 if (!_processNotify)
665 return false;
666
667 if (header->hwndFrom == _headerComboBox)
668 return OnNotifyComboBox(header, result);
669 else if (header->hwndFrom == _headerReBar)
670 return OnNotifyReBar(header, result);
671 else if (header->hwndFrom == _listView)
672 return OnNotifyList(header, result);
673 else if (::GetParent(header->hwndFrom) == _listView)
674 {
675 // NMHDR:code is UINT
676 // NM_RCLICK is unsigned in windows sdk
677 // NM_RCLICK is int in MinGW
678 if (header->code == (UINT)NM_RCLICK)
679 return OnRightClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header, result);
680 }
681 return false;
682}
683
684bool CPanel::OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result)
685{
686 if (itemID == kParentFolderID)
687 {
688 OpenParentFolder();
689 result = 0;
690 return true;
691 }
692 /*
693 if (itemID == kCreateFolderID)
694 {
695 CreateFolder();
696 result = 0;
697 return true;
698 }
699 */
700 if (itemID == _comboBoxID)
701 {
702 if (OnComboBoxCommand(code, lParam, result))
703 return true;
704 }
705 return CWindow2::OnCommand(code, itemID, lParam, result);
706}
707
708
709
710/*
711void CPanel::MessageBox_Info(LPCWSTR message, LPCWSTR caption) const
712 { ::MessageBoxW((HWND)*this, message, caption, MB_OK); }
713void CPanel::MessageBox_Warning(LPCWSTR message) const
714 { ::MessageBoxW((HWND)*this, message, L"7-Zip", MB_OK | MB_ICONWARNING); }
715*/
716
717void CPanel::MessageBox_Error_Caption(LPCWSTR message, LPCWSTR caption) const
718 { ::MessageBoxW((HWND)*this, message, caption, MB_OK | MB_ICONSTOP); }
719
720void CPanel::MessageBox_Error(LPCWSTR message) const
721 { MessageBox_Error_Caption(message, L"7-Zip"); }
722
723static UString ErrorHResult_To_Message(HRESULT errorCode)
724{
725 if (errorCode == 0)
726 errorCode = E_FAIL;
727 return HResultToMessage(errorCode);
728}
729
730void CPanel::MessageBox_Error_HRESULT_Caption(HRESULT errorCode, LPCWSTR caption) const
731{
732 MessageBox_Error_Caption(ErrorHResult_To_Message(errorCode), caption);
733}
734
735void CPanel::MessageBox_Error_HRESULT(HRESULT errorCode) const
736 { MessageBox_Error_HRESULT_Caption(errorCode, L"7-Zip"); }
737
738void CPanel::MessageBox_Error_2Lines_Message_HRESULT(LPCWSTR message, HRESULT errorCode) const
739{
740 UString m = message;
741 m.Add_LF();
742 m += ErrorHResult_To_Message(errorCode);
743 MessageBox_Error(m);
744}
745
746void CPanel::MessageBox_LastError(LPCWSTR caption) const
747 { MessageBox_Error_HRESULT_Caption(::GetLastError(), caption); }
748
749void CPanel::MessageBox_LastError() const
750 { MessageBox_LastError(L"7-Zip"); }
751
752void CPanel::MessageBox_Error_LangID(UINT resourceID) const
753 { MessageBox_Error(LangString(resourceID)); }
754
755void CPanel::MessageBox_Error_UnsupportOperation() const
756 { MessageBox_Error_LangID(IDS_OPERATION_IS_NOT_SUPPORTED); }
757
758
759
760
761void CPanel::SetFocusToList()
762{
763 _listView.SetFocus();
764 // SetCurrentPathText();
765}
766
767void CPanel::SetFocusToLastRememberedItem()
768{
769 if (_lastFocusedIsList)
770 SetFocusToList();
771 else
772 _headerComboBox.SetFocus();
773}
774
775UString CPanel::GetFolderTypeID() const
776{
777 {
778 NCOM::CPropVariant prop;
779 if (_folder->GetFolderProperty(kpidType, &prop) == S_OK)
780 if (prop.vt == VT_BSTR)
781 return (const wchar_t *)prop.bstrVal;
782 }
783 return UString();
784}
785
786bool CPanel::IsFolderTypeEqTo(const char *s) const
787{
788 return StringsAreEqual_Ascii(GetFolderTypeID(), s);
789}
790
791bool CPanel::IsRootFolder() const { return IsFolderTypeEqTo("RootFolder"); }
792bool CPanel::IsFSFolder() const { return IsFolderTypeEqTo("FSFolder"); }
793bool CPanel::IsFSDrivesFolder() const { return IsFolderTypeEqTo("FSDrives"); }
794bool CPanel::IsAltStreamsFolder() const { return IsFolderTypeEqTo("AltStreamsFolder"); }
795bool CPanel::IsArcFolder() const
796{
797 return GetFolderTypeID().IsPrefixedBy_Ascii_NoCase("7-Zip");
798}
799
800bool CPanel::IsHashFolder() const
801{
802 if (_folder)
803 {
804 NCOM::CPropVariant prop;
805 if (_folder->GetFolderProperty(kpidIsHash, &prop) == S_OK)
806 if (prop.vt == VT_BOOL)
807 return VARIANT_BOOLToBool(prop.boolVal);
808 }
809 return false;
810}
811
812UString CPanel::GetFsPath() const
813{
814 if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix() && !IsSuperDrivesPrefix())
815 return UString();
816 return _currentFolderPrefix;
817}
818
819UString CPanel::GetDriveOrNetworkPrefix() const
820{
821 if (!IsFSFolder())
822 return UString();
823 UString drive = GetFsPath();
824 drive.DeleteFrom(NFile::NName::GetRootPrefixSize(drive));
825 return drive;
826}
827
828void CPanel::SetListViewMode(UInt32 index)
829{
830 if (index >= 4)
831 return;
832 _ListViewMode = index;
833 DWORD oldStyle = (DWORD)_listView.GetStyle();
834 DWORD newStyle = kStyles[index];
835
836 // DWORD tickCount1 = GetTickCount();
837 if ((oldStyle & LVS_TYPEMASK) != newStyle)
838 _listView.SetStyle((oldStyle & ~LVS_TYPEMASK) | newStyle);
839 // RefreshListCtrlSaveFocused();
840 /*
841 DWORD tickCount2 = GetTickCount();
842 char s[256];
843 sprintf(s, "SetStyle = %5d",
844 tickCount2 - tickCount1
845 );
846 OutputDebugStringA(s);
847 */
848
849}
850
851void CPanel::ChangeFlatMode()
852{
853 _flatMode = !_flatMode;
854 if (_parentFolders.Size() > 0)
855 _flatModeForArc = _flatMode;
856 else
857 _flatModeForDisk = _flatMode;
858 RefreshListCtrl_SaveFocused();
859}
860
861/*
862void CPanel::Change_ShowNtfsStrems_Mode()
863{
864 _showNtfsStrems_Mode = !_showNtfsStrems_Mode;
865 if (_parentFolders.Size() > 0)
866 _showNtfsStrems_ModeForArc = _showNtfsStrems_Mode;
867 else
868 _showNtfsStrems_ModeForDisk = _showNtfsStrems_Mode;
869 RefreshListCtrlSaveFocused();
870}
871*/
872
873void CPanel::Post_Refresh_StatusBar()
874{
875 if (_processStatusBar)
876 PostMsg(kRefresh_StatusBar);
877}
878
879void CPanel::AddToArchive()
880{
881 CRecordVector<UInt32> indices;
882 GetOperatedItemIndices(indices);
883 if (!Is_IO_FS_Folder())
884 {
885 MessageBox_Error_UnsupportOperation();
886 return;
887 }
888 if (indices.Size() == 0)
889 {
890 MessageBox_Error_LangID(IDS_SELECT_FILES);
891 return;
892 }
893 UStringVector names;
894
895 const UString curPrefix = GetFsPath();
896 UString destCurDirPrefix = curPrefix;
897 if (IsFSDrivesFolder())
898 destCurDirPrefix = ROOT_FS_FOLDER;
899
900 FOR_VECTOR (i, indices)
901 names.Add(curPrefix + GetItemRelPath2(indices[i]));
902
903 const UString arcName = CreateArchiveName(names);
904
905 HRESULT res = CompressFiles(destCurDirPrefix, arcName, L"",
906 true, // addExtension
907 names, false, true, false);
908 if (res != S_OK)
909 {
910 if (destCurDirPrefix.Len() >= MAX_PATH)
911 MessageBox_Error_LangID(IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER);
912 }
913 // KillSelection();
914}
915
916// function from ContextMenu.cpp
917UString GetSubFolderNameForExtract(const UString &arcPath);
918
919static UString GetSubFolderNameForExtract2(const UString &arcPath)
920{
921 int slashPos = arcPath.ReverseFind_PathSepar();
922 UString s;
923 UString name = arcPath;
924 if (slashPos >= 0)
925 {
926 s = arcPath.Left((unsigned)(slashPos + 1));
927 name = arcPath.Ptr((unsigned)(slashPos + 1));
928 }
929 s += GetSubFolderNameForExtract(name);
930 return s;
931}
932
933void CPanel::GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths, bool allowFolders)
934{
935 const UString prefix = GetFsPath();
936 FOR_VECTOR (i, indices)
937 {
938 int index = indices[i];
939 if (!allowFolders && IsItem_Folder(index))
940 {
941 paths.Clear();
942 break;
943 }
944 paths.Add(prefix + GetItemRelPath2(index));
945 }
946 if (paths.Size() == 0)
947 {
948 MessageBox_Error_LangID(IDS_SELECT_FILES);
949 return;
950 }
951}
952
953void CPanel::ExtractArchives()
954{
955 if (_parentFolders.Size() > 0)
956 {
957 _panelCallback->OnCopy(false, false);
958 return;
959 }
960 CRecordVector<UInt32> indices;
961 GetOperatedItemIndices(indices);
962 UStringVector paths;
963 GetFilePaths(indices, paths);
964 if (paths.IsEmpty())
965 return;
966
967 UString outFolder = GetFsPath();
968 if (indices.Size() == 1)
969 outFolder += GetSubFolderNameForExtract2(GetItemRelPath(indices[0]));
970 else
971 outFolder += '*';
972 outFolder.Add_PathSepar();
973
974 ::ExtractArchives(paths, outFolder
975 , true // showDialog
976 , false // elimDup
977 );
978}
979
980/*
981static void AddValuePair(UINT resourceID, UInt64 value, UString &s)
982{
983 AddLangString(s, resourceID);
984 char sz[32];
985 s += ": ";
986 ConvertUInt64ToString(value, sz);
987 s += sz;
988 s.Add_LF();
989}
990
991// now we don't need CThreadTest, since now we call CopyTo for "test command
992
993class CThreadTest: public CProgressThreadVirt
994{
995 HRESULT ProcessVirt();
996public:
997 CRecordVector<UInt32> Indices;
998 CExtractCallbackImp *ExtractCallbackSpec;
999 CMyComPtr<IFolderArchiveExtractCallback> ExtractCallback;
1000 CMyComPtr<IArchiveFolder> ArchiveFolder;
1001};
1002
1003HRESULT CThreadTest::ProcessVirt()
1004{
1005 RINOK(ArchiveFolder->Extract(&Indices[0], Indices.Size(),
1006 true, // includeAltStreams
1007 false, // replaceAltStreamColon
1008 NExtract::NPathMode::kFullPathnames,
1009 NExtract::NOverwriteMode::kAskBefore,
1010 NULL, // path
1011 BoolToInt(true), // testMode
1012 ExtractCallback));
1013 if (ExtractCallbackSpec->IsOK())
1014 {
1015 UString s;
1016 AddValuePair(IDS_PROP_FOLDERS, ExtractCallbackSpec->NumFolders, s);
1017 AddValuePair(IDS_PROP_FILES, ExtractCallbackSpec->NumFiles, s);
1018 // AddValuePair(IDS_PROP_SIZE, ExtractCallbackSpec->UnpackSize, s);
1019 // AddSizePair(IDS_COMPRESSED_COLON, Stat.PackSize, s);
1020 s.Add_LF();
1021 AddLangString(s, IDS_MESSAGE_NO_ERRORS);
1022 FinalMessage.OkMessage.Message = s;
1023 }
1024 return S_OK;
1025}
1026
1027static void AddSizePair(UInt32 langID, UInt64 value, UString &s)
1028{
1029 char sz[32];
1030 AddLangString(s, langID);
1031 s += L' ';
1032 ConvertUInt64ToString(value, sz);
1033 s += sz;
1034 ConvertUInt64ToString(value >> 20, sz);
1035 s += " (";
1036 s += sz;
1037 s += " MB)";
1038 s.Add_LF();
1039}
1040*/
1041
1042void CPanel::TestArchives()
1043{
1044 CRecordVector<UInt32> indices;
1045 GetOperatedIndicesSmart(indices);
1046 CMyComPtr<IArchiveFolder> archiveFolder;
1047 _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder);
1048 if (archiveFolder)
1049 {
1050 CCopyToOptions options;
1051 options.streamMode = true;
1052 options.showErrorMessages = true;
1053 options.testMode = true;
1054
1055 UStringVector messages;
1056 HRESULT res = CopyTo(options, indices, &messages);
1057 if (res != S_OK)
1058 {
1059 if (res != E_ABORT)
1060 MessageBox_Error_HRESULT(res);
1061 }
1062 return;
1063
1064 /*
1065 {
1066 CThreadTest extracter;
1067
1068 extracter.ArchiveFolder = archiveFolder;
1069 extracter.ExtractCallbackSpec = new CExtractCallbackImp;
1070 extracter.ExtractCallback = extracter.ExtractCallbackSpec;
1071 extracter.ExtractCallbackSpec->ProgressDialog = &extracter.ProgressDialog;
1072 if (!_parentFolders.IsEmpty())
1073 {
1074 const CFolderLink &fl = _parentFolders.Back();
1075 extracter.ExtractCallbackSpec->PasswordIsDefined = fl.UsePassword;
1076 extracter.ExtractCallbackSpec->Password = fl.Password;
1077 }
1078
1079 if (indices.IsEmpty())
1080 return;
1081
1082 extracter.Indices = indices;
1083
1084 UString title = LangString(IDS_PROGRESS_TESTING);
1085
1086 extracter.ProgressDialog.CompressingMode = false;
1087 extracter.ProgressDialog.MainWindow = GetParent();
1088 extracter.ProgressDialog.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
1089 extracter.ProgressDialog.MainAddTitle = title + L' ';
1090
1091 extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
1092 extracter.ExtractCallbackSpec->Init();
1093
1094 if (extracter.Create(title, GetParent()) != S_OK)
1095 return;
1096
1097 }
1098 RefreshTitleAlways();
1099 return;
1100 */
1101 }
1102
1103 if (!IsFSFolder())
1104 {
1105 MessageBox_Error_UnsupportOperation();
1106 return;
1107 }
1108 UStringVector paths;
1109 GetFilePaths(indices, paths, true);
1110 if (paths.IsEmpty())
1111 return;
1112 ::TestArchives(paths);
1113}
diff --git a/CPP/7zip/UI/FileManager/Panel.h b/CPP/7zip/UI/FileManager/Panel.h
new file mode 100644
index 0000000..d1e4d24
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Panel.h
@@ -0,0 +1,926 @@
1// Panel.h
2
3#ifndef __PANEL_H
4#define __PANEL_H
5
6#include "../../../Common/MyWindows.h"
7
8#include <ShlObj.h>
9
10#include "../../../../C/Alloc.h"
11
12#include "../../../Common/Defs.h"
13#include "../../../Common/MyCom.h"
14
15#include "../../../Windows/DLL.h"
16#include "../../../Windows/FileDir.h"
17#include "../../../Windows/FileFind.h"
18#include "../../../Windows/FileName.h"
19#include "../../../Windows/Handle.h"
20#include "../../../Windows/PropVariantConv.h"
21#include "../../../Windows/Synchronization.h"
22
23#include "../../../Windows/Control/ComboBox.h"
24#include "../../../Windows/Control/Edit.h"
25#include "../../../Windows/Control/ListView.h"
26#include "../../../Windows/Control/ReBar.h"
27#include "../../../Windows/Control/Static.h"
28#include "../../../Windows/Control/StatusBar.h"
29#include "../../../Windows/Control/ToolBar.h"
30#include "../../../Windows/Control/Window2.h"
31
32#include "../../Archive/IArchive.h"
33
34#include "ExtractCallback.h"
35
36#include "AppState.h"
37#include "IFolder.h"
38#include "MyCom2.h"
39#include "ProgressDialog2.h"
40#include "SysIconUtils.h"
41
42#ifdef UNDER_CE
43#define NON_CE_VAR(_v_)
44#else
45#define NON_CE_VAR(_v_) _v_
46#endif
47
48const int kParentFolderID = 100;
49
50const int kParentIndex = -1;
51const UInt32 kParentIndex_UInt32 = (UInt32)(Int32)kParentIndex;
52
53#if !defined(_WIN32) || defined(UNDER_CE)
54#define ROOT_FS_FOLDER L"\\"
55#else
56#define ROOT_FS_FOLDER L"C:\\"
57#endif
58
59struct CPanelCallback
60{
61 virtual void OnTab() = 0;
62 virtual void SetFocusToPath(unsigned index) = 0;
63 virtual void OnCopy(bool move, bool copyToSame) = 0;
64 virtual void OnSetSameFolder() = 0;
65 virtual void OnSetSubFolder() = 0;
66 virtual void PanelWasFocused() = 0;
67 virtual void DragBegin() = 0;
68 virtual void DragEnd() = 0;
69 virtual void RefreshTitle(bool always) = 0;
70};
71
72void PanelCopyItems();
73
74
75struct CPropColumn
76{
77 int Order;
78 PROPID ID;
79 VARTYPE Type;
80 bool IsVisible;
81 bool IsRawProp;
82 UInt32 Width;
83 UString Name;
84
85 bool IsEqualTo(const CPropColumn &a) const
86 {
87 return Order == a.Order
88 && ID == a.ID
89 && Type == a.Type
90 && IsVisible == a.IsVisible
91 && IsRawProp == a.IsRawProp
92 && Width == a.Width
93 && Name == a.Name;
94 }
95
96 int Compare(const CPropColumn &a) const { return MyCompare(Order, a.Order); }
97
98 int Compare_NameFirst(const CPropColumn &a) const
99 {
100 if (ID == kpidName)
101 {
102 if (a.ID != kpidName)
103 return -1;
104 }
105 else if (a.ID == kpidName)
106 return 1;
107 return MyCompare(Order, a.Order);
108 }
109};
110
111
112class CPropColumns: public CObjectVector<CPropColumn>
113{
114public:
115 int FindItem_for_PropID(PROPID id) const
116 {
117 FOR_VECTOR (i, (*this))
118 if ((*this)[i].ID == id)
119 return i;
120 return -1;
121 }
122
123 bool IsEqualTo(const CPropColumns &props) const
124 {
125 if (Size() != props.Size())
126 return false;
127 FOR_VECTOR (i, (*this))
128 if (!(*this)[i].IsEqualTo(props[i]))
129 return false;
130 return true;
131 }
132};
133
134
135struct CTempFileInfo
136{
137 UInt32 FileIndex; // index of file in folder
138 UString RelPath; // Relative path of file from Folder
139 FString FolderPath;
140 FString FilePath;
141 NWindows::NFile::NFind::CFileInfo FileInfo;
142 bool NeedDelete;
143
144 CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {}
145 void DeleteDirAndFile() const
146 {
147 if (NeedDelete)
148 {
149 NWindows::NFile::NDir::DeleteFileAlways(FilePath);
150 NWindows::NFile::NDir::RemoveDir(FolderPath);
151 }
152 }
153 bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
154 {
155 return newFileInfo.Size != FileInfo.Size ||
156 CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0;
157 }
158};
159
160struct CFolderLink: public CTempFileInfo
161{
162 NWindows::NDLL::CLibrary Library;
163 CMyComPtr<IFolderFolder> ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0])
164 UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level)
165 bool UsePassword;
166 UString Password;
167 bool IsVirtual;
168
169 UString VirtualPath; // without tail slash
170 CFolderLink(): UsePassword(false), IsVirtual(false) {}
171
172 bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const
173 {
174 return IsVirtual || CTempFileInfo::WasChanged(newFileInfo);
175 }
176
177};
178
179enum MyMessages
180{
181 // we can use WM_USER, since we have defined new window class.
182 // so we don't need WM_APP.
183 kShiftSelectMessage = WM_USER + 1,
184 kReLoadMessage,
185 kSetFocusToListView,
186 kOpenItemChanged,
187 kRefresh_StatusBar
188 #ifdef UNDER_CE
189 , kRefresh_HeaderComboBox
190 #endif
191};
192
193UString GetFolderPath(IFolderFolder *folder);
194
195class CPanel;
196
197class CMyListView: public NWindows::NControl::CListView2
198{
199public:
200 CPanel *_panel;
201 LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
202};
203
204/*
205class CMyComboBox: public NWindows::NControl::CComboBoxEx
206{
207public:
208 WNDPROC _origWindowProc;
209 CPanel *_panel;
210 LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
211};
212*/
213class CMyComboBoxEdit: public NWindows::NControl::CEdit
214{
215public:
216 WNDPROC _origWindowProc;
217 CPanel *_panel;
218 LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
219};
220
221struct CSelectedState
222{
223 int FocusedItem;
224 bool SelectFocused;
225 bool FocusedName_Defined;
226 UString FocusedName;
227 UStringVector SelectedNames;
228
229 CSelectedState(): FocusedItem(-1), SelectFocused(true), FocusedName_Defined(false) {}
230};
231
232#ifdef UNDER_CE
233#define MY_NMLISTVIEW_NMITEMACTIVATE NMLISTVIEW
234#else
235#define MY_NMLISTVIEW_NMITEMACTIVATE NMITEMACTIVATE
236#endif
237
238struct CCopyToOptions
239{
240 bool streamMode;
241 bool moveMode;
242 bool testMode;
243 bool includeAltStreams;
244 bool replaceAltStreamChars;
245 bool showErrorMessages;
246
247 UString folder;
248
249 UStringVector hashMethods;
250
251 CVirtFileSystem *VirtFileSystemSpec;
252 ISequentialOutStream *VirtFileSystem;
253
254 CCopyToOptions():
255 streamMode(false),
256 moveMode(false),
257 testMode(false),
258 includeAltStreams(true),
259 replaceAltStreamChars(false),
260 showErrorMessages(false),
261 VirtFileSystemSpec(NULL),
262 VirtFileSystem(NULL)
263 {}
264};
265
266
267
268struct COpenResult
269{
270 // bool needOpenArc;
271 // out:
272 bool ArchiveIsOpened;
273 bool Encrypted;
274 UString ErrorMessage;
275
276 COpenResult():
277 // needOpenArc(false),
278 ArchiveIsOpened(false), Encrypted(false) {}
279};
280
281
282
283
284class CPanel: public NWindows::NControl::CWindow2
285{
286 CExtToIconMap _extToIconMap;
287 UINT _baseID;
288 int _comboBoxID;
289 UINT _statusBarID;
290
291 CAppState *_appState;
292
293 bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result);
294 LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
295 virtual bool OnCreate(CREATESTRUCT *createStruct);
296 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
297 virtual void OnDestroy();
298 virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result);
299
300 void AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList);
301
302 bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result);
303
304 #ifndef UNDER_CE
305
306 LRESULT OnNotifyComboBoxEnter(const UString &s);
307 bool OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result);
308 #ifndef _UNICODE
309 bool OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result);
310 #endif
311
312 #endif
313
314 bool OnNotifyReBar(LPNMHDR lParam, LRESULT &result);
315 bool OnNotifyComboBox(LPNMHDR lParam, LRESULT &result);
316 void OnItemChanged(NMLISTVIEW *item);
317 void OnNotifyActivateItems();
318 bool OnNotifyList(LPNMHDR lParam, LRESULT &result);
319 void OnDrag(LPNMLISTVIEW nmListView);
320 bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result);
321 BOOL OnBeginLabelEdit(LV_DISPINFOW * lpnmh);
322 BOOL OnEndLabelEdit(LV_DISPINFOW * lpnmh);
323 void OnColumnClick(LPNMLISTVIEW info);
324 bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result);
325
326
327public:
328 HWND _mainWindow;
329 CPanelCallback *_panelCallback;
330
331 void SysIconsWereChanged() { _extToIconMap.Clear(); }
332
333 void DeleteItems(bool toRecycleBin);
334 void CreateFolder();
335 void CreateFile();
336 bool CorrectFsPath(const UString &path, UString &result);
337 // bool IsPathForPlugin(const UString &path);
338
339private:
340
341 void ChangeWindowSize(int xSize, int ySize);
342
343 HRESULT InitColumns();
344 void DeleteColumn(unsigned index);
345 void AddColumn(const CPropColumn &prop);
346
347 void SetFocusedSelectedItem(int index, bool select);
348
349 void OnShiftSelectMessage();
350 void OnArrowWithShift();
351
352 void OnInsert();
353 // void OnUpWithShift();
354 // void OnDownWithShift();
355public:
356 void UpdateSelection();
357 void SelectSpec(bool selectMode);
358 void SelectByType(bool selectMode);
359 void SelectAll(bool selectMode);
360 void InvertSelection();
361private:
362
363 // UString GetFileType(UInt32 index);
364 LRESULT SetItemText(LVITEMW &item);
365
366 // CRecordVector<PROPID> m_ColumnsPropIDs;
367
368public:
369 NWindows::NControl::CReBar _headerReBar;
370 NWindows::NControl::CToolBar _headerToolBar;
371 NWindows::NControl::
372 #ifdef UNDER_CE
373 CComboBox
374 #else
375 CComboBoxEx
376 #endif
377 _headerComboBox;
378 UStringVector ComboBoxPaths;
379 // CMyComboBox _headerComboBox;
380 CMyComboBoxEdit _comboBoxEdit;
381 CMyListView _listView;
382 bool _thereAre_ListView_Items;
383 NWindows::NControl::CStatusBar _statusBar;
384 bool _lastFocusedIsList;
385 // NWindows::NControl::CStatusBar _statusBar2;
386
387 DWORD _exStyle;
388 bool _showDots;
389 bool _showRealFileIcons;
390 // bool _virtualMode;
391 // CUIntVector _realIndices;
392 bool _enableItemChangeNotify;
393 bool _mySelectMode;
394
395 int _timestampLevel;
396
397
398 void RedrawListItems()
399 {
400 _listView.RedrawAllItems();
401 }
402
403
404 CBoolVector _selectedStatusVector;
405
406 CSelectedState _selectedState;
407 bool _thereAreDeletedItems;
408 bool _markDeletedItems;
409
410 bool PanelCreated;
411
412 void DeleteListItems()
413 {
414 if (_thereAre_ListView_Items)
415 {
416 bool b = _enableItemChangeNotify;
417 _enableItemChangeNotify = false;
418 _listView.DeleteAllItems();
419 _thereAre_ListView_Items = false;
420 _enableItemChangeNotify = b;
421 }
422 }
423
424 HWND GetParent() const;
425
426 UInt32 GetRealIndex(const LVITEMW &item) const
427 {
428 /*
429 if (_virtualMode)
430 return _realIndices[item.iItem];
431 */
432 return (UInt32)item.lParam;
433 }
434
435 int GetRealItemIndex(int indexInListView) const
436 {
437 /*
438 if (_virtualMode)
439 return indexInListView;
440 */
441 LPARAM param;
442 if (!_listView.GetItemParam(indexInListView, param))
443 throw 1;
444 return (int)param;
445 }
446
447 UInt32 _ListViewMode;
448 int _xSize;
449
450 bool _flatMode;
451 bool _flatModeForDisk;
452 bool _flatModeForArc;
453
454 // bool _showNtfsStrems_Mode;
455 // bool _showNtfsStrems_ModeForDisk;
456 // bool _showNtfsStrems_ModeForArc;
457
458 bool _dontShowMode;
459
460
461 UString _currentFolderPrefix;
462
463 CObjectVector<CFolderLink> _parentFolders;
464 NWindows::NDLL::CLibrary _library;
465
466 CMyComPtr<IFolderFolder> _folder;
467 CMyComPtr<IFolderCompare> _folderCompare;
468 CMyComPtr<IFolderGetItemName> _folderGetItemName;
469 CMyComPtr<IArchiveGetRawProps> _folderRawProps;
470 CMyComPtr<IFolderAltStreams> _folderAltStreams;
471 CMyComPtr<IFolderOperations> _folderOperations;
472
473 void ReleaseFolder();
474 void SetNewFolder(IFolderFolder *newFolder);
475
476 // CMyComPtr<IFolderGetSystemIconIndex> _folderGetSystemIconIndex;
477
478 UStringVector _fastFolders;
479
480 void GetSelectedNames(UStringVector &selectedNames);
481 void SaveSelectedState(CSelectedState &s);
482 HRESULT RefreshListCtrl(const CSelectedState &s);
483 HRESULT RefreshListCtrl_SaveFocused();
484
485 bool GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const;
486 bool IsItem_Deleted(int itemIndex) const;
487 bool IsItem_Folder(int itemIndex) const;
488 bool IsItem_AltStream(int itemIndex) const;
489
490 UString GetItemName(int itemIndex) const;
491 UString GetItemName_for_Copy(int itemIndex) const;
492 void GetItemName(int itemIndex, UString &s) const;
493 UString GetItemPrefix(int itemIndex) const;
494 UString GetItemRelPath(int itemIndex) const;
495 UString GetItemRelPath2(int itemIndex) const;
496 UString GetItemFullPath(int itemIndex) const;
497 UInt64 GetItem_UInt64Prop(int itemIndex, PROPID propID) const;
498 UInt64 GetItemSize(int itemIndex) const;
499
500 ////////////////////////
501 // PanelFolderChange.cpp
502
503 void SetToRootFolder();
504 HRESULT BindToPath(const UString &fullPath, const UString &arcFormat, COpenResult &openRes); // can be prefix
505 HRESULT BindToPathAndRefresh(const UString &path);
506 void OpenDrivesFolder();
507
508 void SetBookmark(unsigned index);
509 void OpenBookmark(unsigned index);
510
511 void LoadFullPath();
512 void LoadFullPathAndShow();
513 void FoldersHistory();
514 void OpenParentFolder();
515 void CloseOneLevel();
516 void CloseOpenFolders();
517 void OpenRootFolder();
518
519 UString GetParentDirPrefix() const;
520
521 HRESULT Create(HWND mainWindow, HWND parentWindow,
522 UINT id,
523 const UString &currentFolderPrefix,
524 const UString &arcFormat,
525 CPanelCallback *panelCallback,
526 CAppState *appState,
527 bool needOpenArc,
528 COpenResult &openRes);
529
530 void SetFocusToList();
531 void SetFocusToLastRememberedItem();
532
533
534 void SaveListViewInfo();
535
536 CPanel() :
537 _thereAre_ListView_Items(false),
538 _exStyle(0),
539 _showDots(false),
540 _showRealFileIcons(false),
541 // _virtualMode(flase),
542 _enableItemChangeNotify(true),
543 _mySelectMode(false),
544 _timestampLevel(kTimestampPrintLevel_MIN),
545
546 _thereAreDeletedItems(false),
547 _markDeletedItems(true),
548 PanelCreated(false),
549
550 _ListViewMode(3),
551 _xSize(300),
552
553 _flatMode(false),
554 _flatModeForDisk(false),
555 _flatModeForArc(false),
556
557 // _showNtfsStrems_Mode(false),
558 // _showNtfsStrems_ModeForDisk(false),
559 // _showNtfsStrems_ModeForArc(false),
560
561 _dontShowMode(false),
562
563 _needSaveInfo(false),
564 _startGroupSelect(0),
565 _selectionIsDefined(false)
566 {}
567
568 void SetExtendedStyle()
569 {
570 if (_listView != 0)
571 _listView.SetExtendedListViewStyle(_exStyle);
572 }
573
574
575 bool _needSaveInfo;
576 UString _typeIDString;
577 CListViewInfo _listViewInfo;
578
579 CPropColumns _columns;
580 CPropColumns _visibleColumns;
581
582 PROPID _sortID;
583 // int _sortIndex;
584 bool _ascending;
585 Int32 _isRawSortProp;
586
587 void SetSortRawStatus();
588
589 void Release();
590 ~CPanel();
591 void OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate);
592 bool OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate, LRESULT &result);
593 void ShowColumnsContextMenu(int x, int y);
594
595 void OnTimer();
596 void OnReload();
597 bool OnContextMenu(HANDLE windowHandle, int xPos, int yPos);
598
599 CMyComPtr<IContextMenu> _sevenZipContextMenu;
600 CMyComPtr<IContextMenu> _systemContextMenu;
601 HRESULT CreateShellContextMenu(
602 const CRecordVector<UInt32> &operatedIndices,
603 CMyComPtr<IContextMenu> &systemContextMenu);
604 void CreateSystemMenu(HMENU menu,
605 const CRecordVector<UInt32> &operatedIndices,
606 CMyComPtr<IContextMenu> &systemContextMenu);
607 void CreateSevenZipMenu(HMENU menu,
608 const CRecordVector<UInt32> &operatedIndices,
609 CMyComPtr<IContextMenu> &sevenZipContextMenu);
610 void CreateFileMenu(HMENU menu,
611 CMyComPtr<IContextMenu> &sevenZipContextMenu,
612 CMyComPtr<IContextMenu> &systemContextMenu,
613 bool programMenu);
614 void CreateFileMenu(HMENU menu);
615 bool InvokePluginCommand(unsigned id);
616 bool InvokePluginCommand(unsigned id, IContextMenu *sevenZipContextMenu,
617 IContextMenu *systemContextMenu);
618
619 void InvokeSystemCommand(const char *command);
620 void Properties();
621 void EditCut();
622 void EditCopy();
623 void EditPaste();
624
625 int _startGroupSelect;
626
627 bool _selectionIsDefined;
628 bool _selectMark;
629 int _prevFocusedItem;
630
631
632 // void SortItems(int index);
633 void SortItemsWithPropID(PROPID propID);
634
635 void GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const;
636 void GetOperatedItemIndices(CRecordVector<UInt32> &indices) const;
637 void GetAllItemIndices(CRecordVector<UInt32> &indices) const;
638 void GetOperatedIndicesSmart(CRecordVector<UInt32> &indices) const;
639 // void GetOperatedListViewIndices(CRecordVector<UInt32> &indices) const;
640 void KillSelection();
641
642 UString GetFolderTypeID() const;
643
644 bool IsFolderTypeEqTo(const char *s) const;
645 bool IsRootFolder() const;
646 bool IsFSFolder() const;
647 bool IsFSDrivesFolder() const;
648 bool IsAltStreamsFolder() const;
649 bool IsArcFolder() const;
650 bool IsHashFolder() const;
651
652 /*
653 c:\Dir
654 Computer\
655 \\?\
656 \\.\
657 */
658 bool Is_IO_FS_Folder() const
659 {
660 return IsFSFolder() || IsFSDrivesFolder() || IsAltStreamsFolder();
661 }
662
663 bool Is_Slow_Icon_Folder() const
664 {
665 return IsFSFolder() || IsAltStreamsFolder();
666 }
667
668 // bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); }
669 bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; }
670 bool IsSuperDrivesPrefix() const { return _currentFolderPrefix == L"\\\\?\\"; }
671
672 /*
673 c:\Dir
674 Computer\
675 \\?\
676 */
677 bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); }
678
679 /*
680 c:\Dir
681 Computer\
682 \\?\
683 \\SERVER\
684 */
685 bool IsFolder_with_FsItems() const
686 {
687 if (IsFsOrPureDrivesFolder())
688 return true;
689 #if defined(_WIN32) && !defined(UNDER_CE)
690 FString prefix = us2fs(GetFsPath());
691 return (prefix.Len() == NWindows::NFile::NName::GetNetworkServerPrefixSize(prefix));
692 #else
693 return false;
694 #endif
695 }
696
697 UString GetFsPath() const;
698 UString GetDriveOrNetworkPrefix() const;
699
700 bool DoesItSupportOperations() const { return _folderOperations != NULL; }
701 bool IsThereReadOnlyFolder() const;
702 bool CheckBeforeUpdate(UINT resourceID);
703
704 bool _processTimer;
705 bool _processNotify;
706 bool _processStatusBar;
707
708 class CDisableTimerProcessing
709 {
710 CLASS_NO_COPY(CDisableTimerProcessing);
711
712 bool _processTimer;
713
714 CPanel &_panel;
715
716 public:
717
718 CDisableTimerProcessing(CPanel &panel): _panel(panel) { Disable(); }
719 ~CDisableTimerProcessing() { Restore(); }
720 void Disable()
721 {
722 _processTimer = _panel._processTimer;
723 _panel._processTimer = false;
724 }
725 void Restore()
726 {
727 _panel._processTimer = _processTimer;
728 }
729 };
730
731 class CDisableNotify
732 {
733 CLASS_NO_COPY(CDisableNotify);
734
735 bool _processNotify;
736 bool _processStatusBar;
737
738 CPanel &_panel;
739
740 public:
741
742 CDisableNotify(CPanel &panel): _panel(panel) { Disable(); }
743 ~CDisableNotify() { Restore(); }
744 void Disable()
745 {
746 _processNotify = _panel._processNotify;
747 _processStatusBar = _panel._processStatusBar;
748 _panel._processNotify = false;
749 _panel._processStatusBar = false;
750 }
751 void SetMemMode_Enable()
752 {
753 _processNotify = true;
754 _processStatusBar = true;
755 }
756 void Restore()
757 {
758 _panel._processNotify = _processNotify;
759 _panel._processStatusBar = _processStatusBar;
760 }
761 };
762
763 void InvalidateList() { _listView.InvalidateRect(NULL, true); }
764
765 HRESULT RefreshListCtrl();
766
767
768 // void MessageBox_Info(LPCWSTR message, LPCWSTR caption) const;
769 // void MessageBox_Warning(LPCWSTR message) const;
770 void MessageBox_Error_Caption(LPCWSTR message, LPCWSTR caption) const;
771 void MessageBox_Error(LPCWSTR message) const;
772 void MessageBox_Error_HRESULT_Caption(HRESULT errorCode, LPCWSTR caption) const;
773 void MessageBox_Error_HRESULT(HRESULT errorCode) const;
774 void MessageBox_Error_2Lines_Message_HRESULT(LPCWSTR message, HRESULT errorCode) const;
775 void MessageBox_LastError(LPCWSTR caption) const;
776 void MessageBox_LastError() const;
777 void MessageBox_Error_LangID(UINT resourceID) const;
778 void MessageBox_Error_UnsupportOperation() const;
779 // void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID);
780
781
782 void OpenAltStreams();
783
784 void OpenFocusedItemAsInternal(const wchar_t *type = NULL);
785 void OpenSelectedItems(bool internal);
786
787 void OpenFolderExternal(int index);
788
789 void OpenFolder(int index);
790 HRESULT OpenParentArchiveFolder();
791
792 HRESULT OpenAsArc(IInStream *inStream,
793 const CTempFileInfo &tempFileInfo,
794 const UString &virtualFilePath,
795 const UString &arcFormat,
796 COpenResult &openRes);
797
798 HRESULT OpenAsArc_Msg(IInStream *inStream,
799 const CTempFileInfo &tempFileInfo,
800 const UString &virtualFilePath,
801 const UString &arcFormat
802 // , bool showErrorMessage
803 );
804
805 HRESULT OpenAsArc_Name(const UString &relPath, const UString &arcFormat
806 // , bool showErrorMessage
807 );
808 HRESULT OpenAsArc_Index(int index, const wchar_t *type /* = NULL */
809 // , bool showErrorMessage
810 );
811
812 void OpenItemInArchive(int index, bool tryInternal, bool tryExternal,
813 bool editMode, bool useEditor, const wchar_t *type = NULL);
814
815 HRESULT OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, bool usePassword, const UString &password);
816 LRESULT OnOpenItemChanged(LPARAM lParam);
817
818 bool IsVirus_Message(const UString &name);
819 void OpenItem(int index, bool tryInternal, bool tryExternal, const wchar_t *type = NULL);
820 void EditItem(bool useEditor);
821 void EditItem(int index, bool useEditor);
822
823 void RenameFile();
824 void ChangeComment();
825
826 void SetListViewMode(UInt32 index);
827 UInt32 GetListViewMode() const { return _ListViewMode; }
828 PROPID GetSortID() const { return _sortID; }
829
830 void ChangeFlatMode();
831 void Change_ShowNtfsStrems_Mode();
832 bool GetFlatMode() const { return _flatMode; }
833 // bool Get_ShowNtfsStrems_Mode() const { return _showNtfsStrems_Mode; }
834
835 bool AutoRefresh_Mode;
836 void Set_AutoRefresh_Mode(bool mode)
837 {
838 AutoRefresh_Mode = mode;
839 }
840
841 void Post_Refresh_StatusBar();
842 void Refresh_StatusBar();
843
844 void AddToArchive();
845
846 void GetFilePaths(const CRecordVector<UInt32> &indices, UStringVector &paths, bool allowFolders = false);
847 void ExtractArchives();
848 void TestArchives();
849
850 HRESULT CopyTo(CCopyToOptions &options,
851 const CRecordVector<UInt32> &indices,
852 UStringVector *messages,
853 bool &usePassword, UString &password);
854
855 HRESULT CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &indices, UStringVector *messages)
856 {
857 bool usePassword = false;
858 UString password;
859 if (_parentFolders.Size() > 0)
860 {
861 const CFolderLink &fl = _parentFolders.Back();
862 usePassword = fl.UsePassword;
863 password = fl.Password;
864 }
865 return CopyTo(options, indices, messages, usePassword, password);
866 }
867
868 HRESULT CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
869 bool showErrorMessages, UStringVector *messages);
870
871 void CopyFromNoAsk(const UStringVector &filePaths);
872 void CopyFromAsk(const UStringVector &filePaths);
873
874 // empty folderPath means create new Archive to path of first fileName.
875 void DropObject(IDataObject * dataObject, const UString &folderPath);
876
877 // empty folderPath means create new Archive to path of first fileName.
878 void CompressDropFiles(const UStringVector &fileNames, const UString &folderPath);
879
880 void RefreshTitle(bool always = false) { _panelCallback->RefreshTitle(always); }
881 void RefreshTitleAlways() { RefreshTitle(true); }
882
883 UString GetItemsInfoString(const CRecordVector<UInt32> &indices);
884};
885
886class CMyBuffer
887{
888 void *_data;
889public:
890 CMyBuffer(): _data(0) {}
891 operator void *() { return _data; }
892 bool Allocate(size_t size)
893 {
894 if (_data != 0)
895 return false;
896 _data = ::MidAlloc(size);
897 return _data != 0;
898 }
899 ~CMyBuffer() { ::MidFree(_data); }
900};
901
902class CExitEventLauncher
903{
904public:
905 NWindows::NSynchronization::CManualResetEvent _exitEvent;
906 bool _needExit;
907 CRecordVector< ::CThread > _threads;
908 unsigned _numActiveThreads;
909
910 CExitEventLauncher()
911 {
912 _needExit = false;
913 if (_exitEvent.Create(false) != S_OK)
914 throw 9387173;
915 _needExit = true;
916 _numActiveThreads = 0;
917 };
918
919 ~CExitEventLauncher() { Exit(true); }
920
921 void Exit(bool hardExit);
922};
923
924extern CExitEventLauncher g_ExitEventLauncher;
925
926#endif
diff --git a/CPP/7zip/UI/FileManager/PanelCopy.cpp b/CPP/7zip/UI/FileManager/PanelCopy.cpp
new file mode 100644
index 0000000..7e1937c
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelCopy.cpp
@@ -0,0 +1,410 @@
1/// PanelCopy.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyException.h"
6
7#include "../GUI/HashGUI.h"
8
9#include "ExtractCallback.h"
10#include "LangUtils.h"
11#include "Panel.h"
12#include "resource.h"
13#include "UpdateCallback100.h"
14
15using namespace NWindows;
16
17class CPanelCopyThread: public CProgressThreadVirt
18{
19 bool ResultsWereShown;
20 bool NeedShowRes;
21
22 HRESULT ProcessVirt();
23 virtual void ProcessWasFinished_GuiVirt();
24public:
25 const CCopyToOptions *options;
26 CMyComPtr<IFolderOperations> FolderOperations;
27 CRecordVector<UInt32> Indices;
28 CExtractCallbackImp *ExtractCallbackSpec;
29 CMyComPtr<IFolderOperationsExtractCallback> ExtractCallback;
30
31 CHashBundle Hash;
32 // UString FirstFilePath;
33
34 // HRESULT Result2;
35
36 void ShowFinalResults(HWND hwnd);
37
38 CPanelCopyThread():
39 ResultsWereShown(false),
40 NeedShowRes(false)
41 // , Result2(E_FAIL)
42 {}
43};
44
45void CPanelCopyThread::ShowFinalResults(HWND hwnd)
46{
47 if (NeedShowRes)
48 if (!ResultsWereShown)
49 {
50 ResultsWereShown = true;
51 ShowHashResults(Hash, hwnd);
52 }
53}
54
55void CPanelCopyThread::ProcessWasFinished_GuiVirt()
56{
57 ShowFinalResults(*this);
58}
59
60HRESULT CPanelCopyThread::ProcessVirt()
61{
62 /*
63 CMyComPtr<IFolderSetReplaceAltStreamCharsMode> iReplace;
64 FolderOperations.QueryInterface(IID_IFolderSetReplaceAltStreamCharsMode, &iReplace);
65 if (iReplace)
66 {
67 RINOK(iReplace->SetReplaceAltStreamCharsMode(ReplaceAltStreamChars ? 1 : 0));
68 }
69 */
70
71 HRESULT result2;
72
73 if (options->testMode)
74 {
75 CMyComPtr<IArchiveFolder> archiveFolder;
76 FolderOperations.QueryInterface(IID_IArchiveFolder, &archiveFolder);
77 if (!archiveFolder)
78 return E_NOTIMPL;
79 CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
80 RINOK(ExtractCallback.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2));
81 NExtract::NPathMode::EEnum pathMode =
82 NExtract::NPathMode::kCurPaths;
83 // NExtract::NPathMode::kFullPathnames;
84 result2 = archiveFolder->Extract(&Indices.Front(), Indices.Size(),
85 BoolToInt(options->includeAltStreams),
86 BoolToInt(options->replaceAltStreamChars),
87 pathMode, NExtract::NOverwriteMode::kAsk,
88 options->folder, BoolToInt(true), extractCallback2);
89 }
90 else
91 result2 = FolderOperations->CopyTo(
92 BoolToInt(options->moveMode),
93 &Indices.Front(), Indices.Size(),
94 BoolToInt(options->includeAltStreams),
95 BoolToInt(options->replaceAltStreamChars),
96 options->folder, ExtractCallback);
97
98 if (result2 == S_OK && !ExtractCallbackSpec->ThereAreMessageErrors)
99 {
100 if (!options->hashMethods.IsEmpty())
101 NeedShowRes = true;
102 else if (options->testMode)
103 {
104 CProgressMessageBoxPair &pair = GetMessagePair(false); // GetMessagePair(ExtractCallbackSpec->Hash.NumErrors != 0);
105 AddHashBundleRes(pair.Message, Hash);
106 }
107 }
108
109 return result2;
110}
111
112
113/*
114#ifdef EXTERNAL_CODECS
115
116static void ThrowException_if_Error(HRESULT res)
117{
118 if (res != S_OK)
119 throw CSystemException(res);
120}
121
122#endif
123*/
124
125HRESULT CPanel::CopyTo(CCopyToOptions &options, const CRecordVector<UInt32> &indices,
126 UStringVector *messages,
127 bool &usePassword, UString &password)
128{
129 if (IsHashFolder())
130 {
131 if (!options.testMode)
132 return E_NOTIMPL;
133 }
134
135 if (!_folderOperations)
136 {
137 UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
138 if (options.showErrorMessages)
139 MessageBox_Error(errorMessage);
140 else if (messages)
141 messages->Add(errorMessage);
142 return E_FAIL;
143 }
144
145 HRESULT res = S_OK;
146
147 {
148 /*
149 #ifdef EXTERNAL_CODECS
150 CExternalCodecs g_ExternalCodecs;
151 #endif
152 */
153 /* extracter.Hash uses g_ExternalCodecs
154 extracter must be declared after g_ExternalCodecs for correct destructor order !!! */
155
156 CPanelCopyThread extracter;
157
158 extracter.ExtractCallbackSpec = new CExtractCallbackImp;
159 extracter.ExtractCallback = extracter.ExtractCallbackSpec;
160
161 extracter.options = &options;
162 extracter.ExtractCallbackSpec->ProgressDialog = &extracter;
163 extracter.CompressingMode = false;
164
165 extracter.ExtractCallbackSpec->StreamMode = options.streamMode;
166
167
168 if (indices.Size() == 1)
169 {
170 extracter.Hash.FirstFileName = GetItemRelPath(indices[0]);
171 extracter.Hash.MainName = extracter.Hash.FirstFileName;
172 }
173
174 if (options.VirtFileSystem)
175 {
176 extracter.ExtractCallbackSpec->VirtFileSystem = options.VirtFileSystem;
177 extracter.ExtractCallbackSpec->VirtFileSystemSpec = options.VirtFileSystemSpec;
178 }
179 extracter.ExtractCallbackSpec->ProcessAltStreams = options.includeAltStreams;
180
181 if (!options.hashMethods.IsEmpty())
182 {
183 /* this code is used when we call CRC calculation for files in side archive
184 But new code uses global codecs so we don't need to call LoadGlobalCodecs again */
185
186 /*
187 #ifdef EXTERNAL_CODECS
188 ThrowException_if_Error(LoadGlobalCodecs());
189 #endif
190 */
191
192 extracter.Hash.SetMethods(EXTERNAL_CODECS_VARS_G options.hashMethods);
193 extracter.ExtractCallbackSpec->SetHashMethods(&extracter.Hash);
194 }
195 else if (options.testMode)
196 {
197 extracter.ExtractCallbackSpec->SetHashCalc(&extracter.Hash);
198 }
199
200 // extracter.Hash.Init();
201
202 UString title;
203 {
204 UInt32 titleID = IDS_COPYING;
205 if (options.moveMode)
206 titleID = IDS_MOVING;
207 else if (!options.hashMethods.IsEmpty() && options.streamMode)
208 {
209 titleID = IDS_CHECKSUM_CALCULATING;
210 if (options.hashMethods.Size() == 1)
211 {
212 const UString &s = options.hashMethods[0];
213 if (s != L"*")
214 title = s;
215 }
216 }
217 else if (options.testMode)
218 titleID = IDS_PROGRESS_TESTING;
219
220 if (title.IsEmpty())
221 title = LangString(titleID);
222 }
223
224 UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
225
226 extracter.MainWindow = GetParent();
227 extracter.MainTitle = progressWindowTitle;
228 extracter.MainAddTitle = title + L' ';
229
230 extracter.ExtractCallbackSpec->OverwriteMode = NExtract::NOverwriteMode::kAsk;
231 extracter.ExtractCallbackSpec->Init();
232 extracter.Indices = indices;
233 extracter.FolderOperations = _folderOperations;
234
235 extracter.ExtractCallbackSpec->PasswordIsDefined = usePassword;
236 extracter.ExtractCallbackSpec->Password = password;
237
238 RINOK(extracter.Create(title, GetParent()));
239
240
241 if (messages)
242 *messages = extracter.Sync.Messages;
243
244 // res = extracter.Result2;
245 res = extracter.Result;
246
247 if (res == S_OK && extracter.ExtractCallbackSpec->IsOK())
248 {
249 usePassword = extracter.ExtractCallbackSpec->PasswordIsDefined;
250 password = extracter.ExtractCallbackSpec->Password;
251 }
252
253 extracter.ShowFinalResults(_window);
254
255 }
256
257 RefreshTitleAlways();
258 return res;
259}
260
261
262struct CThreadUpdate
263{
264 CMyComPtr<IFolderOperations> FolderOperations;
265 UString FolderPrefix;
266 UStringVector FileNames;
267 CRecordVector<const wchar_t *> FileNamePointers;
268 CProgressDialog ProgressDialog;
269 CMyComPtr<IFolderArchiveUpdateCallback> UpdateCallback;
270 CUpdateCallback100Imp *UpdateCallbackSpec;
271 HRESULT Result;
272 bool MoveMode;
273
274 void Process()
275 {
276 try
277 {
278 CProgressCloser closer(ProgressDialog);
279 Result = FolderOperations->CopyFrom(
280 MoveMode,
281 FolderPrefix,
282 &FileNamePointers.Front(),
283 FileNamePointers.Size(),
284 UpdateCallback);
285 }
286 catch(...) { Result = E_FAIL; }
287 }
288 static THREAD_FUNC_DECL MyThreadFunction(void *param)
289 {
290 ((CThreadUpdate *)param)->Process();
291 return 0;
292 }
293};
294
295
296HRESULT CPanel::CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths,
297 bool showErrorMessages, UStringVector *messages)
298{
299 if (IsHashFolder())
300 {
301 if (moveMode)
302 return E_NOTIMPL;
303 }
304 // CDisableNotify disableNotify(*this);
305
306 HRESULT res;
307 if (!_folderOperations)
308 res = E_NOINTERFACE;
309 else
310 {
311 CThreadUpdate updater;
312 updater.MoveMode = moveMode;
313 updater.UpdateCallbackSpec = new CUpdateCallback100Imp;
314 updater.UpdateCallback = updater.UpdateCallbackSpec;
315 updater.UpdateCallbackSpec->Init();
316
317 updater.UpdateCallbackSpec->ProgressDialog = &updater.ProgressDialog;
318
319 UString title = LangString(IDS_COPYING);
320 UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE);
321
322 updater.ProgressDialog.MainWindow = GetParent();
323 updater.ProgressDialog.MainTitle = progressWindowTitle;
324 updater.ProgressDialog.MainAddTitle = title + L' ';
325
326 {
327 if (!_parentFolders.IsEmpty())
328 {
329 const CFolderLink &fl = _parentFolders.Back();
330 updater.UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
331 updater.UpdateCallbackSpec->Password = fl.Password;
332 }
333 }
334
335 updater.FolderOperations = _folderOperations;
336 updater.FolderPrefix = folderPrefix;
337 updater.FileNames.ClearAndReserve(filePaths.Size());
338 unsigned i;
339 for (i = 0; i < filePaths.Size(); i++)
340 updater.FileNames.AddInReserved(filePaths[i]);
341 updater.FileNamePointers.ClearAndReserve(updater.FileNames.Size());
342 for (i = 0; i < updater.FileNames.Size(); i++)
343 updater.FileNamePointers.AddInReserved(updater.FileNames[i]);
344
345 {
346 NWindows::CThread thread;
347 RINOK(thread.Create(CThreadUpdate::MyThreadFunction, &updater));
348 updater.ProgressDialog.Create(title, thread, GetParent());
349 }
350
351 if (messages)
352 *messages = updater.ProgressDialog.Sync.Messages;
353
354 res = updater.Result;
355 }
356
357 if (res == E_NOINTERFACE)
358 {
359 UString errorMessage = LangString(IDS_OPERATION_IS_NOT_SUPPORTED);
360 if (showErrorMessages)
361 MessageBox_Error(errorMessage);
362 else if (messages)
363 messages->Add(errorMessage);
364 return E_ABORT;
365 }
366
367 RefreshTitleAlways();
368 return res;
369}
370
371void CPanel::CopyFromNoAsk(const UStringVector &filePaths)
372{
373 CDisableTimerProcessing disableTimerProcessing(*this);
374
375 CSelectedState srcSelState;
376 SaveSelectedState(srcSelState);
377
378 CDisableNotify disableNotify(*this);
379
380 HRESULT result = CopyFrom(false, L"", filePaths, true, 0);
381
382 if (result != S_OK)
383 {
384 disableNotify.Restore();
385 // For Password:
386 SetFocusToList();
387 if (result != E_ABORT)
388 MessageBox_Error_HRESULT(result);
389 return;
390 }
391
392 RefreshListCtrl(srcSelState);
393
394 disableNotify.Restore();
395 SetFocusToList();
396}
397
398void CPanel::CopyFromAsk(const UStringVector &filePaths)
399{
400 UString title = LangString(IDS_CONFIRM_FILE_COPY);
401 UString message = LangString(IDS_WANT_TO_COPY_FILES);
402 message += "\n\'";
403 message += _currentFolderPrefix;
404 message += "\' ?";
405 int res = ::MessageBoxW(*(this), message, title, MB_YESNOCANCEL | MB_ICONQUESTION);
406 if (res != IDYES)
407 return;
408
409 CopyFromNoAsk(filePaths);
410}
diff --git a/CPP/7zip/UI/FileManager/PanelCrc.cpp b/CPP/7zip/UI/FileManager/PanelCrc.cpp
new file mode 100644
index 0000000..1d483ca
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelCrc.cpp
@@ -0,0 +1,421 @@
1// PanelCrc.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyException.h"
6
7#include "../../../Windows/FileFind.h"
8#include "../../../Windows/FileIO.h"
9#include "../../../Windows/FileName.h"
10
11#include "../Common/LoadCodecs.h"
12
13#include "../GUI/HashGUI.h"
14
15#include "App.h"
16#include "LangUtils.h"
17
18#include "resource.h"
19
20using namespace NWindows;
21using namespace NFile;
22
23#ifdef EXTERNAL_CODECS
24extern CExternalCodecs g_ExternalCodecs;
25HRESULT LoadGlobalCodecs();
26#endif
27
28static const UInt32 kBufSize = (1 << 15);
29
30struct CDirEnumerator
31{
32 bool EnterToDirs;
33 FString BasePrefix;
34 FString BasePrefix_for_Open;
35 FStringVector FilePaths;
36
37 CObjectVector<NFind::CEnumerator> Enumerators;
38 FStringVector Prefixes;
39 unsigned Index;
40
41 CDirEnumerator(): EnterToDirs(false), Index(0) {};
42
43 void Init();
44 DWORD GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath);
45};
46
47void CDirEnumerator::Init()
48{
49 Enumerators.Clear();
50 Prefixes.Clear();
51 Index = 0;
52}
53
54static DWORD GetNormalizedError()
55{
56 DWORD error = GetLastError();
57 return (error == 0) ? E_FAIL : error;
58}
59
60DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath)
61{
62 filled = false;
63 resPath.Empty();
64
65 for (;;)
66 {
67 #if defined(_WIN32) && !defined(UNDER_CE)
68 bool isRootPrefix = (BasePrefix.IsEmpty() || (NName::IsSuperPath(BasePrefix) && BasePrefix[NName::kSuperPathPrefixSize] == 0));
69 #endif
70
71 if (Enumerators.IsEmpty())
72 {
73 if (Index >= FilePaths.Size())
74 return S_OK;
75 const FString &path = FilePaths[Index++];
76 int pos = path.ReverseFind_PathSepar();
77 if (pos >= 0)
78 resPath.SetFrom(path, pos + 1);
79
80 #if defined(_WIN32) && !defined(UNDER_CE)
81 if (isRootPrefix && path.Len() == 2 && NName::IsDrivePath2(path))
82 {
83 // we use "c:" item as directory item
84 fi.ClearBase();
85 fi.Name = path;
86 fi.SetAsDir();
87 fi.Size = 0;
88 }
89 else
90 #endif
91 if (!fi.Find(BasePrefix + path))
92 {
93 DWORD error = GetNormalizedError();
94 resPath = path;
95 return error;
96 }
97
98 break;
99 }
100
101 bool found;
102
103 if (Enumerators.Back().Next(fi, found))
104 {
105 if (found)
106 {
107 resPath = Prefixes.Back();
108 break;
109 }
110 }
111 else
112 {
113 DWORD error = GetNormalizedError();
114 resPath = Prefixes.Back();
115 Enumerators.DeleteBack();
116 Prefixes.DeleteBack();
117 return error;
118 }
119
120 Enumerators.DeleteBack();
121 Prefixes.DeleteBack();
122 }
123
124 resPath += fi.Name;
125
126 if (EnterToDirs && fi.IsDir())
127 {
128 FString s = resPath;
129 s.Add_PathSepar();
130 Prefixes.Add(s);
131 Enumerators.AddNew().SetDirPrefix(BasePrefix + s);
132 }
133
134 filled = true;
135 return S_OK;
136}
137
138
139
140class CThreadCrc: public CProgressThreadVirt
141{
142 bool ResultsWereShown;
143 bool WasFinished;
144
145 HRESULT ProcessVirt();
146 virtual void ProcessWasFinished_GuiVirt();
147public:
148 CDirEnumerator Enumerator;
149 CHashBundle Hash;
150 // FString FirstFilePath;
151
152 void SetStatus(const UString &s);
153 void AddErrorMessage(DWORD systemError, const FChar *name);
154 void ShowFinalResults(HWND hwnd);
155
156 CThreadCrc():
157 ResultsWereShown(false),
158 WasFinished(false)
159 {}
160};
161
162void CThreadCrc::ShowFinalResults(HWND hwnd)
163{
164 if (WasFinished)
165 if (!ResultsWereShown)
166 {
167 ResultsWereShown = true;
168 ShowHashResults(Hash, hwnd);
169 }
170}
171
172void CThreadCrc::ProcessWasFinished_GuiVirt()
173{
174 ShowFinalResults(*this);
175}
176
177void CThreadCrc::AddErrorMessage(DWORD systemError, const FChar *name)
178{
179 Sync.AddError_Code_Name(systemError, fs2us(Enumerator.BasePrefix + name));
180 Hash.NumErrors++;
181}
182
183void CThreadCrc::SetStatus(const UString &s2)
184{
185 UString s = s2;
186 if (!Enumerator.BasePrefix.IsEmpty())
187 {
188 s.Add_Space_if_NotEmpty();
189 s += fs2us(Enumerator.BasePrefix);
190 }
191 Sync.Set_Status(s);
192}
193
194HRESULT CThreadCrc::ProcessVirt()
195{
196 // Hash.Init();
197
198 CMyBuffer buf;
199 if (!buf.Allocate(kBufSize))
200 return E_OUTOFMEMORY;
201
202 CProgressSync &sync = Sync;
203
204 SetStatus(LangString(IDS_SCANNING));
205
206 Enumerator.Init();
207
208 FString path;
209 NFind::CFileInfo fi;
210 UInt64 numFiles = 0;
211 UInt64 numItems = 0, numItems_Prev = 0;
212 UInt64 totalSize = 0;
213
214 for (;;)
215 {
216 bool filled;
217 DWORD error = Enumerator.GetNextFile(fi, filled, path);
218 if (error != 0)
219 {
220 AddErrorMessage(error, path);
221 continue;
222 }
223 if (!filled)
224 break;
225 if (!fi.IsDir())
226 {
227 totalSize += fi.Size;
228 numFiles++;
229 }
230 numItems++;
231 bool needPrint = false;
232 // if (fi.IsDir())
233 {
234 if (numItems - numItems_Prev >= 100)
235 {
236 needPrint = true;
237 numItems_Prev = numItems;
238 }
239 }
240 /*
241 else if (numFiles - numFiles_Prev >= 200)
242 {
243 needPrint = true;
244 numFiles_Prev = numFiles;
245 }
246 */
247 if (needPrint)
248 {
249 RINOK(sync.ScanProgress(numFiles, totalSize, path, fi.IsDir()));
250 }
251 }
252 RINOK(sync.ScanProgress(numFiles, totalSize, FString(), false));
253 // sync.SetNumFilesTotal(numFiles);
254 // sync.SetProgress(totalSize, 0);
255 // SetStatus(LangString(IDS_CHECKSUM_CALCULATING));
256 // sync.SetCurFilePath(L"");
257 SetStatus(L"");
258
259 Enumerator.Init();
260
261 FString tempPath;
262 bool isFirstFile = true;
263 UInt64 errorsFilesSize = 0;
264
265 for (;;)
266 {
267 bool filled;
268 DWORD error = Enumerator.GetNextFile(fi, filled, path);
269 if (error != 0)
270 {
271 AddErrorMessage(error, path);
272 continue;
273 }
274 if (!filled)
275 break;
276
277 error = 0;
278 Hash.InitForNewFile();
279 if (!fi.IsDir())
280 {
281 NIO::CInFile inFile;
282 tempPath = Enumerator.BasePrefix_for_Open;
283 tempPath += path;
284 if (!inFile.Open(tempPath))
285 {
286 error = GetNormalizedError();
287 AddErrorMessage(error, path);
288 continue;
289 }
290 if (isFirstFile)
291 {
292 Hash.FirstFileName = fs2us(path);
293 isFirstFile = false;
294 }
295 sync.Set_FilePath(fs2us(path));
296 sync.Set_NumFilesCur(Hash.NumFiles);
297 UInt64 progress_Prev = 0;
298 for (;;)
299 {
300 UInt32 size;
301 if (!inFile.Read(buf, kBufSize, size))
302 {
303 error = GetNormalizedError();
304 AddErrorMessage(error, path);
305 UInt64 errorSize = 0;
306 if (inFile.GetLength(errorSize))
307 errorsFilesSize += errorSize;
308 break;
309 }
310 if (size == 0)
311 break;
312 Hash.Update(buf, size);
313 if (Hash.CurSize - progress_Prev >= ((UInt32)1 << 21))
314 {
315 RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize + Hash.CurSize));
316 progress_Prev = Hash.CurSize;
317 }
318 }
319 }
320 if (error == 0)
321 Hash.Final(fi.IsDir(), false, fs2us(path));
322 RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize));
323 }
324 RINOK(sync.Set_NumBytesCur(errorsFilesSize + Hash.FilesSize));
325 sync.Set_NumFilesCur(Hash.NumFiles);
326 if (Hash.NumFiles != 1)
327 sync.Set_FilePath(L"");
328 SetStatus(L"");
329
330 CProgressMessageBoxPair &pair = GetMessagePair(Hash.NumErrors != 0);
331 WasFinished = true;
332 LangString(IDS_CHECKSUM_INFORMATION, pair.Title);
333 return S_OK;
334}
335
336
337
338HRESULT CApp::CalculateCrc2(const UString &methodName)
339{
340 unsigned srcPanelIndex = GetFocusedPanelIndex();
341 CPanel &srcPanel = Panels[srcPanelIndex];
342
343 CRecordVector<UInt32> indices;
344 srcPanel.GetOperatedIndicesSmart(indices);
345 if (indices.IsEmpty())
346 return S_OK;
347
348 if (!srcPanel.Is_IO_FS_Folder())
349 {
350 CCopyToOptions options;
351 options.streamMode = true;
352 options.showErrorMessages = true;
353 options.hashMethods.Add(methodName);
354
355 UStringVector messages;
356 return srcPanel.CopyTo(options, indices, &messages);
357 }
358
359 #ifdef EXTERNAL_CODECS
360
361 LoadGlobalCodecs();
362
363 #endif
364
365 {
366 CThreadCrc t;
367
368 {
369 UStringVector methods;
370 methods.Add(methodName);
371 RINOK(t.Hash.SetMethods(EXTERNAL_CODECS_VARS_G methods));
372 }
373
374 FOR_VECTOR (i, indices)
375 t.Enumerator.FilePaths.Add(us2fs(srcPanel.GetItemRelPath(indices[i])));
376
377 if (t.Enumerator.FilePaths.Size() == 1)
378 t.Hash.MainName = fs2us(t.Enumerator.FilePaths[0]);
379
380 UString basePrefix = srcPanel.GetFsPath();
381 UString basePrefix2 = basePrefix;
382 if (basePrefix2.Back() == ':')
383 {
384 int pos = basePrefix2.ReverseFind_PathSepar();
385 if (pos >= 0)
386 basePrefix2.DeleteFrom((unsigned)(pos + 1));
387 }
388
389 t.Enumerator.BasePrefix = us2fs(basePrefix);
390 t.Enumerator.BasePrefix_for_Open = us2fs(basePrefix2);
391
392 t.Enumerator.EnterToDirs = !GetFlatMode();
393
394 t.ShowCompressionInfo = false;
395
396 UString title = LangString(IDS_CHECKSUM_CALCULATING);
397
398 t.MainWindow = _window;
399 t.MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
400 t.MainAddTitle = title;
401 t.MainAddTitle.Add_Space();
402
403 RINOK(t.Create(title, _window));
404
405 t.ShowFinalResults(_window);
406 }
407
408 RefreshTitleAlways();
409 return S_OK;
410}
411
412void CApp::CalculateCrc(const char *methodName)
413{
414 HRESULT res = CalculateCrc2(UString(methodName));
415 if (res != S_OK && res != E_ABORT)
416 {
417 unsigned srcPanelIndex = GetFocusedPanelIndex();
418 CPanel &srcPanel = Panels[srcPanelIndex];
419 srcPanel.MessageBox_Error_HRESULT(res);
420 }
421}
diff --git a/CPP/7zip/UI/FileManager/PanelDrag.cpp b/CPP/7zip/UI/FileManager/PanelDrag.cpp
new file mode 100644
index 0000000..af8799c
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelDrag.cpp
@@ -0,0 +1,956 @@
1// PanelDrag.cpp
2
3#include "StdAfx.h"
4
5#ifdef UNDER_CE
6#include <winuserm.h>
7#endif
8
9#include "../../../Common/StringConvert.h"
10#include "../../../Common/Wildcard.h"
11
12#include "../../../Windows/MemoryGlobal.h"
13#include "../../../Windows/FileDir.h"
14#include "../../../Windows/FileName.h"
15#include "../../../Windows/Shell.h"
16
17#include "../Common/ArchiveName.h"
18#include "../Common/CompressCall.h"
19#include "../Common/ExtractingFilePath.h"
20
21#include "MessagesDialog.h"
22
23#include "App.h"
24#include "EnumFormatEtc.h"
25
26using namespace NWindows;
27using namespace NFile;
28using namespace NDir;
29
30#ifndef _UNICODE
31extern bool g_IsNT;
32#endif
33
34#define kTempDirPrefix FTEXT("7zE")
35
36static LPCTSTR const kSvenZipSetFolderFormat = TEXT("7-Zip::SetTargetFolder");
37
38////////////////////////////////////////////////////////
39
40class CDataObject:
41 public IDataObject,
42 public CMyUnknownImp
43{
44private:
45 FORMATETC m_Etc;
46 UINT m_SetFolderFormat;
47
48public:
49 MY_UNKNOWN_IMP1_MT(IDataObject)
50
51 STDMETHODIMP GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM medium);
52 STDMETHODIMP GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM medium);
53 STDMETHODIMP QueryGetData(LPFORMATETC pformatetc );
54
55 STDMETHODIMP GetCanonicalFormatEtc ( LPFORMATETC /* pformatetc */, LPFORMATETC pformatetcOut)
56 { pformatetcOut->ptd = NULL; return ResultFromScode(E_NOTIMPL); }
57
58 STDMETHODIMP SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL release);
59 STDMETHODIMP EnumFormatEtc(DWORD drection, LPENUMFORMATETC *enumFormatEtc);
60
61 STDMETHODIMP DAdvise(FORMATETC * /* etc */, DWORD /* advf */, LPADVISESINK /* pAdvSink */, DWORD * /* pdwConnection */)
62 { return OLE_E_ADVISENOTSUPPORTED; }
63 STDMETHODIMP DUnadvise(DWORD /* dwConnection */) { return OLE_E_ADVISENOTSUPPORTED; }
64 STDMETHODIMP EnumDAdvise( LPENUMSTATDATA * /* ppenumAdvise */) { return OLE_E_ADVISENOTSUPPORTED; }
65
66 CDataObject();
67
68 NMemory::CGlobal hGlobal;
69 UString Path;
70};
71
72CDataObject::CDataObject()
73{
74 m_SetFolderFormat = RegisterClipboardFormat(kSvenZipSetFolderFormat);
75 m_Etc.cfFormat = CF_HDROP;
76 m_Etc.ptd = NULL;
77 m_Etc.dwAspect = DVASPECT_CONTENT;
78 m_Etc.lindex = -1;
79 m_Etc.tymed = TYMED_HGLOBAL;
80}
81
82STDMETHODIMP CDataObject::SetData(LPFORMATETC etc, STGMEDIUM *medium, BOOL /* release */)
83{
84 if (etc->cfFormat == m_SetFolderFormat
85 && etc->tymed == TYMED_HGLOBAL
86 && etc->dwAspect == DVASPECT_CONTENT
87 && medium->tymed == TYMED_HGLOBAL)
88 {
89 Path.Empty();
90 if (!medium->hGlobal)
91 return S_OK;
92 size_t size = GlobalSize(medium->hGlobal) / sizeof(wchar_t);
93 const wchar_t *src = (const wchar_t *)GlobalLock(medium->hGlobal);
94 if (src)
95 {
96 for (size_t i = 0; i < size; i++)
97 {
98 wchar_t c = src[i];
99 if (c == 0)
100 break;
101 Path += c;
102 }
103 GlobalUnlock(medium->hGlobal);
104 return S_OK;
105 }
106 }
107 return E_NOTIMPL;
108}
109
110static HGLOBAL DuplicateGlobalMem(HGLOBAL srcGlobal)
111{
112 SIZE_T size = GlobalSize(srcGlobal);
113 const void *src = GlobalLock(srcGlobal);
114 if (!src)
115 return 0;
116 HGLOBAL destGlobal = GlobalAlloc(GHND | GMEM_SHARE, size);
117 if (destGlobal)
118 {
119 void *dest = GlobalLock(destGlobal);
120 if (!dest)
121 {
122 GlobalFree(destGlobal);
123 destGlobal = 0;
124 }
125 else
126 {
127 memcpy(dest, src, size);
128 GlobalUnlock(destGlobal);
129 }
130 }
131 GlobalUnlock(srcGlobal);
132 return destGlobal;
133}
134
135STDMETHODIMP CDataObject::GetData(LPFORMATETC etc, LPSTGMEDIUM medium)
136{
137 RINOK(QueryGetData(etc));
138 medium->tymed = m_Etc.tymed;
139 medium->pUnkForRelease = 0;
140 medium->hGlobal = DuplicateGlobalMem(hGlobal);
141 if (!medium->hGlobal)
142 return E_OUTOFMEMORY;
143 return S_OK;
144}
145
146STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC /* etc */, LPSTGMEDIUM /* medium */)
147{
148 // Seems Windows doesn't call it, so we will not implement it.
149 return E_UNEXPECTED;
150}
151
152
153STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC etc)
154{
155 if ((m_Etc.tymed & etc->tymed) &&
156 m_Etc.cfFormat == etc->cfFormat &&
157 m_Etc.dwAspect == etc->dwAspect)
158 return S_OK;
159 return DV_E_FORMATETC;
160}
161
162STDMETHODIMP CDataObject::EnumFormatEtc(DWORD direction, LPENUMFORMATETC FAR* enumFormatEtc)
163{
164 if (direction != DATADIR_GET)
165 return E_NOTIMPL;
166 return CreateEnumFormatEtc(1, &m_Etc, enumFormatEtc);
167}
168
169////////////////////////////////////////////////////////
170
171class CDropSource:
172 public IDropSource,
173 public CMyUnknownImp
174{
175 DWORD m_Effect;
176public:
177 MY_UNKNOWN_IMP1_MT(IDropSource)
178 STDMETHOD(QueryContinueDrag)(BOOL escapePressed, DWORD keyState);
179 STDMETHOD(GiveFeedback)(DWORD effect);
180
181
182 bool NeedExtract;
183 CPanel *Panel;
184 CRecordVector<UInt32> Indices;
185 UString Folder;
186 CDataObject *DataObjectSpec;
187 CMyComPtr<IDataObject> DataObject;
188
189 bool NeedPostCopy;
190 HRESULT Result;
191 UStringVector Messages;
192
193 CDropSource(): m_Effect(DROPEFFECT_NONE), Panel(NULL), NeedPostCopy(false), Result(S_OK) {}
194};
195
196STDMETHODIMP CDropSource::QueryContinueDrag(BOOL escapePressed, DWORD keyState)
197{
198 if (escapePressed == TRUE)
199 return DRAGDROP_S_CANCEL;
200 if ((keyState & MK_LBUTTON) == 0)
201 {
202 if (m_Effect == DROPEFFECT_NONE)
203 return DRAGDROP_S_CANCEL;
204 Result = S_OK;
205 bool needExtract = NeedExtract;
206 // MoveMode = (((keyState & MK_SHIFT) != 0) && MoveIsAllowed);
207 if (!DataObjectSpec->Path.IsEmpty())
208 {
209 needExtract = false;
210 NeedPostCopy = true;
211 }
212 if (needExtract)
213 {
214 CCopyToOptions options;
215 options.folder = Folder;
216
217 // 15.13: fixed problem with mouse cursor for password window.
218 // DoDragDrop() probably calls SetCapture() to some hidden window.
219 // But it's problem, if we show some modal window, like MessageBox.
220 // So we return capture to our window.
221 // If you know better way to solve the problem, please notify 7-Zip developer.
222
223 // MessageBoxW(*Panel, L"test", L"test", 0);
224
225 /* HWND oldHwnd = */ SetCapture(*Panel);
226
227 Result = Panel->CopyTo(options, Indices, &Messages);
228
229 // do we need to restore capture?
230 // ReleaseCapture();
231 // oldHwnd = SetCapture(oldHwnd);
232
233 if (Result != S_OK || !Messages.IsEmpty())
234 return DRAGDROP_S_CANCEL;
235 }
236 return DRAGDROP_S_DROP;
237 }
238 return S_OK;
239}
240
241STDMETHODIMP CDropSource::GiveFeedback(DWORD effect)
242{
243 m_Effect = effect;
244 return DRAGDROP_S_USEDEFAULTCURSORS;
245}
246
247static bool CopyNamesToHGlobal(NMemory::CGlobal &hgDrop, const UStringVector &names)
248{
249 size_t totalLen = 1;
250
251 #ifndef _UNICODE
252 if (!g_IsNT)
253 {
254 AStringVector namesA;
255 unsigned i;
256 for (i = 0; i < names.Size(); i++)
257 namesA.Add(GetSystemString(names[i]));
258 for (i = 0; i < names.Size(); i++)
259 totalLen += namesA[i].Len() + 1;
260
261 if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLen * sizeof(CHAR) + sizeof(DROPFILES)))
262 return false;
263
264 NMemory::CGlobalLock dropLock(hgDrop);
265 DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer();
266 if (!dropFiles)
267 return false;
268 dropFiles->fNC = FALSE;
269 dropFiles->pt.x = 0;
270 dropFiles->pt.y = 0;
271 dropFiles->pFiles = sizeof(DROPFILES);
272 dropFiles->fWide = FALSE;
273 CHAR *p = (CHAR *)((BYTE *)dropFiles + sizeof(DROPFILES));
274 for (i = 0; i < names.Size(); i++)
275 {
276 const AString &s = namesA[i];
277 unsigned fullLen = s.Len() + 1;
278 MyStringCopy(p, (const char *)s);
279 p += fullLen;
280 totalLen -= fullLen;
281 }
282 *p = 0;
283 }
284 else
285 #endif
286 {
287 unsigned i;
288 for (i = 0; i < names.Size(); i++)
289 totalLen += names[i].Len() + 1;
290
291 if (!hgDrop.Alloc(GHND | GMEM_SHARE, totalLen * sizeof(WCHAR) + sizeof(DROPFILES)))
292 return false;
293
294 NMemory::CGlobalLock dropLock(hgDrop);
295 DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer();
296 if (!dropFiles)
297 return false;
298 dropFiles->fNC = FALSE;
299 dropFiles->pt.x = 0;
300 dropFiles->pt.y = 0;
301 dropFiles->pFiles = sizeof(DROPFILES);
302 dropFiles->fWide = TRUE;
303 WCHAR *p = (WCHAR *) (void *) ((BYTE *)dropFiles + sizeof(DROPFILES));
304 for (i = 0; i < names.Size(); i++)
305 {
306 const UString &s = names[i];
307 unsigned fullLen = s.Len() + 1;
308 MyStringCopy(p, (const WCHAR *)s);
309 p += fullLen;
310 totalLen -= fullLen;
311 }
312 *p = 0;
313 }
314 return true;
315}
316
317void CPanel::OnDrag(LPNMLISTVIEW /* nmListView */)
318{
319 if (!DoesItSupportOperations())
320 return;
321
322 CDisableTimerProcessing disableTimerProcessing2(*this);
323
324 CRecordVector<UInt32> indices;
325 GetOperatedItemIndices(indices);
326 if (indices.Size() == 0)
327 return;
328
329 // CSelectedState selState;
330 // SaveSelectedState(selState);
331
332 // FString dirPrefix2;
333 FString dirPrefix;
334 CTempDir tempDirectory;
335
336 bool isFSFolder = IsFSFolder();
337 if (isFSFolder)
338 dirPrefix = us2fs(GetFsPath());
339 else
340 {
341 if (!tempDirectory.Create(kTempDirPrefix))
342 {
343 MessageBox_Error(L"Can't create temp folder");
344 return;
345 }
346 dirPrefix = tempDirectory.GetPath();
347 // dirPrefix2 = dirPrefix;
348 NFile::NName::NormalizeDirPathPrefix(dirPrefix);
349 }
350
351 CDataObject *dataObjectSpec = new CDataObject;
352 CMyComPtr<IDataObject> dataObject = dataObjectSpec;
353
354 {
355 UStringVector names;
356
357 // names variable is USED for drag and drop from 7-zip to Explorer or to 7-zip archive folder.
358 // names variable is NOT USED for drag and drop from 7-zip to 7-zip File System folder.
359
360 FOR_VECTOR (i, indices)
361 {
362 UInt32 index = indices[i];
363 UString s;
364 if (isFSFolder)
365 s = GetItemRelPath(index);
366 else
367 {
368 s = GetItemName(index);
369 /*
370 // We use (keepAndReplaceEmptyPrefixes = true) in CAgentFolder::Extract
371 // So the following code is not required.
372 // Maybe we also can change IFolder interface and send some flag also.
373
374 if (s.IsEmpty())
375 {
376 // Correct_FsFile_Name("") returns "_".
377 // If extracting code removes empty folder prefixes from path (as it was in old version),
378 // Explorer can't find "_" folder in temp folder.
379 // We can ask Explorer to copy parent temp folder "7zE" instead.
380
381 names.Clear();
382 names.Add(dirPrefix2);
383 break;
384 }
385 */
386 s = Get_Correct_FsFile_Name(s);
387 }
388 names.Add(fs2us(dirPrefix) + s);
389 }
390 if (!CopyNamesToHGlobal(dataObjectSpec->hGlobal, names))
391 return;
392 }
393
394 CDropSource *dropSourceSpec = new CDropSource;
395 CMyComPtr<IDropSource> dropSource = dropSourceSpec;
396 dropSourceSpec->NeedExtract = !isFSFolder;
397 dropSourceSpec->Panel = this;
398 dropSourceSpec->Indices = indices;
399 dropSourceSpec->Folder = fs2us(dirPrefix);
400 dropSourceSpec->DataObjectSpec = dataObjectSpec;
401 dropSourceSpec->DataObject = dataObjectSpec;
402
403
404 /*
405 CTime - file creation timestamp.
406 There are two operations in Windows with Drag and Drop:
407 COPY_OPERATION - icon with Plus sign - CTime will be set as current_time.
408 MOVE_OPERATION - icon without Plus sign - CTime will be preserved
409
410 Note: if we call DoDragDrop() with (effectsOK = DROPEFFECT_MOVE), then
411 it will use MOVE_OPERATION and CTime will be preserved.
412 But MoveFile() function doesn't preserve CTime, if different volumes are used.
413 Why it's so?
414 Does DoDragDrop() use some another function (not MoveFile())?
415
416 if (effectsOK == DROPEFFECT_COPY) it works as COPY_OPERATION
417
418 if (effectsOK == DROPEFFECT_MOVE) drag works as MOVE_OPERATION
419
420 if (effectsOK == (DROPEFFECT_COPY | DROPEFFECT_MOVE))
421 {
422 if we drag file to same volume, then Windows suggests:
423 CTRL - COPY_OPERATION
424 [default] - MOVE_OPERATION
425
426 if we drag file to another volume, then Windows suggests
427 [default] - COPY_OPERATION
428 SHIFT - MOVE_OPERATION
429 }
430
431 We want to use MOVE_OPERATION for extracting from archive (open in 7-Zip) to Explorer:
432 It has the following advantages:
433 1) it uses fast MOVE_OPERATION instead of slow COPY_OPERATION and DELETE, if same volume.
434 2) it preserved CTime
435
436 Some another programs support only COPY_OPERATION.
437 So we can use (DROPEFFECT_COPY | DROPEFFECT_MOVE)
438
439 Also another program can return from DoDragDrop() before
440 files using. But we delete temp folder after DoDragDrop(),
441 and another program can't open input files in that case.
442
443 We create objects:
444 IDropSource *dropSource
445 IDataObject *dataObject
446 if DropTarget is 7-Zip window, then 7-Zip's
447 IDropTarget::DragOver() sets Path in IDataObject.
448 and
449 IDropSource::QueryContinueDrag() sets NeedPostCopy, if Path is not epmty.
450 So we can detect destination path after DoDragDrop().
451 Now we don't know any good way to detect destination path for D&D to Explorer.
452 */
453
454 bool moveIsAllowed = isFSFolder;
455 /*
456 DWORD effectsOK = DROPEFFECT_COPY;
457 if (moveIsAllowed)
458 effectsOK |= DROPEFFECT_MOVE;
459 */
460
461 // 18.04: was changed
462 DWORD effectsOK = DROPEFFECT_MOVE | DROPEFFECT_COPY;
463
464 DWORD effect;
465 _panelCallback->DragBegin();
466
467 HRESULT res = DoDragDrop(dataObject, dropSource, effectsOK, &effect);
468
469 _panelCallback->DragEnd();
470 bool canceled = (res == DRAGDROP_S_CANCEL);
471
472 CDisableNotify disableNotify(*this);
473
474 if (res == DRAGDROP_S_DROP)
475 {
476 res = dropSourceSpec->Result;
477 if (dropSourceSpec->NeedPostCopy)
478 if (!dataObjectSpec->Path.IsEmpty())
479 {
480 NFile::NName::NormalizeDirPathPrefix(dataObjectSpec->Path);
481 CCopyToOptions options;
482 options.folder = dataObjectSpec->Path;
483 // if MOVE is not allowed, we just use COPY operation
484 options.moveMode = (effect == DROPEFFECT_MOVE && moveIsAllowed);
485 res = CopyTo(options, indices, &dropSourceSpec->Messages);
486 }
487 /*
488 if (effect == DROPEFFECT_MOVE)
489 RefreshListCtrl(selState);
490 */
491 }
492 else
493 {
494 // we ignore E_UNEXPECTED that is returned if we drag file to printer
495 if (res != DRAGDROP_S_CANCEL && res != S_OK
496 && res != E_UNEXPECTED)
497 MessageBox_Error_HRESULT(res);
498
499 res = dropSourceSpec->Result;
500 }
501
502 if (!dropSourceSpec->Messages.IsEmpty())
503 {
504 CMessagesDialog messagesDialog;
505 messagesDialog.Messages = &dropSourceSpec->Messages;
506 messagesDialog.Create((*this));
507 }
508
509 if (res != S_OK && res != E_ABORT)
510 {
511 // we restore Notify before MessageBox_Error_HRESULT. So we will se files selection
512 disableNotify.Restore();
513 // SetFocusToList();
514 MessageBox_Error_HRESULT(res);
515 }
516 if (res == S_OK && dropSourceSpec->Messages.IsEmpty() && !canceled)
517 KillSelection();
518}
519
520void CDropTarget::QueryGetData(IDataObject *dataObject)
521{
522 FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
523 m_DropIsAllowed = (dataObject->QueryGetData(&etc) == S_OK);
524
525}
526
527static void MySetDropHighlighted(HWND hWnd, int index, bool enable)
528{
529 LVITEM item;
530 item.mask = LVIF_STATE;
531 item.iItem = index;
532 item.iSubItem = 0;
533 item.state = enable ? LVIS_DROPHILITED : 0;
534 item.stateMask = LVIS_DROPHILITED;
535 item.pszText = 0;
536 ListView_SetItem(hWnd, &item);
537}
538
539void CDropTarget::RemoveSelection()
540{
541 if (m_SelectionIndex >= 0 && m_Panel)
542 MySetDropHighlighted(m_Panel->_listView, m_SelectionIndex, false);
543 m_SelectionIndex = -1;
544}
545
546#ifdef UNDER_CE
547#define ChildWindowFromPointEx(hwndParent, pt, uFlags) ChildWindowFromPoint(hwndParent, pt)
548#endif
549
550void CDropTarget::PositionCursor(POINTL ptl)
551{
552 m_SubFolderIndex = -1;
553 POINT pt;
554 pt.x = ptl.x;
555 pt.y = ptl.y;
556
557 RemoveSelection();
558 m_IsAppTarget = true;
559 m_Panel = NULL;
560
561 m_PanelDropIsAllowed = true;
562 if (!m_DropIsAllowed)
563 return;
564 {
565 POINT pt2 = pt;
566 App->_window.ScreenToClient(&pt2);
567 for (unsigned i = 0; i < kNumPanelsMax; i++)
568 if (App->IsPanelVisible(i))
569 if (App->Panels[i].IsEnabled())
570 if (ChildWindowFromPointEx(App->_window, pt2,
571 CWP_SKIPINVISIBLE | CWP_SKIPDISABLED) == (HWND)App->Panels[i])
572 {
573 m_Panel = &App->Panels[i];
574 m_IsAppTarget = false;
575 if ((int)i == SrcPanelIndex)
576 {
577 m_PanelDropIsAllowed = false;
578 return;
579 }
580 break;
581 }
582 if (m_IsAppTarget)
583 {
584 if (TargetPanelIndex >= 0)
585 m_Panel = &App->Panels[TargetPanelIndex];
586 return;
587 }
588 }
589
590 /*
591 m_PanelDropIsAllowed = m_Panel->DoesItSupportOperations();
592 if (!m_PanelDropIsAllowed)
593 return;
594 */
595
596 if (!m_Panel->IsFsOrPureDrivesFolder())
597 return;
598
599 if (WindowFromPoint(pt) != (HWND)m_Panel->_listView)
600 return;
601
602 LVHITTESTINFO info;
603 m_Panel->_listView.ScreenToClient(&pt);
604 info.pt = pt;
605 int index = ListView_HitTest(m_Panel->_listView, &info);
606 if (index < 0)
607 return;
608 int realIndex = m_Panel->GetRealItemIndex(index);
609 if (realIndex == kParentIndex)
610 return;
611 if (!m_Panel->IsItem_Folder(realIndex))
612 return;
613 m_SubFolderIndex = realIndex;
614 m_SubFolderName = m_Panel->GetItemName(m_SubFolderIndex);
615 MySetDropHighlighted(m_Panel->_listView, index, true);
616 m_SelectionIndex = index;
617}
618
619bool CDropTarget::IsFsFolderPath() const
620{
621 if (!m_IsAppTarget && m_Panel)
622 return (m_Panel->IsFSFolder() || (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0));
623 return false;
624}
625
626static void ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names)
627{
628 names.Clear();
629 UString name;
630 for (;size > 0; size--)
631 {
632 wchar_t c = *p++;
633 if (c == 0)
634 {
635 if (name.IsEmpty())
636 break;
637 names.Add(name);
638 name.Empty();
639 }
640 else
641 name += c;
642 }
643}
644
645static void ReadAnsiStrings(const char *p, size_t size, UStringVector &names)
646{
647 names.Clear();
648 AString name;
649 for (;size > 0; size--)
650 {
651 char c = *p++;
652 if (c == 0)
653 {
654 if (name.IsEmpty())
655 break;
656 names.Add(GetUnicodeString(name));
657 name.Empty();
658 }
659 else
660 name += c;
661 }
662}
663
664static void GetNamesFromDataObject(IDataObject *dataObject, UStringVector &names)
665{
666 names.Clear();
667 FORMATETC etc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
668 STGMEDIUM medium;
669 HRESULT res = dataObject->GetData(&etc, &medium);
670 if (res != S_OK)
671 return;
672 if (medium.tymed != TYMED_HGLOBAL)
673 return;
674 {
675 NMemory::CGlobal global;
676 global.Attach(medium.hGlobal);
677 size_t blockSize = GlobalSize(medium.hGlobal);
678 NMemory::CGlobalLock dropLock(medium.hGlobal);
679 const DROPFILES* dropFiles = (DROPFILES*)dropLock.GetPointer();
680 if (!dropFiles)
681 return;
682 if (blockSize < dropFiles->pFiles)
683 return;
684 size_t size = blockSize - dropFiles->pFiles;
685 const void *namesData = (const Byte *)dropFiles + dropFiles->pFiles;
686 if (dropFiles->fWide)
687 ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names);
688 else
689 ReadAnsiStrings((const char *)namesData, size, names);
690 }
691}
692
693bool CDropTarget::IsItSameDrive() const
694{
695 if (!m_Panel)
696 return false;
697 if (!IsFsFolderPath())
698 return false;
699
700 UString drive;
701
702 if (m_Panel->IsFSFolder())
703 {
704 drive = m_Panel->GetDriveOrNetworkPrefix();
705 if (drive.IsEmpty())
706 return false;
707 }
708 else if (m_Panel->IsFSDrivesFolder() && m_SelectionIndex >= 0)
709 {
710 drive = m_SubFolderName;
711 drive.Add_PathSepar();
712 }
713 else
714 return false;
715
716 if (m_SourcePaths.Size() == 0)
717 return false;
718
719 FOR_VECTOR (i, m_SourcePaths)
720 {
721 if (!m_SourcePaths[i].IsPrefixedBy_NoCase(drive))
722 return false;
723 }
724
725 return true;
726}
727
728
729/*
730 There are 2 different actions, when we drag to 7-Zip:
731 1) Drag from any external program except of Explorer to "7-Zip" FS folder.
732 We want to create new archive for that operation.
733 2) all another operation work as usual file COPY/MOVE
734 - Drag from "7-Zip" FS to "7-Zip" FS.
735 COPY/MOVE are supported.
736 - Drag to open archive in 7-Zip.
737 We want to update archive.
738 We replace COPY to MOVE.
739 - Drag from "7-Zip" archive to "7-Zip" FS.
740 We replace COPY to MOVE.
741*/
742
743DWORD CDropTarget::GetEffect(DWORD keyState, POINTL /* pt */, DWORD allowedEffect)
744{
745 if (!m_DropIsAllowed || !m_PanelDropIsAllowed)
746 return DROPEFFECT_NONE;
747
748 if (!IsFsFolderPath() || !m_SetPathIsOK)
749 allowedEffect &= ~DROPEFFECT_MOVE;
750
751 DWORD effect = 0;
752
753 if (keyState & MK_CONTROL)
754 effect = allowedEffect & DROPEFFECT_COPY;
755 else if (keyState & MK_SHIFT)
756 effect = allowedEffect & DROPEFFECT_MOVE;
757
758 if (effect == 0)
759 {
760 if (allowedEffect & DROPEFFECT_COPY)
761 effect = DROPEFFECT_COPY;
762 if (allowedEffect & DROPEFFECT_MOVE)
763 {
764 if (IsItSameDrive())
765 effect = DROPEFFECT_MOVE;
766 }
767 }
768 if (effect == 0)
769 return DROPEFFECT_NONE;
770 return effect;
771}
772
773UString CDropTarget::GetTargetPath() const
774{
775 if (!IsFsFolderPath())
776 return UString();
777 UString path = m_Panel->GetFsPath();
778 if (m_SubFolderIndex >= 0 && !m_SubFolderName.IsEmpty())
779 {
780 path += m_SubFolderName;
781 path.Add_PathSepar();
782 }
783 return path;
784}
785
786bool CDropTarget::SetPath(bool enablePath) const
787{
788 UINT setFolderFormat = RegisterClipboardFormat(kSvenZipSetFolderFormat);
789
790 FORMATETC etc = { (CLIPFORMAT)setFolderFormat, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
791 STGMEDIUM medium;
792 medium.tymed = etc.tymed;
793 medium.pUnkForRelease = 0;
794 UString path;
795 if (enablePath)
796 path = GetTargetPath();
797 size_t size = path.Len() + 1;
798 medium.hGlobal = GlobalAlloc(GHND | GMEM_SHARE, size * sizeof(wchar_t));
799 if (!medium.hGlobal)
800 return false;
801 wchar_t *dest = (wchar_t *)GlobalLock(medium.hGlobal);
802 if (!dest)
803 {
804 GlobalUnlock(medium.hGlobal);
805 return false;
806 }
807 MyStringCopy(dest, (const wchar_t *)path);
808 GlobalUnlock(medium.hGlobal);
809 bool res = m_DataObject->SetData(&etc, &medium, FALSE) == S_OK;
810 GlobalFree(medium.hGlobal);
811 return res;
812}
813
814bool CDropTarget::SetPath()
815{
816 m_SetPathIsOK = SetPath(m_DropIsAllowed && m_PanelDropIsAllowed && IsFsFolderPath());
817 return m_SetPathIsOK;
818}
819
820STDMETHODIMP CDropTarget::DragEnter(IDataObject * dataObject, DWORD keyState,
821 POINTL pt, DWORD *effect)
822{
823 GetNamesFromDataObject(dataObject, m_SourcePaths);
824 QueryGetData(dataObject);
825 m_DataObject = dataObject;
826 return DragOver(keyState, pt, effect);
827}
828
829
830STDMETHODIMP CDropTarget::DragOver(DWORD keyState, POINTL pt, DWORD *effect)
831{
832 PositionCursor(pt);
833 SetPath();
834 *effect = GetEffect(keyState, pt, *effect);
835 return S_OK;
836}
837
838
839STDMETHODIMP CDropTarget::DragLeave()
840{
841 RemoveSelection();
842 SetPath(false);
843 m_DataObject.Release();
844 return S_OK;
845}
846
847// We suppose that there was ::DragOver for same POINTL_pt before ::Drop
848// So SetPath() is same as in Drop.
849
850STDMETHODIMP CDropTarget::Drop(IDataObject *dataObject, DWORD keyState,
851 POINTL pt, DWORD * effect)
852{
853 QueryGetData(dataObject);
854 PositionCursor(pt);
855 m_DataObject = dataObject;
856 bool needDrop = true;
857 if (m_DropIsAllowed && m_PanelDropIsAllowed)
858 if (IsFsFolderPath())
859 needDrop = !SetPath();
860 *effect = GetEffect(keyState, pt, *effect);
861 if (m_DropIsAllowed && m_PanelDropIsAllowed)
862 {
863 if (needDrop)
864 {
865 UString path = GetTargetPath();
866 if (m_IsAppTarget && m_Panel)
867 if (m_Panel->IsFSFolder())
868 path = m_Panel->GetFsPath();
869 m_Panel->DropObject(dataObject, path);
870 }
871 }
872 RemoveSelection();
873 m_DataObject.Release();
874 return S_OK;
875}
876
877void CPanel::DropObject(IDataObject *dataObject, const UString &folderPath)
878{
879 UStringVector names;
880 GetNamesFromDataObject(dataObject, names);
881 CompressDropFiles(names, folderPath);
882}
883
884/*
885void CPanel::CompressDropFiles(HDROP dr)
886{
887 UStringVector fileNames;
888 {
889 NShell::CDrop drop(true);
890 drop.Attach(dr);
891 drop.QueryFileNames(fileNames);
892 }
893 CompressDropFiles(fileNamesUnicode);
894}
895*/
896
897static bool IsFolderInTemp(const FString &path)
898{
899 FString tempPath;
900 if (!MyGetTempPath(tempPath))
901 return false;
902 if (tempPath.IsEmpty())
903 return false;
904 unsigned len = tempPath.Len();
905 if (path.Len() < len)
906 return false;
907 return CompareFileNames(path.Left(len), tempPath) == 0;
908}
909
910static bool AreThereNamesFromTemp(const UStringVector &fileNames)
911{
912 FString tempPathF;
913 if (!MyGetTempPath(tempPathF))
914 return false;
915 UString tempPath = fs2us(tempPathF);
916 if (tempPath.IsEmpty())
917 return false;
918 FOR_VECTOR (i, fileNames)
919 if (fileNames[i].IsPrefixedBy_NoCase(tempPath))
920 return true;
921 return false;
922}
923
924void CPanel::CompressDropFiles(const UStringVector &fileNames, const UString &folderPath)
925{
926 if (fileNames.Size() == 0)
927 return;
928 bool createNewArchive = true;
929 if (!IsFSFolder())
930 createNewArchive = !DoesItSupportOperations();
931
932 if (createNewArchive)
933 {
934 UString folderPath2 = folderPath;
935 if (folderPath2.IsEmpty())
936 {
937 FString folderPath2F;
938 GetOnlyDirPrefix(us2fs(fileNames.Front()), folderPath2F);
939 folderPath2 = fs2us(folderPath2F);
940 if (IsFolderInTemp(folderPath2F))
941 folderPath2 = ROOT_FS_FOLDER;
942 }
943
944 const UString arcName = CreateArchiveName(fileNames);
945
946 CompressFiles(folderPath2, arcName, L"",
947 true, // addExtension
948 fileNames,
949 false, // email
950 true, // showDialog
951 AreThereNamesFromTemp(fileNames) // waitFinish
952 );
953 }
954 else
955 CopyFromAsk(fileNames);
956}
diff --git a/CPP/7zip/UI/FileManager/PanelFolderChange.cpp b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
new file mode 100644
index 0000000..b91195f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelFolderChange.cpp
@@ -0,0 +1,879 @@
1// PanelFolderChange.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/StringConvert.h"
6#include "../../../Common/Wildcard.h"
7
8#include "../../../Windows/FileName.h"
9#include "../../../Windows/FileDir.h"
10#include "../../../Windows/PropVariant.h"
11
12#include "../../PropID.h"
13
14#ifdef UNDER_CE
15#include "FSFolder.h"
16#else
17#include "FSDrives.h"
18#endif
19#include "LangUtils.h"
20#include "ListViewDialog.h"
21#include "Panel.h"
22#include "RootFolder.h"
23#include "ViewSettings.h"
24
25#include "resource.h"
26
27using namespace NWindows;
28using namespace NFile;
29using namespace NFind;
30
31void CPanel::ReleaseFolder()
32{
33 DeleteListItems();
34
35 _folder.Release();
36
37 _folderCompare.Release();
38 _folderGetItemName.Release();
39 _folderRawProps.Release();
40 _folderAltStreams.Release();
41 _folderOperations.Release();
42
43 _thereAreDeletedItems = false;
44}
45
46void CPanel::SetNewFolder(IFolderFolder *newFolder)
47{
48 ReleaseFolder();
49 _folder = newFolder;
50 if (_folder)
51 {
52 _folder.QueryInterface(IID_IFolderCompare, &_folderCompare);
53 _folder.QueryInterface(IID_IFolderGetItemName, &_folderGetItemName);
54 _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps);
55 _folder.QueryInterface(IID_IFolderAltStreams, &_folderAltStreams);
56 _folder.QueryInterface(IID_IFolderOperations, &_folderOperations);
57 }
58}
59
60void CPanel::SetToRootFolder()
61{
62 ReleaseFolder();
63 _library.Free();
64
65 CRootFolder *rootFolderSpec = new CRootFolder;
66 SetNewFolder(rootFolderSpec);
67 rootFolderSpec->Init();
68}
69
70
71static bool DoesNameContainWildcard_SkipRoot(const UString &path)
72{
73 return DoesNameContainWildcard(path.Ptr(NName::GetRootPrefixSize(path)));
74}
75
76HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, COpenResult &openRes)
77{
78 UString path = fullPath;
79 #ifdef _WIN32
80 path.Replace(L'/', WCHAR_PATH_SEPARATOR);
81 #endif
82
83 openRes.ArchiveIsOpened = false;
84 openRes.Encrypted = false;
85
86 CDisableTimerProcessing disableTimerProcessing(*this);
87 CDisableNotify disableNotify(*this);
88
89 for (; !_parentFolders.IsEmpty(); CloseOneLevel())
90 {
91 // ---------- we try to use open archive ----------
92
93 const CFolderLink &link = _parentFolders.Back();
94 const UString &virtPath = link.VirtualPath;
95 if (!path.IsPrefixedBy(virtPath))
96 continue;
97 UString relatPath = path.Ptr(virtPath.Len());
98 if (!relatPath.IsEmpty())
99 {
100 if (!IS_PATH_SEPAR(relatPath[0]))
101 continue;
102 else
103 relatPath.Delete(0);
104 }
105
106 UString relatPath2 = relatPath;
107 if (!relatPath2.IsEmpty() && !IS_PATH_SEPAR(relatPath2.Back()))
108 relatPath2.Add_PathSepar();
109
110 for (;;)
111 {
112 const UString foldPath = GetFolderPath(_folder);
113 if (relatPath2 == foldPath)
114 break;
115 if (relatPath.IsPrefixedBy(foldPath))
116 {
117 path = relatPath.Ptr(foldPath.Len());
118 break;
119 }
120 CMyComPtr<IFolderFolder> newFolder;
121 if (_folder->BindToParentFolder(&newFolder) != S_OK)
122 throw 20140918;
123 if (!newFolder) // we exit from loop above if (relatPath.IsPrefixedBy(empty path for root folder)
124 throw 20140918;
125 SetNewFolder(newFolder);
126 }
127 break;
128 }
129
130 if (_parentFolders.IsEmpty())
131 {
132 // ---------- we open file or folder from file system ----------
133
134 CloseOpenFolders();
135 UString sysPath = path;
136
137 unsigned prefixSize = NName::GetRootPrefixSize(sysPath);
138 if (prefixSize == 0 || sysPath[prefixSize] == 0)
139 sysPath.Empty();
140
141 #if defined(_WIN32) && !defined(UNDER_CE)
142 if (!sysPath.IsEmpty() && sysPath.Back() == ':' &&
143 (sysPath.Len() != 2 || !NName::IsDrivePath2(sysPath)))
144 {
145 UString baseFile = sysPath;
146 baseFile.DeleteBack();
147 if (NFind::DoesFileOrDirExist(us2fs(baseFile)))
148 sysPath.Empty();
149 }
150 #endif
151
152 CFileInfo fileInfo;
153
154 while (!sysPath.IsEmpty())
155 {
156 if (fileInfo.Find(us2fs(sysPath)))
157 break;
158 int pos = sysPath.ReverseFind_PathSepar();
159 if (pos < 0)
160 sysPath.Empty();
161 else
162 {
163 /*
164 if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1)
165 reducedParts.Add(sysPath.Ptr(pos + 1));
166 */
167 #if defined(_WIN32) && !defined(UNDER_CE)
168 if (pos == 2 && NName::IsDrivePath2(sysPath) && sysPath.Len() > 3)
169 pos++;
170 #endif
171
172 sysPath.DeleteFrom((unsigned)pos);
173 }
174 }
175
176 SetToRootFolder();
177
178 CMyComPtr<IFolderFolder> newFolder;
179
180 if (sysPath.IsEmpty())
181 {
182 _folder->BindToFolder(path, &newFolder);
183 }
184 else if (fileInfo.IsDir())
185 {
186 #ifdef _WIN32
187 if (DoesNameContainWildcard_SkipRoot(sysPath))
188 {
189 FString dirPrefix, fileName;
190 NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
191 if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix)))
192 return E_INVALIDARG;
193 sysPath = fs2us(dirPrefix + fileInfo.Name);
194 }
195 #endif
196
197 NName::NormalizeDirPathPrefix(sysPath);
198 _folder->BindToFolder(sysPath, &newFolder);
199 }
200 else
201 {
202 FString dirPrefix, fileName;
203
204 NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
205
206 HRESULT res = S_OK;
207
208 #ifdef _WIN32
209 if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix)))
210 return E_INVALIDARG;
211
212 if (DoesNameContainWildcard(fs2us(fileName)))
213 res = S_FALSE;
214 else
215 #endif
216 {
217 CTempFileInfo tfi;
218 tfi.RelPath = fs2us(fileName);
219 tfi.FolderPath = dirPrefix;
220 tfi.FilePath = us2fs(sysPath);
221 res = OpenAsArc(NULL, tfi, sysPath, arcFormat, openRes);
222 }
223
224 if (res == S_FALSE)
225 _folder->BindToFolder(fs2us(dirPrefix), &newFolder);
226 else
227 {
228 RINOK(res);
229 openRes.ArchiveIsOpened = true;
230 _parentFolders.Back().ParentFolderPath = fs2us(dirPrefix);
231 path.DeleteFrontal(sysPath.Len());
232 if (!path.IsEmpty() && IS_PATH_SEPAR(path[0]))
233 path.Delete(0);
234 }
235 }
236
237 if (newFolder)
238 {
239 SetNewFolder(newFolder);
240 // LoadFullPath();
241 return S_OK;
242 }
243 }
244
245 {
246 // ---------- we open folder remPath in archive and sub archives ----------
247
248 for (unsigned curPos = 0; curPos != path.Len();)
249 {
250 UString s = path.Ptr(curPos);
251 int slashPos = NName::FindSepar(s);
252 unsigned skipLen = s.Len();
253 if (slashPos >= 0)
254 {
255 s.DeleteFrom((unsigned)slashPos);
256 skipLen = slashPos + 1;
257 }
258
259 CMyComPtr<IFolderFolder> newFolder;
260 _folder->BindToFolder(s, &newFolder);
261 if (newFolder)
262 curPos += skipLen;
263 else if (_folderAltStreams)
264 {
265 int pos = s.Find(L':');
266 if (pos >= 0)
267 {
268 UString baseName = s;
269 baseName.DeleteFrom((unsigned)pos);
270 if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder)
271 curPos += pos + 1;
272 }
273 }
274
275 if (!newFolder)
276 break;
277
278 SetNewFolder(newFolder);
279 }
280 }
281
282 return S_OK;
283}
284
285HRESULT CPanel::BindToPathAndRefresh(const UString &path)
286{
287 CDisableTimerProcessing disableTimerProcessing(*this);
288 CDisableNotify disableNotify(*this);
289 COpenResult openRes;
290 UString s = path;
291
292 #ifdef _WIN32
293 if (!s.IsEmpty() && s[0] == '\"' && s.Back() == '\"')
294 {
295 s.DeleteBack();
296 s.Delete(0);
297 }
298 #endif
299
300 HRESULT res = BindToPath(s, UString(), openRes);
301 RefreshListCtrl();
302 return res;
303}
304
305void CPanel::SetBookmark(unsigned index)
306{
307 _appState->FastFolders.SetString(index, _currentFolderPrefix);
308}
309
310void CPanel::OpenBookmark(unsigned index)
311{
312 BindToPathAndRefresh(_appState->FastFolders.GetString(index));
313}
314
315UString GetFolderPath(IFolderFolder *folder)
316{
317 {
318 NCOM::CPropVariant prop;
319 if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)
320 if (prop.vt == VT_BSTR)
321 return (wchar_t *)prop.bstrVal;
322 }
323 return UString();
324}
325
326void CPanel::LoadFullPath()
327{
328 _currentFolderPrefix.Empty();
329 FOR_VECTOR (i, _parentFolders)
330 {
331 const CFolderLink &folderLink = _parentFolders[i];
332 _currentFolderPrefix += folderLink.ParentFolderPath;
333 // GetFolderPath(folderLink.ParentFolder);
334 _currentFolderPrefix += folderLink.RelPath;
335 _currentFolderPrefix.Add_PathSepar();
336 }
337 if (_folder)
338 _currentFolderPrefix += GetFolderPath(_folder);
339}
340
341static int GetRealIconIndex(CFSTR path, DWORD attributes)
342{
343 int index = -1;
344 if (GetRealIconIndex(path, attributes, index) != 0)
345 return index;
346 return -1;
347}
348
349void CPanel::LoadFullPathAndShow()
350{
351 LoadFullPath();
352 _appState->FolderHistory.AddString(_currentFolderPrefix);
353
354 _headerComboBox.SetText(_currentFolderPrefix);
355
356 #ifndef UNDER_CE
357
358 COMBOBOXEXITEM item;
359 item.mask = 0;
360
361 UString path = _currentFolderPrefix;
362 if (path.Len() >
363 #ifdef _WIN32
364 3
365 #else
366 1
367 #endif
368 && IS_PATH_SEPAR(path.Back()))
369 path.DeleteBack();
370
371 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
372
373 // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path
374 if (path.IsPrefixedBy(L"\\\\.\\"))
375 path = "_TestFolder_";
376 else
377 {
378 CFileInfo fi;
379 if (fi.Find(us2fs(path)))
380 attrib = fi.Attrib;
381 }
382 item.iImage = GetRealIconIndex(us2fs(path), attrib);
383
384 if (item.iImage >= 0)
385 {
386 item.iSelectedImage = item.iImage;
387 item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
388 }
389 item.iItem = -1;
390 _headerComboBox.SetItem(&item);
391
392 #endif
393
394 RefreshTitle();
395}
396
397#ifndef UNDER_CE
398LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s)
399{
400 if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK)
401 {
402 PostMsg(kSetFocusToListView);
403 return TRUE;
404 }
405 return FALSE;
406}
407
408bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result)
409{
410 if (info->iWhy == CBENF_ESCAPE)
411 {
412 _headerComboBox.SetText(_currentFolderPrefix);
413 PostMsg(kSetFocusToListView);
414 result = FALSE;
415 return true;
416 }
417
418 /*
419 if (info->iWhy == CBENF_DROPDOWN)
420 {
421 result = FALSE;
422 return true;
423 }
424 */
425
426 if (info->iWhy == CBENF_RETURN)
427 {
428 // When we use Edit control and press Enter.
429 UString s;
430 _headerComboBox.GetText(s);
431 result = OnNotifyComboBoxEnter(s);
432 return true;
433 }
434 return false;
435}
436#endif
437
438#ifndef _UNICODE
439bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
440{
441 if (info->iWhy == CBENF_ESCAPE)
442 {
443 _headerComboBox.SetText(_currentFolderPrefix);
444 PostMsg(kSetFocusToListView);
445 result = FALSE;
446 return true;
447 }
448 /*
449 if (info->iWhy == CBENF_DROPDOWN)
450 {
451 result = FALSE;
452 return true;
453 }
454 */
455
456 if (info->iWhy == CBENF_RETURN)
457 {
458 UString s;
459 _headerComboBox.GetText(s);
460 // GetUnicodeString(info->szText)
461 result = OnNotifyComboBoxEnter(s);
462 return true;
463 }
464 return false;
465}
466#endif
467
468void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList)
469{
470 #ifdef UNDER_CE
471
472 UString s;
473 iconIndex = iconIndex;
474 for (int i = 0; i < indent; i++)
475 s += " ";
476 _headerComboBox.AddString(s + name);
477
478 #else
479
480 COMBOBOXEXITEMW item;
481 item.mask = CBEIF_TEXT | CBEIF_INDENT;
482 item.iSelectedImage = item.iImage = iconIndex;
483 if (iconIndex >= 0)
484 item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
485 item.iItem = -1;
486 item.iIndent = indent;
487 item.pszText = name.Ptr_non_const();
488 _headerComboBox.InsertItem(&item);
489
490 #endif
491
492 if (addToList)
493 ComboBoxPaths.Add(name);
494}
495
496extern UString RootFolder_GetName_Computer(int &iconIndex);
497extern UString RootFolder_GetName_Network(int &iconIndex);
498extern UString RootFolder_GetName_Documents(int &iconIndex);
499
500bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
501{
502 result = FALSE;
503 switch (code)
504 {
505 case CBN_DROPDOWN:
506 {
507 ComboBoxPaths.Clear();
508 _headerComboBox.ResetContent();
509
510 unsigned i;
511 UStringVector pathParts;
512
513 SplitPathToParts(_currentFolderPrefix, pathParts);
514 UString sumPass;
515 if (!pathParts.IsEmpty())
516 pathParts.DeleteBack();
517 for (i = 0; i < pathParts.Size(); i++)
518 {
519 UString name = pathParts[i];
520 sumPass += name;
521 sumPass.Add_PathSepar();
522 CFileInfo info;
523 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
524 if (info.Find(us2fs(sumPass)))
525 attrib = info.Attrib;
526 AddComboBoxItem(name.IsEmpty() ? L"\\" : name, GetRealIconIndex(us2fs(sumPass), attrib), i, false);
527 ComboBoxPaths.Add(sumPass);
528 }
529
530 #ifndef UNDER_CE
531
532 int iconIndex;
533 UString name;
534 name = RootFolder_GetName_Documents(iconIndex);
535 AddComboBoxItem(name, iconIndex, 0, true);
536
537 name = RootFolder_GetName_Computer(iconIndex);
538 AddComboBoxItem(name, iconIndex, 0, true);
539
540 FStringVector driveStrings;
541 MyGetLogicalDriveStrings(driveStrings);
542 for (i = 0; i < driveStrings.Size(); i++)
543 {
544 FString s = driveStrings[i];
545 ComboBoxPaths.Add(fs2us(s));
546 int iconIndex2 = GetRealIconIndex(s, 0);
547 if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR)
548 s.DeleteBack();
549 AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
550 }
551
552 name = RootFolder_GetName_Network(iconIndex);
553 AddComboBoxItem(name, iconIndex, 0, true);
554
555 #endif
556
557 return false;
558 }
559
560 case CBN_SELENDOK:
561 {
562 int index = _headerComboBox.GetCurSel();
563 if (index >= 0)
564 {
565 UString pass = ComboBoxPaths[index];
566 _headerComboBox.SetCurSel(-1);
567 // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.
568 if (BindToPathAndRefresh(pass) == S_OK)
569 {
570 PostMsg(kSetFocusToListView);
571 #ifdef UNDER_CE
572 PostMsg(kRefresh_HeaderComboBox);
573 #endif
574 return true;
575 }
576 }
577 return false;
578 }
579 /*
580 case CBN_CLOSEUP:
581 {
582 LoadFullPathAndShow();
583 true;
584
585 }
586 case CBN_SELCHANGE:
587 {
588 // LoadFullPathAndShow();
589 return true;
590 }
591 */
592 }
593 return false;
594}
595
596bool CPanel::OnNotifyComboBox(LPNMHDR NON_CE_VAR(header), LRESULT & NON_CE_VAR(result))
597{
598 #ifndef UNDER_CE
599 switch (header->code)
600 {
601 case CBEN_BEGINEDIT:
602 {
603 _lastFocusedIsList = false;
604 _panelCallback->PanelWasFocused();
605 break;
606 }
607 #ifndef _UNICODE
608 case CBEN_ENDEDIT:
609 {
610 return OnNotifyComboBoxEndEdit((PNMCBEENDEDIT)header, result);
611 }
612 #endif
613 case CBEN_ENDEDITW:
614 {
615 return OnNotifyComboBoxEndEdit((PNMCBEENDEDITW)header, result);
616 }
617 }
618 #endif
619 return false;
620}
621
622
623void CPanel::FoldersHistory()
624{
625 CListViewDialog listViewDialog;
626 listViewDialog.DeleteIsAllowed = true;
627 listViewDialog.SelectFirst = true;
628 LangString(IDS_FOLDERS_HISTORY, listViewDialog.Title);
629 _appState->FolderHistory.GetList(listViewDialog.Strings);
630 if (listViewDialog.Create(GetParent()) != IDOK)
631 return;
632 UString selectString;
633 if (listViewDialog.StringsWereChanged)
634 {
635 _appState->FolderHistory.RemoveAll();
636 for (int i = listViewDialog.Strings.Size() - 1; i >= 0; i--)
637 _appState->FolderHistory.AddString(listViewDialog.Strings[i]);
638 if (listViewDialog.FocusedItemIndex >= 0)
639 selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
640 }
641 else
642 {
643 if (listViewDialog.FocusedItemIndex >= 0)
644 selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
645 }
646 if (listViewDialog.FocusedItemIndex >= 0)
647 BindToPathAndRefresh(selectString);
648}
649
650
651UString CPanel::GetParentDirPrefix() const
652{
653 UString s;
654 if (!_currentFolderPrefix.IsEmpty())
655 {
656 wchar_t c = _currentFolderPrefix.Back();
657 if (IS_PATH_SEPAR(c) || c == ':')
658 {
659 s = _currentFolderPrefix;
660 s.DeleteBack();
661 if (s != L"\\\\." &&
662 s != L"\\\\?")
663 {
664 int pos = s.ReverseFind_PathSepar();
665 if (pos >= 0)
666 s.DeleteFrom((unsigned)(pos + 1));
667 }
668 }
669 }
670 return s;
671}
672
673
674void CPanel::OpenParentFolder()
675{
676 LoadFullPath(); // Maybe we don't need it ??
677
678 UString parentFolderPrefix;
679 UString focusedName;
680
681 if (!_currentFolderPrefix.IsEmpty())
682 {
683 wchar_t c = _currentFolderPrefix.Back();
684 if (IS_PATH_SEPAR(c) || c == ':')
685 {
686 focusedName = _currentFolderPrefix;
687 focusedName.DeleteBack();
688 /*
689 if (c == ':' && !focusedName.IsEmpty() && IS_PATH_SEPAR(focusedName.Back()))
690 {
691 focusedName.DeleteBack();
692 }
693 else
694 */
695 if (focusedName != L"\\\\." &&
696 focusedName != L"\\\\?")
697 {
698 int pos = focusedName.ReverseFind_PathSepar();
699 if (pos >= 0)
700 {
701 parentFolderPrefix = focusedName;
702 parentFolderPrefix.DeleteFrom((unsigned)(pos + 1));
703 focusedName.DeleteFrontal(pos + 1);
704 }
705 }
706 }
707 }
708
709 CDisableTimerProcessing disableTimerProcessing(*this);
710 CDisableNotify disableNotify(*this);
711
712 CMyComPtr<IFolderFolder> newFolder;
713 _folder->BindToParentFolder(&newFolder);
714
715 // newFolder.Release(); // for test
716
717 if (newFolder)
718 SetNewFolder(newFolder);
719 else
720 {
721 bool needSetFolder = true;
722 if (!_parentFolders.IsEmpty())
723 {
724 {
725 const CFolderLink &link = _parentFolders.Back();
726 parentFolderPrefix = link.ParentFolderPath;
727 focusedName = link.RelPath;
728 }
729 CloseOneLevel();
730 needSetFolder = (!_folder);
731 }
732
733 if (needSetFolder)
734 {
735 {
736 COpenResult openRes;
737 BindToPath(parentFolderPrefix, UString(), openRes);
738 }
739 }
740 }
741
742 CSelectedState state;
743 state.FocusedName = focusedName;
744 state.FocusedName_Defined = true;
745 /*
746 if (!focusedName.IsEmpty())
747 state.SelectedNames.Add(focusedName);
748 */
749 LoadFullPath();
750 // ::SetCurrentDirectory(::_currentFolderPrefix);
751 RefreshListCtrl(state);
752 // _listView.EnsureVisible(_listView.GetFocusedItem(), false);
753}
754
755
756void CPanel::CloseOneLevel()
757{
758 ReleaseFolder();
759 _library.Free();
760 {
761 CFolderLink &link = _parentFolders.Back();
762 if (link.ParentFolder)
763 SetNewFolder(link.ParentFolder);
764 _library.Attach(link.Library.Detach());
765 }
766 if (_parentFolders.Size() > 1)
767 OpenParentArchiveFolder();
768 _parentFolders.DeleteBack();
769 if (_parentFolders.IsEmpty())
770 _flatMode = _flatModeForDisk;
771}
772
773void CPanel::CloseOpenFolders()
774{
775 while (!_parentFolders.IsEmpty())
776 CloseOneLevel();
777 _flatMode = _flatModeForDisk;
778 ReleaseFolder();
779 _library.Free();
780}
781
782void CPanel::OpenRootFolder()
783{
784 CDisableTimerProcessing disableTimerProcessing(*this);
785 CDisableNotify disableNotify(*this);
786 _parentFolders.Clear();
787 SetToRootFolder();
788 RefreshListCtrl();
789 // ::SetCurrentDirectory(::_currentFolderPrefix);
790 /*
791 BeforeChangeFolder();
792 _currentFolderPrefix.Empty();
793 AfterChangeFolder();
794 SetCurrentPathText();
795 RefreshListCtrl(UString(), 0, UStringVector());
796 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
797 */
798}
799
800void CPanel::OpenDrivesFolder()
801{
802 CloseOpenFolders();
803 #ifdef UNDER_CE
804 NFsFolder::CFSFolder *folderSpec = new NFsFolder::CFSFolder;
805 SetNewFolder(folderSpec);
806 folderSpec->InitToRoot();
807 #else
808 CFSDrives *folderSpec = new CFSDrives;
809 SetNewFolder(folderSpec);
810 folderSpec->Init();
811 #endif
812 RefreshListCtrl();
813}
814
815void CPanel::OpenFolder(int index)
816{
817 if (index == kParentIndex)
818 {
819 OpenParentFolder();
820 return;
821 }
822 CMyComPtr<IFolderFolder> newFolder;
823 HRESULT res = _folder->BindToFolder(index, &newFolder);
824 if (res != 0)
825 {
826 MessageBox_Error_HRESULT(res);
827 return;
828 }
829 if (!newFolder)
830 return;
831 SetNewFolder(newFolder);
832 LoadFullPath();
833 RefreshListCtrl();
834 // 17.02: fixed : now we don't select first item
835 // _listView.SetItemState_Selected(_listView.GetFocusedItem());
836 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
837}
838
839void CPanel::OpenAltStreams()
840{
841 CRecordVector<UInt32> indices;
842 GetOperatedItemIndices(indices);
843 Int32 realIndex = -1;
844 if (indices.Size() > 1)
845 return;
846 if (indices.Size() == 1)
847 realIndex = indices[0];
848
849 if (_folderAltStreams)
850 {
851 CMyComPtr<IFolderFolder> newFolder;
852 _folderAltStreams->BindToAltStreams(realIndex, &newFolder);
853 if (newFolder)
854 {
855 CDisableTimerProcessing disableTimerProcessing(*this);
856 CDisableNotify disableNotify(*this);
857 SetNewFolder(newFolder);
858 RefreshListCtrl();
859 return;
860 }
861 return;
862 }
863
864 #if defined(_WIN32) && !defined(UNDER_CE)
865 UString path;
866 if (realIndex >= 0)
867 path = GetItemFullPath(realIndex);
868 else
869 {
870 path = GetFsPath();
871 if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path)))
872 if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back()))
873 path.DeleteBack();
874 }
875
876 path += ':';
877 BindToPathAndRefresh(path);
878 #endif
879}
diff --git a/CPP/7zip/UI/FileManager/PanelItemOpen.cpp b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
new file mode 100644
index 0000000..ba54491
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelItemOpen.cpp
@@ -0,0 +1,1874 @@
1// PanelItemOpen.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyWindows.h"
6
7#include <TlHelp32.h>
8
9#include "../../../Common/IntToString.h"
10
11#include "../../../Common/AutoPtr.h"
12#include "../../../Common/StringConvert.h"
13
14#include "../../../Windows/ProcessUtils.h"
15#include "../../../Windows/FileName.h"
16#include "../../../Windows/PropVariant.h"
17#include "../../../Windows/PropVariantConv.h"
18
19#include "../../Common/FileStreams.h"
20#include "../../Common/StreamObjects.h"
21
22#include "../Common/ExtractingFilePath.h"
23
24#include "App.h"
25
26#include "FileFolderPluginOpen.h"
27#include "FormatUtils.h"
28#include "LangUtils.h"
29#include "PropertyNameRes.h"
30#include "RegistryUtils.h"
31#include "UpdateCallback100.h"
32
33#include "../GUI/ExtractRes.h"
34
35#include "resource.h"
36
37using namespace NWindows;
38using namespace NSynchronization;
39using namespace NFile;
40using namespace NDir;
41
42extern bool g_RAM_Size_Defined;
43extern UInt64 g_RAM_Size;
44
45#ifndef _UNICODE
46extern bool g_IsNT;
47#endif
48
49#define kTempDirPrefix FTEXT("7zO")
50
51// #define SHOW_DEBUG_INFO
52
53#ifdef SHOW_DEBUG_INFO
54 #define DEBUG_PRINT(s) OutputDebugStringA(s);
55 #define DEBUG_PRINT_W(s) OutputDebugStringW(s);
56 #define DEBUG_PRINT_NUM(s, num) { char ttt[32]; ConvertUInt32ToString(num, ttt); OutputDebugStringA(s); OutputDebugStringA(ttt); }
57#else
58 #define DEBUG_PRINT(s)
59 #define DEBUG_PRINT_W(s)
60 #define DEBUG_PRINT_NUM(s, num)
61#endif
62
63
64
65#ifndef UNDER_CE
66
67class CProcessSnapshot
68{
69 HANDLE _handle;
70public:
71 CProcessSnapshot(): _handle(INVALID_HANDLE_VALUE) {};
72 ~CProcessSnapshot() { Close(); }
73
74 bool Close()
75 {
76 if (_handle == INVALID_HANDLE_VALUE)
77 return true;
78 if (!::CloseHandle(_handle))
79 return false;
80 _handle = INVALID_HANDLE_VALUE;
81 return true;
82 }
83
84 bool Create()
85 {
86 _handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
87 return (_handle != INVALID_HANDLE_VALUE);
88 }
89
90 bool GetFirstProcess(PROCESSENTRY32 *pe) { return BOOLToBool(Process32First(_handle, pe)); }
91 bool GetNextProcess(PROCESSENTRY32 *pe) { return BOOLToBool(Process32Next(_handle, pe)); }
92};
93
94#endif
95
96
97/*
98struct COpenExtProg
99{
100 const char *Ext;
101 const char *Prog;
102};
103
104static const COpenExtProg g_Progs[] =
105{
106 { "jpeg jpg png bmp gif", "Microsoft.Photos.exe" },
107 { "html htm pdf", "MicrosoftEdge.exe" },
108 // , { "rrr", "notepad.exe" }
109};
110
111static bool FindExtProg(const char *exts, const char *ext)
112{
113 unsigned len = (unsigned)strlen(ext);
114 for (;;)
115 {
116 const char *p = exts;
117 for (;; p++)
118 {
119 const char c = *p;
120 if (c == 0 || c == ' ')
121 break;
122 }
123 if (len == (unsigned)(p - exts) && IsString1PrefixedByString2(exts, ext))
124 return true;
125 if (*p == 0)
126 return false;
127 exts = p + 1;
128 }
129}
130
131class CPossibleProgs
132{
133public:
134 AStringVector ProgNames;
135
136 void SetFromExtension(const char *ext) // ext must be low case
137 {
138 ProgNames.Clear();
139 for (unsigned i = 0; i < ARRAY_SIZE(g_Progs); i++)
140 if (FindExtProg(g_Progs[i].Ext, ext))
141 {
142 ProgNames.Add(g_Progs[i].Prog);
143 }
144 }
145
146 bool IsFromList(const UString &progName) const
147 {
148 FOR_VECTOR (i, ProgNames)
149 if (progName.IsEqualTo_Ascii_NoCase(ProgNames[i]))
150 return true;
151 return false;
152 }
153};
154*/
155
156
157#ifndef UNDER_CE
158
159EXTERN_C_BEGIN
160
161/*
162GetProcessImageFileName
163 returns the path in device form, rather than drive letters:
164 \Device\HarddiskVolume1\WINDOWS\SysWOW64\notepad.exe
165
166GetModuleFileNameEx works only after Sleep(something). Why?
167 returns the path
168 C:\WINDOWS\system32\NOTEPAD.EXE
169*/
170
171/* Kernel32.dll: Win7, Win2008R2;
172 Psapi.dll: (if PSAPI_VERSION=1) on Win7 and Win2008R2;
173 Psapi.dll: XP, Win2003, Vista, 2008;
174*/
175
176typedef DWORD (WINAPI *Func_GetProcessImageFileNameW)(
177 HANDLE hProcess, LPWSTR lpFilename, DWORD nSize);
178
179typedef DWORD (WINAPI *Func_GetModuleFileNameExW)(
180 HANDLE hProcess, HMODULE hModule, LPWSTR lpFilename, DWORD nSize);
181
182typedef DWORD (WINAPI *Func_GetProcessId)(HANDLE process);
183
184EXTERN_C_END
185
186
187static HMODULE g_Psapi_dll_module;
188
189/*
190static void My_GetProcessFileName_2(HANDLE hProcess, UString &path)
191{
192 path.Empty();
193 const unsigned maxPath = 1024;
194 WCHAR temp[maxPath + 1];
195
196 const char *func_name = "GetModuleFileNameExW";
197 Func_GetModuleFileNameExW my_func = (Func_GetModuleFileNameExW)
198 ::GetProcAddress(::GetModuleHandleA("kernel32.dll"), func_name);
199 if (!my_func)
200 {
201 if (!g_Psapi_dll_module)
202 g_Psapi_dll_module = LoadLibraryW(L"Psapi.dll");
203 if (g_Psapi_dll_module)
204 my_func = (Func_GetModuleFileNameExW)::GetProcAddress(g_Psapi_dll_module, func_name);
205 }
206 if (my_func)
207 {
208 // DWORD num = GetModuleFileNameEx(hProcess, NULL, temp, maxPath);
209 DWORD num = my_func(hProcess, NULL, temp, maxPath);
210 if (num != 0)
211 path = temp;
212 }
213 // FreeLibrary(lib);
214}
215*/
216
217static void My_GetProcessFileName(HANDLE hProcess, UString &path)
218{
219 path.Empty();
220 const unsigned maxPath = 1024;
221 WCHAR temp[maxPath + 1];
222
223 const char *func_name = "GetProcessImageFileNameW";
224 Func_GetProcessImageFileNameW my_func = (Func_GetProcessImageFileNameW)
225 (void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), func_name);
226
227 if (!my_func)
228 {
229 if (!g_Psapi_dll_module)
230 g_Psapi_dll_module = LoadLibraryW(L"Psapi.dll");
231 if (g_Psapi_dll_module)
232 my_func = (Func_GetProcessImageFileNameW)(void *)::GetProcAddress(g_Psapi_dll_module, func_name);
233 }
234
235 if (my_func)
236 {
237 // DWORD num = GetProcessImageFileNameW(hProcess, temp, maxPath);
238 DWORD num = my_func(hProcess, temp, maxPath);
239 if (num != 0)
240 path = temp;
241 }
242 // FreeLibrary(lib);
243}
244
245struct CSnapshotProcess
246{
247 DWORD Id;
248 DWORD ParentId;
249 UString Name;
250};
251
252static void GetSnapshot(CObjectVector<CSnapshotProcess> &items)
253{
254 items.Clear();
255
256 CProcessSnapshot snapshot;
257 if (!snapshot.Create())
258 return;
259
260 DEBUG_PRINT("snapshot.Create() OK");
261 PROCESSENTRY32 pe;
262 CSnapshotProcess item;
263 memset(&pe, 0, sizeof(pe));
264 pe.dwSize = sizeof(pe);
265 BOOL res = snapshot.GetFirstProcess(&pe);
266 while (res)
267 {
268 item.Id = pe.th32ProcessID;
269 item.ParentId = pe.th32ParentProcessID;
270 item.Name = GetUnicodeString(pe.szExeFile);
271 items.Add(item);
272 res = snapshot.GetNextProcess(&pe);
273 }
274}
275
276#endif
277
278
279class CChildProcesses
280{
281 #ifndef UNDER_CE
282 CRecordVector<DWORD> _ids;
283 #endif
284
285public:
286 // bool ProgsWereUsed;
287 CRecordVector<HANDLE> Handles;
288 CRecordVector<bool> NeedWait;
289 // UStringVector Names;
290
291 #ifndef UNDER_CE
292 UString Path;
293 #endif
294
295 // CChildProcesses(): ProgsWereUsed(false) {}
296 ~CChildProcesses() { CloseAll(); }
297 void DisableWait(unsigned index) { NeedWait[index] = false; }
298
299 void CloseAll()
300 {
301 FOR_VECTOR (i, Handles)
302 {
303 HANDLE h = Handles[i];
304 if (h != NULL)
305 CloseHandle(h);
306 }
307
308 Handles.Clear();
309 NeedWait.Clear();
310 // Names.Clear();
311
312 #ifndef UNDER_CE
313 // Path.Empty();
314 _ids.Clear();
315 #endif
316 }
317
318 void SetMainProcess(HANDLE h)
319 {
320 #ifndef UNDER_CE
321
322 Func_GetProcessId func = (Func_GetProcessId)(void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GetProcessId");
323 if (func)
324 {
325 DWORD id = func(h);
326 if (id != 0)
327 _ids.AddToUniqueSorted(id);
328 }
329
330 My_GetProcessFileName(h, Path);
331 DEBUG_PRINT_W(Path);
332
333 #endif
334
335 Handles.Add(h);
336 NeedWait.Add(true);
337 }
338
339 #ifndef UNDER_CE
340
341 void Update(bool needFindProcessByPath /* , const CPossibleProgs &progs */)
342 {
343 /*
344 if (_ids.IsEmpty())
345 return;
346 */
347
348 CObjectVector<CSnapshotProcess> sps;
349 GetSnapshot(sps);
350
351 const int separ = Path.ReverseFind_PathSepar();
352 const UString mainName = Path.Ptr((unsigned)(separ + 1));
353 if (mainName.IsEmpty())
354 needFindProcessByPath = false;
355
356 const DWORD currentProcessId = GetCurrentProcessId();
357
358 for (;;)
359 {
360 bool wasAdded = false;
361
362 FOR_VECTOR (i, sps)
363 {
364 const CSnapshotProcess &sp = sps[i];
365 const DWORD id = sp.Id;
366
367 if (id == currentProcessId)
368 continue;
369 if (_ids.FindInSorted(id) >= 0)
370 continue;
371
372 bool isSameName = false;
373 const UString &name = sp.Name;
374
375 if (needFindProcessByPath)
376 isSameName = mainName.IsEqualTo_NoCase(name);
377
378 bool needAdd = false;
379 // bool isFromProgs = false;
380
381 if (isSameName || _ids.FindInSorted(sp.ParentId) >= 0)
382 needAdd = true;
383 /*
384 else if (progs.IsFromList(name))
385 {
386 needAdd = true;
387 isFromProgs = true;
388 }
389 */
390
391 if (needAdd)
392 {
393 DEBUG_PRINT("----- OpenProcess -----");
394 DEBUG_PRINT_W(name);
395 HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, id);
396 if (hProcess)
397 {
398 DEBUG_PRINT("----- OpenProcess OK -----");
399 // if (!isFromProgs)
400 _ids.AddToUniqueSorted(id);
401 Handles.Add(hProcess);
402 NeedWait.Add(true);
403 // Names.Add(name);
404 wasAdded = true;
405 // ProgsWereUsed = isFromProgs;
406 }
407 }
408 }
409
410 if (!wasAdded)
411 break;
412 }
413 }
414
415 #endif
416};
417
418
419struct CTmpProcessInfo: public CTempFileInfo
420{
421 CChildProcesses Processes;
422 HWND Window;
423 UString FullPathFolderPrefix;
424 bool UsePassword;
425 UString Password;
426
427 bool ReadOnly;
428
429 CTmpProcessInfo(): UsePassword(false), ReadOnly(false) {}
430};
431
432
433class CTmpProcessInfoRelease
434{
435 CTmpProcessInfo *_tmpProcessInfo;
436public:
437 bool _needDelete;
438 CTmpProcessInfoRelease(CTmpProcessInfo &tpi):
439 _tmpProcessInfo(&tpi), _needDelete(true) {}
440 ~CTmpProcessInfoRelease()
441 {
442 if (_needDelete)
443 _tmpProcessInfo->DeleteDirAndFile();
444 }
445};
446
447void GetFolderError(CMyComPtr<IFolderFolder> &folder, UString &s);
448
449
450HRESULT CPanel::OpenAsArc(IInStream *inStream,
451 const CTempFileInfo &tempFileInfo,
452 const UString &virtualFilePath,
453 const UString &arcFormat,
454 COpenResult &openRes)
455{
456 openRes.Encrypted = false;
457 CFolderLink folderLink;
458 (CTempFileInfo &)folderLink = tempFileInfo;
459
460 if (inStream)
461 folderLink.IsVirtual = true;
462 else
463 {
464 if (!folderLink.FileInfo.Find(folderLink.FilePath))
465 return ::GetLastError();
466 if (folderLink.FileInfo.IsDir())
467 return S_FALSE;
468 folderLink.IsVirtual = false;
469 }
470
471 folderLink.VirtualPath = virtualFilePath;
472
473 CFfpOpen ffp;
474 HRESULT res = ffp.OpenFileFolderPlugin(inStream,
475 folderLink.FilePath.IsEmpty() ? us2fs(virtualFilePath) : folderLink.FilePath,
476 arcFormat, GetParent());
477
478 openRes.Encrypted = ffp.Encrypted;
479 openRes.ErrorMessage = ffp.ErrorMessage;
480
481 RINOK(res);
482
483 folderLink.Password = ffp.Password;
484 folderLink.UsePassword = ffp.Encrypted;
485
486 if (_folder)
487 folderLink.ParentFolderPath = GetFolderPath(_folder);
488 else
489 folderLink.ParentFolderPath = _currentFolderPrefix;
490
491 if (!_parentFolders.IsEmpty())
492 folderLink.ParentFolder = _folder;
493
494 _parentFolders.Add(folderLink);
495 _parentFolders.Back().Library.Attach(_library.Detach());
496
497 ReleaseFolder();
498 _library.Free();
499 SetNewFolder(ffp.Folder);
500 _library.Attach(ffp.Library.Detach());
501
502 _flatMode = _flatModeForArc;
503
504 _thereAreDeletedItems = false;
505
506 if (!openRes.ErrorMessage.IsEmpty())
507 MessageBox_Error(openRes.ErrorMessage);
508 /*
509 UString s;
510 GetFolderError(_folder, s);
511 if (!s.IsEmpty())
512 MessageBox_Error(s);
513 */
514 // we don't show error here by some reasons:
515 // after MessageBox_Warning it throws exception in nested archives in Debug Mode. why ?.
516 // MessageBox_Warning(L"test error");
517
518 return S_OK;
519}
520
521
522HRESULT CPanel::OpenAsArc_Msg(IInStream *inStream,
523 const CTempFileInfo &tempFileInfo,
524 const UString &virtualFilePath,
525 const UString &arcFormat
526 // , bool &encrypted
527 // , bool showErrorMessage
528 )
529{
530 COpenResult opRes;
531
532 HRESULT res = OpenAsArc(inStream, tempFileInfo, virtualFilePath, arcFormat, opRes);
533
534 if (res == S_OK)
535 return res;
536 if (res == E_ABORT)
537 return res;
538
539 // if (showErrorMessage)
540 if (opRes.Encrypted || res != S_FALSE) // 17.01 : we show message also for (res != S_FALSE)
541 {
542 UString message;
543 if (res == S_FALSE)
544 {
545 message = MyFormatNew(
546 opRes.Encrypted ?
547 IDS_CANT_OPEN_ENCRYPTED_ARCHIVE :
548 IDS_CANT_OPEN_ARCHIVE,
549 virtualFilePath);
550 }
551 else
552 message = HResultToMessage(res);
553 MessageBox_Error(message);
554 }
555
556 return res;
557}
558
559
560HRESULT CPanel::OpenAsArc_Name(const UString &relPath, const UString &arcFormat
561 // , bool &encrypted,
562 // , bool showErrorMessage
563 )
564{
565 CTempFileInfo tfi;
566 tfi.RelPath = relPath;
567 tfi.FolderPath = us2fs(GetFsPath());
568 const UString fullPath = GetFsPath() + relPath;
569 tfi.FilePath = us2fs(fullPath);
570 return OpenAsArc_Msg(NULL, tfi, fullPath, arcFormat /* , encrypted, showErrorMessage */);
571}
572
573
574HRESULT CPanel::OpenAsArc_Index(int index, const wchar_t *type
575 // , bool showErrorMessage
576 )
577{
578 CDisableTimerProcessing disableTimerProcessing1(*this);
579 CDisableNotify disableNotify(*this);
580
581 HRESULT res = OpenAsArc_Name(GetItemRelPath2(index), type ? type : L"" /* , encrypted, showErrorMessage */);
582 if (res != S_OK)
583 {
584 RefreshTitle(true); // in case of error we must refresh changed title of 7zFM
585 return res;
586 }
587 RefreshListCtrl();
588 return S_OK;
589}
590
591
592HRESULT CPanel::OpenParentArchiveFolder()
593{
594 CDisableTimerProcessing disableTimerProcessing(*this);
595 CDisableNotify disableNotify(*this);
596 if (_parentFolders.Size() < 2)
597 return S_OK;
598 const CFolderLink &folderLinkPrev = _parentFolders[_parentFolders.Size() - 2];
599 const CFolderLink &folderLink = _parentFolders.Back();
600 NFind::CFileInfo newFileInfo;
601 if (newFileInfo.Find(folderLink.FilePath))
602 {
603 if (folderLink.WasChanged(newFileInfo))
604 {
605 UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, folderLink.RelPath);
606 if (::MessageBoxW((HWND)*this, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
607 {
608 if (OnOpenItemChanged(folderLink.FileIndex, fs2us(folderLink.FilePath),
609 folderLinkPrev.UsePassword, folderLinkPrev.Password) != S_OK)
610 {
611 ::MessageBoxW((HWND)*this, MyFormatNew(IDS_CANNOT_UPDATE_FILE,
612 fs2us(folderLink.FilePath)), L"7-Zip", MB_OK | MB_ICONSTOP);
613 return S_OK;
614 }
615 }
616 }
617 }
618 folderLink.DeleteDirAndFile();
619 return S_OK;
620}
621
622
623static const char * const kExeExtensions =
624 " exe bat ps1 com"
625 " ";
626
627static const char * const kStartExtensions =
628 #ifdef UNDER_CE
629 " cab"
630 #endif
631 " exe bat ps1 com"
632 " chm"
633 " msi doc dot xls ppt pps wps wpt wks xlr wdb vsd pub"
634
635 " docx docm dotx dotm xlsx xlsm xltx xltm xlsb xps"
636 " xlam pptx pptm potx potm ppam ppsx ppsm vsdx xsn"
637 " mpp"
638 " msg"
639 " dwf"
640
641 " flv swf"
642
643 " epub"
644 " odt ods"
645 " wb3"
646 " pdf"
647 " ps"
648 " txt"
649 " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
650 " h hpp hxx c cpp cxx m mm go swift"
651 " awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs"
652 " asm"
653 " mak clw csproj vcproj sln dsp dsw"
654 " ";
655
656static bool FindExt(const char *p, const UString &name)
657{
658 int dotPos = name.ReverseFind_Dot();
659 if (dotPos < 0 || dotPos == (int)name.Len() - 1)
660 return false;
661
662 AString s;
663 for (unsigned pos = dotPos + 1;; pos++)
664 {
665 wchar_t c = name[pos];
666 if (c == 0)
667 break;
668 if (c >= 0x80)
669 return false;
670 s += (char)MyCharLower_Ascii((char)c);
671 }
672 for (unsigned i = 0; p[i] != 0;)
673 {
674 unsigned j;
675 for (j = i; p[j] != ' '; j++);
676 if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0)
677 return true;
678 i = j + 1;
679 }
680 return false;
681}
682
683static bool DoItemAlwaysStart(const UString &name)
684{
685 return FindExt(kStartExtensions, name);
686}
687
688UString GetQuotedString(const UString &s);
689
690
691void SplitCmdLineSmart(const UString &cmd, UString &prg, UString &params);
692void SplitCmdLineSmart(const UString &cmd, UString &prg, UString &params)
693{
694 params.Empty();
695 prg = cmd;
696 prg.Trim();
697 if (prg.Len() >= 2 && prg[0] == L'"')
698 {
699 int pos = prg.Find(L'"', 1);
700 if (pos >= 0)
701 {
702 if ((unsigned)(pos + 1) == prg.Len() || prg[pos + 1] == ' ')
703 {
704 params = prg.Ptr((unsigned)(pos + 1));
705 params.Trim();
706 prg.DeleteFrom((unsigned)pos);
707 prg.DeleteFrontal(1);
708 }
709 }
710 }
711}
712
713
714static WRes StartAppWithParams(const UString &cmd, const UStringVector &paramVector, CProcess &process)
715{
716 UString param;
717 UString prg;
718
719 SplitCmdLineSmart(cmd, prg, param);
720
721 param.Trim();
722
723 // int pos = params.Find(L"%1");
724
725 FOR_VECTOR (i, paramVector)
726 {
727 if (!param.IsEmpty() && param.Back() != ' ')
728 param.Add_Space();
729 param += GetQuotedString(paramVector[i]);
730 }
731
732 return process.Create(prg, param, NULL);
733}
734
735
736static HRESULT StartEditApplication(const UString &path, bool useEditor, HWND window, CProcess &process)
737{
738 UString command;
739 ReadRegEditor(useEditor, command);
740 if (command.IsEmpty())
741 {
742 #ifdef UNDER_CE
743 command = "\\Windows\\";
744 #else
745 FString winDir;
746 if (!GetWindowsDir(winDir))
747 return 0;
748 NName::NormalizeDirPathPrefix(winDir);
749 command = fs2us(winDir);
750 #endif
751 command += "notepad.exe";
752 }
753
754 UStringVector params;
755 params.Add(path);
756
757 HRESULT res = StartAppWithParams(command, params, process);
758 if (res != SZ_OK)
759 ::MessageBoxW(window, LangString(IDS_CANNOT_START_EDITOR), L"7-Zip", MB_OK | MB_ICONSTOP);
760 return res;
761}
762
763
764void CApp::DiffFiles()
765{
766 const CPanel &panel = GetFocusedPanel();
767
768 if (!panel.Is_IO_FS_Folder())
769 {
770 panel.MessageBox_Error_UnsupportOperation();
771 return;
772 }
773
774 CRecordVector<UInt32> indices;
775 panel.GetSelectedItemsIndices(indices);
776
777 UString path1, path2;
778 if (indices.Size() == 2)
779 {
780 path1 = panel.GetItemFullPath(indices[0]);
781 path2 = panel.GetItemFullPath(indices[1]);
782 }
783 else if (indices.Size() == 1 && NumPanels >= 2)
784 {
785 const CPanel &destPanel = Panels[1 - LastFocusedPanel];
786
787 if (!destPanel.Is_IO_FS_Folder())
788 {
789 panel.MessageBox_Error_UnsupportOperation();
790 return;
791 }
792
793 path1 = panel.GetItemFullPath(indices[0]);
794 CRecordVector<UInt32> indices2;
795 destPanel.GetSelectedItemsIndices(indices2);
796 if (indices2.Size() == 1)
797 path2 = destPanel.GetItemFullPath(indices2[0]);
798 else
799 {
800 UString relPath = panel.GetItemRelPath2(indices[0]);
801 if (panel._flatMode && !destPanel._flatMode)
802 relPath = panel.GetItemName(indices[0]);
803 path2 = destPanel._currentFolderPrefix + relPath;
804 }
805 }
806 else
807 return;
808
809 DiffFiles(path1, path2);
810}
811
812void CApp::DiffFiles(const UString &path1, const UString &path2)
813{
814 UString command;
815 ReadRegDiff(command);
816 if (command.IsEmpty())
817 return;
818
819 UStringVector params;
820 params.Add(path1);
821 params.Add(path2);
822
823 HRESULT res;
824 {
825 CProcess process;
826 res = StartAppWithParams(command, params, process);
827 }
828 if (res == SZ_OK)
829 return;
830 ::MessageBoxW(_window, LangString(IDS_CANNOT_START_EDITOR), L"7-Zip", MB_OK | MB_ICONSTOP);
831}
832
833
834#ifndef _UNICODE
835typedef BOOL (WINAPI * ShellExecuteExWP)(LPSHELLEXECUTEINFOW lpExecInfo);
836#endif
837
838static HRESULT StartApplication(const UString &dir, const UString &path, HWND window, CProcess &process)
839{
840 UString path2 = path;
841
842 #ifdef _WIN32
843 {
844 int dot = path2.ReverseFind_Dot();
845 int separ = path2.ReverseFind_PathSepar();
846 if (dot < 0 || dot < separ)
847 path2 += '.';
848 }
849 #endif
850
851 UINT32 result;
852
853 #ifndef _UNICODE
854 if (g_IsNT)
855 {
856 SHELLEXECUTEINFOW execInfo;
857 execInfo.cbSize = sizeof(execInfo);
858 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
859 execInfo.hwnd = NULL;
860 execInfo.lpVerb = NULL;
861 execInfo.lpFile = path2;
862 execInfo.lpParameters = NULL;
863 execInfo.lpDirectory = dir.IsEmpty() ? NULL : (LPCWSTR)dir;
864 execInfo.nShow = SW_SHOWNORMAL;
865 execInfo.hProcess = 0;
866 ShellExecuteExWP shellExecuteExW = (ShellExecuteExWP)
867 (void *)::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "ShellExecuteExW");
868 if (!shellExecuteExW)
869 return 0;
870 shellExecuteExW(&execInfo);
871 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
872 process.Attach(execInfo.hProcess);
873 }
874 else
875 #endif
876 {
877 SHELLEXECUTEINFO execInfo;
878 execInfo.cbSize = sizeof(execInfo);
879 execInfo.fMask = SEE_MASK_NOCLOSEPROCESS
880 #ifndef UNDER_CE
881 | SEE_MASK_FLAG_DDEWAIT
882 #endif
883 ;
884 execInfo.hwnd = NULL;
885 execInfo.lpVerb = NULL;
886 const CSysString sysPath (GetSystemString(path2));
887 const CSysString sysDir (GetSystemString(dir));
888 execInfo.lpFile = sysPath;
889 execInfo.lpParameters = NULL;
890 execInfo.lpDirectory =
891 #ifdef UNDER_CE
892 NULL
893 #else
894 sysDir.IsEmpty() ? NULL : (LPCTSTR)sysDir
895 #endif
896 ;
897 execInfo.nShow = SW_SHOWNORMAL;
898 execInfo.hProcess = 0;
899 ::ShellExecuteEx(&execInfo);
900 result = (UINT32)(UINT_PTR)execInfo.hInstApp;
901 process.Attach(execInfo.hProcess);
902 }
903
904
905 DEBUG_PRINT_NUM("-- ShellExecuteEx -- execInfo.hInstApp = ", result)
906
907 if (result <= 32)
908 {
909 switch (result)
910 {
911 case SE_ERR_NOASSOC:
912 ::MessageBoxW(window,
913 NError::MyFormatMessage(::GetLastError()),
914 // L"There is no application associated with the given file name extension",
915 L"7-Zip", MB_OK | MB_ICONSTOP);
916 }
917
918 return E_FAIL; // fixed in 15.13. Can we use it for any Windows version?
919 }
920
921 return S_OK;
922}
923
924static void StartApplicationDontWait(const UString &dir, const UString &path, HWND window)
925{
926 CProcess process;
927 StartApplication(dir, path, window, process);
928}
929
930void CPanel::EditItem(int index, bool useEditor)
931{
932 if (!_parentFolders.IsEmpty())
933 {
934 OpenItemInArchive(index, false, true, true, useEditor);
935 return;
936 }
937 CProcess process;
938 StartEditApplication(GetItemFullPath(index), useEditor, (HWND)*this, process);
939}
940
941
942void CPanel::OpenFolderExternal(int index)
943{
944 UString prefix = GetFsPath();
945 UString path = prefix;
946
947 if (index == kParentIndex)
948 {
949 if (prefix.IsEmpty())
950 return;
951 const wchar_t c = prefix.Back();
952 if (!IS_PATH_SEPAR(c) && c != ':')
953 return;
954 prefix.DeleteBack();
955 int pos = prefix.ReverseFind_PathSepar();
956 if (pos < 0)
957 return;
958 prefix.DeleteFrom((unsigned)(pos + 1));
959 path = prefix;
960 }
961 else
962 {
963 path += GetItemRelPath(index);
964 path.Add_PathSepar();
965 }
966
967 StartApplicationDontWait(prefix, path, (HWND)*this);
968}
969
970
971bool CPanel::IsVirus_Message(const UString &name)
972{
973 UString name2;
974
975 const wchar_t cRLO = (wchar_t)0x202E;
976 bool isVirus = false;
977 bool isSpaceError = false;
978 name2 = name;
979
980 if (name2.Find(cRLO) >= 0)
981 {
982 const UString badString(cRLO);
983 name2.Replace(badString, L"[RLO]");
984 isVirus = true;
985 }
986 {
987 const wchar_t * const kVirusSpaces = L" ";
988 // const unsigned kNumSpaces = strlen(kVirusSpaces);
989 for (;;)
990 {
991 int pos = name2.Find(kVirusSpaces);
992 if (pos < 0)
993 break;
994 isVirus = true;
995 isSpaceError = true;
996 name2.Replace(kVirusSpaces, L" ");
997 }
998 }
999
1000 #ifdef _WIN32
1001 {
1002 unsigned i;
1003 for (i = name2.Len(); i != 0;)
1004 {
1005 wchar_t c = name2[i - 1];
1006 if (c != '.' && c != ' ')
1007 break;
1008 i--;
1009 name2.ReplaceOneCharAtPos(i, '_');
1010 }
1011 if (i != name2.Len())
1012 {
1013 UString name3 = name2;
1014 name3.DeleteFrom(i);
1015 if (FindExt(kExeExtensions, name3))
1016 isVirus = true;
1017 }
1018 }
1019 #endif
1020
1021 if (!isVirus)
1022 return false;
1023
1024 UString s = LangString(IDS_VIRUS);
1025
1026 if (!isSpaceError)
1027 {
1028 int pos1 = s.Find(L'(');
1029 if (pos1 >= 0)
1030 {
1031 int pos2 = s.Find(L')', pos1 + 1);
1032 if (pos2 >= 0)
1033 {
1034 s.Delete(pos1, pos2 + 1 - pos1);
1035 if (pos1 > 0 && s[pos1 - 1] == ' ' && s[pos1] == '.')
1036 s.Delete(pos1 - 1);
1037 }
1038 }
1039 }
1040
1041 UString name3 = name;
1042 name3.Replace(L'\n', L'_');
1043 name2.Replace(L'\n', L'_');
1044
1045 s.Add_LF(); s += name2;
1046 s.Add_LF(); s += name3;
1047
1048 MessageBox_Error(s);
1049 return true;
1050}
1051
1052
1053void CPanel::OpenItem(int index, bool tryInternal, bool tryExternal, const wchar_t *type)
1054{
1055 CDisableTimerProcessing disableTimerProcessing(*this);
1056 UString name = GetItemRelPath2(index);
1057
1058 if (tryExternal)
1059 if (IsVirus_Message(name))
1060 return;
1061
1062 if (!_parentFolders.IsEmpty())
1063 {
1064 OpenItemInArchive(index, tryInternal, tryExternal, false, false, type);
1065 return;
1066 }
1067
1068 CDisableNotify disableNotify(*this);
1069 UString prefix = GetFsPath();
1070 UString fullPath = prefix + name;
1071
1072 if (tryInternal)
1073 if (!tryExternal || !DoItemAlwaysStart(name))
1074 {
1075 HRESULT res = OpenAsArc_Index(index, type
1076 // , true
1077 );
1078 disableNotify.Restore(); // we must restore to allow text notification update
1079 InvalidateList();
1080 if (res == S_OK || res == E_ABORT)
1081 return;
1082 if (res != S_FALSE)
1083 {
1084 MessageBox_Error_HRESULT(res);
1085 return;
1086 }
1087 }
1088
1089 if (tryExternal)
1090 {
1091 // SetCurrentDirectory opens HANDLE to folder!!!
1092 // NDirectory::MySetCurrentDirectory(prefix);
1093 StartApplicationDontWait(prefix, fullPath, (HWND)*this);
1094 }
1095}
1096
1097class CThreadCopyFrom: public CProgressThreadVirt
1098{
1099 HRESULT ProcessVirt();
1100public:
1101 UString FullPath;
1102 UInt32 ItemIndex;
1103
1104 CMyComPtr<IFolderOperations> FolderOperations;
1105 CMyComPtr<IProgress> UpdateCallback;
1106 CUpdateCallback100Imp *UpdateCallbackSpec;
1107};
1108
1109HRESULT CThreadCopyFrom::ProcessVirt()
1110{
1111 return FolderOperations->CopyFromFile(ItemIndex, FullPath, UpdateCallback);
1112}
1113
1114HRESULT CPanel::OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath,
1115 bool usePassword, const UString &password)
1116{
1117 if (!_folderOperations)
1118 {
1119 MessageBox_Error_UnsupportOperation();
1120 return E_FAIL;
1121 }
1122
1123 CThreadCopyFrom t;
1124 t.UpdateCallbackSpec = new CUpdateCallback100Imp;
1125 t.UpdateCallback = t.UpdateCallbackSpec;
1126 t.UpdateCallbackSpec->ProgressDialog = &t;
1127 t.ItemIndex = index;
1128 t.FullPath = fullFilePath;
1129 t.FolderOperations = _folderOperations;
1130
1131 t.UpdateCallbackSpec->Init();
1132 t.UpdateCallbackSpec->PasswordIsDefined = usePassword;
1133 t.UpdateCallbackSpec->Password = password;
1134
1135
1136 RINOK(t.Create(GetItemName(index), (HWND)*this));
1137 return t.Result;
1138}
1139
1140LRESULT CPanel::OnOpenItemChanged(LPARAM lParam)
1141{
1142 // DEBUG_PRINT_NUM("OnOpenItemChanged", GetCurrentThreadId());
1143
1144 CTmpProcessInfo &tpi = *(CTmpProcessInfo *)lParam;
1145 if (tpi.FullPathFolderPrefix != _currentFolderPrefix)
1146 return 0;
1147 UInt32 fileIndex = tpi.FileIndex;
1148 UInt32 numItems;
1149 _folder->GetNumberOfItems(&numItems);
1150
1151 // This code is not 100% OK for cases when there are several files with
1152 // tpi.RelPath name and there are changes in archive before update.
1153 // So tpi.FileIndex can point to another file.
1154
1155 if (fileIndex >= numItems || GetItemRelPath(fileIndex) != tpi.RelPath)
1156 {
1157 UInt32 i;
1158 for (i = 0; i < numItems; i++)
1159 if (GetItemRelPath(i) == tpi.RelPath)
1160 break;
1161 if (i == numItems)
1162 return 0;
1163 fileIndex = i;
1164 }
1165
1166 CSelectedState state;
1167 SaveSelectedState(state);
1168
1169 CDisableNotify disableNotify(*this); // do we need it??
1170
1171 HRESULT result = OnOpenItemChanged(fileIndex, fs2us(tpi.FilePath), tpi.UsePassword, tpi.Password);
1172 RefreshListCtrl(state);
1173 if (result != S_OK)
1174 return 0;
1175 return 1;
1176}
1177
1178
1179CExitEventLauncher g_ExitEventLauncher;
1180
1181void CExitEventLauncher::Exit(bool hardExit)
1182{
1183 if (_needExit)
1184 {
1185 _exitEvent.Set();
1186 _needExit = false;
1187 }
1188
1189 if (_numActiveThreads == 0)
1190 return;
1191
1192 FOR_VECTOR (i, _threads)
1193 {
1194 ::CThread &th = _threads[i];
1195 DWORD wait = (hardExit ? 100 : INFINITE);
1196 if (Thread_WasCreated(&th))
1197 {
1198 DWORD waitResult = WaitForSingleObject(th, wait);
1199 // Thread_Wait(&th);
1200 if (waitResult == WAIT_TIMEOUT)
1201 wait = 1;
1202 if (!hardExit && waitResult != WAIT_OBJECT_0)
1203 continue;
1204 Thread_Close(&th);
1205 _numActiveThreads--;
1206 }
1207 }
1208}
1209
1210
1211
1212static THREAD_FUNC_DECL MyThreadFunction(void *param)
1213{
1214 DEBUG_PRINT("==== MyThreadFunction ====");
1215
1216 CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr((CTmpProcessInfo *)param);
1217 CTmpProcessInfo *tpi = tmpProcessInfoPtr.get();
1218 CChildProcesses &processes = tpi->Processes;
1219
1220 bool mainProcessWasSet = !processes.Handles.IsEmpty();
1221
1222 bool isComplexMode = true;
1223
1224 if (!processes.Handles.IsEmpty())
1225 {
1226
1227 const DWORD startTime = GetTickCount();
1228
1229 /*
1230 CPossibleProgs progs;
1231 {
1232 const UString &name = tpi->RelPath;
1233 int slashPos = name.ReverseFind_PathSepar();
1234 int dotPos = name.ReverseFind_Dot();
1235 if (dotPos > slashPos)
1236 {
1237 const UString ext = name.Ptr(dotPos + 1);
1238 AString extA = UnicodeStringToMultiByte(ext);
1239 extA.MakeLower_Ascii();
1240 progs.SetFromExtension(extA);
1241 }
1242 }
1243 */
1244
1245 bool firstPass = true;
1246
1247 for (;;)
1248 {
1249 CRecordVector<HANDLE> handles;
1250 CUIntVector indices;
1251
1252 FOR_VECTOR (i, processes.Handles)
1253 {
1254 if (handles.Size() > 60)
1255 break;
1256 if (processes.NeedWait[i])
1257 {
1258 handles.Add(processes.Handles[i]);
1259 indices.Add(i);
1260 }
1261 }
1262
1263 bool needFindProcessByPath = false;
1264
1265 if (handles.IsEmpty())
1266 {
1267 if (!firstPass)
1268 break;
1269 }
1270 else
1271 {
1272 handles.Add(g_ExitEventLauncher._exitEvent);
1273
1274 DWORD waitResult = WaitForMultiObj_Any_Infinite(handles.Size(), &handles.Front());
1275
1276 waitResult -= WAIT_OBJECT_0;
1277
1278 if (waitResult >= handles.Size() - 1)
1279 {
1280 processes.CloseAll();
1281 /*
1282 if (waitResult == handles.Size() - 1)
1283 {
1284 // exit event
1285 // we want to delete temp files, if progs were used
1286 if (processes.ProgsWereUsed)
1287 break;
1288 }
1289 */
1290 return waitResult >= (DWORD)handles.Size() ? 1 : 0;
1291 }
1292
1293 if (firstPass && indices.Size() == 1)
1294 {
1295 DWORD curTime = GetTickCount() - startTime;
1296
1297 /*
1298 if (curTime > 5 * 1000)
1299 progs.ProgNames.Clear();
1300 */
1301
1302 needFindProcessByPath = (curTime < 2 * 1000);
1303
1304 if (needFindProcessByPath)
1305 {
1306 NFind::CFileInfo newFileInfo;
1307 if (newFileInfo.Find(tpi->FilePath))
1308 if (tpi->WasChanged(newFileInfo))
1309 needFindProcessByPath = false;
1310 }
1311
1312 DEBUG_PRINT_NUM(" -- firstPass -- time = ", curTime)
1313 }
1314
1315 processes.DisableWait(indices[waitResult]);
1316 }
1317
1318 firstPass = false;
1319
1320 // Sleep(300);
1321 #ifndef UNDER_CE
1322 processes.Update(needFindProcessByPath /* , progs */);
1323 #endif
1324 }
1325
1326
1327 DWORD curTime = GetTickCount() - startTime;
1328
1329 DEBUG_PRINT_NUM("after time = ", curTime)
1330
1331 processes.CloseAll();
1332
1333 isComplexMode = (curTime < 2 * 1000);
1334
1335 }
1336
1337 bool needCheckTimestamp = true;
1338
1339 for (;;)
1340 {
1341 NFind::CFileInfo newFileInfo;
1342
1343 if (!newFileInfo.Find(tpi->FilePath))
1344 break;
1345
1346 if (mainProcessWasSet)
1347 {
1348 if (tpi->WasChanged(newFileInfo))
1349 {
1350 UString m = MyFormatNew(IDS_CANNOT_UPDATE_FILE, fs2us(tpi->FilePath));
1351 if (tpi->ReadOnly)
1352 {
1353 m.Add_LF();
1354 AddLangString(m, IDS_PROP_READ_ONLY);
1355 m.Add_LF();
1356 m += tpi->FullPathFolderPrefix;
1357 ::MessageBoxW(g_HWND, m, L"7-Zip", MB_OK | MB_ICONSTOP);
1358 return 0;
1359 }
1360 {
1361 const UString message = MyFormatNew(IDS_WANT_UPDATE_MODIFIED_FILE, tpi->RelPath);
1362 if (::MessageBoxW(g_HWND, message, L"7-Zip", MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
1363 {
1364 // DEBUG_PRINT_NUM("SendMessage", GetCurrentThreadId());
1365 if (SendMessage(tpi->Window, kOpenItemChanged, 0, (LONG_PTR)tpi) != 1)
1366 {
1367 ::MessageBoxW(g_HWND, m, L"7-Zip", MB_OK | MB_ICONSTOP);
1368 return 0;
1369 }
1370 }
1371 needCheckTimestamp = false;
1372 break;
1373 }
1374 }
1375
1376 if (!isComplexMode)
1377 break;
1378 }
1379
1380 // DEBUG_PRINT("WaitForSingleObject");
1381 DWORD waitResult = ::WaitForSingleObject(g_ExitEventLauncher._exitEvent, INFINITE);
1382 // DEBUG_PRINT("---");
1383
1384 if (waitResult == WAIT_OBJECT_0)
1385 break;
1386
1387 return 1;
1388 }
1389
1390 {
1391 NFind::CFileInfo newFileInfo;
1392
1393 bool finded = newFileInfo.Find(tpi->FilePath);
1394
1395 if (!needCheckTimestamp || !finded || !tpi->WasChanged(newFileInfo))
1396 {
1397 DEBUG_PRINT("Delete Temp file");
1398 tpi->DeleteDirAndFile();
1399 }
1400 }
1401
1402 return 0;
1403}
1404
1405
1406
1407#if defined(_WIN32) && !defined(UNDER_CE)
1408static const FChar * const k_ZoneId_StreamName = FTEXT(":Zone.Identifier");
1409#endif
1410
1411
1412#ifndef UNDER_CE
1413
1414static void ReadZoneFile(CFSTR fileName, CByteBuffer &buf)
1415{
1416 buf.Free();
1417 NIO::CInFile file;
1418 if (!file.Open(fileName))
1419 return;
1420 UInt64 fileSize;
1421 if (!file.GetLength(fileSize))
1422 return;
1423 if (fileSize == 0 || fileSize >= ((UInt32)1 << 20))
1424 return;
1425 buf.Alloc((size_t)fileSize);
1426 size_t processed;
1427 if (file.ReadFull(buf, (size_t)fileSize, processed) && processed == fileSize)
1428 return;
1429 buf.Free();
1430}
1431
1432static bool WriteZoneFile(CFSTR fileName, const CByteBuffer &buf)
1433{
1434 NIO::COutFile file;
1435 if (!file.Create(fileName, true))
1436 return false;
1437 UInt32 processed;
1438 if (!file.Write(buf, (UInt32)buf.Size(), processed))
1439 return false;
1440 return processed == buf.Size();
1441}
1442
1443#endif
1444
1445/*
1446class CBufSeqOutStream_WithFile:
1447 public ISequentialOutStream,
1448 public CMyUnknownImp
1449{
1450 Byte *_buffer;
1451 size_t _size;
1452 size_t _pos;
1453
1454
1455 size_t _fileWritePos;
1456 bool fileMode;
1457public:
1458
1459 bool IsStreamInMem() const { return !fileMode; }
1460 size_t GetMemStreamWrittenSize() const { return _pos; }
1461
1462 // ISequentialOutStream *FileStream;
1463 FString FilePath;
1464 COutFileStream *outFileStreamSpec;
1465 CMyComPtr<ISequentialOutStream> outFileStream;
1466
1467 CBufSeqOutStream_WithFile(): outFileStreamSpec(NULL) {}
1468
1469 void Init(Byte *buffer, size_t size)
1470 {
1471 fileMode = false;
1472 _buffer = buffer;
1473 _pos = 0;
1474 _size = size;
1475 _fileWritePos = 0;
1476 }
1477
1478 HRESULT FlushToFile();
1479 size_t GetPos() const { return _pos; }
1480
1481 MY_UNKNOWN_IMP
1482 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
1483};
1484
1485static const UInt32 kBlockSize = ((UInt32)1 << 31);
1486
1487STDMETHODIMP CBufSeqOutStream_WithFile::Write(const void *data, UInt32 size, UInt32 *processedSize)
1488{
1489 if (processedSize)
1490 *processedSize = 0;
1491 if (!fileMode)
1492 {
1493 if (_size - _pos >= size)
1494 {
1495 if (size != 0)
1496 {
1497 memcpy(_buffer + _pos, data, size);
1498 _pos += size;
1499 }
1500 if (processedSize)
1501 *processedSize = (UInt32)size;
1502 return S_OK;
1503 }
1504
1505 fileMode = true;
1506 }
1507 RINOK(FlushToFile());
1508 return outFileStream->Write(data, size, processedSize);
1509}
1510
1511HRESULT CBufSeqOutStream_WithFile::FlushToFile()
1512{
1513 if (!outFileStream)
1514 {
1515 outFileStreamSpec = new COutFileStream;
1516 outFileStream = outFileStreamSpec;
1517 if (!outFileStreamSpec->Create(FilePath, false))
1518 {
1519 outFileStream.Release();
1520 return E_FAIL;
1521 // MessageBoxMyError(UString("Can't create file ") + fs2us(tempFilePath));
1522 }
1523 }
1524 while (_fileWritePos != _pos)
1525 {
1526 size_t cur = _pos - _fileWritePos;
1527 UInt32 curSize = (cur < kBlockSize) ? (UInt32)cur : kBlockSize;
1528 UInt32 processedSizeLoc = 0;
1529 HRESULT res = outFileStream->Write(_buffer + _fileWritePos, curSize, &processedSizeLoc);
1530 _fileWritePos += processedSizeLoc;
1531 RINOK(res);
1532 if (processedSizeLoc == 0)
1533 return E_FAIL;
1534 }
1535 return S_OK;
1536}
1537*/
1538
1539/*
1540static HRESULT GetTime(IFolderFolder *folder, UInt32 index, PROPID propID, FILETIME &filetime, bool &filetimeIsDefined)
1541{
1542 filetimeIsDefined = false;
1543 NCOM::CPropVariant prop;
1544 RINOK(folder->GetProperty(index, propID, &prop));
1545 if (prop.vt == VT_FILETIME)
1546 {
1547 filetime = prop.filetime;
1548 filetimeIsDefined = (filetime.dwHighDateTime != 0 || filetime.dwLowDateTime != 0);
1549 }
1550 else if (prop.vt != VT_EMPTY)
1551 return E_FAIL;
1552 return S_OK;
1553}
1554*/
1555
1556
1557/*
1558tryInternal tryExternal
1559 false false : unused
1560 false true : external
1561 true false : internal
1562 true true : smart based on file extension:
1563 !alwaysStart(name) : both
1564 alwaysStart(name) : external
1565*/
1566
1567void CPanel::OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode, bool useEditor, const wchar_t *type)
1568{
1569 // we don't want to change hash data here
1570 if (IsHashFolder())
1571 return;
1572
1573 const UString name = GetItemName(index);
1574 const UString relPath = GetItemRelPath(index);
1575
1576 if (tryExternal)
1577 if (IsVirus_Message(name))
1578 return;
1579
1580 if (!_folderOperations)
1581 {
1582 MessageBox_Error_UnsupportOperation();
1583 return;
1584 }
1585
1586 bool tryAsArchive = tryInternal && (!tryExternal || !DoItemAlwaysStart(name));
1587
1588 const UString fullVirtPath = _currentFolderPrefix + relPath;
1589
1590 CTempDir tempDirectory;
1591 if (!tempDirectory.Create(kTempDirPrefix))
1592 {
1593 MessageBox_LastError();
1594 return;
1595 }
1596
1597 FString tempDir = tempDirectory.GetPath();
1598 FString tempDirNorm = tempDir;
1599 NName::NormalizeDirPathPrefix(tempDirNorm);
1600 const FString tempFilePath = tempDirNorm + us2fs(Get_Correct_FsFile_Name(name));
1601
1602 CTempFileInfo tempFileInfo;
1603 tempFileInfo.FileIndex = index;
1604 tempFileInfo.RelPath = relPath;
1605 tempFileInfo.FolderPath = tempDir;
1606 tempFileInfo.FilePath = tempFilePath;
1607 tempFileInfo.NeedDelete = true;
1608
1609 if (tryAsArchive)
1610 {
1611 CMyComPtr<IInArchiveGetStream> getStream;
1612 _folder.QueryInterface(IID_IInArchiveGetStream, &getStream);
1613 if (getStream)
1614 {
1615 CMyComPtr<ISequentialInStream> subSeqStream;
1616 getStream->GetStream(index, &subSeqStream);
1617 if (subSeqStream)
1618 {
1619 CMyComPtr<IInStream> subStream;
1620 subSeqStream.QueryInterface(IID_IInStream, &subStream);
1621 if (subStream)
1622 {
1623 HRESULT res = OpenAsArc_Msg(subStream, tempFileInfo, fullVirtPath, type ? type : L""
1624 // , true // showErrorMessage
1625 );
1626 if (res == S_OK)
1627 {
1628 tempDirectory.DisableDeleting();
1629 RefreshListCtrl();
1630 return;
1631 }
1632 if (res == E_ABORT || res != S_FALSE)
1633 return;
1634 if (!tryExternal)
1635 return;
1636 tryAsArchive = false;
1637 }
1638 }
1639 }
1640 }
1641
1642
1643 CRecordVector<UInt32> indices;
1644 indices.Add(index);
1645
1646 UStringVector messages;
1647
1648 bool usePassword = false;
1649 UString password;
1650 if (_parentFolders.Size() > 0)
1651 {
1652 const CFolderLink &fl = _parentFolders.Back();
1653 usePassword = fl.UsePassword;
1654 password = fl.Password;
1655 }
1656
1657 #if defined(_WIN32) && !defined(UNDER_CE)
1658 CByteBuffer zoneBuf;
1659 #ifndef _UNICODE
1660 if (g_IsNT)
1661 #endif
1662 if (_parentFolders.Size() > 0)
1663 {
1664 const CFolderLink &fl = _parentFolders.Front();
1665 if (!fl.IsVirtual && !fl.FilePath.IsEmpty())
1666 ReadZoneFile(fl.FilePath + k_ZoneId_StreamName, zoneBuf);
1667 }
1668 #endif
1669
1670
1671 CVirtFileSystem *virtFileSystemSpec = NULL;
1672 CMyComPtr<ISequentialOutStream> virtFileSystem;
1673
1674 bool isAltStream = IsItem_AltStream(index);
1675
1676 CCopyToOptions options;
1677 options.includeAltStreams = true;
1678 options.replaceAltStreamChars = isAltStream;
1679
1680 if (tryAsArchive)
1681 {
1682 NCOM::CPropVariant prop;
1683 _folder->GetProperty(index, kpidSize, &prop);
1684 UInt64 fileLimit = 1 << 22;
1685 if (g_RAM_Size_Defined)
1686 fileLimit = g_RAM_Size / 4;
1687
1688 UInt64 fileSize = 0;
1689 if (!ConvertPropVariantToUInt64(prop, fileSize))
1690 fileSize = fileLimit;
1691 if (fileSize <= fileLimit && fileSize > 0)
1692 {
1693 options.streamMode = true;
1694 virtFileSystemSpec = new CVirtFileSystem;
1695 virtFileSystem = virtFileSystemSpec;
1696 // we allow additional total size for small alt streams;
1697 virtFileSystemSpec->MaxTotalAllocSize = fileSize + (1 << 10);
1698
1699 virtFileSystemSpec->DirPrefix = tempDirNorm;
1700 virtFileSystemSpec->Init();
1701 options.VirtFileSystem = virtFileSystem;
1702 options.VirtFileSystemSpec = virtFileSystemSpec;
1703 }
1704 }
1705
1706 options.folder = fs2us(tempDirNorm);
1707 options.showErrorMessages = true;
1708
1709 HRESULT result = CopyTo(options, indices, &messages, usePassword, password);
1710
1711 if (_parentFolders.Size() > 0)
1712 {
1713 CFolderLink &fl = _parentFolders.Back();
1714 fl.UsePassword = usePassword;
1715 fl.Password = password;
1716 }
1717
1718 if (!messages.IsEmpty())
1719 return;
1720 if (result != S_OK)
1721 {
1722 if (result != E_ABORT)
1723 MessageBox_Error_HRESULT(result);
1724 return;
1725 }
1726
1727 if (options.VirtFileSystem)
1728 {
1729 if (virtFileSystemSpec->IsStreamInMem())
1730 {
1731 const CVirtFile &file = virtFileSystemSpec->Files[0];
1732
1733 size_t streamSize = (size_t)file.Size;
1734 CBufInStream *bufInStreamSpec = new CBufInStream;
1735 CMyComPtr<IInStream> bufInStream = bufInStreamSpec;
1736 bufInStreamSpec->Init(file.Data, streamSize, virtFileSystem);
1737
1738 HRESULT res = OpenAsArc_Msg(bufInStream, tempFileInfo, fullVirtPath, type ? type : L""
1739 // , encrypted
1740 // , true // showErrorMessage
1741 );
1742
1743 if (res == S_OK)
1744 {
1745 tempDirectory.DisableDeleting();
1746 RefreshListCtrl();
1747 return;
1748 }
1749
1750 if (res == E_ABORT || res != S_FALSE)
1751 return;
1752 if (!tryExternal)
1753 return;
1754
1755 tryAsArchive = false;
1756 if (virtFileSystemSpec->FlushToDisk(true) != S_OK)
1757 return;
1758 }
1759 }
1760
1761
1762 #if defined(_WIN32) && !defined(UNDER_CE)
1763 if (zoneBuf.Size() != 0)
1764 {
1765 if (NFind::DoesFileExist_Raw(tempFilePath))
1766 {
1767 WriteZoneFile(tempFilePath + k_ZoneId_StreamName, zoneBuf);
1768 }
1769 }
1770 #endif
1771
1772
1773 if (tryAsArchive)
1774 {
1775 HRESULT res = OpenAsArc_Msg(NULL, tempFileInfo, fullVirtPath, type ? type : L""
1776 // , encrypted
1777 // , true // showErrorMessage
1778 );
1779 if (res == S_OK)
1780 {
1781 tempDirectory.DisableDeleting();
1782 RefreshListCtrl();
1783 return;
1784 }
1785 if (res == E_ABORT || res != S_FALSE)
1786 return;
1787 }
1788
1789 if (!tryExternal)
1790 return;
1791
1792 CMyAutoPtr<CTmpProcessInfo> tmpProcessInfoPtr(new CTmpProcessInfo());
1793 CTmpProcessInfo *tpi = tmpProcessInfoPtr.get();
1794 tpi->FolderPath = tempDir;
1795 tpi->FilePath = tempFilePath;
1796 tpi->NeedDelete = true;
1797 tpi->UsePassword = usePassword;
1798 tpi->Password = password;
1799 tpi->ReadOnly = IsThereReadOnlyFolder();
1800 if (IsHashFolder())
1801 tpi->ReadOnly = true;
1802
1803 if (!tpi->FileInfo.Find(tempFilePath))
1804 return;
1805
1806 CTmpProcessInfoRelease tmpProcessInfoRelease(*tpi);
1807
1808 CProcess process;
1809 HRESULT res;
1810 if (editMode)
1811 res = StartEditApplication(fs2us(tempFilePath), useEditor, (HWND)*this, process);
1812 else
1813 res = StartApplication(fs2us(tempDirNorm), fs2us(tempFilePath), (HWND)*this, process);
1814
1815 if ((HANDLE)process == NULL)
1816 {
1817 // win7 / win10 work so for some extensions (pdf, html ..);
1818 DEBUG_PRINT("#### (HANDLE)process == 0");
1819 // return;
1820 if (res != SZ_OK)
1821 return;
1822 }
1823
1824 tpi->Window = (HWND)(*this);
1825 tpi->FullPathFolderPrefix = _currentFolderPrefix;
1826 tpi->FileIndex = index;
1827 tpi->RelPath = relPath;
1828
1829 if ((HANDLE)process != 0)
1830 tpi->Processes.SetMainProcess(process.Detach());
1831
1832 ::CThread th;
1833 if (Thread_Create(&th, MyThreadFunction, tpi) != 0)
1834 throw 271824;
1835 g_ExitEventLauncher._threads.Add(th);
1836 g_ExitEventLauncher._numActiveThreads++;
1837
1838 tempDirectory.DisableDeleting();
1839 tmpProcessInfoPtr.release();
1840 tmpProcessInfoRelease._needDelete = false;
1841}
1842
1843
1844/*
1845static const UINT64 kTimeLimit = UINT64(10000000) * 3600 * 24;
1846
1847static bool CheckDeleteItem(UINT64 currentFileTime, UINT64 folderFileTime)
1848{
1849 return (currentFileTime - folderFileTime > kTimeLimit &&
1850 folderFileTime - currentFileTime > kTimeLimit);
1851}
1852
1853void DeleteOldTempFiles()
1854{
1855 UString tempPath;
1856 if (!MyGetTempPath(tempPath))
1857 throw 1;
1858
1859 UINT64 currentFileTime;
1860 NTime::GetCurUtcFileTime(currentFileTime);
1861 UString searchWildCard = tempPath + kTempDirPrefix + L"*.tmp";
1862 searchWildCard += WCHAR(NName::kAnyStringWildcard);
1863 NFind::CEnumeratorW enumerator(searchWildCard);
1864 NFind::CFileInfo fileInfo;
1865 while (enumerator.Next(fileInfo))
1866 {
1867 if (!fileInfo.IsDir())
1868 continue;
1869 const UINT64 &cTime = *(const UINT64 *)(&fileInfo.CTime);
1870 if (CheckDeleteItem(cTime, currentFileTime))
1871 RemoveDirectoryWithSubItems(tempPath + fileInfo.Name);
1872 }
1873}
1874*/
diff --git a/CPP/7zip/UI/FileManager/PanelItems.cpp b/CPP/7zip/UI/FileManager/PanelItems.cpp
new file mode 100644
index 0000000..33e4458
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelItems.cpp
@@ -0,0 +1,1306 @@
1// PanelItems.cpp
2
3#include "StdAfx.h"
4
5#include "../../../../C/Sort.h"
6
7#include "../../../Windows/FileName.h"
8#include "../../../Windows/Menu.h"
9#include "../../../Windows/PropVariant.h"
10#include "../../../Windows/PropVariantConv.h"
11
12#include "../../PropID.h"
13
14#include "../Common/ExtractingFilePath.h"
15
16#include "resource.h"
17
18#include "LangUtils.h"
19#include "Panel.h"
20#include "PropertyName.h"
21#include "RootFolder.h"
22
23using namespace NWindows;
24
25static bool GetColumnVisible(PROPID propID, bool isFsFolder)
26{
27 if (isFsFolder)
28 {
29 switch (propID)
30 {
31 case kpidATime:
32 case kpidAttrib:
33 case kpidPackSize:
34 case kpidINode:
35 case kpidLinks:
36 case kpidNtReparse:
37 return false;
38 }
39 }
40 return true;
41}
42
43static int GetColumnWidth(PROPID propID, VARTYPE /* varType */)
44{
45 switch (propID)
46 {
47 case kpidName: return 160;
48 }
49 return 100;
50}
51
52static int GetColumnAlign(PROPID propID, VARTYPE varType)
53{
54 switch (propID)
55 {
56 case kpidCTime:
57 case kpidATime:
58 case kpidMTime:
59 return LVCFMT_LEFT;
60 }
61
62 switch (varType)
63 {
64 case VT_UI1:
65 case VT_I2:
66 case VT_UI2:
67 case VT_I4:
68 case VT_INT:
69 case VT_UI4:
70 case VT_UINT:
71 case VT_I8:
72 case VT_UI8:
73 case VT_BOOL:
74 return LVCFMT_RIGHT;
75
76 case VT_EMPTY:
77 case VT_I1:
78 case VT_FILETIME:
79 case VT_BSTR:
80 return LVCFMT_LEFT;
81
82 default:
83 return LVCFMT_CENTER;
84 }
85}
86
87
88static int ItemProperty_Compare_NameFirst(void *const *a1, void *const *a2, void * /* param */)
89{
90 return (*(*((const CPropColumn *const *)a1))).Compare_NameFirst(*(*((const CPropColumn *const *)a2)));
91}
92
93HRESULT CPanel::InitColumns()
94{
95 SaveListViewInfo();
96
97 // DeleteListItems();
98 _selectedStatusVector.Clear();
99
100 {
101 // ReadListViewInfo();
102 const UString oldType = _typeIDString;
103 _typeIDString = GetFolderTypeID();
104 // an empty _typeIDString is allowed.
105
106 // we read registry only for new FolderTypeID
107 if (!_needSaveInfo || _typeIDString != oldType)
108 _listViewInfo.Read(_typeIDString);
109
110 // folders with same FolderTypeID can have different columns
111 // so we still read columns for that case.
112 // if (_needSaveInfo && _typeIDString == oldType) return S_OK;
113 }
114
115 // PROPID sortID;
116 /*
117 if (_listViewInfo.SortIndex >= 0)
118 sortID = _listViewInfo.Columns[_listViewInfo.SortIndex].PropID;
119 */
120 // sortID = _listViewInfo.SortID;
121
122 _ascending = _listViewInfo.Ascending;
123
124 _columns.Clear();
125
126 bool isFsFolder = IsFSFolder() || IsAltStreamsFolder();
127
128 {
129 UInt32 numProps;
130 _folder->GetNumberOfProperties(&numProps);
131
132 for (UInt32 i = 0; i < numProps; i++)
133 {
134 CMyComBSTR name;
135 PROPID propID;
136 VARTYPE varType;
137 HRESULT res = _folder->GetPropertyInfo(i, &name, &propID, &varType);
138
139 if (res != S_OK)
140 {
141 /* We can return ERROR, but in that case, other code will not be called,
142 and user can see empty window without error message. So we just ignore that field */
143 continue;
144 }
145 if (propID == kpidIsDir)
146 continue;
147 CPropColumn prop;
148 prop.Type = varType;
149 prop.ID = propID;
150 prop.Name = GetNameOfProperty(propID, name);
151 prop.Order = -1;
152 prop.IsVisible = GetColumnVisible(propID, isFsFolder);
153 prop.Width = GetColumnWidth(propID, varType);
154 prop.IsRawProp = false;
155 _columns.Add(prop);
156 }
157
158 /*
159 {
160 // debug column
161 CPropColumn prop;
162 prop.Type = VT_BSTR;
163 prop.ID = 2000;
164 prop.Name = "Debug";
165 prop.Order = -1;
166 prop.IsVisible = true;
167 prop.Width = 300;
168 prop.IsRawProp = false;
169 _columns.Add(prop);
170 }
171 */
172 }
173
174 if (_folderRawProps)
175 {
176 UInt32 numProps;
177 _folderRawProps->GetNumRawProps(&numProps);
178
179 for (UInt32 i = 0; i < numProps; i++)
180 {
181 CMyComBSTR name;
182 PROPID propID;
183 HRESULT res = _folderRawProps->GetRawPropInfo(i, &name, &propID);
184 if (res != S_OK)
185 continue;
186 CPropColumn prop;
187 prop.Type = VT_EMPTY;
188 prop.ID = propID;
189 prop.Name = GetNameOfProperty(propID, name);
190 prop.Order = -1;
191 prop.IsVisible = GetColumnVisible(propID, isFsFolder);
192 prop.Width = GetColumnWidth(propID, VT_BSTR);
193 prop.IsRawProp = true;
194 _columns.Add(prop);
195 }
196 }
197
198 unsigned order = 0;
199 unsigned i;
200
201 for (i = 0; i < _listViewInfo.Columns.Size(); i++)
202 {
203 const CColumnInfo &columnInfo = _listViewInfo.Columns[i];
204 int index = _columns.FindItem_for_PropID(columnInfo.PropID);
205 if (index >= 0)
206 {
207 CPropColumn &item = _columns[index];
208 if (item.Order >= 0)
209 continue; // we ignore duplicated items
210 bool isVisible = columnInfo.IsVisible;
211 // we enable kpidName, if it was disabled by some incorrect code
212 if (columnInfo.PropID == kpidName)
213 isVisible = true;
214 item.IsVisible = isVisible;
215 item.Width = columnInfo.Width;
216 if (isVisible)
217 item.Order = order++;
218 continue;
219 }
220 }
221
222 for (i = 0; i < _columns.Size(); i++)
223 {
224 CPropColumn &item = _columns[i];
225 if (item.IsVisible && item.Order < 0)
226 item.Order = order++;
227 }
228
229 for (i = 0; i < _columns.Size(); i++)
230 {
231 CPropColumn &item = _columns[i];
232 if (item.Order < 0)
233 item.Order = order++;
234 }
235
236 CPropColumns newColumns;
237
238 for (i = 0; i < _columns.Size(); i++)
239 {
240 const CPropColumn &prop = _columns[i];
241 if (prop.IsVisible)
242 newColumns.Add(prop);
243 }
244
245
246 /*
247 _sortIndex = 0;
248 if (_listViewInfo.SortIndex >= 0)
249 {
250 int sortIndex = _columns.FindItem_for_PropID(sortID);
251 if (sortIndex >= 0)
252 _sortIndex = sortIndex;
253 }
254 */
255
256 if (_listViewInfo.IsLoaded)
257 _sortID = _listViewInfo.SortID;
258 else
259 {
260 _sortID = 0;
261 if (IsFSFolder() || IsAltStreamsFolder() || IsArcFolder())
262 _sortID = kpidName;
263 }
264
265 /* There are restrictions in ListView control:
266 1) main column (kpidName) must have (LV_COLUMNW::iSubItem = 0)
267 So we need special sorting for columns.
268 2) when we add new column, LV_COLUMNW::iOrder cannot be larger than already inserted columns)
269 So we set column order after all columns are added.
270 */
271 newColumns.Sort(ItemProperty_Compare_NameFirst, NULL);
272
273 if (newColumns.IsEqualTo(_visibleColumns))
274 return S_OK;
275
276 CIntArr columns(newColumns.Size());
277 for (i = 0; i < newColumns.Size(); i++)
278 columns[i] = -1;
279
280 bool orderError = false;
281
282 for (i = 0; i < newColumns.Size(); i++)
283 {
284 const CPropColumn &prop = newColumns[i];
285 if (prop.Order < (int)newColumns.Size() && columns[prop.Order] == -1)
286 columns[prop.Order] = i;
287 else
288 orderError = true;
289 }
290
291 for (;;)
292 {
293 unsigned numColumns = _visibleColumns.Size();
294 if (numColumns == 0)
295 break;
296 DeleteColumn(numColumns - 1);
297 }
298
299 for (i = 0; i < newColumns.Size(); i++)
300 AddColumn(newColumns[i]);
301
302 // columns[0], columns[1], .... should be displayed from left to right:
303 if (!orderError)
304 _listView.SetColumnOrderArray(_visibleColumns.Size(), columns);
305
306 _needSaveInfo = true;
307
308 return S_OK;
309}
310
311
312void CPanel::DeleteColumn(unsigned index)
313{
314 _visibleColumns.Delete(index);
315 _listView.DeleteColumn(index);
316}
317
318void CPanel::AddColumn(const CPropColumn &prop)
319{
320 const int index = _visibleColumns.Size();
321
322 LV_COLUMNW column;
323 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_ORDER;
324 column.cx = prop.Width;
325 column.fmt = GetColumnAlign(prop.ID, prop.Type);
326 column.iOrder = index; // must be <= _listView.ItemCount
327 column.iSubItem = index; // must be <= _listView.ItemCount
328 column.pszText = const_cast<wchar_t *>((const wchar_t *)prop.Name);
329
330 _visibleColumns.Add(prop);
331 _listView.InsertColumn(index, &column);
332}
333
334
335HRESULT CPanel::RefreshListCtrl()
336{
337 CSelectedState state;
338 return RefreshListCtrl(state);
339}
340
341int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
342
343
344void CPanel::GetSelectedNames(UStringVector &selectedNames)
345{
346 CRecordVector<UInt32> indices;
347 GetSelectedItemsIndices(indices);
348 selectedNames.ClearAndReserve(indices.Size());
349 FOR_VECTOR (i, indices)
350 selectedNames.AddInReserved(GetItemRelPath(indices[i]));
351
352 /*
353 for (int i = 0; i < _listView.GetItemCount(); i++)
354 {
355 const int kSize = 1024;
356 WCHAR name[kSize + 1];
357 LVITEMW item;
358 item.iItem = i;
359 item.pszText = name;
360 item.cchTextMax = kSize;
361 item.iSubItem = 0;
362 item.mask = LVIF_TEXT | LVIF_PARAM;
363 if (!_listView.GetItem(&item))
364 continue;
365 int realIndex = GetRealIndex(item);
366 if (realIndex == kParentIndex)
367 continue;
368 if (_selectedStatusVector[realIndex])
369 selectedNames.Add(item.pszText);
370 }
371 */
372 selectedNames.Sort();
373}
374
375void CPanel::SaveSelectedState(CSelectedState &s)
376{
377 s.FocusedName_Defined = false;
378 s.FocusedName.Empty();
379 s.SelectFocused = true; // false;
380 s.SelectedNames.Clear();
381 s.FocusedItem = _listView.GetFocusedItem();
382 {
383 if (s.FocusedItem >= 0)
384 {
385 int realIndex = GetRealItemIndex(s.FocusedItem);
386 if (realIndex != kParentIndex)
387 {
388 s.FocusedName = GetItemRelPath(realIndex);
389 s.FocusedName_Defined = true;
390
391 s.SelectFocused = _listView.IsItemSelected(s.FocusedItem);
392
393 /*
394 const int kSize = 1024;
395 WCHAR name[kSize + 1];
396 LVITEMW item;
397 item.iItem = focusedItem;
398 item.pszText = name;
399 item.cchTextMax = kSize;
400 item.iSubItem = 0;
401 item.mask = LVIF_TEXT;
402 if (_listView.GetItem(&item))
403 focusedName = item.pszText;
404 */
405 }
406 }
407 }
408 GetSelectedNames(s.SelectedNames);
409}
410
411/*
412HRESULT CPanel::RefreshListCtrl(const CSelectedState &s)
413{
414 bool selectFocused = s.SelectFocused;
415 if (_mySelectMode)
416 selectFocused = true;
417 return RefreshListCtrl2(
418 s.FocusedItem >= 0, // allowEmptyFocusedName
419 s.FocusedName, s.FocusedItem, selectFocused, s.SelectedNames);
420}
421*/
422
423HRESULT CPanel::RefreshListCtrl_SaveFocused()
424{
425 CSelectedState state;
426 SaveSelectedState(state);
427 return RefreshListCtrl(state);
428}
429
430void CPanel::SetFocusedSelectedItem(int index, bool select)
431{
432 UINT state = LVIS_FOCUSED;
433 if (select)
434 state |= LVIS_SELECTED;
435 _listView.SetItemState(index, state, state);
436 if (!_mySelectMode && select)
437 {
438 int realIndex = GetRealItemIndex(index);
439 if (realIndex != kParentIndex)
440 _selectedStatusVector[realIndex] = true;
441 }
442}
443
444// #define PRINT_STAT
445
446#ifdef PRINT_STAT
447 void Print_OnNotify(const char *name);
448#else
449 #define Print_OnNotify(x)
450#endif
451
452
453
454/*
455
456extern UInt32 g_NumGroups;
457extern DWORD g_start_tick;
458extern DWORD g_prev_tick;
459extern DWORD g_Num_SetItemText;
460extern UInt32 g_NumMessages;
461*/
462
463HRESULT CPanel::RefreshListCtrl(const CSelectedState &state)
464{
465 if (!_folder)
466 return S_OK;
467
468 /*
469 g_start_tick = GetTickCount();
470 g_Num_SetItemText = 0;
471 g_NumMessages = 0;
472 */
473
474 _dontShowMode = false;
475 LoadFullPathAndShow();
476 // OutputDebugStringA("=======\n");
477 // OutputDebugStringA("s1 \n");
478 CDisableTimerProcessing timerProcessing(*this);
479 CDisableNotify disableNotify(*this);
480
481 int focusedPos = state.FocusedItem;
482 if (focusedPos < 0)
483 focusedPos = 0;
484
485 _listView.SetRedraw(false);
486 // m_RedrawEnabled = false;
487
488 LVITEMW item;
489 ZeroMemory(&item, sizeof(item));
490
491 // DWORD tickCount0 = GetTickCount();
492
493 // _enableItemChangeNotify = false;
494 DeleteListItems();
495 _enableItemChangeNotify = true;
496
497 int listViewItemCount = 0;
498
499 _selectedStatusVector.Clear();
500 // _realIndices.Clear();
501 _startGroupSelect = 0;
502
503 _selectionIsDefined = false;
504
505 // m_Files.Clear();
506
507 if (!_folder)
508 {
509 // throw 1;
510 SetToRootFolder();
511 }
512
513 _headerToolBar.EnableButton(kParentFolderID, !IsRootFolder());
514
515 {
516 CMyComPtr<IFolderSetFlatMode> folderSetFlatMode;
517 _folder.QueryInterface(IID_IFolderSetFlatMode, &folderSetFlatMode);
518 if (folderSetFlatMode)
519 folderSetFlatMode->SetFlatMode(BoolToInt(_flatMode));
520 }
521
522 /*
523 {
524 CMyComPtr<IFolderSetShowNtfsStreamsMode> setShow;
525 _folder.QueryInterface(IID_IFolderSetShowNtfsStreamsMode, &setShow);
526 if (setShow)
527 setShow->SetShowNtfsStreamsMode(BoolToInt(_showNtfsStrems_Mode));
528 }
529 */
530
531 // DWORD tickCount1 = GetTickCount();
532 RINOK(_folder->LoadItems());
533 // DWORD tickCount2 = GetTickCount();
534 RINOK(InitColumns());
535
536 // OutputDebugString(TEXT("Start Dir\n"));
537 UInt32 numItems;
538 _folder->GetNumberOfItems(&numItems);
539
540 bool showDots = _showDots && !IsRootFolder();
541
542 _listView.SetItemCount(numItems + (showDots ? 1 : 0));
543
544 _selectedStatusVector.ClearAndReserve(numItems);
545 int cursorIndex = -1;
546
547 CMyComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
548 if (!Is_Slow_Icon_Folder() || _showRealFileIcons)
549 _folder.QueryInterface(IID_IFolderGetSystemIconIndex, &folderGetSystemIconIndex);
550
551 if (!IsFSFolder())
552 {
553 CMyComPtr<IGetFolderArcProps> getFolderArcProps;
554 _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
555 _thereAreDeletedItems = false;
556 if (getFolderArcProps)
557 {
558 CMyComPtr<IFolderArcProps> arcProps;
559 getFolderArcProps->GetFolderArcProps(&arcProps);
560 if (arcProps)
561 {
562 UInt32 numLevels;
563 if (arcProps->GetArcNumLevels(&numLevels) != S_OK)
564 numLevels = 0;
565 NCOM::CPropVariant prop;
566 if (arcProps->GetArcProp(numLevels - 1, kpidIsDeleted, &prop) == S_OK)
567 if (prop.vt == VT_BOOL && VARIANT_BOOLToBool(prop.boolVal))
568 _thereAreDeletedItems = true;
569 }
570 }
571 }
572
573 _thereAre_ListView_Items = true;
574
575 // OutputDebugStringA("\n\n");
576
577 Print_OnNotify("===== Before Load");
578
579 // #define USE_EMBED_ITEM
580
581 if (showDots)
582 {
583 UString itemName ("..");
584 item.iItem = listViewItemCount;
585 if (itemName == state.FocusedName)
586 cursorIndex = listViewItemCount;
587 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
588 int subItem = 0;
589 item.iSubItem = subItem++;
590 item.lParam = kParentIndex;
591 #ifdef USE_EMBED_ITEM
592 item.pszText = const_cast<wchar_t *>((const wchar_t *)itemName);
593 #else
594 item.pszText = LPSTR_TEXTCALLBACKW;
595 #endif
596 UInt32 attrib = FILE_ATTRIBUTE_DIRECTORY;
597 item.iImage = _extToIconMap.GetIconIndex(attrib, itemName);
598 if (item.iImage < 0)
599 item.iImage = 0;
600 if (_listView.InsertItem(&item) == -1)
601 return E_FAIL;
602 listViewItemCount++;
603 }
604
605 // OutputDebugStringA("S1\n");
606
607 UString correctedName;
608 UString itemName;
609 UString relPath;
610
611 for (UInt32 i = 0; i < numItems; i++)
612 {
613 const wchar_t *name = NULL;
614 unsigned nameLen = 0;
615
616 if (_folderGetItemName)
617 _folderGetItemName->GetItemName(i, &name, &nameLen);
618 if (!name)
619 {
620 GetItemName(i, itemName);
621 name = itemName;
622 nameLen = itemName.Len();
623 }
624
625 bool selected = false;
626
627 if (state.FocusedName_Defined || !state.SelectedNames.IsEmpty())
628 {
629 relPath.Empty();
630 // relPath += GetItemPrefix(i);
631 if (_flatMode)
632 {
633 const wchar_t *prefix = NULL;
634 if (_folderGetItemName)
635 {
636 unsigned prefixLen = 0;
637 _folderGetItemName->GetItemPrefix(i, &prefix, &prefixLen);
638 if (prefix)
639 relPath = prefix;
640 }
641 if (!prefix)
642 {
643 NCOM::CPropVariant prop;
644 if (_folder->GetProperty(i, kpidPrefix, &prop) != S_OK)
645 throw 2723400;
646 if (prop.vt == VT_BSTR)
647 relPath.SetFromBstr(prop.bstrVal);
648 }
649 }
650 relPath += name;
651 if (relPath == state.FocusedName)
652 cursorIndex = listViewItemCount;
653 if (state.SelectedNames.FindInSorted(relPath) >= 0)
654 selected = true;
655 }
656
657 _selectedStatusVector.AddInReserved(selected);
658
659 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
660
661 if (!_mySelectMode)
662 if (selected)
663 {
664 item.mask |= LVIF_STATE;
665 item.state = LVIS_SELECTED;
666 }
667
668 int subItem = 0;
669 item.iItem = listViewItemCount;
670
671 item.iSubItem = subItem++;
672 item.lParam = i;
673
674 /*
675 int finish = nameLen - 4;
676 int j;
677 for (j = 0; j < finish; j++)
678 {
679 if (name[j ] == ' ' &&
680 name[j + 1] == ' ' &&
681 name[j + 2] == ' ' &&
682 name[j + 3] == ' ' &&
683 name[j + 4] == ' ')
684 break;
685 }
686 if (j < finish)
687 {
688 correctedName.Empty();
689 correctedName = "virus";
690 int pos = 0;
691 for (;;)
692 {
693 int posNew = itemName.Find(L" ", pos);
694 if (posNew < 0)
695 {
696 correctedName += itemName.Ptr(pos);
697 break;
698 }
699 correctedName += itemName.Mid(pos, posNew - pos);
700 correctedName += " ... ";
701 pos = posNew;
702 while (itemName[++pos] == ' ');
703 }
704 item.pszText = const_cast<wchar_t *>((const wchar_t *)correctedName);
705 }
706 else
707 */
708 {
709 #ifdef USE_EMBED_ITEM
710 item.pszText = const_cast<wchar_t *>((const wchar_t *)name);
711 #else
712 item.pszText = LPSTR_TEXTCALLBACKW;
713 #endif
714 /* LPSTR_TEXTCALLBACKW works, but in some cases there are problems,
715 since we block notify handler.
716 LPSTR_TEXTCALLBACKW can be 2-3 times faster for loading in this loop. */
717 }
718
719 bool defined = false;
720
721 if (folderGetSystemIconIndex)
722 {
723 folderGetSystemIconIndex->GetSystemIconIndex(i, &item.iImage);
724 defined = (item.iImage > 0);
725 }
726
727 if (!defined)
728 {
729 UInt32 attrib = 0;
730 {
731 NCOM::CPropVariant prop;
732 RINOK(_folder->GetProperty(i, kpidAttrib, &prop));
733 if (prop.vt == VT_UI4)
734 attrib = prop.ulVal;
735 }
736 if (IsItem_Folder(i))
737 attrib |= FILE_ATTRIBUTE_DIRECTORY;
738
739 if (_currentFolderPrefix.IsEmpty())
740 {
741 int iconIndexTemp;
742 GetRealIconIndex(us2fs((UString)name) + FCHAR_PATH_SEPARATOR, attrib, iconIndexTemp);
743 item.iImage = iconIndexTemp;
744 }
745 else
746 {
747 item.iImage = _extToIconMap.GetIconIndex(attrib, name);
748 }
749 }
750
751 if (item.iImage < 0)
752 item.iImage = 0;
753
754 if (_listView.InsertItem(&item) == -1)
755 return E_FAIL;
756 listViewItemCount++;
757 }
758
759 /*
760 xp-64: there is different order when Windows calls CPanel::OnNotify for _listView modes:
761 Details : after whole code
762 List : 2 times:
763 1) - ListView.SotRedraw()
764 2) - after whole code
765 Small Icons :
766 Large icons : 2 times:
767 1) - ListView.Sort()
768 2) - after whole code (calls with reverse order of items)
769
770 So we need to allow Notify(), when windows requests names during the following code.
771 */
772
773 Print_OnNotify("after Load");
774
775 disableNotify.SetMemMode_Enable();
776 disableNotify.Restore();
777
778 if (_listView.GetItemCount() > 0 && cursorIndex >= 0)
779 SetFocusedSelectedItem(cursorIndex, state.SelectFocused);
780
781 Print_OnNotify("after SetFocusedSelectedItem");
782
783 SetSortRawStatus();
784 _listView.SortItems(CompareItems, (LPARAM)this);
785
786 Print_OnNotify("after Sort");
787
788 if (cursorIndex < 0 && _listView.GetItemCount() > 0)
789 {
790 if (focusedPos >= _listView.GetItemCount())
791 focusedPos = _listView.GetItemCount() - 1;
792 // we select item only in showDots mode.
793 SetFocusedSelectedItem(focusedPos, showDots && (focusedPos == 0));
794 }
795
796 // m_RedrawEnabled = true;
797
798 Print_OnNotify("after SetFocusedSelectedItem2");
799
800 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
801
802 // disableNotify.SetMemMode_Enable();
803 // disableNotify.Restore();
804
805 Print_OnNotify("after EnsureVisible");
806
807 _listView.SetRedraw(true);
808
809 Print_OnNotify("after SetRedraw");
810
811 _listView.InvalidateRect(NULL, true);
812
813 Print_OnNotify("after InvalidateRect");
814 /*
815 _listView.UpdateWindow();
816 */
817 Refresh_StatusBar();
818 /*
819 char s[256];
820 sprintf(s,
821 // "attribMap = %5d, extMap = %5d, "
822 "delete = %5d, load = %5d, list = %5d, sort = %5d, end = %5d",
823 // _extToIconMap._attribMap.Size(),
824 // _extToIconMap._extMap.Size(),
825 tickCount1 - tickCount0,
826 tickCount2 - tickCount1,
827 tickCount3 - tickCount2,
828 tickCount4 - tickCount3,
829 tickCount5 - tickCount4
830 );
831 sprintf(s,
832 "5 = %5d, 6 = %5d, 7 = %5d, 8 = %5d, 9 = %5d",
833 tickCount5 - tickCount4,
834 tickCount6 - tickCount5,
835 tickCount7 - tickCount6,
836 tickCount8 - tickCount7,
837 tickCount9 - tickCount8
838 );
839 OutputDebugStringA(s);
840 */
841 return S_OK;
842}
843
844
845void CPanel::GetSelectedItemsIndices(CRecordVector<UInt32> &indices) const
846{
847 indices.Clear();
848 /*
849 int itemIndex = -1;
850 while ((itemIndex = _listView.GetNextSelectedItem(itemIndex)) != -1)
851 {
852 LPARAM param;
853 if (_listView.GetItemParam(itemIndex, param))
854 indices.Add(param);
855 }
856 HeapSort(&indices.Front(), indices.Size());
857 */
858 const bool *v = &_selectedStatusVector.Front();
859 unsigned size = _selectedStatusVector.Size();
860 for (unsigned i = 0; i < size; i++)
861 if (v[i])
862 indices.Add(i);
863}
864
865
866void CPanel::GetOperatedItemIndices(CRecordVector<UInt32> &indices) const
867{
868 GetSelectedItemsIndices(indices);
869 if (!indices.IsEmpty())
870 return;
871 if (_listView.GetSelectedCount() == 0)
872 return;
873 int focusedItem = _listView.GetFocusedItem();
874 if (focusedItem >= 0)
875 {
876 if (_listView.IsItemSelected(focusedItem))
877 {
878 int realIndex = GetRealItemIndex(focusedItem);
879 if (realIndex != kParentIndex)
880 indices.Add(realIndex);
881 }
882 }
883}
884
885void CPanel::GetAllItemIndices(CRecordVector<UInt32> &indices) const
886{
887 indices.Clear();
888 UInt32 numItems;
889 if (_folder->GetNumberOfItems(&numItems) == S_OK)
890 for (UInt32 i = 0; i < numItems; i++)
891 indices.Add(i);
892}
893
894void CPanel::GetOperatedIndicesSmart(CRecordVector<UInt32> &indices) const
895{
896 GetOperatedItemIndices(indices);
897 if (indices.IsEmpty() || (indices.Size() == 1 && indices[0] == (UInt32)(Int32)-1))
898 GetAllItemIndices(indices);
899}
900
901/*
902void CPanel::GetOperatedListViewIndices(CRecordVector<UInt32> &indices) const
903{
904 indices.Clear();
905 int numItems = _listView.GetItemCount();
906 for (int i = 0; i < numItems; i++)
907 {
908 int realIndex = GetRealItemIndex(i);
909 if (realIndex >= 0)
910 if (_selectedStatusVector[realIndex])
911 indices.Add(i);
912 }
913 if (indices.IsEmpty())
914 {
915 int focusedItem = _listView.GetFocusedItem();
916 if (focusedItem >= 0)
917 indices.Add(focusedItem);
918 }
919}
920*/
921
922void CPanel::EditItem(bool useEditor)
923{
924 if (!useEditor)
925 {
926 CMyComPtr<IFolderCalcItemFullSize> calcItemFullSize;
927 _folder.QueryInterface(IID_IFolderCalcItemFullSize, &calcItemFullSize);
928 if (calcItemFullSize)
929 {
930 bool needRefresh = false;
931 CRecordVector<UInt32> indices;
932 GetOperatedItemIndices(indices);
933 FOR_VECTOR (i, indices)
934 {
935 UInt32 index = indices[i];
936 if (IsItem_Folder(index))
937 {
938 calcItemFullSize->CalcItemFullSize(index, NULL);
939 needRefresh = true;
940 }
941 }
942 if (needRefresh)
943 {
944 // _listView.RedrawItem(0);
945 // _listView.RedrawAllItems();
946 InvalidateList();
947 return;
948 }
949 }
950 }
951
952
953 int focusedItem = _listView.GetFocusedItem();
954 if (focusedItem < 0)
955 return;
956 int realIndex = GetRealItemIndex(focusedItem);
957 if (realIndex == kParentIndex)
958 return;
959 if (!IsItem_Folder(realIndex))
960 EditItem(realIndex, useEditor);
961}
962
963void CPanel::OpenFocusedItemAsInternal(const wchar_t *type)
964{
965 int focusedItem = _listView.GetFocusedItem();
966 if (focusedItem < 0)
967 return;
968 int realIndex = GetRealItemIndex(focusedItem);
969 if (IsItem_Folder(realIndex))
970 OpenFolder(realIndex);
971 else
972 OpenItem(realIndex, true, false, type);
973}
974
975void CPanel::OpenSelectedItems(bool tryInternal)
976{
977 CRecordVector<UInt32> indices;
978 GetOperatedItemIndices(indices);
979 if (indices.Size() > 20)
980 {
981 MessageBox_Error_LangID(IDS_TOO_MANY_ITEMS);
982 return;
983 }
984
985 int focusedItem = _listView.GetFocusedItem();
986 if (focusedItem >= 0)
987 {
988 int realIndex = GetRealItemIndex(focusedItem);
989 if (realIndex == kParentIndex && (tryInternal || indices.Size() == 0) && _listView.IsItemSelected(focusedItem))
990 indices.Insert(0, realIndex);
991 }
992
993 bool dirIsStarted = false;
994 FOR_VECTOR (i, indices)
995 {
996 UInt32 index = indices[i];
997 // CFileInfo &aFile = m_Files[index];
998 if (IsItem_Folder(index))
999 {
1000 if (!dirIsStarted)
1001 {
1002 if (tryInternal)
1003 {
1004 OpenFolder(index);
1005 dirIsStarted = true;
1006 break;
1007 }
1008 else
1009 OpenFolderExternal(index);
1010 }
1011 }
1012 else
1013 OpenItem(index, (tryInternal && indices.Size() == 1), true);
1014 }
1015}
1016
1017UString CPanel::GetItemName(int itemIndex) const
1018{
1019 if (itemIndex == kParentIndex)
1020 return L"..";
1021 NCOM::CPropVariant prop;
1022 if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK)
1023 throw 2723400;
1024 if (prop.vt != VT_BSTR)
1025 throw 2723401;
1026 return prop.bstrVal;
1027}
1028
1029UString CPanel::GetItemName_for_Copy(int itemIndex) const
1030{
1031 if (itemIndex == kParentIndex)
1032 return L"..";
1033 UString s;
1034 {
1035 NCOM::CPropVariant prop;
1036 if (_folder->GetProperty(itemIndex, kpidOutName, &prop) == S_OK)
1037 {
1038 if (prop.vt == VT_BSTR)
1039 s = prop.bstrVal;
1040 else if (prop.vt != VT_EMPTY)
1041 throw 2723401;
1042 }
1043 if (s.IsEmpty())
1044 s = GetItemName(itemIndex);
1045 }
1046 return Get_Correct_FsFile_Name(s);
1047}
1048
1049void CPanel::GetItemName(int itemIndex, UString &s) const
1050{
1051 if (itemIndex == kParentIndex)
1052 {
1053 s = "..";
1054 return;
1055 }
1056 NCOM::CPropVariant prop;
1057 if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK)
1058 throw 2723400;
1059 if (prop.vt != VT_BSTR)
1060 throw 2723401;
1061 s.SetFromBstr(prop.bstrVal);
1062}
1063
1064UString CPanel::GetItemPrefix(int itemIndex) const
1065{
1066 if (itemIndex == kParentIndex)
1067 return UString();
1068 NCOM::CPropVariant prop;
1069 if (_folder->GetProperty(itemIndex, kpidPrefix, &prop) != S_OK)
1070 throw 2723400;
1071 UString prefix;
1072 if (prop.vt == VT_BSTR)
1073 prefix.SetFromBstr(prop.bstrVal);
1074 return prefix;
1075}
1076
1077UString CPanel::GetItemRelPath(int itemIndex) const
1078{
1079 return GetItemPrefix(itemIndex) + GetItemName(itemIndex);
1080}
1081
1082UString CPanel::GetItemRelPath2(int itemIndex) const
1083{
1084 UString s = GetItemRelPath(itemIndex);
1085 #if defined(_WIN32) && !defined(UNDER_CE)
1086 if (s.Len() == 2 && NFile::NName::IsDrivePath2(s))
1087 {
1088 if (IsFSDrivesFolder() && !IsDeviceDrivesPrefix())
1089 s.Add_PathSepar();
1090 }
1091 #endif
1092 return s;
1093}
1094
1095UString CPanel::GetItemFullPath(int itemIndex) const
1096{
1097 return GetFsPath() + GetItemRelPath2(itemIndex);
1098}
1099
1100bool CPanel::GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const
1101{
1102 NCOM::CPropVariant prop;
1103 if (_folder->GetProperty(itemIndex, propID, &prop) != S_OK)
1104 throw 2723400;
1105 if (prop.vt == VT_BOOL)
1106 return VARIANT_BOOLToBool(prop.boolVal);
1107 if (prop.vt == VT_EMPTY)
1108 return false;
1109 throw 2723401;
1110}
1111
1112bool CPanel::IsItem_Deleted(int itemIndex) const
1113{
1114 if (itemIndex == kParentIndex)
1115 return false;
1116 return GetItem_BoolProp(itemIndex, kpidIsDeleted);
1117}
1118
1119bool CPanel::IsItem_Folder(int itemIndex) const
1120{
1121 if (itemIndex == kParentIndex)
1122 return true;
1123 return GetItem_BoolProp(itemIndex, kpidIsDir);
1124}
1125
1126bool CPanel::IsItem_AltStream(int itemIndex) const
1127{
1128 if (itemIndex == kParentIndex)
1129 return false;
1130 return GetItem_BoolProp(itemIndex, kpidIsAltStream);
1131}
1132
1133UInt64 CPanel::GetItem_UInt64Prop(int itemIndex, PROPID propID) const
1134{
1135 if (itemIndex == kParentIndex)
1136 return 0;
1137 NCOM::CPropVariant prop;
1138 if (_folder->GetProperty(itemIndex, propID, &prop) != S_OK)
1139 throw 2723400;
1140 UInt64 val = 0;
1141 if (ConvertPropVariantToUInt64(prop, val))
1142 return val;
1143 return 0;
1144}
1145
1146UInt64 CPanel::GetItemSize(int itemIndex) const
1147{
1148 if (itemIndex == kParentIndex)
1149 return 0;
1150 if (_folderGetItemName)
1151 return _folderGetItemName->GetItemSize(itemIndex);
1152 return GetItem_UInt64Prop(itemIndex, kpidSize);
1153}
1154
1155void CPanel::SaveListViewInfo()
1156{
1157 if (!_needSaveInfo)
1158 return;
1159
1160 unsigned i;
1161
1162 for (i = 0; i < _visibleColumns.Size(); i++)
1163 {
1164 CPropColumn &prop = _visibleColumns[i];
1165 LVCOLUMN winColumnInfo;
1166 winColumnInfo.mask = LVCF_ORDER | LVCF_WIDTH;
1167 if (!_listView.GetColumn(i, &winColumnInfo))
1168 throw 1;
1169 prop.Order = winColumnInfo.iOrder;
1170 prop.Width = winColumnInfo.cx;
1171 }
1172
1173 CListViewInfo viewInfo;
1174
1175 // PROPID sortPropID = _columns[_sortIndex].ID;
1176 PROPID sortPropID = _sortID;
1177
1178 // we save columns as "sorted by order" to registry
1179
1180 CPropColumns sortedProperties = _visibleColumns;
1181
1182 sortedProperties.Sort();
1183
1184 for (i = 0; i < sortedProperties.Size(); i++)
1185 {
1186 const CPropColumn &prop = sortedProperties[i];
1187 CColumnInfo columnInfo;
1188 columnInfo.IsVisible = prop.IsVisible;
1189 columnInfo.PropID = prop.ID;
1190 columnInfo.Width = prop.Width;
1191 viewInfo.Columns.Add(columnInfo);
1192 }
1193
1194 for (i = 0; i < _columns.Size(); i++)
1195 {
1196 const CPropColumn &prop = _columns[i];
1197 if (sortedProperties.FindItem_for_PropID(prop.ID) < 0)
1198 {
1199 CColumnInfo columnInfo;
1200 columnInfo.IsVisible = false;
1201 columnInfo.PropID = prop.ID;
1202 columnInfo.Width = prop.Width;
1203 viewInfo.Columns.Add(columnInfo);
1204 }
1205 }
1206
1207 viewInfo.SortID = sortPropID;
1208 viewInfo.Ascending = _ascending;
1209 viewInfo.IsLoaded = true;
1210 if (!_listViewInfo.IsEqual(viewInfo))
1211 {
1212 viewInfo.Save(_typeIDString);
1213 _listViewInfo = viewInfo;
1214 }
1215}
1216
1217
1218bool CPanel::OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActiveate, LRESULT &result)
1219{
1220 if (itemActiveate->hdr.hwndFrom == HWND(_listView))
1221 return false;
1222 POINT point;
1223 ::GetCursorPos(&point);
1224 ShowColumnsContextMenu(point.x, point.y);
1225 result = TRUE;
1226 return true;
1227}
1228
1229void CPanel::ShowColumnsContextMenu(int x, int y)
1230{
1231 CMenu menu;
1232 CMenuDestroyer menuDestroyer(menu);
1233
1234 menu.CreatePopup();
1235
1236 const int kCommandStart = 100;
1237 FOR_VECTOR (i, _columns)
1238 {
1239 const CPropColumn &prop = _columns[i];
1240 UINT flags = MF_STRING;
1241 if (prop.IsVisible)
1242 flags |= MF_CHECKED;
1243 if (i == 0)
1244 flags |= MF_GRAYED;
1245 menu.AppendItem(flags, kCommandStart + i, prop.Name);
1246 }
1247
1248 int menuResult = menu.Track(TPM_LEFTALIGN | TPM_RETURNCMD | TPM_NONOTIFY, x, y, _listView);
1249
1250 if (menuResult >= kCommandStart && menuResult <= kCommandStart + (int)_columns.Size())
1251 {
1252 int index = menuResult - kCommandStart;
1253 CPropColumn &prop = _columns[index];
1254 prop.IsVisible = !prop.IsVisible;
1255
1256 if (prop.IsVisible)
1257 {
1258 prop.Order = _visibleColumns.Size();
1259 AddColumn(prop);
1260 }
1261 else
1262 {
1263 int visibleIndex = _visibleColumns.FindItem_for_PropID(prop.ID);
1264 if (visibleIndex >= 0)
1265 {
1266 /*
1267 if (_sortIndex == index)
1268 {
1269 _sortIndex = 0;
1270 _ascending = true;
1271 }
1272 */
1273 if (_sortID == prop.ID)
1274 {
1275 _sortID = kpidName;
1276 _ascending = true;
1277 }
1278 DeleteColumn(visibleIndex);
1279 }
1280 }
1281 }
1282}
1283
1284void CPanel::OnReload()
1285{
1286 HRESULT res = RefreshListCtrl_SaveFocused();
1287 if (res != S_OK)
1288 MessageBox_Error_HRESULT(res);
1289}
1290
1291void CPanel::OnTimer()
1292{
1293 if (!_processTimer)
1294 return;
1295 if (!AutoRefresh_Mode)
1296 return;
1297 CMyComPtr<IFolderWasChanged> folderWasChanged;
1298 if (_folder.QueryInterface(IID_IFolderWasChanged, &folderWasChanged) != S_OK)
1299 return;
1300 Int32 wasChanged;
1301 if (folderWasChanged->WasChanged(&wasChanged) != S_OK)
1302 return;
1303 if (wasChanged == 0)
1304 return;
1305 OnReload();
1306}
diff --git a/CPP/7zip/UI/FileManager/PanelKey.cpp b/CPP/7zip/UI/FileManager/PanelKey.cpp
new file mode 100644
index 0000000..3ab478e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelKey.cpp
@@ -0,0 +1,347 @@
1// PanelKey.cpp
2
3#include "StdAfx.h"
4
5#include "Panel.h"
6#include "HelpUtils.h"
7
8#include "../../PropID.h"
9#include "App.h"
10
11using namespace NWindows;
12
13// #define kHelpTopic "FM/index.htm"
14
15struct CVKeyPropIDPair
16{
17 WORD VKey;
18 PROPID PropID;
19};
20
21static const CVKeyPropIDPair g_VKeyPropIDPairs[] =
22{
23 { VK_F3, kpidName },
24 { VK_F4, kpidExtension },
25 { VK_F5, kpidMTime },
26 { VK_F6, kpidSize },
27 { VK_F7, kpidNoProperty }
28};
29
30static int FindVKeyPropIDPair(WORD vKey)
31{
32 for (unsigned i = 0; i < ARRAY_SIZE(g_VKeyPropIDPairs); i++)
33 if (g_VKeyPropIDPairs[i].VKey == vKey)
34 return i;
35 return -1;
36}
37
38
39bool CPanel::OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result)
40{
41 if (keyDownInfo->wVKey == VK_TAB && keyDownInfo->hdr.hwndFrom == _listView)
42 {
43 _panelCallback->OnTab();
44 return false;
45 }
46 bool alt = IsKeyDown(VK_MENU);
47 bool ctrl = IsKeyDown(VK_CONTROL);
48 // bool leftCtrl = IsKeyDown(VK_LCONTROL);
49 bool rightCtrl = IsKeyDown(VK_RCONTROL);
50 bool shift = IsKeyDown(VK_SHIFT);
51 result = 0;
52
53 if (keyDownInfo->wVKey >= '0' && keyDownInfo->wVKey <= '9' &&
54 (rightCtrl || alt))
55 {
56 int index = keyDownInfo->wVKey - '0';
57 if (shift)
58 {
59 SetBookmark(index);
60 return true;
61 }
62 else
63 {
64 OpenBookmark(index);
65 return true;
66 }
67 }
68
69 if ((keyDownInfo->wVKey == VK_F2 ||
70 keyDownInfo->wVKey == VK_F1) && alt && !ctrl && !shift)
71 {
72 _panelCallback->SetFocusToPath(keyDownInfo->wVKey == VK_F1 ? 0 : 1);
73 return true;
74 }
75
76 if ((keyDownInfo->wVKey == VK_F9) && !alt && !ctrl && !shift)
77 {
78 g_App.SwitchOnOffOnePanel();
79 }
80
81 if (keyDownInfo->wVKey >= VK_F3 && keyDownInfo->wVKey <= VK_F12 && ctrl)
82 {
83 int index = FindVKeyPropIDPair(keyDownInfo->wVKey);
84 if (index >= 0)
85 SortItemsWithPropID(g_VKeyPropIDPairs[index].PropID);
86 }
87
88 switch (keyDownInfo->wVKey)
89 {
90 case VK_SHIFT:
91 {
92 _selectionIsDefined = false;
93 _prevFocusedItem = _listView.GetFocusedItem();
94 break;
95 }
96 /*
97 case VK_F1:
98 {
99 // ShowHelpWindow(NULL, kHelpTopic);
100 break;
101 }
102 */
103 case VK_F2:
104 {
105 if (!alt && !ctrl &&!shift)
106 {
107 RenameFile();
108 return true;
109 }
110 break;
111 }
112 case VK_F3:
113 {
114 if (!alt && !ctrl && !shift)
115 {
116 EditItem(false);
117 return true;
118 }
119 break;
120 }
121 case VK_F4:
122 {
123 if (!alt && !ctrl && !shift)
124 {
125 EditItem(true);
126 return true;
127 }
128 if (!alt && !ctrl && shift)
129 {
130 CreateFile();
131 return true;
132 }
133 break;
134 }
135 case VK_F5:
136 {
137 if (!alt && !ctrl)
138 {
139 _panelCallback->OnCopy(false, shift);
140 return true;
141 }
142 break;
143 }
144 case VK_F6:
145 {
146 if (!alt && !ctrl)
147 {
148 _panelCallback->OnCopy(true, shift);
149 return true;
150 }
151 break;
152 }
153 case VK_F7:
154 {
155 if (!alt && !ctrl && !shift)
156 {
157 /* we can process F7 via menu ACCELERATOR.
158 But menu loading can be slow in case of UNC paths and system menu.
159 So we use don't use ACCELERATOR */
160 CreateFolder();
161 return true;
162 }
163 break;
164 }
165 case VK_DELETE:
166 {
167 DeleteItems(!shift);
168 return true;
169 }
170 case VK_INSERT:
171 {
172 if (!alt)
173 {
174 if (ctrl && !shift)
175 {
176 EditCopy();
177 return true;
178 }
179 if (shift && !ctrl)
180 {
181 EditPaste();
182 return true;
183 }
184 if (!shift && !ctrl && _mySelectMode)
185 {
186 OnInsert();
187 return true;
188 }
189 }
190 return false;
191 }
192 case VK_DOWN:
193 {
194 if (shift)
195 OnArrowWithShift();
196 return false;
197 }
198 case VK_UP:
199 {
200 if (alt)
201 _panelCallback->OnSetSameFolder();
202 else if (shift)
203 OnArrowWithShift();
204 return false;
205 }
206 case VK_RIGHT:
207 {
208 if (alt)
209 _panelCallback->OnSetSubFolder();
210 else if (shift)
211 OnArrowWithShift();
212 return false;
213 }
214 case VK_LEFT:
215 {
216 if (alt)
217 _panelCallback->OnSetSubFolder();
218 else if (shift)
219 OnArrowWithShift();
220 return false;
221 }
222 case VK_NEXT:
223 {
224 if (ctrl && !alt && !shift)
225 {
226 // EnterToFocused();
227 return true;
228 }
229 break;
230 }
231 case VK_ADD:
232 {
233 if (alt)
234 SelectByType(true);
235 else if (shift)
236 SelectAll(true);
237 else if (!ctrl)
238 SelectSpec(true);
239 return true;
240 }
241 case VK_SUBTRACT:
242 {
243 if (alt)
244 SelectByType(false);
245 else if (shift)
246 SelectAll(false);
247 else
248 SelectSpec(false);
249 return true;
250 }
251 /*
252 case VK_DELETE:
253 CommandDelete();
254 return 0;
255 case VK_F1:
256 CommandHelp();
257 return 0;
258 */
259 case VK_BACK:
260 OpenParentFolder();
261 return true;
262 /*
263 case VK_DIVIDE:
264 case '\\':
265 case '/':
266 case VK_OEM_5:
267 {
268 // OpenRootFolder();
269 OpenDrivesFolder();
270
271 return true;
272 }
273 */
274 case 'A':
275 if (ctrl)
276 {
277 SelectAll(true);
278 return true;
279 }
280 return false;
281 case 'X':
282 if (ctrl)
283 {
284 EditCut();
285 return true;
286 }
287 return false;
288 case 'C':
289 if (ctrl)
290 {
291 EditCopy();
292 return true;
293 }
294 return false;
295 case 'V':
296 if (ctrl)
297 {
298 EditPaste();
299 return true;
300 }
301 return false;
302 case 'N':
303 if (ctrl)
304 {
305 CreateFile();
306 return true;
307 }
308 return false;
309 case 'R':
310 if (ctrl)
311 {
312 OnReload();
313 return true;
314 }
315 return false;
316 case 'Z':
317 if (ctrl)
318 {
319 ChangeComment();
320 return true;
321 }
322 return false;
323 case '1':
324 case '2':
325 case '3':
326 case '4':
327 if (ctrl)
328 {
329 int styleIndex = keyDownInfo->wVKey - '1';
330 SetListViewMode(styleIndex);
331 return true;
332 }
333 return false;
334 case VK_MULTIPLY:
335 {
336 InvertSelection();
337 return true;
338 }
339 case VK_F12:
340 if (alt && !ctrl && !shift)
341 {
342 FoldersHistory();
343 return true;
344 }
345 }
346 return false;
347}
diff --git a/CPP/7zip/UI/FileManager/PanelListNotify.cpp b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
new file mode 100644
index 0000000..d2114f1
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelListNotify.cpp
@@ -0,0 +1,860 @@
1// PanelListNotify.cpp
2
3#include "StdAfx.h"
4
5#include "resource.h"
6
7#include "../../../Common/IntToString.h"
8#include "../../../Common/StringConvert.h"
9
10#include "../../../Windows/PropVariant.h"
11#include "../../../Windows/PropVariantConv.h"
12
13#include "../Common/PropIDUtils.h"
14#include "../../PropID.h"
15
16#include "App.h"
17#include "Panel.h"
18#include "FormatUtils.h"
19
20using namespace NWindows;
21
22/* Unicode characters for space:
230x009C STRING TERMINATOR
240x00B7 Middle dot
250x237D Shouldered open box
260x2420 Symbol for space
270x2422 Blank symbol
280x2423 Open box
29*/
30
31#define SPACE_REPLACE_CHAR (wchar_t)(0x2423)
32#define SPACE_TERMINATOR_CHAR (wchar_t)(0x9C)
33
34#define INT_TO_STR_SPEC(v) \
35 while (v >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(v % 10)); v /= 10; } \
36 *s++ = (unsigned char)('0' + (unsigned)v);
37
38static void ConvertSizeToString(UInt64 val, wchar_t *s) throw()
39{
40 unsigned char temp[32];
41 unsigned i = 0;
42
43 if (val <= (UInt32)0xFFFFFFFF)
44 {
45 UInt32 val32 = (UInt32)val;
46 INT_TO_STR_SPEC(val32)
47 }
48 else
49 {
50 INT_TO_STR_SPEC(val)
51 }
52
53 if (i < 3)
54 {
55 if (i != 0)
56 {
57 *s++ = temp[(size_t)i - 1];
58 if (i == 2)
59 *s++ = temp[0];
60 }
61 *s = 0;
62 return;
63 }
64
65 unsigned r = i % 3;
66 if (r != 0)
67 {
68 s[0] = temp[--i];
69 if (r == 2)
70 s[1] = temp[--i];
71 s += r;
72 }
73
74 do
75 {
76 s[0] = ' ';
77 s[1] = temp[(size_t)i - 1];
78 s[2] = temp[(size_t)i - 2];
79 s[3] = temp[(size_t)i - 3];
80 s += 4;
81 }
82 while (i -= 3);
83
84 *s = 0;
85}
86
87UString ConvertSizeToString(UInt64 value);
88UString ConvertSizeToString(UInt64 value)
89{
90 wchar_t s[32];
91 ConvertSizeToString(value, s);
92 return s;
93}
94
95static inline unsigned GetHex_Upper(unsigned v)
96{
97 return (v < 10) ? ('0' + v) : ('A' + (v - 10));
98}
99
100static inline unsigned GetHex_Lower(unsigned v)
101{
102 return (v < 10) ? ('0' + v) : ('a' + (v - 10));
103}
104
105/*
106static void HexToString(char *dest, const Byte *data, UInt32 size)
107{
108 for (UInt32 i = 0; i < size; i++)
109 {
110 unsigned b = data[i];
111 dest[0] = GetHex((b >> 4) & 0xF);
112 dest[1] = GetHex(b & 0xF);
113 dest += 2;
114 }
115 *dest = 0;
116}
117*/
118
119bool IsSizeProp(UINT propID) throw();
120bool IsSizeProp(UINT propID) throw()
121{
122 switch (propID)
123 {
124 case kpidSize:
125 case kpidPackSize:
126 case kpidNumSubDirs:
127 case kpidNumSubFiles:
128 case kpidOffset:
129 case kpidLinks:
130 case kpidNumBlocks:
131 case kpidNumVolumes:
132 case kpidPhySize:
133 case kpidHeadersSize:
134 case kpidTotalSize:
135 case kpidFreeSpace:
136 case kpidClusterSize:
137 case kpidNumErrors:
138 case kpidNumStreams:
139 case kpidNumAltStreams:
140 case kpidAltStreamsSize:
141 case kpidVirtualSize:
142 case kpidUnpackSize:
143 case kpidTotalPhySize:
144 case kpidTailSize:
145 case kpidEmbeddedStubSize:
146 return true;
147 }
148 return false;
149}
150
151
152
153/*
154#include <stdio.h>
155
156UInt64 GetCpuTicks()
157{
158 #ifdef _WIN64
159 return __rdtsc();
160 #else
161 UInt32 lowVal, highVal;
162 __asm RDTSC;
163 __asm mov lowVal, EAX;
164 __asm mov highVal, EDX;
165 return ((UInt64)highVal << 32) | lowVal;
166 #endif
167}
168
169UInt32 g_NumGroups;
170UInt64 g_start_tick;
171UInt64 g_prev_tick;
172DWORD g_Num_SetItemText;
173UInt32 g_NumMessages;
174*/
175
176LRESULT CPanel::SetItemText(LVITEMW &item)
177{
178 if (_dontShowMode)
179 return 0;
180 UInt32 realIndex = GetRealIndex(item);
181
182 // g_Num_SetItemText++;
183
184 /*
185 if ((item.mask & LVIF_IMAGE) != 0)
186 {
187 bool defined = false;
188 CComPtr<IFolderGetSystemIconIndex> folderGetSystemIconIndex;
189 _folder.QueryInterface(&folderGetSystemIconIndex);
190 if (folderGetSystemIconIndex)
191 {
192 folderGetSystemIconIndex->GetSystemIconIndex(index, &item.iImage);
193 defined = (item.iImage > 0);
194 }
195 if (!defined)
196 {
197 NCOM::CPropVariant prop;
198 _folder->GetProperty(index, kpidAttrib, &prop);
199 UINT32 attrib = 0;
200 if (prop.vt == VT_UI4)
201 attrib = prop.ulVal;
202 else if (IsItemFolder(index))
203 attrib |= FILE_ATTRIBUTE_DIRECTORY;
204 if (_currentFolderPrefix.IsEmpty())
205 throw 1;
206 else
207 item.iImage = _extToIconMap.GetIconIndex(attrib, GetSystemString(GetItemName(index)));
208 }
209 // item.iImage = 1;
210 }
211 */
212
213 if ((item.mask & LVIF_TEXT) == 0)
214 return 0;
215
216 LPWSTR text = item.pszText;
217
218 if (item.cchTextMax > 0)
219 text[0] = 0;
220
221 if (item.cchTextMax <= 1)
222 return 0;
223
224 const CPropColumn &property = _visibleColumns[item.iSubItem];
225 PROPID propID = property.ID;
226
227 if (realIndex == kParentIndex_UInt32)
228 {
229 if (propID == kpidName)
230 {
231 if (item.cchTextMax > 2)
232 {
233 text[0] = '.';
234 text[1] = '.';
235 text[2] = 0;
236 }
237 }
238 return 0;
239 }
240
241 /*
242 // List-view in report-view in Windows 10 is slow (50+ ms) for page change.
243 // that code shows the time of page reload for items
244 // if you know how to improve the speed of list view refresh, notify 7-Zip developer
245
246 // if (propID == 2000)
247 // if (propID == kpidName)
248 {
249 // debug column;
250 // DWORD dw = GetCpuTicks();
251 UInt64 dw = GetCpuTicks();
252 UInt64 deltaLast = dw - g_prev_tick;
253 #define conv_ticks(t) ((unsigned)((t) / 100000))
254 if (deltaLast > 1000u * 1000 * 1000)
255 {
256 UInt64 deltaFull = g_prev_tick - g_start_tick;
257 char s[128];
258 sprintf(s, "%d", conv_ticks(deltaFull));
259 OutputDebugStringA(s);
260 g_start_tick = dw;
261 g_NumGroups++;
262 }
263 g_prev_tick = dw;
264 UString u;
265 char s[128];
266 UInt64 deltaFull = dw - g_start_tick;
267 // for (int i = 0; i < 100000; i++)
268 sprintf(s, "%d %d %d-%d ", g_NumMessages, g_Num_SetItemText, g_NumGroups, conv_ticks(deltaFull));
269 // sprintf(s, "%d-%d ", g_NumGroups, conv_ticks(deltaFull));
270 u = s;
271 lstrcpyW(text, u.Ptr());
272 text += u.Len();
273
274 // dw = GetCpuTicks();
275 // deltaFull = dw - g_prev_tick;
276 // sprintf(s, "-%d ", conv_ticks(deltaFull));
277 // u = s;
278 // lstrcpyW(text, u.Ptr());
279 // text += u.Len();
280
281 if (propID != kpidName)
282 return 0;
283 }
284 */
285
286
287 if (property.IsRawProp)
288 {
289 const void *data;
290 UInt32 dataSize;
291 UInt32 propType;
292 RINOK(_folderRawProps->GetRawProp(realIndex, propID, &data, &dataSize, &propType));
293 unsigned limit = item.cchTextMax - 1;
294 if (dataSize == 0)
295 {
296 text[0] = 0;
297 return 0;
298 }
299
300 if (propID == kpidNtReparse)
301 {
302 UString s;
303 ConvertNtReparseToString((const Byte *)data, dataSize, s);
304 if (!s.IsEmpty())
305 {
306 unsigned i;
307 for (i = 0; i < limit; i++)
308 {
309 wchar_t c = s[i];
310 if (c == 0)
311 break;
312 text[i] = c;
313 }
314 text[i] = 0;
315 return 0;
316 }
317 }
318 else if (propID == kpidNtSecure)
319 {
320 AString s;
321 ConvertNtSecureToString((const Byte *)data, dataSize, s);
322 if (!s.IsEmpty())
323 {
324 unsigned i;
325 for (i = 0; i < limit; i++)
326 {
327 wchar_t c = (Byte)s[i];
328 if (c == 0)
329 break;
330 text[i] = c;
331 }
332 text[i] = 0;
333 return 0;
334 }
335 }
336 {
337 const unsigned kMaxDataSize = 64;
338 if (dataSize > kMaxDataSize)
339 {
340 char temp[32];
341 MyStringCopy(temp, "data:");
342 ConvertUInt32ToString(dataSize, temp + 5);
343 unsigned i;
344 for (i = 0; i < limit; i++)
345 {
346 wchar_t c = (Byte)temp[i];
347 if (c == 0)
348 break;
349 text[i] = c;
350 }
351 text[i] = 0;
352 }
353 else
354 {
355 if (dataSize > limit)
356 dataSize = limit;
357 WCHAR *dest = text;
358 const bool needUpper = (dataSize <= 8)
359 && (propID == kpidCRC || propID == kpidChecksum);
360 for (UInt32 i = 0; i < dataSize; i++)
361 {
362 unsigned b = ((const Byte *)data)[i];
363 if (needUpper)
364 {
365 dest[0] = (WCHAR)GetHex_Upper((b >> 4) & 0xF);
366 dest[1] = (WCHAR)GetHex_Upper(b & 0xF);
367 }
368 else
369 {
370 dest[0] = (WCHAR)GetHex_Lower((b >> 4) & 0xF);
371 dest[1] = (WCHAR)GetHex_Lower(b & 0xF);
372 }
373 dest += 2;
374 }
375 *dest = 0;
376 }
377 }
378 return 0;
379 }
380 /*
381 {
382 NCOM::CPropVariant prop;
383 if (propID == kpidType)
384 string = GetFileType(index);
385 else
386 {
387 HRESULT result = m_ArchiveFolder->GetProperty(index, propID, &prop);
388 if (result != S_OK)
389 {
390 // PrintMessage("GetPropertyValue error");
391 return 0;
392 }
393 string = ConvertPropertyToString(prop, propID, false);
394 }
395 }
396 */
397 // const NFind::CFileInfo &aFileInfo = m_Files[index];
398
399 NCOM::CPropVariant prop;
400 /*
401 bool needRead = true;
402 if (propID == kpidSize)
403 {
404 CComPtr<IFolderGetItemFullSize> getItemFullSize;
405 if (_folder.QueryInterface(&getItemFullSize) == S_OK)
406 {
407 if (getItemFullSize->GetItemFullSize(index, &prop) == S_OK)
408 needRead = false;
409 }
410 }
411 if (needRead)
412 */
413
414 if (item.cchTextMax < 32)
415 return 0;
416
417 if (propID == kpidName)
418 {
419 if (_folderGetItemName)
420 {
421 const wchar_t *name = NULL;
422 unsigned nameLen = 0;
423 _folderGetItemName->GetItemName(realIndex, &name, &nameLen);
424
425 if (name)
426 {
427 unsigned dest = 0;
428 unsigned limit = item.cchTextMax - 1;
429
430 for (unsigned i = 0; dest < limit;)
431 {
432 wchar_t c = name[i++];
433 if (c == 0)
434 break;
435 text[dest++] = c;
436
437 if (c != ' ')
438 {
439 if (c != 0x202E) // RLO
440 continue;
441 text[(size_t)dest - 1] = '_';
442 continue;
443 }
444
445 if (name[i] != ' ')
446 continue;
447
448 unsigned t = 1;
449 for (; name[i + t] == ' '; t++);
450
451 if (t >= 4 && dest + 4 < limit)
452 {
453 text[dest++] = '.';
454 text[dest++] = '.';
455 text[dest++] = '.';
456 text[dest++] = ' ';
457 i += t;
458 }
459 }
460
461 if (dest == 0)
462 text[dest++]= '_';
463
464 #ifdef _WIN32
465 else if (text[(size_t)dest - 1] == ' ')
466 {
467 if (dest < limit)
468 text[dest++] = SPACE_TERMINATOR_CHAR;
469 else
470 text[dest - 1] = SPACE_REPLACE_CHAR;
471 }
472 #endif
473
474 text[dest] = 0;
475 // OutputDebugStringW(text);
476 return 0;
477 }
478 }
479 }
480
481 if (propID == kpidPrefix)
482 {
483 if (_folderGetItemName)
484 {
485 const wchar_t *name = NULL;
486 unsigned nameLen = 0;
487 _folderGetItemName->GetItemPrefix(realIndex, &name, &nameLen);
488 if (name)
489 {
490 unsigned dest = 0;
491 unsigned limit = item.cchTextMax - 1;
492 for (unsigned i = 0; dest < limit;)
493 {
494 wchar_t c = name[i++];
495 if (c == 0)
496 break;
497 text[dest++] = c;
498 }
499 text[dest] = 0;
500 return 0;
501 }
502 }
503 }
504
505 HRESULT res = _folder->GetProperty(realIndex, propID, &prop);
506
507 if (res != S_OK)
508 {
509 MyStringCopy(text, L"Error: ");
510 // s = UString("Error: ") + HResultToMessage(res);
511 }
512 else if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
513 {
514 UInt64 v = 0;
515 ConvertPropVariantToUInt64(prop, v);
516 ConvertSizeToString(v, text);
517 }
518 else if (prop.vt == VT_BSTR)
519 {
520 unsigned limit = item.cchTextMax - 1;
521 const wchar_t *src = prop.bstrVal;
522 unsigned i;
523 for (i = 0; i < limit; i++)
524 {
525 wchar_t c = src[i];
526 if (c == 0) break;
527 if (c == 0xA) c = ' ';
528 if (c == 0xD) c = ' ';
529 text[i] = c;
530 }
531 text[i] = 0;
532 }
533 else
534 {
535 char temp[64];
536 ConvertPropertyToShortString2(temp, prop, propID, _timestampLevel);
537 unsigned i;
538 unsigned limit = item.cchTextMax - 1;
539 for (i = 0; i < limit; i++)
540 {
541 wchar_t c = (Byte)temp[i];
542 if (c == 0)
543 break;
544 text[i] = c;
545 }
546 text[i] = 0;
547 }
548
549 return 0;
550}
551
552#ifndef UNDER_CE
553extern DWORD g_ComCtl32Version;
554#endif
555
556void CPanel::OnItemChanged(NMLISTVIEW *item)
557{
558 int index = (int)item->lParam;
559 if (index == kParentIndex)
560 return;
561 bool oldSelected = (item->uOldState & LVIS_SELECTED) != 0;
562 bool newSelected = (item->uNewState & LVIS_SELECTED) != 0;
563 // Don't change this code. It works only with such check
564 if (oldSelected != newSelected)
565 _selectedStatusVector[index] = newSelected;
566}
567
568extern bool g_LVN_ITEMACTIVATE_Support;
569
570void CPanel::OnNotifyActivateItems()
571{
572 bool alt = IsKeyDown(VK_MENU);
573 bool ctrl = IsKeyDown(VK_CONTROL);
574 bool shift = IsKeyDown(VK_SHIFT);
575 if (!shift && alt && !ctrl)
576 Properties();
577 else
578 OpenSelectedItems(!shift || alt || ctrl);
579}
580
581bool CPanel::OnNotifyList(LPNMHDR header, LRESULT &result)
582{
583 switch (header->code)
584 {
585 case LVN_ITEMCHANGED:
586 {
587 if (_enableItemChangeNotify)
588 {
589 if (!_mySelectMode)
590 OnItemChanged((LPNMLISTVIEW)header);
591
592 // Post_Refresh_StatusBar();
593 /* 9.26: we don't call Post_Refresh_StatusBar.
594 it was very slow if we select big number of files
595 and then clead slection by selecting just new file.
596 probably it called slow Refresh_StatusBar for each item deselection.
597 I hope Refresh_StatusBar still will be called for each key / mouse action.
598 */
599 }
600 return false;
601 }
602 /*
603
604 case LVN_ODSTATECHANGED:
605 {
606 break;
607 }
608 */
609
610 case LVN_GETDISPINFOW:
611 {
612 LV_DISPINFOW *dispInfo = (LV_DISPINFOW *)header;
613
614 //is the sub-item information being requested?
615
616 if ((dispInfo->item.mask & LVIF_TEXT) != 0 ||
617 (dispInfo->item.mask & LVIF_IMAGE) != 0)
618 SetItemText(dispInfo->item);
619 {
620 // 20.03:
621 result = 0;
622 return true;
623 // old 7-Zip:
624 // return false;
625 }
626 }
627 case LVN_KEYDOWN:
628 {
629 LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);
630 bool boolResult = OnKeyDown(keyDownInfo, result);
631 switch (keyDownInfo->wVKey)
632 {
633 case VK_CONTROL:
634 case VK_SHIFT:
635 case VK_MENU:
636 break;
637 default:
638 Post_Refresh_StatusBar();
639 }
640 return boolResult;
641 }
642
643 case LVN_COLUMNCLICK:
644 OnColumnClick(LPNMLISTVIEW(header));
645 return false;
646
647 case LVN_ITEMACTIVATE:
648 if (g_LVN_ITEMACTIVATE_Support)
649 {
650 OnNotifyActivateItems();
651 return false;
652 }
653 break;
654 case NM_DBLCLK:
655 case NM_RETURN:
656 if (!g_LVN_ITEMACTIVATE_Support)
657 {
658 OnNotifyActivateItems();
659 return false;
660 }
661 break;
662
663 case NM_RCLICK:
664 Post_Refresh_StatusBar();
665 break;
666
667 /*
668 return OnRightClick((LPNMITEMACTIVATE)header, result);
669 */
670 /*
671 case NM_CLICK:
672 SendRefreshStatusBarMessage();
673 return 0;
674
675 // TODO : Handler default action...
676 return 0;
677 case LVN_ITEMCHANGED:
678 {
679 NMLISTVIEW *pNMLV = (NMLISTVIEW *) lpnmh;
680 SelChange(pNMLV);
681 return TRUE;
682 }
683 case NM_SETFOCUS:
684 return onSetFocus(NULL);
685 case NM_KILLFOCUS:
686 return onKillFocus(NULL);
687 */
688 case NM_CLICK:
689 {
690 // we need SetFocusToList, if we drag-select items from other panel.
691 SetFocusToList();
692 Post_Refresh_StatusBar();
693 if (_mySelectMode)
694 #ifndef UNDER_CE
695 if (g_ComCtl32Version >= MAKELONG(71, 4))
696 #endif
697 OnLeftClick((MY_NMLISTVIEW_NMITEMACTIVATE *)header);
698 return false;
699 }
700 case LVN_BEGINLABELEDITW:
701 result = OnBeginLabelEdit((LV_DISPINFOW *)header);
702 return true;
703 case LVN_ENDLABELEDITW:
704 result = OnEndLabelEdit((LV_DISPINFOW *)header);
705 return true;
706
707 case NM_CUSTOMDRAW:
708 {
709 if (_mySelectMode || (_markDeletedItems && _thereAreDeletedItems))
710 return OnCustomDraw((LPNMLVCUSTOMDRAW)header, result);
711 break;
712 }
713 case LVN_BEGINDRAG:
714 {
715 OnDrag((LPNMLISTVIEW)header);
716 Post_Refresh_StatusBar();
717 break;
718 }
719 // case LVN_BEGINRDRAG:
720 }
721 return false;
722}
723
724bool CPanel::OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result)
725{
726 switch (lplvcd->nmcd.dwDrawStage)
727 {
728 case CDDS_PREPAINT :
729 result = CDRF_NOTIFYITEMDRAW;
730 return true;
731
732 case CDDS_ITEMPREPAINT:
733 /*
734 SelectObject(lplvcd->nmcd.hdc,
735 GetFontForItem(lplvcd->nmcd.dwItemSpec,
736 lplvcd->nmcd.lItemlParam) );
737 lplvcd->clrText = GetColorForItem(lplvcd->nmcd.dwItemSpec,
738 lplvcd->nmcd.lItemlParam);
739 lplvcd->clrTextBk = GetBkColorForItem(lplvcd->nmcd.dwItemSpec,
740 lplvcd->nmcd.lItemlParam);
741 */
742 int realIndex = (int)lplvcd->nmcd.lItemlParam;
743 lplvcd->clrTextBk = _listView.GetBkColor();
744 if (_mySelectMode)
745 {
746 if (realIndex != kParentIndex && _selectedStatusVector[realIndex])
747 lplvcd->clrTextBk = RGB(255, 192, 192);
748 }
749
750 if (_markDeletedItems && _thereAreDeletedItems)
751 {
752 if (IsItem_Deleted(realIndex))
753 lplvcd->clrText = RGB(255, 0, 0);
754 }
755 // lplvcd->clrText = RGB(0, 0, 0);
756 // result = CDRF_NEWFONT;
757 result = CDRF_NOTIFYITEMDRAW;
758 return true;
759
760 // return false;
761 // return true;
762 /*
763 case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
764 if (lplvcd->iSubItem == 0)
765 {
766 // lplvcd->clrText = RGB(255, 0, 0);
767 lplvcd->clrTextBk = RGB(192, 192, 192);
768 }
769 else
770 {
771 lplvcd->clrText = RGB(0, 0, 0);
772 lplvcd->clrTextBk = RGB(255, 255, 255);
773 }
774 return true;
775 */
776
777 /* At this point, you can change the background colors for the item
778 and any subitems and return CDRF_NEWFONT. If the list-view control
779 is in report mode, you can simply return CDRF_NOTIFYSUBITEMREDRAW
780 to customize the item's subitems individually */
781 }
782 return false;
783}
784
785void CPanel::Refresh_StatusBar()
786{
787 /*
788 g_name_cnt++;
789 char s[256];
790 sprintf(s, "g_name_cnt = %8d", g_name_cnt);
791 OutputDebugStringA(s);
792 */
793 // DWORD dw = GetTickCount();
794
795 CRecordVector<UInt32> indices;
796 GetOperatedItemIndices(indices);
797
798 wchar_t temp[32];
799 ConvertUInt32ToString(indices.Size(), temp);
800 wcscat(temp, L" / ");
801 ConvertUInt32ToString(_selectedStatusVector.Size(), temp + wcslen(temp));
802
803 // UString s1 = MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, NumberToString(indices.Size()));
804 // UString s1 = MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size()));
805 _statusBar.SetText(0, MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, temp));
806 // _statusBar.SetText(0, MyFormatNew(IDS_N_SELECTED_ITEMS, NumberToString(indices.Size())));
807
808 wchar_t selectSizeString[32];
809 selectSizeString[0] = 0;
810
811 if (indices.Size() > 0)
812 {
813 // for (unsigned ttt = 0; ttt < 1000; ttt++) {
814 UInt64 totalSize = 0;
815 FOR_VECTOR (i, indices)
816 totalSize += GetItemSize(indices[i]);
817 ConvertSizeToString(totalSize, selectSizeString);
818 // }
819 }
820 _statusBar.SetText(1, selectSizeString);
821
822 int focusedItem = _listView.GetFocusedItem();
823 wchar_t sizeString[32];
824 sizeString[0] = 0;
825 wchar_t dateString[32];
826 dateString[0] = 0;
827 if (focusedItem >= 0 && _listView.GetSelectedCount() > 0)
828 {
829 int realIndex = GetRealItemIndex(focusedItem);
830 if (realIndex != kParentIndex)
831 {
832 ConvertSizeToString(GetItemSize(realIndex), sizeString);
833 NCOM::CPropVariant prop;
834 if (_folder->GetProperty(realIndex, kpidMTime, &prop) == S_OK)
835 {
836 char dateString2[32];
837 dateString2[0] = 0;
838 ConvertPropertyToShortString2(dateString2, prop, kpidMTime);
839 for (unsigned i = 0;; i++)
840 {
841 char c = dateString2[i];
842 dateString[i] = (Byte)c;
843 if (c == 0)
844 break;
845 }
846 }
847 }
848 }
849 _statusBar.SetText(2, sizeString);
850 _statusBar.SetText(3, dateString);
851
852 // _statusBar.SetText(4, nameString);
853 // _statusBar2.SetText(1, MyFormatNew(L"{0} bytes", NumberToStringW(totalSize)));
854 // }
855 /*
856 dw = GetTickCount() - dw;
857 sprintf(s, "status = %8d ms", dw);
858 OutputDebugStringA(s);
859 */
860}
diff --git a/CPP/7zip/UI/FileManager/PanelMenu.cpp b/CPP/7zip/UI/FileManager/PanelMenu.cpp
new file mode 100644
index 0000000..1a09a8f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelMenu.cpp
@@ -0,0 +1,1153 @@
1#include "StdAfx.h"
2
3#include "../../../Common/IntToString.h"
4#include "../../../Common/StringConvert.h"
5
6#include "../../../Windows/COM.h"
7#include "../../../Windows/Clipboard.h"
8#include "../../../Windows/Menu.h"
9#include "../../../Windows/PropVariant.h"
10#include "../../../Windows/PropVariantConv.h"
11
12#include "../../PropID.h"
13#include "../Common/PropIDUtils.h"
14#include "../Explorer/ContextMenu.h"
15
16#include "App.h"
17#include "FormatUtils.h"
18#include "LangUtils.h"
19#include "ListViewDialog.h"
20#include "MyLoadMenu.h"
21#include "PropertyName.h"
22
23#include "resource.h"
24#include "PropertyNameRes.h"
25
26using namespace NWindows;
27
28extern
29LONG g_DllRefCount;
30LONG g_DllRefCount = 0;
31
32static const UINT kSevenZipStartMenuID = kMenuCmdID_Plugin_Start;
33static const UINT kSystemStartMenuID = kMenuCmdID_Plugin_Start + 400;
34
35void CPanel::InvokeSystemCommand(const char *command)
36{
37 NCOM::CComInitializer comInitializer;
38 if (!IsFsOrPureDrivesFolder())
39 return;
40 CRecordVector<UInt32> operatedIndices;
41 GetOperatedItemIndices(operatedIndices);
42 if (operatedIndices.IsEmpty())
43 return;
44 CMyComPtr<IContextMenu> contextMenu;
45 if (CreateShellContextMenu(operatedIndices, contextMenu) != S_OK)
46 return;
47
48 CMINVOKECOMMANDINFO ci;
49 ZeroMemory(&ci, sizeof(ci));
50 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
51 ci.hwnd = GetParent();
52 ci.lpVerb = command;
53 contextMenu->InvokeCommand(&ci);
54}
55
56static const char * const kSeparator = "------------------------";
57static const char * const kSeparatorSmall = "----------------";
58
59extern UString ConvertSizeToString(UInt64 value) throw();
60bool IsSizeProp(UINT propID) throw();
61
62UString GetOpenArcErrorMessage(UInt32 errorFlags);
63
64
65static void AddListAscii(CListViewDialog &dialog, const char *s)
66{
67 dialog.Strings.Add((UString)s);
68 dialog.Values.AddNew();
69}
70
71static void AddSeparator(CListViewDialog &dialog)
72{
73 AddListAscii(dialog, kSeparator);
74}
75
76static void AddSeparatorSmall(CListViewDialog &dialog)
77{
78 AddListAscii(dialog, kSeparatorSmall);
79}
80
81static void AddPropertyPair(const UString &name, const UString &val, CListViewDialog &dialog)
82{
83 dialog.Strings.Add(name);
84 dialog.Values.Add(val);
85}
86
87
88static void AddPropertyString(PROPID propID, const wchar_t *nameBSTR,
89 const NCOM::CPropVariant &prop, CListViewDialog &dialog)
90{
91 if (prop.vt != VT_EMPTY)
92 {
93 UString val;
94
95 if (propID == kpidErrorFlags ||
96 propID == kpidWarningFlags)
97 {
98 UInt32 flags = GetOpenArcErrorFlags(prop);
99 if (flags == 0)
100 return;
101 if (flags != 0)
102 val = GetOpenArcErrorMessage(flags);
103 }
104
105 if (val.IsEmpty())
106 {
107 if ((prop.vt == VT_UI8 || prop.vt == VT_UI4 || prop.vt == VT_UI2) && IsSizeProp(propID))
108 {
109 UInt64 v = 0;
110 ConvertPropVariantToUInt64(prop, v);
111 val = ConvertSizeToString(v);
112 }
113 else
114 ConvertPropertyToString2(val, prop, propID);
115 }
116
117 if (!val.IsEmpty())
118 {
119 if (propID == kpidErrorType)
120 {
121 AddPropertyPair(L"Open WARNING:", L"Cannot open the file as expected archive type", dialog);
122 }
123 AddPropertyPair(GetNameOfProperty(propID, nameBSTR), val, dialog);
124 }
125 }
126}
127
128
129static void AddPropertyString(PROPID propID, UInt64 val, CListViewDialog &dialog)
130{
131 NCOM::CPropVariant prop = val;
132 AddPropertyString(propID, NULL, prop, dialog);
133}
134
135
136static inline unsigned GetHex_Upper(unsigned v)
137{
138 return (v < 10) ? ('0' + v) : ('A' + (v - 10));
139}
140
141static inline unsigned GetHex_Lower(unsigned v)
142{
143 return (v < 10) ? ('0' + v) : ('a' + (v - 10));
144}
145
146static const Byte kSpecProps[] =
147{
148 kpidPath,
149 kpidType,
150 kpidErrorType,
151 kpidError,
152 kpidErrorFlags,
153 kpidWarning,
154 kpidWarningFlags,
155 kpidOffset,
156 kpidPhySize,
157 kpidTailSize
158};
159
160void CPanel::Properties()
161{
162 CMyComPtr<IGetFolderArcProps> getFolderArcProps;
163 _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
164 if (!getFolderArcProps)
165 {
166 InvokeSystemCommand("properties");
167 return;
168 }
169
170 {
171 CListViewDialog message;
172 // message.DeleteIsAllowed = false;
173 // message.SelectFirst = false;
174
175 CRecordVector<UInt32> operatedIndices;
176 GetOperatedItemIndices(operatedIndices);
177
178 if (operatedIndices.Size() == 1)
179 {
180 UInt32 index = operatedIndices[0];
181 // message += "Item:\n");
182 UInt32 numProps;
183 if (_folder->GetNumberOfProperties(&numProps) == S_OK)
184 {
185 for (UInt32 i = 0; i < numProps; i++)
186 {
187 CMyComBSTR name;
188 PROPID propID;
189 VARTYPE varType;
190
191 if (_folder->GetPropertyInfo(i, &name, &propID, &varType) != S_OK)
192 continue;
193
194 NCOM::CPropVariant prop;
195 if (_folder->GetProperty(index, propID, &prop) != S_OK)
196 continue;
197 AddPropertyString(propID, name, prop, message);
198 }
199 }
200
201
202 if (_folderRawProps)
203 {
204 _folderRawProps->GetNumRawProps(&numProps);
205 for (UInt32 i = 0; i < numProps; i++)
206 {
207 CMyComBSTR name;
208 PROPID propID;
209 if (_folderRawProps->GetRawPropInfo(i, &name, &propID) != S_OK)
210 continue;
211
212 const void *data;
213 UInt32 dataSize;
214 UInt32 propType;
215 if (_folderRawProps->GetRawProp(index, propID, &data, &dataSize, &propType) != S_OK)
216 continue;
217
218 if (dataSize != 0)
219 {
220 AString s;
221 if (propID == kpidNtSecure)
222 ConvertNtSecureToString((const Byte *)data, dataSize, s);
223 else
224 {
225 const UInt32 kMaxDataSize = 64;
226 if (dataSize > kMaxDataSize)
227 {
228 s += "data:";
229 s.Add_UInt32(dataSize);
230 }
231 else
232 {
233 const bool needUpper = (dataSize <= 8)
234 && (propID == kpidCRC || propID == kpidChecksum);
235 for (UInt32 k = 0; k < dataSize; k++)
236 {
237 const Byte b = ((const Byte *)data)[k];
238 if (needUpper)
239 {
240 s += (char)GetHex_Upper((b >> 4) & 0xF);
241 s += (char)GetHex_Upper(b & 0xF);
242 }
243 else
244 {
245 s += (char)GetHex_Lower((b >> 4) & 0xF);
246 s += (char)GetHex_Lower(b & 0xF);
247 }
248 }
249 }
250 }
251 AddPropertyPair(GetNameOfProperty(propID, name), (UString)s.Ptr(), message);
252 }
253 }
254 }
255
256 AddSeparator(message);
257 }
258 else if (operatedIndices.Size() >= 1)
259 {
260 UInt64 packSize = 0;
261 UInt64 unpackSize = 0;
262 UInt64 numFiles = 0;
263 UInt64 numDirs = 0;
264
265 FOR_VECTOR (i, operatedIndices)
266 {
267 const UInt32 index = operatedIndices[i];
268 unpackSize += GetItemSize(index);
269 packSize += GetItem_UInt64Prop(index, kpidPackSize);
270 if (IsItem_Folder(index))
271 {
272 numDirs++;
273 numDirs += GetItem_UInt64Prop(index, kpidNumSubDirs);
274 numFiles += GetItem_UInt64Prop(index, kpidNumSubFiles);
275 }
276 else
277 numFiles++;
278 }
279 {
280 wchar_t temp[32];
281 ConvertUInt32ToString(operatedIndices.Size(), temp);
282 AddPropertyPair(L"", MyFormatNew(g_App.LangString_N_SELECTED_ITEMS, temp), message);
283 }
284
285 if (numDirs != 0)
286 AddPropertyString(kpidNumSubDirs, numDirs, message);
287 if (numFiles != 0)
288 AddPropertyString(kpidNumSubFiles, numFiles, message);
289 AddPropertyString(kpidSize, unpackSize, message);
290 AddPropertyString(kpidPackSize, packSize, message);
291
292 AddSeparator(message);
293 }
294
295
296 /*
297 AddLangString(message, IDS_PROP_FILE_TYPE);
298 message += kPropValueSeparator;
299 message += GetFolderTypeID();
300 message.Add_LF();
301 */
302
303 {
304 NCOM::CPropVariant prop;
305 if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK)
306 {
307 AddPropertyString(kpidName, L"Path", prop, message);
308 }
309 }
310
311 CMyComPtr<IFolderProperties> folderProperties;
312 _folder.QueryInterface(IID_IFolderProperties, &folderProperties);
313 if (folderProperties)
314 {
315 UInt32 numProps;
316 if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK)
317 {
318 for (UInt32 i = 0; i < numProps; i++)
319 {
320 CMyComBSTR name;
321 PROPID propID;
322 VARTYPE vt;
323 if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK)
324 continue;
325 NCOM::CPropVariant prop;
326 if (_folder->GetFolderProperty(propID, &prop) != S_OK)
327 continue;
328 AddPropertyString(propID, name, prop, message);
329 }
330 }
331 }
332
333 if (getFolderArcProps)
334 {
335 CMyComPtr<IFolderArcProps> getProps;
336 getFolderArcProps->GetFolderArcProps(&getProps);
337 if (getProps)
338 {
339 UInt32 numLevels;
340 if (getProps->GetArcNumLevels(&numLevels) != S_OK)
341 numLevels = 0;
342 for (UInt32 level2 = 0; level2 < numLevels; level2++)
343 {
344 {
345 UInt32 level = numLevels - 1 - level2;
346 UInt32 numProps;
347 if (getProps->GetArcNumProps(level, &numProps) == S_OK)
348 {
349 const int kNumSpecProps = ARRAY_SIZE(kSpecProps);
350
351 AddSeparator(message);
352
353 for (Int32 i = -(int)kNumSpecProps; i < (Int32)numProps; i++)
354 {
355 CMyComBSTR name;
356 PROPID propID;
357 VARTYPE vt;
358 if (i < 0)
359 propID = kSpecProps[i + kNumSpecProps];
360 else if (getProps->GetArcPropInfo(level, i, &name, &propID, &vt) != S_OK)
361 continue;
362 NCOM::CPropVariant prop;
363 if (getProps->GetArcProp(level, propID, &prop) != S_OK)
364 continue;
365 AddPropertyString(propID, name, prop, message);
366 }
367 }
368 }
369
370 if (level2 < numLevels - 1)
371 {
372 UInt32 level = numLevels - 1 - level2;
373 UInt32 numProps;
374 if (getProps->GetArcNumProps2(level, &numProps) == S_OK)
375 {
376 AddSeparatorSmall(message);
377 for (Int32 i = 0; i < (Int32)numProps; i++)
378 {
379 CMyComBSTR name;
380 PROPID propID;
381 VARTYPE vt;
382 if (getProps->GetArcPropInfo2(level, i, &name, &propID, &vt) != S_OK)
383 continue;
384 NCOM::CPropVariant prop;
385 if (getProps->GetArcProp2(level, propID, &prop) != S_OK)
386 continue;
387 AddPropertyString(propID, name, prop, message);
388 }
389 }
390 }
391 }
392
393 {
394 // we ERROR message for NonOpen level
395 bool needSep = true;
396 const int kNumSpecProps = ARRAY_SIZE(kSpecProps);
397 for (Int32 i = -(int)kNumSpecProps; i < 0; i++)
398 {
399 CMyComBSTR name;
400 PROPID propID = kSpecProps[i + kNumSpecProps];
401 NCOM::CPropVariant prop;
402 if (getProps->GetArcProp(numLevels, propID, &prop) != S_OK)
403 continue;
404 if (needSep)
405 {
406 AddSeparator(message);
407 AddSeparator(message);
408 needSep = false;
409 }
410 AddPropertyString(propID, name, prop, message);
411 }
412 }
413
414 }
415 }
416
417 message.Title = LangString(IDS_PROPERTIES);
418 message.NumColumns = 2;
419 message.Create(GetParent());
420 }
421}
422
423
424
425void CPanel::EditCut()
426{
427 // InvokeSystemCommand("cut");
428}
429
430void CPanel::EditCopy()
431{
432 /*
433 CMyComPtr<IGetFolderArcProps> getFolderArcProps;
434 _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
435 if (!getFolderArcProps)
436 {
437 InvokeSystemCommand("copy");
438 return;
439 }
440 */
441 UString s;
442 CRecordVector<UInt32> indices;
443 GetSelectedItemsIndices(indices);
444 FOR_VECTOR (i, indices)
445 {
446 if (i != 0)
447 s += "\xD\n";
448 s += GetItemName(indices[i]);
449 }
450 ClipboardSetText(_mainWindow, s);
451}
452
453void CPanel::EditPaste()
454{
455 /*
456 UStringVector names;
457 ClipboardGetFileNames(names);
458 CopyFromNoAsk(names);
459 UString s;
460 for (int i = 0; i < names.Size(); i++)
461 {
462 s += L' ';
463 s += names[i];
464 }
465
466 MessageBoxW(0, s, L"", 0);
467 */
468
469 // InvokeSystemCommand("paste");
470}
471
472
473
474struct CFolderPidls
475{
476 LPITEMIDLIST parent;
477 CRecordVector<LPITEMIDLIST> items;
478
479 CFolderPidls(): parent(NULL) {}
480 ~CFolderPidls()
481 {
482 FOR_VECTOR (i, items)
483 CoTaskMemFree(items[i]);
484 CoTaskMemFree(parent);
485 }
486};
487
488
489HRESULT CPanel::CreateShellContextMenu(
490 const CRecordVector<UInt32> &operatedIndices,
491 CMyComPtr<IContextMenu> &systemContextMenu)
492{
493 systemContextMenu.Release();
494 const UString folderPath = GetFsPath();
495
496 CMyComPtr<IShellFolder> desktopFolder;
497 RINOK(::SHGetDesktopFolder(&desktopFolder));
498 if (!desktopFolder)
499 {
500 // ShowMessage("Failed to get Desktop folder");
501 return E_FAIL;
502 }
503
504 CFolderPidls pidls;
505 DWORD eaten;
506
507 // if (folderPath.IsEmpty()), then ParseDisplayName returns pidls of "My Computer"
508 RINOK(desktopFolder->ParseDisplayName(
509 GetParent(), NULL, folderPath.Ptr_non_const(),
510 &eaten, &pidls.parent, NULL));
511
512 /*
513 STRRET pName;
514 res = desktopFolder->GetDisplayNameOf(pidls.parent, SHGDN_NORMAL, &pName);
515 WCHAR dir[MAX_PATH];
516 if (!SHGetPathFromIDListW(pidls.parent, dir))
517 dir[0] = 0;
518 */
519
520 if (!pidls.parent)
521 return E_FAIL;
522
523 if (operatedIndices.IsEmpty())
524 {
525 // how to get IContextMenu, if there are no selected files?
526 return E_FAIL;
527
528 /*
529 xp64 :
530 1) we can't use GetUIObjectOf() with (numItems == 0), it throws exception
531 2) we can't use desktopFolder->GetUIObjectOf() with absolute pidls of folder
532 context menu items are different in that case:
533 "Open / Explorer" for folder
534 "Delete" for "My Computer" icon
535 "Preperties" for "System"
536 */
537 /*
538 parentFolder = desktopFolder;
539 pidls.items.AddInReserved(pidls.parent);
540 pidls.parent = NULL;
541 */
542
543 // CreateViewObject() doesn't show all context menu items
544 /*
545 HRESULT res = parentFolder->CreateViewObject(
546 GetParent(), IID_IContextMenu, (void**)&systemContextMenu);
547 */
548 }
549
550 CMyComPtr<IShellFolder> parentFolder;
551 RINOK(desktopFolder->BindToObject(pidls.parent,
552 NULL, IID_IShellFolder, (void**)&parentFolder));
553 if (!parentFolder)
554 {
555 // ShowMessage("Invalid file name");
556 return E_FAIL;
557 }
558
559 pidls.items.ClearAndReserve(operatedIndices.Size());
560 FOR_VECTOR (i, operatedIndices)
561 {
562 LPITEMIDLIST pidl;
563 const UString fileName = GetItemRelPath2(operatedIndices[i]);
564 RINOK(parentFolder->ParseDisplayName(GetParent(), 0,
565 fileName.Ptr_non_const(), &eaten, &pidl, 0));
566 pidls.items.AddInReserved(pidl);
567 }
568
569 // Get IContextMenu for items
570
571 RINOK(parentFolder->GetUIObjectOf(GetParent(), pidls.items.Size(),
572 (LPCITEMIDLIST *)(void *)&pidls.items.Front(), IID_IContextMenu, 0, (void**)&systemContextMenu));
573
574 if (!systemContextMenu)
575 {
576 // ShowMessage("Unable to get context menu interface");
577 return E_FAIL;
578 }
579 return S_OK;
580}
581
582// #define SHOW_DEBUG_FM_CTX_MENU
583
584#ifdef SHOW_DEBUG_FM_CTX_MENU
585
586#include <stdio.h>
587
588// #include Common/IntToString.h"
589
590static void PrintHex(UString &s, UInt32 v)
591{
592 char sz[32];
593 ConvertUInt32ToHex(v, sz);
594 s += sz;
595}
596
597static void PrintContextStr(UString &s, IContextMenu *ctxm, unsigned i, unsigned id, const char *name)
598{
599 s += " | ";
600 name = name;
601 // s += name;
602 // s += ": ";
603
604 UString s1;
605 {
606 char buf[256];
607 buf[0] = 0;
608 HRESULT res = ctxm->GetCommandString(i, id,
609 NULL, buf, ARRAY_SIZE(buf) - 1);
610 if (res != S_OK)
611 {
612 PrintHex(s1, res);
613 s1.Add_Space();
614 }
615 s1 += GetUnicodeString(buf);
616 }
617
618 UString s2;
619 {
620 wchar_t buf2[256];
621 buf2[0] = 0;
622 HRESULT res = ctxm->GetCommandString(i, id | GCS_UNICODE,
623 NULL, (char *)buf2, ARRAY_SIZE(buf2) - 1);
624 if (res != S_OK)
625 {
626 PrintHex(s2, res);
627 s2.Add_Space();
628 }
629 s2 += buf2;
630 }
631
632 s += s1;
633 if (s2.Compare(s1) != 0)
634 {
635 s += " Unicode: ";
636 s += s2;
637 }
638}
639
640
641static void PrintAllContextItems(IContextMenu *ctxm, unsigned num)
642{
643 for (unsigned i = 0; i < num; i++)
644 {
645 UString s;
646 s.Add_UInt32(i);
647 s += ": ";
648
649 /*
650 UString valid;
651 {
652 char name[256];
653 HRESULT res = ctxm->GetCommandString(i, GCS_VALIDATEA,
654 NULL, name, ARRAY_SIZE(name) - 1);
655
656 if (res == S_OK)
657 {
658 // valid = "valid";
659 }
660 else if (res == S_FALSE)
661 valid = "non-valid";
662 else
663 PrintHex(valid, res);
664 }
665 s += valid;
666 */
667
668 PrintContextStr(s, ctxm, i, GCS_VALIDATEA, "valid");
669 PrintContextStr(s, ctxm, i, GCS_VERBA, "v");
670 PrintContextStr(s, ctxm, i, GCS_HELPTEXTA, "h");
671 OutputDebugStringW(s);
672 }
673}
674#endif
675
676void CPanel::CreateSystemMenu(HMENU menuSpec,
677 const CRecordVector<UInt32> &operatedIndices,
678 CMyComPtr<IContextMenu> &systemContextMenu)
679{
680 systemContextMenu.Release();
681
682 CreateShellContextMenu(operatedIndices, systemContextMenu);
683
684 if (!systemContextMenu)
685 return;
686
687 /*
688 // Set up a CMINVOKECOMMANDINFO structure.
689 CMINVOKECOMMANDINFO ci;
690 ZeroMemory(&ci, sizeof(ci));
691 ci.cbSize = sizeof(CMINVOKECOMMANDINFO);
692 ci.hwnd = GetParent();
693 */
694
695 /*
696 if (Sender == GoBtn)
697 {
698 // Verbs that can be used are cut, paste,
699 // properties, delete, and so on.
700 String action;
701 if (CutRb->Checked)
702 action = "cut";
703 else if (CopyRb->Checked)
704 action = "copy";
705 else if (DeleteRb->Checked)
706 action = "delete";
707 else if (PropertiesRb->Checked)
708 action = "properties";
709
710 ci.lpVerb = action.c_str();
711 result = cm->InvokeCommand(&ci);
712 if (result)
713 ShowMessage(
714 "Error copying file to clipboard.");
715
716 }
717 else
718 */
719 {
720 // HMENU hMenu = CreatePopupMenu();
721 CMenu popupMenu;
722 CMenuDestroyer menuDestroyer(popupMenu);
723 if (!popupMenu.CreatePopup())
724 throw 210503;
725
726 HMENU hMenu = popupMenu;
727
728 DWORD Flags = CMF_EXPLORE;
729 // Optionally the shell will show the extended
730 // context menu on some operating systems when
731 // the shift key is held down at the time the
732 // context menu is invoked. The following is
733 // commented out but you can uncommnent this
734 // line to show the extended context menu.
735 // Flags |= 0x00000080;
736 HRESULT res = systemContextMenu->QueryContextMenu(hMenu, 0, kSystemStartMenuID, 0x7FFF, Flags);
737
738 if (SUCCEEDED(res))
739 {
740 #ifdef SHOW_DEBUG_FM_CTX_MENU
741 PrintAllContextItems(systemContextMenu, (unsigned)res);
742 #endif
743
744 CMenu menu;
745 menu.Attach(menuSpec);
746 CMenuItem menuItem;
747 menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
748 menuItem.fType = MFT_STRING;
749 menuItem.hSubMenu = popupMenu.Detach();
750 menuDestroyer.Disable();
751 LangString(IDS_SYSTEM, menuItem.StringValue);
752 menu.InsertItem(0, true, menuItem);
753 }
754 /*
755 if (Cmd < 100 && Cmd != 0)
756 {
757 ci.lpVerb = MAKEINTRESOURCE(Cmd - 1);
758 ci.lpParameters = "";
759 ci.lpDirectory = "";
760 ci.nShow = SW_SHOWNORMAL;
761 cm->InvokeCommand(&ci);
762 }
763 // If Cmd is > 100 then it's one of our
764 // inserted menu items.
765 else
766 // Find the menu item.
767 for (int i = 0; i < popupMenu1->Items->Count; i++)
768 {
769 TMenuItem* menu = popupMenu1->Items->Items[i];
770 // Call its OnClick handler.
771 if (menu->Command == Cmd - 100)
772 menu->OnClick(this);
773 }
774 // Release the memory allocated for the menu.
775 DestroyMenu(hMenu);
776 */
777 }
778}
779
780void CPanel::CreateFileMenu(HMENU menuSpec)
781{
782 CreateFileMenu(menuSpec, _sevenZipContextMenu, _systemContextMenu, true);
783}
784
785void CPanel::CreateSevenZipMenu(HMENU menuSpec,
786 const CRecordVector<UInt32> &operatedIndices,
787 CMyComPtr<IContextMenu> &sevenZipContextMenu)
788{
789 sevenZipContextMenu.Release();
790
791 CMenu menu;
792 menu.Attach(menuSpec);
793 // CMenuDestroyer menuDestroyer(menu);
794 // menu.CreatePopup();
795
796 CZipContextMenu *contextMenuSpec = new CZipContextMenu;
797 CMyComPtr<IContextMenu> contextMenu = contextMenuSpec;
798 // if (contextMenu.CoCreateInstance(CLSID_CZipContextMenu, IID_IContextMenu) == S_OK)
799 {
800 /*
801 CMyComPtr<IInitContextMenu> initContextMenu;
802 if (contextMenu.QueryInterface(IID_IInitContextMenu, &initContextMenu) != S_OK)
803 return;
804 */
805 UString currentFolderUnicode = GetFsPath();
806 UStringVector names;
807 unsigned i;
808 for (i = 0; i < operatedIndices.Size(); i++)
809 names.Add(currentFolderUnicode + GetItemRelPath2(operatedIndices[i]));
810 CRecordVector<const wchar_t *> namePointers;
811 for (i = 0; i < operatedIndices.Size(); i++)
812 namePointers.Add(names[i]);
813
814 // NFile::NDirectory::MySetCurrentDirectory(currentFolderUnicode);
815 if (contextMenuSpec->InitContextMenu(currentFolderUnicode, &namePointers.Front(),
816 operatedIndices.Size()) == S_OK)
817 {
818 HRESULT res = contextMenu->QueryContextMenu(menu, 0, kSevenZipStartMenuID,
819 kSystemStartMenuID - 1, 0);
820 bool sevenZipMenuCreated = SUCCEEDED(res);
821 if (sevenZipMenuCreated)
822 {
823 // if (res != 0)
824 {
825 // some "non-good" implementation of QueryContextMenu() could add some items to menu, but it return 0.
826 // so we still allow these items
827 sevenZipContextMenu = contextMenu;
828 #ifdef SHOW_DEBUG_FM_CTX_MENU
829 PrintAllContextItems(contextMenu, (unsigned)res);
830 #endif
831 }
832 }
833 else
834 {
835 // MessageBox_Error_HRESULT_Caption(res, L"QueryContextMenu");
836 }
837
838 // int code = HRESULT_CODE(res);
839 // int nextItemID = code;
840 }
841 }
842}
843
844static bool IsReadOnlyFolder(IFolderFolder *folder)
845{
846 if (!folder)
847 return false;
848
849 bool res = false;
850 {
851 NCOM::CPropVariant prop;
852 if (folder->GetFolderProperty(kpidReadOnly, &prop) == S_OK)
853 if (prop.vt == VT_BOOL)
854 res = VARIANT_BOOLToBool(prop.boolVal);
855 }
856 return res;
857}
858
859bool CPanel::IsThereReadOnlyFolder() const
860{
861 if (!_folderOperations)
862 return true;
863 if (IsReadOnlyFolder(_folder))
864 return true;
865 FOR_VECTOR (i, _parentFolders)
866 {
867 if (IsReadOnlyFolder(_parentFolders[i].ParentFolder))
868 return true;
869 }
870 return false;
871}
872
873bool CPanel::CheckBeforeUpdate(UINT resourceID)
874{
875 if (!_folderOperations)
876 {
877 MessageBox_Error_UnsupportOperation();
878 // resourceID = resourceID;
879 // MessageBoxErrorForUpdate(E_NOINTERFACE, resourceID);
880 return false;
881 }
882
883 for (int i = (int)_parentFolders.Size(); i >= 0; i--)
884 {
885 IFolderFolder *folder;
886 if (i == (int)_parentFolders.Size())
887 folder = _folder;
888 else
889 folder = _parentFolders[i].ParentFolder;
890
891 if (!IsReadOnlyFolder(folder))
892 continue;
893
894 UString s;
895 AddLangString(s, resourceID);
896 s.Add_LF();
897 AddLangString(s, IDS_OPERATION_IS_NOT_SUPPORTED);
898 s.Add_LF();
899 if (i == 0)
900 s += GetFolderPath(folder);
901 else
902 s += _parentFolders[i - 1].VirtualPath;
903 s.Add_LF();
904 AddLangString(s, IDS_PROP_READ_ONLY);
905 MessageBox_Error(s);
906 return false;
907 }
908
909 return true;
910}
911
912void CPanel::CreateFileMenu(HMENU menuSpec,
913 CMyComPtr<IContextMenu> &sevenZipContextMenu,
914 CMyComPtr<IContextMenu> &systemContextMenu,
915 bool programMenu)
916{
917 sevenZipContextMenu.Release();
918 systemContextMenu.Release();
919
920 CRecordVector<UInt32> operatedIndices;
921 GetOperatedItemIndices(operatedIndices);
922
923 CMenu menu;
924 menu.Attach(menuSpec);
925
926 if (!IsArcFolder())
927 {
928 CreateSevenZipMenu(menu, operatedIndices, sevenZipContextMenu);
929 // CreateSystemMenu is very slow if you call it inside ZIP archive with big number of files
930 // Windows probably can parse items inside ZIP archive.
931 if (g_App.ShowSystemMenu)
932 CreateSystemMenu(menu, operatedIndices, systemContextMenu);
933 }
934
935 /*
936 if (menu.GetItemCount() > 0)
937 menu.AppendItem(MF_SEPARATOR, 0, (LPCTSTR)0);
938 */
939
940 unsigned i;
941 for (i = 0; i < operatedIndices.Size(); i++)
942 if (IsItem_Folder(operatedIndices[i]))
943 break;
944 bool allAreFiles = (i == operatedIndices.Size());
945
946 CFileMenu fm;
947
948 fm.readOnly = IsThereReadOnlyFolder();
949 fm.isHashFolder = IsHashFolder();
950 fm.isFsFolder = Is_IO_FS_Folder();
951 fm.programMenu = programMenu;
952 fm.allAreFiles = allAreFiles;
953 fm.numItems = operatedIndices.Size();
954
955 fm.isAltStreamsSupported = false;
956
957 if (fm.numItems == 1)
958 fm.FilePath = us2fs(GetItemFullPath(operatedIndices[0]));
959
960 if (_folderAltStreams)
961 {
962 if (operatedIndices.Size() <= 1)
963 {
964 Int32 realIndex = -1;
965 if (operatedIndices.Size() == 1)
966 realIndex = operatedIndices[0];
967 Int32 val = 0;
968 if (_folderAltStreams->AreAltStreamsSupported(realIndex, &val) == S_OK)
969 fm.isAltStreamsSupported = IntToBool(val);
970 }
971 }
972 else
973 {
974 if (fm.numItems == 0)
975 fm.isAltStreamsSupported = IsFSFolder();
976 else
977 fm.isAltStreamsSupported = IsFolder_with_FsItems();
978 }
979
980 fm.Load(menu, menu.GetItemCount());
981}
982
983bool CPanel::InvokePluginCommand(unsigned id)
984{
985 return InvokePluginCommand(id, _sevenZipContextMenu, _systemContextMenu);
986}
987
988#if defined(_MSC_VER) && !defined(UNDER_CE)
989#define use_CMINVOKECOMMANDINFOEX
990#endif
991
992bool CPanel::InvokePluginCommand(unsigned id,
993 IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu)
994{
995 UInt32 offset;
996 const bool isSystemMenu = (id >= kSystemStartMenuID);
997 if (isSystemMenu)
998 {
999 if (!systemContextMenu)
1000 return false;
1001 offset = id - kSystemStartMenuID;
1002 }
1003 else
1004 {
1005 if (!sevenZipContextMenu)
1006 return false;
1007 offset = id - kSevenZipStartMenuID;
1008 }
1009
1010 #ifdef use_CMINVOKECOMMANDINFOEX
1011 CMINVOKECOMMANDINFOEX
1012 #else
1013 CMINVOKECOMMANDINFO
1014 #endif
1015 commandInfo;
1016
1017 memset(&commandInfo, 0, sizeof(commandInfo));
1018 commandInfo.cbSize = sizeof(commandInfo);
1019
1020 commandInfo.fMask = 0
1021 #ifdef use_CMINVOKECOMMANDINFOEX
1022 | CMIC_MASK_UNICODE
1023 #endif
1024 ;
1025
1026 commandInfo.hwnd = GetParent();
1027 commandInfo.lpVerb = (LPCSTR)(MAKEINTRESOURCE(offset));
1028 commandInfo.lpParameters = NULL;
1029 // 19.01: fixed CSysString to AString
1030 // MSDN suggest to send NULL: lpDirectory: This member is always NULL for menu items inserted by a Shell extension.
1031 const AString currentFolderA (GetAnsiString(_currentFolderPrefix));
1032 commandInfo.lpDirectory = (LPCSTR)(currentFolderA);
1033 commandInfo.nShow = SW_SHOW;
1034
1035 #ifdef use_CMINVOKECOMMANDINFOEX
1036
1037 commandInfo.lpParametersW = NULL;
1038 commandInfo.lpTitle = "";
1039
1040 /*
1041 system ContextMenu handler supports ContextMenu subhandlers.
1042 so InvokeCommand() converts (command_offset) from global number to subhandler number.
1043 XP-64 / win10:
1044 system ContextMenu converts (command_offset) in lpVerb only,
1045 and it keeps lpVerbW unchanged.
1046 also explorer.exe sends 0 in lpVerbW.
1047 We try to keep compatibility with Windows Explorer here.
1048 */
1049 commandInfo.lpVerbW = NULL;
1050
1051 const UString currentFolderUnicode = _currentFolderPrefix;
1052 commandInfo.lpDirectoryW = currentFolderUnicode;
1053 commandInfo.lpTitleW = L"";
1054 // commandInfo.ptInvoke.x = xPos;
1055 // commandInfo.ptInvoke.y = yPos;
1056 commandInfo.ptInvoke.x = 0;
1057 commandInfo.ptInvoke.y = 0;
1058
1059 #endif
1060
1061 HRESULT result;
1062 if (isSystemMenu)
1063 result = systemContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));
1064 else
1065 result = sevenZipContextMenu->InvokeCommand(LPCMINVOKECOMMANDINFO(&commandInfo));
1066 if (result == NOERROR)
1067 {
1068 KillSelection();
1069 return true;
1070 }
1071 else
1072 MessageBox_Error_HRESULT_Caption(result, L"InvokeCommand");
1073 return false;
1074}
1075
1076bool CPanel::OnContextMenu(HANDLE windowHandle, int xPos, int yPos)
1077{
1078 if (::GetParent((HWND)windowHandle) == _listView)
1079 {
1080 ShowColumnsContextMenu(xPos, yPos);
1081 return true;
1082 }
1083
1084 if (windowHandle != _listView)
1085 return false;
1086 /*
1087 POINT point;
1088 point.x = xPos;
1089 point.y = yPos;
1090 if (!_listView.ScreenToClient(&point))
1091 return false;
1092
1093 LVHITTESTINFO info;
1094 info.pt = point;
1095 int index = _listView.HitTest(&info);
1096 */
1097
1098 CRecordVector<UInt32> operatedIndices;
1099 GetOperatedItemIndices(operatedIndices);
1100
1101 // negative x,y are possible for multi-screen modes.
1102 // x=-1 && y=-1 for keyboard call (SHIFT+F10 and others).
1103 if (xPos == -1 && yPos == -1)
1104 {
1105 if (operatedIndices.Size() == 0)
1106 {
1107 xPos = 0;
1108 yPos = 0;
1109 }
1110 else
1111 {
1112 int itemIndex = _listView.GetNextItem(-1, LVNI_FOCUSED);
1113 if (itemIndex == -1)
1114 return false;
1115 RECT rect;
1116 if (!_listView.GetItemRect(itemIndex, &rect, LVIR_ICON))
1117 return false;
1118 xPos = (rect.left + rect.right) / 2;
1119 yPos = (rect.top + rect.bottom) / 2;
1120 }
1121 POINT point = {xPos, yPos};
1122 _listView.ClientToScreen(&point);
1123 xPos = point.x;
1124 yPos = point.y;
1125 }
1126
1127 CMenu menu;
1128 CMenuDestroyer menuDestroyer(menu);
1129 menu.CreatePopup();
1130
1131 CMyComPtr<IContextMenu> sevenZipContextMenu;
1132 CMyComPtr<IContextMenu> systemContextMenu;
1133 CreateFileMenu(menu, sevenZipContextMenu, systemContextMenu, false);
1134
1135 unsigned id = menu.Track(TPM_LEFTALIGN
1136 #ifndef UNDER_CE
1137 | TPM_RIGHTBUTTON
1138 #endif
1139 | TPM_RETURNCMD | TPM_NONOTIFY,
1140 xPos, yPos, _listView);
1141
1142 if (id == 0)
1143 return true;
1144
1145 if (id >= kMenuCmdID_Plugin_Start)
1146 {
1147 InvokePluginCommand(id, sevenZipContextMenu, systemContextMenu);
1148 return true;
1149 }
1150 if (ExecuteFileCommand(id))
1151 return true;
1152 return true;
1153}
diff --git a/CPP/7zip/UI/FileManager/PanelOperations.cpp b/CPP/7zip/UI/FileManager/PanelOperations.cpp
new file mode 100644
index 0000000..e34e74f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelOperations.cpp
@@ -0,0 +1,526 @@
1// PanelOperations.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/DynamicBuffer.h"
6#include "../../../Common/StringConvert.h"
7#include "../../../Common/Wildcard.h"
8
9#include "../../../Windows/COM.h"
10#include "../../../Windows/FileName.h"
11#include "../../../Windows/PropVariant.h"
12
13#include "ComboDialog.h"
14
15#include "FSFolder.h"
16#include "FormatUtils.h"
17#include "LangUtils.h"
18#include "Panel.h"
19#include "UpdateCallback100.h"
20
21#include "resource.h"
22
23using namespace NWindows;
24using namespace NFile;
25using namespace NName;
26
27#ifndef _UNICODE
28extern bool g_IsNT;
29#endif
30
31enum EFolderOpType
32{
33 FOLDER_TYPE_CREATE_FOLDER = 0,
34 FOLDER_TYPE_DELETE = 1,
35 FOLDER_TYPE_RENAME = 2
36};
37
38class CThreadFolderOperations: public CProgressThreadVirt
39{
40 HRESULT ProcessVirt();
41public:
42 EFolderOpType OpType;
43 UString Name;
44 UInt32 Index;
45 CRecordVector<UInt32> Indices;
46
47 CMyComPtr<IFolderOperations> FolderOperations;
48 CMyComPtr<IProgress> UpdateCallback;
49 CUpdateCallback100Imp *UpdateCallbackSpec;
50
51 CThreadFolderOperations(EFolderOpType opType): OpType(opType) {}
52 HRESULT DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError);
53};
54
55HRESULT CThreadFolderOperations::ProcessVirt()
56{
57 NCOM::CComInitializer comInitializer;
58 switch (OpType)
59 {
60 case FOLDER_TYPE_CREATE_FOLDER:
61 return FolderOperations->CreateFolder(Name, UpdateCallback);
62 case FOLDER_TYPE_DELETE:
63 return FolderOperations->Delete(&Indices.Front(), Indices.Size(), UpdateCallback);
64 case FOLDER_TYPE_RENAME:
65 return FolderOperations->Rename(Index, Name, UpdateCallback);
66 default:
67 return E_FAIL;
68 }
69}
70
71
72HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError)
73{
74 UpdateCallbackSpec = new CUpdateCallback100Imp;
75 UpdateCallback = UpdateCallbackSpec;
76 UpdateCallbackSpec->ProgressDialog = this;
77
78 WaitMode = true;
79 Sync.FinalMessage.ErrorMessage.Title = titleError;
80
81 UpdateCallbackSpec->Init();
82
83 if (panel._parentFolders.Size() > 0)
84 {
85 const CFolderLink &fl = panel._parentFolders.Back();
86 UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
87 UpdateCallbackSpec->Password = fl.Password;
88 }
89
90 MainWindow = panel._mainWindow; // panel.GetParent()
91 MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
92 MainAddTitle = progressTitle + L' ';
93
94 RINOK(Create(progressTitle, MainWindow));
95 return Result;
96}
97
98#ifndef _UNICODE
99typedef int (WINAPI * SHFileOperationWP)(LPSHFILEOPSTRUCTW lpFileOp);
100#endif
101
102/*
103void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID)
104{
105 if (errorCode == E_NOINTERFACE)
106 MessageBox_Error_UnsupportOperation();
107 else
108 MessageBox_Error_HRESULT_Caption(errorCode, LangString(resourceID));
109}
110*/
111
112void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
113{
114 CDisableTimerProcessing disableTimerProcessing(*this);
115 CRecordVector<UInt32> indices;
116 GetOperatedItemIndices(indices);
117 if (indices.IsEmpty())
118 return;
119 CSelectedState state;
120 SaveSelectedState(state);
121
122 #ifndef UNDER_CE
123 // WM6 / SHFileOperationW doesn't ask user! So we use internal delete
124 if (IsFSFolder() && toRecycleBin)
125 {
126 bool useInternalDelete = false;
127 #ifndef _UNICODE
128 if (!g_IsNT)
129 {
130 CDynamicBuffer<CHAR> buffer;
131 FOR_VECTOR (i, indices)
132 {
133 const AString path (GetSystemString(GetItemFullPath(indices[i])));
134 buffer.AddData(path, path.Len() + 1);
135 }
136 *buffer.GetCurPtrAndGrow(1) = 0;
137 SHFILEOPSTRUCTA fo;
138 fo.hwnd = GetParent();
139 fo.wFunc = FO_DELETE;
140 fo.pFrom = (const CHAR *)buffer;
141 fo.pTo = 0;
142 fo.fFlags = 0;
143 if (toRecycleBin)
144 fo.fFlags |= FOF_ALLOWUNDO;
145 // fo.fFlags |= FOF_NOCONFIRMATION;
146 // fo.fFlags |= FOF_NOERRORUI;
147 // fo.fFlags |= FOF_SILENT;
148 // fo.fFlags |= FOF_WANTNUKEWARNING;
149 fo.fAnyOperationsAborted = FALSE;
150 fo.hNameMappings = 0;
151 fo.lpszProgressTitle = 0;
152 /* int res = */ ::SHFileOperationA(&fo);
153 }
154 else
155 #endif
156 {
157 CDynamicBuffer<WCHAR> buffer;
158 unsigned maxLen = 0;
159 const UString prefix = GetFsPath();
160 FOR_VECTOR (i, indices)
161 {
162 // L"\\\\?\\") doesn't work here.
163 const UString path = prefix + GetItemRelPath2(indices[i]);
164 if (path.Len() > maxLen)
165 maxLen = path.Len();
166 buffer.AddData(path, path.Len() + 1);
167 }
168 *buffer.GetCurPtrAndGrow(1) = 0;
169 if (maxLen >= MAX_PATH)
170 {
171 if (toRecycleBin)
172 {
173 MessageBox_Error_LangID(IDS_ERROR_LONG_PATH_TO_RECYCLE);
174 return;
175 }
176 useInternalDelete = true;
177 }
178 else
179 {
180 SHFILEOPSTRUCTW fo;
181 fo.hwnd = GetParent();
182 fo.wFunc = FO_DELETE;
183 fo.pFrom = (const WCHAR *)buffer;
184 fo.pTo = 0;
185 fo.fFlags = 0;
186 if (toRecycleBin)
187 fo.fFlags |= FOF_ALLOWUNDO;
188 fo.fAnyOperationsAborted = FALSE;
189 fo.hNameMappings = 0;
190 fo.lpszProgressTitle = 0;
191 // int res;
192 #ifdef _UNICODE
193 /* res = */ ::SHFileOperationW(&fo);
194 #else
195 SHFileOperationWP shFileOperationW = (SHFileOperationWP)
196 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHFileOperationW");
197 if (shFileOperationW == 0)
198 return;
199 /* res = */ shFileOperationW(&fo);
200 #endif
201 }
202 }
203 /*
204 if (fo.fAnyOperationsAborted)
205 MessageBox_Error_HRESULT_Caption(result, LangString(IDS_ERROR_DELETING));
206 */
207 if (!useInternalDelete)
208 {
209 RefreshListCtrl(state);
210 return;
211 }
212 }
213 #endif
214
215 // DeleteItemsInternal
216
217 if (!CheckBeforeUpdate(IDS_ERROR_DELETING))
218 return;
219
220 UInt32 titleID, messageID;
221 UString messageParam;
222 if (indices.Size() == 1)
223 {
224 int index = indices[0];
225 messageParam = GetItemRelPath2(index);
226 if (IsItem_Folder(index))
227 {
228 titleID = IDS_CONFIRM_FOLDER_DELETE;
229 messageID = IDS_WANT_TO_DELETE_FOLDER;
230 }
231 else
232 {
233 titleID = IDS_CONFIRM_FILE_DELETE;
234 messageID = IDS_WANT_TO_DELETE_FILE;
235 }
236 }
237 else
238 {
239 titleID = IDS_CONFIRM_ITEMS_DELETE;
240 messageID = IDS_WANT_TO_DELETE_ITEMS;
241 messageParam = NumberToString(indices.Size());
242 }
243 if (::MessageBoxW(GetParent(), MyFormatNew(messageID, messageParam), LangString(titleID), MB_OKCANCEL | MB_ICONQUESTION) != IDOK)
244 return;
245
246 CDisableNotify disableNotify(*this);
247 {
248 CThreadFolderOperations op(FOLDER_TYPE_DELETE);
249 op.FolderOperations = _folderOperations;
250 op.Indices = indices;
251 op.DoOperation(*this,
252 LangString(IDS_DELETING),
253 LangString(IDS_ERROR_DELETING));
254 }
255 RefreshTitleAlways();
256 RefreshListCtrl(state);
257}
258
259BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh)
260{
261 int realIndex = GetRealIndex(lpnmh->item);
262 if (realIndex == kParentIndex)
263 return TRUE;
264 if (IsThereReadOnlyFolder())
265 return TRUE;
266 return FALSE;
267}
268
269static bool IsCorrectFsName(const UString &name)
270{
271 const UString lastPart = name.Ptr((unsigned)(name.ReverseFind_PathSepar() + 1));
272 return
273 lastPart != L"." &&
274 lastPart != L"..";
275}
276
277bool CorrectFsPath(const UString &relBase, const UString &path, UString &result);
278
279bool CPanel::CorrectFsPath(const UString &path2, UString &result)
280{
281 return ::CorrectFsPath(GetFsPath(), path2, result);
282}
283
284BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
285{
286 if (lpnmh->item.pszText == NULL)
287 return FALSE;
288 CDisableTimerProcessing disableTimerProcessing2(*this);
289
290 if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
291 return FALSE;
292
293 UString newName = lpnmh->item.pszText;
294 if (!IsCorrectFsName(newName))
295 {
296 MessageBox_Error_HRESULT(E_INVALIDARG);
297 return FALSE;
298 }
299
300 if (IsFSFolder())
301 {
302 UString correctName;
303 if (!CorrectFsPath(newName, correctName))
304 {
305 MessageBox_Error_HRESULT(E_INVALIDARG);
306 return FALSE;
307 }
308 newName = correctName;
309 }
310
311 SaveSelectedState(_selectedState);
312
313 int realIndex = GetRealIndex(lpnmh->item);
314 if (realIndex == kParentIndex)
315 return FALSE;
316 const UString prefix = GetItemPrefix(realIndex);
317
318
319 CDisableNotify disableNotify(*this);
320 {
321 CThreadFolderOperations op(FOLDER_TYPE_RENAME);
322 op.FolderOperations = _folderOperations;
323 op.Index = realIndex;
324 op.Name = newName;
325 /* HRESULTres = */ op.DoOperation(*this,
326 LangString(IDS_RENAMING),
327 LangString(IDS_ERROR_RENAMING));
328 // fixed in 9.26: we refresh list even after errors
329 // (it's more safe, since error can be at different stages, so list can be incorrect).
330 /*
331 if (res != S_OK)
332 return FALSE;
333 */
334 }
335
336 // Can't use RefreshListCtrl here.
337 // RefreshListCtrlSaveFocused();
338 _selectedState.FocusedName = prefix + newName;
339 _selectedState.FocusedName_Defined = true;
340 _selectedState.SelectFocused = true;
341
342 // We need clear all items to disable GetText before Reload:
343 // number of items can change.
344 // DeleteListItems();
345 // But seems it can still call GetText (maybe for current item)
346 // so we can't delete items.
347
348 _dontShowMode = true;
349
350 PostMsg(kReLoadMessage);
351 return TRUE;
352}
353
354bool Dlg_CreateFolder(HWND wnd, UString &destName);
355
356void CPanel::CreateFolder()
357{
358 if (IsHashFolder())
359 return;
360
361 if (!CheckBeforeUpdate(IDS_CREATE_FOLDER_ERROR))
362 return;
363
364 CDisableTimerProcessing disableTimerProcessing2(*this);
365 CSelectedState state;
366 SaveSelectedState(state);
367
368 UString newName;
369 if (!Dlg_CreateFolder(GetParent(), newName))
370 return;
371
372 if (!IsCorrectFsName(newName))
373 {
374 MessageBox_Error_HRESULT(E_INVALIDARG);
375 return;
376 }
377
378 if (IsFSFolder())
379 {
380 UString correctName;
381 if (!CorrectFsPath(newName, correctName))
382 {
383 MessageBox_Error_HRESULT(E_INVALIDARG);
384 return;
385 }
386 newName = correctName;
387 }
388
389 HRESULT res;
390 CDisableNotify disableNotify(*this);
391 {
392 CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER);
393 op.FolderOperations = _folderOperations;
394 op.Name = newName;
395 res = op.DoOperation(*this,
396 LangString(IDS_CREATE_FOLDER),
397 LangString(IDS_CREATE_FOLDER_ERROR));
398 /*
399 // fixed for 9.26: we must refresh always
400 if (res != S_OK)
401 return;
402 */
403 }
404 if (res == S_OK)
405 {
406 int pos = newName.Find(WCHAR_PATH_SEPARATOR);
407 if (pos >= 0)
408 newName.DeleteFrom((unsigned)(pos));
409 if (!_mySelectMode)
410 state.SelectedNames.Clear();
411 state.FocusedName = newName;
412 state.FocusedName_Defined = true;
413 state.SelectFocused = true;
414 }
415 RefreshTitleAlways();
416 RefreshListCtrl(state);
417}
418
419void CPanel::CreateFile()
420{
421 if (IsHashFolder())
422 return;
423
424 if (!CheckBeforeUpdate(IDS_CREATE_FILE_ERROR))
425 return;
426
427 CDisableTimerProcessing disableTimerProcessing2(*this);
428 CSelectedState state;
429 SaveSelectedState(state);
430 CComboDialog dlg;
431 LangString(IDS_CREATE_FILE, dlg.Title);
432 LangString(IDS_CREATE_FILE_NAME, dlg.Static);
433 LangString(IDS_CREATE_FILE_DEFAULT_NAME, dlg.Value);
434
435 if (dlg.Create(GetParent()) != IDOK)
436 return;
437
438 CDisableNotify disableNotify(*this);
439
440 UString newName = dlg.Value;
441
442 if (IsFSFolder())
443 {
444 UString correctName;
445 if (!CorrectFsPath(newName, correctName))
446 {
447 MessageBox_Error_HRESULT(E_INVALIDARG);
448 return;
449 }
450 newName = correctName;
451 }
452
453 HRESULT result = _folderOperations->CreateFile(newName, 0);
454 if (result != S_OK)
455 {
456 MessageBox_Error_HRESULT_Caption(result, LangString(IDS_CREATE_FILE_ERROR));
457 // MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR);
458 return;
459 }
460 int pos = newName.Find(WCHAR_PATH_SEPARATOR);
461 if (pos >= 0)
462 newName.DeleteFrom((unsigned)pos);
463 if (!_mySelectMode)
464 state.SelectedNames.Clear();
465 state.FocusedName = newName;
466 state.FocusedName_Defined = true;
467 state.SelectFocused = true;
468 RefreshListCtrl(state);
469}
470
471void CPanel::RenameFile()
472{
473 if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
474 return;
475 int index = _listView.GetFocusedItem();
476 if (index >= 0)
477 _listView.EditLabel(index);
478}
479
480void CPanel::ChangeComment()
481{
482 if (IsHashFolder())
483 return;
484 if (!CheckBeforeUpdate(IDS_COMMENT))
485 return;
486 CDisableTimerProcessing disableTimerProcessing2(*this);
487 int index = _listView.GetFocusedItem();
488 if (index < 0)
489 return;
490 int realIndex = GetRealItemIndex(index);
491 if (realIndex == kParentIndex)
492 return;
493 CSelectedState state;
494 SaveSelectedState(state);
495 UString comment;
496 {
497 NCOM::CPropVariant propVariant;
498 if (_folder->GetProperty(realIndex, kpidComment, &propVariant) != S_OK)
499 return;
500 if (propVariant.vt == VT_BSTR)
501 comment = propVariant.bstrVal;
502 else if (propVariant.vt != VT_EMPTY)
503 return;
504 }
505 UString name = GetItemRelPath2(realIndex);
506 CComboDialog dlg;
507 dlg.Title = name;
508 dlg.Title += " : ";
509 AddLangString(dlg.Title, IDS_COMMENT);
510 dlg.Value = comment;
511 LangString(IDS_COMMENT2, dlg.Static);
512 if (dlg.Create(GetParent()) != IDOK)
513 return;
514 NCOM::CPropVariant propVariant (dlg.Value);
515
516 CDisableNotify disableNotify(*this);
517 HRESULT result = _folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL);
518 if (result != S_OK)
519 {
520 if (result == E_NOINTERFACE)
521 MessageBox_Error_UnsupportOperation();
522 else
523 MessageBox_Error_HRESULT_Caption(result, L"Set Comment Error");
524 }
525 RefreshListCtrl(state);
526}
diff --git a/CPP/7zip/UI/FileManager/PanelSelect.cpp b/CPP/7zip/UI/FileManager/PanelSelect.cpp
new file mode 100644
index 0000000..eab9e1a
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelSelect.cpp
@@ -0,0 +1,315 @@
1// PanelSelect.cpp
2
3#include "StdAfx.h"
4
5#include "resource.h"
6
7#include "../../../Common/StringConvert.h"
8#include "../../../Common/Wildcard.h"
9
10#include "ComboDialog.h"
11#include "LangUtils.h"
12#include "Panel.h"
13
14void CPanel::OnShiftSelectMessage()
15{
16 if (!_mySelectMode)
17 return;
18 int focusedItem = _listView.GetFocusedItem();
19 if (focusedItem < 0)
20 return;
21 if (!_selectionIsDefined)
22 return;
23 int startItem = MyMin(focusedItem, _prevFocusedItem);
24 int finishItem = MyMax(focusedItem, _prevFocusedItem);
25
26 int numItems = _listView.GetItemCount();
27 for (int i = 0; i < numItems; i++)
28 {
29 int realIndex = GetRealItemIndex(i);
30 if (realIndex == kParentIndex)
31 continue;
32 if (i >= startItem && i <= finishItem)
33 if (_selectedStatusVector[realIndex] != _selectMark)
34 {
35 _selectedStatusVector[realIndex] = _selectMark;
36 _listView.RedrawItem(i);
37 }
38 }
39
40 _prevFocusedItem = focusedItem;
41}
42
43void CPanel::OnArrowWithShift()
44{
45 if (!_mySelectMode)
46 return;
47 int focusedItem = _listView.GetFocusedItem();
48 if (focusedItem < 0)
49 return;
50 int realIndex = GetRealItemIndex(focusedItem);
51
52 if (_selectionIsDefined)
53 {
54 if (realIndex != kParentIndex)
55 _selectedStatusVector[realIndex] = _selectMark;
56 }
57 else
58 {
59 if (realIndex == kParentIndex)
60 {
61 _selectionIsDefined = true;
62 _selectMark = true;
63 }
64 else
65 {
66 _selectionIsDefined = true;
67 _selectMark = !_selectedStatusVector[realIndex];
68 _selectedStatusVector[realIndex] = _selectMark;
69 }
70 }
71
72 _prevFocusedItem = focusedItem;
73 PostMsg(kShiftSelectMessage);
74 _listView.RedrawItem(focusedItem);
75}
76
77void CPanel::OnInsert()
78{
79 /*
80 const int kState = CDIS_MARKED; // LVIS_DROPHILITED;
81 UINT state = (_listView.GetItemState(focusedItem, LVIS_CUT) == 0) ?
82 LVIS_CUT : 0;
83 _listView.SetItemState(focusedItem, state, LVIS_CUT);
84 // _listView.SetItemState_Selected(focusedItem);
85 */
86
87 int focusedItem = _listView.GetFocusedItem();
88 if (focusedItem < 0)
89 return;
90
91 int realIndex = GetRealItemIndex(focusedItem);
92 if (realIndex != kParentIndex)
93 {
94 bool isSelected = !_selectedStatusVector[realIndex];
95 _selectedStatusVector[realIndex] = isSelected;
96 if (!_mySelectMode)
97 _listView.SetItemState_Selected(focusedItem, isSelected);
98 _listView.RedrawItem(focusedItem);
99 }
100
101 int nextIndex = focusedItem + 1;
102 if (nextIndex < _listView.GetItemCount())
103 {
104 _listView.SetItemState_FocusedSelected(nextIndex);
105 _listView.EnsureVisible(nextIndex, false);
106 }
107}
108
109/*
110void CPanel::OnUpWithShift()
111{
112 int focusedItem = _listView.GetFocusedItem();
113 if (focusedItem < 0)
114 return;
115 int index = GetRealItemIndex(focusedItem);
116 if (index == kParentIndex)
117 return;
118 _selectedStatusVector[index] = !_selectedStatusVector[index];
119 _listView.RedrawItem(index);
120}
121
122void CPanel::OnDownWithShift()
123{
124 int focusedItem = _listView.GetFocusedItem();
125 if (focusedItem < 0)
126 return;
127 int index = GetRealItemIndex(focusedItem);
128 if (index == kParentIndex)
129 return;
130 _selectedStatusVector[index] = !_selectedStatusVector[index];
131 _listView.RedrawItem(index);
132}
133*/
134
135void CPanel::UpdateSelection()
136{
137 if (!_mySelectMode)
138 {
139 bool enableTemp = _enableItemChangeNotify;
140 _enableItemChangeNotify = false;
141 int numItems = _listView.GetItemCount();
142 for (int i = 0; i < numItems; i++)
143 {
144 int realIndex = GetRealItemIndex(i);
145 if (realIndex != kParentIndex)
146 _listView.SetItemState_Selected(i, _selectedStatusVector[realIndex]);
147 }
148 _enableItemChangeNotify = enableTemp;
149 }
150 _listView.RedrawAllItems();
151}
152
153
154void CPanel::SelectSpec(bool selectMode)
155{
156 CComboDialog dlg;
157 LangString(selectMode ? IDS_SELECT : IDS_DESELECT, dlg.Title );
158 LangString(IDS_SELECT_MASK, dlg.Static);
159 dlg.Value = '*';
160 if (dlg.Create(GetParent()) != IDOK)
161 return;
162 const UString &mask = dlg.Value;
163 FOR_VECTOR (i, _selectedStatusVector)
164 if (DoesWildcardMatchName(mask, GetItemName(i)))
165 _selectedStatusVector[i] = selectMode;
166 UpdateSelection();
167}
168
169void CPanel::SelectByType(bool selectMode)
170{
171 int focusedItem = _listView.GetFocusedItem();
172 if (focusedItem < 0)
173 return;
174 int realIndex = GetRealItemIndex(focusedItem);
175 UString name = GetItemName(realIndex);
176 bool isItemFolder = IsItem_Folder(realIndex);
177
178 if (isItemFolder)
179 {
180 FOR_VECTOR (i, _selectedStatusVector)
181 if (IsItem_Folder(i) == isItemFolder)
182 _selectedStatusVector[i] = selectMode;
183 }
184 else
185 {
186 int pos = name.ReverseFind_Dot();
187 if (pos < 0)
188 {
189 FOR_VECTOR (i, _selectedStatusVector)
190 if (IsItem_Folder(i) == isItemFolder && GetItemName(i).ReverseFind_Dot() < 0)
191 _selectedStatusVector[i] = selectMode;
192 }
193 else
194 {
195 UString mask ('*');
196 mask += name.Ptr((unsigned)pos);
197 FOR_VECTOR (i, _selectedStatusVector)
198 if (IsItem_Folder(i) == isItemFolder && DoesWildcardMatchName(mask, GetItemName(i)))
199 _selectedStatusVector[i] = selectMode;
200 }
201 }
202
203 UpdateSelection();
204}
205
206void CPanel::SelectAll(bool selectMode)
207{
208 FOR_VECTOR (i, _selectedStatusVector)
209 _selectedStatusVector[i] = selectMode;
210 UpdateSelection();
211}
212
213void CPanel::InvertSelection()
214{
215 if (!_mySelectMode)
216 {
217 unsigned numSelected = 0;
218 FOR_VECTOR (i, _selectedStatusVector)
219 if (_selectedStatusVector[i])
220 numSelected++;
221 // 17.02: fixed : now we invert item even, if single item is selected
222 /*
223 if (numSelected == 1)
224 {
225 int focused = _listView.GetFocusedItem();
226 if (focused >= 0)
227 {
228 int realIndex = GetRealItemIndex(focused);
229 if (realIndex >= 0)
230 if (_selectedStatusVector[realIndex])
231 _selectedStatusVector[realIndex] = false;
232 }
233 }
234 */
235 }
236 FOR_VECTOR (i, _selectedStatusVector)
237 _selectedStatusVector[i] = !_selectedStatusVector[i];
238 UpdateSelection();
239}
240
241void CPanel::KillSelection()
242{
243 SelectAll(false);
244 // ver 20.01: now we don't like that focused will be selected item.
245 // So the following code was disabled:
246 /*
247 if (!_mySelectMode)
248 {
249 int focused = _listView.GetFocusedItem();
250 if (focused >= 0)
251 {
252 // CPanel::OnItemChanged notify for LVIS_SELECTED change doesn't work here. Why?
253 // so we change _selectedStatusVector[realIndex] here.
254 int realIndex = GetRealItemIndex(focused);
255 if (realIndex != kParentIndex)
256 _selectedStatusVector[realIndex] = true;
257 _listView.SetItemState_Selected(focused);
258 }
259 }
260 */
261}
262
263void CPanel::OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate)
264{
265 if (itemActivate->hdr.hwndFrom != HWND(_listView))
266 return;
267 // It will work only for Version 4.71 (IE 4);
268 int indexInList = itemActivate->iItem;
269 if (indexInList < 0)
270 return;
271
272 #ifndef UNDER_CE
273 if ((itemActivate->uKeyFlags & LVKF_SHIFT) != 0)
274 {
275 // int focusedIndex = _listView.GetFocusedItem();
276 int focusedIndex = _startGroupSelect;
277 if (focusedIndex < 0)
278 return;
279 int startItem = MyMin(focusedIndex, indexInList);
280 int finishItem = MyMax(focusedIndex, indexInList);
281
282 int numItems = _listView.GetItemCount();
283 for (int i = 0; i < numItems; i++)
284 {
285 int realIndex = GetRealItemIndex(i);
286 if (realIndex == kParentIndex)
287 continue;
288 bool selected = (i >= startItem && i <= finishItem);
289 if (_selectedStatusVector[realIndex] != selected)
290 {
291 _selectedStatusVector[realIndex] = selected;
292 _listView.RedrawItem(i);
293 }
294 }
295 }
296 else
297 #endif
298 {
299 _startGroupSelect = indexInList;
300
301 #ifndef UNDER_CE
302 if ((itemActivate->uKeyFlags & LVKF_CONTROL) != 0)
303 {
304 int realIndex = GetRealItemIndex(indexInList);
305 if (realIndex != kParentIndex)
306 {
307 _selectedStatusVector[realIndex] = !_selectedStatusVector[realIndex];
308 _listView.RedrawItem(indexInList);
309 }
310 }
311 #endif
312 }
313
314 return;
315}
diff --git a/CPP/7zip/UI/FileManager/PanelSort.cpp b/CPP/7zip/UI/FileManager/PanelSort.cpp
new file mode 100644
index 0000000..d26acb7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelSort.cpp
@@ -0,0 +1,269 @@
1// PanelSort.cpp
2
3#include "StdAfx.h"
4
5#include "../../../../C/CpuArch.h"
6#include "../../../Windows/PropVariant.h"
7
8#include "../../PropID.h"
9
10#include "Panel.h"
11
12using namespace NWindows;
13
14int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2)
15{
16 for (;;)
17 {
18 wchar_t c1 = *s1;
19 wchar_t c2 = *s2;
20 if ((c1 >= '0' && c1 <= '9') &&
21 (c2 >= '0' && c2 <= '9'))
22 {
23 for (; *s1 == '0'; s1++);
24 for (; *s2 == '0'; s2++);
25 size_t len1 = 0;
26 size_t len2 = 0;
27 for (; (s1[len1] >= '0' && s1[len1] <= '9'); len1++);
28 for (; (s2[len2] >= '0' && s2[len2] <= '9'); len2++);
29 if (len1 < len2) return -1;
30 if (len1 > len2) return 1;
31 for (; len1 > 0; s1++, s2++, len1--)
32 {
33 if (*s1 == *s2) continue;
34 return (*s1 < *s2) ? -1 : 1;
35 }
36 c1 = *s1;
37 c2 = *s2;
38 }
39 s1++;
40 s2++;
41 if (c1 != c2)
42 {
43 // Probably we need to change the order for special characters like in Explorer.
44 wchar_t u1 = MyCharUpper(c1);
45 wchar_t u2 = MyCharUpper(c2);
46 if (u1 < u2) return -1;
47 if (u1 > u2) return 1;
48 }
49 if (c1 == 0) return 0;
50 }
51}
52
53static int CompareFileNames_Le16(const Byte *s1, unsigned size1, const Byte *s2, unsigned size2)
54{
55 size1 &= ~1;
56 size2 &= ~1;
57 for (unsigned i = 0;; i += 2)
58 {
59 if (i >= size1)
60 return (i >= size2) ? 0 : -1;
61 if (i >= size2)
62 return 1;
63 UInt16 c1 = GetUi16(s1 + i);
64 UInt16 c2 = GetUi16(s2 + i);
65 if (c1 == c2)
66 {
67 if (c1 == 0)
68 return 0;
69 continue;
70 }
71 if (c1 < c2)
72 return -1;
73 return 1;
74 }
75}
76
77static inline const wchar_t *GetExtensionPtr(const UString &name)
78{
79 int dotPos = name.ReverseFind_Dot();
80 return name.Ptr((dotPos < 0) ? name.Len() : dotPos);
81}
82
83void CPanel::SetSortRawStatus()
84{
85 _isRawSortProp = false;
86 FOR_VECTOR (i, _columns)
87 {
88 const CPropColumn &prop = _columns[i];
89 if (prop.ID == _sortID)
90 {
91 _isRawSortProp = prop.IsRawProp ? 1 : 0;
92 return;
93 }
94 }
95}
96
97
98static int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
99{
100 if (lpData == 0)
101 return 0;
102 CPanel *panel = (CPanel*)lpData;
103
104
105 PROPID propID = panel->_sortID;
106
107 if (propID == kpidNoProperty)
108 return MyCompare(lParam1, lParam2);
109
110 if (panel->_isRawSortProp)
111 {
112 // Sha1, NtSecurity, NtReparse
113 const void *data1;
114 const void *data2;
115 UInt32 dataSize1;
116 UInt32 dataSize2;
117 UInt32 propType1;
118 UInt32 propType2;
119 if (panel->_folderRawProps->GetRawProp((UInt32)lParam1, propID, &data1, &dataSize1, &propType1) != 0) return 0;
120 if (panel->_folderRawProps->GetRawProp((UInt32)lParam2, propID, &data2, &dataSize2, &propType2) != 0) return 0;
121 if (dataSize1 == 0)
122 return (dataSize2 == 0) ? 0 : -1;
123 if (dataSize2 == 0)
124 return 1;
125 if (propType1 != NPropDataType::kRaw) return 0;
126 if (propType2 != NPropDataType::kRaw) return 0;
127 if (propID == kpidNtReparse)
128 {
129 NFile::CReparseShortInfo r1; r1.Parse((const Byte *)data1, dataSize1);
130 NFile::CReparseShortInfo r2; r2.Parse((const Byte *)data2, dataSize2);
131 return CompareFileNames_Le16(
132 (const Byte *)data1 + r1.Offset, r1.Size,
133 (const Byte *)data2 + r2.Offset, r2.Size);
134 }
135 }
136
137 if (panel->_folderCompare)
138 return panel->_folderCompare->CompareItems((UInt32)lParam1, (UInt32)lParam2, propID, panel->_isRawSortProp);
139
140 switch (propID)
141 {
142 // if (panel->_sortIndex == 0)
143 case kpidName:
144 {
145 const UString name1 = panel->GetItemName((int)lParam1);
146 const UString name2 = panel->GetItemName((int)lParam2);
147 int res = CompareFileNames_ForFolderList(name1, name2);
148 /*
149 if (res != 0 || !panel->_flatMode)
150 return res;
151 const UString prefix1 = panel->GetItemPrefix(lParam1);
152 const UString prefix2 = panel->GetItemPrefix(lParam2);
153 return res = CompareFileNames_ForFolderList(prefix1, prefix2);
154 */
155 return res;
156 }
157 case kpidExtension:
158 {
159 const UString name1 = panel->GetItemName((int)lParam1);
160 const UString name2 = panel->GetItemName((int)lParam2);
161 return CompareFileNames_ForFolderList(
162 GetExtensionPtr(name1),
163 GetExtensionPtr(name2));
164 }
165 }
166 /*
167 if (panel->_sortIndex == 1)
168 return MyCompare(file1.Size, file2.Size);
169 return ::CompareFileTime(&file1.MTime, &file2.MTime);
170 */
171
172 // PROPID propID = panel->_columns[panel->_sortIndex].ID;
173
174 NCOM::CPropVariant prop1, prop2;
175 // Name must be first property
176 panel->_folder->GetProperty((UInt32)lParam1, propID, &prop1);
177 panel->_folder->GetProperty((UInt32)lParam2, propID, &prop2);
178 if (prop1.vt != prop2.vt)
179 return MyCompare(prop1.vt, prop2.vt);
180 if (prop1.vt == VT_BSTR)
181 return MyStringCompareNoCase(prop1.bstrVal, prop2.bstrVal);
182 return prop1.Compare(prop2);
183}
184
185int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
186int CALLBACK CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
187{
188 if (lpData == 0) return 0;
189 if (lParam1 == kParentIndex) return -1;
190 if (lParam2 == kParentIndex) return 1;
191
192 CPanel *panel = (CPanel*)lpData;
193
194 bool isDir1 = panel->IsItem_Folder((int)lParam1);
195 bool isDir2 = panel->IsItem_Folder((int)lParam2);
196
197 if (isDir1 && !isDir2) return -1;
198 if (isDir2 && !isDir1) return 1;
199
200 int result = CompareItems2(lParam1, lParam2, lpData);
201 return panel->_ascending ? result: (-result);
202}
203
204
205/*
206void CPanel::SortItems(int index)
207{
208 if (index == _sortIndex)
209 _ascending = !_ascending;
210 else
211 {
212 _sortIndex = index;
213 _ascending = true;
214 switch (_columns[_sortIndex].ID)
215 {
216 case kpidSize:
217 case kpidPackedSize:
218 case kpidCTime:
219 case kpidATime:
220 case kpidMTime:
221 _ascending = false;
222 break;
223 }
224 }
225 _listView.SortItems(CompareItems, (LPARAM)this);
226 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
227}
228
229void CPanel::SortItemsWithPropID(PROPID propID)
230{
231 int index = _columns.FindItem_for_PropID(propID);
232 if (index >= 0)
233 SortItems(index);
234}
235*/
236
237void CPanel::SortItemsWithPropID(PROPID propID)
238{
239 if (propID == _sortID)
240 _ascending = !_ascending;
241 else
242 {
243 _sortID = propID;
244 _ascending = true;
245 switch (propID)
246 {
247 case kpidSize:
248 case kpidPackSize:
249 case kpidCTime:
250 case kpidATime:
251 case kpidMTime:
252 _ascending = false;
253 break;
254 }
255 }
256 SetSortRawStatus();
257 _listView.SortItems(CompareItems, (LPARAM)this);
258 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
259}
260
261
262void CPanel::OnColumnClick(LPNMLISTVIEW info)
263{
264 /*
265 int index = _columns.FindItem_for_PropID(_visibleColumns[info->iSubItem].ID);
266 SortItems(index);
267 */
268 SortItemsWithPropID(_visibleColumns[info->iSubItem].ID);
269}
diff --git a/CPP/7zip/UI/FileManager/PanelSplitFile.cpp b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
new file mode 100644
index 0000000..00a0d80
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PanelSplitFile.cpp
@@ -0,0 +1,562 @@
1// PanelSplitFile.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6
7#include "../../../Windows/ErrorMsg.h"
8#include "../../../Windows/FileName.h"
9
10#include "../GUI/ExtractRes.h"
11
12#include "resource.h"
13
14#include "App.h"
15#include "CopyDialog.h"
16#include "FormatUtils.h"
17#include "LangUtils.h"
18#include "SplitDialog.h"
19#include "SplitUtils.h"
20
21#include "PropertyNameRes.h"
22
23using namespace NWindows;
24using namespace NFile;
25using namespace NDir;
26
27static const char * const g_Message_FileWriteError = "File write error";
28
29struct CVolSeqName
30{
31 UString UnchangedPart;
32 UString ChangedPart;
33 CVolSeqName(): ChangedPart("000") {};
34
35 void SetNumDigits(UInt64 numVolumes)
36 {
37 ChangedPart = "000";
38 while (numVolumes > 999)
39 {
40 numVolumes /= 10;
41 ChangedPart += '0';
42 }
43 }
44
45 bool ParseName(const UString &name)
46 {
47 if (name.Len() < 2)
48 return false;
49 if (name.Back() != L'1' || name[name.Len() - 2] != L'0')
50 return false;
51
52 unsigned pos = name.Len() - 2;
53 for (; pos > 0 && name[pos - 1] == '0'; pos--);
54 UnchangedPart.SetFrom(name, pos);
55 ChangedPart = name.Ptr(pos);
56 return true;
57 }
58
59 UString GetNextName();
60};
61
62
63UString CVolSeqName::GetNextName()
64{
65 for (int i = (int)ChangedPart.Len() - 1; i >= 0; i--)
66 {
67 wchar_t c = ChangedPart[i];
68 if (c != L'9')
69 {
70 ChangedPart.ReplaceOneCharAtPos(i, (wchar_t)(c + 1));
71 break;
72 }
73 ChangedPart.ReplaceOneCharAtPos(i, L'0');
74 if (i == 0)
75 ChangedPart.InsertAtFront(L'1');
76 }
77 return UnchangedPart + ChangedPart;
78}
79
80class CThreadSplit: public CProgressThreadVirt
81{
82 HRESULT ProcessVirt();
83public:
84 FString FilePath;
85 FString VolBasePath;
86 UInt64 NumVolumes;
87 CRecordVector<UInt64> VolumeSizes;
88};
89
90
91class CPreAllocOutFile
92{
93 UInt64 _preAllocSize;
94public:
95 NIO::COutFile File;
96 UInt64 Written;
97
98 CPreAllocOutFile(): _preAllocSize(0), Written(0) {}
99
100 ~CPreAllocOutFile()
101 {
102 SetCorrectFileLength();
103 }
104
105 void PreAlloc(UInt64 preAllocSize)
106 {
107 _preAllocSize = 0;
108 if (File.SetLength(preAllocSize))
109 _preAllocSize = preAllocSize;
110 File.SeekToBegin();
111 }
112
113 bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw()
114 {
115 bool res = File.Write(data, size, processedSize);
116 Written += processedSize;
117 return res;
118 }
119
120 void Close()
121 {
122 SetCorrectFileLength();
123 Written = 0;
124 _preAllocSize = 0;
125 File.Close();
126 }
127
128 void SetCorrectFileLength()
129 {
130 if (Written < _preAllocSize)
131 {
132 File.SetLength(Written);
133 _preAllocSize = 0;
134 }
135 }
136};
137
138
139static const UInt32 kBufSize = (1 << 20);
140
141HRESULT CThreadSplit::ProcessVirt()
142{
143 NIO::CInFile inFile;
144 if (!inFile.Open(FilePath))
145 return GetLastError();
146
147 CPreAllocOutFile outFile;
148
149 CMyBuffer buffer;
150 if (!buffer.Allocate(kBufSize))
151 return E_OUTOFMEMORY;
152
153 CVolSeqName seqName;
154 seqName.SetNumDigits(NumVolumes);
155
156 UInt64 length;
157 if (!inFile.GetLength(length))
158 return GetLastError();
159
160 CProgressSync &sync = Sync;
161 sync.Set_NumBytesTotal(length);
162
163 UInt64 pos = 0;
164 UInt64 prev = 0;
165 UInt64 numFiles = 0;
166 unsigned volIndex = 0;
167
168 for (;;)
169 {
170 UInt64 volSize;
171 if (volIndex < VolumeSizes.Size())
172 volSize = VolumeSizes[volIndex];
173 else
174 volSize = VolumeSizes.Back();
175
176 UInt32 needSize = kBufSize;
177 {
178 const UInt64 rem = volSize - outFile.Written;
179 if (needSize > rem)
180 needSize = (UInt32)rem;
181 }
182 UInt32 processedSize;
183 if (!inFile.Read(buffer, needSize, processedSize))
184 return GetLastError();
185 if (processedSize == 0)
186 return S_OK;
187 needSize = processedSize;
188
189 if (outFile.Written == 0)
190 {
191 FString name = VolBasePath;
192 name += '.';
193 name += us2fs(seqName.GetNextName());
194 sync.Set_FilePath(fs2us(name));
195 if (!outFile.File.Create(name, false))
196 {
197 HRESULT res = GetLastError();
198 AddErrorPath(name);
199 return res;
200 }
201 UInt64 expectSize = volSize;
202 if (pos < length)
203 {
204 const UInt64 rem = length - pos;
205 if (expectSize > rem)
206 expectSize = rem;
207 }
208 outFile.PreAlloc(expectSize);
209 }
210
211 if (!outFile.Write(buffer, needSize, processedSize))
212 return GetLastError();
213 if (needSize != processedSize)
214 throw g_Message_FileWriteError;
215
216 pos += processedSize;
217
218 if (outFile.Written == volSize)
219 {
220 outFile.Close();
221 sync.Set_NumFilesCur(++numFiles);
222 if (volIndex < VolumeSizes.Size())
223 volIndex++;
224 }
225
226 if (pos - prev >= ((UInt32)1 << 22) || outFile.Written == 0)
227 {
228 RINOK(sync.Set_NumBytesCur(pos));
229 prev = pos;
230 }
231 }
232}
233
234
235void CApp::Split()
236{
237 int srcPanelIndex = GetFocusedPanelIndex();
238 CPanel &srcPanel = Panels[srcPanelIndex];
239 if (!srcPanel.Is_IO_FS_Folder())
240 {
241 srcPanel.MessageBox_Error_UnsupportOperation();
242 return;
243 }
244 CRecordVector<UInt32> indices;
245 srcPanel.GetOperatedItemIndices(indices);
246 if (indices.IsEmpty())
247 return;
248 if (indices.Size() != 1)
249 {
250 srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
251 return;
252 }
253 int index = indices[0];
254 if (srcPanel.IsItem_Folder(index))
255 {
256 srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
257 return;
258 }
259 const UString itemName = srcPanel.GetItemName(index);
260
261 UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
262 UString path = srcPath;
263 unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
264 CPanel &destPanel = Panels[destPanelIndex];
265 if (NumPanels > 1)
266 if (destPanel.IsFSFolder())
267 path = destPanel.GetFsPath();
268 CSplitDialog splitDialog;
269 splitDialog.FilePath = srcPanel.GetItemRelPath(index);
270 splitDialog.Path = path;
271 if (splitDialog.Create(srcPanel.GetParent()) != IDOK)
272 return;
273
274 NFind::CFileInfo fileInfo;
275 if (!fileInfo.Find(us2fs(srcPath + itemName)))
276 {
277 srcPanel.MessageBox_Error(L"Cannot find file");
278 return;
279 }
280 if (fileInfo.Size <= splitDialog.VolumeSizes.Front())
281 {
282 srcPanel.MessageBox_Error_LangID(IDS_SPLIT_VOL_MUST_BE_SMALLER);
283 return;
284 }
285 const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes);
286 if (numVolumes >= 100)
287 {
288 wchar_t s[32];
289 ConvertUInt64ToString(numVolumes, s);
290 if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, s),
291 LangString(IDS_SPLIT_CONFIRM_TITLE),
292 MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
293 return;
294 }
295
296 path = splitDialog.Path;
297 NName::NormalizeDirPathPrefix(path);
298 if (!CreateComplexDir(us2fs(path)))
299 {
300 DWORD lastError = ::GetLastError();
301 srcPanel.MessageBox_Error_2Lines_Message_HRESULT(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), lastError);
302 return;
303 }
304
305 {
306 CThreadSplit spliter;
307 spliter.NumVolumes = numVolumes;
308
309 CProgressDialog &progressDialog = spliter;
310
311 UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000);
312 UString title = LangString(IDS_SPLITTING);
313
314 progressDialog.ShowCompressionInfo = false;
315
316 progressDialog.MainWindow = _window;
317 progressDialog.MainTitle = progressWindowTitle;
318 progressDialog.MainAddTitle = title;
319 progressDialog.MainAddTitle.Add_Space();
320 progressDialog.Sync.Set_TitleFileName(itemName);
321
322
323 spliter.FilePath = us2fs(srcPath + itemName);
324 spliter.VolBasePath = us2fs(path + srcPanel.GetItemName_for_Copy(index));
325 spliter.VolumeSizes = splitDialog.VolumeSizes;
326
327 // if (splitDialog.VolumeSizes.Size() == 0) return;
328
329 // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
330 // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);
331
332 if (spliter.Create(title, _window) != 0)
333 return;
334 }
335 RefreshTitleAlways();
336
337
338 // disableNotify.Restore();
339 // disableNotify.Restore();
340 // srcPanel.SetFocusToList();
341 // srcPanel.RefreshListCtrlSaveFocused();
342}
343
344
345class CThreadCombine: public CProgressThreadVirt
346{
347 HRESULT ProcessVirt();
348public:
349 FString InputDirPrefix;
350 FStringVector Names;
351 FString OutputPath;
352 UInt64 TotalSize;
353};
354
355HRESULT CThreadCombine::ProcessVirt()
356{
357 NIO::COutFile outFile;
358 if (!outFile.Create(OutputPath, false))
359 {
360 HRESULT res = GetLastError();
361 AddErrorPath(OutputPath);
362 return res;
363 }
364
365 CProgressSync &sync = Sync;
366 sync.Set_NumBytesTotal(TotalSize);
367
368 CMyBuffer bufferObject;
369 if (!bufferObject.Allocate(kBufSize))
370 return E_OUTOFMEMORY;
371 Byte *buffer = (Byte *)(void *)bufferObject;
372 UInt64 pos = 0;
373 FOR_VECTOR (i, Names)
374 {
375 NIO::CInFile inFile;
376 const FString nextName = InputDirPrefix + Names[i];
377 if (!inFile.Open(nextName))
378 {
379 HRESULT res = GetLastError();
380 AddErrorPath(nextName);
381 return res;
382 }
383 sync.Set_FilePath(fs2us(nextName));
384 for (;;)
385 {
386 UInt32 processedSize;
387 if (!inFile.Read(buffer, kBufSize, processedSize))
388 {
389 HRESULT res = GetLastError();
390 AddErrorPath(nextName);
391 return res;
392 }
393 if (processedSize == 0)
394 break;
395 UInt32 needSize = processedSize;
396 if (!outFile.Write(buffer, needSize, processedSize))
397 {
398 HRESULT res = GetLastError();
399 AddErrorPath(OutputPath);
400 return res;
401 }
402 if (needSize != processedSize)
403 throw g_Message_FileWriteError;
404 pos += processedSize;
405 RINOK(sync.Set_NumBytesCur(pos));
406 }
407 }
408 return S_OK;
409}
410
411extern void AddValuePair2(UString &s, UINT resourceID, UInt64 num, UInt64 size);
412
413static void AddInfoFileName(UString &dest, const UString &name)
414{
415 dest += "\n ";
416 dest += name;
417}
418
419void CApp::Combine()
420{
421 int srcPanelIndex = GetFocusedPanelIndex();
422 CPanel &srcPanel = Panels[srcPanelIndex];
423 if (!srcPanel.IsFSFolder())
424 {
425 srcPanel.MessageBox_Error_LangID(IDS_OPERATION_IS_NOT_SUPPORTED);
426 return;
427 }
428 CRecordVector<UInt32> indices;
429 srcPanel.GetOperatedItemIndices(indices);
430 if (indices.IsEmpty())
431 return;
432 int index = indices[0];
433 if (indices.Size() != 1 || srcPanel.IsItem_Folder(index))
434 {
435 srcPanel.MessageBox_Error_LangID(IDS_COMBINE_SELECT_ONE_FILE);
436 return;
437 }
438 const UString itemName = srcPanel.GetItemName(index);
439
440 UString srcPath = srcPanel.GetFsPath() + srcPanel.GetItemPrefix(index);
441 UString path = srcPath;
442 unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
443 CPanel &destPanel = Panels[destPanelIndex];
444 if (NumPanels > 1)
445 if (destPanel.IsFSFolder())
446 path = destPanel.GetFsPath();
447
448 CVolSeqName volSeqName;
449 if (!volSeqName.ParseName(itemName))
450 {
451 srcPanel.MessageBox_Error_LangID(IDS_COMBINE_CANT_DETECT_SPLIT_FILE);
452 return;
453 }
454
455 {
456 CThreadCombine combiner;
457
458 UString nextName = itemName;
459 combiner.TotalSize = 0;
460 for (;;)
461 {
462 NFind::CFileInfo fileInfo;
463 if (!fileInfo.Find(us2fs(srcPath + nextName)) || fileInfo.IsDir())
464 break;
465 combiner.Names.Add(us2fs(nextName));
466 combiner.TotalSize += fileInfo.Size;
467 nextName = volSeqName.GetNextName();
468 }
469 if (combiner.Names.Size() == 1)
470 {
471 srcPanel.MessageBox_Error_LangID(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART);
472 return;
473 }
474
475 if (combiner.TotalSize == 0)
476 {
477 srcPanel.MessageBox_Error(L"No data");
478 return;
479 }
480
481 UString info;
482 AddValuePair2(info, IDS_PROP_FILES, combiner.Names.Size(), combiner.TotalSize);
483
484 info.Add_LF();
485 info += srcPath;
486
487 unsigned i;
488 for (i = 0; i < combiner.Names.Size() && i < 2; i++)
489 AddInfoFileName(info, fs2us(combiner.Names[i]));
490 if (i != combiner.Names.Size())
491 {
492 if (i + 1 != combiner.Names.Size())
493 AddInfoFileName(info, L"...");
494 AddInfoFileName(info, fs2us(combiner.Names.Back()));
495 }
496
497 {
498 CCopyDialog copyDialog;
499 copyDialog.Value = path;
500 LangString(IDS_COMBINE, copyDialog.Title);
501 copyDialog.Title.Add_Space();
502 copyDialog.Title += srcPanel.GetItemRelPath(index);
503 LangString(IDS_COMBINE_TO, copyDialog.Static);
504 copyDialog.Info = info;
505 if (copyDialog.Create(srcPanel.GetParent()) != IDOK)
506 return;
507 path = copyDialog.Value;
508 }
509
510 NName::NormalizeDirPathPrefix(path);
511 if (!CreateComplexDir(us2fs(path)))
512 {
513 DWORD lastError = ::GetLastError();
514 srcPanel.MessageBox_Error_2Lines_Message_HRESULT(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, path), lastError);
515 return;
516 }
517
518 UString outName = volSeqName.UnchangedPart;
519 while (!outName.IsEmpty())
520 {
521 if (outName.Back() != L'.')
522 break;
523 outName.DeleteBack();
524 }
525 if (outName.IsEmpty())
526 outName = "file";
527
528 NFind::CFileInfo fileInfo;
529 UString destFilePath = path + outName;
530 combiner.OutputPath = us2fs(destFilePath);
531 if (fileInfo.Find(combiner.OutputPath))
532 {
533 srcPanel.MessageBox_Error(MyFormatNew(IDS_FILE_EXIST, destFilePath));
534 return;
535 }
536
537 CProgressDialog &progressDialog = combiner;
538 progressDialog.ShowCompressionInfo = false;
539
540 UString progressWindowTitle ("7-Zip"); // LangString(IDS_APP_TITLE, 0x03000000);
541 UString title = LangString(IDS_COMBINING);
542
543 progressDialog.MainWindow = _window;
544 progressDialog.MainTitle = progressWindowTitle;
545 progressDialog.MainAddTitle = title;
546 progressDialog.MainAddTitle.Add_Space();
547
548 combiner.InputDirPrefix = us2fs(srcPath);
549
550 // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel);
551 // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel);
552
553 if (combiner.Create(title, _window) != 0)
554 return;
555 }
556 RefreshTitleAlways();
557
558 // disableNotify.Restore();
559 // disableNotify.Restore();
560 // srcPanel.SetFocusToList();
561 // srcPanel.RefreshListCtrlSaveFocused();
562}
diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.cpp b/CPP/7zip/UI/FileManager/PasswordDialog.cpp
new file mode 100644
index 0000000..6ead39c
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialog.cpp
@@ -0,0 +1,58 @@
1// PasswordDialog.cpp
2
3#include "StdAfx.h"
4
5#include "PasswordDialog.h"
6
7#ifdef LANG
8#include "LangUtils.h"
9#endif
10
11#ifdef LANG
12static const UInt32 kLangIDs[] =
13{
14 IDT_PASSWORD_ENTER,
15 IDX_PASSWORD_SHOW
16};
17#endif
18
19void CPasswordDialog::ReadControls()
20{
21 _passwordEdit.GetText(Password);
22 ShowPassword = IsButtonCheckedBool(IDX_PASSWORD_SHOW);
23}
24
25void CPasswordDialog::SetTextSpec()
26{
27 _passwordEdit.SetPasswordChar(ShowPassword ? 0: TEXT('*'));
28 _passwordEdit.SetText(Password);
29}
30
31bool CPasswordDialog::OnInit()
32{
33 #ifdef LANG
34 LangSetWindowText(*this, IDD_PASSWORD);
35 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
36 #endif
37 _passwordEdit.Attach(GetItem(IDE_PASSWORD_PASSWORD));
38 CheckButton(IDX_PASSWORD_SHOW, ShowPassword);
39 SetTextSpec();
40 return CModalDialog::OnInit();
41}
42
43bool CPasswordDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
44{
45 if (buttonID == IDX_PASSWORD_SHOW)
46 {
47 ReadControls();
48 SetTextSpec();
49 return true;
50 }
51 return CDialog::OnButtonClicked(buttonID, buttonHWND);
52}
53
54void CPasswordDialog::OnOK()
55{
56 ReadControls();
57 CModalDialog::OnOK();
58}
diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.h b/CPP/7zip/UI/FileManager/PasswordDialog.h
new file mode 100644
index 0000000..339ebda
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialog.h
@@ -0,0 +1,28 @@
1// PasswordDialog.h
2
3#ifndef __PASSWORD_DIALOG_H
4#define __PASSWORD_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7#include "../../../Windows/Control/Edit.h"
8
9#include "PasswordDialogRes.h"
10
11class CPasswordDialog: public NWindows::NControl::CModalDialog
12{
13 NWindows::NControl::CEdit _passwordEdit;
14
15 virtual void OnOK();
16 virtual bool OnInit();
17 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
18 void SetTextSpec();
19 void ReadControls();
20public:
21 UString Password;
22 bool ShowPassword;
23
24 CPasswordDialog(): ShowPassword(false) {}
25 INT_PTR Create(HWND parentWindow = 0) { return CModalDialog::Create(IDD_PASSWORD, parentWindow); }
26};
27
28#endif
diff --git a/CPP/7zip/UI/FileManager/PasswordDialog.rc b/CPP/7zip/UI/FileManager/PasswordDialog.rc
new file mode 100644
index 0000000..90c57ef
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialog.rc
@@ -0,0 +1,14 @@
1#include "PasswordDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 140
5#define yc 72
6
7IDD_PASSWORD DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
8CAPTION "Enter password"
9BEGIN
10 LTEXT "&Enter password:", IDT_PASSWORD_ENTER, m, m, xc, 8
11 EDITTEXT IDE_PASSWORD_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL
12 CONTROL "&Show password", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10
13 OK_CANCEL
14END
diff --git a/CPP/7zip/UI/FileManager/PasswordDialogRes.h b/CPP/7zip/UI/FileManager/PasswordDialogRes.h
new file mode 100644
index 0000000..1fe32e1
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PasswordDialogRes.h
@@ -0,0 +1,5 @@
1#define IDD_PASSWORD 3800
2#define IDT_PASSWORD_ENTER 3801
3#define IDX_PASSWORD_SHOW 3803
4
5#define IDE_PASSWORD_PASSWORD 120
diff --git a/CPP/7zip/UI/FileManager/PluginInterface.h b/CPP/7zip/UI/FileManager/PluginInterface.h
new file mode 100644
index 0000000..37654a0
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PluginInterface.h
@@ -0,0 +1,31 @@
1// PluginInterface.h
2
3#ifndef __PLUGIN_INTERFACE_H
4#define __PLUGIN_INTERFACE_H
5
6/*
7#include "../../../Common/Types.h"
8#include "../../IDecl.h"
9
10#define PLUGIN_INTERFACE(i, x) DECL_INTERFACE(i, 0x0A, x)
11
12PLUGIN_INTERFACE(IInitContextMenu, 0x00)
13{
14 STDMETHOD(InitContextMenu)(const wchar_t *folder, const wchar_t * const *names, UInt32 numFiles) PURE;
15};
16
17PLUGIN_INTERFACE(IPluginOptionsCallback, 0x01)
18{
19 STDMETHOD(GetProgramFolderPath)(BSTR *value) PURE;
20 STDMETHOD(GetProgramPath)(BSTR *value) PURE;
21 STDMETHOD(GetRegistryCUPath)(BSTR *value) PURE;
22};
23
24PLUGIN_INTERFACE(IPluginOptions, 0x02)
25{
26 STDMETHOD(PluginOptions)(HWND hWnd, IPluginOptionsCallback *callback) PURE;
27 // STDMETHOD(GetFileExtensions)(BSTR *extensions) PURE;
28};
29*/
30
31#endif
diff --git a/CPP/7zip/UI/FileManager/PluginLoader.h b/CPP/7zip/UI/FileManager/PluginLoader.h
new file mode 100644
index 0000000..fed38d6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PluginLoader.h
@@ -0,0 +1,28 @@
1// PluginLoader.h
2
3#ifndef __PLUGIN_LOADER_H
4#define __PLUGIN_LOADER_H
5
6#include "../../../Windows/DLL.h"
7
8#include "IFolder.h"
9
10class CPluginLibrary: public NWindows::NDLL::CLibrary
11{
12public:
13 HRESULT CreateManager(REFGUID clsID, IFolderManager **manager)
14 {
15 Func_CreateObject createObject = (Func_CreateObject)GetProc("CreateObject");
16 if (!createObject)
17 return GetLastError();
18 return createObject(&clsID, &IID_IFolderManager, (void **)manager);
19 }
20 HRESULT LoadAndCreateManager(CFSTR filePath, REFGUID clsID, IFolderManager **manager)
21 {
22 if (!Load(filePath))
23 return GetLastError();
24 return CreateManager(clsID, manager);
25 }
26};
27
28#endif
diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.cpp b/CPP/7zip/UI/FileManager/ProgramLocation.cpp
new file mode 100644
index 0000000..50ca5ca
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgramLocation.cpp
@@ -0,0 +1,3 @@
1// ProgramLocation.cpp
2
3#include "StdAfx.h"
diff --git a/CPP/7zip/UI/FileManager/ProgramLocation.h b/CPP/7zip/UI/FileManager/ProgramLocation.h
new file mode 100644
index 0000000..6bfb711
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgramLocation.h
@@ -0,0 +1,6 @@
1// ProgramLocation.h
2
3#ifndef __PROGRAM_LOCATION_H
4#define __PROGRAM_LOCATION_H
5
6#endif
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.cpp b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
new file mode 100644
index 0000000..b688a90
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.cpp
@@ -0,0 +1,199 @@
1// ProgressDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6
7#include "resource.h"
8
9#include "ProgressDialog.h"
10
11using namespace NWindows;
12
13extern HINSTANCE g_hInstance;
14
15static const UINT_PTR kTimerID = 3;
16static const UINT kTimerElapse = 100;
17
18#ifdef LANG
19#include "LangUtils.h"
20#endif
21
22HRESULT CProgressSync::ProcessStopAndPause()
23{
24 for (;;)
25 {
26 if (GetStopped())
27 return E_ABORT;
28 if (!GetPaused())
29 break;
30 ::Sleep(100);
31 }
32 return S_OK;
33}
34
35#ifndef _SFX
36CProgressDialog::~CProgressDialog()
37{
38 AddToTitle(L"");
39}
40void CProgressDialog::AddToTitle(LPCWSTR s)
41{
42 if (MainWindow != 0)
43 MySetWindowText(MainWindow, UString(s) + MainTitle);
44}
45#endif
46
47
48bool CProgressDialog::OnInit()
49{
50 _range = (UInt64)(Int64)-1;
51 _prevPercentValue = -1;
52
53 _wasCreated = true;
54 _dialogCreatedEvent.Set();
55
56 #ifdef LANG
57 LangSetDlgItems(*this, NULL, 0);
58 #endif
59
60 m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));
61
62 if (IconID >= 0)
63 {
64 HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));
65 SetIcon(ICON_BIG, icon);
66 }
67
68 _timer = SetTimer(kTimerID, kTimerElapse);
69 SetText(_title);
70 CheckNeedClose();
71 return CModalDialog::OnInit();
72}
73
74void CProgressDialog::OnCancel() { Sync.SetStopped(true); }
75void CProgressDialog::OnOK() { }
76
77void CProgressDialog::SetRange(UInt64 range)
78{
79 _range = range;
80 _peviousPos = (UInt64)(Int64)-1;
81 _converter.Init(range);
82 m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100%
83}
84
85void CProgressDialog::SetPos(UInt64 pos)
86{
87 bool redraw = true;
88 if (pos < _range && pos > _peviousPos)
89 {
90 UInt64 posDelta = pos - _peviousPos;
91 if (posDelta < (_range >> 10))
92 redraw = false;
93 }
94 if (redraw)
95 {
96 m_ProgressBar.SetPos(_converter.Count(pos)); // Test it for 100%
97 _peviousPos = pos;
98 }
99}
100
101bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
102{
103 if (Sync.GetPaused())
104 return true;
105
106 CheckNeedClose();
107
108 UInt64 total, completed;
109 Sync.GetProgress(total, completed);
110 if (total != _range)
111 SetRange(total);
112 SetPos(completed);
113
114 if (total == 0)
115 total = 1;
116
117 int percentValue = (int)(completed * 100 / total);
118 if (percentValue != _prevPercentValue)
119 {
120 wchar_t s[64];
121 ConvertUInt64ToString(percentValue, s);
122 UString title = s;
123 title += "% ";
124 SetText(title + _title);
125 #ifndef _SFX
126 AddToTitle(title + MainAddTitle);
127 #endif
128 _prevPercentValue = percentValue;
129 }
130 return true;
131}
132
133bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
134{
135 switch (message)
136 {
137 case kCloseMessage:
138 {
139 if (_timer)
140 {
141 KillTimer(kTimerID);
142 _timer = 0;
143 }
144 if (_inCancelMessageBox)
145 {
146 _externalCloseMessageWasReceived = true;
147 break;
148 }
149 return OnExternalCloseMessage();
150 }
151 /*
152 case WM_SETTEXT:
153 {
154 if (_timer == 0)
155 return true;
156 }
157 */
158 }
159 return CModalDialog::OnMessage(message, wParam, lParam);
160}
161
162bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
163{
164 switch (buttonID)
165 {
166 case IDCANCEL:
167 {
168 bool paused = Sync.GetPaused();
169 Sync.SetPaused(true);
170 _inCancelMessageBox = true;
171 int res = ::MessageBoxW(*this, L"Are you sure you want to cancel?", _title, MB_YESNOCANCEL);
172 _inCancelMessageBox = false;
173 Sync.SetPaused(paused);
174 if (res == IDCANCEL || res == IDNO)
175 {
176 if (_externalCloseMessageWasReceived)
177 OnExternalCloseMessage();
178 return true;
179 }
180 break;
181 }
182 }
183 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
184}
185
186void CProgressDialog::CheckNeedClose()
187{
188 if (_needClose)
189 {
190 PostMsg(kCloseMessage);
191 _needClose = false;
192 }
193}
194
195bool CProgressDialog::OnExternalCloseMessage()
196{
197 End(0);
198 return true;
199}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.h b/CPP/7zip/UI/FileManager/ProgressDialog.h
new file mode 100644
index 0000000..35c182a
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.h
@@ -0,0 +1,170 @@
1// ProgressDialog.h
2
3#ifndef __PROGRESS_DIALOG_H
4#define __PROGRESS_DIALOG_H
5
6#include "../../../Windows/Synchronization.h"
7#include "../../../Windows/Thread.h"
8
9#include "../../../Windows/Control/Dialog.h"
10#include "../../../Windows/Control/ProgressBar.h"
11
12#include "ProgressDialogRes.h"
13
14class CProgressSync
15{
16 NWindows::NSynchronization::CCriticalSection _cs;
17 bool _stopped;
18 bool _paused;
19 UInt64 _total;
20 UInt64 _completed;
21public:
22 CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {}
23
24 HRESULT ProcessStopAndPause();
25 bool GetStopped()
26 {
27 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
28 return _stopped;
29 }
30 void SetStopped(bool value)
31 {
32 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
33 _stopped = value;
34 }
35 bool GetPaused()
36 {
37 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
38 return _paused;
39 }
40 void SetPaused(bool value)
41 {
42 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
43 _paused = value;
44 }
45 void SetProgress(UInt64 total, UInt64 completed)
46 {
47 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
48 _total = total;
49 _completed = completed;
50 }
51 void SetPos(UInt64 completed)
52 {
53 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
54 _completed = completed;
55 }
56 void GetProgress(UInt64 &total, UInt64 &completed)
57 {
58 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
59 total = _total;
60 completed = _completed;
61 }
62};
63
64class CU64ToI32Converter
65{
66 UInt64 _numShiftBits;
67public:
68 void Init(UInt64 range)
69 {
70 // Windows CE doesn't like big number here.
71 for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++)
72 range >>= 1;
73 }
74 int Count(UInt64 value) { return int(value >> _numShiftBits); }
75};
76
77class CProgressDialog: public NWindows::NControl::CModalDialog
78{
79private:
80 UINT_PTR _timer;
81
82 UString _title;
83 CU64ToI32Converter _converter;
84 UInt64 _peviousPos;
85 UInt64 _range;
86 NWindows::NControl::CProgressBar m_ProgressBar;
87
88 int _prevPercentValue;
89
90 bool _wasCreated;
91 bool _needClose;
92 bool _inCancelMessageBox;
93 bool _externalCloseMessageWasReceived;
94
95 bool OnTimer(WPARAM timerID, LPARAM callback);
96 void SetRange(UInt64 range);
97 void SetPos(UInt64 pos);
98 virtual bool OnInit();
99 virtual void OnCancel();
100 virtual void OnOK();
101 NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;
102 #ifndef _SFX
103 void AddToTitle(LPCWSTR string);
104 #endif
105 bool OnButtonClicked(int buttonID, HWND buttonHWND);
106
107 void WaitCreating() { _dialogCreatedEvent.Lock(); }
108 void CheckNeedClose();
109 bool OnExternalCloseMessage();
110public:
111 CProgressSync Sync;
112 int IconID;
113
114 #ifndef _SFX
115 HWND MainWindow;
116 UString MainTitle;
117 UString MainAddTitle;
118 ~CProgressDialog();
119 #endif
120
121 CProgressDialog(): _timer(0)
122 #ifndef _SFX
123 ,MainWindow(0)
124 #endif
125 {
126 IconID = -1;
127 _wasCreated = false;
128 _needClose = false;
129 _inCancelMessageBox = false;
130 _externalCloseMessageWasReceived = false;
131
132 if (_dialogCreatedEvent.Create() != S_OK)
133 throw 1334987;
134 }
135
136 INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0)
137 {
138 _title = title;
139 INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent);
140 thread.Wait_Close();
141 return res;
142 }
143
144 enum
145 {
146 kCloseMessage = WM_APP + 1
147 };
148
149 virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
150
151 void ProcessWasFinished()
152 {
153 WaitCreating();
154 if (_wasCreated)
155 PostMsg(kCloseMessage);
156 else
157 _needClose = true;
158 };
159};
160
161
162class CProgressCloser
163{
164 CProgressDialog *_p;
165public:
166 CProgressCloser(CProgressDialog &p) : _p(&p) {}
167 ~CProgressCloser() { _p->ProcessWasFinished(); }
168};
169
170#endif
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog.rc b/CPP/7zip/UI/FileManager/ProgressDialog.rc
new file mode 100644
index 0000000..55d9923
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog.rc
@@ -0,0 +1,12 @@
1#include "ProgressDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 172
5#define yc 44
6
7IDD_PROGRESS DIALOG 0, 0, xs, ys MY_MODAL_DIALOG_STYLE MY_FONT
8CAPTION "Progress"
9BEGIN
10 PUSHBUTTON "Cancel", IDCANCEL, bx, by, bxs, bys
11 CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, m, xc, 14
12END
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.cpp b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
new file mode 100644
index 0000000..54273d0
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.cpp
@@ -0,0 +1,1460 @@
1// ProgressDialog2.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6#include "../../../Common/StringConvert.h"
7
8#include "../../../Windows/Clipboard.h"
9#include "../../../Windows/ErrorMsg.h"
10
11#include "../GUI/ExtractRes.h"
12
13#include "LangUtils.h"
14
15#include "DialogSize.h"
16#include "ProgressDialog2.h"
17#include "ProgressDialog2Res.h"
18
19using namespace NWindows;
20
21extern HINSTANCE g_hInstance;
22
23static const UINT_PTR kTimerID = 3;
24
25static const UINT kCloseMessage = WM_APP + 1;
26// we can't use WM_USER, since WM_USER can be used by standard Windows procedure for Dialog
27
28static const UINT kTimerElapse =
29 #ifdef UNDER_CE
30 500
31 #else
32 200
33 #endif
34 ;
35
36static const UINT kCreateDelay =
37 #ifdef UNDER_CE
38 2500
39 #else
40 500
41 #endif
42 ;
43
44static const DWORD kPauseSleepTime = 100;
45
46#ifdef LANG
47
48static const UInt32 kLangIDs[] =
49{
50 IDT_PROGRESS_ELAPSED,
51 IDT_PROGRESS_REMAINING,
52 IDT_PROGRESS_TOTAL,
53 IDT_PROGRESS_SPEED,
54 IDT_PROGRESS_PROCESSED,
55 IDT_PROGRESS_RATIO,
56 IDT_PROGRESS_ERRORS,
57 IDB_PROGRESS_BACKGROUND,
58 IDB_PAUSE
59};
60
61static const UInt32 kLangIDs_Colon[] =
62{
63 IDT_PROGRESS_PACKED,
64 IDT_PROGRESS_FILES
65};
66
67#endif
68
69
70#define UNDEFINED_VAL ((UInt64)(Int64)-1)
71#define INIT_AS_UNDEFINED(v) v = UNDEFINED_VAL;
72#define IS_UNDEFINED_VAL(v) ((v) == UNDEFINED_VAL)
73#define IS_DEFINED_VAL(v) ((v) != UNDEFINED_VAL)
74
75CProgressSync::CProgressSync():
76 _stopped(false), _paused(false),
77 _bytesProgressMode(true),
78 _totalBytes(UNDEFINED_VAL), _completedBytes(0),
79 _totalFiles(UNDEFINED_VAL), _curFiles(0),
80 _inSize(UNDEFINED_VAL),
81 _outSize(UNDEFINED_VAL),
82 _isDir(false)
83 {}
84
85#define CHECK_STOP if (_stopped) return E_ABORT; if (!_paused) return S_OK;
86#define CRITICAL_LOCK NSynchronization::CCriticalSectionLock lock(_cs);
87
88bool CProgressSync::Get_Paused()
89{
90 CRITICAL_LOCK
91 return _paused;
92}
93
94HRESULT CProgressSync::CheckStop()
95{
96 for (;;)
97 {
98 {
99 CRITICAL_LOCK
100 CHECK_STOP
101 }
102 ::Sleep(kPauseSleepTime);
103 }
104}
105
106HRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir)
107{
108 {
109 CRITICAL_LOCK
110 _totalFiles = numFiles;
111 _totalBytes = totalSize;
112 _filePath = fs2us(fileName);
113 _isDir = isDir;
114 // _completedBytes = 0;
115 CHECK_STOP
116 }
117 return CheckStop();
118}
119
120HRESULT CProgressSync::Set_NumFilesTotal(UInt64 val)
121{
122 {
123 CRITICAL_LOCK
124 _totalFiles = val;
125 CHECK_STOP
126 }
127 return CheckStop();
128}
129
130void CProgressSync::Set_NumBytesTotal(UInt64 val)
131{
132 CRITICAL_LOCK
133 _totalBytes = val;
134}
135
136void CProgressSync::Set_NumFilesCur(UInt64 val)
137{
138 CRITICAL_LOCK
139 _curFiles = val;
140}
141
142HRESULT CProgressSync::Set_NumBytesCur(const UInt64 *val)
143{
144 {
145 CRITICAL_LOCK
146 if (val)
147 _completedBytes = *val;
148 CHECK_STOP
149 }
150 return CheckStop();
151}
152
153HRESULT CProgressSync::Set_NumBytesCur(UInt64 val)
154{
155 {
156 CRITICAL_LOCK
157 _completedBytes = val;
158 CHECK_STOP
159 }
160 return CheckStop();
161}
162
163void CProgressSync::Set_Ratio(const UInt64 *inSize, const UInt64 *outSize)
164{
165 CRITICAL_LOCK
166 if (inSize)
167 _inSize = *inSize;
168 if (outSize)
169 _outSize = *outSize;
170}
171
172void CProgressSync::Set_TitleFileName(const UString &fileName)
173{
174 CRITICAL_LOCK
175 _titleFileName = fileName;
176}
177
178void CProgressSync::Set_Status(const UString &s)
179{
180 CRITICAL_LOCK
181 _status = s;
182}
183
184HRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir)
185{
186 {
187 CRITICAL_LOCK
188 _status = s;
189 if (path)
190 _filePath = path;
191 else
192 _filePath.Empty();
193 _isDir = isDir;
194 }
195 return CheckStop();
196}
197
198void CProgressSync::Set_FilePath(const wchar_t *path, bool isDir)
199{
200 CRITICAL_LOCK
201 if (path)
202 _filePath = path;
203 else
204 _filePath.Empty();
205 _isDir = isDir;
206}
207
208
209void CProgressSync::AddError_Message(const wchar_t *message)
210{
211 CRITICAL_LOCK
212 Messages.Add(message);
213}
214
215void CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t *name)
216{
217 UString s;
218 if (name && *name != 0)
219 s += name;
220 if (message && *message != 0)
221 {
222 if (!s.IsEmpty())
223 s.Add_LF();
224 s += message;
225 if (!s.IsEmpty() && s.Back() == L'\n')
226 s.DeleteBack();
227 }
228 AddError_Message(s);
229}
230
231void CProgressSync::AddError_Code_Name(DWORD systemError, const wchar_t *name)
232{
233 UString s = NError::MyFormatMessage(systemError);
234 if (systemError == 0)
235 s = "Error";
236 AddError_Message_Name(s, name);
237}
238
239CProgressDialog::CProgressDialog():
240 _timer(0),
241 CompressingMode(true),
242 MainWindow(NULL)
243{
244 _isDir = false;
245
246 _numMessages = 0;
247 IconID = -1;
248 MessagesDisplayed = false;
249 _wasCreated = false;
250 _needClose = false;
251 _inCancelMessageBox = false;
252 _externalCloseMessageWasReceived = false;
253
254 _numPostedMessages = 0;
255 _numAutoSizeMessages = 0;
256 _errorsWereDisplayed = false;
257 _waitCloseByCancelButton = false;
258 _cancelWasPressed = false;
259 ShowCompressionInfo = true;
260 WaitMode = false;
261 if (_dialogCreatedEvent.Create() != S_OK)
262 throw 1334987;
263 if (_createDialogEvent.Create() != S_OK)
264 throw 1334987;
265 #ifdef __ITaskbarList3_INTERFACE_DEFINED__
266 CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&_taskbarList);
267 if (_taskbarList)
268 _taskbarList->HrInit();
269 #endif
270}
271
272#ifndef _SFX
273
274CProgressDialog::~CProgressDialog()
275{
276 #ifdef __ITaskbarList3_INTERFACE_DEFINED__
277 SetTaskbarProgressState(TBPF_NOPROGRESS);
278 #endif
279 AddToTitle(L"");
280}
281void CProgressDialog::AddToTitle(LPCWSTR s)
282{
283 if (MainWindow)
284 {
285 CWindow window(MainWindow);
286 window.SetText((UString)s + MainTitle);
287 }
288}
289
290#endif
291
292
293void CProgressDialog::SetTaskbarProgressState()
294{
295 #ifdef __ITaskbarList3_INTERFACE_DEFINED__
296 if (_taskbarList && _hwndForTaskbar)
297 {
298 TBPFLAG tbpFlags;
299 if (Sync.Get_Paused())
300 tbpFlags = TBPF_PAUSED;
301 else
302 tbpFlags = _errorsWereDisplayed ? TBPF_ERROR: TBPF_NORMAL;
303 SetTaskbarProgressState(tbpFlags);
304 }
305 #endif
306}
307
308static const unsigned kTitleFileNameSizeLimit = 36;
309static const unsigned kCurrentFileNameSizeLimit = 82;
310
311static void ReduceString(UString &s, unsigned size)
312{
313 if (s.Len() <= size)
314 return;
315 s.Delete(size / 2, s.Len() - size);
316 s.Insert(size / 2, L" ... ");
317}
318
319void CProgressDialog::EnableErrorsControls(bool enable)
320{
321 ShowItem_Bool(IDT_PROGRESS_ERRORS, enable);
322 ShowItem_Bool(IDT_PROGRESS_ERRORS_VAL, enable);
323 ShowItem_Bool(IDL_PROGRESS_MESSAGES, enable);
324}
325
326bool CProgressDialog::OnInit()
327{
328 _hwndForTaskbar = MainWindow;
329 if (!_hwndForTaskbar)
330 _hwndForTaskbar = GetParent();
331 if (!_hwndForTaskbar)
332 _hwndForTaskbar = *this;
333
334 INIT_AS_UNDEFINED(_progressBar_Range);
335 INIT_AS_UNDEFINED(_progressBar_Pos);
336
337 INIT_AS_UNDEFINED(_prevPercentValue);
338 INIT_AS_UNDEFINED(_prevElapsedSec);
339 INIT_AS_UNDEFINED(_prevRemainingSec);
340
341 INIT_AS_UNDEFINED(_prevSpeed);
342 _prevSpeed_MoveBits = 0;
343
344 _prevTime = ::GetTickCount();
345 _elapsedTime = 0;
346
347 INIT_AS_UNDEFINED(_totalBytes_Prev);
348 INIT_AS_UNDEFINED(_processed_Prev);
349 INIT_AS_UNDEFINED(_packed_Prev);
350 INIT_AS_UNDEFINED(_ratio_Prev);
351
352 _filesStr_Prev.Empty();
353 _filesTotStr_Prev.Empty();
354
355 _foreground = true;
356
357 m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));
358 _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES));
359 _messageList.SetUnicodeFormat();
360 _messageList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
361
362 _wasCreated = true;
363 _dialogCreatedEvent.Set();
364
365 #ifdef LANG
366 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
367 LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));
368 #endif
369
370 CWindow window(GetItem(IDB_PROGRESS_BACKGROUND));
371 window.GetText(_background_String);
372 _backgrounded_String = _background_String;
373 _backgrounded_String.RemoveChar(L'&');
374
375 window = GetItem(IDB_PAUSE);
376 window.GetText(_pause_String);
377
378 LangString(IDS_PROGRESS_FOREGROUND, _foreground_String);
379 LangString(IDS_CONTINUE, _continue_String);
380 LangString(IDS_PROGRESS_PAUSED, _paused_String);
381
382 SetText(_title);
383 SetPauseText();
384 SetPriorityText();
385
386 _messageList.InsertColumn(0, L"", 30);
387 _messageList.InsertColumn(1, L"", 600);
388
389 _messageList.SetColumnWidthAuto(0);
390 _messageList.SetColumnWidthAuto(1);
391
392 EnableErrorsControls(false);
393
394 GetItemSizes(IDCANCEL, _buttonSizeX, _buttonSizeY);
395 _numReduceSymbols = kCurrentFileNameSizeLimit;
396 NormalizeSize(true);
397
398 if (!ShowCompressionInfo)
399 {
400 HideItem(IDT_PROGRESS_PACKED);
401 HideItem(IDT_PROGRESS_PACKED_VAL);
402 HideItem(IDT_PROGRESS_RATIO);
403 HideItem(IDT_PROGRESS_RATIO_VAL);
404 }
405
406 if (IconID >= 0)
407 {
408 HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));
409 // SetIcon(ICON_SMALL, icon);
410 SetIcon(ICON_BIG, icon);
411 }
412 _timer = SetTimer(kTimerID, kTimerElapse);
413 #ifdef UNDER_CE
414 Foreground();
415 #endif
416
417 CheckNeedClose();
418
419 SetTaskbarProgressState();
420
421 return CModalDialog::OnInit();
422}
423
424static const UINT kIDs[] =
425{
426 IDT_PROGRESS_ELAPSED, IDT_PROGRESS_ELAPSED_VAL,
427 IDT_PROGRESS_REMAINING, IDT_PROGRESS_REMAINING_VAL,
428 IDT_PROGRESS_FILES, IDT_PROGRESS_FILES_VAL,
429 0, IDT_PROGRESS_FILES_TOTAL,
430 IDT_PROGRESS_ERRORS, IDT_PROGRESS_ERRORS_VAL,
431
432 IDT_PROGRESS_TOTAL, IDT_PROGRESS_TOTAL_VAL,
433 IDT_PROGRESS_SPEED, IDT_PROGRESS_SPEED_VAL,
434 IDT_PROGRESS_PROCESSED, IDT_PROGRESS_PROCESSED_VAL,
435 IDT_PROGRESS_PACKED, IDT_PROGRESS_PACKED_VAL,
436 IDT_PROGRESS_RATIO, IDT_PROGRESS_RATIO_VAL
437};
438
439bool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
440{
441 int sY;
442 int sStep;
443 int mx, my;
444 {
445 RECT r;
446 GetClientRectOfItem(IDT_PROGRESS_ELAPSED, r);
447 mx = r.left;
448 my = r.top;
449 sY = RECT_SIZE_Y(r);
450 GetClientRectOfItem(IDT_PROGRESS_REMAINING, r);
451 sStep = r.top - my;
452 }
453
454 InvalidateRect(NULL);
455
456 int xSizeClient = xSize - mx * 2;
457
458 {
459 int i;
460 for (i = 800; i > 40; i = i * 9 / 10)
461 if (Units_To_Pixels_X(i) <= xSizeClient)
462 break;
463 _numReduceSymbols = i / 4;
464 }
465
466 int yPos = ySize - my - _buttonSizeY;
467
468 ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2);
469 ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2);
470 ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2);
471
472 int bSizeX = _buttonSizeX;
473 int mx2 = mx;
474 for (;; mx2--)
475 {
476 int bSize2 = bSizeX * 3 + mx2 * 2;
477 if (bSize2 <= xSizeClient)
478 break;
479 if (mx2 < 5)
480 {
481 bSizeX = (xSizeClient - mx2 * 2) / 3;
482 break;
483 }
484 }
485 if (bSizeX < 2)
486 bSizeX = 2;
487
488 {
489 RECT r;
490 GetClientRectOfItem(IDL_PROGRESS_MESSAGES, r);
491 int y = r.top;
492 int ySize2 = yPos - my - y;
493 const int kMinYSize = _buttonSizeY + _buttonSizeY * 3 / 4;
494 int xx = xSize - mx * 2;
495 if (ySize2 < kMinYSize)
496 {
497 ySize2 = kMinYSize;
498 if (xx > bSizeX * 2)
499 xx -= bSizeX;
500 }
501
502 _messageList.Move(mx, y, xx, ySize2);
503 }
504
505 {
506 int xPos = xSize - mx;
507 xPos -= bSizeX;
508 MoveItem(IDCANCEL, xPos, yPos, bSizeX, _buttonSizeY);
509 xPos -= (mx2 + bSizeX);
510 MoveItem(IDB_PAUSE, xPos, yPos, bSizeX, _buttonSizeY);
511 xPos -= (mx2 + bSizeX);
512 MoveItem(IDB_PROGRESS_BACKGROUND, xPos, yPos, bSizeX, _buttonSizeY);
513 }
514
515 int valueSize;
516 int labelSize;
517 int padSize;
518
519 labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN);
520 valueSize = Units_To_Pixels_X(MY_PROGRESS_VAL_UNITS);
521 padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS);
522 int requiredSize = (labelSize + valueSize) * 2 + padSize;
523
524 int gSize;
525 {
526 if (requiredSize < xSizeClient)
527 {
528 int incr = (xSizeClient - requiredSize) / 3;
529 labelSize += incr;
530 }
531 else
532 labelSize = (xSizeClient - valueSize * 2 - padSize) / 2;
533 if (labelSize < 0)
534 labelSize = 0;
535
536 gSize = labelSize + valueSize;
537 padSize = xSizeClient - gSize * 2;
538 }
539
540 labelSize = gSize - valueSize;
541
542 yPos = my;
543 for (unsigned i = 0; i < ARRAY_SIZE(kIDs); i += 2)
544 {
545 int x = mx;
546 const unsigned kNumColumn1Items = 5 * 2;
547 if (i >= kNumColumn1Items)
548 {
549 if (i == kNumColumn1Items)
550 yPos = my;
551 x = mx + gSize + padSize;
552 }
553 if (kIDs[i] != 0)
554 MoveItem(kIDs[i], x, yPos, labelSize, sY);
555 MoveItem(kIDs[i + 1], x + labelSize, yPos, valueSize, sY);
556 yPos += sStep;
557 }
558 return false;
559}
560
561void CProgressDialog::OnCancel() { Sync.Set_Stopped(true); }
562void CProgressDialog::OnOK() { }
563
564void CProgressDialog::SetProgressRange(UInt64 range)
565{
566 if (range == _progressBar_Range)
567 return;
568 _progressBar_Range = range;
569 INIT_AS_UNDEFINED(_progressBar_Pos);
570 _progressConv.Init(range);
571 m_ProgressBar.SetRange32(0, _progressConv.Count(range));
572}
573
574void CProgressDialog::SetProgressPos(UInt64 pos)
575{
576 if (pos >= _progressBar_Range ||
577 pos <= _progressBar_Pos ||
578 pos - _progressBar_Pos >= (_progressBar_Range >> 10))
579 {
580 m_ProgressBar.SetPos(_progressConv.Count(pos));
581 #ifdef __ITaskbarList3_INTERFACE_DEFINED__
582 if (_taskbarList && _hwndForTaskbar)
583 _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _progressBar_Range);
584 #endif
585 _progressBar_Pos = pos;
586 }
587}
588
589#define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; }
590
591void GetTimeString(UInt64 timeValue, wchar_t *s);
592void GetTimeString(UInt64 timeValue, wchar_t *s)
593{
594 UInt64 hours = timeValue / 3600;
595 UInt32 seconds = (UInt32)(timeValue - hours * 3600);
596 UInt32 minutes = seconds / 60;
597 seconds %= 60;
598 if (hours > 99)
599 {
600 ConvertUInt64ToString(hours, s);
601 for (; *s != 0; s++);
602 }
603 else
604 {
605 UInt32 hours32 = (UInt32)hours;
606 UINT_TO_STR_2(hours32);
607 }
608 *s++ = ':'; UINT_TO_STR_2(minutes);
609 *s++ = ':'; UINT_TO_STR_2(seconds);
610 *s = 0;
611}
612
613static void ConvertSizeToString(UInt64 v, wchar_t *s)
614{
615 Byte c = 0;
616 if (v >= ((UInt64)100000 << 20)) { v >>= 30; c = 'G'; }
617 else if (v >= ((UInt64)100000 << 10)) { v >>= 20; c = 'M'; }
618 else if (v >= ((UInt64)100000 << 0)) { v >>= 10; c = 'K'; }
619 ConvertUInt64ToString(v, s);
620 if (c != 0)
621 {
622 s += MyStringLen(s);
623 *s++ = ' ';
624 *s++ = c;
625 *s++ = 'B';
626 *s++ = 0;
627 }
628}
629
630void CProgressDialog::ShowSize(int id, UInt64 val, UInt64 &prev)
631{
632 if (val == prev)
633 return;
634 prev = val;
635 wchar_t s[40];
636 s[0] = 0;
637 if (IS_DEFINED_VAL(val))
638 ConvertSizeToString(val, s);
639 SetItemText(id, s);
640}
641
642static void GetChangedString(const UString &newStr, UString &prevStr, bool &hasChanged)
643{
644 hasChanged = !(prevStr == newStr);
645 if (hasChanged)
646 prevStr = newStr;
647}
648
649static unsigned GetPower32(UInt32 val)
650{
651 const unsigned kStart = 32;
652 UInt32 mask = ((UInt32)1 << (kStart - 1));
653 for (unsigned i = kStart;; i--)
654 {
655 if (i == 0 || (val & mask) != 0)
656 return i;
657 mask >>= 1;
658 }
659}
660
661static unsigned GetPower64(UInt64 val)
662{
663 UInt32 high = (UInt32)(val >> 32);
664 if (high == 0)
665 return GetPower32((UInt32)val);
666 return GetPower32(high) + 32;
667}
668
669static UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)
670{
671 unsigned pow1 = GetPower64(mult1);
672 unsigned pow2 = GetPower64(mult2);
673 while (pow1 + pow2 > 64)
674 {
675 if (pow1 > pow2) { pow1--; mult1 >>= 1; }
676 else { pow2--; mult2 >>= 1; }
677 divider >>= 1;
678 }
679 UInt64 res = mult1 * mult2;
680 if (divider != 0)
681 res /= divider;
682 return res;
683}
684
685void CProgressDialog::UpdateStatInfo(bool showAll)
686{
687 UInt64 total, completed, totalFiles, completedFiles, inSize, outSize;
688 bool bytesProgressMode;
689
690 bool titleFileName_Changed;
691 bool curFilePath_Changed;
692 bool status_Changed;
693 unsigned numErrors;
694 {
695 NSynchronization::CCriticalSectionLock lock(Sync._cs);
696 total = Sync._totalBytes;
697 completed = Sync._completedBytes;
698 totalFiles = Sync._totalFiles;
699 completedFiles = Sync._curFiles;
700 inSize = Sync._inSize;
701 outSize = Sync._outSize;
702 bytesProgressMode = Sync._bytesProgressMode;
703
704 GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed);
705 GetChangedString(Sync._filePath, _filePath, curFilePath_Changed);
706 GetChangedString(Sync._status, _status, status_Changed);
707 if (_isDir != Sync._isDir)
708 {
709 curFilePath_Changed = true;
710 _isDir = Sync._isDir;
711 }
712 numErrors = Sync.Messages.Size();
713 }
714
715 UInt32 curTime = ::GetTickCount();
716
717 const UInt64 progressTotal = bytesProgressMode ? total : totalFiles;
718 const UInt64 progressCompleted = bytesProgressMode ? completed : completedFiles;
719 {
720 if (IS_UNDEFINED_VAL(progressTotal))
721 {
722 // SetPos(0);
723 // SetRange(progressCompleted);
724 }
725 else
726 {
727 if (_progressBar_Pos != 0 || progressCompleted != 0 ||
728 (_progressBar_Range == 0 && progressTotal != 0))
729 {
730 SetProgressRange(progressTotal);
731 SetProgressPos(progressCompleted);
732 }
733 }
734 }
735
736 ShowSize(IDT_PROGRESS_TOTAL_VAL, total, _totalBytes_Prev);
737
738 _elapsedTime += (curTime - _prevTime);
739 _prevTime = curTime;
740 UInt64 elapsedSec = _elapsedTime / 1000;
741 bool elapsedChanged = false;
742 if (elapsedSec != _prevElapsedSec)
743 {
744 _prevElapsedSec = elapsedSec;
745 elapsedChanged = true;
746 wchar_t s[40];
747 GetTimeString(elapsedSec, s);
748 SetItemText(IDT_PROGRESS_ELAPSED_VAL, s);
749 }
750
751 bool needSetTitle = false;
752 if (elapsedChanged || showAll)
753 {
754 if (numErrors > _numPostedMessages)
755 {
756 UpdateMessagesDialog();
757 wchar_t s[32];
758 ConvertUInt64ToString(numErrors, s);
759 SetItemText(IDT_PROGRESS_ERRORS_VAL, s);
760 if (!_errorsWereDisplayed)
761 {
762 _errorsWereDisplayed = true;
763 EnableErrorsControls(true);
764 SetTaskbarProgressState();
765 }
766 }
767
768 if (progressCompleted != 0)
769 {
770 if (IS_UNDEFINED_VAL(progressTotal))
771 {
772 if (IS_DEFINED_VAL(_prevRemainingSec))
773 {
774 INIT_AS_UNDEFINED(_prevRemainingSec);
775 SetItemText(IDT_PROGRESS_REMAINING_VAL, L"");
776 }
777 }
778 else
779 {
780 UInt64 remainingTime = 0;
781 if (progressCompleted < progressTotal)
782 remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted);
783 UInt64 remainingSec = remainingTime / 1000;
784 if (remainingSec != _prevRemainingSec)
785 {
786 _prevRemainingSec = remainingSec;
787 wchar_t s[40];
788 GetTimeString(remainingSec, s);
789 SetItemText(IDT_PROGRESS_REMAINING_VAL, s);
790 }
791 }
792 {
793 UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;
794 UInt64 v = (progressCompleted * 1000) / elapsedTime;
795 Byte c = 0;
796 unsigned moveBits = 0;
797 if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; }
798 else if (v >= ((UInt64)10000 << 0)) { moveBits = 10; c = 'K'; }
799 v >>= moveBits;
800 if (moveBits != _prevSpeed_MoveBits || v != _prevSpeed)
801 {
802 _prevSpeed_MoveBits = moveBits;
803 _prevSpeed = v;
804 wchar_t s[40];
805 ConvertUInt64ToString(v, s);
806 unsigned pos = MyStringLen(s);
807 s[pos++] = ' ';
808 if (moveBits != 0)
809 s[pos++] = c;
810 s[pos++] = 'B';
811 s[pos++] = '/';
812 s[pos++] = 's';
813 s[pos++] = 0;
814 SetItemText(IDT_PROGRESS_SPEED_VAL, s);
815 }
816 }
817 }
818
819 {
820 UInt64 percent = 0;
821 {
822 if (IS_DEFINED_VAL(progressTotal))
823 {
824 percent = progressCompleted * 100;
825 if (progressTotal != 0)
826 percent /= progressTotal;
827 }
828 }
829 if (percent != _prevPercentValue)
830 {
831 _prevPercentValue = percent;
832 needSetTitle = true;
833 }
834 }
835
836 {
837 wchar_t s[64];
838
839 ConvertUInt64ToString(completedFiles, s);
840 if (_filesStr_Prev != s)
841 {
842 _filesStr_Prev = s;
843 SetItemText(IDT_PROGRESS_FILES_VAL, s);
844 }
845
846 s[0] = 0;
847 if (IS_DEFINED_VAL(totalFiles))
848 {
849 MyStringCopy(s, L" / ");
850 ConvertUInt64ToString(totalFiles, s + MyStringLen(s));
851 }
852 if (_filesTotStr_Prev != s)
853 {
854 _filesTotStr_Prev = s;
855 SetItemText(IDT_PROGRESS_FILES_TOTAL, s);
856 }
857 }
858
859 const UInt64 packSize = CompressingMode ? outSize : inSize;
860 const UInt64 unpackSize = CompressingMode ? inSize : outSize;
861
862 if (IS_UNDEFINED_VAL(unpackSize) &&
863 IS_UNDEFINED_VAL(packSize))
864 {
865 ShowSize(IDT_PROGRESS_PROCESSED_VAL, completed, _processed_Prev);
866 ShowSize(IDT_PROGRESS_PACKED_VAL, UNDEFINED_VAL, _packed_Prev);
867 }
868 else
869 {
870 ShowSize(IDT_PROGRESS_PROCESSED_VAL, unpackSize, _processed_Prev);
871 ShowSize(IDT_PROGRESS_PACKED_VAL, packSize, _packed_Prev);
872
873 if (IS_DEFINED_VAL(packSize) &&
874 IS_DEFINED_VAL(unpackSize) &&
875 unpackSize != 0)
876 {
877 wchar_t s[32];
878 UInt64 ratio = packSize * 100 / unpackSize;
879 if (_ratio_Prev != ratio)
880 {
881 _ratio_Prev = ratio;
882 ConvertUInt64ToString(ratio, s);
883 MyStringCat(s, L"%");
884 SetItemText(IDT_PROGRESS_RATIO_VAL, s);
885 }
886 }
887 }
888 }
889
890 if (needSetTitle || titleFileName_Changed)
891 SetTitleText();
892
893 if (status_Changed)
894 {
895 UString s = _status;
896 ReduceString(s, _numReduceSymbols);
897 SetItemText(IDT_PROGRESS_STATUS, _status);
898 }
899
900 if (curFilePath_Changed)
901 {
902 UString s1, s2;
903 if (_isDir)
904 s1 = _filePath;
905 else
906 {
907 int slashPos = _filePath.ReverseFind_PathSepar();
908 if (slashPos >= 0)
909 {
910 s1.SetFrom(_filePath, (unsigned)(slashPos + 1));
911 s2 = _filePath.Ptr((unsigned)(slashPos + 1));
912 }
913 else
914 s2 = _filePath;
915 }
916 ReduceString(s1, _numReduceSymbols);
917 ReduceString(s2, _numReduceSymbols);
918 s1.Add_LF();
919 s1 += s2;
920 SetItemText(IDT_PROGRESS_FILE_NAME, s1);
921 }
922}
923
924bool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
925{
926 if (Sync.Get_Paused())
927 return true;
928 CheckNeedClose();
929 UpdateStatInfo(false);
930 return true;
931}
932
933struct CWaitCursor
934{
935 HCURSOR _waitCursor;
936 HCURSOR _oldCursor;
937 CWaitCursor()
938 {
939 _waitCursor = LoadCursor(NULL, IDC_WAIT);
940 if (_waitCursor != NULL)
941 _oldCursor = SetCursor(_waitCursor);
942 }
943 ~CWaitCursor()
944 {
945 if (_waitCursor != NULL)
946 SetCursor(_oldCursor);
947 }
948};
949
950INT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, HWND wndParent)
951{
952 INT_PTR res = 0;
953 try
954 {
955 if (WaitMode)
956 {
957 CWaitCursor waitCursor;
958 HANDLE h[] = { thread, _createDialogEvent };
959
960 DWORD res2 = WaitForMultipleObjects(ARRAY_SIZE(h), h, FALSE, kCreateDelay);
961 if (res2 == WAIT_OBJECT_0 && !Sync.ThereIsMessage())
962 return 0;
963 }
964 _title = title;
965 BIG_DIALOG_SIZE(360, 192);
966 res = CModalDialog::Create(SIZED_DIALOG(IDD_PROGRESS), wndParent);
967 }
968 catch(...)
969 {
970 _wasCreated = true;
971 _dialogCreatedEvent.Set();
972 }
973 thread.Wait_Close();
974 if (!MessagesDisplayed)
975 MessageBoxW(wndParent, L"Progress Error", L"7-Zip", MB_ICONERROR);
976 return res;
977}
978
979bool CProgressDialog::OnExternalCloseMessage()
980{
981 // it doesn't work if there is MessageBox.
982 #ifdef __ITaskbarList3_INTERFACE_DEFINED__
983 SetTaskbarProgressState(TBPF_NOPROGRESS);
984 #endif
985 // AddToTitle(L"Finished ");
986 // SetText(L"Finished2 ");
987
988 UpdateStatInfo(true);
989
990 SetItemText(IDCANCEL, LangString(IDS_CLOSE));
991 ::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));
992 HideItem(IDB_PROGRESS_BACKGROUND);
993 HideItem(IDB_PAUSE);
994
995 ProcessWasFinished_GuiVirt();
996
997 bool thereAreMessages;
998 CProgressFinalMessage fm;
999 {
1000 NSynchronization::CCriticalSectionLock lock(Sync._cs);
1001 thereAreMessages = !Sync.Messages.IsEmpty();
1002 fm = Sync.FinalMessage;
1003 }
1004
1005 if (!fm.ErrorMessage.Message.IsEmpty())
1006 {
1007 MessagesDisplayed = true;
1008 if (fm.ErrorMessage.Title.IsEmpty())
1009 fm.ErrorMessage.Title = "7-Zip";
1010 MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR);
1011 }
1012 else if (!thereAreMessages)
1013 {
1014 MessagesDisplayed = true;
1015
1016 if (!fm.OkMessage.Message.IsEmpty())
1017 {
1018 if (fm.OkMessage.Title.IsEmpty())
1019 fm.OkMessage.Title = "7-Zip";
1020 MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK);
1021 }
1022 }
1023
1024 if (thereAreMessages && !_cancelWasPressed)
1025 {
1026 _waitCloseByCancelButton = true;
1027 UpdateMessagesDialog();
1028 return true;
1029 }
1030
1031 End(0);
1032 return true;
1033}
1034
1035bool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
1036{
1037 switch (message)
1038 {
1039 case kCloseMessage:
1040 {
1041 if (_timer)
1042 {
1043 /* 21.03 : KillTimer(kTimerID) instead of KillTimer(_timer).
1044 But (_timer == kTimerID) in Win10. So it worked too */
1045 KillTimer(kTimerID);
1046 _timer = 0;
1047 }
1048 if (_inCancelMessageBox)
1049 {
1050 /* if user is in MessageBox(), we will call OnExternalCloseMessage()
1051 later, when MessageBox() will be closed */
1052 _externalCloseMessageWasReceived = true;
1053 break;
1054 }
1055 return OnExternalCloseMessage();
1056 }
1057 /*
1058 case WM_SETTEXT:
1059 {
1060 if (_timer == 0)
1061 return true;
1062 break;
1063 }
1064 */
1065 }
1066 return CModalDialog::OnMessage(message, wParam, lParam);
1067}
1068
1069void CProgressDialog::SetTitleText()
1070{
1071 UString s;
1072 if (Sync.Get_Paused())
1073 {
1074 s += _paused_String;
1075 s.Add_Space();
1076 }
1077 if (IS_DEFINED_VAL(_prevPercentValue))
1078 {
1079 char temp[32];
1080 ConvertUInt64ToString(_prevPercentValue, temp);
1081 s += temp;
1082 s += '%';
1083 }
1084 if (!_foreground)
1085 {
1086 s.Add_Space();
1087 s += _backgrounded_String;
1088 }
1089
1090 s.Add_Space();
1091 #ifndef _SFX
1092 {
1093 unsigned len = s.Len();
1094 s += MainAddTitle;
1095 AddToTitle(s);
1096 s.DeleteFrom(len);
1097 }
1098 #endif
1099
1100 s += _title;
1101 if (!_titleFileName.IsEmpty())
1102 {
1103 UString fileName = _titleFileName;
1104 ReduceString(fileName, kTitleFileNameSizeLimit);
1105 s.Add_Space();
1106 s += fileName;
1107 }
1108 SetText(s);
1109}
1110
1111void CProgressDialog::SetPauseText()
1112{
1113 SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String);
1114 SetTitleText();
1115}
1116
1117void CProgressDialog::OnPauseButton()
1118{
1119 bool paused = !Sync.Get_Paused();
1120 Sync.Set_Paused(paused);
1121 UInt32 curTime = ::GetTickCount();
1122 if (paused)
1123 _elapsedTime += (curTime - _prevTime);
1124 SetTaskbarProgressState();
1125 _prevTime = curTime;
1126 SetPauseText();
1127}
1128
1129void CProgressDialog::SetPriorityText()
1130{
1131 SetItemText(IDB_PROGRESS_BACKGROUND, _foreground ?
1132 _background_String :
1133 _foreground_String);
1134 SetTitleText();
1135}
1136
1137void CProgressDialog::OnPriorityButton()
1138{
1139 _foreground = !_foreground;
1140 #ifndef UNDER_CE
1141 SetPriorityClass(GetCurrentProcess(), _foreground ? NORMAL_PRIORITY_CLASS: IDLE_PRIORITY_CLASS);
1142 #endif
1143 SetPriorityText();
1144}
1145
1146void CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber)
1147{
1148 wchar_t sz[16];
1149 sz[0] = 0;
1150 if (needNumber)
1151 ConvertUInt32ToString(_numMessages + 1, sz);
1152 const unsigned itemIndex = _messageStrings.Size(); // _messageList.GetItemCount();
1153 if (_messageList.InsertItem((int)itemIndex, sz) == (int)itemIndex)
1154 {
1155 _messageList.SetSubItem((int)itemIndex, 1, message);
1156 _messageStrings.Add(message);
1157 }
1158}
1159
1160void CProgressDialog::AddMessage(LPCWSTR message)
1161{
1162 UString s = message;
1163 bool needNumber = true;
1164 while (!s.IsEmpty())
1165 {
1166 int pos = s.Find(L'\n');
1167 if (pos < 0)
1168 break;
1169 AddMessageDirect(s.Left(pos), needNumber);
1170 needNumber = false;
1171 s.DeleteFrontal(pos + 1);
1172 }
1173 AddMessageDirect(s, needNumber);
1174 _numMessages++;
1175}
1176
1177static unsigned GetNumDigits(UInt32 val)
1178{
1179 unsigned i;
1180 for (i = 0; val >= 10; i++)
1181 val /= 10;
1182 return i;
1183}
1184
1185void CProgressDialog::UpdateMessagesDialog()
1186{
1187 UStringVector messages;
1188 {
1189 NSynchronization::CCriticalSectionLock lock(Sync._cs);
1190 unsigned num = Sync.Messages.Size();
1191 if (num > _numPostedMessages)
1192 {
1193 messages.ClearAndReserve(num - _numPostedMessages);
1194 for (unsigned i = _numPostedMessages; i < num; i++)
1195 messages.AddInReserved(Sync.Messages[i]);
1196 _numPostedMessages = num;
1197 }
1198 }
1199 if (!messages.IsEmpty())
1200 {
1201 FOR_VECTOR (i, messages)
1202 AddMessage(messages[i]);
1203 if (_numAutoSizeMessages < 256 || GetNumDigits(_numPostedMessages) > GetNumDigits(_numAutoSizeMessages))
1204 {
1205 _messageList.SetColumnWidthAuto(0);
1206 _messageList.SetColumnWidthAuto(1);
1207 _numAutoSizeMessages = _numPostedMessages;
1208 }
1209 }
1210}
1211
1212
1213bool CProgressDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
1214{
1215 switch (buttonID)
1216 {
1217 // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON
1218 case IDCANCEL:
1219 {
1220 if (_waitCloseByCancelButton)
1221 {
1222 MessagesDisplayed = true;
1223 End(IDCLOSE);
1224 break;
1225 }
1226
1227 if (_cancelWasPressed)
1228 return true;
1229
1230 const bool paused = Sync.Get_Paused();
1231
1232 if (!paused)
1233 {
1234 OnPauseButton();
1235 }
1236
1237 _inCancelMessageBox = true;
1238 const int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL);
1239 _inCancelMessageBox = false;
1240 if (res == IDYES)
1241 _cancelWasPressed = true;
1242
1243 if (!paused)
1244 {
1245 OnPauseButton();
1246 }
1247
1248 if (_externalCloseMessageWasReceived)
1249 {
1250 /* we have received kCloseMessage while we were in MessageBoxW().
1251 so we call OnExternalCloseMessage() here.
1252 it can show MessageBox and it can close dialog */
1253 OnExternalCloseMessage();
1254 return true;
1255 }
1256
1257 if (!_cancelWasPressed)
1258 return true;
1259
1260 MessagesDisplayed = true;
1261 // we will call Sync.Set_Stopped(true) in OnButtonClicked() : OnCancel()
1262 break;
1263 }
1264
1265 case IDB_PAUSE:
1266 OnPauseButton();
1267 return true;
1268 case IDB_PROGRESS_BACKGROUND:
1269 OnPriorityButton();
1270 return true;
1271 }
1272 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
1273}
1274
1275void CProgressDialog::CheckNeedClose()
1276{
1277 if (_needClose)
1278 {
1279 PostMsg(kCloseMessage);
1280 _needClose = false;
1281 }
1282}
1283
1284void CProgressDialog::ProcessWasFinished()
1285{
1286 // Set Window title here.
1287 if (!WaitMode)
1288 WaitCreating();
1289
1290 if (_wasCreated)
1291 PostMsg(kCloseMessage);
1292 else
1293 _needClose = true;
1294}
1295
1296
1297bool CProgressDialog::OnNotify(UINT /* controlID */, LPNMHDR header)
1298{
1299 if (header->hwndFrom != _messageList)
1300 return false;
1301 switch (header->code)
1302 {
1303 case LVN_KEYDOWN:
1304 {
1305 LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);
1306 switch (keyDownInfo->wVKey)
1307 {
1308 case 'A':
1309 {
1310 if (IsKeyDown(VK_CONTROL))
1311 {
1312 _messageList.SelectAll();
1313 return true;
1314 }
1315 break;
1316 }
1317 case VK_INSERT:
1318 case 'C':
1319 {
1320 if (IsKeyDown(VK_CONTROL))
1321 {
1322 CopyToClipboard();
1323 return true;
1324 }
1325 break;
1326 }
1327 }
1328 }
1329 }
1330 return false;
1331}
1332
1333
1334static void ListView_GetSelected(NControl::CListView &listView, CUIntVector &vector)
1335{
1336 vector.Clear();
1337 int index = -1;
1338 for (;;)
1339 {
1340 index = listView.GetNextSelectedItem(index);
1341 if (index < 0)
1342 break;
1343 vector.Add(index);
1344 }
1345}
1346
1347
1348void CProgressDialog::CopyToClipboard()
1349{
1350 CUIntVector indexes;
1351 ListView_GetSelected(_messageList, indexes);
1352 UString s;
1353 unsigned numIndexes = indexes.Size();
1354 if (numIndexes == 0)
1355 numIndexes = _messageList.GetItemCount();
1356
1357 for (unsigned i = 0; i < numIndexes; i++)
1358 {
1359 const unsigned index = (i < indexes.Size() ? indexes[i] : i);
1360 // s.Add_UInt32(index);
1361 // s += ": ";
1362 s += _messageStrings[index];
1363 {
1364 s +=
1365 #ifdef _WIN32
1366 "\r\n"
1367 #else
1368 "\n"
1369 #endif
1370 ;
1371 }
1372 }
1373
1374 ClipboardSetText(*this, s);
1375}
1376
1377
1378static THREAD_FUNC_DECL MyThreadFunction(void *param)
1379{
1380 CProgressThreadVirt *p = (CProgressThreadVirt *)param;
1381 try
1382 {
1383 p->Process();
1384 p->ThreadFinishedOK = true;
1385 }
1386 catch (...) { p->Result = E_FAIL; }
1387 return 0;
1388}
1389
1390
1391HRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow)
1392{
1393 NWindows::CThread thread;
1394 RINOK(thread.Create(MyThreadFunction, this));
1395 CProgressDialog::Create(title, thread, parentWindow);
1396 return S_OK;
1397}
1398
1399static void AddMessageToString(UString &dest, const UString &src)
1400{
1401 if (!src.IsEmpty())
1402 {
1403 if (!dest.IsEmpty())
1404 dest.Add_LF();
1405 dest += src;
1406 }
1407}
1408
1409void CProgressThreadVirt::Process()
1410{
1411 CProgressCloser closer(*this);
1412 UString m;
1413 try { Result = ProcessVirt(); }
1414 catch(const wchar_t *s) { m = s; }
1415 catch(const UString &s) { m = s; }
1416 catch(const char *s) { m = GetUnicodeString(s); }
1417 catch(int v)
1418 {
1419 m = "Error #";
1420 m.Add_UInt32(v);
1421 }
1422 catch(...) { m = "Error"; }
1423 if (Result != E_ABORT)
1424 {
1425 if (m.IsEmpty() && Result != S_OK)
1426 m = HResultToMessage(Result);
1427 }
1428 AddMessageToString(m, FinalMessage.ErrorMessage.Message);
1429
1430 {
1431 FOR_VECTOR(i, ErrorPaths)
1432 {
1433 if (i >= 32)
1434 break;
1435 AddMessageToString(m, fs2us(ErrorPaths[i]));
1436 }
1437 }
1438
1439 CProgressSync &sync = Sync;
1440 NSynchronization::CCriticalSectionLock lock(sync._cs);
1441 if (m.IsEmpty())
1442 {
1443 if (!FinalMessage.OkMessage.Message.IsEmpty())
1444 sync.FinalMessage.OkMessage = FinalMessage.OkMessage;
1445 }
1446 else
1447 {
1448 sync.FinalMessage.ErrorMessage.Message = m;
1449 if (Result == S_OK)
1450 Result = E_FAIL;
1451 }
1452}
1453
1454UString HResultToMessage(HRESULT errorCode)
1455{
1456 if (errorCode == E_OUTOFMEMORY)
1457 return LangString(IDS_MEM_ERROR);
1458 else
1459 return NError::MyFormatMessage(errorCode);
1460}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.h b/CPP/7zip/UI/FileManager/ProgressDialog2.h
new file mode 100644
index 0000000..d8259d6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.h
@@ -0,0 +1,357 @@
1// ProgressDialog2.h
2
3#ifndef __PROGRESS_DIALOG_2_H
4#define __PROGRESS_DIALOG_2_H
5
6#include "../../../Common/MyCom.h"
7
8#include "../../../Windows/ErrorMsg.h"
9#include "../../../Windows/Synchronization.h"
10#include "../../../Windows/Thread.h"
11
12#include "../../../Windows/Control/Dialog.h"
13#include "../../../Windows/Control/ListView.h"
14#include "../../../Windows/Control/ProgressBar.h"
15
16#include "MyWindowsNew.h"
17
18struct CProgressMessageBoxPair
19{
20 UString Title;
21 UString Message;
22};
23
24struct CProgressFinalMessage
25{
26 CProgressMessageBoxPair ErrorMessage;
27 CProgressMessageBoxPair OkMessage;
28
29 bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); }
30};
31
32class CProgressSync
33{
34 bool _stopped;
35 bool _paused;
36
37public:
38 bool _bytesProgressMode;
39 UInt64 _totalBytes;
40 UInt64 _completedBytes;
41 UInt64 _totalFiles;
42 UInt64 _curFiles;
43 UInt64 _inSize;
44 UInt64 _outSize;
45
46 UString _titleFileName;
47 UString _status;
48 UString _filePath;
49 bool _isDir;
50
51 UStringVector Messages;
52 CProgressFinalMessage FinalMessage;
53
54 NWindows::NSynchronization::CCriticalSection _cs;
55
56 CProgressSync();
57
58 bool Get_Stopped()
59 {
60 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
61 return _stopped;
62 }
63 void Set_Stopped(bool val)
64 {
65 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
66 _stopped = val;
67 }
68
69 bool Get_Paused();
70 void Set_Paused(bool val)
71 {
72 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
73 _paused = val;
74 }
75
76 void Set_BytesProgressMode(bool bytesProgressMode)
77 {
78 NWindows::NSynchronization::CCriticalSectionLock lock(_cs);
79 _bytesProgressMode = bytesProgressMode;
80 }
81
82 HRESULT CheckStop();
83 HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false);
84
85 HRESULT Set_NumFilesTotal(UInt64 val);
86 void Set_NumBytesTotal(UInt64 val);
87 void Set_NumFilesCur(UInt64 val);
88 HRESULT Set_NumBytesCur(const UInt64 *val);
89 HRESULT Set_NumBytesCur(UInt64 val);
90 void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize);
91
92 void Set_TitleFileName(const UString &fileName);
93 void Set_Status(const UString &s);
94 HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false);
95 void Set_FilePath(const wchar_t *path, bool isDir = false);
96
97 void AddError_Message(const wchar_t *message);
98 void AddError_Message_Name(const wchar_t *message, const wchar_t *name);
99 void AddError_Code_Name(DWORD systemError, const wchar_t *name);
100
101 bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); }
102};
103
104class CProgressDialog: public NWindows::NControl::CModalDialog
105{
106 UString _titleFileName;
107 UString _filePath;
108 UString _status;
109 bool _isDir;
110
111 UString _background_String;
112 UString _backgrounded_String;
113 UString _foreground_String;
114 UString _pause_String;
115 UString _continue_String;
116 UString _paused_String;
117
118 int _buttonSizeX;
119 int _buttonSizeY;
120
121 UINT_PTR _timer;
122
123 UString _title;
124
125 class CU64ToI32Converter
126 {
127 unsigned _numShiftBits;
128 UInt64 _range;
129 public:
130 CU64ToI32Converter(): _numShiftBits(0), _range(1) {}
131 void Init(UInt64 range)
132 {
133 _range = range;
134 // Windows CE doesn't like big number for ProgressBar.
135 for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++)
136 range >>= 1;
137 }
138 int Count(UInt64 val)
139 {
140 int res = (int)(val >> _numShiftBits);
141 if (val == _range)
142 res++;
143 return res;
144 }
145 };
146
147 CU64ToI32Converter _progressConv;
148 UInt64 _progressBar_Pos;
149 UInt64 _progressBar_Range;
150
151 NWindows::NControl::CProgressBar m_ProgressBar;
152 NWindows::NControl::CListView _messageList;
153
154 int _numMessages;
155 UStringVector _messageStrings;
156
157 #ifdef __ITaskbarList3_INTERFACE_DEFINED__
158 CMyComPtr<ITaskbarList3> _taskbarList;
159 #endif
160 HWND _hwndForTaskbar;
161
162 UInt32 _prevTime;
163 UInt64 _elapsedTime;
164
165 UInt64 _prevPercentValue;
166 UInt64 _prevElapsedSec;
167 UInt64 _prevRemainingSec;
168
169 UInt64 _totalBytes_Prev;
170 UInt64 _processed_Prev;
171 UInt64 _packed_Prev;
172 UInt64 _ratio_Prev;
173
174 UString _filesStr_Prev;
175 UString _filesTotStr_Prev;
176
177 unsigned _prevSpeed_MoveBits;
178 UInt64 _prevSpeed;
179
180 bool _foreground;
181
182 unsigned _numReduceSymbols;
183
184 bool _wasCreated;
185 bool _needClose;
186
187 unsigned _numPostedMessages;
188 UInt32 _numAutoSizeMessages;
189
190 bool _errorsWereDisplayed;
191
192 bool _waitCloseByCancelButton;
193 bool _cancelWasPressed;
194
195 bool _inCancelMessageBox;
196 bool _externalCloseMessageWasReceived;
197
198
199 #ifdef __ITaskbarList3_INTERFACE_DEFINED__
200 void SetTaskbarProgressState(TBPFLAG tbpFlags)
201 {
202 if (_taskbarList && _hwndForTaskbar)
203 _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags);
204 }
205 #endif
206 void SetTaskbarProgressState();
207
208 void UpdateStatInfo(bool showAll);
209 bool OnTimer(WPARAM timerID, LPARAM callback);
210 void SetProgressRange(UInt64 range);
211 void SetProgressPos(UInt64 pos);
212 virtual bool OnInit();
213 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
214 virtual void OnCancel();
215 virtual void OnOK();
216 virtual bool OnNotify(UINT /* controlID */, LPNMHDR header);
217 void CopyToClipboard();
218
219 NWindows::NSynchronization::CManualResetEvent _createDialogEvent;
220 NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;
221 #ifndef _SFX
222 void AddToTitle(LPCWSTR string);
223 #endif
224
225 void SetPauseText();
226 void SetPriorityText();
227 void OnPauseButton();
228 void OnPriorityButton();
229 bool OnButtonClicked(int buttonID, HWND buttonHWND);
230 bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
231
232 void SetTitleText();
233 void ShowSize(int id, UInt64 val, UInt64 &prev);
234
235 void UpdateMessagesDialog();
236
237 void AddMessageDirect(LPCWSTR message, bool needNumber);
238 void AddMessage(LPCWSTR message);
239
240 bool OnExternalCloseMessage();
241 void EnableErrorsControls(bool enable);
242
243 void ShowAfterMessages(HWND wndParent);
244
245 void CheckNeedClose();
246public:
247 CProgressSync Sync;
248 bool CompressingMode;
249 bool WaitMode;
250 bool ShowCompressionInfo;
251 bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages.
252 int IconID;
253
254 HWND MainWindow;
255 #ifndef _SFX
256 UString MainTitle;
257 UString MainAddTitle;
258 ~CProgressDialog();
259 #endif
260
261 CProgressDialog();
262 void WaitCreating()
263 {
264 _createDialogEvent.Set();
265 _dialogCreatedEvent.Lock();
266 }
267
268 INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = 0);
269
270
271 /* how it works:
272 1) the working thread calls ProcessWasFinished()
273 that sends kCloseMessage message to CProgressDialog (GUI) thread
274 2) CProgressDialog (GUI) thread receives kCloseMessage message and
275 calls ProcessWasFinished_GuiVirt();
276 So we can implement ProcessWasFinished_GuiVirt() and show special
277 results window in GUI thread with CProgressDialog as parent window
278 */
279
280 void ProcessWasFinished();
281 virtual void ProcessWasFinished_GuiVirt() {}
282};
283
284
285class CProgressCloser
286{
287 CProgressDialog *_p;
288public:
289 CProgressCloser(CProgressDialog &p) : _p(&p) {}
290 ~CProgressCloser() { _p->ProcessWasFinished(); }
291};
292
293
294class CProgressThreadVirt: public CProgressDialog
295{
296protected:
297 FStringVector ErrorPaths;
298 CProgressFinalMessage FinalMessage;
299
300 // error if any of HRESULT, ErrorMessage, ErrorPath
301 virtual HRESULT ProcessVirt() = 0;
302public:
303 HRESULT Result;
304 bool ThreadFinishedOK; // if there is no fatal exception
305
306 void Process();
307 void AddErrorPath(const FString &path) { ErrorPaths.Add(path); }
308
309 HRESULT Create(const UString &title, HWND parentWindow = 0);
310 CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}
311
312 CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; }
313};
314
315UString HResultToMessage(HRESULT errorCode);
316
317/*
318how it works:
319
320client code inherits CProgressThreadVirt and calls
321CProgressThreadVirt::Create()
322{
323 it creates new thread that calls CProgressThreadVirt::Process();
324 it creates modal progress dialog window with ProgressDialog.Create()
325}
326
327CProgressThreadVirt::Process()
328{
329 {
330 Result = ProcessVirt(); // virtual function that must implement real work
331 }
332 if (exceptions) or FinalMessage.ErrorMessage.Message
333 {
334 set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message
335 }
336 else if (FinalMessage.OkMessage.Message)
337 {
338 set message to ProgressDialog.Sync.FinalMessage.OkMessage
339 }
340
341 PostMsg(kCloseMessage);
342}
343
344
345CProgressDialog::OnExternalCloseMessage()
346{
347 if (ProgressDialog.Sync.FinalMessage)
348 {
349 WorkWasFinishedVirt();
350 Show (ProgressDialog.Sync.FinalMessage)
351 MessagesDisplayed = true;
352 }
353}
354
355*/
356
357#endif
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2.rc b/CPP/7zip/UI/FileManager/ProgressDialog2.rc
new file mode 100644
index 0000000..4d0e0c7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2.rc
@@ -0,0 +1,40 @@
1#include "ProgressDialog2Res.h"
2#include "../../GuiCommon.rc"
3
4#undef DIALOG_ID
5#define DIALOG_ID IDD_PROGRESS
6#define xc 360
7#define k 11
8#define z1s 16
9
10#include "ProgressDialog2a.rc"
11
12#ifdef UNDER_CE
13
14#include "../../GuiCommon.rc"
15
16
17#undef DIALOG_ID
18#undef m
19#undef k
20#undef z1s
21
22#define DIALOG_ID IDD_PROGRESS_2
23#define m 4
24#define k 8
25#define z1s 12
26
27#define xc 280
28
29#include "ProgressDialog2a.rc"
30
31#endif
32
33STRINGTABLE DISCARDABLE
34{
35 IDS_PROGRESS_PAUSED "Paused"
36 IDS_PROGRESS_FOREGROUND "&Foreground"
37 IDS_CONTINUE "&Continue"
38 IDS_PROGRESS_ASK_CANCEL "Are you sure you want to cancel?"
39 IDS_CLOSE "&Close"
40}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2Res.h b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h
new file mode 100644
index 0000000..736c717
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2Res.h
@@ -0,0 +1,49 @@
1#define IDD_PROGRESS 97
2#define IDD_PROGRESS_2 10097
3
4#define IDS_CLOSE 408
5#define IDS_CONTINUE 411
6
7#define IDB_PROGRESS_BACKGROUND 444
8#define IDS_PROGRESS_FOREGROUND 445
9#define IDB_PAUSE 446
10#define IDS_PROGRESS_PAUSED 447
11#define IDS_PROGRESS_ASK_CANCEL 448
12
13#define IDT_PROGRESS_PACKED 1008
14#define IDT_PROGRESS_FILES 1032
15
16#define IDT_PROGRESS_ELAPSED 3900
17#define IDT_PROGRESS_REMAINING 3901
18#define IDT_PROGRESS_TOTAL 3902
19#define IDT_PROGRESS_SPEED 3903
20#define IDT_PROGRESS_PROCESSED 3904
21#define IDT_PROGRESS_RATIO 3905
22#define IDT_PROGRESS_ERRORS 3906
23
24#define IDC_PROGRESS1 100
25#define IDL_PROGRESS_MESSAGES 101
26#define IDT_PROGRESS_FILE_NAME 102
27#define IDT_PROGRESS_STATUS 103
28
29#define IDT_PROGRESS_PACKED_VAL 110
30#define IDT_PROGRESS_FILES_VAL 111
31#define IDT_PROGRESS_FILES_TOTAL 112
32
33#define IDT_PROGRESS_ELAPSED_VAL 120
34#define IDT_PROGRESS_REMAINING_VAL 121
35#define IDT_PROGRESS_TOTAL_VAL 122
36#define IDT_PROGRESS_SPEED_VAL 123
37#define IDT_PROGRESS_PROCESSED_VAL 124
38#define IDT_PROGRESS_RATIO_VAL 125
39#define IDT_PROGRESS_ERRORS_VAL 126
40
41
42#ifdef UNDER_CE
43#define MY_PROGRESS_VAL_UNITS 44
44#else
45#define MY_PROGRESS_VAL_UNITS 72
46#endif
47#define MY_PROGRESS_LABEL_UNITS_MIN 60
48#define MY_PROGRESS_LABEL_UNITS_START 90
49#define MY_PROGRESS_PAD_UNITS 4
diff --git a/CPP/7zip/UI/FileManager/ProgressDialog2a.rc b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc
new file mode 100644
index 0000000..dc7d797
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialog2a.rc
@@ -0,0 +1,85 @@
1#undef bxs
2#define bxs 80
3
4#define x0s MY_PROGRESS_LABEL_UNITS_START
5#define x1s MY_PROGRESS_VAL_UNITS
6#define x2s MY_PROGRESS_LABEL_UNITS_START
7#define x3s MY_PROGRESS_VAL_UNITS
8
9#define x1 (m + x0s)
10#define x3 (xs - m - x3s)
11#define x2 (x3 - x2s)
12
13#undef y0
14#undef y1
15#undef y2
16#undef y3
17#undef y4
18
19#undef z0
20#undef z1
21#undef z2
22#undef z3
23
24#define y0 m
25#define y1 (y0 + k)
26#define y2 (y1 + k)
27#define y3 (y2 + k)
28#define y4 (y3 + k)
29
30#define z3 (y4 + k + 1)
31
32#define z2 (z3 + k + 1)
33#define z2s 24
34
35#define z1 (z2 + z2s)
36
37#define z0 (z1 + z1s + m)
38#define z0s 48
39
40#define yc (z0 + z0s + bys)
41
42
43DIALOG_ID DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
44CAPTION "Progress"
45{
46 DEFPUSHBUTTON "&Background", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys
47 PUSHBUTTON "&Pause", IDB_PAUSE, bx2, by, bxs, bys
48 PUSHBUTTON "Cancel", IDCANCEL, bx1, by, bxs, bys
49
50
51 LTEXT "Elapsed time:", IDT_PROGRESS_ELAPSED, m, y0, x0s, 8
52 LTEXT "Remaining time:", IDT_PROGRESS_REMAINING, m, y1, x0s, 8
53 LTEXT "Files:", IDT_PROGRESS_FILES, m, y2, x0s, 8
54
55 LTEXT "Errors:", IDT_PROGRESS_ERRORS, m, y4, x0s, 8
56
57
58 LTEXT "Total size:", IDT_PROGRESS_TOTAL, x2, y0, x2s, 8
59 LTEXT "Speed:", IDT_PROGRESS_SPEED, x2, y1, x2s, 8
60 LTEXT "Processed:", IDT_PROGRESS_PROCESSED,x2, y2, x2s, 8
61 LTEXT "Compressed size:" , IDT_PROGRESS_PACKED, x2, y3, x2s, 8
62 LTEXT "Compression ratio:", IDT_PROGRESS_RATIO, x2, y4, x2s, 8
63
64
65 RTEXT "", IDT_PROGRESS_ELAPSED_VAL, x1, y0, x1s, MY_TEXT_NOPREFIX
66 RTEXT "", IDT_PROGRESS_REMAINING_VAL, x1, y1, x1s, MY_TEXT_NOPREFIX
67 RTEXT "", IDT_PROGRESS_FILES_VAL, x1, y2, x1s, MY_TEXT_NOPREFIX
68 RTEXT "", IDT_PROGRESS_FILES_TOTAL, x1, y3, x1s, MY_TEXT_NOPREFIX
69 RTEXT "", IDT_PROGRESS_ERRORS_VAL, x1, y4, x1s, MY_TEXT_NOPREFIX
70
71 RTEXT "", IDT_PROGRESS_TOTAL_VAL, x3, y0, x3s, MY_TEXT_NOPREFIX
72 RTEXT "", IDT_PROGRESS_SPEED_VAL, x3, y1, x3s, MY_TEXT_NOPREFIX
73 RTEXT "", IDT_PROGRESS_PROCESSED_VAL, x3, y2, x3s, MY_TEXT_NOPREFIX
74 RTEXT "", IDT_PROGRESS_PACKED_VAL, x3, y3, x3s, MY_TEXT_NOPREFIX
75 RTEXT "", IDT_PROGRESS_RATIO_VAL, x3, y4, x3s, MY_TEXT_NOPREFIX
76
77 LTEXT "", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX
78 CONTROL "", IDT_PROGRESS_FILE_NAME, "Static", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s
79
80 CONTROL "Progress1", IDC_PROGRESS1, "msctls_progress32", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s
81
82 CONTROL "List1", IDL_PROGRESS_MESSAGES, "SysListView32",
83 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
84 m, z0, xc, z0s
85}
diff --git a/CPP/7zip/UI/FileManager/ProgressDialogRes.h b/CPP/7zip/UI/FileManager/ProgressDialogRes.h
new file mode 100644
index 0000000..cbf3beb
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ProgressDialogRes.h
@@ -0,0 +1,3 @@
1#define IDD_PROGRESS 97
2
3#define IDC_PROGRESS1 100
diff --git a/CPP/7zip/UI/FileManager/PropertyName.cpp b/CPP/7zip/UI/FileManager/PropertyName.cpp
new file mode 100644
index 0000000..838b6e3
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PropertyName.cpp
@@ -0,0 +1,23 @@
1// PropertyName.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6
7#include "LangUtils.h"
8#include "PropertyName.h"
9
10UString GetNameOfProperty(PROPID propID, const wchar_t *name)
11{
12 if (propID < 1000)
13 {
14 UString s = LangString(1000 + propID);
15 if (!s.IsEmpty())
16 return s;
17 }
18 if (name)
19 return name;
20 wchar_t temp[16];
21 ConvertUInt32ToString(propID, temp);
22 return temp;
23}
diff --git a/CPP/7zip/UI/FileManager/PropertyName.h b/CPP/7zip/UI/FileManager/PropertyName.h
new file mode 100644
index 0000000..4f0d6dc
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PropertyName.h
@@ -0,0 +1,10 @@
1// PropertyName.h
2
3#ifndef __PROPERTY_NAME_H
4#define __PROPERTY_NAME_H
5
6#include "../../../Common/MyString.h"
7
8UString GetNameOfProperty(PROPID propID, const wchar_t *name);
9
10#endif
diff --git a/CPP/7zip/UI/FileManager/PropertyName.rc b/CPP/7zip/UI/FileManager/PropertyName.rc
new file mode 100644
index 0000000..5de5aee
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PropertyName.rc
@@ -0,0 +1,100 @@
1#include "PropertyNameRes.h"
2
3LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
4
5STRINGTABLE
6BEGIN
7 IDS_PROP_PATH "Path"
8 IDS_PROP_NAME "Name"
9 IDS_PROP_EXTENSION "Extension"
10 IDS_PROP_IS_FOLDER "Folder"
11 IDS_PROP_SIZE "Size"
12 IDS_PROP_PACKED_SIZE "Packed Size"
13 IDS_PROP_ATTRIBUTES "Attributes"
14 IDS_PROP_CTIME "Created"
15 IDS_PROP_ATIME "Accessed"
16 IDS_PROP_MTIME "Modified"
17 IDS_PROP_SOLID "Solid"
18 IDS_PROP_C0MMENTED "Commented"
19 IDS_PROP_ENCRYPTED "Encrypted"
20 IDS_PROP_SPLIT_BEFORE "Split Before"
21 IDS_PROP_SPLIT_AFTER "Split After"
22 IDS_PROP_DICTIONARY_SIZE "Dictionary"
23 IDS_PROP_CRC "CRC"
24 IDS_PROP_FILE_TYPE "Type"
25 IDS_PROP_ANTI "Anti"
26 IDS_PROP_METHOD "Method"
27 IDS_PROP_HOST_OS "Host OS"
28 IDS_PROP_FILE_SYSTEM "File System"
29 IDS_PROP_USER "User"
30 IDS_PROP_GROUP "Group"
31 IDS_PROP_BLOCK "Block"
32 IDS_PROP_COMMENT "Comment"
33 IDS_PROP_POSITION "Position"
34 IDS_PROP_PREFIX "Path Prefix"
35 IDS_PROP_FOLDERS "Folders"
36 IDS_PROP_FILES "Files"
37 IDS_PROP_VERSION "Version"
38 IDS_PROP_VOLUME "Volume"
39 IDS_PROP_IS_VOLUME "Multivolume"
40 IDS_PROP_OFFSET "Offset"
41 IDS_PROP_LINKS "Links"
42 IDS_PROP_NUM_BLOCKS "Blocks"
43 IDS_PROP_NUM_VOLUMES "Volumes"
44
45 IDS_PROP_BIT64 "64-bit"
46 IDS_PROP_BIG_ENDIAN "Big-endian"
47 IDS_PROP_CPU "CPU"
48 IDS_PROP_PHY_SIZE "Physical Size"
49 IDS_PROP_HEADERS_SIZE "Headers Size"
50 IDS_PROP_CHECKSUM "Checksum"
51 IDS_PROP_CHARACTS "Characteristics"
52 IDS_PROP_VA "Virtual Address"
53 IDS_PROP_ID "ID"
54 IDS_PROP_SHORT_NAME "Short Name"
55 IDS_PROP_CREATOR_APP "Creator Application"
56 IDS_PROP_SECTOR_SIZE "Sector Size"
57 IDS_PROP_POSIX_ATTRIB "Mode"
58 IDS_PROP_SYM_LINK "Symbolic Link"
59 IDS_PROP_ERROR "Error"
60 IDS_PROP_TOTAL_SIZE "Total Size"
61 IDS_PROP_FREE_SPACE "Free Space"
62 IDS_PROP_CLUSTER_SIZE "Cluster Size"
63 IDS_PROP_VOLUME_NAME "Label"
64 IDS_PROP_LOCAL_NAME "Local Name"
65 IDS_PROP_PROVIDER "Provider"
66 IDS_PROP_NT_SECURITY "NT Security"
67 IDS_PROP_ALT_STREAM "Alternate Stream"
68 IDS_PROP_AUX "Aux"
69 IDS_PROP_DELETED "Deleted"
70 IDS_PROP_IS_TREE "Is Tree"
71 IDS_PROP_SHA1 "SHA-1"
72 IDS_PROP_SHA256 "SHA-256"
73 IDS_PROP_ERROR_TYPE "Error Type"
74 IDS_PROP_NUM_ERRORS "Errors"
75 IDS_PROP_ERROR_FLAGS "Errors"
76 IDS_PROP_WARNING_FLAGS "Warnings"
77 IDS_PROP_WARNING "Warning"
78 IDS_PROP_NUM_STREAMS "Streams"
79 IDS_PROP_NUM_ALT_STREAMS "Alternate Streams"
80 IDS_PROP_ALT_STREAMS_SIZE "Alternate Streams Size"
81 IDS_PROP_VIRTUAL_SIZE "Virtual Size"
82 IDS_PROP_UNPACK_SIZE "Unpack Size"
83 IDS_PROP_TOTAL_PHY_SIZE "Total Physical Size"
84 IDS_PROP_VOLUME_INDEX "Volume Index"
85 IDS_PROP_SUBTYPE "SubType"
86 IDS_PROP_SHORT_COMMENT "Short Comment"
87 IDS_PROP_CODE_PAGE "Code Page"
88 IDS_PROP_IS_NOT_ARC_TYPE "Is not archive type"
89 IDS_PROP_PHY_SIZE_CANT_BE_DETECTED "Physical Size can't be detected"
90 IDS_PROP_ZEROS_TAIL_IS_ALLOWED "Zeros Tail Is Allowed"
91 IDS_PROP_TAIL_SIZE "Tail Size"
92 IDS_PROP_EMB_STUB_SIZE "Embedded Stub Size"
93 IDS_PROP_NT_REPARSE "Link"
94 IDS_PROP_HARD_LINK "Hard Link"
95 IDS_PROP_INODE "iNode"
96 IDS_PROP_STREAM_ID "Stream ID"
97 IDS_PROP_READ_ONLY "Read-only"
98 IDS_PROP_OUT_NAME "Out Name"
99 IDS_PROP_COPY_LINK "Copy Link"
100END
diff --git a/CPP/7zip/UI/FileManager/PropertyNameRes.h b/CPP/7zip/UI/FileManager/PropertyNameRes.h
new file mode 100644
index 0000000..67f3390
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/PropertyNameRes.h
@@ -0,0 +1,95 @@
1
2
3#define IDS_PROP_PATH 1003
4#define IDS_PROP_NAME 1004
5#define IDS_PROP_EXTENSION 1005
6#define IDS_PROP_IS_FOLDER 1006
7#define IDS_PROP_SIZE 1007
8#define IDS_PROP_PACKED_SIZE 1008
9#define IDS_PROP_ATTRIBUTES 1009
10#define IDS_PROP_CTIME 1010
11#define IDS_PROP_ATIME 1011
12#define IDS_PROP_MTIME 1012
13#define IDS_PROP_SOLID 1013
14#define IDS_PROP_C0MMENTED 1014
15#define IDS_PROP_ENCRYPTED 1015
16#define IDS_PROP_SPLIT_BEFORE 1016
17#define IDS_PROP_SPLIT_AFTER 1017
18#define IDS_PROP_DICTIONARY_SIZE 1018
19#define IDS_PROP_CRC 1019
20#define IDS_PROP_FILE_TYPE 1020
21#define IDS_PROP_ANTI 1021
22#define IDS_PROP_METHOD 1022
23#define IDS_PROP_HOST_OS 1023
24#define IDS_PROP_FILE_SYSTEM 1024
25#define IDS_PROP_USER 1025
26#define IDS_PROP_GROUP 1026
27#define IDS_PROP_BLOCK 1027
28#define IDS_PROP_COMMENT 1028
29#define IDS_PROP_POSITION 1029
30#define IDS_PROP_PREFIX 1030
31#define IDS_PROP_FOLDERS 1031
32#define IDS_PROP_FILES 1032
33#define IDS_PROP_VERSION 1033
34#define IDS_PROP_VOLUME 1034
35#define IDS_PROP_IS_VOLUME 1035
36#define IDS_PROP_OFFSET 1036
37#define IDS_PROP_LINKS 1037
38#define IDS_PROP_NUM_BLOCKS 1038
39#define IDS_PROP_NUM_VOLUMES 1039
40
41#define IDS_PROP_BIT64 1041
42#define IDS_PROP_BIG_ENDIAN 1042
43#define IDS_PROP_CPU 1043
44#define IDS_PROP_PHY_SIZE 1044
45#define IDS_PROP_HEADERS_SIZE 1045
46#define IDS_PROP_CHECKSUM 1046
47#define IDS_PROP_CHARACTS 1047
48#define IDS_PROP_VA 1048
49#define IDS_PROP_ID 1049
50#define IDS_PROP_SHORT_NAME 1050
51#define IDS_PROP_CREATOR_APP 1051
52#define IDS_PROP_SECTOR_SIZE 1052
53#define IDS_PROP_POSIX_ATTRIB 1053
54#define IDS_PROP_SYM_LINK 1054
55#define IDS_PROP_ERROR 1055
56#define IDS_PROP_TOTAL_SIZE 1056
57#define IDS_PROP_FREE_SPACE 1057
58#define IDS_PROP_CLUSTER_SIZE 1058
59#define IDS_PROP_VOLUME_NAME 1059
60#define IDS_PROP_LOCAL_NAME 1060
61#define IDS_PROP_PROVIDER 1061
62#define IDS_PROP_NT_SECURITY 1062
63#define IDS_PROP_ALT_STREAM 1063
64#define IDS_PROP_AUX 1064
65#define IDS_PROP_DELETED 1065
66#define IDS_PROP_IS_TREE 1066
67#define IDS_PROP_SHA1 1067
68#define IDS_PROP_SHA256 1068
69#define IDS_PROP_ERROR_TYPE 1069
70#define IDS_PROP_NUM_ERRORS 1070
71#define IDS_PROP_ERROR_FLAGS 1071
72#define IDS_PROP_WARNING_FLAGS 1072
73#define IDS_PROP_WARNING 1073
74#define IDS_PROP_NUM_STREAMS 1074
75#define IDS_PROP_NUM_ALT_STREAMS 1075
76#define IDS_PROP_ALT_STREAMS_SIZE 1076
77#define IDS_PROP_VIRTUAL_SIZE 1077
78#define IDS_PROP_UNPACK_SIZE 1078
79#define IDS_PROP_TOTAL_PHY_SIZE 1079
80#define IDS_PROP_VOLUME_INDEX 1080
81#define IDS_PROP_SUBTYPE 1081
82#define IDS_PROP_SHORT_COMMENT 1082
83#define IDS_PROP_CODE_PAGE 1083
84#define IDS_PROP_IS_NOT_ARC_TYPE 1084
85#define IDS_PROP_PHY_SIZE_CANT_BE_DETECTED 1085
86#define IDS_PROP_ZEROS_TAIL_IS_ALLOWED 1086
87#define IDS_PROP_TAIL_SIZE 1087
88#define IDS_PROP_EMB_STUB_SIZE 1088
89#define IDS_PROP_NT_REPARSE 1089
90#define IDS_PROP_HARD_LINK 1090
91#define IDS_PROP_INODE 1091
92#define IDS_PROP_STREAM_ID 1092
93#define IDS_PROP_READ_ONLY 1093
94#define IDS_PROP_OUT_NAME 1094
95#define IDS_PROP_COPY_LINK 1095
diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.cpp b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
new file mode 100644
index 0000000..e48dbb4
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RegistryAssociations.cpp
@@ -0,0 +1,167 @@
1// RegistryAssociations.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6#include "../../../Common/StringConvert.h"
7#include "../../../Common/StringToInt.h"
8
9#include "../../../Windows/Registry.h"
10
11#include "RegistryAssociations.h"
12
13using namespace NWindows;
14using namespace NRegistry;
15
16namespace NRegistryAssoc {
17
18// static NSynchronization::CCriticalSection g_CriticalSection;
19
20static const TCHAR * const kClasses = TEXT("Software\\Classes\\");
21// static const TCHAR * const kShellNewKeyName = TEXT("ShellNew");
22// static const TCHAR * const kShellNewDataValueName = TEXT("Data");
23static const TCHAR * const kDefaultIconKeyName = TEXT("DefaultIcon");
24static const TCHAR * const kShellKeyName = TEXT("shell");
25static const TCHAR * const kOpenKeyName = TEXT("open");
26static const TCHAR * const kCommandKeyName = TEXT("command");
27static const char * const k7zipPrefix = "7-Zip.";
28
29static CSysString GetExtProgramKeyName(const CSysString &ext)
30{
31 return CSysString(k7zipPrefix) + ext;
32}
33
34static CSysString GetFullKeyPath(HKEY hkey, const CSysString &name)
35{
36 CSysString s;
37 if (hkey != HKEY_CLASSES_ROOT)
38 s = kClasses;
39 return s + name;
40}
41
42static CSysString GetExtKeyPath(HKEY hkey, const CSysString &ext)
43{
44 return GetFullKeyPath(hkey, (TEXT(".")) + ext);
45}
46
47bool CShellExtInfo::ReadFromRegistry(HKEY hkey, const CSysString &ext)
48{
49 ProgramKey.Empty();
50 IconPath.Empty();
51 IconIndex = -1;
52 // NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
53 {
54 CKey extKey;
55 if (extKey.Open(hkey, GetExtKeyPath(hkey, ext), KEY_READ) != ERROR_SUCCESS)
56 return false;
57 if (extKey.QueryValue(NULL, ProgramKey) != ERROR_SUCCESS)
58 return false;
59 }
60 {
61 CKey iconKey;
62
63 if (iconKey.Open(hkey, GetFullKeyPath(hkey, ProgramKey + CSysString(CHAR_PATH_SEPARATOR) + kDefaultIconKeyName), KEY_READ) == ERROR_SUCCESS)
64 {
65 UString value;
66 if (iconKey.QueryValue(NULL, value) == ERROR_SUCCESS)
67 {
68 int pos = value.ReverseFind(L',');
69 IconPath = value;
70 if (pos >= 0)
71 {
72 const wchar_t *end;
73 Int32 index = ConvertStringToInt32((const wchar_t *)value + pos + 1, &end);
74 if (*end == 0)
75 {
76 // 9.31: if there is no icon index, we use -1. Is it OK?
77 if (pos != (int)value.Len() - 1)
78 IconIndex = (int)index;
79 IconPath.SetFrom(value, pos);
80 }
81 }
82 }
83 }
84 }
85 return true;
86}
87
88bool CShellExtInfo::IsIt7Zip() const
89{
90 return ProgramKey.IsPrefixedBy_Ascii_NoCase(k7zipPrefix);
91}
92
93LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext)
94{
95 // NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
96 CKey rootKey;
97 rootKey.Attach(hkey);
98 LONG res = rootKey.RecurseDeleteKey(GetExtKeyPath(hkey, ext));
99 // then we delete only 7-Zip.* key.
100 rootKey.RecurseDeleteKey(GetFullKeyPath(hkey, GetExtProgramKeyName(ext)));
101 rootKey.Detach();
102 return res;
103}
104
105LONG AddShellExtensionInfo(HKEY hkey,
106 const CSysString &ext,
107 const UString &programTitle,
108 const UString &programOpenCommand,
109 const UString &iconPath, int iconIndex
110 // , const void *shellNewData, int shellNewDataSize
111 )
112{
113 LONG res = 0;
114 DeleteShellExtensionInfo(hkey, ext);
115 // NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
116 CSysString programKeyName;
117 {
118 CSysString ext2 (ext);
119 if (iconIndex < 0)
120 ext2 = "*";
121 programKeyName = GetExtProgramKeyName(ext2);
122 }
123 {
124 CKey extKey;
125 res = extKey.Create(hkey, GetExtKeyPath(hkey, ext));
126 extKey.SetValue(NULL, programKeyName);
127 /*
128 if (shellNewData != NULL)
129 {
130 CKey shellNewKey;
131 shellNewKey.Create(extKey, kShellNewKeyName);
132 shellNewKey.SetValue(kShellNewDataValueName, shellNewData, shellNewDataSize);
133 }
134 */
135 }
136 CKey programKey;
137 programKey.Create(hkey, GetFullKeyPath(hkey, programKeyName));
138 programKey.SetValue(NULL, programTitle);
139 {
140 CKey iconKey;
141 UString iconPathFull = iconPath;
142 if (iconIndex < 0)
143 iconIndex = 0;
144 // if (iconIndex >= 0)
145 {
146 iconPathFull += ',';
147 iconPathFull.Add_UInt32((UInt32)iconIndex);
148 }
149 iconKey.Create(programKey, kDefaultIconKeyName);
150 iconKey.SetValue(NULL, iconPathFull);
151 }
152
153 CKey shellKey;
154 shellKey.Create(programKey, kShellKeyName);
155 shellKey.SetValue(NULL, TEXT(""));
156
157 CKey openKey;
158 openKey.Create(shellKey, kOpenKeyName);
159 openKey.SetValue(NULL, TEXT(""));
160
161 CKey commandKey;
162 commandKey.Create(openKey, kCommandKeyName);
163 commandKey.SetValue(NULL, programOpenCommand);
164 return res;
165}
166
167}
diff --git a/CPP/7zip/UI/FileManager/RegistryAssociations.h b/CPP/7zip/UI/FileManager/RegistryAssociations.h
new file mode 100644
index 0000000..975c9d5
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RegistryAssociations.h
@@ -0,0 +1,31 @@
1// RegistryAssociations.h
2
3#ifndef __REGISTRY_ASSOCIATIONS_H
4#define __REGISTRY_ASSOCIATIONS_H
5
6#include "../../../Common/MyString.h"
7
8namespace NRegistryAssoc {
9
10 struct CShellExtInfo
11 {
12 CSysString ProgramKey;
13 UString IconPath;
14 int IconIndex;
15
16 bool ReadFromRegistry(HKEY hkey, const CSysString &ext);
17 bool IsIt7Zip() const;
18 };
19
20 LONG DeleteShellExtensionInfo(HKEY hkey, const CSysString &ext);
21
22 LONG AddShellExtensionInfo(HKEY hkey,
23 const CSysString &ext,
24 const UString &programTitle,
25 const UString &programOpenCommand,
26 const UString &iconPath, int iconIndex
27 // , const void *shellNewData, int shellNewDataSize
28 );
29}
30
31#endif
diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.cpp b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp
new file mode 100644
index 0000000..76a5787
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RegistryPlugins.cpp
@@ -0,0 +1,139 @@
1// RegistryPlugins.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/DLL.h"
6#include "../../../Windows/FileFind.h"
7#include "../../../Windows/PropVariant.h"
8
9#include "IFolder.h"
10#include "RegistryPlugins.h"
11
12using namespace NWindows;
13using namespace NFile;
14
15/*
16static LPCTSTR const kLMBasePath = TEXT("Software\\7-Zip\\FM");
17
18static LPCTSTR const kPluginsKeyName = TEXT("Plugins");
19static LPCTSTR const kPluginsOpenClassIDValue = TEXT("CLSID");
20static LPCTSTR const kPluginsOptionsClassIDValue = TEXT("Options");
21static LPCTSTR const kPluginsTypeValue = TEXT("Type");
22
23static CSysString GetFileFolderPluginsKeyName()
24{
25 return CSysString(kLMBasePath) + CSysString(TEXT('\\')) +
26 CSysString(kPluginsKeyName);
27}
28
29*/
30
31typedef UINT32 (WINAPI * GetPluginPropertyFunc)(PROPID propID, PROPVARIANT *value);
32
33static bool ReadPluginInfo(CPluginInfo &pluginInfo, bool needCheckDll)
34{
35 if (needCheckDll)
36 {
37 NDLL::CLibrary lib;
38 if (!lib.LoadEx(pluginInfo.FilePath, LOAD_LIBRARY_AS_DATAFILE))
39 return false;
40 }
41 NDLL::CLibrary lib;
42 if (!lib.Load(pluginInfo.FilePath))
43 return false;
44 GetPluginPropertyFunc getPluginProperty = (GetPluginPropertyFunc)lib.GetProc("GetPluginProperty");
45 if (getPluginProperty == NULL)
46 return false;
47
48 NCOM::CPropVariant prop;
49 if (getPluginProperty(NPlugin::kName, &prop) != S_OK)
50 return false;
51 if (prop.vt != VT_BSTR)
52 return false;
53 pluginInfo.Name = prop.bstrVal;
54 prop.Clear();
55
56 if (getPluginProperty(NPlugin::kClassID, &prop) != S_OK)
57 return false;
58 if (prop.vt == VT_EMPTY)
59 pluginInfo.ClassIDDefined = false;
60 else if (prop.vt != VT_BSTR)
61 return false;
62 else
63 {
64 pluginInfo.ClassIDDefined = true;
65 pluginInfo.ClassID = *(const GUID *)(const void *)prop.bstrVal;
66 }
67 prop.Clear();
68
69 if (getPluginProperty(NPlugin::kOptionsClassID, &prop) != S_OK)
70 return false;
71 if (prop.vt == VT_EMPTY)
72 pluginInfo.OptionsClassIDDefined = false;
73 else if (prop.vt != VT_BSTR)
74 return false;
75 else
76 {
77 pluginInfo.OptionsClassIDDefined = true;
78 pluginInfo.OptionsClassID = *(const GUID *)(const void *)prop.bstrVal;
79 }
80 prop.Clear();
81
82 if (getPluginProperty(NPlugin::kType, &prop) != S_OK)
83 return false;
84 if (prop.vt == VT_EMPTY)
85 pluginInfo.Type = kPluginTypeFF;
86 else if (prop.vt == VT_UI4)
87 pluginInfo.Type = (EPluginType)prop.ulVal;
88 else
89 return false;
90 return true;
91}
92
93void ReadPluginInfoList(CObjectVector<CPluginInfo> &plugins)
94{
95 plugins.Clear();
96
97 FString baseFolderPrefix = NDLL::GetModuleDirPrefix();
98 {
99 CPluginInfo pluginInfo;
100 pluginInfo.FilePath = baseFolderPrefix + FTEXT("7-zip.dll");
101 if (::ReadPluginInfo(pluginInfo, false))
102 plugins.Add(pluginInfo);
103 }
104 FString folderPath = baseFolderPrefix;
105 folderPath += "Plugins" STRING_PATH_SEPARATOR;
106 NFind::CEnumerator enumerator;
107 enumerator.SetDirPrefix(folderPath);
108 NFind::CFileInfo fileInfo;
109 while (enumerator.Next(fileInfo))
110 {
111 if (fileInfo.IsDir())
112 continue;
113 CPluginInfo pluginInfo;
114 pluginInfo.FilePath = folderPath + fileInfo.Name;
115 if (::ReadPluginInfo(pluginInfo, true))
116 plugins.Add(pluginInfo);
117 }
118}
119
120void ReadFileFolderPluginInfoList(CObjectVector<CPluginInfo> &plugins)
121{
122 ReadPluginInfoList(plugins);
123 for (unsigned i = 0; i < plugins.Size();)
124 if (plugins[i].Type != kPluginTypeFF)
125 plugins.Delete(i);
126 else
127 i++;
128 {
129 CPluginInfo p;
130 // p.FilePath.Empty();
131 p.Type = kPluginTypeFF;
132 p.Name = "7-Zip";
133 // p.ClassID = CLSID_CAgentArchiveHandler;
134 p.ClassIDDefined = true;
135 // p.OptionsClassID;
136 p.OptionsClassIDDefined = false;
137 plugins.Add(p);
138 }
139}
diff --git a/CPP/7zip/UI/FileManager/RegistryPlugins.h b/CPP/7zip/UI/FileManager/RegistryPlugins.h
new file mode 100644
index 0000000..dfa6de5
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RegistryPlugins.h
@@ -0,0 +1,32 @@
1// RegistryPlugins.h
2
3#ifndef __REGISTRY_PLUGINS_H
4#define __REGISTRY_PLUGINS_H
5
6#include "../../../Common/MyString.h"
7
8enum EPluginType
9{
10 kPluginTypeFF = 0
11};
12
13struct CPluginInfo
14{
15 FString FilePath;
16 EPluginType Type;
17 UString Name;
18 CLSID ClassID;
19 CLSID OptionsClassID;
20 bool ClassIDDefined;
21 bool OptionsClassIDDefined;
22
23 // CSysString Extension;
24 // CSysString AddExtension;
25 // bool UpdateEnabled;
26 // bool KeepName;
27};
28
29void ReadPluginInfoList(CObjectVector<CPluginInfo> &plugins);
30void ReadFileFolderPluginInfoList(CObjectVector<CPluginInfo> &plugins);
31
32#endif
diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.cpp b/CPP/7zip/UI/FileManager/RegistryUtils.cpp
new file mode 100644
index 0000000..a2fc201
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RegistryUtils.cpp
@@ -0,0 +1,191 @@
1// RegistryUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/IntToString.h"
6
7#include "../../../Windows/Registry.h"
8
9#include "RegistryUtils.h"
10
11using namespace NWindows;
12using namespace NRegistry;
13
14#define REG_PATH_7Z TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip")
15
16static LPCTSTR const kCUBasePath = REG_PATH_7Z;
17static LPCTSTR const kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM");
18// static LPCTSTR const kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT("FM");
19
20static LPCWSTR const kLangValueName = L"Lang";
21
22static LPCWSTR const kViewer = L"Viewer";
23static LPCWSTR const kEditor = L"Editor";
24static LPCWSTR const kDiff = L"Diff";
25static LPCWSTR const kVerCtrlPath = L"7vc";
26
27static LPCTSTR const kShowDots = TEXT("ShowDots");
28static LPCTSTR const kShowRealFileIcons = TEXT("ShowRealFileIcons");
29static LPCTSTR const kFullRow = TEXT("FullRow");
30static LPCTSTR const kShowGrid = TEXT("ShowGrid");
31static LPCTSTR const kSingleClick = TEXT("SingleClick");
32static LPCTSTR const kAlternativeSelection = TEXT("AlternativeSelection");
33// static LPCTSTR const kUnderline = TEXT("Underline");
34
35static LPCTSTR const kShowSystemMenu = TEXT("ShowSystemMenu");
36
37// static LPCTSTR const kLockMemoryAdd = TEXT("LockMemoryAdd");
38static LPCTSTR const kLargePages = TEXT("LargePages");
39
40static LPCTSTR const kFlatViewName = TEXT("FlatViewArc");
41// static LPCTSTR const kShowDeletedFiles = TEXT("ShowDeleted");
42
43static void SaveCuString(LPCTSTR keyPath, LPCWSTR valuePath, LPCWSTR value)
44{
45 CKey key;
46 key.Create(HKEY_CURRENT_USER, keyPath);
47 key.SetValue(valuePath, value);
48}
49
50static void ReadCuString(LPCTSTR keyPath, LPCWSTR valuePath, UString &res)
51{
52 res.Empty();
53 CKey key;
54 if (key.Open(HKEY_CURRENT_USER, keyPath, KEY_READ) == ERROR_SUCCESS)
55 key.QueryValue(valuePath, res);
56}
57
58void SaveRegLang(const UString &path) { SaveCuString(kCUBasePath, kLangValueName, path); }
59void ReadRegLang(UString &path) { ReadCuString(kCUBasePath, kLangValueName, path); }
60
61void SaveRegEditor(bool useEditor, const UString &path) { SaveCuString(kCU_FMPath, useEditor ? kEditor : kViewer, path); }
62void ReadRegEditor(bool useEditor, UString &path) { ReadCuString(kCU_FMPath, useEditor ? kEditor : kViewer, path); }
63
64void SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); }
65void ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); }
66
67void ReadReg_VerCtrlPath(UString &path) { ReadCuString(kCU_FMPath, kVerCtrlPath, path); }
68
69static void Save7ZipOption(LPCTSTR value, bool enabled)
70{
71 CKey key;
72 key.Create(HKEY_CURRENT_USER, kCUBasePath);
73 key.SetValue(value, enabled);
74}
75
76static void SaveOption(LPCTSTR value, bool enabled)
77{
78 CKey key;
79 key.Create(HKEY_CURRENT_USER, kCU_FMPath);
80 key.SetValue(value, enabled);
81}
82
83static bool Read7ZipOption(LPCTSTR value, bool defaultValue)
84{
85 CKey key;
86 if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)
87 {
88 bool enabled;
89 if (key.QueryValue(value, enabled) == ERROR_SUCCESS)
90 return enabled;
91 }
92 return defaultValue;
93}
94
95static void ReadOption(CKey &key, LPCTSTR value, bool &dest)
96{
97 bool enabled = false;
98 if (key.QueryValue(value, enabled) == ERROR_SUCCESS)
99 dest = enabled;
100}
101
102/*
103static void SaveLmOption(LPCTSTR value, bool enabled)
104{
105 CKey key;
106 key.Create(HKEY_LOCAL_MACHINE, kLM_Path);
107 key.SetValue(value, enabled);
108}
109
110static bool ReadLmOption(LPCTSTR value, bool defaultValue)
111{
112 CKey key;
113 if (key.Open(HKEY_LOCAL_MACHINE, kLM_Path, KEY_READ) == ERROR_SUCCESS)
114 {
115 bool enabled;
116 if (key.QueryValue(value, enabled) == ERROR_SUCCESS)
117 return enabled;
118 }
119 return defaultValue;
120}
121*/
122
123void CFmSettings::Save() const
124{
125 SaveOption(kShowDots, ShowDots);
126 SaveOption(kShowRealFileIcons, ShowRealFileIcons);
127 SaveOption(kFullRow, FullRow);
128 SaveOption(kShowGrid, ShowGrid);
129 SaveOption(kSingleClick, SingleClick);
130 SaveOption(kAlternativeSelection, AlternativeSelection);
131 // SaveOption(kUnderline, Underline);
132
133 SaveOption(kShowSystemMenu, ShowSystemMenu);
134}
135
136void CFmSettings::Load()
137{
138 ShowDots = false;
139 ShowRealFileIcons = false;
140 FullRow = false;
141 ShowGrid = false;
142 SingleClick = false;
143 AlternativeSelection = false;
144 // Underline = false;
145
146 ShowSystemMenu = false;
147
148 CKey key;
149 if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS)
150 {
151 ReadOption(key, kShowDots, ShowDots);
152 ReadOption(key, kShowRealFileIcons, ShowRealFileIcons);
153 ReadOption(key, kFullRow, FullRow);
154 ReadOption(key, kShowGrid, ShowGrid);
155 ReadOption(key, kSingleClick, SingleClick);
156 ReadOption(key, kAlternativeSelection, AlternativeSelection);
157 // ReadOption(key, kUnderline, Underline);
158
159 ReadOption(key, kShowSystemMenu, ShowSystemMenu );
160 }
161}
162
163
164// void SaveLockMemoryAdd(bool enable) { SaveLmOption(kLockMemoryAdd, enable); }
165// bool ReadLockMemoryAdd() { return ReadLmOption(kLockMemoryAdd, true); }
166
167void SaveLockMemoryEnable(bool enable) { Save7ZipOption(kLargePages, enable); }
168bool ReadLockMemoryEnable() { return Read7ZipOption(kLargePages, false); }
169
170static CSysString GetFlatViewName(UInt32 panelIndex)
171{
172 TCHAR panelString[16];
173 ConvertUInt32ToString(panelIndex, panelString);
174 return (CSysString)kFlatViewName + panelString;
175}
176
177void SaveFlatView(UInt32 panelIndex, bool enable) { SaveOption(GetFlatViewName(panelIndex), enable); }
178
179bool ReadFlatView(UInt32 panelIndex)
180{
181 bool enabled = false;
182 CKey key;
183 if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS)
184 ReadOption(key, GetFlatViewName(panelIndex), enabled);
185 return enabled;
186}
187
188/*
189void Save_ShowDeleted(bool enable) { SaveOption(kShowDeletedFiles, enable); }
190bool Read_ShowDeleted() { return ReadOption(kShowDeletedFiles, false); }
191*/
diff --git a/CPP/7zip/UI/FileManager/RegistryUtils.h b/CPP/7zip/UI/FileManager/RegistryUtils.h
new file mode 100644
index 0000000..b85d670
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RegistryUtils.h
@@ -0,0 +1,50 @@
1// RegistryUtils.h
2
3#ifndef __REGISTRY_UTILS_H
4#define __REGISTRY_UTILS_H
5
6#include "../../../Common/MyTypes.h"
7#include "../../../Common/MyString.h"
8
9void SaveRegLang(const UString &path);
10void ReadRegLang(UString &path);
11
12void SaveRegEditor(bool useEditor, const UString &path);
13void ReadRegEditor(bool useEditor, UString &path);
14
15void SaveRegDiff(const UString &path);
16void ReadRegDiff(UString &path);
17
18void ReadReg_VerCtrlPath(UString &path);
19
20struct CFmSettings
21{
22 bool ShowDots;
23 bool ShowRealFileIcons;
24 bool FullRow;
25 bool ShowGrid;
26 bool SingleClick;
27 bool AlternativeSelection;
28 // bool Underline;
29
30 bool ShowSystemMenu;
31
32 void Save() const;
33 void Load();
34};
35
36// void SaveLockMemoryAdd(bool enable);
37// bool ReadLockMemoryAdd();
38
39bool ReadLockMemoryEnable();
40void SaveLockMemoryEnable(bool enable);
41
42void SaveFlatView(UInt32 panelIndex, bool enable);
43bool ReadFlatView(UInt32 panelIndex);
44
45/*
46void Save_ShowDeleted(bool enable);
47bool Read_ShowDeleted();
48*/
49
50#endif
diff --git a/CPP/7zip/UI/FileManager/RootFolder.cpp b/CPP/7zip/UI/FileManager/RootFolder.cpp
new file mode 100644
index 0000000..84844c7
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RootFolder.cpp
@@ -0,0 +1,318 @@
1// RootFolder.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyWindows.h"
6
7#include <ShlObj.h>
8
9#include "../../../Common/StringConvert.h"
10
11#include "../../../Windows/DLL.h"
12#include "../../../Windows/FileName.h"
13#include "../../../Windows/PropVariant.h"
14
15#include "../../PropID.h"
16
17#if defined(_WIN32) && !defined(UNDER_CE)
18#define USE_WIN_PATHS
19#endif
20
21static const unsigned kNumRootFolderItems =
22 #ifdef USE_WIN_PATHS
23 4
24 #else
25 1
26 #endif
27 ;
28
29
30#include "FSFolder.h"
31#include "LangUtils.h"
32#ifdef USE_WIN_PATHS
33#include "NetFolder.h"
34#include "FSDrives.h"
35#include "AltStreamsFolder.h"
36#endif
37#include "RootFolder.h"
38#include "SysIconUtils.h"
39
40#include "resource.h"
41
42using namespace NWindows;
43
44static const Byte kProps[] =
45{
46 kpidName
47};
48
49UString RootFolder_GetName_Computer(int &iconIndex);
50UString RootFolder_GetName_Computer(int &iconIndex)
51{
52 #ifdef USE_WIN_PATHS
53 iconIndex = GetIconIndexForCSIDL(CSIDL_DRIVES);
54 #else
55 GetRealIconIndex(FSTRING_PATH_SEPARATOR, FILE_ATTRIBUTE_DIRECTORY, iconIndex);
56 #endif
57 return LangString(IDS_COMPUTER);
58}
59
60UString RootFolder_GetName_Network(int &iconIndex);
61UString RootFolder_GetName_Network(int &iconIndex)
62{
63 iconIndex = GetIconIndexForCSIDL(CSIDL_NETWORK);
64 return LangString(IDS_NETWORK);
65}
66
67UString RootFolder_GetName_Documents(int &iconIndex);
68UString RootFolder_GetName_Documents(int &iconIndex)
69{
70 iconIndex = GetIconIndexForCSIDL(CSIDL_PERSONAL);
71 return LangString(IDS_DOCUMENTS);
72}
73
74enum
75{
76 ROOT_INDEX_COMPUTER = 0
77 #ifdef USE_WIN_PATHS
78 , ROOT_INDEX_DOCUMENTS
79 , ROOT_INDEX_NETWORK
80 , ROOT_INDEX_VOLUMES
81 #endif
82};
83
84#ifdef USE_WIN_PATHS
85static const char * const kVolPrefix = "\\\\.";
86#endif
87
88void CRootFolder::Init()
89{
90 _names[ROOT_INDEX_COMPUTER] = RootFolder_GetName_Computer(_iconIndices[ROOT_INDEX_COMPUTER]);
91 #ifdef USE_WIN_PATHS
92 _names[ROOT_INDEX_DOCUMENTS] = RootFolder_GetName_Documents(_iconIndices[ROOT_INDEX_DOCUMENTS]);
93 _names[ROOT_INDEX_NETWORK] = RootFolder_GetName_Network(_iconIndices[ROOT_INDEX_NETWORK]);
94 _names[ROOT_INDEX_VOLUMES] = kVolPrefix;
95 _iconIndices[ROOT_INDEX_VOLUMES] = GetIconIndexForCSIDL(CSIDL_DRIVES);
96 #endif
97}
98
99STDMETHODIMP CRootFolder::LoadItems()
100{
101 Init();
102 return S_OK;
103}
104
105STDMETHODIMP CRootFolder::GetNumberOfItems(UInt32 *numItems)
106{
107 *numItems = kNumRootFolderItems;
108 return S_OK;
109}
110
111STDMETHODIMP CRootFolder::GetProperty(UInt32 itemIndex, PROPID propID, PROPVARIANT *value)
112{
113 NCOM::CPropVariant prop;
114 switch (propID)
115 {
116 case kpidIsDir: prop = true; break;
117 case kpidName: prop = _names[itemIndex]; break;
118 }
119 prop.Detach(value);
120 return S_OK;
121}
122
123typedef BOOL (WINAPI *SHGetSpecialFolderPathWp)(HWND hwnd, LPWSTR pszPath, int csidl, BOOL fCreate);
124typedef BOOL (WINAPI *SHGetSpecialFolderPathAp)(HWND hwnd, LPSTR pszPath, int csidl, BOOL fCreate);
125
126static UString GetMyDocsPath()
127{
128 UString us;
129 WCHAR s[MAX_PATH + 1];
130 SHGetSpecialFolderPathWp getW = (SHGetSpecialFolderPathWp)
131 #ifdef UNDER_CE
132 My_GetProcAddress(GetModuleHandle(TEXT("coredll.dll")), "SHGetSpecialFolderPath");
133 #else
134 My_GetProcAddress(GetModuleHandle(TEXT("shell32.dll")), "SHGetSpecialFolderPathW");
135 #endif
136 if (getW && getW(0, s, CSIDL_PERSONAL, FALSE))
137 us = s;
138 #ifndef _UNICODE
139 else
140 {
141 SHGetSpecialFolderPathAp getA = (SHGetSpecialFolderPathAp)
142 (void *)::GetProcAddress(::GetModuleHandleA("shell32.dll"), "SHGetSpecialFolderPathA");
143 CHAR s2[MAX_PATH + 1];
144 if (getA && getA(0, s2, CSIDL_PERSONAL, FALSE))
145 us = GetUnicodeString(s2);
146 }
147 #endif
148 NFile::NName::NormalizeDirPathPrefix(us);
149 return us;
150}
151
152STDMETHODIMP CRootFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
153{
154 *resultFolder = NULL;
155 CMyComPtr<IFolderFolder> subFolder;
156
157 #ifdef USE_WIN_PATHS
158 if (index == ROOT_INDEX_COMPUTER || index == ROOT_INDEX_VOLUMES)
159 {
160 CFSDrives *fsDrivesSpec = new CFSDrives;
161 subFolder = fsDrivesSpec;
162 fsDrivesSpec->Init(index == ROOT_INDEX_VOLUMES);
163 }
164 else if (index == ROOT_INDEX_NETWORK)
165 {
166 CNetFolder *netFolderSpec = new CNetFolder;
167 subFolder = netFolderSpec;
168 netFolderSpec->Init(0, 0, _names[ROOT_INDEX_NETWORK] + WCHAR_PATH_SEPARATOR);
169 }
170 else if (index == ROOT_INDEX_DOCUMENTS)
171 {
172 UString s = GetMyDocsPath();
173 if (!s.IsEmpty())
174 {
175 NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
176 subFolder = fsFolderSpec;
177 RINOK(fsFolderSpec->Init(us2fs(s)));
178 }
179 }
180 #else
181 if (index == ROOT_INDEX_COMPUTER)
182 {
183 NFsFolder::CFSFolder *fsFolder = new NFsFolder::CFSFolder;
184 subFolder = fsFolder;
185 fsFolder->InitToRoot();
186 }
187 #endif
188 else
189 return E_INVALIDARG;
190
191 *resultFolder = subFolder.Detach();
192 return S_OK;
193}
194
195static bool AreEqualNames(const UString &path, const wchar_t *name)
196{
197 unsigned len = MyStringLen(name);
198 if (len > path.Len() || len + 1 < path.Len())
199 return false;
200 if (len + 1 == path.Len() && !IS_PATH_SEPAR(path[len]))
201 return false;
202 return path.IsPrefixedBy(name);
203}
204
205STDMETHODIMP CRootFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
206{
207 *resultFolder = 0;
208 UString name2 = name;
209 name2.Trim();
210
211 if (name2.IsEmpty())
212 {
213 CRootFolder *rootFolderSpec = new CRootFolder;
214 CMyComPtr<IFolderFolder> rootFolder = rootFolderSpec;
215 rootFolderSpec->Init();
216 *resultFolder = rootFolder.Detach();
217 return S_OK;
218 }
219
220 for (unsigned i = 0; i < kNumRootFolderItems; i++)
221 if (AreEqualNames(name2, _names[i]))
222 return BindToFolder((UInt32)i, resultFolder);
223
224 #ifdef USE_WIN_PATHS
225 if (AreEqualNames(name2, L"My Documents") ||
226 AreEqualNames(name2, L"Documents"))
227 return BindToFolder((UInt32)ROOT_INDEX_DOCUMENTS, resultFolder);
228 #else
229 if (name2 == WSTRING_PATH_SEPARATOR)
230 return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
231 #endif
232
233 if (AreEqualNames(name2, L"My Computer") ||
234 AreEqualNames(name2, L"Computer"))
235 return BindToFolder((UInt32)ROOT_INDEX_COMPUTER, resultFolder);
236
237 if (name2 == WSTRING_PATH_SEPARATOR)
238 {
239 CMyComPtr<IFolderFolder> subFolder = this;
240 *resultFolder = subFolder.Detach();
241 return S_OK;
242 }
243
244 if (name2.Len() < 2)
245 return E_INVALIDARG;
246
247 CMyComPtr<IFolderFolder> subFolder;
248
249 #ifdef USE_WIN_PATHS
250 if (name2.IsPrefixedBy_Ascii_NoCase(kVolPrefix))
251 {
252 CFSDrives *folderSpec = new CFSDrives;
253 subFolder = folderSpec;
254 folderSpec->Init(true);
255 }
256 else if (name2.IsEqualTo(NFile::NName::kSuperPathPrefix))
257 {
258 CFSDrives *folderSpec = new CFSDrives;
259 subFolder = folderSpec;
260 folderSpec->Init(false, true);
261 }
262 else if (name2.Back() == ':')
263 {
264 NAltStreamsFolder::CAltStreamsFolder *folderSpec = new NAltStreamsFolder::CAltStreamsFolder;
265 subFolder = folderSpec;
266 if (folderSpec->Init(us2fs(name2)) != S_OK)
267 return E_INVALIDARG;
268 }
269 else
270 #endif
271 {
272 NFile::NName::NormalizeDirPathPrefix(name2);
273 NFsFolder::CFSFolder *fsFolderSpec = new NFsFolder::CFSFolder;
274 subFolder = fsFolderSpec;
275 if (fsFolderSpec->Init(us2fs(name2)) != S_OK)
276 {
277 #ifdef USE_WIN_PATHS
278 if (IS_PATH_SEPAR(name2[0]))
279 {
280 CNetFolder *netFolderSpec = new CNetFolder;
281 subFolder = netFolderSpec;
282 netFolderSpec->Init(name2);
283 }
284 else
285 #endif
286 return E_INVALIDARG;
287 }
288 }
289
290 *resultFolder = subFolder.Detach();
291 return S_OK;
292}
293
294STDMETHODIMP CRootFolder::BindToParentFolder(IFolderFolder **resultFolder)
295{
296 *resultFolder = 0;
297 return S_OK;
298}
299
300IMP_IFolderFolder_Props(CRootFolder)
301
302STDMETHODIMP CRootFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
303{
304 NCOM::CPropVariant prop;
305 switch (propID)
306 {
307 case kpidType: prop = "RootFolder"; break;
308 case kpidPath: prop = ""; break;
309 }
310 prop.Detach(value);
311 return S_OK;
312}
313
314STDMETHODIMP CRootFolder::GetSystemIconIndex(UInt32 index, Int32 *iconIndex)
315{
316 *iconIndex = _iconIndices[index];
317 return S_OK;
318}
diff --git a/CPP/7zip/UI/FileManager/RootFolder.h b/CPP/7zip/UI/FileManager/RootFolder.h
new file mode 100644
index 0000000..e253783
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/RootFolder.h
@@ -0,0 +1,27 @@
1// RootFolder.h
2
3#ifndef __ROOT_FOLDER_H
4#define __ROOT_FOLDER_H
5
6#include "../../../Common/MyString.h"
7
8#include "IFolder.h"
9
10const unsigned kNumRootFolderItems_Max = 4;
11
12class CRootFolder:
13 public IFolderFolder,
14 public IFolderGetSystemIconIndex,
15 public CMyUnknownImp
16{
17 UString _names[kNumRootFolderItems_Max];
18 int _iconIndices[kNumRootFolderItems_Max];
19
20public:
21 MY_UNKNOWN_IMP1(IFolderGetSystemIconIndex)
22 INTERFACE_FolderFolder(;)
23 STDMETHOD(GetSystemIconIndex)(UInt32 index, Int32 *iconIndex);
24 void Init();
25};
26
27#endif
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.cpp b/CPP/7zip/UI/FileManager/SettingsPage.cpp
new file mode 100644
index 0000000..2868721
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SettingsPage.cpp
@@ -0,0 +1,350 @@
1// SettingsPage.cpp
2
3#include "StdAfx.h"
4
5// #include "../../../Common/IntToString.h"
6// #include "../../../Common/StringConvert.h"
7
8#ifndef UNDER_CE
9#include "../../../Windows/MemoryLock.h"
10// #include "../../../Windows/System.h"
11#endif
12
13// #include "../Common/ZipRegistry.h"
14
15#include "HelpUtils.h"
16#include "LangUtils.h"
17#include "RegistryUtils.h"
18#include "SettingsPage.h"
19#include "SettingsPageRes.h"
20
21using namespace NWindows;
22
23static const UInt32 kLangIDs[] =
24{
25 IDX_SETTINGS_SHOW_DOTS,
26 IDX_SETTINGS_SHOW_REAL_FILE_ICONS,
27 IDX_SETTINGS_SHOW_SYSTEM_MENU,
28 IDX_SETTINGS_FULL_ROW,
29 IDX_SETTINGS_SHOW_GRID,
30 IDX_SETTINGS_SINGLE_CLICK,
31 IDX_SETTINGS_ALTERNATIVE_SELECTION,
32 IDX_SETTINGS_LARGE_PAGES
33 // , IDT_COMPRESS_MEMORY
34};
35
36#define kSettingsTopic "FM/options.htm#settings"
37
38extern bool IsLargePageSupported();
39
40/*
41static void AddMemSize(UString &res, UInt64 size, bool needRound = false)
42{
43 char c;
44 unsigned moveBits = 0;
45 if (needRound)
46 {
47 UInt64 rn = 0;
48 if (size >= (1 << 31))
49 rn = (1 << 28) - 1;
50 UInt32 kRound = (1 << 20) - 1;
51 if (rn < kRound)
52 rn = kRound;
53 size += rn;
54 size &= ~rn;
55 }
56 if (size >= ((UInt64)1 << 31) && (size & 0x3FFFFFFF) == 0)
57 { moveBits = 30; c = 'G'; }
58 else
59 { moveBits = 20; c = 'M'; }
60 res.Add_UInt64(size >> moveBits);
61 res.Add_Space();
62 if (moveBits != 0)
63 res += c;
64 res += 'B';
65}
66
67
68int CSettingsPage::AddMemComboItem(UInt64 size, UInt64 percents, bool isDefault)
69{
70 UString sUser;
71 UString sRegistry;
72 if (size == 0)
73 {
74 UString s;
75 s.Add_UInt64(percents);
76 s += '%';
77 if (isDefault)
78 sUser = "* ";
79 else
80 sRegistry = s;
81 sUser += s;
82 }
83 else
84 {
85 AddMemSize(sUser, size);
86 sRegistry = sUser;
87 for (;;)
88 {
89 int pos = sRegistry.Find(L' ');
90 if (pos < 0)
91 break;
92 sRegistry.Delete(pos);
93 }
94 if (!sRegistry.IsEmpty())
95 if (sRegistry.Back() == 'B')
96 sRegistry.DeleteBack();
97 }
98 const int index = (int)_memCombo.AddString(sUser);
99 _memCombo.SetItemData(index, _memLimitStrings.Size());
100 _memLimitStrings.Add(sRegistry);
101 return index;
102}
103*/
104
105bool CSettingsPage::OnInit()
106{
107 _wasChanged = false;
108 _largePages_wasChanged = false;
109 /*
110 _wasChanged_MemLimit = false;
111 _memLimitStrings.Clear();
112 _memCombo.Attach(GetItem(IDC_SETTINGS_MEM));
113 */
114
115 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
116
117 CFmSettings st;
118 st.Load();
119
120 CheckButton(IDX_SETTINGS_SHOW_DOTS, st.ShowDots);
121 CheckButton(IDX_SETTINGS_SHOW_REAL_FILE_ICONS, st.ShowRealFileIcons);
122 CheckButton(IDX_SETTINGS_FULL_ROW, st.FullRow);
123 CheckButton(IDX_SETTINGS_SHOW_GRID, st.ShowGrid);
124 CheckButton(IDX_SETTINGS_SINGLE_CLICK, st.SingleClick);
125 CheckButton(IDX_SETTINGS_ALTERNATIVE_SELECTION, st.AlternativeSelection);
126 // CheckButton(IDX_SETTINGS_UNDERLINE, st.Underline);
127
128 CheckButton(IDX_SETTINGS_SHOW_SYSTEM_MENU, st.ShowSystemMenu);
129
130 if (IsLargePageSupported())
131 CheckButton(IDX_SETTINGS_LARGE_PAGES, ReadLockMemoryEnable());
132 else
133 EnableItem(IDX_SETTINGS_LARGE_PAGES, false);
134
135
136 /*
137 NCompression::CMemUse mu;
138 bool needSetCur = NCompression::MemLimit_Load(mu);
139 UInt64 curMemLimit;
140 {
141 AddMemComboItem(0, 90, true);
142 _memCombo.SetCurSel(0);
143 }
144 if (mu.IsPercent)
145 {
146 const int index = AddMemComboItem(0, mu.Val);
147 _memCombo.SetCurSel(index);
148 needSetCur = false;
149 }
150 {
151 _ramSize = (UInt64)(sizeof(size_t)) << 29;
152 _ramSize_Defined = NSystem::GetRamSize(_ramSize);
153 UString s;
154 if (_ramSize_Defined)
155 {
156 s += "/ ";
157 AddMemSize(s, _ramSize, true);
158 }
159 SetItemText(IDT_SETTINGS_MEM_RAM, s);
160
161 curMemLimit = mu.GetBytes(_ramSize);
162
163 // size = 100 << 20; // for debug only;
164 for (unsigned i = (27) * 2;; i++)
165 {
166 UInt64 size = (UInt64)(2 + (i & 1)) << (i / 2);
167 if (i > (20 + sizeof(size_t) * 3 * 1 - 1) * 2)
168 size = (UInt64)(Int64)-1;
169 if (needSetCur && (size >= curMemLimit))
170 {
171 const int index = AddMemComboItem(curMemLimit);
172 _memCombo.SetCurSel(index);
173 needSetCur = false;
174 if (size == curMemLimit)
175 continue;
176 }
177 if (size == (UInt64)(Int64)-1)
178 break;
179 AddMemComboItem(size);
180 }
181 }
182 */
183
184 // EnableSubItems();
185
186 return CPropertyPage::OnInit();
187}
188
189/*
190void CSettingsPage::EnableSubItems()
191{
192 EnableItem(IDX_SETTINGS_UNDERLINE, IsButtonCheckedBool(IDX_SETTINGS_SINGLE_CLICK));
193}
194*/
195
196/*
197static void AddSize_MB(UString &s, UInt64 size)
198{
199 s.Add_UInt64((size + (1 << 20) - 1) >> 20);
200 s += " MB";
201}
202*/
203
204LONG CSettingsPage::OnApply()
205{
206 if (_wasChanged)
207 {
208 CFmSettings st;
209 st.ShowDots = IsButtonCheckedBool(IDX_SETTINGS_SHOW_DOTS);
210 st.ShowRealFileIcons = IsButtonCheckedBool(IDX_SETTINGS_SHOW_REAL_FILE_ICONS);
211 st.FullRow = IsButtonCheckedBool(IDX_SETTINGS_FULL_ROW);
212 st.ShowGrid = IsButtonCheckedBool(IDX_SETTINGS_SHOW_GRID);
213 st.SingleClick = IsButtonCheckedBool(IDX_SETTINGS_SINGLE_CLICK);
214 st.AlternativeSelection = IsButtonCheckedBool(IDX_SETTINGS_ALTERNATIVE_SELECTION);
215 // st.Underline = IsButtonCheckedBool(IDX_SETTINGS_UNDERLINE);
216
217 st.ShowSystemMenu = IsButtonCheckedBool(IDX_SETTINGS_SHOW_SYSTEM_MENU);
218
219 st.Save();
220 _wasChanged = false;
221 }
222
223 #ifndef UNDER_CE
224 if (_largePages_wasChanged)
225 {
226 if (IsLargePageSupported())
227 {
228 bool enable = IsButtonCheckedBool(IDX_SETTINGS_LARGE_PAGES);
229 NSecurity::EnablePrivilege_LockMemory(enable);
230 SaveLockMemoryEnable(enable);
231 }
232 _largePages_wasChanged = false;
233 }
234 #endif
235
236 /*
237 if (_wasChanged_MemLimit)
238 {
239 const unsigned index = (int)_memCombo.GetItemData_of_CurSel();
240 const UString str = _memLimitStrings[index];
241
242 bool needSave = true;
243
244 NCompression::CMemUse mu;
245
246 if (_ramSize_Defined)
247 mu.Parse(str);
248 if (mu.IsDefined)
249 {
250 const UInt64 usage64 = mu.GetBytes(_ramSize);
251 if (_ramSize <= usage64)
252 {
253 UString s2 = LangString(IDT_COMPRESS_MEMORY);
254 if (s2.IsEmpty())
255 GetItemText(IDT_COMPRESS_MEMORY, s2);
256 UString s;
257
258 s += "The selected value is not safe for system performance.";
259 s.Add_LF();
260 s += "The memory consumption for compression operation will exceed RAM size.";
261 s.Add_LF();
262 s.Add_LF();
263 AddSize_MB(s, usage64);
264
265 if (!s2.IsEmpty())
266 {
267 s += " : ";
268 s += s2;
269 }
270
271 s.Add_LF();
272 AddSize_MB(s, _ramSize);
273 s += " : RAM";
274
275 s.Add_LF();
276 s.Add_LF();
277 s += "Are you sure you want set that unsafe value for memory usage?";
278
279 int res = MessageBoxW(*this, s, L"7-Zip", MB_YESNOCANCEL | MB_ICONQUESTION);
280 if (res != IDYES)
281 needSave = false;
282 }
283 }
284
285 if (needSave)
286 {
287 NCompression::MemLimit_Save(str);
288 _wasChanged_MemLimit = false;
289 }
290 else
291 return PSNRET_INVALID_NOCHANGEPAGE;
292 }
293 */
294
295 return PSNRET_NOERROR;
296}
297
298void CSettingsPage::OnNotifyHelp()
299{
300 ShowHelpWindow(kSettingsTopic);
301}
302
303/*
304bool CSettingsPage::OnCommand(int code, int itemID, LPARAM param)
305{
306 if (code == CBN_SELCHANGE)
307 {
308 switch (itemID)
309 {
310 case IDC_SETTINGS_MEM:
311 {
312 _wasChanged_MemLimit = true;
313 Changed();
314 break;
315 }
316 }
317 }
318 return CPropertyPage::OnCommand(code, itemID, param);
319}
320*/
321
322bool CSettingsPage::OnButtonClicked(int buttonID, HWND buttonHWND)
323{
324 switch (buttonID)
325 {
326 case IDX_SETTINGS_SINGLE_CLICK:
327 /*
328 EnableSubItems();
329 break;
330 */
331 case IDX_SETTINGS_SHOW_DOTS:
332 case IDX_SETTINGS_SHOW_SYSTEM_MENU:
333 case IDX_SETTINGS_SHOW_REAL_FILE_ICONS:
334 case IDX_SETTINGS_FULL_ROW:
335 case IDX_SETTINGS_SHOW_GRID:
336 case IDX_SETTINGS_ALTERNATIVE_SELECTION:
337 _wasChanged = true;
338 break;
339
340 case IDX_SETTINGS_LARGE_PAGES:
341 _largePages_wasChanged = true;
342 break;
343
344 default:
345 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
346 }
347
348 Changed();
349 return true;
350}
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.h b/CPP/7zip/UI/FileManager/SettingsPage.h
new file mode 100644
index 0000000..f3f57a4
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SettingsPage.h
@@ -0,0 +1,33 @@
1// SettingsPage.h
2
3#ifndef __SETTINGS_PAGE_H
4#define __SETTINGS_PAGE_H
5
6#include "../../../Windows/Control/PropertyPage.h"
7#include "../../../Windows/Control/ComboBox.h"
8#include "../../../Windows/Control/Edit.h"
9
10class CSettingsPage: public NWindows::NControl::CPropertyPage
11{
12 bool _wasChanged;
13 bool _largePages_wasChanged;
14 /*
15 bool _wasChanged_MemLimit;
16 NWindows::NControl::CComboBox _memCombo;
17 UStringVector _memLimitStrings;
18 UInt64 _ramSize;
19 UInt64 _ramSize_Defined;
20
21 int AddMemComboItem(UInt64 size, UInt64 percents = 0, bool isDefault = false);
22 */
23
24 // void EnableSubItems();
25 // bool OnCommand(int code, int itemID, LPARAM param);
26 bool OnButtonClicked(int buttonID, HWND buttonHWND);
27 virtual bool OnInit();
28 virtual void OnNotifyHelp();
29 virtual LONG OnApply();
30public:
31};
32
33#endif
diff --git a/CPP/7zip/UI/FileManager/SettingsPage.rc b/CPP/7zip/UI/FileManager/SettingsPage.rc
new file mode 100644
index 0000000..baab484
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SettingsPage.rc
@@ -0,0 +1,22 @@
1#include "SettingsPageRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 240
5#define yc 250
6
7IDD_SETTINGS MY_PAGE
8#include "SettingsPage2.rc"
9
10
11#ifdef UNDER_CE
12
13#undef m
14#undef xc
15
16#define m 4
17#define xc (SMALL_PAGE_SIZE_X + 8)
18
19IDD_SETTINGS_2 MY_PAGE
20#include "SettingsPage2.rc"
21
22#endif
diff --git a/CPP/7zip/UI/FileManager/SettingsPage2.rc b/CPP/7zip/UI/FileManager/SettingsPage2.rc
new file mode 100644
index 0000000..cf90742
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SettingsPage2.rc
@@ -0,0 +1,19 @@
1// #define g1xs 60
2
3CAPTION "Settings"
4BEGIN
5 CONTROL "Show "".."" item", IDX_SETTINGS_SHOW_DOTS, MY_CHECKBOX, m, 8, xc, 10
6 CONTROL "Show real file &icons", IDX_SETTINGS_SHOW_REAL_FILE_ICONS, MY_CHECKBOX, m, 22, xc, 10
7 CONTROL "&Full row select", IDX_SETTINGS_FULL_ROW, MY_CHECKBOX, m, 36, xc, 10
8 CONTROL "Show &grid lines", IDX_SETTINGS_SHOW_GRID, MY_CHECKBOX, m, 50, xc, 10
9 CONTROL "&Single-click to open an item", IDX_SETTINGS_SINGLE_CLICK, MY_CHECKBOX, m, 64, xc, 10
10 CONTROL "&Alternative selection mode", IDX_SETTINGS_ALTERNATIVE_SELECTION, MY_CHECKBOX, m, 78, xc, 10
11
12 CONTROL "Show system &menu", IDX_SETTINGS_SHOW_SYSTEM_MENU, MY_CHECKBOX, m, 100, xc, 10
13
14 CONTROL "Use &large memory pages", IDX_SETTINGS_LARGE_PAGES, MY_CHECKBOX, m, 122, xc, 10
15
16 // LTEXT "Memory usage for Compressing:", IDT_COMPRESS_MEMORY, m, 140, xc, 8
17 // COMBOBOX IDC_SETTINGS_MEM, m , 152, g1xs, yc - 152, MY_COMBO
18 // LTEXT "/ RAM", IDT_SETTINGS_MEM_RAM, m + g1xs + m, 154, xc - g1xs - m, MY_TEXT_NOPREFIX
19END
diff --git a/CPP/7zip/UI/FileManager/SettingsPageRes.h b/CPP/7zip/UI/FileManager/SettingsPageRes.h
new file mode 100644
index 0000000..e990bab
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SettingsPageRes.h
@@ -0,0 +1,17 @@
1#define IDD_SETTINGS 2500
2#define IDD_SETTINGS_2 12500
3
4#define IDX_SETTINGS_SHOW_DOTS 2501
5#define IDX_SETTINGS_SHOW_REAL_FILE_ICONS 2502
6#define IDX_SETTINGS_SHOW_SYSTEM_MENU 2503
7#define IDX_SETTINGS_FULL_ROW 2504
8#define IDX_SETTINGS_SHOW_GRID 2505
9#define IDX_SETTINGS_SINGLE_CLICK 2506
10#define IDX_SETTINGS_ALTERNATIVE_SELECTION 2507
11#define IDX_SETTINGS_LARGE_PAGES 2508
12
13
14// #define IDT_SETTINGS_MEM 100
15// #define IDC_SETTINGS_MEM 101
16// #define IDT_SETTINGS_MEM_RAM 102
17// #define IDT_COMPRESS_MEMORY 4017
diff --git a/CPP/7zip/UI/FileManager/SplitDialog.cpp b/CPP/7zip/UI/FileManager/SplitDialog.cpp
new file mode 100644
index 0000000..0c9fdd1
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SplitDialog.cpp
@@ -0,0 +1,116 @@
1// SplitDialog.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/FileName.h"
6
7#ifdef LANG
8#include "LangUtils.h"
9#endif
10
11#include "BrowseDialog.h"
12#include "CopyDialogRes.h"
13#include "SplitDialog.h"
14#include "SplitUtils.h"
15#include "resourceGui.h"
16
17using namespace NWindows;
18
19#ifdef LANG
20static const UInt32 kLangIDs[] =
21{
22 IDT_SPLIT_PATH,
23 IDT_SPLIT_VOLUME
24};
25#endif
26
27
28bool CSplitDialog::OnInit()
29{
30 #ifdef LANG
31 LangSetWindowText(*this, IDD_SPLIT);
32 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
33 #endif
34 _pathCombo.Attach(GetItem(IDC_SPLIT_PATH));
35 _volumeCombo.Attach(GetItem(IDC_SPLIT_VOLUME));
36
37 if (!FilePath.IsEmpty())
38 {
39 UString title;
40 GetText(title);
41 title.Add_Space();
42 title += FilePath;
43 SetText(title);
44 }
45 _pathCombo.SetText(Path);
46 AddVolumeItems(_volumeCombo);
47 _volumeCombo.SetCurSel(0);
48 NormalizeSize();
49 return CModalDialog::OnInit();
50}
51
52bool CSplitDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
53{
54 int mx, my;
55 GetMargins(8, mx, my);
56 int bx1, bx2, by;
57 GetItemSizes(IDCANCEL, bx1, by);
58 GetItemSizes(IDOK, bx2, by);
59 int yPos = ySize - my - by;
60 int xPos = xSize - mx - bx1;
61
62 InvalidateRect(NULL);
63
64 {
65 RECT r;
66 GetClientRectOfItem(IDB_SPLIT_PATH, r);
67 int bx = RECT_SIZE_X(r);
68 MoveItem(IDB_SPLIT_PATH, xSize - mx - bx, r.top, bx, RECT_SIZE_Y(r));
69 ChangeSubWindowSizeX(_pathCombo, xSize - mx - mx - bx - mx);
70 }
71
72 MoveItem(IDCANCEL, xPos, yPos, bx1, by);
73 MoveItem(IDOK, xPos - mx - bx2, yPos, bx2, by);
74
75 return false;
76}
77
78bool CSplitDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
79{
80 switch (buttonID)
81 {
82 case IDB_SPLIT_PATH:
83 OnButtonSetPath();
84 return true;
85 }
86 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
87}
88
89void CSplitDialog::OnButtonSetPath()
90{
91 UString currentPath;
92 _pathCombo.GetText(currentPath);
93 // UString title = "Specify a location for output folder";
94 UString title = LangString(IDS_SET_FOLDER);
95
96 UString resultPath;
97 if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
98 return;
99 NFile::NName::NormalizeDirPathPrefix(resultPath);
100 _pathCombo.SetCurSel(-1);
101 _pathCombo.SetText(resultPath);
102}
103
104void CSplitDialog::OnOK()
105{
106 _pathCombo.GetText(Path);
107 UString volumeString;
108 _volumeCombo.GetText(volumeString);
109 volumeString.Trim();
110 if (!ParseVolumeSizes(volumeString, VolumeSizes) || VolumeSizes.Size() == 0)
111 {
112 ::MessageBoxW(*this, LangString(IDS_INCORRECT_VOLUME_SIZE), L"7-Zip", MB_ICONERROR);
113 return;
114 }
115 CModalDialog::OnOK();
116}
diff --git a/CPP/7zip/UI/FileManager/SplitDialog.h b/CPP/7zip/UI/FileManager/SplitDialog.h
new file mode 100644
index 0000000..00aae65
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SplitDialog.h
@@ -0,0 +1,28 @@
1// SplitDialog.h
2
3#ifndef __SPLIT_DIALOG_H
4#define __SPLIT_DIALOG_H
5
6#include "../../../Windows/Control/Dialog.h"
7#include "../../../Windows/Control/ComboBox.h"
8
9#include "SplitDialogRes.h"
10
11class CSplitDialog: public NWindows::NControl::CModalDialog
12{
13 NWindows::NControl::CComboBox _pathCombo;
14 NWindows::NControl::CComboBox _volumeCombo;
15 virtual void OnOK();
16 virtual bool OnInit();
17 virtual bool OnSize(WPARAM wParam, int xSize, int ySize);
18 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
19 void OnButtonSetPath();
20public:
21 UString FilePath;
22 UString Path;
23 CRecordVector<UInt64> VolumeSizes;
24 INT_PTR Create(HWND parentWindow = 0)
25 { return CModalDialog::Create(IDD_SPLIT, parentWindow); }
26};
27
28#endif
diff --git a/CPP/7zip/UI/FileManager/SplitDialog.rc b/CPP/7zip/UI/FileManager/SplitDialog.rc
new file mode 100644
index 0000000..5a026e8
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SplitDialog.rc
@@ -0,0 +1,16 @@
1#include "SplitDialogRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 288
5#define yc 96
6
7IDD_SPLIT DIALOG 0, 0, xs, ys MY_MODAL_RESIZE_DIALOG_STYLE MY_FONT
8CAPTION "Split File"
9BEGIN
10 LTEXT "&Split to:", IDT_SPLIT_PATH, m, m, xc, 8
11 COMBOBOX IDC_SPLIT_PATH, m, 20, xc - bxsDots - m, 64, MY_COMBO_WITH_EDIT
12 PUSHBUTTON "...", IDB_SPLIT_PATH, xs - m - bxsDots, 18, bxsDots, bys, WS_GROUP
13 LTEXT "Split to &volumes, bytes:", IDT_SPLIT_VOLUME, m, 44, xc, 8
14 COMBOBOX IDC_SPLIT_VOLUME, m, 56, 96, 52, MY_COMBO_WITH_EDIT
15 OK_CANCEL
16END
diff --git a/CPP/7zip/UI/FileManager/SplitDialogRes.h b/CPP/7zip/UI/FileManager/SplitDialogRes.h
new file mode 100644
index 0000000..50584a1
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SplitDialogRes.h
@@ -0,0 +1,8 @@
1#define IDD_SPLIT 7300
2
3#define IDT_SPLIT_PATH 7301
4#define IDT_SPLIT_VOLUME 7302
5
6#define IDC_SPLIT_PATH 100
7#define IDB_SPLIT_PATH 101
8#define IDC_SPLIT_VOLUME 102
diff --git a/CPP/7zip/UI/FileManager/SplitUtils.cpp b/CPP/7zip/UI/FileManager/SplitUtils.cpp
new file mode 100644
index 0000000..4b6235b
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SplitUtils.cpp
@@ -0,0 +1,96 @@
1// SplitUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/StringToInt.h"
6
7#include "SplitUtils.h"
8
9bool ParseVolumeSizes(const UString &s, CRecordVector<UInt64> &values)
10{
11 values.Clear();
12 bool prevIsNumber = false;
13 for (unsigned i = 0; i < s.Len();)
14 {
15 wchar_t c = s[i++];
16 if (c == L' ')
17 continue;
18 if (c == L'-')
19 return true;
20 if (prevIsNumber)
21 {
22 prevIsNumber = false;
23 unsigned numBits = 0;
24 switch (MyCharLower_Ascii(c))
25 {
26 case 'b': continue;
27 case 'k': numBits = 10; break;
28 case 'm': numBits = 20; break;
29 case 'g': numBits = 30; break;
30 case 't': numBits = 40; break;
31 }
32 if (numBits != 0)
33 {
34 UInt64 &val = values.Back();
35 if (val >= ((UInt64)1 << (64 - numBits)))
36 return false;
37 val <<= numBits;
38
39 for (; i < s.Len(); i++)
40 if (s[i] == L' ')
41 break;
42 continue;
43 }
44 }
45 i--;
46 const wchar_t *start = s.Ptr(i);
47 const wchar_t *end;
48 UInt64 val = ConvertStringToUInt64(start, &end);
49 if (start == end)
50 return false;
51 if (val == 0)
52 return false;
53 values.Add(val);
54 prevIsNumber = true;
55 i += (unsigned)(end - start);
56 }
57 return true;
58}
59
60
61static const char * const k_Sizes[] =
62{
63 "10M"
64 , "100M"
65 , "1000M"
66 , "650M - CD"
67 , "700M - CD"
68 , "4092M - FAT"
69 , "4480M - DVD" // 4489 MiB limit
70 , "8128M - DVD DL" // 8147 MiB limit
71 , "23040M - BD" // 23866 MiB limit
72 // , "1457664 - 3.5\" floppy"
73};
74
75void AddVolumeItems(NWindows::NControl::CComboBox &combo)
76{
77 for (unsigned i = 0; i < ARRAY_SIZE(k_Sizes); i++)
78 combo.AddString(CSysString(k_Sizes[i]));
79}
80
81UInt64 GetNumberOfVolumes(UInt64 size, const CRecordVector<UInt64> &volSizes)
82{
83 if (size == 0 || volSizes.Size() == 0)
84 return 1;
85 FOR_VECTOR (i, volSizes)
86 {
87 UInt64 volSize = volSizes[i];
88 if (volSize >= size)
89 return i + 1;
90 size -= volSize;
91 }
92 UInt64 volSize = volSizes.Back();
93 if (volSize == 0)
94 return (UInt64)(Int64)-1;
95 return volSizes.Size() + (size - 1) / volSize + 1;
96}
diff --git a/CPP/7zip/UI/FileManager/SplitUtils.h b/CPP/7zip/UI/FileManager/SplitUtils.h
new file mode 100644
index 0000000..641dfe6
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SplitUtils.h
@@ -0,0 +1,15 @@
1// SplitUtils.h
2
3#ifndef __SPLIT_UTILS_H
4#define __SPLIT_UTILS_H
5
6#include "../../../Common/MyTypes.h"
7#include "../../../Common/MyString.h"
8
9#include "../../../Windows/Control/ComboBox.h"
10
11bool ParseVolumeSizes(const UString &s, CRecordVector<UInt64> &values);
12void AddVolumeItems(NWindows::NControl::CComboBox &volumeCombo);
13UInt64 GetNumberOfVolumes(UInt64 size, const CRecordVector<UInt64> &volSizes);
14
15#endif
diff --git a/CPP/7zip/UI/FileManager/StdAfx.cpp b/CPP/7zip/UI/FileManager/StdAfx.cpp
new file mode 100644
index 0000000..d0feea8
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/StdAfx.cpp
@@ -0,0 +1,3 @@
1// StdAfx.cpp
2
3#include "StdAfx.h"
diff --git a/CPP/7zip/UI/FileManager/StdAfx.h b/CPP/7zip/UI/FileManager/StdAfx.h
new file mode 100644
index 0000000..0e6d446
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/StdAfx.h
@@ -0,0 +1,21 @@
1// stdafx.h
2
3#ifndef __STDAFX_H
4#define __STDAFX_H
5
6/* we used 0x0400 for Windows NT supporting (MENUITEMINFOW)
7 But now menu problem is fixed. So it's OK to use 0x0500 (Windows 2000) */
8
9// #define _WIN32_WINNT 0x0400
10#define _WIN32_WINNT 0x0500
11#define WINVER _WIN32_WINNT
12
13#include "../../../Common/Common.h"
14
15// #include "../../../Common/MyWindows.h"
16
17// #include <CommCtrl.h>
18// #include <ShlObj.h>
19// #include <Shlwapi.h>
20
21#endif
diff --git a/CPP/7zip/UI/FileManager/StringUtils.cpp b/CPP/7zip/UI/FileManager/StringUtils.cpp
new file mode 100644
index 0000000..0478399
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/StringUtils.cpp
@@ -0,0 +1,65 @@
1// StringUtils.cpp
2
3#include "StdAfx.h"
4
5#include "StringUtils.h"
6
7void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2)
8{
9 dest1.Empty();
10 dest2.Empty();
11 bool quoteMode = false;
12 for (unsigned i = 0; i < src.Len(); i++)
13 {
14 const wchar_t c = src[i];
15 if (c == '\"')
16 quoteMode = !quoteMode;
17 else if (c == ' ' && !quoteMode)
18 {
19 dest2 = src.Ptr(i + 1);
20 return;
21 }
22 else
23 dest1 += c;
24 }
25}
26
27void SplitString(const UString &srcString, UStringVector &destStrings)
28{
29 destStrings.Clear();
30 unsigned len = srcString.Len();
31 if (len == 0)
32 return;
33 UString s;
34 for (unsigned i = 0; i < len; i++)
35 {
36 wchar_t c = srcString[i];
37 if (c == ' ')
38 {
39 if (!s.IsEmpty())
40 {
41 destStrings.Add(s);
42 s.Empty();
43 }
44 }
45 else
46 s += c;
47 }
48 if (!s.IsEmpty())
49 destStrings.Add(s);
50}
51
52/*
53UString JoinStrings(const UStringVector &srcStrings)
54{
55
56 UString s;
57 FOR_VECTOR (i, srcStrings)
58 {
59 if (i != 0)
60 s.Add_Space();
61 s += srcStrings[i];
62 }
63 return s;
64}
65*/
diff --git a/CPP/7zip/UI/FileManager/StringUtils.h b/CPP/7zip/UI/FileManager/StringUtils.h
new file mode 100644
index 0000000..fc070de
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/StringUtils.h
@@ -0,0 +1,13 @@
1// StringUtils.h
2
3#ifndef __STRING_UTILS_H
4#define __STRING_UTILS_H
5
6#include "../../../Common/MyString.h"
7
8void SplitStringToTwoStrings(const UString &src, UString &dest1, UString &dest2);
9
10void SplitString(const UString &srcString, UStringVector &destStrings);
11UString JoinStrings(const UStringVector &srcStrings);
12
13#endif
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.cpp b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
new file mode 100644
index 0000000..b756dfc
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.cpp
@@ -0,0 +1,255 @@
1// SysIconUtils.cpp
2
3#include "StdAfx.h"
4
5#ifndef _UNICODE
6#include "../../../Common/StringConvert.h"
7#endif
8
9#include "../../../Windows/FileDir.h"
10
11#include "SysIconUtils.h"
12
13#include <ShlObj.h>
14
15#ifndef _UNICODE
16extern bool g_IsNT;
17#endif
18
19int GetIconIndexForCSIDL(int csidl)
20{
21 LPITEMIDLIST pidl = 0;
22 SHGetSpecialFolderLocation(NULL, csidl, &pidl);
23 if (pidl)
24 {
25 SHFILEINFO shellInfo;
26 SHGetFileInfo((LPCTSTR)(const void *)(pidl), FILE_ATTRIBUTE_NORMAL,
27 &shellInfo, sizeof(shellInfo),
28 SHGFI_PIDL | SHGFI_SYSICONINDEX);
29 IMalloc *pMalloc;
30 SHGetMalloc(&pMalloc);
31 if (pMalloc)
32 {
33 pMalloc->Free(pidl);
34 pMalloc->Release();
35 }
36 return shellInfo.iIcon;
37 }
38 return 0;
39}
40
41#ifndef _UNICODE
42typedef int (WINAPI * SHGetFileInfoWP)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);
43
44static struct CSHGetFileInfoInit
45{
46 SHGetFileInfoWP shGetFileInfoW;
47 CSHGetFileInfoInit()
48 {
49 shGetFileInfoW = (SHGetFileInfoWP)
50 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetFileInfoW");
51 }
52} g_SHGetFileInfoInit;
53#endif
54
55static DWORD_PTR MySHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)
56{
57 #ifdef _UNICODE
58 return SHGetFileInfo
59 #else
60 if (g_SHGetFileInfoInit.shGetFileInfoW == 0)
61 return 0;
62 return g_SHGetFileInfoInit.shGetFileInfoW
63 #endif
64 (pszPath, attrib, psfi, cbFileInfo, uFlags);
65}
66
67DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex)
68{
69 #ifndef _UNICODE
70 if (!g_IsNT)
71 {
72 SHFILEINFO shellInfo;
73 DWORD_PTR res = ::SHGetFileInfo(fs2fas(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
74 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
75 iconIndex = shellInfo.iIcon;
76 return res;
77 }
78 else
79 #endif
80 {
81 SHFILEINFOW shellInfo;
82 DWORD_PTR res = ::MySHGetFileInfoW(fs2us(path), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
83 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
84 iconIndex = shellInfo.iIcon;
85 return res;
86 }
87}
88
89/*
90DWORD_PTR GetRealIconIndex(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)
91{
92 #ifndef _UNICODE
93 if (!g_IsNT)
94 {
95 SHFILEINFO shellInfo;
96 shellInfo.szTypeName[0] = 0;
97 DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
98 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
99 if (typeName)
100 *typeName = GetUnicodeString(shellInfo.szTypeName);
101 iconIndex = shellInfo.iIcon;
102 return res;
103 }
104 else
105 #endif
106 {
107 SHFILEINFOW shellInfo;
108 shellInfo.szTypeName[0] = 0;
109 DWORD_PTR res = ::MySHGetFileInfoW(fileName, FILE_ATTRIBUTE_NORMAL | attrib, &shellInfo,
110 sizeof(shellInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);
111 if (typeName)
112 *typeName = shellInfo.szTypeName;
113 iconIndex = shellInfo.iIcon;
114 return res;
115 }
116}
117*/
118
119static int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, int &insertPos)
120{
121 unsigned left = 0, right = vect.Size();
122 while (left != right)
123 {
124 unsigned mid = (left + right) / 2;
125 DWORD midAttrib = vect[mid].Attrib;
126 if (attrib == midAttrib)
127 return mid;
128 if (attrib < midAttrib)
129 right = mid;
130 else
131 left = mid + 1;
132 }
133 insertPos = left;
134 return -1;
135}
136
137static int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, int &insertPos)
138{
139 unsigned left = 0, right = vect.Size();
140 while (left != right)
141 {
142 unsigned mid = (left + right) / 2;
143 int compare = MyStringCompareNoCase(ext, vect[mid].Ext);
144 if (compare == 0)
145 return mid;
146 if (compare < 0)
147 right = mid;
148 else
149 left = mid + 1;
150 }
151 insertPos = left;
152 return -1;
153}
154
155int CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)
156{
157 int dotPos = -1;
158 unsigned i;
159 for (i = 0;; i++)
160 {
161 wchar_t c = fileName[i];
162 if (c == 0)
163 break;
164 if (c == '.')
165 dotPos = i;
166 }
167
168 /*
169 if (MyStringCompareNoCase(fileName, L"$Recycle.Bin") == 0)
170 {
171 char s[256];
172 sprintf(s, "SPEC i = %3d, attr = %7x", _attribMap.Size(), attrib);
173 OutputDebugStringA(s);
174 OutputDebugStringW(fileName);
175 }
176 */
177
178 if ((attrib & FILE_ATTRIBUTE_DIRECTORY) != 0 || dotPos < 0)
179 {
180 int insertPos = 0;
181 int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);
182 if (index >= 0)
183 {
184 // if (typeName) *typeName = _attribMap[index].TypeName;
185 return _attribMap[index].IconIndex;
186 }
187 CAttribIconPair pair;
188 GetRealIconIndex(
189 #ifdef UNDER_CE
190 FTEXT("\\")
191 #endif
192 FTEXT("__DIR__")
193 , attrib, pair.IconIndex
194 // , pair.TypeName
195 );
196
197 /*
198 char s[256];
199 sprintf(s, "i = %3d, attr = %7x", _attribMap.Size(), attrib);
200 OutputDebugStringA(s);
201 */
202
203 pair.Attrib = attrib;
204 _attribMap.Insert(insertPos, pair);
205 // if (typeName) *typeName = pair.TypeName;
206 return pair.IconIndex;
207 }
208
209 const wchar_t *ext = fileName + dotPos + 1;
210 int insertPos = 0;
211 int index = FindInSorted_Ext(_extMap, ext, insertPos);
212 if (index >= 0)
213 {
214 const CExtIconPair &pa = _extMap[index];
215 // if (typeName) *typeName = pa.TypeName;
216 return pa.IconIndex;
217 }
218
219 for (i = 0;; i++)
220 {
221 wchar_t c = ext[i];
222 if (c == 0)
223 break;
224 if (c < L'0' || c > L'9')
225 break;
226 }
227 if (i != 0 && ext[i] == 0)
228 {
229 // GetRealIconIndex is too slow for big number of split extensions: .001, .002, .003
230 if (!SplitIconIndex_Defined)
231 {
232 GetRealIconIndex(
233 #ifdef UNDER_CE
234 FTEXT("\\")
235 #endif
236 FTEXT("__FILE__.001"), 0, SplitIconIndex);
237 SplitIconIndex_Defined = true;
238 }
239 return SplitIconIndex;
240 }
241
242 CExtIconPair pair;
243 pair.Ext = ext;
244 GetRealIconIndex(us2fs(fileName + dotPos), attrib, pair.IconIndex);
245 _extMap.Insert(insertPos, pair);
246 // if (typeName) *typeName = pair.TypeName;
247 return pair.IconIndex;
248}
249
250/*
251int CExtToIconMap::GetIconIndex(DWORD attrib, const UString &fileName)
252{
253 return GetIconIndex(attrib, fileName, NULL);
254}
255*/
diff --git a/CPP/7zip/UI/FileManager/SysIconUtils.h b/CPP/7zip/UI/FileManager/SysIconUtils.h
new file mode 100644
index 0000000..fde16e4
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SysIconUtils.h
@@ -0,0 +1,62 @@
1// SysIconUtils.h
2
3#ifndef __SYS_ICON_UTILS_H
4#define __SYS_ICON_UTILS_H
5
6#include "../../../Common/MyWindows.h"
7
8#include <CommCtrl.h>
9
10#include "../../../Common/MyString.h"
11
12struct CExtIconPair
13{
14 UString Ext;
15 int IconIndex;
16 // UString TypeName;
17
18 // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }
19};
20
21struct CAttribIconPair
22{
23 DWORD Attrib;
24 int IconIndex;
25 // UString TypeName;
26
27 // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }
28};
29
30class CExtToIconMap
31{
32public:
33 CRecordVector<CAttribIconPair> _attribMap;
34 CObjectVector<CExtIconPair> _extMap;
35 int SplitIconIndex;
36 int SplitIconIndex_Defined;
37
38 CExtToIconMap(): SplitIconIndex_Defined(false) {}
39
40 void Clear()
41 {
42 SplitIconIndex_Defined = false;
43 _extMap.Clear();
44 _attribMap.Clear();
45 }
46 int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */);
47 // int GetIconIndex(DWORD attrib, const UString &fileName);
48};
49
50DWORD_PTR GetRealIconIndex(CFSTR path, DWORD attrib, int &iconIndex);
51int GetIconIndexForCSIDL(int csidl);
52
53inline HIMAGELIST GetSysImageList(bool smallIcons)
54{
55 SHFILEINFO shellInfo;
56 return (HIMAGELIST)SHGetFileInfo(TEXT(""),
57 FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY,
58 &shellInfo, sizeof(shellInfo),
59 SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | (smallIcons ? SHGFI_SMALLICON : SHGFI_ICON));
60}
61
62#endif
diff --git a/CPP/7zip/UI/FileManager/SystemPage.cpp b/CPP/7zip/UI/FileManager/SystemPage.cpp
new file mode 100644
index 0000000..a95999f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SystemPage.cpp
@@ -0,0 +1,464 @@
1// SystemPage.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/MyWindows.h"
6
7#include <ShlObj.h>
8
9#include "../../../Common/Defs.h"
10#include "../../../Common/StringConvert.h"
11
12#include "../../../Windows/DLL.h"
13#include "../../../Windows/ErrorMsg.h"
14
15#include "HelpUtils.h"
16#include "IFolder.h"
17#include "LangUtils.h"
18#include "PropertyNameRes.h"
19#include "SystemPage.h"
20#include "SystemPageRes.h"
21
22using namespace NWindows;
23
24#ifndef _UNICODE
25extern bool g_IsNT;
26#endif
27
28static const UInt32 kLangIDs[] =
29{
30 IDT_SYSTEM_ASSOCIATE
31};
32
33#define kSystemTopic "FM/options.htm#system"
34
35CSysString CModifiedExtInfo::GetString() const
36{
37 const char *s;
38 if (State == kExtState_7Zip)
39 s = "7-Zip";
40 else if (State == kExtState_Clear)
41 s = "";
42 else if (Other7Zip)
43 s = "[7-Zip]";
44 else
45 return ProgramKey;
46 return CSysString (s);
47};
48
49
50int CSystemPage::AddIcon(const UString &iconPath, int iconIndex)
51{
52 if (iconPath.IsEmpty())
53 return -1;
54 if (iconIndex == -1)
55 iconIndex = 0;
56
57 HICON hicon;
58
59 #ifdef UNDER_CE
60 ExtractIconExW(iconPath, iconIndex, NULL, &hicon, 1);
61 if (!hicon)
62 #else
63 // we expand path from REG_EXPAND_SZ registry item.
64 UString path;
65 DWORD size = MAX_PATH + 10;
66 DWORD needLen = ::ExpandEnvironmentStringsW(iconPath, path.GetBuf(size + 2), size);
67 path.ReleaseBuf_CalcLen(size);
68 if (needLen == 0 || needLen >= size)
69 path = iconPath;
70 int num = ExtractIconExW(path, iconIndex, NULL, &hicon, 1);
71 if (num != 1 || !hicon)
72 #endif
73 return -1;
74
75 _imageList.AddIcon(hicon);
76 DestroyIcon(hicon);
77 return _numIcons++;
78}
79
80
81void CSystemPage::RefreshListItem(unsigned group, unsigned listIndex)
82{
83 const CAssoc &assoc = _items[GetRealIndex(listIndex)];
84 _listView.SetSubItem(listIndex, group + 1, assoc.Pair[group].GetString());
85 LVITEMW newItem;
86 memset(&newItem, 0, sizeof(newItem));
87 newItem.iItem = listIndex;
88 newItem.mask = LVIF_IMAGE;
89 newItem.iImage = assoc.GetIconIndex();
90 _listView.SetItem(&newItem);
91}
92
93
94void CSystemPage::ChangeState(unsigned group, const CUIntVector &indices)
95{
96 if (indices.IsEmpty())
97 return;
98
99 bool thereAreClearItems = false;
100 unsigned counters[3] = { 0, 0, 0 };
101
102 unsigned i;
103 for (i = 0; i < indices.Size(); i++)
104 {
105 const CModifiedExtInfo &mi = _items[GetRealIndex(indices[i])].Pair[group];
106 int state = kExtState_7Zip;
107 if (mi.State == kExtState_7Zip)
108 state = kExtState_Clear;
109 else if (mi.State == kExtState_Clear)
110 {
111 thereAreClearItems = true;
112 if (mi.Other)
113 state = kExtState_Other;
114 }
115 counters[state]++;
116 }
117
118 int state = kExtState_Clear;
119 if (counters[kExtState_Other] != 0)
120 state = kExtState_Other;
121 else if (counters[kExtState_7Zip] != 0)
122 state = kExtState_7Zip;
123
124 for (i = 0; i < indices.Size(); i++)
125 {
126 unsigned listIndex = indices[i];
127 CAssoc &assoc = _items[GetRealIndex(listIndex)];
128 CModifiedExtInfo &mi = assoc.Pair[group];
129 bool change = false;
130
131 switch (state)
132 {
133 case kExtState_Clear: change = true; break;
134 case kExtState_Other: change = mi.Other; break;
135 default: change = !(mi.Other && thereAreClearItems); break;
136 }
137
138 if (change)
139 {
140 mi.State = state;
141 RefreshListItem(group, listIndex);
142 }
143 }
144
145 _needSave = true;
146 Changed();
147}
148
149
150bool CSystemPage::OnInit()
151{
152 _needSave = false;
153
154 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
155
156 _listView.Attach(GetItem(IDL_SYSTEM_ASSOCIATE));
157 _listView.SetUnicodeFormat();
158 DWORD newFlags = LVS_EX_FULLROWSELECT;
159 _listView.SetExtendedListViewStyle(newFlags, newFlags);
160
161 _numIcons = 0;
162 _imageList.Create(16, 16, ILC_MASK | ILC_COLOR32, 0, 0);
163
164 _listView.SetImageList(_imageList, LVSIL_SMALL);
165
166 _listView.InsertColumn(0, LangString(IDS_PROP_FILE_TYPE), 72);
167
168 UString s;
169
170 #if NUM_EXT_GROUPS == 1
171 s = "Program";
172 #else
173 #ifndef UNDER_CE
174 const unsigned kSize = 256;
175 BOOL res;
176
177 DWORD size = kSize;
178
179 #ifndef _UNICODE
180 if (!g_IsNT)
181 {
182 AString s2;
183 res = GetUserNameA(s2.GetBuf(size), &size);
184 s2.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize));
185 s = GetUnicodeString(s2);
186 }
187 else
188 #endif
189 {
190 res = GetUserNameW(s.GetBuf(size), &size);
191 s.ReleaseBuf_CalcLen(MyMin((unsigned)size, kSize));
192 }
193
194 if (!res)
195 #endif
196 s = "Current User";
197 #endif
198
199 LV_COLUMNW ci;
200 ci.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
201 ci.cx = 128;
202 ci.fmt = LVCFMT_CENTER;
203 ci.pszText = s.Ptr_non_const();
204 ci.iSubItem = 1;
205 _listView.InsertColumn(1, &ci);
206
207 #if NUM_EXT_GROUPS > 1
208 {
209 LangString(IDS_SYSTEM_ALL_USERS, s);
210 ci.pszText = s.Ptr_non_const();
211 ci.iSubItem = 2;
212 _listView.InsertColumn(2, &ci);
213 }
214 #endif
215
216 _extDB.Read();
217 _items.Clear();
218
219 FOR_VECTOR (i, _extDB.Exts)
220 {
221 const CExtPlugins &extInfo = _extDB.Exts[i];
222
223 LVITEMW item;
224 item.iItem = i;
225 item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
226 item.lParam = i;
227 item.iSubItem = 0;
228 // ListView always uses internal iImage that is 0 by default?
229 // so we always use LVIF_IMAGE.
230 item.iImage = -1;
231 item.pszText = extInfo.Ext.Ptr_non_const();
232
233 CAssoc assoc;
234 const CPluginToIcon &plug = extInfo.Plugins[0];
235 assoc.SevenZipImageIndex = AddIcon(plug.IconPath, plug.IconIndex);
236
237 CSysString texts[NUM_EXT_GROUPS];
238 unsigned g;
239 for (g = 0; g < NUM_EXT_GROUPS; g++)
240 {
241 CModifiedExtInfo &mi = assoc.Pair[g];
242 mi.ReadFromRegistry(GetHKey(g), GetSystemString(extInfo.Ext));
243 mi.SetState(plug.IconPath);
244 mi.ImageIndex = AddIcon(mi.IconPath, mi.IconIndex);
245 texts[g] = mi.GetString();
246 }
247 item.iImage = assoc.GetIconIndex();
248 int itemIndex = _listView.InsertItem(&item);
249 for (g = 0; g < NUM_EXT_GROUPS; g++)
250 _listView.SetSubItem(itemIndex, 1 + g, texts[g]);
251 _items.Add(assoc);
252 }
253
254 if (_listView.GetItemCount() > 0)
255 _listView.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);
256
257 return CPropertyPage::OnInit();
258}
259
260
261static UString GetProgramCommand()
262{
263 UString s ('\"');
264 s += fs2us(NDLL::GetModuleDirPrefix());
265 s += "7zFM.exe\" \"%1\"";
266 return s;
267}
268
269
270LONG CSystemPage::OnApply()
271{
272 if (!_needSave)
273 return PSNRET_NOERROR;
274
275 const UString command = GetProgramCommand();
276
277 LONG res = 0;
278
279 FOR_VECTOR (listIndex, _extDB.Exts)
280 {
281 unsigned realIndex = GetRealIndex(listIndex);
282 const CExtPlugins &extInfo = _extDB.Exts[realIndex];
283 CAssoc &assoc = _items[realIndex];
284
285 for (unsigned g = 0; g < NUM_EXT_GROUPS; g++)
286 {
287 CModifiedExtInfo &mi = assoc.Pair[g];
288 HKEY key = GetHKey(g);
289
290 if (mi.OldState != mi.State)
291 {
292 LONG res2 = 0;
293
294 if (mi.State == kExtState_7Zip)
295 {
296 UString title = extInfo.Ext;
297 title += " Archive";
298 const CPluginToIcon &plug = extInfo.Plugins[0];
299 res2 = NRegistryAssoc::AddShellExtensionInfo(key, GetSystemString(extInfo.Ext),
300 title, command, plug.IconPath, plug.IconIndex);
301 }
302 else if (mi.State == kExtState_Clear)
303 res2 = NRegistryAssoc::DeleteShellExtensionInfo(key, GetSystemString(extInfo.Ext));
304
305 if (res == 0)
306 res = res2;
307 if (res2 == 0)
308 mi.OldState = mi.State;
309
310 mi.State = mi.OldState;
311 RefreshListItem(g, listIndex);
312 }
313 }
314 }
315
316 #ifndef UNDER_CE
317 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
318 #endif
319
320 WasChanged = true;
321
322 _needSave = false;
323
324 if (res != 0)
325 MessageBoxW(*this, NError::MyFormatMessage(res), L"7-Zip", MB_ICONERROR);
326
327 return PSNRET_NOERROR;
328}
329
330
331void CSystemPage::OnNotifyHelp()
332{
333 ShowHelpWindow(kSystemTopic);
334}
335
336
337bool CSystemPage::OnButtonClicked(int buttonID, HWND buttonHWND)
338{
339 switch (buttonID)
340 {
341 /*
342 case IDC_SYSTEM_SELECT_ALL:
343 _listView.SelectAll();
344 return true;
345 */
346 case IDB_SYSTEM_CURRENT:
347 case IDB_SYSTEM_ALL:
348 ChangeState(buttonID == IDB_SYSTEM_CURRENT ? 0 : 1);
349 return true;
350 }
351 return CPropertyPage::OnButtonClicked(buttonID, buttonHWND);
352}
353
354
355bool CSystemPage::OnNotify(UINT controlID, LPNMHDR lParam)
356{
357 if (lParam->hwndFrom == HWND(_listView))
358 {
359 switch (lParam->code)
360 {
361 case NM_RETURN:
362 {
363 ChangeState(0);
364 return true;
365 }
366
367 case NM_CLICK:
368 {
369 #ifdef UNDER_CE
370 NMLISTVIEW *item = (NMLISTVIEW *)lParam;
371 #else
372 NMITEMACTIVATE *item = (NMITEMACTIVATE *)lParam;
373 if (item->uKeyFlags == 0)
374 #endif
375 {
376 if (item->iItem >= 0)
377 {
378 // unsigned realIndex = GetRealIndex(item->iItem);
379 if (item->iSubItem >= 1 && item->iSubItem <= 2)
380 {
381 CUIntVector indices;
382 indices.Add(item->iItem);
383 ChangeState(item->iSubItem < 2 ? 0 : 1, indices);
384 }
385 }
386 }
387 break;
388 }
389
390 case LVN_KEYDOWN:
391 {
392 if (OnListKeyDown(LPNMLVKEYDOWN(lParam)))
393 return true;
394 break;
395 }
396
397 /*
398 case NM_RCLICK:
399 case NM_DBLCLK:
400 case LVN_BEGINRDRAG:
401 // PostMessage(kRefreshpluginsListMessage, 0);
402 PostMessage(kUpdateDatabase, 0);
403 break;
404 */
405 }
406 }
407 return CPropertyPage::OnNotify(controlID, lParam);
408}
409
410
411void CSystemPage::ChangeState(unsigned group)
412{
413 CUIntVector indices;
414
415 int itemIndex = -1;
416 while ((itemIndex = _listView.GetNextSelectedItem(itemIndex)) != -1)
417 indices.Add(itemIndex);
418
419 if (indices.IsEmpty())
420 FOR_VECTOR (i, _items)
421 indices.Add(i);
422
423 ChangeState(group, indices);
424}
425
426
427bool CSystemPage::OnListKeyDown(LPNMLVKEYDOWN keyDownInfo)
428{
429 bool ctrl = IsKeyDown(VK_CONTROL);
430 bool alt = IsKeyDown(VK_MENU);
431
432 if (alt)
433 return false;
434
435 if ((ctrl && keyDownInfo->wVKey == 'A')
436 || (!ctrl && keyDownInfo->wVKey == VK_MULTIPLY))
437 {
438 _listView.SelectAll();
439 return true;
440 }
441
442 switch (keyDownInfo->wVKey)
443 {
444 case VK_SPACE:
445 case VK_ADD:
446 case VK_SUBTRACT:
447 case VK_SEPARATOR:
448 case VK_DIVIDE:
449
450 #ifndef UNDER_CE
451 case VK_OEM_PLUS:
452 case VK_OEM_MINUS:
453 #endif
454
455 if (!ctrl)
456 {
457 ChangeState(keyDownInfo->wVKey == VK_SPACE ? 0 : 1);
458 return true;
459 }
460 break;
461 }
462
463 return false;
464}
diff --git a/CPP/7zip/UI/FileManager/SystemPage.h b/CPP/7zip/UI/FileManager/SystemPage.h
new file mode 100644
index 0000000..765214c
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SystemPage.h
@@ -0,0 +1,126 @@
1// SystemPage.h
2
3#ifndef __SYSTEM_PAGE_H
4#define __SYSTEM_PAGE_H
5
6#include "../../../Windows/Control/ImageList.h"
7#include "../../../Windows/Control/ListView.h"
8#include "../../../Windows/Control/PropertyPage.h"
9
10#include "FilePlugins.h"
11#include "RegistryAssociations.h"
12
13enum EExtState
14{
15 kExtState_Clear = 0,
16 kExtState_Other,
17 kExtState_7Zip
18};
19
20struct CModifiedExtInfo: public NRegistryAssoc::CShellExtInfo
21{
22 int OldState;
23 int State;
24 int ImageIndex;
25 bool Other;
26 bool Other7Zip;
27
28 CModifiedExtInfo(): ImageIndex(-1) {}
29
30 CSysString GetString() const;
31
32 void SetState(const UString &iconPath)
33 {
34 State = kExtState_Clear;
35 Other = false;
36 Other7Zip = false;
37 if (!ProgramKey.IsEmpty())
38 {
39 State = kExtState_Other;
40 Other = true;
41 if (IsIt7Zip())
42 {
43 Other7Zip = !iconPath.IsEqualTo_NoCase(IconPath);
44 if (!Other7Zip)
45 {
46 State = kExtState_7Zip;
47 Other = false;
48 }
49 }
50 }
51 OldState = State;
52 };
53};
54
55struct CAssoc
56{
57 CModifiedExtInfo Pair[2];
58 int SevenZipImageIndex;
59
60 int GetIconIndex() const
61 {
62 for (unsigned i = 0; i < 2; i++)
63 {
64 const CModifiedExtInfo &pair = Pair[i];
65 if (pair.State == kExtState_Clear)
66 continue;
67 if (pair.State == kExtState_7Zip)
68 return SevenZipImageIndex;
69 if (pair.ImageIndex != -1)
70 return pair.ImageIndex;
71 }
72 return -1;
73 }
74};
75
76#ifdef UNDER_CE
77 #define NUM_EXT_GROUPS 1
78#else
79 #define NUM_EXT_GROUPS 2
80#endif
81
82class CSystemPage: public NWindows::NControl::CPropertyPage
83{
84 CExtDatabase _extDB;
85 CObjectVector<CAssoc> _items;
86
87 unsigned _numIcons;
88 NWindows::NControl::CImageList _imageList;
89 NWindows::NControl::CListView _listView;
90
91 bool _needSave;
92
93 HKEY GetHKey(unsigned
94 #if NUM_EXT_GROUPS != 1
95 group
96 #endif
97 ) const
98 {
99 #if NUM_EXT_GROUPS == 1
100 return HKEY_CLASSES_ROOT;
101 #else
102 return group == 0 ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
103 #endif
104 }
105
106 int AddIcon(const UString &path, int iconIndex);
107 unsigned GetRealIndex(unsigned listIndex) const { return listIndex; }
108 void RefreshListItem(unsigned group, unsigned listIndex);
109 void ChangeState(unsigned group, const CUIntVector &indices);
110 void ChangeState(unsigned group);
111
112 bool OnListKeyDown(LPNMLVKEYDOWN keyDownInfo);
113
114public:
115 bool WasChanged;
116
117 CSystemPage(): WasChanged(false) {}
118
119 virtual bool OnInit();
120 virtual void OnNotifyHelp();
121 virtual bool OnNotify(UINT controlID, LPNMHDR lParam);
122 virtual LONG OnApply();
123 virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
124};
125
126#endif
diff --git a/CPP/7zip/UI/FileManager/SystemPage.rc b/CPP/7zip/UI/FileManager/SystemPage.rc
new file mode 100644
index 0000000..3bb143a
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SystemPage.rc
@@ -0,0 +1,43 @@
1#include "SystemPageRes.h"
2#include "../../GuiCommon.rc"
3
4#define xc 240
5#define yc 252
6
7IDD_SYSTEM DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
8CAPTION "System"
9BEGIN
10 LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8
11 PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 80, m + 12, 40, bys
12 PUSHBUTTON "+", IDB_SYSTEM_ALL, 166, m + 12, 40, bys
13 CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32",
14 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
15 m, m + 32, xc, (yc - 32)
16END
17
18#ifdef UNDER_CE
19
20#undef m
21#undef xc
22#undef yc
23
24#define m 4
25#define xc (SMALL_PAGE_SIZE_X + 8)
26#define yc (128 + 8)
27
28IDD_SYSTEM_2 DIALOG 0, 0, xs, ys MY_PAGE_STYLE MY_FONT
29CAPTION "System"
30BEGIN
31 LTEXT "Associate 7-Zip with:", IDT_SYSTEM_ASSOCIATE, m, m, xc, 8
32 PUSHBUTTON "+", IDB_SYSTEM_CURRENT, 60, m + 12, 40, bys
33 CONTROL "List1", IDL_SYSTEM_ASSOCIATE, "SysListView32",
34 LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,
35 m, m + 32, xc, (yc - 32)
36END
37
38#endif
39
40STRINGTABLE
41BEGIN
42 IDS_SYSTEM_ALL_USERS "All users"
43END
diff --git a/CPP/7zip/UI/FileManager/SystemPageRes.h b/CPP/7zip/UI/FileManager/SystemPageRes.h
new file mode 100644
index 0000000..c894448
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/SystemPageRes.h
@@ -0,0 +1,9 @@
1#define IDD_SYSTEM 2200
2#define IDD_SYSTEM_2 12200
3
4#define IDT_SYSTEM_ASSOCIATE 2201
5#define IDS_SYSTEM_ALL_USERS 2202
6
7#define IDL_SYSTEM_ASSOCIATE 100
8#define IDB_SYSTEM_CURRENT 101
9#define IDB_SYSTEM_ALL 102
diff --git a/CPP/7zip/UI/FileManager/Test.bmp b/CPP/7zip/UI/FileManager/Test.bmp
new file mode 100644
index 0000000..ef85ba2
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Test.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/Test2.bmp b/CPP/7zip/UI/FileManager/Test2.bmp
new file mode 100644
index 0000000..99b7dbf
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/Test2.bmp
Binary files differ
diff --git a/CPP/7zip/UI/FileManager/TextPairs.cpp b/CPP/7zip/UI/FileManager/TextPairs.cpp
new file mode 100644
index 0000000..6a989fc
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/TextPairs.cpp
@@ -0,0 +1,190 @@
1// TextPairs.cpp
2
3#include "StdAfx.h"
4
5#include "TextPairs.h"
6
7static const wchar_t kNewLineChar = '\n';
8static const wchar_t kQuoteChar = '\"';
9
10static const wchar_t kBOM = (wchar_t)0xFEFF;
11
12static bool IsSeparatorChar(wchar_t c)
13{
14 return (c == ' ' || c == '\t');
15}
16
17static void RemoveCr(UString &s)
18{
19 s.RemoveChar(L'\x0D');
20}
21
22static UString GetIDString(const wchar_t *srcString, unsigned &finishPos)
23{
24 UString result;
25 bool quotes = false;
26 for (finishPos = 0;;)
27 {
28 wchar_t c = srcString[finishPos];
29 if (c == 0)
30 break;
31 finishPos++;
32 bool isSeparatorChar = IsSeparatorChar(c);
33 if (c == kNewLineChar || (isSeparatorChar && !quotes)
34 || (c == kQuoteChar && quotes))
35 break;
36 else if (c == kQuoteChar)
37 quotes = true;
38 else
39 result += c;
40 }
41 result.Trim();
42 RemoveCr(result);
43 return result;
44}
45
46static UString GetValueString(const wchar_t *srcString, unsigned &finishPos)
47{
48 UString result;
49 for (finishPos = 0;;)
50 {
51 wchar_t c = srcString[finishPos];
52 if (c == 0)
53 break;
54 finishPos++;
55 if (c == kNewLineChar)
56 break;
57 result += c;
58 }
59 result.Trim();
60 RemoveCr(result);
61 return result;
62}
63
64static bool GetTextPairs(const UString &srcString, CObjectVector<CTextPair> &pairs)
65{
66 pairs.Clear();
67 unsigned pos = 0;
68
69 if (srcString.Len() > 0)
70 {
71 if (srcString[0] == kBOM)
72 pos++;
73 }
74 while (pos < srcString.Len())
75 {
76 unsigned finishPos;
77 UString id = GetIDString((const wchar_t *)srcString + pos, finishPos);
78 pos += finishPos;
79 if (id.IsEmpty())
80 continue;
81 UString value = GetValueString((const wchar_t *)srcString + pos, finishPos);
82 pos += finishPos;
83 if (!id.IsEmpty())
84 {
85 CTextPair pair;
86 pair.ID = id;
87 pair.Value = value;
88 pairs.Add(pair);
89 }
90 }
91 return true;
92}
93
94static int ComparePairIDs(const UString &s1, const UString &s2)
95 { return MyStringCompareNoCase(s1, s2); }
96
97static int ComparePairItems(const CTextPair &p1, const CTextPair &p2)
98 { return ComparePairIDs(p1.ID, p2.ID); }
99
100static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */)
101 { return ComparePairItems(**(const CTextPair *const *)a1, **(const CTextPair *const *)a2); }
102
103void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); }
104
105int CPairsStorage::FindID(const UString &id, int &insertPos) const
106{
107 int left = 0, right = Pairs.Size();
108 while (left != right)
109 {
110 int mid = (left + right) / 2;
111 int compResult = ComparePairIDs(id, Pairs[mid].ID);
112 if (compResult == 0)
113 return mid;
114 if (compResult < 0)
115 right = mid;
116 else
117 left = mid + 1;
118 }
119 insertPos = left;
120 return -1;
121}
122
123int CPairsStorage::FindID(const UString &id) const
124{
125 int pos;
126 return FindID(id, pos);
127}
128
129void CPairsStorage::AddPair(const CTextPair &pair)
130{
131 int insertPos;
132 int pos = FindID(pair.ID, insertPos);
133 if (pos >= 0)
134 Pairs[pos] = pair;
135 else
136 Pairs.Insert(insertPos, pair);
137}
138
139void CPairsStorage::DeletePair(const UString &id)
140{
141 int pos = FindID(id);
142 if (pos >= 0)
143 Pairs.Delete(pos);
144}
145
146bool CPairsStorage::GetValue(const UString &id, UString &value) const
147{
148 value.Empty();
149 int pos = FindID(id);
150 if (pos < 0)
151 return false;
152 value = Pairs[pos].Value;
153 return true;
154}
155
156UString CPairsStorage::GetValue(const UString &id) const
157{
158 int pos = FindID(id);
159 if (pos < 0)
160 return UString();
161 return Pairs[pos].Value;
162}
163
164bool CPairsStorage::ReadFromString(const UString &text)
165{
166 bool result = ::GetTextPairs(text, Pairs);
167 if (result)
168 Sort();
169 else
170 Pairs.Clear();
171 return result;
172}
173
174void CPairsStorage::SaveToString(UString &text) const
175{
176 FOR_VECTOR (i, Pairs)
177 {
178 const CTextPair &pair = Pairs[i];
179 bool multiWord = (pair.ID.Find(L' ') >= 0);
180 if (multiWord)
181 text += '\"';
182 text += pair.ID;
183 if (multiWord)
184 text += '\"';
185 text += ' ';
186 text += pair.Value;
187 text += '\x0D';
188 text.Add_LF();
189 }
190}
diff --git a/CPP/7zip/UI/FileManager/TextPairs.h b/CPP/7zip/UI/FileManager/TextPairs.h
new file mode 100644
index 0000000..0a71d04
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/TextPairs.h
@@ -0,0 +1,32 @@
1// TextPairs.h
2
3#ifndef __FM_TEXT_PAIRS_H
4#define __FM_TEXT_PAIRS_H
5
6#include "../../../Common/MyString.h"
7
8struct CTextPair
9{
10 UString ID;
11 UString Value;
12};
13
14class CPairsStorage
15{
16 CObjectVector<CTextPair> Pairs;
17
18 int FindID(const UString &id, int &insertPos) const;
19 int FindID(const UString &id) const;
20 void Sort();
21public:
22 void Clear() { Pairs.Clear(); }
23 bool ReadFromString(const UString &text);
24 void SaveToString(UString &text) const;
25
26 bool GetValue(const UString &id, UString &value) const;
27 UString GetValue(const UString &id) const;
28 void AddPair(const CTextPair &pair);
29 void DeletePair(const UString &id);
30};
31
32#endif
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.cpp b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp
new file mode 100644
index 0000000..67e70fb
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/UpdateCallback100.cpp
@@ -0,0 +1,124 @@
1// UpdateCallback100.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Windows/ErrorMsg.h"
6
7#include "../GUI/resource3.h"
8
9#include "LangUtils.h"
10#include "UpdateCallback100.h"
11
12STDMETHODIMP CUpdateCallback100Imp::ScanProgress(UInt64 /* numFolders */, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 /* isDir */)
13{
14 return ProgressDialog->Sync.ScanProgress(numFiles, totalSize, us2fs(path));
15}
16
17STDMETHODIMP CUpdateCallback100Imp::ScanError(const wchar_t *path, HRESULT errorCode)
18{
19 ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
20 return S_OK;
21}
22
23STDMETHODIMP CUpdateCallback100Imp::SetNumFiles(UInt64 numFiles)
24{
25 return ProgressDialog->Sync.Set_NumFilesTotal(numFiles);
26}
27
28STDMETHODIMP CUpdateCallback100Imp::SetTotal(UInt64 size)
29{
30 ProgressDialog->Sync.Set_NumBytesTotal(size);
31 return S_OK;
32}
33
34STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 *completed)
35{
36 return ProgressDialog->Sync.Set_NumBytesCur(completed);
37}
38
39STDMETHODIMP CUpdateCallback100Imp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
40{
41 ProgressDialog->Sync.Set_Ratio(inSize, outSize);
42 return S_OK;
43}
44
45STDMETHODIMP CUpdateCallback100Imp::CompressOperation(const wchar_t *name)
46{
47 return SetOperation_Base(NUpdateNotifyOp::kAdd, name, false);
48}
49
50STDMETHODIMP CUpdateCallback100Imp::DeleteOperation(const wchar_t *name)
51{
52 return SetOperation_Base(NUpdateNotifyOp::kDelete, name, false);
53}
54
55STDMETHODIMP CUpdateCallback100Imp::OperationResult(Int32 /* operationResult */)
56{
57 ProgressDialog->Sync.Set_NumFilesCur(++NumFiles);
58 return S_OK;
59}
60
61void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
62
63HRESULT CUpdateCallback100Imp::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
64{
65 if (opRes != NArchive::NExtract::NOperationResult::kOK)
66 {
67 UString s;
68 SetExtractErrorMessage(opRes, isEncrypted, name, s);
69 ProgressDialog->Sync.AddError_Message(s);
70 }
71 return S_OK;
72}
73
74HRESULT CUpdateCallback100Imp::ReportUpdateOperation(UInt32 notifyOp, const wchar_t *name, Int32 isDir)
75{
76 return SetOperation_Base(notifyOp, name, IntToBool(isDir));
77}
78
79STDMETHODIMP CUpdateCallback100Imp::UpdateErrorMessage(const wchar_t *message)
80{
81 ProgressDialog->Sync.AddError_Message(message);
82 return S_OK;
83}
84
85HRESULT CUpdateCallback100Imp::OpenFileError(const wchar_t *path, HRESULT errorCode)
86{
87 ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
88 return S_OK;
89}
90
91STDMETHODIMP CUpdateCallback100Imp::ReadingFileError(const wchar_t *path, HRESULT errorCode)
92{
93 ProgressDialog->Sync.AddError_Code_Name(errorCode, path);
94 return S_OK;
95}
96
97STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
98{
99 *password = NULL;
100 *passwordIsDefined = BoolToInt(PasswordIsDefined);
101 if (!PasswordIsDefined)
102 return S_OK;
103 return StringToBstr(Password, password);
104}
105
106STDMETHODIMP CUpdateCallback100Imp::SetTotal(const UInt64 * /* files */, const UInt64 * /* bytes */)
107{
108 return S_OK;
109}
110
111STDMETHODIMP CUpdateCallback100Imp::SetCompleted(const UInt64 * /* files */, const UInt64 * /* bytes */)
112{
113 return ProgressDialog->Sync.CheckStop();
114}
115
116STDMETHODIMP CUpdateCallback100Imp::CryptoGetTextPassword(BSTR *password)
117{
118 *password = NULL;
119 if (!PasswordIsDefined)
120 {
121 RINOK(ShowAskPasswordDialog())
122 }
123 return StringToBstr(Password, password);
124}
diff --git a/CPP/7zip/UI/FileManager/UpdateCallback100.h b/CPP/7zip/UI/FileManager/UpdateCallback100.h
new file mode 100644
index 0000000..7cbc11e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/UpdateCallback100.h
@@ -0,0 +1,52 @@
1// UpdateCallback100.h
2
3#ifndef __UPDATE_CALLBACK100_H
4#define __UPDATE_CALLBACK100_H
5
6#include "../../../Common/MyCom.h"
7
8#include "../../IPassword.h"
9
10#include "../Agent/IFolderArchive.h"
11
12#include "../GUI/UpdateCallbackGUI2.h"
13
14#include "ProgressDialog2.h"
15
16class CUpdateCallback100Imp:
17 public IFolderArchiveUpdateCallback,
18 public IFolderArchiveUpdateCallback2,
19 public IFolderScanProgress,
20 public ICryptoGetTextPassword2,
21 public ICryptoGetTextPassword,
22 public IArchiveOpenCallback,
23 public ICompressProgressInfo,
24 public CUpdateCallbackGUI2,
25 public CMyUnknownImp
26{
27public:
28
29 // CUpdateCallback100Imp() {}
30
31 MY_UNKNOWN_IMP7(
32 IFolderArchiveUpdateCallback,
33 IFolderArchiveUpdateCallback2,
34 IFolderScanProgress,
35 ICryptoGetTextPassword2,
36 ICryptoGetTextPassword,
37 IArchiveOpenCallback,
38 ICompressProgressInfo)
39
40 INTERFACE_IProgress(;)
41 INTERFACE_IArchiveOpenCallback(;)
42 INTERFACE_IFolderArchiveUpdateCallback(;)
43 INTERFACE_IFolderArchiveUpdateCallback2(;)
44 INTERFACE_IFolderScanProgress(;)
45
46 STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
47
48 STDMETHOD(CryptoGetTextPassword)(BSTR *password);
49 STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
50};
51
52#endif
diff --git a/CPP/7zip/UI/FileManager/VerCtrl.cpp b/CPP/7zip/UI/FileManager/VerCtrl.cpp
new file mode 100644
index 0000000..4bb034f
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/VerCtrl.cpp
@@ -0,0 +1,428 @@
1// VerCtrl.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/StringToInt.h"
6
7#include "../../../Windows/FileName.h"
8#include "../../../Windows/FileFind.h"
9
10#include "App.h"
11#include "RegistryUtils.h"
12#include "OverwriteDialog.h"
13
14#include "resource.h"
15
16using namespace NWindows;
17using namespace NFile;
18using namespace NFind;
19using namespace NDir;
20
21static FString ConvertPath_to_Ctrl(const FString &path)
22{
23 FString s = path;
24 s.Replace(FChar(':'), FChar('_'));
25 return s;
26}
27
28struct CFileDataInfo
29{
30 CByteBuffer Data;
31 BY_HANDLE_FILE_INFORMATION Info;
32 bool IsOpen;
33
34 CFileDataInfo(): IsOpen (false) {}
35 UInt64 GetSize() const { return (((UInt64)Info.nFileSizeHigh) << 32) + Info.nFileSizeLow; }
36 bool Read(const FString &path);
37};
38
39
40bool CFileDataInfo::Read(const FString &path)
41{
42 IsOpen = false;
43 NIO::CInFile file;
44 if (!file.Open(path))
45 return false;
46 if (!file.GetFileInformation(&Info))
47 return false;
48
49 const UInt64 size = GetSize();
50 const size_t size2 = (size_t)size;
51 if (size2 != size || size2 > (1 << 28))
52 {
53 SetLastError(1);
54 return false;
55 }
56
57 Data.Alloc(size2);
58
59 size_t processedSize;
60 if (!file.ReadFull(Data, size2, processedSize))
61 return false;
62 if (processedSize != size2)
63 {
64 SetLastError(1);
65 return false;
66 }
67 IsOpen = true;
68 return true;
69}
70
71
72static bool CreateComplexDir_for_File(const FString &path)
73{
74 FString resDirPrefix;
75 FString resFileName;
76 if (!GetFullPathAndSplit(path, resDirPrefix, resFileName))
77 return false;
78 return CreateComplexDir(resDirPrefix);
79}
80
81
82static bool ParseNumberString(const FString &s, UInt32 &number)
83{
84 const FChar *end;
85 UInt64 result = ConvertStringToUInt64(s, &end);
86 if (*end != 0 || s.IsEmpty() || result > (UInt32)0x7FFFFFFF)
87 return false;
88 number = (UInt32)result;
89 return true;
90}
91
92
93static void WriteFile(const FString &path, bool createAlways, const CFileDataInfo &fdi, const CPanel &panel)
94{
95 NIO::COutFile outFile;
96 if (!outFile.Create(path, createAlways)) // (createAlways = false) means CREATE_NEW
97 {
98 panel.MessageBox_LastError();
99 return;
100 }
101 UInt32 processedSize;
102 if (!outFile.Write(fdi.Data, (UInt32)fdi.Data.Size(), processedSize))
103 {
104 panel.MessageBox_LastError();
105 return;
106 }
107 if (processedSize != fdi.Data.Size())
108 {
109 panel.MessageBox_Error(L"Write error");
110 return;
111 }
112 if (!outFile.SetTime(
113 &fdi.Info.ftCreationTime,
114 &fdi.Info.ftLastAccessTime,
115 &fdi.Info.ftLastWriteTime))
116 {
117 panel.MessageBox_LastError();
118 return;
119 }
120
121 if (!SetFileAttrib(path, fdi.Info.dwFileAttributes))
122 {
123 panel.MessageBox_LastError();
124 return;
125 }
126}
127
128
129static UInt64 FILETIME_to_UInt64(const FILETIME &ft)
130{
131 return ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);
132}
133
134static void UInt64_TO_FILETIME(UInt64 v, FILETIME &ft)
135{
136 ft.dwLowDateTime = (DWORD)v;
137 ft.dwHighDateTime = (DWORD)(v >> 32);
138}
139
140
141void CApp::VerCtrl(unsigned id)
142{
143 const CPanel &panel = GetFocusedPanel();
144
145 if (!panel.Is_IO_FS_Folder())
146 {
147 panel.MessageBox_Error_UnsupportOperation();
148 return;
149 }
150
151 CRecordVector<UInt32> indices;
152 panel.GetSelectedItemsIndices(indices);
153
154 if (indices.Size() != 1)
155 {
156 // panel.MessageBox_Error_UnsupportOperation();
157 return;
158 }
159
160 const FString path = us2fs(panel.GetItemFullPath(indices[0]));
161
162 UString vercPath;
163 ReadReg_VerCtrlPath(vercPath);
164 if (vercPath.IsEmpty())
165 return;
166 NName::NormalizeDirPathPrefix(vercPath);
167
168 FString dirPrefix;
169 FString fileName;
170 if (!GetFullPathAndSplit(path, dirPrefix, fileName))
171 {
172 panel.MessageBox_LastError();
173 return;
174 }
175
176 const FString dirPrefix2 = us2fs(vercPath) + ConvertPath_to_Ctrl(dirPrefix);
177 const FString path2 = dirPrefix2 + fileName;
178
179 bool sameTime = false;
180 bool sameData = false;
181 bool areIdentical = false;
182
183 CFileDataInfo fdi, fdi2;
184 if (!fdi.Read(path))
185 {
186 panel.MessageBox_LastError();
187 return;
188 }
189
190 if (fdi2.Read(path2))
191 {
192 sameData = (fdi.Data == fdi2.Data);
193 sameTime = (CompareFileTime(&fdi.Info.ftLastWriteTime, &fdi2.Info.ftLastWriteTime) == 0);
194 areIdentical = (sameData && sameTime);
195 }
196
197 const bool isReadOnly = NAttributes::IsReadOnly(fdi.Info.dwFileAttributes);
198
199 if (id == IDM_VER_EDIT)
200 {
201 if (!isReadOnly)
202 {
203 panel.MessageBox_Error(L"File is not read-only");
204 return;
205 }
206
207 if (!areIdentical)
208 {
209 if (fdi2.IsOpen)
210 {
211 NFind::CEnumerator enumerator;
212 FString d2 = dirPrefix2;
213 d2 += "_7vc";
214 d2.Add_PathSepar();
215 d2 += fileName;
216 d2.Add_PathSepar();
217 enumerator.SetDirPrefix(d2);
218 NFind::CDirEntry fi;
219 Int32 maxVal = -1;
220 while (enumerator.Next(fi))
221 {
222 UInt32 val;
223 if (!ParseNumberString(fi.Name, val))
224 continue;
225 if ((Int32)val > maxVal)
226 maxVal = val;
227 }
228
229 UInt32 next = (UInt32)maxVal + 1;
230 if (maxVal < 0)
231 {
232 next = 1;
233 if (!::CreateComplexDir_for_File(path2))
234 {
235 panel.MessageBox_LastError();
236 return;
237 }
238 }
239
240 // we rename old file2 to some name;
241 FString path_num = d2;
242 {
243 AString t;
244 t.Add_UInt32((UInt32)next);
245 while (t.Len() < 3)
246 t.InsertAtFront('0');
247 path_num += t;
248 }
249
250 if (maxVal < 0)
251 {
252 if (!::CreateComplexDir_for_File(path_num))
253 {
254 panel.MessageBox_LastError();
255 return;
256 }
257 }
258
259 if (!NDir::MyMoveFile(path2, path_num))
260 {
261 panel.MessageBox_LastError();
262 return;
263 }
264 }
265 else
266 {
267 if (!::CreateComplexDir_for_File(path2))
268 {
269 panel.MessageBox_LastError();
270 return;
271 }
272 }
273 /*
274 if (!::CopyFile(fs2fas(path), fs2fas(path2), TRUE))
275 {
276 panel.MessageBox_LastError();
277 return;
278 }
279 */
280 WriteFile(path2,
281 false, // (createAlways = false) means CREATE_NEW
282 fdi, panel);
283 }
284
285 if (!SetFileAttrib(path, fdi.Info.dwFileAttributes & ~(DWORD)FILE_ATTRIBUTE_READONLY))
286 {
287 panel.MessageBox_LastError();
288 return;
289 }
290
291 return;
292 }
293
294 if (isReadOnly)
295 {
296 panel.MessageBox_Error(L"File is read-only");
297 return;
298 }
299
300 if (id == IDM_VER_COMMIT)
301 {
302 if (sameData)
303 {
304 if (!sameTime)
305 {
306 panel.MessageBox_Error(
307 L"Same data, but different timestamps.\n"
308 L"Use `Revert` to recover timestamp.");
309 return;
310 }
311 }
312
313 const UInt64 timeStampOriginal = FILETIME_to_UInt64(fdi.Info.ftLastWriteTime);
314 UInt64 timeStamp2 = 0;
315 if (fdi2.IsOpen)
316 timeStamp2 = FILETIME_to_UInt64(fdi2.Info.ftLastWriteTime);
317
318 if (timeStampOriginal > timeStamp2)
319 {
320 const UInt64 k_Ntfs_prec = 10000000;
321 UInt64 timeStamp = timeStampOriginal;
322 const UInt32 k_precs[] = { 60 * 60, 60, 2, 1 };
323 for (unsigned i = 0; i < ARRAY_SIZE(k_precs); i++)
324 {
325 timeStamp = timeStampOriginal;
326 const UInt64 prec = k_Ntfs_prec * k_precs[i];
327 // timeStamp += prec - 1; // for rounding up
328 timeStamp /= prec;
329 timeStamp *= prec;
330 if (timeStamp > timeStamp2)
331 break;
332 }
333
334 if (timeStamp != timeStampOriginal
335 && timeStamp > timeStamp2)
336 {
337 FILETIME mTime;
338 UInt64_TO_FILETIME(timeStamp, mTime);
339 // NDir::SetFileAttrib(path, 0);
340 {
341 NIO::COutFile outFile;
342 if (!outFile.Open(path, OPEN_EXISTING))
343 {
344 panel.MessageBox_LastError();
345 return;
346 // if (::GetLastError() != ERROR_SUCCESS)
347 // throw "open error";
348 }
349 else
350 {
351 const UInt64 cTime = FILETIME_to_UInt64(fdi.Info.ftCreationTime);
352 if (cTime > timeStamp)
353 outFile.SetTime(&mTime, NULL, &mTime);
354 else
355 outFile.SetMTime(&mTime);
356 }
357 }
358 }
359 }
360
361 if (!SetFileAttrib(path, fdi.Info.dwFileAttributes | FILE_ATTRIBUTE_READONLY))
362 {
363 panel.MessageBox_LastError();
364 return;
365 }
366 return;
367 }
368
369 if (id == IDM_VER_REVERT)
370 {
371 if (!fdi2.IsOpen)
372 {
373 panel.MessageBox_Error(L"No file to revert");
374 return;
375 }
376 if (!sameData || !sameTime)
377 {
378 if (!sameData)
379 {
380 /*
381 UString m;
382 m = "Are you sure you want to revert file ?";
383 m.Add_LF();
384 m += path;
385 if (::MessageBoxW(panel.GetParent(), m, L"Version Control: File Revert", MB_OKCANCEL | MB_ICONQUESTION) != IDOK)
386 return;
387 */
388 COverwriteDialog dialog;
389
390 dialog.OldFileInfo.SetTime(&fdi.Info.ftLastWriteTime);
391 dialog.OldFileInfo.SetSize(fdi.GetSize());
392 dialog.OldFileInfo.Name = fs2us(path);
393
394 dialog.NewFileInfo.SetTime(&fdi2.Info.ftLastWriteTime);
395 dialog.NewFileInfo.SetSize(fdi2.GetSize());
396 dialog.NewFileInfo.Name = fs2us(path2);
397
398 dialog.ShowExtraButtons = false;
399 dialog.DefaultButton_is_NO = true;
400
401 INT_PTR writeAnswer = dialog.Create(panel.GetParent());
402
403 if (writeAnswer != IDYES)
404 return;
405 }
406
407 WriteFile(path,
408 true, // (createAlways = true) means CREATE_ALWAYS
409 fdi2, panel);
410 }
411 else
412 {
413 if (!SetFileAttrib(path, fdi2.Info.dwFileAttributes | FILE_ATTRIBUTE_READONLY))
414 {
415 panel.MessageBox_LastError();
416 return;
417 }
418 }
419 return;
420 }
421
422 // if (id == IDM_VER_DIFF)
423 {
424 if (!fdi2.IsOpen)
425 return;
426 DiffFiles(fs2us(path2), fs2us(path));
427 }
428}
diff --git a/CPP/7zip/UI/FileManager/ViewSettings.cpp b/CPP/7zip/UI/FileManager/ViewSettings.cpp
new file mode 100644
index 0000000..0f87711
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ViewSettings.cpp
@@ -0,0 +1,313 @@
1// ViewSettings.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/Registry.h"
11#include "../../../Windows/Synchronization.h"
12
13#include "ViewSettings.h"
14
15using namespace NWindows;
16using namespace NRegistry;
17
18#define REG_PATH_FM TEXT("Software") TEXT(STRING_PATH_SEPARATOR) TEXT("7-Zip") TEXT(STRING_PATH_SEPARATOR) TEXT("FM")
19
20static LPCTSTR const kCUBasePath = REG_PATH_FM;
21static LPCTSTR const kCulumnsKeyName = REG_PATH_FM TEXT(STRING_PATH_SEPARATOR) TEXT("Columns");
22
23static LPCTSTR const kPositionValueName = TEXT("Position");
24static LPCTSTR const kPanelsInfoValueName = TEXT("Panels");
25static LPCTSTR const kToolbars = TEXT("Toolbars");
26
27static LPCWSTR const kPanelPathValueName = L"PanelPath";
28
29static LPCTSTR const kListMode = TEXT("ListMode");
30static LPCTSTR const kFolderHistoryValueName = TEXT("FolderHistory");
31static LPCTSTR const kFastFoldersValueName = TEXT("FolderShortcuts");
32static LPCTSTR const kCopyHistoryValueName = TEXT("CopyHistory");
33
34static NSynchronization::CCriticalSection g_CS;
35
36#define Set32(p, v) SetUi32(((Byte *)p), v)
37#define SetBool(p, v) Set32(p, ((v) ? 1 : 0))
38
39#define Get32(p, dest) dest = GetUi32((const Byte *)p)
40#define GetBool(p, dest) dest = (GetUi32(p) != 0);
41
42/*
43struct CColumnHeader
44{
45 UInt32 Version;
46 UInt32 SortID;
47 UInt32 Ascending; // bool
48};
49*/
50
51static const UInt32 kListViewHeaderSize = 3 * 4;
52static const UInt32 kColumnInfoSize = 3 * 4;
53static const UInt32 kListViewVersion = 1;
54
55void CListViewInfo::Save(const UString &id) const
56{
57 const UInt32 dataSize = kListViewHeaderSize + kColumnInfoSize * Columns.Size();
58 CByteArr buf(dataSize);
59
60 Set32(buf, kListViewVersion);
61 Set32(buf + 4, SortID);
62 SetBool(buf + 8, Ascending);
63 FOR_VECTOR (i, Columns)
64 {
65 const CColumnInfo &column = Columns[i];
66 Byte *p = buf + kListViewHeaderSize + i * kColumnInfoSize;
67 Set32(p, column.PropID);
68 SetBool(p + 4, column.IsVisible);
69 Set32(p + 8, column.Width);
70 }
71 {
72 NSynchronization::CCriticalSectionLock lock(g_CS);
73 CKey key;
74 key.Create(HKEY_CURRENT_USER, kCulumnsKeyName);
75 key.SetValue(GetSystemString(id), (const Byte *)buf, dataSize);
76 }
77}
78
79void CListViewInfo::Read(const UString &id)
80{
81 Clear();
82 CByteBuffer buf;
83 UInt32 size;
84 {
85 NSynchronization::CCriticalSectionLock lock(g_CS);
86 CKey key;
87 if (key.Open(HKEY_CURRENT_USER, kCulumnsKeyName, KEY_READ) != ERROR_SUCCESS)
88 return;
89 if (key.QueryValue(GetSystemString(id), buf, size) != ERROR_SUCCESS)
90 return;
91 }
92 if (size < kListViewHeaderSize)
93 return;
94 UInt32 version;
95 Get32(buf, version);
96 if (version != kListViewVersion)
97 return;
98 Get32(buf + 4, SortID);
99 GetBool(buf + 8, Ascending);
100
101 IsLoaded = true;
102
103 size -= kListViewHeaderSize;
104 if (size % kColumnInfoSize != 0)
105 return;
106 unsigned numItems = size / kColumnInfoSize;
107 Columns.ClearAndReserve(numItems);
108 for (unsigned i = 0; i < numItems; i++)
109 {
110 CColumnInfo column;
111 const Byte *p = buf + kListViewHeaderSize + i * kColumnInfoSize;
112 Get32(p, column.PropID);
113 GetBool(p + 4, column.IsVisible);
114 Get32(p + 8, column.Width);
115 Columns.AddInReserved(column);
116 }
117}
118
119
120/*
121struct CWindowPosition
122{
123 RECT Rect;
124 UInt32 Maximized; // bool
125};
126
127struct CPanelsInfo
128{
129 UInt32 NumPanels;
130 UInt32 CurrentPanel;
131 UInt32 SplitterPos;
132};
133*/
134
135static const UInt32 kWindowPositionHeaderSize = 5 * 4;
136static const UInt32 kPanelsInfoHeaderSize = 3 * 4;
137
138void CWindowInfo::Save() const
139{
140 NSynchronization::CCriticalSectionLock lock(g_CS);
141 CKey key;
142 key.Create(HKEY_CURRENT_USER, kCUBasePath);
143 {
144 Byte buf[kWindowPositionHeaderSize];
145 Set32(buf, rect.left);
146 Set32(buf + 4, rect.top);
147 Set32(buf + 8, rect.right);
148 Set32(buf + 12, rect.bottom);
149 SetBool(buf + 16, maximized);
150 key.SetValue(kPositionValueName, buf, kWindowPositionHeaderSize);
151 }
152 {
153 Byte buf[kPanelsInfoHeaderSize];
154 Set32(buf, numPanels);
155 Set32(buf + 4, currentPanel);
156 Set32(buf + 8, splitterPos);
157 key.SetValue(kPanelsInfoValueName, buf, kPanelsInfoHeaderSize);
158 }
159}
160
161static bool QueryBuf(CKey &key, LPCTSTR name, CByteBuffer &buf, UInt32 dataSize)
162{
163 UInt32 size;
164 return key.QueryValue(name, buf, size) == ERROR_SUCCESS && size == dataSize;
165}
166
167void CWindowInfo::Read(bool &windowPosDefined, bool &panelInfoDefined)
168{
169 windowPosDefined = false;
170 panelInfoDefined = false;
171 NSynchronization::CCriticalSectionLock lock(g_CS);
172 CKey key;
173 if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)
174 return;
175 CByteBuffer buf;
176 if (QueryBuf(key, kPositionValueName, buf, kWindowPositionHeaderSize))
177 {
178 Get32(buf, rect.left);
179 Get32(buf + 4, rect.top);
180 Get32(buf + 8, rect.right);
181 Get32(buf + 12, rect.bottom);
182 GetBool(buf + 16, maximized);
183 windowPosDefined = true;
184 }
185 if (QueryBuf(key, kPanelsInfoValueName, buf, kPanelsInfoHeaderSize))
186 {
187 Get32(buf, numPanels);
188 Get32(buf + 4, currentPanel);
189 Get32(buf + 8, splitterPos);
190 panelInfoDefined = true;
191 }
192 return;
193}
194
195
196static void SaveUi32Val(const TCHAR *name, UInt32 value)
197{
198 CKey key;
199 key.Create(HKEY_CURRENT_USER, kCUBasePath);
200 key.SetValue(name, value);
201}
202
203static bool ReadUi32Val(const TCHAR *name, UInt32 &value)
204{
205 CKey key;
206 if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)
207 return false;
208 return key.QueryValue(name, value) == ERROR_SUCCESS;
209}
210
211void SaveToolbarsMask(UInt32 toolbarMask)
212{
213 SaveUi32Val(kToolbars, toolbarMask);
214}
215
216static const UInt32 kDefaultToolbarMask = ((UInt32)1 << 31) | 8 | 4 | 1;
217
218UInt32 ReadToolbarsMask()
219{
220 UInt32 mask;
221 if (!ReadUi32Val(kToolbars, mask))
222 return kDefaultToolbarMask;
223 return mask;
224}
225
226
227void CListMode::Save() const
228{
229 UInt32 t = 0;
230 for (int i = 0; i < 2; i++)
231 t |= ((Panels[i]) & 0xFF) << (i * 8);
232 SaveUi32Val(kListMode, t);
233}
234
235void CListMode::Read()
236{
237 Init();
238 UInt32 t;
239 if (!ReadUi32Val(kListMode, t))
240 return;
241 for (int i = 0; i < 2; i++)
242 {
243 Panels[i] = (t & 0xFF);
244 t >>= 8;
245 }
246}
247
248static UString GetPanelPathName(UInt32 panelIndex)
249{
250 UString s (kPanelPathValueName);
251 s.Add_UInt32(panelIndex);
252 return s;
253}
254
255void SavePanelPath(UInt32 panel, const UString &path)
256{
257 NSynchronization::CCriticalSectionLock lock(g_CS);
258 CKey key;
259 key.Create(HKEY_CURRENT_USER, kCUBasePath);
260 key.SetValue(GetPanelPathName(panel), path);
261}
262
263bool ReadPanelPath(UInt32 panel, UString &path)
264{
265 NSynchronization::CCriticalSectionLock lock(g_CS);
266 CKey key;
267 if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) != ERROR_SUCCESS)
268 return false;
269 return (key.QueryValue(GetPanelPathName(panel), path) == ERROR_SUCCESS);
270}
271
272
273static void SaveStringList(LPCTSTR valueName, const UStringVector &folders)
274{
275 NSynchronization::CCriticalSectionLock lock(g_CS);
276 CKey key;
277 key.Create(HKEY_CURRENT_USER, kCUBasePath);
278 key.SetValue_Strings(valueName, folders);
279}
280
281static void ReadStringList(LPCTSTR valueName, UStringVector &folders)
282{
283 folders.Clear();
284 NSynchronization::CCriticalSectionLock lock(g_CS);
285 CKey key;
286 if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)
287 key.GetValue_Strings(valueName, folders);
288}
289
290void SaveFolderHistory(const UStringVector &folders)
291 { SaveStringList(kFolderHistoryValueName, folders); }
292void ReadFolderHistory(UStringVector &folders)
293 { ReadStringList(kFolderHistoryValueName, folders); }
294
295void SaveFastFolders(const UStringVector &folders)
296 { SaveStringList(kFastFoldersValueName, folders); }
297void ReadFastFolders(UStringVector &folders)
298 { ReadStringList(kFastFoldersValueName, folders); }
299
300void SaveCopyHistory(const UStringVector &folders)
301 { SaveStringList(kCopyHistoryValueName, folders); }
302void ReadCopyHistory(UStringVector &folders)
303 { ReadStringList(kCopyHistoryValueName, folders); }
304
305void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s)
306{
307 for (unsigned i = 0; i < list.Size();)
308 if (s.IsEqualTo_NoCase(list[i]))
309 list.Delete(i);
310 else
311 i++;
312 list.Insert(0, s);
313}
diff --git a/CPP/7zip/UI/FileManager/ViewSettings.h b/CPP/7zip/UI/FileManager/ViewSettings.h
new file mode 100644
index 0000000..aeb6897
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/ViewSettings.h
@@ -0,0 +1,115 @@
1// ViewSettings.h
2
3#ifndef __VIEW_SETTINGS_H
4#define __VIEW_SETTINGS_H
5
6#include "../../../Common/MyTypes.h"
7#include "../../../Common/MyString.h"
8
9struct CColumnInfo
10{
11 PROPID PropID;
12 bool IsVisible;
13 UInt32 Width;
14
15 bool IsEqual(const CColumnInfo &a) const
16 {
17 return PropID == a.PropID && IsVisible == a.IsVisible && Width == a.Width;
18 }
19};
20
21struct CListViewInfo
22{
23 CRecordVector<CColumnInfo> Columns;
24 PROPID SortID;
25 bool Ascending;
26 bool IsLoaded;
27
28 void Clear()
29 {
30 SortID = 0;
31 Ascending = true;
32 IsLoaded = false;
33 Columns.Clear();
34 }
35
36 CListViewInfo():
37 SortID(0),
38 Ascending(true),
39 IsLoaded(false)
40 {}
41
42 /*
43 int FindColumnWithID(PROPID propID) const
44 {
45 FOR_VECTOR (i, Columns)
46 if (Columns[i].PropID == propID)
47 return i;
48 return -1;
49 }
50 */
51
52 bool IsEqual(const CListViewInfo &info) const
53 {
54 if (Columns.Size() != info.Columns.Size() ||
55 SortID != info.SortID ||
56 Ascending != info.Ascending)
57 return false;
58 FOR_VECTOR (i, Columns)
59 if (!Columns[i].IsEqual(info.Columns[i]))
60 return false;
61 return true;
62 }
63
64 void Save(const UString &id) const;
65 void Read(const UString &id);
66};
67
68
69struct CWindowInfo
70{
71 RECT rect;
72 bool maximized;
73
74 UInt32 numPanels;
75 UInt32 currentPanel;
76 UInt32 splitterPos;
77
78 void Save() const;
79 void Read(bool &windowPosDefined, bool &panelInfoDefined);
80};
81
82void SaveToolbarsMask(UInt32 toolbarMask);
83UInt32 ReadToolbarsMask();
84
85const UInt32 kListMode_Report = 3;
86
87struct CListMode
88{
89 UInt32 Panels[2];
90
91 void Init() { Panels[0] = Panels[1] = kListMode_Report; }
92 CListMode() { Init(); }
93
94 void Save() const ;
95 void Read();
96};
97
98
99
100void SavePanelPath(UInt32 panel, const UString &path);
101bool ReadPanelPath(UInt32 panel, UString &path);
102
103
104void SaveFolderHistory(const UStringVector &folders);
105void ReadFolderHistory(UStringVector &folders);
106
107void SaveFastFolders(const UStringVector &folders);
108void ReadFastFolders(UStringVector &folders);
109
110void SaveCopyHistory(const UStringVector &folders);
111void ReadCopyHistory(UStringVector &folders);
112
113void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s);
114
115#endif
diff --git a/CPP/7zip/UI/FileManager/makefile b/CPP/7zip/UI/FileManager/makefile
new file mode 100644
index 0000000..dd2a2f2
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/makefile
@@ -0,0 +1,107 @@
1PROG = 7zFM.exe
2CFLAGS = $(CFLAGS) \
3 -DEXTERNAL_CODECS \
4
5!include "FM.mak"
6
7COMMON_OBJS = \
8 $O\DynLimBuf.obj \
9 $O\IntToString.obj \
10 $O\Lang.obj \
11 $O\MyString.obj \
12 $O\MyVector.obj \
13 $O\NewHandler.obj \
14 $O\Random.obj \
15 $O\StringConvert.obj \
16 $O\StringToInt.obj \
17 $O\UTFConvert.obj \
18 $O\Wildcard.obj \
19
20WIN_OBJS = $(WIN_OBJS) \
21 $O\Clipboard.obj \
22 $O\CommonDialog.obj \
23 $O\DLL.obj \
24 $O\ErrorMsg.obj \
25 $O\FileDir.obj \
26 $O\FileFind.obj \
27 $O\FileIO.obj \
28 $O\FileLink.obj \
29 $O\FileName.obj \
30 $O\MemoryGlobal.obj \
31 $O\MemoryLock.obj \
32 $O\Menu.obj \
33 $O\ProcessUtils.obj \
34 $O\PropVariant.obj \
35 $O\PropVariantConv.obj \
36 $O\Registry.obj \
37 $O\ResourceString.obj \
38 $O\Shell.obj \
39 $O\Synchronization.obj \
40 $O\System.obj \
41 $O\TimeUtils.obj \
42 $O\Window.obj \
43
44
45WIN_CTRL_OBJS = \
46 $O\ComboBox.obj \
47 $O\Dialog.obj \
48 $O\ListView.obj \
49 $O\PropertyPage.obj \
50 $O\Window2.obj \
51
527ZIP_COMMON_OBJS = \
53 $O\CreateCoder.obj \
54 $O\FilePathAutoRename.obj \
55 $O\FileStreams.obj \
56 $O\FilterCoder.obj \
57 $O\LimitedStreams.obj \
58 $O\MethodProps.obj \
59 $O\ProgressUtils.obj \
60 $O\PropId.obj \
61 $O\StreamObjects.obj \
62 $O\StreamUtils.obj \
63 $O\UniqBlocks.obj \
64
65UI_COMMON_OBJS = \
66 $O\ArchiveExtractCallback.obj \
67 $O\ArchiveName.obj \
68 $O\ArchiveOpenCallback.obj \
69 $O\CompressCall.obj \
70 $O\DefaultName.obj \
71 $O\EnumDirItems.obj \
72 $O\ExtractingFilePath.obj \
73 $O\HashCalc.obj \
74 $O\LoadCodecs.obj \
75 $O\OpenArchive.obj \
76 $O\PropIDUtils.obj \
77 $O\SetProperties.obj \
78 $O\SortUtils.obj \
79 $O\UpdateAction.obj \
80 $O\UpdateCallback.obj \
81 $O\UpdatePair.obj \
82 $O\UpdateProduce.obj \
83 $O\WorkDir.obj \
84 $O\ZipRegistry.obj \
85
86EXPLORER_OBJS = \
87 $O\ContextMenu.obj \
88 $O\RegistryContextMenu.obj \
89
90GUI_OBJS = \
91 $O\HashGUI.obj \
92 $O\UpdateCallbackGUI2.obj \
93
94COMPRESS_OBJS = \
95 $O\CopyCoder.obj \
96
97AR_COMMON_OBJS = \
98 $O\ItemNameUtils.obj \
99
100
101C_OBJS = $(C_OBJS) \
102 $O\Alloc.obj \
103 $O\CpuArch.obj \
104 $O\Sort.obj \
105 $O\Threads.obj \
106
107!include "../../7zip.mak"
diff --git a/CPP/7zip/UI/FileManager/resource.h b/CPP/7zip/UI/FileManager/resource.h
new file mode 100644
index 0000000..98cb4fd
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/resource.h
@@ -0,0 +1,182 @@
1#include "resourceGui.h"
2
3#define IDR_MENUBAR1 70
4#define IDM_MENU 71
5#define IDR_ACCELERATOR1 72
6
7#define IDB_ADD 100
8#define IDB_EXTRACT 101
9#define IDB_TEST 102
10#define IDB_COPY 103
11#define IDB_MOVE 104
12#define IDB_DELETE 105
13#define IDB_INFO 106
14
15#define IDB_ADD2 150
16#define IDB_EXTRACT2 151
17#define IDB_TEST2 152
18#define IDB_COPY2 153
19#define IDB_MOVE2 154
20#define IDB_DELETE2 155
21#define IDB_INFO2 156
22
23#define IDM_HASH_ALL 101
24#define IDM_CRC32 102
25#define IDM_CRC64 103
26#define IDM_SHA1 104
27#define IDM_SHA256 105
28
29#define IDM_OPEN 540
30#define IDM_OPEN_INSIDE 541
31#define IDM_OPEN_OUTSIDE 542
32#define IDM_FILE_VIEW 543
33#define IDM_FILE_EDIT 544
34#define IDM_RENAME 545
35#define IDM_COPY_TO 546
36#define IDM_MOVE_TO 547
37#define IDM_DELETE 548
38#define IDM_SPLIT 549
39#define IDM_COMBINE 550
40#define IDM_PROPERTIES 551
41#define IDM_COMMENT 552
42#define IDM_CRC 553
43#define IDM_DIFF 554
44#define IDM_CREATE_FOLDER 555
45#define IDM_CREATE_FILE 556
46// #define IDM_EXIT 557
47#define IDM_LINK 558
48#define IDM_ALT_STREAMS 559
49
50#define IDM_VER_EDIT 580
51#define IDM_VER_COMMIT 581
52#define IDM_VER_REVERT 582
53#define IDM_VER_DIFF 583
54
55#define IDM_OPEN_INSIDE_ONE 590
56#define IDM_OPEN_INSIDE_PARSER 591
57
58#define IDM_SELECT_ALL 600
59#define IDM_DESELECT_ALL 601
60#define IDM_INVERT_SELECTION 602
61#define IDM_SELECT 603
62#define IDM_DESELECT 604
63#define IDM_SELECT_BY_TYPE 605
64#define IDM_DESELECT_BY_TYPE 606
65
66#define IDM_VIEW_LARGE_ICONS 700
67#define IDM_VIEW_SMALL_ICONS 701
68#define IDM_VIEW_LIST 702
69#define IDM_VIEW_DETAILS 703
70
71#define IDM_VIEW_ARANGE_BY_NAME 710
72#define IDM_VIEW_ARANGE_BY_TYPE 711
73#define IDM_VIEW_ARANGE_BY_DATE 712
74#define IDM_VIEW_ARANGE_BY_SIZE 713
75
76#define IDM_VIEW_ARANGE_NO_SORT 730
77#define IDM_VIEW_FLAT_VIEW 731
78#define IDM_VIEW_TWO_PANELS 732
79#define IDM_VIEW_TOOLBARS 733
80#define IDM_OPEN_ROOT_FOLDER 734
81#define IDM_OPEN_PARENT_FOLDER 735
82#define IDM_FOLDERS_HISTORY 736
83#define IDM_VIEW_REFRESH 737
84#define IDM_VIEW_AUTO_REFRESH 738
85// #define IDM_VIEW_SHOW_DELETED 739
86// #define IDM_VIEW_SHOW_STREAMS 740
87
88#define IDM_VIEW_ARCHIVE_TOOLBAR 750
89#define IDM_VIEW_STANDARD_TOOLBAR 751
90#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS 752
91#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753
92
93#define IDM_VIEW_TIME 761
94
95#define IDS_BOOKMARK 801
96
97#define IDM_OPTIONS 900
98#define IDM_BENCHMARK 901
99#define IDM_BENCHMARK2 902
100
101#define IDM_HELP_CONTENTS 960
102#define IDM_ABOUT 961
103
104#define IDS_OPTIONS 2100
105
106#define IDS_N_SELECTED_ITEMS 3002
107
108#define IDS_FILE_EXIST 3008
109#define IDS_WANT_UPDATE_MODIFIED_FILE 3009
110#define IDS_CANNOT_UPDATE_FILE 3010
111#define IDS_CANNOT_START_EDITOR 3011
112#define IDS_VIRUS 3012
113#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER 3013
114#define IDS_SELECT_ONE_FILE 3014
115#define IDS_SELECT_FILES 3015
116#define IDS_TOO_MANY_ITEMS 3016
117
118#define IDS_COPY 6000
119#define IDS_MOVE 6001
120#define IDS_COPY_TO 6002
121#define IDS_MOVE_TO 6003
122#define IDS_COPYING 6004
123#define IDS_MOVING 6005
124#define IDS_RENAMING 6006
125
126#define IDS_OPERATION_IS_NOT_SUPPORTED 6008
127#define IDS_ERROR_RENAMING 6009
128#define IDS_CONFIRM_FILE_COPY 6010
129#define IDS_WANT_TO_COPY_FILES 6011
130
131#define IDS_CONFIRM_FILE_DELETE 6100
132#define IDS_CONFIRM_FOLDER_DELETE 6101
133#define IDS_CONFIRM_ITEMS_DELETE 6102
134#define IDS_WANT_TO_DELETE_FILE 6103
135#define IDS_WANT_TO_DELETE_FOLDER 6104
136#define IDS_WANT_TO_DELETE_ITEMS 6105
137#define IDS_DELETING 6106
138#define IDS_ERROR_DELETING 6107
139#define IDS_ERROR_LONG_PATH_TO_RECYCLE 6108
140
141#define IDS_CREATE_FOLDER 6300
142#define IDS_CREATE_FILE 6301
143#define IDS_CREATE_FOLDER_NAME 6302
144#define IDS_CREATE_FILE_NAME 6303
145#define IDS_CREATE_FOLDER_DEFAULT_NAME 6304
146#define IDS_CREATE_FILE_DEFAULT_NAME 6305
147#define IDS_CREATE_FOLDER_ERROR 6306
148#define IDS_CREATE_FILE_ERROR 6307
149
150#define IDS_COMMENT 6400
151#define IDS_COMMENT2 6401
152#define IDS_SELECT 6402
153#define IDS_DESELECT 6403
154#define IDS_SELECT_MASK 6404
155
156#define IDS_PROPERTIES 6600
157#define IDS_FOLDERS_HISTORY 6601
158
159#define IDS_COMPUTER 7100
160#define IDS_NETWORK 7101
161#define IDS_DOCUMENTS 7102
162#define IDS_SYSTEM 7103
163
164#define IDS_ADD 7200
165#define IDS_EXTRACT 7201
166#define IDS_TEST 7202
167#define IDS_BUTTON_COPY 7203
168#define IDS_BUTTON_MOVE 7204
169#define IDS_BUTTON_DELETE 7205
170#define IDS_BUTTON_INFO 7206
171
172#define IDS_SPLITTING 7303
173#define IDS_SPLIT_CONFIRM_TITLE 7304
174#define IDS_SPLIT_CONFIRM_MESSAGE 7305
175#define IDS_SPLIT_VOL_MUST_BE_SMALLER 7306
176
177#define IDS_COMBINE 7400
178#define IDS_COMBINE_TO 7401
179#define IDS_COMBINING 7402
180#define IDS_COMBINE_SELECT_ONE_FILE 7403
181#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 7404
182#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 7405
diff --git a/CPP/7zip/UI/FileManager/resource.rc b/CPP/7zip/UI/FileManager/resource.rc
new file mode 100644
index 0000000..fc2c840
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/resource.rc
@@ -0,0 +1,268 @@
1#include "../../MyVersionInfo.rc"
2#include "../../GuiCommon.rc"
3#include "resource.h"
4
5MY_VERSION_INFO_APP("7-Zip File Manager", "7zFM")
6
7IDR_ACCELERATOR1 ACCELERATORS
8BEGIN
9// "N", IDM_CREATE_FILE, VIRTKEY, CONTROL, NOINVERT
10 VK_F1, IDM_HELP_CONTENTS, VIRTKEY, NOINVERT
11 VK_F12, IDM_FOLDERS_HISTORY, VIRTKEY, ALT, NOINVERT
12// VK_F7, IDM_CREATE_FOLDER, VIRTKEY, NOINVERT
13END
14
15
16IDM_MENU MENU
17BEGIN
18 POPUP "&File"
19 BEGIN
20 MENUITEM "&Open\tEnter", IDM_OPEN
21 MENUITEM "Open &Inside\tCtrl+PgDn", IDM_OPEN_INSIDE
22 MENUITEM "Open Inside *", IDM_OPEN_INSIDE_ONE
23 MENUITEM "Open Inside #", IDM_OPEN_INSIDE_PARSER
24 MENUITEM "Open O&utside\tShift+Enter", IDM_OPEN_OUTSIDE
25 MENUITEM "&View\tF3", IDM_FILE_VIEW
26 MENUITEM "&Edit\tF4", IDM_FILE_EDIT
27 MENUITEM SEPARATOR
28 MENUITEM "Rena&me\tF2", IDM_RENAME
29 MENUITEM "&Copy To...\tF5", IDM_COPY_TO
30 MENUITEM "&Move To...\tF6", IDM_MOVE_TO
31 MENUITEM "&Delete\tDel", IDM_DELETE
32 MENUITEM SEPARATOR
33 MENUITEM "&Split file...", IDM_SPLIT
34 MENUITEM "Com&bine files...", IDM_COMBINE
35 MENUITEM SEPARATOR
36 MENUITEM "P&roperties\tAlt+Enter", IDM_PROPERTIES
37 MENUITEM "Comme&nt...\tCtrl+Z", IDM_COMMENT
38 // MENUITEM "Calculate checksum", IDM_CRC
39 POPUP "CRC"
40 BEGIN
41 MENUITEM "CRC-32", IDM_CRC32
42 MENUITEM "CRC-64", IDM_CRC64
43 MENUITEM "SHA-1", IDM_SHA1
44 MENUITEM "SHA-256", IDM_SHA256
45 MENUITEM "*", IDM_HASH_ALL
46 END
47 MENUITEM "Di&ff", IDM_DIFF
48 MENUITEM SEPARATOR
49 MENUITEM "Create Folder\tF7", IDM_CREATE_FOLDER
50 MENUITEM "Create File\tCtrl+N", IDM_CREATE_FILE
51 MENUITEM SEPARATOR
52 MENUITEM "&Link...", IDM_LINK
53 MENUITEM "&Alternate streams", IDM_ALT_STREAMS
54 MENUITEM SEPARATOR
55 MENUITEM "E&xit\tAlt+F4", IDCLOSE
56 END
57 POPUP "&Edit"
58 BEGIN
59 // MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT, GRAYED
60 // MENUITEM "&Copy\tCtrl+C", IDM_EDIT_COPY, GRAYED
61 // MENUITEM "&Paste\tCtrl+V", IDM_EDIT_PASTE, GRAYED
62 // MENUITEM SEPARATOR
63 MENUITEM "Select &All\tShift+[Grey +]", IDM_SELECT_ALL
64 MENUITEM "Deselect All\tShift+[Grey -]", IDM_DESELECT_ALL
65 MENUITEM "&Invert Selection\tGrey *", IDM_INVERT_SELECTION
66 MENUITEM "Select...\tGrey +", IDM_SELECT
67 MENUITEM "Deselect...\tGrey -", IDM_DESELECT
68 MENUITEM "Select by Type\tAlt+[Grey+]", IDM_SELECT_BY_TYPE
69 MENUITEM "Deselect by Type\tAlt+[Grey -]", IDM_DESELECT_BY_TYPE
70 END
71 POPUP "&View"
72 BEGIN
73 MENUITEM "Lar&ge Icons\tCtrl+1", IDM_VIEW_LARGE_ICONS
74 MENUITEM "S&mall Icons\tCtrl+2", IDM_VIEW_SMALL_ICONS
75 MENUITEM "&List\tCtrl+3", IDM_VIEW_LIST
76 MENUITEM "&Details\tCtrl+4", IDM_VIEW_DETAILS, CHECKED
77 MENUITEM SEPARATOR
78 MENUITEM "Name\tCtrl+F3", IDM_VIEW_ARANGE_BY_NAME
79 MENUITEM "Type\tCtrl+F4", IDM_VIEW_ARANGE_BY_TYPE
80 MENUITEM "Date\tCtrl+F5", IDM_VIEW_ARANGE_BY_DATE
81 MENUITEM "Size\tCtrl+F6", IDM_VIEW_ARANGE_BY_SIZE
82 MENUITEM "Unsorted\tCtrl+F7", IDM_VIEW_ARANGE_NO_SORT
83 MENUITEM SEPARATOR
84 MENUITEM "Flat View", IDM_VIEW_FLAT_VIEW
85 MENUITEM "&2 Panels\tF9", IDM_VIEW_TWO_PANELS
86
87 POPUP "2017"
88 BEGIN
89 MENUITEM "Time", IDM_VIEW_TIME
90 END
91
92 POPUP "Toolbars"
93 BEGIN
94 MENUITEM "Archive Toolbar", IDM_VIEW_ARCHIVE_TOOLBAR
95 MENUITEM "Standard Toolbar", IDM_VIEW_STANDARD_TOOLBAR
96 MENUITEM SEPARATOR
97 MENUITEM "Large Buttons", IDM_VIEW_TOOLBARS_LARGE_BUTTONS
98 MENUITEM "Show Buttons Text", IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT
99 END
100 MENUITEM "Open Root Folder\t\\", IDM_OPEN_ROOT_FOLDER
101 MENUITEM "Up One Level\tBackspace", IDM_OPEN_PARENT_FOLDER
102 MENUITEM "Folders History...\tAlt+F12", IDM_FOLDERS_HISTORY
103 MENUITEM "&Refresh\tCtrl+R", IDM_VIEW_REFRESH
104 MENUITEM "Auto Refresh", IDM_VIEW_AUTO_REFRESH
105
106 // MENUITEM "Show NTFS streams", IDM_VIEW_SHOW_STREAMS
107 // MENUITEM "Show deleted files", IDM_VIEW_SHOW_DELETED
108
109 END
110 POPUP "F&avorites"
111 BEGIN
112 POPUP "&Add folder to Favorites as"
113 BEGIN
114 MENUITEM SEPARATOR
115 END
116 MENUITEM SEPARATOR
117 END
118 POPUP "&Tools"
119 BEGIN
120 MENUITEM "&Options...", IDM_OPTIONS
121 MENUITEM SEPARATOR
122 MENUITEM "&Benchmark", IDM_BENCHMARK
123 #ifdef UNDER_CE
124 MENUITEM "Benchmark 2", IDM_BENCHMARK2
125 #endif
126 #ifndef UNDER_CE
127 END
128 POPUP "&Help"
129 BEGIN
130 MENUITEM "&Contents...\tF1", IDM_HELP_CONTENTS
131 #endif
132 MENUITEM SEPARATOR
133 MENUITEM "&About 7-Zip...", IDM_ABOUT
134 END
135END
136
137
138IDI_ICON ICON "../../UI/FileManager/FM.ico"
139
140#ifndef UNDER_CE
1411 24 MOVEABLE PURE "../../UI/FileManager/7zFM.exe.manifest"
142#endif
143
144IDB_ADD BITMAP "../../UI/FileManager/Add.bmp"
145IDB_EXTRACT BITMAP "../../UI/FileManager/Extract.bmp"
146IDB_TEST BITMAP "../../UI/FileManager/Test.bmp"
147IDB_COPY BITMAP "../../UI/FileManager/Copy.bmp"
148IDB_MOVE BITMAP "../../UI/FileManager/Move.bmp"
149IDB_DELETE BITMAP "../../UI/FileManager/Delete.bmp"
150IDB_INFO BITMAP "../../UI/FileManager/Info.bmp"
151IDB_ADD2 BITMAP "../../UI/FileManager/Add2.bmp"
152IDB_EXTRACT2 BITMAP "../../UI/FileManager/Extract2.bmp"
153IDB_TEST2 BITMAP "../../UI/FileManager/Test2.bmp"
154IDB_COPY2 BITMAP "../../UI/FileManager/Copy2.bmp"
155IDB_MOVE2 BITMAP "../../UI/FileManager/Move2.bmp"
156IDB_DELETE2 BITMAP "../../UI/FileManager/Delete2.bmp"
157IDB_INFO2 BITMAP "../../UI/FileManager/Info2.bmp"
158
159
160STRINGTABLE
161BEGIN
162 IDS_BOOKMARK "Bookmark"
163
164 IDS_OPTIONS "Options"
165
166 IDS_N_SELECTED_ITEMS "{0} object(s) selected"
167
168 IDS_FILE_EXIST "File {0} is already exist"
169 IDS_WANT_UPDATE_MODIFIED_FILE "File '{0}' was modified.\nDo you want to update it in the archive?"
170 IDS_CANNOT_UPDATE_FILE "Cannot update file\n'{0}'"
171 IDS_CANNOT_START_EDITOR "Cannot start editor."
172 IDS_VIRUS "The file looks like a virus (the file name contains long spaces in name)."
173 IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER "The operation cannot be called from a folder that has a long path."
174 IDS_SELECT_ONE_FILE "You must select one file"
175 IDS_SELECT_FILES "You must select one or more files"
176 IDS_TOO_MANY_ITEMS "Too many items"
177
178 IDS_COPY "Copy"
179 IDS_MOVE "Move"
180 IDS_COPY_TO "Copy to:"
181 IDS_MOVE_TO "Move to:"
182 IDS_COPYING "Copying..."
183 IDS_MOVING "Moving..."
184 IDS_RENAMING "Renaming..."
185
186 IDS_OPERATION_IS_NOT_SUPPORTED "Operation is not supported."
187 IDS_ERROR_RENAMING "Error Renaming File or Folder"
188 IDS_CONFIRM_FILE_COPY "Confirm File Copy"
189 IDS_WANT_TO_COPY_FILES "Are you sure you want to copy files to archive"
190
191 IDS_CONFIRM_FILE_DELETE "Confirm File Delete"
192 IDS_CONFIRM_FOLDER_DELETE "Confirm Folder Delete"
193 IDS_CONFIRM_ITEMS_DELETE "Confirm Multiple File Delete"
194 IDS_WANT_TO_DELETE_FILE "Are you sure you want to delete '{0}'?"
195 IDS_WANT_TO_DELETE_FOLDER "Are you sure you want to delete the folder '{0}' and all its contents?"
196 IDS_WANT_TO_DELETE_ITEMS "Are you sure you want to delete these {0} items?"
197 IDS_DELETING "Deleting..."
198 IDS_ERROR_DELETING "Error Deleting File or Folder"
199 IDS_ERROR_LONG_PATH_TO_RECYCLE "The system cannot move a file with long path to the Recycle Bin"
200
201 IDS_CREATE_FOLDER "Create Folder"
202 IDS_CREATE_FILE "Create File"
203 IDS_CREATE_FOLDER_NAME "Folder name:"
204 IDS_CREATE_FILE_NAME "File Name:"
205 IDS_CREATE_FOLDER_DEFAULT_NAME "New Folder"
206 IDS_CREATE_FILE_DEFAULT_NAME "New File"
207 IDS_CREATE_FOLDER_ERROR "Error Creating Folder"
208 IDS_CREATE_FILE_ERROR "Error Creating File"
209
210 IDS_COMMENT "Comment"
211 IDS_COMMENT2 "&Comment:"
212 IDS_SELECT "Select"
213 IDS_DESELECT "Deselect"
214 IDS_SELECT_MASK "Mask:"
215
216 IDS_PROPERTIES "Properties"
217 IDS_FOLDERS_HISTORY "Folders History"
218
219 IDS_COMPUTER "Computer"
220 IDS_NETWORK "Network"
221 IDS_DOCUMENTS "Documents"
222 IDS_SYSTEM "System"
223
224 IDS_ADD "Add"
225 IDS_EXTRACT "Extract"
226 IDS_TEST "Test"
227 IDS_BUTTON_COPY "Copy"
228 IDS_BUTTON_MOVE "Move"
229 IDS_BUTTON_DELETE "Delete"
230 IDS_BUTTON_INFO "Info"
231
232 IDS_SPLITTING "Splitting..."
233 IDS_SPLIT_CONFIRM_TITLE "Confirm Splitting"
234 IDS_SPLIT_CONFIRM_MESSAGE "Are you sure you want to split file into {0} volumes?"
235 IDS_SPLIT_VOL_MUST_BE_SMALLER "Volume size must be smaller than size of original file"
236
237 IDS_COMBINE "Combine Files"
238 IDS_COMBINE_TO "&Combine to:"
239 IDS_COMBINING "Combining..."
240 IDS_COMBINE_SELECT_ONE_FILE "Select only first part of split file"
241 IDS_COMBINE_CANT_DETECT_SPLIT_FILE "Cannot detect file as split file"
242 IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART "Cannot find more than one part of split file"
243
244END
245
246#include "AboutDialog.rc"
247#include "BrowseDialog.rc"
248#include "ComboDialog.rc"
249#include "CopyDialog.rc"
250#include "EditDialog.rc"
251#include "EditPage.rc"
252#include "FoldersPage.rc"
253#include "LangPage.rc"
254#include "LinkDialog.rc"
255#include "ListViewDialog.rc"
256#include "MenuPage.rc"
257#include "MessagesDialog.rc"
258#include "OverwriteDialog.rc"
259#include "PasswordDialog.rc"
260#include "ProgressDialog2.rc"
261#include "PropertyName.rc"
262#include "SettingsPage.rc"
263#include "SplitDialog.rc"
264#include "SystemPage.rc"
265#include "../GUI/Extract.rc"
266#include "../GUI/resource3.rc"
267#include "../Explorer/resource2.rc"
268#include "resourceGui.rc"
diff --git a/CPP/7zip/UI/FileManager/resourceGui.h b/CPP/7zip/UI/FileManager/resourceGui.h
new file mode 100644
index 0000000..7c1b40e
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/resourceGui.h
@@ -0,0 +1,15 @@
1#define IDI_ICON 1
2
3#define IDS_MESSAGE_NO_ERRORS 3001
4
5#define IDS_PROGRESS_TESTING 3302
6#define IDS_OPENNING 3303
7#define IDS_SCANNING 3304
8
9#define IDS_CHECKSUM_CALCULATING 7500
10#define IDS_CHECKSUM_INFORMATION 7501
11#define IDS_CHECKSUM_CRC_DATA 7502
12#define IDS_CHECKSUM_CRC_DATA_NAMES 7503
13#define IDS_CHECKSUM_CRC_STREAMS_NAMES 7504
14
15#define IDS_INCORRECT_VOLUME_SIZE 7307
diff --git a/CPP/7zip/UI/FileManager/resourceGui.rc b/CPP/7zip/UI/FileManager/resourceGui.rc
new file mode 100644
index 0000000..f748e0b
--- /dev/null
+++ b/CPP/7zip/UI/FileManager/resourceGui.rc
@@ -0,0 +1,19 @@
1#include "resourceGui.h"
2
3STRINGTABLE
4BEGIN
5 IDS_MESSAGE_NO_ERRORS "There are no errors"
6
7 IDS_PROGRESS_TESTING "Testing"
8
9 IDS_CHECKSUM_CALCULATING "Checksum calculating..."
10 IDS_CHECKSUM_INFORMATION "Checksum information"
11 IDS_CHECKSUM_CRC_DATA "CRC checksum for data:"
12 IDS_CHECKSUM_CRC_DATA_NAMES "CRC checksum for data and names:"
13 IDS_CHECKSUM_CRC_STREAMS_NAMES "CRC checksum for streams and names:"
14
15 IDS_INCORRECT_VOLUME_SIZE "Incorrect volume size"
16
17 IDS_OPENNING "Opening..."
18 IDS_SCANNING "Scanning..."
19END