7
#include "Common/StringConvert.h"
8
#include "Windows/FileDir.h"
9
#include "Windows/Error.h"
10
#include "Windows/COM.h"
11
#include "Windows/Thread.h"
16
#include "CopyDialog.h"
18
#include "ExtractCallback.h"
19
#include "ViewSettings.h"
20
#include "RegistryUtils.h"
21
#include "LangUtils.h"
23
using namespace NWindows;
24
using namespace NFile;
25
using namespace NFind;
27
extern DWORD g_ComCtl32Version;
28
extern HINSTANCE g_hInstance;
30
static LPCWSTR kTempDirPrefix = L"7zE";
32
void CPanelCallbackImp::OnTab()
34
if (g_App.NumPanels != 1)
35
_app->Panels[1 - _index].SetFocusToList();
39
void CPanelCallbackImp::SetFocusToPath(int index)
41
int newPanelIndex = index;
42
if (g_App.NumPanels == 1)
43
newPanelIndex = g_App.LastFocusedPanel;
44
_app->Panels[newPanelIndex]._headerComboBox.SetFocus();
49
void CPanelCallbackImp::OnCopy(bool move, bool copyToSame) { _app->OnCopy(move, copyToSame, _index); }
50
void CPanelCallbackImp::OnSetSameFolder() { _app->OnSetSameFolder(_index); }
51
void CPanelCallbackImp::OnSetSubFolder() { _app->OnSetSubFolder(_index); }
52
void CPanelCallbackImp::PanelWasFocused() { _app->SetFocusedPanel(_index); _app->RefreshTitle(_index); }
53
void CPanelCallbackImp::DragBegin() { _app->DragBegin(_index); }
54
void CPanelCallbackImp::DragEnd() { _app->DragEnd(); }
55
void CPanelCallbackImp::RefreshTitle(bool always) { _app->RefreshTitle(_index, always); }
57
void CApp::SetListSettings()
59
bool showDots = ReadShowDots();
60
bool showRealFileIcons = ReadShowRealFileIcons();
62
DWORD extendedStyle = LVS_EX_HEADERDRAGDROP;
64
extendedStyle |= LVS_EX_FULLROWSELECT;
66
extendedStyle |= LVS_EX_GRIDLINES;
67
bool mySelectionMode = ReadAlternativeSelection();
70
if (ReadSingleClick())
72
extendedStyle |= LVS_EX_ONECLICKACTIVATE
75
extendedStyle |= LVS_EX_UNDERLINEHOT;
79
for (int i = 0; i < kNumPanelsMax; i++)
81
CPanel &panel = Panels[i];
82
panel._mySelectMode = mySelectionMode;
83
panel._showDots = showDots;
84
panel._showRealFileIcons = showRealFileIcons;
85
panel._exStyle = extendedStyle;
87
DWORD style = (DWORD)panel._listView.GetStyle();
89
style |= LVS_SINGLESEL;
91
style &= ~LVS_SINGLESEL;
92
panel._listView.SetStyle(style);
93
panel.SetExtendedStyle();
97
void CApp::SetShowSystemMenu()
99
ShowSystemMenu = ReadShowSystemMenu();
102
void CApp::CreateOnePanel(int panelIndex, const UString &mainPath, bool &archiveIsOpened, bool &encrypted)
104
if (PanelsCreated[panelIndex])
106
m_PanelCallbackImp[panelIndex].Init(this, panelIndex);
108
if (mainPath.IsEmpty())
110
if (!::ReadPanelPath(panelIndex, path))
115
int id = 1000 + 100 * panelIndex;
116
Panels[panelIndex].Create(_window, _window,
117
id, path, &m_PanelCallbackImp[panelIndex], &AppState, archiveIsOpened, encrypted);
118
PanelsCreated[panelIndex] = true;
121
static void CreateToolbar(
123
NWindows::NControl::CImageList &imageList,
124
NWindows::NControl::CToolBar &toolBar,
127
toolBar.Attach(::CreateWindowEx(0,
137
// | TBSTYLE_AUTOSIZE
139
,0,0,0,0, parent, NULL, g_hInstance, NULL));
141
// TB_BUTTONSTRUCTSIZE message, which is required for
142
// backward compatibility.
143
toolBar.ButtonStructSize();
146
LargeButtons ? 48: 24,
147
LargeButtons ? 36: 24,
149
toolBar.SetImageList(0, imageList);
159
UString GetText()const { return LangString(StringResID, LangID); };
162
static CButtonInfo g_StandardButtons[] =
164
{ IDM_COPY_TO, IDB_COPY, IDB_COPY2, IDS_BUTTON_COPY, 0x03020420},
165
{ IDM_MOVE_TO, IDB_MOVE, IDB_MOVE2, IDS_BUTTON_MOVE, 0x03020421},
166
{ IDM_DELETE, IDB_DELETE, IDB_DELETE2, IDS_BUTTON_DELETE, 0x03020422} ,
167
{ IDM_FILE_PROPERTIES, IDB_INFO, IDB_INFO2, IDS_BUTTON_INFO, 0x03020423}
170
static CButtonInfo g_ArchiveButtons[] =
172
{ kAddCommand, IDB_ADD, IDB_ADD2, IDS_ADD, 0x03020400},
173
{ kExtractCommand, IDB_EXTRACT, IDB_EXTRACT2, IDS_EXTRACT, 0x03020401},
174
{ kTestCommand , IDB_TEST, IDB_TEST2, IDS_TEST, 0x03020402}
177
bool SetButtonText(UINT32 commandID, CButtonInfo *buttons, int numButtons, UString &s)
179
for (int i = 0; i < numButtons; i++)
181
const CButtonInfo &b = buttons[i];
182
if (b.commandID == commandID)
191
void SetButtonText(UINT32 commandID, UString &s)
193
if (SetButtonText(commandID, g_StandardButtons,
194
sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]), s))
196
SetButtonText(commandID, g_ArchiveButtons,
197
sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]), s);
200
static void AddButton(
201
NControl::CImageList &imageList,
202
NControl::CToolBar &toolBar,
203
CButtonInfo &butInfo,
209
but.idCommand = butInfo.commandID;
210
but.fsState = TBSTATE_ENABLED;
211
but.fsStyle = BTNS_BUTTON
216
UString s = butInfo.GetText();
219
but.iString = (INT_PTR)(LPCWSTR)s;
221
but.iBitmap = imageList.GetImageCount();
222
HBITMAP b = ::LoadBitmap(g_hInstance,
224
MAKEINTRESOURCE(butInfo.BitmapResID):
225
MAKEINTRESOURCE(butInfo.Bitmap2ResID));
228
imageList.AddMasked(b, RGB(255, 0, 255));
232
toolBar.AddButton(1, &but);
234
toolBar.AddButtonW(1, &but);
238
static void AddBand(NControl::CReBar &reBar, NControl::CToolBar &toolBar)
241
toolBar.GetMaxSize(&size);
244
toolBar.GetWindowRect(&rect);
246
REBARBANDINFO rbBand;
247
rbBand.cbSize = sizeof(REBARBANDINFO); // Required
248
rbBand.fMask = RBBIM_STYLE
249
| RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE;
250
rbBand.fStyle = RBBS_CHILDEDGE; // RBBS_NOGRIPPER;
251
rbBand.cxMinChild = size.cx; // rect.right - rect.left;
252
rbBand.cyMinChild = size.cy; // rect.bottom - rect.top;
253
rbBand.cyChild = rbBand.cyMinChild;
254
rbBand.cx = rbBand.cxMinChild;
255
rbBand.cxIdeal = rbBand.cxMinChild;
256
rbBand.hwndChild = toolBar;
257
reBar.InsertBand(-1, &rbBand);
260
void CApp::ReloadToolbars()
264
HWND parent = _rebar;
266
while(_rebar.GetBandCount() > 0)
267
_rebar.DeleteBand(0);
269
_archiveToolBar.Destroy();
270
_archiveButtonsImageList.Destroy();
272
_standardButtonsImageList.Destroy();
273
_standardToolBar.Destroy();
275
if (ShowArchiveToolbar)
277
CreateToolbar(parent, _archiveButtonsImageList, _archiveToolBar, LargeButtons);
278
for (int i = 0; i < sizeof(g_ArchiveButtons) / sizeof(g_ArchiveButtons[0]); i++)
279
AddButton(_archiveButtonsImageList, _archiveToolBar, g_ArchiveButtons[i],
280
ShowButtonsLables, LargeButtons);
281
AddBand(_rebar, _archiveToolBar);
284
if (ShowStandardToolbar)
286
CreateToolbar(parent, _standardButtonsImageList, _standardToolBar, LargeButtons);
287
for (int i = 0; i < sizeof(g_StandardButtons) / sizeof(g_StandardButtons[0]); i++)
288
AddButton(_standardButtonsImageList, _standardToolBar, g_StandardButtons[i],
289
ShowButtonsLables, LargeButtons);
290
AddBand(_rebar, _standardToolBar);
294
void CApp::ReloadRebar(HWND hwnd)
297
if (!ShowArchiveToolbar && !ShowStandardToolbar)
299
if (g_ComCtl32Version >= MAKELONG(71, 4))
301
INITCOMMONCONTROLSEX icex;
302
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
303
icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
304
InitCommonControlsEx(&icex);
306
_rebar.Attach(::CreateWindowEx(WS_EX_TOOLWINDOW,
315
// | CCS_NOPARENTALIGN // it's bead for moveing of two bands
320
,0,0,0,0, hwnd, NULL, g_hInstance, NULL));
325
rbi.cbSize = sizeof(REBARINFO); // Required when using this struct.
327
rbi.himl = (HIMAGELIST)NULL;
328
_rebar.SetBarInfo(&rbi);
332
void CApp::Create(HWND hwnd, const UString &mainPath, int xSizes[2], bool &archiveIsOpened, bool &encrypted)
338
for (i = 0; i < kNumPanelsMax; i++)
339
PanelsCreated[i] = false;
341
_window.Attach(hwnd);
345
if (LastFocusedPanel >= kNumPanelsMax)
346
LastFocusedPanel = 0;
349
ReadListMode(listMode);
350
for (i = 0; i < kNumPanelsMax; i++)
352
Panels[i]._ListViewMode = listMode.Panels[i];
353
Panels[i]._xSize = xSizes[i];
355
for (i = 0; i < kNumPanelsMax; i++)
356
if (NumPanels > 1 || i == LastFocusedPanel)
359
Panels[i]._xSize = xSizes[0] + xSizes[1];
360
bool archiveIsOpened2 = false;
361
bool encrypted2 = false;
362
bool mainPanel = (i == LastFocusedPanel);
363
CreateOnePanel(i, mainPanel ? mainPath : L"", archiveIsOpened2, encrypted2);
366
archiveIsOpened = archiveIsOpened2;
367
encrypted = encrypted2;
370
SetFocusedPanel(LastFocusedPanel);
371
Panels[LastFocusedPanel].SetFocusToList();
374
extern void MoveSubWindows(HWND hWnd);
376
void CApp::SwitchOnOffOnePanel()
381
bool archiveIsOpened, encrypted;
382
CreateOnePanel(1 - LastFocusedPanel, UString(), archiveIsOpened, encrypted);
383
Panels[1 - LastFocusedPanel].Enable(true);
384
Panels[1 - LastFocusedPanel].Show(SW_SHOWNORMAL);
389
Panels[1 - LastFocusedPanel].Enable(false);
390
Panels[1 - LastFocusedPanel].Show(SW_HIDE);
392
MoveSubWindows(_window);
399
for (int i = 0; i < kNumPanelsMax; i++)
401
const CPanel &panel = Panels[i];
403
if (panel._parentFolders.IsEmpty())
404
path = panel._currentFolderPrefix;
406
path = GetFolderPath(panel._parentFolders[0].ParentFolder);
407
SavePanelPath(i, path);
408
listMode.Panels[i] = panel.GetListViewMode();
410
SaveListMode(listMode);
415
// It's for unloading COM dll's: don't change it.
416
for (int i = 0; i < kNumPanelsMax; i++)
420
static bool IsThereFolderOfPath(const UString &path)
423
if (!FindFile(path, fileInfo))
425
return fileInfo.IsDirectory();
428
// reduces path to part that exists on disk
429
static void ReducePathToRealFileSystemPath(UString &path)
431
while(!path.IsEmpty())
433
if (IsThereFolderOfPath(path))
435
NName::NormalizeDirPathPrefix(path);
438
int pos = path.ReverseFind('\\');
443
path = path.Left(pos + 1);
444
if (path.Length() == 3 && path[1] == L':')
446
path = path.Left(pos);
451
// return true for dir\, if dir exist
452
static bool CheckFolderPath(const UString &path)
454
UString pathReduced = path;
455
ReducePathToRealFileSystemPath(pathReduced);
456
return (pathReduced == path);
459
static bool IsPathAbsolute(const UString &path)
461
if ((path.Length() >= 1 && path[0] == L'\\') ||
462
(path.Length() >= 3 && path[1] == L':' && path[2] == L'\\'))
467
void CApp::OnCopy(bool move, bool copyToSame, int srcPanelIndex)
469
int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
470
CPanel &srcPanel = Panels[srcPanelIndex];
471
CPanel &destPanel = Panels[destPanelIndex];
473
CPanel::CDisableTimerProcessing disableTimerProcessing1(destPanel);
474
CPanel::CDisableTimerProcessing disableTimerProcessing2(srcPanel);
476
if (!srcPanel.DoesItSupportOperations())
478
srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
482
CRecordVector<UInt32> indices;
484
bool useDestPanel = false;
489
int focusedItem = srcPanel._listView.GetFocusedItem();
492
int realIndex = srcPanel.GetRealItemIndex(focusedItem);
493
if (realIndex == kParentIndex)
495
indices.Add(realIndex);
496
destPath = srcPanel.GetItemName(realIndex);
500
srcPanel.GetOperatedItemIndices(indices);
501
if (indices.Size() == 0)
503
destPath = destPanel._currentFolderPrefix;
505
ReducePathToRealFileSystemPath(destPath);
508
CCopyDialog copyDialog;
509
UStringVector copyFolders;
510
ReadCopyHistory(copyFolders);
512
copyDialog.Strings = copyFolders;
513
copyDialog.Value = destPath;
515
copyDialog.Title = move ?
516
LangString(IDS_MOVE, 0x03020202):
517
LangString(IDS_COPY, 0x03020201);
518
copyDialog.Static = move ?
519
LangString(IDS_MOVE_TO, 0x03020204):
520
LangString(IDS_COPY_TO, 0x03020203);
522
if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL)
525
destPath = copyDialog.Value;
527
if (!IsPathAbsolute(destPath))
529
if (!srcPanel.IsFSFolder())
531
srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
534
destPath = srcPanel._currentFolderPrefix + destPath;
537
if (indices.Size() > 1 || (destPath.Length() > 0 && destPath.ReverseFind('\\') == destPath.Length() - 1) ||
538
IsThereFolderOfPath(destPath))
540
NDirectory::CreateComplexDirectory(destPath);
541
NName::NormalizeDirPathPrefix(destPath);
542
if (!CheckFolderPath(destPath))
544
if (NumPanels < 2 || destPath != destPanel._currentFolderPrefix || !destPanel.DoesItSupportOperations())
546
srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
554
int pos = destPath.ReverseFind('\\');
557
UString prefix = destPath.Left(pos + 1);
558
NDirectory::CreateComplexDirectory(prefix);
559
if (!CheckFolderPath(prefix))
561
srcPanel.MessageBox(LangString(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208));
567
AddUniqueStringToHeadOfList(copyFolders, destPath);
568
while (copyFolders.Size() > 20)
569
copyFolders.DeleteBack();
570
SaveCopyHistory(copyFolders);
573
bool useSrcPanel = (!useDestPanel || !srcPanel.IsFSFolder() || destPanel.IsFSFolder());
574
bool useTemp = useSrcPanel && useDestPanel;
575
NFile::NDirectory::CTempDirectoryW tempDirectory;
576
UString tempDirPrefix;
579
tempDirectory.Create(kTempDirPrefix);
580
tempDirPrefix = tempDirectory.GetPath();
581
NFile::NName::NormalizeDirPathPrefix(tempDirPrefix);
584
CSelectedState srcSelState;
585
CSelectedState destSelState;
586
srcPanel.SaveSelectedState(srcSelState);
587
destPanel.SaveSelectedState(destSelState);
592
UString folder = useTemp ? tempDirPrefix : destPath;
593
result = srcPanel.CopyTo(indices, folder, move, true, 0);
596
disableTimerProcessing1.Restore();
597
disableTimerProcessing2.Restore();
599
srcPanel.SetFocusToList();
600
if (result != E_ABORT)
601
srcPanel.MessageBoxError(result, L"Error");
608
UStringVector filePaths;
609
UString folderPrefix;
611
folderPrefix = tempDirPrefix;
613
folderPrefix = srcPanel._currentFolderPrefix;
614
filePaths.Reserve(indices.Size());
615
for(int i = 0; i < indices.Size(); i++)
616
filePaths.Add(srcPanel.GetItemRelPath(indices[i]));
618
result = destPanel.CopyFrom(folderPrefix, filePaths, true, 0);
622
disableTimerProcessing1.Restore();
623
disableTimerProcessing2.Restore();
625
srcPanel.SetFocusToList();
626
if (result != E_ABORT)
627
srcPanel.MessageBoxError(result, L"Error");
632
RefreshTitleAlways();
633
if (copyToSame || move)
635
srcPanel.RefreshListCtrl(srcSelState);
639
destPanel.RefreshListCtrl(destSelState);
640
srcPanel.KillSelection();
642
disableTimerProcessing1.Restore();
643
disableTimerProcessing2.Restore();
644
srcPanel.SetFocusToList();
647
void CApp::OnSetSameFolder(int srcPanelIndex)
651
const CPanel &srcPanel = Panels[srcPanelIndex];
652
CPanel &destPanel = Panels[1 - srcPanelIndex];
653
destPanel.BindToPathAndRefresh(srcPanel._currentFolderPrefix);
656
void CApp::OnSetSubFolder(int srcPanelIndex)
660
const CPanel &srcPanel = Panels[srcPanelIndex];
661
CPanel &destPanel = Panels[1 - srcPanelIndex];
663
int focusedItem = srcPanel._listView.GetFocusedItem();
666
int realIndex = srcPanel.GetRealItemIndex(focusedItem);
667
if (!srcPanel.IsItemFolder(realIndex))
672
UString string = srcPanel._currentFolderPrefix +
673
srcPanel.GetItemName(realIndex) + L'\\';
674
destPanel.BindToFolder(string);
676
CMyComPtr<IFolderFolder> newFolder;
677
if (realIndex == kParentIndex)
679
if (srcPanel._folder->BindToParentFolder(&newFolder) != S_OK)
684
if (srcPanel._folder->BindToFolder(realIndex, &newFolder) != S_OK)
687
destPanel.CloseOpenFolders();
688
destPanel._folder = newFolder;
689
destPanel.RefreshListCtrl();
693
int CApp::GetFocusedPanelIndex() const
695
return LastFocusedPanel;
696
HWND hwnd = ::GetFocus();
701
for (int i = 0; i < kNumPanelsMax; i++)
703
if (PanelsCreated[i] &&
704
((HWND)Panels[i] == hwnd || Panels[i]._listView == hwnd))
707
hwnd = GetParent(hwnd);
712
static UString g_ToolTipBuffer;
713
static CSysString g_ToolTipBufferSys;
715
void CApp::OnNotify(int /* ctrlID */, LPNMHDR pnmh)
717
if (pnmh->hwndFrom == _rebar)
721
case RBN_HEIGHTCHANGE:
723
MoveSubWindows(g_HWND);
731
if (pnmh->code == TTN_GETDISPINFO)
733
LPNMTTDISPINFO info = (LPNMTTDISPINFO)pnmh;
735
g_ToolTipBuffer.Empty();
736
SetButtonText((UINT32)info->hdr.idFrom, g_ToolTipBuffer);
737
g_ToolTipBufferSys = GetSystemString(g_ToolTipBuffer);
738
info->lpszText = (LPTSTR)(LPCTSTR)g_ToolTipBufferSys;
742
if (pnmh->code == TTN_GETDISPINFOW)
744
LPNMTTDISPINFOW info = (LPNMTTDISPINFOW)pnmh;
746
g_ToolTipBuffer.Empty();
747
SetButtonText((UINT32)info->hdr.idFrom, g_ToolTipBuffer);
748
info->lpszText = (LPWSTR)(LPCWSTR)g_ToolTipBuffer;
755
void CApp::RefreshTitle(bool always)
757
UString path = GetFocusedPanel()._currentFolderPrefix;
759
path += LangString(IDS_APP_TITLE, 0x03000000);
760
if (!always && path == PrevTitle)
763
NWindows::MySetWindowText(_window, path);
766
void CApp::RefreshTitle(int panelIndex, bool always)
768
if (panelIndex != GetFocusedPanelIndex())
770
RefreshTitle(always);