// Panel.h #ifndef __PANEL_H #define __PANEL_H #include "../../../Common/MyWindows.h" #include #include "../../../../C/Alloc.h" #include "../../../Common/Defs.h" #include "../../../Common/MyCom.h" #include "../../../Windows/DLL.h" #include "../../../Windows/FileDir.h" #include "../../../Windows/FileFind.h" #include "../../../Windows/FileName.h" #include "../../../Windows/Handle.h" #include "../../../Windows/PropVariantConv.h" #include "../../../Windows/Synchronization.h" #include "../../../Windows/Control/ComboBox.h" #include "../../../Windows/Control/Edit.h" #include "../../../Windows/Control/ListView.h" #include "../../../Windows/Control/ReBar.h" #include "../../../Windows/Control/Static.h" #include "../../../Windows/Control/StatusBar.h" #include "../../../Windows/Control/ToolBar.h" #include "../../../Windows/Control/Window2.h" #include "../../Archive/IArchive.h" #include "ExtractCallback.h" #include "AppState.h" #include "IFolder.h" #include "MyCom2.h" #include "ProgressDialog2.h" #include "SysIconUtils.h" #ifdef UNDER_CE #define NON_CE_VAR(_v_) #else #define NON_CE_VAR(_v_) _v_ #endif const int kParentFolderID = 100; const int kParentIndex = -1; const UInt32 kParentIndex_UInt32 = (UInt32)(Int32)kParentIndex; #if !defined(_WIN32) || defined(UNDER_CE) #define ROOT_FS_FOLDER L"\\" #else #define ROOT_FS_FOLDER L"C:\\" #endif struct CPanelCallback { virtual void OnTab() = 0; virtual void SetFocusToPath(unsigned index) = 0; virtual void OnCopy(bool move, bool copyToSame) = 0; virtual void OnSetSameFolder() = 0; virtual void OnSetSubFolder() = 0; virtual void PanelWasFocused() = 0; virtual void DragBegin() = 0; virtual void DragEnd() = 0; virtual void RefreshTitle(bool always) = 0; }; void PanelCopyItems(); struct CPropColumn { int Order; PROPID ID; VARTYPE Type; bool IsVisible; bool IsRawProp; UInt32 Width; UString Name; bool IsEqualTo(const CPropColumn &a) const { return Order == a.Order && ID == a.ID && Type == a.Type && IsVisible == a.IsVisible && IsRawProp == a.IsRawProp && Width == a.Width && Name == a.Name; } int Compare(const CPropColumn &a) const { return MyCompare(Order, a.Order); } int Compare_NameFirst(const CPropColumn &a) const { if (ID == kpidName) { if (a.ID != kpidName) return -1; } else if (a.ID == kpidName) return 1; return MyCompare(Order, a.Order); } }; class CPropColumns: public CObjectVector { public: int FindItem_for_PropID(PROPID id) const { FOR_VECTOR (i, (*this)) if ((*this)[i].ID == id) return i; return -1; } bool IsEqualTo(const CPropColumns &props) const { if (Size() != props.Size()) return false; FOR_VECTOR (i, (*this)) if (!(*this)[i].IsEqualTo(props[i])) return false; return true; } }; struct CTempFileInfo { UInt32 FileIndex; // index of file in folder UString RelPath; // Relative path of file from Folder FString FolderPath; FString FilePath; NWindows::NFile::NFind::CFileInfo FileInfo; bool NeedDelete; CTempFileInfo(): FileIndex((UInt32)(Int32)-1), NeedDelete(false) {} void DeleteDirAndFile() const { if (NeedDelete) { NWindows::NFile::NDir::DeleteFileAlways(FilePath); NWindows::NFile::NDir::RemoveDir(FolderPath); } } bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const { return newFileInfo.Size != FileInfo.Size || CompareFileTime(&newFileInfo.MTime, &FileInfo.MTime) != 0; } }; struct CFolderLink: public CTempFileInfo { NWindows::NDLL::CLibrary Library; CMyComPtr ParentFolder; // can be NULL, if parent is FS folder (in _parentFolders[0]) UString ParentFolderPath; // including tail slash (doesn't include paths parts of parent in next level) bool UsePassword; UString Password; bool IsVirtual; UString VirtualPath; // without tail slash CFolderLink(): UsePassword(false), IsVirtual(false) {} bool WasChanged(const NWindows::NFile::NFind::CFileInfo &newFileInfo) const { return IsVirtual || CTempFileInfo::WasChanged(newFileInfo); } }; enum MyMessages { // we can use WM_USER, since we have defined new window class. // so we don't need WM_APP. kShiftSelectMessage = WM_USER + 1, kReLoadMessage, kSetFocusToListView, kOpenItemChanged, kRefresh_StatusBar #ifdef UNDER_CE , kRefresh_HeaderComboBox #endif }; UString GetFolderPath(IFolderFolder *folder); class CPanel; class CMyListView: public NWindows::NControl::CListView2 { public: CPanel *_panel; LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); }; /* class CMyComboBox: public NWindows::NControl::CComboBoxEx { public: WNDPROC _origWindowProc; CPanel *_panel; LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); }; */ class CMyComboBoxEdit: public NWindows::NControl::CEdit { public: WNDPROC _origWindowProc; CPanel *_panel; LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); }; struct CSelectedState { int FocusedItem; bool SelectFocused; bool FocusedName_Defined; UString FocusedName; UStringVector SelectedNames; CSelectedState(): FocusedItem(-1), SelectFocused(true), FocusedName_Defined(false) {} }; #ifdef UNDER_CE #define MY_NMLISTVIEW_NMITEMACTIVATE NMLISTVIEW #else #define MY_NMLISTVIEW_NMITEMACTIVATE NMITEMACTIVATE #endif struct CCopyToOptions { bool streamMode; bool moveMode; bool testMode; bool includeAltStreams; bool replaceAltStreamChars; bool showErrorMessages; UString folder; UStringVector hashMethods; CVirtFileSystem *VirtFileSystemSpec; ISequentialOutStream *VirtFileSystem; CCopyToOptions(): streamMode(false), moveMode(false), testMode(false), includeAltStreams(true), replaceAltStreamChars(false), showErrorMessages(false), VirtFileSystemSpec(NULL), VirtFileSystem(NULL) {} }; struct COpenResult { // bool needOpenArc; // out: bool ArchiveIsOpened; bool Encrypted; UString ErrorMessage; COpenResult(): // needOpenArc(false), ArchiveIsOpened(false), Encrypted(false) {} }; class CPanel: public NWindows::NControl::CWindow2 { CExtToIconMap _extToIconMap; UINT _baseID; int _comboBoxID; UINT _statusBarID; CAppState *_appState; bool OnCommand(int code, int itemID, LPARAM lParam, LRESULT &result); LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); virtual bool OnCreate(CREATESTRUCT *createStruct); virtual bool OnSize(WPARAM wParam, int xSize, int ySize); virtual void OnDestroy(); virtual bool OnNotify(UINT controlID, LPNMHDR lParam, LRESULT &result); void AddComboBoxItem(const UString &name, int iconIndex, int indent, bool addToList); bool OnComboBoxCommand(UINT code, LPARAM param, LRESULT &result); #ifndef UNDER_CE LRESULT OnNotifyComboBoxEnter(const UString &s); bool OnNotifyComboBoxEndEdit(PNMCBEENDEDITW info, LRESULT &result); #ifndef _UNICODE bool OnNotifyComboBoxEndEdit(PNMCBEENDEDIT info, LRESULT &result); #endif #endif bool OnNotifyReBar(LPNMHDR lParam, LRESULT &result); bool OnNotifyComboBox(LPNMHDR lParam, LRESULT &result); void OnItemChanged(NMLISTVIEW *item); void OnNotifyActivateItems(); bool OnNotifyList(LPNMHDR lParam, LRESULT &result); void OnDrag(LPNMLISTVIEW nmListView); bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo, LRESULT &result); BOOL OnBeginLabelEdit(LV_DISPINFOW * lpnmh); BOOL OnEndLabelEdit(LV_DISPINFOW * lpnmh); void OnColumnClick(LPNMLISTVIEW info); bool OnCustomDraw(LPNMLVCUSTOMDRAW lplvcd, LRESULT &result); public: HWND _mainWindow; CPanelCallback *_panelCallback; void SysIconsWereChanged() { _extToIconMap.Clear(); } void DeleteItems(bool toRecycleBin); void CreateFolder(); void CreateFile(); bool CorrectFsPath(const UString &path, UString &result); // bool IsPathForPlugin(const UString &path); private: void ChangeWindowSize(int xSize, int ySize); HRESULT InitColumns(); void DeleteColumn(unsigned index); void AddColumn(const CPropColumn &prop); void SetFocusedSelectedItem(int index, bool select); void OnShiftSelectMessage(); void OnArrowWithShift(); void OnInsert(); // void OnUpWithShift(); // void OnDownWithShift(); public: void UpdateSelection(); void SelectSpec(bool selectMode); void SelectByType(bool selectMode); void SelectAll(bool selectMode); void InvertSelection(); private: // UString GetFileType(UInt32 index); LRESULT SetItemText(LVITEMW &item); // CRecordVector m_ColumnsPropIDs; public: NWindows::NControl::CReBar _headerReBar; NWindows::NControl::CToolBar _headerToolBar; NWindows::NControl:: #ifdef UNDER_CE CComboBox #else CComboBoxEx #endif _headerComboBox; UStringVector ComboBoxPaths; // CMyComboBox _headerComboBox; CMyComboBoxEdit _comboBoxEdit; CMyListView _listView; bool _thereAre_ListView_Items; NWindows::NControl::CStatusBar _statusBar; bool _lastFocusedIsList; // NWindows::NControl::CStatusBar _statusBar2; DWORD _exStyle; bool _showDots; bool _showRealFileIcons; // bool _virtualMode; // CUIntVector _realIndices; bool _enableItemChangeNotify; bool _mySelectMode; int _timestampLevel; void RedrawListItems() { _listView.RedrawAllItems(); } CBoolVector _selectedStatusVector; CSelectedState _selectedState; bool _thereAreDeletedItems; bool _markDeletedItems; bool PanelCreated; void DeleteListItems() { if (_thereAre_ListView_Items) { bool b = _enableItemChangeNotify; _enableItemChangeNotify = false; _listView.DeleteAllItems(); _thereAre_ListView_Items = false; _enableItemChangeNotify = b; } } HWND GetParent() const; UInt32 GetRealIndex(const LVITEMW &item) const { /* if (_virtualMode) return _realIndices[item.iItem]; */ return (UInt32)item.lParam; } int GetRealItemIndex(int indexInListView) const { /* if (_virtualMode) return indexInListView; */ LPARAM param; if (!_listView.GetItemParam(indexInListView, param)) throw 1; return (int)param; } UInt32 _ListViewMode; int _xSize; bool _flatMode; bool _flatModeForDisk; bool _flatModeForArc; // bool _showNtfsStrems_Mode; // bool _showNtfsStrems_ModeForDisk; // bool _showNtfsStrems_ModeForArc; bool _dontShowMode; UString _currentFolderPrefix; CObjectVector _parentFolders; NWindows::NDLL::CLibrary _library; CMyComPtr _folder; CMyComPtr _folderCompare; CMyComPtr _folderGetItemName; CMyComPtr _folderRawProps; CMyComPtr _folderAltStreams; CMyComPtr _folderOperations; void ReleaseFolder(); void SetNewFolder(IFolderFolder *newFolder); // CMyComPtr _folderGetSystemIconIndex; UStringVector _fastFolders; void GetSelectedNames(UStringVector &selectedNames); void SaveSelectedState(CSelectedState &s); HRESULT RefreshListCtrl(const CSelectedState &s); HRESULT RefreshListCtrl_SaveFocused(); bool GetItem_BoolProp(UInt32 itemIndex, PROPID propID) const; bool IsItem_Deleted(int itemIndex) const; bool IsItem_Folder(int itemIndex) const; bool IsItem_AltStream(int itemIndex) const; UString GetItemName(int itemIndex) const; UString GetItemName_for_Copy(int itemIndex) const; void GetItemName(int itemIndex, UString &s) const; UString GetItemPrefix(int itemIndex) const; UString GetItemRelPath(int itemIndex) const; UString GetItemRelPath2(int itemIndex) const; UString GetItemFullPath(int itemIndex) const; UInt64 GetItem_UInt64Prop(int itemIndex, PROPID propID) const; UInt64 GetItemSize(int itemIndex) const; //////////////////////// // PanelFolderChange.cpp void SetToRootFolder(); HRESULT BindToPath(const UString &fullPath, const UString &arcFormat, COpenResult &openRes); // can be prefix HRESULT BindToPathAndRefresh(const UString &path); void OpenDrivesFolder(); void SetBookmark(unsigned index); void OpenBookmark(unsigned index); void LoadFullPath(); void LoadFullPathAndShow(); void FoldersHistory(); void OpenParentFolder(); void CloseOneLevel(); void CloseOpenFolders(); void OpenRootFolder(); UString GetParentDirPrefix() const; HRESULT Create(HWND mainWindow, HWND parentWindow, UINT id, const UString ¤tFolderPrefix, const UString &arcFormat, CPanelCallback *panelCallback, CAppState *appState, bool needOpenArc, COpenResult &openRes); void SetFocusToList(); void SetFocusToLastRememberedItem(); void SaveListViewInfo(); CPanel() : _thereAre_ListView_Items(false), _exStyle(0), _showDots(false), _showRealFileIcons(false), // _virtualMode(flase), _enableItemChangeNotify(true), _mySelectMode(false), _timestampLevel(kTimestampPrintLevel_MIN), _thereAreDeletedItems(false), _markDeletedItems(true), PanelCreated(false), _ListViewMode(3), _xSize(300), _flatMode(false), _flatModeForDisk(false), _flatModeForArc(false), // _showNtfsStrems_Mode(false), // _showNtfsStrems_ModeForDisk(false), // _showNtfsStrems_ModeForArc(false), _dontShowMode(false), _needSaveInfo(false), _startGroupSelect(0), _selectionIsDefined(false) {} void SetExtendedStyle() { if (_listView != 0) _listView.SetExtendedListViewStyle(_exStyle); } bool _needSaveInfo; UString _typeIDString; CListViewInfo _listViewInfo; CPropColumns _columns; CPropColumns _visibleColumns; PROPID _sortID; // int _sortIndex; bool _ascending; Int32 _isRawSortProp; void SetSortRawStatus(); void Release(); ~CPanel(); void OnLeftClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate); bool OnRightClick(MY_NMLISTVIEW_NMITEMACTIVATE *itemActivate, LRESULT &result); void ShowColumnsContextMenu(int x, int y); void OnTimer(); void OnReload(); bool OnContextMenu(HANDLE windowHandle, int xPos, int yPos); CMyComPtr _sevenZipContextMenu; CMyComPtr _systemContextMenu; HRESULT CreateShellContextMenu( const CRecordVector &operatedIndices, CMyComPtr &systemContextMenu); void CreateSystemMenu(HMENU menu, const CRecordVector &operatedIndices, CMyComPtr &systemContextMenu); void CreateSevenZipMenu(HMENU menu, const CRecordVector &operatedIndices, CMyComPtr &sevenZipContextMenu); void CreateFileMenu(HMENU menu, CMyComPtr &sevenZipContextMenu, CMyComPtr &systemContextMenu, bool programMenu); void CreateFileMenu(HMENU menu); bool InvokePluginCommand(unsigned id); bool InvokePluginCommand(unsigned id, IContextMenu *sevenZipContextMenu, IContextMenu *systemContextMenu); void InvokeSystemCommand(const char *command); void Properties(); void EditCut(); void EditCopy(); void EditPaste(); int _startGroupSelect; bool _selectionIsDefined; bool _selectMark; int _prevFocusedItem; // void SortItems(int index); void SortItemsWithPropID(PROPID propID); void GetSelectedItemsIndices(CRecordVector &indices) const; void GetOperatedItemIndices(CRecordVector &indices) const; void GetAllItemIndices(CRecordVector &indices) const; void GetOperatedIndicesSmart(CRecordVector &indices) const; // void GetOperatedListViewIndices(CRecordVector &indices) const; void KillSelection(); UString GetFolderTypeID() const; bool IsFolderTypeEqTo(const char *s) const; bool IsRootFolder() const; bool IsFSFolder() const; bool IsFSDrivesFolder() const; bool IsAltStreamsFolder() const; bool IsArcFolder() const; bool IsHashFolder() const; /* c:\Dir Computer\ \\?\ \\.\ */ bool Is_IO_FS_Folder() const { return IsFSFolder() || IsFSDrivesFolder() || IsAltStreamsFolder(); } bool Is_Slow_Icon_Folder() const { return IsFSFolder() || IsAltStreamsFolder(); } // bool IsFsOrDrivesFolder() const { return IsFSFolder() || IsFSDrivesFolder(); } bool IsDeviceDrivesPrefix() const { return _currentFolderPrefix == L"\\\\.\\"; } bool IsSuperDrivesPrefix() const { return _currentFolderPrefix == L"\\\\?\\"; } /* c:\Dir Computer\ \\?\ */ bool IsFsOrPureDrivesFolder() const { return IsFSFolder() || (IsFSDrivesFolder() && !IsDeviceDrivesPrefix()); } /* c:\Dir Computer\ \\?\ \\SERVER\ */ bool IsFolder_with_FsItems() const { if (IsFsOrPureDrivesFolder()) return true; #if defined(_WIN32) && !defined(UNDER_CE) FString prefix = us2fs(GetFsPath()); return (prefix.Len() == NWindows::NFile::NName::GetNetworkServerPrefixSize(prefix)); #else return false; #endif } UString GetFsPath() const; UString GetDriveOrNetworkPrefix() const; bool DoesItSupportOperations() const { return _folderOperations != NULL; } bool IsThereReadOnlyFolder() const; bool CheckBeforeUpdate(UINT resourceID); bool _processTimer; bool _processNotify; bool _processStatusBar; class CDisableTimerProcessing { CLASS_NO_COPY(CDisableTimerProcessing); bool _processTimer; CPanel &_panel; public: CDisableTimerProcessing(CPanel &panel): _panel(panel) { Disable(); } ~CDisableTimerProcessing() { Restore(); } void Disable() { _processTimer = _panel._processTimer; _panel._processTimer = false; } void Restore() { _panel._processTimer = _processTimer; } }; class CDisableNotify { CLASS_NO_COPY(CDisableNotify); bool _processNotify; bool _processStatusBar; CPanel &_panel; public: CDisableNotify(CPanel &panel): _panel(panel) { Disable(); } ~CDisableNotify() { Restore(); } void Disable() { _processNotify = _panel._processNotify; _processStatusBar = _panel._processStatusBar; _panel._processNotify = false; _panel._processStatusBar = false; } void SetMemMode_Enable() { _processNotify = true; _processStatusBar = true; } void Restore() { _panel._processNotify = _processNotify; _panel._processStatusBar = _processStatusBar; } }; void InvalidateList() { _listView.InvalidateRect(NULL, true); } HRESULT RefreshListCtrl(); // void MessageBox_Info(LPCWSTR message, LPCWSTR caption) const; // void MessageBox_Warning(LPCWSTR message) const; void MessageBox_Error_Caption(LPCWSTR message, LPCWSTR caption) const; void MessageBox_Error(LPCWSTR message) const; void MessageBox_Error_HRESULT_Caption(HRESULT errorCode, LPCWSTR caption) const; void MessageBox_Error_HRESULT(HRESULT errorCode) const; void MessageBox_Error_2Lines_Message_HRESULT(LPCWSTR message, HRESULT errorCode) const; void MessageBox_LastError(LPCWSTR caption) const; void MessageBox_LastError() const; void MessageBox_Error_LangID(UINT resourceID) const; void MessageBox_Error_UnsupportOperation() const; // void MessageBoxErrorForUpdate(HRESULT errorCode, UINT resourceID); void OpenAltStreams(); void OpenFocusedItemAsInternal(const wchar_t *type = NULL); void OpenSelectedItems(bool internal); void OpenFolderExternal(int index); void OpenFolder(int index); HRESULT OpenParentArchiveFolder(); HRESULT OpenAsArc(IInStream *inStream, const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, const UString &arcFormat, COpenResult &openRes); HRESULT OpenAsArc_Msg(IInStream *inStream, const CTempFileInfo &tempFileInfo, const UString &virtualFilePath, const UString &arcFormat // , bool showErrorMessage ); HRESULT OpenAsArc_Name(const UString &relPath, const UString &arcFormat // , bool showErrorMessage ); HRESULT OpenAsArc_Index(int index, const wchar_t *type /* = NULL */ // , bool showErrorMessage ); void OpenItemInArchive(int index, bool tryInternal, bool tryExternal, bool editMode, bool useEditor, const wchar_t *type = NULL); HRESULT OnOpenItemChanged(UInt32 index, const wchar_t *fullFilePath, bool usePassword, const UString &password); LRESULT OnOpenItemChanged(LPARAM lParam); bool IsVirus_Message(const UString &name); void OpenItem(int index, bool tryInternal, bool tryExternal, const wchar_t *type = NULL); void EditItem(bool useEditor); void EditItem(int index, bool useEditor); void RenameFile(); void ChangeComment(); void SetListViewMode(UInt32 index); UInt32 GetListViewMode() const { return _ListViewMode; } PROPID GetSortID() const { return _sortID; } void ChangeFlatMode(); void Change_ShowNtfsStrems_Mode(); bool GetFlatMode() const { return _flatMode; } // bool Get_ShowNtfsStrems_Mode() const { return _showNtfsStrems_Mode; } bool AutoRefresh_Mode; void Set_AutoRefresh_Mode(bool mode) { AutoRefresh_Mode = mode; } void Post_Refresh_StatusBar(); void Refresh_StatusBar(); void AddToArchive(); void GetFilePaths(const CRecordVector &indices, UStringVector &paths, bool allowFolders = false); void ExtractArchives(); void TestArchives(); HRESULT CopyTo(CCopyToOptions &options, const CRecordVector &indices, UStringVector *messages, bool &usePassword, UString &password); HRESULT CopyTo(CCopyToOptions &options, const CRecordVector &indices, UStringVector *messages) { bool usePassword = false; UString password; if (_parentFolders.Size() > 0) { const CFolderLink &fl = _parentFolders.Back(); usePassword = fl.UsePassword; password = fl.Password; } return CopyTo(options, indices, messages, usePassword, password); } HRESULT CopyFrom(bool moveMode, const UString &folderPrefix, const UStringVector &filePaths, bool showErrorMessages, UStringVector *messages); void CopyFromNoAsk(const UStringVector &filePaths); void CopyFromAsk(const UStringVector &filePaths); // empty folderPath means create new Archive to path of first fileName. void DropObject(IDataObject * dataObject, const UString &folderPath); // empty folderPath means create new Archive to path of first fileName. void CompressDropFiles(const UStringVector &fileNames, const UString &folderPath); void RefreshTitle(bool always = false) { _panelCallback->RefreshTitle(always); } void RefreshTitleAlways() { RefreshTitle(true); } UString GetItemsInfoString(const CRecordVector &indices); }; class CMyBuffer { void *_data; public: CMyBuffer(): _data(0) {} operator void *() { return _data; } bool Allocate(size_t size) { if (_data != 0) return false; _data = ::MidAlloc(size); return _data != 0; } ~CMyBuffer() { ::MidFree(_data); } }; class CExitEventLauncher { public: NWindows::NSynchronization::CManualResetEvent _exitEvent; bool _needExit; CRecordVector< ::CThread > _threads; unsigned _numActiveThreads; CExitEventLauncher() { _needExit = false; if (_exitEvent.Create(false) != S_OK) throw 9387173; _needExit = true; _numActiveThreads = 0; }; ~CExitEventLauncher() { Exit(true); } void Exit(bool hardExit); }; extern CExitEventLauncher g_ExitEventLauncher; #endif