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