xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/PanelOperations.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // PanelOperations.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/DynamicBuffer.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/StringConvert.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Wildcard.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/COM.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
11*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/PropVariant.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "ComboDialog.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "FSFolder.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "FormatUtils.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "LangUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "Panel.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "UpdateCallback100.h"
20*f6dc9357SAndroid Build Coastguard Worker 
21*f6dc9357SAndroid Build Coastguard Worker #include "resource.h"
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
24*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
25*f6dc9357SAndroid Build Coastguard Worker using namespace NName;
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
28*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
29*f6dc9357SAndroid Build Coastguard Worker #endif
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker enum EFolderOpType
32*f6dc9357SAndroid Build Coastguard Worker {
33*f6dc9357SAndroid Build Coastguard Worker   FOLDER_TYPE_CREATE_FOLDER = 0,
34*f6dc9357SAndroid Build Coastguard Worker   FOLDER_TYPE_DELETE = 1,
35*f6dc9357SAndroid Build Coastguard Worker   FOLDER_TYPE_RENAME = 2
36*f6dc9357SAndroid Build Coastguard Worker };
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker class CThreadFolderOperations: public CProgressThreadVirt
39*f6dc9357SAndroid Build Coastguard Worker {
40*f6dc9357SAndroid Build Coastguard Worker   HRESULT ProcessVirt() Z7_override;
41*f6dc9357SAndroid Build Coastguard Worker public:
42*f6dc9357SAndroid Build Coastguard Worker   EFolderOpType OpType;
43*f6dc9357SAndroid Build Coastguard Worker   UString Name;
44*f6dc9357SAndroid Build Coastguard Worker   UInt32 Index;
45*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> Indices;
46*f6dc9357SAndroid Build Coastguard Worker 
47*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IFolderOperations> FolderOperations;
48*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IProgress> UpdateCallback;
49*f6dc9357SAndroid Build Coastguard Worker   CUpdateCallback100Imp *UpdateCallbackSpec;
50*f6dc9357SAndroid Build Coastguard Worker 
CThreadFolderOperations(EFolderOpType opType)51*f6dc9357SAndroid Build Coastguard Worker   CThreadFolderOperations(EFolderOpType opType): OpType(opType) {}
52*f6dc9357SAndroid Build Coastguard Worker   HRESULT DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError);
53*f6dc9357SAndroid Build Coastguard Worker };
54*f6dc9357SAndroid Build Coastguard Worker 
ProcessVirt()55*f6dc9357SAndroid Build Coastguard Worker HRESULT CThreadFolderOperations::ProcessVirt()
56*f6dc9357SAndroid Build Coastguard Worker {
57*f6dc9357SAndroid Build Coastguard Worker   NCOM::CComInitializer comInitializer;
58*f6dc9357SAndroid Build Coastguard Worker   switch ((int)OpType)
59*f6dc9357SAndroid Build Coastguard Worker   {
60*f6dc9357SAndroid Build Coastguard Worker     case FOLDER_TYPE_CREATE_FOLDER:
61*f6dc9357SAndroid Build Coastguard Worker       return FolderOperations->CreateFolder(Name, UpdateCallback);
62*f6dc9357SAndroid Build Coastguard Worker     case FOLDER_TYPE_DELETE:
63*f6dc9357SAndroid Build Coastguard Worker       return FolderOperations->Delete(Indices.ConstData(), Indices.Size(), UpdateCallback);
64*f6dc9357SAndroid Build Coastguard Worker     case FOLDER_TYPE_RENAME:
65*f6dc9357SAndroid Build Coastguard Worker       return FolderOperations->Rename(Index, Name, UpdateCallback);
66*f6dc9357SAndroid Build Coastguard Worker     default:
67*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
68*f6dc9357SAndroid Build Coastguard Worker   }
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker 
DoOperation(CPanel & panel,const UString & progressTitle,const UString & titleError)72*f6dc9357SAndroid Build Coastguard Worker HRESULT CThreadFolderOperations::DoOperation(CPanel &panel, const UString &progressTitle, const UString &titleError)
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker   UpdateCallbackSpec = new CUpdateCallback100Imp;
75*f6dc9357SAndroid Build Coastguard Worker   UpdateCallback = UpdateCallbackSpec;
76*f6dc9357SAndroid Build Coastguard Worker   UpdateCallbackSpec->ProgressDialog = this;
77*f6dc9357SAndroid Build Coastguard Worker 
78*f6dc9357SAndroid Build Coastguard Worker   WaitMode = true;
79*f6dc9357SAndroid Build Coastguard Worker   Sync.FinalMessage.ErrorMessage.Title = titleError;
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker   UpdateCallbackSpec->Init();
82*f6dc9357SAndroid Build Coastguard Worker 
83*f6dc9357SAndroid Build Coastguard Worker   if (!panel._parentFolders.IsEmpty())
84*f6dc9357SAndroid Build Coastguard Worker   {
85*f6dc9357SAndroid Build Coastguard Worker     const CFolderLink &fl = panel._parentFolders.Back();
86*f6dc9357SAndroid Build Coastguard Worker     UpdateCallbackSpec->PasswordIsDefined = fl.UsePassword;
87*f6dc9357SAndroid Build Coastguard Worker     UpdateCallbackSpec->Password = fl.Password;
88*f6dc9357SAndroid Build Coastguard Worker   }
89*f6dc9357SAndroid Build Coastguard Worker 
90*f6dc9357SAndroid Build Coastguard Worker   MainWindow = panel._mainWindow; // panel.GetParent()
91*f6dc9357SAndroid Build Coastguard Worker   MainTitle = "7-Zip"; // LangString(IDS_APP_TITLE);
92*f6dc9357SAndroid Build Coastguard Worker   MainAddTitle = progressTitle + L' ';
93*f6dc9357SAndroid Build Coastguard Worker 
94*f6dc9357SAndroid Build Coastguard Worker   RINOK(Create(progressTitle, MainWindow))
95*f6dc9357SAndroid Build Coastguard Worker   return Result;
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker 
98*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
99*f6dc9357SAndroid Build Coastguard Worker typedef int (WINAPI * Func_SHFileOperationW)(LPSHFILEOPSTRUCTW lpFileOp);
100*f6dc9357SAndroid Build Coastguard Worker #endif
101*f6dc9357SAndroid Build Coastguard Worker 
102*f6dc9357SAndroid Build Coastguard Worker /*
103*f6dc9357SAndroid Build Coastguard Worker void CPanel::MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID)
104*f6dc9357SAndroid Build Coastguard Worker {
105*f6dc9357SAndroid Build Coastguard Worker   if (errorCode == E_NOINTERFACE)
106*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_UnsupportOperation();
107*f6dc9357SAndroid Build Coastguard Worker   else
108*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_HRESULT_Caption(errorCode, LangString(resourceID));
109*f6dc9357SAndroid Build Coastguard Worker }
110*f6dc9357SAndroid Build Coastguard Worker */
111*f6dc9357SAndroid Build Coastguard Worker 
DeleteItems(bool NON_CE_VAR (toRecycleBin))112*f6dc9357SAndroid Build Coastguard Worker void CPanel::DeleteItems(bool NON_CE_VAR(toRecycleBin))
113*f6dc9357SAndroid Build Coastguard Worker {
114*f6dc9357SAndroid Build Coastguard Worker   CDisableTimerProcessing disableTimerProcessing(*this);
115*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> indices;
116*f6dc9357SAndroid Build Coastguard Worker   Get_ItemIndices_Operated(indices);
117*f6dc9357SAndroid Build Coastguard Worker   if (indices.IsEmpty())
118*f6dc9357SAndroid Build Coastguard Worker     return;
119*f6dc9357SAndroid Build Coastguard Worker   CSelectedState state;
120*f6dc9357SAndroid Build Coastguard Worker   SaveSelectedState(state);
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker   #ifndef UNDER_CE
123*f6dc9357SAndroid Build Coastguard Worker   // WM6 / SHFileOperationW doesn't ask user! So we use internal delete
124*f6dc9357SAndroid Build Coastguard Worker   if (IsFSFolder() && toRecycleBin)
125*f6dc9357SAndroid Build Coastguard Worker   {
126*f6dc9357SAndroid Build Coastguard Worker     bool useInternalDelete = false;
127*f6dc9357SAndroid Build Coastguard Worker     #ifndef _UNICODE
128*f6dc9357SAndroid Build Coastguard Worker     if (!g_IsNT)
129*f6dc9357SAndroid Build Coastguard Worker     {
130*f6dc9357SAndroid Build Coastguard Worker       CDynamicBuffer<CHAR> buffer;
131*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, indices)
132*f6dc9357SAndroid Build Coastguard Worker       {
133*f6dc9357SAndroid Build Coastguard Worker         const AString path (GetSystemString(GetItemFullPath(indices[i])));
134*f6dc9357SAndroid Build Coastguard Worker         buffer.AddData(path, path.Len() + 1);
135*f6dc9357SAndroid Build Coastguard Worker       }
136*f6dc9357SAndroid Build Coastguard Worker       *buffer.GetCurPtrAndGrow(1) = 0;
137*f6dc9357SAndroid Build Coastguard Worker       SHFILEOPSTRUCTA fo;
138*f6dc9357SAndroid Build Coastguard Worker       fo.hwnd = GetParent();
139*f6dc9357SAndroid Build Coastguard Worker       fo.wFunc = FO_DELETE;
140*f6dc9357SAndroid Build Coastguard Worker       fo.pFrom = (const CHAR *)buffer;
141*f6dc9357SAndroid Build Coastguard Worker       fo.pTo = NULL;
142*f6dc9357SAndroid Build Coastguard Worker       fo.fFlags = 0;
143*f6dc9357SAndroid Build Coastguard Worker       if (toRecycleBin)
144*f6dc9357SAndroid Build Coastguard Worker         fo.fFlags |= FOF_ALLOWUNDO;
145*f6dc9357SAndroid Build Coastguard Worker       // fo.fFlags |= FOF_NOCONFIRMATION;
146*f6dc9357SAndroid Build Coastguard Worker       // fo.fFlags |= FOF_NOERRORUI;
147*f6dc9357SAndroid Build Coastguard Worker       // fo.fFlags |= FOF_SILENT;
148*f6dc9357SAndroid Build Coastguard Worker       // fo.fFlags |= FOF_WANTNUKEWARNING;
149*f6dc9357SAndroid Build Coastguard Worker       fo.fAnyOperationsAborted = FALSE;
150*f6dc9357SAndroid Build Coastguard Worker       fo.hNameMappings = NULL;
151*f6dc9357SAndroid Build Coastguard Worker       fo.lpszProgressTitle = NULL;
152*f6dc9357SAndroid Build Coastguard Worker       /* int res = */ ::SHFileOperationA(&fo);
153*f6dc9357SAndroid Build Coastguard Worker     }
154*f6dc9357SAndroid Build Coastguard Worker     else
155*f6dc9357SAndroid Build Coastguard Worker     #endif
156*f6dc9357SAndroid Build Coastguard Worker     {
157*f6dc9357SAndroid Build Coastguard Worker       CDynamicBuffer<WCHAR> buffer;
158*f6dc9357SAndroid Build Coastguard Worker       unsigned maxLen = 0;
159*f6dc9357SAndroid Build Coastguard Worker       const UString prefix = GetFsPath();
160*f6dc9357SAndroid Build Coastguard Worker       FOR_VECTOR (i, indices)
161*f6dc9357SAndroid Build Coastguard Worker       {
162*f6dc9357SAndroid Build Coastguard Worker         // L"\\\\?\\") doesn't work here.
163*f6dc9357SAndroid Build Coastguard Worker         const UString path = prefix + GetItemRelPath2(indices[i]);
164*f6dc9357SAndroid Build Coastguard Worker         if (path.Len() > maxLen)
165*f6dc9357SAndroid Build Coastguard Worker           maxLen = path.Len();
166*f6dc9357SAndroid Build Coastguard Worker         buffer.AddData(path, path.Len() + 1);
167*f6dc9357SAndroid Build Coastguard Worker       }
168*f6dc9357SAndroid Build Coastguard Worker       *buffer.GetCurPtrAndGrow(1) = 0;
169*f6dc9357SAndroid Build Coastguard Worker       if (maxLen >= MAX_PATH)
170*f6dc9357SAndroid Build Coastguard Worker       {
171*f6dc9357SAndroid Build Coastguard Worker         if (toRecycleBin)
172*f6dc9357SAndroid Build Coastguard Worker         {
173*f6dc9357SAndroid Build Coastguard Worker           MessageBox_Error_LangID(IDS_ERROR_LONG_PATH_TO_RECYCLE);
174*f6dc9357SAndroid Build Coastguard Worker           return;
175*f6dc9357SAndroid Build Coastguard Worker         }
176*f6dc9357SAndroid Build Coastguard Worker         useInternalDelete = true;
177*f6dc9357SAndroid Build Coastguard Worker       }
178*f6dc9357SAndroid Build Coastguard Worker       else
179*f6dc9357SAndroid Build Coastguard Worker       {
180*f6dc9357SAndroid Build Coastguard Worker         SHFILEOPSTRUCTW fo;
181*f6dc9357SAndroid Build Coastguard Worker         fo.hwnd = GetParent();
182*f6dc9357SAndroid Build Coastguard Worker         fo.wFunc = FO_DELETE;
183*f6dc9357SAndroid Build Coastguard Worker         fo.pFrom = (const WCHAR *)buffer;
184*f6dc9357SAndroid Build Coastguard Worker         fo.pTo = NULL;
185*f6dc9357SAndroid Build Coastguard Worker         fo.fFlags = 0;
186*f6dc9357SAndroid Build Coastguard Worker         if (toRecycleBin)
187*f6dc9357SAndroid Build Coastguard Worker           fo.fFlags |= FOF_ALLOWUNDO;
188*f6dc9357SAndroid Build Coastguard Worker         fo.fAnyOperationsAborted = FALSE;
189*f6dc9357SAndroid Build Coastguard Worker         fo.hNameMappings = NULL;
190*f6dc9357SAndroid Build Coastguard Worker         fo.lpszProgressTitle = NULL;
191*f6dc9357SAndroid Build Coastguard Worker         // int res;
192*f6dc9357SAndroid Build Coastguard Worker         #ifdef _UNICODE
193*f6dc9357SAndroid Build Coastguard Worker         /* res = */ ::SHFileOperationW(&fo);
194*f6dc9357SAndroid Build Coastguard Worker         #else
195*f6dc9357SAndroid Build Coastguard Worker Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
196*f6dc9357SAndroid Build Coastguard Worker         const
197*f6dc9357SAndroid Build Coastguard Worker         Func_SHFileOperationW
198*f6dc9357SAndroid Build Coastguard Worker            f_SHFileOperationW = Z7_GET_PROC_ADDRESS(
199*f6dc9357SAndroid Build Coastguard Worker         Func_SHFileOperationW, ::GetModuleHandleW(L"shell32.dll"),
200*f6dc9357SAndroid Build Coastguard Worker             "SHFileOperationW");
201*f6dc9357SAndroid Build Coastguard Worker         if (!f_SHFileOperationW)
202*f6dc9357SAndroid Build Coastguard Worker           return;
203*f6dc9357SAndroid Build Coastguard Worker         /* res = */ f_SHFileOperationW(&fo);
204*f6dc9357SAndroid Build Coastguard Worker         #endif
205*f6dc9357SAndroid Build Coastguard Worker       }
206*f6dc9357SAndroid Build Coastguard Worker     }
207*f6dc9357SAndroid Build Coastguard Worker     /*
208*f6dc9357SAndroid Build Coastguard Worker     if (fo.fAnyOperationsAborted)
209*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error_HRESULT_Caption(result, LangString(IDS_ERROR_DELETING));
210*f6dc9357SAndroid Build Coastguard Worker     */
211*f6dc9357SAndroid Build Coastguard Worker     if (!useInternalDelete)
212*f6dc9357SAndroid Build Coastguard Worker     {
213*f6dc9357SAndroid Build Coastguard Worker       RefreshListCtrl(state);
214*f6dc9357SAndroid Build Coastguard Worker       return;
215*f6dc9357SAndroid Build Coastguard Worker     }
216*f6dc9357SAndroid Build Coastguard Worker   }
217*f6dc9357SAndroid Build Coastguard Worker   #endif
218*f6dc9357SAndroid Build Coastguard Worker 
219*f6dc9357SAndroid Build Coastguard Worker   // DeleteItemsInternal
220*f6dc9357SAndroid Build Coastguard Worker 
221*f6dc9357SAndroid Build Coastguard Worker   if (!CheckBeforeUpdate(IDS_ERROR_DELETING))
222*f6dc9357SAndroid Build Coastguard Worker     return;
223*f6dc9357SAndroid Build Coastguard Worker 
224*f6dc9357SAndroid Build Coastguard Worker   UInt32 titleID, messageID;
225*f6dc9357SAndroid Build Coastguard Worker   UString messageParam;
226*f6dc9357SAndroid Build Coastguard Worker   if (indices.Size() == 1)
227*f6dc9357SAndroid Build Coastguard Worker   {
228*f6dc9357SAndroid Build Coastguard Worker     const unsigned index = indices[0];
229*f6dc9357SAndroid Build Coastguard Worker     messageParam = GetItemRelPath2(index);
230*f6dc9357SAndroid Build Coastguard Worker     if (IsItem_Folder(index))
231*f6dc9357SAndroid Build Coastguard Worker     {
232*f6dc9357SAndroid Build Coastguard Worker       titleID = IDS_CONFIRM_FOLDER_DELETE;
233*f6dc9357SAndroid Build Coastguard Worker       messageID = IDS_WANT_TO_DELETE_FOLDER;
234*f6dc9357SAndroid Build Coastguard Worker     }
235*f6dc9357SAndroid Build Coastguard Worker     else
236*f6dc9357SAndroid Build Coastguard Worker     {
237*f6dc9357SAndroid Build Coastguard Worker       titleID = IDS_CONFIRM_FILE_DELETE;
238*f6dc9357SAndroid Build Coastguard Worker       messageID = IDS_WANT_TO_DELETE_FILE;
239*f6dc9357SAndroid Build Coastguard Worker     }
240*f6dc9357SAndroid Build Coastguard Worker   }
241*f6dc9357SAndroid Build Coastguard Worker   else
242*f6dc9357SAndroid Build Coastguard Worker   {
243*f6dc9357SAndroid Build Coastguard Worker     titleID = IDS_CONFIRM_ITEMS_DELETE;
244*f6dc9357SAndroid Build Coastguard Worker     messageID = IDS_WANT_TO_DELETE_ITEMS;
245*f6dc9357SAndroid Build Coastguard Worker     messageParam = NumberToString(indices.Size());
246*f6dc9357SAndroid Build Coastguard Worker   }
247*f6dc9357SAndroid Build Coastguard Worker   if (::MessageBoxW(GetParent(), MyFormatNew(messageID, messageParam), LangString(titleID),
248*f6dc9357SAndroid Build Coastguard Worker       MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES)
249*f6dc9357SAndroid Build Coastguard Worker     return;
250*f6dc9357SAndroid Build Coastguard Worker 
251*f6dc9357SAndroid Build Coastguard Worker   CDisableNotify disableNotify(*this);
252*f6dc9357SAndroid Build Coastguard Worker   {
253*f6dc9357SAndroid Build Coastguard Worker     CThreadFolderOperations op(FOLDER_TYPE_DELETE);
254*f6dc9357SAndroid Build Coastguard Worker     op.FolderOperations = _folderOperations;
255*f6dc9357SAndroid Build Coastguard Worker     op.Indices = indices;
256*f6dc9357SAndroid Build Coastguard Worker     op.DoOperation(*this,
257*f6dc9357SAndroid Build Coastguard Worker         LangString(IDS_DELETING),
258*f6dc9357SAndroid Build Coastguard Worker         LangString(IDS_ERROR_DELETING));
259*f6dc9357SAndroid Build Coastguard Worker   }
260*f6dc9357SAndroid Build Coastguard Worker   RefreshTitleAlways();
261*f6dc9357SAndroid Build Coastguard Worker   RefreshListCtrl(state);
262*f6dc9357SAndroid Build Coastguard Worker }
263*f6dc9357SAndroid Build Coastguard Worker 
OnBeginLabelEdit(LV_DISPINFOW * lpnmh)264*f6dc9357SAndroid Build Coastguard Worker BOOL CPanel::OnBeginLabelEdit(LV_DISPINFOW * lpnmh)
265*f6dc9357SAndroid Build Coastguard Worker {
266*f6dc9357SAndroid Build Coastguard Worker   const unsigned realIndex = GetRealIndex(lpnmh->item);
267*f6dc9357SAndroid Build Coastguard Worker   if (realIndex == kParentIndex)
268*f6dc9357SAndroid Build Coastguard Worker     return TRUE;
269*f6dc9357SAndroid Build Coastguard Worker   if (IsThereReadOnlyFolder())
270*f6dc9357SAndroid Build Coastguard Worker     return TRUE;
271*f6dc9357SAndroid Build Coastguard Worker   return FALSE;
272*f6dc9357SAndroid Build Coastguard Worker }
273*f6dc9357SAndroid Build Coastguard Worker 
IsCorrectFsName(const UString & name)274*f6dc9357SAndroid Build Coastguard Worker static bool IsCorrectFsName(const UString &name)
275*f6dc9357SAndroid Build Coastguard Worker {
276*f6dc9357SAndroid Build Coastguard Worker   const UString lastPart = name.Ptr((unsigned)(name.ReverseFind_PathSepar() + 1));
277*f6dc9357SAndroid Build Coastguard Worker   return
278*f6dc9357SAndroid Build Coastguard Worker       lastPart != L"." &&
279*f6dc9357SAndroid Build Coastguard Worker       lastPart != L"..";
280*f6dc9357SAndroid Build Coastguard Worker }
281*f6dc9357SAndroid Build Coastguard Worker 
282*f6dc9357SAndroid Build Coastguard Worker bool CorrectFsPath(const UString &relBase, const UString &path, UString &result);
283*f6dc9357SAndroid Build Coastguard Worker 
CorrectFsPath(const UString & path2,UString & result)284*f6dc9357SAndroid Build Coastguard Worker bool CPanel::CorrectFsPath(const UString &path2, UString &result)
285*f6dc9357SAndroid Build Coastguard Worker {
286*f6dc9357SAndroid Build Coastguard Worker   return ::CorrectFsPath(GetFsPath(), path2, result);
287*f6dc9357SAndroid Build Coastguard Worker }
288*f6dc9357SAndroid Build Coastguard Worker 
OnEndLabelEdit(LV_DISPINFOW * lpnmh)289*f6dc9357SAndroid Build Coastguard Worker BOOL CPanel::OnEndLabelEdit(LV_DISPINFOW * lpnmh)
290*f6dc9357SAndroid Build Coastguard Worker {
291*f6dc9357SAndroid Build Coastguard Worker   if (lpnmh->item.pszText == NULL)
292*f6dc9357SAndroid Build Coastguard Worker     return FALSE;
293*f6dc9357SAndroid Build Coastguard Worker   CDisableTimerProcessing disableTimerProcessing2(*this);
294*f6dc9357SAndroid Build Coastguard Worker 
295*f6dc9357SAndroid Build Coastguard Worker   if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
296*f6dc9357SAndroid Build Coastguard Worker     return FALSE;
297*f6dc9357SAndroid Build Coastguard Worker 
298*f6dc9357SAndroid Build Coastguard Worker   UString newName = lpnmh->item.pszText;
299*f6dc9357SAndroid Build Coastguard Worker   if (!IsCorrectFsName(newName))
300*f6dc9357SAndroid Build Coastguard Worker   {
301*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_HRESULT(E_INVALIDARG);
302*f6dc9357SAndroid Build Coastguard Worker     return FALSE;
303*f6dc9357SAndroid Build Coastguard Worker   }
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker   if (IsFSFolder())
306*f6dc9357SAndroid Build Coastguard Worker   {
307*f6dc9357SAndroid Build Coastguard Worker     UString correctName;
308*f6dc9357SAndroid Build Coastguard Worker     if (!CorrectFsPath(newName, correctName))
309*f6dc9357SAndroid Build Coastguard Worker     {
310*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error_HRESULT(E_INVALIDARG);
311*f6dc9357SAndroid Build Coastguard Worker       return FALSE;
312*f6dc9357SAndroid Build Coastguard Worker     }
313*f6dc9357SAndroid Build Coastguard Worker     newName = correctName;
314*f6dc9357SAndroid Build Coastguard Worker   }
315*f6dc9357SAndroid Build Coastguard Worker 
316*f6dc9357SAndroid Build Coastguard Worker   SaveSelectedState(_selectedState);
317*f6dc9357SAndroid Build Coastguard Worker 
318*f6dc9357SAndroid Build Coastguard Worker   const unsigned realIndex = GetRealIndex(lpnmh->item);
319*f6dc9357SAndroid Build Coastguard Worker   if (realIndex == kParentIndex)
320*f6dc9357SAndroid Build Coastguard Worker     return FALSE;
321*f6dc9357SAndroid Build Coastguard Worker   const UString prefix = GetItemPrefix(realIndex);
322*f6dc9357SAndroid Build Coastguard Worker   const UString oldName = GetItemName(realIndex);
323*f6dc9357SAndroid Build Coastguard Worker 
324*f6dc9357SAndroid Build Coastguard Worker   CDisableNotify disableNotify(*this);
325*f6dc9357SAndroid Build Coastguard Worker   {
326*f6dc9357SAndroid Build Coastguard Worker     CThreadFolderOperations op(FOLDER_TYPE_RENAME);
327*f6dc9357SAndroid Build Coastguard Worker     op.FolderOperations = _folderOperations;
328*f6dc9357SAndroid Build Coastguard Worker     op.Index = realIndex;
329*f6dc9357SAndroid Build Coastguard Worker     op.Name = newName;
330*f6dc9357SAndroid Build Coastguard Worker     const HRESULT res = op.DoOperation(*this,
331*f6dc9357SAndroid Build Coastguard Worker         LangString(IDS_RENAMING),
332*f6dc9357SAndroid Build Coastguard Worker         LangString(IDS_ERROR_RENAMING));
333*f6dc9357SAndroid Build Coastguard Worker     // fixed in 9.26: we refresh list even after errors
334*f6dc9357SAndroid Build Coastguard Worker     // (it's more safe, since error can be at different stages, so list can be incorrect).
335*f6dc9357SAndroid Build Coastguard Worker     if (res == S_OK)
336*f6dc9357SAndroid Build Coastguard Worker       _selectedState.FocusedName = prefix + newName;
337*f6dc9357SAndroid Build Coastguard Worker     else
338*f6dc9357SAndroid Build Coastguard Worker     {
339*f6dc9357SAndroid Build Coastguard Worker       _selectedState.FocusedName = prefix + oldName;
340*f6dc9357SAndroid Build Coastguard Worker       // return FALSE;
341*f6dc9357SAndroid Build Coastguard Worker     }
342*f6dc9357SAndroid Build Coastguard Worker   }
343*f6dc9357SAndroid Build Coastguard Worker 
344*f6dc9357SAndroid Build Coastguard Worker   // Can't use RefreshListCtrl here.
345*f6dc9357SAndroid Build Coastguard Worker   // RefreshListCtrlSaveFocused();
346*f6dc9357SAndroid Build Coastguard Worker   _selectedState.FocusedName_Defined = true;
347*f6dc9357SAndroid Build Coastguard Worker   _selectedState.SelectFocused = true;
348*f6dc9357SAndroid Build Coastguard Worker 
349*f6dc9357SAndroid Build Coastguard Worker   // We need clear all items to disable GetText before Reload:
350*f6dc9357SAndroid Build Coastguard Worker   // number of items can change.
351*f6dc9357SAndroid Build Coastguard Worker   // DeleteListItems();
352*f6dc9357SAndroid Build Coastguard Worker   // But seems it can still call GetText (maybe for current item)
353*f6dc9357SAndroid Build Coastguard Worker   // so we can't delete items.
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker   _dontShowMode = true;
356*f6dc9357SAndroid Build Coastguard Worker 
357*f6dc9357SAndroid Build Coastguard Worker   PostMsg(kReLoadMessage);
358*f6dc9357SAndroid Build Coastguard Worker   return TRUE;
359*f6dc9357SAndroid Build Coastguard Worker }
360*f6dc9357SAndroid Build Coastguard Worker 
361*f6dc9357SAndroid Build Coastguard Worker bool Dlg_CreateFolder(HWND wnd, UString &destName);
362*f6dc9357SAndroid Build Coastguard Worker 
CreateFolder()363*f6dc9357SAndroid Build Coastguard Worker void CPanel::CreateFolder()
364*f6dc9357SAndroid Build Coastguard Worker {
365*f6dc9357SAndroid Build Coastguard Worker   if (IsHashFolder())
366*f6dc9357SAndroid Build Coastguard Worker     return;
367*f6dc9357SAndroid Build Coastguard Worker 
368*f6dc9357SAndroid Build Coastguard Worker   if (!CheckBeforeUpdate(IDS_CREATE_FOLDER_ERROR))
369*f6dc9357SAndroid Build Coastguard Worker     return;
370*f6dc9357SAndroid Build Coastguard Worker 
371*f6dc9357SAndroid Build Coastguard Worker   CDisableTimerProcessing disableTimerProcessing2(*this);
372*f6dc9357SAndroid Build Coastguard Worker   CSelectedState state;
373*f6dc9357SAndroid Build Coastguard Worker   SaveSelectedState(state);
374*f6dc9357SAndroid Build Coastguard Worker 
375*f6dc9357SAndroid Build Coastguard Worker   UString newName;
376*f6dc9357SAndroid Build Coastguard Worker   if (!Dlg_CreateFolder(GetParent(), newName))
377*f6dc9357SAndroid Build Coastguard Worker     return;
378*f6dc9357SAndroid Build Coastguard Worker 
379*f6dc9357SAndroid Build Coastguard Worker   if (!IsCorrectFsName(newName))
380*f6dc9357SAndroid Build Coastguard Worker   {
381*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_HRESULT(E_INVALIDARG);
382*f6dc9357SAndroid Build Coastguard Worker     return;
383*f6dc9357SAndroid Build Coastguard Worker   }
384*f6dc9357SAndroid Build Coastguard Worker 
385*f6dc9357SAndroid Build Coastguard Worker   if (IsFSFolder())
386*f6dc9357SAndroid Build Coastguard Worker   {
387*f6dc9357SAndroid Build Coastguard Worker     UString correctName;
388*f6dc9357SAndroid Build Coastguard Worker     if (!CorrectFsPath(newName, correctName))
389*f6dc9357SAndroid Build Coastguard Worker     {
390*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error_HRESULT(E_INVALIDARG);
391*f6dc9357SAndroid Build Coastguard Worker       return;
392*f6dc9357SAndroid Build Coastguard Worker     }
393*f6dc9357SAndroid Build Coastguard Worker     newName = correctName;
394*f6dc9357SAndroid Build Coastguard Worker   }
395*f6dc9357SAndroid Build Coastguard Worker 
396*f6dc9357SAndroid Build Coastguard Worker   HRESULT res;
397*f6dc9357SAndroid Build Coastguard Worker   CDisableNotify disableNotify(*this);
398*f6dc9357SAndroid Build Coastguard Worker   {
399*f6dc9357SAndroid Build Coastguard Worker     CThreadFolderOperations op(FOLDER_TYPE_CREATE_FOLDER);
400*f6dc9357SAndroid Build Coastguard Worker     op.FolderOperations = _folderOperations;
401*f6dc9357SAndroid Build Coastguard Worker     op.Name = newName;
402*f6dc9357SAndroid Build Coastguard Worker     res = op.DoOperation(*this,
403*f6dc9357SAndroid Build Coastguard Worker         LangString(IDS_CREATE_FOLDER),
404*f6dc9357SAndroid Build Coastguard Worker         LangString(IDS_CREATE_FOLDER_ERROR));
405*f6dc9357SAndroid Build Coastguard Worker     /*
406*f6dc9357SAndroid Build Coastguard Worker     // fixed for 9.26: we must refresh always
407*f6dc9357SAndroid Build Coastguard Worker     if (res != S_OK)
408*f6dc9357SAndroid Build Coastguard Worker       return;
409*f6dc9357SAndroid Build Coastguard Worker     */
410*f6dc9357SAndroid Build Coastguard Worker   }
411*f6dc9357SAndroid Build Coastguard Worker   if (res == S_OK)
412*f6dc9357SAndroid Build Coastguard Worker   {
413*f6dc9357SAndroid Build Coastguard Worker     int pos = newName.Find(WCHAR_PATH_SEPARATOR);
414*f6dc9357SAndroid Build Coastguard Worker     if (pos >= 0)
415*f6dc9357SAndroid Build Coastguard Worker       newName.DeleteFrom((unsigned)(pos));
416*f6dc9357SAndroid Build Coastguard Worker     if (!_mySelectMode)
417*f6dc9357SAndroid Build Coastguard Worker       state.SelectedNames.Clear();
418*f6dc9357SAndroid Build Coastguard Worker     state.FocusedName = newName;
419*f6dc9357SAndroid Build Coastguard Worker     state.FocusedName_Defined = true;
420*f6dc9357SAndroid Build Coastguard Worker     state.SelectFocused = true;
421*f6dc9357SAndroid Build Coastguard Worker   }
422*f6dc9357SAndroid Build Coastguard Worker   RefreshTitleAlways();
423*f6dc9357SAndroid Build Coastguard Worker   RefreshListCtrl(state);
424*f6dc9357SAndroid Build Coastguard Worker }
425*f6dc9357SAndroid Build Coastguard Worker 
CreateFile()426*f6dc9357SAndroid Build Coastguard Worker void CPanel::CreateFile()
427*f6dc9357SAndroid Build Coastguard Worker {
428*f6dc9357SAndroid Build Coastguard Worker   if (IsHashFolder())
429*f6dc9357SAndroid Build Coastguard Worker     return;
430*f6dc9357SAndroid Build Coastguard Worker 
431*f6dc9357SAndroid Build Coastguard Worker   if (!CheckBeforeUpdate(IDS_CREATE_FILE_ERROR))
432*f6dc9357SAndroid Build Coastguard Worker     return;
433*f6dc9357SAndroid Build Coastguard Worker 
434*f6dc9357SAndroid Build Coastguard Worker   CDisableTimerProcessing disableTimerProcessing2(*this);
435*f6dc9357SAndroid Build Coastguard Worker   CSelectedState state;
436*f6dc9357SAndroid Build Coastguard Worker   SaveSelectedState(state);
437*f6dc9357SAndroid Build Coastguard Worker   CComboDialog dlg;
438*f6dc9357SAndroid Build Coastguard Worker   LangString(IDS_CREATE_FILE, dlg.Title);
439*f6dc9357SAndroid Build Coastguard Worker   LangString(IDS_CREATE_FILE_NAME, dlg.Static);
440*f6dc9357SAndroid Build Coastguard Worker   LangString(IDS_CREATE_FILE_DEFAULT_NAME, dlg.Value);
441*f6dc9357SAndroid Build Coastguard Worker 
442*f6dc9357SAndroid Build Coastguard Worker   if (dlg.Create(GetParent()) != IDOK)
443*f6dc9357SAndroid Build Coastguard Worker     return;
444*f6dc9357SAndroid Build Coastguard Worker 
445*f6dc9357SAndroid Build Coastguard Worker   CDisableNotify disableNotify(*this);
446*f6dc9357SAndroid Build Coastguard Worker 
447*f6dc9357SAndroid Build Coastguard Worker   UString newName = dlg.Value;
448*f6dc9357SAndroid Build Coastguard Worker 
449*f6dc9357SAndroid Build Coastguard Worker   if (IsFSFolder())
450*f6dc9357SAndroid Build Coastguard Worker   {
451*f6dc9357SAndroid Build Coastguard Worker     UString correctName;
452*f6dc9357SAndroid Build Coastguard Worker     if (!CorrectFsPath(newName, correctName))
453*f6dc9357SAndroid Build Coastguard Worker     {
454*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error_HRESULT(E_INVALIDARG);
455*f6dc9357SAndroid Build Coastguard Worker       return;
456*f6dc9357SAndroid Build Coastguard Worker     }
457*f6dc9357SAndroid Build Coastguard Worker     newName = correctName;
458*f6dc9357SAndroid Build Coastguard Worker   }
459*f6dc9357SAndroid Build Coastguard Worker 
460*f6dc9357SAndroid Build Coastguard Worker   const HRESULT result = _folderOperations->CreateFile(newName, NULL);
461*f6dc9357SAndroid Build Coastguard Worker   if (result != S_OK)
462*f6dc9357SAndroid Build Coastguard Worker   {
463*f6dc9357SAndroid Build Coastguard Worker     MessageBox_Error_HRESULT_Caption(result, LangString(IDS_CREATE_FILE_ERROR));
464*f6dc9357SAndroid Build Coastguard Worker     // MessageBoxErrorForUpdate(result, IDS_CREATE_FILE_ERROR);
465*f6dc9357SAndroid Build Coastguard Worker     return;
466*f6dc9357SAndroid Build Coastguard Worker   }
467*f6dc9357SAndroid Build Coastguard Worker   const int pos = newName.Find(WCHAR_PATH_SEPARATOR);
468*f6dc9357SAndroid Build Coastguard Worker   if (pos >= 0)
469*f6dc9357SAndroid Build Coastguard Worker     newName.DeleteFrom((unsigned)pos);
470*f6dc9357SAndroid Build Coastguard Worker   if (!_mySelectMode)
471*f6dc9357SAndroid Build Coastguard Worker     state.SelectedNames.Clear();
472*f6dc9357SAndroid Build Coastguard Worker   state.FocusedName = newName;
473*f6dc9357SAndroid Build Coastguard Worker   state.FocusedName_Defined = true;
474*f6dc9357SAndroid Build Coastguard Worker   state.SelectFocused = true;
475*f6dc9357SAndroid Build Coastguard Worker   RefreshListCtrl(state);
476*f6dc9357SAndroid Build Coastguard Worker }
477*f6dc9357SAndroid Build Coastguard Worker 
RenameFile()478*f6dc9357SAndroid Build Coastguard Worker void CPanel::RenameFile()
479*f6dc9357SAndroid Build Coastguard Worker {
480*f6dc9357SAndroid Build Coastguard Worker   if (!CheckBeforeUpdate(IDS_ERROR_RENAMING))
481*f6dc9357SAndroid Build Coastguard Worker     return;
482*f6dc9357SAndroid Build Coastguard Worker   int index = _listView.GetFocusedItem();
483*f6dc9357SAndroid Build Coastguard Worker   if (index >= 0)
484*f6dc9357SAndroid Build Coastguard Worker     _listView.EditLabel(index);
485*f6dc9357SAndroid Build Coastguard Worker }
486*f6dc9357SAndroid Build Coastguard Worker 
ChangeComment()487*f6dc9357SAndroid Build Coastguard Worker void CPanel::ChangeComment()
488*f6dc9357SAndroid Build Coastguard Worker {
489*f6dc9357SAndroid Build Coastguard Worker   if (IsHashFolder())
490*f6dc9357SAndroid Build Coastguard Worker     return;
491*f6dc9357SAndroid Build Coastguard Worker   if (!CheckBeforeUpdate(IDS_COMMENT))
492*f6dc9357SAndroid Build Coastguard Worker     return;
493*f6dc9357SAndroid Build Coastguard Worker   CDisableTimerProcessing disableTimerProcessing2(*this);
494*f6dc9357SAndroid Build Coastguard Worker   const int index = _listView.GetFocusedItem();
495*f6dc9357SAndroid Build Coastguard Worker   if (index < 0)
496*f6dc9357SAndroid Build Coastguard Worker     return;
497*f6dc9357SAndroid Build Coastguard Worker   const unsigned realIndex = GetRealItemIndex(index);
498*f6dc9357SAndroid Build Coastguard Worker   if (realIndex == kParentIndex)
499*f6dc9357SAndroid Build Coastguard Worker     return;
500*f6dc9357SAndroid Build Coastguard Worker   CSelectedState state;
501*f6dc9357SAndroid Build Coastguard Worker   SaveSelectedState(state);
502*f6dc9357SAndroid Build Coastguard Worker   UString comment;
503*f6dc9357SAndroid Build Coastguard Worker   {
504*f6dc9357SAndroid Build Coastguard Worker     NCOM::CPropVariant propVariant;
505*f6dc9357SAndroid Build Coastguard Worker     if (_folder->GetProperty(realIndex, kpidComment, &propVariant) != S_OK)
506*f6dc9357SAndroid Build Coastguard Worker       return;
507*f6dc9357SAndroid Build Coastguard Worker     if (propVariant.vt == VT_BSTR)
508*f6dc9357SAndroid Build Coastguard Worker       comment = propVariant.bstrVal;
509*f6dc9357SAndroid Build Coastguard Worker     else if (propVariant.vt != VT_EMPTY)
510*f6dc9357SAndroid Build Coastguard Worker       return;
511*f6dc9357SAndroid Build Coastguard Worker   }
512*f6dc9357SAndroid Build Coastguard Worker   const UString name = GetItemRelPath2(realIndex);
513*f6dc9357SAndroid Build Coastguard Worker   CComboDialog dlg;
514*f6dc9357SAndroid Build Coastguard Worker   dlg.Title = name;
515*f6dc9357SAndroid Build Coastguard Worker   dlg.Title += " : ";
516*f6dc9357SAndroid Build Coastguard Worker   AddLangString(dlg.Title, IDS_COMMENT);
517*f6dc9357SAndroid Build Coastguard Worker   dlg.Value = comment;
518*f6dc9357SAndroid Build Coastguard Worker   LangString(IDS_COMMENT2, dlg.Static);
519*f6dc9357SAndroid Build Coastguard Worker   if (dlg.Create(GetParent()) != IDOK)
520*f6dc9357SAndroid Build Coastguard Worker     return;
521*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant propVariant (dlg.Value);
522*f6dc9357SAndroid Build Coastguard Worker 
523*f6dc9357SAndroid Build Coastguard Worker   CDisableNotify disableNotify(*this);
524*f6dc9357SAndroid Build Coastguard Worker   const HRESULT result = _folderOperations->SetProperty(realIndex, kpidComment, &propVariant, NULL);
525*f6dc9357SAndroid Build Coastguard Worker   if (result != S_OK)
526*f6dc9357SAndroid Build Coastguard Worker   {
527*f6dc9357SAndroid Build Coastguard Worker     if (result == E_NOINTERFACE)
528*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error_UnsupportOperation();
529*f6dc9357SAndroid Build Coastguard Worker     else
530*f6dc9357SAndroid Build Coastguard Worker       MessageBox_Error_HRESULT_Caption(result, L"Set Comment Error");
531*f6dc9357SAndroid Build Coastguard Worker   }
532*f6dc9357SAndroid Build Coastguard Worker   RefreshListCtrl(state);
533*f6dc9357SAndroid Build Coastguard Worker }
534