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
27 using namespace NWindows;
28 using namespace NFile;
29 using namespace NFind;
30
ReleaseFolder()31 void 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
SetNewFolder(IFolderFolder * newFolder)46 void 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
SetToRootFolder()60 void CPanel::SetToRootFolder()
61 {
62 ReleaseFolder();
63 _library.Free();
64
65 CRootFolder *rootFolderSpec = new CRootFolder;
66 SetNewFolder(rootFolderSpec);
67 rootFolderSpec->Init();
68 }
69
70
DoesNameContainWildcard_SkipRoot(const UString & path)71 static bool DoesNameContainWildcard_SkipRoot(const UString &path)
72 {
73 return DoesNameContainWildcard(path.Ptr(NName::GetRootPrefixSize(path)));
74 }
75
BindToPath(const UString & fullPath,const UString & arcFormat,COpenResult & openRes)76 HRESULT 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 /* we will Empty() sysPath variable, if we need to BindToFolder()
137 directly with (path) variable */
138 const unsigned prefixSize = NName::GetRootPrefixSize(sysPath);
139 if (prefixSize == 0 || sysPath[prefixSize] == 0)
140 sysPath.Empty();
141
142 #if defined(_WIN32) && !defined(UNDER_CE)
143 if (!sysPath.IsEmpty() && sysPath.Back() == ':' &&
144 (sysPath.Len() != 2 || !NName::IsDrivePath2(sysPath)))
145 {
146 // if base item for alt streams prefix "base:" exists, we will use it
147 UString baseFile = sysPath;
148 baseFile.DeleteBack();
149 if (NFind::DoesFileOrDirExist(us2fs(baseFile)))
150 sysPath.Empty();
151 }
152 #endif
153
154 CFileInfo fileInfo;
155
156 while (!sysPath.IsEmpty())
157 {
158 if (sysPath.Len() <= prefixSize)
159 {
160 path.DeleteFrom(prefixSize);
161 sysPath.Empty();
162 break;
163 }
164
165 fileInfo.ClearBase();
166 if (IsPathSepar(sysPath.Back()))
167 {
168 /* Windows 10 by default doesn't allow look "Local Settings" that is junction to "AppData\Local",
169 but it does allow look "Local Settings\Temp\*"
170 22.02: at first we try to use paths with slashes "path\" */
171 CFileInfo fi;
172 // CFindFile findFile;
173 // FString path2 = us2fs(sysPath);
174 // path2 += '*'; // CHAR_ANY_MASK;
175 // if (findFile.FindFirst(path2, fi))
176 CEnumerator enumerator;
177 enumerator.SetDirPrefix(us2fs(sysPath));
178 bool found = false;
179 if (enumerator.Next(fi, found))
180 {
181 // sysPath.DeleteBack();
182 fileInfo.SetAsDir();
183 fileInfo.Size = 0;
184 fileInfo.Name.Empty();
185 break;
186 }
187 sysPath.DeleteBack();
188 continue;
189 }
190
191 if (fileInfo.Find(us2fs(sysPath)))
192 break;
193 int pos = sysPath.ReverseFind_PathSepar();
194 if (pos < 0)
195 {
196 sysPath.Empty();
197 break;
198 }
199 {
200 if ((unsigned)pos != sysPath.Len() - 1)
201 pos++;
202 sysPath.DeleteFrom((unsigned)pos);
203 }
204 }
205
206 SetToRootFolder();
207
208 CMyComPtr<IFolderFolder> newFolder;
209
210 if (sysPath.IsEmpty())
211 {
212 _folder->BindToFolder(path, &newFolder);
213 }
214 else if (fileInfo.IsDir())
215 {
216 #ifdef _WIN32
217 if (DoesNameContainWildcard_SkipRoot(sysPath))
218 {
219 FString dirPrefix, fileName;
220 NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
221 if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix)))
222 return E_INVALIDARG;
223 sysPath = fs2us(dirPrefix + fileInfo.Name);
224 }
225 #endif
226
227 NName::NormalizeDirPathPrefix(sysPath);
228 _folder->BindToFolder(sysPath, &newFolder);
229 }
230 else
231 {
232 FString dirPrefix, fileName;
233
234 NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
235
236 HRESULT res = S_OK;
237
238 #ifdef _WIN32
239 if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix)))
240 return E_INVALIDARG;
241
242 if (DoesNameContainWildcard(fs2us(fileName)))
243 res = S_FALSE;
244 else
245 #endif
246 {
247 CTempFileInfo tfi;
248 tfi.RelPath = fs2us(fileName);
249 tfi.FolderPath = dirPrefix;
250 tfi.FilePath = us2fs(sysPath);
251 res = OpenAsArc(NULL, tfi, sysPath, arcFormat, openRes);
252 }
253
254 if (res == S_FALSE)
255 _folder->BindToFolder(fs2us(dirPrefix), &newFolder);
256 else
257 {
258 RINOK(res)
259 openRes.ArchiveIsOpened = true;
260 _parentFolders.Back().ParentFolderPath = fs2us(dirPrefix);
261 path.DeleteFrontal(sysPath.Len());
262 if (!path.IsEmpty() && IS_PATH_SEPAR(path[0]))
263 path.Delete(0);
264 }
265 }
266
267 if (newFolder)
268 {
269 SetNewFolder(newFolder);
270 // LoadFullPath();
271 return S_OK;
272 }
273 }
274
275 {
276 // ---------- we open folder remPath in archive and sub archives ----------
277
278 for (unsigned curPos = 0; curPos != path.Len();)
279 {
280 UString s = path.Ptr(curPos);
281 const int slashPos = NName::FindSepar(s);
282 unsigned skipLen = s.Len();
283 if (slashPos >= 0)
284 {
285 s.DeleteFrom((unsigned)slashPos);
286 skipLen = (unsigned)slashPos + 1;
287 }
288
289 CMyComPtr<IFolderFolder> newFolder;
290 _folder->BindToFolder(s, &newFolder);
291 if (newFolder)
292 curPos += skipLen;
293 else if (_folderAltStreams)
294 {
295 const int pos = s.Find(L':');
296 if (pos >= 0)
297 {
298 UString baseName = s;
299 baseName.DeleteFrom((unsigned)pos);
300 if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder)
301 curPos += (unsigned)pos + 1;
302 }
303 }
304
305 if (!newFolder)
306 break;
307
308 SetNewFolder(newFolder);
309 }
310 }
311
312 return S_OK;
313 }
314
BindToPathAndRefresh(const UString & path)315 HRESULT CPanel::BindToPathAndRefresh(const UString &path)
316 {
317 CDisableTimerProcessing disableTimerProcessing(*this);
318 CDisableNotify disableNotify(*this);
319 COpenResult openRes;
320 UString s = path;
321
322 #ifdef _WIN32
323 if (!s.IsEmpty() && s[0] == '\"' && s.Back() == '\"')
324 {
325 s.DeleteBack();
326 s.Delete(0);
327 }
328 #endif
329
330 HRESULT res = BindToPath(s, UString(), openRes);
331 RefreshListCtrl();
332 return res;
333 }
334
SetBookmark(unsigned index)335 void CPanel::SetBookmark(unsigned index)
336 {
337 _appState->FastFolders.SetString(index, _currentFolderPrefix);
338 }
339
OpenBookmark(unsigned index)340 void CPanel::OpenBookmark(unsigned index)
341 {
342 BindToPathAndRefresh(_appState->FastFolders.GetString(index));
343 }
344
GetFolderPath(IFolderFolder * folder)345 UString GetFolderPath(IFolderFolder *folder)
346 {
347 {
348 NCOM::CPropVariant prop;
349 if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)
350 if (prop.vt == VT_BSTR)
351 return (wchar_t *)prop.bstrVal;
352 }
353 return UString();
354 }
355
LoadFullPath()356 void CPanel::LoadFullPath()
357 {
358 _currentFolderPrefix.Empty();
359 FOR_VECTOR (i, _parentFolders)
360 {
361 const CFolderLink &folderLink = _parentFolders[i];
362 _currentFolderPrefix += folderLink.ParentFolderPath;
363 // GetFolderPath(folderLink.ParentFolder);
364 _currentFolderPrefix += folderLink.RelPath;
365 _currentFolderPrefix.Add_PathSepar();
366 }
367 if (_folder)
368 _currentFolderPrefix += GetFolderPath(_folder);
369 }
370
371
372
GetRealIconIndex_for_DirPath(CFSTR path,DWORD attrib)373 static int GetRealIconIndex_for_DirPath(CFSTR path, DWORD attrib)
374 {
375 attrib |= FILE_ATTRIBUTE_DIRECTORY; // optional
376 int index = -1;
377 if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(path, attrib, index))
378 if (index >= 0)
379 return index;
380 return g_Ext_to_Icon_Map.GetIconIndex_DIR(attrib);
381 }
382
383
384 extern UString RootFolder_GetName_Computer(int &iconIndex);
385 extern UString RootFolder_GetName_Network(int &iconIndex);
386 extern UString RootFolder_GetName_Documents(int &iconIndex);
387
388
Find_FileExtension_DotPos_in_path(const wchar_t * path)389 static int Find_FileExtension_DotPos_in_path(const wchar_t *path)
390 {
391 int dotPos = -1;
392 unsigned i;
393 for (i = 0;; i++)
394 {
395 const wchar_t c = path[i];
396 if (c == 0)
397 return dotPos;
398 if (c == '.')
399 dotPos = (int)i;
400 else if (IS_PATH_SEPAR(c) || c == ':')
401 dotPos = -1;
402 }
403 }
404
405
LoadFullPathAndShow()406 void CPanel::LoadFullPathAndShow()
407 {
408 LoadFullPath();
409 _appState->FolderHistory.AddString(_currentFolderPrefix);
410
411 _headerComboBox.SetText(_currentFolderPrefix);
412
413 #ifndef UNDER_CE
414
415 COMBOBOXEXITEM item;
416 item.mask = 0;
417 item.iImage = -1;
418
419 UString path = _currentFolderPrefix;
420 // path = "\\\\.\\PhysicalDrive1\\"; // for debug
421 // path = "\\\\.\\y:\\"; // for debug
422 if (!path.IsEmpty())
423 {
424 const unsigned rootPrefixSize = NName::GetRootPrefixSize(path);
425 if (rootPrefixSize == 0 && path[0] != '\\')
426 {
427 int iconIndex = -1;
428 UString name_Computer = RootFolder_GetName_Computer(iconIndex);
429 name_Computer.Add_PathSepar();
430 if (path == name_Computer
431 || path == L"\\\\?\\")
432 item.iImage = iconIndex;
433 else
434 {
435 UString name = RootFolder_GetName_Network(iconIndex);
436 name.Add_PathSepar();
437 if (path == name)
438 item.iImage = iconIndex;
439 }
440 }
441
442 if (item.iImage < 0)
443 {
444 if (rootPrefixSize == 0 || rootPrefixSize == path.Len())
445 {
446 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
447 CFileInfo info;
448 if (info.Find(us2fs(path)))
449 attrib = info.Attrib;
450 NName::If_IsSuperPath_RemoveSuperPrefix(path);
451 item.iImage = GetRealIconIndex_for_DirPath(us2fs(path), attrib);
452 }
453 else if (rootPrefixSize == NName::kDevicePathPrefixSize
454 && NName::IsDevicePath(us2fs(path.Left(path.Len() - 1))))
455 {
456 if (path.IsPrefixedBy_Ascii_NoCase("\\\\.\\"))
457 path.DeleteFrontal(4);
458 if (path.Len() > 3) // is not "c:\\"
459 {
460 // PhysicalDrive
461 if (path.Back() == '\\')
462 path.DeleteBack();
463 }
464 item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(path), FILE_ATTRIBUTE_ARCHIVE);
465 }
466 else
467 {
468 if (path.Back() == '\\')
469 path.DeleteBack();
470 bool need_Fs_Check = true;
471 bool is_File = false;
472 if (!_parentFolders.IsEmpty())
473 {
474 const CFolderLink &link = _parentFolders.Back();
475 if (link.VirtualPath == path)
476 {
477 is_File = true;
478 if (_parentFolders.Size() != 1)
479 need_Fs_Check = false;
480 }
481 else
482 need_Fs_Check = false;
483 }
484 if (need_Fs_Check)
485 {
486 CFileInfo info;
487 const bool finded = info.Find(us2fs(path));
488 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
489 if (finded)
490 attrib = info.Attrib;
491 item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(path), attrib);
492 }
493 if (item.iImage <= 0 && is_File)
494 {
495 int dotPos = Find_FileExtension_DotPos_in_path(path);
496 if (dotPos < 0)
497 dotPos = (int)path.Len();
498 item.iImage = g_Ext_to_Icon_Map.GetIconIndex(FILE_ATTRIBUTE_ARCHIVE, path.Ptr(dotPos));
499 }
500 }
501 }
502 }
503
504 if (item.iImage < 0)
505 item.iImage = g_Ext_to_Icon_Map.GetIconIndex_DIR();
506 // if (item.iImage < 0) item.iImage = 0;
507 // item.iImage = -1; // for debug
508 if (item.iImage >= 0)
509 {
510 item.iSelectedImage = item.iImage;
511 item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
512 }
513 item.iItem = -1;
514 _headerComboBox.SetItem(&item);
515
516 #endif
517
518 RefreshTitle();
519 }
520
521 #ifndef UNDER_CE
OnNotifyComboBoxEnter(const UString & s)522 LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s)
523 {
524 if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK)
525 {
526 PostMsg(kSetFocusToListView);
527 return TRUE;
528 }
529 return FALSE;
530 }
531
OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info,LRESULT & result)532 bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result)
533 {
534 if (info->iWhy == CBENF_ESCAPE)
535 {
536 _headerComboBox.SetText(_currentFolderPrefix);
537 PostMsg(kSetFocusToListView);
538 result = FALSE;
539 return true;
540 }
541
542 /*
543 if (info->iWhy == CBENF_DROPDOWN)
544 {
545 result = FALSE;
546 return true;
547 }
548 */
549
550 if (info->iWhy == CBENF_RETURN)
551 {
552 // When we use Edit control and press Enter.
553 UString s;
554 _headerComboBox.GetText(s);
555 result = OnNotifyComboBoxEnter(s);
556 return true;
557 }
558 return false;
559 }
560 #endif
561
562 #ifndef _UNICODE
OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info,LRESULT & result)563 bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
564 {
565 if (info->iWhy == CBENF_ESCAPE)
566 {
567 _headerComboBox.SetText(_currentFolderPrefix);
568 PostMsg(kSetFocusToListView);
569 result = FALSE;
570 return true;
571 }
572 /*
573 if (info->iWhy == CBENF_DROPDOWN)
574 {
575 result = FALSE;
576 return true;
577 }
578 */
579
580 if (info->iWhy == CBENF_RETURN)
581 {
582 UString s;
583 _headerComboBox.GetText(s);
584 // GetUnicodeString(info->szText)
585 result = OnNotifyComboBoxEnter(s);
586 return true;
587 }
588 return false;
589 }
590 #endif
591
AddComboBoxItem(const UString & name,int iconIndex,unsigned indent,bool addToList)592 void CPanel::AddComboBoxItem(const UString &name, int iconIndex, unsigned indent, bool addToList)
593 {
594 #ifdef UNDER_CE
595
596 UString s;
597 iconIndex = iconIndex;
598 for (unsigned i = 0; i < indent; i++)
599 s += " ";
600 _headerComboBox.AddString(s + name);
601
602 #else
603
604 COMBOBOXEXITEMW item;
605 item.mask = CBEIF_TEXT | CBEIF_INDENT;
606 if (iconIndex < 0)
607 iconIndex = g_Ext_to_Icon_Map.GetIconIndex_DIR();
608 item.iSelectedImage = item.iImage = iconIndex;
609 if (iconIndex >= 0)
610 item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
611 item.iItem = -1;
612 item.iIndent = (int)indent;
613 item.pszText = name.Ptr_non_const();
614 _headerComboBox.InsertItem(&item);
615
616 #endif
617
618 if (addToList)
619 {
620 UString s = name;
621 s.Add_PathSepar();
622 ComboBoxPaths.Add(s);
623 }
624 }
625
626
OnComboBoxCommand(UINT code,LPARAM,LRESULT & result)627 bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
628 {
629 result = FALSE;
630 switch (code)
631 {
632 case CBN_DROPDOWN:
633 {
634 ComboBoxPaths.Clear();
635 _headerComboBox.ResetContent();
636
637 UString sumPath;
638 UStringVector pathParts;
639 unsigned indent = 0;
640 {
641 UString path = _currentFolderPrefix;
642 // path = L"\\\\.\\y:\\"; // for debug
643 UString prefix0;
644 if (path.IsPrefixedBy_Ascii_NoCase("\\\\"))
645 {
646 const int separ = FindCharPosInString(path.Ptr(2), '\\');
647 if (separ > 0
648 && (separ > 1 || path[2] != '.')) // "\\\\.\\" will be processed later
649 {
650 const UString s = path.Left(2 + separ);
651 prefix0 = s;
652 prefix0.Add_PathSepar();
653 AddComboBoxItem(s,
654 GetRealIconIndex_for_DirPath(us2fs(prefix0), FILE_ATTRIBUTE_DIRECTORY),
655 indent++,
656 false); // addToList
657 ComboBoxPaths.Add(prefix0);
658 }
659 }
660
661 unsigned rootPrefixSize = NName::GetRootPrefixSize(path);
662
663 sumPath = path;
664
665 if (rootPrefixSize <= prefix0.Len())
666 {
667 rootPrefixSize = prefix0.Len();
668 sumPath.DeleteFrom(rootPrefixSize);
669 }
670 else
671 {
672 // rootPrefixSize > prefix0.Len()
673 sumPath.DeleteFrom(rootPrefixSize);
674
675 CFileInfo info;
676 DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
677 if (info.Find(us2fs(sumPath)) && info.IsDir())
678 attrib = info.Attrib;
679 UString s = sumPath.Ptr(prefix0.Len());
680 if (!s.IsEmpty())
681 {
682 const wchar_t c = s.Back();
683 if (IS_PATH_SEPAR(c))
684 s.DeleteBack();
685 }
686 UString path_for_icon = sumPath;
687 NName::If_IsSuperPath_RemoveSuperPrefix(path_for_icon);
688
689 AddComboBoxItem(s,
690 GetRealIconIndex_for_DirPath(us2fs(path_for_icon), attrib),
691 indent++,
692 false); // addToList
693 ComboBoxPaths.Add(sumPath);
694 }
695
696 path.DeleteFrontal(rootPrefixSize);
697 SplitPathToParts(path, pathParts);
698 }
699
700 // it's expected that pathParts.Back() is empty, because _currentFolderPrefix has PathSeparator.
701 unsigned next_Arc_index = 0;
702 int iconIndex_Computer;
703 const UString name_Computer = RootFolder_GetName_Computer(iconIndex_Computer);
704
705 // const bool is_devicePrefix = (sumPath == L"\\\\.\\");
706
707 if (pathParts.Size() > 1)
708 if (!sumPath.IsEmpty()
709 || pathParts.Size() != 2
710 || pathParts[0] != name_Computer)
711 for (unsigned i = 0; i + 1 < pathParts.Size(); i++)
712 {
713 UString name = pathParts[i];
714 sumPath += name;
715
716 bool isRootDir_inLink = false;
717 if (next_Arc_index < _parentFolders.Size())
718 {
719 const CFolderLink &link = _parentFolders[next_Arc_index];
720 if (link.VirtualPath == sumPath)
721 {
722 isRootDir_inLink = true;
723 next_Arc_index++;
724 }
725 }
726
727 int iconIndex = -1;
728 DWORD attrib = isRootDir_inLink ?
729 FILE_ATTRIBUTE_ARCHIVE:
730 FILE_ATTRIBUTE_DIRECTORY;
731 if (next_Arc_index == 0
732 || (next_Arc_index == 1 && isRootDir_inLink))
733 {
734 if (i == 0 && NName::IsDevicePath(us2fs(sumPath)))
735 {
736 UString path = name;
737 path.Add_PathSepar();
738 attrib = FILE_ATTRIBUTE_ARCHIVE;
739 // FILE_ATTRIBUTE_DIRECTORY;
740 }
741 else
742 {
743 CFileInfo info;
744 if (info.Find(us2fs(sumPath)))
745 attrib = info.Attrib;
746 }
747 iconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(us2fs(sumPath), attrib);
748 }
749
750 if (iconIndex < 0)
751 iconIndex = g_Ext_to_Icon_Map.GetIconIndex(attrib, name);
752 // iconIndex = -1; // for debug
753 if (iconIndex < 0 && isRootDir_inLink)
754 iconIndex = 0; // default file
755
756 sumPath.Add_PathSepar();
757
758 ComboBoxPaths.Add(sumPath);
759 if (name.IsEmpty())
760 name.Add_PathSepar();
761 AddComboBoxItem(name, iconIndex, indent++,
762 false); // addToList
763 }
764
765 #ifndef UNDER_CE
766
767 {
768 int iconIndex;
769 const UString name = RootFolder_GetName_Documents(iconIndex);
770 // iconIndex = -1; // for debug
771 AddComboBoxItem(name, iconIndex, 0, true);
772 }
773 AddComboBoxItem(name_Computer, iconIndex_Computer, 0, true);
774 {
775 FStringVector driveStrings;
776 MyGetLogicalDriveStrings(driveStrings);
777 FOR_VECTOR (i, driveStrings)
778 {
779 FString s = driveStrings[i];
780 ComboBoxPaths.Add(fs2us(s));
781 int iconIndex2 = GetRealIconIndex_for_DirPath(s, FILE_ATTRIBUTE_DIRECTORY);
782 if (!s.IsEmpty())
783 {
784 const FChar c = s.Back();
785 if (IS_PATH_SEPAR(c))
786 s.DeleteBack();
787 }
788 // iconIndex2 = -1; // for debug
789 AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
790 }
791 }
792 {
793 int iconIndex;
794 const UString name = RootFolder_GetName_Network(iconIndex);
795 AddComboBoxItem(name, iconIndex, 0, true);
796 }
797
798 #endif
799
800 return false;
801 }
802
803 case CBN_SELENDOK:
804 {
805 int index = _headerComboBox.GetCurSel();
806 if (index >= 0)
807 {
808 const UString path = ComboBoxPaths[index];
809 _headerComboBox.SetCurSel(-1);
810 // _headerComboBox.SetText(pass); // it's fix for selecting by mouse.
811 if (BindToPathAndRefresh(path) == S_OK)
812 {
813 PostMsg(kSetFocusToListView);
814 #ifdef UNDER_CE
815 PostMsg(kRefresh_HeaderComboBox);
816 #endif
817 return true;
818 }
819 }
820 return false;
821 }
822 /*
823 case CBN_CLOSEUP:
824 {
825 LoadFullPathAndShow();
826 true;
827
828 }
829 case CBN_SELCHANGE:
830 {
831 // LoadFullPathAndShow();
832 return true;
833 }
834 */
835 }
836 return false;
837 }
838
OnNotifyComboBox(LPNMHDR NON_CE_VAR (header),LRESULT & NON_CE_VAR (result))839 bool CPanel::OnNotifyComboBox(LPNMHDR NON_CE_VAR(header), LRESULT & NON_CE_VAR(result))
840 {
841 #ifndef UNDER_CE
842 switch (header->code)
843 {
844 case CBEN_BEGINEDIT:
845 {
846 _lastFocusedIsList = false;
847 _panelCallback->PanelWasFocused();
848 break;
849 }
850 #ifndef _UNICODE
851 case CBEN_ENDEDIT:
852 {
853 return OnNotifyComboBoxEndEdit((PNMCBEENDEDIT)header, result);
854 }
855 #endif
856 case CBEN_ENDEDITW:
857 {
858 return OnNotifyComboBoxEndEdit((PNMCBEENDEDITW)header, result);
859 }
860 }
861 #endif
862 return false;
863 }
864
865
FoldersHistory()866 void CPanel::FoldersHistory()
867 {
868 CListViewDialog listViewDialog;
869 listViewDialog.DeleteIsAllowed = true;
870 listViewDialog.SelectFirst = true;
871 LangString(IDS_FOLDERS_HISTORY, listViewDialog.Title);
872 _appState->FolderHistory.GetList(listViewDialog.Strings);
873 if (listViewDialog.Create(GetParent()) != IDOK)
874 return;
875 UString selectString;
876 if (listViewDialog.StringsWereChanged)
877 {
878 _appState->FolderHistory.RemoveAll();
879 for (int i = (int)listViewDialog.Strings.Size() - 1; i >= 0; i--)
880 _appState->FolderHistory.AddString(listViewDialog.Strings[i]);
881 if (listViewDialog.FocusedItemIndex >= 0)
882 selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
883 }
884 else
885 {
886 if (listViewDialog.FocusedItemIndex >= 0)
887 selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
888 }
889 if (listViewDialog.FocusedItemIndex >= 0)
890 BindToPathAndRefresh(selectString);
891 }
892
893
GetParentDirPrefix() const894 UString CPanel::GetParentDirPrefix() const
895 {
896 UString s;
897 if (!_currentFolderPrefix.IsEmpty())
898 {
899 wchar_t c = _currentFolderPrefix.Back();
900 if (IS_PATH_SEPAR(c) || c == ':')
901 {
902 s = _currentFolderPrefix;
903 s.DeleteBack();
904 if (s != L"\\\\." &&
905 s != L"\\\\?")
906 {
907 int pos = s.ReverseFind_PathSepar();
908 if (pos >= 0)
909 s.DeleteFrom((unsigned)(pos + 1));
910 }
911 }
912 }
913 return s;
914 }
915
916
OpenParentFolder()917 void CPanel::OpenParentFolder()
918 {
919 LoadFullPath(); // Maybe we don't need it ??
920
921 UString parentFolderPrefix;
922 UString focusedName;
923
924 if (!_currentFolderPrefix.IsEmpty())
925 {
926 wchar_t c = _currentFolderPrefix.Back();
927 if (IS_PATH_SEPAR(c) || c == ':')
928 {
929 focusedName = _currentFolderPrefix;
930 focusedName.DeleteBack();
931 /*
932 if (c == ':' && !focusedName.IsEmpty() && IS_PATH_SEPAR(focusedName.Back()))
933 {
934 focusedName.DeleteBack();
935 }
936 else
937 */
938 if (focusedName != L"\\\\." &&
939 focusedName != L"\\\\?")
940 {
941 const int pos = focusedName.ReverseFind_PathSepar();
942 if (pos >= 0)
943 {
944 parentFolderPrefix = focusedName;
945 parentFolderPrefix.DeleteFrom((unsigned)(pos + 1));
946 focusedName.DeleteFrontal((unsigned)(pos + 1));
947 }
948 }
949 }
950 }
951
952 CDisableTimerProcessing disableTimerProcessing(*this);
953 CDisableNotify disableNotify(*this);
954
955 CMyComPtr<IFolderFolder> newFolder;
956 _folder->BindToParentFolder(&newFolder);
957
958 // newFolder.Release(); // for test
959
960 if (newFolder)
961 SetNewFolder(newFolder);
962 else
963 {
964 bool needSetFolder = true;
965 if (!_parentFolders.IsEmpty())
966 {
967 {
968 const CFolderLink &link = _parentFolders.Back();
969 parentFolderPrefix = link.ParentFolderPath;
970 focusedName = link.RelPath;
971 }
972 CloseOneLevel();
973 needSetFolder = (!_folder);
974 }
975
976 if (needSetFolder)
977 {
978 {
979 COpenResult openRes;
980 BindToPath(parentFolderPrefix, UString(), openRes);
981 }
982 }
983 }
984
985 CSelectedState state;
986 state.FocusedName = focusedName;
987 state.FocusedName_Defined = true;
988 /*
989 if (!focusedName.IsEmpty())
990 state.SelectedNames.Add(focusedName);
991 */
992 LoadFullPath();
993 // ::SetCurrentDirectory(::_currentFolderPrefix);
994 RefreshListCtrl(state);
995 // _listView.EnsureVisible(_listView.GetFocusedItem(), false);
996 }
997
998
CloseOneLevel()999 void CPanel::CloseOneLevel()
1000 {
1001 ReleaseFolder();
1002 _library.Free();
1003 {
1004 CFolderLink &link = _parentFolders.Back();
1005 if (link.ParentFolder)
1006 SetNewFolder(link.ParentFolder);
1007 _library.Attach(link.Library.Detach());
1008 }
1009 if (_parentFolders.Size() > 1)
1010 OpenParentArchiveFolder();
1011 _parentFolders.DeleteBack();
1012 if (_parentFolders.IsEmpty())
1013 _flatMode = _flatModeForDisk;
1014 }
1015
CloseOpenFolders()1016 void CPanel::CloseOpenFolders()
1017 {
1018 while (!_parentFolders.IsEmpty())
1019 CloseOneLevel();
1020 _flatMode = _flatModeForDisk;
1021 ReleaseFolder();
1022 _library.Free();
1023 }
1024
OpenRootFolder()1025 void CPanel::OpenRootFolder()
1026 {
1027 CDisableTimerProcessing disableTimerProcessing(*this);
1028 CDisableNotify disableNotify(*this);
1029 _parentFolders.Clear();
1030 SetToRootFolder();
1031 RefreshListCtrl();
1032 // ::SetCurrentDirectory(::_currentFolderPrefix);
1033 /*
1034 BeforeChangeFolder();
1035 _currentFolderPrefix.Empty();
1036 AfterChangeFolder();
1037 SetCurrentPathText();
1038 RefreshListCtrl(UString(), 0, UStringVector());
1039 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
1040 */
1041 }
1042
OpenDrivesFolder()1043 void CPanel::OpenDrivesFolder()
1044 {
1045 CloseOpenFolders();
1046 #ifdef UNDER_CE
1047 NFsFolder::CFSFolder *folderSpec = new NFsFolder::CFSFolder;
1048 SetNewFolder(folderSpec);
1049 folderSpec->InitToRoot();
1050 #else
1051 CFSDrives *folderSpec = new CFSDrives;
1052 SetNewFolder(folderSpec);
1053 folderSpec->Init();
1054 #endif
1055 RefreshListCtrl();
1056 }
1057
OpenFolder(unsigned index)1058 void CPanel::OpenFolder(unsigned index)
1059 {
1060 if (index == kParentIndex)
1061 {
1062 OpenParentFolder();
1063 return;
1064 }
1065 CMyComPtr<IFolderFolder> newFolder;
1066 const HRESULT res = _folder->BindToFolder((unsigned)index, &newFolder);
1067 if (res != 0)
1068 {
1069 MessageBox_Error_HRESULT(res);
1070 return;
1071 }
1072 if (!newFolder)
1073 return;
1074 SetNewFolder(newFolder);
1075 LoadFullPath();
1076 RefreshListCtrl();
1077 // 17.02: fixed : now we don't select first item
1078 // _listView.SetItemState_Selected(_listView.GetFocusedItem());
1079 _listView.EnsureVisible(_listView.GetFocusedItem(), false);
1080 }
1081
OpenAltStreams()1082 void CPanel::OpenAltStreams()
1083 {
1084 CRecordVector<UInt32> indices;
1085 Get_ItemIndices_Operated(indices);
1086 Int32 realIndex = -1;
1087 if (indices.Size() > 1)
1088 return;
1089 if (indices.Size() == 1)
1090 realIndex = (Int32)indices[0];
1091
1092 if (_folderAltStreams)
1093 {
1094 CMyComPtr<IFolderFolder> newFolder;
1095 _folderAltStreams->BindToAltStreams((UInt32)realIndex, &newFolder);
1096 if (newFolder)
1097 {
1098 CDisableTimerProcessing disableTimerProcessing(*this);
1099 CDisableNotify disableNotify(*this);
1100 SetNewFolder(newFolder);
1101 RefreshListCtrl();
1102 return;
1103 }
1104 return;
1105 }
1106
1107 #if defined(_WIN32) && !defined(UNDER_CE)
1108 UString path;
1109 if (realIndex >= 0)
1110 path = GetItemFullPath((UInt32)realIndex);
1111 else
1112 {
1113 path = GetFsPath();
1114 if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path)))
1115 if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back()))
1116 path.DeleteBack();
1117 }
1118
1119 path.Add_Colon();
1120 BindToPathAndRefresh(path);
1121 #endif
1122 }
1123