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,bool & archiveIsOpened,bool & encrypted)76 HRESULT CPanel::BindToPath(const UString &fullPath, const UString &arcFormat, bool &archiveIsOpened, bool &encrypted)
77 {
78   UString path = fullPath;
79   #ifdef _WIN32
80   path.Replace(L'/', WCHAR_PATH_SEPARATOR);
81   #endif
82 
83   archiveIsOpened = false;
84   encrypted = false;
85 
86   CDisableTimerProcessing disableTimerProcessing(*this);
87   CDisableNotify disableNotify(*this);
88 
89   for (; !_parentFolders.IsEmpty(); CloseOneLevel())
90   {
91     // ---------- we try to use open archive ----------
92 
93     const CFolderLink &link = _parentFolders.Back();
94     const UString &virtPath = link.VirtualPath;
95     if (!path.IsPrefixedBy(virtPath))
96       continue;
97     UString relatPath = path.Ptr(virtPath.Len());
98     if (!relatPath.IsEmpty())
99     {
100       if (!IS_PATH_SEPAR(relatPath[0]))
101         continue;
102       else
103         relatPath.Delete(0);
104     }
105 
106     UString relatPath2 = relatPath;
107     if (!relatPath2.IsEmpty() && !IS_PATH_SEPAR(relatPath2.Back()))
108       relatPath2.Add_PathSepar();
109 
110     for (;;)
111     {
112       const UString foldPath = GetFolderPath(_folder);
113       if (relatPath2 == foldPath)
114         break;
115       if (relatPath.IsPrefixedBy(foldPath))
116       {
117         path = relatPath.Ptr(foldPath.Len());
118         break;
119       }
120       CMyComPtr<IFolderFolder> newFolder;
121       if (_folder->BindToParentFolder(&newFolder) != S_OK)
122         throw 20140918;
123       if (!newFolder) // we exit from loop above if (relatPath.IsPrefixedBy(empty path for root folder)
124         throw 20140918;
125       SetNewFolder(newFolder);
126     }
127     break;
128   }
129 
130   if (_parentFolders.IsEmpty())
131   {
132     // ---------- we open file or folder from file system ----------
133 
134     CloseOpenFolders();
135     UString sysPath = path;
136 
137     unsigned prefixSize = NName::GetRootPrefixSize(sysPath);
138     if (prefixSize == 0 || sysPath[prefixSize] == 0)
139       sysPath.Empty();
140 
141     #if defined(_WIN32) && !defined(UNDER_CE)
142     if (!sysPath.IsEmpty() && sysPath.Back() == ':' &&
143       (sysPath.Len() != 2 || !NName::IsDrivePath2(sysPath)))
144     {
145       UString baseFile = sysPath;
146       baseFile.DeleteBack();
147       if (NFind::DoesFileOrDirExist(us2fs(baseFile)))
148         sysPath.Empty();
149     }
150     #endif
151 
152     CFileInfo fileInfo;
153 
154     while (!sysPath.IsEmpty())
155     {
156       if (fileInfo.Find(us2fs(sysPath)))
157         break;
158       int pos = sysPath.ReverseFind_PathSepar();
159       if (pos < 0)
160         sysPath.Empty();
161       else
162       {
163         /*
164         if (reducedParts.Size() > 0 || pos < (int)sysPath.Len() - 1)
165           reducedParts.Add(sysPath.Ptr(pos + 1));
166         */
167         #if defined(_WIN32) && !defined(UNDER_CE)
168         if (pos == 2 && NName::IsDrivePath2(sysPath) && sysPath.Len() > 3)
169           pos++;
170         #endif
171 
172         sysPath.DeleteFrom(pos);
173       }
174     }
175 
176     SetToRootFolder();
177 
178     CMyComPtr<IFolderFolder> newFolder;
179 
180     if (sysPath.IsEmpty())
181     {
182       _folder->BindToFolder(path, &newFolder);
183     }
184     else if (fileInfo.IsDir())
185     {
186       #ifdef _WIN32
187       if (DoesNameContainWildcard_SkipRoot(sysPath))
188       {
189         FString dirPrefix, fileName;
190         NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
191         if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix)))
192           return E_INVALIDARG;
193         sysPath = fs2us(dirPrefix + fileInfo.Name);
194       }
195       #endif
196 
197       NName::NormalizeDirPathPrefix(sysPath);
198       _folder->BindToFolder(sysPath, &newFolder);
199     }
200     else
201     {
202       FString dirPrefix, fileName;
203 
204       NDir::GetFullPathAndSplit(us2fs(sysPath), dirPrefix, fileName);
205 
206       HRESULT res = S_OK;
207 
208       #ifdef _WIN32
209       if (DoesNameContainWildcard_SkipRoot(fs2us(dirPrefix)))
210         return E_INVALIDARG;
211 
212       if (DoesNameContainWildcard(fs2us(fileName)))
213         res = S_FALSE;
214       else
215       #endif
216       {
217         CTempFileInfo tfi;
218         tfi.RelPath = fs2us(fileName);
219         tfi.FolderPath = dirPrefix;
220         tfi.FilePath = us2fs(sysPath);
221         res = OpenAsArc(NULL, tfi, sysPath, arcFormat, encrypted);
222       }
223 
224       if (res == S_FALSE)
225         _folder->BindToFolder(fs2us(dirPrefix), &newFolder);
226       else
227       {
228         RINOK(res);
229         archiveIsOpened = true;
230         _parentFolders.Back().ParentFolderPath = fs2us(dirPrefix);
231         path.DeleteFrontal(sysPath.Len());
232         if (!path.IsEmpty() && IS_PATH_SEPAR(path[0]))
233           path.Delete(0);
234       }
235     }
236 
237     if (newFolder)
238     {
239       SetNewFolder(newFolder);
240       // LoadFullPath();
241       return S_OK;
242     }
243   }
244 
245   {
246     // ---------- we open folder remPath in archive and sub archives ----------
247 
248     for (unsigned curPos = 0; curPos != path.Len();)
249     {
250       UString s = path.Ptr(curPos);
251       int slashPos = NName::FindSepar(s);
252       unsigned skipLen = s.Len();
253       if (slashPos >= 0)
254       {
255         s.DeleteFrom(slashPos);
256         skipLen = slashPos + 1;
257       }
258 
259       CMyComPtr<IFolderFolder> newFolder;
260       _folder->BindToFolder(s, &newFolder);
261       if (newFolder)
262         curPos += skipLen;
263       else if (_folderAltStreams)
264       {
265         int pos = s.Find(L':');
266         if (pos >= 0)
267         {
268           UString baseName = s;
269           baseName.DeleteFrom(pos);
270           if (_folderAltStreams->BindToAltStreams(baseName, &newFolder) == S_OK && newFolder)
271             curPos += pos + 1;
272         }
273       }
274 
275       if (!newFolder)
276         break;
277 
278       SetNewFolder(newFolder);
279     }
280   }
281 
282   return S_OK;
283 }
284 
BindToPathAndRefresh(const UString & path)285 HRESULT CPanel::BindToPathAndRefresh(const UString &path)
286 {
287   CDisableTimerProcessing disableTimerProcessing(*this);
288   CDisableNotify disableNotify(*this);
289   bool archiveIsOpened, encrypted;
290   UString s = path;
291 
292   #ifdef _WIN32
293     if (!s.IsEmpty() && s[0] == '\"' && s.Back() == '\"')
294     {
295       s.DeleteBack();
296       s.Delete(0);
297     }
298   #endif
299 
300   HRESULT res = BindToPath(s, UString(), archiveIsOpened, encrypted);
301   RefreshListCtrl();
302   return res;
303 }
304 
SetBookmark(unsigned index)305 void CPanel::SetBookmark(unsigned index)
306 {
307   _appState->FastFolders.SetString(index, _currentFolderPrefix);
308 }
309 
OpenBookmark(unsigned index)310 void CPanel::OpenBookmark(unsigned index)
311 {
312   BindToPathAndRefresh(_appState->FastFolders.GetString(index));
313 }
314 
GetFolderPath(IFolderFolder * folder)315 UString GetFolderPath(IFolderFolder *folder)
316 {
317   {
318     NCOM::CPropVariant prop;
319     if (folder->GetFolderProperty(kpidPath, &prop) == S_OK)
320       if (prop.vt == VT_BSTR)
321         return (wchar_t *)prop.bstrVal;
322   }
323   return UString();
324 }
325 
LoadFullPath()326 void CPanel::LoadFullPath()
327 {
328   _currentFolderPrefix.Empty();
329   FOR_VECTOR (i, _parentFolders)
330   {
331     const CFolderLink &folderLink = _parentFolders[i];
332     _currentFolderPrefix += folderLink.ParentFolderPath;
333         // GetFolderPath(folderLink.ParentFolder);
334     _currentFolderPrefix += folderLink.RelPath;
335     _currentFolderPrefix.Add_PathSepar();
336   }
337   if (_folder)
338     _currentFolderPrefix += GetFolderPath(_folder);
339 }
340 
GetRealIconIndex(CFSTR path,DWORD attributes)341 static int GetRealIconIndex(CFSTR path, DWORD attributes)
342 {
343   int index = -1;
344   if (GetRealIconIndex(path, attributes, index) != 0)
345     return index;
346   return -1;
347 }
348 
LoadFullPathAndShow()349 void CPanel::LoadFullPathAndShow()
350 {
351   LoadFullPath();
352   _appState->FolderHistory.AddString(_currentFolderPrefix);
353 
354   _headerComboBox.SetText(_currentFolderPrefix);
355 
356   #ifndef UNDER_CE
357 
358   COMBOBOXEXITEM item;
359   item.mask = 0;
360 
361   UString path = _currentFolderPrefix;
362   if (path.Len() >
363       #ifdef _WIN32
364       3
365       #else
366       1
367       #endif
368       && IS_PATH_SEPAR(path.Back()))
369     path.DeleteBack();
370 
371   DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
372 
373   // GetRealIconIndex is slow for direct DVD/UDF path. So we use dummy path
374   if (path.IsPrefixedBy(L"\\\\.\\"))
375     path = "_TestFolder_";
376   else
377   {
378     CFileInfo fi;
379     if (fi.Find(us2fs(path)))
380       attrib = fi.Attrib;
381   }
382   item.iImage = GetRealIconIndex(us2fs(path), attrib);
383 
384   if (item.iImage >= 0)
385   {
386     item.iSelectedImage = item.iImage;
387     item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
388   }
389   item.iItem = -1;
390   _headerComboBox.SetItem(&item);
391 
392   #endif
393 
394   RefreshTitle();
395 }
396 
397 #ifndef UNDER_CE
OnNotifyComboBoxEnter(const UString & s)398 LRESULT CPanel::OnNotifyComboBoxEnter(const UString &s)
399 {
400   if (BindToPathAndRefresh(GetUnicodeString(s)) == S_OK)
401   {
402     PostMsg(kSetFocusToListView);
403     return TRUE;
404   }
405   return FALSE;
406 }
407 
OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info,LRESULT & result)408 bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result)
409 {
410   if (info->iWhy == CBENF_ESCAPE)
411   {
412     _headerComboBox.SetText(_currentFolderPrefix);
413     PostMsg(kSetFocusToListView);
414     result = FALSE;
415     return true;
416   }
417 
418   /*
419   if (info->iWhy == CBENF_DROPDOWN)
420   {
421     result = FALSE;
422     return true;
423   }
424   */
425 
426   if (info->iWhy == CBENF_RETURN)
427   {
428     // When we use Edit control and press Enter.
429     UString s;
430     _headerComboBox.GetText(s);
431     result = OnNotifyComboBoxEnter(s);
432     return true;
433   }
434   return false;
435 }
436 #endif
437 
438 #ifndef _UNICODE
OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info,LRESULT & result)439 bool CPanel::OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result)
440 {
441   if (info->iWhy == CBENF_ESCAPE)
442   {
443     _headerComboBox.SetText(_currentFolderPrefix);
444     PostMsg(kSetFocusToListView);
445     result = FALSE;
446     return true;
447   }
448   /*
449   if (info->iWhy == CBENF_DROPDOWN)
450   {
451     result = FALSE;
452     return true;
453   }
454   */
455 
456   if (info->iWhy == CBENF_RETURN)
457   {
458     UString s;
459     _headerComboBox.GetText(s);
460     // GetUnicodeString(info->szText)
461     result = OnNotifyComboBoxEnter(s);
462     return true;
463   }
464   return false;
465 }
466 #endif
467 
AddComboBoxItem(const UString & name,int iconIndex,int indent,bool addToList)468 void CPanel::AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList)
469 {
470   #ifdef UNDER_CE
471 
472   UString s;
473   iconIndex = iconIndex;
474   for (int i = 0; i < indent; i++)
475     s += "  ";
476   _headerComboBox.AddString(s + name);
477 
478   #else
479 
480   COMBOBOXEXITEMW item;
481   item.mask = CBEIF_TEXT | CBEIF_INDENT;
482   item.iSelectedImage = item.iImage = iconIndex;
483   if (iconIndex >= 0)
484     item.mask |= (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE);
485   item.iItem = -1;
486   item.iIndent = indent;
487   item.pszText = (LPWSTR)(LPCWSTR)name;
488   _headerComboBox.InsertItem(&item);
489 
490   #endif
491 
492   if (addToList)
493     ComboBoxPaths.Add(name);
494 }
495 
496 extern UString RootFolder_GetName_Computer(int &iconIndex);
497 extern UString RootFolder_GetName_Network(int &iconIndex);
498 extern UString RootFolder_GetName_Documents(int &iconIndex);
499 
OnComboBoxCommand(UINT code,LPARAM,LRESULT & result)500 bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result)
501 {
502   result = FALSE;
503   switch (code)
504   {
505     case CBN_DROPDOWN:
506     {
507       ComboBoxPaths.Clear();
508       _headerComboBox.ResetContent();
509 
510       unsigned i;
511       UStringVector pathParts;
512 
513       SplitPathToParts(_currentFolderPrefix, pathParts);
514       UString sumPass;
515       if (!pathParts.IsEmpty())
516         pathParts.DeleteBack();
517       for (i = 0; i < pathParts.Size(); i++)
518       {
519         UString name = pathParts[i];
520         sumPass += name;
521         sumPass.Add_PathSepar();
522         CFileInfo info;
523         DWORD attrib = FILE_ATTRIBUTE_DIRECTORY;
524         if (info.Find(us2fs(sumPass)))
525           attrib = info.Attrib;
526         AddComboBoxItem(name.IsEmpty() ? L"\\" : name, GetRealIconIndex(us2fs(sumPass), attrib), i, false);
527         ComboBoxPaths.Add(sumPass);
528       }
529 
530       #ifndef UNDER_CE
531 
532       int iconIndex;
533       UString name;
534       name = RootFolder_GetName_Documents(iconIndex);
535       AddComboBoxItem(name, iconIndex, 0, true);
536 
537       name = RootFolder_GetName_Computer(iconIndex);
538       AddComboBoxItem(name, iconIndex, 0, true);
539 
540       FStringVector driveStrings;
541       MyGetLogicalDriveStrings(driveStrings);
542       for (i = 0; i < driveStrings.Size(); i++)
543       {
544         FString s = driveStrings[i];
545         ComboBoxPaths.Add(fs2us(s));
546         int iconIndex2 = GetRealIconIndex(s, 0);
547         if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR)
548           s.DeleteBack();
549         AddComboBoxItem(fs2us(s), iconIndex2, 1, false);
550       }
551 
552       name = RootFolder_GetName_Network(iconIndex);
553       AddComboBoxItem(name, iconIndex, 0, true);
554 
555       #endif
556 
557       return false;
558     }
559 
560     case CBN_SELENDOK:
561     {
562       code = code;
563       int index = _headerComboBox.GetCurSel();
564       if (index >= 0)
565       {
566         UString pass = ComboBoxPaths[index];
567         _headerComboBox.SetCurSel(-1);
568         // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse.
569         if (BindToPathAndRefresh(pass) == S_OK)
570         {
571           PostMsg(kSetFocusToListView);
572           #ifdef UNDER_CE
573           PostMsg(kRefresh_HeaderComboBox);
574           #endif
575           return true;
576         }
577       }
578       return false;
579     }
580     /*
581     case CBN_CLOSEUP:
582     {
583       LoadFullPathAndShow();
584       true;
585 
586     }
587     case CBN_SELCHANGE:
588     {
589       // LoadFullPathAndShow();
590       return true;
591     }
592     */
593   }
594   return false;
595 }
596 
OnNotifyComboBox(LPNMHDR NON_CE_VAR (header),LRESULT & NON_CE_VAR (result))597 bool CPanel::OnNotifyComboBox(LPNMHDR NON_CE_VAR(header), LRESULT & NON_CE_VAR(result))
598 {
599   #ifndef UNDER_CE
600   switch (header->code)
601   {
602     case CBEN_BEGINEDIT:
603     {
604       _lastFocusedIsList = false;
605       _panelCallback->PanelWasFocused();
606       break;
607     }
608     #ifndef _UNICODE
609     case CBEN_ENDEDIT:
610     {
611       return OnNotifyComboBoxEndEdit((PNMCBEENDEDIT)header, result);
612     }
613     #endif
614     case CBEN_ENDEDITW:
615     {
616       return OnNotifyComboBoxEndEdit((PNMCBEENDEDITW)header, result);
617     }
618   }
619   #endif
620   return false;
621 }
622 
623 
FoldersHistory()624 void CPanel::FoldersHistory()
625 {
626   CListViewDialog listViewDialog;
627   listViewDialog.DeleteIsAllowed = true;
628   LangString(IDS_FOLDERS_HISTORY, listViewDialog.Title);
629   _appState->FolderHistory.GetList(listViewDialog.Strings);
630   if (listViewDialog.Create(GetParent()) != IDOK)
631     return;
632   UString selectString;
633   if (listViewDialog.StringsWereChanged)
634   {
635     _appState->FolderHistory.RemoveAll();
636     for (int i = listViewDialog.Strings.Size() - 1; i >= 0; i--)
637       _appState->FolderHistory.AddString(listViewDialog.Strings[i]);
638     if (listViewDialog.FocusedItemIndex >= 0)
639       selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
640   }
641   else
642   {
643     if (listViewDialog.FocusedItemIndex >= 0)
644       selectString = listViewDialog.Strings[listViewDialog.FocusedItemIndex];
645   }
646   if (listViewDialog.FocusedItemIndex >= 0)
647     BindToPathAndRefresh(selectString);
648 }
649 
650 
GetParentDirPrefix() const651 UString CPanel::GetParentDirPrefix() const
652 {
653   UString s;
654   if (!_currentFolderPrefix.IsEmpty())
655   {
656     wchar_t c = _currentFolderPrefix.Back();
657     if (IS_PATH_SEPAR(c) || c == ':')
658     {
659       s = _currentFolderPrefix;
660       s.DeleteBack();
661       if (s != L"\\\\." &&
662           s != L"\\\\?")
663       {
664         int pos = s.ReverseFind_PathSepar();
665         if (pos >= 0)
666           s.DeleteFrom(pos + 1);
667       }
668     }
669   }
670   return s;
671 }
672 
673 
OpenParentFolder()674 void CPanel::OpenParentFolder()
675 {
676   LoadFullPath(); // Maybe we don't need it ??
677 
678   UString parentFolderPrefix;
679   UString focusedName;
680 
681   if (!_currentFolderPrefix.IsEmpty())
682   {
683     wchar_t c = _currentFolderPrefix.Back();
684     if (IS_PATH_SEPAR(c) || c == ':')
685     {
686       focusedName = _currentFolderPrefix;
687       focusedName.DeleteBack();
688       /*
689       if (c == ':' && !focusedName.IsEmpty() && IS_PATH_SEPAR(focusedName.Back()))
690       {
691         focusedName.DeleteBack();
692       }
693       else
694       */
695       if (focusedName != L"\\\\." &&
696           focusedName != L"\\\\?")
697       {
698         int pos = focusedName.ReverseFind_PathSepar();
699         if (pos >= 0)
700         {
701           parentFolderPrefix = focusedName;
702           parentFolderPrefix.DeleteFrom(pos + 1);
703           focusedName.DeleteFrontal(pos + 1);
704         }
705       }
706     }
707   }
708 
709   CDisableTimerProcessing disableTimerProcessing(*this);
710   CDisableNotify disableNotify(*this);
711 
712   CMyComPtr<IFolderFolder> newFolder;
713   _folder->BindToParentFolder(&newFolder);
714 
715   // newFolder.Release(); // for test
716 
717   if (newFolder)
718     SetNewFolder(newFolder);
719   else
720   {
721     bool needSetFolder = true;
722     if (!_parentFolders.IsEmpty())
723     {
724       {
725         const CFolderLink &link = _parentFolders.Back();
726         parentFolderPrefix = link.ParentFolderPath;
727         focusedName = link.RelPath;
728       }
729       CloseOneLevel();
730       needSetFolder = (!_folder);
731     }
732 
733     if (needSetFolder)
734     {
735       {
736         bool archiveIsOpened;
737         bool encrypted;
738         BindToPath(parentFolderPrefix, UString(), archiveIsOpened, encrypted);
739       }
740     }
741   }
742 
743   CSelectedState state;
744   state.FocusedName = focusedName;
745   state.FocusedName_Defined = true;
746   /*
747   if (!focusedName.IsEmpty())
748     state.SelectedNames.Add(focusedName);
749   */
750   LoadFullPath();
751   // ::SetCurrentDirectory(::_currentFolderPrefix);
752   RefreshListCtrl(state);
753   // _listView.EnsureVisible(_listView.GetFocusedItem(), false);
754 }
755 
756 
CloseOneLevel()757 void CPanel::CloseOneLevel()
758 {
759   ReleaseFolder();
760   _library.Free();
761   {
762     CFolderLink &link = _parentFolders.Back();
763     if (link.ParentFolder)
764       SetNewFolder(link.ParentFolder);
765     _library.Attach(link.Library.Detach());
766   }
767   if (_parentFolders.Size() > 1)
768     OpenParentArchiveFolder();
769   _parentFolders.DeleteBack();
770   if (_parentFolders.IsEmpty())
771     _flatMode = _flatModeForDisk;
772 }
773 
CloseOpenFolders()774 void CPanel::CloseOpenFolders()
775 {
776   while (!_parentFolders.IsEmpty())
777     CloseOneLevel();
778   _flatMode = _flatModeForDisk;
779   ReleaseFolder();
780   _library.Free();
781 }
782 
OpenRootFolder()783 void CPanel::OpenRootFolder()
784 {
785   CDisableTimerProcessing disableTimerProcessing(*this);
786   CDisableNotify disableNotify(*this);
787   _parentFolders.Clear();
788   SetToRootFolder();
789   RefreshListCtrl();
790   // ::SetCurrentDirectory(::_currentFolderPrefix);
791   /*
792   BeforeChangeFolder();
793   _currentFolderPrefix.Empty();
794   AfterChangeFolder();
795   SetCurrentPathText();
796   RefreshListCtrl(UString(), 0, UStringVector());
797   _listView.EnsureVisible(_listView.GetFocusedItem(), false);
798   */
799 }
800 
OpenDrivesFolder()801 void CPanel::OpenDrivesFolder()
802 {
803   CloseOpenFolders();
804   #ifdef UNDER_CE
805   NFsFolder::CFSFolder *folderSpec = new NFsFolder::CFSFolder;
806   SetNewFolder(folderSpec);
807   folderSpec->InitToRoot();
808   #else
809   CFSDrives *folderSpec = new CFSDrives;
810   SetNewFolder(folderSpec);
811   folderSpec->Init();
812   #endif
813   RefreshListCtrl();
814 }
815 
OpenFolder(int index)816 void CPanel::OpenFolder(int index)
817 {
818   if (index == kParentIndex)
819   {
820     OpenParentFolder();
821     return;
822   }
823   CMyComPtr<IFolderFolder> newFolder;
824   _folder->BindToFolder(index, &newFolder);
825   if (!newFolder)
826     return;
827   SetNewFolder(newFolder);
828   LoadFullPath();
829   RefreshListCtrl();
830   // 17.02: fixed : now we don't select first item
831   // _listView.SetItemState_Selected(_listView.GetFocusedItem());
832   _listView.EnsureVisible(_listView.GetFocusedItem(), false);
833 }
834 
OpenAltStreams()835 void CPanel::OpenAltStreams()
836 {
837   CRecordVector<UInt32> indices;
838   GetOperatedItemIndices(indices);
839   Int32 realIndex = -1;
840   if (indices.Size() > 1)
841     return;
842   if (indices.Size() == 1)
843     realIndex = indices[0];
844 
845   if (_folderAltStreams)
846   {
847     CMyComPtr<IFolderFolder> newFolder;
848     _folderAltStreams->BindToAltStreams(realIndex, &newFolder);
849     if (newFolder)
850     {
851       CDisableTimerProcessing disableTimerProcessing(*this);
852       CDisableNotify disableNotify(*this);
853       SetNewFolder(newFolder);
854       RefreshListCtrl();
855       return;
856     }
857     return;
858   }
859 
860   #if defined(_WIN32) && !defined(UNDER_CE)
861   UString path;
862   if (realIndex >= 0)
863     path = GetItemFullPath(realIndex);
864   else
865   {
866     path = GetFsPath();
867     if (!NName::IsDriveRootPath_SuperAllowed(us2fs(path)))
868       if (!path.IsEmpty() && IS_PATH_SEPAR(path.Back()))
869         path.DeleteBack();
870   }
871 
872   path += ':';
873   BindToPathAndRefresh(path);
874   #endif
875 }
876