• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetRealIconIndex(CFSTR path,DWORD attributes)371 static int GetRealIconIndex(CFSTR path, DWORD attributes)
372 {
373   int index = -1;
374   if (GetRealIconIndex(path, attributes, index) != 0)
375     return index;
376   return -1;
377 }
378 
LoadFullPathAndShow()379 void CPanel::LoadFullPathAndShow()
380 {
381   LoadFullPath();
382   _appState->FolderHistory.AddString(_currentFolderPrefix);
383 
384   _headerComboBox.SetText(_currentFolderPrefix);
385 
386   #ifndef UNDER_CE
387 
388   COMBOBOXEXITEM item;
389   item.mask = 0;
390 
391   UString path = _currentFolderPrefix;
392   if (path.Len() >
393       #ifdef _WIN32
394       3
395       #else
396       1
397       #endif
398       && IS_PATH_SEPAR(path.Back()))
399     path.DeleteBack();
400 
401   DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
402 
403   // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path
404   if (path.IsPrefixedBy(L"\\\\.\\"))
405     path = "_TestFolder_";
406   else
407   {
408     CFileInfo fi;
409     if (fi.Find(us2fs(path)))
410       attrib = fi.Attrib;
411   }
412   item.iImage = GetRealIconIndex(us2fs(path), attrib);
413 
414   if (item.iImage >= 0)
415   {
416     item.iSelectedImage = item.iImage;
417     item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
418   }
419   item.iItem = -1;
420   _headerComboBox.SetItem(&item);
421 
422   #endif
423 
424   RefreshTitle();
425 }
426 
427 #ifndef UNDER_CE
OnNotifyComboBoxEnter(const UString & s)428 LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s)
429 {
430   if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK)
431   {
432     PostMsg(kSetFocusToListView);
433     return TRUE;
434   }
435   return FALSE;
436 }
437 
OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info,LRESULT & result)438 bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result)
439 {
440   if (info->iWhy == CBENF_ESCAPE)
441   {
442     _headerComboBox.SetText(_currentFolderPrefix);
443     PostMsg(kSetFocusToListView);
444     result = FALSE;
445     return true;
446   }
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     // When we use Edit control and press Enter.
459     UString s;
460     _headerComboBox.GetText(s);
461     result = OnNotifyComboBoxEnter(s);
462     return true;
463   }
464   return false;
465 }
466 #endif
467 
468 #ifndef _UNICODE
OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info,LRESULT & result)469 bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
470 {
471   if (info->iWhy == CBENF_ESCAPE)
472   {
473     _headerComboBox.SetText(_currentFolderPrefix);
474     PostMsg(kSetFocusToListView);
475     result = FALSE;
476     return true;
477   }
478   /*
479   if (info->iWhy == CBENF_DROPDOWN)
480   {
481     result = FALSE;
482     return true;
483   }
484   */
485 
486   if (info->iWhy == CBENF_RETURN)
487   {
488     UString s;
489     _headerComboBox.GetText(s);
490     // GetUnicodeString(info->szText)
491     result = OnNotifyComboBoxEnter(s);
492     return true;
493   }
494   return false;
495 }
496 #endif
497 
AddComboBoxItem(const UString & name,int iconIndex,int indent,bool addToList)498 void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList)
499 {
500   #ifdef UNDER_CE
501 
502   UString s;
503   iconIndex = iconIndex;
504   for (int i = 0; i < indent; i++)
505     s += "  ";
506   _headerComboBox.AddString(s + name);
507 
508   #else
509 
510   COMBOBOXEXITEMW item;
511   item.mask = CBEIF_TEXT | CBEIF_INDENT;
512   item.iSelectedImage = item.iImage = iconIndex;
513   if (iconIndex >= 0)
514     item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
515   item.iItem = -1;
516   item.iIndent = indent;
517   item.pszText = name.Ptr_non_const();
518   _headerComboBox.InsertItem(&item);
519 
520   #endif
521 
522   if (addToList)
523     ComboBoxPaths.Add(name);
524 }
525 
526 extern UString RootFolder_GetName_Computer(int &iconIndex);
527 extern UString RootFolder_GetName_Network(int &iconIndex);
528 extern UString RootFolder_GetName_Documents(int &iconIndex);
529 
OnComboBoxCommand(UINT code,LPARAM,LRESULT & result)530 bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
531 {
532   result = FALSE;
533   switch (code)
534   {
535     case CBN_DROPDOWN:
536     {
537       ComboBoxPaths.Clear();
538       _headerComboBox.ResetContent();
539 
540       unsigned i;
541       UStringVector pathParts;
542 
543       SplitPathToParts(_currentFolderPrefix, pathParts);
544       UString sumPass;
545       if (!pathParts.IsEmpty())
546         pathParts.DeleteBack();
547       for (i = 0; i < pathParts.Size(); i++)
548       {
549         const UString name = pathParts[i];
550         sumPass += name;
551         sumPass.Add_PathSepar();
552         CFileInfo info;
553         DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
554         if (info.Find(us2fs(sumPass)))
555           attrib = info.Attrib;
556         AddComboBoxItem(
557             name.IsEmpty() ? L"\\" : name,
558             GetRealIconIndex(us2fs(sumPass), attrib),
559             (int)i, // iIndent
560             false); // addToList
561         ComboBoxPaths.Add(sumPass);
562       }
563 
564       #ifndef UNDER_CE
565 
566       int iconIndex;
567       UString name;
568       name = RootFolder_GetName_Documents(iconIndex);
569       AddComboBoxItem(name, iconIndex, 0, true);
570 
571       name = RootFolder_GetName_Computer(iconIndex);
572       AddComboBoxItem(name, iconIndex, 0, true);
573 
574       FStringVector driveStrings;
575       MyGetLogicalDriveStrings(driveStrings);
576       for (i = 0; i < driveStrings.Size(); i++)
577       {
578         FString s = driveStrings[i];
579         ComboBoxPaths.Add(fs2us(s));
580         int iconIndex2 = GetRealIconIndex(s, 0);
581         if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR)
582           s.DeleteBack();
583         AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
584       }
585 
586       name = RootFolder_GetName_Network(iconIndex);
587       AddComboBoxItem(name, iconIndex, 0, true);
588 
589       #endif
590 
591       return false;
592     }
593 
594     case CBN_SELENDOK:
595     {
596       int index = _headerComboBox.GetCurSel();
597       if (index >= 0)
598       {
599         UString pass = ComboBoxPaths[index];
600         _headerComboBox.SetCurSel(-1);
601         // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.
602         if (BindToPathAndRefresh(pass) == S_OK)
603         {
604           PostMsg(kSetFocusToListView);
605           #ifdef UNDER_CE
606           PostMsg(kRefresh_HeaderComboBox);
607           #endif
608           return true;
609         }
610       }
611       return false;
612     }
613     /*
614     case CBN_CLOSEUP:
615     {
616       LoadFullPathAndShow();
617       true;
618 
619     }
620     case CBN_SELCHANGE:
621     {
622       // LoadFullPathAndShow();
623       return true;
624     }
625     */
626   }
627   return false;
628 }
629 
OnNotifyComboBox(LPNMHDR NON_CE_VAR (header),LRESULT & NON_CE_VAR (result))630 bool CPanel::OnNotifyComboBox(LPNMHDR NON_CE_VAR(header), LRESULT & NON_CE_VAR(result))
631 {
632   #ifndef UNDER_CE
633   switch (header->code)
634   {
635     case CBEN_BEGINEDIT:
636     {
637       _lastFocusedIsList = false;
638       _panelCallback->PanelWasFocused();
639       break;
640     }
641     #ifndef _UNICODE
642     case CBEN_ENDEDIT:
643     {
644       return OnNotifyComboBoxEndEdit((PNMCBEENDEDIT)header, result);
645     }
646     #endif
647     case CBEN_ENDEDITW:
648     {
649       return OnNotifyComboBoxEndEdit((PNMCBEENDEDITW)header, result);
650     }
651   }
652   #endif
653   return false;
654 }
655 
656 
FoldersHistory()657 void CPanel::FoldersHistory()
658 {
659   CListViewDialog listViewDialog;
660   listViewDialog.DeleteIsAllowed = true;
661   listViewDialog.SelectFirst = true;
662   LangString(IDS_FOLDERS_HISTORY, listViewDialog.Title);
663   _appState->FolderHistory.GetList(listViewDialog.Strings);
664   if (listViewDialog.Create(GetParent()) != IDOK)
665     return;
666   UString selectString;
667   if (listViewDialog.StringsWereChanged)
668   {
669     _appState->FolderHistory.RemoveAll();
670     for (int i = (int)listViewDialog.Strings.Size() - 1; i >= 0; i--)
671       _appState->FolderHistory.AddString(listViewDialog.Strings[i]);
672     if (listViewDialog.FocusedItemIndex >= 0)
673       selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
674   }
675   else
676   {
677     if (listViewDialog.FocusedItemIndex >= 0)
678       selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
679   }
680   if (listViewDialog.FocusedItemIndex >= 0)
681     BindToPathAndRefresh(selectString);
682 }
683 
684 
GetParentDirPrefix() const685 UString CPanel::GetParentDirPrefix() const
686 {
687   UString s;
688   if (!_currentFolderPrefix.IsEmpty())
689   {
690     wchar_t c = _currentFolderPrefix.Back();
691     if (IS_PATH_SEPAR(c) || c == ':')
692     {
693       s = _currentFolderPrefix;
694       s.DeleteBack();
695       if (s != L"\\\\." &&
696           s != L"\\\\?")
697       {
698         int pos = s.ReverseFind_PathSepar();
699         if (pos >= 0)
700           s.DeleteFrom((unsigned)(pos + 1));
701       }
702     }
703   }
704   return s;
705 }
706 
707 
OpenParentFolder()708 void CPanel::OpenParentFolder()
709 {
710   LoadFullPath(); // Maybe we don't need it ??
711 
712   UString parentFolderPrefix;
713   UString focusedName;
714 
715   if (!_currentFolderPrefix.IsEmpty())
716   {
717     wchar_t c = _currentFolderPrefix.Back();
718     if (IS_PATH_SEPAR(c) || c == ':')
719     {
720       focusedName = _currentFolderPrefix;
721       focusedName.DeleteBack();
722       /*
723       if (c == ':' && !focusedName.IsEmpty() && IS_PATH_SEPAR(focusedName.Back()))
724       {
725         focusedName.DeleteBack();
726       }
727       else
728       */
729       if (focusedName != L"\\\\." &&
730           focusedName != L"\\\\?")
731       {
732         const int pos = focusedName.ReverseFind_PathSepar();
733         if (pos >= 0)
734         {
735           parentFolderPrefix = focusedName;
736           parentFolderPrefix.DeleteFrom((unsigned)(pos + 1));
737           focusedName.DeleteFrontal((unsigned)(pos + 1));
738         }
739       }
740     }
741   }
742 
743   CDisableTimerProcessing disableTimerProcessing(*this);
744   CDisableNotify disableNotify(*this);
745 
746   CMyComPtr<IFolderFolder> newFolder;
747   _folder->BindToParentFolder(&newFolder);
748 
749   // newFolder.Release(); // for test
750 
751   if (newFolder)
752     SetNewFolder(newFolder);
753   else
754   {
755     bool needSetFolder = true;
756     if (!_parentFolders.IsEmpty())
757     {
758       {
759         const CFolderLink &link = _parentFolders.Back();
760         parentFolderPrefix = link.ParentFolderPath;
761         focusedName = link.RelPath;
762       }
763       CloseOneLevel();
764       needSetFolder = (!_folder);
765     }
766 
767     if (needSetFolder)
768     {
769       {
770         COpenResult openRes;
771         BindToPath(parentFolderPrefix, UString(), openRes);
772       }
773     }
774   }
775 
776   CSelectedState state;
777   state.FocusedName = focusedName;
778   state.FocusedName_Defined = true;
779   /*
780   if (!focusedName.IsEmpty())
781     state.SelectedNames.Add(focusedName);
782   */
783   LoadFullPath();
784   // ::SetCurrentDirectory(::_currentFolderPrefix);
785   RefreshListCtrl(state);
786   // _listView.EnsureVisible(_listView.GetFocusedItem(), false);
787 }
788 
789 
CloseOneLevel()790 void CPanel::CloseOneLevel()
791 {
792   ReleaseFolder();
793   _library.Free();
794   {
795     CFolderLink &link = _parentFolders.Back();
796     if (link.ParentFolder)
797       SetNewFolder(link.ParentFolder);
798     _library.Attach(link.Library.Detach());
799   }
800   if (_parentFolders.Size() > 1)
801     OpenParentArchiveFolder();
802   _parentFolders.DeleteBack();
803   if (_parentFolders.IsEmpty())
804     _flatMode = _flatModeForDisk;
805 }
806 
CloseOpenFolders()807 void CPanel::CloseOpenFolders()
808 {
809   while (!_parentFolders.IsEmpty())
810     CloseOneLevel();
811   _flatMode = _flatModeForDisk;
812   ReleaseFolder();
813   _library.Free();
814 }
815 
OpenRootFolder()816 void CPanel::OpenRootFolder()
817 {
818   CDisableTimerProcessing disableTimerProcessing(*this);
819   CDisableNotify disableNotify(*this);
820   _parentFolders.Clear();
821   SetToRootFolder();
822   RefreshListCtrl();
823   // ::SetCurrentDirectory(::_currentFolderPrefix);
824   /*
825   BeforeChangeFolder();
826   _currentFolderPrefix.Empty();
827   AfterChangeFolder();
828   SetCurrentPathText();
829   RefreshListCtrl(UString(), 0, UStringVector());
830   _listView.EnsureVisible(_listView.GetFocusedItem(), false);
831   */
832 }
833 
OpenDrivesFolder()834 void CPanel::OpenDrivesFolder()
835 {
836   CloseOpenFolders();
837   #ifdef UNDER_CE
838   NFsFolder::CFSFolder *folderSpec = new NFsFolder::CFSFolder;
839   SetNewFolder(folderSpec);
840   folderSpec->InitToRoot();
841   #else
842   CFSDrives *folderSpec = new CFSDrives;
843   SetNewFolder(folderSpec);
844   folderSpec->Init();
845   #endif
846   RefreshListCtrl();
847 }
848 
OpenFolder(unsigned index)849 void CPanel::OpenFolder(unsigned index)
850 {
851   if (index == kParentIndex)
852   {
853     OpenParentFolder();
854     return;
855   }
856   CMyComPtr<IFolderFolder> newFolder;
857   const HRESULT res = _folder->BindToFolder((unsigned)index, &newFolder);
858   if (res != 0)
859   {
860     MessageBox_Error_HRESULT(res);
861     return;
862   }
863   if (!newFolder)
864     return;
865   SetNewFolder(newFolder);
866   LoadFullPath();
867   RefreshListCtrl();
868   // 17.02: fixed : now we don't select first item
869   // _listView.SetItemState_Selected(_listView.GetFocusedItem());
870   _listView.EnsureVisible(_listView.GetFocusedItem(), false);
871 }
872 
OpenAltStreams()873 void CPanel::OpenAltStreams()
874 {
875   CRecordVector<UInt32> indices;
876   Get_ItemIndices_Operated(indices);
877   Int32 realIndex = -1;
878   if (indices.Size() > 1)
879     return;
880   if (indices.Size() == 1)
881     realIndex = (Int32)indices[0];
882 
883   if (_folderAltStreams)
884   {
885     CMyComPtr<IFolderFolder> newFolder;
886     _folderAltStreams->BindToAltStreams((UInt32)realIndex, &newFolder);
887     if (newFolder)
888     {
889       CDisableTimerProcessing disableTimerProcessing(*this);
890       CDisableNotify disableNotify(*this);
891       SetNewFolder(newFolder);
892       RefreshListCtrl();
893       return;
894     }
895     return;
896   }
897 
898   #if defined(_WIN32) && !defined(UNDER_CE)
899   UString path;
900   if (realIndex >= 0)
901     path = GetItemFullPath((UInt32)realIndex);
902   else
903   {
904     path = GetFsPath();
905     if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path)))
906       if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back()))
907         path.DeleteBack();
908   }
909 
910   path.Add_Colon();
911   BindToPathAndRefresh(path);
912   #endif
913 }
914